--- initial
+++ final
@@ -1,120 +1,108 @@
 static int vfe_config(struct msm_vfe_cfg_cmd *cmd, void *data) {
   struct msm_pmem_region *regptr;
   struct msm_vfe_command_8k vfecmd;
   uint32_t i;
   void *cmd_data = NULL;
   long rc = 0;
   struct vfe_cmd_axi_output_config *axio = NULL;
   struct vfe_cmd_stats_setting *scfg = NULL;
   if (cmd->cmd_type != CMD_FRAME_BUF_RELEASE && cmd->cmd_type != CMD_STATS_BUF_RELEASE) {
     if (copy_from_user(&vfecmd, (void __user *)(cmd->value), sizeof(struct msm_vfe_command_8k))) return -EFAULT;
   }
   CDBG("vfe_config: cmdType = %d\n", cmd->cmd_type);
   switch (cmd->cmd_type) {
   case CMD_GENERAL: rc = vfe_proc_general(&vfecmd); break;
   case CMD_STATS_ENABLE:
   case CMD_STATS_AXI_CFG: {
     struct axidata *axid;
     axid = data;
     if (!axid) return -EFAULT;
     scfg = kmalloc(sizeof(struct vfe_cmd_stats_setting), GFP_ATOMIC);
     if (!scfg) return -ENOMEM;
     if (copy_from_user(scfg, (void __user *)(vfecmd.value), vfecmd.length)) {
       kfree(scfg);
       return -EFAULT;
     }
     regptr = axid->region;
     if (axid->bufnum1 > 0) {
       for (i = 0; i < axid->bufnum1; i++) {
         scfg->awbBuffer[i] = (uint32_t)(regptr->paddr);
         regptr++;
       }
     }
     if (axid->bufnum2 > 0) {
       for (i = 0; i < axid->bufnum2; i++) {
         scfg->afBuffer[i] = (uint32_t)(regptr->paddr);
         regptr++;
       }
     }
     vfe_stats_config(scfg);
   } break;
   case CMD_STATS_AF_AXI_CFG: {
   } break;
   case CMD_FRAME_BUF_RELEASE: {
     /* preview buffer release */
     struct msm_frame *b;
     unsigned long p;
     struct vfe_cmd_output_ack fack;
     if (!data) return -EFAULT;
     b = (struct msm_frame *)(cmd->value);
     p = *(unsigned long *)data;
     b->path = MSM_FRAME_ENC;
     fack.ybufaddr[0] = (uint32_t)(p + b->y_off);
     fack.chromabufaddr[0] = (uint32_t)(p + b->cbcr_off);
     if (b->path == MSM_FRAME_PREV_1) vfe_output1_ack(&fack);
     if (b->path == MSM_FRAME_ENC || b->path == MSM_FRAME_PREV_2) vfe_output2_ack(&fack);
   } break;
   case CMD_SNAP_BUF_RELEASE: {
   } break;
   case CMD_STATS_BUF_RELEASE: {
     struct vfe_cmd_stats_wb_exp_ack sack;
     if (!data) return -EFAULT;
     sack.nextWbExpOutputBufferAddr = *(uint32_t *)data;
     vfe_stats_wb_exp_ack(&sack);
   } break;
   case CMD_AXI_CFG_OUT1: {
     struct axidata *axid;
     axid = data;
     if (!axid) return -EFAULT;
-    axio = kmalloc(sizeof(struct vfe_cmd_axi_output_config), GFP_ATOMIC);
-    if (!axio) return -ENOMEM;
-    if (copy_from_user(axio, (void __user *)(vfecmd.value), sizeof(struct vfe_cmd_axi_output_config))) {
-      kfree(axio);
-      return -EFAULT;
-    }
+    axio = memdup_user((void __user *)(vfecmd.value), sizeof(struct vfe_cmd_axi_output_config));
+    if (IS_ERR(axio)) return PTR_ERR(axio);
     vfe_config_axi(OUTPUT_1, axid, axio);
     vfe_axi_output_config(axio);
   } break;
   case CMD_AXI_CFG_OUT2:
   case CMD_RAW_PICT_AXI_CFG: {
     struct axidata *axid;
     axid = data;
     if (!axid) return -EFAULT;
-    axio = kmalloc(sizeof(struct vfe_cmd_axi_output_config), GFP_ATOMIC);
-    if (!axio) return -ENOMEM;
-    if (copy_from_user(axio, (void __user *)(vfecmd.value), sizeof(struct vfe_cmd_axi_output_config))) {
-      kfree(axio);
-      return -EFAULT;
-    }
+    axio = memdup_user((void __user *)(vfecmd.value), sizeof(struct vfe_cmd_axi_output_config));
+    if (IS_ERR(axio)) return PTR_ERR(axio);
     vfe_config_axi(OUTPUT_2, axid, axio);
     axio->outputDataSize = 0;
     vfe_axi_output_config(axio);
   } break;
   case CMD_AXI_CFG_SNAP_O1_AND_O2: {
     struct axidata *axid;
     axid = data;
     if (!axid) return -EFAULT;
-    axio = kmalloc(sizeof(struct vfe_cmd_axi_output_config), GFP_ATOMIC);
-    if (!axio) return -ENOMEM;
-    if (copy_from_user(axio, (void __user *)(vfecmd.value), sizeof(struct vfe_cmd_axi_output_config))) {
-      kfree(axio);
-      return -EFAULT;
-    }
+    axio = memdup_user((void __user *)(vfecmd.value), sizeof(struct vfe_cmd_axi_output_config));
+    if (IS_ERR(axio)) return PTR_ERR(axio);
     vfe_config_axi(OUTPUT_1_AND_2, axid, axio);
     vfe_axi_output_config(axio);
     cmd_data = axio;
   } break;
   default: break;
   } /* switch */
   kfree(scfg);
   kfree(axio);
   /*
           if (cmd->length > 256 &&
                           cmd_data &&
                           (cmd->cmd_type == CMD_GENERAL ||
                            cmd->cmd_type == CMD_STATS_DISABLE)) {
                   kfree(cmd_data);
           }
   */
   return rc;
 }<sep>@@
expression e1,e2,e3,r;
statement S;
constant GFP_KERNEL;
@@

-	e1 = kmalloc(e3, GFP_KERNEL);
-	if (e1 == NULL)
-		S

-	if (copy_from_user(e1, e2, e3))
+	e1 = memdup_user(e2, e3);
+	if (IS_ERR(e1))
-       {
-		kfree(e1);
-		return r;
+		return PTR_ERR(e1);
-	}