aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c183
1 files changed, 109 insertions, 74 deletions
diff --git a/fs/exec.c b/fs/exec.c
index d5165d899a49..911dd0fd7e09 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -56,6 +56,7 @@
56#include <asm/uaccess.h> 56#include <asm/uaccess.h>
57#include <asm/mmu_context.h> 57#include <asm/mmu_context.h>
58#include <asm/tlb.h> 58#include <asm/tlb.h>
59#include "internal.h"
59 60
60#ifdef __alpha__ 61#ifdef __alpha__
61/* for /sbin/loader handling in search_binary_handler() */ 62/* for /sbin/loader handling in search_binary_handler() */
@@ -981,7 +982,7 @@ int flush_old_exec(struct linux_binprm * bprm)
981 /* This is the point of no return */ 982 /* This is the point of no return */
982 current->sas_ss_sp = current->sas_ss_size = 0; 983 current->sas_ss_sp = current->sas_ss_size = 0;
983 984
984 if (current->euid == current->uid && current->egid == current->gid) 985 if (current_euid() == current_uid() && current_egid() == current_gid())
985 set_dumpable(current->mm, 1); 986 set_dumpable(current->mm, 1);
986 else 987 else
987 set_dumpable(current->mm, suid_dumpable); 988 set_dumpable(current->mm, suid_dumpable);
@@ -1008,16 +1009,17 @@ int flush_old_exec(struct linux_binprm * bprm)
1008 */ 1009 */
1009 current->mm->task_size = TASK_SIZE; 1010 current->mm->task_size = TASK_SIZE;
1010 1011
1011 if (bprm->e_uid != current->euid || bprm->e_gid != current->egid) { 1012 /* install the new credentials */
1012 suid_keys(current); 1013 if (bprm->cred->uid != current_euid() ||
1013 set_dumpable(current->mm, suid_dumpable); 1014 bprm->cred->gid != current_egid()) {
1014 current->pdeath_signal = 0; 1015 current->pdeath_signal = 0;
1015 } else if (file_permission(bprm->file, MAY_READ) || 1016 } else if (file_permission(bprm->file, MAY_READ) ||
1016 (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) { 1017 bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP) {
1017 suid_keys(current);
1018 set_dumpable(current->mm, suid_dumpable); 1018 set_dumpable(current->mm, suid_dumpable);
1019 } 1019 }
1020 1020
1021 current->personality &= ~bprm->per_clear;
1022
1021 /* 1023 /*
1022 * Flush performance counters when crossing a 1024 * Flush performance counters when crossing a
1023 * security domain: 1025 * security domain:
@@ -1041,13 +1043,50 @@ out:
1041 1043
1042EXPORT_SYMBOL(flush_old_exec); 1044EXPORT_SYMBOL(flush_old_exec);
1043 1045
1046/*
1047 * install the new credentials for this executable
1048 */
1049void install_exec_creds(struct linux_binprm *bprm)
1050{
1051 security_bprm_committing_creds(bprm);
1052
1053 commit_creds(bprm->cred);
1054 bprm->cred = NULL;
1055
1056 /* cred_exec_mutex must be held at least to this point to prevent
1057 * ptrace_attach() from altering our determination of the task's
1058 * credentials; any time after this it may be unlocked */
1059
1060 security_bprm_committed_creds(bprm);
1061}
1062EXPORT_SYMBOL(install_exec_creds);
1063
1064/*
1065 * determine how safe it is to execute the proposed program
1066 * - the caller must hold current->cred_exec_mutex to protect against
1067 * PTRACE_ATTACH
1068 */
1069void check_unsafe_exec(struct linux_binprm *bprm)
1070{
1071 struct task_struct *p = current;
1072
1073 bprm->unsafe = tracehook_unsafe_exec(p);
1074
1075 if (atomic_read(&p->fs->count) > 1 ||
1076 atomic_read(&p->files->count) > 1 ||
1077 atomic_read(&p->sighand->count) > 1)
1078 bprm->unsafe |= LSM_UNSAFE_SHARE;
1079}
1080
1044/* 1081/*
1045 * Fill the binprm structure from the inode. 1082 * Fill the binprm structure from the inode.
1046 * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes 1083 * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
1084 *
1085 * This may be called multiple times for binary chains (scripts for example).
1047 */ 1086 */
1048int prepare_binprm(struct linux_binprm *bprm) 1087int prepare_binprm(struct linux_binprm *bprm)
1049{ 1088{
1050 int mode; 1089 umode_t mode;
1051 struct inode * inode = bprm->file->f_path.dentry->d_inode; 1090 struct inode * inode = bprm->file->f_path.dentry->d_inode;
1052 int retval; 1091 int retval;
1053 1092
@@ -1055,14 +1094,15 @@ int prepare_binprm(struct linux_binprm *bprm)
1055 if (bprm->file->f_op == NULL) 1094 if (bprm->file->f_op == NULL)
1056 return -EACCES; 1095 return -EACCES;
1057 1096
1058 bprm->e_uid = current->euid; 1097 /* clear any previous set[ug]id data from a previous binary */
1059 bprm->e_gid = current->egid; 1098 bprm->cred->euid = current_euid();
1099 bprm->cred->egid = current_egid();
1060 1100
1061 if(!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) { 1101 if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
1062 /* Set-uid? */ 1102 /* Set-uid? */
1063 if (mode & S_ISUID) { 1103 if (mode & S_ISUID) {
1064 current->personality &= ~PER_CLEAR_ON_SETID; 1104 bprm->per_clear |= PER_CLEAR_ON_SETID;
1065 bprm->e_uid = inode->i_uid; 1105 bprm->cred->euid = inode->i_uid;
1066 } 1106 }
1067 1107
1068 /* Set-gid? */ 1108 /* Set-gid? */
@@ -1072,52 +1112,23 @@ int prepare_binprm(struct linux_binprm *bprm)
1072 * executable. 1112 * executable.
1073 */ 1113 */
1074 if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { 1114 if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
1075 current->personality &= ~PER_CLEAR_ON_SETID; 1115 bprm->per_clear |= PER_CLEAR_ON_SETID;
1076 bprm->e_gid = inode->i_gid; 1116 bprm->cred->egid = inode->i_gid;
1077 } 1117 }
1078 } 1118 }
1079 1119
1080 /* fill in binprm security blob */ 1120 /* fill in binprm security blob */
1081 retval = security_bprm_set(bprm); 1121 retval = security_bprm_set_creds(bprm);
1082 if (retval) 1122 if (retval)
1083 return retval; 1123 return retval;
1124 bprm->cred_prepared = 1;
1084 1125
1085 memset(bprm->buf,0,BINPRM_BUF_SIZE); 1126 memset(bprm->buf, 0, BINPRM_BUF_SIZE);
1086 return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE); 1127 return kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE);
1087} 1128}
1088 1129
1089EXPORT_SYMBOL(prepare_binprm); 1130EXPORT_SYMBOL(prepare_binprm);
1090 1131
1091static int unsafe_exec(struct task_struct *p)
1092{
1093 int unsafe = tracehook_unsafe_exec(p);
1094
1095 if (atomic_read(&p->fs->count) > 1 ||
1096 atomic_read(&p->files->count) > 1 ||
1097 atomic_read(&p->sighand->count) > 1)
1098 unsafe |= LSM_UNSAFE_SHARE;
1099
1100 return unsafe;
1101}
1102
1103void compute_creds(struct linux_binprm *bprm)
1104{
1105 int unsafe;
1106
1107 if (bprm->e_uid != current->uid) {
1108 suid_keys(current);
1109 current->pdeath_signal = 0;
1110 }
1111 exec_keys(current);
1112
1113 task_lock(current);
1114 unsafe = unsafe_exec(current);
1115 security_bprm_apply_creds(bprm, unsafe);
1116 task_unlock(current);
1117 security_bprm_post_apply_creds(bprm);
1118}
1119EXPORT_SYMBOL(compute_creds);
1120
1121/* 1132/*
1122 * Arguments are '\0' separated strings found at the location bprm->p 1133 * Arguments are '\0' separated strings found at the location bprm->p
1123 * points to; chop off the first by relocating brpm->p to right after 1134 * points to; chop off the first by relocating brpm->p to right after
@@ -1278,6 +1289,8 @@ EXPORT_SYMBOL(search_binary_handler);
1278void free_bprm(struct linux_binprm *bprm) 1289void free_bprm(struct linux_binprm *bprm)
1279{ 1290{
1280 free_arg_pages(bprm); 1291 free_arg_pages(bprm);
1292 if (bprm->cred)
1293 abort_creds(bprm->cred);
1281 kfree(bprm); 1294 kfree(bprm);
1282} 1295}
1283 1296
@@ -1303,10 +1316,20 @@ int do_execve(char * filename,
1303 if (!bprm) 1316 if (!bprm)
1304 goto out_files; 1317 goto out_files;
1305 1318
1319 retval = mutex_lock_interruptible(&current->cred_exec_mutex);
1320 if (retval < 0)
1321 goto out_free;
1322
1323 retval = -ENOMEM;
1324 bprm->cred = prepare_exec_creds();
1325 if (!bprm->cred)
1326 goto out_unlock;
1327 check_unsafe_exec(bprm);
1328
1306 file = open_exec(filename); 1329 file = open_exec(filename);
1307 retval = PTR_ERR(file); 1330 retval = PTR_ERR(file);
1308 if (IS_ERR(file)) 1331 if (IS_ERR(file))
1309 goto out_kfree; 1332 goto out_unlock;
1310 1333
1311 sched_exec(); 1334 sched_exec();
1312 1335
@@ -1320,14 +1343,10 @@ int do_execve(char * filename,
1320 1343
1321 bprm->argc = count(argv, MAX_ARG_STRINGS); 1344 bprm->argc = count(argv, MAX_ARG_STRINGS);
1322 if ((retval = bprm->argc) < 0) 1345 if ((retval = bprm->argc) < 0)
1323 goto out_mm; 1346 goto out;
1324 1347
1325 bprm->envc = count(envp, MAX_ARG_STRINGS); 1348 bprm->envc = count(envp, MAX_ARG_STRINGS);
1326 if ((retval = bprm->envc) < 0) 1349 if ((retval = bprm->envc) < 0)
1327 goto out_mm;
1328
1329 retval = security_bprm_alloc(bprm);
1330 if (retval)
1331 goto out; 1350 goto out;
1332 1351
1333 retval = prepare_binprm(bprm); 1352 retval = prepare_binprm(bprm);
@@ -1349,21 +1368,18 @@ int do_execve(char * filename,
1349 1368
1350 current->flags &= ~PF_KTHREAD; 1369 current->flags &= ~PF_KTHREAD;
1351 retval = search_binary_handler(bprm,regs); 1370 retval = search_binary_handler(bprm,regs);
1352 if (retval >= 0) { 1371 if (retval < 0)
1353 /* execve success */ 1372 goto out;
1354 security_bprm_free(bprm);
1355 acct_update_integrals(current);
1356 free_bprm(bprm);
1357 if (displaced)
1358 put_files_struct(displaced);
1359 return retval;
1360 }
1361 1373
1362out: 1374 /* execve succeeded */
1363 if (bprm->security) 1375 mutex_unlock(&current->cred_exec_mutex);
1364 security_bprm_free(bprm); 1376 acct_update_integrals(current);
1377 free_bprm(bprm);
1378 if (displaced)
1379 put_files_struct(displaced);
1380 return retval;
1365 1381
1366out_mm: 1382out:
1367 if (bprm->mm) 1383 if (bprm->mm)
1368 mmput (bprm->mm); 1384 mmput (bprm->mm);
1369 1385
@@ -1372,7 +1388,11 @@ out_file:
1372 allow_write_access(bprm->file); 1388 allow_write_access(bprm->file);
1373 fput(bprm->file); 1389 fput(bprm->file);
1374 } 1390 }
1375out_kfree: 1391
1392out_unlock:
1393 mutex_unlock(&current->cred_exec_mutex);
1394
1395out_free:
1376 free_bprm(bprm); 1396 free_bprm(bprm);
1377 1397
1378out_files: 1398out_files:
@@ -1404,6 +1424,7 @@ EXPORT_SYMBOL(set_binfmt);
1404 */ 1424 */
1405static int format_corename(char *corename, long signr) 1425static int format_corename(char *corename, long signr)
1406{ 1426{
1427 const struct cred *cred = current_cred();
1407 const char *pat_ptr = core_pattern; 1428 const char *pat_ptr = core_pattern;
1408 int ispipe = (*pat_ptr == '|'); 1429 int ispipe = (*pat_ptr == '|');
1409 char *out_ptr = corename; 1430 char *out_ptr = corename;
@@ -1440,7 +1461,7 @@ static int format_corename(char *corename, long signr)
1440 /* uid */ 1461 /* uid */
1441 case 'u': 1462 case 'u':
1442 rc = snprintf(out_ptr, out_end - out_ptr, 1463 rc = snprintf(out_ptr, out_end - out_ptr,
1443 "%d", current->uid); 1464 "%d", cred->uid);
1444 if (rc > out_end - out_ptr) 1465 if (rc > out_end - out_ptr)
1445 goto out; 1466 goto out;
1446 out_ptr += rc; 1467 out_ptr += rc;
@@ -1448,7 +1469,7 @@ static int format_corename(char *corename, long signr)
1448 /* gid */ 1469 /* gid */
1449 case 'g': 1470 case 'g':
1450 rc = snprintf(out_ptr, out_end - out_ptr, 1471 rc = snprintf(out_ptr, out_end - out_ptr,
1451 "%d", current->gid); 1472 "%d", cred->gid);
1452 if (rc > out_end - out_ptr) 1473 if (rc > out_end - out_ptr)
1453 goto out; 1474 goto out;
1454 out_ptr += rc; 1475 out_ptr += rc;
@@ -1724,8 +1745,9 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
1724 struct linux_binfmt * binfmt; 1745 struct linux_binfmt * binfmt;
1725 struct inode * inode; 1746 struct inode * inode;
1726 struct file * file; 1747 struct file * file;
1748 const struct cred *old_cred;
1749 struct cred *cred;
1727 int retval = 0; 1750 int retval = 0;
1728 int fsuid = current->fsuid;
1729 int flag = 0; 1751 int flag = 0;
1730 int ispipe = 0; 1752 int ispipe = 0;
1731 unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; 1753 unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
@@ -1738,12 +1760,20 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
1738 binfmt = current->binfmt; 1760 binfmt = current->binfmt;
1739 if (!binfmt || !binfmt->core_dump) 1761 if (!binfmt || !binfmt->core_dump)
1740 goto fail; 1762 goto fail;
1763
1764 cred = prepare_creds();
1765 if (!cred) {
1766 retval = -ENOMEM;
1767 goto fail;
1768 }
1769
1741 down_write(&mm->mmap_sem); 1770 down_write(&mm->mmap_sem);
1742 /* 1771 /*
1743 * If another thread got here first, or we are not dumpable, bail out. 1772 * If another thread got here first, or we are not dumpable, bail out.
1744 */ 1773 */
1745 if (mm->core_state || !get_dumpable(mm)) { 1774 if (mm->core_state || !get_dumpable(mm)) {
1746 up_write(&mm->mmap_sem); 1775 up_write(&mm->mmap_sem);
1776 put_cred(cred);
1747 goto fail; 1777 goto fail;
1748 } 1778 }
1749 1779
@@ -1754,12 +1784,16 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
1754 */ 1784 */
1755 if (get_dumpable(mm) == 2) { /* Setuid core dump mode */ 1785 if (get_dumpable(mm) == 2) { /* Setuid core dump mode */
1756 flag = O_EXCL; /* Stop rewrite attacks */ 1786 flag = O_EXCL; /* Stop rewrite attacks */
1757 current->fsuid = 0; /* Dump root private */ 1787 cred->fsuid = 0; /* Dump root private */
1758 } 1788 }
1759 1789
1760 retval = coredump_wait(exit_code, &core_state); 1790 retval = coredump_wait(exit_code, &core_state);
1761 if (retval < 0) 1791 if (retval < 0) {
1792 put_cred(cred);
1762 goto fail; 1793 goto fail;
1794 }
1795
1796 old_cred = override_creds(cred);
1763 1797
1764 /* 1798 /*
1765 * Clear any false indication of pending signals that might 1799 * Clear any false indication of pending signals that might
@@ -1831,7 +1865,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
1831 * Dont allow local users get cute and trick others to coredump 1865 * Dont allow local users get cute and trick others to coredump
1832 * into their pre-created files: 1866 * into their pre-created files:
1833 */ 1867 */
1834 if (inode->i_uid != current->fsuid) 1868 if (inode->i_uid != current_fsuid())
1835 goto close_fail; 1869 goto close_fail;
1836 if (!file->f_op) 1870 if (!file->f_op)
1837 goto close_fail; 1871 goto close_fail;
@@ -1850,7 +1884,8 @@ fail_unlock:
1850 if (helper_argv) 1884 if (helper_argv)
1851 argv_free(helper_argv); 1885 argv_free(helper_argv);
1852 1886
1853 current->fsuid = fsuid; 1887 revert_creds(old_cred);
1888 put_cred(cred);
1854 coredump_finish(mm); 1889 coredump_finish(mm);
1855fail: 1890fail:
1856 return retval; 1891 return retval;