aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c52
1 files changed, 40 insertions, 12 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 929b58004b7e..052a961e41aa 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -45,6 +45,7 @@
45#include <linux/proc_fs.h> 45#include <linux/proc_fs.h>
46#include <linux/mount.h> 46#include <linux/mount.h>
47#include <linux/security.h> 47#include <linux/security.h>
48#include <linux/ima.h>
48#include <linux/syscalls.h> 49#include <linux/syscalls.h>
49#include <linux/tsacct_kern.h> 50#include <linux/tsacct_kern.h>
50#include <linux/cn_proc.h> 51#include <linux/cn_proc.h>
@@ -52,6 +53,7 @@
52#include <linux/tracehook.h> 53#include <linux/tracehook.h>
53#include <linux/kmod.h> 54#include <linux/kmod.h>
54#include <linux/fsnotify.h> 55#include <linux/fsnotify.h>
56#include <linux/fs_struct.h>
55 57
56#include <asm/uaccess.h> 58#include <asm/uaccess.h>
57#include <asm/mmu_context.h> 59#include <asm/mmu_context.h>
@@ -127,6 +129,9 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
127 MAY_READ | MAY_EXEC | MAY_OPEN); 129 MAY_READ | MAY_EXEC | MAY_OPEN);
128 if (error) 130 if (error)
129 goto exit; 131 goto exit;
132 error = ima_path_check(&nd.path, MAY_READ | MAY_EXEC | MAY_OPEN);
133 if (error)
134 goto exit;
130 135
131 file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE); 136 file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE);
132 error = PTR_ERR(file); 137 error = PTR_ERR(file);
@@ -674,6 +679,9 @@ struct file *open_exec(const char *name)
674 err = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_OPEN); 679 err = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_OPEN);
675 if (err) 680 if (err)
676 goto out_path_put; 681 goto out_path_put;
682 err = ima_path_check(&nd.path, MAY_EXEC | MAY_OPEN);
683 if (err)
684 goto out_path_put;
677 685
678 file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE); 686 file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE);
679 if (IS_ERR(file)) 687 if (IS_ERR(file))
@@ -1049,32 +1057,35 @@ EXPORT_SYMBOL(install_exec_creds);
1049 * - the caller must hold current->cred_exec_mutex to protect against 1057 * - the caller must hold current->cred_exec_mutex to protect against
1050 * PTRACE_ATTACH 1058 * PTRACE_ATTACH
1051 */ 1059 */
1052void check_unsafe_exec(struct linux_binprm *bprm, struct files_struct *files) 1060int check_unsafe_exec(struct linux_binprm *bprm)
1053{ 1061{
1054 struct task_struct *p = current, *t; 1062 struct task_struct *p = current, *t;
1055 unsigned long flags; 1063 unsigned long flags;
1056 unsigned n_fs, n_files, n_sighand; 1064 unsigned n_fs;
1065 int res = 0;
1057 1066
1058 bprm->unsafe = tracehook_unsafe_exec(p); 1067 bprm->unsafe = tracehook_unsafe_exec(p);
1059 1068
1060 n_fs = 1; 1069 n_fs = 1;
1061 n_files = 1; 1070 write_lock(&p->fs->lock);
1062 n_sighand = 1;
1063 lock_task_sighand(p, &flags); 1071 lock_task_sighand(p, &flags);
1064 for (t = next_thread(p); t != p; t = next_thread(t)) { 1072 for (t = next_thread(p); t != p; t = next_thread(t)) {
1065 if (t->fs == p->fs) 1073 if (t->fs == p->fs)
1066 n_fs++; 1074 n_fs++;
1067 if (t->files == files)
1068 n_files++;
1069 n_sighand++;
1070 } 1075 }
1071 1076
1072 if (atomic_read(&p->fs->count) > n_fs || 1077 if (p->fs->users > n_fs) {
1073 atomic_read(&p->files->count) > n_files ||
1074 atomic_read(&p->sighand->count) > n_sighand)
1075 bprm->unsafe |= LSM_UNSAFE_SHARE; 1078 bprm->unsafe |= LSM_UNSAFE_SHARE;
1079 } else {
1080 if (p->fs->in_exec)
1081 res = -EAGAIN;
1082 p->fs->in_exec = 1;
1083 }
1076 1084
1077 unlock_task_sighand(p, &flags); 1085 unlock_task_sighand(p, &flags);
1086 write_unlock(&p->fs->lock);
1087
1088 return res;
1078} 1089}
1079 1090
1080/* 1091/*
@@ -1184,6 +1195,9 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
1184 retval = security_bprm_check(bprm); 1195 retval = security_bprm_check(bprm);
1185 if (retval) 1196 if (retval)
1186 return retval; 1197 return retval;
1198 retval = ima_bprm_check(bprm);
1199 if (retval)
1200 return retval;
1187 1201
1188 /* kernel module loader fixup */ 1202 /* kernel module loader fixup */
1189 /* so we don't try to load run modprobe in kernel space. */ 1203 /* so we don't try to load run modprobe in kernel space. */
@@ -1284,17 +1298,21 @@ int do_execve(char * filename,
1284 retval = mutex_lock_interruptible(&current->cred_exec_mutex); 1298 retval = mutex_lock_interruptible(&current->cred_exec_mutex);
1285 if (retval < 0) 1299 if (retval < 0)
1286 goto out_free; 1300 goto out_free;
1301 current->in_execve = 1;
1287 1302
1288 retval = -ENOMEM; 1303 retval = -ENOMEM;
1289 bprm->cred = prepare_exec_creds(); 1304 bprm->cred = prepare_exec_creds();
1290 if (!bprm->cred) 1305 if (!bprm->cred)
1291 goto out_unlock; 1306 goto out_unlock;
1292 check_unsafe_exec(bprm, displaced); 1307
1308 retval = check_unsafe_exec(bprm);
1309 if (retval)
1310 goto out_unlock;
1293 1311
1294 file = open_exec(filename); 1312 file = open_exec(filename);
1295 retval = PTR_ERR(file); 1313 retval = PTR_ERR(file);
1296 if (IS_ERR(file)) 1314 if (IS_ERR(file))
1297 goto out_unlock; 1315 goto out_unmark;
1298 1316
1299 sched_exec(); 1317 sched_exec();
1300 1318
@@ -1337,6 +1355,10 @@ int do_execve(char * filename,
1337 goto out; 1355 goto out;
1338 1356
1339 /* execve succeeded */ 1357 /* execve succeeded */
1358 write_lock(&current->fs->lock);
1359 current->fs->in_exec = 0;
1360 write_unlock(&current->fs->lock);
1361 current->in_execve = 0;
1340 mutex_unlock(&current->cred_exec_mutex); 1362 mutex_unlock(&current->cred_exec_mutex);
1341 acct_update_integrals(current); 1363 acct_update_integrals(current);
1342 free_bprm(bprm); 1364 free_bprm(bprm);
@@ -1354,7 +1376,13 @@ out_file:
1354 fput(bprm->file); 1376 fput(bprm->file);
1355 } 1377 }
1356 1378
1379out_unmark:
1380 write_lock(&current->fs->lock);
1381 current->fs->in_exec = 0;
1382 write_unlock(&current->fs->lock);
1383
1357out_unlock: 1384out_unlock:
1385 current->in_execve = 0;
1358 mutex_unlock(&current->cred_exec_mutex); 1386 mutex_unlock(&current->cred_exec_mutex);
1359 1387
1360out_free: 1388out_free: