aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c126
1 files changed, 58 insertions, 68 deletions
diff --git a/fs/exec.c b/fs/exec.c
index c5128fbc9165..895823d0149d 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -53,6 +53,7 @@
53#include <linux/tracehook.h> 53#include <linux/tracehook.h>
54#include <linux/kmod.h> 54#include <linux/kmod.h>
55#include <linux/fsnotify.h> 55#include <linux/fsnotify.h>
56#include <linux/fs_struct.h>
56 57
57#include <asm/uaccess.h> 58#include <asm/uaccess.h>
58#include <asm/mmu_context.h> 59#include <asm/mmu_context.h>
@@ -68,17 +69,18 @@ int suid_dumpable = 0;
68static LIST_HEAD(formats); 69static LIST_HEAD(formats);
69static DEFINE_RWLOCK(binfmt_lock); 70static DEFINE_RWLOCK(binfmt_lock);
70 71
71int register_binfmt(struct linux_binfmt * fmt) 72int __register_binfmt(struct linux_binfmt * fmt, int insert)
72{ 73{
73 if (!fmt) 74 if (!fmt)
74 return -EINVAL; 75 return -EINVAL;
75 write_lock(&binfmt_lock); 76 write_lock(&binfmt_lock);
76 list_add(&fmt->lh, &formats); 77 insert ? list_add(&fmt->lh, &formats) :
78 list_add_tail(&fmt->lh, &formats);
77 write_unlock(&binfmt_lock); 79 write_unlock(&binfmt_lock);
78 return 0; 80 return 0;
79} 81}
80 82
81EXPORT_SYMBOL(register_binfmt); 83EXPORT_SYMBOL(__register_binfmt);
82 84
83void unregister_binfmt(struct linux_binfmt * fmt) 85void unregister_binfmt(struct linux_binfmt * fmt)
84{ 86{
@@ -103,40 +105,28 @@ static inline void put_binfmt(struct linux_binfmt * fmt)
103SYSCALL_DEFINE1(uselib, const char __user *, library) 105SYSCALL_DEFINE1(uselib, const char __user *, library)
104{ 106{
105 struct file *file; 107 struct file *file;
106 struct nameidata nd;
107 char *tmp = getname(library); 108 char *tmp = getname(library);
108 int error = PTR_ERR(tmp); 109 int error = PTR_ERR(tmp);
109 110
110 if (!IS_ERR(tmp)) { 111 if (IS_ERR(tmp))
111 error = path_lookup_open(AT_FDCWD, tmp, 112 goto out;
112 LOOKUP_FOLLOW, &nd, 113
113 FMODE_READ|FMODE_EXEC); 114 file = do_filp_open(AT_FDCWD, tmp,
114 putname(tmp); 115 O_LARGEFILE | O_RDONLY | FMODE_EXEC, 0,
115 } 116 MAY_READ | MAY_EXEC | MAY_OPEN);
116 if (error) 117 putname(tmp);
118 error = PTR_ERR(file);
119 if (IS_ERR(file))
117 goto out; 120 goto out;
118 121
119 error = -EINVAL; 122 error = -EINVAL;
120 if (!S_ISREG(nd.path.dentry->d_inode->i_mode)) 123 if (!S_ISREG(file->f_path.dentry->d_inode->i_mode))
121 goto exit; 124 goto exit;
122 125
123 error = -EACCES; 126 error = -EACCES;
124 if (nd.path.mnt->mnt_flags & MNT_NOEXEC) 127 if (file->f_path.mnt->mnt_flags & MNT_NOEXEC)
125 goto exit; 128 goto exit;
126 129
127 error = inode_permission(nd.path.dentry->d_inode,
128 MAY_READ | MAY_EXEC | MAY_OPEN);
129 if (error)
130 goto exit;
131 error = ima_path_check(&nd.path, MAY_READ | MAY_EXEC | MAY_OPEN);
132 if (error)
133 goto exit;
134
135 file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE);
136 error = PTR_ERR(file);
137 if (IS_ERR(file))
138 goto out;
139
140 fsnotify_open(file->f_path.dentry); 130 fsnotify_open(file->f_path.dentry);
141 131
142 error = -ENOEXEC; 132 error = -ENOEXEC;
@@ -158,13 +148,10 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
158 } 148 }
159 read_unlock(&binfmt_lock); 149 read_unlock(&binfmt_lock);
160 } 150 }
151exit:
161 fput(file); 152 fput(file);
162out: 153out:
163 return error; 154 return error;
164exit:
165 release_open_intent(&nd);
166 path_put(&nd.path);
167 goto out;
168} 155}
169 156
170#ifdef CONFIG_MMU 157#ifdef CONFIG_MMU
@@ -659,47 +646,33 @@ EXPORT_SYMBOL(setup_arg_pages);
659 646
660struct file *open_exec(const char *name) 647struct file *open_exec(const char *name)
661{ 648{
662 struct nameidata nd;
663 struct file *file; 649 struct file *file;
664 int err; 650 int err;
665 651
666 err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, 652 file = do_filp_open(AT_FDCWD, name,
667 FMODE_READ|FMODE_EXEC); 653 O_LARGEFILE | O_RDONLY | FMODE_EXEC, 0,
668 if (err) 654 MAY_EXEC | MAY_OPEN);
655 if (IS_ERR(file))
669 goto out; 656 goto out;
670 657
671 err = -EACCES; 658 err = -EACCES;
672 if (!S_ISREG(nd.path.dentry->d_inode->i_mode)) 659 if (!S_ISREG(file->f_path.dentry->d_inode->i_mode))
673 goto out_path_put; 660 goto exit;
674
675 if (nd.path.mnt->mnt_flags & MNT_NOEXEC)
676 goto out_path_put;
677
678 err = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_OPEN);
679 if (err)
680 goto out_path_put;
681 err = ima_path_check(&nd.path, MAY_EXEC | MAY_OPEN);
682 if (err)
683 goto out_path_put;
684 661
685 file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE); 662 if (file->f_path.mnt->mnt_flags & MNT_NOEXEC)
686 if (IS_ERR(file)) 663 goto exit;
687 return file;
688 664
689 fsnotify_open(file->f_path.dentry); 665 fsnotify_open(file->f_path.dentry);
690 666
691 err = deny_write_access(file); 667 err = deny_write_access(file);
692 if (err) { 668 if (err)
693 fput(file); 669 goto exit;
694 goto out;
695 }
696 670
671out:
697 return file; 672 return file;
698 673
699 out_path_put: 674exit:
700 release_open_intent(&nd); 675 fput(file);
701 path_put(&nd.path);
702 out:
703 return ERR_PTR(err); 676 return ERR_PTR(err);
704} 677}
705EXPORT_SYMBOL(open_exec); 678EXPORT_SYMBOL(open_exec);
@@ -1056,28 +1029,35 @@ EXPORT_SYMBOL(install_exec_creds);
1056 * - the caller must hold current->cred_exec_mutex to protect against 1029 * - the caller must hold current->cred_exec_mutex to protect against
1057 * PTRACE_ATTACH 1030 * PTRACE_ATTACH
1058 */ 1031 */
1059void check_unsafe_exec(struct linux_binprm *bprm) 1032int check_unsafe_exec(struct linux_binprm *bprm)
1060{ 1033{
1061 struct task_struct *p = current, *t; 1034 struct task_struct *p = current, *t;
1062 unsigned long flags; 1035 unsigned n_fs;
1063 unsigned n_fs, n_sighand; 1036 int res = 0;
1064 1037
1065 bprm->unsafe = tracehook_unsafe_exec(p); 1038 bprm->unsafe = tracehook_unsafe_exec(p);
1066 1039
1067 n_fs = 1; 1040 n_fs = 1;
1068 n_sighand = 1; 1041 write_lock(&p->fs->lock);
1069 lock_task_sighand(p, &flags); 1042 rcu_read_lock();
1070 for (t = next_thread(p); t != p; t = next_thread(t)) { 1043 for (t = next_thread(p); t != p; t = next_thread(t)) {
1071 if (t->fs == p->fs) 1044 if (t->fs == p->fs)
1072 n_fs++; 1045 n_fs++;
1073 n_sighand++;
1074 } 1046 }
1047 rcu_read_unlock();
1075 1048
1076 if (atomic_read(&p->fs->count) > n_fs || 1049 if (p->fs->users > n_fs) {
1077 atomic_read(&p->sighand->count) > n_sighand)
1078 bprm->unsafe |= LSM_UNSAFE_SHARE; 1050 bprm->unsafe |= LSM_UNSAFE_SHARE;
1051 } else {
1052 res = -EAGAIN;
1053 if (!p->fs->in_exec) {
1054 p->fs->in_exec = 1;
1055 res = 1;
1056 }
1057 }
1058 write_unlock(&p->fs->lock);
1079 1059
1080 unlock_task_sighand(p, &flags); 1060 return res;
1081} 1061}
1082 1062
1083/* 1063/*
@@ -1276,6 +1256,7 @@ int do_execve(char * filename,
1276 struct linux_binprm *bprm; 1256 struct linux_binprm *bprm;
1277 struct file *file; 1257 struct file *file;
1278 struct files_struct *displaced; 1258 struct files_struct *displaced;
1259 bool clear_in_exec;
1279 int retval; 1260 int retval;
1280 1261
1281 retval = unshare_files(&displaced); 1262 retval = unshare_files(&displaced);
@@ -1296,12 +1277,16 @@ int do_execve(char * filename,
1296 bprm->cred = prepare_exec_creds(); 1277 bprm->cred = prepare_exec_creds();
1297 if (!bprm->cred) 1278 if (!bprm->cred)
1298 goto out_unlock; 1279 goto out_unlock;
1299 check_unsafe_exec(bprm); 1280
1281 retval = check_unsafe_exec(bprm);
1282 if (retval < 0)
1283 goto out_unlock;
1284 clear_in_exec = retval;
1300 1285
1301 file = open_exec(filename); 1286 file = open_exec(filename);
1302 retval = PTR_ERR(file); 1287 retval = PTR_ERR(file);
1303 if (IS_ERR(file)) 1288 if (IS_ERR(file))
1304 goto out_unlock; 1289 goto out_unmark;
1305 1290
1306 sched_exec(); 1291 sched_exec();
1307 1292
@@ -1344,6 +1329,7 @@ int do_execve(char * filename,
1344 goto out; 1329 goto out;
1345 1330
1346 /* execve succeeded */ 1331 /* execve succeeded */
1332 current->fs->in_exec = 0;
1347 current->in_execve = 0; 1333 current->in_execve = 0;
1348 mutex_unlock(&current->cred_exec_mutex); 1334 mutex_unlock(&current->cred_exec_mutex);
1349 acct_update_integrals(current); 1335 acct_update_integrals(current);
@@ -1362,6 +1348,10 @@ out_file:
1362 fput(bprm->file); 1348 fput(bprm->file);
1363 } 1349 }
1364 1350
1351out_unmark:
1352 if (clear_in_exec)
1353 current->fs->in_exec = 0;
1354
1365out_unlock: 1355out_unlock:
1366 current->in_execve = 0; 1356 current->in_execve = 0;
1367 mutex_unlock(&current->cred_exec_mutex); 1357 mutex_unlock(&current->cred_exec_mutex);