## Automatically generated incremental diff ## From: linux-2.0.39-pre3 ## To: linux-2.0.39-pre4 ## Robot: $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $ diff -urN linux-2.0.39-pre3/drivers/block/ide.c linux-2.0.39-pre4/drivers/block/ide.c --- linux-2.0.39-pre3/drivers/block/ide.c 1999-06-13 10:21:00.000000000 -0700 +++ linux-2.0.39-pre4/drivers/block/ide.c 2003-08-15 15:04:55.000000000 -0700 @@ -606,6 +606,9 @@ * * Returns: 1 if lba_capacity looks sensible * 0 otherwise + * + * Note: we must not change id->cyls here, otherwise a second call + * of this routine might no longer find lba_capacity ok. */ static int lba_capacity_is_ok (struct hd_driveid *id) { @@ -614,14 +617,15 @@ unsigned long _10_percent = chs_sects / 10; /* - * very large drives (8GB+) may lie about the number of cylinders - * This is a split test for drives 8 Gig and Bigger only. - */ - if ((id->lba_capacity >= 16514064) && (id->cyls == 0x3fff) && - (id->heads == 16) && (id->sectors == 63)) { - id->cyls = lba_sects / (16 * 63); /* correct cyls */ + * The ATA spec tells large drives to return + * C/H/S = 16383/16/63 independent of their size. + * Some drives can be jumpered to use 15 heads instead of 16. + */ + if (id->cyls == 16383 && id->sectors == 63 && + (id->heads == 15 || id->heads == 16) && + id->lba_capacity >= 16383*63*id->heads) return 1; /* lba_capacity is our only option */ - } + /* perform a rough sanity check on lba_sects: within 10% is "okay" */ if ((lba_sects - chs_sects) < _10_percent) return 1; /* lba_capacity is good */ @@ -638,11 +642,13 @@ /* * current_capacity() returns the capacity (in sectors) of a drive * according to its current geometry/LBA settings. + * + * It also sets select.b.lba. */ static unsigned long current_capacity (ide_drive_t *drive) { struct hd_driveid *id = drive->id; - unsigned long capacity = drive->cyl * drive->head * drive->sect; + unsigned long capacity; if (!drive->present) return 0; @@ -652,22 +658,14 @@ #endif /* CONFIG_BLK_DEV_IDEFLOPPY */ if (drive->media != ide_disk) return 0x7fffffff; /* cdrom or tape */ + drive->select.b.lba = 0; /* Determine capacity, and use LBA if the drive properly supports it */ + capacity = drive->cyl * drive->head * drive->sect; if (id != NULL && (id->capability & 2) && lba_capacity_is_ok(id)) { if (id->lba_capacity >= capacity) { - drive->cyl = id->lba_capacity / (drive->head * drive->sect); capacity = id->lba_capacity; drive->select.b.lba = 1; -#if 0 - /* - * This is the correct place to perform this task; - * however, we do this later for reporting. - */ - if (*(int *)&id->cur_capacity0 != id->lba_capacity) { - *(int *)&id->cur_capacity0 = id->lba_capacity; - } -#endif } } return (capacity - drive->sect0); @@ -697,8 +695,9 @@ idefloppy_setup(drive); #endif /* CONFIG_BLK_DEV_IDEFLOPPY */ drive->part[0].nr_sects = current_capacity(drive); - if (!drive->present || (drive->media != ide_disk && drive->media != ide_floppy) || - !drive->part[0].nr_sects) { + if (!drive->present + || (drive->media != ide_disk && drive->media != ide_floppy) + || !drive->part[0].nr_sects) { drive->part[0].start_sect = -1; /* skip partition check */ } } @@ -2127,7 +2126,8 @@ }; drive->part[0].nr_sects = current_capacity(drive); - if ((drive->media != ide_disk && drive->media != ide_floppy) || !drive->part[0].nr_sects) + if ((drive->media != ide_disk && drive->media != ide_floppy) + || !drive->part[0].nr_sects) drive->part[0].start_sect = -1; resetup_one_dev(HWIF(drive)->gd, drive->select.b.unit); @@ -2565,8 +2565,8 @@ drive->sect = drive->bios_sect = id->sectors; } /* Handle logical geometry translation by the drive */ - if ((id->field_valid & 1) && id->cur_cyls && - id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) { + if ((id->field_valid & 1) && id->cur_cyls && id->cur_heads + && (id->cur_heads <= 16) && id->cur_sectors) { /* * Extract the physical drive geometry for our use. * Note that we purposely do *not* update the bios info. @@ -2593,12 +2593,9 @@ /* Use physical geometry if what we have still makes no sense */ if ((!drive->head || drive->head > 16) && id->heads && id->heads <= 16) { - if ((id->lba_capacity > 16514064) || (id->cyls == 0x3fff)) { - id->cyls = ((int)(id->lba_capacity/(id->heads * id->sectors))); - } - drive->cyl = id->cur_cyls = id->cyls; - drive->head = id->cur_heads = id->heads; - drive->sect = id->cur_sectors = id->sectors; + drive->cyl = id->cyls; + drive->head = id->heads; + drive->sect = id->sectors; } /* calculate drive capacity, and select LBA if possible */ @@ -2608,21 +2605,17 @@ * if possible, give fdisk access to more of the drive, * by correcting bios_cyls: */ - if ((capacity >= (id->cyls * id->heads * id->sectors)) && - (!drive->forced_geom) && drive->bios_sect && drive->bios_head) { - drive->bios_cyl = (capacity / drive->bios_sect) / drive->bios_head; -#ifdef DEBUG - printk("FDISK Fixing Geometry :: CHS=%d/%d/%d to CHS=%d/%d/%d\n", - drive->id->cur_cyls, - drive->id->cur_heads, - drive->id->cur_sectors, - drive->bios_cyl, - drive->bios_head, - drive->bios_sect); -#endif - drive->id->cur_cyls = drive->bios_cyl; - drive->id->cur_heads = drive->bios_head; - drive->id->cur_sectors = drive->bios_sect; + if (capacity > drive->bios_cyl * drive->bios_head * drive->bios_sect + && !drive->forced_geom && drive->bios_sect && drive->bios_head) { + int cyl = (capacity / drive->bios_sect) / drive->bios_head; + if (cyl <= 65535) + drive->bios_cyl = cyl; + else { + /* OK until 539 GB */ + drive->bios_sect = 63; + drive->bios_head = 255; + drive->bios_cyl = capacity / (63*255); + } } if (!strncmp(id->model, "BMI ", 4) && @@ -2666,18 +2659,6 @@ } } printk("\n"); - if (drive->select.b.lba) { - if (*(int *)&id->cur_capacity0 != id->lba_capacity) { -#ifdef DEBUG - printk(" CurSects=%d, LBASects=%d, ", - *(int *)&id->cur_capacity0, id->lba_capacity); -#endif - *(int *)&id->cur_capacity0 = id->lba_capacity; -#ifdef DEBUG - printk( "Fixed CurSects=%d\n", *(int *)&id->cur_capacity0); -#endif - } - } } /* @@ -3380,12 +3361,6 @@ * Returns 1 if the geometry translation was successful. */ -/* - * We update the values if the current CHS as determined by the kernel. - * This now allows for the hdparm tool to read the actual settings of the - * being used by the kernel. This removes the need for doing guess - * translations based on the raw values of the drive. - */ int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg) { ide_drive_t *drive; @@ -3397,48 +3372,14 @@ if (!drive) return 0; - if (drive->forced_geom) { - /* - * Update the current 3D drive values. - */ - drive->id->cur_cyls = drive->bios_cyl; - drive->id->cur_heads = drive->bios_head; - drive->id->cur_sectors = drive->bios_sect; + if (drive->forced_geom) return 0; - } - if (xparm > 1 && xparm <= drive->bios_head && drive->bios_sect == 63) { - /* - * Update the current 3D drive values. - */ - drive->id->cur_cyls = drive->bios_cyl; - drive->id->cur_heads = drive->bios_head; - drive->id->cur_sectors = drive->bios_sect; + if (xparm > 1 && xparm <= drive->bios_head && drive->bios_sect == 63) return 0; /* we already have a translation */ - } printk("%s ", msg); - if (xparm < 0 && (drive->bios_cyl * drive->bios_head * drive->bios_sect) < (1024 * 16 * 63)) { - /* - * Update the current 3D drive values. - */ - drive->id->cur_cyls = drive->bios_cyl; - drive->id->cur_heads = drive->bios_head; - drive->id->cur_sectors = drive->bios_sect; - return 0; /* small disk: no translation needed */ - } - - if (drive->id) { - drive->cyl = drive->id->cyls; - drive->head = drive->id->heads; - drive->sect = drive->id->sectors; - } - drive->bios_cyl = drive->cyl; - drive->bios_head = drive->head; - drive->bios_sect = drive->sect; - drive->special.b.set_geometry = 1; - tracks = drive->bios_cyl * drive->bios_head * drive->bios_sect / 63; drive->bios_sect = 63; if (xparm > 1) { @@ -3466,12 +3407,6 @@ } drive->part[0].nr_sects = current_capacity(drive); printk("[%d/%d/%d]", drive->bios_cyl, drive->bios_head, drive->bios_sect); - /* - * Update the current 3D drive values. - */ - drive->id->cur_cyls = drive->bios_cyl; - drive->id->cur_heads = drive->bios_head; - drive->id->cur_sectors = drive->bios_sect; return 1; } diff -urN linux-2.0.39-pre3/drivers/net/ppp.c linux-2.0.39-pre4/drivers/net/ppp.c --- linux-2.0.39-pre3/drivers/net/ppp.c 1999-06-13 10:21:01.000000000 -0700 +++ linux-2.0.39-pre4/drivers/net/ppp.c 2003-08-15 15:04:55.000000000 -0700 @@ -780,11 +780,16 @@ static int ppp_tty_open (struct tty_struct *tty) { - struct ppp *ppp = tty2ppp (tty); + struct ppp *ppp; int indx; + + if (!suser()) + return -EPERM; + /* * There should not be an existing table for this slot. */ + ppp = tty2ppp (tty); if (ppp) { if (ppp->flags & SC_DEBUG) printk (KERN_ERR diff -urN linux-2.0.39-pre3/drivers/net/slip.c linux-2.0.39-pre4/drivers/net/slip.c --- linux-2.0.39-pre3/drivers/net/slip.c 1998-07-13 13:47:31.000000000 -0700 +++ linux-2.0.39-pre4/drivers/net/slip.c 2003-08-15 15:04:55.000000000 -0700 @@ -698,10 +698,14 @@ static int slip_open(struct tty_struct *tty) { - struct slip *sl = (struct slip *) tty->disc_data; + struct slip *sl; int err; + if (!suser()) + return -EPERM; + /* First make sure we're not already connected. */ + sl = (struct slip *) tty->disc_data; if (sl && sl->magic == SLIP_MAGIC) { return -EEXIST; } diff -urN linux-2.0.39-pre3/drivers/net/wavelan.c linux-2.0.39-pre4/drivers/net/wavelan.c --- linux-2.0.39-pre3/drivers/net/wavelan.c 1999-06-13 10:21:02.000000000 -0700 +++ linux-2.0.39-pre4/drivers/net/wavelan.c 2003-08-15 15:04:55.000000000 -0700 @@ -324,6 +324,7 @@ return crc_bytes; } /* psa_crc */ +#endif /* SET_PSA_CRC */ /*------------------------------------------------------------------*/ /* @@ -334,6 +335,7 @@ u_long ioaddr, u_short hacr) { +#ifdef SET_PSA_CRC psa_t psa; u_short crc; @@ -363,8 +365,8 @@ if(crc != 0) printk(KERN_WARNING "%s: update_psa_checksum(): CRC does not agree with PSA data (even after recalculating)\n", dev->name); #endif /* DEBUG_IOCTL_INFO */ -} /* update_psa_checksum */ #endif /* SET_PSA_CRC */ +} /* update_psa_checksum */ /*------------------------------------------------------------------*/ /* @@ -748,23 +750,23 @@ unsigned short ias_addr; /* Check mc_config command */ - if((status & AC_SFLD_OK) != 0) - printk(KERN_INFO "wv_config_complete(): set_multicast_address failed; status = 0x%x\n", - dev->name, str, status); + if((status & AC_SFLD_OK) != AC_SFLD_OK) + printk(KERN_INFO "%s: wv_config_complete(): set_multicast_address failed; status = 0x%x\n", + dev->name, status); /* check ia-config command */ ias_addr = mcs_addr - sizeof(ac_ias_t); obram_read(ioaddr, acoff(ias_addr, ac_status), (unsigned char *)&status, sizeof(status)); - if((status & AC_SFLD_OK) != 0) - printk(KERN_INFO "wv_config_complete(): set_MAC_address; status = 0x%x\n", - dev->name, str, status); + if((status & AC_SFLD_OK) != AC_SFLD_OK) + printk(KERN_INFO "%s: wv_config_complete(): set_MAC_address failed; status = 0x%x\n", + dev->name, status); /* Check config command */ cfg_addr = ias_addr - sizeof(ac_cfg_t); obram_read(ioaddr, acoff(cfg_addr, ac_status), (unsigned char *)&status, sizeof(status)); - if((status & AC_SFLD_OK) != 0) - printk(KERN_INFO "wv_config_complete(): configure; status = 0x%x\n", - dev->name, str, status); + if((status & AC_SFLD_OK) != AC_SFLD_OK) + printk(KERN_INFO "%s: wv_config_complete(): configure failed; status = 0x%x\n", + dev->name, status); #endif /* DEBUG_CONFIG_ERROR */ ret = 1; /* Ready to be scrapped */ @@ -800,15 +802,15 @@ /* Read the first transmit buffer */ obram_read(ioaddr, acoff(lp->tx_first_in_use, ac_status), (unsigned char *)&tx_status, sizeof(tx_status)); + /* If not completed -> exit */ + if((tx_status & AC_SFLD_C) == 0) + break; + /* Hack for reconfiguration... */ if(tx_status == 0xFFFF) if(!wv_config_complete(dev, ioaddr, lp)) break; /* Not completed */ - /* If not completed -> exit */ - if((tx_status & AC_SFLD_C) == 0) - break; - /* We now remove this buffer */ nreaped++; --lp->tx_n_in_use; @@ -841,7 +843,7 @@ lp->stats.tx_packets++; ncollisions = tx_status & AC_SFLD_MAXCOL; lp->stats.collisions += ncollisions; -#ifdef DEBUG_INTERRUPT_INFO +#ifdef DEBUG_TX_INFO if(ncollisions > 0) printk(KERN_DEBUG "%s: wv_complete(): tx completed after %d collisions.\n", dev->name, ncollisions); @@ -850,53 +852,49 @@ else { lp->stats.tx_errors++; -#ifndef IGNORE_NORMAL_XMIT_ERRS if(tx_status & AC_SFLD_S10) { lp->stats.tx_carrier_errors++; -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "%s: wv_complete(): tx error: no CS.\n", +#ifdef DEBUG_TX_FAIL + printk(KERN_DEBUG "%s: wv_complete(): tx error: no CS.\n", dev->name); #endif } -#endif /* IGNORE_NORMAL_XMIT_ERRS */ if(tx_status & AC_SFLD_S9) { lp->stats.tx_carrier_errors++; -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "%s: wv_complete(): tx error: lost CTS.\n", +#ifdef DEBUG_TX_FAIL + printk(KERN_DEBUG "%s: wv_complete(): tx error: lost CTS.\n", dev->name); #endif } if(tx_status & AC_SFLD_S8) { lp->stats.tx_fifo_errors++; -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "%s: wv_complete(): tx error: slow DMA.\n", +#ifdef DEBUG_TX_FAIL + printk(KERN_DEBUG "%s: wv_complete(): tx error: slow DMA.\n", dev->name); #endif } -#ifndef IGNORE_NORMAL_XMIT_ERRS if(tx_status & AC_SFLD_S6) { lp->stats.tx_heartbeat_errors++; -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "%s: wv_complete(): tx error: heart beat.\n", +#ifdef DEBUG_TX_FAIL + printk(KERN_DEBUG "%s: wv_complete(): tx error: heart beat.\n", dev->name); #endif } if(tx_status & AC_SFLD_S5) { lp->stats.tx_aborted_errors++; -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "%s: wv_complete(): tx error: too many collisions.\n", +#ifdef DEBUG_TX_FAIL + printk(KERN_DEBUG "%s: wv_complete(): tx error: too many collisions.\n", dev->name); #endif } -#endif /* IGNORE_NORMAL_XMIT_ERRS */ } -#ifdef DEBUG_INTERRUPT_INFO +#ifdef DEBUG_TX_INFO printk(KERN_DEBUG "%s: wv_complete(): tx completed, tx_status 0x%04x\n", dev->name, tx_status); #endif @@ -1323,21 +1321,21 @@ char * msg1, /* Name of the device */ char * msg2) /* Name of the function */ { -#ifndef DEBUG_PACKET_DUMP + int i; + int maxi; + printk(KERN_DEBUG "%s: %s(): dest %02X:%02X:%02X:%02X:%02X:%02X, length %d\n", msg1, msg2, p[0], p[1], p[2], p[3], p[4], p[5], length); printk(KERN_DEBUG "%s: %s(): src %02X:%02X:%02X:%02X:%02X:%02X, type 0x%02X%02X\n", msg1, msg2, p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13]); -#else /* DEBUG_PACKET_DUMP */ - int i; - int maxi; +#ifdef DEBUG_PACKET_DUMP - printk(KERN_DEBUG "%s: %s(): len=%d, data=\"", msg1, msg2, length); + printk(KERN_DEBUG "data=\""); if((maxi = length) > DEBUG_PACKET_DUMP) maxi = DEBUG_PACKET_DUMP; - for(i = 0; i < maxi; i++) + for(i = 14; i < maxi; i++) if(p[i] >= ' ' && p[i] <= '~') printk(" %c", p[i]); else @@ -1565,7 +1563,9 @@ /*------------------------------------------------------------------*/ /* * This function doesn't exist... + * (Note : it was a nice way to test the reconfigure stuff...) */ +#ifdef SET_MAC_ADDRESS static int wavelan_set_mac_address(device * dev, void * addr) @@ -1580,6 +1580,7 @@ return 0; } +#endif /* SET_MAC_ADDRESS */ #ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */ @@ -1940,10 +1941,8 @@ /* Disable nwid in the mmc (no filtering) */ mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), MMW_LOOPT_SEL_DIS_NWID); } -#ifdef SET_PSA_CRC /* update the Wavelan checksum */ update_psa_checksum(dev, ioaddr, lp->hacr); -#endif break; case SIOCGIWNWID: @@ -2001,10 +2000,8 @@ psa.psa_thr_pre_set = wrq->u.sensitivity & 0x3F; psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa, (unsigned char *) &psa.psa_thr_pre_set, 1); -#ifdef SET_PSA_CRC /* update the Wavelan checksum */ update_psa_checksum(dev, ioaddr, lp->hacr); -#endif mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set), psa.psa_thr_pre_set); break; @@ -2052,10 +2049,8 @@ mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0); } -#ifdef SET_PSA_CRC /* update the Wavelan checksum */ update_psa_checksum(dev, ioaddr, lp->hacr); -#endif break; case SIOCGIWENCODE: @@ -2269,10 +2264,8 @@ psa.psa_quality_thr = *(wrq->u.name) & 0x0F; psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa, (unsigned char *)&psa.psa_quality_thr, 1); -#ifdef SET_PSA_CRC /* update the Wavelan checksum */ update_psa_checksum(dev, ioaddr, lp->hacr); -#endif mmc_out(ioaddr, mmwoff(0, mmw_quality_thr), psa.psa_quality_thr); break; @@ -2435,7 +2428,7 @@ #ifdef DEBUG_RX_TRACE printk(KERN_DEBUG "%s: ->wv_packet_read(0x%X, %d)\n", - dev->name, fd_p, sksize); + dev->name, buf_off, sksize); #endif /* Allocate buffer for the data */ @@ -2520,6 +2513,8 @@ { u_long ioaddr = dev->base_addr; net_local * lp = (net_local *)dev->priv; + fd_t fd; + rbd_t rbd; int nreaped = 0; #ifdef DEBUG_RX_TRACE @@ -2529,48 +2524,62 @@ /* Loop on each received packet */ for(;;) { - fd_t fd; - rbd_t rbd; - ushort pkt_len; - obram_read(ioaddr, lp->rx_head, (unsigned char *) &fd, sizeof(fd)); - /* If the current frame is not complete, we have reach the end... */ + /* Note about the status : + * It start up to be 0 (the value we set). Then, when the RU + * grab the buffer to prepare for reception, it sets the + * FD_STATUS_B flag. When the RU has finished receiving the + * frame, it clears FD_STATUS_B, set FD_STATUS_C to indicate + * completion and set the other flags to indicate the eventual + * errors. FD_STATUS_OK indicates that the reception was OK. + */ + + /* If the current frame is not complete, we have reached the end. */ if((fd.fd_status & FD_STATUS_C) != FD_STATUS_C) - break; /* This is how we exit the loop */ + break; /* This is how we exit the loop. */ nreaped++; - /* Check if frame correctly received */ - if((fd.fd_status & (FD_STATUS_B | FD_STATUS_OK)) != - (FD_STATUS_B | FD_STATUS_OK)) + /* Check whether frame was correctly received. */ + if((fd.fd_status & FD_STATUS_OK) == FD_STATUS_OK) { - /* - * Not sure about this one -- it does not seem - * to be an error so we will keep quiet about it. - */ -#ifndef IGNORE_NORMAL_XMIT_ERRS -#ifdef DEBUG_RX_ERROR - if((fd.fd_status & FD_STATUS_B) != FD_STATUS_B) - printk(KERN_INFO "%s: wv_receive(): frame not consumed by RU.\n", - dev->name); -#endif -#endif /* IGNORE_NORMAL_XMIT_ERRS */ + /* Does the frame contain a pointer to the data? Let's check. */ + if(fd.fd_rbd_offset != I82586NULL) + { + /* Read the receive buffer descriptor */ + obram_read(ioaddr, fd.fd_rbd_offset, + (unsigned char *) &rbd, sizeof(rbd)); #ifdef DEBUG_RX_ERROR - if((fd.fd_status & FD_STATUS_OK) != FD_STATUS_OK) - printk(KERN_INFO "%s: wv_receive(): frame not received successfully.\n", + if((rbd.rbd_status & RBD_STATUS_EOF) != RBD_STATUS_EOF) + printk(KERN_INFO "%s: wv_receive(): missing EOF flag.\n", + dev->name); + + if((rbd.rbd_status & RBD_STATUS_F) != RBD_STATUS_F) + printk(KERN_INFO "%s: wv_receive(): missing F flag.\n", + dev->name); +#endif /* DEBUG_RX_ERROR */ + + /* Read the packet and transmit to Linux */ + wv_packet_read(dev, rbd.rbd_bufl, + rbd.rbd_status & RBD_STATUS_ACNT); + } +#ifdef DEBUG_RX_ERROR + else /* if frame has no data */ + printk(KERN_INFO "%s: wv_receive(): frame has no data.\n", dev->name); #endif } - - /* Were there problems in processing the frame? Let's check. */ - if((fd.fd_status & (FD_STATUS_S6 | FD_STATUS_S7 | FD_STATUS_S8 | - FD_STATUS_S9 | FD_STATUS_S10 | FD_STATUS_S11)) - != 0) + else /* If reception was no successful */ { lp->stats.rx_errors++; +#ifdef DEBUG_RX_INFO + printk(KERN_DEBUG "%s: wv_receive(): frame not received successfully (%X).\n", + dev->name, fd.fd_status); +#endif + #ifdef DEBUG_RX_ERROR if((fd.fd_status & FD_STATUS_S6) != 0) printk(KERN_INFO "%s: wv_receive(): no EOF flag.\n", dev->name); @@ -2579,8 +2588,8 @@ if((fd.fd_status & FD_STATUS_S7) != 0) { lp->stats.rx_length_errors++; -#ifdef DEBUG_RX_ERROR - printk(KERN_INFO "%s: wv_receive(): frame too short.\n", +#ifdef DEBUG_RX_FAIL + printk(KERN_DEBUG "%s: wv_receive(): frame too short.\n", dev->name); #endif } @@ -2588,8 +2597,8 @@ if((fd.fd_status & FD_STATUS_S8) != 0) { lp->stats.rx_over_errors++; -#ifdef DEBUG_RX_ERROR - printk(KERN_INFO "%s: wv_receive(): rx DMA overrun.\n", +#ifdef DEBUG_RX_FAIL + printk(KERN_DEBUG "%s: wv_receive(): rx DMA overrun.\n", dev->name); #endif } @@ -2597,8 +2606,8 @@ if((fd.fd_status & FD_STATUS_S9) != 0) { lp->stats.rx_fifo_errors++; -#ifdef DEBUG_RX_ERROR - printk(KERN_INFO "%s: wv_receive(): ran out of resources.\n", +#ifdef DEBUG_RX_FAIL + printk(KERN_DEBUG "%s: wv_receive(): ran out of resources.\n", dev->name); #endif } @@ -2606,8 +2615,8 @@ if((fd.fd_status & FD_STATUS_S10) != 0) { lp->stats.rx_frame_errors++; -#ifdef DEBUG_RX_ERROR - printk(KERN_INFO "%s: wv_receive(): alignment error.\n", +#ifdef DEBUG_RX_FAIL + printk(KERN_DEBUG "%s: wv_receive(): alignment error.\n", dev->name); #endif } @@ -2615,38 +2624,12 @@ if((fd.fd_status & FD_STATUS_S11) != 0) { lp->stats.rx_crc_errors++; -#ifdef DEBUG_RX_ERROR - printk(KERN_INFO "%s: wv_receive(): CRC error.\n", dev->name); +#ifdef DEBUG_RX_FAIL + printk(KERN_DEBUG "%s: wv_receive(): CRC error.\n", dev->name); #endif } } - /* Does the frame contain a pointer to the data? Let's check. */ - if(fd.fd_rbd_offset == I82586NULL) -#ifdef DEBUG_RX_ERROR - printk(KERN_INFO "%s: wv_receive(): frame has no data.\n", dev->name); -#endif - else - { - obram_read(ioaddr, fd.fd_rbd_offset, - (unsigned char *) &rbd, sizeof(rbd)); - -#ifdef DEBUG_RX_ERROR - if((rbd.rbd_status & RBD_STATUS_EOF) != RBD_STATUS_EOF) - printk(KERN_INFO "%s: wv_receive(): missing EOF flag.\n", - dev->name); - - if((rbd.rbd_status & RBD_STATUS_F) != RBD_STATUS_F) - printk(KERN_INFO "%s: wv_receive(): missing F flag.\n", - dev->name); -#endif - - pkt_len = rbd.rbd_status & RBD_STATUS_ACNT; - - /* Read the packet and transmit to Linux */ - wv_packet_read(dev, rbd.rbd_bufl, pkt_len); - } /* if frame has data */ - fd.fd_status = 0; obram_write(ioaddr, fdoff(lp->rx_head, fd_status), (unsigned char *) &fd.fd_status, sizeof(fd.fd_status)); @@ -2781,7 +2764,7 @@ /* * Data */ - obram_write(ioaddr, buf_addr, buf, clen); + obram_write(ioaddr, buf_addr, buf, length); /* * Overwrite the predecessor NOP link @@ -2967,11 +2950,9 @@ (unsigned char *)&psa.psa_quality_thr, 1); psa_write(ioaddr, lp->hacr, (char *)&psa.psa_conf_status - (char *)&psa, (unsigned char *)&psa.psa_conf_status, 1); -#ifdef SET_PSA_CRC /* update the Wavelan checksum */ update_psa_checksum(dev, ioaddr, lp->hacr); #endif -#endif } /* Zero the mmc structure */ @@ -3142,7 +3123,7 @@ if(i <= 0) { -#ifdef DEBUG_CONFIG_ERRORS +#ifdef DEBUG_CONFIG_ERROR printk(KERN_INFO "%s: wavelan_ru_start(): board not accepting command.\n", dev->name); #endif @@ -3246,7 +3227,7 @@ if(i <= 0) { -#ifdef DEBUG_CONFIG_ERRORS +#ifdef DEBUG_CONFIG_ERROR printk(KERN_INFO "%s: wavelan_cu_start(): board not accepting command.\n", dev->name); #endif @@ -3332,7 +3313,7 @@ if(i <= 0) { -#ifdef DEBUG_CONFIG_ERRORS +#ifdef DEBUG_CONFIG_ERROR printk(KERN_INFO "%s: wv_82586_start(): iscp_busy timeout.\n", dev->name); #endif @@ -3352,7 +3333,7 @@ if (i <= 0) { -#ifdef DEBUG_CONFIG_ERRORS +#ifdef DEBUG_CONFIG_ERROR printk(KERN_INFO "%s: wv_82586_start(): status: expected 0x%02x, got 0x%02x.\n", dev->name, SCB_ST_CX | SCB_ST_CNA, scb.scb_status); #endif @@ -3373,7 +3354,7 @@ obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb)); if(cb.ac_status & AC_SFLD_FAIL) { -#ifdef DEBUG_CONFIG_ERRORS +#ifdef DEBUG_CONFIG_ERROR printk(KERN_INFO "%s: wv_82586_start(): i82586 Self Test failed.\n", dev->name); #endif @@ -3654,13 +3635,16 @@ wv_ints_on(dev); /* Start card functions */ - if((wv_ru_start(dev) < 0) || - (wv_cu_start(dev) < 0)) + if(wv_cu_start(dev) < 0) return -1; - /* Finish configuration */ + /* Setup the controller and parameters */ wv_82586_config(dev); + /* Finish configuration with the receive unit */ + if(wv_ru_start(dev) < 0) + return -1; + #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: <-wv_hw_reset()\n", dev->name); #endif @@ -3968,7 +3952,7 @@ /* Check irq */ if(dev->irq == 0) { -#ifdef DEBUG_CONFIG_ERRORS +#ifdef DEBUG_CONFIG_ERROR printk(KERN_WARNING "%s: wavelan_open(): no IRQ\n", dev->name); #endif return -ENXIO; @@ -3980,7 +3964,7 @@ (request_irq(dev->irq, &wavelan_interrupt, 0, "WaveLAN", NULL) != 0)) { irq2dev_map[dev->irq] = (device *) NULL; -#ifdef DEBUG_CONFIG_ERRORS +#ifdef DEBUG_CONFIG_ERROR printk(KERN_WARNING "%s: wavelan_open(): invalid IRQ\n", dev->name); #endif return -EAGAIN; @@ -3996,7 +3980,7 @@ { free_irq(dev->irq, NULL); irq2dev_map[dev->irq] = (device *) NULL; -#ifdef DEBUG_CONFIG_ERRORS +#ifdef DEBUG_CONFIG_ERROR printk(KERN_INFO "%s: wavelan_open(): impossible to start the card\n", dev->name); #endif @@ -4094,10 +4078,8 @@ #endif psa_write(ioaddr, HACR_DEFAULT, psaoff(0, psa_int_req_no), &irq_mask, 1); -#ifdef SET_PSA_CRC /* update the Wavelan checksum */ update_psa_checksum(dev, ioaddr, HACR_DEFAULT); -#endif wv_hacr_reset(ioaddr); } } @@ -4151,7 +4133,9 @@ dev->hard_start_xmit = wavelan_packet_xmit; dev->get_stats = wavelan_get_stats; dev->set_multicast_list = &wavelan_set_multicast_list; +#ifdef SET_MAC_ADDRESS dev->set_mac_address = &wavelan_set_mac_address; +#endif /* SET_MAC_ADDRESS */ #ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */ dev->do_ioctl = wavelan_ioctl; @@ -4207,7 +4191,7 @@ /* Don't probe at all. */ if(base_addr < 0) { -#ifdef DEBUG_CONFIG_ERRORS +#ifdef DEBUG_CONFIG_ERROR printk(KERN_WARNING "%s: wavelan_probe(): invalid base address\n", dev->name); #endif @@ -4290,7 +4274,7 @@ /* If probing is asked */ if(io[0] == 0) { -#ifdef DEBUG_CONFIG_ERRORS +#ifdef DEBUG_CONFIG_ERROR printk(KERN_WARNING "WaveLAN init_module(): doing device probing (bad !)\n"); printk(KERN_WARNING "Specify base addresses while loading module to correct the problem\n"); #endif @@ -4334,7 +4318,7 @@ } /* if there is something at the address */ } /* Loop on all addresses. */ -#ifdef DEBUG_CONFIG_ERRORS +#ifdef DEBUG_CONFIG_ERROR if(wavelan_list == (net_local *) NULL) printk(KERN_WARNING "WaveLAN init_module(): no device found\n"); #endif diff -urN linux-2.0.39-pre3/drivers/net/wavelan.p.h linux-2.0.39-pre4/drivers/net/wavelan.p.h --- linux-2.0.39-pre3/drivers/net/wavelan.p.h 1999-06-13 10:21:02.000000000 -0700 +++ linux-2.0.39-pre4/drivers/net/wavelan.p.h 2003-08-15 15:04:55.000000000 -0700 @@ -34,11 +34,22 @@ * I try to maintain a web page with the Wireless LAN Howto at : * http://www-uk.hpl.hp.com/people/jt/Linux/Wavelan.html * + * Debugging and options + * --------------------- + * You will find below a set of '#define" allowing a very fine control + * on the driver behaviour and the debug messages printed. + * The main options are : + * o SET_PSA_CRC, to have your card correctly recognised by + * an access point and the Point-to-Point diagnostic tool. + * o USE_PSA_CONFIG, to read configuration from the PSA (EEprom) + * (otherwise we always start afresh with some defaults) + * * wavelan.o is darn too big * ------------------------- * That's true ! There is a very simple way to reduce the driver * object by 33% (yes !). Comment out the following line : * #include + * Other compile options can also reduce the size of it... * * Debugging and options * --------------------- @@ -272,7 +283,17 @@ * - Correct i82586 configuration parameters * - Encryption initialisation bug (Robert McCormack) * - New mac addresses detected in the probe - * - Increase watchdog for busy envirnoments + * - Increase watchdog for busy environments + * + * Changes made for release in 2.0.38 & 2.2.7 : + * ------------------------------------------ + * - Correct the reception logic to better report errors and avoid + * sending bogus packet up the stack + * - Delay RU config to avoid corrupting first received packet + * - Change config completion code (to actually check something) + * - Avoid reading out of bound in skbuf to transmit + * - Rectify a lot of (useless) debugging code + * - Change the way to `#ifdef SET_PSA_CRC' * * Wishes & dreams : * --------------- @@ -311,6 +332,24 @@ #include "i82586.h" #include "wavelan.h" +/************************** DRIVER OPTIONS **************************/ +/* + * `#define' or `#undef' the following constant to change the behaviour + * of the driver... + */ +#undef SET_PSA_CRC /* Calculate and set the CRC on PSA (slower) */ +#define USE_PSA_CONFIG /* Use info from the PSA. */ +#undef STRUCT_CHECK /* Verify padding of structures. */ +#undef EEPROM_IS_PROTECTED /* doesn't seem to be necessary */ +#define MULTICAST_AVOID /* Avoid extra multicast (I'm sceptical). */ +#undef SET_MAC_ADDRESS /* Experimental */ + +#ifdef WIRELESS_EXT /* If wireless extensions exist in the kernel */ +/* Warning: this stuff will slow down the driver. */ +#define WIRELESS_SPY /* Enable spying addresses. */ +#undef HISTOGRAM /* Enable histogram of signal level. */ +#endif + /****************************** DEBUG ******************************/ #undef DEBUG_MODULE_TRACE /* Module insertion/removal */ @@ -320,14 +359,16 @@ #define DEBUG_INTERRUPT_ERROR /* problems */ #undef DEBUG_CONFIG_TRACE /* Trace the config functions */ #undef DEBUG_CONFIG_INFO /* What's going on... */ -#define DEBUG_CONFIG_ERRORS /* Errors on configuration */ +#define DEBUG_CONFIG_ERROR /* Errors on configuration */ #undef DEBUG_TX_TRACE /* Transmission calls */ #undef DEBUG_TX_INFO /* Header of the transmited packet */ -#define DEBUG_TX_ERROR /* unexpected conditions */ +#undef DEBUG_TX_FAIL /* Normal failure conditions */ +#define DEBUG_TX_ERROR /* Unexpected conditions */ #undef DEBUG_RX_TRACE /* Transmission calls */ -#undef DEBUG_RX_INFO /* Header of the transmited packet */ -#define DEBUG_RX_ERROR /* unexpected conditions */ -#undef DEBUG_PACKET_DUMP 16 /* Dump packet on the screen */ +#undef DEBUG_RX_INFO /* Header of the received packet */ +#undef DEBUG_RX_FAIL /* Normal failure conditions */ +#define DEBUG_RX_ERROR /* Unexpected conditions */ +#undef DEBUG_PACKET_DUMP 32 /* Dump packet on the screen */ #undef DEBUG_IOCTL_TRACE /* Misc call by Linux */ #undef DEBUG_IOCTL_INFO /* Various debug info */ #define DEBUG_IOCTL_ERROR /* What's going wrong */ @@ -339,26 +380,10 @@ #undef DEBUG_I82586_SHOW /* Show i82586 status */ #undef DEBUG_DEVICE_SHOW /* Show device parameters */ -/* Options : */ -#define USE_PSA_CONFIG /* Use info from the PSA */ -#define SET_PSA_CRC /* Calculate and set the CRC on PSA */ -#define IGNORE_NORMAL_XMIT_ERRS /* Don't bother with normal conditions */ -#undef STRUCT_CHECK /* Verify padding of structures */ -#undef OLDIES /* Old code (to redo) */ -#undef RECORD_SNR /* To redo */ -#undef EEPROM_IS_PROTECTED /* Doesn't seem to be necessary */ -#define MULTICAST_AVOID /* Avoid extra multicast (I'm sceptical) */ - -#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */ -/* Warning : these stuff will slow down the driver... */ -#define WIRELESS_SPY /* Enable spying addresses */ -#undef HISTOGRAM /* Enable histogram of sig level... */ -#endif - /************************ CONSTANTS & MACROS ************************/ #ifdef DEBUG_VERSION_SHOW -static const char *version = "wavelan.c : v18 (wireless extensions) 18/2/99\n"; +static const char *version = "wavelan.c : v19 (wireless extensions) 20/4/99\n"; #endif /* Watchdog temporisation */ diff -urN linux-2.0.39-pre3/fs/binfmt_elf.c linux-2.0.39-pre4/fs/binfmt_elf.c --- linux-2.0.39-pre3/fs/binfmt_elf.c 1998-06-03 15:17:49.000000000 -0700 +++ linux-2.0.39-pre4/fs/binfmt_elf.c 2003-08-15 15:04:55.000000000 -0700 @@ -197,28 +197,20 @@ interp_elf_ex->e_type != ET_DYN) || !elf_check_arch(interp_elf_ex->e_machine) || (!interpreter_inode->i_op || - !interpreter_inode->i_op->default_file_ops->mmap)) { + !interpreter_inode->i_op->default_file_ops->mmap) || + interp_elf_ex->e_phentsize != sizeof(struct elf_phdr) || + interp_elf_ex->e_phnum < 1 || + interp_elf_ex->e_phnum > PAGE_SIZE / sizeof(struct elf_phdr)) { return ~0UL; } /* Now read in all of the header information */ - if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) - return ~0UL; - elf_phdata = (struct elf_phdr *) kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, GFP_KERNEL); if (!elf_phdata) return ~0UL; - /* - * If the size of this structure has changed, then punt, since - * we will be doing the wrong thing. - */ - if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) { - kfree(elf_phdata); - return ~0UL; - } retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff, (char *) elf_phdata, sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, 1); @@ -306,6 +298,11 @@ kfree(elf_phdata); *interp_load_addr = load_addr; + /* + * AUDIT: is everything deallocated properly if this happens + * to be ~0UL? We'd better switch to out-of-band error reporting. + * Also for a.out. + */ return ((unsigned long) interp_elf_ex->e_entry) + load_addr; } @@ -397,7 +394,10 @@ elf_ex.e_type != ET_DYN) || (!elf_check_arch(elf_ex.e_machine)) || (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops || - !bprm->inode->i_op->default_file_ops->mmap)) { + !bprm->inode->i_op->default_file_ops->mmap) || + elf_ex.e_phentsize != sizeof(struct elf_phdr) || + elf_ex.e_phnum < 1 || + elf_ex.e_phnum > 0xfff0 / sizeof(struct elf_phdr)) { return -ENOEXEC; } /* Now read in all of the header information */ @@ -434,12 +434,14 @@ for (i = 0; i < elf_ex.e_phnum; i++) { if (elf_ppnt->p_type == PT_INTERP) { - if (elf_interpreter != NULL) { + if (elf_interpreter != NULL || + elf_ppnt->p_filesz < 2 || + elf_ppnt->p_filesz > PAGE_SIZE) { iput(interpreter_inode); kfree(elf_phdata); kfree(elf_interpreter); sys_close(elf_exec_fileno); - return -EINVAL; + return -ENOEXEC; } /* This is the program interpreter used for * shared libraries - for now assume that this @@ -456,6 +458,7 @@ retval = read_exec(bprm->inode, elf_ppnt->p_offset, elf_interpreter, elf_ppnt->p_filesz, 1); + elf_interpreter[elf_ppnt->p_filesz - 1] = 0; /* If the program interpreter is one of these two, then assume an iBCS2 image. Otherwise assume a native linux image. */ @@ -629,14 +632,17 @@ &interp_load_addr); iput(interpreter_inode); - kfree(elf_interpreter); if (elf_entry == ~0UL) { - printk("Unable to load interpreter\n"); + printk("Unable to load interpreter %.128s\n", + elf_interpreter); + kfree(elf_interpreter); kfree(elf_phdata); send_sig(SIGSEGV, current, 0); return 0; } + + kfree(elf_interpreter); } kfree(elf_phdata); diff -urN linux-2.0.39-pre3/fs/dquot.c linux-2.0.39-pre4/fs/dquot.c --- linux-2.0.39-pre3/fs/dquot.c 1998-07-13 13:47:34.000000000 -0700 +++ linux-2.0.39-pre4/fs/dquot.c 2003-08-15 15:04:55.000000000 -0700 @@ -143,14 +143,17 @@ return; dqstats.pages_allocated++; cnt = PAGE_SIZE / sizeof(struct dquot); + memset(dquot, 0, PAGE_SIZE); nr_dquots += cnt; nr_free_dquots += cnt; if (!first_dquot) { dquot->dq_next = dquot->dq_prev = first_dquot = dquot++; cnt--; } - for (; cnt; cnt--) + for (; cnt; cnt--) { + init_waitqueue(&dquot->dq_wait); insert_dquot_free(dquot++); + } } /* @@ -219,11 +222,18 @@ short type = dquot->dq_type; struct file *filp = dquot->dq_mnt->mnt_quotas[type]; unsigned short fs; + struct dqblk wrt_dquot; if (!(dquot->dq_flags & DQ_MOD) || (filp == (struct file *)NULL)) return; lock_dquot(dquot); + if (!dquot->dq_mnt) { /* Invalidated dquot? */ + unlock_dquot(dquot); + return; + } down(&dquot->dq_mnt->mnt_sem); + dquot->dq_flags &= ~DQ_MOD; /* Clear the flag unconditionally - we don't want to loop on error */ + memcpy(&wrt_dquot, &dquot->dq_dqb, sizeof(struct dqblk)); /* Copy structure so we can unlock it */ if (filp->f_op->lseek) { if (filp->f_op->lseek(filp->f_inode, filp, dqoff(dquot->dq_id), 0) != dqoff(dquot->dq_id)) { @@ -238,14 +248,13 @@ if(p>=0) filp->f_pos = p; } + unlock_dquot(dquot); /* We have to unlock structure as write might need to update it */ fs = get_fs(); set_fs(KERNEL_DS); - if (filp->f_op->write(filp->f_inode, filp, - (char *)&dquot->dq_dqb, sizeof(struct dqblk)) == sizeof(struct dqblk)) - dquot->dq_flags &= ~DQ_MOD; + if (filp->f_op->write(filp->f_inode, filp, (char *)&wrt_dquot, sizeof(struct dqblk)) != sizeof(struct dqblk)) + printk(KERN_ERR "VFS: write_dquot() failed.\n"); up(&dquot->dq_mnt->mnt_sem); set_fs(fs); - unlock_dquot(dquot); dqstats.writes++; } @@ -286,14 +295,18 @@ int i; dqstats.syncs++; +restart: for (i = 0; i < nr_dquots * 2; i++, dquot = dquot->dq_next) { if (dev == NODEV || dquot->dq_count == 0 || dquot->dq_dev != dev) continue; if (type != -1 && dquot->dq_type != type) continue; + if (!(dquot->dq_flags & DQ_MOD)) /* It might get modified I know but to restart after each locked dquot... */ + continue; wait_on_dquot(dquot); if (dquot->dq_flags & DQ_MOD) write_dquot(dquot); + goto restart; } return(0); } @@ -306,6 +319,7 @@ struct dquot *dquot, *next; int cnt; +restart: next = first_dquot; for (cnt = nr_dquots ; cnt > 0 ; cnt--) { dquot = next; @@ -316,10 +330,14 @@ printk("VFS: dquot busy on removed device %s\n", kdevname(dev)); continue; } - if (dquot->dq_flags & DQ_MOD) + if (dquot->dq_flags & DQ_MOD) { write_dquot(dquot); + dqstats.drops++; + clear_dquot(dquot); + goto restart; /* As we might block inside of write or clear_dquot */ + } dqstats.drops++; - clear_dquot(dquot); + clear_dquot(dquot); /* Here we can't block - DQ_LOCKED was tested before */ } } @@ -463,30 +481,34 @@ * checking and doesn't need to be written. It just an empty * dquot that is put back into the freelist. */ - if (dquot->dq_mnt != (struct vfsmount *)NULL) { - dqstats.drops++; - wait_on_dquot(dquot); +repeat: + if (dquot->dq_mnt) { /* We can block inside of wait and so we have to check again */ + if (dquot->dq_flags & DQ_LOCKED) { + __wait_on_dquot(dquot); + goto repeat; + } + if (!dquot->dq_count) { printk("VFS: dqput: trying to free free dquot\n"); printk("VFS: device %s, dquot of %s %d\n", kdevname(dquot->dq_dev), quotatypes[dquot->dq_type], dquot->dq_id); return; } -repeat: if (dquot->dq_count > 1) { dquot->dq_count--; return; } - wake_up(&dquot_wait); if (dquot->dq_flags & DQ_MOD) { write_dquot(dquot); /* we can sleep - so do again */ wait_on_dquot(dquot); goto repeat; } + dqstats.drops++; } if (dquot->dq_count) { dquot->dq_count--; nr_free_dquots++; + wake_up(&dquot_wait); /* Here the dquot is really free */ } return; } @@ -583,6 +605,14 @@ put_last_free(dquot); insert_dquot_hash(dquot); read_dquot(dquot); + if (!dquot->dq_mnt) { /* Invalidated in the mean time? */ + /* + * As quota was turned off we can just return NODQUOT. I know it's + * not perfect as somebody might turn quota on again but... + */ + dqput(dquot); + return NODQUOT; + } return(dquot); } @@ -959,9 +989,11 @@ vfsmnt->mnt_sb->dq_op = (struct dquot_operations *)NULL; reset_dquot_ptrs(dev, cnt); invalidate_dquots(dev, cnt); + down(&vfsmnt->mnt_sem); /* Wait for any pending IO - dquot is not locked on write so we can easily go here during write */ close_fp(vfsmnt->mnt_quotas[cnt]); vfsmnt->mnt_quotas[cnt] = (struct file *)NULL; vfsmnt->mnt_iexp[cnt] = vfsmnt->mnt_bexp[cnt] = (time_t)NULL; + up(&vfsmnt->mnt_sem); } return(0); } diff -urN linux-2.0.39-pre3/fs/exec.c linux-2.0.39-pre4/fs/exec.c --- linux-2.0.39-pre3/fs/exec.c 1998-07-13 13:47:34.000000000 -0700 +++ linux-2.0.39-pre4/fs/exec.c 2003-08-15 15:04:55.000000000 -0700 @@ -178,26 +178,51 @@ /* * count() counts the number of arguments/envelopes - * - * We also do some limited EFAULT checking: this isn't complete, but - * it does cover most cases. I'll have to do this correctly some day.. */ -static int count(char ** argv) +static int count(void *base, int size, int max) { int error, i = 0; - char ** tmp, *p; + void *tmp = base; + unsigned long length = 0, chunk = size, limit; + int grow = 1; + + if (!tmp) return 0; + + limit = PAGE_SIZE - ((unsigned long)tmp & (PAGE_SIZE - 1)); + error = verify_area(VERIFY_READ, tmp, limit); + if (error) limit = 0; + + do { + if (length >= limit) + do { + if (!grow) { + if (chunk <= sizeof(char *)) + return -EFAULT; + chunk >>= 1; + } + error = verify_area(VERIFY_READ, tmp, chunk); + if (error) grow = 0; else { + limit += chunk; + if (grow) chunk <<= 1; + } + } while (error); - if ((tmp = argv) != NULL) { - error = verify_area(VERIFY_READ, tmp, sizeof(char *)); - if (error) - return error; - while ((p = get_user(tmp++)) != NULL) { - i++; - error = verify_area(VERIFY_READ, p, 1); - if (error) - return error; + if (size == 1) { + do { + if (!get_user(((char *)tmp)++)) goto out; + if (++i > max) return -E2BIG; + } while (i < limit); + length = i; + } else { + do { + if (!get_user(((char **)tmp)++)) goto out; + if ((length += size) > max) return -E2BIG; + i++; + } while (length < limit); } - } + } while (1); + +out: return i; } @@ -221,12 +246,12 @@ unsigned long copy_strings(int argc,char ** argv,unsigned long *page, unsigned long p, int from_kmem) { - char *tmp, *tmp1, *pag = NULL; + char *tmp, *pag = NULL; int len, offset = 0; unsigned long old_fs, new_fs; - if (!p) - return 0; /* bullet-proofing */ + if ((long)p <= 0) + return p; /* bullet-proofing */ new_fs = get_ds(); old_fs = get_fs(); if (from_kmem==2) @@ -234,16 +259,16 @@ while (argc-- > 0) { if (from_kmem == 1) set_fs(new_fs); - if (!(tmp1 = tmp = get_user(argv+argc))) + if (!(tmp = get_user(argv+argc))) panic("VFS: argc is wrong"); if (from_kmem == 1) set_fs(old_fs); - while (get_user(tmp++)); - len = tmp - tmp1; - if (p < len) { /* this shouldn't happen - 128kB */ + len = count(tmp, 1, p); + if (len < 0 || len >= p) { /* EFAULT or E2BIG */ set_fs(old_fs); - return 0; + return len < 0 ? len : -E2BIG; } + tmp += ++len; while (len) { --p; --tmp; --len; if (--offset < 0) { @@ -253,7 +278,7 @@ if (!(pag = (char *) page[p/PAGE_SIZE]) && !(pag = (char *) page[p/PAGE_SIZE] = (unsigned long *) get_free_page(GFP_USER))) - return 0; + return -EFAULT; if (from_kmem==2) set_fs(new_fs); @@ -559,6 +584,27 @@ if (!suser()) return -EPERM; } + + /* + * Increment the privileged execution counter, so that our + * old children know not to send bad exit_signal's to us. + */ + if (!++current->priv) { + struct task_struct *p; + + /* + * The counter can't really overflow with real-world + * programs (and it has to be the privileged program + * itself that causes the overflow), but we handle + * this case anyway, just for correctness. + */ + for_each_task(p) { + if (p->p_pptr == current) { + p->ppriv = 0; + current->priv = 1; + } + } + } } memset(bprm->buf,0,sizeof(bprm->buf)); @@ -601,6 +647,8 @@ bprm->dont_iput = 1; remove_arg_zero(bprm); bprm->p = copy_strings(1, dynloader, bprm->page, bprm->p, 2); + if ((long)bprm->p < 0) + return (long)bprm->p; bprm->argc++; bprm->loader = bprm->p; retval = open_namei(dynloader[0], 0, 0, &bprm->inode, NULL); @@ -673,9 +721,9 @@ bprm.loader = 0; bprm.exec = 0; bprm.dont_iput = 0; - if ((bprm.argc = count(argv)) < 0) + if ((bprm.argc = count(argv, sizeof(char *), bprm.p)) < 0) return bprm.argc; - if ((bprm.envc = count(envp)) < 0) + if ((bprm.envc = count(envp, sizeof(char *), bprm.p)) < 0) return bprm.envc; retval = prepare_binprm(&bprm); @@ -685,8 +733,8 @@ bprm.exec = bprm.p; bprm.p = copy_strings(bprm.envc,envp,bprm.page,bprm.p,0); bprm.p = copy_strings(bprm.argc,argv,bprm.page,bprm.p,0); - if (!bprm.p) - retval = -E2BIG; + if ((long)bprm.p < 0) + retval = (long)bprm.p; } if(retval>=0) diff -urN linux-2.0.39-pre3/fs/proc/array.c linux-2.0.39-pre4/fs/proc/array.c --- linux-2.0.39-pre3/fs/proc/array.c 1999-06-13 10:21:03.000000000 -0700 +++ linux-2.0.39-pre4/fs/proc/array.c 2003-08-15 15:04:55.000000000 -0700 @@ -610,6 +610,7 @@ vsize += vma->vm_end - vma->vm_start; vma = vma->vm_next; } + if ((current->fsuid == tsk->euid && tsk->dumpable) || suser()) if (tsk->kernel_stack_page) { eip = KSTK_EIP(tsk); esp = KSTK_ESP(tsk); @@ -1026,7 +1027,7 @@ case PROC_PID_CMDLINE: return 0; } - if(suser() || current->fsuid == (*p)->euid) + if ((current->fsuid == (*p)->euid && (*p)->dumpable) || suser()) return 0; return 1; } diff -urN linux-2.0.39-pre3/fs/proc/fd.c linux-2.0.39-pre4/fs/proc/fd.c --- linux-2.0.39-pre3/fs/proc/fd.c 1997-11-12 20:36:41.000000000 -0800 +++ linux-2.0.39-pre4/fs/proc/fd.c 2003-08-15 15:04:55.000000000 -0700 @@ -86,6 +86,7 @@ } iput(dir); fd = 0; + if (len > 1 && *name == '0') fd = 0xfffff; else while (len-- > 0) { c = *name - '0'; name++; diff -urN linux-2.0.39-pre3/fs/proc/mem.c linux-2.0.39-pre4/fs/proc/mem.c --- linux-2.0.39-pre3/fs/proc/mem.c 2003-08-15 15:04:55.000000000 -0700 +++ linux-2.0.39-pre4/fs/proc/mem.c 1998-11-15 10:33:14.000000000 -0800 @@ -17,17 +17,16 @@ /* * mem_write isn't really a good idea right now. It needs - * to check a lot more: if the process we try to write to + * to check a lot more: if the process we try to write to * dies in the middle right now, mem_write will overwrite * kernel memory.. This disables it altogether. */ #define mem_write NULL -static ssize_t check_range(struct mm_struct * mm, unsigned long addr, - size_t count) +static int check_range(struct mm_struct * mm, unsigned long addr, int count) { struct vm_area_struct *vma; - ssize_t retval; + int retval; vma = find_vma(mm, addr); if (!vma) @@ -77,8 +76,7 @@ return tsk; } -static ssize_t mem_read(struct inode * inode, struct file * file, - char * buf, size_t count) +static int mem_read(struct inode * inode, struct file * file,char * buf, int count) { pgd_t *page_dir; pmd_t *page_middle; @@ -87,7 +85,7 @@ struct task_struct * tsk; unsigned long addr; char *tmp; - ssize_t scount, i; + int i; if (count < 0) return -EINVAL; @@ -95,11 +93,11 @@ if (!tsk) return -ESRCH; addr = file->f_pos; - scount = check_range(tsk->mm, addr, count); - if (scount < 0) - return scount; + count = check_range(tsk->mm, addr, count); + if (count < 0) + return count; tmp = buf; - while (scount > 0) { + while (count > 0) { if (current->signal & ~current->blocked) break; page_dir = pgd_offset(tsk->mm,addr); @@ -123,12 +121,12 @@ break; page = (char *) pte_page(pte) + (addr & ~PAGE_MASK); i = PAGE_SIZE-(addr & ~PAGE_MASK); - if (i > scount) - i = scount; + if (i > count) + i = count; memcpy_tofs(tmp, page, i); addr += i; tmp += i; - scount -= i; + count -= i; } file->f_pos = addr; return tmp-buf; @@ -136,8 +134,7 @@ #ifndef mem_write -static ssize_t mem_write(struct inode * inode, struct file * file, - char * buf, ssize_t count) +static int mem_write(struct inode * inode, struct file * file,char * buf, int count) { pgd_t *page_dir; pmd_t *page_middle; @@ -146,7 +143,7 @@ struct task_struct * tsk; unsigned long addr; char *tmp; - ssize_t i; + int i; if (count < 0) return -EINVAL; @@ -198,8 +195,7 @@ #endif -static off_t mem_lseek(struct inode * inode, struct file * file, - off_t offset, int orig) +static int mem_lseek(struct inode * inode, struct file * file, off_t offset, int orig) { switch (orig) { case 0: diff -urN linux-2.0.39-pre3/fs/proc/root.c linux-2.0.39-pre4/fs/proc/root.c --- linux-2.0.39-pre3/fs/proc/root.c 1996-04-30 03:09:45.000000000 -0700 +++ linux-2.0.39-pre4/fs/proc/root.c 2003-08-15 15:04:55.000000000 -0700 @@ -466,6 +466,7 @@ } pid *= 10; pid += c; + if (!pid) break; if (pid & 0xffff0000) { pid = 0; break; diff -urN linux-2.0.39-pre3/include/linux/sched.h linux-2.0.39-pre4/include/linux/sched.h --- linux-2.0.39-pre3/include/linux/sched.h 1997-12-02 14:18:11.000000000 -0800 +++ linux-2.0.39-pre4/include/linux/sched.h 2003-08-15 15:04:55.000000000 -0700 @@ -244,6 +244,8 @@ struct mm_struct *mm; /* signal handlers */ struct signal_struct *sig; +/* privileged execution counters, for exit_signal permission checking */ + int priv, ppriv; #ifdef __SMP__ int processor; int last_processor; @@ -309,6 +311,7 @@ /* files */ &init_files, \ /* mm */ &init_mm, \ /* signals */ &init_signals, \ +/* priv */ 0, 0, \ } extern struct mm_struct init_mm; diff -urN linux-2.0.39-pre3/include/net/ip_masq.h linux-2.0.39-pre4/include/net/ip_masq.h --- linux-2.0.39-pre3/include/net/ip_masq.h 1999-06-13 10:21:04.000000000 -0700 +++ linux-2.0.39-pre4/include/net/ip_masq.h 2003-08-15 15:04:55.000000000 -0700 @@ -24,6 +24,8 @@ #define PORT_MASQ_BEGIN 61000 #define PORT_MASQ_END (PORT_MASQ_BEGIN+4096) +#define IP_MASQ_TAB_SIZE 256 /* MUST be a power of 2 */ + /* * Default timeouts for masquerade functions The control channels now * expire the same as TCP channels (other than being updated by @@ -113,6 +115,18 @@ extern int ip_masq_free_ports[3]; +#ifdef CONFIG_IP_MASQUERADE_IPSEC +/* + * Any application support module that changes the destination + * IP or port *must* rehash if IPsec masq is enabled + */ +extern struct ip_masq *ip_masq_m_tab[IP_MASQ_TAB_SIZE]; +extern struct ip_masq *ip_masq_s_tab[IP_MASQ_TAB_SIZE]; +extern struct ip_masq *ip_masq_d_tab[IP_MASQ_TAB_SIZE]; +extern __inline__ int ip_masq_hash(struct ip_masq *ms); +extern __inline__ int ip_masq_unhash(struct ip_masq *ms); +#endif /* CONFIG_IP_MASQUERADE_IPSEC */ + /* * ip_masq initializer (registers symbols and /proc/net entries) */ diff -urN linux-2.0.39-pre3/kernel/exit.c linux-2.0.39-pre4/kernel/exit.c --- linux-2.0.39-pre3/kernel/exit.c 1998-06-03 15:17:50.000000000 -0700 +++ linux-2.0.39-pre4/kernel/exit.c 2003-08-15 15:04:55.000000000 -0700 @@ -118,7 +118,8 @@ void notify_parent(struct task_struct * tsk, int signal) { - send_sig(signal, tsk->p_pptr, 1); + send_sig(signal, tsk->p_pptr, !signal || signal == SIGCHLD || + tsk->p_pptr->priv == tsk->ppriv); wake_up_interruptible(&tsk->p_pptr->wait_chldexit); } diff -urN linux-2.0.39-pre3/kernel/fork.c linux-2.0.39-pre4/kernel/fork.c --- linux-2.0.39-pre3/kernel/fork.c 1998-06-03 15:17:50.000000000 -0700 +++ linux-2.0.39-pre4/kernel/fork.c 2003-08-15 15:04:55.000000000 -0700 @@ -228,10 +228,23 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) { int nr; - int error = -ENOMEM; + int error = -EINVAL; unsigned long new_stack; struct task_struct *p; +/* + * Disallow unknown clone(2) flags, as well as CLONE_PID, unless we are + * the boot up thread. + * + * Avoid taking any branches in the common case. + */ + if (clone_flags & + (-(signed long)current->pid >> (sizeof(long) * 8 - 1)) & + ~(unsigned long)(CSIGNAL | + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND)) + goto bad_fork; + + error = -ENOMEM; p = (struct task_struct *) kmalloc(sizeof(*p), GFP_KERNEL); if (!p) goto bad_fork; @@ -264,6 +277,8 @@ p->p_cptr = NULL; init_waitqueue(&p->wait_chldexit); p->signal = 0; + p->priv = 0; + p->ppriv = current->priv; p->it_real_value = p->it_virt_value = p->it_prof_value = 0; p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0; init_timer(&p->real_timer); diff -urN linux-2.0.39-pre3/net/ipv4/ip_masq.c linux-2.0.39-pre4/net/ipv4/ip_masq.c --- linux-2.0.39-pre3/net/ipv4/ip_masq.c 1999-06-13 10:21:04.000000000 -0700 +++ linux-2.0.39-pre4/net/ipv4/ip_masq.c 2003-08-15 15:04:55.000000000 -0700 @@ -1,8 +1,8 @@ /* * - * Masquerading functionality + * Masquerading functionality * - * Copyright (c) 1994 Pauline Middelink + * Copyright (c) 1994 Pauline Middelink * * See ip_fw.c for original log * @@ -20,8 +20,9 @@ * Delian Delchev : Added support for ICMP requests and replys * Nigel Metheringham : ICMP in ICMP handling, tidy ups, bug fixes, made ICMP optional * Juan Jose Ciarlante : re-assign maddr if no packet received from outside - * John D. Hardin : Added PPTP and IPSEC protocols - * + * John D. Hardin : Added PPTP and IPSEC protocols + * Rudolf Lippan : dest hashing bugfix + * */ #include @@ -44,8 +45,6 @@ #include #include -#define IP_MASQ_TAB_SIZE 256 /* must be power of 2 */ - #ifdef CONFIG_IP_MASQUERADE_PPTP /* * This is clumsier than it otherwise might be (i.e. the @@ -301,6 +300,10 @@ X(ip_masq_set_expire), X(ip_masq_free_ports), X(ip_masq_expire), +#ifdef CONFIG_IP_MASQUERADE_IPSEC + X(ip_masq_hash), + X(ip_masq_unhash), +#endif /* CONFIG_IP_MASQUERADE_IPSEC */ X(ip_masq_out_get_2), #include }; @@ -445,7 +448,10 @@ * returns bool success. */ -static __inline__ int +#ifndef CONFIG_IP_MASQUERADE_IPSEC +static +#endif /* CONFIG_IP_MASQUERADE_IPSEC */ +__inline__ int ip_masq_hash(struct ip_masq *ms) { unsigned hash; @@ -495,7 +501,10 @@ * returns bool success. */ -static __inline__ int ip_masq_unhash(struct ip_masq *ms) +#ifndef CONFIG_IP_MASQUERADE_IPSEC +static +#endif /* CONFIG_IP_MASQUERADE_IPSEC */ +__inline__ int ip_masq_unhash(struct ip_masq *ms) { unsigned hash; struct ip_masq ** ms_p; @@ -3158,16 +3167,38 @@ */ if ( ms->flags & IP_MASQ_F_NO_DPORT && ms->protocol == IPPROTO_TCP ) { +#ifdef CONFIG_IP_MASQUERADE_IPSEC + unsigned long flags; + save_flags(flags); + cli(); + ip_masq_unhash(ms); +#endif /* CONFIG_IP_MASQUERADE_IPSEC */ ms->flags &= ~IP_MASQ_F_NO_DPORT; ms->dport = portptr[0]; +#ifdef CONFIG_IP_MASQUERADE_IPSEC + ip_masq_hash(ms); + restore_flags(flags); +#endif /* CONFIG_IP_MASQUERADE_IPSEC */ + #ifdef DEBUG_CONFIG_IP_MASQUERADE printk("ip_fw_demasquerade(): filled dport=%d\n", ntohs(ms->dport)); #endif } if (ms->flags & IP_MASQ_F_NO_DADDR && ms->protocol == IPPROTO_TCP) { +#ifdef CONFIG_IP_MASQUERADE_IPSEC + unsigned long flags; + save_flags(flags); + cli(); + ip_masq_unhash(ms); +#endif /* CONFIG_IP_MASQUERADE_IPSEC */ ms->flags &= ~IP_MASQ_F_NO_DADDR; ms->daddr = iph->saddr; +#ifdef CONFIG_IP_MASQUERADE_IPSEC + ip_masq_hash(ms); + restore_flags(flags); +#endif /* CONFIG_IP_MASQUERADE_IPSEC */ + #ifdef DEBUG_CONFIG_IP_MASQUERADE printk("ip_fw_demasquerade(): filled daddr=%X\n", ntohs(ms->daddr)); diff -urN linux-2.0.39-pre3/net/ipv4/ip_masq_quake.c linux-2.0.39-pre4/net/ipv4/ip_masq_quake.c --- linux-2.0.39-pre3/net/ipv4/ip_masq_quake.c 1998-11-15 10:33:21.000000000 -0800 +++ linux-2.0.39-pre4/net/ipv4/ip_masq_quake.c 2003-08-15 15:04:55.000000000 -0700 @@ -85,6 +85,9 @@ int masq_quake_in (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, struct device *dev) { +#ifdef CONFIG_IP_MASQUERADE_IPSEC + unsigned long flags; +#endif /* CONFIG_IP_MASQUERADE_IPSEC */ struct sk_buff *skb; struct iphdr *iph; struct udphdr *uh; @@ -155,7 +158,16 @@ memcpy(&udp_port, data, 2); +#ifdef CONFIG_IP_MASQUERADE_IPSEC + save_flags(flags); + cli(); + ip_masq_unhash(ms); +#endif /* CONFIG_IP_MASQUERADE_IPSEC */ ms->dport = htons(udp_port); +#ifdef CONFIG_IP_MASQUERADE_IPSEC + ip_masq_hash(ms); + restore_flags(flags); +#endif /* CONFIG_IP_MASQUERADE_IPSEC */ #if DEBUG_CONFIG_IP_MASQ_QUAKE printk("Quake_in: in_rewrote UDP port %d \n", udp_port); diff -urN linux-2.0.39-pre3/net/ipv4/tcp_input.c linux-2.0.39-pre4/net/ipv4/tcp_input.c --- linux-2.0.39-pre3/net/ipv4/tcp_input.c 2003-08-15 15:04:55.000000000 -0700 +++ linux-2.0.39-pre4/net/ipv4/tcp_input.c 2003-08-15 15:04:55.000000000 -0700 @@ -1186,6 +1186,15 @@ * then we can probably ignore it. */ + if (sk->state == TCP_SYN_RECV) { + /* + * Should be the exact sequence number for the handshake + * to succeed, or sequence prediction gets a bit easier. + * Also, "partially-established" connections are bad for + * the rest of our code. + */ + if (ack != sk->sent_seq) goto uninteresting_ack; + } else if (after(ack, sk->sent_seq) || before(ack, sk->rcv_ack_seq)) goto uninteresting_ack;