aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/binfmt_aout.c2
-rw-r--r--fs/binfmt_elf.c2
-rw-r--r--fs/binfmt_elf_fdpic.c2
-rw-r--r--fs/binfmt_flat.c2
-rw-r--r--fs/binfmt_som.c2
-rw-r--r--fs/compat.c42
-rw-r--r--fs/exec.c149
-rw-r--r--fs/internal.h6
8 files changed, 121 insertions, 86 deletions
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 204cfd1d7676..f1f3f4192a60 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -320,7 +320,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
320 current->mm->free_area_cache = current->mm->mmap_base; 320 current->mm->free_area_cache = current->mm->mmap_base;
321 current->mm->cached_hole_size = 0; 321 current->mm->cached_hole_size = 0;
322 322
323 compute_creds(bprm); 323 install_exec_creds(bprm);
324 current->flags &= ~PF_FORKNOEXEC; 324 current->flags &= ~PF_FORKNOEXEC;
325#ifdef __sparc__ 325#ifdef __sparc__
326 if (N_MAGIC(ex) == NMAGIC) { 326 if (N_MAGIC(ex) == NMAGIC) {
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 9142ff5dc8e6..f458c1217c5e 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -956,7 +956,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
956 } 956 }
957#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ 957#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
958 958
959 compute_creds(bprm); 959 install_exec_creds(bprm);
960 current->flags &= ~PF_FORKNOEXEC; 960 current->flags &= ~PF_FORKNOEXEC;
961 retval = create_elf_tables(bprm, &loc->elf_ex, 961 retval = create_elf_tables(bprm, &loc->elf_ex,
962 load_addr, interp_load_addr); 962 load_addr, interp_load_addr);
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 45dabd59936f..aa5b43205e37 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -404,7 +404,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
404 current->mm->start_stack = current->mm->start_brk + stack_size; 404 current->mm->start_stack = current->mm->start_brk + stack_size;
405#endif 405#endif
406 406
407 compute_creds(bprm); 407 install_exec_creds(bprm);
408 current->flags &= ~PF_FORKNOEXEC; 408 current->flags &= ~PF_FORKNOEXEC;
409 if (create_elf_fdpic_tables(bprm, current->mm, 409 if (create_elf_fdpic_tables(bprm, current->mm,
410 &exec_params, &interp_params) < 0) 410 &exec_params, &interp_params) < 0)
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index ccb781a6a804..7bbd5c6b3725 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -880,7 +880,7 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
880 (libinfo.lib_list[j].loaded)? 880 (libinfo.lib_list[j].loaded)?
881 libinfo.lib_list[j].start_data:UNLOADED_LIB; 881 libinfo.lib_list[j].start_data:UNLOADED_LIB;
882 882
883 compute_creds(bprm); 883 install_exec_creds(bprm);
884 current->flags &= ~PF_FORKNOEXEC; 884 current->flags &= ~PF_FORKNOEXEC;
885 885
886 set_binfmt(&flat_format); 886 set_binfmt(&flat_format);
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c
index 74e587a52796..08644a61616e 100644
--- a/fs/binfmt_som.c
+++ b/fs/binfmt_som.c
@@ -255,7 +255,7 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
255 kfree(hpuxhdr); 255 kfree(hpuxhdr);
256 256
257 set_binfmt(&som_format); 257 set_binfmt(&som_format);
258 compute_creds(bprm); 258 install_exec_creds(bprm);
259 setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); 259 setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
260 260
261 create_som_tables(bprm); 261 create_som_tables(bprm);
diff --git a/fs/compat.c b/fs/compat.c
index e5f49f538502..d1ece79b6411 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1393,10 +1393,20 @@ int compat_do_execve(char * filename,
1393 if (!bprm) 1393 if (!bprm)
1394 goto out_ret; 1394 goto out_ret;
1395 1395
1396 retval = mutex_lock_interruptible(&current->cred_exec_mutex);
1397 if (retval < 0)
1398 goto out_free;
1399
1400 retval = -ENOMEM;
1401 bprm->cred = prepare_exec_creds();
1402 if (!bprm->cred)
1403 goto out_unlock;
1404 check_unsafe_exec(bprm);
1405
1396 file = open_exec(filename); 1406 file = open_exec(filename);
1397 retval = PTR_ERR(file); 1407 retval = PTR_ERR(file);
1398 if (IS_ERR(file)) 1408 if (IS_ERR(file))
1399 goto out_kfree; 1409 goto out_unlock;
1400 1410
1401 sched_exec(); 1411 sched_exec();
1402 1412
@@ -1410,14 +1420,10 @@ int compat_do_execve(char * filename,
1410 1420
1411 bprm->argc = compat_count(argv, MAX_ARG_STRINGS); 1421 bprm->argc = compat_count(argv, MAX_ARG_STRINGS);
1412 if ((retval = bprm->argc) < 0) 1422 if ((retval = bprm->argc) < 0)
1413 goto out_mm; 1423 goto out;
1414 1424
1415 bprm->envc = compat_count(envp, MAX_ARG_STRINGS); 1425 bprm->envc = compat_count(envp, MAX_ARG_STRINGS);
1416 if ((retval = bprm->envc) < 0) 1426 if ((retval = bprm->envc) < 0)
1417 goto out_mm;
1418
1419 retval = security_bprm_alloc(bprm);
1420 if (retval)
1421 goto out; 1427 goto out;
1422 1428
1423 retval = prepare_binprm(bprm); 1429 retval = prepare_binprm(bprm);
@@ -1438,19 +1444,16 @@ int compat_do_execve(char * filename,
1438 goto out; 1444 goto out;
1439 1445
1440 retval = search_binary_handler(bprm, regs); 1446 retval = search_binary_handler(bprm, regs);
1441 if (retval >= 0) { 1447 if (retval < 0)
1442 /* execve success */ 1448 goto out;
1443 security_bprm_free(bprm);
1444 acct_update_integrals(current);
1445 free_bprm(bprm);
1446 return retval;
1447 }
1448 1449
1449out: 1450 /* execve succeeded */
1450 if (bprm->security) 1451 mutex_unlock(&current->cred_exec_mutex);
1451 security_bprm_free(bprm); 1452 acct_update_integrals(current);
1453 free_bprm(bprm);
1454 return retval;
1452 1455
1453out_mm: 1456out:
1454 if (bprm->mm) 1457 if (bprm->mm)
1455 mmput(bprm->mm); 1458 mmput(bprm->mm);
1456 1459
@@ -1460,7 +1463,10 @@ out_file:
1460 fput(bprm->file); 1463 fput(bprm->file);
1461 } 1464 }
1462 1465
1463out_kfree: 1466out_unlock:
1467 mutex_unlock(&current->cred_exec_mutex);
1468
1469out_free:
1464 free_bprm(bprm); 1470 free_bprm(bprm);
1465 1471
1466out_ret: 1472out_ret:
diff --git a/fs/exec.c b/fs/exec.c
index 9bd3559ddece..32f13e299417 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -55,6 +55,7 @@
55#include <asm/uaccess.h> 55#include <asm/uaccess.h>
56#include <asm/mmu_context.h> 56#include <asm/mmu_context.h>
57#include <asm/tlb.h> 57#include <asm/tlb.h>
58#include "internal.h"
58 59
59#ifdef __alpha__ 60#ifdef __alpha__
60/* for /sbin/loader handling in search_binary_handler() */ 61/* for /sbin/loader handling in search_binary_handler() */
@@ -1007,15 +1008,17 @@ int flush_old_exec(struct linux_binprm * bprm)
1007 */ 1008 */
1008 current->mm->task_size = TASK_SIZE; 1009 current->mm->task_size = TASK_SIZE;
1009 1010
1010 if (bprm->e_uid != current_euid() || 1011 /* install the new credentials */
1011 bprm->e_gid != current_egid()) { 1012 if (bprm->cred->uid != current_euid() ||
1012 set_dumpable(current->mm, suid_dumpable); 1013 bprm->cred->gid != current_egid()) {
1013 current->pdeath_signal = 0; 1014 current->pdeath_signal = 0;
1014 } else if (file_permission(bprm->file, MAY_READ) || 1015 } else if (file_permission(bprm->file, MAY_READ) ||
1015 (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) { 1016 bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP) {
1016 set_dumpable(current->mm, suid_dumpable); 1017 set_dumpable(current->mm, suid_dumpable);
1017 } 1018 }
1018 1019
1020 current->personality &= ~bprm->per_clear;
1021
1019 /* An exec changes our domain. We are no longer part of the thread 1022 /* An exec changes our domain. We are no longer part of the thread
1020 group */ 1023 group */
1021 1024
@@ -1032,13 +1035,50 @@ out:
1032 1035
1033EXPORT_SYMBOL(flush_old_exec); 1036EXPORT_SYMBOL(flush_old_exec);
1034 1037
1038/*
1039 * install the new credentials for this executable
1040 */
1041void install_exec_creds(struct linux_binprm *bprm)
1042{
1043 security_bprm_committing_creds(bprm);
1044
1045 commit_creds(bprm->cred);
1046 bprm->cred = NULL;
1047
1048 /* cred_exec_mutex must be held at least to this point to prevent
1049 * ptrace_attach() from altering our determination of the task's
1050 * credentials; any time after this it may be unlocked */
1051
1052 security_bprm_committed_creds(bprm);
1053}
1054EXPORT_SYMBOL(install_exec_creds);
1055
1056/*
1057 * determine how safe it is to execute the proposed program
1058 * - the caller must hold current->cred_exec_mutex to protect against
1059 * PTRACE_ATTACH
1060 */
1061void check_unsafe_exec(struct linux_binprm *bprm)
1062{
1063 struct task_struct *p = current;
1064
1065 bprm->unsafe = tracehook_unsafe_exec(p);
1066
1067 if (atomic_read(&p->fs->count) > 1 ||
1068 atomic_read(&p->files->count) > 1 ||
1069 atomic_read(&p->sighand->count) > 1)
1070 bprm->unsafe |= LSM_UNSAFE_SHARE;
1071}
1072
1035/* 1073/*
1036 * Fill the binprm structure from the inode. 1074 * Fill the binprm structure from the inode.
1037 * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes 1075 * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
1076 *
1077 * This may be called multiple times for binary chains (scripts for example).
1038 */ 1078 */
1039int prepare_binprm(struct linux_binprm *bprm) 1079int prepare_binprm(struct linux_binprm *bprm)
1040{ 1080{
1041 int mode; 1081 umode_t mode;
1042 struct inode * inode = bprm->file->f_path.dentry->d_inode; 1082 struct inode * inode = bprm->file->f_path.dentry->d_inode;
1043 int retval; 1083 int retval;
1044 1084
@@ -1046,14 +1086,15 @@ int prepare_binprm(struct linux_binprm *bprm)
1046 if (bprm->file->f_op == NULL) 1086 if (bprm->file->f_op == NULL)
1047 return -EACCES; 1087 return -EACCES;
1048 1088
1049 bprm->e_uid = current_euid(); 1089 /* clear any previous set[ug]id data from a previous binary */
1050 bprm->e_gid = current_egid(); 1090 bprm->cred->euid = current_euid();
1091 bprm->cred->egid = current_egid();
1051 1092
1052 if(!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) { 1093 if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
1053 /* Set-uid? */ 1094 /* Set-uid? */
1054 if (mode & S_ISUID) { 1095 if (mode & S_ISUID) {
1055 current->personality &= ~PER_CLEAR_ON_SETID; 1096 bprm->per_clear |= PER_CLEAR_ON_SETID;
1056 bprm->e_uid = inode->i_uid; 1097 bprm->cred->euid = inode->i_uid;
1057 } 1098 }
1058 1099
1059 /* Set-gid? */ 1100 /* Set-gid? */
@@ -1063,50 +1104,23 @@ int prepare_binprm(struct linux_binprm *bprm)
1063 * executable. 1104 * executable.
1064 */ 1105 */
1065 if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { 1106 if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
1066 current->personality &= ~PER_CLEAR_ON_SETID; 1107 bprm->per_clear |= PER_CLEAR_ON_SETID;
1067 bprm->e_gid = inode->i_gid; 1108 bprm->cred->egid = inode->i_gid;
1068 } 1109 }
1069 } 1110 }
1070 1111
1071 /* fill in binprm security blob */ 1112 /* fill in binprm security blob */
1072 retval = security_bprm_set(bprm); 1113 retval = security_bprm_set_creds(bprm);
1073 if (retval) 1114 if (retval)
1074 return retval; 1115 return retval;
1116 bprm->cred_prepared = 1;
1075 1117
1076 memset(bprm->buf,0,BINPRM_BUF_SIZE); 1118 memset(bprm->buf, 0, BINPRM_BUF_SIZE);
1077 return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE); 1119 return kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE);
1078} 1120}
1079 1121
1080EXPORT_SYMBOL(prepare_binprm); 1122EXPORT_SYMBOL(prepare_binprm);
1081 1123
1082static int unsafe_exec(struct task_struct *p)
1083{
1084 int unsafe = tracehook_unsafe_exec(p);
1085
1086 if (atomic_read(&p->fs->count) > 1 ||
1087 atomic_read(&p->files->count) > 1 ||
1088 atomic_read(&p->sighand->count) > 1)
1089 unsafe |= LSM_UNSAFE_SHARE;
1090
1091 return unsafe;
1092}
1093
1094void compute_creds(struct linux_binprm *bprm)
1095{
1096 int unsafe;
1097
1098 if (bprm->e_uid != current_uid())
1099 current->pdeath_signal = 0;
1100 exec_keys(current);
1101
1102 task_lock(current);
1103 unsafe = unsafe_exec(current);
1104 security_bprm_apply_creds(bprm, unsafe);
1105 task_unlock(current);
1106 security_bprm_post_apply_creds(bprm);
1107}
1108EXPORT_SYMBOL(compute_creds);
1109
1110/* 1124/*
1111 * Arguments are '\0' separated strings found at the location bprm->p 1125 * Arguments are '\0' separated strings found at the location bprm->p
1112 * points to; chop off the first by relocating brpm->p to right after 1126 * points to; chop off the first by relocating brpm->p to right after
@@ -1259,6 +1273,8 @@ EXPORT_SYMBOL(search_binary_handler);
1259void free_bprm(struct linux_binprm *bprm) 1273void free_bprm(struct linux_binprm *bprm)
1260{ 1274{
1261 free_arg_pages(bprm); 1275 free_arg_pages(bprm);
1276 if (bprm->cred)
1277 abort_creds(bprm->cred);
1262 kfree(bprm); 1278 kfree(bprm);
1263} 1279}
1264 1280
@@ -1284,10 +1300,20 @@ int do_execve(char * filename,
1284 if (!bprm) 1300 if (!bprm)
1285 goto out_files; 1301 goto out_files;
1286 1302
1303 retval = mutex_lock_interruptible(&current->cred_exec_mutex);
1304 if (retval < 0)
1305 goto out_free;
1306
1307 retval = -ENOMEM;
1308 bprm->cred = prepare_exec_creds();
1309 if (!bprm->cred)
1310 goto out_unlock;
1311 check_unsafe_exec(bprm);
1312
1287 file = open_exec(filename); 1313 file = open_exec(filename);
1288 retval = PTR_ERR(file); 1314 retval = PTR_ERR(file);
1289 if (IS_ERR(file)) 1315 if (IS_ERR(file))
1290 goto out_kfree; 1316 goto out_unlock;
1291 1317
1292 sched_exec(); 1318 sched_exec();
1293 1319
@@ -1301,14 +1327,10 @@ int do_execve(char * filename,
1301 1327
1302 bprm->argc = count(argv, MAX_ARG_STRINGS); 1328 bprm->argc = count(argv, MAX_ARG_STRINGS);
1303 if ((retval = bprm->argc) < 0) 1329 if ((retval = bprm->argc) < 0)
1304 goto out_mm; 1330 goto out;
1305 1331
1306 bprm->envc = count(envp, MAX_ARG_STRINGS); 1332 bprm->envc = count(envp, MAX_ARG_STRINGS);
1307 if ((retval = bprm->envc) < 0) 1333 if ((retval = bprm->envc) < 0)
1308 goto out_mm;
1309
1310 retval = security_bprm_alloc(bprm);
1311 if (retval)
1312 goto out; 1334 goto out;
1313 1335
1314 retval = prepare_binprm(bprm); 1336 retval = prepare_binprm(bprm);
@@ -1330,21 +1352,18 @@ int do_execve(char * filename,
1330 1352
1331 current->flags &= ~PF_KTHREAD; 1353 current->flags &= ~PF_KTHREAD;
1332 retval = search_binary_handler(bprm,regs); 1354 retval = search_binary_handler(bprm,regs);
1333 if (retval >= 0) { 1355 if (retval < 0)
1334 /* execve success */ 1356 goto out;
1335 security_bprm_free(bprm);
1336 acct_update_integrals(current);
1337 free_bprm(bprm);
1338 if (displaced)
1339 put_files_struct(displaced);
1340 return retval;
1341 }
1342 1357
1343out: 1358 /* execve succeeded */
1344 if (bprm->security) 1359 mutex_unlock(&current->cred_exec_mutex);
1345 security_bprm_free(bprm); 1360 acct_update_integrals(current);
1361 free_bprm(bprm);
1362 if (displaced)
1363 put_files_struct(displaced);
1364 return retval;
1346 1365
1347out_mm: 1366out:
1348 if (bprm->mm) 1367 if (bprm->mm)
1349 mmput (bprm->mm); 1368 mmput (bprm->mm);
1350 1369
@@ -1353,7 +1372,11 @@ out_file:
1353 allow_write_access(bprm->file); 1372 allow_write_access(bprm->file);
1354 fput(bprm->file); 1373 fput(bprm->file);
1355 } 1374 }
1356out_kfree: 1375
1376out_unlock:
1377 mutex_unlock(&current->cred_exec_mutex);
1378
1379out_free:
1357 free_bprm(bprm); 1380 free_bprm(bprm);
1358 1381
1359out_files: 1382out_files:
diff --git a/fs/internal.h b/fs/internal.h
index 80aa9a023372..53af885f1732 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -10,6 +10,7 @@
10 */ 10 */
11 11
12struct super_block; 12struct super_block;
13struct linux_binprm;
13 14
14/* 15/*
15 * block_dev.c 16 * block_dev.c
@@ -40,6 +41,11 @@ static inline int sb_is_blkdev_sb(struct super_block *sb)
40extern void __init chrdev_init(void); 41extern void __init chrdev_init(void);
41 42
42/* 43/*
44 * exec.c
45 */
46extern void check_unsafe_exec(struct linux_binprm *);
47
48/*
43 * namespace.c 49 * namespace.c
44 */ 50 */
45extern int copy_mount_options(const void __user *, unsigned long *); 51extern int copy_mount_options(const void __user *, unsigned long *);