--- /dev/null
+Index: alsa-kernel/core/ioctl32/hwdep32.c
+===================================================================
+RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/ioctl32/hwdep32.c,v
+retrieving revision 1.10
+diff -u -r1.10 hwdep32.c
+--- alsa-kernel/core/ioctl32/hwdep32.c 18 Oct 2004 14:31:33 -0000 1.10
++++ alsa-kernel/core/ioctl32/hwdep32.c 23 Nov 2004 14:22:41 -0000
+@@ -36,24 +36,24 @@
+
+ static inline int _snd_ioctl32_hwdep_dsp_image(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+ {
+- struct sndrv_hwdep_dsp_image data;
+- struct sndrv_hwdep_dsp_image32 data32;
+- mm_segment_t oldseg;
+- int err;
++ struct sndrv_hwdep_dsp_image __user *data, *dst;
++ struct sndrv_hwdep_dsp_image32 __user *data32, *src;
++ compat_caddr_t ptr;
+
+- if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))
++ data32 = compat_ptr(arg);
++ data = compat_alloc_user_space(sizeof(*data));
++
++ /* index and name */
++ if (copy_in_user(data, data32, 4 + 64))
++ return -EFAULT;
++ if (__get_user(ptr, &data32->image) ||
++ __put_user(compat_ptr(ptr), &data->image))
+ return -EFAULT;
+- memset(&data, 0, sizeof(data));
+- data.index = data32.index;
+- memcpy(data.name, data32.name, sizeof(data.name));
+- data.image = compat_ptr(data32.image);
+- data.length = data32.length;
+- data.driver_data = data32.driver_data;
+- oldseg = get_fs();
+- set_fs(KERNEL_DS);
+- err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);
+- set_fs(oldseg);
+- return err;
++ src = data32;
++ dst = data;
++ COPY_CVT(length);
++ COPY_CVT(driver_data);
++ return file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+ }
+
+ DEFINE_ALSA_IOCTL_ENTRY(hwdep_dsp_image, hwdep_dsp_image, SNDRV_HWDEP_IOCTL_DSP_LOAD);
+Index: alsa-kernel/core/ioctl32/ioctl32.c
+===================================================================
+RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/ioctl32/ioctl32.c,v
+retrieving revision 1.27
+diff -u -r1.27 ioctl32.c
+--- alsa-kernel/core/ioctl32/ioctl32.c 18 Oct 2004 14:31:33 -0000 1.27
++++ alsa-kernel/core/ioctl32/ioctl32.c 23 Nov 2004 14:13:47 -0000
+@@ -93,43 +93,28 @@
+ unsigned char reserved[50];
+ } /* don't set packed attribute here */;
+
+-#define CVT_sndrv_ctl_elem_list()\
+-{\
+- COPY(offset);\
+- COPY(space);\
+- COPY(used);\
+- COPY(count);\
+- CPTR(pids);\
+-}
+-
+ static inline int _snd_ioctl32_ctl_elem_list(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+ {
+- struct sndrv_ctl_elem_list32 data32;
+- struct sndrv_ctl_elem_list data;
+- mm_segment_t oldseg;
++ struct sndrv_ctl_elem_list32 __user *data32;
++ struct sndrv_ctl_elem_list __user *data;
++ compat_caddr_t ptr;
+ int err;
+
+- if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))
++ data32 = compat_ptr(arg);
++ data = compat_alloc_user_space(sizeof(*data));
++
++ /* offset, space, used, count */
++ if (copy_in_user(data, data32, 4 * 4))
+ return -EFAULT;
+- memset(&data, 0, sizeof(data));
+- data.offset = data32.offset;
+- data.space = data32.space;
+- data.used = data32.used;
+- data.count = data32.count;
+- data.pids = compat_ptr(data32.pids);
+- oldseg = get_fs();
+- set_fs(KERNEL_DS);
+- err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);
+- set_fs(oldseg);
++ /* pids */
++ if (__get_user(ptr, &data32->pids) ||
++ __put_user(compat_ptr(ptr), &data->pids))
++ return -EFAULT;
++ err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+ if (err < 0)
+ return err;
+ /* copy the result */
+- data32.offset = data.offset;
+- data32.space = data.space;
+- data32.used = data.used;
+- data32.count = data.count;
+- //data.pids = data.pids;
+- if (copy_to_user((void __user *)arg, &data32, sizeof(data32)))
++ if (copy_in_user(data32, data, 4 * 4))
+ return -EFAULT;
+ return 0;
+ }
+@@ -170,54 +155,57 @@
+
+ static inline int _snd_ioctl32_ctl_elem_info(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+ {
+- struct sndrv_ctl_elem_info data;
+- struct sndrv_ctl_elem_info32 data32;
++ struct sndrv_ctl_elem_info __user *data, *src;
++ struct sndrv_ctl_elem_info32 __user *data32, *dst;
++ unsigned int type;
+ int err;
+- mm_segment_t oldseg;
+
+- if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))
++ data32 = compat_ptr(arg);
++ data = compat_alloc_user_space(sizeof(*data));
++
++ /* copy id */
++ if (copy_in_user(&data->id, &data32->id, sizeof(data->id)))
+ return -EFAULT;
+- memset(&data, 0, sizeof(data));
+- data.id = data32.id;
+ /* we need to copy the item index.
+ * hope this doesn't break anything..
+ */
+- data.value.enumerated.item = data32.value.enumerated.item;
+- oldseg = get_fs();
+- set_fs(KERNEL_DS);
+- err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);
+- set_fs(oldseg);
++ if (__copy_in_user(&data->value.enumerated.item,
++ &data32->value.enumerated.item, 4))
++ return -EFAULT;
++ err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+ if (err < 0)
+ return err;
+ /* restore info to 32bit */
+- data32.id = data.id;
+- data32.type = data.type;
+- data32.access = data.access;
+- data32.count = data.count;
+- data32.owner = data.owner;
+- switch (data.type) {
++ /* id, type, access, count */
++ if (copy_in_user(data32, data, 4 * 4))
++ return -EFAULT;
++ /* for COPY_CVT macro */
++ src = data;
++ dst = data32;
++ COPY_CVT(owner);
++ __get_user(type, &data->type);
++ switch (type) {
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+ case SNDRV_CTL_ELEM_TYPE_INTEGER:
+- data32.value.integer.min = data.value.integer.min;
+- data32.value.integer.max = data.value.integer.max;
+- data32.value.integer.step = data.value.integer.step;
++ COPY_CVT(value.integer.min);
++ COPY_CVT(value.integer.max);
++ COPY_CVT(value.integer.step);
+ break;
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+- data32.value.integer64.min = data.value.integer64.min;
+- data32.value.integer64.max = data.value.integer64.max;
+- data32.value.integer64.step = data.value.integer64.step;
++ if (__copy_in_user(&data32->value.integer64,
++ &data->value.integer64,
++ sizeof(data->value.integer64)))
++ return -EFAULT;
+ break;
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+- data32.value.enumerated.items = data.value.enumerated.items;
+- data32.value.enumerated.item = data.value.enumerated.item;
+- memcpy(data32.value.enumerated.name, data.value.enumerated.name,
+- sizeof(data.value.enumerated.name));
++ if (__copy_in_user(&data32->value.enumerated,
++ &data->value.enumerated,
++ sizeof(data->value.enumerated)))
++ return -EFAULT;
+ break;
+ default:
+ break;
+ }
+- if (copy_to_user((void __user *)arg, &data32, sizeof(data32)))
+- return -EFAULT;
+ return 0;
+ }
+
+@@ -277,60 +265,85 @@
+ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+ {
+ struct sndrv_ctl_elem_value *data;
+- struct sndrv_ctl_elem_value32 *data32;
++ struct sndrv_ctl_elem_value32 __user *data32;
++ mm_segment_t oldseg;
+ int err, i;
+ int type;
+- mm_segment_t oldseg;
+
+ /* FIXME: check the sane ioctl.. */
+
++ data32 = compat_ptr(arg);
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+- data32 = kmalloc(sizeof(*data32), GFP_KERNEL);
+- if (data == NULL || data32 == NULL) {
+- err = -ENOMEM;
++ if (data == NULL)
++ return -ENOMEM;
++
++ if (copy_from_user(&data->id, &data32->id, 4)) {
++ err = -EFAULT;
+ goto __end;
+ }
+-
+- if (copy_from_user(data32, (void __user *)arg, sizeof(*data32))) {
++ if (__get_user(data->indirect, &data32->indirect)) {
+ err = -EFAULT;
+ goto __end;
+ }
+- memset(data, 0, sizeof(*data));
+- data->id = data32->id;
+- data->indirect = data32->indirect;
+- if (data->indirect) /* FIXME: this is not correct for long arrays */
+- data->value.integer.value_ptr = compat_ptr(data32->value.integer.value_ptr);
++ /* FIXME: indirect access is not supported */
++ if (data->indirect) {
++ err = -EINVAL;
++ goto __end;
++ }
+ type = get_ctl_type(file, &data->id);
+ if (type < 0) {
+ err = type;
+ goto __end;
+ }
+- if (! data->indirect) {
+- switch (type) {
+- case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+- case SNDRV_CTL_ELEM_TYPE_INTEGER:
+- for (i = 0; i < 128; i++)
+- data->value.integer.value[i] = data32->value.integer.value[i];
+- break;
+- case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+- for (i = 0; i < 64; i++)
+- data->value.integer64.value[i] = data32->value.integer64.value[i];
+- break;
+- case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+- for (i = 0; i < 128; i++)
+- data->value.enumerated.item[i] = data32->value.enumerated.item[i];
+- break;
+- case SNDRV_CTL_ELEM_TYPE_BYTES:
+- memcpy(data->value.bytes.data, data32->value.bytes.data,
+- sizeof(data->value.bytes.data));
+- break;
+- case SNDRV_CTL_ELEM_TYPE_IEC958:
+- data->value.iec958 = data32->value.iec958;
+- break;
+- default:
+- printk("unknown type %d\n", type);
+- break;
++
++ switch (type) {
++ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
++ case SNDRV_CTL_ELEM_TYPE_INTEGER:
++ for (i = 0; i < 128; i++) {
++ int val;
++ if (__get_user(val, &data32->value.integer.value[i])) {
++ err = -EFAULT;
++ goto __end;
++ }
++ data->value.integer.value[i] = val;
+ }
++ break;
++ case SNDRV_CTL_ELEM_TYPE_INTEGER64:
++ if (__copy_from_user(data->value.integer64.value,
++ data32->value.integer64.value,
++ sizeof(data->value.integer64.value))) {
++ err = -EFAULT;
++ goto __end;
++ }
++ break;
++ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
++ if (__copy_from_user(data->value.enumerated.item,
++ data32->value.enumerated.item,
++ sizeof(data32->value.enumerated.item))) {
++ err = -EFAULT;
++ goto __end;
++ }
++ break;
++ case SNDRV_CTL_ELEM_TYPE_BYTES:
++ if (__copy_from_user(data->value.bytes.data,
++ data32->value.bytes.data,
++ sizeof(data32->value.bytes.data))) {
++ err = -EFAULT;
++ goto __end;
++ }
++ break;
++ case SNDRV_CTL_ELEM_TYPE_IEC958:
++ if (__copy_from_user(&data->value.iec958,
++ &data32->value.iec958,
++ sizeof(data32->value.iec958))) {
++ err = -EFAULT;
++ goto __end;
++ }
++ break;
++ default:
++ printk(KERN_ERR "snd_ioctl32_ctl_elem_value: unknown type %d\n", type);
++ err = -EINVAL;
++ goto __end;
+ }
+
+ oldseg = get_fs();
+@@ -340,38 +353,53 @@
+ if (err < 0)
+ goto __end;
+ /* restore info to 32bit */
+- if (! data->indirect) {
+- switch (type) {
+- case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+- case SNDRV_CTL_ELEM_TYPE_INTEGER:
+- for (i = 0; i < 128; i++)
+- data32->value.integer.value[i] = data->value.integer.value[i];
+- break;
+- case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+- for (i = 0; i < 64; i++)
+- data32->value.integer64.value[i] = data->value.integer64.value[i];
+- break;
+- case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+- for (i = 0; i < 128; i++)
+- data32->value.enumerated.item[i] = data->value.enumerated.item[i];
+- break;
+- case SNDRV_CTL_ELEM_TYPE_BYTES:
+- memcpy(data32->value.bytes.data, data->value.bytes.data,
+- sizeof(data->value.bytes.data));
+- break;
+- case SNDRV_CTL_ELEM_TYPE_IEC958:
+- data32->value.iec958 = data->value.iec958;
+- break;
+- default:
+- break;
++ switch (type) {
++ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
++ case SNDRV_CTL_ELEM_TYPE_INTEGER:
++ for (i = 0; i < 128; i++) {
++ int val;
++ val = data->value.integer.value[i];
++ if (__put_user(val, &data32->value.integer.value[i])) {
++ err = -EFAULT;
++ goto __end;
++ }
++ }
++ break;
++ case SNDRV_CTL_ELEM_TYPE_INTEGER64:
++ if (__copy_to_user(data32->value.integer64.value,
++ data->value.integer64.value,
++ sizeof(data32->value.integer64.value))) {
++ err = -EFAULT;
++ goto __end;
++ }
++ break;
++ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
++ if (__copy_to_user(data32->value.enumerated.item,
++ data->value.enumerated.item,
++ sizeof(data32->value.enumerated.item))) {
++ err = -EFAULT;
++ goto __end;
+ }
++ break;
++ case SNDRV_CTL_ELEM_TYPE_BYTES:
++ if (__copy_to_user(data32->value.bytes.data,
++ data->value.bytes.data,
++ sizeof(data32->value.bytes.data))) {
++ err = -EFAULT;
++ goto __end;
++ }
++ break;
++ case SNDRV_CTL_ELEM_TYPE_IEC958:
++ if (__copy_to_user(&data32->value.iec958,
++ &data->value.iec958,
++ sizeof(data32->value.iec958))) {
++ err = -EFAULT;
++ goto __end;
++ }
++ break;
+ }
+ err = 0;
+- if (copy_to_user((void __user *)arg, data32, sizeof(*data32)))
+- err = -EFAULT;
+ __end:
+- if (data32)
+- kfree(data32);
+ if (data)
+ kfree(data);
+ return err;
+Index: alsa-kernel/core/ioctl32/ioctl32.h
+===================================================================
+RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/ioctl32/ioctl32.h,v
+retrieving revision 1.14
+diff -u -r1.14 ioctl32.h
+--- alsa-kernel/core/ioctl32/ioctl32.h 18 Oct 2004 14:31:33 -0000 1.14
++++ alsa-kernel/core/ioctl32/ioctl32.h 23 Nov 2004 14:12:15 -0000
+@@ -28,20 +28,37 @@
+
+ #include <linux/compat.h>
+
+-#define COPY(x) (dst->x = src->x)
+-#define CPTR(x) (dst->x = compat_ptr(src->x))
++#define COPY(x) \
++ do { \
++ if (copy_in_user(&dst->x, &src->x, sizeof(dst->x))) \
++ return -EFAULT; \
++ } while (0)
++
++#define COPY_ARRAY(x) \
++ do { \
++ if (copy_in_user(dst->x, src->x, sizeof(dst->x))) \
++ return -EFAULT; \
++ } while (0)
++
++#define COPY_CVT(x) \
++ do { \
++ __typeof__(src->x) __val_tmp; \
++ if (get_user(__val_tmp, &src->x) || \
++ put_user(__val_tmp, &dst->x))\
++ return -EFAULT; \
++ } while (0)
+
+ #define convert_from_32(type, dstp, srcp)\
+ {\
+- struct sndrv_##type *dst = dstp;\
+- struct sndrv_##type##32 *src = srcp;\
++ struct sndrv_##type __user *dst = dstp;\
++ struct sndrv_##type##32 __user *src = srcp;\
+ CVT_##sndrv_##type();\
+ }
+
+ #define convert_to_32(type, dstp, srcp)\
+ {\
+- struct sndrv_##type *src = srcp;\
+- struct sndrv_##type##32 *dst = dstp;\
++ struct sndrv_##type __user *src = srcp;\
++ struct sndrv_##type##32 __user *dst = dstp;\
+ CVT_##sndrv_##type();\
+ }
+
+@@ -49,65 +66,19 @@
+ #define DEFINE_ALSA_IOCTL(type) \
+ static inline int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)\
+ {\
+- struct sndrv_##type##32 data32;\
+- struct sndrv_##type data;\
+- mm_segment_t oldseg;\
++ struct sndrv_##type##32 __user *data32;\
++ struct sndrv_##type __user *data;\
+ int err;\
+- if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))\
+- return -EFAULT;\
+- memset(&data, 0, sizeof(data));\
+- convert_from_32(type, &data, &data32);\
+- oldseg = get_fs();\
+- set_fs(KERNEL_DS);\
+- err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);\
+- set_fs(oldseg);\
+- if (err < 0) \
+- return err;\
+- if (native_ctl & (_IOC_READ << _IOC_DIRSHIFT)) {\
+- convert_to_32(type, &data32, &data);\
+- if (copy_to_user((void __user *)arg, &data32, sizeof(data32)))\
+- return -EFAULT;\
+- }\
+- return 0;\
+-}
+-
+-#define DEFINE_ALSA_IOCTL_BIG(type) \
+-static inline int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)\
+-{\
+- struct sndrv_##type##32 *data32;\
+- struct sndrv_##type *data;\
+- mm_segment_t oldseg;\
+- int err;\
+- data32 = kmalloc(sizeof(*data32), GFP_KERNEL); \
+- data = kmalloc(sizeof(*data), GFP_KERNEL); \
+- if (data32 == NULL || data == NULL) { \
+- err = -ENOMEM; \
+- goto __end; \
+- }\
+- if (copy_from_user(data32, (void __user *)arg, sizeof(*data32))) { \
+- err = -EFAULT; \
+- goto __end; \
+- }\
+- memset(data, 0, sizeof(*data));\
++ data32 = compat_ptr(arg);\
++ data = compat_alloc_user_space(sizeof(*data));\
+ convert_from_32(type, data, data32);\
+- oldseg = get_fs();\
+- set_fs(KERNEL_DS);\
+ err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);\
+- set_fs(oldseg);\
+ if (err < 0) \
+- goto __end;\
+- err = 0;\
++ return err;\
+ if (native_ctl & (_IOC_READ << _IOC_DIRSHIFT)) {\
+ convert_to_32(type, data32, data);\
+- if (copy_to_user((void __user *)arg, data32, sizeof(*data32)))\
+- err = -EFAULT;\
+ }\
+- __end:\
+- if (data)\
+- kfree(data);\
+- if (data32)\
+- kfree(data32);\
+- return err;\
++ return 0;\
+ }
+
+ #define DEFINE_ALSA_IOCTL_ENTRY(name,type,native_ctl) \
+Index: alsa-kernel/core/ioctl32/pcm32.c
+===================================================================
+RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/ioctl32/pcm32.c,v
+retrieving revision 1.25
+diff -u -r1.25 pcm32.c
+--- alsa-kernel/core/ioctl32/pcm32.c 18 Oct 2004 14:36:00 -0000 1.25
++++ alsa-kernel/core/ioctl32/pcm32.c 23 Nov 2004 14:15:56 -0000
+@@ -41,16 +41,13 @@
+ u32 val;
+ };
+
+-#define CVT_sndrv_pcm_sframes_str() { COPY(val); }
+-#define CVT_sndrv_pcm_uframes_str() { COPY(val); }
++#define CVT_sndrv_pcm_sframes_str() { COPY_CVT(val); }
++#define CVT_sndrv_pcm_uframes_str() { COPY_CVT(val); }
+
+
+ struct sndrv_interval32 {
+ u32 min, max;
+- unsigned int openmin:1,
+- openmax:1,
+- integer:1,
+- empty:1;
++ u32 flags; /* bit fields */
+ };
+
+ struct sndrv_pcm_hw_params32 {
+@@ -73,25 +70,9 @@
+
+ #define CVT_sndrv_pcm_hw_params()\
+ {\
+- unsigned int i;\
+- COPY(flags);\
+- for (i = 0; i < numberof(dst->masks); i++)\
+- COPY(masks[i]);\
+- for (i = 0; i < numberof(dst->intervals); i++) {\
+- COPY(intervals[i].min);\
+- COPY(intervals[i].max);\
+- COPY(intervals[i].openmin);\
+- COPY(intervals[i].openmax);\
+- COPY(intervals[i].integer);\
+- COPY(intervals[i].empty);\
+- }\
+- COPY(rmask);\
+- COPY(cmask);\
+- COPY(info);\
+- COPY(msbits);\
+- COPY(rate_num);\
+- COPY(rate_den);\
+- COPY(fifo_size);\
++ if (copy_in_user(dst, src, sizeof(snd_pcm_hw_params_t) - sizeof(sndrv_pcm_uframes_t) - 64)) \
++ return -EFAULT;\
++ COPY_CVT(fifo_size);\
+ }
+
+ struct sndrv_pcm_sw_params32 {
+@@ -113,13 +94,13 @@
+ COPY(tstamp_mode);\
+ COPY(period_step);\
+ COPY(sleep_min);\
+- COPY(avail_min);\
+- COPY(xfer_align);\
+- COPY(start_threshold);\
+- COPY(stop_threshold);\
+- COPY(silence_threshold);\
+- COPY(silence_size);\
+- COPY(boundary);\
++ COPY_CVT(avail_min);\
++ COPY_CVT(xfer_align);\
++ COPY_CVT(start_threshold);\
++ COPY_CVT(stop_threshold);\
++ COPY_CVT(silence_threshold);\
++ COPY_CVT(silence_size);\
++ COPY_CVT(boundary);\
+ }
+
+ struct sndrv_pcm_channel_info32 {
+@@ -132,7 +113,7 @@
+ #define CVT_sndrv_pcm_channel_info()\
+ {\
+ COPY(channel);\
+- COPY(offset);\
++ COPY_CVT(offset);\
+ COPY(first);\
+ COPY(step);\
+ }
+@@ -154,16 +135,16 @@
+ #define CVT_sndrv_pcm_status()\
+ {\
+ COPY(state);\
+- COPY(trigger_tstamp.tv_sec);\
+- COPY(trigger_tstamp.tv_nsec);\
+- COPY(tstamp.tv_sec);\
+- COPY(tstamp.tv_nsec);\
+- COPY(appl_ptr);\
+- COPY(hw_ptr);\
+- COPY(delay);\
+- COPY(avail);\
+- COPY(avail_max);\
+- COPY(overrange);\
++ COPY_CVT(trigger_tstamp.tv_sec);\
++ COPY_CVT(trigger_tstamp.tv_nsec);\
++ COPY_CVT(tstamp.tv_sec);\
++ COPY_CVT(tstamp.tv_nsec);\
++ COPY_CVT(appl_ptr);\
++ COPY_CVT(hw_ptr);\
++ COPY_CVT(delay);\
++ COPY_CVT(avail);\
++ COPY_CVT(avail_max);\
++ COPY_CVT(overrange);\
+ COPY(suspended_state);\
+ }
+
+@@ -194,41 +175,19 @@
+
+ static inline int _snd_ioctl32_pcm_hw_params(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+ {
+- struct sndrv_pcm_hw_params32 *data32;
+- struct sndrv_pcm_hw_params *data;
+- mm_segment_t oldseg;
++ struct sndrv_pcm_hw_params32 __user *data32;
++ struct sndrv_pcm_hw_params __user *data;
+ int err;
+
+- data32 = kmalloc(sizeof(*data32), GFP_KERNEL);
+- data = kmalloc(sizeof(*data), GFP_KERNEL);
+- if (data32 == NULL || data == NULL) {
+- err = -ENOMEM;
+- goto __end;
+- }
+- if (copy_from_user(data32, (void __user *)arg, sizeof(*data32))) {
+- err = -EFAULT;
+- goto __end;
+- }
+- memset(data, 0, sizeof(*data));
++ data32 = compat_ptr(arg);
++ data = compat_alloc_user_space(sizeof(*data));
+ convert_from_32(pcm_hw_params, data, data32);
+- oldseg = get_fs();
+- set_fs(KERNEL_DS);
+ err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+- set_fs(oldseg);
+ if (err < 0)
+- goto __end;
+- err = 0;
++ return err;
+ convert_to_32(pcm_hw_params, data32, data);
+- if (copy_to_user((void __user *)arg, data32, sizeof(*data32)))
+- err = -EFAULT;
+- else
+- recalculate_boundary(file);
+- __end:
+- if (data)
+- kfree(data);
+- if (data32)
+- kfree(data32);
+- return err;
++ recalculate_boundary(file);
++ return 0;
+ }
+
+
+@@ -243,24 +202,24 @@
+ static inline int _snd_ioctl32_xferi(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+ {
+ struct sndrv_xferi32 data32;
+- struct sndrv_xferi data;
+- mm_segment_t oldseg;
++ struct sndrv_xferi __user *data;
++ snd_pcm_sframes_t result;
+ int err;
+
+ if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))
+ return -EFAULT;
+- memset(&data, 0, sizeof(data));
+- data.result = data32.result;
+- data.buf = compat_ptr(data32.buf);
+- data.frames = data32.frames;
+- oldseg = get_fs();
+- set_fs(KERNEL_DS);
+- err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);
+- set_fs(oldseg);
++ data = compat_alloc_user_space(sizeof(*data));
++ if (put_user((snd_pcm_sframes_t)data32.result, &data->result) ||
++ __put_user(compat_ptr(data32.buf), &data->buf) ||
++ __put_user((snd_pcm_uframes_t)data32.frames, &data->frames))
++ return -EFAULT;
++ err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+ if (err < 0)
+ return err;
+ /* copy the result */
+- data32.result = data.result;
++ if (__get_user(result, &data->result))
++ return -EFAULT;
++ data32.result = result;
+ if (copy_to_user((void __user *)arg, &data32, sizeof(data32)))
+ return -EFAULT;
+ return 0;
+@@ -284,12 +243,11 @@
+ {
+ snd_pcm_file_t *pcm_file;
+ snd_pcm_substream_t *substream;
++ struct sndrv_xfern32 __user *srcptr = compat_ptr(arg);
+ struct sndrv_xfern32 data32;
+- struct sndrv_xfern32 __user *srcptr = (void __user *)arg;
+- void __user **bufs = NULL;
++ void __user **bufs;
+ int err = 0, ch, i;
+ u32 __user *bufptr;
+- mm_segment_t oldseg;
+
+ /* FIXME: need to check whether fop->ioctl is sane */
+
+@@ -312,22 +270,21 @@
+ }
+ if ((ch = substream->runtime->channels) > 128)
+ return -EINVAL;
+- if (get_user(data32.frames, &srcptr->frames))
++ if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))
+ return -EFAULT;
+- __get_user(data32.bufs, &srcptr->bufs);
+ bufptr = compat_ptr(data32.bufs);
+- bufs = kmalloc(sizeof(void *) * 128, GFP_KERNEL);
++ bufs = kmalloc(sizeof(void __user *) * ch, GFP_KERNEL);
+ if (bufs == NULL)
+ return -ENOMEM;
+ for (i = 0; i < ch; i++) {
+ u32 ptr;
+- if (get_user(ptr, bufptr))
++ if (get_user(ptr, bufptr)) {
++ kfree(bufs);
+ return -EFAULT;
++ }
+ bufs[ch] = compat_ptr(ptr);
+ bufptr++;
+ }
+- oldseg = get_fs();
+- set_fs(KERNEL_DS);
+ switch (native_ctl) {
+ case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
+ err = snd_pcm_lib_writev(substream, bufs, data32.frames);
+@@ -336,109 +293,15 @@
+ err = snd_pcm_lib_readv(substream, bufs, data32.frames);
+ break;
+ }
+- set_fs(oldseg);
+ if (err >= 0) {
+ if (put_user(err, &srcptr->result))
+ err = -EFAULT;
+ }
+ kfree(bufs);
+- return 0;
+-}
+-
+-
+-struct sndrv_pcm_hw_params_old32 {
+- u32 flags;
+- u32 masks[SNDRV_PCM_HW_PARAM_SUBFORMAT -
+- SNDRV_PCM_HW_PARAM_ACCESS + 1];
+- struct sndrv_interval32 intervals[SNDRV_PCM_HW_PARAM_TICK_TIME -
+- SNDRV_PCM_HW_PARAM_SAMPLE_BITS + 1];
+- u32 rmask;
+- u32 cmask;
+- u32 info;
+- u32 msbits;
+- u32 rate_num;
+- u32 rate_den;
+- u32 fifo_size;
+- unsigned char reserved[64];
+-} __attribute__((packed));
+-
+-#define __OLD_TO_NEW_MASK(x) ((x&7)|((x&0x07fffff8)<<5))
+-#define __NEW_TO_OLD_MASK(x) ((x&7)|((x&0xffffff00)>>5))
+-
+-static void snd_pcm_hw_convert_from_old_params(snd_pcm_hw_params_t *params, struct sndrv_pcm_hw_params_old32 *oparams)
+-{
+- unsigned int i;
+-
+- memset(params, 0, sizeof(*params));
+- params->flags = oparams->flags;
+- for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
+- params->masks[i].bits[0] = oparams->masks[i];
+- memcpy(params->intervals, oparams->intervals, sizeof(oparams->intervals));
+- params->rmask = __OLD_TO_NEW_MASK(oparams->rmask);
+- params->cmask = __OLD_TO_NEW_MASK(oparams->cmask);
+- params->info = oparams->info;
+- params->msbits = oparams->msbits;
+- params->rate_num = oparams->rate_num;
+- params->rate_den = oparams->rate_den;
+- params->fifo_size = oparams->fifo_size;
+-}
+-
+-static void snd_pcm_hw_convert_to_old_params(struct sndrv_pcm_hw_params_old32 *oparams, snd_pcm_hw_params_t *params)
+-{
+- unsigned int i;
+-
+- memset(oparams, 0, sizeof(*oparams));
+- oparams->flags = params->flags;
+- for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
+- oparams->masks[i] = params->masks[i].bits[0];
+- memcpy(oparams->intervals, params->intervals, sizeof(oparams->intervals));
+- oparams->rmask = __NEW_TO_OLD_MASK(params->rmask);
+- oparams->cmask = __NEW_TO_OLD_MASK(params->cmask);
+- oparams->info = params->info;
+- oparams->msbits = params->msbits;
+- oparams->rate_num = params->rate_num;
+- oparams->rate_den = params->rate_den;
+- oparams->fifo_size = params->fifo_size;
+-}
+-
+-static inline int _snd_ioctl32_pcm_hw_params_old(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+-{
+- struct sndrv_pcm_hw_params_old32 *data32;
+- struct sndrv_pcm_hw_params *data;
+- mm_segment_t oldseg;
+- int err;
+-
+- data32 = kcalloc(1, sizeof(*data32), GFP_KERNEL);
+- data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+- if (data32 == NULL || data == NULL) {
+- err = -ENOMEM;
+- goto __end;
+- }
+- if (copy_from_user(data32, (void __user *)arg, sizeof(*data32))) {
+- err = -EFAULT;
+- goto __end;
+- }
+- snd_pcm_hw_convert_from_old_params(data, data32);
+- oldseg = get_fs();
+- set_fs(KERNEL_DS);
+- err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+- set_fs(oldseg);
+- if (err < 0)
+- goto __end;
+- snd_pcm_hw_convert_to_old_params(data32, data);
+- err = 0;
+- if (copy_to_user((void __user *)arg, data32, sizeof(*data32)))
+- err = -EFAULT;
+- else
+- recalculate_boundary(file);
+- __end:
+- if (data)
+- kfree(data);
+- if (data32)
+- kfree(data32);
+ return err;
+ }
+
++
+ struct sndrv_pcm_mmap_status32 {
+ s32 state;
+ s32 pad1;
+@@ -469,15 +332,15 @@
+ COPY(flags);\
+ COPY(s.status.state);\
+ COPY(s.status.pad1);\
+- COPY(s.status.hw_ptr);\
+- COPY(s.status.tstamp.tv_sec);\
+- COPY(s.status.tstamp.tv_nsec);\
++ COPY_CVT(s.status.hw_ptr);\
++ COPY_CVT(s.status.tstamp.tv_sec);\
++ COPY_CVT(s.status.tstamp.tv_nsec);\
+ COPY(s.status.suspended_state);\
+- COPY(c.control.appl_ptr);\
+- COPY(c.control.avail_min);\
++ COPY_CVT(c.control.appl_ptr);\
++ COPY_CVT(c.control.avail_min);\
+ }
+
+-DEFINE_ALSA_IOCTL_BIG(pcm_sync_ptr);
++DEFINE_ALSA_IOCTL(pcm_sync_ptr);
+
+ /*
+ */
+@@ -485,8 +348,6 @@
+ DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_refine, pcm_hw_params, SNDRV_PCM_IOCTL_HW_REFINE);
+ DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_params, pcm_hw_params, SNDRV_PCM_IOCTL_HW_PARAMS);
+ DEFINE_ALSA_IOCTL_ENTRY(pcm_sw_params, pcm_sw_params, SNDRV_PCM_IOCTL_SW_PARAMS);
+-DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_refine_old, pcm_hw_params_old, SNDRV_PCM_IOCTL_HW_REFINE);
+-DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_params_old, pcm_hw_params_old, SNDRV_PCM_IOCTL_HW_PARAMS);
+ DEFINE_ALSA_IOCTL_ENTRY(pcm_status, pcm_status, SNDRV_PCM_IOCTL_STATUS);
+ DEFINE_ALSA_IOCTL_ENTRY(pcm_delay, pcm_sframes_str, SNDRV_PCM_IOCTL_DELAY);
+ DEFINE_ALSA_IOCTL_ENTRY(pcm_channel_info, pcm_channel_info, SNDRV_PCM_IOCTL_CHANNEL_INFO);
+@@ -538,8 +399,6 @@
+ SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct sndrv_xferi32),
+ SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct sndrv_xfern32),
+ SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct sndrv_xfern32),
+- SNDRV_PCM_IOCTL_HW_REFINE_OLD32 = _IOWR('A', 0x10, struct sndrv_pcm_hw_params_old32),
+- SNDRV_PCM_IOCTL_HW_PARAMS_OLD32 = _IOWR('A', 0x11, struct sndrv_pcm_hw_params_old32),
+ SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr32),
+
+ };
+@@ -551,8 +410,6 @@
+ MAP_COMPAT(SNDRV_PCM_IOCTL_TSTAMP),
+ { SNDRV_PCM_IOCTL_HW_REFINE32, AP(pcm_hw_refine) },
+ { SNDRV_PCM_IOCTL_HW_PARAMS32, AP(pcm_hw_params) },
+- { SNDRV_PCM_IOCTL_HW_REFINE_OLD32, AP(pcm_hw_refine_old) },
+- { SNDRV_PCM_IOCTL_HW_PARAMS_OLD32, AP(pcm_hw_params_old) },
+ MAP_COMPAT(SNDRV_PCM_IOCTL_HW_FREE),
+ { SNDRV_PCM_IOCTL_SW_PARAMS32, AP(pcm_sw_params) },
+ { SNDRV_PCM_IOCTL_STATUS32, AP(pcm_status) },
+Index: alsa-kernel/core/ioctl32/rawmidi32.c
+===================================================================
+RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/ioctl32/rawmidi32.c,v
+retrieving revision 1.7
+diff -u -r1.7 rawmidi32.c
+--- alsa-kernel/core/ioctl32/rawmidi32.c 18 Jun 2003 10:34:08 -0000 1.7
++++ alsa-kernel/core/ioctl32/rawmidi32.c 23 Nov 2004 14:21:11 -0000
+@@ -38,9 +38,11 @@
+ #define CVT_sndrv_rawmidi_params()\
+ {\
+ COPY(stream);\
+- COPY(buffer_size);\
+- COPY(avail_min);\
+- COPY(no_active_sensing);\
++ COPY_CVT(buffer_size);\
++ COPY_CVT(avail_min);\
++ if (copy_in_user(((size_t __user *)&dst->avail_min + 1),\
++ ((size_t __user *)&src->avail_min + 1), 4)) \
++ return -EFAULT;\
+ }
+
+ struct sndrv_rawmidi_status32 {
+@@ -54,10 +56,10 @@
+ #define CVT_sndrv_rawmidi_status()\
+ {\
+ COPY(stream);\
+- COPY(tstamp.tv_sec);\
+- COPY(tstamp.tv_nsec);\
+- COPY(avail);\
+- COPY(xruns);\
++ COPY_CVT(tstamp.tv_sec);\
++ COPY_CVT(tstamp.tv_nsec);\
++ COPY_CVT(avail);\
++ COPY_CVT(xruns);\
+ }
+
+ DEFINE_ALSA_IOCTL(rawmidi_params);
+Index: alsa-kernel/core/ioctl32/seq32.c
+===================================================================
+RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/ioctl32/seq32.c,v
+retrieving revision 1.8
+diff -u -r1.8 seq32.c
+--- alsa-kernel/core/ioctl32/seq32.c 6 Feb 2003 17:58:36 -0000 1.8
++++ alsa-kernel/core/ioctl32/seq32.c 23 Nov 2004 14:23:44 -0000
+@@ -42,13 +42,14 @@
+
+ u32 kernel; /* reserved for kernel use (must be NULL) */
+ u32 flags; /* misc. conditioning */
+- char reserved[60]; /* for future use */
++ unsigned char time_queue; /* queue # for timestamping */
++ char reserved[59]; /* for future use */
+ };
+
+ #define CVT_sndrv_seq_port_info()\
+ {\
+ COPY(addr);\
+- memcpy(dst->name, src->name, sizeof(dst->name));\
++ COPY_ARRAY(name);\
+ COPY(capability);\
+ COPY(type);\
+ COPY(midi_channels);\
+@@ -57,6 +58,7 @@
+ COPY(read_use);\
+ COPY(write_use);\
+ COPY(flags);\
++ COPY(time_queue);\
+ }
+
+ DEFINE_ALSA_IOCTL(seq_port_info);
+Index: alsa-kernel/core/ioctl32/timer32.c
+===================================================================
+RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/ioctl32/timer32.c,v
+retrieving revision 1.8
+diff -u -r1.8 timer32.c
+--- alsa-kernel/core/ioctl32/timer32.c 28 Mar 2004 15:57:48 -0000 1.8
++++ alsa-kernel/core/ioctl32/timer32.c 23 Nov 2004 14:12:47 -0000
+@@ -41,9 +41,9 @@
+ {\
+ COPY(flags);\
+ COPY(card);\
+- memcpy(dst->id, src->id, sizeof(src->id));\
+- memcpy(dst->name, src->name, sizeof(src->name));\
+- COPY(resolution);\
++ COPY_ARRAY(id);\
++ COPY_ARRAY(name);\
++ COPY_CVT(resolution);\
+ }
+
+ struct sndrv_timer_status32 {
+@@ -57,8 +57,8 @@
+
+ #define CVT_sndrv_timer_status()\
+ {\
+- COPY(tstamp.tv_sec);\
+- COPY(tstamp.tv_nsec);\
++ COPY_CVT(tstamp.tv_sec);\
++ COPY_CVT(tstamp.tv_nsec);\
+ COPY(resolution);\
+ COPY(lost);\
+ COPY(overrun);\