aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c40
1 files changed, 33 insertions, 7 deletions
diff --git a/fs/exec.c b/fs/exec.c
index b1fd2025e59a..52c9e2ff6e6b 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1139,7 +1139,7 @@ void setup_new_exec(struct linux_binprm * bprm)
1139 /* This is the point of no return */ 1139 /* This is the point of no return */
1140 current->sas_ss_sp = current->sas_ss_size = 0; 1140 current->sas_ss_sp = current->sas_ss_size = 0;
1141 1141
1142 if (current_euid() == current_uid() && current_egid() == current_gid()) 1142 if (uid_eq(current_euid(), current_uid()) && gid_eq(current_egid(), current_gid()))
1143 set_dumpable(current->mm, 1); 1143 set_dumpable(current->mm, 1);
1144 else 1144 else
1145 set_dumpable(current->mm, suid_dumpable); 1145 set_dumpable(current->mm, suid_dumpable);
@@ -1153,8 +1153,8 @@ void setup_new_exec(struct linux_binprm * bprm)
1153 current->mm->task_size = TASK_SIZE; 1153 current->mm->task_size = TASK_SIZE;
1154 1154
1155 /* install the new credentials */ 1155 /* install the new credentials */
1156 if (bprm->cred->uid != current_euid() || 1156 if (!uid_eq(bprm->cred->uid, current_euid()) ||
1157 bprm->cred->gid != current_egid()) { 1157 !gid_eq(bprm->cred->gid, current_egid())) {
1158 current->pdeath_signal = 0; 1158 current->pdeath_signal = 0;
1159 } else { 1159 } else {
1160 would_dump(bprm, bprm->file); 1160 would_dump(bprm, bprm->file);
@@ -1245,6 +1245,13 @@ static int check_unsafe_exec(struct linux_binprm *bprm)
1245 bprm->unsafe |= LSM_UNSAFE_PTRACE; 1245 bprm->unsafe |= LSM_UNSAFE_PTRACE;
1246 } 1246 }
1247 1247
1248 /*
1249 * This isn't strictly necessary, but it makes it harder for LSMs to
1250 * mess up.
1251 */
1252 if (current->no_new_privs)
1253 bprm->unsafe |= LSM_UNSAFE_NO_NEW_PRIVS;
1254
1248 n_fs = 1; 1255 n_fs = 1;
1249 spin_lock(&p->fs->lock); 1256 spin_lock(&p->fs->lock);
1250 rcu_read_lock(); 1257 rcu_read_lock();
@@ -1288,11 +1295,15 @@ int prepare_binprm(struct linux_binprm *bprm)
1288 bprm->cred->euid = current_euid(); 1295 bprm->cred->euid = current_euid();
1289 bprm->cred->egid = current_egid(); 1296 bprm->cred->egid = current_egid();
1290 1297
1291 if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) { 1298 if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) &&
1299 !current->no_new_privs) {
1292 /* Set-uid? */ 1300 /* Set-uid? */
1293 if (mode & S_ISUID) { 1301 if (mode & S_ISUID) {
1302 if (!kuid_has_mapping(bprm->cred->user_ns, inode->i_uid))
1303 return -EPERM;
1294 bprm->per_clear |= PER_CLEAR_ON_SETID; 1304 bprm->per_clear |= PER_CLEAR_ON_SETID;
1295 bprm->cred->euid = inode->i_uid; 1305 bprm->cred->euid = inode->i_uid;
1306
1296 } 1307 }
1297 1308
1298 /* Set-gid? */ 1309 /* Set-gid? */
@@ -1302,6 +1313,8 @@ int prepare_binprm(struct linux_binprm *bprm)
1302 * executable. 1313 * executable.
1303 */ 1314 */
1304 if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { 1315 if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
1316 if (!kgid_has_mapping(bprm->cred->user_ns, inode->i_gid))
1317 return -EPERM;
1305 bprm->per_clear |= PER_CLEAR_ON_SETID; 1318 bprm->per_clear |= PER_CLEAR_ON_SETID;
1306 bprm->cred->egid = inode->i_gid; 1319 bprm->cred->egid = inode->i_gid;
1307 } 1320 }
@@ -1930,8 +1943,21 @@ static int coredump_wait(int exit_code, struct core_state *core_state)
1930 core_waiters = zap_threads(tsk, mm, core_state, exit_code); 1943 core_waiters = zap_threads(tsk, mm, core_state, exit_code);
1931 up_write(&mm->mmap_sem); 1944 up_write(&mm->mmap_sem);
1932 1945
1933 if (core_waiters > 0) 1946 if (core_waiters > 0) {
1947 struct core_thread *ptr;
1948
1934 wait_for_completion(&core_state->startup); 1949 wait_for_completion(&core_state->startup);
1950 /*
1951 * Wait for all the threads to become inactive, so that
1952 * all the thread context (extended register state, like
1953 * fpu etc) gets copied to the memory.
1954 */
1955 ptr = core_state->dumper.next;
1956 while (ptr != NULL) {
1957 wait_task_inactive(ptr->task, 0);
1958 ptr = ptr->next;
1959 }
1960 }
1935 1961
1936 return core_waiters; 1962 return core_waiters;
1937} 1963}
@@ -2121,7 +2147,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
2121 if (__get_dumpable(cprm.mm_flags) == 2) { 2147 if (__get_dumpable(cprm.mm_flags) == 2) {
2122 /* Setuid core dump mode */ 2148 /* Setuid core dump mode */
2123 flag = O_EXCL; /* Stop rewrite attacks */ 2149 flag = O_EXCL; /* Stop rewrite attacks */
2124 cred->fsuid = 0; /* Dump root private */ 2150 cred->fsuid = GLOBAL_ROOT_UID; /* Dump root private */
2125 } 2151 }
2126 2152
2127 retval = coredump_wait(exit_code, &core_state); 2153 retval = coredump_wait(exit_code, &core_state);
@@ -2222,7 +2248,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
2222 * Dont allow local users get cute and trick others to coredump 2248 * Dont allow local users get cute and trick others to coredump
2223 * into their pre-created files. 2249 * into their pre-created files.
2224 */ 2250 */
2225 if (inode->i_uid != current_fsuid()) 2251 if (!uid_eq(inode->i_uid, current_fsuid()))
2226 goto close_fail; 2252 goto close_fail;
2227 if (!cprm.file->f_op || !cprm.file->f_op->write) 2253 if (!cprm.file->f_op || !cprm.file->f_op->write)
2228 goto close_fail; 2254 goto close_fail;