mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
sched: move no_new_privs into new atomic flags
Since seccomp transitions between threads requires updates to the no_new_privs flag to be atomic, the flag must be part of an atomic flag set. This moves the nnp flag into a separate task field, and introduces accessors. Signed-off-by: Kees Cook <keescook@chromium.org> Reviewed-by: Oleg Nesterov <oleg@redhat.com> Reviewed-by: Andy Lutomirski <luto@amacapital.net> Conflicts: fs/exec.c include/linux/sched.h kernel/sys.c
This commit is contained in:
parent
61d45b4a98
commit
0901f9aec4
5 changed files with 22 additions and 10 deletions
|
@ -1249,7 +1249,7 @@ static int check_unsafe_exec(struct linux_binprm *bprm)
|
|||
* This isn't strictly necessary, but it makes it harder for LSMs to
|
||||
* mess up.
|
||||
*/
|
||||
if (current->no_new_privs)
|
||||
if (task_no_new_privs(current))
|
||||
bprm->unsafe |= LSM_UNSAFE_NO_NEW_PRIVS;
|
||||
|
||||
n_fs = 1;
|
||||
|
@ -1296,7 +1296,7 @@ int prepare_binprm(struct linux_binprm *bprm)
|
|||
bprm->cred->egid = current_egid();
|
||||
|
||||
if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) &&
|
||||
!current->no_new_privs) {
|
||||
!task_no_new_privs(current)) {
|
||||
/* Set-uid? */
|
||||
if (mode & S_ISUID) {
|
||||
bprm->per_clear |= PER_CLEAR_ON_SETID;
|
||||
|
|
|
@ -1343,9 +1343,6 @@ struct task_struct {
|
|||
* execve */
|
||||
unsigned in_iowait:1;
|
||||
|
||||
/* task may not gain privileges */
|
||||
unsigned no_new_privs:1;
|
||||
|
||||
/* Revert to default priority/policy when forking */
|
||||
unsigned sched_reset_on_fork:1;
|
||||
unsigned sched_contributes_to_load:1;
|
||||
|
@ -1355,6 +1352,8 @@ struct task_struct {
|
|||
unsigned irq_thread:1;
|
||||
#endif
|
||||
|
||||
unsigned long atomic_flags; /* Flags needing atomic access. */
|
||||
|
||||
pid_t pid;
|
||||
pid_t tgid;
|
||||
|
||||
|
@ -1864,6 +1863,19 @@ extern int task_free_unregister(struct notifier_block *n);
|
|||
#define tsk_used_math(p) ((p)->flags & PF_USED_MATH)
|
||||
#define used_math() tsk_used_math(current)
|
||||
|
||||
/* Per-process atomic flags. */
|
||||
#define PFA_NO_NEW_PRIVS 0x00000001 /* May not gain new privileges. */
|
||||
|
||||
static inline bool task_no_new_privs(struct task_struct *p)
|
||||
{
|
||||
return test_bit(PFA_NO_NEW_PRIVS, &p->atomic_flags);
|
||||
}
|
||||
|
||||
static inline void task_set_no_new_privs(struct task_struct *p)
|
||||
{
|
||||
set_bit(PFA_NO_NEW_PRIVS, &p->atomic_flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* task->jobctl flags
|
||||
*/
|
||||
|
|
|
@ -262,7 +262,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog)
|
|||
* This avoids scenarios where unprivileged tasks can affect the
|
||||
* behavior of privileged children.
|
||||
*/
|
||||
if (!current->no_new_privs &&
|
||||
if (!task_no_new_privs(current) &&
|
||||
security_capable_noaudit(current_cred(), current_user_ns(),
|
||||
CAP_SYS_ADMIN) != 0)
|
||||
return -EACCES;
|
||||
|
|
|
@ -2152,12 +2152,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
|
|||
if (arg2 != 1 || arg3 || arg4 || arg5)
|
||||
return -EINVAL;
|
||||
|
||||
current->no_new_privs = 1;
|
||||
task_set_no_new_privs(current);
|
||||
break;
|
||||
case PR_GET_NO_NEW_PRIVS:
|
||||
if (arg2 || arg3 || arg4 || arg5)
|
||||
return -EINVAL;
|
||||
return current->no_new_privs ? 1 : 0;
|
||||
return task_no_new_privs(current) ? 1 : 0;
|
||||
default:
|
||||
error = -EINVAL;
|
||||
break;
|
||||
|
|
|
@ -629,7 +629,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
|
|||
* There is no exception for unconfined as change_hat is not
|
||||
* available.
|
||||
*/
|
||||
if (current->no_new_privs)
|
||||
if (task_no_new_privs(current))
|
||||
return -EPERM;
|
||||
|
||||
/* released below */
|
||||
|
@ -780,7 +780,7 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
|
|||
* no_new_privs is set because this aways results in a reduction
|
||||
* of permissions.
|
||||
*/
|
||||
if (current->no_new_privs && !unconfined(profile)) {
|
||||
if (task_no_new_privs(current) && !unconfined(profile)) {
|
||||
put_cred(cred);
|
||||
return -EPERM;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue