[PATCH] ixj.c: check put_user, get rid of check_region, etc

From: Arnaldo Carvalho de Melo (acme@conectiva.com.br)
Date: Sun Aug 27 2000 - 17:21:20 EST


Hi,

                Please consider applying.

                        - Arnaldo

--- linux-2.4.0-test7/drivers/telephony/ixj.c Thu Jul 13 01:58:43 2000
+++ linux-2.4.0-test7.acme/drivers/telephony/ixj.c Sun Aug 27 19:17:42 2000
@@ -17,10 +17,16 @@
  * David W. Erhart, <derhart@quicknet.net>
  * John Sellers, <jsellers@quicknet.net>
  * Mike Preston, <mpreston@quicknet.net>
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *
  * Fixes:
  *
  * 2.3.x port : Alan Cox
+ * check put_user return,
+ * resource release on failure in
+ * ixj_build_cadence, get rid of
+ * check_region (race in 2.4),
+ * some cleanups : Arnaldo Carvalho de Melo
  *
  * More information about the hardware related to this driver can be found
  * at our website: http://www.quicknet.net
@@ -1306,10 +1312,7 @@
         /* Don't ever copy more than the user asks */
         i = copy_to_user(buf, j->read_buffer, min(length, j->read_buffer_size));
         j->read_buffer_ready = 0;
- if (i)
- return -EFAULT;
- else
- return min(length, j->read_buffer_size);
+ return i ? -EFAULT : min(length, j->read_buffer_size);
 }
 
 ssize_t ixj_enhanced_read(struct file * file_p, char *buf, size_t length,
@@ -1373,10 +1376,7 @@
         if (j->write_buffer_wp + count >= j->write_buffer_end)
                 j->write_buffer_wp = j->write_buffer;
         i = copy_from_user(j->write_buffer_wp, buf, min(count, j->write_buffer_size));
- if (i)
- return -EFAULT;
-
- return min(count, j->write_buffer_size);
+ return i ? -EFAULT : min(count, j->write_buffer_size);
 }
 
 ssize_t ixj_enhanced_write(struct file * file_p, const char *buf, size_t count,
@@ -3391,21 +3391,22 @@
         IXJ_CADENCE_ELEMENT *lcep;
         IXJ_TONE ti;
         IXJ *j = &ixj[board];
+ int ret = -EFAULT;
 
         lcp = kmalloc(sizeof(IXJ_CADENCE), GFP_KERNEL);
         if (lcp == NULL)
                 return -ENOMEM;
 
         if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_CADENCE)))
- return -EFAULT;
+ goto cleanup_lcp;
 
         lcep = kmalloc(sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used, GFP_KERNEL);
         if (lcep == NULL) {
- kfree(lcp);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto cleanup_lcp;
         }
         if (copy_from_user(lcep, lcp->ce, sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used))
- return -EFAULT;
+ goto cleanup_lcep;
 
         if(j->cadence_t)
         {
@@ -3429,6 +3430,9 @@
         ixj_play_tone(board, lcp->ce[0].index);
 
         return 1;
+cleanup_lcep: kfree(lcep);
+cleanup_lcp: kfree(lcp);
+ return ret;
 }
 
 static void add_caps(int board)
@@ -3668,22 +3672,22 @@
                         samplerate = arg;
                 break;
         case IXJCTL_DRYBUFFER_READ:
- put_user(j->drybuffer, (unsigned long *) arg);
+ retval = put_user(j->drybuffer, (unsigned long *) arg);
                 break;
         case IXJCTL_DRYBUFFER_CLEAR:
                 j->drybuffer = 0;
                 break;
         case IXJCTL_FRAMES_READ:
- put_user(j->framesread, (unsigned long *) arg);
+ retval = put_user(j->framesread, (unsigned long *) arg);
                 break;
         case IXJCTL_FRAMES_WRITTEN:
- put_user(j->frameswritten, (unsigned long *) arg);
+ retval = put_user(j->frameswritten, (unsigned long *) arg);
                 break;
         case IXJCTL_READ_WAIT:
- put_user(j->read_wait, (unsigned long *) arg);
+ retval = put_user(j->read_wait, (unsigned long *) arg);
                 break;
         case IXJCTL_WRITE_WAIT:
- put_user(j->write_wait, (unsigned long *) arg);
+ retval = put_user(j->write_wait, (unsigned long *) arg);
                 break;
         case PHONE_MAXRINGS:
                 j->maxrings = arg;
@@ -3814,9 +3818,7 @@
                         default:val=proto_size[pd.type]*3;break;
                 }
                 pd.buf_min=pd.buf_max=pd.buf_opt=val;
- if(copy_to_user((void *)arg, &pd, sizeof(pd)))
- return -EFAULT;
- return 0;
+ return copy_to_user((void *)arg, &pd, sizeof(pd)) ? -EFAULT : 0;
         }
         case IXJCTL_DSP_IDLE:
                 idle(board);
