--- initial
+++ final
@@ -1,117 +1,113 @@
 static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 { /* @ ADG ou ATO selon le cas */
   int i;
   unsigned char IndexCard;
   void __iomem *pmem;
   int ret = 0;
   volatile unsigned char byte_reset_it;
   struct st_ram_io *adgl;
   void __user *argp = (void __user *)arg;
   /* In general, the device is only openable by root anyway, so we're not
      particularly concerned that bogus ioctls can flood the console. */
-  adgl = kmalloc(sizeof(struct st_ram_io), GFP_KERNEL);
-  if (!adgl) return -ENOMEM;
-  if (copy_from_user(adgl, argp, sizeof(struct st_ram_io))) {
-    kfree(adgl);
-    return -EFAULT;
-  }
+  adgl = memdup_user(argp, sizeof(struct st_ram_io));
+  if (IS_ERR(adgl)) return PTR_ERR(adgl);
   lock_kernel();
   IndexCard = adgl->num_card - 1;
 
   if (cmd != 6 && ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) {
     static int warncount = 10;
     if (warncount) {
       printk(KERN_WARNING "APPLICOM driver IOCTL, bad board number %d\n", (int)IndexCard + 1);
       warncount--;
     }
     kfree(adgl);
     unlock_kernel();
     return -EINVAL;
   }
   switch (cmd) {
 
   case 0:
     pmem = apbs[IndexCard].RamIO;
     for (i = 0; i < sizeof(struct st_ram_io); i++)
       ((unsigned char *)adgl)[i] = readb(pmem++);
     if (copy_to_user(argp, adgl, sizeof(struct st_ram_io))) ret = -EFAULT;
     break;
   case 1:
     pmem = apbs[IndexCard].RamIO + CONF_END_TEST;
     for (i = 0; i < 4; i++)
       adgl->conf_end_test[i] = readb(pmem++);
     for (i = 0; i < 2; i++)
       adgl->error_code[i] = readb(pmem++);
     for (i = 0; i < 4; i++)
       adgl->parameter_error[i] = readb(pmem++);
     pmem = apbs[IndexCard].RamIO + VERS;
     adgl->vers = readb(pmem);
     pmem = apbs[IndexCard].RamIO + TYPE_CARD;
     for (i = 0; i < 20; i++)
       adgl->reserv1[i] = readb(pmem++);
     *(int *)&adgl->reserv1[20] = (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER) << 16) + (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 1) << 8) + (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 2));
     if (copy_to_user(argp, adgl, sizeof(struct st_ram_io))) ret = -EFAULT;
     break;
   case 2:
     pmem = apbs[IndexCard].RamIO + CONF_END_TEST;
     for (i = 0; i < 10; i++)
       writeb(0xff, pmem++);
     writeb(adgl->data_from_pc_ready, apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
     writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
 
     for (i = 0; i < MAX_BOARD; i++) {
       if (apbs[i].RamIO) { byte_reset_it = readb(apbs[i].RamIO + RAM_IT_TO_PC); }
     }
     break;
   case 3:
     pmem = apbs[IndexCard].RamIO + TIC_DES_FROM_PC;
     writeb(adgl->tic_des_from_pc, pmem);
     break;
   case 4:
     pmem = apbs[IndexCard].RamIO + TIC_OWNER_TO_PC;
     adgl->tic_owner_to_pc = readb(pmem++);
     adgl->numcard_owner_to_pc = readb(pmem);
     if (copy_to_user(argp, adgl, sizeof(struct st_ram_io))) ret = -EFAULT;
     break;
   case 5:
     writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC);
     writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC);
     writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC);
     writeb(4, apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
     writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
     break;
   case 6:
     printk(KERN_INFO "APPLICOM driver release .... V2.8.0 ($Revision: 1.30 $)\n");
     printk(KERN_INFO "Number of installed boards . %d\n", (int)numboards);
     printk(KERN_INFO "Segment of board ........... %X\n", (int)mem);
     printk(KERN_INFO "Interrupt IRQ number ....... %d\n", (int)irq);
     for (i = 0; i < MAX_BOARD; i++) {
       int serial;
       char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1];
       if (!apbs[i].RamIO) continue;
       for (serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++)
         boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial);
       boardname[serial] = 0;
       printk(KERN_INFO "Prom version board %d ....... V%d.%d %s", i + 1, (int)(readb(apbs[IndexCard].RamIO + VERS) >> 4), (int)(readb(apbs[IndexCard].RamIO + VERS) & 0xF), boardname);
       serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) + (readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) + (readb(apbs[i].RamIO + SERIAL_NUMBER + 2));
       if (serial != 0)
         printk(" S/N %d\n", serial);
       else
         printk("\n");
     }
     if (DeviceErrorCount != 0) printk(KERN_INFO "DeviceErrorCount ........... %d\n", DeviceErrorCount);
     if (ReadErrorCount != 0) printk(KERN_INFO "ReadErrorCount ............. %d\n", ReadErrorCount);
     if (WriteErrorCount != 0) printk(KERN_INFO "WriteErrorCount ............ %d\n", WriteErrorCount);
     if (waitqueue_active(&FlagSleepRec)) printk(KERN_INFO "Process in read pending\n");
     for (i = 0; i < MAX_BOARD; i++) {
       if (apbs[i].RamIO && waitqueue_active(&apbs[i].FlagSleepSend)) printk(KERN_INFO "Process in write pending board %d\n", i + 1);
     }
     break;
   default: ret = -ENOTTY; break;
   }
   Dummy = readb(apbs[IndexCard].RamIO + VERS);
   kfree(adgl);
   unlock_kernel();
   return 0;
 }<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);
-	}