diff options
author | Andrew Chant <achant@google.com> | 2019-07-25 12:04:48 -0700 |
---|---|---|
committer | juyuchen <juyuchen@google.com> | 2019-07-27 02:38:26 +0800 |
commit | a8840fb476279fcef4f3710fd2e650b592b8d1ad (patch) | |
tree | 119bb89e2bcd95c3ceec6d3cb7d68382e3f3181f | |
parent | 1b1e665ff6ecc7a1283bf0244f8e117b218fb54f (diff) | |
download | msm-extra-a8840fb476279fcef4f3710fd2e650b592b8d1ad.tar.gz |
audio: fixup crus_sp_compat_ioctl
crus_sp_ioctl_header needs to be re-allocated in
crus_sp_compat_ioctl since the size of the structure
is different between 32-bit and 64-bit callers.
Also fixup the contained userspace pointer with
compat_ptr().
Bug: 135130450
Bug: 135129430
Test:
The calibration data is good to send to library and re-calibration works.
Change-Id: Ie2c2473bf5ac061fd18426ae8c69b6dbf1895cda
Signed-off-by: Andrew Chant <achant@google.com>
Signed-off-by: juyuchen <juyuchen@google.com>
-rw-r--r-- | asoc/msm-cirrus-playback.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/asoc/msm-cirrus-playback.c b/asoc/msm-cirrus-playback.c index a4c529ad..697b26f4 100644 --- a/asoc/msm-cirrus-playback.c +++ b/asoc/msm-cirrus-playback.c @@ -1422,13 +1422,48 @@ static long crus_sp_ioctl(struct file *f, return crus_sp_shared_ioctl(f, cmd, (void __user *)arg); } +struct compat_crus_sp_ioctl_header { + uint32_t size; + uint32_t module_id; + uint32_t param_id; + uint32_t data_length; + compat_caddr_t data; +}; + static long crus_sp_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg) { unsigned int cmd64; + struct compat_crus_sp_ioctl_header __user *ua32; + struct crus_sp_ioctl_header __user *ua; + compat_caddr_t __user ua32_data; + void __user *ua_data; + uint32_t ua32_size, ua_size; pr_info("%s\n", __func__); + ua32 = compat_ptr(arg); + if (get_user(ua32_size, (uint32_t __user*)&ua32->size)) + return -EFAULT; + if (ua32_size != sizeof(*ua32)) + return -EINVAL; + + ua_size = sizeof(*ua); + ua = compat_alloc_user_space(ua_size); + if (!ua) + return -ENOMEM; + + /* Copy everything but data, then fixup size & data. */ + if (copy_in_user(ua, ua32, sizeof(*ua32) - sizeof(ua32->data))) + return -EFAULT; + if (put_user(ua_size, (uint32_t __user*)&ua->size)) + return -EFAULT; + if (get_user(ua32_data, (compat_caddr_t __user*)&ua32->data)) + return -EFAULT; + ua_data = compat_ptr(ua32_data); + if (put_user(ua_data, (void* __user*)&ua->data)) + return -EFAULT; + switch (cmd) { case CRUS_SP_IOCTL_GET32: cmd64 = CRUS_SP_IOCTL_GET; @@ -1447,7 +1482,7 @@ static long crus_sp_compat_ioctl(struct file *f, return -EINVAL; } - return crus_sp_shared_ioctl(f, cmd64, compat_ptr(arg)); + return crus_sp_shared_ioctl(f, cmd64, ua); } static int crus_sp_open(struct inode *inode, struct file *f) |