aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/exec.c4
-rw-r--r--include/linux/sched.h18
-rw-r--r--kernel/seccomp.c2
-rw-r--r--kernel/sys.c4
-rw-r--r--security/apparmor/domain.c4
5 files changed, 22 insertions, 10 deletions
diff --git a/fs/exec.c b/fs/exec.c
index a3d33fe592d6..0f5c272410f6 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1234,7 +1234,7 @@ static void check_unsafe_exec(struct linux_binprm *bprm)
1234 * This isn't strictly necessary, but it makes it harder for LSMs to 1234 * This isn't strictly necessary, but it makes it harder for LSMs to
1235 * mess up. 1235 * mess up.
1236 */ 1236 */
1237 if (current->no_new_privs) 1237 if (task_no_new_privs(current))
1238 bprm->unsafe |= LSM_UNSAFE_NO_NEW_PRIVS; 1238 bprm->unsafe |= LSM_UNSAFE_NO_NEW_PRIVS;
1239 1239
1240 t = p; 1240 t = p;
@@ -1272,7 +1272,7 @@ int prepare_binprm(struct linux_binprm *bprm)
1272 bprm->cred->egid = current_egid(); 1272 bprm->cred->egid = current_egid();
1273 1273
1274 if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) && 1274 if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) &&
1275 !current->no_new_privs && 1275 !task_no_new_privs(current) &&
1276 kuid_has_mapping(bprm->cred->user_ns, inode->i_uid) && 1276 kuid_has_mapping(bprm->cred->user_ns, inode->i_uid) &&
1277 kgid_has_mapping(bprm->cred->user_ns, inode->i_gid)) { 1277 kgid_has_mapping(bprm->cred->user_ns, inode->i_gid)) {
1278 /* Set-uid? */ 1278 /* Set-uid? */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 306f4f0c987a..0fd19055bb64 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1307,13 +1307,12 @@ struct task_struct {
1307 * execve */ 1307 * execve */
1308 unsigned in_iowait:1; 1308 unsigned in_iowait:1;
1309 1309
1310 /* task may not gain privileges */
1311 unsigned no_new_privs:1;
1312
1313 /* Revert to default priority/policy when forking */ 1310 /* Revert to default priority/policy when forking */
1314 unsigned sched_reset_on_fork:1; 1311 unsigned sched_reset_on_fork:1;
1315 unsigned sched_contributes_to_load:1; 1312 unsigned sched_contributes_to_load:1;
1316 1313
1314 unsigned long atomic_flags; /* Flags needing atomic access. */
1315
1317 pid_t pid; 1316 pid_t pid;
1318 pid_t tgid; 1317 pid_t tgid;
1319 1318
@@ -1967,6 +1966,19 @@ static inline void memalloc_noio_restore(unsigned int flags)
1967 current->flags = (current->flags & ~PF_MEMALLOC_NOIO) | flags; 1966 current->flags = (current->flags & ~PF_MEMALLOC_NOIO) | flags;
1968} 1967}
1969 1968
1969/* Per-process atomic flags. */
1970#define PFA_NO_NEW_PRIVS 0x00000001 /* May not gain new privileges. */
1971
1972static inline bool task_no_new_privs(struct task_struct *p)
1973{
1974 return test_bit(PFA_NO_NEW_PRIVS, &p->atomic_flags);
1975}
1976
1977static inline void task_set_no_new_privs(struct task_struct *p)
1978{
1979 set_bit(PFA_NO_NEW_PRIVS, &p->atomic_flags);
1980}
1981
1970/* 1982/*
1971 * task->jobctl flags 1983 * task->jobctl flags
1972 */ 1984 */
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index f0652578af75..d2596136b0d1 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -241,7 +241,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog)
241 * This avoids scenarios where unprivileged tasks can affect the 241 * This avoids scenarios where unprivileged tasks can affect the
242 * behavior of privileged children. 242 * behavior of privileged children.
243 */ 243 */
244 if (!current->no_new_privs && 244 if (!task_no_new_privs(current) &&
245 security_capable_noaudit(current_cred(), current_user_ns(), 245 security_capable_noaudit(current_cred(), current_user_ns(),
246 CAP_SYS_ADMIN) != 0) 246 CAP_SYS_ADMIN) != 0)
247 return -EACCES; 247 return -EACCES;
diff --git a/kernel/sys.c b/kernel/sys.c
index 66a751ebf9d9..ce8129192a26 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1990,12 +1990,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
1990 if (arg2 != 1 || arg3 || arg4 || arg5) 1990 if (arg2 != 1 || arg3 || arg4 || arg5)
1991 return -EINVAL; 1991 return -EINVAL;
1992 1992
1993 current->no_new_privs = 1; 1993 task_set_no_new_privs(current);
1994 break; 1994 break;
1995 case PR_GET_NO_NEW_PRIVS: 1995 case PR_GET_NO_NEW_PRIVS:
1996 if (arg2 || arg3 || arg4 || arg5) 1996 if (arg2 || arg3 || arg4 || arg5)
1997 return -EINVAL; 1997 return -EINVAL;
1998 return current->no_new_privs ? 1 : 0; 1998 return task_no_new_privs(current) ? 1 : 0;
1999 case PR_GET_THP_DISABLE: 1999 case PR_GET_THP_DISABLE:
2000 if (arg2 || arg3 || arg4 || arg5) 2000 if (arg2 || arg3 || arg4 || arg5)
2001 return -EINVAL; 2001 return -EINVAL;
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 452567d3a08e..d97cba3e3849 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -621,7 +621,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
621 * There is no exception for unconfined as change_hat is not 621 * There is no exception for unconfined as change_hat is not
622 * available. 622 * available.
623 */ 623 */
624 if (current->no_new_privs) 624 if (task_no_new_privs(current))
625 return -EPERM; 625 return -EPERM;
626 626
627 /* released below */ 627 /* released below */
@@ -776,7 +776,7 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
776 * no_new_privs is set because this aways results in a reduction 776 * no_new_privs is set because this aways results in a reduction
777 * of permissions. 777 * of permissions.
778 */ 778 */
779 if (current->no_new_privs && !unconfined(profile)) { 779 if (task_no_new_privs(current) && !unconfined(profile)) {
780 put_cred(cred); 780 put_cred(cred);
781 return -EPERM; 781 return -EPERM;
782 } 782 }