@@ -3904,7 +3906,8 @@
                 retval = j->filter_hist[arg];
                 break;
         case IXJCTL_INIT_TONE:
- copy_from_user(&ti, (char *) arg, sizeof(ti));
+ if (copy_from_user(&ti, (char *) arg, sizeof(ti)))
+ return -EFAULT;
                 retval = ixj_init_tone(board, &ti);
                 break;
         case IXJCTL_TONE_CADENCE:
@@ -4101,26 +4104,27 @@
                         {
                                 j->cardtype = 400; // Internet PhoneJACK Lite
 
- if (check_region(j->XILINXbase, 4)) {
+ if (!request_region(j->XILINXbase, 4, "ixj control")) {
                                         printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase);
                                         return -1;
                                 }
- request_region(j->XILINXbase, 4, "ixj control");
                                 j->pld_slicw.pcib.e1 = 1;
                                 outb_p(j->pld_slicw.byte, j->XILINXbase);
                         } else {
                                 j->cardtype = 300; // Internet LineJACK
 
- if (check_region(j->XILINXbase, 8)) {
+ if (!request_region(j->XILINXbase, 8, "ixj control")) {
                                         printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase);
                                         return -1;
                                 }
- request_region(j->XILINXbase, 8, "ixj control");
                         }
                 } else if (j->dsp.low == 0x22) {
                         j->cardtype = 500; // Internet PhoneJACK PCI
 
- request_region(j->XILINXbase, 4, "ixj control");
+ if (!request_region(j->XILINXbase, 4, "ixj control")) {
+ printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase);
+ return -1;
+ }
                         j->pld_slicw.pcib.e1 = 1;
                         outb_p(j->pld_slicw.byte, j->XILINXbase);
                 } else
@@ -4140,21 +4144,18 @@
                         break;
                 case 300: // Internet LineJACK
 
- if (check_region(j->XILINXbase, 8)) {
+ if (!request_region(j->XILINXbase, 8, "ixj control")) {
                                 printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase);
                                 return -1;
                         }
- request_region(j->XILINXbase, 8, "ixj control");
                         break;
                 case 400: //Internet PhoneJACK Lite
 
                 case 500: //Internet PhoneJACK PCI
-
- if (check_region(j->XILINXbase, 4)) {
+ if (!request_region(j->XILINXbase, 4, "ixj control")) {
                                 printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase);
                                 return -1;
                         }
- request_region(j->XILINXbase, 4, "ixj control");
                         j->pld_slicw.pcib.e1 = 1;
                         outb_p(j->pld_slicw.byte, j->XILINXbase);
                         break;
@@ -4549,13 +4550,11 @@
                         if (func != 0x110)
                                 ixj[cnt].XILINXbase = dev->resource[1].start; /* get real port */
 
- result = check_region(ixj[cnt].DSPbase, 16);
- if (result) {
+ if (!request_region(ixj[cnt].DSPbase, 16, "ixj DSP")) {
                                 printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", ixj[cnt].DSPbase);
                                 cleanup();
- return result;
+ return -EBUSY;
                         }
- request_region(ixj[cnt].DSPbase, 16, "ixj DSP");
                         switch (func) {
                         case (0x110):
                                 ixj[cnt].cardtype = 100;
@@ -4591,13 +4590,11 @@
                         ixj[cnt].DSPbase = dspio[cnt];
                         ixj[cnt].XILINXbase = xio[cnt];
                         ixj[cnt].cardtype = 0;
- result = check_region(ixj[cnt].DSPbase, 16);
- if (result) {
+ if (!request_region(ixj[cnt].DSPbase, 16, "ixj DSP")) {
                                 printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", ixj[cnt].DSPbase);
                                 cleanup();
- return result;
+ return -EBUSY;
                         }
- request_region(ixj[cnt].DSPbase, 16, "ixj DSP");
                         probe = ixj_selfprobe(cnt);
                         ixj[cnt].dev = NULL;
                 }
@@ -4616,13 +4613,11 @@
                                 ixj[cnt].XILINXbase = ixj[cnt].DSPbase + 0x10;
                                 ixj[cnt].serial = (PCIEE_GetSerialNumber)pci_resource_start(pci, 2);
 
- result = check_region(ixj[cnt].DSPbase, 16);
- if (result) {
+ if (!request_region(ixj[cnt].DSPbase, 16, "ixj DSP")) {
                                         printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", ixj[cnt].DSPbase);
                                         cleanup();
- return result;
+ return -EBUSY;
                                 }
- request_region(ixj[cnt].DSPbase, 16, "ixj DSP");
                                 ixj[cnt].cardtype = 500;
                                 probe = ixj_selfprobe(cnt);
                                 cnt++;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu Aug 31 2000 - 21:00:20 EST