diff -urPX nopatch linux-2.4.21/arch/ia64/ia32/sys_ia32.c linux/arch/ia64/ia32/sys_ia32.c --- linux-2.4.21/arch/ia64/ia32/sys_ia32.c Fri Jun 13 14:51:29 2003 +++ linux/arch/ia64/ia32/sys_ia32.c Sun Jun 15 17:21:08 2003 @@ -109,6 +109,8 @@ *ap++ = (char *) A(addr); arg += sizeof(unsigned int); n++; + if (n >= (MAX_ARG_PAGES * PAGE_SIZE) / sizeof(char *)) + return -E2BIG; } while (addr); return n - 1; } diff -urPX nopatch linux-2.4.21/arch/mips64/kernel/linux32.c linux/arch/mips64/kernel/linux32.c --- linux-2.4.21/arch/mips64/kernel/linux32.c Thu Nov 28 23:53:10 2002 +++ linux/arch/mips64/kernel/linux32.c Sun Jun 15 17:23:00 2003 @@ -434,6 +450,8 @@ return ret; arg += sizeof(unsigned int); n++; + if (n >= (MAX_ARG_PAGES * PAGE_SIZE) / sizeof(char *)) + return -E2BIG; } while (ptr); return n - 1; diff -urPX nopatch linux-2.4.21/arch/x86_64/ia32/sys_ia32.c linux/arch/x86_64/ia32/sys_ia32.c --- linux-2.4.21/arch/x86_64/ia32/sys_ia32.c Fri Jun 13 14:51:32 2003 +++ linux/arch/x86_64/ia32/sys_ia32.c Sun Jun 15 17:23:47 2003 @@ -2120,7 +2120,7 @@ dst[cnt] = (char *)(u64)val; cnt++; src += 4; - if (cnt >= (MAX_ARG_PAGES*PAGE_SIZE)/sizeof(void*)) + if (cnt >= (MAX_ARG_PAGES * PAGE_SIZE) / sizeof(char *)) return -E2BIG; } while(val); if (dst) diff -urPX nopatch linux-2.4.21/drivers/char/agp/agpgart_be.c linux/drivers/char/agp/agpgart_be.c --- linux-2.4.21/drivers/char/agp/agpgart_be.c Fri Jun 13 14:51:32 2003 +++ linux/drivers/char/agp/agpgart_be.c Sun Jun 15 15:51:12 2003 @@ -577,7 +577,7 @@ for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) SetPageReserved(page); - agp_bridge.gatt_table_real = (unsigned long *) table; + agp_bridge.gatt_table_real = (u32 *) table; agp_gatt_table = (void *)table; #ifdef CONFIG_X86 err = change_page_attr(virt_to_page(table), 1<drv_block >= 0) STps->drv_block += 1; - return (-ENOMEM); + return (-EIO); } (STp->buffer)->buffer_bytes = bytes - transfer; } else { diff -urPX nopatch linux-2.4.21/fs/exec.c linux/fs/exec.c --- linux-2.4.21/fs/exec.c Fri Jun 13 14:51:37 2003 +++ linux/fs/exec.c Sun Jun 15 16:48:25 2003 @@ -725,6 +733,8 @@ || atomic_read(¤t->fs->count) > 1 || atomic_read(¤t->files->count) > 1 || atomic_read(¤t->sig->count) > 1) { + /* XXX: should fail rather than execute with no raised + * effective privileges */ if(!capable(CAP_SETUID)) { bprm->e_uid = current->uid; bprm->e_gid = current->gid; diff -urPX nopatch linux-2.4.21/fs/namei.c linux/fs/namei.c --- linux-2.4.21/fs/namei.c Fri Jun 13 14:51:37 2003 +++ linux/fs/namei.c Sun Jun 15 15:51:12 2003 @@ -335,10 +370,10 @@ static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) { int err; - if (current->link_count >= 5) + if (current->link_count >= 8) goto loop; if (current->total_link_count >= 40) goto loop; if (current->need_resched) { current->state = TASK_RUNNING; schedule(); diff -urPX nopatch linux-2.4.21/fs/proc/generic.c linux/fs/proc/generic.c --- linux-2.4.21/fs/proc/generic.c Fri Jun 13 14:51:37 2003 +++ linux/fs/proc/generic.c Sun Jun 15 15:51:12 2003 @@ -391,7 +391,9 @@ static void proc_kill_inodes(struct proc_dir_entry *de) { struct list_head *p; - struct super_block *sb = proc_mnt->mnt_sb; + struct super_block *sb = proc_super; + + if (!sb) return; /* * Actually it's a partial revoke(). @@ -485,12 +487,12 @@ return ent; } -struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent) +struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode, + struct proc_dir_entry *parent) { struct proc_dir_entry *ent; - ent = proc_create(&parent,name, - (S_IFDIR | S_IRUGO | S_IXUGO),2); + ent = proc_create(&parent, name, S_IFDIR | mode, 2); if (ent) { ent->proc_fops = &proc_dir_operations; ent->proc_iops = &proc_dir_inode_operations; @@ -501,6 +503,12 @@ } } return ent; +} + +struct proc_dir_entry *proc_mkdir(const char *name, + struct proc_dir_entry *parent) +{ + return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent); } struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, diff -urPX nopatch linux-2.4.21/fs/proc/inode.c linux/fs/proc/inode.c --- linux-2.4.21/fs/proc/inode.c Fri Jun 13 14:51:37 2003 +++ linux/fs/proc/inode.c Sun Jun 15 15:51:12 2003 @@ -73,8 +74,6 @@ } } -struct vfsmount *proc_mnt; - static void proc_read_inode(struct inode * inode) { inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; @@ -176,11 +179,15 @@ goto out; } +struct super_block *proc_super = NULL; + struct super_block *proc_read_super(struct super_block *s,void *data, int silent) { struct inode * root_inode; struct task_struct *p; + + proc_super = s; s->s_blocksize = 1024; s->s_blocksize_bits = 10; diff -urPX nopatch linux-2.4.21/fs/proc/proc_tty.c linux/fs/proc/proc_tty.c --- linux-2.4.21/fs/proc/proc_tty.c Fri Apr 21 22:17:57 2000 +++ linux/fs/proc/proc_tty.c Sun Jun 15 15:51:12 2003 @@ -128,7 +128,7 @@ } /* - * Thsi function is called by register_tty_driver() to handle + * This function is called by tty_register_driver() to handle * registering the driver's /proc handler into /proc/tty/driver/ */ void proc_tty_register_driver(struct tty_driver *driver) @@ -151,7 +151,7 @@ } /* - * This function is called by unregister_tty_driver() + * This function is called by tty_unregister_driver() */ void proc_tty_unregister_driver(struct tty_driver *driver) { @@ -174,7 +174,13 @@ if (!proc_mkdir("tty", 0)) return; proc_tty_ldisc = proc_mkdir("tty/ldisc", 0); - proc_tty_driver = proc_mkdir("tty/driver", 0); + /* + * /proc/tty/driver/serial reveals the exact character counts for + * serial links which is just too easy to abuse for inferring + * password lengths and inter-keystroke timings during password + * entry. + */ + proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR | S_IXUSR, 0); create_proc_read_entry("tty/ldiscs", 0, 0, tty_ldiscs_read_proc,NULL); create_proc_read_entry("tty/drivers", 0, 0, tty_drivers_read_proc,NULL); diff -urPX nopatch linux-2.4.21/fs/proc/root.c linux/fs/proc/root.c --- linux-2.4.21/fs/proc/root.c Sat Aug 3 00:39:45 2002 +++ linux/fs/proc/root.c Sun Jun 15 15:51:12 2003 @@ -30,14 +31,8 @@ int err = register_filesystem(&proc_fs_type); if (err) return; - proc_mnt = kern_mount(&proc_fs_type); - err = PTR_ERR(proc_mnt); - if (IS_ERR(proc_mnt)) { - unregister_filesystem(&proc_fs_type); - return; - } proc_misc_init(); proc_net = proc_mkdir("net", 0); #ifdef CONFIG_SYSVIPC proc_mkdir("sysvipc", 0); #endif diff -urPX nopatch linux-2.4.21/include/linux/kernel.h linux/include/linux/kernel.h --- linux-2.4.21/include/linux/kernel.h Thu Nov 28 23:53:15 2002 +++ linux/include/linux/kernel.h Sun Jun 15 15:51:12 2003 @@ -71,14 +71,17 @@ extern long long simple_strtoll(const char *,char **,unsigned int); extern int sprintf(char * buf, const char * fmt, ...) __attribute__ ((format (printf, 2, 3))); -extern int vsprintf(char *buf, const char *, va_list); +extern int vsprintf(char *buf, const char *, va_list) + __attribute__ ((format (printf, 2, 0))); extern int snprintf(char * buf, size_t size, const char * fmt, ...) __attribute__ ((format (printf, 3, 4))); -extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args); +extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) + __attribute__ ((format (printf, 3, 0))); extern int sscanf(const char *, const char *, ...) - __attribute__ ((format (scanf,2,3))); -extern int vsscanf(const char *, const char *, va_list); + __attribute__ ((format (scanf, 2, 3))); +extern int vsscanf(const char *, const char *, va_list) + __attribute__ ((format (scanf, 2, 0))); extern int get_option(char **str, int *pint); extern char *get_options(char *str, int nints, int *ints); diff -urPX nopatch linux-2.4.21/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- linux-2.4.21/include/linux/proc_fs.h Sat Aug 3 00:39:45 2002 +++ linux/include/linux/proc_fs.h Sun Jun 15 15:51:12 2003 @@ -94,7 +94,7 @@ struct proc_dir_entry *parent); extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent); -extern struct vfsmount *proc_mnt; +extern struct super_block *proc_super; extern struct super_block *proc_read_super(struct super_block *,void *,int); extern struct inode * proc_get_inode(struct super_block *, int, struct proc_dir_entry *); @@ -142,6 +142,8 @@ struct proc_dir_entry *, const char *); extern struct proc_dir_entry *proc_mknod(const char *,mode_t, struct proc_dir_entry *,kdev_t); +extern struct proc_dir_entry *proc_mkdir_mode(const char *,mode_t, + struct proc_dir_entry *); extern struct proc_dir_entry *proc_mkdir(const char *,struct proc_dir_entry *); static inline struct proc_dir_entry *create_proc_read_entry(const char *name, diff -urPX nopatch linux-2.4.21/kernel/sysctl.c linux/kernel/sysctl.c --- linux-2.4.21/kernel/sysctl.c Fri Jun 13 14:51:39 2003 +++ linux/kernel/sysctl.c Sun Jun 15 15:51:12 2003 @@ -344,6 +344,9 @@ int old_len; if (!oldlenp || get_user(old_len, oldlenp)) return -EFAULT; + /* XXX: insufficient for SMP, but should be redundant anyway */ + if ((ssize_t)old_len < 0) + return -EINVAL; } tmp = &root_table_header.ctl_entry; do { @@ -466,7 +469,8 @@ * zero, proceed with automatic r/w */ if (table->data && table->maxlen) { if (oldval && oldlenp) { - get_user(len, oldlenp); + if (get_user(len, oldlenp)) + return -EFAULT; if (len) { if (len > table->maxlen) len = table->maxlen; @@ -757,7 +761,7 @@ len = 0; p = buffer; while (len < *lenp) { - if(get_user(c, p++)) + if (get_user(c, p++)) return -EFAULT; if (c == 0 || c == '\n') break; @@ -840,7 +844,7 @@ if (write) { while (left) { char c; - if(get_user(c,(char *) buffer)) + if (get_user(c, (char *) buffer)) return -EFAULT; if (!isspace(c)) break; @@ -906,7 +910,7 @@ p = (char *) buffer; while (left) { char c; - if(get_user(c, p++)) + if (get_user(c, p++)) return -EFAULT; if (!isspace(c)) break; @@ -993,7 +997,7 @@ if (write) { while (left) { char c; - if(get_user(c, (char *) buffer)) + if (get_user(c, (char *) buffer)) return -EFAULT; if (!isspace(c)) break; @@ -1052,7 +1056,7 @@ p = (char *) buffer; while (left) { char c; - if(get_user(c, p++)) + if (get_user(c, p++)) return -EFAULT; if (!isspace(c)) break; @@ -1094,7 +1098,7 @@ if (write) { while (left) { char c; - if(get_user(c, (char *) buffer)) + if (get_user(c, (char *) buffer)) return -EFAULT; if (!isspace(c)) break; @@ -1157,7 +1161,7 @@ p = (char *) buffer; while (left) { char c; - if(get_user(c, p++)) + if (get_user(c, p++)) return -EFAULT; if (!isspace(c)) break; @@ -1311,7 +1315,7 @@ return -ENOTDIR; if (oldval && oldlenp) { - if(get_user(len, oldlenp)) + if (get_user(len, oldlenp)) return -EFAULT; if (len) { l = strlen(table->data); @@ -1368,7 +1372,8 @@ for (i = 0; i < length; i++) { int value; - get_user(value, vec + i); + if (get_user(value, vec + i)) + return -EFAULT; if (min && value < min[i]) return -EINVAL; if (max && value > max[i]) diff -urPX nopatch linux-2.4.21/mm/swapfile.c linux/mm/swapfile.c --- linux-2.4.21/mm/swapfile.c Fri Jun 13 14:51:39 2003 +++ linux/mm/swapfile.c Sun Jun 15 15:51:12 2003 @@ -725,8 +725,10 @@ for (type = swap_list.head; type >= 0; type = swap_info[type].next) { p = swap_info + type; if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) { - if (p->swap_file == nd.dentry) - break; + if (p->swap_file == nd.dentry || + (S_ISBLK(nd.dentry->d_inode->i_mode) && + p->swap_device == nd.dentry->d_inode->i_rdev)) + break; } prev = type; } diff -urPX nopatch linux-2.4.21/net/socket.c linux/net/socket.c --- linux-2.4.21/net/socket.c Fri Jun 13 14:51:39 2003 +++ linux/net/socket.c Sun Jun 15 15:51:12 2003 @@ -1305,10 +1305,18 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname, char *optval, int *optlen) { int err; + int len; struct socket *sock; 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