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