Messages in this thread | | | Date | Wed, 7 Jan 1998 19:35:13 -0600 | From | Michael Elizabeth Chastain <> | Subject | Re: broken pas2 ioctl followup |
| |
Welcome to the riddles of drivers/sound.
> I would have expected to see a "cmd = C0045004" and a "cmd = C0045003" > in there somewhere, among other anomalies. Sure hope the above helps > someone figure out what's going on.
It does. Good bug report.
I can explain both of these:
sox calls ioctl(SNDCTL_DSP_GETBLKSIZE), which is 0xC0045004. sound_ioctl hands this off to audio_ioctl. audio_ioctl handles it without calling the device-specific pas_audio_ioctl. That's why you don't see 'cmd = C0045004'. I believe there is no bug here.
sox calls ioctl(SNDCTL_DSP_STEREO), which is 0xC0045003. sound_ioctl hands this off to audio_ioctl. audio_ioctl does some processing itself, and then calls the device-specific set_channels function.
pas_audio_driver does not specify a device-specific set_channels function, so this defaults to default_set_channels (see check_driver in dmabuf.c and the callers of check_driver). default_set_channels calls the device-specific ioctl function, pas_audio_ioctl, with SNDCTL_DSP_CHANNELS, which is 0xC0045006.
That is why 'strace' reports 0xC0045003, but pas2_audio_ioctl reports 0xC0045006. Apparently the intent is that SNDCTL_DSP_CHANNELS is a more general form.
pas_audio_ioctl has a case for SOUND_PCM_WRITE_CHANNELS, which is a synonym for SNDCTL_DSP_CHANNELS.
I believe here is where the bug creeps in.
/* Original OSS/Free code */ /* Also in Linux 2.1.76 */ case SOUND_PCM_WRITE_CHANNELS: val = *(int *) arg; return (*(int *) arg = pcm_set_channels (val)); break;
/* Linux 2.1.78 */ case SOUND_PCM_WRITE_CHANNELS: if (__get_user(val, (int *)arg)) return -EFAULT; ret = pcm_set_channels(val);
...
return __put_user(ret, (int *)arg);
The return value of pas_audio_ioctl has changed. Before, it returned the return value of pcm_set_channels. Now, it returns the return value of __put_user.
By the way, I would very much like to see all the new __put_user and __get_user calls replaced by put_user and get_user. The associated verify_area calls are in other functions, in other files, and sooner or later someone is going to find another execution path that yields a security hole. (I found one in 2.1.77).
Michael Chastain <mailto:mec@shout.net> "love without fear"
| |