MLK-14642 imx: sim: fix segment fault caused by user address access
authorGao Pan <pandy.gao@nxp.com>
Thu, 13 Apr 2017 06:58:03 +0000 (14:58 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:21:53 +0000 (15:21 -0500)
Kernel space cannot access user space memory directly.
In fact, the issue always exited. Since 4.4, the kernel
handle the action as page abort.

Signed-off-by: Gao Pan <pandy.gao@nxp.com>
Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
drivers/mxc/sim/imx_sim.c

index b527142..d33c11a 100755 (executable)
@@ -1299,6 +1299,9 @@ static long sim_ioctl(struct file *file,
        u32 delay;
        u32 copy_cnt, val;
        unsigned long flags;
+       unsigned char __user *atr_buffer;
+       unsigned char __user *xmt_buffer;
+       unsigned char __user *rcv_buffer;
 
        struct sim_t *sim = (struct sim_t *) file->private_data;
 
@@ -1341,8 +1344,8 @@ static long sim_ioctl(struct file *file,
                        break;
                }
 
-               ret = copy_to_user(((sim_atr_t *)arg)->atr_buffer, sim->rcv_buffer,
-                                       sim->rcv_count);
+               __get_user(atr_buffer, &((sim_atr_t __user *)arg)->atr_buffer);
+               ret = copy_to_user(atr_buffer, sim->rcv_buffer, sim->rcv_count);
                if (ret) {
                        pr_err("ATR ACCESS buffer Error %d %d\n", sim->rcv_count, ret);
                        errval = -SIM_E_ACCESS;
@@ -1389,8 +1392,9 @@ static long sim_ioctl(struct file *file,
                        errval = -EINVAL;
                        break;
                }
-               ret = copy_from_user(sim->xmt_buffer, (((sim_xmt_t *)arg)->xmt_buffer),
-                                    sim->xmt_remaining);
+
+               __get_user(xmt_buffer, &((sim_xmt_t *)arg)->xmt_buffer);
+               ret = copy_from_user(sim->xmt_buffer, xmt_buffer, sim->xmt_remaining);
 
                if (ret) {
                        pr_err("Copy Error\n");
@@ -1526,8 +1530,8 @@ copy_data:
                        break;
                }
 
-               ret = copy_to_user(((sim_rcv_t *)arg)->rcv_buffer, &sim->rcv_buffer[sim->rcv_head],
-                                       copy_cnt);
+               __get_user(rcv_buffer, &((sim_rcv_t *)arg)->rcv_buffer);
+               ret = copy_to_user(rcv_buffer, &sim->rcv_buffer[sim->rcv_head], copy_cnt);
                if (ret) {
                        pr_err("ATR ACCESS Error\n");
                        errval = -SIM_E_ACCESS;