diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 41 |
1 files changed, 35 insertions, 6 deletions
@@ -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> |
@@ -127,6 +128,9 @@ SYSCALL_DEFINE1(uselib, const char __user *, library) | |||
127 | MAY_READ | MAY_EXEC | MAY_OPEN); | 128 | MAY_READ | MAY_EXEC | MAY_OPEN); |
128 | if (error) | 129 | if (error) |
129 | goto exit; | 130 | goto exit; |
131 | error = ima_path_check(&nd.path, MAY_READ | MAY_EXEC | MAY_OPEN); | ||
132 | if (error) | ||
133 | goto exit; | ||
130 | 134 | ||
131 | file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE); | 135 | file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE); |
132 | error = PTR_ERR(file); | 136 | error = PTR_ERR(file); |
@@ -674,6 +678,9 @@ struct file *open_exec(const char *name) | |||
674 | err = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_OPEN); | 678 | err = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_OPEN); |
675 | if (err) | 679 | if (err) |
676 | goto out_path_put; | 680 | goto out_path_put; |
681 | err = ima_path_check(&nd.path, MAY_EXEC | MAY_OPEN); | ||
682 | if (err) | ||
683 | goto out_path_put; | ||
677 | 684 | ||
678 | file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE); | 685 | file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE); |
679 | if (IS_ERR(file)) | 686 | if (IS_ERR(file)) |
@@ -1049,16 +1056,32 @@ EXPORT_SYMBOL(install_exec_creds); | |||
1049 | * - the caller must hold current->cred_exec_mutex to protect against | 1056 | * - the caller must hold current->cred_exec_mutex to protect against |
1050 | * PTRACE_ATTACH | 1057 | * PTRACE_ATTACH |
1051 | */ | 1058 | */ |
1052 | void check_unsafe_exec(struct linux_binprm *bprm) | 1059 | void check_unsafe_exec(struct linux_binprm *bprm, struct files_struct *files) |
1053 | { | 1060 | { |
1054 | struct task_struct *p = current; | 1061 | struct task_struct *p = current, *t; |
1062 | unsigned long flags; | ||
1063 | unsigned n_fs, n_files, n_sighand; | ||
1055 | 1064 | ||
1056 | bprm->unsafe = tracehook_unsafe_exec(p); | 1065 | bprm->unsafe = tracehook_unsafe_exec(p); |
1057 | 1066 | ||
1058 | if (atomic_read(&p->fs->count) > 1 || | 1067 | n_fs = 1; |
1059 | atomic_read(&p->files->count) > 1 || | 1068 | n_files = 1; |
1060 | atomic_read(&p->sighand->count) > 1) | 1069 | n_sighand = 1; |
1070 | lock_task_sighand(p, &flags); | ||
1071 | for (t = next_thread(p); t != p; t = next_thread(t)) { | ||
1072 | if (t->fs == p->fs) | ||
1073 | n_fs++; | ||
1074 | if (t->files == files) | ||
1075 | n_files++; | ||
1076 | n_sighand++; | ||
1077 | } | ||
1078 | |||
1079 | if (atomic_read(&p->fs->count) > n_fs || | ||
1080 | atomic_read(&p->files->count) > n_files || | ||
1081 | atomic_read(&p->sighand->count) > n_sighand) | ||
1061 | bprm->unsafe |= LSM_UNSAFE_SHARE; | 1082 | bprm->unsafe |= LSM_UNSAFE_SHARE; |
1083 | |||
1084 | unlock_task_sighand(p, &flags); | ||
1062 | } | 1085 | } |
1063 | 1086 | ||
1064 | /* | 1087 | /* |
@@ -1168,6 +1191,9 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) | |||
1168 | retval = security_bprm_check(bprm); | 1191 | retval = security_bprm_check(bprm); |
1169 | if (retval) | 1192 | if (retval) |
1170 | return retval; | 1193 | return retval; |
1194 | retval = ima_bprm_check(bprm); | ||
1195 | if (retval) | ||
1196 | return retval; | ||
1171 | 1197 | ||
1172 | /* kernel module loader fixup */ | 1198 | /* kernel module loader fixup */ |
1173 | /* so we don't try to load run modprobe in kernel space. */ | 1199 | /* so we don't try to load run modprobe in kernel space. */ |
@@ -1268,12 +1294,13 @@ int do_execve(char * filename, | |||
1268 | retval = mutex_lock_interruptible(¤t->cred_exec_mutex); | 1294 | retval = mutex_lock_interruptible(¤t->cred_exec_mutex); |
1269 | if (retval < 0) | 1295 | if (retval < 0) |
1270 | goto out_free; | 1296 | goto out_free; |
1297 | current->in_execve = 1; | ||
1271 | 1298 | ||
1272 | retval = -ENOMEM; | 1299 | retval = -ENOMEM; |
1273 | bprm->cred = prepare_exec_creds(); | 1300 | bprm->cred = prepare_exec_creds(); |
1274 | if (!bprm->cred) | 1301 | if (!bprm->cred) |
1275 | goto out_unlock; | 1302 | goto out_unlock; |
1276 | check_unsafe_exec(bprm); | 1303 | check_unsafe_exec(bprm, displaced); |
1277 | 1304 | ||
1278 | file = open_exec(filename); | 1305 | file = open_exec(filename); |
1279 | retval = PTR_ERR(file); | 1306 | retval = PTR_ERR(file); |
@@ -1321,6 +1348,7 @@ int do_execve(char * filename, | |||
1321 | goto out; | 1348 | goto out; |
1322 | 1349 | ||
1323 | /* execve succeeded */ | 1350 | /* execve succeeded */ |
1351 | current->in_execve = 0; | ||
1324 | mutex_unlock(¤t->cred_exec_mutex); | 1352 | mutex_unlock(¤t->cred_exec_mutex); |
1325 | acct_update_integrals(current); | 1353 | acct_update_integrals(current); |
1326 | free_bprm(bprm); | 1354 | free_bprm(bprm); |
@@ -1339,6 +1367,7 @@ out_file: | |||
1339 | } | 1367 | } |
1340 | 1368 | ||
1341 | out_unlock: | 1369 | out_unlock: |
1370 | current->in_execve = 0; | ||
1342 | mutex_unlock(¤t->cred_exec_mutex); | 1371 | mutex_unlock(¤t->cred_exec_mutex); |
1343 | 1372 | ||
1344 | out_free: | 1373 | out_free: |