Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

userns: Store uid and gid values in struct cred with kuid_t and kgid_t types

cred.h and a few trivial users of struct cred are changed. The rest of the users
of struct cred are left for other patches as there are too many changes to make
in one go and leave the change reviewable. If the user namespace is disabled and
CONFIG_UIDGID_STRICT_TYPE_CHECKS are disabled the code will contiue to compile
and behave correctly.

Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>

+59 -62
+1 -1
arch/x86/mm/fault.c
··· 582 582 pte_t *pte = lookup_address(address, &level); 583 583 584 584 if (pte && pte_present(*pte) && !pte_exec(*pte)) 585 - printk(nx_warning, current_uid()); 585 + printk(nx_warning, from_kuid(&init_user_ns, current_uid())); 586 586 } 587 587 588 588 printk(KERN_ALERT "BUG: unable to handle kernel ");
+2 -6
fs/ioprio.c
··· 123 123 break; 124 124 125 125 do_each_thread(g, p) { 126 - const struct cred *tcred = __task_cred(p); 127 - kuid_t tcred_uid = make_kuid(tcred->user_ns, tcred->uid); 128 - if (!uid_eq(tcred_uid, uid)) 126 + if (!uid_eq(task_uid(p), uid)) 129 127 continue; 130 128 ret = set_task_ioprio(p, ioprio); 131 129 if (ret) ··· 218 220 break; 219 221 220 222 do_each_thread(g, p) { 221 - const struct cred *tcred = __task_cred(p); 222 - kuid_t tcred_uid = make_kuid(tcred->user_ns, tcred->uid); 223 - if (!uid_eq(tcred_uid, user->uid)) 223 + if (!uid_eq(task_uid(p), user->uid)) 224 224 continue; 225 225 tmpio = get_task_ioprio(p); 226 226 if (tmpio < 0)
+8 -8
include/linux/cred.h
··· 123 123 #define CRED_MAGIC 0x43736564 124 124 #define CRED_MAGIC_DEAD 0x44656144 125 125 #endif 126 - uid_t uid; /* real UID of the task */ 127 - gid_t gid; /* real GID of the task */ 128 - uid_t suid; /* saved UID of the task */ 129 - gid_t sgid; /* saved GID of the task */ 130 - uid_t euid; /* effective UID of the task */ 131 - gid_t egid; /* effective GID of the task */ 132 - uid_t fsuid; /* UID for VFS ops */ 133 - gid_t fsgid; /* GID for VFS ops */ 126 + kuid_t uid; /* real UID of the task */ 127 + kgid_t gid; /* real GID of the task */ 128 + kuid_t suid; /* saved UID of the task */ 129 + kgid_t sgid; /* saved GID of the task */ 130 + kuid_t euid; /* effective UID of the task */ 131 + kgid_t egid; /* effective GID of the task */ 132 + kuid_t fsuid; /* UID for VFS ops */ 133 + kgid_t fsgid; /* GID for VFS ops */ 134 134 unsigned securebits; /* SUID-less security management */ 135 135 kernel_cap_t cap_inheritable; /* caps our children can inherit */ 136 136 kernel_cap_t cap_permitted; /* caps we're permitted */
+4 -4
include/linux/user_namespace.h
··· 70 70 #endif 71 71 72 72 static inline uid_t user_ns_map_uid(struct user_namespace *to, 73 - const struct cred *cred, uid_t uid) 73 + const struct cred *cred, kuid_t uid) 74 74 { 75 - return from_kuid_munged(to, make_kuid(cred->user_ns, uid)); 75 + return from_kuid_munged(to, uid); 76 76 } 77 77 78 78 static inline gid_t user_ns_map_gid(struct user_namespace *to, 79 - const struct cred *cred, gid_t gid) 79 + const struct cred *cred, kgid_t gid) 80 80 { 81 - return from_kgid_munged(to, make_kgid(cred->user_ns, gid)); 81 + return from_kgid_munged(to, gid); 82 82 } 83 83 84 84 #endif /* _LINUX_USER_H */
+22 -14
kernel/cred.c
··· 49 49 .subscribers = ATOMIC_INIT(2), 50 50 .magic = CRED_MAGIC, 51 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 60 .securebits = SECUREBITS_DEFAULT, 53 61 .cap_inheritable = CAP_EMPTY_SET, 54 62 .cap_permitted = CAP_FULL_SET, ··· 496 488 get_cred(new); /* we will require a ref for the subj creds too */ 497 489 498 490 /* dumpability changes */ 499 - if (old->euid != new->euid || 500 - old->egid != new->egid || 501 - old->fsuid != new->fsuid || 502 - old->fsgid != new->fsgid || 491 + if (!uid_eq(old->euid, new->euid) || 492 + !gid_eq(old->egid, new->egid) || 493 + !uid_eq(old->fsuid, new->fsuid) || 494 + !gid_eq(old->fsgid, new->fsgid) || 503 495 !cap_issubset(new->cap_permitted, old->cap_permitted)) { 504 496 if (task->mm) 505 497 set_dumpable(task->mm, suid_dumpable); ··· 508 500 } 509 501 510 502 /* alter the thread keyring */ 511 - if (new->fsuid != old->fsuid) 503 + if (!uid_eq(new->fsuid, old->fsuid)) 512 504 key_fsuid_changed(task); 513 - if (new->fsgid != old->fsgid) 505 + if (!gid_eq(new->fsgid, old->fsgid)) 514 506 key_fsgid_changed(task); 515 507 516 508 /* do it ··· 527 519 alter_cred_subscribers(old, -2); 528 520 529 521 /* send notifications */ 530 - if (new->uid != old->uid || 531 - new->euid != old->euid || 532 - new->suid != old->suid || 533 - new->fsuid != old->fsuid) 522 + if (!uid_eq(new->uid, old->uid) || 523 + !uid_eq(new->euid, old->euid) || 524 + !uid_eq(new->suid, old->suid) || 525 + !uid_eq(new->fsuid, old->fsuid)) 534 526 proc_id_connector(task, PROC_EVENT_UID); 535 527 536 - if (new->gid != old->gid || 537 - new->egid != old->egid || 538 - new->sgid != old->sgid || 539 - new->fsgid != old->fsgid) 528 + if (!gid_eq(new->gid, old->gid) || 529 + !gid_eq(new->egid, old->egid) || 530 + !gid_eq(new->sgid, old->sgid) || 531 + !gid_eq(new->fsgid, old->fsgid)) 540 532 proc_id_connector(task, PROC_EVENT_GID); 541 533 542 534 /* release the old obj and subj refs both */
+8 -6
kernel/signal.c
··· 1038 1038 if (SI_FROMKERNEL(info)) 1039 1039 return; 1040 1040 1041 - info->si_uid = user_ns_map_uid(task_cred_xxx(t, user_ns), 1042 - current_cred(), info->si_uid); 1041 + rcu_read_lock(); 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 1046 #else 1045 1047 static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) ··· 1108 1106 q->info.si_code = SI_USER; 1109 1107 q->info.si_pid = task_tgid_nr_ns(current, 1110 1108 task_active_pid_ns(t)); 1111 - q->info.si_uid = current_uid(); 1109 + q->info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); 1112 1110 break; 1113 1111 case (unsigned long) SEND_SIG_PRIV: 1114 1112 q->info.si_signo = sig; ··· 1975 1973 info.si_signo = signr; 1976 1974 info.si_code = exit_code; 1977 1975 info.si_pid = task_pid_vnr(current); 1978 - info.si_uid = current_uid(); 1976 + info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); 1979 1977 1980 1978 /* Let the debugger run. */ 1981 1979 ptrace_stop(exit_code, why, 1, &info); ··· 2830 2828 info.si_errno = 0; 2831 2829 info.si_code = SI_USER; 2832 2830 info.si_pid = task_tgid_vnr(current); 2833 - info.si_uid = current_uid(); 2831 + info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); 2834 2832 2835 2833 return kill_something_info(sig, &info, pid); 2836 2834 } ··· 2873 2871 info.si_errno = 0; 2874 2872 info.si_code = SI_TKILL; 2875 2873 info.si_pid = task_tgid_vnr(current); 2876 - info.si_uid = current_uid(); 2874 + info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); 2877 2875 2878 2876 return do_send_specific(tgid, pid, sig, &info); 2879 2877 }
+9 -17
kernel/sys.c
··· 175 175 const struct cred *cred = current_cred(); 176 176 int error = -EINVAL; 177 177 struct pid *pgrp; 178 - kuid_t cred_uid; 179 178 kuid_t uid; 180 179 181 180 if (which > PRIO_USER || which < PRIO_PROCESS) ··· 208 209 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); 209 210 break; 210 211 case PRIO_USER: 211 - cred_uid = make_kuid(cred->user_ns, cred->uid); 212 212 uid = make_kuid(cred->user_ns, who); 213 213 user = cred->user; 214 214 if (!who) 215 - uid = cred_uid; 216 - else if (!uid_eq(uid, cred_uid) && 215 + uid = cred->uid; 216 + else if (!uid_eq(uid, cred->uid) && 217 217 !(user = find_user(uid))) 218 218 goto out_unlock; /* No processes for this user */ 219 219 220 220 do_each_thread(g, p) { 221 - const struct cred *tcred = __task_cred(p); 222 - kuid_t tcred_uid = make_kuid(tcred->user_ns, tcred->uid); 223 - if (uid_eq(tcred_uid, uid)) 221 + if (uid_eq(task_uid(p), uid)) 224 222 error = set_one_prio(p, niceval, error); 225 223 } while_each_thread(g, p); 226 - if (!uid_eq(uid, cred_uid)) 224 + if (!uid_eq(uid, cred->uid)) 227 225 free_uid(user); /* For find_user() */ 228 226 break; 229 227 } ··· 244 248 const struct cred *cred = current_cred(); 245 249 long niceval, retval = -ESRCH; 246 250 struct pid *pgrp; 247 - kuid_t cred_uid; 248 251 kuid_t uid; 249 252 250 253 if (which > PRIO_USER || which < PRIO_PROCESS) ··· 275 280 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); 276 281 break; 277 282 case PRIO_USER: 278 - cred_uid = make_kuid(cred->user_ns, cred->uid); 279 283 uid = make_kuid(cred->user_ns, who); 280 284 user = cred->user; 281 285 if (!who) 282 - uid = cred_uid; 283 - else if (!uid_eq(uid, cred_uid) && 286 + uid = cred->uid; 287 + else if (!uid_eq(uid, cred->uid) && 284 288 !(user = find_user(uid))) 285 289 goto out_unlock; /* No processes for this user */ 286 290 287 291 do_each_thread(g, p) { 288 - const struct cred *tcred = __task_cred(p); 289 - kuid_t tcred_uid = make_kuid(tcred->user_ns, tcred->uid); 290 - if (uid_eq(tcred_uid, uid)) { 292 + if (uid_eq(task_uid(p), uid)) { 291 293 niceval = 20 - task_nice(p); 292 294 if (niceval > retval) 293 295 retval = niceval; 294 296 } 295 297 } while_each_thread(g, p); 296 - if (!uid_eq(uid, cred_uid)) 298 + if (!uid_eq(uid, cred->uid)) 297 299 free_uid(user); /* for find_user() */ 298 300 break; 299 301 } ··· 633 641 { 634 642 struct user_struct *new_user; 635 643 636 - new_user = alloc_uid(make_kuid(new->user_ns, new->uid)); 644 + new_user = alloc_uid(new->uid); 637 645 if (!new_user) 638 646 return -EAGAIN; 639 647
+2 -2
kernel/user_namespace.c
··· 36 36 int create_user_ns(struct cred *new) 37 37 { 38 38 struct user_namespace *ns, *parent_ns = new->user_ns; 39 - kuid_t owner = make_kuid(new->user_ns, new->euid); 40 - kgid_t group = make_kgid(new->user_ns, new->egid); 39 + kuid_t owner = new->euid; 40 + kgid_t group = new->egid; 41 41 42 42 /* The creator needs a mapping in the parent user namespace 43 43 * or else we won't be able to reasonably tell userspace who
+2 -2
mm/oom_kill.c
··· 410 410 } 411 411 412 412 pr_info("[%5d] %5d %5d %8lu %8lu %3u %3d %5d %s\n", 413 - task->pid, task_uid(task), task->tgid, 414 - task->mm->total_vm, get_mm_rss(task->mm), 413 + task->pid, from_kuid(&init_user_ns, task_uid(task)), 414 + task->tgid, task->mm->total_vm, get_mm_rss(task->mm), 415 415 task_cpu(task), task->signal->oom_adj, 416 416 task->signal->oom_score_adj, task->comm); 417 417 task_unlock(task);
+1 -2
security/commoncap.c
··· 77 77 { 78 78 for (;;) { 79 79 /* The owner of the user namespace has all caps. */ 80 - if (targ_ns != &init_user_ns && uid_eq(targ_ns->owner, 81 - make_kuid(cred->user_ns, cred->euid))) 80 + if (targ_ns != &init_user_ns && uid_eq(targ_ns->owner, cred->euid)) 82 81 return 0; 83 82 84 83 /* Do we have the necessary capabilities? */