Messages in this thread Patch in this message |  | | | Date | Tue, 7 Jul 1998 19:56:15 +0200 (MET DST) | | From | Pavel Kankovsky <> | | Subject | amended "secure fd 0,1,2" patch |
| |
Being highly motivated by Alan Cox's words ("Ok. Im convinced.") I have found some free time and made a new version of the patch. This one should handle close-on-exec properly, and should free all fd's it has allocated when execve() fails.
BTW: Alan, will 2.0.35+ fix this problem?
struct inode * ext2_new_inode (..., int * err) { ... declarations ... if (!dir || !(inode = get_empty_inode ())) return NULL; /* *err uninitialized here */ ... }
--Pavel Kankovsky aka Peak [ Boycott Microsoft--http://www.vcnet.com/bms ] "You can't be truly paranoid unless you're sure they have already got you."
*** Here is the amended patch ***
--- ./fs/exec.c.fds Mon Apr 20 22:02:45 1998 +++ ./fs/exec.c Tue Jul 7 17:11:14 1998 @@ -47,6 +47,9 @@ #ifdef CONFIG_KERNELD #include <linux/kerneld.h> #endif +#ifdef CONFIG_SECURE_FD_0_1_2 +#include <linux/major.h> +#endif asmlinkage int sys_exit(int exit_code); asmlinkage int sys_brk(unsigned long); @@ -424,6 +427,77 @@ return 0; } +#ifdef CONFIG_SECURE_FD_0_1_2 + +/* make sure fd's 0, 1, and 2 are open to prevent nasty + * security problems -- 98/07/01 peak */ + +static inline int tweak_fd_open_null(struct linux_binprm * bprm) +{ + struct file * f = NULL; + struct inode * i = NULL; + + i = get_empty_inode(); + if (!i) + return -ENOMEM; /* see 2.1.108 ext2_new_inode() */ + f = get_empty_filp(); + if (!f) + goto bailout; + i->i_rdev = MKDEV(MEM_MAJOR, 3); /* /dev/null */ + i->i_op = &chrdev_inode_operations; + f->f_flags = O_RDWR; + f->f_mode = FMODE_READ | FMODE_WRITE; + f->f_inode = i; + f->f_pos = 0; + f->f_reada = 0; + f->f_op = i->i_op->default_file_ops; + f->f_op->open(i, f); /* chrdev_open */ + + bprm->tweak_fd_null = f; + + return 0; + +bailout: + --i->i_count; + iput(i); + return -ENFILE; +} + +static int tweak_fd_0_1_2(struct linux_binprm * bprm, struct files_struct * files) +{ + int fd, check_me, retval; + + for (fd = 0; fd <= 2; ++fd) { + if (files->fd[fd]) + continue; + check_me = get_unused_fd(); + if (check_me != fd) { + retval = -EMFILE; + goto bailout; + } + if (!bprm->tweak_fd_null) { + /* fake open("/dev/null", O_RDWR) */ + retval = tweak_fd_open_null(bprm); + if (retval) + goto bailout; + } else { + /* fake dup2() */ + ++bprm->tweak_fd_null->f_count; + } + files->fd[fd] = bprm->tweak_fd_null; + bprm->tweak_fd_mask |= (1 << fd); + } + + return 0; + +bailout: + if (check_me >= 0) + put_unused_fd(check_me); + return retval; +} + +#endif /* CONFIG_SECURE_FD_0_1_2 */ + /* * These functions flushes out all traces of the currently running executable * so that a new one can be started @@ -497,6 +571,12 @@ flush_old_signals(current->sig); flush_old_files(current->files); +#ifdef CONFIG_SECURE_FD_0_1_2 + /* take care of close-on-exec files */ + if (bprm->e_uid != current->euid || bprm->e_gid != current->egid) + return tweak_fd_0_1_2(bprm, current->files); +#endif + return 0; } @@ -559,6 +639,12 @@ if (!suser()) return -EPERM; } +#ifdef CONFIG_SECURE_FD_0_1_2 + /* warning: must be done BEFORE binfmt calls open_inode() */ + retval = tweak_fd_0_1_2(bprm, current->files); + if (retval) + return retval; +#endif } memset(bprm->buf,0,sizeof(bprm->buf)); @@ -677,6 +763,10 @@ return bprm.argc; if ((bprm.envc = count(envp)) < 0) return bprm.envc; +#ifdef CONFIG_SECURE_FD_0_1_2 + bprm.tweak_fd_mask = 0; + bprm.tweak_fd_null = NULL; +#endif retval = prepare_binprm(&bprm); @@ -700,5 +790,11 @@ iput(bprm.inode); for (i=0 ; i<MAX_ARG_PAGES ; i++) free_page(bprm.page[i]); +#ifdef CONFIG_SECURE_FD_0_1_2 + /* recover from fd tweaking */ + for (i = 0; i <= 2; ++i) + if (bprm.tweak_fd_mask << i) + (void) sys_close(i); +#endif return(retval); } --- ./include/linux/binfmts.h.fds Wed Oct 15 23:56:43 1997 +++ ./include/linux/binfmts.h Tue Jul 7 17:07:36 1998 @@ -24,6 +24,8 @@ char * filename; /* Name of binary */ unsigned long loader, exec; int dont_iput; /* binfmt handler has put inode */ + int tweak_fd_mask; + struct file * tweak_fd_null; /* /dev/null */ }; /* --- ./security/Common.in.fds Mon Apr 20 22:02:57 1998 +++ ./security/Common.in Wed Jul 1 14:52:59 1998 @@ -9,3 +9,4 @@ bool 'Restricted /proc' CONFIG_SECURE_PROC bool 'Improved securelevel support' CONFIG_SECURE_LEVEL bool 'Unofficial bugfixes' CONFIG_SECURE_BUGFIX +bool 'Special handling of fd 0, 1 & 2' CONFIG_SECURE_FD_0_1_2
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu
|  |