aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c94
1 files changed, 53 insertions, 41 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 5e559013e30..32993beecbe 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -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 */
107asmlinkage long sys_uselib(const char __user * library) 108asmlinkage 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);
656struct file *open_exec(const char *name) 667struct 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;
681out: 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}
691EXPORT_SYMBOL(open_exec); 707EXPORT_SYMBOL(open_exec);
692 708
693int kernel_read(struct file *file, unsigned long offset, 709int kernel_read(struct file *file, unsigned long offset,
@@ -1071,13 +1087,8 @@ EXPORT_SYMBOL(prepare_binprm);
1071 1087
1072static int unsafe_exec(struct task_struct *p) 1088static 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)