diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/cred.c | 36 | ||||
| -rw-r--r-- | kernel/signal.c | 14 | ||||
| -rw-r--r-- | kernel/sys.c | 26 | ||||
| -rw-r--r-- | kernel/user_namespace.c | 4 |
4 files changed, 41 insertions, 39 deletions
diff --git a/kernel/cred.c b/kernel/cred.c index 7a0d8066988..eddc5e2e958 100644 --- a/kernel/cred.c +++ b/kernel/cred.c | |||
| @@ -49,6 +49,14 @@ struct cred init_cred = { | |||
| 49 | .subscribers = ATOMIC_INIT(2), | 49 | .subscribers = ATOMIC_INIT(2), |
| 50 | .magic = CRED_MAGIC, | 50 | .magic = CRED_MAGIC, |
| 51 | #endif | 51 | #endif |
| 52 | .uid = GLOBAL_ROOT_UID, | ||
| 53 | .gid = GLOBAL_ROOT_GID, | ||
| 54 | .suid = GLOBAL_ROOT_UID, | ||
| 55 | .sgid = GLOBAL_ROOT_GID, | ||
| 56 | .euid = GLOBAL_ROOT_UID, | ||
| 57 | .egid = GLOBAL_ROOT_GID, | ||
| 58 | .fsuid = GLOBAL_ROOT_UID, | ||
| 59 | .fsgid = GLOBAL_ROOT_GID, | ||
| 52 | .securebits = SECUREBITS_DEFAULT, | 60 | .securebits = SECUREBITS_DEFAULT, |
| 53 | .cap_inheritable = CAP_EMPTY_SET, | 61 | .cap_inheritable = CAP_EMPTY_SET, |
| 54 | .cap_permitted = CAP_FULL_SET, | 62 | .cap_permitted = CAP_FULL_SET, |
| @@ -488,10 +496,10 @@ int commit_creds(struct cred *new) | |||
| 488 | get_cred(new); /* we will require a ref for the subj creds too */ | 496 | get_cred(new); /* we will require a ref for the subj creds too */ |
| 489 | 497 | ||
| 490 | /* dumpability changes */ | 498 | /* dumpability changes */ |
| 491 | if (old->euid != new->euid || | 499 | if (!uid_eq(old->euid, new->euid) || |
| 492 | old->egid != new->egid || | 500 | !gid_eq(old->egid, new->egid) || |
| 493 | old->fsuid != new->fsuid || | 501 | !uid_eq(old->fsuid, new->fsuid) || |
| 494 | old->fsgid != new->fsgid || | 502 | !gid_eq(old->fsgid, new->fsgid) || |
| 495 | !cap_issubset(new->cap_permitted, old->cap_permitted)) { | 503 | !cap_issubset(new->cap_permitted, old->cap_permitted)) { |
| 496 | if (task->mm) | 504 | if (task->mm) |
| 497 | set_dumpable(task->mm, suid_dumpable); | 505 | set_dumpable(task->mm, suid_dumpable); |
| @@ -500,9 +508,9 @@ int commit_creds(struct cred *new) | |||
| 500 | } | 508 | } |
| 501 | 509 | ||
| 502 | /* alter the thread keyring */ | 510 | /* alter the thread keyring */ |
| 503 | if (new->fsuid != old->fsuid) | 511 | if (!uid_eq(new->fsuid, old->fsuid)) |
| 504 | key_fsuid_changed(task); | 512 | key_fsuid_changed(task); |
| 505 | if (new->fsgid != old->fsgid) | 513 | if (!gid_eq(new->fsgid, old->fsgid)) |
| 506 | key_fsgid_changed(task); | 514 | key_fsgid_changed(task); |
| 507 | 515 | ||
| 508 | /* do it | 516 | /* do it |
| @@ -519,16 +527,16 @@ int commit_creds(struct cred *new) | |||
| 519 | alter_cred_subscribers(old, -2); | 527 | alter_cred_subscribers(old, -2); |
| 520 | 528 | ||
| 521 | /* send notifications */ | 529 | /* send notifications */ |
| 522 | if (new->uid != old->uid || | 530 | if (!uid_eq(new->uid, old->uid) || |
| 523 | new->euid != old->euid || | 531 | !uid_eq(new->euid, old->euid) || |
| 524 | new->suid != old->suid || | 532 | !uid_eq(new->suid, old->suid) || |
| 525 | new->fsuid != old->fsuid) | 533 | !uid_eq(new->fsuid, old->fsuid)) |
| 526 | proc_id_connector(task, PROC_EVENT_UID); | 534 | proc_id_connector(task, PROC_EVENT_UID); |
| 527 | 535 | ||
| 528 | if (new->gid != old->gid || | 536 | if (!gid_eq(new->gid, old->gid) || |
| 529 | new->egid != old->egid || | 537 | !gid_eq(new->egid, old->egid) || |
| 530 | new->sgid != old->sgid || | 538 | !gid_eq(new->sgid, old->sgid) || |
| 531 | new->fsgid != old->fsgid) | 539 | !gid_eq(new->fsgid, old->fsgid)) |
| 532 | proc_id_connector(task, PROC_EVENT_GID); | 540 | proc_id_connector(task, PROC_EVENT_GID); |
| 533 | 541 | ||
| 534 | /* release the old obj and subj refs both */ | 542 | /* release the old obj and subj refs both */ |
diff --git a/kernel/signal.c b/kernel/signal.c index e2c5d84f2da..2734dc965f6 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
| @@ -1038,8 +1038,10 @@ static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_str | |||
| 1038 | if (SI_FROMKERNEL(info)) | 1038 | if (SI_FROMKERNEL(info)) |
| 1039 | return; | 1039 | return; |
| 1040 | 1040 | ||
| 1041 | info->si_uid = user_ns_map_uid(task_cred_xxx(t, user_ns), | 1041 | rcu_read_lock(); |
| 1042 | current_cred(), info->si_uid); | 1042 | info->si_uid = from_kuid_munged(task_cred_xxx(t, user_ns), |
| 1043 | make_kuid(current_user_ns(), info->si_uid)); | ||
| 1044 | rcu_read_unlock(); | ||
| 1043 | } | 1045 | } |
| 1044 | #else | 1046 | #else |
| 1045 | static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) | 1047 | static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) |
| @@ -1106,7 +1108,7 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
| 1106 | q->info.si_code = SI_USER; | 1108 | q->info.si_code = SI_USER; |
| 1107 | q->info.si_pid = task_tgid_nr_ns(current, | 1109 | q->info.si_pid = task_tgid_nr_ns(current, |
| 1108 | task_active_pid_ns(t)); | 1110 | task_active_pid_ns(t)); |
| 1109 | q->info.si_uid = current_uid(); | 1111 | q->info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); |
| 1110 | break; | 1112 | break; |
| 1111 | case (unsigned long) SEND_SIG_PRIV: | 1113 | case (unsigned long) SEND_SIG_PRIV: |
| 1112 | q->info.si_signo = sig; | 1114 | q->info.si_signo = sig; |
| @@ -1973,7 +1975,7 @@ static void ptrace_do_notify(int signr, int exit_code, int why) | |||
| 1973 | info.si_signo = signr; | 1975 | info.si_signo = signr; |
| 1974 | info.si_code = exit_code; | 1976 | info.si_code = exit_code; |
| 1975 | info.si_pid = task_pid_vnr(current); | 1977 | info.si_pid = task_pid_vnr(current); |
| 1976 | info.si_uid = current_uid(); | 1978 | info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); |
| 1977 | 1979 | ||
| 1978 | /* Let the debugger run. */ | 1980 | /* Let the debugger run. */ |
| 1979 | ptrace_stop(exit_code, why, 1, &info); | 1981 | ptrace_stop(exit_code, why, 1, &info); |
| @@ -2828,7 +2830,7 @@ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig) | |||
| 2828 | info.si_errno = 0; | 2830 | info.si_errno = 0; |
| 2829 | info.si_code = SI_USER; | 2831 | info.si_code = SI_USER; |
| 2830 | info.si_pid = task_tgid_vnr(current); | 2832 | info.si_pid = task_tgid_vnr(current); |
| 2831 | info.si_uid = current_uid(); | 2833 | info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); |
| 2832 | 2834 | ||
| 2833 | return kill_something_info(sig, &info, pid); | 2835 | return kill_something_info(sig, &info, pid); |
| 2834 | } | 2836 | } |
| @@ -2871,7 +2873,7 @@ static int do_tkill(pid_t tgid, pid_t pid, int sig) | |||
| 2871 | info.si_errno = 0; | 2873 | info.si_errno = 0; |
| 2872 | info.si_code = SI_TKILL; | 2874 | info.si_code = SI_TKILL; |
| 2873 | info.si_pid = task_tgid_vnr(current); | 2875 | info.si_pid = task_tgid_vnr(current); |
| 2874 | info.si_uid = current_uid(); | 2876 | info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); |
| 2875 | 2877 | ||
| 2876 | return do_send_specific(tgid, pid, sig, &info); | 2878 | return do_send_specific(tgid, pid, sig, &info); |
| 2877 | } | 2879 | } |
diff --git a/kernel/sys.c b/kernel/sys.c index f0c43b4b665..39962818c00 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
| @@ -175,7 +175,6 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval) | |||
| 175 | const struct cred *cred = current_cred(); | 175 | const struct cred *cred = current_cred(); |
| 176 | int error = -EINVAL; | 176 | int error = -EINVAL; |
| 177 | struct pid *pgrp; | 177 | struct pid *pgrp; |
| 178 | kuid_t cred_uid; | ||
| 179 | kuid_t uid; | 178 | kuid_t uid; |
| 180 | 179 | ||
| 181 | if (which > PRIO_USER || which < PRIO_PROCESS) | 180 | if (which > PRIO_USER || which < PRIO_PROCESS) |
| @@ -209,22 +208,19 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval) | |||
| 209 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); | 208 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); |
| 210 | break; | 209 | break; |
| 211 | case PRIO_USER: | 210 | case PRIO_USER: |
| 212 | cred_uid = make_kuid(cred->user_ns, cred->uid); | ||
| 213 | uid = make_kuid(cred->user_ns, who); | 211 | uid = make_kuid(cred->user_ns, who); |
| 214 | user = cred->user; | 212 | user = cred->user; |
| 215 | if (!who) | 213 | if (!who) |
| 216 | uid = cred_uid; | 214 | uid = cred->uid; |
| 217 | else if (!uid_eq(uid, cred_uid) && | 215 | else if (!uid_eq(uid, cred->uid) && |
| 218 | !(user = find_user(uid))) | 216 | !(user = find_user(uid))) |
| 219 | goto out_unlock; /* No processes for this user */ | 217 | goto out_unlock; /* No processes for this user */ |
| 220 | 218 | ||
| 221 | do_each_thread(g, p) { | 219 | do_each_thread(g, p) { |
| 222 | const struct cred *tcred = __task_cred(p); | 220 | if (uid_eq(task_uid(p), uid)) |
| 223 | kuid_t tcred_uid = make_kuid(tcred->user_ns, tcred->uid); | ||
| 224 | if (uid_eq(tcred_uid, uid)) | ||
| 225 | error = set_one_prio(p, niceval, error); | 221 | error = set_one_prio(p, niceval, error); |
| 226 | } while_each_thread(g, p); | 222 | } while_each_thread(g, p); |
| 227 | if (!uid_eq(uid, cred_uid)) | 223 | if (!uid_eq(uid, cred->uid)) |
| 228 | free_uid(user); /* For find_user() */ | 224 | free_uid(user); /* For find_user() */ |
| 229 | break; | 225 | break; |
| 230 | } | 226 | } |
| @@ -248,7 +244,6 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who) | |||
| 248 | const struct cred *cred = current_cred(); | 244 | const struct cred *cred = current_cred(); |
| 249 | long niceval, retval = -ESRCH; | 245 | long niceval, retval = -ESRCH; |
| 250 | struct pid *pgrp; | 246 | struct pid *pgrp; |
| 251 | kuid_t cred_uid; | ||
| 252 | kuid_t uid; | 247 | kuid_t uid; |
| 253 | 248 | ||
| 254 | if (which > PRIO_USER || which < PRIO_PROCESS) | 249 | if (which > PRIO_USER || which < PRIO_PROCESS) |
| @@ -280,25 +275,22 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who) | |||
| 280 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); | 275 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); |
| 281 | break; | 276 | break; |
| 282 | case PRIO_USER: | 277 | case PRIO_USER: |
| 283 | cred_uid = make_kuid(cred->user_ns, cred->uid); | ||
| 284 | uid = make_kuid(cred->user_ns, who); | 278 | uid = make_kuid(cred->user_ns, who); |
| 285 | user = cred->user; | 279 | user = cred->user; |
| 286 | if (!who) | 280 | if (!who) |
| 287 | uid = cred_uid; | 281 | uid = cred->uid; |
| 288 | else if (!uid_eq(uid, cred_uid) && | 282 | else if (!uid_eq(uid, cred->uid) && |
| 289 | !(user = find_user(uid))) | 283 | !(user = find_user(uid))) |
| 290 | goto out_unlock; /* No processes for this user */ | 284 | goto out_unlock; /* No processes for this user */ |
| 291 | 285 | ||
| 292 | do_each_thread(g, p) { | 286 | do_each_thread(g, p) { |
| 293 | const struct cred *tcred = __task_cred(p); | 287 | if (uid_eq(task_uid(p), uid)) { |
| 294 | kuid_t tcred_uid = make_kuid(tcred->user_ns, tcred->uid); | ||
| 295 | if (uid_eq(tcred_uid, uid)) { | ||
| 296 | niceval = 20 - task_nice(p); | 288 | niceval = 20 - task_nice(p); |
| 297 | if (niceval > retval) | 289 | if (niceval > retval) |
| 298 | retval = niceval; | 290 | retval = niceval; |
| 299 | } | 291 | } |
| 300 | } while_each_thread(g, p); | 292 | } while_each_thread(g, p); |
| 301 | if (!uid_eq(uid, cred_uid)) | 293 | if (!uid_eq(uid, cred->uid)) |
| 302 | free_uid(user); /* for find_user() */ | 294 | free_uid(user); /* for find_user() */ |
| 303 | break; | 295 | break; |
| 304 | } | 296 | } |
| @@ -641,7 +633,7 @@ static int set_user(struct cred *new) | |||
| 641 | { | 633 | { |
| 642 | struct user_struct *new_user; | 634 | struct user_struct *new_user; |
| 643 | 635 | ||
| 644 | new_user = alloc_uid(make_kuid(new->user_ns, new->uid)); | 636 | new_user = alloc_uid(new->uid); |
| 645 | if (!new_user) | 637 | if (!new_user) |
| 646 | return -EAGAIN; | 638 | return -EAGAIN; |
| 647 | 639 | ||
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 7eff867bfac..86602316422 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c | |||
| @@ -36,8 +36,8 @@ static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid, | |||
| 36 | int create_user_ns(struct cred *new) | 36 | int create_user_ns(struct cred *new) |
| 37 | { | 37 | { |
| 38 | struct user_namespace *ns, *parent_ns = new->user_ns; | 38 | struct user_namespace *ns, *parent_ns = new->user_ns; |
| 39 | kuid_t owner = make_kuid(new->user_ns, new->euid); | 39 | kuid_t owner = new->euid; |
| 40 | kgid_t group = make_kgid(new->user_ns, new->egid); | 40 | kgid_t group = new->egid; |
| 41 | 41 | ||
| 42 | /* The creator needs a mapping in the parent user namespace | 42 | /* The creator needs a mapping in the parent user namespace |
| 43 | * or else we won't be able to reasonably tell userspace who | 43 | * or else we won't be able to reasonably tell userspace who |
