Loading sound/core/control_compat.c +74 −16 Original line number Original line Diff line number Diff line Loading @@ -170,6 +170,19 @@ struct snd_ctl_elem_value32 { unsigned char reserved[128]; unsigned char reserved[128]; }; }; #ifdef CONFIG_X86_X32 /* x32 has a different alignment for 64bit values from ia32 */ struct snd_ctl_elem_value_x32 { struct snd_ctl_elem_id id; unsigned int indirect; /* bit-field causes misalignment */ union { s32 integer[128]; unsigned char data[512]; s64 integer64[64]; } value; unsigned char reserved[128]; }; #endif /* CONFIG_X86_X32 */ /* get the value type and count of the control */ /* get the value type and count of the control */ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, Loading Loading @@ -219,9 +232,11 @@ static int get_elem_size(int type, int count) static int copy_ctl_value_from_user(struct snd_card *card, static int copy_ctl_value_from_user(struct snd_card *card, struct snd_ctl_elem_value *data, struct snd_ctl_elem_value *data, struct snd_ctl_elem_value32 __user *data32, void __user *userdata, void __user *valuep, int *typep, int *countp) int *typep, int *countp) { { struct snd_ctl_elem_value32 __user *data32 = userdata; int i, type, size; int i, type, size; int uninitialized_var(count); int uninitialized_var(count); unsigned int indirect; unsigned int indirect; Loading @@ -239,8 +254,9 @@ static int copy_ctl_value_from_user(struct snd_card *card, if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || type == SNDRV_CTL_ELEM_TYPE_INTEGER) { type == SNDRV_CTL_ELEM_TYPE_INTEGER) { for (i = 0; i < count; i++) { for (i = 0; i < count; i++) { s32 __user *intp = valuep; int val; int val; if (get_user(val, &data32->value.integer[i])) if (get_user(val, &intp[i])) return -EFAULT; return -EFAULT; data->value.integer.value[i] = val; data->value.integer.value[i] = val; } } Loading @@ -250,8 +266,7 @@ static int copy_ctl_value_from_user(struct snd_card *card, dev_err(card->dev, "snd_ioctl32_ctl_elem_value: unknown type %d\n", type); dev_err(card->dev, "snd_ioctl32_ctl_elem_value: unknown type %d\n", type); return -EINVAL; return -EINVAL; } } if (copy_from_user(data->value.bytes.data, if (copy_from_user(data->value.bytes.data, valuep, size)) data32->value.data, size)) return -EFAULT; return -EFAULT; } } Loading @@ -261,7 +276,8 @@ static int copy_ctl_value_from_user(struct snd_card *card, } } /* restore the value to 32bit */ /* restore the value to 32bit */ static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32, static int copy_ctl_value_to_user(void __user *userdata, void __user *valuep, struct snd_ctl_elem_value *data, struct snd_ctl_elem_value *data, int type, int count) int type, int count) { { Loading @@ -270,22 +286,22 @@ static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32, if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || type == SNDRV_CTL_ELEM_TYPE_INTEGER) { type == SNDRV_CTL_ELEM_TYPE_INTEGER) { for (i = 0; i < count; i++) { for (i = 0; i < count; i++) { s32 __user *intp = valuep; int val; int val; val = data->value.integer.value[i]; val = data->value.integer.value[i]; if (put_user(val, &data32->value.integer[i])) if (put_user(val, &intp[i])) return -EFAULT; return -EFAULT; } } } else { } else { size = get_elem_size(type, count); size = get_elem_size(type, count); if (copy_to_user(data32->value.data, if (copy_to_user(valuep, data->value.bytes.data, size)) data->value.bytes.data, size)) return -EFAULT; return -EFAULT; } } return 0; return 0; } } static int snd_ctl_elem_read_user_compat(struct snd_card *card, static int ctl_elem_read_user(struct snd_card *card, struct snd_ctl_elem_value32 __user *data32) void __user *userdata, void __user *valuep) { { struct snd_ctl_elem_value *data; struct snd_ctl_elem_value *data; int err, type, count; int err, type, count; Loading @@ -294,7 +310,9 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card, if (data == NULL) if (data == NULL) return -ENOMEM; return -ENOMEM; if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0) err = copy_ctl_value_from_user(card, data, userdata, valuep, &type, &count); if (err < 0) goto error; goto error; snd_power_lock(card); snd_power_lock(card); Loading @@ -303,14 +321,15 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card, err = snd_ctl_elem_read(card, data); err = snd_ctl_elem_read(card, data); snd_power_unlock(card); snd_power_unlock(card); if (err >= 0) if (err >= 0) err = copy_ctl_value_to_user(data32, data, type, count); err = copy_ctl_value_to_user(userdata, valuep, data, type, count); error: error: kfree(data); kfree(data); return err; return err; } } static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, static int ctl_elem_write_user(struct snd_ctl_file *file, struct snd_ctl_elem_value32 __user *data32) void __user *userdata, void __user *valuep) { { struct snd_ctl_elem_value *data; struct snd_ctl_elem_value *data; struct snd_card *card = file->card; struct snd_card *card = file->card; Loading @@ -320,7 +339,9 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, if (data == NULL) if (data == NULL) return -ENOMEM; return -ENOMEM; if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0) err = copy_ctl_value_from_user(card, data, userdata, valuep, &type, &count); if (err < 0) goto error; goto error; snd_power_lock(card); snd_power_lock(card); Loading @@ -329,12 +350,39 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, err = snd_ctl_elem_write(card, file, data); err = snd_ctl_elem_write(card, file, data); snd_power_unlock(card); snd_power_unlock(card); if (err >= 0) if (err >= 0) err = copy_ctl_value_to_user(data32, data, type, count); err = copy_ctl_value_to_user(userdata, valuep, data, type, count); error: error: kfree(data); kfree(data); return err; return err; } } static int snd_ctl_elem_read_user_compat(struct snd_card *card, struct snd_ctl_elem_value32 __user *data32) { return ctl_elem_read_user(card, data32, &data32->value); } static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, struct snd_ctl_elem_value32 __user *data32) { return ctl_elem_write_user(file, data32, &data32->value); } #ifdef CONFIG_X86_X32 static int snd_ctl_elem_read_user_x32(struct snd_card *card, struct snd_ctl_elem_value_x32 __user *data32) { return ctl_elem_read_user(card, data32, &data32->value); } static int snd_ctl_elem_write_user_x32(struct snd_ctl_file *file, struct snd_ctl_elem_value_x32 __user *data32) { return ctl_elem_write_user(file, data32, &data32->value); } #endif /* CONFIG_X86_X32 */ /* add or replace a user control */ /* add or replace a user control */ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, struct snd_ctl_elem_info32 __user *data32, struct snd_ctl_elem_info32 __user *data32, Loading Loading @@ -393,6 +441,10 @@ enum { SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32), SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32), SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32), SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32), SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32), SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32), #ifdef CONFIG_X86_X32 SNDRV_CTL_IOCTL_ELEM_READ_X32 = _IOWR('U', 0x12, struct snd_ctl_elem_value_x32), SNDRV_CTL_IOCTL_ELEM_WRITE_X32 = _IOWR('U', 0x13, struct snd_ctl_elem_value_x32), #endif /* CONFIG_X86_X32 */ }; }; static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) Loading Loading @@ -431,6 +483,12 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns return snd_ctl_elem_add_compat(ctl, argp, 0); return snd_ctl_elem_add_compat(ctl, argp, 0); case SNDRV_CTL_IOCTL_ELEM_REPLACE32: case SNDRV_CTL_IOCTL_ELEM_REPLACE32: return snd_ctl_elem_add_compat(ctl, argp, 1); return snd_ctl_elem_add_compat(ctl, argp, 1); #ifdef CONFIG_X86_X32 case SNDRV_CTL_IOCTL_ELEM_READ_X32: return snd_ctl_elem_read_user_x32(ctl->card, argp); case SNDRV_CTL_IOCTL_ELEM_WRITE_X32: return snd_ctl_elem_write_user_x32(ctl, argp); #endif /* CONFIG_X86_X32 */ } } down_read(&snd_ioctl_rwsem); down_read(&snd_ioctl_rwsem); Loading sound/core/pcm_compat.c +176 −1 Original line number Original line Diff line number Diff line Loading @@ -183,6 +183,14 @@ static int snd_pcm_ioctl_channel_info_compat(struct snd_pcm_substream *substream return err; return err; } } #ifdef CONFIG_X86_X32 /* X32 ABI has the same struct as x86-64 for snd_pcm_channel_info */ static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream, struct snd_pcm_channel_info __user *src); #define snd_pcm_ioctl_channel_info_x32(s, p) \ snd_pcm_channel_info_user(s, p) #endif /* CONFIG_X86_X32 */ struct snd_pcm_status32 { struct snd_pcm_status32 { s32 state; s32 state; struct compat_timespec trigger_tstamp; struct compat_timespec trigger_tstamp; Loading Loading @@ -243,6 +251,71 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, return err; return err; } } #ifdef CONFIG_X86_X32 /* X32 ABI has 64bit timespec and 64bit alignment */ struct snd_pcm_status_x32 { s32 state; u32 rsvd; /* alignment */ struct timespec trigger_tstamp; struct timespec tstamp; u32 appl_ptr; u32 hw_ptr; s32 delay; u32 avail; u32 avail_max; u32 overrange; s32 suspended_state; u32 audio_tstamp_data; struct timespec audio_tstamp; struct timespec driver_tstamp; u32 audio_tstamp_accuracy; unsigned char reserved[52-2*sizeof(struct timespec)]; } __packed; #define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst)) static int snd_pcm_status_user_x32(struct snd_pcm_substream *substream, struct snd_pcm_status_x32 __user *src, bool ext) { struct snd_pcm_status status; int err; memset(&status, 0, sizeof(status)); /* * with extension, parameters are read/write, * get audio_tstamp_data from user, * ignore rest of status structure */ if (ext && get_user(status.audio_tstamp_data, (u32 __user *)(&src->audio_tstamp_data))) return -EFAULT; err = snd_pcm_status(substream, &status); if (err < 0) return err; if (clear_user(src, sizeof(*src))) return -EFAULT; if (put_user(status.state, &src->state) || put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) || put_timespec(&status.tstamp, &src->tstamp) || put_user(status.appl_ptr, &src->appl_ptr) || put_user(status.hw_ptr, &src->hw_ptr) || put_user(status.delay, &src->delay) || put_user(status.avail, &src->avail) || put_user(status.avail_max, &src->avail_max) || put_user(status.overrange, &src->overrange) || put_user(status.suspended_state, &src->suspended_state) || put_user(status.audio_tstamp_data, &src->audio_tstamp_data) || put_timespec(&status.audio_tstamp, &src->audio_tstamp) || put_timespec(&status.driver_tstamp, &src->driver_tstamp) || put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy)) return -EFAULT; return err; } #endif /* CONFIG_X86_X32 */ /* both for HW_PARAMS and HW_REFINE */ /* both for HW_PARAMS and HW_REFINE */ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, int refine, int refine, Loading Loading @@ -469,6 +542,93 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream, return 0; return 0; } } #ifdef CONFIG_X86_X32 /* X32 ABI has 64bit timespec and 64bit alignment */ struct snd_pcm_mmap_status_x32 { s32 state; s32 pad1; u32 hw_ptr; u32 pad2; /* alignment */ struct timespec tstamp; s32 suspended_state; struct timespec audio_tstamp; } __packed; struct snd_pcm_mmap_control_x32 { u32 appl_ptr; u32 avail_min; }; struct snd_pcm_sync_ptr_x32 { u32 flags; u32 rsvd; /* alignment */ union { struct snd_pcm_mmap_status_x32 status; unsigned char reserved[64]; } s; union { struct snd_pcm_mmap_control_x32 control; unsigned char reserved[64]; } c; } __packed; static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream, struct snd_pcm_sync_ptr_x32 __user *src) { struct snd_pcm_runtime *runtime = substream->runtime; volatile struct snd_pcm_mmap_status *status; volatile struct snd_pcm_mmap_control *control; u32 sflags; struct snd_pcm_mmap_control scontrol; struct snd_pcm_mmap_status sstatus; snd_pcm_uframes_t boundary; int err; if (snd_BUG_ON(!runtime)) return -EINVAL; if (get_user(sflags, &src->flags) || get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || get_user(scontrol.avail_min, &src->c.control.avail_min)) return -EFAULT; if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) { err = snd_pcm_hwsync(substream); if (err < 0) return err; } status = runtime->status; control = runtime->control; boundary = recalculate_boundary(runtime); if (!boundary) boundary = 0x7fffffff; snd_pcm_stream_lock_irq(substream); /* FIXME: we should consider the boundary for the sync from app */ if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) control->appl_ptr = scontrol.appl_ptr; else scontrol.appl_ptr = control->appl_ptr % boundary; if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) control->avail_min = scontrol.avail_min; else scontrol.avail_min = control->avail_min; sstatus.state = status->state; sstatus.hw_ptr = status->hw_ptr % boundary; sstatus.tstamp = status->tstamp; sstatus.suspended_state = status->suspended_state; sstatus.audio_tstamp = status->audio_tstamp; snd_pcm_stream_unlock_irq(substream); if (put_user(sstatus.state, &src->s.status.state) || put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) || put_timespec(&sstatus.tstamp, &src->s.status.tstamp) || put_user(sstatus.suspended_state, &src->s.status.suspended_state) || put_timespec(&sstatus.audio_tstamp, &src->s.status.audio_tstamp) || put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || put_user(scontrol.avail_min, &src->c.control.avail_min)) return -EFAULT; return 0; } #endif /* CONFIG_X86_X32 */ /* /* */ */ Loading @@ -487,7 +647,12 @@ enum { SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32), SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32), SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32), SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32), SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32), SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32), #ifdef CONFIG_X86_X32 SNDRV_PCM_IOCTL_CHANNEL_INFO_X32 = _IOR('A', 0x32, struct snd_pcm_channel_info), SNDRV_PCM_IOCTL_STATUS_X32 = _IOR('A', 0x20, struct snd_pcm_status_x32), SNDRV_PCM_IOCTL_STATUS_EXT_X32 = _IOWR('A', 0x24, struct snd_pcm_status_x32), SNDRV_PCM_IOCTL_SYNC_PTR_X32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr_x32), #endif /* CONFIG_X86_X32 */ }; }; static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) Loading Loading @@ -559,6 +724,16 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l return snd_pcm_ioctl_rewind_compat(substream, argp); return snd_pcm_ioctl_rewind_compat(substream, argp); case SNDRV_PCM_IOCTL_FORWARD32: case SNDRV_PCM_IOCTL_FORWARD32: return snd_pcm_ioctl_forward_compat(substream, argp); return snd_pcm_ioctl_forward_compat(substream, argp); #ifdef CONFIG_X86_X32 case SNDRV_PCM_IOCTL_STATUS_X32: return snd_pcm_status_user_x32(substream, argp, false); case SNDRV_PCM_IOCTL_STATUS_EXT_X32: return snd_pcm_status_user_x32(substream, argp, true); case SNDRV_PCM_IOCTL_SYNC_PTR_X32: return snd_pcm_ioctl_sync_ptr_x32(substream, argp); case SNDRV_PCM_IOCTL_CHANNEL_INFO_X32: return snd_pcm_ioctl_channel_info_x32(substream, argp); #endif /* CONFIG_X86_X32 */ } } return -ENOIOCTLCMD; return -ENOIOCTLCMD; Loading sound/core/rawmidi_compat.c +54 −2 Original line number Original line Diff line number Diff line Loading @@ -85,8 +85,7 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, if (err < 0) if (err < 0) return err; return err; if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) || if (compat_put_timespec(&status.tstamp, &src->tstamp) || put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) || put_user(status.avail, &src->avail) || put_user(status.avail, &src->avail) || put_user(status.xruns, &src->xruns)) put_user(status.xruns, &src->xruns)) return -EFAULT; return -EFAULT; Loading @@ -94,9 +93,58 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, return 0; return 0; } } #ifdef CONFIG_X86_X32 /* X32 ABI has 64bit timespec and 64bit alignment */ struct snd_rawmidi_status_x32 { s32 stream; u32 rsvd; /* alignment */ struct timespec tstamp; u32 avail; u32 xruns; unsigned char reserved[16]; } __attribute__((packed)); #define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst)) static int snd_rawmidi_ioctl_status_x32(struct snd_rawmidi_file *rfile, struct snd_rawmidi_status_x32 __user *src) { int err; struct snd_rawmidi_status status; if (rfile->output == NULL) return -EINVAL; if (get_user(status.stream, &src->stream)) return -EFAULT; switch (status.stream) { case SNDRV_RAWMIDI_STREAM_OUTPUT: err = snd_rawmidi_output_status(rfile->output, &status); break; case SNDRV_RAWMIDI_STREAM_INPUT: err = snd_rawmidi_input_status(rfile->input, &status); break; default: return -EINVAL; } if (err < 0) return err; if (put_timespec(&status.tstamp, &src->tstamp) || put_user(status.avail, &src->avail) || put_user(status.xruns, &src->xruns)) return -EFAULT; return 0; } #endif /* CONFIG_X86_X32 */ enum { enum { SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32), SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32), SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32), SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32), #ifdef CONFIG_X86_X32 SNDRV_RAWMIDI_IOCTL_STATUS_X32 = _IOWR('W', 0x20, struct snd_rawmidi_status_x32), #endif /* CONFIG_X86_X32 */ }; }; static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) Loading @@ -115,6 +163,10 @@ static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsign return snd_rawmidi_ioctl_params_compat(rfile, argp); return snd_rawmidi_ioctl_params_compat(rfile, argp); case SNDRV_RAWMIDI_IOCTL_STATUS32: case SNDRV_RAWMIDI_IOCTL_STATUS32: return snd_rawmidi_ioctl_status_compat(rfile, argp); return snd_rawmidi_ioctl_status_compat(rfile, argp); #ifdef CONFIG_X86_X32 case SNDRV_RAWMIDI_IOCTL_STATUS_X32: return snd_rawmidi_ioctl_status_x32(rfile, argp); #endif /* CONFIG_X86_X32 */ } } return -ENOIOCTLCMD; return -ENOIOCTLCMD; } } sound/core/timer_compat.c +16 −2 Original line number Original line Diff line number Diff line Loading @@ -70,13 +70,14 @@ static int snd_timer_user_status_compat(struct file *file, struct snd_timer_status32 __user *_status) struct snd_timer_status32 __user *_status) { { struct snd_timer_user *tu; struct snd_timer_user *tu; struct snd_timer_status status; struct snd_timer_status32 status; tu = file->private_data; tu = file->private_data; if (snd_BUG_ON(!tu->timeri)) if (snd_BUG_ON(!tu->timeri)) return -ENXIO; return -ENXIO; memset(&status, 0, sizeof(status)); memset(&status, 0, sizeof(status)); status.tstamp = tu->tstamp; status.tstamp.tv_sec = tu->tstamp.tv_sec; status.tstamp.tv_nsec = tu->tstamp.tv_nsec; status.resolution = snd_timer_resolution(tu->timeri); status.resolution = snd_timer_resolution(tu->timeri); status.lost = tu->timeri->lost; status.lost = tu->timeri->lost; status.overrun = tu->overrun; status.overrun = tu->overrun; Loading @@ -88,12 +89,21 @@ static int snd_timer_user_status_compat(struct file *file, return 0; return 0; } } #ifdef CONFIG_X86_X32 /* X32 ABI has the same struct as x86-64 */ #define snd_timer_user_status_x32(file, s) \ snd_timer_user_status(file, s) #endif /* CONFIG_X86_X32 */ /* /* */ */ enum { enum { SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32), SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32), SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32), SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32), #ifdef CONFIG_X86_X32 SNDRV_TIMER_IOCTL_STATUS_X32 = _IOW('T', 0x14, struct snd_timer_status), #endif /* CONFIG_X86_X32 */ }; }; static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) Loading Loading @@ -122,6 +132,10 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns return snd_timer_user_info_compat(file, argp); return snd_timer_user_info_compat(file, argp); case SNDRV_TIMER_IOCTL_STATUS32: case SNDRV_TIMER_IOCTL_STATUS32: return snd_timer_user_status_compat(file, argp); return snd_timer_user_status_compat(file, argp); #ifdef CONFIG_X86_X32 case SNDRV_TIMER_IOCTL_STATUS_X32: return snd_timer_user_status_x32(file, argp); #endif /* CONFIG_X86_X32 */ } } return -ENOIOCTLCMD; return -ENOIOCTLCMD; } } Loading
sound/core/control_compat.c +74 −16 Original line number Original line Diff line number Diff line Loading @@ -170,6 +170,19 @@ struct snd_ctl_elem_value32 { unsigned char reserved[128]; unsigned char reserved[128]; }; }; #ifdef CONFIG_X86_X32 /* x32 has a different alignment for 64bit values from ia32 */ struct snd_ctl_elem_value_x32 { struct snd_ctl_elem_id id; unsigned int indirect; /* bit-field causes misalignment */ union { s32 integer[128]; unsigned char data[512]; s64 integer64[64]; } value; unsigned char reserved[128]; }; #endif /* CONFIG_X86_X32 */ /* get the value type and count of the control */ /* get the value type and count of the control */ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, Loading Loading @@ -219,9 +232,11 @@ static int get_elem_size(int type, int count) static int copy_ctl_value_from_user(struct snd_card *card, static int copy_ctl_value_from_user(struct snd_card *card, struct snd_ctl_elem_value *data, struct snd_ctl_elem_value *data, struct snd_ctl_elem_value32 __user *data32, void __user *userdata, void __user *valuep, int *typep, int *countp) int *typep, int *countp) { { struct snd_ctl_elem_value32 __user *data32 = userdata; int i, type, size; int i, type, size; int uninitialized_var(count); int uninitialized_var(count); unsigned int indirect; unsigned int indirect; Loading @@ -239,8 +254,9 @@ static int copy_ctl_value_from_user(struct snd_card *card, if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || type == SNDRV_CTL_ELEM_TYPE_INTEGER) { type == SNDRV_CTL_ELEM_TYPE_INTEGER) { for (i = 0; i < count; i++) { for (i = 0; i < count; i++) { s32 __user *intp = valuep; int val; int val; if (get_user(val, &data32->value.integer[i])) if (get_user(val, &intp[i])) return -EFAULT; return -EFAULT; data->value.integer.value[i] = val; data->value.integer.value[i] = val; } } Loading @@ -250,8 +266,7 @@ static int copy_ctl_value_from_user(struct snd_card *card, dev_err(card->dev, "snd_ioctl32_ctl_elem_value: unknown type %d\n", type); dev_err(card->dev, "snd_ioctl32_ctl_elem_value: unknown type %d\n", type); return -EINVAL; return -EINVAL; } } if (copy_from_user(data->value.bytes.data, if (copy_from_user(data->value.bytes.data, valuep, size)) data32->value.data, size)) return -EFAULT; return -EFAULT; } } Loading @@ -261,7 +276,8 @@ static int copy_ctl_value_from_user(struct snd_card *card, } } /* restore the value to 32bit */ /* restore the value to 32bit */ static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32, static int copy_ctl_value_to_user(void __user *userdata, void __user *valuep, struct snd_ctl_elem_value *data, struct snd_ctl_elem_value *data, int type, int count) int type, int count) { { Loading @@ -270,22 +286,22 @@ static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32, if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || type == SNDRV_CTL_ELEM_TYPE_INTEGER) { type == SNDRV_CTL_ELEM_TYPE_INTEGER) { for (i = 0; i < count; i++) { for (i = 0; i < count; i++) { s32 __user *intp = valuep; int val; int val; val = data->value.integer.value[i]; val = data->value.integer.value[i]; if (put_user(val, &data32->value.integer[i])) if (put_user(val, &intp[i])) return -EFAULT; return -EFAULT; } } } else { } else { size = get_elem_size(type, count); size = get_elem_size(type, count); if (copy_to_user(data32->value.data, if (copy_to_user(valuep, data->value.bytes.data, size)) data->value.bytes.data, size)) return -EFAULT; return -EFAULT; } } return 0; return 0; } } static int snd_ctl_elem_read_user_compat(struct snd_card *card, static int ctl_elem_read_user(struct snd_card *card, struct snd_ctl_elem_value32 __user *data32) void __user *userdata, void __user *valuep) { { struct snd_ctl_elem_value *data; struct snd_ctl_elem_value *data; int err, type, count; int err, type, count; Loading @@ -294,7 +310,9 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card, if (data == NULL) if (data == NULL) return -ENOMEM; return -ENOMEM; if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0) err = copy_ctl_value_from_user(card, data, userdata, valuep, &type, &count); if (err < 0) goto error; goto error; snd_power_lock(card); snd_power_lock(card); Loading @@ -303,14 +321,15 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card, err = snd_ctl_elem_read(card, data); err = snd_ctl_elem_read(card, data); snd_power_unlock(card); snd_power_unlock(card); if (err >= 0) if (err >= 0) err = copy_ctl_value_to_user(data32, data, type, count); err = copy_ctl_value_to_user(userdata, valuep, data, type, count); error: error: kfree(data); kfree(data); return err; return err; } } static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, static int ctl_elem_write_user(struct snd_ctl_file *file, struct snd_ctl_elem_value32 __user *data32) void __user *userdata, void __user *valuep) { { struct snd_ctl_elem_value *data; struct snd_ctl_elem_value *data; struct snd_card *card = file->card; struct snd_card *card = file->card; Loading @@ -320,7 +339,9 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, if (data == NULL) if (data == NULL) return -ENOMEM; return -ENOMEM; if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0) err = copy_ctl_value_from_user(card, data, userdata, valuep, &type, &count); if (err < 0) goto error; goto error; snd_power_lock(card); snd_power_lock(card); Loading @@ -329,12 +350,39 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, err = snd_ctl_elem_write(card, file, data); err = snd_ctl_elem_write(card, file, data); snd_power_unlock(card); snd_power_unlock(card); if (err >= 0) if (err >= 0) err = copy_ctl_value_to_user(data32, data, type, count); err = copy_ctl_value_to_user(userdata, valuep, data, type, count); error: error: kfree(data); kfree(data); return err; return err; } } static int snd_ctl_elem_read_user_compat(struct snd_card *card, struct snd_ctl_elem_value32 __user *data32) { return ctl_elem_read_user(card, data32, &data32->value); } static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, struct snd_ctl_elem_value32 __user *data32) { return ctl_elem_write_user(file, data32, &data32->value); } #ifdef CONFIG_X86_X32 static int snd_ctl_elem_read_user_x32(struct snd_card *card, struct snd_ctl_elem_value_x32 __user *data32) { return ctl_elem_read_user(card, data32, &data32->value); } static int snd_ctl_elem_write_user_x32(struct snd_ctl_file *file, struct snd_ctl_elem_value_x32 __user *data32) { return ctl_elem_write_user(file, data32, &data32->value); } #endif /* CONFIG_X86_X32 */ /* add or replace a user control */ /* add or replace a user control */ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, struct snd_ctl_elem_info32 __user *data32, struct snd_ctl_elem_info32 __user *data32, Loading Loading @@ -393,6 +441,10 @@ enum { SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32), SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32), SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32), SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32), SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32), SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32), #ifdef CONFIG_X86_X32 SNDRV_CTL_IOCTL_ELEM_READ_X32 = _IOWR('U', 0x12, struct snd_ctl_elem_value_x32), SNDRV_CTL_IOCTL_ELEM_WRITE_X32 = _IOWR('U', 0x13, struct snd_ctl_elem_value_x32), #endif /* CONFIG_X86_X32 */ }; }; static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) Loading Loading @@ -431,6 +483,12 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns return snd_ctl_elem_add_compat(ctl, argp, 0); return snd_ctl_elem_add_compat(ctl, argp, 0); case SNDRV_CTL_IOCTL_ELEM_REPLACE32: case SNDRV_CTL_IOCTL_ELEM_REPLACE32: return snd_ctl_elem_add_compat(ctl, argp, 1); return snd_ctl_elem_add_compat(ctl, argp, 1); #ifdef CONFIG_X86_X32 case SNDRV_CTL_IOCTL_ELEM_READ_X32: return snd_ctl_elem_read_user_x32(ctl->card, argp); case SNDRV_CTL_IOCTL_ELEM_WRITE_X32: return snd_ctl_elem_write_user_x32(ctl, argp); #endif /* CONFIG_X86_X32 */ } } down_read(&snd_ioctl_rwsem); down_read(&snd_ioctl_rwsem); Loading
sound/core/pcm_compat.c +176 −1 Original line number Original line Diff line number Diff line Loading @@ -183,6 +183,14 @@ static int snd_pcm_ioctl_channel_info_compat(struct snd_pcm_substream *substream return err; return err; } } #ifdef CONFIG_X86_X32 /* X32 ABI has the same struct as x86-64 for snd_pcm_channel_info */ static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream, struct snd_pcm_channel_info __user *src); #define snd_pcm_ioctl_channel_info_x32(s, p) \ snd_pcm_channel_info_user(s, p) #endif /* CONFIG_X86_X32 */ struct snd_pcm_status32 { struct snd_pcm_status32 { s32 state; s32 state; struct compat_timespec trigger_tstamp; struct compat_timespec trigger_tstamp; Loading Loading @@ -243,6 +251,71 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, return err; return err; } } #ifdef CONFIG_X86_X32 /* X32 ABI has 64bit timespec and 64bit alignment */ struct snd_pcm_status_x32 { s32 state; u32 rsvd; /* alignment */ struct timespec trigger_tstamp; struct timespec tstamp; u32 appl_ptr; u32 hw_ptr; s32 delay; u32 avail; u32 avail_max; u32 overrange; s32 suspended_state; u32 audio_tstamp_data; struct timespec audio_tstamp; struct timespec driver_tstamp; u32 audio_tstamp_accuracy; unsigned char reserved[52-2*sizeof(struct timespec)]; } __packed; #define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst)) static int snd_pcm_status_user_x32(struct snd_pcm_substream *substream, struct snd_pcm_status_x32 __user *src, bool ext) { struct snd_pcm_status status; int err; memset(&status, 0, sizeof(status)); /* * with extension, parameters are read/write, * get audio_tstamp_data from user, * ignore rest of status structure */ if (ext && get_user(status.audio_tstamp_data, (u32 __user *)(&src->audio_tstamp_data))) return -EFAULT; err = snd_pcm_status(substream, &status); if (err < 0) return err; if (clear_user(src, sizeof(*src))) return -EFAULT; if (put_user(status.state, &src->state) || put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) || put_timespec(&status.tstamp, &src->tstamp) || put_user(status.appl_ptr, &src->appl_ptr) || put_user(status.hw_ptr, &src->hw_ptr) || put_user(status.delay, &src->delay) || put_user(status.avail, &src->avail) || put_user(status.avail_max, &src->avail_max) || put_user(status.overrange, &src->overrange) || put_user(status.suspended_state, &src->suspended_state) || put_user(status.audio_tstamp_data, &src->audio_tstamp_data) || put_timespec(&status.audio_tstamp, &src->audio_tstamp) || put_timespec(&status.driver_tstamp, &src->driver_tstamp) || put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy)) return -EFAULT; return err; } #endif /* CONFIG_X86_X32 */ /* both for HW_PARAMS and HW_REFINE */ /* both for HW_PARAMS and HW_REFINE */ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, int refine, int refine, Loading Loading @@ -469,6 +542,93 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream, return 0; return 0; } } #ifdef CONFIG_X86_X32 /* X32 ABI has 64bit timespec and 64bit alignment */ struct snd_pcm_mmap_status_x32 { s32 state; s32 pad1; u32 hw_ptr; u32 pad2; /* alignment */ struct timespec tstamp; s32 suspended_state; struct timespec audio_tstamp; } __packed; struct snd_pcm_mmap_control_x32 { u32 appl_ptr; u32 avail_min; }; struct snd_pcm_sync_ptr_x32 { u32 flags; u32 rsvd; /* alignment */ union { struct snd_pcm_mmap_status_x32 status; unsigned char reserved[64]; } s; union { struct snd_pcm_mmap_control_x32 control; unsigned char reserved[64]; } c; } __packed; static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream, struct snd_pcm_sync_ptr_x32 __user *src) { struct snd_pcm_runtime *runtime = substream->runtime; volatile struct snd_pcm_mmap_status *status; volatile struct snd_pcm_mmap_control *control; u32 sflags; struct snd_pcm_mmap_control scontrol; struct snd_pcm_mmap_status sstatus; snd_pcm_uframes_t boundary; int err; if (snd_BUG_ON(!runtime)) return -EINVAL; if (get_user(sflags, &src->flags) || get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || get_user(scontrol.avail_min, &src->c.control.avail_min)) return -EFAULT; if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) { err = snd_pcm_hwsync(substream); if (err < 0) return err; } status = runtime->status; control = runtime->control; boundary = recalculate_boundary(runtime); if (!boundary) boundary = 0x7fffffff; snd_pcm_stream_lock_irq(substream); /* FIXME: we should consider the boundary for the sync from app */ if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) control->appl_ptr = scontrol.appl_ptr; else scontrol.appl_ptr = control->appl_ptr % boundary; if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) control->avail_min = scontrol.avail_min; else scontrol.avail_min = control->avail_min; sstatus.state = status->state; sstatus.hw_ptr = status->hw_ptr % boundary; sstatus.tstamp = status->tstamp; sstatus.suspended_state = status->suspended_state; sstatus.audio_tstamp = status->audio_tstamp; snd_pcm_stream_unlock_irq(substream); if (put_user(sstatus.state, &src->s.status.state) || put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) || put_timespec(&sstatus.tstamp, &src->s.status.tstamp) || put_user(sstatus.suspended_state, &src->s.status.suspended_state) || put_timespec(&sstatus.audio_tstamp, &src->s.status.audio_tstamp) || put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || put_user(scontrol.avail_min, &src->c.control.avail_min)) return -EFAULT; return 0; } #endif /* CONFIG_X86_X32 */ /* /* */ */ Loading @@ -487,7 +647,12 @@ enum { SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32), SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32), SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32), SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32), SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32), SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32), #ifdef CONFIG_X86_X32 SNDRV_PCM_IOCTL_CHANNEL_INFO_X32 = _IOR('A', 0x32, struct snd_pcm_channel_info), SNDRV_PCM_IOCTL_STATUS_X32 = _IOR('A', 0x20, struct snd_pcm_status_x32), SNDRV_PCM_IOCTL_STATUS_EXT_X32 = _IOWR('A', 0x24, struct snd_pcm_status_x32), SNDRV_PCM_IOCTL_SYNC_PTR_X32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr_x32), #endif /* CONFIG_X86_X32 */ }; }; static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) Loading Loading @@ -559,6 +724,16 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l return snd_pcm_ioctl_rewind_compat(substream, argp); return snd_pcm_ioctl_rewind_compat(substream, argp); case SNDRV_PCM_IOCTL_FORWARD32: case SNDRV_PCM_IOCTL_FORWARD32: return snd_pcm_ioctl_forward_compat(substream, argp); return snd_pcm_ioctl_forward_compat(substream, argp); #ifdef CONFIG_X86_X32 case SNDRV_PCM_IOCTL_STATUS_X32: return snd_pcm_status_user_x32(substream, argp, false); case SNDRV_PCM_IOCTL_STATUS_EXT_X32: return snd_pcm_status_user_x32(substream, argp, true); case SNDRV_PCM_IOCTL_SYNC_PTR_X32: return snd_pcm_ioctl_sync_ptr_x32(substream, argp); case SNDRV_PCM_IOCTL_CHANNEL_INFO_X32: return snd_pcm_ioctl_channel_info_x32(substream, argp); #endif /* CONFIG_X86_X32 */ } } return -ENOIOCTLCMD; return -ENOIOCTLCMD; Loading
sound/core/rawmidi_compat.c +54 −2 Original line number Original line Diff line number Diff line Loading @@ -85,8 +85,7 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, if (err < 0) if (err < 0) return err; return err; if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) || if (compat_put_timespec(&status.tstamp, &src->tstamp) || put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) || put_user(status.avail, &src->avail) || put_user(status.avail, &src->avail) || put_user(status.xruns, &src->xruns)) put_user(status.xruns, &src->xruns)) return -EFAULT; return -EFAULT; Loading @@ -94,9 +93,58 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, return 0; return 0; } } #ifdef CONFIG_X86_X32 /* X32 ABI has 64bit timespec and 64bit alignment */ struct snd_rawmidi_status_x32 { s32 stream; u32 rsvd; /* alignment */ struct timespec tstamp; u32 avail; u32 xruns; unsigned char reserved[16]; } __attribute__((packed)); #define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst)) static int snd_rawmidi_ioctl_status_x32(struct snd_rawmidi_file *rfile, struct snd_rawmidi_status_x32 __user *src) { int err; struct snd_rawmidi_status status; if (rfile->output == NULL) return -EINVAL; if (get_user(status.stream, &src->stream)) return -EFAULT; switch (status.stream) { case SNDRV_RAWMIDI_STREAM_OUTPUT: err = snd_rawmidi_output_status(rfile->output, &status); break; case SNDRV_RAWMIDI_STREAM_INPUT: err = snd_rawmidi_input_status(rfile->input, &status); break; default: return -EINVAL; } if (err < 0) return err; if (put_timespec(&status.tstamp, &src->tstamp) || put_user(status.avail, &src->avail) || put_user(status.xruns, &src->xruns)) return -EFAULT; return 0; } #endif /* CONFIG_X86_X32 */ enum { enum { SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32), SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32), SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32), SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32), #ifdef CONFIG_X86_X32 SNDRV_RAWMIDI_IOCTL_STATUS_X32 = _IOWR('W', 0x20, struct snd_rawmidi_status_x32), #endif /* CONFIG_X86_X32 */ }; }; static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) Loading @@ -115,6 +163,10 @@ static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsign return snd_rawmidi_ioctl_params_compat(rfile, argp); return snd_rawmidi_ioctl_params_compat(rfile, argp); case SNDRV_RAWMIDI_IOCTL_STATUS32: case SNDRV_RAWMIDI_IOCTL_STATUS32: return snd_rawmidi_ioctl_status_compat(rfile, argp); return snd_rawmidi_ioctl_status_compat(rfile, argp); #ifdef CONFIG_X86_X32 case SNDRV_RAWMIDI_IOCTL_STATUS_X32: return snd_rawmidi_ioctl_status_x32(rfile, argp); #endif /* CONFIG_X86_X32 */ } } return -ENOIOCTLCMD; return -ENOIOCTLCMD; } }
sound/core/timer_compat.c +16 −2 Original line number Original line Diff line number Diff line Loading @@ -70,13 +70,14 @@ static int snd_timer_user_status_compat(struct file *file, struct snd_timer_status32 __user *_status) struct snd_timer_status32 __user *_status) { { struct snd_timer_user *tu; struct snd_timer_user *tu; struct snd_timer_status status; struct snd_timer_status32 status; tu = file->private_data; tu = file->private_data; if (snd_BUG_ON(!tu->timeri)) if (snd_BUG_ON(!tu->timeri)) return -ENXIO; return -ENXIO; memset(&status, 0, sizeof(status)); memset(&status, 0, sizeof(status)); status.tstamp = tu->tstamp; status.tstamp.tv_sec = tu->tstamp.tv_sec; status.tstamp.tv_nsec = tu->tstamp.tv_nsec; status.resolution = snd_timer_resolution(tu->timeri); status.resolution = snd_timer_resolution(tu->timeri); status.lost = tu->timeri->lost; status.lost = tu->timeri->lost; status.overrun = tu->overrun; status.overrun = tu->overrun; Loading @@ -88,12 +89,21 @@ static int snd_timer_user_status_compat(struct file *file, return 0; return 0; } } #ifdef CONFIG_X86_X32 /* X32 ABI has the same struct as x86-64 */ #define snd_timer_user_status_x32(file, s) \ snd_timer_user_status(file, s) #endif /* CONFIG_X86_X32 */ /* /* */ */ enum { enum { SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32), SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32), SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32), SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32), #ifdef CONFIG_X86_X32 SNDRV_TIMER_IOCTL_STATUS_X32 = _IOW('T', 0x14, struct snd_timer_status), #endif /* CONFIG_X86_X32 */ }; }; static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) Loading Loading @@ -122,6 +132,10 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns return snd_timer_user_info_compat(file, argp); return snd_timer_user_info_compat(file, argp); case SNDRV_TIMER_IOCTL_STATUS32: case SNDRV_TIMER_IOCTL_STATUS32: return snd_timer_user_status_compat(file, argp); return snd_timer_user_status_compat(file, argp); #ifdef CONFIG_X86_X32 case SNDRV_TIMER_IOCTL_STATUS_X32: return snd_timer_user_status_x32(file, argp); #endif /* CONFIG_X86_X32 */ } } return -ENOIOCTLCMD; return -ENOIOCTLCMD; } }