diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-06-25 01:20:01 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-06-25 01:20:01 +0000 |
commit | 3797ba0b62debb71af4606910acacc9896a9ae3b (patch) | |
tree | 414eea76253c7871bfdf3bd9d1817771eb40917c /fs/exec.c | |
parent | 2b6c0c580795a4404f72d2a794214dd9e080709d (diff) |
Merge with Linux 2.4.0-test2.
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 103 |
1 files changed, 41 insertions, 62 deletions
@@ -101,54 +101,37 @@ static inline void put_binfmt(struct linux_binfmt * fmt) */ asmlinkage long sys_uselib(const char * library) { + int fd, retval; struct file * file; - struct nameidata nd; - int error; - - error = user_path_walk(library, &nd); - if (error) - goto out; - - error = -EINVAL; - if (!S_ISREG(nd.dentry->d_inode->i_mode)) - goto exit; - - error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC); - if (error) - goto exit; - - lock_kernel(); - file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); - unlock_kernel(); - error = PTR_ERR(file); - if (IS_ERR(file)) - goto out; - error = -ENOEXEC; - if(file->f_op && file->f_op->read) { - struct linux_binfmt * fmt; + fd = sys_open(library, 0, 0); + if (fd < 0) + return fd; + file = fget(fd); + retval = -ENOEXEC; + if (file) { + if(file->f_op && file->f_op->read) { + struct linux_binfmt * fmt; - read_lock(&binfmt_lock); - for (fmt = formats ; fmt ; fmt = fmt->next) { - if (!fmt->load_shlib) - continue; - if (!try_inc_mod_count(fmt->module)) - continue; - read_unlock(&binfmt_lock); - error = fmt->load_shlib(file); read_lock(&binfmt_lock); - put_binfmt(fmt); - if (error != -ENOEXEC) - break; + for (fmt = formats ; fmt ; fmt = fmt->next) { + if (!fmt->load_shlib) + continue; + if (!try_inc_mod_count(fmt->module)) + continue; + read_unlock(&binfmt_lock); + retval = fmt->load_shlib(file); + read_lock(&binfmt_lock); + put_binfmt(fmt); + if (retval != -ENOEXEC) + break; + } + read_unlock(&binfmt_lock); } - read_unlock(&binfmt_lock); + fput(file); } - fput(file); -out: - return error; -exit: - path_release(&nd); - goto out; + sys_close(fd); + return retval; } /* @@ -336,7 +319,6 @@ int setup_arg_pages(struct linux_binprm *bprm) struct file *open_exec(const char *name) { struct nameidata nd; - struct inode *inode; struct file *file; int err = 0; @@ -346,22 +328,14 @@ struct file *open_exec(const char *name) unlock_kernel(); file = ERR_PTR(err); if (!err) { - inode = nd.dentry->d_inode; file = ERR_PTR(-EACCES); - if (!IS_NOEXEC(inode) && S_ISREG(inode->i_mode)) { - int err = permission(inode, MAY_EXEC); + if (S_ISREG(nd.dentry->d_inode->i_mode)) { + int err = permission(nd.dentry->d_inode, MAY_EXEC); file = ERR_PTR(err); if (!err) { lock_kernel(); file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); unlock_kernel(); - if (!IS_ERR(file)) { - err = deny_write_access(file); - if (err) { - fput(file); - file = ERR_PTR(err); - } - } out: return file; } @@ -556,7 +530,7 @@ flush_failed: */ static inline int must_not_trace_exec(struct task_struct * p) { - return (p->ptrace&PT_PTRACED) && !cap_raised(p->p_pptr->cap_effective, CAP_SYS_PTRACE); + return (p->ptrace & PT_PTRACED) && !cap_raised(p->p_pptr->cap_effective, CAP_SYS_PTRACE); } /* @@ -566,13 +540,23 @@ static inline int must_not_trace_exec(struct task_struct * p) int prepare_binprm(struct linux_binprm *bprm) { int mode; - int id_change,cap_raised; + int retval,id_change,cap_raised; struct inode * inode = bprm->file->f_dentry->d_inode; mode = inode->i_mode; - /* Huh? We had already checked for MAY_EXEC, WTF do we check this? */ - if (!(mode & 0111)) /* with at least _one_ execute bit set */ + if (!S_ISREG(mode)) /* must be regular file */ + return -EACCES; + if (!(mode & 0111)) /* with at least _one_ execute bit set */ return -EACCES; + if (IS_NOEXEC(inode)) /* FS mustn't be mounted noexec */ + return -EACCES; + if (!inode->i_sb) + return -EACCES; + if ((retval = permission(inode, MAY_EXEC)) != 0) + return retval; + /* better not execute files which are being written to */ + if (atomic_read(&inode->i_writecount) > 0) + return -ETXTBSY; bprm->e_uid = current->euid; bprm->e_gid = current->egid; @@ -744,7 +728,6 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) char * dynloader[] = { "/sbin/loader" }; struct file * file; - allow_write_access(bprm->file); fput(bprm->file); bprm->file = NULL; @@ -778,7 +761,6 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) retval = fn(bprm, regs); if (retval >= 0) { put_binfmt(fmt); - allow_write_access(bprm->file); if (bprm->file) fput(bprm->file); bprm->file = NULL; @@ -840,13 +822,11 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs bprm.loader = 0; bprm.exec = 0; if ((bprm.argc = count(argv, bprm.p / sizeof(void *))) < 0) { - allow_write_access(file); fput(file); return bprm.argc; } if ((bprm.envc = count(envp, bprm.p / sizeof(void *))) < 0) { - allow_write_access(file); fput(file); return bprm.envc; } @@ -875,7 +855,6 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs out: /* Something went wrong, return the inode and free the argument pages*/ - allow_write_access(bprm.file); if (bprm.file) fput(bprm.file); |