--- initial
+++ final
@@ -1,107 +1,95 @@
 static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io) {
   int ctlr = h->ctlr;
   cmdlist_t *c;
   void *p = NULL;
   unsigned long flags;
   int error;
   if ((c = cmd_alloc(h, 0)) == NULL) return -ENOMEM;
   c->ctlr = ctlr;
   c->hdr.unit = (io->unit & UNITVALID) ? (io->unit & ~UNITVALID) : dsk;
   c->hdr.size = sizeof(rblk_t) >> 2;
   c->size += sizeof(rblk_t);
   c->req.hdr.cmd = io->cmd;
   c->req.hdr.blk = io->blk;
   c->req.hdr.blk_cnt = io->blk_cnt;
   c->type = CMD_IOCTL_PEND;
   /* Pre submit processing */
   switch (io->cmd) {
   case PASSTHRU_A:
-    p = kmalloc(io->sg[0].size, GFP_KERNEL);
-    if (!p) {
-      error = -ENOMEM;
+    p = memdup_user(io->sg[0].addr, io->sg[0].size);
+    if (IS_ERR(p)) {
       cmd_free(h, c, 0);
-      return (error);
-    }
-    if (copy_from_user(p, io->sg[0].addr, io->sg[0].size)) {
-      kfree(p);
-      cmd_free(h, c, 0);
-      return -EFAULT;
+      return PTR_ERR(p);
     }
     c->req.hdr.blk = pci_map_single(h->pci_dev, &(io->c), sizeof(ida_ioctl_t), PCI_DMA_BIDIRECTIONAL);
     c->req.sg[0].size = io->sg[0].size;
     c->req.sg[0].addr = pci_map_single(h->pci_dev, p, c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
     c->req.hdr.sg_cnt = 1;
     break;
   case IDA_READ:
   case READ_FLASH_ROM:
   case SENSE_CONTROLLER_PERFORMANCE:
     p = kmalloc(io->sg[0].size, GFP_KERNEL);
     if (!p) {
       error = -ENOMEM;
       cmd_free(h, c, 0);
       return (error);
     }
     c->req.sg[0].size = io->sg[0].size;
     c->req.sg[0].addr = pci_map_single(h->pci_dev, p, c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
     c->req.hdr.sg_cnt = 1;
     break;
   case IDA_WRITE:
   case IDA_WRITE_MEDIA:
   case DIAG_PASS_THRU:
   case COLLECT_BUFFER:
   case WRITE_FLASH_ROM:
-    p = kmalloc(io->sg[0].size, GFP_KERNEL);
-    if (!p) {
-      error = -ENOMEM;
+    p = memdup_user(io->sg[0].addr, io->sg[0].size);
+    if (IS_ERR(p)) {
       cmd_free(h, c, 0);
-      return (error);
-    }
-    if (copy_from_user(p, io->sg[0].addr, io->sg[0].size)) {
-      kfree(p);
-      cmd_free(h, c, 0);
-      return -EFAULT;
+      return PTR_ERR(p);
     }
     c->req.sg[0].size = io->sg[0].size;
     c->req.sg[0].addr = pci_map_single(h->pci_dev, p, c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
     c->req.hdr.sg_cnt = 1;
     break;
   default:
     c->req.sg[0].size = sizeof(io->c);
     c->req.sg[0].addr = pci_map_single(h->pci_dev, &io->c, c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
     c->req.hdr.sg_cnt = 1;
   }
 
   /* Put the request on the tail of the request queue */
   spin_lock_irqsave(IDA_LOCK(ctlr), flags);
   addQ(&h->reqQ, c);
   h->Qdepth++;
   start_io(h);
   spin_unlock_irqrestore(IDA_LOCK(ctlr), flags);
   /* Wait for completion */
   while (c->type != CMD_IOCTL_DONE)
     schedule();
   /* Unmap the DMA  */
   pci_unmap_single(h->pci_dev, c->req.sg[0].addr, c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
   /* Post submit processing */
   switch (io->cmd) {
   case PASSTHRU_A: pci_unmap_single(h->pci_dev, c->req.hdr.blk, sizeof(ida_ioctl_t), PCI_DMA_BIDIRECTIONAL);
   case IDA_READ:
   case DIAG_PASS_THRU:
   case SENSE_CONTROLLER_PERFORMANCE:
   case READ_FLASH_ROM:
     if (copy_to_user(io->sg[0].addr, p, io->sg[0].size)) {
       kfree(p);
       return -EFAULT;
     }
     /* fall through and free p */
   case IDA_WRITE:
   case IDA_WRITE_MEDIA:
   case COLLECT_BUFFER:
   case WRITE_FLASH_ROM: kfree(p); break;
   default:;
     /* Nothing to do */
   }
   io->rcode = c->req.hdr.rcode;
   cmd_free(h, c, 0);
   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);
	}