Commit a5b34076 authored by Jaroslav Kysela's avatar Jaroslav Kysela

[ALSA] Fix ctl_read/write ioctl wrappers

IOCTL32 emulation
Fixed bugs with ctl_read/write ioctls.
The struct size mismatch due to alignment is fixed.
The code is also a bit optimized.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent bdd03b88
...@@ -219,25 +219,10 @@ struct sndrv_ctl_elem_value32 { ...@@ -219,25 +219,10 @@ struct sndrv_ctl_elem_value32 {
struct sndrv_ctl_elem_id id; struct sndrv_ctl_elem_id id;
unsigned int indirect; /* bit-field causes misalignment */ unsigned int indirect; /* bit-field causes misalignment */
union { union {
union { s32 integer[128]; /* integer and boolean need conversion */
s32 value[128]; unsigned char data[512]; /* others should be compatible */
u32 value_ptr;
} integer;
union {
s64 value[64];
u32 value_ptr;
} integer64;
union {
u32 item[128];
u32 item_ptr;
} enumerated;
union {
unsigned char data[512];
u32 data_ptr;
} bytes;
struct sndrv_aes_iec958 iec958;
} value; } value;
unsigned char reserved[128]; unsigned char reserved[128]; /* not used */
}; };
...@@ -269,7 +254,7 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, ...@@ -269,7 +254,7 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd,
struct sndrv_ctl_elem_value *data; struct sndrv_ctl_elem_value *data;
struct sndrv_ctl_elem_value32 __user *data32; struct sndrv_ctl_elem_value32 __user *data32;
snd_ctl_file_t *ctl; snd_ctl_file_t *ctl;
int err, i; int err, i, indirect;
int type; int type;
/* sanity check */ /* sanity check */
...@@ -281,7 +266,7 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, ...@@ -281,7 +266,7 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd,
return -ENOTTY; return -ENOTTY;
data32 = compat_ptr(arg); data32 = compat_ptr(arg);
data = kmalloc(sizeof(*data), GFP_KERNEL); data = kcalloc(1, sizeof(*data), GFP_KERNEL);
if (data == NULL) if (data == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -289,12 +274,12 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, ...@@ -289,12 +274,12 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd,
err = -EFAULT; err = -EFAULT;
goto __end; goto __end;
} }
if (__get_user(data->indirect, &data32->indirect)) { if (__get_user(indirect, &data32->indirect)) {
err = -EFAULT; err = -EFAULT;
goto __end; goto __end;
} }
/* FIXME: indirect access is not supported */ /* FIXME: indirect access is not supported */
if (data->indirect) { if (indirect) {
err = -EINVAL; err = -EINVAL;
goto __end; goto __end;
} }
...@@ -309,7 +294,7 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, ...@@ -309,7 +294,7 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd,
case SNDRV_CTL_ELEM_TYPE_INTEGER: case SNDRV_CTL_ELEM_TYPE_INTEGER:
for (i = 0; i < 128; i++) { for (i = 0; i < 128; i++) {
int val; int val;
if (__get_user(val, &data32->value.integer.value[i])) { if (__get_user(val, &data32->value.integer[i])) {
err = -EFAULT; err = -EFAULT;
goto __end; goto __end;
} }
...@@ -317,33 +302,12 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, ...@@ -317,33 +302,12 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd,
} }
break; break;
case SNDRV_CTL_ELEM_TYPE_INTEGER64: 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: 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: 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: case SNDRV_CTL_ELEM_TYPE_IEC958:
if (__copy_from_user(&data->value.iec958, if (__copy_from_user(data->value.bytes.data,
&data32->value.iec958, data32->value.data,
sizeof(data32->value.iec958))) { sizeof(data32->value.data))) {
err = -EFAULT; err = -EFAULT;
goto __end; goto __end;
} }
...@@ -367,43 +331,20 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, ...@@ -367,43 +331,20 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd,
for (i = 0; i < 128; i++) { for (i = 0; i < 128; i++) {
int val; int val;
val = data->value.integer.value[i]; val = data->value.integer.value[i];
if (__put_user(val, &data32->value.integer.value[i])) { if (__put_user(val, &data32->value.integer[i])) {
err = -EFAULT; err = -EFAULT;
goto __end; goto __end;
} }
} }
break; break;
case SNDRV_CTL_ELEM_TYPE_INTEGER64: default:
if (__copy_to_user(data32->value.integer64.value, if (__copy_to_user(data32->value.data,
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, data->value.bytes.data,
sizeof(data32->value.bytes.data))) { sizeof(data32->value.data))) {
err = -EFAULT; err = -EFAULT;
goto __end; goto __end;
} }
break; 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; break;
} }
err = 0; err = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment