From e941cf585cf1196d6067e6f113d938eced097732 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 23 Nov 2007 15:24:22 -0500 Subject: [PATCH] Linux 2.2.22-rc2 This is going straight to rc1 because it contains a lot of security fixes for local security problems found by Silvio's audit Solar Designer and a couple of other folks. The other stuff is minor and is the entire 2.2 pending queue anyway. Special thanks go to Openwall who did pretty much all of the security backporting work. This is mostly their kernel update not mine. o Fix isofs over loopback problems (Balazs Takacs) o Backport 2.4 shutdown/reset SIGIO from 2.4 (Julian Anastasov) o Fix error reporting in OOM cases (Julian Anastasov) o List a 2.2 maintainer in MAINTAINERS (Keith Owens) o Set atime on AF_UNIX sockets (Solar Designer) o Restore SPARC MD boot configuration (Tomas Szepe) o Multiple further sign/overflow fixes (Solar Designer) o Fix ov511 'vfree in interrupt' (Mark McClelland) --- Documentation/usb/ov511.txt | 12 +--- MAINTAINERS | 5 ++ Makefile | 2 +- arch/i386/vmlinux.lds | 77 -------------------- arch/sparc/config.in | 3 + drivers/cdrom/cdu31a.c | 2 + drivers/char/bttv.c | 8 ++- drivers/char/console.c | 2 + drivers/char/consolemap.c | 12 ++-- drivers/char/hfmodem/tables.h | 90 ------------------------ drivers/char/lp.c | 2 +- drivers/char/vt.c | 5 +- drivers/isdn/isdn_common.c | 31 +++++--- drivers/isdn/isdn_ppp.c | 20 +++--- drivers/isdn/isdn_ppp.h | 4 +- drivers/isdn/pcbit/capi.c | 4 +- drivers/net/hamradio/baycom_par.c | 49 ------------- drivers/net/hamradio/soundmodem/sm_sbc.c | 38 ---------- drivers/net/hamradio/soundmodem/sm_wss.c | 6 -- drivers/net/hamradio/yam.c | 68 ------------------ drivers/sbus/char/openprom.c | 2 +- drivers/sbus/char/sunkbd.c | 4 +- drivers/sbus/char/sunmouse.c | 4 +- drivers/scsi/ips.h | 4 -- drivers/usb/ov511.c | 57 +++------------ drivers/usb/ov511.h | 2 - drivers/video/cgfourteenfb.c | 10 +-- fs/dcache.c | 35 ++++++--- fs/fat/misc.c | 5 +- fs/isofs/inode.c | 7 +- fs/proc/openpromfs.c | 86 ++++++++++++---------- net/core/skbuff.c | 2 + net/ipv4/ip_masq.c | 2 +- net/ipv4/route.c | 14 +++- net/ipv4/tcp.c | 1 + net/ipv4/tcp_input.c | 2 +- net/socket.c | 8 +++ net/unix/af_unix.c | 11 +++ 38 files changed, 200 insertions(+), 496 deletions(-) delete mode 100644 arch/i386/vmlinux.lds delete mode 100644 drivers/char/hfmodem/tables.h diff --git a/Documentation/usb/ov511.txt b/Documentation/usb/ov511.txt index be425c1187ad..06f7ebc653f7 100644 --- a/Documentation/usb/ov511.txt +++ b/Documentation/usb/ov511.txt @@ -178,16 +178,6 @@ MODULE PARAMETERS: programs that expect RGB data (e.g. gqcam) to work with this driver. If your colors look VERY wrong, you may want to change this. - NAME: buf_timeout - TYPE: integer - DEFAULT: 5 (seconds) - DESC: Number of seconds before unused frame buffers are deallocated. - Previously, memory was allocated upon open() and deallocated upon - close(). Deallocation now occurs only if the driver is closed and this - timeout is reached. If you are capturing frames less frequently than - the default timeout, increase this. This will not make any difference - with programs that capture multiple frames during an open/close cycle. - NAME: cams TYPE: integer (1-4 for OV511, 1-31 for OV511+) DEFAULT: 1 @@ -242,7 +232,7 @@ TODO: HOW TO CONTACT ME: -You can email me at mwm@i.am . Please prefix the subject line +You can email me at mark@alpha.dyndns.org . Please prefix the subject line with "OV511: " so that I am certain to notice your message. CREDITS: diff --git a/MAINTAINERS b/MAINTAINERS index f53c67127ec7..ad3d591c6d7f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1176,6 +1176,11 @@ M: fuganti@netbank.com.br W: http://cvs.conectiva.com.br/drivers/ZFL-watchdog/ S: Maintained +LINUX 2.2 FIXES +P: Alan Cox +M: alan@lxorguk.ukuu.org.uk +S: Maintained + THE REST P: Linus Torvalds S: Buried alive in reporters diff --git a/Makefile b/Makefile index c42f9311dabd..cf1de6125b2c 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 2 SUBLEVEL = 22 -EXTRAVERSION = rc1 +EXTRAVERSION = rc2 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff --git a/arch/i386/vmlinux.lds b/arch/i386/vmlinux.lds deleted file mode 100644 index 01685b8a4ee8..000000000000 --- a/arch/i386/vmlinux.lds +++ /dev/null @@ -1,77 +0,0 @@ -/* ld script to make i386 Linux kernel - * Written by Martin Mares ; - */ -OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") -OUTPUT_ARCH(i386) -ENTRY(_start) -SECTIONS -{ - . = 0xC0000000 + 0x100000; - _text = .; /* Text and read-only data */ - .text : { - *(.text) - *(.fixup) - *(.gnu.warning) - } = 0x9090 - .text.lock : { *(.text.lock) } /* out-of-line lock text */ - .rodata : { *(.rodata) } - .kstrtab : { *(.kstrtab) } - - . = ALIGN(16); /* Exception table */ - __start___ex_table = .; - __ex_table : { *(__ex_table) } - __stop___ex_table = .; - - __start___ksymtab = .; /* Kernel symbol table */ - __ksymtab : { *(__ksymtab) } - __stop___ksymtab = .; - - _etext = .; /* End of text section */ - - .data : { /* Data */ - *(.data) - CONSTRUCTORS - } - - _edata = .; /* End of data section */ - - . = ALIGN(8192); /* init_task */ - .data.init_task : { *(.data.init_task) } - - . = ALIGN(4096); /* Init code and data */ - __init_begin = .; - .text.init : { *(.text.init) } - .data.init : { *(.data.init) } - . = ALIGN(16); /* __setup() commandline parameters */ - __setup_start = .; - .setup.init : { *(.setup.init) } - __setup_end = .; - __initcall_start = .; /* the init functions to be called */ - .initcall.init : { *(.initcall.init) } - __initcall_end = .; - . = ALIGN(4096); - __init_end = .; - - - . = ALIGN(32); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - - . = ALIGN(4096); - .data.page_aligned : { *(.data.idt) } - - - __bss_start = .; /* BSS */ - .bss : { - *(.bss) - } - _end = . ; - - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } -} diff --git a/arch/sparc/config.in b/arch/sparc/config.in index a5a8314895c3..d12c71716168 100644 --- a/arch/sparc/config.in +++ b/arch/sparc/config.in @@ -93,6 +93,9 @@ if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 fi +if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_STRIPED" = "y" ]; then + bool ' Boot support (linear, striped)' CONFIG_MD_BOOT +fi tristate 'RAM disk support' CONFIG_BLK_DEV_RAM if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c index d893cdecd815..a613503ae1c3 100644 --- a/drivers/cdrom/cdu31a.c +++ b/drivers/cdrom/cdu31a.c @@ -3027,6 +3027,8 @@ static int scd_dev_ioctl(struct cdrom_device_info *cdi, return 0; } + if (ra.nframes > INT_MAX / CD_FRAMESIZE_RAW) + return -EINVAL; i=verify_area(VERIFY_WRITE, ra.buf, CD_FRAMESIZE_RAW * ra.nframes); if(i<0) return i; diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c index 05fed64278c6..99e7da2ea02d 100644 --- a/drivers/char/bttv.c +++ b/drivers/char/bttv.c @@ -1610,6 +1610,8 @@ static long bttv_read(struct video_device *v, char *buf, unsigned long count, in struct bttv *btv= (struct bttv *)v; int q,todo; /* BROKEN: RETURNS VBI WHEN IT SHOULD RETURN GRABBED VIDEO FRAME */ + if (count > INT_MAX) + return -EINVAL; todo=count; while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) { @@ -1639,7 +1641,7 @@ static long bttv_read(struct video_device *v, char *buf, unsigned long count, in } } } - if (todo) + if (todo > 0 && todo <= VBIBUF_SIZE-btv->vbip) { if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, todo)) return -EFAULT; @@ -2457,6 +2459,8 @@ static long vbi_read(struct video_device *v, char *buf, unsigned long count, struct bttv *btv=(struct bttv *)(v-2); int q,todo; + if (count > INT_MAX) + return -EINVAL; todo=count; while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) { @@ -2486,7 +2490,7 @@ static long vbi_read(struct video_device *v, char *buf, unsigned long count, } } } - if (todo) + if (todo > 0 && todo <= VBIBUF_SIZE-btv->vbip) { if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, todo)) return -EFAULT; diff --git a/drivers/char/console.c b/drivers/char/console.c index e75951e9d020..e2a9c7737b64 100644 --- a/drivers/char/console.c +++ b/drivers/char/console.c @@ -2101,6 +2101,8 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) return -EINVAL; if (current->tty != tty && !suser()) return -EPERM; + /* Further code uses __put_user() relying on this get_user() having + * done the address range checking. */ if (get_user(type, (char *)arg)) return -EFAULT; switch (type) diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c index 7e97e1fe7ea2..0b20ce771558 100644 --- a/drivers/char/consolemap.c +++ b/drivers/char/consolemap.c @@ -611,16 +611,18 @@ con_get_unimap(int con, ushort ct, ushort *uct, struct unipair *list) if ((p2 = *(p1++))) for (k = 0; k < 64; k++) { if (*p2 < MAX_GLYPH && ect++ < ct) { - __put_user((u_short)((i<<11)+(j<<6)+k), - &list->unicode); - __put_user((u_short) *p2, - &list->fontpos); + put_user_ret((u_short)((i<<11)+(j<<6)+k), + &list->unicode, + -EFAULT); + put_user_ret((u_short) *p2, + &list->fontpos, + -EFAULT); list++; } p2++; } } - __put_user(ect, uct); + put_user_ret(ect, uct, -EFAULT); return ((ect <= ct) ? 0 : -ENOMEM); } diff --git a/drivers/char/hfmodem/tables.h b/drivers/char/hfmodem/tables.h deleted file mode 100644 index d976c8e53bce..000000000000 --- a/drivers/char/hfmodem/tables.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This file is automatically generated by ./gentbl, DO NOT EDIT! -*/ - -#define SINTABBITS 9 -#define SINTABSIZE (1<drv[drvidx]->snd_waitq[chidx]); - retval = count; + } while (1); goto out; } if (minor <= ISDN_MINOR_CTRLMAX) { @@ -1874,22 +1876,29 @@ isdn_unexclusive_channel(int di, int ch) /* * writebuf replacement for SKB_ABLE drivers */ -static int -isdn_writebuf_stub(int drvidx, int chan, const u_char * buf, int len, +static ssize_t +isdn_writebuf_stub(int drvidx, int chan, const u_char * buf, size_t len, int user) { - int ret; - int hl = dev->drv[drvidx]->interface->hl_hdrlen; - struct sk_buff *skb = alloc_skb(hl + len, GFP_ATOMIC); + int ret = 0; + unsigned int hl; + struct sk_buff *skb; + + hl = dev->drv[drvidx]->interface->hl_hdrlen; + if (len > INT_MAX / 2 || hl > INT_MAX / 2) + return -EINVAL; + skb = alloc_skb(hl + len, GFP_ATOMIC); if (!skb) - return 0; + return -ENOMEM; skb_reserve(skb, hl); if (user) - copy_from_user(skb_put(skb, len), buf, len); + ret = copy_from_user(skb_put(skb, len), buf, len) ? -EFAULT : 0; else memcpy(skb_put(skb, len), buf, len); - ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb); + if (!ret) + ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, + chan, 1, skb); if (ret <= 0) dev_kfree_skb(skb); if (ret > 0) diff --git a/drivers/isdn/isdn_ppp.c b/drivers/isdn/isdn_ppp.c index d5d081932b6c..a12c328b62d7 100644 --- a/drivers/isdn/isdn_ppp.c +++ b/drivers/isdn/isdn_ppp.c @@ -678,8 +678,8 @@ isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot) * reports, that there is data */ -int -isdn_ppp_read(int min, struct file *file, char *buf, int count) +ssize_t +isdn_ppp_read(int min, struct file *file, char *buf, size_t count) { struct ippp_struct *is; struct ippp_buf_queue *b; @@ -721,8 +721,8 @@ isdn_ppp_read(int min, struct file *file, char *buf, int count) * ipppd wanna write a packet to the card .. non-blocking */ -int -isdn_ppp_write(int min, struct file *file, const char *buf, int count) +ssize_t +isdn_ppp_write(int min, struct file *file, const char *buf, size_t count) { isdn_net_local *lp; struct ippp_struct *is; @@ -757,7 +757,7 @@ isdn_ppp_write(int min, struct file *file, const char *buf, int count) if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) && lp->dialstate == 0 && (lp->flags & ISDN_NET_CONNECTED)) { - unsigned short hl; + unsigned int hl; struct sk_buff *skb; /* * we need to reserve enought space in front of @@ -765,11 +765,11 @@ isdn_ppp_write(int min, struct file *file, const char *buf, int count) * 16 bytes, now we are looking what the driver want */ hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; + if (hl > INT_MAX / 2 || count > INT_MAX / 2) + return -EINVAL; skb = alloc_skb(hl+count, GFP_ATOMIC); - if (!skb) { - printk(KERN_WARNING "isdn_ppp_write: out of memory!\n"); - return count; - } + if (!skb) + return -ENOMEM; skb_reserve(skb, hl); if (copy_from_user(skb_put(skb, count), buf, count)) { @@ -1170,7 +1170,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct device *netdev) #ifdef CONFIG_ISDN_PPP_VJ if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes, but check this again */ struct sk_buff *new_skb; - unsigned short hl; + unsigned int hl; /* * we need to reserve enought space in front of * sk_buff. old call to dev_alloc_skb only reserved diff --git a/drivers/isdn/isdn_ppp.h b/drivers/isdn/isdn_ppp.h index f56a6bc6cca4..8a063fc725f9 100644 --- a/drivers/isdn/isdn_ppp.h +++ b/drivers/isdn/isdn_ppp.h @@ -12,8 +12,8 @@ #include /* for PPP_PROTOCOL */ #include /* for isdn_ppp info */ -extern int isdn_ppp_read(int, struct file *, char *, int); -extern int isdn_ppp_write(int, struct file *, const char *, int); +extern ssize_t isdn_ppp_read(int, struct file *, char *, size_t); +extern ssize_t isdn_ppp_write(int, struct file *, const char *, size_t); extern int isdn_ppp_open(int, struct file *); extern int isdn_ppp_init(void); extern void isdn_ppp_cleanup(void); diff --git a/drivers/isdn/pcbit/capi.c b/drivers/isdn/pcbit/capi.c index 2c882600787a..6c7a7621ce97 100644 --- a/drivers/isdn/pcbit/capi.c +++ b/drivers/isdn/pcbit/capi.c @@ -425,7 +425,7 @@ int capi_decode_conn_ind(struct pcbit_chan * chan, #ifdef DEBUG printk(KERN_DEBUG "CPN: Octect 3 %02x\n", skb->data[1]); #endif - if ((skb->data[1] & 0x80) == 0) + if (len >= 2 && (skb->data[1] & 0x80) == 0) count = 2; if (!(info->data.setup.CallingPN = kmalloc(len - count + 1, GFP_ATOMIC))) @@ -453,7 +453,7 @@ int capi_decode_conn_ind(struct pcbit_chan * chan, if (len > 0) { int count = 1; - if ((skb->data[1] & 0x80) == 0) + if (len >= 2 && (skb->data[1] & 0x80) == 0) count = 2; if (!(info->data.setup.CalledPN = kmalloc(len - count + 1, GFP_ATOMIC))) diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c index bbc29e4c1658..d8d7fb13aa86 100644 --- a/drivers/net/hamradio/baycom_par.c +++ b/drivers/net/hamradio/baycom_par.c @@ -83,53 +83,8 @@ /* --------------------------------------------------------------------- */ -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include - -#if LINUX_VERSION_CODE >= 0x20100 #include -#else -#include -#include - -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - -extern __inline__ int copy_from_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_READ, from, n); - if (i) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -extern __inline__ int copy_to_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_WRITE, to, n); - if (i) - return i; - memcpy_tofs(to, from, n); - return 0; -} -#endif - -#if LINUX_VERSION_CODE >= 0x20123 #include -#else -#define __init -#define __initdata -#define __initfunc(x) x -#endif /* --------------------------------------------------------------------- */ @@ -581,8 +536,6 @@ __initfunc(int baycom_par_init(void)) static const char *mode[NR_PORTS] = { "picpar", }; static int iobase[NR_PORTS] = { 0x378, }; -#if LINUX_VERSION_CODE >= 0x20115 - MODULE_PARM(mode, "1-" __MODULE_STRING(NR_PORTS) "s"); MODULE_PARM_DESC(mode, "baycom operating mode; eg. par96 or picpar"); MODULE_PARM(iobase, "1-" __MODULE_STRING(NR_PORTS) "i"); @@ -591,8 +544,6 @@ MODULE_PARM_DESC(iobase, "baycom io base address"); MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); MODULE_DESCRIPTION("Baycom par96 and picpar amateur radio modem driver"); -#endif - __initfunc(int init_module(void)) { int i; diff --git a/drivers/net/hamradio/soundmodem/sm_sbc.c b/drivers/net/hamradio/soundmodem/sm_sbc.c index e66a2e5cb2b3..331a747e9d84 100644 --- a/drivers/net/hamradio/soundmodem/sm_sbc.c +++ b/drivers/net/hamradio/soundmodem/sm_sbc.c @@ -38,45 +38,7 @@ /* --------------------------------------------------------------------- */ -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include - -#if LINUX_VERSION_CODE >= 0x20100 #include -#else -#include -#include - -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - -extern inline int copy_from_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_READ, from, n); - if (i) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -extern inline int copy_to_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_WRITE, to, n); - if (i) - return i; - memcpy_tofs(to, from, n); - return 0; -} -#endif /* --------------------------------------------------------------------- */ diff --git a/drivers/net/hamradio/soundmodem/sm_wss.c b/drivers/net/hamradio/soundmodem/sm_wss.c index c94ba285f57a..f6889f899279 100644 --- a/drivers/net/hamradio/soundmodem/sm_wss.c +++ b/drivers/net/hamradio/soundmodem/sm_wss.c @@ -52,12 +52,6 @@ #include #include -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - extern inline int copy_from_user(void *to, const void *from, unsigned long n) { int i = verify_area(VERIFY_READ, from, n); diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index 7e8caa39f4be..76d8647e291d 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c @@ -76,63 +76,8 @@ /* --------------------------------------------------------------------- */ -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include - -#if LINUX_VERSION_CODE >= 0x20100 #include -#else -#include -#include - -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - -extern inline int copy_from_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_READ, from, n); - if (i) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -extern inline int copy_to_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_WRITE, to, n); - if (i) - return i; - memcpy_tofs(to, from, n); - return 0; -} -#endif - -#if LINUX_VERSION_CODE < 0x20115 -extern __inline__ void dev_init_buffers(struct device *dev) -{ - int i; - for (i = 0; i < DEV_NUMBUFFS; i++) { - skb_queue_head_init(&dev->buffs[i]); - } -} -#endif - -#if LINUX_VERSION_CODE >= 0x20123 #include -#else -#define __init -#define __initdata -#define __initfunc(x) x -#endif /* --------------------------------------------------------------------- */ @@ -178,11 +123,7 @@ struct yam_port { /* Stats section */ -#if LINUX_VERSION_CODE < 0x20119 - struct enet_statistics stats; -#else struct net_device_stats stats; -#endif int nb_rxint; int nb_mdint; @@ -919,13 +860,8 @@ struct proc_dir_entry yam_proc_dir_entry = /* --------------------------------------------------------------------- */ -#if LINUX_VERSION_CODE >= 0x20119 static struct net_device_stats * yam_get_stats(struct device *dev) -#else -static struct enet_statistics * - yam_get_stats(struct device *dev) -#endif { struct yam_port *yp; @@ -1266,13 +1202,9 @@ __initfunc(int yam_init(struct device *dev)) * command line settable parameters */ -#if LINUX_VERSION_CODE >= 0x20115 - MODULE_AUTHOR("Frederic Rible F1OAT frible@teaser.fr"); MODULE_DESCRIPTION("Yam amateur radio modem driver"); -#endif - __initfunc(int init_module(void)) { int ret = yam_init(NULL); diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c index 0c83ca1ba8b4..2befabe5cd53 100644 --- a/drivers/sbus/char/openprom.c +++ b/drivers/sbus/char/openprom.c @@ -68,7 +68,7 @@ static int options_node; */ static int copyin(struct openpromio *info, struct openpromio **opp_p) { - int bufsize; + unsigned int bufsize; if (!info || !opp_p) return -EFAULT; diff --git a/drivers/sbus/char/sunkbd.c b/drivers/sbus/char/sunkbd.c index 41ffe915981c..f79f0a24465f 100644 --- a/drivers/sbus/char/sunkbd.c +++ b/drivers/sbus/char/sunkbd.c @@ -1309,9 +1309,9 @@ kbd_read (struct file *f, char *buffer, size_t count, loff_t *ppos) copy_to_user_ret((Firm_event *)p, &kbd_queue [kbd_tail], sizeof(Firm_event)-sizeof(struct timeval), -EFAULT); p += sizeof(Firm_event)-sizeof(struct timeval); - __put_user_ret(kbd_queue[kbd_tail].time.tv_sec, (u32 *)p, -EFAULT); + put_user_ret(kbd_queue[kbd_tail].time.tv_sec, (u32 *)p, -EFAULT); p += sizeof(u32); - __put_user_ret(kbd_queue[kbd_tail].time.tv_usec, (u32 *)p, -EFAULT); + put_user_ret(kbd_queue[kbd_tail].time.tv_usec, (u32 *)p, -EFAULT); p += sizeof(u32); } else #endif diff --git a/drivers/sbus/char/sunmouse.c b/drivers/sbus/char/sunmouse.c index a97d21f0a89e..f72adbe4c571 100644 --- a/drivers/sbus/char/sunmouse.c +++ b/drivers/sbus/char/sunmouse.c @@ -444,9 +444,9 @@ sun_mouse_read(struct file *file, char *buffer, sizeof(Firm_event)-sizeof(struct timeval), -EFAULT); p += sizeof(Firm_event)-sizeof(struct timeval); - __put_user_ret(q->time.tv_sec, (u32 *)p, -EFAULT); + put_user_ret(q->time.tv_sec, (u32 *)p, -EFAULT); p += sizeof(u32); - __put_user_ret(q->time.tv_usec, (u32 *)p, -EFAULT); + put_user_ret(q->time.tv_usec, (u32 *)p, -EFAULT); p += sizeof(u32); } else #endif diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index 9443d90eb834..a580d78230e1 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -105,10 +105,6 @@ #define PUT_USER put_user #endif - #ifndef __PUT_USER - #define __PUT_USER __put_user - #endif - #ifndef PUT_USER_RET #define PUT_USER_RET put_user_ret #endif diff --git a/drivers/usb/ov511.c b/drivers/usb/ov511.c index 21027ce030eb..d34a38f94664 100644 --- a/drivers/usb/ov511.c +++ b/drivers/usb/ov511.c @@ -54,8 +54,8 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.28" -#define DRIVER_AUTHOR "Mark McClelland & Bret Wallach & Orion Sky Lawlor & Kevin Moore & Charl P. Botha & Claudio Matsuoka " +#define DRIVER_VERSION "v1.28a for Linux 2.2" +#define DRIVER_AUTHOR "Mark McClelland & Bret Wallach & Orion Sky Lawlor & Kevin Moore & Charl P. Botha & Claudio Matsuoka " #define DRIVER_DESC "OV511 USB Camera Driver" #define OV511_I2C_RETRIES 3 @@ -99,9 +99,6 @@ static int aperture = -1; * programs that expect RGB data (e.g. gqcam) to work with this driver. */ static int force_rgb = 0; -/* Number of seconds before inactive buffers are deallocated */ -static int buf_timeout = 5; - /* Number of cameras to stream from simultaneously */ static int cams = 1; @@ -138,8 +135,6 @@ MODULE_PARM(aperture, "i"); MODULE_PARM_DESC(aperture, "Read the OV7610/7620 specs"); MODULE_PARM(force_rgb, "i"); MODULE_PARM_DESC(force_rgb, "Read RGB instead of BGR"); -MODULE_PARM(buf_timeout, "i"); -MODULE_PARM_DESC(buf_timeout, "Number of seconds before buffer deallocation"); MODULE_PARM(cams, "i"); MODULE_PARM_DESC(cams, "Number of simultaneous cameras"); MODULE_PARM(retry_sync, "i"); @@ -2037,11 +2032,6 @@ static int ov511_alloc(struct usb_ov511 *ov511) PDEBUG(4, "entered"); down(&ov511->buf_lock); - if (ov511->buf_state == BUF_PEND_DEALLOC) { - ov511->buf_state = BUF_ALLOCATED; - del_timer(&ov511->buf_timer); - } - if (ov511->buf_state == BUF_ALLOCATED) goto out; @@ -2106,42 +2096,11 @@ static void ov511_do_dealloc(struct usb_ov511 *ov511) PDEBUG(4, "leaving"); } -static void ov511_buf_callback(unsigned long data) -{ - struct usb_ov511 *ov511 = (struct usb_ov511 *)data; - PDEBUG(4, "entered"); - down(&ov511->buf_lock); - - if (ov511->buf_state == BUF_PEND_DEALLOC) - ov511_do_dealloc(ov511); - - up(&ov511->buf_lock); - PDEBUG(4, "leaving"); -} - -static void ov511_dealloc(struct usb_ov511 *ov511, int now) +static void ov511_dealloc(struct usb_ov511 *ov511) { - struct timer_list *bt = &(ov511->buf_timer); PDEBUG(4, "entered"); down(&ov511->buf_lock); - - PDEBUG(4, "deallocating buffer memory %s", now ? "now" : "later"); - - if (ov511->buf_state == BUF_PEND_DEALLOC) { - ov511->buf_state = BUF_ALLOCATED; - del_timer(bt); - } - - if (now) - ov511_do_dealloc(ov511); - else { - ov511->buf_state = BUF_PEND_DEALLOC; - init_timer(bt); - bt->function = ov511_buf_callback; - bt->data = (unsigned long)ov511; - bt->expires = jiffies + buf_timeout * HZ; - add_timer(bt); - } + ov511_do_dealloc(ov511); up(&ov511->buf_lock); PDEBUG(4, "leaving"); } @@ -2173,7 +2132,7 @@ static int ov511_open(struct video_device *dev, int flags) err = ov511_init_isoc(ov511); if (err) { - ov511_dealloc(ov511, 0); + ov511_dealloc(ov511); goto out; } @@ -2200,12 +2159,12 @@ static void ov511_close(struct video_device *dev) ov511_stop_isoc(ov511); if (ov511->dev) - ov511_dealloc(ov511, 0); + ov511_dealloc(ov511); up(&ov511->lock); if (!ov511->dev) { - ov511_dealloc(ov511, 1); + ov511_dealloc(ov511); video_unregister_device(&ov511->vdev); kfree(ov511); ov511 = NULL; @@ -3410,7 +3369,7 @@ ov511_disconnect(struct usb_device *dev, void *ptr) /* Free the memory */ if (ov511 && !ov511->user) { - ov511_dealloc(ov511, 1); + ov511_dealloc(ov511); kfree(ov511); ov511 = NULL; } diff --git a/drivers/usb/ov511.h b/drivers/usb/ov511.h index a4ef7dacde5b..367820c3389a 100644 --- a/drivers/usb/ov511.h +++ b/drivers/usb/ov511.h @@ -219,7 +219,6 @@ enum { enum { BUF_NOT_ALLOCATED, BUF_ALLOCATED, - BUF_PEND_DEALLOC, /* ov511->buf_timer is set */ }; struct usb_device; @@ -341,7 +340,6 @@ struct usb_ov511 { /* Framebuffer/sbuf management */ int buf_state; struct semaphore buf_lock; - struct timer_list buf_timer; }; struct cam_list { diff --git a/drivers/video/cgfourteenfb.c b/drivers/video/cgfourteenfb.c index 9c4b1c2bd18d..54888b9422d5 100644 --- a/drivers/video/cgfourteenfb.c +++ b/drivers/video/cgfourteenfb.c @@ -283,11 +283,11 @@ static int cg14_ioctl (struct fb_info_sbusfb *fb, unsigned int cmd, unsigned lon case MDI_GET_CFGINFO: mdii = (struct mdi_cfginfo *)arg; put_user_ret(FBTYPE_MDICOLOR, &mdii->mdi_type, -EFAULT); - __put_user_ret(fb->type.fb_height, &mdii->mdi_height, -EFAULT); - __put_user_ret(fb->type.fb_width, &mdii->mdi_width, -EFAULT); - __put_user_ret(fb->s.cg14.mode, &mdii->mdi_mode, -EFAULT); - __put_user_ret(72, &mdii->mdi_pixfreq, -EFAULT); /* FIXME */ - __put_user_ret(fb->s.cg14.ramsize, &mdii->mdi_size, -EFAULT); + put_user_ret(fb->type.fb_height, &mdii->mdi_height, -EFAULT); + put_user_ret(fb->type.fb_width, &mdii->mdi_width, -EFAULT); + put_user_ret(fb->s.cg14.mode, &mdii->mdi_mode, -EFAULT); + put_user_ret(72, &mdii->mdi_pixfreq, -EFAULT); /* FIXME */ + put_user_ret(fb->s.cg14.ramsize, &mdii->mdi_size, -EFAULT); break; case MDI_SET_PIXELMODE: get_user_ret(mode, (int *)arg, -EFAULT); diff --git a/fs/dcache.c b/fs/dcache.c index eed78ad0b241..401c6005b02b 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -764,12 +764,15 @@ void d_move(struct dentry * dentry, struct dentry * target) /* * "buflen" should be PAGE_SIZE or more. */ -char * d_path(struct dentry *dentry, char *buffer, int buflen) +static char * d_path_error(struct dentry *dentry, + char *buffer, int buflen, int *error) { char * end = buffer+buflen; char * retval; struct dentry * root = current->fs->root; + *error = 0; + *--end = '\0'; buflen--; if (dentry->d_parent != dentry && list_empty(&dentry->d_hash)) { @@ -794,8 +797,10 @@ char * d_path(struct dentry *dentry, char *buffer, int buflen) break; namelen = dentry->d_name.len; buflen -= namelen + 1; - if (buflen < 0) + if (buflen < 0) { + *error = -ENAMETOOLONG; break; + } end -= namelen; memcpy(end, dentry->d_name.name, namelen); *--end = '/'; @@ -805,6 +810,13 @@ char * d_path(struct dentry *dentry, char *buffer, int buflen) return retval; } +char * d_path(struct dentry *dentry, char *buffer, int buflen) +{ + int error; + + return d_path_error(dentry, buffer, buflen, &error); +} + /* * NOTE! The user-level library version returns a * character pointer. The kernel system call just @@ -835,14 +847,17 @@ asmlinkage int sys_getcwd(char *buf, unsigned long size) error = -ENOMEM; if (page) { unsigned long len; - char * cwd = d_path(pwd, page, PAGE_SIZE); - - error = -ERANGE; - len = PAGE_SIZE + page - cwd; - if (len <= size) { - error = len; - if (copy_to_user(buf, cwd, len)) - error = -EFAULT; + char * cwd; + + cwd = d_path_error(pwd, page, PAGE_SIZE, &error); + if (!error) { + error = -ERANGE; + len = PAGE_SIZE + page - cwd; + if (len <= size) { + error = len; + if (copy_to_user(buf, cwd, len)) + error = -EFAULT; + } } free_page((unsigned long) page); } diff --git a/fs/fat/misc.c b/fs/fat/misc.c index 0916f8467d3e..9d2c25d6da53 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -554,7 +554,8 @@ static int raw_scan(struct super_block *sb, int start, const char *name, int fat_parent_ino(struct inode *dir,int locked) { static int zero = 0; - int error,curr,prev,nr; + int error,curr,prev; + loff_t nr; PRINTK(("fat_parent_ino: Debug 0\n")); if (!S_ISDIR(dir->i_mode)) panic("Non-directory fed to m_p_i"); @@ -585,7 +586,7 @@ int fat_parent_ino(struct inode *dir,int locked) if (!locked) fat_unlock_creation(); return error; } - PRINTK(("fat_parent_ino: Debug 6 nr=%d\n", nr)); + PRINTK(("fat_parent_ino: Debug 6 nr=%ld\n", (long)nr)); } if (!locked) fat_unlock_creation(); return nr; diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index ccbfeb12c01b..c86d32d69bca 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -430,10 +430,11 @@ static unsigned int isofs_get_last_session(kdev_t dev) /* If a minor device was explicitly opened, set session to the * minor number. For instance, if /dev/hdc1 is mounted, session * 1 on the CD-ROM is selected. CD_PART_MAX gives access to - * a max of 64 sessions on IDE. SCSI drives must still use - * the session option to mount. + * a max of 64 sessions on IDE. For SCSI drives or loop devices + * you must still use the session option to mount. */ - if ((MINOR(dev) % CD_PART_MAX) && (MAJOR(dev) != SCSI_CDROM_MAJOR)) + if ((MINOR(dev) % CD_PART_MAX) && (MAJOR(dev) != SCSI_CDROM_MAJOR) + && (MAJOR(dev) != LOOP_MAJOR)) session = MINOR(dev) % CD_PART_MAX; if (session > 0 && session <= CD_PART_MAX) { struct cdrom_tocentry entry; diff --git a/fs/proc/openpromfs.c b/fs/proc/openpromfs.c index dcb007f11cad..60010b7a03d8 100644 --- a/fs/proc/openpromfs.c +++ b/fs/proc/openpromfs.c @@ -67,7 +67,7 @@ static ssize_t nodenum_read(struct file *file, char *buf, { struct inode *inode = file->f_dentry->d_inode; char buffer[10]; - + if (count < 0 || !inode->u.generic_ip) return -EINVAL; sprintf (buffer, "%8.8x\n", (u32)(long)(inode->u.generic_ip)); @@ -75,7 +75,7 @@ static ssize_t nodenum_read(struct file *file, char *buf, return 0; if (count > 9 - file->f_pos) count = 9 - file->f_pos; - copy_to_user(buf, buffer + file->f_pos, count); + copy_to_user_ret(buf, buffer + file->f_pos, count, -EFAULT); file->f_pos += count; return count; } @@ -90,8 +90,8 @@ static ssize_t property_read(struct file *filp, char *buf, u32 *q; openprom_property *op; char buffer[64]; - - if (filp->f_pos >= 0xffffff) + + if (filp->f_pos >= 0xffffff || count >= 0xffffff) return -EINVAL; if (!filp->private_data) { node = nodes[(u16)((long)inode->u.generic_ip)].node; @@ -182,7 +182,7 @@ static ssize_t property_read(struct file *filp, char *buf, if (count > i - k) count = i - k; if (op->flag & OPP_STRING) { if (!k) { - __put_user('\'', buf); + put_user_ret('\'', buf, -EFAULT); k++; count--; } @@ -193,16 +193,16 @@ static ssize_t property_read(struct file *filp, char *buf, j = count; if (j >= 0) { - copy_to_user(buf + k - filp->f_pos, - op->value + k - 1, j); + copy_to_user_ret(buf + k - filp->f_pos, + op->value + k - 1, j, -EFAULT); count -= j; k += j; } if (count) - __put_user('\'', &buf [k++ - filp->f_pos]); + put_user_ret('\'', &buf [k++ - filp->f_pos], -EFAULT); if (count > 1) - __put_user('\n', &buf [k++ - filp->f_pos]); + put_user_ret('\n', &buf [k++ - filp->f_pos], -EFAULT); } else if (op->flag & OPP_STRINGLIST) { char *tmp; @@ -223,7 +223,7 @@ static ssize_t property_read(struct file *filp, char *buf, } strcpy(s, "'\n"); - copy_to_user(buf, tmp + k, count); + copy_to_user_ret(buf, tmp + k, count, -EFAULT); kfree(tmp); k += count; @@ -241,53 +241,63 @@ static ssize_t property_read(struct file *filp, char *buf, if (first == last) { sprintf (buffer, "%08x.", *first); - copy_to_user (buf, buffer + first_off, last_cnt - first_off); + copy_to_user_ret (buf, buffer + first_off, + last_cnt - first_off, -EFAULT); buf += last_cnt - first_off; } else { for (q = first; q <= last; q++) { sprintf (buffer, "%08x.", *q); if (q == first) { - copy_to_user (buf, buffer + first_off, - 9 - first_off); + copy_to_user_ret (buf, + buffer + first_off, + 9 - first_off, -EFAULT); buf += 9 - first_off; } else if (q == last) { - copy_to_user (buf, buffer, last_cnt); + copy_to_user_ret (buf, buffer, + last_cnt, -EFAULT); buf += last_cnt; } else { - copy_to_user (buf, buffer, 9); + copy_to_user_ret (buf, buffer, + 9, -EFAULT); buf += 9; } } } if (last == (u32 *)(op->value + op->len - 4) && last_cnt == 9) - __put_user('\n', (buf - 1)); + put_user_ret('\n', (buf - 1), -EFAULT); k += count; } else if (op->flag & OPP_HEXSTRING) { - char buffer[2]; + char buffer[3]; if ((k < i - 1) && (k & 1)) { - sprintf (buffer, "%02x", *(op->value + (k >> 1))); - __put_user(buffer[1], &buf[k++ - filp->f_pos]); + sprintf (buffer, "%02x", + (unsigned char)*(op->value + (k >> 1)) & 0xff); + put_user_ret(buffer[1], &buf[k++ - filp->f_pos], + -EFAULT); count--; } for (; (count > 1) && (k < i - 1); k += 2) { - sprintf (buffer, "%02x", *(op->value + (k >> 1))); - copy_to_user (buf + k - filp->f_pos, buffer, 2); + sprintf (buffer, "%02x", + (unsigned char)*(op->value + (k >> 1)) & 0xff); + copy_to_user_ret (buf + k - filp->f_pos, buffer, 2, + -EFAULT); count -= 2; } if (count && (k < i - 1)) { - sprintf (buffer, "%02x", *(op->value + (k >> 1))); - __put_user(buffer[0], &buf[k++ - filp->f_pos]); + sprintf (buffer, "%02x", + (unsigned char)*(op->value + (k >> 1)) & 0xff); + put_user_ret(buffer[0], &buf[k++ - filp->f_pos], + -EFAULT); count--; } if (count) - __put_user('\n', &buf [k++ - filp->f_pos]); + put_user_ret('\n', &buf [k++ - filp->f_pos], -EFAULT); } count = k - filp->f_pos; filp->f_pos = k; @@ -302,8 +312,8 @@ static ssize_t property_write(struct file *filp, const char *buf, u32 *q; void *b; openprom_property *op; - - if (filp->f_pos >= 0xffffff) + + if (filp->f_pos >= 0xffffff || count >= 0xffffff) return -EINVAL; if (!filp->private_data) { i = property_read (filp, NULL, 0, 0); @@ -324,7 +334,7 @@ static ssize_t property_write(struct file *filp, const char *buf, if (j == 9) j = 0; if (!j) { char ctmp; - __get_user(ctmp, &buf[i]); + get_user_ret(ctmp, &buf[i], -EFAULT); if (ctmp != '.') { if (ctmp != '\n') { if (op->flag & OPP_BINARY) @@ -339,7 +349,7 @@ static ssize_t property_write(struct file *filp, const char *buf, } } else { char ctmp; - __get_user(ctmp, &buf[i]); + get_user_ret(ctmp, &buf[i], -EFAULT); if (ctmp < '0' || (ctmp > '9' && ctmp < 'A') || (ctmp > 'F' && ctmp < 'a') || @@ -377,8 +387,9 @@ static ssize_t property_write(struct file *filp, const char *buf, last_cnt = (k + count) % 9; if (first + 1 == last) { memset (tmp, '0', 8); - copy_from_user (tmp + first_off, buf, - (count + first_off > 8) ? 8 - first_off : count); + copy_from_user_ret (tmp + first_off, buf, + (count + first_off > 8) ? 8 - first_off : count, + -EFAULT); mask = 0xffffffff; mask2 = 0xffffffff; for (j = 0; j < first_off; j++) @@ -397,8 +408,9 @@ static ssize_t property_write(struct file *filp, const char *buf, if (q == first) { if (first_off < 8) { memset (tmp, '0', 8); - copy_from_user (tmp + first_off, buf, - 8 - first_off); + copy_from_user_ret ( + tmp + first_off, buf, + 8 - first_off, -EFAULT); mask = 0xffffffff; for (j = 0; j < first_off; j++) mask >>= 1; @@ -409,7 +421,8 @@ static ssize_t property_write(struct file *filp, const char *buf, } else if ((q == last - 1) && last_cnt && (last_cnt < 8)) { memset (tmp, '0', 8); - copy_from_user (tmp, buf, last_cnt); + copy_from_user_ret (tmp, buf, last_cnt, + -EFAULT); mask = 0xffffffff; for (j = 0; j < 8 - last_cnt; j++) mask <<= 1; @@ -419,7 +432,8 @@ static ssize_t property_write(struct file *filp, const char *buf, } else { char tchars[17]; /* XXX yuck... */ - copy_from_user(tchars, buf, 16); + copy_from_user_ret(tchars, buf, 16, + -EFAULT); *q = simple_strtoul (tchars, 0, 16); buf += 9; } @@ -442,7 +456,7 @@ write_try_string: */ if (k > 0) return -EINVAL; - __get_user(ctmp, buf); + get_user_ret(ctmp, buf, -EFAULT); if (ctmp == '\'') { op->flag |= OPP_QUOTED; buf++; @@ -474,7 +488,7 @@ write_try_string: kfree (b); } p = op->value + filp->f_pos - ((op->flag & OPP_QUOTED) ? 1 : 0); - copy_from_user (p, buf, count); + copy_from_user_ret (p, buf, count, -EFAULT); op->flag |= OPP_DIRTY; for (i = 0; i < count; i++, p++) if (*p == '\n') { diff --git a/net/core/skbuff.c b/net/core/skbuff.c index b76364371fb4..93b757c98017 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -136,6 +136,8 @@ struct sk_buff *alloc_skb(unsigned int size,int gfp_mask) goto nohead; /* Get the DATA. Size must match skb_add_mtu(). */ + if (size > 131072 - 32) + goto nodata; size = ((size + 15) & ~15); data = kmalloc(size + sizeof(atomic_t), gfp_mask); if (data == NULL) diff --git a/net/ipv4/ip_masq.c b/net/ipv4/ip_masq.c index af4f3d85ea69..f9b5e4d71ab2 100644 --- a/net/ipv4/ip_masq.c +++ b/net/ipv4/ip_masq.c @@ -2450,7 +2450,7 @@ int ip_masq_uctl(int optname, char * optval , int optlen) struct ip_masq_ctl masq_ctl; int ret = -EINVAL; - if(optlen>sizeof(masq_ctl)) + if(optlen < 0 || optlen > sizeof(masq_ctl)) return -EINVAL; if(copy_from_user(&masq_ctl,optval,optlen)) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index b4bed08aaffe..542353f15f11 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1998,15 +1998,23 @@ struct ip_rt_acct ip_rt_acct[256]; static int ip_rt_acct_read(char *buffer, char **start, off_t offset, int length, int *eof, void *data) { - *start=buffer; + *start = buffer; - if (offset + length > sizeof(ip_rt_acct)) { + if (offset < 0 || length < 0) + return 0; + + if (offset >= sizeof(ip_rt_acct) || length >= sizeof(ip_rt_acct)) { + *eof = 1; + return 0; + } + + if (offset + length >= sizeof(ip_rt_acct)) { length = sizeof(ip_rt_acct) - offset; *eof = 1; } if (length > 0) { start_bh_atomic(); - memcpy(buffer, ((u8*)&ip_rt_acct)+offset, length); + memcpy(buffer, ((u8*)&ip_rt_acct) + offset, length); end_bh_atomic(); return length; } diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 21f55e0bdf36..849b09074a2a 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -940,6 +940,7 @@ int tcp_do_sendmsg(struct sock *sk, struct msghdr *msg) if (!err) tcp_push_pending_frames(sk, tp); wait_for_tcp_memory(sk, err); + err = 0; /* If SACK's were formed or PMTU events happened, * we must find out about it. diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index ee598527c883..853bc60a5d4f 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -296,7 +296,7 @@ static void tcp_reset(struct sock *sk) } sk->shutdown = SHUTDOWN_MASK; if (!sk->dead) - sk->state_change(sk); + sk->error_report(sk); } /* This tags the retransmission queue when SACKs arrive. */ diff --git a/net/socket.c b/net/socket.c index c81c2dea83ac..64836b7a4a67 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1073,11 +1073,19 @@ asmlinkage int sys_setsockopt(int fd, int level, int optname, char *optval, int asmlinkage int sys_getsockopt(int fd, int level, int optname, char *optval, int *optlen) { int err; + int len; struct socket *sock; lock_kernel(); if ((sock = sockfd_lookup(fd, &err))!=NULL) { + /* XXX: insufficient for SMP, but should be redundant anyway */ + if (get_user(len, optlen)) + err = -EFAULT; + else + if (len < 0) + err = -EINVAL; + else if (level == SOL_SOCKET) err=sock_getsockopt(sock,level,optname,optval,optlen); else diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 9e75d0210008..8233062f8453 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -540,6 +540,8 @@ static unix_socket *unix_find_other(struct sockaddr_un *sunname, int len, return NULL; } u=unix_find_socket_byinode(dentry->d_inode); + if (u && u->type == type) + UPDATE_ATIME(dentry->d_inode); dput(dentry); if (u && u->type != type) { @@ -549,7 +551,16 @@ static unix_socket *unix_find_other(struct sockaddr_un *sunname, int len, } } else + { u=unix_find_socket_byname(sunname, len, type, hash); + if (u) + { + struct dentry *dentry; + dentry = u->protinfo.af_unix.dentry; + if (dentry) + UPDATE_ATIME(dentry->d_inode); + } + } if (u==NULL) { -- 2.39.5