diff options
| author | Ingo Molnar <mingo@elte.hu> | 2008-07-28 15:14:43 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-07-28 15:14:43 -0400 |
| commit | 414f746d232d41ed6ae8632c4495ae795373c44b (patch) | |
| tree | 167f9bc8f139c6e82e6732b38c7a938b8a9d31cd /fs/exec.c | |
| parent | 5a7a201c51c324876d00a54e7208af6af12d1ca4 (diff) | |
| parent | c9272c4f9fbe2087beb3392f526dc5b19efaa56b (diff) | |
Merge branch 'linus' into cpus4096
Diffstat (limited to 'fs/exec.c')
| -rw-r--r-- | fs/exec.c | 93 |
1 files changed, 52 insertions, 41 deletions
| @@ -42,13 +42,13 @@ | |||
| 42 | #include <linux/module.h> | 42 | #include <linux/module.h> |
| 43 | #include <linux/namei.h> | 43 | #include <linux/namei.h> |
| 44 | #include <linux/proc_fs.h> | 44 | #include <linux/proc_fs.h> |
| 45 | #include <linux/ptrace.h> | ||
| 46 | #include <linux/mount.h> | 45 | #include <linux/mount.h> |
| 47 | #include <linux/security.h> | 46 | #include <linux/security.h> |
| 48 | #include <linux/syscalls.h> | 47 | #include <linux/syscalls.h> |
| 49 | #include <linux/tsacct_kern.h> | 48 | #include <linux/tsacct_kern.h> |
| 50 | #include <linux/cn_proc.h> | 49 | #include <linux/cn_proc.h> |
| 51 | #include <linux/audit.h> | 50 | #include <linux/audit.h> |
| 51 | #include <linux/tracehook.h> | ||
| 52 | 52 | ||
| 53 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
| 54 | #include <asm/mmu_context.h> | 54 | #include <asm/mmu_context.h> |
| @@ -106,11 +106,17 @@ static inline void put_binfmt(struct linux_binfmt * fmt) | |||
| 106 | */ | 106 | */ |
| 107 | asmlinkage long sys_uselib(const char __user * library) | 107 | asmlinkage long sys_uselib(const char __user * library) |
| 108 | { | 108 | { |
| 109 | struct file * file; | 109 | struct file *file; |
| 110 | struct nameidata nd; | 110 | struct nameidata nd; |
| 111 | int error; | 111 | char *tmp = getname(library); |
| 112 | 112 | int error = PTR_ERR(tmp); | |
| 113 | error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC); | 113 | |
| 114 | if (!IS_ERR(tmp)) { | ||
| 115 | error = path_lookup_open(AT_FDCWD, tmp, | ||
| 116 | LOOKUP_FOLLOW, &nd, | ||
| 117 | FMODE_READ|FMODE_EXEC); | ||
| 118 | putname(tmp); | ||
| 119 | } | ||
| 114 | if (error) | 120 | if (error) |
| 115 | goto out; | 121 | goto out; |
| 116 | 122 | ||
| @@ -118,7 +124,11 @@ asmlinkage long sys_uselib(const char __user * library) | |||
| 118 | if (!S_ISREG(nd.path.dentry->d_inode->i_mode)) | 124 | if (!S_ISREG(nd.path.dentry->d_inode->i_mode)) |
| 119 | goto exit; | 125 | goto exit; |
| 120 | 126 | ||
| 121 | error = vfs_permission(&nd, MAY_READ | MAY_EXEC); | 127 | error = -EACCES; |
| 128 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) | ||
| 129 | goto exit; | ||
| 130 | |||
| 131 | error = vfs_permission(&nd, MAY_READ | MAY_EXEC | MAY_OPEN); | ||
| 122 | if (error) | 132 | if (error) |
| 123 | goto exit; | 133 | goto exit; |
| 124 | 134 | ||
| @@ -656,38 +666,43 @@ EXPORT_SYMBOL(setup_arg_pages); | |||
| 656 | struct file *open_exec(const char *name) | 666 | struct file *open_exec(const char *name) |
| 657 | { | 667 | { |
| 658 | struct nameidata nd; | 668 | struct nameidata nd; |
| 659 | int err; | ||
| 660 | struct file *file; | 669 | struct file *file; |
| 670 | int err; | ||
| 661 | 671 | ||
| 662 | err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC); | 672 | err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, |
| 663 | file = ERR_PTR(err); | 673 | FMODE_READ|FMODE_EXEC); |
| 664 | 674 | if (err) | |
| 665 | if (!err) { | 675 | goto out; |
| 666 | struct inode *inode = nd.path.dentry->d_inode; | 676 | |
| 667 | file = ERR_PTR(-EACCES); | 677 | err = -EACCES; |
| 668 | if (S_ISREG(inode->i_mode)) { | 678 | if (!S_ISREG(nd.path.dentry->d_inode->i_mode)) |
| 669 | int err = vfs_permission(&nd, MAY_EXEC); | 679 | goto out_path_put; |
| 670 | file = ERR_PTR(err); | 680 | |
| 671 | if (!err) { | 681 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) |
| 672 | file = nameidata_to_filp(&nd, | 682 | goto out_path_put; |
| 673 | O_RDONLY|O_LARGEFILE); | 683 | |
| 674 | if (!IS_ERR(file)) { | 684 | err = vfs_permission(&nd, MAY_EXEC | MAY_OPEN); |
| 675 | err = deny_write_access(file); | 685 | if (err) |
| 676 | if (err) { | 686 | goto out_path_put; |
| 677 | fput(file); | 687 | |
| 678 | file = ERR_PTR(err); | 688 | file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE); |
| 679 | } | 689 | if (IS_ERR(file)) |
| 680 | } | 690 | return file; |
| 681 | out: | 691 | |
| 682 | return file; | 692 | err = deny_write_access(file); |
| 683 | } | 693 | if (err) { |
| 684 | } | 694 | fput(file); |
| 685 | release_open_intent(&nd); | 695 | goto out; |
| 686 | path_put(&nd.path); | ||
| 687 | } | 696 | } |
| 688 | goto out; | ||
| 689 | } | ||
| 690 | 697 | ||
| 698 | return file; | ||
| 699 | |||
| 700 | out_path_put: | ||
| 701 | release_open_intent(&nd); | ||
| 702 | path_put(&nd.path); | ||
| 703 | out: | ||
| 704 | return ERR_PTR(err); | ||
| 705 | } | ||
| 691 | EXPORT_SYMBOL(open_exec); | 706 | EXPORT_SYMBOL(open_exec); |
| 692 | 707 | ||
| 693 | int kernel_read(struct file *file, unsigned long offset, | 708 | int kernel_read(struct file *file, unsigned long offset, |
| @@ -1071,13 +1086,8 @@ EXPORT_SYMBOL(prepare_binprm); | |||
| 1071 | 1086 | ||
| 1072 | static int unsafe_exec(struct task_struct *p) | 1087 | static int unsafe_exec(struct task_struct *p) |
| 1073 | { | 1088 | { |
| 1074 | int unsafe = 0; | 1089 | int unsafe = tracehook_unsafe_exec(p); |
| 1075 | if (p->ptrace & PT_PTRACED) { | 1090 | |
| 1076 | if (p->ptrace & PT_PTRACE_CAP) | ||
| 1077 | unsafe |= LSM_UNSAFE_PTRACE_CAP; | ||
| 1078 | else | ||
| 1079 | unsafe |= LSM_UNSAFE_PTRACE; | ||
| 1080 | } | ||
| 1081 | if (atomic_read(&p->fs->count) > 1 || | 1091 | if (atomic_read(&p->fs->count) > 1 || |
| 1082 | atomic_read(&p->files->count) > 1 || | 1092 | atomic_read(&p->files->count) > 1 || |
| 1083 | atomic_read(&p->sighand->count) > 1) | 1093 | atomic_read(&p->sighand->count) > 1) |
| @@ -1214,6 +1224,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) | |||
| 1214 | read_unlock(&binfmt_lock); | 1224 | read_unlock(&binfmt_lock); |
| 1215 | retval = fn(bprm, regs); | 1225 | retval = fn(bprm, regs); |
| 1216 | if (retval >= 0) { | 1226 | if (retval >= 0) { |
| 1227 | tracehook_report_exec(fmt, bprm, regs); | ||
| 1217 | put_binfmt(fmt); | 1228 | put_binfmt(fmt); |
| 1218 | allow_write_access(bprm->file); | 1229 | allow_write_access(bprm->file); |
| 1219 | if (bprm->file) | 1230 | if (bprm->file) |
