diff options
85 files changed, 1787 insertions, 605 deletions
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c index af0aaebf4de6..3e94811690ce 100644 --- a/arch/arm/kernel/sys_oabi-compat.c +++ b/arch/arm/kernel/sys_oabi-compat.c | |||
@@ -124,8 +124,8 @@ static long cp_oldabi_stat64(struct kstat *stat, | |||
124 | tmp.__st_ino = stat->ino; | 124 | tmp.__st_ino = stat->ino; |
125 | tmp.st_mode = stat->mode; | 125 | tmp.st_mode = stat->mode; |
126 | tmp.st_nlink = stat->nlink; | 126 | tmp.st_nlink = stat->nlink; |
127 | tmp.st_uid = stat->uid; | 127 | tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid); |
128 | tmp.st_gid = stat->gid; | 128 | tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid); |
129 | tmp.st_rdev = huge_encode_dev(stat->rdev); | 129 | tmp.st_rdev = huge_encode_dev(stat->rdev); |
130 | tmp.st_size = stat->size; | 130 | tmp.st_size = stat->size; |
131 | tmp.st_blocks = stat->blocks; | 131 | tmp.st_blocks = stat->blocks; |
diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c index 0dc8543acb4f..c71eb6c79897 100644 --- a/arch/parisc/hpux/fs.c +++ b/arch/parisc/hpux/fs.c | |||
@@ -159,8 +159,8 @@ static int cp_hpux_stat(struct kstat *stat, struct hpux_stat64 __user *statbuf) | |||
159 | tmp.st_ino = stat->ino; | 159 | tmp.st_ino = stat->ino; |
160 | tmp.st_mode = stat->mode; | 160 | tmp.st_mode = stat->mode; |
161 | tmp.st_nlink = stat->nlink; | 161 | tmp.st_nlink = stat->nlink; |
162 | tmp.st_uid = stat->uid; | 162 | tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid); |
163 | tmp.st_gid = stat->gid; | 163 | tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid); |
164 | tmp.st_rdev = new_encode_dev(stat->rdev); | 164 | tmp.st_rdev = new_encode_dev(stat->rdev); |
165 | tmp.st_size = stat->size; | 165 | tmp.st_size = stat->size; |
166 | tmp.st_atime = stat->atime.tv_sec; | 166 | tmp.st_atime = stat->atime.tv_sec; |
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index ab64bdbab2ae..65426525d9f2 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c | |||
@@ -173,11 +173,14 @@ asmlinkage long sys32_setfsgid16(u16 gid) | |||
173 | 173 | ||
174 | static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info) | 174 | static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info) |
175 | { | 175 | { |
176 | struct user_namespace *user_ns = current_user_ns(); | ||
176 | int i; | 177 | int i; |
177 | u16 group; | 178 | u16 group; |
179 | kgid_t kgid; | ||
178 | 180 | ||
179 | for (i = 0; i < group_info->ngroups; i++) { | 181 | for (i = 0; i < group_info->ngroups; i++) { |
180 | group = (u16)GROUP_AT(group_info, i); | 182 | kgid = GROUP_AT(group_info, i); |
183 | group = (u16)from_kgid_munged(user_ns, kgid); | ||
181 | if (put_user(group, grouplist+i)) | 184 | if (put_user(group, grouplist+i)) |
182 | return -EFAULT; | 185 | return -EFAULT; |
183 | } | 186 | } |
@@ -187,13 +190,20 @@ static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info | |||
187 | 190 | ||
188 | static int groups16_from_user(struct group_info *group_info, u16 __user *grouplist) | 191 | static int groups16_from_user(struct group_info *group_info, u16 __user *grouplist) |
189 | { | 192 | { |
193 | struct user_namespace *user_ns = current_user_ns(); | ||
190 | int i; | 194 | int i; |
191 | u16 group; | 195 | u16 group; |
196 | kgid_t kgid; | ||
192 | 197 | ||
193 | for (i = 0; i < group_info->ngroups; i++) { | 198 | for (i = 0; i < group_info->ngroups; i++) { |
194 | if (get_user(group, grouplist+i)) | 199 | if (get_user(group, grouplist+i)) |
195 | return -EFAULT; | 200 | return -EFAULT; |
196 | GROUP_AT(group_info, i) = (gid_t)group; | 201 | |
202 | kgid = make_kgid(user_ns, (gid_t)group); | ||
203 | if (!gid_valid(kgid)) | ||
204 | return -EINVAL; | ||
205 | |||
206 | GROUP_AT(group_info, i) = kgid; | ||
197 | } | 207 | } |
198 | 208 | ||
199 | return 0; | 209 | return 0; |
@@ -537,8 +547,8 @@ static int cp_stat64(struct stat64_emu31 __user *ubuf, struct kstat *stat) | |||
537 | tmp.__st_ino = (u32)stat->ino; | 547 | tmp.__st_ino = (u32)stat->ino; |
538 | tmp.st_mode = stat->mode; | 548 | tmp.st_mode = stat->mode; |
539 | tmp.st_nlink = (unsigned int)stat->nlink; | 549 | tmp.st_nlink = (unsigned int)stat->nlink; |
540 | tmp.st_uid = stat->uid; | 550 | tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid); |
541 | tmp.st_gid = stat->gid; | 551 | tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid); |
542 | tmp.st_rdev = huge_encode_dev(stat->rdev); | 552 | tmp.st_rdev = huge_encode_dev(stat->rdev); |
543 | tmp.st_size = stat->size; | 553 | tmp.st_size = stat->size; |
544 | tmp.st_blksize = (u32)stat->blksize; | 554 | tmp.st_blksize = (u32)stat->blksize; |
diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c index 29c478ffed91..f7392336961f 100644 --- a/arch/sparc/kernel/sys_sparc32.c +++ b/arch/sparc/kernel/sys_sparc32.c | |||
@@ -139,8 +139,8 @@ static int cp_compat_stat64(struct kstat *stat, | |||
139 | err |= put_user(stat->ino, &statbuf->st_ino); | 139 | err |= put_user(stat->ino, &statbuf->st_ino); |
140 | err |= put_user(stat->mode, &statbuf->st_mode); | 140 | err |= put_user(stat->mode, &statbuf->st_mode); |
141 | err |= put_user(stat->nlink, &statbuf->st_nlink); | 141 | err |= put_user(stat->nlink, &statbuf->st_nlink); |
142 | err |= put_user(stat->uid, &statbuf->st_uid); | 142 | err |= put_user(from_kuid_munged(current_user_ns(), stat->uid), &statbuf->st_uid); |
143 | err |= put_user(stat->gid, &statbuf->st_gid); | 143 | err |= put_user(from_kgid_munged(current_user_ns(), stat->gid), &statbuf->st_gid); |
144 | err |= put_user(huge_encode_dev(stat->rdev), &statbuf->st_rdev); | 144 | err |= put_user(huge_encode_dev(stat->rdev), &statbuf->st_rdev); |
145 | err |= put_user(0, (unsigned long __user *) &statbuf->__pad3[0]); | 145 | err |= put_user(0, (unsigned long __user *) &statbuf->__pad3[0]); |
146 | err |= put_user(stat->size, &statbuf->st_size); | 146 | err |= put_user(stat->size, &statbuf->st_size); |
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index edca9c0a79cc..4540bece0946 100644 --- a/arch/x86/ia32/sys_ia32.c +++ b/arch/x86/ia32/sys_ia32.c | |||
@@ -71,8 +71,8 @@ static int cp_stat64(struct stat64 __user *ubuf, struct kstat *stat) | |||
71 | { | 71 | { |
72 | typeof(ubuf->st_uid) uid = 0; | 72 | typeof(ubuf->st_uid) uid = 0; |
73 | typeof(ubuf->st_gid) gid = 0; | 73 | typeof(ubuf->st_gid) gid = 0; |
74 | SET_UID(uid, stat->uid); | 74 | SET_UID(uid, from_kuid_munged(current_user_ns(), stat->uid)); |
75 | SET_GID(gid, stat->gid); | 75 | SET_GID(gid, from_kgid_munged(current_user_ns(), stat->gid)); |
76 | if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct stat64)) || | 76 | if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct stat64)) || |
77 | __put_user(huge_encode_dev(stat->dev), &ubuf->st_dev) || | 77 | __put_user(huge_encode_dev(stat->dev), &ubuf->st_dev) || |
78 | __put_user(stat->ino, &ubuf->__st_ino) || | 78 | __put_user(stat->ino, &ubuf->__st_ino) || |
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 3ecfd1aaf214..76dcd9d8e0bc 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
@@ -582,7 +582,7 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code, | |||
582 | pte_t *pte = lookup_address(address, &level); | 582 | pte_t *pte = lookup_address(address, &level); |
583 | 583 | ||
584 | if (pte && pte_present(*pte) && !pte_exec(*pte)) | 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 | printk(KERN_ALERT "BUG: unable to handle kernel "); | 588 | printk(KERN_ALERT "BUG: unable to handle kernel "); |
@@ -47,14 +47,14 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr) | |||
47 | 47 | ||
48 | /* Make sure a caller can chown. */ | 48 | /* Make sure a caller can chown. */ |
49 | if ((ia_valid & ATTR_UID) && | 49 | if ((ia_valid & ATTR_UID) && |
50 | (current_fsuid() != inode->i_uid || | 50 | (!uid_eq(current_fsuid(), inode->i_uid) || |
51 | attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN)) | 51 | !uid_eq(attr->ia_uid, inode->i_uid)) && !capable(CAP_CHOWN)) |
52 | return -EPERM; | 52 | return -EPERM; |
53 | 53 | ||
54 | /* Make sure caller can chgrp. */ | 54 | /* Make sure caller can chgrp. */ |
55 | if ((ia_valid & ATTR_GID) && | 55 | if ((ia_valid & ATTR_GID) && |
56 | (current_fsuid() != inode->i_uid || | 56 | (!uid_eq(current_fsuid(), inode->i_uid) || |
57 | (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid)) && | 57 | (!in_group_p(attr->ia_gid) && !gid_eq(attr->ia_gid, inode->i_gid))) && |
58 | !capable(CAP_CHOWN)) | 58 | !capable(CAP_CHOWN)) |
59 | return -EPERM; | 59 | return -EPERM; |
60 | 60 | ||
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 16f735417072..e658dd134b95 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -226,10 +226,10 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | |||
226 | NEW_AUX_ENT(AT_BASE, interp_load_addr); | 226 | NEW_AUX_ENT(AT_BASE, interp_load_addr); |
227 | NEW_AUX_ENT(AT_FLAGS, 0); | 227 | NEW_AUX_ENT(AT_FLAGS, 0); |
228 | NEW_AUX_ENT(AT_ENTRY, exec->e_entry); | 228 | NEW_AUX_ENT(AT_ENTRY, exec->e_entry); |
229 | NEW_AUX_ENT(AT_UID, cred->uid); | 229 | NEW_AUX_ENT(AT_UID, from_kuid_munged(cred->user_ns, cred->uid)); |
230 | NEW_AUX_ENT(AT_EUID, cred->euid); | 230 | NEW_AUX_ENT(AT_EUID, from_kuid_munged(cred->user_ns, cred->euid)); |
231 | NEW_AUX_ENT(AT_GID, cred->gid); | 231 | NEW_AUX_ENT(AT_GID, from_kgid_munged(cred->user_ns, cred->gid)); |
232 | NEW_AUX_ENT(AT_EGID, cred->egid); | 232 | NEW_AUX_ENT(AT_EGID, from_kgid_munged(cred->user_ns, cred->egid)); |
233 | NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm)); | 233 | NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm)); |
234 | NEW_AUX_ENT(AT_RANDOM, (elf_addr_t)(unsigned long)u_rand_bytes); | 234 | NEW_AUX_ENT(AT_RANDOM, (elf_addr_t)(unsigned long)u_rand_bytes); |
235 | NEW_AUX_ENT(AT_EXECFN, bprm->exec); | 235 | NEW_AUX_ENT(AT_EXECFN, bprm->exec); |
@@ -1356,8 +1356,8 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, | |||
1356 | psinfo->pr_flag = p->flags; | 1356 | psinfo->pr_flag = p->flags; |
1357 | rcu_read_lock(); | 1357 | rcu_read_lock(); |
1358 | cred = __task_cred(p); | 1358 | cred = __task_cred(p); |
1359 | SET_UID(psinfo->pr_uid, cred->uid); | 1359 | SET_UID(psinfo->pr_uid, from_kuid_munged(cred->user_ns, cred->uid)); |
1360 | SET_GID(psinfo->pr_gid, cred->gid); | 1360 | SET_GID(psinfo->pr_gid, from_kgid_munged(cred->user_ns, cred->gid)); |
1361 | rcu_read_unlock(); | 1361 | rcu_read_unlock(); |
1362 | strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname)); | 1362 | strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname)); |
1363 | 1363 | ||
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index d390a0fffc65..3d77cf81ba3c 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
@@ -627,10 +627,10 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, | |||
627 | NEW_AUX_ENT(AT_BASE, interp_params->elfhdr_addr); | 627 | NEW_AUX_ENT(AT_BASE, interp_params->elfhdr_addr); |
628 | NEW_AUX_ENT(AT_FLAGS, 0); | 628 | NEW_AUX_ENT(AT_FLAGS, 0); |
629 | NEW_AUX_ENT(AT_ENTRY, exec_params->entry_addr); | 629 | NEW_AUX_ENT(AT_ENTRY, exec_params->entry_addr); |
630 | NEW_AUX_ENT(AT_UID, (elf_addr_t) cred->uid); | 630 | NEW_AUX_ENT(AT_UID, (elf_addr_t) from_kuid_munged(cred->user_ns, cred->uid)); |
631 | NEW_AUX_ENT(AT_EUID, (elf_addr_t) cred->euid); | 631 | NEW_AUX_ENT(AT_EUID, (elf_addr_t) from_kuid_munged(cred->user_ns, cred->euid)); |
632 | NEW_AUX_ENT(AT_GID, (elf_addr_t) cred->gid); | 632 | NEW_AUX_ENT(AT_GID, (elf_addr_t) from_kgid_munged(cred->user_ns, cred->gid)); |
633 | NEW_AUX_ENT(AT_EGID, (elf_addr_t) cred->egid); | 633 | NEW_AUX_ENT(AT_EGID, (elf_addr_t) from_kgid_munged(cred->user_ns, cred->egid)); |
634 | NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm)); | 634 | NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm)); |
635 | NEW_AUX_ENT(AT_EXECFN, bprm->exec); | 635 | NEW_AUX_ENT(AT_EXECFN, bprm->exec); |
636 | 636 | ||
@@ -1421,8 +1421,8 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, | |||
1421 | psinfo->pr_flag = p->flags; | 1421 | psinfo->pr_flag = p->flags; |
1422 | rcu_read_lock(); | 1422 | rcu_read_lock(); |
1423 | cred = __task_cred(p); | 1423 | cred = __task_cred(p); |
1424 | SET_UID(psinfo->pr_uid, cred->uid); | 1424 | SET_UID(psinfo->pr_uid, from_kuid_munged(cred->user_ns, cred->uid)); |
1425 | SET_GID(psinfo->pr_gid, cred->gid); | 1425 | SET_GID(psinfo->pr_gid, from_kgid_munged(cred->user_ns, cred->gid)); |
1426 | rcu_read_unlock(); | 1426 | rcu_read_unlock(); |
1427 | strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname)); | 1427 | strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname)); |
1428 | 1428 | ||
diff --git a/fs/compat.c b/fs/compat.c index f2944ace7a7b..0781e619a62a 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -144,8 +144,8 @@ static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf) | |||
144 | tmp.st_nlink = stat->nlink; | 144 | tmp.st_nlink = stat->nlink; |
145 | if (tmp.st_nlink != stat->nlink) | 145 | if (tmp.st_nlink != stat->nlink) |
146 | return -EOVERFLOW; | 146 | return -EOVERFLOW; |
147 | SET_UID(tmp.st_uid, stat->uid); | 147 | SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid)); |
148 | SET_GID(tmp.st_gid, stat->gid); | 148 | SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid)); |
149 | tmp.st_rdev = old_encode_dev(stat->rdev); | 149 | tmp.st_rdev = old_encode_dev(stat->rdev); |
150 | if ((u64) stat->size > MAX_NON_LFS) | 150 | if ((u64) stat->size > MAX_NON_LFS) |
151 | return -EOVERFLOW; | 151 | return -EOVERFLOW; |
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 10f5e0b484db..979c1e309c73 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c | |||
@@ -98,8 +98,8 @@ static struct vfsmount *devpts_mnt; | |||
98 | struct pts_mount_opts { | 98 | struct pts_mount_opts { |
99 | int setuid; | 99 | int setuid; |
100 | int setgid; | 100 | int setgid; |
101 | uid_t uid; | 101 | kuid_t uid; |
102 | gid_t gid; | 102 | kgid_t gid; |
103 | umode_t mode; | 103 | umode_t mode; |
104 | umode_t ptmxmode; | 104 | umode_t ptmxmode; |
105 | int newinstance; | 105 | int newinstance; |
@@ -158,11 +158,13 @@ static inline struct super_block *pts_sb_from_inode(struct inode *inode) | |||
158 | static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts) | 158 | static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts) |
159 | { | 159 | { |
160 | char *p; | 160 | char *p; |
161 | kuid_t uid; | ||
162 | kgid_t gid; | ||
161 | 163 | ||
162 | opts->setuid = 0; | 164 | opts->setuid = 0; |
163 | opts->setgid = 0; | 165 | opts->setgid = 0; |
164 | opts->uid = 0; | 166 | opts->uid = GLOBAL_ROOT_UID; |
165 | opts->gid = 0; | 167 | opts->gid = GLOBAL_ROOT_GID; |
166 | opts->mode = DEVPTS_DEFAULT_MODE; | 168 | opts->mode = DEVPTS_DEFAULT_MODE; |
167 | opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE; | 169 | opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE; |
168 | opts->max = NR_UNIX98_PTY_MAX; | 170 | opts->max = NR_UNIX98_PTY_MAX; |
@@ -184,13 +186,19 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts) | |||
184 | case Opt_uid: | 186 | case Opt_uid: |
185 | if (match_int(&args[0], &option)) | 187 | if (match_int(&args[0], &option)) |
186 | return -EINVAL; | 188 | return -EINVAL; |
187 | opts->uid = option; | 189 | uid = make_kuid(current_user_ns(), option); |
190 | if (!uid_valid(uid)) | ||
191 | return -EINVAL; | ||
192 | opts->uid = uid; | ||
188 | opts->setuid = 1; | 193 | opts->setuid = 1; |
189 | break; | 194 | break; |
190 | case Opt_gid: | 195 | case Opt_gid: |
191 | if (match_int(&args[0], &option)) | 196 | if (match_int(&args[0], &option)) |
192 | return -EINVAL; | 197 | return -EINVAL; |
193 | opts->gid = option; | 198 | gid = make_kgid(current_user_ns(), option); |
199 | if (!gid_valid(gid)) | ||
200 | return -EINVAL; | ||
201 | opts->gid = gid; | ||
194 | opts->setgid = 1; | 202 | opts->setgid = 1; |
195 | break; | 203 | break; |
196 | case Opt_mode: | 204 | case Opt_mode: |
@@ -315,9 +323,9 @@ static int devpts_show_options(struct seq_file *seq, struct dentry *root) | |||
315 | struct pts_mount_opts *opts = &fsi->mount_opts; | 323 | struct pts_mount_opts *opts = &fsi->mount_opts; |
316 | 324 | ||
317 | if (opts->setuid) | 325 | if (opts->setuid) |
318 | seq_printf(seq, ",uid=%u", opts->uid); | 326 | seq_printf(seq, ",uid=%u", from_kuid_munged(&init_user_ns, opts->uid)); |
319 | if (opts->setgid) | 327 | if (opts->setgid) |
320 | seq_printf(seq, ",gid=%u", opts->gid); | 328 | seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, opts->gid)); |
321 | seq_printf(seq, ",mode=%03o", opts->mode); | 329 | seq_printf(seq, ",mode=%03o", opts->mode); |
322 | #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES | 330 | #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES |
323 | seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode); | 331 | seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode); |
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index ab2248090515..a750f957b145 100644 --- a/fs/ecryptfs/messaging.c +++ b/fs/ecryptfs/messaging.c | |||
@@ -303,7 +303,7 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, | |||
303 | mutex_unlock(&ecryptfs_daemon_hash_mux); | 303 | mutex_unlock(&ecryptfs_daemon_hash_mux); |
304 | goto wake_up; | 304 | goto wake_up; |
305 | } | 305 | } |
306 | tsk_user_ns = __task_cred(msg_ctx->task)->user->user_ns; | 306 | tsk_user_ns = __task_cred(msg_ctx->task)->user_ns; |
307 | ctx_euid = task_euid(msg_ctx->task); | 307 | ctx_euid = task_euid(msg_ctx->task); |
308 | rc = ecryptfs_find_daemon_by_euid(&daemon, ctx_euid, tsk_user_ns); | 308 | rc = ecryptfs_find_daemon_by_euid(&daemon, ctx_euid, tsk_user_ns); |
309 | rcu_read_unlock(); | 309 | rcu_read_unlock(); |
@@ -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); |
@@ -1299,8 +1299,11 @@ int prepare_binprm(struct linux_binprm *bprm) | |||
1299 | !current->no_new_privs) { | 1299 | !current->no_new_privs) { |
1300 | /* Set-uid? */ | 1300 | /* Set-uid? */ |
1301 | if (mode & S_ISUID) { | 1301 | if (mode & S_ISUID) { |
1302 | if (!kuid_has_mapping(bprm->cred->user_ns, inode->i_uid)) | ||
1303 | return -EPERM; | ||
1302 | bprm->per_clear |= PER_CLEAR_ON_SETID; | 1304 | bprm->per_clear |= PER_CLEAR_ON_SETID; |
1303 | bprm->cred->euid = inode->i_uid; | 1305 | bprm->cred->euid = inode->i_uid; |
1306 | |||
1304 | } | 1307 | } |
1305 | 1308 | ||
1306 | /* Set-gid? */ | 1309 | /* Set-gid? */ |
@@ -1310,6 +1313,8 @@ int prepare_binprm(struct linux_binprm *bprm) | |||
1310 | * executable. | 1313 | * executable. |
1311 | */ | 1314 | */ |
1312 | 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; | ||
1313 | bprm->per_clear |= PER_CLEAR_ON_SETID; | 1318 | bprm->per_clear |= PER_CLEAR_ON_SETID; |
1314 | bprm->cred->egid = inode->i_gid; | 1319 | bprm->cred->egid = inode->i_gid; |
1315 | } | 1320 | } |
@@ -2142,7 +2147,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
2142 | if (__get_dumpable(cprm.mm_flags) == 2) { | 2147 | if (__get_dumpable(cprm.mm_flags) == 2) { |
2143 | /* Setuid core dump mode */ | 2148 | /* Setuid core dump mode */ |
2144 | flag = O_EXCL; /* Stop rewrite attacks */ | 2149 | flag = O_EXCL; /* Stop rewrite attacks */ |
2145 | cred->fsuid = 0; /* Dump root private */ | 2150 | cred->fsuid = GLOBAL_ROOT_UID; /* Dump root private */ |
2146 | } | 2151 | } |
2147 | 2152 | ||
2148 | retval = coredump_wait(exit_code, &core_state); | 2153 | retval = coredump_wait(exit_code, &core_state); |
@@ -2243,7 +2248,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
2243 | * Dont allow local users get cute and trick others to coredump | 2248 | * Dont allow local users get cute and trick others to coredump |
2244 | * into their pre-created files. | 2249 | * into their pre-created files. |
2245 | */ | 2250 | */ |
2246 | if (inode->i_uid != current_fsuid()) | 2251 | if (!uid_eq(inode->i_uid, current_fsuid())) |
2247 | goto close_fail; | 2252 | goto close_fail; |
2248 | if (!cprm.file->f_op || !cprm.file->f_op->write) | 2253 | if (!cprm.file->f_op || !cprm.file->f_op->write) |
2249 | goto close_fail; | 2254 | goto close_fail; |
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index a8cbe1bc6ad4..030c6d277e14 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c | |||
@@ -1193,8 +1193,9 @@ static int ext2_has_free_blocks(struct ext2_sb_info *sbi) | |||
1193 | free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter); | 1193 | free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter); |
1194 | root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count); | 1194 | root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count); |
1195 | if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) && | 1195 | if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) && |
1196 | sbi->s_resuid != current_fsuid() && | 1196 | !uid_eq(sbi->s_resuid, current_fsuid()) && |
1197 | (sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) { | 1197 | (gid_eq(sbi->s_resgid, GLOBAL_ROOT_GID) || |
1198 | !in_group_p (sbi->s_resgid))) { | ||
1198 | return 0; | 1199 | return 0; |
1199 | } | 1200 | } |
1200 | return 1; | 1201 | return 1; |
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 0b2b4db5bdcd..d9a17d0b124d 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h | |||
@@ -82,8 +82,8 @@ struct ext2_sb_info { | |||
82 | struct buffer_head ** s_group_desc; | 82 | struct buffer_head ** s_group_desc; |
83 | unsigned long s_mount_opt; | 83 | unsigned long s_mount_opt; |
84 | unsigned long s_sb_block; | 84 | unsigned long s_sb_block; |
85 | uid_t s_resuid; | 85 | kuid_t s_resuid; |
86 | gid_t s_resgid; | 86 | kgid_t s_resgid; |
87 | unsigned short s_mount_state; | 87 | unsigned short s_mount_state; |
88 | unsigned short s_pad; | 88 | unsigned short s_pad; |
89 | int s_addr_per_block_bits; | 89 | int s_addr_per_block_bits; |
@@ -637,8 +637,8 @@ static inline void verify_offsets(void) | |||
637 | */ | 637 | */ |
638 | struct ext2_mount_options { | 638 | struct ext2_mount_options { |
639 | unsigned long s_mount_opt; | 639 | unsigned long s_mount_opt; |
640 | uid_t s_resuid; | 640 | kuid_t s_resuid; |
641 | gid_t s_resgid; | 641 | kgid_t s_resgid; |
642 | }; | 642 | }; |
643 | 643 | ||
644 | /* | 644 | /* |
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 740cad8dcd8d..f9fa95f8443d 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c | |||
@@ -1293,6 +1293,8 @@ struct inode *ext2_iget (struct super_block *sb, unsigned long ino) | |||
1293 | struct inode *inode; | 1293 | struct inode *inode; |
1294 | long ret = -EIO; | 1294 | long ret = -EIO; |
1295 | int n; | 1295 | int n; |
1296 | uid_t i_uid; | ||
1297 | gid_t i_gid; | ||
1296 | 1298 | ||
1297 | inode = iget_locked(sb, ino); | 1299 | inode = iget_locked(sb, ino); |
1298 | if (!inode) | 1300 | if (!inode) |
@@ -1310,12 +1312,14 @@ struct inode *ext2_iget (struct super_block *sb, unsigned long ino) | |||
1310 | } | 1312 | } |
1311 | 1313 | ||
1312 | inode->i_mode = le16_to_cpu(raw_inode->i_mode); | 1314 | inode->i_mode = le16_to_cpu(raw_inode->i_mode); |
1313 | inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); | 1315 | i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); |
1314 | inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low); | 1316 | i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low); |
1315 | if (!(test_opt (inode->i_sb, NO_UID32))) { | 1317 | if (!(test_opt (inode->i_sb, NO_UID32))) { |
1316 | inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16; | 1318 | i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16; |
1317 | inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16; | 1319 | i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16; |
1318 | } | 1320 | } |
1321 | i_uid_write(inode, i_uid); | ||
1322 | i_gid_write(inode, i_gid); | ||
1319 | set_nlink(inode, le16_to_cpu(raw_inode->i_links_count)); | 1323 | set_nlink(inode, le16_to_cpu(raw_inode->i_links_count)); |
1320 | inode->i_size = le32_to_cpu(raw_inode->i_size); | 1324 | inode->i_size = le32_to_cpu(raw_inode->i_size); |
1321 | inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime); | 1325 | inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime); |
@@ -1413,8 +1417,8 @@ static int __ext2_write_inode(struct inode *inode, int do_sync) | |||
1413 | struct ext2_inode_info *ei = EXT2_I(inode); | 1417 | struct ext2_inode_info *ei = EXT2_I(inode); |
1414 | struct super_block *sb = inode->i_sb; | 1418 | struct super_block *sb = inode->i_sb; |
1415 | ino_t ino = inode->i_ino; | 1419 | ino_t ino = inode->i_ino; |
1416 | uid_t uid = inode->i_uid; | 1420 | uid_t uid = i_uid_read(inode); |
1417 | gid_t gid = inode->i_gid; | 1421 | gid_t gid = i_gid_read(inode); |
1418 | struct buffer_head * bh; | 1422 | struct buffer_head * bh; |
1419 | struct ext2_inode * raw_inode = ext2_get_inode(sb, ino, &bh); | 1423 | struct ext2_inode * raw_inode = ext2_get_inode(sb, ino, &bh); |
1420 | int n; | 1424 | int n; |
@@ -1529,8 +1533,8 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr) | |||
1529 | 1533 | ||
1530 | if (is_quota_modification(inode, iattr)) | 1534 | if (is_quota_modification(inode, iattr)) |
1531 | dquot_initialize(inode); | 1535 | dquot_initialize(inode); |
1532 | if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) || | 1536 | if ((iattr->ia_valid & ATTR_UID && !uid_eq(iattr->ia_uid, inode->i_uid)) || |
1533 | (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid)) { | 1537 | (iattr->ia_valid & ATTR_GID && !gid_eq(iattr->ia_gid, inode->i_gid))) { |
1534 | error = dquot_transfer(inode, iattr); | 1538 | error = dquot_transfer(inode, iattr); |
1535 | if (error) | 1539 | if (error) |
1536 | return error; | 1540 | return error; |
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index e1025c7a437a..38f816071ddb 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
@@ -228,13 +228,15 @@ static int ext2_show_options(struct seq_file *seq, struct dentry *root) | |||
228 | seq_puts(seq, ",grpid"); | 228 | seq_puts(seq, ",grpid"); |
229 | if (!test_opt(sb, GRPID) && (def_mount_opts & EXT2_DEFM_BSDGROUPS)) | 229 | if (!test_opt(sb, GRPID) && (def_mount_opts & EXT2_DEFM_BSDGROUPS)) |
230 | seq_puts(seq, ",nogrpid"); | 230 | seq_puts(seq, ",nogrpid"); |
231 | if (sbi->s_resuid != EXT2_DEF_RESUID || | 231 | if (!uid_eq(sbi->s_resuid, make_kuid(&init_user_ns, EXT2_DEF_RESUID)) || |
232 | le16_to_cpu(es->s_def_resuid) != EXT2_DEF_RESUID) { | 232 | le16_to_cpu(es->s_def_resuid) != EXT2_DEF_RESUID) { |
233 | seq_printf(seq, ",resuid=%u", sbi->s_resuid); | 233 | seq_printf(seq, ",resuid=%u", |
234 | from_kuid_munged(&init_user_ns, sbi->s_resuid)); | ||
234 | } | 235 | } |
235 | if (sbi->s_resgid != EXT2_DEF_RESGID || | 236 | if (!gid_eq(sbi->s_resgid, make_kgid(&init_user_ns, EXT2_DEF_RESGID)) || |
236 | le16_to_cpu(es->s_def_resgid) != EXT2_DEF_RESGID) { | 237 | le16_to_cpu(es->s_def_resgid) != EXT2_DEF_RESGID) { |
237 | seq_printf(seq, ",resgid=%u", sbi->s_resgid); | 238 | seq_printf(seq, ",resgid=%u", |
239 | from_kgid_munged(&init_user_ns, sbi->s_resgid)); | ||
238 | } | 240 | } |
239 | if (test_opt(sb, ERRORS_RO)) { | 241 | if (test_opt(sb, ERRORS_RO)) { |
240 | int def_errors = le16_to_cpu(es->s_errors); | 242 | int def_errors = le16_to_cpu(es->s_errors); |
@@ -436,6 +438,8 @@ static int parse_options(char *options, struct super_block *sb) | |||
436 | struct ext2_sb_info *sbi = EXT2_SB(sb); | 438 | struct ext2_sb_info *sbi = EXT2_SB(sb); |
437 | substring_t args[MAX_OPT_ARGS]; | 439 | substring_t args[MAX_OPT_ARGS]; |
438 | int option; | 440 | int option; |
441 | kuid_t uid; | ||
442 | kgid_t gid; | ||
439 | 443 | ||
440 | if (!options) | 444 | if (!options) |
441 | return 1; | 445 | return 1; |
@@ -462,12 +466,23 @@ static int parse_options(char *options, struct super_block *sb) | |||
462 | case Opt_resuid: | 466 | case Opt_resuid: |
463 | if (match_int(&args[0], &option)) | 467 | if (match_int(&args[0], &option)) |
464 | return 0; | 468 | return 0; |
465 | sbi->s_resuid = option; | 469 | uid = make_kuid(current_user_ns(), option); |
470 | if (!uid_valid(uid)) { | ||
471 | ext2_msg(sb, KERN_ERR, "Invalid uid value %d", option); | ||
472 | return -1; | ||
473 | |||
474 | } | ||
475 | sbi->s_resuid = uid; | ||
466 | break; | 476 | break; |
467 | case Opt_resgid: | 477 | case Opt_resgid: |
468 | if (match_int(&args[0], &option)) | 478 | if (match_int(&args[0], &option)) |
469 | return 0; | 479 | return 0; |
470 | sbi->s_resgid = option; | 480 | gid = make_kgid(current_user_ns(), option); |
481 | if (!gid_valid(gid)) { | ||
482 | ext2_msg(sb, KERN_ERR, "Invalid gid value %d", option); | ||
483 | return -1; | ||
484 | } | ||
485 | sbi->s_resgid = gid; | ||
471 | break; | 486 | break; |
472 | case Opt_sb: | 487 | case Opt_sb: |
473 | /* handled by get_sb_block() instead of here */ | 488 | /* handled by get_sb_block() instead of here */ |
@@ -841,8 +856,8 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) | |||
841 | else | 856 | else |
842 | set_opt(sbi->s_mount_opt, ERRORS_RO); | 857 | set_opt(sbi->s_mount_opt, ERRORS_RO); |
843 | 858 | ||
844 | sbi->s_resuid = le16_to_cpu(es->s_def_resuid); | 859 | sbi->s_resuid = make_kuid(&init_user_ns, le16_to_cpu(es->s_def_resuid)); |
845 | sbi->s_resgid = le16_to_cpu(es->s_def_resgid); | 860 | sbi->s_resgid = make_kgid(&init_user_ns, le16_to_cpu(es->s_def_resgid)); |
846 | 861 | ||
847 | set_opt(sbi->s_mount_opt, RESERVATION); | 862 | set_opt(sbi->s_mount_opt, RESERVATION); |
848 | 863 | ||
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index baac1b129fba..25cd60892116 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c | |||
@@ -1439,8 +1439,9 @@ static int ext3_has_free_blocks(struct ext3_sb_info *sbi, int use_reservation) | |||
1439 | free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter); | 1439 | free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter); |
1440 | root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count); | 1440 | root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count); |
1441 | if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) && | 1441 | if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) && |
1442 | !use_reservation && sbi->s_resuid != current_fsuid() && | 1442 | !use_reservation && !uid_eq(sbi->s_resuid, current_fsuid()) && |
1443 | (sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) { | 1443 | (gid_eq(sbi->s_resgid, GLOBAL_ROOT_GID) || |
1444 | !in_group_p (sbi->s_resgid))) { | ||
1444 | return 0; | 1445 | return 0; |
1445 | } | 1446 | } |
1446 | return 1; | 1447 | return 1; |
diff --git a/fs/ext3/ext3.h b/fs/ext3/ext3.h index b6515fd7e56c..7977973a24f0 100644 --- a/fs/ext3/ext3.h +++ b/fs/ext3/ext3.h | |||
@@ -243,8 +243,8 @@ struct ext3_new_group_data { | |||
243 | */ | 243 | */ |
244 | struct ext3_mount_options { | 244 | struct ext3_mount_options { |
245 | unsigned long s_mount_opt; | 245 | unsigned long s_mount_opt; |
246 | uid_t s_resuid; | 246 | kuid_t s_resuid; |
247 | gid_t s_resgid; | 247 | kgid_t s_resgid; |
248 | unsigned long s_commit_interval; | 248 | unsigned long s_commit_interval; |
249 | #ifdef CONFIG_QUOTA | 249 | #ifdef CONFIG_QUOTA |
250 | int s_jquota_fmt; | 250 | int s_jquota_fmt; |
@@ -637,8 +637,8 @@ struct ext3_sb_info { | |||
637 | struct buffer_head ** s_group_desc; | 637 | struct buffer_head ** s_group_desc; |
638 | unsigned long s_mount_opt; | 638 | unsigned long s_mount_opt; |
639 | ext3_fsblk_t s_sb_block; | 639 | ext3_fsblk_t s_sb_block; |
640 | uid_t s_resuid; | 640 | kuid_t s_resuid; |
641 | gid_t s_resgid; | 641 | kgid_t s_resgid; |
642 | unsigned short s_mount_state; | 642 | unsigned short s_mount_state; |
643 | unsigned short s_pad; | 643 | unsigned short s_pad; |
644 | int s_addr_per_block_bits; | 644 | int s_addr_per_block_bits; |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 10d7812f6021..a09790a412b1 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -2891,6 +2891,8 @@ struct inode *ext3_iget(struct super_block *sb, unsigned long ino) | |||
2891 | transaction_t *transaction; | 2891 | transaction_t *transaction; |
2892 | long ret; | 2892 | long ret; |
2893 | int block; | 2893 | int block; |
2894 | uid_t i_uid; | ||
2895 | gid_t i_gid; | ||
2894 | 2896 | ||
2895 | inode = iget_locked(sb, ino); | 2897 | inode = iget_locked(sb, ino); |
2896 | if (!inode) | 2898 | if (!inode) |
@@ -2907,12 +2909,14 @@ struct inode *ext3_iget(struct super_block *sb, unsigned long ino) | |||
2907 | bh = iloc.bh; | 2909 | bh = iloc.bh; |
2908 | raw_inode = ext3_raw_inode(&iloc); | 2910 | raw_inode = ext3_raw_inode(&iloc); |
2909 | inode->i_mode = le16_to_cpu(raw_inode->i_mode); | 2911 | inode->i_mode = le16_to_cpu(raw_inode->i_mode); |
2910 | inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); | 2912 | i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); |
2911 | inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low); | 2913 | i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low); |
2912 | if(!(test_opt (inode->i_sb, NO_UID32))) { | 2914 | if(!(test_opt (inode->i_sb, NO_UID32))) { |
2913 | inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16; | 2915 | i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16; |
2914 | inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16; | 2916 | i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16; |
2915 | } | 2917 | } |
2918 | i_uid_write(inode, i_uid); | ||
2919 | i_gid_write(inode, i_gid); | ||
2916 | set_nlink(inode, le16_to_cpu(raw_inode->i_links_count)); | 2920 | set_nlink(inode, le16_to_cpu(raw_inode->i_links_count)); |
2917 | inode->i_size = le32_to_cpu(raw_inode->i_size); | 2921 | inode->i_size = le32_to_cpu(raw_inode->i_size); |
2918 | inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime); | 2922 | inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime); |
@@ -3068,6 +3072,8 @@ static int ext3_do_update_inode(handle_t *handle, | |||
3068 | struct ext3_inode_info *ei = EXT3_I(inode); | 3072 | struct ext3_inode_info *ei = EXT3_I(inode); |
3069 | struct buffer_head *bh = iloc->bh; | 3073 | struct buffer_head *bh = iloc->bh; |
3070 | int err = 0, rc, block; | 3074 | int err = 0, rc, block; |
3075 | uid_t i_uid; | ||
3076 | gid_t i_gid; | ||
3071 | 3077 | ||
3072 | again: | 3078 | again: |
3073 | /* we can't allow multiple procs in here at once, its a bit racey */ | 3079 | /* we can't allow multiple procs in here at once, its a bit racey */ |
@@ -3080,27 +3086,29 @@ again: | |||
3080 | 3086 | ||
3081 | ext3_get_inode_flags(ei); | 3087 | ext3_get_inode_flags(ei); |
3082 | raw_inode->i_mode = cpu_to_le16(inode->i_mode); | 3088 | raw_inode->i_mode = cpu_to_le16(inode->i_mode); |
3089 | i_uid = i_uid_read(inode); | ||
3090 | i_gid = i_gid_read(inode); | ||
3083 | if(!(test_opt(inode->i_sb, NO_UID32))) { | 3091 | if(!(test_opt(inode->i_sb, NO_UID32))) { |
3084 | raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid)); | 3092 | raw_inode->i_uid_low = cpu_to_le16(low_16_bits(i_uid)); |
3085 | raw_inode->i_gid_low = cpu_to_le16(low_16_bits(inode->i_gid)); | 3093 | raw_inode->i_gid_low = cpu_to_le16(low_16_bits(i_gid)); |
3086 | /* | 3094 | /* |
3087 | * Fix up interoperability with old kernels. Otherwise, old inodes get | 3095 | * Fix up interoperability with old kernels. Otherwise, old inodes get |
3088 | * re-used with the upper 16 bits of the uid/gid intact | 3096 | * re-used with the upper 16 bits of the uid/gid intact |
3089 | */ | 3097 | */ |
3090 | if(!ei->i_dtime) { | 3098 | if(!ei->i_dtime) { |
3091 | raw_inode->i_uid_high = | 3099 | raw_inode->i_uid_high = |
3092 | cpu_to_le16(high_16_bits(inode->i_uid)); | 3100 | cpu_to_le16(high_16_bits(i_uid)); |
3093 | raw_inode->i_gid_high = | 3101 | raw_inode->i_gid_high = |
3094 | cpu_to_le16(high_16_bits(inode->i_gid)); | 3102 | cpu_to_le16(high_16_bits(i_gid)); |
3095 | } else { | 3103 | } else { |
3096 | raw_inode->i_uid_high = 0; | 3104 | raw_inode->i_uid_high = 0; |
3097 | raw_inode->i_gid_high = 0; | 3105 | raw_inode->i_gid_high = 0; |
3098 | } | 3106 | } |
3099 | } else { | 3107 | } else { |
3100 | raw_inode->i_uid_low = | 3108 | raw_inode->i_uid_low = |
3101 | cpu_to_le16(fs_high2lowuid(inode->i_uid)); | 3109 | cpu_to_le16(fs_high2lowuid(i_uid)); |
3102 | raw_inode->i_gid_low = | 3110 | raw_inode->i_gid_low = |
3103 | cpu_to_le16(fs_high2lowgid(inode->i_gid)); | 3111 | cpu_to_le16(fs_high2lowgid(i_gid)); |
3104 | raw_inode->i_uid_high = 0; | 3112 | raw_inode->i_uid_high = 0; |
3105 | raw_inode->i_gid_high = 0; | 3113 | raw_inode->i_gid_high = 0; |
3106 | } | 3114 | } |
@@ -3262,8 +3270,8 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr) | |||
3262 | 3270 | ||
3263 | if (is_quota_modification(inode, attr)) | 3271 | if (is_quota_modification(inode, attr)) |
3264 | dquot_initialize(inode); | 3272 | dquot_initialize(inode); |
3265 | if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || | 3273 | if ((ia_valid & ATTR_UID && !uid_eq(attr->ia_uid, inode->i_uid)) || |
3266 | (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { | 3274 | (ia_valid & ATTR_GID && !gid_eq(attr->ia_gid, inode->i_gid))) { |
3267 | handle_t *handle; | 3275 | handle_t *handle; |
3268 | 3276 | ||
3269 | /* (user+group)*(old+new) structure, inode write (sb, | 3277 | /* (user+group)*(old+new) structure, inode write (sb, |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index cf0b5921cf0f..94ef7e616129 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -617,13 +617,15 @@ static int ext3_show_options(struct seq_file *seq, struct dentry *root) | |||
617 | seq_puts(seq, ",grpid"); | 617 | seq_puts(seq, ",grpid"); |
618 | if (!test_opt(sb, GRPID) && (def_mount_opts & EXT3_DEFM_BSDGROUPS)) | 618 | if (!test_opt(sb, GRPID) && (def_mount_opts & EXT3_DEFM_BSDGROUPS)) |
619 | seq_puts(seq, ",nogrpid"); | 619 | seq_puts(seq, ",nogrpid"); |
620 | if (sbi->s_resuid != EXT3_DEF_RESUID || | 620 | if (!uid_eq(sbi->s_resuid, make_kuid(&init_user_ns, EXT3_DEF_RESUID)) || |
621 | le16_to_cpu(es->s_def_resuid) != EXT3_DEF_RESUID) { | 621 | le16_to_cpu(es->s_def_resuid) != EXT3_DEF_RESUID) { |
622 | seq_printf(seq, ",resuid=%u", sbi->s_resuid); | 622 | seq_printf(seq, ",resuid=%u", |
623 | from_kuid_munged(&init_user_ns, sbi->s_resuid)); | ||
623 | } | 624 | } |
624 | if (sbi->s_resgid != EXT3_DEF_RESGID || | 625 | if (!gid_eq(sbi->s_resgid, make_kgid(&init_user_ns, EXT3_DEF_RESGID)) || |
625 | le16_to_cpu(es->s_def_resgid) != EXT3_DEF_RESGID) { | 626 | le16_to_cpu(es->s_def_resgid) != EXT3_DEF_RESGID) { |
626 | seq_printf(seq, ",resgid=%u", sbi->s_resgid); | 627 | seq_printf(seq, ",resgid=%u", |
628 | from_kgid_munged(&init_user_ns, sbi->s_resgid)); | ||
627 | } | 629 | } |
628 | if (test_opt(sb, ERRORS_RO)) { | 630 | if (test_opt(sb, ERRORS_RO)) { |
629 | int def_errors = le16_to_cpu(es->s_errors); | 631 | int def_errors = le16_to_cpu(es->s_errors); |
@@ -967,6 +969,8 @@ static int parse_options (char *options, struct super_block *sb, | |||
967 | substring_t args[MAX_OPT_ARGS]; | 969 | substring_t args[MAX_OPT_ARGS]; |
968 | int data_opt = 0; | 970 | int data_opt = 0; |
969 | int option; | 971 | int option; |
972 | kuid_t uid; | ||
973 | kgid_t gid; | ||
970 | #ifdef CONFIG_QUOTA | 974 | #ifdef CONFIG_QUOTA |
971 | int qfmt; | 975 | int qfmt; |
972 | #endif | 976 | #endif |
@@ -1000,12 +1004,23 @@ static int parse_options (char *options, struct super_block *sb, | |||
1000 | case Opt_resuid: | 1004 | case Opt_resuid: |
1001 | if (match_int(&args[0], &option)) | 1005 | if (match_int(&args[0], &option)) |
1002 | return 0; | 1006 | return 0; |
1003 | sbi->s_resuid = option; | 1007 | uid = make_kuid(current_user_ns(), option); |
1008 | if (!uid_valid(uid)) { | ||
1009 | ext3_msg(sb, KERN_ERR, "Invalid uid value %d", option); | ||
1010 | return -1; | ||
1011 | |||
1012 | } | ||
1013 | sbi->s_resuid = uid; | ||
1004 | break; | 1014 | break; |
1005 | case Opt_resgid: | 1015 | case Opt_resgid: |
1006 | if (match_int(&args[0], &option)) | 1016 | if (match_int(&args[0], &option)) |
1007 | return 0; | 1017 | return 0; |
1008 | sbi->s_resgid = option; | 1018 | gid = make_kgid(current_user_ns(), option); |
1019 | if (!gid_valid(gid)) { | ||
1020 | ext3_msg(sb, KERN_ERR, "Invalid gid value %d", option); | ||
1021 | return -1; | ||
1022 | } | ||
1023 | sbi->s_resgid = gid; | ||
1009 | break; | 1024 | break; |
1010 | case Opt_sb: | 1025 | case Opt_sb: |
1011 | /* handled by get_sb_block() instead of here */ | 1026 | /* handled by get_sb_block() instead of here */ |
@@ -1651,8 +1666,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) | |||
1651 | } | 1666 | } |
1652 | sb->s_fs_info = sbi; | 1667 | sb->s_fs_info = sbi; |
1653 | sbi->s_mount_opt = 0; | 1668 | sbi->s_mount_opt = 0; |
1654 | sbi->s_resuid = EXT3_DEF_RESUID; | 1669 | sbi->s_resuid = make_kuid(&init_user_ns, EXT3_DEF_RESUID); |
1655 | sbi->s_resgid = EXT3_DEF_RESGID; | 1670 | sbi->s_resgid = make_kgid(&init_user_ns, EXT3_DEF_RESGID); |
1656 | sbi->s_sb_block = sb_block; | 1671 | sbi->s_sb_block = sb_block; |
1657 | 1672 | ||
1658 | blocksize = sb_min_blocksize(sb, EXT3_MIN_BLOCK_SIZE); | 1673 | blocksize = sb_min_blocksize(sb, EXT3_MIN_BLOCK_SIZE); |
@@ -1716,8 +1731,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) | |||
1716 | else | 1731 | else |
1717 | set_opt(sbi->s_mount_opt, ERRORS_RO); | 1732 | set_opt(sbi->s_mount_opt, ERRORS_RO); |
1718 | 1733 | ||
1719 | sbi->s_resuid = le16_to_cpu(es->s_def_resuid); | 1734 | sbi->s_resuid = make_kuid(&init_user_ns, le16_to_cpu(es->s_def_resuid)); |
1720 | sbi->s_resgid = le16_to_cpu(es->s_def_resgid); | 1735 | sbi->s_resgid = make_kgid(&init_user_ns, le16_to_cpu(es->s_def_resgid)); |
1721 | 1736 | ||
1722 | /* enable barriers by default */ | 1737 | /* enable barriers by default */ |
1723 | set_opt(sbi->s_mount_opt, BARRIER); | 1738 | set_opt(sbi->s_mount_opt, BARRIER); |
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 4bbd07a6fa18..c45c41129a35 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -461,8 +461,8 @@ static int ext4_has_free_clusters(struct ext4_sb_info *sbi, | |||
461 | return 1; | 461 | return 1; |
462 | 462 | ||
463 | /* Hm, nope. Are (enough) root reserved clusters available? */ | 463 | /* Hm, nope. Are (enough) root reserved clusters available? */ |
464 | if (sbi->s_resuid == current_fsuid() || | 464 | if (uid_eq(sbi->s_resuid, current_fsuid()) || |
465 | ((sbi->s_resgid != 0) && in_group_p(sbi->s_resgid)) || | 465 | (!gid_eq(sbi->s_resgid, GLOBAL_ROOT_GID) && in_group_p(sbi->s_resgid)) || |
466 | capable(CAP_SYS_RESOURCE) || | 466 | capable(CAP_SYS_RESOURCE) || |
467 | (flags & EXT4_MB_USE_ROOT_BLOCKS)) { | 467 | (flags & EXT4_MB_USE_ROOT_BLOCKS)) { |
468 | 468 | ||
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 0e01e90add8b..c21b1de51afb 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1153,8 +1153,8 @@ struct ext4_sb_info { | |||
1153 | unsigned int s_mount_flags; | 1153 | unsigned int s_mount_flags; |
1154 | unsigned int s_def_mount_opt; | 1154 | unsigned int s_def_mount_opt; |
1155 | ext4_fsblk_t s_sb_block; | 1155 | ext4_fsblk_t s_sb_block; |
1156 | uid_t s_resuid; | 1156 | kuid_t s_resuid; |
1157 | gid_t s_resgid; | 1157 | kgid_t s_resgid; |
1158 | unsigned short s_mount_state; | 1158 | unsigned short s_mount_state; |
1159 | unsigned short s_pad; | 1159 | unsigned short s_pad; |
1160 | int s_addr_per_block_bits; | 1160 | int s_addr_per_block_bits; |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 409c2ee7750a..9f9acac6c43f 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -808,8 +808,8 @@ got: | |||
808 | } | 808 | } |
809 | if (owner) { | 809 | if (owner) { |
810 | inode->i_mode = mode; | 810 | inode->i_mode = mode; |
811 | inode->i_uid = owner[0]; | 811 | i_uid_write(inode, owner[0]); |
812 | inode->i_gid = owner[1]; | 812 | i_gid_write(inode, owner[1]); |
813 | } else if (test_opt(sb, GRPID)) { | 813 | } else if (test_opt(sb, GRPID)) { |
814 | inode->i_mode = mode; | 814 | inode->i_mode = mode; |
815 | inode->i_uid = current_fsuid(); | 815 | inode->i_uid = current_fsuid(); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c77b0bd2c711..07eaf565fdcb 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -3630,6 +3630,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
3630 | journal_t *journal = EXT4_SB(sb)->s_journal; | 3630 | journal_t *journal = EXT4_SB(sb)->s_journal; |
3631 | long ret; | 3631 | long ret; |
3632 | int block; | 3632 | int block; |
3633 | uid_t i_uid; | ||
3634 | gid_t i_gid; | ||
3633 | 3635 | ||
3634 | inode = iget_locked(sb, ino); | 3636 | inode = iget_locked(sb, ino); |
3635 | if (!inode) | 3637 | if (!inode) |
@@ -3645,12 +3647,14 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
3645 | goto bad_inode; | 3647 | goto bad_inode; |
3646 | raw_inode = ext4_raw_inode(&iloc); | 3648 | raw_inode = ext4_raw_inode(&iloc); |
3647 | inode->i_mode = le16_to_cpu(raw_inode->i_mode); | 3649 | inode->i_mode = le16_to_cpu(raw_inode->i_mode); |
3648 | inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); | 3650 | i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); |
3649 | inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low); | 3651 | i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low); |
3650 | if (!(test_opt(inode->i_sb, NO_UID32))) { | 3652 | if (!(test_opt(inode->i_sb, NO_UID32))) { |
3651 | inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16; | 3653 | i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16; |
3652 | inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16; | 3654 | i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16; |
3653 | } | 3655 | } |
3656 | i_uid_write(inode, i_uid); | ||
3657 | i_gid_write(inode, i_gid); | ||
3654 | set_nlink(inode, le16_to_cpu(raw_inode->i_links_count)); | 3658 | set_nlink(inode, le16_to_cpu(raw_inode->i_links_count)); |
3655 | 3659 | ||
3656 | ext4_clear_state_flags(ei); /* Only relevant on 32-bit archs */ | 3660 | ext4_clear_state_flags(ei); /* Only relevant on 32-bit archs */ |
@@ -3870,6 +3874,8 @@ static int ext4_do_update_inode(handle_t *handle, | |||
3870 | struct ext4_inode_info *ei = EXT4_I(inode); | 3874 | struct ext4_inode_info *ei = EXT4_I(inode); |
3871 | struct buffer_head *bh = iloc->bh; | 3875 | struct buffer_head *bh = iloc->bh; |
3872 | int err = 0, rc, block; | 3876 | int err = 0, rc, block; |
3877 | uid_t i_uid; | ||
3878 | gid_t i_gid; | ||
3873 | 3879 | ||
3874 | /* For fields not not tracking in the in-memory inode, | 3880 | /* For fields not not tracking in the in-memory inode, |
3875 | * initialise them to zero for new inodes. */ | 3881 | * initialise them to zero for new inodes. */ |
@@ -3878,27 +3884,27 @@ static int ext4_do_update_inode(handle_t *handle, | |||
3878 | 3884 | ||
3879 | ext4_get_inode_flags(ei); | 3885 | ext4_get_inode_flags(ei); |
3880 | raw_inode->i_mode = cpu_to_le16(inode->i_mode); | 3886 | raw_inode->i_mode = cpu_to_le16(inode->i_mode); |
3887 | i_uid = i_uid_read(inode); | ||
3888 | i_gid = i_gid_read(inode); | ||
3881 | if (!(test_opt(inode->i_sb, NO_UID32))) { | 3889 | if (!(test_opt(inode->i_sb, NO_UID32))) { |
3882 | raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid)); | 3890 | raw_inode->i_uid_low = cpu_to_le16(low_16_bits(i_uid)); |
3883 | raw_inode->i_gid_low = cpu_to_le16(low_16_bits(inode->i_gid)); | 3891 | raw_inode->i_gid_low = cpu_to_le16(low_16_bits(i_gid)); |
3884 | /* | 3892 | /* |
3885 | * Fix up interoperability with old kernels. Otherwise, old inodes get | 3893 | * Fix up interoperability with old kernels. Otherwise, old inodes get |
3886 | * re-used with the upper 16 bits of the uid/gid intact | 3894 | * re-used with the upper 16 bits of the uid/gid intact |
3887 | */ | 3895 | */ |
3888 | if (!ei->i_dtime) { | 3896 | if (!ei->i_dtime) { |
3889 | raw_inode->i_uid_high = | 3897 | raw_inode->i_uid_high = |
3890 | cpu_to_le16(high_16_bits(inode->i_uid)); | 3898 | cpu_to_le16(high_16_bits(i_uid)); |
3891 | raw_inode->i_gid_high = | 3899 | raw_inode->i_gid_high = |
3892 | cpu_to_le16(high_16_bits(inode->i_gid)); | 3900 | cpu_to_le16(high_16_bits(i_gid)); |
3893 | } else { | 3901 | } else { |
3894 | raw_inode->i_uid_high = 0; | 3902 | raw_inode->i_uid_high = 0; |
3895 | raw_inode->i_gid_high = 0; | 3903 | raw_inode->i_gid_high = 0; |
3896 | } | 3904 | } |
3897 | } else { | 3905 | } else { |
3898 | raw_inode->i_uid_low = | 3906 | raw_inode->i_uid_low = cpu_to_le16(fs_high2lowuid(i_uid)); |
3899 | cpu_to_le16(fs_high2lowuid(inode->i_uid)); | 3907 | raw_inode->i_gid_low = cpu_to_le16(fs_high2lowgid(i_gid)); |
3900 | raw_inode->i_gid_low = | ||
3901 | cpu_to_le16(fs_high2lowgid(inode->i_gid)); | ||
3902 | raw_inode->i_uid_high = 0; | 3908 | raw_inode->i_uid_high = 0; |
3903 | raw_inode->i_gid_high = 0; | 3909 | raw_inode->i_gid_high = 0; |
3904 | } | 3910 | } |
@@ -4084,8 +4090,8 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) | |||
4084 | 4090 | ||
4085 | if (is_quota_modification(inode, attr)) | 4091 | if (is_quota_modification(inode, attr)) |
4086 | dquot_initialize(inode); | 4092 | dquot_initialize(inode); |
4087 | if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || | 4093 | if ((ia_valid & ATTR_UID && !uid_eq(attr->ia_uid, inode->i_uid)) || |
4088 | (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { | 4094 | (ia_valid & ATTR_GID && !gid_eq(attr->ia_gid, inode->i_gid))) { |
4089 | handle_t *handle; | 4095 | handle_t *handle; |
4090 | 4096 | ||
4091 | /* (user+group)*(old+new) structure, inode write (sb, | 4097 | /* (user+group)*(old+new) structure, inode write (sb, |
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index f39f80f8f2c5..f1bb32ec0169 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c | |||
@@ -466,8 +466,8 @@ int ext4_ext_migrate(struct inode *inode) | |||
466 | } | 466 | } |
467 | goal = (((inode->i_ino - 1) / EXT4_INODES_PER_GROUP(inode->i_sb)) * | 467 | goal = (((inode->i_ino - 1) / EXT4_INODES_PER_GROUP(inode->i_sb)) * |
468 | EXT4_INODES_PER_GROUP(inode->i_sb)) + 1; | 468 | EXT4_INODES_PER_GROUP(inode->i_sb)) + 1; |
469 | owner[0] = inode->i_uid; | 469 | owner[0] = i_uid_read(inode); |
470 | owner[1] = inode->i_gid; | 470 | owner[1] = i_gid_read(inode); |
471 | tmp_inode = ext4_new_inode(handle, inode->i_sb->s_root->d_inode, | 471 | tmp_inode = ext4_new_inode(handle, inode->i_sb->s_root->d_inode, |
472 | S_IFREG, NULL, goal, owner); | 472 | S_IFREG, NULL, goal, owner); |
473 | if (IS_ERR(tmp_inode)) { | 473 | if (IS_ERR(tmp_inode)) { |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index e1fb1d5de58e..436b4223df66 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -1448,6 +1448,8 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, | |||
1448 | { | 1448 | { |
1449 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 1449 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
1450 | const struct mount_opts *m; | 1450 | const struct mount_opts *m; |
1451 | kuid_t uid; | ||
1452 | kgid_t gid; | ||
1451 | int arg = 0; | 1453 | int arg = 0; |
1452 | 1454 | ||
1453 | #ifdef CONFIG_QUOTA | 1455 | #ifdef CONFIG_QUOTA |
@@ -1474,10 +1476,20 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, | |||
1474 | "Ignoring removed %s option", opt); | 1476 | "Ignoring removed %s option", opt); |
1475 | return 1; | 1477 | return 1; |
1476 | case Opt_resuid: | 1478 | case Opt_resuid: |
1477 | sbi->s_resuid = arg; | 1479 | uid = make_kuid(current_user_ns(), arg); |
1480 | if (!uid_valid(uid)) { | ||
1481 | ext4_msg(sb, KERN_ERR, "Invalid uid value %d", arg); | ||
1482 | return -1; | ||
1483 | } | ||
1484 | sbi->s_resuid = uid; | ||
1478 | return 1; | 1485 | return 1; |
1479 | case Opt_resgid: | 1486 | case Opt_resgid: |
1480 | sbi->s_resgid = arg; | 1487 | gid = make_kgid(current_user_ns(), arg); |
1488 | if (!gid_valid(gid)) { | ||
1489 | ext4_msg(sb, KERN_ERR, "Invalid gid value %d", arg); | ||
1490 | return -1; | ||
1491 | } | ||
1492 | sbi->s_resgid = gid; | ||
1481 | return 1; | 1493 | return 1; |
1482 | case Opt_abort: | 1494 | case Opt_abort: |
1483 | sbi->s_mount_flags |= EXT4_MF_FS_ABORTED; | 1495 | sbi->s_mount_flags |= EXT4_MF_FS_ABORTED; |
@@ -1732,12 +1744,14 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb, | |||
1732 | SEQ_OPTS_PRINT("%s", token2str(m->token)); | 1744 | SEQ_OPTS_PRINT("%s", token2str(m->token)); |
1733 | } | 1745 | } |
1734 | 1746 | ||
1735 | if (nodefs || sbi->s_resuid != EXT4_DEF_RESUID || | 1747 | if (nodefs || !uid_eq(sbi->s_resuid, make_kuid(&init_user_ns, EXT4_DEF_RESUID)) || |
1736 | le16_to_cpu(es->s_def_resuid) != EXT4_DEF_RESUID) | 1748 | le16_to_cpu(es->s_def_resuid) != EXT4_DEF_RESUID) |
1737 | SEQ_OPTS_PRINT("resuid=%u", sbi->s_resuid); | 1749 | SEQ_OPTS_PRINT("resuid=%u", |
1738 | if (nodefs || sbi->s_resgid != EXT4_DEF_RESGID || | 1750 | from_kuid_munged(&init_user_ns, sbi->s_resuid)); |
1751 | if (nodefs || !gid_eq(sbi->s_resgid, make_kgid(&init_user_ns, EXT4_DEF_RESGID)) || | ||
1739 | le16_to_cpu(es->s_def_resgid) != EXT4_DEF_RESGID) | 1752 | le16_to_cpu(es->s_def_resgid) != EXT4_DEF_RESGID) |
1740 | SEQ_OPTS_PRINT("resgid=%u", sbi->s_resgid); | 1753 | SEQ_OPTS_PRINT("resgid=%u", |
1754 | from_kgid_munged(&init_user_ns, sbi->s_resgid)); | ||
1741 | def_errors = nodefs ? -1 : le16_to_cpu(es->s_errors); | 1755 | def_errors = nodefs ? -1 : le16_to_cpu(es->s_errors); |
1742 | if (test_opt(sb, ERRORS_RO) && def_errors != EXT4_ERRORS_RO) | 1756 | if (test_opt(sb, ERRORS_RO) && def_errors != EXT4_ERRORS_RO) |
1743 | SEQ_OPTS_PUTS("errors=remount-ro"); | 1757 | SEQ_OPTS_PUTS("errors=remount-ro"); |
@@ -2980,8 +2994,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2980 | } | 2994 | } |
2981 | sb->s_fs_info = sbi; | 2995 | sb->s_fs_info = sbi; |
2982 | sbi->s_mount_opt = 0; | 2996 | sbi->s_mount_opt = 0; |
2983 | sbi->s_resuid = EXT4_DEF_RESUID; | 2997 | sbi->s_resuid = make_kuid(&init_user_ns, EXT4_DEF_RESUID); |
2984 | sbi->s_resgid = EXT4_DEF_RESGID; | 2998 | sbi->s_resgid = make_kgid(&init_user_ns, EXT4_DEF_RESGID); |
2985 | sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS; | 2999 | sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS; |
2986 | sbi->s_sb_block = sb_block; | 3000 | sbi->s_sb_block = sb_block; |
2987 | if (sb->s_bdev->bd_part) | 3001 | if (sb->s_bdev->bd_part) |
@@ -3060,8 +3074,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3060 | if (def_mount_opts & EXT4_DEFM_DISCARD) | 3074 | if (def_mount_opts & EXT4_DEFM_DISCARD) |
3061 | set_opt(sb, DISCARD); | 3075 | set_opt(sb, DISCARD); |
3062 | 3076 | ||
3063 | sbi->s_resuid = le16_to_cpu(es->s_def_resuid); | 3077 | sbi->s_resuid = make_kuid(&init_user_ns, le16_to_cpu(es->s_def_resuid)); |
3064 | sbi->s_resgid = le16_to_cpu(es->s_def_resgid); | 3078 | sbi->s_resgid = make_kgid(&init_user_ns, le16_to_cpu(es->s_def_resgid)); |
3065 | sbi->s_commit_interval = JBD2_DEFAULT_MAX_COMMIT_AGE * HZ; | 3079 | sbi->s_commit_interval = JBD2_DEFAULT_MAX_COMMIT_AGE * HZ; |
3066 | sbi->s_min_batch_time = EXT4_DEF_MIN_BATCH_TIME; | 3080 | sbi->s_min_batch_time = EXT4_DEF_MIN_BATCH_TIME; |
3067 | sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME; | 3081 | sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME; |
@@ -4213,8 +4227,8 @@ static int ext4_unfreeze(struct super_block *sb) | |||
4213 | struct ext4_mount_options { | 4227 | struct ext4_mount_options { |
4214 | unsigned long s_mount_opt; | 4228 | unsigned long s_mount_opt; |
4215 | unsigned long s_mount_opt2; | 4229 | unsigned long s_mount_opt2; |
4216 | uid_t s_resuid; | 4230 | kuid_t s_resuid; |
4217 | gid_t s_resgid; | 4231 | kgid_t s_resgid; |
4218 | unsigned long s_commit_interval; | 4232 | unsigned long s_commit_interval; |
4219 | u32 s_min_batch_time, s_max_batch_time; | 4233 | u32 s_min_batch_time, s_max_batch_time; |
4220 | #ifdef CONFIG_QUOTA | 4234 | #ifdef CONFIG_QUOTA |
diff --git a/fs/fcntl.c b/fs/fcntl.c index 75e7c1f3a080..d078b75572a7 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -532,9 +532,9 @@ static inline int sigio_perm(struct task_struct *p, | |||
532 | 532 | ||
533 | rcu_read_lock(); | 533 | rcu_read_lock(); |
534 | cred = __task_cred(p); | 534 | cred = __task_cred(p); |
535 | ret = ((fown->euid == 0 || | 535 | ret = ((uid_eq(fown->euid, GLOBAL_ROOT_UID) || |
536 | fown->euid == cred->suid || fown->euid == cred->uid || | 536 | uid_eq(fown->euid, cred->suid) || uid_eq(fown->euid, cred->uid) || |
537 | fown->uid == cred->suid || fown->uid == cred->uid) && | 537 | uid_eq(fown->uid, cred->suid) || uid_eq(fown->uid, cred->uid)) && |
538 | !security_file_send_sigiotask(p, fown, sig)); | 538 | !security_file_send_sigiotask(p, fown, sig)); |
539 | rcu_read_unlock(); | 539 | rcu_read_unlock(); |
540 | return ret; | 540 | return ret; |
diff --git a/fs/inode.c b/fs/inode.c index 9f4f5fecc096..deb72f6c2b4f 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -135,8 +135,8 @@ int inode_init_always(struct super_block *sb, struct inode *inode) | |||
135 | inode->i_fop = &empty_fops; | 135 | inode->i_fop = &empty_fops; |
136 | inode->__i_nlink = 1; | 136 | inode->__i_nlink = 1; |
137 | inode->i_opflags = 0; | 137 | inode->i_opflags = 0; |
138 | inode->i_uid = 0; | 138 | i_uid_write(inode, 0); |
139 | inode->i_gid = 0; | 139 | i_gid_write(inode, 0); |
140 | atomic_set(&inode->i_writecount, 0); | 140 | atomic_set(&inode->i_writecount, 0); |
141 | inode->i_size = 0; | 141 | inode->i_size = 0; |
142 | inode->i_blocks = 0; | 142 | inode->i_blocks = 0; |
@@ -1732,11 +1732,9 @@ EXPORT_SYMBOL(inode_init_owner); | |||
1732 | */ | 1732 | */ |
1733 | bool inode_owner_or_capable(const struct inode *inode) | 1733 | bool inode_owner_or_capable(const struct inode *inode) |
1734 | { | 1734 | { |
1735 | struct user_namespace *ns = inode_userns(inode); | 1735 | if (uid_eq(current_fsuid(), inode->i_uid)) |
1736 | |||
1737 | if (current_user_ns() == ns && current_fsuid() == inode->i_uid) | ||
1738 | return true; | 1736 | return true; |
1739 | if (ns_capable(ns, CAP_FOWNER)) | 1737 | if (inode_capable(inode, CAP_FOWNER)) |
1740 | return true; | 1738 | return true; |
1741 | return false; | 1739 | return false; |
1742 | } | 1740 | } |
diff --git a/fs/ioprio.c b/fs/ioprio.c index 0f1b9515213b..5e6dbe8958fc 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c | |||
@@ -37,8 +37,8 @@ int set_task_ioprio(struct task_struct *task, int ioprio) | |||
37 | 37 | ||
38 | rcu_read_lock(); | 38 | rcu_read_lock(); |
39 | tcred = __task_cred(task); | 39 | tcred = __task_cred(task); |
40 | if (tcred->uid != cred->euid && | 40 | if (!uid_eq(tcred->uid, cred->euid) && |
41 | tcred->uid != cred->uid && !capable(CAP_SYS_NICE)) { | 41 | !uid_eq(tcred->uid, cred->uid) && !capable(CAP_SYS_NICE)) { |
42 | rcu_read_unlock(); | 42 | rcu_read_unlock(); |
43 | return -EPERM; | 43 | return -EPERM; |
44 | } | 44 | } |
@@ -65,6 +65,7 @@ SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio) | |||
65 | struct task_struct *p, *g; | 65 | struct task_struct *p, *g; |
66 | struct user_struct *user; | 66 | struct user_struct *user; |
67 | struct pid *pgrp; | 67 | struct pid *pgrp; |
68 | kuid_t uid; | ||
68 | int ret; | 69 | int ret; |
69 | 70 | ||
70 | switch (class) { | 71 | switch (class) { |
@@ -110,16 +111,19 @@ SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio) | |||
110 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); | 111 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); |
111 | break; | 112 | break; |
112 | case IOPRIO_WHO_USER: | 113 | case IOPRIO_WHO_USER: |
114 | uid = make_kuid(current_user_ns(), who); | ||
115 | if (!uid_valid(uid)) | ||
116 | break; | ||
113 | if (!who) | 117 | if (!who) |
114 | user = current_user(); | 118 | user = current_user(); |
115 | else | 119 | else |
116 | user = find_user(who); | 120 | user = find_user(uid); |
117 | 121 | ||
118 | if (!user) | 122 | if (!user) |
119 | break; | 123 | break; |
120 | 124 | ||
121 | do_each_thread(g, p) { | 125 | do_each_thread(g, p) { |
122 | if (__task_cred(p)->uid != who) | 126 | if (!uid_eq(task_uid(p), uid)) |
123 | continue; | 127 | continue; |
124 | ret = set_task_ioprio(p, ioprio); | 128 | ret = set_task_ioprio(p, ioprio); |
125 | if (ret) | 129 | if (ret) |
@@ -174,6 +178,7 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who) | |||
174 | struct task_struct *g, *p; | 178 | struct task_struct *g, *p; |
175 | struct user_struct *user; | 179 | struct user_struct *user; |
176 | struct pid *pgrp; | 180 | struct pid *pgrp; |
181 | kuid_t uid; | ||
177 | int ret = -ESRCH; | 182 | int ret = -ESRCH; |
178 | int tmpio; | 183 | int tmpio; |
179 | 184 | ||
@@ -203,16 +208,17 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who) | |||
203 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); | 208 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); |
204 | break; | 209 | break; |
205 | case IOPRIO_WHO_USER: | 210 | case IOPRIO_WHO_USER: |
211 | uid = make_kuid(current_user_ns(), who); | ||
206 | if (!who) | 212 | if (!who) |
207 | user = current_user(); | 213 | user = current_user(); |
208 | else | 214 | else |
209 | user = find_user(who); | 215 | user = find_user(uid); |
210 | 216 | ||
211 | if (!user) | 217 | if (!user) |
212 | break; | 218 | break; |
213 | 219 | ||
214 | do_each_thread(g, p) { | 220 | do_each_thread(g, p) { |
215 | if (__task_cred(p)->uid != user->uid) | 221 | if (!uid_eq(task_uid(p), user->uid)) |
216 | continue; | 222 | continue; |
217 | tmpio = get_task_ioprio(p); | 223 | tmpio = get_task_ioprio(p); |
218 | if (tmpio < 0) | 224 | if (tmpio < 0) |
diff --git a/fs/locks.c b/fs/locks.c index 0d68f1f81799..4f441e46cef4 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -1446,7 +1446,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp) | |||
1446 | struct inode *inode = dentry->d_inode; | 1446 | struct inode *inode = dentry->d_inode; |
1447 | int error; | 1447 | int error; |
1448 | 1448 | ||
1449 | if ((current_fsuid() != inode->i_uid) && !capable(CAP_LEASE)) | 1449 | if ((!uid_eq(current_fsuid(), inode->i_uid)) && !capable(CAP_LEASE)) |
1450 | return -EACCES; | 1450 | return -EACCES; |
1451 | if (!S_ISREG(inode->i_mode)) | 1451 | if (!S_ISREG(inode->i_mode)) |
1452 | return -EINVAL; | 1452 | return -EINVAL; |
diff --git a/fs/namei.c b/fs/namei.c index f9e883c1b856..e70ebab9624b 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -218,10 +218,7 @@ static int acl_permission_check(struct inode *inode, int mask) | |||
218 | { | 218 | { |
219 | unsigned int mode = inode->i_mode; | 219 | unsigned int mode = inode->i_mode; |
220 | 220 | ||
221 | if (current_user_ns() != inode_userns(inode)) | 221 | if (likely(uid_eq(current_fsuid(), inode->i_uid))) |
222 | goto other_perms; | ||
223 | |||
224 | if (likely(current_fsuid() == inode->i_uid)) | ||
225 | mode >>= 6; | 222 | mode >>= 6; |
226 | else { | 223 | else { |
227 | if (IS_POSIXACL(inode) && (mode & S_IRWXG)) { | 224 | if (IS_POSIXACL(inode) && (mode & S_IRWXG)) { |
@@ -234,7 +231,6 @@ static int acl_permission_check(struct inode *inode, int mask) | |||
234 | mode >>= 3; | 231 | mode >>= 3; |
235 | } | 232 | } |
236 | 233 | ||
237 | other_perms: | ||
238 | /* | 234 | /* |
239 | * If the DACs are ok we don't need any capability check. | 235 | * If the DACs are ok we don't need any capability check. |
240 | */ | 236 | */ |
@@ -270,10 +266,10 @@ int generic_permission(struct inode *inode, int mask) | |||
270 | 266 | ||
271 | if (S_ISDIR(inode->i_mode)) { | 267 | if (S_ISDIR(inode->i_mode)) { |
272 | /* DACs are overridable for directories */ | 268 | /* DACs are overridable for directories */ |
273 | if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE)) | 269 | if (inode_capable(inode, CAP_DAC_OVERRIDE)) |
274 | return 0; | 270 | return 0; |
275 | if (!(mask & MAY_WRITE)) | 271 | if (!(mask & MAY_WRITE)) |
276 | if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH)) | 272 | if (inode_capable(inode, CAP_DAC_READ_SEARCH)) |
277 | return 0; | 273 | return 0; |
278 | return -EACCES; | 274 | return -EACCES; |
279 | } | 275 | } |
@@ -283,7 +279,7 @@ int generic_permission(struct inode *inode, int mask) | |||
283 | * at least one exec bit set. | 279 | * at least one exec bit set. |
284 | */ | 280 | */ |
285 | if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO)) | 281 | if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO)) |
286 | if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE)) | 282 | if (inode_capable(inode, CAP_DAC_OVERRIDE)) |
287 | return 0; | 283 | return 0; |
288 | 284 | ||
289 | /* | 285 | /* |
@@ -291,7 +287,7 @@ int generic_permission(struct inode *inode, int mask) | |||
291 | */ | 287 | */ |
292 | mask &= MAY_READ | MAY_WRITE | MAY_EXEC; | 288 | mask &= MAY_READ | MAY_WRITE | MAY_EXEC; |
293 | if (mask == MAY_READ) | 289 | if (mask == MAY_READ) |
294 | if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH)) | 290 | if (inode_capable(inode, CAP_DAC_READ_SEARCH)) |
295 | return 0; | 291 | return 0; |
296 | 292 | ||
297 | return -EACCES; | 293 | return -EACCES; |
@@ -1934,19 +1930,15 @@ static int user_path_parent(int dfd, const char __user *path, | |||
1934 | */ | 1930 | */ |
1935 | static inline int check_sticky(struct inode *dir, struct inode *inode) | 1931 | static inline int check_sticky(struct inode *dir, struct inode *inode) |
1936 | { | 1932 | { |
1937 | uid_t fsuid = current_fsuid(); | 1933 | kuid_t fsuid = current_fsuid(); |
1938 | 1934 | ||
1939 | if (!(dir->i_mode & S_ISVTX)) | 1935 | if (!(dir->i_mode & S_ISVTX)) |
1940 | return 0; | 1936 | return 0; |
1941 | if (current_user_ns() != inode_userns(inode)) | 1937 | if (uid_eq(inode->i_uid, fsuid)) |
1942 | goto other_userns; | ||
1943 | if (inode->i_uid == fsuid) | ||
1944 | return 0; | 1938 | return 0; |
1945 | if (dir->i_uid == fsuid) | 1939 | if (uid_eq(dir->i_uid, fsuid)) |
1946 | return 0; | 1940 | return 0; |
1947 | 1941 | return !inode_capable(inode, CAP_FOWNER); | |
1948 | other_userns: | ||
1949 | return !ns_capable(inode_userns(inode), CAP_FOWNER); | ||
1950 | } | 1942 | } |
1951 | 1943 | ||
1952 | /* | 1944 | /* |
@@ -2534,8 +2526,7 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) | |||
2534 | if (error) | 2526 | if (error) |
2535 | return error; | 2527 | return error; |
2536 | 2528 | ||
2537 | if ((S_ISCHR(mode) || S_ISBLK(mode)) && | 2529 | if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD)) |
2538 | !ns_capable(inode_userns(dir), CAP_MKNOD)) | ||
2539 | return -EPERM; | 2530 | return -EPERM; |
2540 | 2531 | ||
2541 | if (!dir->i_op->mknod) | 2532 | if (!dir->i_op->mknod) |
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c index 79717a40daba..204438cc914e 100644 --- a/fs/nfsd/auth.c +++ b/fs/nfsd/auth.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> */ | 1 | /* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> */ |
2 | 2 | ||
3 | #include <linux/sched.h> | 3 | #include <linux/sched.h> |
4 | #include <linux/user_namespace.h> | ||
4 | #include "nfsd.h" | 5 | #include "nfsd.h" |
5 | #include "auth.h" | 6 | #include "auth.h" |
6 | 7 | ||
@@ -56,8 +57,8 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) | |||
56 | goto oom; | 57 | goto oom; |
57 | 58 | ||
58 | for (i = 0; i < rqgi->ngroups; i++) { | 59 | for (i = 0; i < rqgi->ngroups; i++) { |
59 | if (!GROUP_AT(rqgi, i)) | 60 | if (gid_eq(GLOBAL_ROOT_GID, GROUP_AT(rqgi, i))) |
60 | GROUP_AT(gi, i) = exp->ex_anon_gid; | 61 | GROUP_AT(gi, i) = make_kgid(&init_user_ns, exp->ex_anon_gid); |
61 | else | 62 | else |
62 | GROUP_AT(gi, i) = GROUP_AT(rqgi, i); | 63 | GROUP_AT(gi, i) = GROUP_AT(rqgi, i); |
63 | } | 64 | } |
@@ -316,7 +316,8 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode) | |||
316 | 316 | ||
317 | if (!issecure(SECURE_NO_SETUID_FIXUP)) { | 317 | if (!issecure(SECURE_NO_SETUID_FIXUP)) { |
318 | /* Clear the capabilities if we switch to a non-root user */ | 318 | /* Clear the capabilities if we switch to a non-root user */ |
319 | if (override_cred->uid) | 319 | kuid_t root_uid = make_kuid(override_cred->user_ns, 0); |
320 | if (!uid_eq(override_cred->uid, root_uid)) | ||
320 | cap_clear(override_cred->cap_effective); | 321 | cap_clear(override_cred->cap_effective); |
321 | else | 322 | else |
322 | override_cred->cap_effective = | 323 | override_cred->cap_effective = |
@@ -505,15 +506,24 @@ static int chown_common(struct path *path, uid_t user, gid_t group) | |||
505 | struct inode *inode = path->dentry->d_inode; | 506 | struct inode *inode = path->dentry->d_inode; |
506 | int error; | 507 | int error; |
507 | struct iattr newattrs; | 508 | struct iattr newattrs; |
509 | kuid_t uid; | ||
510 | kgid_t gid; | ||
511 | |||
512 | uid = make_kuid(current_user_ns(), user); | ||
513 | gid = make_kgid(current_user_ns(), group); | ||
508 | 514 | ||
509 | newattrs.ia_valid = ATTR_CTIME; | 515 | newattrs.ia_valid = ATTR_CTIME; |
510 | if (user != (uid_t) -1) { | 516 | if (user != (uid_t) -1) { |
517 | if (!uid_valid(uid)) | ||
518 | return -EINVAL; | ||
511 | newattrs.ia_valid |= ATTR_UID; | 519 | newattrs.ia_valid |= ATTR_UID; |
512 | newattrs.ia_uid = user; | 520 | newattrs.ia_uid = uid; |
513 | } | 521 | } |
514 | if (group != (gid_t) -1) { | 522 | if (group != (gid_t) -1) { |
523 | if (!gid_valid(gid)) | ||
524 | return -EINVAL; | ||
515 | newattrs.ia_valid |= ATTR_GID; | 525 | newattrs.ia_valid |= ATTR_GID; |
516 | newattrs.ia_gid = group; | 526 | newattrs.ia_gid = gid; |
517 | } | 527 | } |
518 | if (!S_ISDIR(inode->i_mode)) | 528 | if (!S_ISDIR(inode->i_mode)) |
519 | newattrs.ia_valid |= | 529 | newattrs.ia_valid |= |
diff --git a/fs/proc/array.c b/fs/proc/array.c index f9bd395b3473..dc4c5a7b9ece 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -81,6 +81,7 @@ | |||
81 | #include <linux/pid_namespace.h> | 81 | #include <linux/pid_namespace.h> |
82 | #include <linux/ptrace.h> | 82 | #include <linux/ptrace.h> |
83 | #include <linux/tracehook.h> | 83 | #include <linux/tracehook.h> |
84 | #include <linux/user_namespace.h> | ||
84 | 85 | ||
85 | #include <asm/pgtable.h> | 86 | #include <asm/pgtable.h> |
86 | #include <asm/processor.h> | 87 | #include <asm/processor.h> |
@@ -161,6 +162,7 @@ static inline const char *get_task_state(struct task_struct *tsk) | |||
161 | static inline void task_state(struct seq_file *m, struct pid_namespace *ns, | 162 | static inline void task_state(struct seq_file *m, struct pid_namespace *ns, |
162 | struct pid *pid, struct task_struct *p) | 163 | struct pid *pid, struct task_struct *p) |
163 | { | 164 | { |
165 | struct user_namespace *user_ns = current_user_ns(); | ||
164 | struct group_info *group_info; | 166 | struct group_info *group_info; |
165 | int g; | 167 | int g; |
166 | struct fdtable *fdt = NULL; | 168 | struct fdtable *fdt = NULL; |
@@ -189,8 +191,14 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, | |||
189 | task_tgid_nr_ns(p, ns), | 191 | task_tgid_nr_ns(p, ns), |
190 | pid_nr_ns(pid, ns), | 192 | pid_nr_ns(pid, ns), |
191 | ppid, tpid, | 193 | ppid, tpid, |
192 | cred->uid, cred->euid, cred->suid, cred->fsuid, | 194 | from_kuid_munged(user_ns, cred->uid), |
193 | cred->gid, cred->egid, cred->sgid, cred->fsgid); | 195 | from_kuid_munged(user_ns, cred->euid), |
196 | from_kuid_munged(user_ns, cred->suid), | ||
197 | from_kuid_munged(user_ns, cred->fsuid), | ||
198 | from_kgid_munged(user_ns, cred->gid), | ||
199 | from_kgid_munged(user_ns, cred->egid), | ||
200 | from_kgid_munged(user_ns, cred->sgid), | ||
201 | from_kgid_munged(user_ns, cred->fsgid)); | ||
194 | 202 | ||
195 | task_lock(p); | 203 | task_lock(p); |
196 | if (p->files) | 204 | if (p->files) |
@@ -205,7 +213,8 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, | |||
205 | task_unlock(p); | 213 | task_unlock(p); |
206 | 214 | ||
207 | for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++) | 215 | for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++) |
208 | seq_printf(m, "%d ", GROUP_AT(group_info, g)); | 216 | seq_printf(m, "%d ", |
217 | from_kgid_munged(user_ns, GROUP_AT(group_info, g))); | ||
209 | put_cred(cred); | 218 | put_cred(cred); |
210 | 219 | ||
211 | seq_putc(m, '\n'); | 220 | seq_putc(m, '\n'); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 57b8159f26f3..d2d3108a611c 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -81,6 +81,7 @@ | |||
81 | #include <linux/oom.h> | 81 | #include <linux/oom.h> |
82 | #include <linux/elf.h> | 82 | #include <linux/elf.h> |
83 | #include <linux/pid_namespace.h> | 83 | #include <linux/pid_namespace.h> |
84 | #include <linux/user_namespace.h> | ||
84 | #include <linux/fs_struct.h> | 85 | #include <linux/fs_struct.h> |
85 | #include <linux/slab.h> | 86 | #include <linux/slab.h> |
86 | #include <linux/flex_array.h> | 87 | #include <linux/flex_array.h> |
@@ -1561,8 +1562,8 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
1561 | generic_fillattr(inode, stat); | 1562 | generic_fillattr(inode, stat); |
1562 | 1563 | ||
1563 | rcu_read_lock(); | 1564 | rcu_read_lock(); |
1564 | stat->uid = 0; | 1565 | stat->uid = GLOBAL_ROOT_UID; |
1565 | stat->gid = 0; | 1566 | stat->gid = GLOBAL_ROOT_GID; |
1566 | task = pid_task(proc_pid(inode), PIDTYPE_PID); | 1567 | task = pid_task(proc_pid(inode), PIDTYPE_PID); |
1567 | if (task) { | 1568 | if (task) { |
1568 | if (!has_pid_permissions(pid, task, 2)) { | 1569 | if (!has_pid_permissions(pid, task, 2)) { |
@@ -1622,8 +1623,8 @@ int pid_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1622 | inode->i_gid = cred->egid; | 1623 | inode->i_gid = cred->egid; |
1623 | rcu_read_unlock(); | 1624 | rcu_read_unlock(); |
1624 | } else { | 1625 | } else { |
1625 | inode->i_uid = 0; | 1626 | inode->i_uid = GLOBAL_ROOT_UID; |
1626 | inode->i_gid = 0; | 1627 | inode->i_gid = GLOBAL_ROOT_GID; |
1627 | } | 1628 | } |
1628 | inode->i_mode &= ~(S_ISUID | S_ISGID); | 1629 | inode->i_mode &= ~(S_ISUID | S_ISGID); |
1629 | security_task_to_inode(task, inode); | 1630 | security_task_to_inode(task, inode); |
@@ -1815,8 +1816,8 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1815 | inode->i_gid = cred->egid; | 1816 | inode->i_gid = cred->egid; |
1816 | rcu_read_unlock(); | 1817 | rcu_read_unlock(); |
1817 | } else { | 1818 | } else { |
1818 | inode->i_uid = 0; | 1819 | inode->i_uid = GLOBAL_ROOT_UID; |
1819 | inode->i_gid = 0; | 1820 | inode->i_gid = GLOBAL_ROOT_GID; |
1820 | } | 1821 | } |
1821 | 1822 | ||
1822 | i_mode = S_IFLNK; | 1823 | i_mode = S_IFLNK; |
@@ -2045,8 +2046,8 @@ static int map_files_d_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
2045 | inode->i_gid = cred->egid; | 2046 | inode->i_gid = cred->egid; |
2046 | rcu_read_unlock(); | 2047 | rcu_read_unlock(); |
2047 | } else { | 2048 | } else { |
2048 | inode->i_uid = 0; | 2049 | inode->i_uid = GLOBAL_ROOT_UID; |
2049 | inode->i_gid = 0; | 2050 | inode->i_gid = GLOBAL_ROOT_GID; |
2050 | } | 2051 | } |
2051 | security_task_to_inode(task, inode); | 2052 | security_task_to_inode(task, inode); |
2052 | status = 1; | 2053 | status = 1; |
@@ -2924,6 +2925,74 @@ static int proc_tgid_io_accounting(struct task_struct *task, char *buffer) | |||
2924 | } | 2925 | } |
2925 | #endif /* CONFIG_TASK_IO_ACCOUNTING */ | 2926 | #endif /* CONFIG_TASK_IO_ACCOUNTING */ |
2926 | 2927 | ||
2928 | #ifdef CONFIG_USER_NS | ||
2929 | static int proc_id_map_open(struct inode *inode, struct file *file, | ||
2930 | struct seq_operations *seq_ops) | ||
2931 | { | ||
2932 | struct user_namespace *ns = NULL; | ||
2933 | struct task_struct *task; | ||
2934 | struct seq_file *seq; | ||
2935 | int ret = -EINVAL; | ||
2936 | |||
2937 | task = get_proc_task(inode); | ||
2938 | if (task) { | ||
2939 | rcu_read_lock(); | ||
2940 | ns = get_user_ns(task_cred_xxx(task, user_ns)); | ||
2941 | rcu_read_unlock(); | ||
2942 | put_task_struct(task); | ||
2943 | } | ||
2944 | if (!ns) | ||
2945 | goto err; | ||
2946 | |||
2947 | ret = seq_open(file, seq_ops); | ||
2948 | if (ret) | ||
2949 | goto err_put_ns; | ||
2950 | |||
2951 | seq = file->private_data; | ||
2952 | seq->private = ns; | ||
2953 | |||
2954 | return 0; | ||
2955 | err_put_ns: | ||
2956 | put_user_ns(ns); | ||
2957 | err: | ||
2958 | return ret; | ||
2959 | } | ||
2960 | |||
2961 | static int proc_id_map_release(struct inode *inode, struct file *file) | ||
2962 | { | ||
2963 | struct seq_file *seq = file->private_data; | ||
2964 | struct user_namespace *ns = seq->private; | ||
2965 | put_user_ns(ns); | ||
2966 | return seq_release(inode, file); | ||
2967 | } | ||
2968 | |||
2969 | static int proc_uid_map_open(struct inode *inode, struct file *file) | ||
2970 | { | ||
2971 | return proc_id_map_open(inode, file, &proc_uid_seq_operations); | ||
2972 | } | ||
2973 | |||
2974 | static int proc_gid_map_open(struct inode *inode, struct file *file) | ||
2975 | { | ||
2976 | return proc_id_map_open(inode, file, &proc_gid_seq_operations); | ||
2977 | } | ||
2978 | |||
2979 | static const struct file_operations proc_uid_map_operations = { | ||
2980 | .open = proc_uid_map_open, | ||
2981 | .write = proc_uid_map_write, | ||
2982 | .read = seq_read, | ||
2983 | .llseek = seq_lseek, | ||
2984 | .release = proc_id_map_release, | ||
2985 | }; | ||
2986 | |||
2987 | static const struct file_operations proc_gid_map_operations = { | ||
2988 | .open = proc_gid_map_open, | ||
2989 | .write = proc_gid_map_write, | ||
2990 | .read = seq_read, | ||
2991 | .llseek = seq_lseek, | ||
2992 | .release = proc_id_map_release, | ||
2993 | }; | ||
2994 | #endif /* CONFIG_USER_NS */ | ||
2995 | |||
2927 | static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns, | 2996 | static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns, |
2928 | struct pid *pid, struct task_struct *task) | 2997 | struct pid *pid, struct task_struct *task) |
2929 | { | 2998 | { |
@@ -3026,6 +3095,10 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
3026 | #ifdef CONFIG_HARDWALL | 3095 | #ifdef CONFIG_HARDWALL |
3027 | INF("hardwall", S_IRUGO, proc_pid_hardwall), | 3096 | INF("hardwall", S_IRUGO, proc_pid_hardwall), |
3028 | #endif | 3097 | #endif |
3098 | #ifdef CONFIG_USER_NS | ||
3099 | REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations), | ||
3100 | REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations), | ||
3101 | #endif | ||
3029 | }; | 3102 | }; |
3030 | 3103 | ||
3031 | static int proc_tgid_base_readdir(struct file * filp, | 3104 | static int proc_tgid_base_readdir(struct file * filp, |
@@ -3381,6 +3454,10 @@ static const struct pid_entry tid_base_stuff[] = { | |||
3381 | #ifdef CONFIG_HARDWALL | 3454 | #ifdef CONFIG_HARDWALL |
3382 | INF("hardwall", S_IRUGO, proc_pid_hardwall), | 3455 | INF("hardwall", S_IRUGO, proc_pid_hardwall), |
3383 | #endif | 3456 | #endif |
3457 | #ifdef CONFIG_USER_NS | ||
3458 | REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations), | ||
3459 | REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations), | ||
3460 | #endif | ||
3384 | }; | 3461 | }; |
3385 | 3462 | ||
3386 | static int proc_tid_base_readdir(struct file * filp, | 3463 | static int proc_tid_base_readdir(struct file * filp, |
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 205c92280838..554ecc54799f 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
@@ -108,8 +108,8 @@ static int proc_show_options(struct seq_file *seq, struct dentry *root) | |||
108 | struct super_block *sb = root->d_sb; | 108 | struct super_block *sb = root->d_sb; |
109 | struct pid_namespace *pid = sb->s_fs_info; | 109 | struct pid_namespace *pid = sb->s_fs_info; |
110 | 110 | ||
111 | if (pid->pid_gid) | 111 | if (!gid_eq(pid->pid_gid, GLOBAL_ROOT_GID)) |
112 | seq_printf(seq, ",gid=%lu", (unsigned long)pid->pid_gid); | 112 | seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, pid->pid_gid)); |
113 | if (pid->hide_pid != 0) | 113 | if (pid->hide_pid != 0) |
114 | seq_printf(seq, ",hidepid=%u", pid->hide_pid); | 114 | seq_printf(seq, ",hidepid=%u", pid->hide_pid); |
115 | 115 | ||
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index 21d836f40292..3476bca8f7af 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c | |||
@@ -371,9 +371,9 @@ void register_sysctl_root(struct ctl_table_root *root) | |||
371 | 371 | ||
372 | static int test_perm(int mode, int op) | 372 | static int test_perm(int mode, int op) |
373 | { | 373 | { |
374 | if (!current_euid()) | 374 | if (uid_eq(current_euid(), GLOBAL_ROOT_UID)) |
375 | mode >>= 6; | 375 | mode >>= 6; |
376 | else if (in_egroup_p(0)) | 376 | else if (in_egroup_p(GLOBAL_ROOT_GID)) |
377 | mode >>= 3; | 377 | mode >>= 3; |
378 | if ((op & ~mode & (MAY_READ|MAY_WRITE|MAY_EXEC)) == 0) | 378 | if ((op & ~mode & (MAY_READ|MAY_WRITE|MAY_EXEC)) == 0) |
379 | return 0; | 379 | return 0; |
diff --git a/fs/proc/root.c b/fs/proc/root.c index eed44bfc85db..7c30fce037c0 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -67,7 +67,7 @@ static int proc_parse_options(char *options, struct pid_namespace *pid) | |||
67 | case Opt_gid: | 67 | case Opt_gid: |
68 | if (match_int(&args[0], &option)) | 68 | if (match_int(&args[0], &option)) |
69 | return 0; | 69 | return 0; |
70 | pid->pid_gid = option; | 70 | pid->pid_gid = make_kgid(current_user_ns(), option); |
71 | break; | 71 | break; |
72 | case Opt_hidepid: | 72 | case Opt_hidepid: |
73 | if (match_int(&args[0], &option)) | 73 | if (match_int(&args[0], &option)) |
@@ -138,8 +138,8 @@ static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * sta | |||
138 | tmp.st_nlink = stat->nlink; | 138 | tmp.st_nlink = stat->nlink; |
139 | if (tmp.st_nlink != stat->nlink) | 139 | if (tmp.st_nlink != stat->nlink) |
140 | return -EOVERFLOW; | 140 | return -EOVERFLOW; |
141 | SET_UID(tmp.st_uid, stat->uid); | 141 | SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid)); |
142 | SET_GID(tmp.st_gid, stat->gid); | 142 | SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid)); |
143 | tmp.st_rdev = old_encode_dev(stat->rdev); | 143 | tmp.st_rdev = old_encode_dev(stat->rdev); |
144 | #if BITS_PER_LONG == 32 | 144 | #if BITS_PER_LONG == 32 |
145 | if (stat->size > MAX_NON_LFS) | 145 | if (stat->size > MAX_NON_LFS) |
@@ -224,8 +224,8 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf) | |||
224 | tmp.st_nlink = stat->nlink; | 224 | tmp.st_nlink = stat->nlink; |
225 | if (tmp.st_nlink != stat->nlink) | 225 | if (tmp.st_nlink != stat->nlink) |
226 | return -EOVERFLOW; | 226 | return -EOVERFLOW; |
227 | SET_UID(tmp.st_uid, stat->uid); | 227 | SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid)); |
228 | SET_GID(tmp.st_gid, stat->gid); | 228 | SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid)); |
229 | tmp.st_rdev = encode_dev(stat->rdev); | 229 | tmp.st_rdev = encode_dev(stat->rdev); |
230 | tmp.st_size = stat->size; | 230 | tmp.st_size = stat->size; |
231 | tmp.st_atime = stat->atime.tv_sec; | 231 | tmp.st_atime = stat->atime.tv_sec; |
@@ -355,8 +355,8 @@ static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf) | |||
355 | #endif | 355 | #endif |
356 | tmp.st_mode = stat->mode; | 356 | tmp.st_mode = stat->mode; |
357 | tmp.st_nlink = stat->nlink; | 357 | tmp.st_nlink = stat->nlink; |
358 | tmp.st_uid = stat->uid; | 358 | tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid); |
359 | tmp.st_gid = stat->gid; | 359 | tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid); |
360 | tmp.st_atime = stat->atime.tv_sec; | 360 | tmp.st_atime = stat->atime.tv_sec; |
361 | tmp.st_atime_nsec = stat->atime.tv_nsec; | 361 | tmp.st_atime_nsec = stat->atime.tv_nsec; |
362 | tmp.st_mtime = stat->mtime.tv_sec; | 362 | tmp.st_mtime = stat->mtime.tv_sec; |
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index feb2d69396cf..907c2b3af758 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -62,8 +62,8 @@ static struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd) | |||
62 | 62 | ||
63 | /* assign default attributes */ | 63 | /* assign default attributes */ |
64 | iattrs->ia_mode = sd->s_mode; | 64 | iattrs->ia_mode = sd->s_mode; |
65 | iattrs->ia_uid = 0; | 65 | iattrs->ia_uid = GLOBAL_ROOT_UID; |
66 | iattrs->ia_gid = 0; | 66 | iattrs->ia_gid = GLOBAL_ROOT_GID; |
67 | iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME; | 67 | iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME; |
68 | 68 | ||
69 | return attrs; | 69 | return attrs; |
diff --git a/include/linux/capability.h b/include/linux/capability.h index c398cff3dab7..68d56effc328 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h | |||
@@ -377,6 +377,7 @@ struct cpu_vfs_cap_data { | |||
377 | 377 | ||
378 | #ifdef __KERNEL__ | 378 | #ifdef __KERNEL__ |
379 | 379 | ||
380 | struct inode; | ||
380 | struct dentry; | 381 | struct dentry; |
381 | struct user_namespace; | 382 | struct user_namespace; |
382 | 383 | ||
@@ -551,6 +552,7 @@ extern bool has_ns_capability_noaudit(struct task_struct *t, | |||
551 | extern bool capable(int cap); | 552 | extern bool capable(int cap); |
552 | extern bool ns_capable(struct user_namespace *ns, int cap); | 553 | extern bool ns_capable(struct user_namespace *ns, int cap); |
553 | extern bool nsown_capable(int cap); | 554 | extern bool nsown_capable(int cap); |
555 | extern bool inode_capable(const struct inode *inode, int cap); | ||
554 | 556 | ||
555 | /* audit system wants to get cap info from files as well */ | 557 | /* audit system wants to get cap info from files as well */ |
556 | extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps); | 558 | extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps); |
diff --git a/include/linux/cred.h b/include/linux/cred.h index adadf71a7327..917dc5aeb1d4 100644 --- a/include/linux/cred.h +++ b/include/linux/cred.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/key.h> | 17 | #include <linux/key.h> |
18 | #include <linux/selinux.h> | 18 | #include <linux/selinux.h> |
19 | #include <linux/atomic.h> | 19 | #include <linux/atomic.h> |
20 | #include <linux/uidgid.h> | ||
20 | 21 | ||
21 | struct user_struct; | 22 | struct user_struct; |
22 | struct cred; | 23 | struct cred; |
@@ -26,14 +27,14 @@ struct inode; | |||
26 | * COW Supplementary groups list | 27 | * COW Supplementary groups list |
27 | */ | 28 | */ |
28 | #define NGROUPS_SMALL 32 | 29 | #define NGROUPS_SMALL 32 |
29 | #define NGROUPS_PER_BLOCK ((unsigned int)(PAGE_SIZE / sizeof(gid_t))) | 30 | #define NGROUPS_PER_BLOCK ((unsigned int)(PAGE_SIZE / sizeof(kgid_t))) |
30 | 31 | ||
31 | struct group_info { | 32 | struct group_info { |
32 | atomic_t usage; | 33 | atomic_t usage; |
33 | int ngroups; | 34 | int ngroups; |
34 | int nblocks; | 35 | int nblocks; |
35 | gid_t small_block[NGROUPS_SMALL]; | 36 | kgid_t small_block[NGROUPS_SMALL]; |
36 | gid_t *blocks[0]; | 37 | kgid_t *blocks[0]; |
37 | }; | 38 | }; |
38 | 39 | ||
39 | /** | 40 | /** |
@@ -66,14 +67,14 @@ extern struct group_info init_groups; | |||
66 | extern void groups_free(struct group_info *); | 67 | extern void groups_free(struct group_info *); |
67 | extern int set_current_groups(struct group_info *); | 68 | extern int set_current_groups(struct group_info *); |
68 | extern int set_groups(struct cred *, struct group_info *); | 69 | extern int set_groups(struct cred *, struct group_info *); |
69 | extern int groups_search(const struct group_info *, gid_t); | 70 | extern int groups_search(const struct group_info *, kgid_t); |
70 | 71 | ||
71 | /* access the groups "array" with this macro */ | 72 | /* access the groups "array" with this macro */ |
72 | #define GROUP_AT(gi, i) \ | 73 | #define GROUP_AT(gi, i) \ |
73 | ((gi)->blocks[(i) / NGROUPS_PER_BLOCK][(i) % NGROUPS_PER_BLOCK]) | 74 | ((gi)->blocks[(i) / NGROUPS_PER_BLOCK][(i) % NGROUPS_PER_BLOCK]) |
74 | 75 | ||
75 | extern int in_group_p(gid_t); | 76 | extern int in_group_p(kgid_t); |
76 | extern int in_egroup_p(gid_t); | 77 | extern int in_egroup_p(kgid_t); |
77 | 78 | ||
78 | /* | 79 | /* |
79 | * The common credentials for a thread group | 80 | * The common credentials for a thread group |
@@ -122,14 +123,14 @@ struct cred { | |||
122 | #define CRED_MAGIC 0x43736564 | 123 | #define CRED_MAGIC 0x43736564 |
123 | #define CRED_MAGIC_DEAD 0x44656144 | 124 | #define CRED_MAGIC_DEAD 0x44656144 |
124 | #endif | 125 | #endif |
125 | uid_t uid; /* real UID of the task */ | 126 | kuid_t uid; /* real UID of the task */ |
126 | gid_t gid; /* real GID of the task */ | 127 | kgid_t gid; /* real GID of the task */ |
127 | uid_t suid; /* saved UID of the task */ | 128 | kuid_t suid; /* saved UID of the task */ |
128 | gid_t sgid; /* saved GID of the task */ | 129 | kgid_t sgid; /* saved GID of the task */ |
129 | uid_t euid; /* effective UID of the task */ | 130 | kuid_t euid; /* effective UID of the task */ |
130 | gid_t egid; /* effective GID of the task */ | 131 | kgid_t egid; /* effective GID of the task */ |
131 | uid_t fsuid; /* UID for VFS ops */ | 132 | kuid_t fsuid; /* UID for VFS ops */ |
132 | gid_t fsgid; /* GID for VFS ops */ | 133 | kgid_t fsgid; /* GID for VFS ops */ |
133 | unsigned securebits; /* SUID-less security management */ | 134 | unsigned securebits; /* SUID-less security management */ |
134 | kernel_cap_t cap_inheritable; /* caps our children can inherit */ | 135 | kernel_cap_t cap_inheritable; /* caps our children can inherit */ |
135 | kernel_cap_t cap_permitted; /* caps we're permitted */ | 136 | kernel_cap_t cap_permitted; /* caps we're permitted */ |
@@ -146,7 +147,7 @@ struct cred { | |||
146 | void *security; /* subjective LSM security */ | 147 | void *security; /* subjective LSM security */ |
147 | #endif | 148 | #endif |
148 | struct user_struct *user; /* real user ID subscription */ | 149 | struct user_struct *user; /* real user ID subscription */ |
149 | struct user_namespace *user_ns; /* cached user->user_ns */ | 150 | struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */ |
150 | struct group_info *group_info; /* supplementary groups for euid/fsgid */ | 151 | struct group_info *group_info; /* supplementary groups for euid/fsgid */ |
151 | struct rcu_head rcu; /* RCU deletion hook */ | 152 | struct rcu_head rcu; /* RCU deletion hook */ |
152 | }; | 153 | }; |
@@ -357,11 +358,11 @@ static inline void put_cred(const struct cred *_cred) | |||
357 | #define current_user() (current_cred_xxx(user)) | 358 | #define current_user() (current_cred_xxx(user)) |
358 | #define current_security() (current_cred_xxx(security)) | 359 | #define current_security() (current_cred_xxx(security)) |
359 | 360 | ||
361 | extern struct user_namespace init_user_ns; | ||
360 | #ifdef CONFIG_USER_NS | 362 | #ifdef CONFIG_USER_NS |
361 | #define current_user_ns() (current_cred_xxx(user_ns)) | 363 | #define current_user_ns() (current_cred_xxx(user_ns)) |
362 | #define task_user_ns(task) (task_cred_xxx((task), user_ns)) | 364 | #define task_user_ns(task) (task_cred_xxx((task), user_ns)) |
363 | #else | 365 | #else |
364 | extern struct user_namespace init_user_ns; | ||
365 | #define current_user_ns() (&init_user_ns) | 366 | #define current_user_ns() (&init_user_ns) |
366 | #define task_user_ns(task) (&init_user_ns) | 367 | #define task_user_ns(task) (&init_user_ns) |
367 | #endif | 368 | #endif |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 25c40b9f848a..c0e53372b082 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -402,6 +402,7 @@ struct inodes_stat_t { | |||
402 | #include <linux/atomic.h> | 402 | #include <linux/atomic.h> |
403 | #include <linux/shrinker.h> | 403 | #include <linux/shrinker.h> |
404 | #include <linux/migrate_mode.h> | 404 | #include <linux/migrate_mode.h> |
405 | #include <linux/uidgid.h> | ||
405 | 406 | ||
406 | #include <asm/byteorder.h> | 407 | #include <asm/byteorder.h> |
407 | 408 | ||
@@ -469,8 +470,8 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset, | |||
469 | struct iattr { | 470 | struct iattr { |
470 | unsigned int ia_valid; | 471 | unsigned int ia_valid; |
471 | umode_t ia_mode; | 472 | umode_t ia_mode; |
472 | uid_t ia_uid; | 473 | kuid_t ia_uid; |
473 | gid_t ia_gid; | 474 | kgid_t ia_gid; |
474 | loff_t ia_size; | 475 | loff_t ia_size; |
475 | struct timespec ia_atime; | 476 | struct timespec ia_atime; |
476 | struct timespec ia_mtime; | 477 | struct timespec ia_mtime; |
@@ -761,8 +762,8 @@ struct posix_acl; | |||
761 | struct inode { | 762 | struct inode { |
762 | umode_t i_mode; | 763 | umode_t i_mode; |
763 | unsigned short i_opflags; | 764 | unsigned short i_opflags; |
764 | uid_t i_uid; | 765 | kuid_t i_uid; |
765 | gid_t i_gid; | 766 | kgid_t i_gid; |
766 | unsigned int i_flags; | 767 | unsigned int i_flags; |
767 | 768 | ||
768 | #ifdef CONFIG_FS_POSIX_ACL | 769 | #ifdef CONFIG_FS_POSIX_ACL |
@@ -927,6 +928,31 @@ static inline void i_size_write(struct inode *inode, loff_t i_size) | |||
927 | #endif | 928 | #endif |
928 | } | 929 | } |
929 | 930 | ||
931 | /* Helper functions so that in most cases filesystems will | ||
932 | * not need to deal directly with kuid_t and kgid_t and can | ||
933 | * instead deal with the raw numeric values that are stored | ||
934 | * in the filesystem. | ||
935 | */ | ||
936 | static inline uid_t i_uid_read(const struct inode *inode) | ||
937 | { | ||
938 | return from_kuid(&init_user_ns, inode->i_uid); | ||
939 | } | ||
940 | |||
941 | static inline gid_t i_gid_read(const struct inode *inode) | ||
942 | { | ||
943 | return from_kgid(&init_user_ns, inode->i_gid); | ||
944 | } | ||
945 | |||
946 | static inline void i_uid_write(struct inode *inode, uid_t uid) | ||
947 | { | ||
948 | inode->i_uid = make_kuid(&init_user_ns, uid); | ||
949 | } | ||
950 | |||
951 | static inline void i_gid_write(struct inode *inode, gid_t gid) | ||
952 | { | ||
953 | inode->i_gid = make_kgid(&init_user_ns, gid); | ||
954 | } | ||
955 | |||
930 | static inline unsigned iminor(const struct inode *inode) | 956 | static inline unsigned iminor(const struct inode *inode) |
931 | { | 957 | { |
932 | return MINOR(inode->i_rdev); | 958 | return MINOR(inode->i_rdev); |
@@ -943,7 +969,7 @@ struct fown_struct { | |||
943 | rwlock_t lock; /* protects pid, uid, euid fields */ | 969 | rwlock_t lock; /* protects pid, uid, euid fields */ |
944 | struct pid *pid; /* pid or -pgrp where SIGIO should be sent */ | 970 | struct pid *pid; /* pid or -pgrp where SIGIO should be sent */ |
945 | enum pid_type pid_type; /* Kind of process group SIGIO should be sent to */ | 971 | enum pid_type pid_type; /* Kind of process group SIGIO should be sent to */ |
946 | uid_t uid, euid; /* uid/euid of process setting the owner */ | 972 | kuid_t uid, euid; /* uid/euid of process setting the owner */ |
947 | int signum; /* posix.1b rt signal to be delivered on IO */ | 973 | int signum; /* posix.1b rt signal to be delivered on IO */ |
948 | }; | 974 | }; |
949 | 975 | ||
@@ -1527,12 +1553,6 @@ enum { | |||
1527 | #define vfs_check_frozen(sb, level) \ | 1553 | #define vfs_check_frozen(sb, level) \ |
1528 | wait_event((sb)->s_wait_unfrozen, ((sb)->s_frozen < (level))) | 1554 | wait_event((sb)->s_wait_unfrozen, ((sb)->s_frozen < (level))) |
1529 | 1555 | ||
1530 | /* | ||
1531 | * until VFS tracks user namespaces for inodes, just make all files | ||
1532 | * belong to init_user_ns | ||
1533 | */ | ||
1534 | extern struct user_namespace init_user_ns; | ||
1535 | #define inode_userns(inode) (&init_user_ns) | ||
1536 | extern bool inode_owner_or_capable(const struct inode *inode); | 1556 | extern bool inode_owner_or_capable(const struct inode *inode); |
1537 | 1557 | ||
1538 | /* not quite ready to be deprecated, but... */ | 1558 | /* not quite ready to be deprecated, but... */ |
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index b067bd8c49d0..00474b047145 100644 --- a/include/linux/pid_namespace.h +++ b/include/linux/pid_namespace.h | |||
@@ -31,7 +31,7 @@ struct pid_namespace { | |||
31 | #ifdef CONFIG_BSD_PROCESS_ACCT | 31 | #ifdef CONFIG_BSD_PROCESS_ACCT |
32 | struct bsd_acct_struct *bacct; | 32 | struct bsd_acct_struct *bacct; |
33 | #endif | 33 | #endif |
34 | gid_t pid_gid; | 34 | kgid_t pid_gid; |
35 | int hide_pid; | 35 | int hide_pid; |
36 | int reboot; /* group exit code if this pidns was rebooted */ | 36 | int reboot; /* group exit code if this pidns was rebooted */ |
37 | }; | 37 | }; |
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 85c507306239..3fd2e871ff1b 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h | |||
@@ -52,8 +52,8 @@ struct proc_dir_entry { | |||
52 | unsigned int low_ino; | 52 | unsigned int low_ino; |
53 | umode_t mode; | 53 | umode_t mode; |
54 | nlink_t nlink; | 54 | nlink_t nlink; |
55 | uid_t uid; | 55 | kuid_t uid; |
56 | gid_t gid; | 56 | kgid_t gid; |
57 | loff_t size; | 57 | loff_t size; |
58 | const struct inode_operations *proc_iops; | 58 | const struct inode_operations *proc_iops; |
59 | /* | 59 | /* |
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index d93f95e6177c..17b977304a09 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h | |||
@@ -22,8 +22,8 @@ static inline struct quota_info *sb_dqopt(struct super_block *sb) | |||
22 | static inline bool is_quota_modification(struct inode *inode, struct iattr *ia) | 22 | static inline bool is_quota_modification(struct inode *inode, struct iattr *ia) |
23 | { | 23 | { |
24 | return (ia->ia_valid & ATTR_SIZE && ia->ia_size != inode->i_size) || | 24 | return (ia->ia_valid & ATTR_SIZE && ia->ia_size != inode->i_size) || |
25 | (ia->ia_valid & ATTR_UID && ia->ia_uid != inode->i_uid) || | 25 | (ia->ia_valid & ATTR_UID && !uid_eq(ia->ia_uid, inode->i_uid)) || |
26 | (ia->ia_valid & ATTR_GID && ia->ia_gid != inode->i_gid); | 26 | (ia->ia_valid & ATTR_GID && !gid_eq(ia->ia_gid, inode->i_gid)); |
27 | } | 27 | } |
28 | 28 | ||
29 | #if defined(CONFIG_QUOTA) | 29 | #if defined(CONFIG_QUOTA) |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 28fa9d02fd59..5ea8baea9387 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -90,6 +90,7 @@ struct sched_param { | |||
90 | #include <linux/latencytop.h> | 90 | #include <linux/latencytop.h> |
91 | #include <linux/cred.h> | 91 | #include <linux/cred.h> |
92 | #include <linux/llist.h> | 92 | #include <linux/llist.h> |
93 | #include <linux/uidgid.h> | ||
93 | 94 | ||
94 | #include <asm/processor.h> | 95 | #include <asm/processor.h> |
95 | 96 | ||
@@ -728,8 +729,7 @@ struct user_struct { | |||
728 | 729 | ||
729 | /* Hash table maintenance information */ | 730 | /* Hash table maintenance information */ |
730 | struct hlist_node uidhash_node; | 731 | struct hlist_node uidhash_node; |
731 | uid_t uid; | 732 | kuid_t uid; |
732 | struct user_namespace *user_ns; | ||
733 | 733 | ||
734 | #ifdef CONFIG_PERF_EVENTS | 734 | #ifdef CONFIG_PERF_EVENTS |
735 | atomic_long_t locked_vm; | 735 | atomic_long_t locked_vm; |
@@ -738,7 +738,7 @@ struct user_struct { | |||
738 | 738 | ||
739 | extern int uids_sysfs_init(void); | 739 | extern int uids_sysfs_init(void); |
740 | 740 | ||
741 | extern struct user_struct *find_user(uid_t); | 741 | extern struct user_struct *find_user(kuid_t); |
742 | 742 | ||
743 | extern struct user_struct root_user; | 743 | extern struct user_struct root_user; |
744 | #define INIT_USER (&root_user) | 744 | #define INIT_USER (&root_user) |
@@ -2142,14 +2142,13 @@ extern struct task_struct *find_task_by_pid_ns(pid_t nr, | |||
2142 | extern void __set_special_pids(struct pid *pid); | 2142 | extern void __set_special_pids(struct pid *pid); |
2143 | 2143 | ||
2144 | /* per-UID process charging. */ | 2144 | /* per-UID process charging. */ |
2145 | extern struct user_struct * alloc_uid(struct user_namespace *, uid_t); | 2145 | extern struct user_struct * alloc_uid(kuid_t); |
2146 | static inline struct user_struct *get_uid(struct user_struct *u) | 2146 | static inline struct user_struct *get_uid(struct user_struct *u) |
2147 | { | 2147 | { |
2148 | atomic_inc(&u->__count); | 2148 | atomic_inc(&u->__count); |
2149 | return u; | 2149 | return u; |
2150 | } | 2150 | } |
2151 | extern void free_uid(struct user_struct *); | 2151 | extern void free_uid(struct user_struct *); |
2152 | extern void release_uids(struct user_namespace *ns); | ||
2153 | 2152 | ||
2154 | #include <asm/current.h> | 2153 | #include <asm/current.h> |
2155 | 2154 | ||
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index 79ab2555b3b0..bef2cf00b3be 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h | |||
@@ -28,8 +28,8 @@ struct shmem_sb_info { | |||
28 | unsigned long max_inodes; /* How many inodes are allowed */ | 28 | unsigned long max_inodes; /* How many inodes are allowed */ |
29 | unsigned long free_inodes; /* How many are left for allocation */ | 29 | unsigned long free_inodes; /* How many are left for allocation */ |
30 | spinlock_t stat_lock; /* Serialize shmem_sb_info changes */ | 30 | spinlock_t stat_lock; /* Serialize shmem_sb_info changes */ |
31 | uid_t uid; /* Mount uid for root directory */ | 31 | kuid_t uid; /* Mount uid for root directory */ |
32 | gid_t gid; /* Mount gid for root directory */ | 32 | kgid_t gid; /* Mount gid for root directory */ |
33 | umode_t mode; /* Mount mode for root directory */ | 33 | umode_t mode; /* Mount mode for root directory */ |
34 | struct mempolicy *mpol; /* default memory policy for mappings */ | 34 | struct mempolicy *mpol; /* default memory policy for mappings */ |
35 | }; | 35 | }; |
diff --git a/include/linux/stat.h b/include/linux/stat.h index 611c398dab72..46132409a3f7 100644 --- a/include/linux/stat.h +++ b/include/linux/stat.h | |||
@@ -58,14 +58,15 @@ | |||
58 | 58 | ||
59 | #include <linux/types.h> | 59 | #include <linux/types.h> |
60 | #include <linux/time.h> | 60 | #include <linux/time.h> |
61 | #include <linux/uidgid.h> | ||
61 | 62 | ||
62 | struct kstat { | 63 | struct kstat { |
63 | u64 ino; | 64 | u64 ino; |
64 | dev_t dev; | 65 | dev_t dev; |
65 | umode_t mode; | 66 | umode_t mode; |
66 | unsigned int nlink; | 67 | unsigned int nlink; |
67 | uid_t uid; | 68 | kuid_t uid; |
68 | gid_t gid; | 69 | kgid_t gid; |
69 | dev_t rdev; | 70 | dev_t rdev; |
70 | loff_t size; | 71 | loff_t size; |
71 | struct timespec atime; | 72 | struct timespec atime; |
diff --git a/include/linux/uidgid.h b/include/linux/uidgid.h new file mode 100644 index 000000000000..8e522cbcef29 --- /dev/null +++ b/include/linux/uidgid.h | |||
@@ -0,0 +1,200 @@ | |||
1 | #ifndef _LINUX_UIDGID_H | ||
2 | #define _LINUX_UIDGID_H | ||
3 | |||
4 | /* | ||
5 | * A set of types for the internal kernel types representing uids and gids. | ||
6 | * | ||
7 | * The types defined in this header allow distinguishing which uids and gids in | ||
8 | * the kernel are values used by userspace and which uid and gid values are | ||
9 | * the internal kernel values. With the addition of user namespaces the values | ||
10 | * can be different. Using the type system makes it possible for the compiler | ||
11 | * to detect when we overlook these differences. | ||
12 | * | ||
13 | */ | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/highuid.h> | ||
16 | |||
17 | struct user_namespace; | ||
18 | extern struct user_namespace init_user_ns; | ||
19 | |||
20 | #ifdef CONFIG_UIDGID_STRICT_TYPE_CHECKS | ||
21 | |||
22 | typedef struct { | ||
23 | uid_t val; | ||
24 | } kuid_t; | ||
25 | |||
26 | |||
27 | typedef struct { | ||
28 | gid_t val; | ||
29 | } kgid_t; | ||
30 | |||
31 | #define KUIDT_INIT(value) (kuid_t){ value } | ||
32 | #define KGIDT_INIT(value) (kgid_t){ value } | ||
33 | |||
34 | static inline uid_t __kuid_val(kuid_t uid) | ||
35 | { | ||
36 | return uid.val; | ||
37 | } | ||
38 | |||
39 | static inline gid_t __kgid_val(kgid_t gid) | ||
40 | { | ||
41 | return gid.val; | ||
42 | } | ||
43 | |||
44 | #else | ||
45 | |||
46 | typedef uid_t kuid_t; | ||
47 | typedef gid_t kgid_t; | ||
48 | |||
49 | static inline uid_t __kuid_val(kuid_t uid) | ||
50 | { | ||
51 | return uid; | ||
52 | } | ||
53 | |||
54 | static inline gid_t __kgid_val(kgid_t gid) | ||
55 | { | ||
56 | return gid; | ||
57 | } | ||
58 | |||
59 | #define KUIDT_INIT(value) ((kuid_t) value ) | ||
60 | #define KGIDT_INIT(value) ((kgid_t) value ) | ||
61 | |||
62 | #endif | ||
63 | |||
64 | #define GLOBAL_ROOT_UID KUIDT_INIT(0) | ||
65 | #define GLOBAL_ROOT_GID KGIDT_INIT(0) | ||
66 | |||
67 | #define INVALID_UID KUIDT_INIT(-1) | ||
68 | #define INVALID_GID KGIDT_INIT(-1) | ||
69 | |||
70 | static inline bool uid_eq(kuid_t left, kuid_t right) | ||
71 | { | ||
72 | return __kuid_val(left) == __kuid_val(right); | ||
73 | } | ||
74 | |||
75 | static inline bool gid_eq(kgid_t left, kgid_t right) | ||
76 | { | ||
77 | return __kgid_val(left) == __kgid_val(right); | ||
78 | } | ||
79 | |||
80 | static inline bool uid_gt(kuid_t left, kuid_t right) | ||
81 | { | ||
82 | return __kuid_val(left) > __kuid_val(right); | ||
83 | } | ||
84 | |||
85 | static inline bool gid_gt(kgid_t left, kgid_t right) | ||
86 | { | ||
87 | return __kgid_val(left) > __kgid_val(right); | ||
88 | } | ||
89 | |||
90 | static inline bool uid_gte(kuid_t left, kuid_t right) | ||
91 | { | ||
92 | return __kuid_val(left) >= __kuid_val(right); | ||
93 | } | ||
94 | |||
95 | static inline bool gid_gte(kgid_t left, kgid_t right) | ||
96 | { | ||
97 | return __kgid_val(left) >= __kgid_val(right); | ||
98 | } | ||
99 | |||
100 | static inline bool uid_lt(kuid_t left, kuid_t right) | ||
101 | { | ||
102 | return __kuid_val(left) < __kuid_val(right); | ||
103 | } | ||
104 | |||
105 | static inline bool gid_lt(kgid_t left, kgid_t right) | ||
106 | { | ||
107 | return __kgid_val(left) < __kgid_val(right); | ||
108 | } | ||
109 | |||
110 | static inline bool uid_lte(kuid_t left, kuid_t right) | ||
111 | { | ||
112 | return __kuid_val(left) <= __kuid_val(right); | ||
113 | } | ||
114 | |||
115 | static inline bool gid_lte(kgid_t left, kgid_t right) | ||
116 | { | ||
117 | return __kgid_val(left) <= __kgid_val(right); | ||
118 | } | ||
119 | |||
120 | static inline bool uid_valid(kuid_t uid) | ||
121 | { | ||
122 | return !uid_eq(uid, INVALID_UID); | ||
123 | } | ||
124 | |||
125 | static inline bool gid_valid(kgid_t gid) | ||
126 | { | ||
127 | return !gid_eq(gid, INVALID_GID); | ||
128 | } | ||
129 | |||
130 | #ifdef CONFIG_USER_NS | ||
131 | |||
132 | extern kuid_t make_kuid(struct user_namespace *from, uid_t uid); | ||
133 | extern kgid_t make_kgid(struct user_namespace *from, gid_t gid); | ||
134 | |||
135 | extern uid_t from_kuid(struct user_namespace *to, kuid_t uid); | ||
136 | extern gid_t from_kgid(struct user_namespace *to, kgid_t gid); | ||
137 | extern uid_t from_kuid_munged(struct user_namespace *to, kuid_t uid); | ||
138 | extern gid_t from_kgid_munged(struct user_namespace *to, kgid_t gid); | ||
139 | |||
140 | static inline bool kuid_has_mapping(struct user_namespace *ns, kuid_t uid) | ||
141 | { | ||
142 | return from_kuid(ns, uid) != (uid_t) -1; | ||
143 | } | ||
144 | |||
145 | static inline bool kgid_has_mapping(struct user_namespace *ns, kgid_t gid) | ||
146 | { | ||
147 | return from_kgid(ns, gid) != (gid_t) -1; | ||
148 | } | ||
149 | |||
150 | #else | ||
151 | |||
152 | static inline kuid_t make_kuid(struct user_namespace *from, uid_t uid) | ||
153 | { | ||
154 | return KUIDT_INIT(uid); | ||
155 | } | ||
156 | |||
157 | static inline kgid_t make_kgid(struct user_namespace *from, gid_t gid) | ||
158 | { | ||
159 | return KGIDT_INIT(gid); | ||
160 | } | ||
161 | |||
162 | static inline uid_t from_kuid(struct user_namespace *to, kuid_t kuid) | ||
163 | { | ||
164 | return __kuid_val(kuid); | ||
165 | } | ||
166 | |||
167 | static inline gid_t from_kgid(struct user_namespace *to, kgid_t kgid) | ||
168 | { | ||
169 | return __kgid_val(kgid); | ||
170 | } | ||
171 | |||
172 | static inline uid_t from_kuid_munged(struct user_namespace *to, kuid_t kuid) | ||
173 | { | ||
174 | uid_t uid = from_kuid(to, kuid); | ||
175 | if (uid == (uid_t)-1) | ||
176 | uid = overflowuid; | ||
177 | return uid; | ||
178 | } | ||
179 | |||
180 | static inline gid_t from_kgid_munged(struct user_namespace *to, kgid_t kgid) | ||
181 | { | ||
182 | gid_t gid = from_kgid(to, kgid); | ||
183 | if (gid == (gid_t)-1) | ||
184 | gid = overflowgid; | ||
185 | return gid; | ||
186 | } | ||
187 | |||
188 | static inline bool kuid_has_mapping(struct user_namespace *ns, kuid_t uid) | ||
189 | { | ||
190 | return true; | ||
191 | } | ||
192 | |||
193 | static inline bool kgid_has_mapping(struct user_namespace *ns, kgid_t gid) | ||
194 | { | ||
195 | return true; | ||
196 | } | ||
197 | |||
198 | #endif /* CONFIG_USER_NS */ | ||
199 | |||
200 | #endif /* _LINUX_UIDGID_H */ | ||
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index faf467944baf..4e72922e5a75 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h | |||
@@ -6,14 +6,24 @@ | |||
6 | #include <linux/sched.h> | 6 | #include <linux/sched.h> |
7 | #include <linux/err.h> | 7 | #include <linux/err.h> |
8 | 8 | ||
9 | #define UIDHASH_BITS (CONFIG_BASE_SMALL ? 3 : 7) | 9 | #define UID_GID_MAP_MAX_EXTENTS 5 |
10 | #define UIDHASH_SZ (1 << UIDHASH_BITS) | 10 | |
11 | struct uid_gid_map { /* 64 bytes -- 1 cache line */ | ||
12 | u32 nr_extents; | ||
13 | struct uid_gid_extent { | ||
14 | u32 first; | ||
15 | u32 lower_first; | ||
16 | u32 count; | ||
17 | } extent[UID_GID_MAP_MAX_EXTENTS]; | ||
18 | }; | ||
11 | 19 | ||
12 | struct user_namespace { | 20 | struct user_namespace { |
21 | struct uid_gid_map uid_map; | ||
22 | struct uid_gid_map gid_map; | ||
13 | struct kref kref; | 23 | struct kref kref; |
14 | struct hlist_head uidhash_table[UIDHASH_SZ]; | 24 | struct user_namespace *parent; |
15 | struct user_struct *creator; | 25 | kuid_t owner; |
16 | struct work_struct destroyer; | 26 | kgid_t group; |
17 | }; | 27 | }; |
18 | 28 | ||
19 | extern struct user_namespace init_user_ns; | 29 | extern struct user_namespace init_user_ns; |
@@ -36,9 +46,11 @@ static inline void put_user_ns(struct user_namespace *ns) | |||
36 | kref_put(&ns->kref, free_user_ns); | 46 | kref_put(&ns->kref, free_user_ns); |
37 | } | 47 | } |
38 | 48 | ||
39 | uid_t user_ns_map_uid(struct user_namespace *to, const struct cred *cred, uid_t uid); | 49 | struct seq_operations; |
40 | gid_t user_ns_map_gid(struct user_namespace *to, const struct cred *cred, gid_t gid); | 50 | extern struct seq_operations proc_uid_seq_operations; |
41 | 51 | extern struct seq_operations proc_gid_seq_operations; | |
52 | extern ssize_t proc_uid_map_write(struct file *, const char __user *, size_t, loff_t *); | ||
53 | extern ssize_t proc_gid_map_write(struct file *, const char __user *, size_t, loff_t *); | ||
42 | #else | 54 | #else |
43 | 55 | ||
44 | static inline struct user_namespace *get_user_ns(struct user_namespace *ns) | 56 | static inline struct user_namespace *get_user_ns(struct user_namespace *ns) |
@@ -55,17 +67,6 @@ static inline void put_user_ns(struct user_namespace *ns) | |||
55 | { | 67 | { |
56 | } | 68 | } |
57 | 69 | ||
58 | static inline uid_t user_ns_map_uid(struct user_namespace *to, | ||
59 | const struct cred *cred, uid_t uid) | ||
60 | { | ||
61 | return uid; | ||
62 | } | ||
63 | static inline gid_t user_ns_map_gid(struct user_namespace *to, | ||
64 | const struct cred *cred, gid_t gid) | ||
65 | { | ||
66 | return gid; | ||
67 | } | ||
68 | |||
69 | #endif | 70 | #endif |
70 | 71 | ||
71 | #endif /* _LINUX_USER_H */ | 72 | #endif /* _LINUX_USER_H */ |
diff --git a/include/trace/events/ext3.h b/include/trace/events/ext3.h index 7b53c0573dc9..15d11a39be47 100644 --- a/include/trace/events/ext3.h +++ b/include/trace/events/ext3.h | |||
@@ -24,8 +24,8 @@ TRACE_EVENT(ext3_free_inode, | |||
24 | __entry->dev = inode->i_sb->s_dev; | 24 | __entry->dev = inode->i_sb->s_dev; |
25 | __entry->ino = inode->i_ino; | 25 | __entry->ino = inode->i_ino; |
26 | __entry->mode = inode->i_mode; | 26 | __entry->mode = inode->i_mode; |
27 | __entry->uid = inode->i_uid; | 27 | __entry->uid = i_uid_read(inode); |
28 | __entry->gid = inode->i_gid; | 28 | __entry->gid = i_gid_read(inode); |
29 | __entry->blocks = inode->i_blocks; | 29 | __entry->blocks = inode->i_blocks; |
30 | ), | 30 | ), |
31 | 31 | ||
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h index 319538bf17d2..69d8a69ea831 100644 --- a/include/trace/events/ext4.h +++ b/include/trace/events/ext4.h | |||
@@ -36,8 +36,8 @@ TRACE_EVENT(ext4_free_inode, | |||
36 | __entry->dev = inode->i_sb->s_dev; | 36 | __entry->dev = inode->i_sb->s_dev; |
37 | __entry->ino = inode->i_ino; | 37 | __entry->ino = inode->i_ino; |
38 | __entry->mode = inode->i_mode; | 38 | __entry->mode = inode->i_mode; |
39 | __entry->uid = inode->i_uid; | 39 | __entry->uid = i_uid_read(inode); |
40 | __entry->gid = inode->i_gid; | 40 | __entry->gid = i_gid_read(inode); |
41 | __entry->blocks = inode->i_blocks; | 41 | __entry->blocks = inode->i_blocks; |
42 | ), | 42 | ), |
43 | 43 | ||
diff --git a/init/Kconfig b/init/Kconfig index a30fe085940e..ccb5248474c2 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -873,7 +873,10 @@ config IPC_NS | |||
873 | config USER_NS | 873 | config USER_NS |
874 | bool "User namespace (EXPERIMENTAL)" | 874 | bool "User namespace (EXPERIMENTAL)" |
875 | depends on EXPERIMENTAL | 875 | depends on EXPERIMENTAL |
876 | default y | 876 | depends on UIDGID_CONVERTED |
877 | select UIDGID_STRICT_TYPE_CHECKS | ||
878 | |||
879 | default n | ||
877 | help | 880 | help |
878 | This allows containers, i.e. vservers, to use user namespaces | 881 | This allows containers, i.e. vservers, to use user namespaces |
879 | to provide different user info for different servers. | 882 | to provide different user info for different servers. |
@@ -897,6 +900,131 @@ config NET_NS | |||
897 | 900 | ||
898 | endif # NAMESPACES | 901 | endif # NAMESPACES |
899 | 902 | ||
903 | config UIDGID_CONVERTED | ||
904 | # True if all of the selected software conmponents are known | ||
905 | # to have uid_t and gid_t converted to kuid_t and kgid_t | ||
906 | # where appropriate and are otherwise safe to use with | ||
907 | # the user namespace. | ||
908 | bool | ||
909 | default y | ||
910 | |||
911 | # List of kernel pieces that need user namespace work | ||
912 | # Features | ||
913 | depends on SYSVIPC = n | ||
914 | depends on IMA = n | ||
915 | depends on EVM = n | ||
916 | depends on KEYS = n | ||
917 | depends on AUDIT = n | ||
918 | depends on AUDITSYSCALL = n | ||
919 | depends on TASKSTATS = n | ||
920 | depends on TRACING = n | ||
921 | depends on FS_POSIX_ACL = n | ||
922 | depends on QUOTA = n | ||
923 | depends on QUOTACTL = n | ||
924 | depends on DEBUG_CREDENTIALS = n | ||
925 | depends on BSD_PROCESS_ACCT = n | ||
926 | depends on DRM = n | ||
927 | depends on PROC_EVENTS = n | ||
928 | |||
929 | # Networking | ||
930 | depends on NET = n | ||
931 | depends on NET_9P = n | ||
932 | depends on IPX = n | ||
933 | depends on PHONET = n | ||
934 | depends on NET_CLS_FLOW = n | ||
935 | depends on NETFILTER_XT_MATCH_OWNER = n | ||
936 | depends on NETFILTER_XT_MATCH_RECENT = n | ||
937 | depends on NETFILTER_XT_TARGET_LOG = n | ||
938 | depends on NETFILTER_NETLINK_LOG = n | ||
939 | depends on INET = n | ||
940 | depends on IPV6 = n | ||
941 | depends on IP_SCTP = n | ||
942 | depends on AF_RXRPC = n | ||
943 | depends on LLC2 = n | ||
944 | depends on NET_KEY = n | ||
945 | depends on INET_DIAG = n | ||
946 | depends on DNS_RESOLVER = n | ||
947 | depends on AX25 = n | ||
948 | depends on ATALK = n | ||
949 | |||
950 | # Filesystems | ||
951 | depends on USB_DEVICEFS = n | ||
952 | depends on USB_GADGETFS = n | ||
953 | depends on USB_FUNCTIONFS = n | ||
954 | depends on DEVTMPFS = n | ||
955 | depends on XENFS = n | ||
956 | |||
957 | depends on 9P_FS = n | ||
958 | depends on ADFS_FS = n | ||
959 | depends on AFFS_FS = n | ||
960 | depends on AFS_FS = n | ||
961 | depends on AUTOFS4_FS = n | ||
962 | depends on BEFS_FS = n | ||
963 | depends on BFS_FS = n | ||
964 | depends on BTRFS_FS = n | ||
965 | depends on CEPH_FS = n | ||
966 | depends on CIFS = n | ||
967 | depends on CODA_FS = n | ||
968 | depends on CONFIGFS_FS = n | ||
969 | depends on CRAMFS = n | ||
970 | depends on DEBUG_FS = n | ||
971 | depends on ECRYPT_FS = n | ||
972 | depends on EFS_FS = n | ||
973 | depends on EXOFS_FS = n | ||
974 | depends on FAT_FS = n | ||
975 | depends on FUSE_FS = n | ||
976 | depends on GFS2_FS = n | ||
977 | depends on HFS_FS = n | ||
978 | depends on HFSPLUS_FS = n | ||
979 | depends on HPFS_FS = n | ||
980 | depends on HUGETLBFS = n | ||
981 | depends on ISO9660_FS = n | ||
982 | depends on JFFS2_FS = n | ||
983 | depends on JFS_FS = n | ||
984 | depends on LOGFS = n | ||
985 | depends on MINIX_FS = n | ||
986 | depends on NCP_FS = n | ||
987 | depends on NFSD = n | ||
988 | depends on NFS_FS = n | ||
989 | depends on NILFS2_FS = n | ||
990 | depends on NTFS_FS = n | ||
991 | depends on OCFS2_FS = n | ||
992 | depends on OMFS_FS = n | ||
993 | depends on QNX4FS_FS = n | ||
994 | depends on QNX6FS_FS = n | ||
995 | depends on REISERFS_FS = n | ||
996 | depends on SQUASHFS = n | ||
997 | depends on SYSV_FS = n | ||
998 | depends on UBIFS_FS = n | ||
999 | depends on UDF_FS = n | ||
1000 | depends on UFS_FS = n | ||
1001 | depends on VXFS_FS = n | ||
1002 | depends on XFS_FS = n | ||
1003 | |||
1004 | depends on !UML || HOSTFS = n | ||
1005 | |||
1006 | # The rare drivers that won't build | ||
1007 | depends on AIRO = n | ||
1008 | depends on AIRO_CS = n | ||
1009 | depends on TUN = n | ||
1010 | depends on INFINIBAND_QIB = n | ||
1011 | depends on BLK_DEV_LOOP = n | ||
1012 | depends on ANDROID_BINDER_IPC = n | ||
1013 | |||
1014 | # Security modules | ||
1015 | depends on SECURITY_TOMOYO = n | ||
1016 | depends on SECURITY_APPARMOR = n | ||
1017 | |||
1018 | config UIDGID_STRICT_TYPE_CHECKS | ||
1019 | bool "Require conversions between uid/gids and their internal representation" | ||
1020 | depends on UIDGID_CONVERTED | ||
1021 | default n | ||
1022 | help | ||
1023 | While the nececessary conversions are being added to all subsystems this option allows | ||
1024 | the code to continue to build for unconverted subsystems. | ||
1025 | |||
1026 | Say Y here if you want the strict type checking enabled | ||
1027 | |||
900 | config SCHED_AUTOGROUP | 1028 | config SCHED_AUTOGROUP |
901 | bool "Automatic process group scheduling" | 1029 | bool "Automatic process group scheduling" |
902 | select EVENTFD | 1030 | select EVENTFD |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 28bd64ddeda3..b6a0d46fbad7 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
@@ -66,6 +66,7 @@ struct mqueue_inode_info { | |||
66 | 66 | ||
67 | struct sigevent notify; | 67 | struct sigevent notify; |
68 | struct pid* notify_owner; | 68 | struct pid* notify_owner; |
69 | struct user_namespace *notify_user_ns; | ||
69 | struct user_struct *user; /* user who created, for accounting */ | 70 | struct user_struct *user; /* user who created, for accounting */ |
70 | struct sock *notify_sock; | 71 | struct sock *notify_sock; |
71 | struct sk_buff *notify_cookie; | 72 | struct sk_buff *notify_cookie; |
@@ -139,6 +140,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb, | |||
139 | INIT_LIST_HEAD(&info->e_wait_q[0].list); | 140 | INIT_LIST_HEAD(&info->e_wait_q[0].list); |
140 | INIT_LIST_HEAD(&info->e_wait_q[1].list); | 141 | INIT_LIST_HEAD(&info->e_wait_q[1].list); |
141 | info->notify_owner = NULL; | 142 | info->notify_owner = NULL; |
143 | info->notify_user_ns = NULL; | ||
142 | info->qsize = 0; | 144 | info->qsize = 0; |
143 | info->user = NULL; /* set when all is ok */ | 145 | info->user = NULL; /* set when all is ok */ |
144 | memset(&info->attr, 0, sizeof(info->attr)); | 146 | memset(&info->attr, 0, sizeof(info->attr)); |
@@ -536,8 +538,7 @@ static void __do_notify(struct mqueue_inode_info *info) | |||
536 | rcu_read_lock(); | 538 | rcu_read_lock(); |
537 | sig_i.si_pid = task_tgid_nr_ns(current, | 539 | sig_i.si_pid = task_tgid_nr_ns(current, |
538 | ns_of_pid(info->notify_owner)); | 540 | ns_of_pid(info->notify_owner)); |
539 | sig_i.si_uid = user_ns_map_uid(info->user->user_ns, | 541 | sig_i.si_uid = from_kuid_munged(info->notify_user_ns, current_uid()); |
540 | current_cred(), current_uid()); | ||
541 | rcu_read_unlock(); | 542 | rcu_read_unlock(); |
542 | 543 | ||
543 | kill_pid_info(info->notify.sigev_signo, | 544 | kill_pid_info(info->notify.sigev_signo, |
@@ -550,7 +551,9 @@ static void __do_notify(struct mqueue_inode_info *info) | |||
550 | } | 551 | } |
551 | /* after notification unregisters process */ | 552 | /* after notification unregisters process */ |
552 | put_pid(info->notify_owner); | 553 | put_pid(info->notify_owner); |
554 | put_user_ns(info->notify_user_ns); | ||
553 | info->notify_owner = NULL; | 555 | info->notify_owner = NULL; |
556 | info->notify_user_ns = NULL; | ||
554 | } | 557 | } |
555 | wake_up(&info->wait_q); | 558 | wake_up(&info->wait_q); |
556 | } | 559 | } |
@@ -575,7 +578,9 @@ static void remove_notification(struct mqueue_inode_info *info) | |||
575 | netlink_sendskb(info->notify_sock, info->notify_cookie); | 578 | netlink_sendskb(info->notify_sock, info->notify_cookie); |
576 | } | 579 | } |
577 | put_pid(info->notify_owner); | 580 | put_pid(info->notify_owner); |
581 | put_user_ns(info->notify_user_ns); | ||
578 | info->notify_owner = NULL; | 582 | info->notify_owner = NULL; |
583 | info->notify_user_ns = NULL; | ||
579 | } | 584 | } |
580 | 585 | ||
581 | static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr) | 586 | static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr) |
@@ -1140,6 +1145,7 @@ retry: | |||
1140 | } | 1145 | } |
1141 | 1146 | ||
1142 | info->notify_owner = get_pid(task_tgid(current)); | 1147 | info->notify_owner = get_pid(task_tgid(current)); |
1148 | info->notify_user_ns = get_user_ns(current_user_ns()); | ||
1143 | inode->i_atime = inode->i_ctime = CURRENT_TIME; | 1149 | inode->i_atime = inode->i_ctime = CURRENT_TIME; |
1144 | } | 1150 | } |
1145 | spin_unlock(&info->lock); | 1151 | spin_unlock(&info->lock); |
diff --git a/ipc/namespace.c b/ipc/namespace.c index ce0a647869b1..f362298c5ce4 100644 --- a/ipc/namespace.c +++ b/ipc/namespace.c | |||
@@ -46,7 +46,7 @@ static struct ipc_namespace *create_ipc_ns(struct task_struct *tsk, | |||
46 | ipcns_notify(IPCNS_CREATED); | 46 | ipcns_notify(IPCNS_CREATED); |
47 | register_ipcns_notifier(ns); | 47 | register_ipcns_notifier(ns); |
48 | 48 | ||
49 | ns->user_ns = get_user_ns(task_cred_xxx(tsk, user)->user_ns); | 49 | ns->user_ns = get_user_ns(task_cred_xxx(tsk, user_ns)); |
50 | 50 | ||
51 | return ns; | 51 | return ns; |
52 | } | 52 | } |
diff --git a/kernel/capability.c b/kernel/capability.c index 3f1adb6c6470..493d97259484 100644 --- a/kernel/capability.c +++ b/kernel/capability.c | |||
@@ -419,3 +419,24 @@ bool nsown_capable(int cap) | |||
419 | { | 419 | { |
420 | return ns_capable(current_user_ns(), cap); | 420 | return ns_capable(current_user_ns(), cap); |
421 | } | 421 | } |
422 | |||
423 | /** | ||
424 | * inode_capable - Check superior capability over inode | ||
425 | * @inode: The inode in question | ||
426 | * @cap: The capability in question | ||
427 | * | ||
428 | * Return true if the current task has the given superior capability | ||
429 | * targeted at it's own user namespace and that the given inode is owned | ||
430 | * by the current user namespace or a child namespace. | ||
431 | * | ||
432 | * Currently we check to see if an inode is owned by the current | ||
433 | * user namespace by seeing if the inode's owner maps into the | ||
434 | * current user namespace. | ||
435 | * | ||
436 | */ | ||
437 | bool inode_capable(const struct inode *inode, int cap) | ||
438 | { | ||
439 | struct user_namespace *ns = current_user_ns(); | ||
440 | |||
441 | return ns_capable(ns, cap) && kuid_has_mapping(ns, inode->i_uid); | ||
442 | } | ||
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index ad8eae5bb801..a0c6af34d500 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -2214,9 +2214,9 @@ retry_find_task: | |||
2214 | * only need to check permissions on one of them. | 2214 | * only need to check permissions on one of them. |
2215 | */ | 2215 | */ |
2216 | tcred = __task_cred(tsk); | 2216 | tcred = __task_cred(tsk); |
2217 | if (cred->euid && | 2217 | if (!uid_eq(cred->euid, GLOBAL_ROOT_UID) && |
2218 | cred->euid != tcred->uid && | 2218 | !uid_eq(cred->euid, tcred->uid) && |
2219 | cred->euid != tcred->suid) { | 2219 | !uid_eq(cred->euid, tcred->suid)) { |
2220 | rcu_read_unlock(); | 2220 | rcu_read_unlock(); |
2221 | ret = -EACCES; | 2221 | ret = -EACCES; |
2222 | goto out_unlock_cgroup; | 2222 | goto out_unlock_cgroup; |
diff --git a/kernel/cred.c b/kernel/cred.c index e70683d9ec32..430557ea488f 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, |
@@ -148,6 +156,7 @@ static void put_cred_rcu(struct rcu_head *rcu) | |||
148 | if (cred->group_info) | 156 | if (cred->group_info) |
149 | put_group_info(cred->group_info); | 157 | put_group_info(cred->group_info); |
150 | free_uid(cred->user); | 158 | free_uid(cred->user); |
159 | put_user_ns(cred->user_ns); | ||
151 | kmem_cache_free(cred_jar, cred); | 160 | kmem_cache_free(cred_jar, cred); |
152 | } | 161 | } |
153 | 162 | ||
@@ -303,6 +312,7 @@ struct cred *prepare_creds(void) | |||
303 | set_cred_subscribers(new, 0); | 312 | set_cred_subscribers(new, 0); |
304 | get_group_info(new->group_info); | 313 | get_group_info(new->group_info); |
305 | get_uid(new->user); | 314 | get_uid(new->user); |
315 | get_user_ns(new->user_ns); | ||
306 | 316 | ||
307 | #ifdef CONFIG_KEYS | 317 | #ifdef CONFIG_KEYS |
308 | key_get(new->thread_keyring); | 318 | key_get(new->thread_keyring); |
@@ -414,11 +424,6 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags) | |||
414 | goto error_put; | 424 | goto error_put; |
415 | } | 425 | } |
416 | 426 | ||
417 | /* cache user_ns in cred. Doesn't need a refcount because it will | ||
418 | * stay pinned by cred->user | ||
419 | */ | ||
420 | new->user_ns = new->user->user_ns; | ||
421 | |||
422 | #ifdef CONFIG_KEYS | 427 | #ifdef CONFIG_KEYS |
423 | /* new threads get their own thread keyrings if their parent already | 428 | /* new threads get their own thread keyrings if their parent already |
424 | * had one */ | 429 | * had one */ |
@@ -493,10 +498,10 @@ int commit_creds(struct cred *new) | |||
493 | get_cred(new); /* we will require a ref for the subj creds too */ | 498 | get_cred(new); /* we will require a ref for the subj creds too */ |
494 | 499 | ||
495 | /* dumpability changes */ | 500 | /* dumpability changes */ |
496 | if (old->euid != new->euid || | 501 | if (!uid_eq(old->euid, new->euid) || |
497 | old->egid != new->egid || | 502 | !gid_eq(old->egid, new->egid) || |
498 | old->fsuid != new->fsuid || | 503 | !uid_eq(old->fsuid, new->fsuid) || |
499 | old->fsgid != new->fsgid || | 504 | !gid_eq(old->fsgid, new->fsgid) || |
500 | !cap_issubset(new->cap_permitted, old->cap_permitted)) { | 505 | !cap_issubset(new->cap_permitted, old->cap_permitted)) { |
501 | if (task->mm) | 506 | if (task->mm) |
502 | set_dumpable(task->mm, suid_dumpable); | 507 | set_dumpable(task->mm, suid_dumpable); |
@@ -505,9 +510,9 @@ int commit_creds(struct cred *new) | |||
505 | } | 510 | } |
506 | 511 | ||
507 | /* alter the thread keyring */ | 512 | /* alter the thread keyring */ |
508 | if (new->fsuid != old->fsuid) | 513 | if (!uid_eq(new->fsuid, old->fsuid)) |
509 | key_fsuid_changed(task); | 514 | key_fsuid_changed(task); |
510 | if (new->fsgid != old->fsgid) | 515 | if (!gid_eq(new->fsgid, old->fsgid)) |
511 | key_fsgid_changed(task); | 516 | key_fsgid_changed(task); |
512 | 517 | ||
513 | /* do it | 518 | /* do it |
@@ -524,16 +529,16 @@ int commit_creds(struct cred *new) | |||
524 | alter_cred_subscribers(old, -2); | 529 | alter_cred_subscribers(old, -2); |
525 | 530 | ||
526 | /* send notifications */ | 531 | /* send notifications */ |
527 | if (new->uid != old->uid || | 532 | if (!uid_eq(new->uid, old->uid) || |
528 | new->euid != old->euid || | 533 | !uid_eq(new->euid, old->euid) || |
529 | new->suid != old->suid || | 534 | !uid_eq(new->suid, old->suid) || |
530 | new->fsuid != old->fsuid) | 535 | !uid_eq(new->fsuid, old->fsuid)) |
531 | proc_id_connector(task, PROC_EVENT_UID); | 536 | proc_id_connector(task, PROC_EVENT_UID); |
532 | 537 | ||
533 | if (new->gid != old->gid || | 538 | if (!gid_eq(new->gid, old->gid) || |
534 | new->egid != old->egid || | 539 | !gid_eq(new->egid, old->egid) || |
535 | new->sgid != old->sgid || | 540 | !gid_eq(new->sgid, old->sgid) || |
536 | new->fsgid != old->fsgid) | 541 | !gid_eq(new->fsgid, old->fsgid)) |
537 | proc_id_connector(task, PROC_EVENT_GID); | 542 | proc_id_connector(task, PROC_EVENT_GID); |
538 | 543 | ||
539 | /* release the old obj and subj refs both */ | 544 | /* release the old obj and subj refs both */ |
@@ -678,6 +683,7 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon) | |||
678 | atomic_set(&new->usage, 1); | 683 | atomic_set(&new->usage, 1); |
679 | set_cred_subscribers(new, 0); | 684 | set_cred_subscribers(new, 0); |
680 | get_uid(new->user); | 685 | get_uid(new->user); |
686 | get_user_ns(new->user_ns); | ||
681 | get_group_info(new->group_info); | 687 | get_group_info(new->group_info); |
682 | 688 | ||
683 | #ifdef CONFIG_KEYS | 689 | #ifdef CONFIG_KEYS |
diff --git a/kernel/exit.c b/kernel/exit.c index d8bd3b425fa7..910a0716e17a 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -1214,7 +1214,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p) | |||
1214 | unsigned long state; | 1214 | unsigned long state; |
1215 | int retval, status, traced; | 1215 | int retval, status, traced; |
1216 | pid_t pid = task_pid_vnr(p); | 1216 | pid_t pid = task_pid_vnr(p); |
1217 | uid_t uid = __task_cred(p)->uid; | 1217 | uid_t uid = from_kuid_munged(current_user_ns(), __task_cred(p)->uid); |
1218 | struct siginfo __user *infop; | 1218 | struct siginfo __user *infop; |
1219 | 1219 | ||
1220 | if (!likely(wo->wo_flags & WEXITED)) | 1220 | if (!likely(wo->wo_flags & WEXITED)) |
@@ -1427,7 +1427,7 @@ static int wait_task_stopped(struct wait_opts *wo, | |||
1427 | if (!unlikely(wo->wo_flags & WNOWAIT)) | 1427 | if (!unlikely(wo->wo_flags & WNOWAIT)) |
1428 | *p_code = 0; | 1428 | *p_code = 0; |
1429 | 1429 | ||
1430 | uid = task_uid(p); | 1430 | uid = from_kuid_munged(current_user_ns(), task_uid(p)); |
1431 | unlock_sig: | 1431 | unlock_sig: |
1432 | spin_unlock_irq(&p->sighand->siglock); | 1432 | spin_unlock_irq(&p->sighand->siglock); |
1433 | if (!exit_code) | 1433 | if (!exit_code) |
@@ -1500,7 +1500,7 @@ static int wait_task_continued(struct wait_opts *wo, struct task_struct *p) | |||
1500 | } | 1500 | } |
1501 | if (!unlikely(wo->wo_flags & WNOWAIT)) | 1501 | if (!unlikely(wo->wo_flags & WNOWAIT)) |
1502 | p->signal->flags &= ~SIGNAL_STOP_CONTINUED; | 1502 | p->signal->flags &= ~SIGNAL_STOP_CONTINUED; |
1503 | uid = task_uid(p); | 1503 | uid = from_kuid_munged(current_user_ns(), task_uid(p)); |
1504 | spin_unlock_irq(&p->sighand->siglock); | 1504 | spin_unlock_irq(&p->sighand->siglock); |
1505 | 1505 | ||
1506 | pid = task_pid_vnr(p); | 1506 | pid = task_pid_vnr(p); |
diff --git a/kernel/groups.c b/kernel/groups.c index 99b53d1eb7ea..6b2588dd04ff 100644 --- a/kernel/groups.c +++ b/kernel/groups.c | |||
@@ -31,7 +31,7 @@ struct group_info *groups_alloc(int gidsetsize) | |||
31 | group_info->blocks[0] = group_info->small_block; | 31 | group_info->blocks[0] = group_info->small_block; |
32 | else { | 32 | else { |
33 | for (i = 0; i < nblocks; i++) { | 33 | for (i = 0; i < nblocks; i++) { |
34 | gid_t *b; | 34 | kgid_t *b; |
35 | b = (void *)__get_free_page(GFP_USER); | 35 | b = (void *)__get_free_page(GFP_USER); |
36 | if (!b) | 36 | if (!b) |
37 | goto out_undo_partial_alloc; | 37 | goto out_undo_partial_alloc; |
@@ -66,18 +66,15 @@ EXPORT_SYMBOL(groups_free); | |||
66 | static int groups_to_user(gid_t __user *grouplist, | 66 | static int groups_to_user(gid_t __user *grouplist, |
67 | const struct group_info *group_info) | 67 | const struct group_info *group_info) |
68 | { | 68 | { |
69 | struct user_namespace *user_ns = current_user_ns(); | ||
69 | int i; | 70 | int i; |
70 | unsigned int count = group_info->ngroups; | 71 | unsigned int count = group_info->ngroups; |
71 | 72 | ||
72 | for (i = 0; i < group_info->nblocks; i++) { | 73 | for (i = 0; i < count; i++) { |
73 | unsigned int cp_count = min(NGROUPS_PER_BLOCK, count); | 74 | gid_t gid; |
74 | unsigned int len = cp_count * sizeof(*grouplist); | 75 | gid = from_kgid_munged(user_ns, GROUP_AT(group_info, i)); |
75 | 76 | if (put_user(gid, grouplist+i)) | |
76 | if (copy_to_user(grouplist, group_info->blocks[i], len)) | ||
77 | return -EFAULT; | 77 | return -EFAULT; |
78 | |||
79 | grouplist += NGROUPS_PER_BLOCK; | ||
80 | count -= cp_count; | ||
81 | } | 78 | } |
82 | return 0; | 79 | return 0; |
83 | } | 80 | } |
@@ -86,18 +83,21 @@ static int groups_to_user(gid_t __user *grouplist, | |||
86 | static int groups_from_user(struct group_info *group_info, | 83 | static int groups_from_user(struct group_info *group_info, |
87 | gid_t __user *grouplist) | 84 | gid_t __user *grouplist) |
88 | { | 85 | { |
86 | struct user_namespace *user_ns = current_user_ns(); | ||
89 | int i; | 87 | int i; |
90 | unsigned int count = group_info->ngroups; | 88 | unsigned int count = group_info->ngroups; |
91 | 89 | ||
92 | for (i = 0; i < group_info->nblocks; i++) { | 90 | for (i = 0; i < count; i++) { |
93 | unsigned int cp_count = min(NGROUPS_PER_BLOCK, count); | 91 | gid_t gid; |
94 | unsigned int len = cp_count * sizeof(*grouplist); | 92 | kgid_t kgid; |
95 | 93 | if (get_user(gid, grouplist+i)) | |
96 | if (copy_from_user(group_info->blocks[i], grouplist, len)) | ||
97 | return -EFAULT; | 94 | return -EFAULT; |
98 | 95 | ||
99 | grouplist += NGROUPS_PER_BLOCK; | 96 | kgid = make_kgid(user_ns, gid); |
100 | count -= cp_count; | 97 | if (!gid_valid(kgid)) |
98 | return -EINVAL; | ||
99 | |||
100 | GROUP_AT(group_info, i) = kgid; | ||
101 | } | 101 | } |
102 | return 0; | 102 | return 0; |
103 | } | 103 | } |
@@ -117,9 +117,9 @@ static void groups_sort(struct group_info *group_info) | |||
117 | for (base = 0; base < max; base++) { | 117 | for (base = 0; base < max; base++) { |
118 | int left = base; | 118 | int left = base; |
119 | int right = left + stride; | 119 | int right = left + stride; |
120 | gid_t tmp = GROUP_AT(group_info, right); | 120 | kgid_t tmp = GROUP_AT(group_info, right); |
121 | 121 | ||
122 | while (left >= 0 && GROUP_AT(group_info, left) > tmp) { | 122 | while (left >= 0 && gid_gt(GROUP_AT(group_info, left), tmp)) { |
123 | GROUP_AT(group_info, right) = | 123 | GROUP_AT(group_info, right) = |
124 | GROUP_AT(group_info, left); | 124 | GROUP_AT(group_info, left); |
125 | right = left; | 125 | right = left; |
@@ -132,7 +132,7 @@ static void groups_sort(struct group_info *group_info) | |||
132 | } | 132 | } |
133 | 133 | ||
134 | /* a simple bsearch */ | 134 | /* a simple bsearch */ |
135 | int groups_search(const struct group_info *group_info, gid_t grp) | 135 | int groups_search(const struct group_info *group_info, kgid_t grp) |
136 | { | 136 | { |
137 | unsigned int left, right; | 137 | unsigned int left, right; |
138 | 138 | ||
@@ -143,9 +143,9 @@ int groups_search(const struct group_info *group_info, gid_t grp) | |||
143 | right = group_info->ngroups; | 143 | right = group_info->ngroups; |
144 | while (left < right) { | 144 | while (left < right) { |
145 | unsigned int mid = (left+right)/2; | 145 | unsigned int mid = (left+right)/2; |
146 | if (grp > GROUP_AT(group_info, mid)) | 146 | if (gid_gt(grp, GROUP_AT(group_info, mid))) |
147 | left = mid + 1; | 147 | left = mid + 1; |
148 | else if (grp < GROUP_AT(group_info, mid)) | 148 | else if (gid_lt(grp, GROUP_AT(group_info, mid))) |
149 | right = mid; | 149 | right = mid; |
150 | else | 150 | else |
151 | return 1; | 151 | return 1; |
@@ -256,24 +256,24 @@ SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist) | |||
256 | /* | 256 | /* |
257 | * Check whether we're fsgid/egid or in the supplemental group.. | 257 | * Check whether we're fsgid/egid or in the supplemental group.. |
258 | */ | 258 | */ |
259 | int in_group_p(gid_t grp) | 259 | int in_group_p(kgid_t grp) |
260 | { | 260 | { |
261 | const struct cred *cred = current_cred(); | 261 | const struct cred *cred = current_cred(); |
262 | int retval = 1; | 262 | int retval = 1; |
263 | 263 | ||
264 | if (grp != cred->fsgid) | 264 | if (!gid_eq(grp, cred->fsgid)) |
265 | retval = groups_search(cred->group_info, grp); | 265 | retval = groups_search(cred->group_info, grp); |
266 | return retval; | 266 | return retval; |
267 | } | 267 | } |
268 | 268 | ||
269 | EXPORT_SYMBOL(in_group_p); | 269 | EXPORT_SYMBOL(in_group_p); |
270 | 270 | ||
271 | int in_egroup_p(gid_t grp) | 271 | int in_egroup_p(kgid_t grp) |
272 | { | 272 | { |
273 | const struct cred *cred = current_cred(); | 273 | const struct cred *cred = current_cred(); |
274 | int retval = 1; | 274 | int retval = 1; |
275 | 275 | ||
276 | if (grp != cred->egid) | 276 | if (!gid_eq(grp, cred->egid)) |
277 | retval = groups_search(cred->group_info, grp); | 277 | retval = groups_search(cred->group_info, grp); |
278 | return retval; | 278 | return retval; |
279 | } | 279 | } |
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index ee8d49b9c309..a232bb59d93f 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -198,15 +198,14 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode) | |||
198 | return 0; | 198 | return 0; |
199 | rcu_read_lock(); | 199 | rcu_read_lock(); |
200 | tcred = __task_cred(task); | 200 | tcred = __task_cred(task); |
201 | if (cred->user->user_ns == tcred->user->user_ns && | 201 | if (uid_eq(cred->uid, tcred->euid) && |
202 | (cred->uid == tcred->euid && | 202 | uid_eq(cred->uid, tcred->suid) && |
203 | cred->uid == tcred->suid && | 203 | uid_eq(cred->uid, tcred->uid) && |
204 | cred->uid == tcred->uid && | 204 | gid_eq(cred->gid, tcred->egid) && |
205 | cred->gid == tcred->egid && | 205 | gid_eq(cred->gid, tcred->sgid) && |
206 | cred->gid == tcred->sgid && | 206 | gid_eq(cred->gid, tcred->gid)) |
207 | cred->gid == tcred->gid)) | ||
208 | goto ok; | 207 | goto ok; |
209 | if (ptrace_has_cap(tcred->user->user_ns, mode)) | 208 | if (ptrace_has_cap(tcred->user_ns, mode)) |
210 | goto ok; | 209 | goto ok; |
211 | rcu_read_unlock(); | 210 | rcu_read_unlock(); |
212 | return -EPERM; | 211 | return -EPERM; |
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index a5a9d39b845c..39eb6011bc38 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
@@ -4070,11 +4070,8 @@ static bool check_same_owner(struct task_struct *p) | |||
4070 | 4070 | ||
4071 | rcu_read_lock(); | 4071 | rcu_read_lock(); |
4072 | pcred = __task_cred(p); | 4072 | pcred = __task_cred(p); |
4073 | if (cred->user->user_ns == pcred->user->user_ns) | 4073 | match = (uid_eq(cred->euid, pcred->euid) || |
4074 | match = (cred->euid == pcred->euid || | 4074 | uid_eq(cred->euid, pcred->uid)); |
4075 | cred->euid == pcred->uid); | ||
4076 | else | ||
4077 | match = false; | ||
4078 | rcu_read_unlock(); | 4075 | rcu_read_unlock(); |
4079 | return match; | 4076 | return match; |
4080 | } | 4077 | } |
diff --git a/kernel/signal.c b/kernel/signal.c index 1a006b5d9d9d..21ebe75ff85f 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -767,14 +767,13 @@ static int kill_ok_by_cred(struct task_struct *t) | |||
767 | const struct cred *cred = current_cred(); | 767 | const struct cred *cred = current_cred(); |
768 | const struct cred *tcred = __task_cred(t); | 768 | const struct cred *tcred = __task_cred(t); |
769 | 769 | ||
770 | if (cred->user->user_ns == tcred->user->user_ns && | 770 | if (uid_eq(cred->euid, tcred->suid) || |
771 | (cred->euid == tcred->suid || | 771 | uid_eq(cred->euid, tcred->uid) || |
772 | cred->euid == tcred->uid || | 772 | uid_eq(cred->uid, tcred->suid) || |
773 | cred->uid == tcred->suid || | 773 | uid_eq(cred->uid, tcred->uid)) |
774 | cred->uid == tcred->uid)) | ||
775 | return 1; | 774 | return 1; |
776 | 775 | ||
777 | if (ns_capable(tcred->user->user_ns, CAP_KILL)) | 776 | if (ns_capable(tcred->user_ns, CAP_KILL)) |
778 | return 1; | 777 | return 1; |
779 | 778 | ||
780 | return 0; | 779 | return 0; |
@@ -1020,15 +1019,6 @@ static inline int legacy_queue(struct sigpending *signals, int sig) | |||
1020 | return (sig < SIGRTMIN) && sigismember(&signals->signal, sig); | 1019 | return (sig < SIGRTMIN) && sigismember(&signals->signal, sig); |
1021 | } | 1020 | } |
1022 | 1021 | ||
1023 | /* | ||
1024 | * map the uid in struct cred into user namespace *ns | ||
1025 | */ | ||
1026 | static inline uid_t map_cred_ns(const struct cred *cred, | ||
1027 | struct user_namespace *ns) | ||
1028 | { | ||
1029 | return user_ns_map_uid(ns, cred, cred->uid); | ||
1030 | } | ||
1031 | |||
1032 | #ifdef CONFIG_USER_NS | 1022 | #ifdef CONFIG_USER_NS |
1033 | static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) | 1023 | static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) |
1034 | { | 1024 | { |
@@ -1038,8 +1028,10 @@ static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_str | |||
1038 | if (SI_FROMKERNEL(info)) | 1028 | if (SI_FROMKERNEL(info)) |
1039 | return; | 1029 | return; |
1040 | 1030 | ||
1041 | info->si_uid = user_ns_map_uid(task_cred_xxx(t, user_ns), | 1031 | rcu_read_lock(); |
1042 | current_cred(), info->si_uid); | 1032 | info->si_uid = from_kuid_munged(task_cred_xxx(t, user_ns), |
1033 | make_kuid(current_user_ns(), info->si_uid)); | ||
1034 | rcu_read_unlock(); | ||
1043 | } | 1035 | } |
1044 | #else | 1036 | #else |
1045 | static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) | 1037 | static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) |
@@ -1106,7 +1098,7 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
1106 | q->info.si_code = SI_USER; | 1098 | q->info.si_code = SI_USER; |
1107 | q->info.si_pid = task_tgid_nr_ns(current, | 1099 | q->info.si_pid = task_tgid_nr_ns(current, |
1108 | task_active_pid_ns(t)); | 1100 | task_active_pid_ns(t)); |
1109 | q->info.si_uid = current_uid(); | 1101 | q->info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); |
1110 | break; | 1102 | break; |
1111 | case (unsigned long) SEND_SIG_PRIV: | 1103 | case (unsigned long) SEND_SIG_PRIV: |
1112 | q->info.si_signo = sig; | 1104 | q->info.si_signo = sig; |
@@ -1387,10 +1379,8 @@ static int kill_as_cred_perm(const struct cred *cred, | |||
1387 | struct task_struct *target) | 1379 | struct task_struct *target) |
1388 | { | 1380 | { |
1389 | const struct cred *pcred = __task_cred(target); | 1381 | const struct cred *pcred = __task_cred(target); |
1390 | if (cred->user_ns != pcred->user_ns) | 1382 | if (!uid_eq(cred->euid, pcred->suid) && !uid_eq(cred->euid, pcred->uid) && |
1391 | return 0; | 1383 | !uid_eq(cred->uid, pcred->suid) && !uid_eq(cred->uid, pcred->uid)) |
1392 | if (cred->euid != pcred->suid && cred->euid != pcred->uid && | ||
1393 | cred->uid != pcred->suid && cred->uid != pcred->uid) | ||
1394 | return 0; | 1384 | return 0; |
1395 | return 1; | 1385 | return 1; |
1396 | } | 1386 | } |
@@ -1678,8 +1668,8 @@ bool do_notify_parent(struct task_struct *tsk, int sig) | |||
1678 | */ | 1668 | */ |
1679 | rcu_read_lock(); | 1669 | rcu_read_lock(); |
1680 | info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns); | 1670 | info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns); |
1681 | info.si_uid = map_cred_ns(__task_cred(tsk), | 1671 | info.si_uid = from_kuid_munged(task_cred_xxx(tsk->parent, user_ns), |
1682 | task_cred_xxx(tsk->parent, user_ns)); | 1672 | task_uid(tsk)); |
1683 | rcu_read_unlock(); | 1673 | rcu_read_unlock(); |
1684 | 1674 | ||
1685 | info.si_utime = cputime_to_clock_t(tsk->utime + tsk->signal->utime); | 1675 | info.si_utime = cputime_to_clock_t(tsk->utime + tsk->signal->utime); |
@@ -1762,8 +1752,7 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, | |||
1762 | */ | 1752 | */ |
1763 | rcu_read_lock(); | 1753 | rcu_read_lock(); |
1764 | info.si_pid = task_pid_nr_ns(tsk, parent->nsproxy->pid_ns); | 1754 | info.si_pid = task_pid_nr_ns(tsk, parent->nsproxy->pid_ns); |
1765 | info.si_uid = map_cred_ns(__task_cred(tsk), | 1755 | info.si_uid = from_kuid_munged(task_cred_xxx(parent, user_ns), task_uid(tsk)); |
1766 | task_cred_xxx(parent, user_ns)); | ||
1767 | rcu_read_unlock(); | 1756 | rcu_read_unlock(); |
1768 | 1757 | ||
1769 | info.si_utime = cputime_to_clock_t(tsk->utime); | 1758 | info.si_utime = cputime_to_clock_t(tsk->utime); |
@@ -1973,7 +1962,7 @@ static void ptrace_do_notify(int signr, int exit_code, int why) | |||
1973 | info.si_signo = signr; | 1962 | info.si_signo = signr; |
1974 | info.si_code = exit_code; | 1963 | info.si_code = exit_code; |
1975 | info.si_pid = task_pid_vnr(current); | 1964 | info.si_pid = task_pid_vnr(current); |
1976 | info.si_uid = current_uid(); | 1965 | info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); |
1977 | 1966 | ||
1978 | /* Let the debugger run. */ | 1967 | /* Let the debugger run. */ |
1979 | ptrace_stop(exit_code, why, 1, &info); | 1968 | ptrace_stop(exit_code, why, 1, &info); |
@@ -2181,8 +2170,8 @@ static int ptrace_signal(int signr, siginfo_t *info, | |||
2181 | info->si_code = SI_USER; | 2170 | info->si_code = SI_USER; |
2182 | rcu_read_lock(); | 2171 | rcu_read_lock(); |
2183 | info->si_pid = task_pid_vnr(current->parent); | 2172 | info->si_pid = task_pid_vnr(current->parent); |
2184 | info->si_uid = map_cred_ns(__task_cred(current->parent), | 2173 | info->si_uid = from_kuid_munged(current_user_ns(), |
2185 | current_user_ns()); | 2174 | task_uid(current->parent)); |
2186 | rcu_read_unlock(); | 2175 | rcu_read_unlock(); |
2187 | } | 2176 | } |
2188 | 2177 | ||
@@ -2835,7 +2824,7 @@ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig) | |||
2835 | info.si_errno = 0; | 2824 | info.si_errno = 0; |
2836 | info.si_code = SI_USER; | 2825 | info.si_code = SI_USER; |
2837 | info.si_pid = task_tgid_vnr(current); | 2826 | info.si_pid = task_tgid_vnr(current); |
2838 | info.si_uid = current_uid(); | 2827 | info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); |
2839 | 2828 | ||
2840 | return kill_something_info(sig, &info, pid); | 2829 | return kill_something_info(sig, &info, pid); |
2841 | } | 2830 | } |
@@ -2878,7 +2867,7 @@ static int do_tkill(pid_t tgid, pid_t pid, int sig) | |||
2878 | info.si_errno = 0; | 2867 | info.si_errno = 0; |
2879 | info.si_code = SI_TKILL; | 2868 | info.si_code = SI_TKILL; |
2880 | info.si_pid = task_tgid_vnr(current); | 2869 | info.si_pid = task_tgid_vnr(current); |
2881 | info.si_uid = current_uid(); | 2870 | info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); |
2882 | 2871 | ||
2883 | return do_send_specific(tgid, pid, sig, &info); | 2872 | return do_send_specific(tgid, pid, sig, &info); |
2884 | } | 2873 | } |
diff --git a/kernel/sys.c b/kernel/sys.c index ba0ae8eea6fb..6df42624e454 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -93,10 +93,8 @@ | |||
93 | int overflowuid = DEFAULT_OVERFLOWUID; | 93 | int overflowuid = DEFAULT_OVERFLOWUID; |
94 | int overflowgid = DEFAULT_OVERFLOWGID; | 94 | int overflowgid = DEFAULT_OVERFLOWGID; |
95 | 95 | ||
96 | #ifdef CONFIG_UID16 | ||
97 | EXPORT_SYMBOL(overflowuid); | 96 | EXPORT_SYMBOL(overflowuid); |
98 | EXPORT_SYMBOL(overflowgid); | 97 | EXPORT_SYMBOL(overflowgid); |
99 | #endif | ||
100 | 98 | ||
101 | /* | 99 | /* |
102 | * the same as above, but for filesystems which can only store a 16-bit | 100 | * the same as above, but for filesystems which can only store a 16-bit |
@@ -133,11 +131,10 @@ static bool set_one_prio_perm(struct task_struct *p) | |||
133 | { | 131 | { |
134 | const struct cred *cred = current_cred(), *pcred = __task_cred(p); | 132 | const struct cred *cred = current_cred(), *pcred = __task_cred(p); |
135 | 133 | ||
136 | if (pcred->user->user_ns == cred->user->user_ns && | 134 | if (uid_eq(pcred->uid, cred->euid) || |
137 | (pcred->uid == cred->euid || | 135 | uid_eq(pcred->euid, cred->euid)) |
138 | pcred->euid == cred->euid)) | ||
139 | return true; | 136 | return true; |
140 | if (ns_capable(pcred->user->user_ns, CAP_SYS_NICE)) | 137 | if (ns_capable(pcred->user_ns, CAP_SYS_NICE)) |
141 | return true; | 138 | return true; |
142 | return false; | 139 | return false; |
143 | } | 140 | } |
@@ -177,6 +174,7 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval) | |||
177 | const struct cred *cred = current_cred(); | 174 | const struct cred *cred = current_cred(); |
178 | int error = -EINVAL; | 175 | int error = -EINVAL; |
179 | struct pid *pgrp; | 176 | struct pid *pgrp; |
177 | kuid_t uid; | ||
180 | 178 | ||
181 | if (which > PRIO_USER || which < PRIO_PROCESS) | 179 | if (which > PRIO_USER || which < PRIO_PROCESS) |
182 | goto out; | 180 | goto out; |
@@ -209,18 +207,19 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval) | |||
209 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); | 207 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); |
210 | break; | 208 | break; |
211 | case PRIO_USER: | 209 | case PRIO_USER: |
212 | user = (struct user_struct *) cred->user; | 210 | uid = make_kuid(cred->user_ns, who); |
211 | user = cred->user; | ||
213 | if (!who) | 212 | if (!who) |
214 | who = cred->uid; | 213 | uid = cred->uid; |
215 | else if ((who != cred->uid) && | 214 | else if (!uid_eq(uid, cred->uid) && |
216 | !(user = find_user(who))) | 215 | !(user = find_user(uid))) |
217 | goto out_unlock; /* No processes for this user */ | 216 | goto out_unlock; /* No processes for this user */ |
218 | 217 | ||
219 | do_each_thread(g, p) { | 218 | do_each_thread(g, p) { |
220 | if (__task_cred(p)->uid == who) | 219 | if (uid_eq(task_uid(p), uid)) |
221 | error = set_one_prio(p, niceval, error); | 220 | error = set_one_prio(p, niceval, error); |
222 | } while_each_thread(g, p); | 221 | } while_each_thread(g, p); |
223 | if (who != cred->uid) | 222 | if (!uid_eq(uid, cred->uid)) |
224 | free_uid(user); /* For find_user() */ | 223 | free_uid(user); /* For find_user() */ |
225 | break; | 224 | break; |
226 | } | 225 | } |
@@ -244,6 +243,7 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who) | |||
244 | const struct cred *cred = current_cred(); | 243 | const struct cred *cred = current_cred(); |
245 | long niceval, retval = -ESRCH; | 244 | long niceval, retval = -ESRCH; |
246 | struct pid *pgrp; | 245 | struct pid *pgrp; |
246 | kuid_t uid; | ||
247 | 247 | ||
248 | if (which > PRIO_USER || which < PRIO_PROCESS) | 248 | if (which > PRIO_USER || which < PRIO_PROCESS) |
249 | return -EINVAL; | 249 | return -EINVAL; |
@@ -274,21 +274,22 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who) | |||
274 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); | 274 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); |
275 | break; | 275 | break; |
276 | case PRIO_USER: | 276 | case PRIO_USER: |
277 | user = (struct user_struct *) cred->user; | 277 | uid = make_kuid(cred->user_ns, who); |
278 | user = cred->user; | ||
278 | if (!who) | 279 | if (!who) |
279 | who = cred->uid; | 280 | uid = cred->uid; |
280 | else if ((who != cred->uid) && | 281 | else if (!uid_eq(uid, cred->uid) && |
281 | !(user = find_user(who))) | 282 | !(user = find_user(uid))) |
282 | goto out_unlock; /* No processes for this user */ | 283 | goto out_unlock; /* No processes for this user */ |
283 | 284 | ||
284 | do_each_thread(g, p) { | 285 | do_each_thread(g, p) { |
285 | if (__task_cred(p)->uid == who) { | 286 | if (uid_eq(task_uid(p), uid)) { |
286 | niceval = 20 - task_nice(p); | 287 | niceval = 20 - task_nice(p); |
287 | if (niceval > retval) | 288 | if (niceval > retval) |
288 | retval = niceval; | 289 | retval = niceval; |
289 | } | 290 | } |
290 | } while_each_thread(g, p); | 291 | } while_each_thread(g, p); |
291 | if (who != cred->uid) | 292 | if (!uid_eq(uid, cred->uid)) |
292 | free_uid(user); /* for find_user() */ | 293 | free_uid(user); /* for find_user() */ |
293 | break; | 294 | break; |
294 | } | 295 | } |
@@ -553,9 +554,19 @@ void ctrl_alt_del(void) | |||
553 | */ | 554 | */ |
554 | SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) | 555 | SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) |
555 | { | 556 | { |
557 | struct user_namespace *ns = current_user_ns(); | ||
556 | const struct cred *old; | 558 | const struct cred *old; |
557 | struct cred *new; | 559 | struct cred *new; |
558 | int retval; | 560 | int retval; |
561 | kgid_t krgid, kegid; | ||
562 | |||
563 | krgid = make_kgid(ns, rgid); | ||
564 | kegid = make_kgid(ns, egid); | ||
565 | |||
566 | if ((rgid != (gid_t) -1) && !gid_valid(krgid)) | ||
567 | return -EINVAL; | ||
568 | if ((egid != (gid_t) -1) && !gid_valid(kegid)) | ||
569 | return -EINVAL; | ||
559 | 570 | ||
560 | new = prepare_creds(); | 571 | new = prepare_creds(); |
561 | if (!new) | 572 | if (!new) |
@@ -564,25 +575,25 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) | |||
564 | 575 | ||
565 | retval = -EPERM; | 576 | retval = -EPERM; |
566 | if (rgid != (gid_t) -1) { | 577 | if (rgid != (gid_t) -1) { |
567 | if (old->gid == rgid || | 578 | if (gid_eq(old->gid, krgid) || |
568 | old->egid == rgid || | 579 | gid_eq(old->egid, krgid) || |
569 | nsown_capable(CAP_SETGID)) | 580 | nsown_capable(CAP_SETGID)) |
570 | new->gid = rgid; | 581 | new->gid = krgid; |
571 | else | 582 | else |
572 | goto error; | 583 | goto error; |
573 | } | 584 | } |
574 | if (egid != (gid_t) -1) { | 585 | if (egid != (gid_t) -1) { |
575 | if (old->gid == egid || | 586 | if (gid_eq(old->gid, kegid) || |
576 | old->egid == egid || | 587 | gid_eq(old->egid, kegid) || |
577 | old->sgid == egid || | 588 | gid_eq(old->sgid, kegid) || |
578 | nsown_capable(CAP_SETGID)) | 589 | nsown_capable(CAP_SETGID)) |
579 | new->egid = egid; | 590 | new->egid = kegid; |
580 | else | 591 | else |
581 | goto error; | 592 | goto error; |
582 | } | 593 | } |
583 | 594 | ||
584 | if (rgid != (gid_t) -1 || | 595 | if (rgid != (gid_t) -1 || |
585 | (egid != (gid_t) -1 && egid != old->gid)) | 596 | (egid != (gid_t) -1 && !gid_eq(kegid, old->gid))) |
586 | new->sgid = new->egid; | 597 | new->sgid = new->egid; |
587 | new->fsgid = new->egid; | 598 | new->fsgid = new->egid; |
588 | 599 | ||
@@ -600,9 +611,15 @@ error: | |||
600 | */ | 611 | */ |
601 | SYSCALL_DEFINE1(setgid, gid_t, gid) | 612 | SYSCALL_DEFINE1(setgid, gid_t, gid) |
602 | { | 613 | { |
614 | struct user_namespace *ns = current_user_ns(); | ||
603 | const struct cred *old; | 615 | const struct cred *old; |
604 | struct cred *new; | 616 | struct cred *new; |
605 | int retval; | 617 | int retval; |
618 | kgid_t kgid; | ||
619 | |||
620 | kgid = make_kgid(ns, gid); | ||
621 | if (!gid_valid(kgid)) | ||
622 | return -EINVAL; | ||
606 | 623 | ||
607 | new = prepare_creds(); | 624 | new = prepare_creds(); |
608 | if (!new) | 625 | if (!new) |
@@ -611,9 +628,9 @@ SYSCALL_DEFINE1(setgid, gid_t, gid) | |||
611 | 628 | ||
612 | retval = -EPERM; | 629 | retval = -EPERM; |
613 | if (nsown_capable(CAP_SETGID)) | 630 | if (nsown_capable(CAP_SETGID)) |
614 | new->gid = new->egid = new->sgid = new->fsgid = gid; | 631 | new->gid = new->egid = new->sgid = new->fsgid = kgid; |
615 | else if (gid == old->gid || gid == old->sgid) | 632 | else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid)) |
616 | new->egid = new->fsgid = gid; | 633 | new->egid = new->fsgid = kgid; |
617 | else | 634 | else |
618 | goto error; | 635 | goto error; |
619 | 636 | ||
@@ -631,7 +648,7 @@ static int set_user(struct cred *new) | |||
631 | { | 648 | { |
632 | struct user_struct *new_user; | 649 | struct user_struct *new_user; |
633 | 650 | ||
634 | new_user = alloc_uid(current_user_ns(), new->uid); | 651 | new_user = alloc_uid(new->uid); |
635 | if (!new_user) | 652 | if (!new_user) |
636 | return -EAGAIN; | 653 | return -EAGAIN; |
637 | 654 | ||
@@ -670,9 +687,19 @@ static int set_user(struct cred *new) | |||
670 | */ | 687 | */ |
671 | SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) | 688 | SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) |
672 | { | 689 | { |
690 | struct user_namespace *ns = current_user_ns(); | ||
673 | const struct cred *old; | 691 | const struct cred *old; |
674 | struct cred *new; | 692 | struct cred *new; |
675 | int retval; | 693 | int retval; |
694 | kuid_t kruid, keuid; | ||
695 | |||
696 | kruid = make_kuid(ns, ruid); | ||
697 | keuid = make_kuid(ns, euid); | ||
698 | |||
699 | if ((ruid != (uid_t) -1) && !uid_valid(kruid)) | ||
700 | return -EINVAL; | ||
701 | if ((euid != (uid_t) -1) && !uid_valid(keuid)) | ||
702 | return -EINVAL; | ||
676 | 703 | ||
677 | new = prepare_creds(); | 704 | new = prepare_creds(); |
678 | if (!new) | 705 | if (!new) |
@@ -681,29 +708,29 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) | |||
681 | 708 | ||
682 | retval = -EPERM; | 709 | retval = -EPERM; |
683 | if (ruid != (uid_t) -1) { | 710 | if (ruid != (uid_t) -1) { |
684 | new->uid = ruid; | 711 | new->uid = kruid; |
685 | if (old->uid != ruid && | 712 | if (!uid_eq(old->uid, kruid) && |
686 | old->euid != ruid && | 713 | !uid_eq(old->euid, kruid) && |
687 | !nsown_capable(CAP_SETUID)) | 714 | !nsown_capable(CAP_SETUID)) |
688 | goto error; | 715 | goto error; |
689 | } | 716 | } |
690 | 717 | ||
691 | if (euid != (uid_t) -1) { | 718 | if (euid != (uid_t) -1) { |
692 | new->euid = euid; | 719 | new->euid = keuid; |
693 | if (old->uid != euid && | 720 | if (!uid_eq(old->uid, keuid) && |
694 | old->euid != euid && | 721 | !uid_eq(old->euid, keuid) && |
695 | old->suid != euid && | 722 | !uid_eq(old->suid, keuid) && |
696 | !nsown_capable(CAP_SETUID)) | 723 | !nsown_capable(CAP_SETUID)) |
697 | goto error; | 724 | goto error; |
698 | } | 725 | } |
699 | 726 | ||
700 | if (new->uid != old->uid) { | 727 | if (!uid_eq(new->uid, old->uid)) { |
701 | retval = set_user(new); | 728 | retval = set_user(new); |
702 | if (retval < 0) | 729 | if (retval < 0) |
703 | goto error; | 730 | goto error; |
704 | } | 731 | } |
705 | if (ruid != (uid_t) -1 || | 732 | if (ruid != (uid_t) -1 || |
706 | (euid != (uid_t) -1 && euid != old->uid)) | 733 | (euid != (uid_t) -1 && !uid_eq(keuid, old->uid))) |
707 | new->suid = new->euid; | 734 | new->suid = new->euid; |
708 | new->fsuid = new->euid; | 735 | new->fsuid = new->euid; |
709 | 736 | ||
@@ -731,9 +758,15 @@ error: | |||
731 | */ | 758 | */ |
732 | SYSCALL_DEFINE1(setuid, uid_t, uid) | 759 | SYSCALL_DEFINE1(setuid, uid_t, uid) |
733 | { | 760 | { |
761 | struct user_namespace *ns = current_user_ns(); | ||
734 | const struct cred *old; | 762 | const struct cred *old; |
735 | struct cred *new; | 763 | struct cred *new; |
736 | int retval; | 764 | int retval; |
765 | kuid_t kuid; | ||
766 | |||
767 | kuid = make_kuid(ns, uid); | ||
768 | if (!uid_valid(kuid)) | ||
769 | return -EINVAL; | ||
737 | 770 | ||
738 | new = prepare_creds(); | 771 | new = prepare_creds(); |
739 | if (!new) | 772 | if (!new) |
@@ -742,17 +775,17 @@ SYSCALL_DEFINE1(setuid, uid_t, uid) | |||
742 | 775 | ||
743 | retval = -EPERM; | 776 | retval = -EPERM; |
744 | if (nsown_capable(CAP_SETUID)) { | 777 | if (nsown_capable(CAP_SETUID)) { |
745 | new->suid = new->uid = uid; | 778 | new->suid = new->uid = kuid; |
746 | if (uid != old->uid) { | 779 | if (!uid_eq(kuid, old->uid)) { |
747 | retval = set_user(new); | 780 | retval = set_user(new); |
748 | if (retval < 0) | 781 | if (retval < 0) |
749 | goto error; | 782 | goto error; |
750 | } | 783 | } |
751 | } else if (uid != old->uid && uid != new->suid) { | 784 | } else if (!uid_eq(kuid, old->uid) && !uid_eq(kuid, new->suid)) { |
752 | goto error; | 785 | goto error; |
753 | } | 786 | } |
754 | 787 | ||
755 | new->fsuid = new->euid = uid; | 788 | new->fsuid = new->euid = kuid; |
756 | 789 | ||
757 | retval = security_task_fix_setuid(new, old, LSM_SETID_ID); | 790 | retval = security_task_fix_setuid(new, old, LSM_SETID_ID); |
758 | if (retval < 0) | 791 | if (retval < 0) |
@@ -772,9 +805,24 @@ error: | |||
772 | */ | 805 | */ |
773 | SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) | 806 | SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) |
774 | { | 807 | { |
808 | struct user_namespace *ns = current_user_ns(); | ||
775 | const struct cred *old; | 809 | const struct cred *old; |
776 | struct cred *new; | 810 | struct cred *new; |
777 | int retval; | 811 | int retval; |
812 | kuid_t kruid, keuid, ksuid; | ||
813 | |||
814 | kruid = make_kuid(ns, ruid); | ||
815 | keuid = make_kuid(ns, euid); | ||
816 | ksuid = make_kuid(ns, suid); | ||
817 | |||
818 | if ((ruid != (uid_t) -1) && !uid_valid(kruid)) | ||
819 | return -EINVAL; | ||
820 | |||
821 | if ((euid != (uid_t) -1) && !uid_valid(keuid)) | ||
822 | return -EINVAL; | ||
823 | |||
824 | if ((suid != (uid_t) -1) && !uid_valid(ksuid)) | ||
825 | return -EINVAL; | ||
778 | 826 | ||
779 | new = prepare_creds(); | 827 | new = prepare_creds(); |
780 | if (!new) | 828 | if (!new) |
@@ -784,29 +832,29 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) | |||
784 | 832 | ||
785 | retval = -EPERM; | 833 | retval = -EPERM; |
786 | if (!nsown_capable(CAP_SETUID)) { | 834 | if (!nsown_capable(CAP_SETUID)) { |
787 | if (ruid != (uid_t) -1 && ruid != old->uid && | 835 | if (ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) && |
788 | ruid != old->euid && ruid != old->suid) | 836 | !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid)) |
789 | goto error; | 837 | goto error; |
790 | if (euid != (uid_t) -1 && euid != old->uid && | 838 | if (euid != (uid_t) -1 && !uid_eq(keuid, old->uid) && |
791 | euid != old->euid && euid != old->suid) | 839 | !uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid)) |
792 | goto error; | 840 | goto error; |
793 | if (suid != (uid_t) -1 && suid != old->uid && | 841 | if (suid != (uid_t) -1 && !uid_eq(ksuid, old->uid) && |
794 | suid != old->euid && suid != old->suid) | 842 | !uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid)) |
795 | goto error; | 843 | goto error; |
796 | } | 844 | } |
797 | 845 | ||
798 | if (ruid != (uid_t) -1) { | 846 | if (ruid != (uid_t) -1) { |
799 | new->uid = ruid; | 847 | new->uid = kruid; |
800 | if (ruid != old->uid) { | 848 | if (!uid_eq(kruid, old->uid)) { |
801 | retval = set_user(new); | 849 | retval = set_user(new); |
802 | if (retval < 0) | 850 | if (retval < 0) |
803 | goto error; | 851 | goto error; |
804 | } | 852 | } |
805 | } | 853 | } |
806 | if (euid != (uid_t) -1) | 854 | if (euid != (uid_t) -1) |
807 | new->euid = euid; | 855 | new->euid = keuid; |
808 | if (suid != (uid_t) -1) | 856 | if (suid != (uid_t) -1) |
809 | new->suid = suid; | 857 | new->suid = ksuid; |
810 | new->fsuid = new->euid; | 858 | new->fsuid = new->euid; |
811 | 859 | ||
812 | retval = security_task_fix_setuid(new, old, LSM_SETID_RES); | 860 | retval = security_task_fix_setuid(new, old, LSM_SETID_RES); |
@@ -820,14 +868,19 @@ error: | |||
820 | return retval; | 868 | return retval; |
821 | } | 869 | } |
822 | 870 | ||
823 | SYSCALL_DEFINE3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __user *, suid) | 871 | SYSCALL_DEFINE3(getresuid, uid_t __user *, ruidp, uid_t __user *, euidp, uid_t __user *, suidp) |
824 | { | 872 | { |
825 | const struct cred *cred = current_cred(); | 873 | const struct cred *cred = current_cred(); |
826 | int retval; | 874 | int retval; |
875 | uid_t ruid, euid, suid; | ||
876 | |||
877 | ruid = from_kuid_munged(cred->user_ns, cred->uid); | ||
878 | euid = from_kuid_munged(cred->user_ns, cred->euid); | ||
879 | suid = from_kuid_munged(cred->user_ns, cred->suid); | ||
827 | 880 | ||
828 | if (!(retval = put_user(cred->uid, ruid)) && | 881 | if (!(retval = put_user(ruid, ruidp)) && |
829 | !(retval = put_user(cred->euid, euid))) | 882 | !(retval = put_user(euid, euidp))) |
830 | retval = put_user(cred->suid, suid); | 883 | retval = put_user(suid, suidp); |
831 | 884 | ||
832 | return retval; | 885 | return retval; |
833 | } | 886 | } |
@@ -837,9 +890,22 @@ SYSCALL_DEFINE3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __u | |||
837 | */ | 890 | */ |
838 | SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid) | 891 | SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid) |
839 | { | 892 | { |
893 | struct user_namespace *ns = current_user_ns(); | ||
840 | const struct cred *old; | 894 | const struct cred *old; |
841 | struct cred *new; | 895 | struct cred *new; |
842 | int retval; | 896 | int retval; |
897 | kgid_t krgid, kegid, ksgid; | ||
898 | |||
899 | krgid = make_kgid(ns, rgid); | ||
900 | kegid = make_kgid(ns, egid); | ||
901 | ksgid = make_kgid(ns, sgid); | ||
902 | |||
903 | if ((rgid != (gid_t) -1) && !gid_valid(krgid)) | ||
904 | return -EINVAL; | ||
905 | if ((egid != (gid_t) -1) && !gid_valid(kegid)) | ||
906 | return -EINVAL; | ||
907 | if ((sgid != (gid_t) -1) && !gid_valid(ksgid)) | ||
908 | return -EINVAL; | ||
843 | 909 | ||
844 | new = prepare_creds(); | 910 | new = prepare_creds(); |
845 | if (!new) | 911 | if (!new) |
@@ -848,23 +914,23 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid) | |||
848 | 914 | ||
849 | retval = -EPERM; | 915 | retval = -EPERM; |
850 | if (!nsown_capable(CAP_SETGID)) { | 916 | if (!nsown_capable(CAP_SETGID)) { |
851 | if (rgid != (gid_t) -1 && rgid != old->gid && | 917 | if (rgid != (gid_t) -1 && !gid_eq(krgid, old->gid) && |
852 | rgid != old->egid && rgid != old->sgid) | 918 | !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid)) |
853 | goto error; | 919 | goto error; |
854 | if (egid != (gid_t) -1 && egid != old->gid && | 920 | if (egid != (gid_t) -1 && !gid_eq(kegid, old->gid) && |
855 | egid != old->egid && egid != old->sgid) | 921 | !gid_eq(kegid, old->egid) && !gid_eq(kegid, old->sgid)) |
856 | goto error; | 922 | goto error; |
857 | if (sgid != (gid_t) -1 && sgid != old->gid && | 923 | if (sgid != (gid_t) -1 && !gid_eq(ksgid, old->gid) && |
858 | sgid != old->egid && sgid != old->sgid) | 924 | !gid_eq(ksgid, old->egid) && !gid_eq(ksgid, old->sgid)) |
859 | goto error; | 925 | goto error; |
860 | } | 926 | } |
861 | 927 | ||
862 | if (rgid != (gid_t) -1) | 928 | if (rgid != (gid_t) -1) |
863 | new->gid = rgid; | 929 | new->gid = krgid; |
864 | if (egid != (gid_t) -1) | 930 | if (egid != (gid_t) -1) |
865 | new->egid = egid; | 931 | new->egid = kegid; |
866 | if (sgid != (gid_t) -1) | 932 | if (sgid != (gid_t) -1) |
867 | new->sgid = sgid; | 933 | new->sgid = ksgid; |
868 | new->fsgid = new->egid; | 934 | new->fsgid = new->egid; |
869 | 935 | ||
870 | return commit_creds(new); | 936 | return commit_creds(new); |
@@ -874,14 +940,19 @@ error: | |||
874 | return retval; | 940 | return retval; |
875 | } | 941 | } |
876 | 942 | ||
877 | SYSCALL_DEFINE3(getresgid, gid_t __user *, rgid, gid_t __user *, egid, gid_t __user *, sgid) | 943 | SYSCALL_DEFINE3(getresgid, gid_t __user *, rgidp, gid_t __user *, egidp, gid_t __user *, sgidp) |
878 | { | 944 | { |
879 | const struct cred *cred = current_cred(); | 945 | const struct cred *cred = current_cred(); |
880 | int retval; | 946 | int retval; |
947 | gid_t rgid, egid, sgid; | ||
948 | |||
949 | rgid = from_kgid_munged(cred->user_ns, cred->gid); | ||
950 | egid = from_kgid_munged(cred->user_ns, cred->egid); | ||
951 | sgid = from_kgid_munged(cred->user_ns, cred->sgid); | ||
881 | 952 | ||
882 | if (!(retval = put_user(cred->gid, rgid)) && | 953 | if (!(retval = put_user(rgid, rgidp)) && |
883 | !(retval = put_user(cred->egid, egid))) | 954 | !(retval = put_user(egid, egidp))) |
884 | retval = put_user(cred->sgid, sgid); | 955 | retval = put_user(sgid, sgidp); |
885 | 956 | ||
886 | return retval; | 957 | return retval; |
887 | } | 958 | } |
@@ -898,18 +969,24 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid) | |||
898 | const struct cred *old; | 969 | const struct cred *old; |
899 | struct cred *new; | 970 | struct cred *new; |
900 | uid_t old_fsuid; | 971 | uid_t old_fsuid; |
972 | kuid_t kuid; | ||
973 | |||
974 | old = current_cred(); | ||
975 | old_fsuid = from_kuid_munged(old->user_ns, old->fsuid); | ||
976 | |||
977 | kuid = make_kuid(old->user_ns, uid); | ||
978 | if (!uid_valid(kuid)) | ||
979 | return old_fsuid; | ||
901 | 980 | ||
902 | new = prepare_creds(); | 981 | new = prepare_creds(); |
903 | if (!new) | 982 | if (!new) |
904 | return current_fsuid(); | 983 | return old_fsuid; |
905 | old = current_cred(); | ||
906 | old_fsuid = old->fsuid; | ||
907 | 984 | ||
908 | if (uid == old->uid || uid == old->euid || | 985 | if (uid_eq(kuid, old->uid) || uid_eq(kuid, old->euid) || |
909 | uid == old->suid || uid == old->fsuid || | 986 | uid_eq(kuid, old->suid) || uid_eq(kuid, old->fsuid) || |
910 | nsown_capable(CAP_SETUID)) { | 987 | nsown_capable(CAP_SETUID)) { |
911 | if (uid != old_fsuid) { | 988 | if (!uid_eq(kuid, old->fsuid)) { |
912 | new->fsuid = uid; | 989 | new->fsuid = kuid; |
913 | if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0) | 990 | if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0) |
914 | goto change_okay; | 991 | goto change_okay; |
915 | } | 992 | } |
@@ -931,18 +1008,24 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid) | |||
931 | const struct cred *old; | 1008 | const struct cred *old; |
932 | struct cred *new; | 1009 | struct cred *new; |
933 | gid_t old_fsgid; | 1010 | gid_t old_fsgid; |
1011 | kgid_t kgid; | ||
1012 | |||
1013 | old = current_cred(); | ||
1014 | old_fsgid = from_kgid_munged(old->user_ns, old->fsgid); | ||
1015 | |||
1016 | kgid = make_kgid(old->user_ns, gid); | ||
1017 | if (!gid_valid(kgid)) | ||
1018 | return old_fsgid; | ||
934 | 1019 | ||
935 | new = prepare_creds(); | 1020 | new = prepare_creds(); |
936 | if (!new) | 1021 | if (!new) |
937 | return current_fsgid(); | 1022 | return old_fsgid; |
938 | old = current_cred(); | ||
939 | old_fsgid = old->fsgid; | ||
940 | 1023 | ||
941 | if (gid == old->gid || gid == old->egid || | 1024 | if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->egid) || |
942 | gid == old->sgid || gid == old->fsgid || | 1025 | gid_eq(kgid, old->sgid) || gid_eq(kgid, old->fsgid) || |
943 | nsown_capable(CAP_SETGID)) { | 1026 | nsown_capable(CAP_SETGID)) { |
944 | if (gid != old_fsgid) { | 1027 | if (!gid_eq(kgid, old->fsgid)) { |
945 | new->fsgid = gid; | 1028 | new->fsgid = kgid; |
946 | goto change_okay; | 1029 | goto change_okay; |
947 | } | 1030 | } |
948 | } | 1031 | } |
@@ -1498,15 +1581,14 @@ static int check_prlimit_permission(struct task_struct *task) | |||
1498 | return 0; | 1581 | return 0; |
1499 | 1582 | ||
1500 | tcred = __task_cred(task); | 1583 | tcred = __task_cred(task); |
1501 | if (cred->user->user_ns == tcred->user->user_ns && | 1584 | if (uid_eq(cred->uid, tcred->euid) && |
1502 | (cred->uid == tcred->euid && | 1585 | uid_eq(cred->uid, tcred->suid) && |
1503 | cred->uid == tcred->suid && | 1586 | uid_eq(cred->uid, tcred->uid) && |
1504 | cred->uid == tcred->uid && | 1587 | gid_eq(cred->gid, tcred->egid) && |
1505 | cred->gid == tcred->egid && | 1588 | gid_eq(cred->gid, tcred->sgid) && |
1506 | cred->gid == tcred->sgid && | 1589 | gid_eq(cred->gid, tcred->gid)) |
1507 | cred->gid == tcred->gid)) | ||
1508 | return 0; | 1590 | return 0; |
1509 | if (ns_capable(tcred->user->user_ns, CAP_SYS_RESOURCE)) | 1591 | if (ns_capable(tcred->user_ns, CAP_SYS_RESOURCE)) |
1510 | return 0; | 1592 | return 0; |
1511 | 1593 | ||
1512 | return -EPERM; | 1594 | return -EPERM; |
diff --git a/kernel/timer.c b/kernel/timer.c index 09de9a941cd7..6ec7e7e0db43 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -1435,25 +1435,25 @@ SYSCALL_DEFINE0(getppid) | |||
1435 | SYSCALL_DEFINE0(getuid) | 1435 | SYSCALL_DEFINE0(getuid) |
1436 | { | 1436 | { |
1437 | /* Only we change this so SMP safe */ | 1437 | /* Only we change this so SMP safe */ |
1438 | return current_uid(); | 1438 | return from_kuid_munged(current_user_ns(), current_uid()); |
1439 | } | 1439 | } |
1440 | 1440 | ||
1441 | SYSCALL_DEFINE0(geteuid) | 1441 | SYSCALL_DEFINE0(geteuid) |
1442 | { | 1442 | { |
1443 | /* Only we change this so SMP safe */ | 1443 | /* Only we change this so SMP safe */ |
1444 | return current_euid(); | 1444 | return from_kuid_munged(current_user_ns(), current_euid()); |
1445 | } | 1445 | } |
1446 | 1446 | ||
1447 | SYSCALL_DEFINE0(getgid) | 1447 | SYSCALL_DEFINE0(getgid) |
1448 | { | 1448 | { |
1449 | /* Only we change this so SMP safe */ | 1449 | /* Only we change this so SMP safe */ |
1450 | return current_gid(); | 1450 | return from_kgid_munged(current_user_ns(), current_gid()); |
1451 | } | 1451 | } |
1452 | 1452 | ||
1453 | SYSCALL_DEFINE0(getegid) | 1453 | SYSCALL_DEFINE0(getegid) |
1454 | { | 1454 | { |
1455 | /* Only we change this so SMP safe */ | 1455 | /* Only we change this so SMP safe */ |
1456 | return current_egid(); | 1456 | return from_kgid_munged(current_user_ns(), current_egid()); |
1457 | } | 1457 | } |
1458 | 1458 | ||
1459 | #endif | 1459 | #endif |
diff --git a/kernel/uid16.c b/kernel/uid16.c index 51c6e89e8619..d7948eb10225 100644 --- a/kernel/uid16.c +++ b/kernel/uid16.c | |||
@@ -81,14 +81,19 @@ SYSCALL_DEFINE3(setresuid16, old_uid_t, ruid, old_uid_t, euid, old_uid_t, suid) | |||
81 | return ret; | 81 | return ret; |
82 | } | 82 | } |
83 | 83 | ||
84 | SYSCALL_DEFINE3(getresuid16, old_uid_t __user *, ruid, old_uid_t __user *, euid, old_uid_t __user *, suid) | 84 | SYSCALL_DEFINE3(getresuid16, old_uid_t __user *, ruidp, old_uid_t __user *, euidp, old_uid_t __user *, suidp) |
85 | { | 85 | { |
86 | const struct cred *cred = current_cred(); | 86 | const struct cred *cred = current_cred(); |
87 | int retval; | 87 | int retval; |
88 | old_uid_t ruid, euid, suid; | ||
88 | 89 | ||
89 | if (!(retval = put_user(high2lowuid(cred->uid), ruid)) && | 90 | ruid = high2lowuid(from_kuid_munged(cred->user_ns, cred->uid)); |
90 | !(retval = put_user(high2lowuid(cred->euid), euid))) | 91 | euid = high2lowuid(from_kuid_munged(cred->user_ns, cred->euid)); |
91 | retval = put_user(high2lowuid(cred->suid), suid); | 92 | suid = high2lowuid(from_kuid_munged(cred->user_ns, cred->suid)); |
93 | |||
94 | if (!(retval = put_user(ruid, ruidp)) && | ||
95 | !(retval = put_user(euid, euidp))) | ||
96 | retval = put_user(suid, suidp); | ||
92 | 97 | ||
93 | return retval; | 98 | return retval; |
94 | } | 99 | } |
@@ -103,14 +108,19 @@ SYSCALL_DEFINE3(setresgid16, old_gid_t, rgid, old_gid_t, egid, old_gid_t, sgid) | |||
103 | } | 108 | } |
104 | 109 | ||
105 | 110 | ||
106 | SYSCALL_DEFINE3(getresgid16, old_gid_t __user *, rgid, old_gid_t __user *, egid, old_gid_t __user *, sgid) | 111 | SYSCALL_DEFINE3(getresgid16, old_gid_t __user *, rgidp, old_gid_t __user *, egidp, old_gid_t __user *, sgidp) |
107 | { | 112 | { |
108 | const struct cred *cred = current_cred(); | 113 | const struct cred *cred = current_cred(); |
109 | int retval; | 114 | int retval; |
115 | old_gid_t rgid, egid, sgid; | ||
116 | |||
117 | rgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->gid)); | ||
118 | egid = high2lowgid(from_kgid_munged(cred->user_ns, cred->egid)); | ||
119 | sgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->sgid)); | ||
110 | 120 | ||
111 | if (!(retval = put_user(high2lowgid(cred->gid), rgid)) && | 121 | if (!(retval = put_user(rgid, rgidp)) && |
112 | !(retval = put_user(high2lowgid(cred->egid), egid))) | 122 | !(retval = put_user(egid, egidp))) |
113 | retval = put_user(high2lowgid(cred->sgid), sgid); | 123 | retval = put_user(sgid, sgidp); |
114 | 124 | ||
115 | return retval; | 125 | return retval; |
116 | } | 126 | } |
@@ -134,11 +144,14 @@ SYSCALL_DEFINE1(setfsgid16, old_gid_t, gid) | |||
134 | static int groups16_to_user(old_gid_t __user *grouplist, | 144 | static int groups16_to_user(old_gid_t __user *grouplist, |
135 | struct group_info *group_info) | 145 | struct group_info *group_info) |
136 | { | 146 | { |
147 | struct user_namespace *user_ns = current_user_ns(); | ||
137 | int i; | 148 | int i; |
138 | old_gid_t group; | 149 | old_gid_t group; |
150 | kgid_t kgid; | ||
139 | 151 | ||
140 | for (i = 0; i < group_info->ngroups; i++) { | 152 | for (i = 0; i < group_info->ngroups; i++) { |
141 | group = high2lowgid(GROUP_AT(group_info, i)); | 153 | kgid = GROUP_AT(group_info, i); |
154 | group = high2lowgid(from_kgid_munged(user_ns, kgid)); | ||
142 | if (put_user(group, grouplist+i)) | 155 | if (put_user(group, grouplist+i)) |
143 | return -EFAULT; | 156 | return -EFAULT; |
144 | } | 157 | } |
@@ -149,13 +162,20 @@ static int groups16_to_user(old_gid_t __user *grouplist, | |||
149 | static int groups16_from_user(struct group_info *group_info, | 162 | static int groups16_from_user(struct group_info *group_info, |
150 | old_gid_t __user *grouplist) | 163 | old_gid_t __user *grouplist) |
151 | { | 164 | { |
165 | struct user_namespace *user_ns = current_user_ns(); | ||
152 | int i; | 166 | int i; |
153 | old_gid_t group; | 167 | old_gid_t group; |
168 | kgid_t kgid; | ||
154 | 169 | ||
155 | for (i = 0; i < group_info->ngroups; i++) { | 170 | for (i = 0; i < group_info->ngroups; i++) { |
156 | if (get_user(group, grouplist+i)) | 171 | if (get_user(group, grouplist+i)) |
157 | return -EFAULT; | 172 | return -EFAULT; |
158 | GROUP_AT(group_info, i) = low2highgid(group); | 173 | |
174 | kgid = make_kgid(user_ns, low2highgid(group)); | ||
175 | if (!gid_valid(kgid)) | ||
176 | return -EINVAL; | ||
177 | |||
178 | GROUP_AT(group_info, i) = kgid; | ||
159 | } | 179 | } |
160 | 180 | ||
161 | return 0; | 181 | return 0; |
@@ -211,20 +231,20 @@ SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist) | |||
211 | 231 | ||
212 | SYSCALL_DEFINE0(getuid16) | 232 | SYSCALL_DEFINE0(getuid16) |
213 | { | 233 | { |
214 | return high2lowuid(current_uid()); | 234 | return high2lowuid(from_kuid_munged(current_user_ns(), current_uid())); |
215 | } | 235 | } |
216 | 236 | ||
217 | SYSCALL_DEFINE0(geteuid16) | 237 | SYSCALL_DEFINE0(geteuid16) |
218 | { | 238 | { |
219 | return high2lowuid(current_euid()); | 239 | return high2lowuid(from_kuid_munged(current_user_ns(), current_euid())); |
220 | } | 240 | } |
221 | 241 | ||
222 | SYSCALL_DEFINE0(getgid16) | 242 | SYSCALL_DEFINE0(getgid16) |
223 | { | 243 | { |
224 | return high2lowgid(current_gid()); | 244 | return high2lowgid(from_kgid_munged(current_user_ns(), current_gid())); |
225 | } | 245 | } |
226 | 246 | ||
227 | SYSCALL_DEFINE0(getegid16) | 247 | SYSCALL_DEFINE0(getegid16) |
228 | { | 248 | { |
229 | return high2lowgid(current_egid()); | 249 | return high2lowgid(from_kgid_munged(current_user_ns(), current_egid())); |
230 | } | 250 | } |
diff --git a/kernel/user.c b/kernel/user.c index 71dd2363ab0f..b815fefbe76f 100644 --- a/kernel/user.c +++ b/kernel/user.c | |||
@@ -22,10 +22,27 @@ | |||
22 | * and 1 for... ? | 22 | * and 1 for... ? |
23 | */ | 23 | */ |
24 | struct user_namespace init_user_ns = { | 24 | struct user_namespace init_user_ns = { |
25 | .uid_map = { | ||
26 | .nr_extents = 1, | ||
27 | .extent[0] = { | ||
28 | .first = 0, | ||
29 | .lower_first = 0, | ||
30 | .count = 4294967295U, | ||
31 | }, | ||
32 | }, | ||
33 | .gid_map = { | ||
34 | .nr_extents = 1, | ||
35 | .extent[0] = { | ||
36 | .first = 0, | ||
37 | .lower_first = 0, | ||
38 | .count = 4294967295U, | ||
39 | }, | ||
40 | }, | ||
25 | .kref = { | 41 | .kref = { |
26 | .refcount = ATOMIC_INIT(3), | 42 | .refcount = ATOMIC_INIT(3), |
27 | }, | 43 | }, |
28 | .creator = &root_user, | 44 | .owner = GLOBAL_ROOT_UID, |
45 | .group = GLOBAL_ROOT_GID, | ||
29 | }; | 46 | }; |
30 | EXPORT_SYMBOL_GPL(init_user_ns); | 47 | EXPORT_SYMBOL_GPL(init_user_ns); |
31 | 48 | ||
@@ -34,11 +51,14 @@ EXPORT_SYMBOL_GPL(init_user_ns); | |||
34 | * when changing user ID's (ie setuid() and friends). | 51 | * when changing user ID's (ie setuid() and friends). |
35 | */ | 52 | */ |
36 | 53 | ||
54 | #define UIDHASH_BITS (CONFIG_BASE_SMALL ? 3 : 7) | ||
55 | #define UIDHASH_SZ (1 << UIDHASH_BITS) | ||
37 | #define UIDHASH_MASK (UIDHASH_SZ - 1) | 56 | #define UIDHASH_MASK (UIDHASH_SZ - 1) |
38 | #define __uidhashfn(uid) (((uid >> UIDHASH_BITS) + uid) & UIDHASH_MASK) | 57 | #define __uidhashfn(uid) (((uid >> UIDHASH_BITS) + uid) & UIDHASH_MASK) |
39 | #define uidhashentry(ns, uid) ((ns)->uidhash_table + __uidhashfn((uid))) | 58 | #define uidhashentry(uid) (uidhash_table + __uidhashfn((__kuid_val(uid)))) |
40 | 59 | ||
41 | static struct kmem_cache *uid_cachep; | 60 | static struct kmem_cache *uid_cachep; |
61 | struct hlist_head uidhash_table[UIDHASH_SZ]; | ||
42 | 62 | ||
43 | /* | 63 | /* |
44 | * The uidhash_lock is mostly taken from process context, but it is | 64 | * The uidhash_lock is mostly taken from process context, but it is |
@@ -51,14 +71,14 @@ static struct kmem_cache *uid_cachep; | |||
51 | */ | 71 | */ |
52 | static DEFINE_SPINLOCK(uidhash_lock); | 72 | static DEFINE_SPINLOCK(uidhash_lock); |
53 | 73 | ||
54 | /* root_user.__count is 2, 1 for init task cred, 1 for init_user_ns->user_ns */ | 74 | /* root_user.__count is 1, for init task cred */ |
55 | struct user_struct root_user = { | 75 | struct user_struct root_user = { |
56 | .__count = ATOMIC_INIT(2), | 76 | .__count = ATOMIC_INIT(1), |
57 | .processes = ATOMIC_INIT(1), | 77 | .processes = ATOMIC_INIT(1), |
58 | .files = ATOMIC_INIT(0), | 78 | .files = ATOMIC_INIT(0), |
59 | .sigpending = ATOMIC_INIT(0), | 79 | .sigpending = ATOMIC_INIT(0), |
60 | .locked_shm = 0, | 80 | .locked_shm = 0, |
61 | .user_ns = &init_user_ns, | 81 | .uid = GLOBAL_ROOT_UID, |
62 | }; | 82 | }; |
63 | 83 | ||
64 | /* | 84 | /* |
@@ -72,16 +92,15 @@ static void uid_hash_insert(struct user_struct *up, struct hlist_head *hashent) | |||
72 | static void uid_hash_remove(struct user_struct *up) | 92 | static void uid_hash_remove(struct user_struct *up) |
73 | { | 93 | { |
74 | hlist_del_init(&up->uidhash_node); | 94 | hlist_del_init(&up->uidhash_node); |
75 | put_user_ns(up->user_ns); | ||
76 | } | 95 | } |
77 | 96 | ||
78 | static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent) | 97 | static struct user_struct *uid_hash_find(kuid_t uid, struct hlist_head *hashent) |
79 | { | 98 | { |
80 | struct user_struct *user; | 99 | struct user_struct *user; |
81 | struct hlist_node *h; | 100 | struct hlist_node *h; |
82 | 101 | ||
83 | hlist_for_each_entry(user, h, hashent, uidhash_node) { | 102 | hlist_for_each_entry(user, h, hashent, uidhash_node) { |
84 | if (user->uid == uid) { | 103 | if (uid_eq(user->uid, uid)) { |
85 | atomic_inc(&user->__count); | 104 | atomic_inc(&user->__count); |
86 | return user; | 105 | return user; |
87 | } | 106 | } |
@@ -110,14 +129,13 @@ static void free_user(struct user_struct *up, unsigned long flags) | |||
110 | * | 129 | * |
111 | * If the user_struct could not be found, return NULL. | 130 | * If the user_struct could not be found, return NULL. |
112 | */ | 131 | */ |
113 | struct user_struct *find_user(uid_t uid) | 132 | struct user_struct *find_user(kuid_t uid) |
114 | { | 133 | { |
115 | struct user_struct *ret; | 134 | struct user_struct *ret; |
116 | unsigned long flags; | 135 | unsigned long flags; |
117 | struct user_namespace *ns = current_user_ns(); | ||
118 | 136 | ||
119 | spin_lock_irqsave(&uidhash_lock, flags); | 137 | spin_lock_irqsave(&uidhash_lock, flags); |
120 | ret = uid_hash_find(uid, uidhashentry(ns, uid)); | 138 | ret = uid_hash_find(uid, uidhashentry(uid)); |
121 | spin_unlock_irqrestore(&uidhash_lock, flags); | 139 | spin_unlock_irqrestore(&uidhash_lock, flags); |
122 | return ret; | 140 | return ret; |
123 | } | 141 | } |
@@ -136,9 +154,9 @@ void free_uid(struct user_struct *up) | |||
136 | local_irq_restore(flags); | 154 | local_irq_restore(flags); |
137 | } | 155 | } |
138 | 156 | ||
139 | struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid) | 157 | struct user_struct *alloc_uid(kuid_t uid) |
140 | { | 158 | { |
141 | struct hlist_head *hashent = uidhashentry(ns, uid); | 159 | struct hlist_head *hashent = uidhashentry(uid); |
142 | struct user_struct *up, *new; | 160 | struct user_struct *up, *new; |
143 | 161 | ||
144 | spin_lock_irq(&uidhash_lock); | 162 | spin_lock_irq(&uidhash_lock); |
@@ -153,8 +171,6 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid) | |||
153 | new->uid = uid; | 171 | new->uid = uid; |
154 | atomic_set(&new->__count, 1); | 172 | atomic_set(&new->__count, 1); |
155 | 173 | ||
156 | new->user_ns = get_user_ns(ns); | ||
157 | |||
158 | /* | 174 | /* |
159 | * Before adding this, check whether we raced | 175 | * Before adding this, check whether we raced |
160 | * on adding the same user already.. | 176 | * on adding the same user already.. |
@@ -162,7 +178,6 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid) | |||
162 | spin_lock_irq(&uidhash_lock); | 178 | spin_lock_irq(&uidhash_lock); |
163 | up = uid_hash_find(uid, hashent); | 179 | up = uid_hash_find(uid, hashent); |
164 | if (up) { | 180 | if (up) { |
165 | put_user_ns(ns); | ||
166 | key_put(new->uid_keyring); | 181 | key_put(new->uid_keyring); |
167 | key_put(new->session_keyring); | 182 | key_put(new->session_keyring); |
168 | kmem_cache_free(uid_cachep, new); | 183 | kmem_cache_free(uid_cachep, new); |
@@ -187,11 +202,11 @@ static int __init uid_cache_init(void) | |||
187 | 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); | 202 | 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); |
188 | 203 | ||
189 | for(n = 0; n < UIDHASH_SZ; ++n) | 204 | for(n = 0; n < UIDHASH_SZ; ++n) |
190 | INIT_HLIST_HEAD(init_user_ns.uidhash_table + n); | 205 | INIT_HLIST_HEAD(uidhash_table + n); |
191 | 206 | ||
192 | /* Insert the root user immediately (init already runs as root) */ | 207 | /* Insert the root user immediately (init already runs as root) */ |
193 | spin_lock_irq(&uidhash_lock); | 208 | spin_lock_irq(&uidhash_lock); |
194 | uid_hash_insert(&root_user, uidhashentry(&init_user_ns, 0)); | 209 | uid_hash_insert(&root_user, uidhashentry(GLOBAL_ROOT_UID)); |
195 | spin_unlock_irq(&uidhash_lock); | 210 | spin_unlock_irq(&uidhash_lock); |
196 | 211 | ||
197 | return 0; | 212 | return 0; |
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 3b906e98b1db..86602316422d 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c | |||
@@ -11,9 +11,20 @@ | |||
11 | #include <linux/user_namespace.h> | 11 | #include <linux/user_namespace.h> |
12 | #include <linux/highuid.h> | 12 | #include <linux/highuid.h> |
13 | #include <linux/cred.h> | 13 | #include <linux/cred.h> |
14 | #include <linux/securebits.h> | ||
15 | #include <linux/keyctl.h> | ||
16 | #include <linux/key-type.h> | ||
17 | #include <keys/user-type.h> | ||
18 | #include <linux/seq_file.h> | ||
19 | #include <linux/fs.h> | ||
20 | #include <linux/uaccess.h> | ||
21 | #include <linux/ctype.h> | ||
14 | 22 | ||
15 | static struct kmem_cache *user_ns_cachep __read_mostly; | 23 | static struct kmem_cache *user_ns_cachep __read_mostly; |
16 | 24 | ||
25 | static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid, | ||
26 | struct uid_gid_map *map); | ||
27 | |||
17 | /* | 28 | /* |
18 | * Create a new user namespace, deriving the creator from the user in the | 29 | * Create a new user namespace, deriving the creator from the user in the |
19 | * passed credentials, and replacing that user with the new root user for the | 30 | * passed credentials, and replacing that user with the new root user for the |
@@ -24,109 +35,565 @@ static struct kmem_cache *user_ns_cachep __read_mostly; | |||
24 | */ | 35 | */ |
25 | int create_user_ns(struct cred *new) | 36 | int create_user_ns(struct cred *new) |
26 | { | 37 | { |
27 | struct user_namespace *ns; | 38 | struct user_namespace *ns, *parent_ns = new->user_ns; |
28 | struct user_struct *root_user; | 39 | kuid_t owner = new->euid; |
29 | int n; | 40 | kgid_t group = new->egid; |
41 | |||
42 | /* The creator needs a mapping in the parent user namespace | ||
43 | * or else we won't be able to reasonably tell userspace who | ||
44 | * created a user_namespace. | ||
45 | */ | ||
46 | if (!kuid_has_mapping(parent_ns, owner) || | ||
47 | !kgid_has_mapping(parent_ns, group)) | ||
48 | return -EPERM; | ||
30 | 49 | ||
31 | ns = kmem_cache_alloc(user_ns_cachep, GFP_KERNEL); | 50 | ns = kmem_cache_zalloc(user_ns_cachep, GFP_KERNEL); |
32 | if (!ns) | 51 | if (!ns) |
33 | return -ENOMEM; | 52 | return -ENOMEM; |
34 | 53 | ||
35 | kref_init(&ns->kref); | 54 | kref_init(&ns->kref); |
55 | ns->parent = parent_ns; | ||
56 | ns->owner = owner; | ||
57 | ns->group = group; | ||
36 | 58 | ||
37 | for (n = 0; n < UIDHASH_SZ; ++n) | 59 | /* Start with the same capabilities as init but useless for doing |
38 | INIT_HLIST_HEAD(ns->uidhash_table + n); | 60 | * anything as the capabilities are bound to the new user namespace. |
39 | 61 | */ | |
40 | /* Alloc new root user. */ | 62 | new->securebits = SECUREBITS_DEFAULT; |
41 | root_user = alloc_uid(ns, 0); | 63 | new->cap_inheritable = CAP_EMPTY_SET; |
42 | if (!root_user) { | 64 | new->cap_permitted = CAP_FULL_SET; |
43 | kmem_cache_free(user_ns_cachep, ns); | 65 | new->cap_effective = CAP_FULL_SET; |
44 | return -ENOMEM; | 66 | new->cap_bset = CAP_FULL_SET; |
45 | } | ||
46 | |||
47 | /* set the new root user in the credentials under preparation */ | ||
48 | ns->creator = new->user; | ||
49 | new->user = root_user; | ||
50 | new->uid = new->euid = new->suid = new->fsuid = 0; | ||
51 | new->gid = new->egid = new->sgid = new->fsgid = 0; | ||
52 | put_group_info(new->group_info); | ||
53 | new->group_info = get_group_info(&init_groups); | ||
54 | #ifdef CONFIG_KEYS | 67 | #ifdef CONFIG_KEYS |
55 | key_put(new->request_key_auth); | 68 | key_put(new->request_key_auth); |
56 | new->request_key_auth = NULL; | 69 | new->request_key_auth = NULL; |
57 | #endif | 70 | #endif |
58 | /* tgcred will be cleared in our caller bc CLONE_THREAD won't be set */ | 71 | /* tgcred will be cleared in our caller bc CLONE_THREAD won't be set */ |
59 | 72 | ||
60 | /* root_user holds a reference to ns, our reference can be dropped */ | 73 | /* Leave the new->user_ns reference with the new user namespace. */ |
61 | put_user_ns(ns); | 74 | /* Leave the reference to our user_ns with the new cred. */ |
75 | new->user_ns = ns; | ||
62 | 76 | ||
63 | return 0; | 77 | return 0; |
64 | } | 78 | } |
65 | 79 | ||
66 | /* | 80 | void free_user_ns(struct kref *kref) |
67 | * Deferred destructor for a user namespace. This is required because | ||
68 | * free_user_ns() may be called with uidhash_lock held, but we need to call | ||
69 | * back to free_uid() which will want to take the lock again. | ||
70 | */ | ||
71 | static void free_user_ns_work(struct work_struct *work) | ||
72 | { | 81 | { |
73 | struct user_namespace *ns = | 82 | struct user_namespace *parent, *ns = |
74 | container_of(work, struct user_namespace, destroyer); | 83 | container_of(kref, struct user_namespace, kref); |
75 | free_uid(ns->creator); | 84 | |
85 | parent = ns->parent; | ||
76 | kmem_cache_free(user_ns_cachep, ns); | 86 | kmem_cache_free(user_ns_cachep, ns); |
87 | put_user_ns(parent); | ||
77 | } | 88 | } |
89 | EXPORT_SYMBOL(free_user_ns); | ||
78 | 90 | ||
79 | void free_user_ns(struct kref *kref) | 91 | static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count) |
80 | { | 92 | { |
81 | struct user_namespace *ns = | 93 | unsigned idx, extents; |
82 | container_of(kref, struct user_namespace, kref); | 94 | u32 first, last, id2; |
95 | |||
96 | id2 = id + count - 1; | ||
97 | |||
98 | /* Find the matching extent */ | ||
99 | extents = map->nr_extents; | ||
100 | smp_read_barrier_depends(); | ||
101 | for (idx = 0; idx < extents; idx++) { | ||
102 | first = map->extent[idx].first; | ||
103 | last = first + map->extent[idx].count - 1; | ||
104 | if (id >= first && id <= last && | ||
105 | (id2 >= first && id2 <= last)) | ||
106 | break; | ||
107 | } | ||
108 | /* Map the id or note failure */ | ||
109 | if (idx < extents) | ||
110 | id = (id - first) + map->extent[idx].lower_first; | ||
111 | else | ||
112 | id = (u32) -1; | ||
83 | 113 | ||
84 | INIT_WORK(&ns->destroyer, free_user_ns_work); | 114 | return id; |
85 | schedule_work(&ns->destroyer); | ||
86 | } | 115 | } |
87 | EXPORT_SYMBOL(free_user_ns); | ||
88 | 116 | ||
89 | uid_t user_ns_map_uid(struct user_namespace *to, const struct cred *cred, uid_t uid) | 117 | static u32 map_id_down(struct uid_gid_map *map, u32 id) |
90 | { | 118 | { |
91 | struct user_namespace *tmp; | 119 | unsigned idx, extents; |
120 | u32 first, last; | ||
92 | 121 | ||
93 | if (likely(to == cred->user->user_ns)) | 122 | /* Find the matching extent */ |
94 | return uid; | 123 | extents = map->nr_extents; |
124 | smp_read_barrier_depends(); | ||
125 | for (idx = 0; idx < extents; idx++) { | ||
126 | first = map->extent[idx].first; | ||
127 | last = first + map->extent[idx].count - 1; | ||
128 | if (id >= first && id <= last) | ||
129 | break; | ||
130 | } | ||
131 | /* Map the id or note failure */ | ||
132 | if (idx < extents) | ||
133 | id = (id - first) + map->extent[idx].lower_first; | ||
134 | else | ||
135 | id = (u32) -1; | ||
95 | 136 | ||
137 | return id; | ||
138 | } | ||
96 | 139 | ||
97 | /* Is cred->user the creator of the target user_ns | 140 | static u32 map_id_up(struct uid_gid_map *map, u32 id) |
98 | * or the creator of one of it's parents? | 141 | { |
99 | */ | 142 | unsigned idx, extents; |
100 | for ( tmp = to; tmp != &init_user_ns; | 143 | u32 first, last; |
101 | tmp = tmp->creator->user_ns ) { | 144 | |
102 | if (cred->user == tmp->creator) { | 145 | /* Find the matching extent */ |
103 | return (uid_t)0; | 146 | extents = map->nr_extents; |
104 | } | 147 | smp_read_barrier_depends(); |
148 | for (idx = 0; idx < extents; idx++) { | ||
149 | first = map->extent[idx].lower_first; | ||
150 | last = first + map->extent[idx].count - 1; | ||
151 | if (id >= first && id <= last) | ||
152 | break; | ||
105 | } | 153 | } |
154 | /* Map the id or note failure */ | ||
155 | if (idx < extents) | ||
156 | id = (id - first) + map->extent[idx].first; | ||
157 | else | ||
158 | id = (u32) -1; | ||
159 | |||
160 | return id; | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * make_kuid - Map a user-namespace uid pair into a kuid. | ||
165 | * @ns: User namespace that the uid is in | ||
166 | * @uid: User identifier | ||
167 | * | ||
168 | * Maps a user-namespace uid pair into a kernel internal kuid, | ||
169 | * and returns that kuid. | ||
170 | * | ||
171 | * When there is no mapping defined for the user-namespace uid | ||
172 | * pair INVALID_UID is returned. Callers are expected to test | ||
173 | * for and handle handle INVALID_UID being returned. INVALID_UID | ||
174 | * may be tested for using uid_valid(). | ||
175 | */ | ||
176 | kuid_t make_kuid(struct user_namespace *ns, uid_t uid) | ||
177 | { | ||
178 | /* Map the uid to a global kernel uid */ | ||
179 | return KUIDT_INIT(map_id_down(&ns->uid_map, uid)); | ||
180 | } | ||
181 | EXPORT_SYMBOL(make_kuid); | ||
182 | |||
183 | /** | ||
184 | * from_kuid - Create a uid from a kuid user-namespace pair. | ||
185 | * @targ: The user namespace we want a uid in. | ||
186 | * @kuid: The kernel internal uid to start with. | ||
187 | * | ||
188 | * Map @kuid into the user-namespace specified by @targ and | ||
189 | * return the resulting uid. | ||
190 | * | ||
191 | * There is always a mapping into the initial user_namespace. | ||
192 | * | ||
193 | * If @kuid has no mapping in @targ (uid_t)-1 is returned. | ||
194 | */ | ||
195 | uid_t from_kuid(struct user_namespace *targ, kuid_t kuid) | ||
196 | { | ||
197 | /* Map the uid from a global kernel uid */ | ||
198 | return map_id_up(&targ->uid_map, __kuid_val(kuid)); | ||
199 | } | ||
200 | EXPORT_SYMBOL(from_kuid); | ||
106 | 201 | ||
107 | /* No useful relationship so no mapping */ | 202 | /** |
108 | return overflowuid; | 203 | * from_kuid_munged - Create a uid from a kuid user-namespace pair. |
204 | * @targ: The user namespace we want a uid in. | ||
205 | * @kuid: The kernel internal uid to start with. | ||
206 | * | ||
207 | * Map @kuid into the user-namespace specified by @targ and | ||
208 | * return the resulting uid. | ||
209 | * | ||
210 | * There is always a mapping into the initial user_namespace. | ||
211 | * | ||
212 | * Unlike from_kuid from_kuid_munged never fails and always | ||
213 | * returns a valid uid. This makes from_kuid_munged appropriate | ||
214 | * for use in syscalls like stat and getuid where failing the | ||
215 | * system call and failing to provide a valid uid are not an | ||
216 | * options. | ||
217 | * | ||
218 | * If @kuid has no mapping in @targ overflowuid is returned. | ||
219 | */ | ||
220 | uid_t from_kuid_munged(struct user_namespace *targ, kuid_t kuid) | ||
221 | { | ||
222 | uid_t uid; | ||
223 | uid = from_kuid(targ, kuid); | ||
224 | |||
225 | if (uid == (uid_t) -1) | ||
226 | uid = overflowuid; | ||
227 | return uid; | ||
109 | } | 228 | } |
229 | EXPORT_SYMBOL(from_kuid_munged); | ||
110 | 230 | ||
111 | gid_t user_ns_map_gid(struct user_namespace *to, const struct cred *cred, gid_t gid) | 231 | /** |
232 | * make_kgid - Map a user-namespace gid pair into a kgid. | ||
233 | * @ns: User namespace that the gid is in | ||
234 | * @uid: group identifier | ||
235 | * | ||
236 | * Maps a user-namespace gid pair into a kernel internal kgid, | ||
237 | * and returns that kgid. | ||
238 | * | ||
239 | * When there is no mapping defined for the user-namespace gid | ||
240 | * pair INVALID_GID is returned. Callers are expected to test | ||
241 | * for and handle INVALID_GID being returned. INVALID_GID may be | ||
242 | * tested for using gid_valid(). | ||
243 | */ | ||
244 | kgid_t make_kgid(struct user_namespace *ns, gid_t gid) | ||
112 | { | 245 | { |
113 | struct user_namespace *tmp; | 246 | /* Map the gid to a global kernel gid */ |
247 | return KGIDT_INIT(map_id_down(&ns->gid_map, gid)); | ||
248 | } | ||
249 | EXPORT_SYMBOL(make_kgid); | ||
114 | 250 | ||
115 | if (likely(to == cred->user->user_ns)) | 251 | /** |
116 | return gid; | 252 | * from_kgid - Create a gid from a kgid user-namespace pair. |
253 | * @targ: The user namespace we want a gid in. | ||
254 | * @kgid: The kernel internal gid to start with. | ||
255 | * | ||
256 | * Map @kgid into the user-namespace specified by @targ and | ||
257 | * return the resulting gid. | ||
258 | * | ||
259 | * There is always a mapping into the initial user_namespace. | ||
260 | * | ||
261 | * If @kgid has no mapping in @targ (gid_t)-1 is returned. | ||
262 | */ | ||
263 | gid_t from_kgid(struct user_namespace *targ, kgid_t kgid) | ||
264 | { | ||
265 | /* Map the gid from a global kernel gid */ | ||
266 | return map_id_up(&targ->gid_map, __kgid_val(kgid)); | ||
267 | } | ||
268 | EXPORT_SYMBOL(from_kgid); | ||
269 | |||
270 | /** | ||
271 | * from_kgid_munged - Create a gid from a kgid user-namespace pair. | ||
272 | * @targ: The user namespace we want a gid in. | ||
273 | * @kgid: The kernel internal gid to start with. | ||
274 | * | ||
275 | * Map @kgid into the user-namespace specified by @targ and | ||
276 | * return the resulting gid. | ||
277 | * | ||
278 | * There is always a mapping into the initial user_namespace. | ||
279 | * | ||
280 | * Unlike from_kgid from_kgid_munged never fails and always | ||
281 | * returns a valid gid. This makes from_kgid_munged appropriate | ||
282 | * for use in syscalls like stat and getgid where failing the | ||
283 | * system call and failing to provide a valid gid are not options. | ||
284 | * | ||
285 | * If @kgid has no mapping in @targ overflowgid is returned. | ||
286 | */ | ||
287 | gid_t from_kgid_munged(struct user_namespace *targ, kgid_t kgid) | ||
288 | { | ||
289 | gid_t gid; | ||
290 | gid = from_kgid(targ, kgid); | ||
117 | 291 | ||
118 | /* Is cred->user the creator of the target user_ns | 292 | if (gid == (gid_t) -1) |
119 | * or the creator of one of it's parents? | 293 | gid = overflowgid; |
294 | return gid; | ||
295 | } | ||
296 | EXPORT_SYMBOL(from_kgid_munged); | ||
297 | |||
298 | static int uid_m_show(struct seq_file *seq, void *v) | ||
299 | { | ||
300 | struct user_namespace *ns = seq->private; | ||
301 | struct uid_gid_extent *extent = v; | ||
302 | struct user_namespace *lower_ns; | ||
303 | uid_t lower; | ||
304 | |||
305 | lower_ns = current_user_ns(); | ||
306 | if ((lower_ns == ns) && lower_ns->parent) | ||
307 | lower_ns = lower_ns->parent; | ||
308 | |||
309 | lower = from_kuid(lower_ns, KUIDT_INIT(extent->lower_first)); | ||
310 | |||
311 | seq_printf(seq, "%10u %10u %10u\n", | ||
312 | extent->first, | ||
313 | lower, | ||
314 | extent->count); | ||
315 | |||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static int gid_m_show(struct seq_file *seq, void *v) | ||
320 | { | ||
321 | struct user_namespace *ns = seq->private; | ||
322 | struct uid_gid_extent *extent = v; | ||
323 | struct user_namespace *lower_ns; | ||
324 | gid_t lower; | ||
325 | |||
326 | lower_ns = current_user_ns(); | ||
327 | if ((lower_ns == ns) && lower_ns->parent) | ||
328 | lower_ns = lower_ns->parent; | ||
329 | |||
330 | lower = from_kgid(lower_ns, KGIDT_INIT(extent->lower_first)); | ||
331 | |||
332 | seq_printf(seq, "%10u %10u %10u\n", | ||
333 | extent->first, | ||
334 | lower, | ||
335 | extent->count); | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static void *m_start(struct seq_file *seq, loff_t *ppos, struct uid_gid_map *map) | ||
341 | { | ||
342 | struct uid_gid_extent *extent = NULL; | ||
343 | loff_t pos = *ppos; | ||
344 | |||
345 | if (pos < map->nr_extents) | ||
346 | extent = &map->extent[pos]; | ||
347 | |||
348 | return extent; | ||
349 | } | ||
350 | |||
351 | static void *uid_m_start(struct seq_file *seq, loff_t *ppos) | ||
352 | { | ||
353 | struct user_namespace *ns = seq->private; | ||
354 | |||
355 | return m_start(seq, ppos, &ns->uid_map); | ||
356 | } | ||
357 | |||
358 | static void *gid_m_start(struct seq_file *seq, loff_t *ppos) | ||
359 | { | ||
360 | struct user_namespace *ns = seq->private; | ||
361 | |||
362 | return m_start(seq, ppos, &ns->gid_map); | ||
363 | } | ||
364 | |||
365 | static void *m_next(struct seq_file *seq, void *v, loff_t *pos) | ||
366 | { | ||
367 | (*pos)++; | ||
368 | return seq->op->start(seq, pos); | ||
369 | } | ||
370 | |||
371 | static void m_stop(struct seq_file *seq, void *v) | ||
372 | { | ||
373 | return; | ||
374 | } | ||
375 | |||
376 | struct seq_operations proc_uid_seq_operations = { | ||
377 | .start = uid_m_start, | ||
378 | .stop = m_stop, | ||
379 | .next = m_next, | ||
380 | .show = uid_m_show, | ||
381 | }; | ||
382 | |||
383 | struct seq_operations proc_gid_seq_operations = { | ||
384 | .start = gid_m_start, | ||
385 | .stop = m_stop, | ||
386 | .next = m_next, | ||
387 | .show = gid_m_show, | ||
388 | }; | ||
389 | |||
390 | static DEFINE_MUTEX(id_map_mutex); | ||
391 | |||
392 | static ssize_t map_write(struct file *file, const char __user *buf, | ||
393 | size_t count, loff_t *ppos, | ||
394 | int cap_setid, | ||
395 | struct uid_gid_map *map, | ||
396 | struct uid_gid_map *parent_map) | ||
397 | { | ||
398 | struct seq_file *seq = file->private_data; | ||
399 | struct user_namespace *ns = seq->private; | ||
400 | struct uid_gid_map new_map; | ||
401 | unsigned idx; | ||
402 | struct uid_gid_extent *extent, *last = NULL; | ||
403 | unsigned long page = 0; | ||
404 | char *kbuf, *pos, *next_line; | ||
405 | ssize_t ret = -EINVAL; | ||
406 | |||
407 | /* | ||
408 | * The id_map_mutex serializes all writes to any given map. | ||
409 | * | ||
410 | * Any map is only ever written once. | ||
411 | * | ||
412 | * An id map fits within 1 cache line on most architectures. | ||
413 | * | ||
414 | * On read nothing needs to be done unless you are on an | ||
415 | * architecture with a crazy cache coherency model like alpha. | ||
416 | * | ||
417 | * There is a one time data dependency between reading the | ||
418 | * count of the extents and the values of the extents. The | ||
419 | * desired behavior is to see the values of the extents that | ||
420 | * were written before the count of the extents. | ||
421 | * | ||
422 | * To achieve this smp_wmb() is used on guarantee the write | ||
423 | * order and smp_read_barrier_depends() is guaranteed that we | ||
424 | * don't have crazy architectures returning stale data. | ||
425 | * | ||
120 | */ | 426 | */ |
121 | for ( tmp = to; tmp != &init_user_ns; | 427 | mutex_lock(&id_map_mutex); |
122 | tmp = tmp->creator->user_ns ) { | 428 | |
123 | if (cred->user == tmp->creator) { | 429 | ret = -EPERM; |
124 | return (gid_t)0; | 430 | /* Only allow one successful write to the map */ |
431 | if (map->nr_extents != 0) | ||
432 | goto out; | ||
433 | |||
434 | /* Require the appropriate privilege CAP_SETUID or CAP_SETGID | ||
435 | * over the user namespace in order to set the id mapping. | ||
436 | */ | ||
437 | if (!ns_capable(ns, cap_setid)) | ||
438 | goto out; | ||
439 | |||
440 | /* Get a buffer */ | ||
441 | ret = -ENOMEM; | ||
442 | page = __get_free_page(GFP_TEMPORARY); | ||
443 | kbuf = (char *) page; | ||
444 | if (!page) | ||
445 | goto out; | ||
446 | |||
447 | /* Only allow <= page size writes at the beginning of the file */ | ||
448 | ret = -EINVAL; | ||
449 | if ((*ppos != 0) || (count >= PAGE_SIZE)) | ||
450 | goto out; | ||
451 | |||
452 | /* Slurp in the user data */ | ||
453 | ret = -EFAULT; | ||
454 | if (copy_from_user(kbuf, buf, count)) | ||
455 | goto out; | ||
456 | kbuf[count] = '\0'; | ||
457 | |||
458 | /* Parse the user data */ | ||
459 | ret = -EINVAL; | ||
460 | pos = kbuf; | ||
461 | new_map.nr_extents = 0; | ||
462 | for (;pos; pos = next_line) { | ||
463 | extent = &new_map.extent[new_map.nr_extents]; | ||
464 | |||
465 | /* Find the end of line and ensure I don't look past it */ | ||
466 | next_line = strchr(pos, '\n'); | ||
467 | if (next_line) { | ||
468 | *next_line = '\0'; | ||
469 | next_line++; | ||
470 | if (*next_line == '\0') | ||
471 | next_line = NULL; | ||
125 | } | 472 | } |
473 | |||
474 | pos = skip_spaces(pos); | ||
475 | extent->first = simple_strtoul(pos, &pos, 10); | ||
476 | if (!isspace(*pos)) | ||
477 | goto out; | ||
478 | |||
479 | pos = skip_spaces(pos); | ||
480 | extent->lower_first = simple_strtoul(pos, &pos, 10); | ||
481 | if (!isspace(*pos)) | ||
482 | goto out; | ||
483 | |||
484 | pos = skip_spaces(pos); | ||
485 | extent->count = simple_strtoul(pos, &pos, 10); | ||
486 | if (*pos && !isspace(*pos)) | ||
487 | goto out; | ||
488 | |||
489 | /* Verify there is not trailing junk on the line */ | ||
490 | pos = skip_spaces(pos); | ||
491 | if (*pos != '\0') | ||
492 | goto out; | ||
493 | |||
494 | /* Verify we have been given valid starting values */ | ||
495 | if ((extent->first == (u32) -1) || | ||
496 | (extent->lower_first == (u32) -1 )) | ||
497 | goto out; | ||
498 | |||
499 | /* Verify count is not zero and does not cause the extent to wrap */ | ||
500 | if ((extent->first + extent->count) <= extent->first) | ||
501 | goto out; | ||
502 | if ((extent->lower_first + extent->count) <= extent->lower_first) | ||
503 | goto out; | ||
504 | |||
505 | /* For now only accept extents that are strictly in order */ | ||
506 | if (last && | ||
507 | (((last->first + last->count) > extent->first) || | ||
508 | ((last->lower_first + last->count) > extent->lower_first))) | ||
509 | goto out; | ||
510 | |||
511 | new_map.nr_extents++; | ||
512 | last = extent; | ||
513 | |||
514 | /* Fail if the file contains too many extents */ | ||
515 | if ((new_map.nr_extents == UID_GID_MAP_MAX_EXTENTS) && | ||
516 | (next_line != NULL)) | ||
517 | goto out; | ||
518 | } | ||
519 | /* Be very certaint the new map actually exists */ | ||
520 | if (new_map.nr_extents == 0) | ||
521 | goto out; | ||
522 | |||
523 | ret = -EPERM; | ||
524 | /* Validate the user is allowed to use user id's mapped to. */ | ||
525 | if (!new_idmap_permitted(ns, cap_setid, &new_map)) | ||
526 | goto out; | ||
527 | |||
528 | /* Map the lower ids from the parent user namespace to the | ||
529 | * kernel global id space. | ||
530 | */ | ||
531 | for (idx = 0; idx < new_map.nr_extents; idx++) { | ||
532 | u32 lower_first; | ||
533 | extent = &new_map.extent[idx]; | ||
534 | |||
535 | lower_first = map_id_range_down(parent_map, | ||
536 | extent->lower_first, | ||
537 | extent->count); | ||
538 | |||
539 | /* Fail if we can not map the specified extent to | ||
540 | * the kernel global id space. | ||
541 | */ | ||
542 | if (lower_first == (u32) -1) | ||
543 | goto out; | ||
544 | |||
545 | extent->lower_first = lower_first; | ||
126 | } | 546 | } |
127 | 547 | ||
128 | /* No useful relationship so no mapping */ | 548 | /* Install the map */ |
129 | return overflowgid; | 549 | memcpy(map->extent, new_map.extent, |
550 | new_map.nr_extents*sizeof(new_map.extent[0])); | ||
551 | smp_wmb(); | ||
552 | map->nr_extents = new_map.nr_extents; | ||
553 | |||
554 | *ppos = count; | ||
555 | ret = count; | ||
556 | out: | ||
557 | mutex_unlock(&id_map_mutex); | ||
558 | if (page) | ||
559 | free_page(page); | ||
560 | return ret; | ||
561 | } | ||
562 | |||
563 | ssize_t proc_uid_map_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos) | ||
564 | { | ||
565 | struct seq_file *seq = file->private_data; | ||
566 | struct user_namespace *ns = seq->private; | ||
567 | |||
568 | if (!ns->parent) | ||
569 | return -EPERM; | ||
570 | |||
571 | return map_write(file, buf, size, ppos, CAP_SETUID, | ||
572 | &ns->uid_map, &ns->parent->uid_map); | ||
573 | } | ||
574 | |||
575 | ssize_t proc_gid_map_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos) | ||
576 | { | ||
577 | struct seq_file *seq = file->private_data; | ||
578 | struct user_namespace *ns = seq->private; | ||
579 | |||
580 | if (!ns->parent) | ||
581 | return -EPERM; | ||
582 | |||
583 | return map_write(file, buf, size, ppos, CAP_SETGID, | ||
584 | &ns->gid_map, &ns->parent->gid_map); | ||
585 | } | ||
586 | |||
587 | static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid, | ||
588 | struct uid_gid_map *new_map) | ||
589 | { | ||
590 | /* Allow the specified ids if we have the appropriate capability | ||
591 | * (CAP_SETUID or CAP_SETGID) over the parent user namespace. | ||
592 | */ | ||
593 | if (ns_capable(ns->parent, cap_setid)) | ||
594 | return true; | ||
595 | |||
596 | return false; | ||
130 | } | 597 | } |
131 | 598 | ||
132 | static __init int user_namespaces_init(void) | 599 | static __init int user_namespaces_init(void) |
diff --git a/kernel/utsname.c b/kernel/utsname.c index 405caf91aad5..679d97a5d3fd 100644 --- a/kernel/utsname.c +++ b/kernel/utsname.c | |||
@@ -43,7 +43,7 @@ static struct uts_namespace *clone_uts_ns(struct task_struct *tsk, | |||
43 | 43 | ||
44 | down_read(&uts_sem); | 44 | down_read(&uts_sem); |
45 | memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); | 45 | memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); |
46 | ns->user_ns = get_user_ns(task_cred_xxx(tsk, user)->user_ns); | 46 | ns->user_ns = get_user_ns(task_cred_xxx(tsk, user_ns)); |
47 | up_read(&uts_sem); | 47 | up_read(&uts_sem); |
48 | return ns; | 48 | return ns; |
49 | } | 49 | } |
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index b19569137529..39fd416ae14f 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -1334,8 +1334,8 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode, | |||
1334 | * userid as the target process. | 1334 | * userid as the target process. |
1335 | */ | 1335 | */ |
1336 | tcred = __task_cred(task); | 1336 | tcred = __task_cred(task); |
1337 | if (cred->euid != tcred->suid && cred->euid != tcred->uid && | 1337 | if (!uid_eq(cred->euid, tcred->suid) && !uid_eq(cred->euid, tcred->uid) && |
1338 | cred->uid != tcred->suid && cred->uid != tcred->uid && | 1338 | !uid_eq(cred->uid, tcred->suid) && !uid_eq(cred->uid, tcred->uid) && |
1339 | !capable(CAP_SYS_NICE)) { | 1339 | !capable(CAP_SYS_NICE)) { |
1340 | rcu_read_unlock(); | 1340 | rcu_read_unlock(); |
1341 | err = -EPERM; | 1341 | err = -EPERM; |
diff --git a/mm/migrate.c b/mm/migrate.c index 11072383ae12..ab81d482ae6f 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -1371,8 +1371,8 @@ SYSCALL_DEFINE6(move_pages, pid_t, pid, unsigned long, nr_pages, | |||
1371 | * userid as the target process. | 1371 | * userid as the target process. |
1372 | */ | 1372 | */ |
1373 | tcred = __task_cred(task); | 1373 | tcred = __task_cred(task); |
1374 | if (cred->euid != tcred->suid && cred->euid != tcred->uid && | 1374 | if (!uid_eq(cred->euid, tcred->suid) && !uid_eq(cred->euid, tcred->uid) && |
1375 | cred->uid != tcred->suid && cred->uid != tcred->uid && | 1375 | !uid_eq(cred->uid, tcred->suid) && !uid_eq(cred->uid, tcred->uid) && |
1376 | !capable(CAP_SYS_NICE)) { | 1376 | !capable(CAP_SYS_NICE)) { |
1377 | rcu_read_unlock(); | 1377 | rcu_read_unlock(); |
1378 | err = -EPERM; | 1378 | err = -EPERM; |
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 46bf2ed5594c..9f09a1fde9f9 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -410,8 +410,8 @@ static void dump_tasks(const struct mem_cgroup *memcg, const nodemask_t *nodemas | |||
410 | } | 410 | } |
411 | 411 | ||
412 | pr_info("[%5d] %5d %5d %8lu %8lu %3u %3d %5d %s\n", | 412 | pr_info("[%5d] %5d %5d %8lu %8lu %3u %3d %5d %s\n", |
413 | task->pid, task_uid(task), task->tgid, | 413 | task->pid, from_kuid(&init_user_ns, task_uid(task)), |
414 | task->mm->total_vm, get_mm_rss(task->mm), | 414 | task->tgid, task->mm->total_vm, get_mm_rss(task->mm), |
415 | task_cpu(task), task->signal->oom_adj, | 415 | task_cpu(task), task->signal->oom_adj, |
416 | task->signal->oom_score_adj, task->comm); | 416 | task->signal->oom_score_adj, task->comm); |
417 | task_unlock(task); | 417 | task_unlock(task); |
diff --git a/mm/shmem.c b/mm/shmem.c index f99ff3e50bd6..d7b433a1ef5e 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -2075,6 +2075,8 @@ static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo, | |||
2075 | bool remount) | 2075 | bool remount) |
2076 | { | 2076 | { |
2077 | char *this_char, *value, *rest; | 2077 | char *this_char, *value, *rest; |
2078 | uid_t uid; | ||
2079 | gid_t gid; | ||
2078 | 2080 | ||
2079 | while (options != NULL) { | 2081 | while (options != NULL) { |
2080 | this_char = options; | 2082 | this_char = options; |
@@ -2134,15 +2136,21 @@ static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo, | |||
2134 | } else if (!strcmp(this_char,"uid")) { | 2136 | } else if (!strcmp(this_char,"uid")) { |
2135 | if (remount) | 2137 | if (remount) |
2136 | continue; | 2138 | continue; |
2137 | sbinfo->uid = simple_strtoul(value, &rest, 0); | 2139 | uid = simple_strtoul(value, &rest, 0); |
2138 | if (*rest) | 2140 | if (*rest) |
2139 | goto bad_val; | 2141 | goto bad_val; |
2142 | sbinfo->uid = make_kuid(current_user_ns(), uid); | ||
2143 | if (!uid_valid(sbinfo->uid)) | ||
2144 | goto bad_val; | ||
2140 | } else if (!strcmp(this_char,"gid")) { | 2145 | } else if (!strcmp(this_char,"gid")) { |
2141 | if (remount) | 2146 | if (remount) |
2142 | continue; | 2147 | continue; |
2143 | sbinfo->gid = simple_strtoul(value, &rest, 0); | 2148 | gid = simple_strtoul(value, &rest, 0); |
2144 | if (*rest) | 2149 | if (*rest) |
2145 | goto bad_val; | 2150 | goto bad_val; |
2151 | sbinfo->gid = make_kgid(current_user_ns(), gid); | ||
2152 | if (!gid_valid(sbinfo->gid)) | ||
2153 | goto bad_val; | ||
2146 | } else if (!strcmp(this_char,"mpol")) { | 2154 | } else if (!strcmp(this_char,"mpol")) { |
2147 | if (mpol_parse_str(value, &sbinfo->mpol, 1)) | 2155 | if (mpol_parse_str(value, &sbinfo->mpol, 1)) |
2148 | goto bad_val; | 2156 | goto bad_val; |
@@ -2210,10 +2218,12 @@ static int shmem_show_options(struct seq_file *seq, struct dentry *root) | |||
2210 | seq_printf(seq, ",nr_inodes=%lu", sbinfo->max_inodes); | 2218 | seq_printf(seq, ",nr_inodes=%lu", sbinfo->max_inodes); |
2211 | if (sbinfo->mode != (S_IRWXUGO | S_ISVTX)) | 2219 | if (sbinfo->mode != (S_IRWXUGO | S_ISVTX)) |
2212 | seq_printf(seq, ",mode=%03ho", sbinfo->mode); | 2220 | seq_printf(seq, ",mode=%03ho", sbinfo->mode); |
2213 | if (sbinfo->uid != 0) | 2221 | if (!uid_eq(sbinfo->uid, GLOBAL_ROOT_UID)) |
2214 | seq_printf(seq, ",uid=%u", sbinfo->uid); | 2222 | seq_printf(seq, ",uid=%u", |
2215 | if (sbinfo->gid != 0) | 2223 | from_kuid_munged(&init_user_ns, sbinfo->uid)); |
2216 | seq_printf(seq, ",gid=%u", sbinfo->gid); | 2224 | if (!gid_eq(sbinfo->gid, GLOBAL_ROOT_GID)) |
2225 | seq_printf(seq, ",gid=%u", | ||
2226 | from_kgid_munged(&init_user_ns, sbinfo->gid)); | ||
2217 | shmem_show_mpol(seq, sbinfo->mpol); | 2227 | shmem_show_mpol(seq, sbinfo->mpol); |
2218 | return 0; | 2228 | return 0; |
2219 | } | 2229 | } |
diff --git a/net/core/sock.c b/net/core/sock.c index f372d9bf4976..653f8c0aedc5 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -813,8 +813,8 @@ void cred_to_ucred(struct pid *pid, const struct cred *cred, | |||
813 | if (cred) { | 813 | if (cred) { |
814 | struct user_namespace *current_ns = current_user_ns(); | 814 | struct user_namespace *current_ns = current_user_ns(); |
815 | 815 | ||
816 | ucred->uid = user_ns_map_uid(current_ns, cred, cred->euid); | 816 | ucred->uid = from_kuid(current_ns, cred->euid); |
817 | ucred->gid = user_ns_map_gid(current_ns, cred, cred->egid); | 817 | ucred->gid = from_kgid(current_ns, cred->egid); |
818 | } | 818 | } |
819 | } | 819 | } |
820 | EXPORT_SYMBOL_GPL(cred_to_ucred); | 820 | EXPORT_SYMBOL_GPL(cred_to_ucred); |
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 6e930c7174dd..2c00e8bf684d 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
@@ -207,17 +207,22 @@ static int ping_init_sock(struct sock *sk) | |||
207 | gid_t range[2]; | 207 | gid_t range[2]; |
208 | struct group_info *group_info = get_current_groups(); | 208 | struct group_info *group_info = get_current_groups(); |
209 | int i, j, count = group_info->ngroups; | 209 | int i, j, count = group_info->ngroups; |
210 | kgid_t low, high; | ||
210 | 211 | ||
211 | inet_get_ping_group_range_net(net, range, range+1); | 212 | inet_get_ping_group_range_net(net, range, range+1); |
213 | low = make_kgid(&init_user_ns, range[0]); | ||
214 | high = make_kgid(&init_user_ns, range[1]); | ||
215 | if (!gid_valid(low) || !gid_valid(high) || gid_lt(high, low)) | ||
216 | return -EACCES; | ||
217 | |||
212 | if (range[0] <= group && group <= range[1]) | 218 | if (range[0] <= group && group <= range[1]) |
213 | return 0; | 219 | return 0; |
214 | 220 | ||
215 | for (i = 0; i < group_info->nblocks; i++) { | 221 | for (i = 0; i < group_info->nblocks; i++) { |
216 | int cp_count = min_t(int, NGROUPS_PER_BLOCK, count); | 222 | int cp_count = min_t(int, NGROUPS_PER_BLOCK, count); |
217 | |||
218 | for (j = 0; j < cp_count; j++) { | 223 | for (j = 0; j < cp_count; j++) { |
219 | group = group_info->blocks[i][j]; | 224 | kgid_t gid = group_info->blocks[i][j]; |
220 | if (range[0] <= group && group <= range[1]) | 225 | if (gid_lte(low, gid) && gid_lte(gid, high)) |
221 | return 0; | 226 | return 0; |
222 | } | 227 | } |
223 | 228 | ||
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index 75762f346975..6ed6f201b022 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c | |||
@@ -160,8 +160,8 @@ generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags) | |||
160 | if (gcred->acred.group_info->ngroups != acred->group_info->ngroups) | 160 | if (gcred->acred.group_info->ngroups != acred->group_info->ngroups) |
161 | goto out_nomatch; | 161 | goto out_nomatch; |
162 | for (i = 0; i < gcred->acred.group_info->ngroups; i++) { | 162 | for (i = 0; i < gcred->acred.group_info->ngroups; i++) { |
163 | if (GROUP_AT(gcred->acred.group_info, i) != | 163 | if (!gid_eq(GROUP_AT(gcred->acred.group_info, i), |
164 | GROUP_AT(acred->group_info, i)) | 164 | GROUP_AT(acred->group_info, i))) |
165 | goto out_nomatch; | 165 | goto out_nomatch; |
166 | } | 166 | } |
167 | out_match: | 167 | out_match: |
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 1600cfb1618c..28b62dbb6d1e 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/types.h> | 41 | #include <linux/types.h> |
42 | #include <linux/module.h> | 42 | #include <linux/module.h> |
43 | #include <linux/pagemap.h> | 43 | #include <linux/pagemap.h> |
44 | #include <linux/user_namespace.h> | ||
44 | 45 | ||
45 | #include <linux/sunrpc/auth_gss.h> | 46 | #include <linux/sunrpc/auth_gss.h> |
46 | #include <linux/sunrpc/gss_err.h> | 47 | #include <linux/sunrpc/gss_err.h> |
@@ -470,9 +471,13 @@ static int rsc_parse(struct cache_detail *cd, | |||
470 | status = -EINVAL; | 471 | status = -EINVAL; |
471 | for (i=0; i<N; i++) { | 472 | for (i=0; i<N; i++) { |
472 | gid_t gid; | 473 | gid_t gid; |
474 | kgid_t kgid; | ||
473 | if (get_int(&mesg, &gid)) | 475 | if (get_int(&mesg, &gid)) |
474 | goto out; | 476 | goto out; |
475 | GROUP_AT(rsci.cred.cr_group_info, i) = gid; | 477 | kgid = make_kgid(&init_user_ns, gid); |
478 | if (!gid_valid(kgid)) | ||
479 | goto out; | ||
480 | GROUP_AT(rsci.cred.cr_group_info, i) = kgid; | ||
476 | } | 481 | } |
477 | 482 | ||
478 | /* mech name */ | 483 | /* mech name */ |
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index e50502d8ceb7..52c5abdee211 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/sunrpc/clnt.h> | 13 | #include <linux/sunrpc/clnt.h> |
14 | #include <linux/sunrpc/auth.h> | 14 | #include <linux/sunrpc/auth.h> |
15 | #include <linux/user_namespace.h> | ||
15 | 16 | ||
16 | #define NFS_NGROUPS 16 | 17 | #define NFS_NGROUPS 16 |
17 | 18 | ||
@@ -78,8 +79,11 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
78 | groups = NFS_NGROUPS; | 79 | groups = NFS_NGROUPS; |
79 | 80 | ||
80 | cred->uc_gid = acred->gid; | 81 | cred->uc_gid = acred->gid; |
81 | for (i = 0; i < groups; i++) | 82 | for (i = 0; i < groups; i++) { |
82 | cred->uc_gids[i] = GROUP_AT(acred->group_info, i); | 83 | gid_t gid; |
84 | gid = from_kgid(&init_user_ns, GROUP_AT(acred->group_info, i)); | ||
85 | cred->uc_gids[i] = gid; | ||
86 | } | ||
83 | if (i < NFS_NGROUPS) | 87 | if (i < NFS_NGROUPS) |
84 | cred->uc_gids[i] = NOGROUP; | 88 | cred->uc_gids[i] = NOGROUP; |
85 | 89 | ||
@@ -126,9 +130,12 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags) | |||
126 | groups = acred->group_info->ngroups; | 130 | groups = acred->group_info->ngroups; |
127 | if (groups > NFS_NGROUPS) | 131 | if (groups > NFS_NGROUPS) |
128 | groups = NFS_NGROUPS; | 132 | groups = NFS_NGROUPS; |
129 | for (i = 0; i < groups ; i++) | 133 | for (i = 0; i < groups ; i++) { |
130 | if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i)) | 134 | gid_t gid; |
135 | gid = from_kgid(&init_user_ns, GROUP_AT(acred->group_info, i)); | ||
136 | if (cred->uc_gids[i] != gid) | ||
131 | return 0; | 137 | return 0; |
138 | } | ||
132 | if (groups < NFS_NGROUPS && | 139 | if (groups < NFS_NGROUPS && |
133 | cred->uc_gids[groups] != NOGROUP) | 140 | cred->uc_gids[groups] != NOGROUP) |
134 | return 0; | 141 | return 0; |
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 521d8f7dc833..71ec8530ec8c 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <net/sock.h> | 14 | #include <net/sock.h> |
15 | #include <net/ipv6.h> | 15 | #include <net/ipv6.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/user_namespace.h> | ||
17 | #define RPCDBG_FACILITY RPCDBG_AUTH | 18 | #define RPCDBG_FACILITY RPCDBG_AUTH |
18 | 19 | ||
19 | #include <linux/sunrpc/clnt.h> | 20 | #include <linux/sunrpc/clnt.h> |
@@ -530,11 +531,15 @@ static int unix_gid_parse(struct cache_detail *cd, | |||
530 | 531 | ||
531 | for (i = 0 ; i < gids ; i++) { | 532 | for (i = 0 ; i < gids ; i++) { |
532 | int gid; | 533 | int gid; |
534 | kgid_t kgid; | ||
533 | rv = get_int(&mesg, &gid); | 535 | rv = get_int(&mesg, &gid); |
534 | err = -EINVAL; | 536 | err = -EINVAL; |
535 | if (rv) | 537 | if (rv) |
536 | goto out; | 538 | goto out; |
537 | GROUP_AT(ug.gi, i) = gid; | 539 | kgid = make_kgid(&init_user_ns, gid); |
540 | if (!gid_valid(kgid)) | ||
541 | goto out; | ||
542 | GROUP_AT(ug.gi, i) = kgid; | ||
538 | } | 543 | } |
539 | 544 | ||
540 | ugp = unix_gid_lookup(cd, uid); | 545 | ugp = unix_gid_lookup(cd, uid); |
@@ -563,6 +568,7 @@ static int unix_gid_show(struct seq_file *m, | |||
563 | struct cache_detail *cd, | 568 | struct cache_detail *cd, |
564 | struct cache_head *h) | 569 | struct cache_head *h) |
565 | { | 570 | { |
571 | struct user_namespace *user_ns = current_user_ns(); | ||
566 | struct unix_gid *ug; | 572 | struct unix_gid *ug; |
567 | int i; | 573 | int i; |
568 | int glen; | 574 | int glen; |
@@ -580,7 +586,7 @@ static int unix_gid_show(struct seq_file *m, | |||
580 | 586 | ||
581 | seq_printf(m, "%u %d:", ug->uid, glen); | 587 | seq_printf(m, "%u %d:", ug->uid, glen); |
582 | for (i = 0; i < glen; i++) | 588 | for (i = 0; i < glen; i++) |
583 | seq_printf(m, " %d", GROUP_AT(ug->gi, i)); | 589 | seq_printf(m, " %d", from_kgid_munged(user_ns, GROUP_AT(ug->gi, i))); |
584 | seq_printf(m, "\n"); | 590 | seq_printf(m, "\n"); |
585 | return 0; | 591 | return 0; |
586 | } | 592 | } |
@@ -831,8 +837,12 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
831 | cred->cr_group_info = groups_alloc(slen); | 837 | cred->cr_group_info = groups_alloc(slen); |
832 | if (cred->cr_group_info == NULL) | 838 | if (cred->cr_group_info == NULL) |
833 | return SVC_CLOSE; | 839 | return SVC_CLOSE; |
834 | for (i = 0; i < slen; i++) | 840 | for (i = 0; i < slen; i++) { |
835 | GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv); | 841 | kgid_t kgid = make_kgid(&init_user_ns, svc_getnl(argv)); |
842 | if (!gid_valid(kgid)) | ||
843 | goto badcred; | ||
844 | GROUP_AT(cred->cr_group_info, i) = kgid; | ||
845 | } | ||
836 | if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { | 846 | if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { |
837 | *authp = rpc_autherr_badverf; | 847 | *authp = rpc_autherr_badverf; |
838 | return SVC_DENIED; | 848 | return SVC_DENIED; |
diff --git a/security/commoncap.c b/security/commoncap.c index f80d11609391..e771cb1b2d79 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -77,12 +77,12 @@ int cap_capable(const struct cred *cred, struct user_namespace *targ_ns, | |||
77 | int cap, int audit) | 77 | int cap, int audit) |
78 | { | 78 | { |
79 | for (;;) { | 79 | for (;;) { |
80 | /* The creator of the user namespace has all caps. */ | 80 | /* The owner of the user namespace has all caps. */ |
81 | if (targ_ns != &init_user_ns && targ_ns->creator == cred->user) | 81 | if (targ_ns != &init_user_ns && uid_eq(targ_ns->owner, cred->euid)) |
82 | return 0; | 82 | return 0; |
83 | 83 | ||
84 | /* Do we have the necessary capabilities? */ | 84 | /* Do we have the necessary capabilities? */ |
85 | if (targ_ns == cred->user->user_ns) | 85 | if (targ_ns == cred->user_ns) |
86 | return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM; | 86 | return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM; |
87 | 87 | ||
88 | /* Have we tried all of the parent namespaces? */ | 88 | /* Have we tried all of the parent namespaces? */ |
@@ -93,7 +93,7 @@ int cap_capable(const struct cred *cred, struct user_namespace *targ_ns, | |||
93 | *If you have a capability in a parent user ns, then you have | 93 | *If you have a capability in a parent user ns, then you have |
94 | * it over all children user namespaces as well. | 94 | * it over all children user namespaces as well. |
95 | */ | 95 | */ |
96 | targ_ns = targ_ns->creator->user_ns; | 96 | targ_ns = targ_ns->parent; |
97 | } | 97 | } |
98 | 98 | ||
99 | /* We never get here */ | 99 | /* We never get here */ |
@@ -137,10 +137,10 @@ int cap_ptrace_access_check(struct task_struct *child, unsigned int mode) | |||
137 | rcu_read_lock(); | 137 | rcu_read_lock(); |
138 | cred = current_cred(); | 138 | cred = current_cred(); |
139 | child_cred = __task_cred(child); | 139 | child_cred = __task_cred(child); |
140 | if (cred->user->user_ns == child_cred->user->user_ns && | 140 | if (cred->user_ns == child_cred->user_ns && |
141 | cap_issubset(child_cred->cap_permitted, cred->cap_permitted)) | 141 | cap_issubset(child_cred->cap_permitted, cred->cap_permitted)) |
142 | goto out; | 142 | goto out; |
143 | if (ns_capable(child_cred->user->user_ns, CAP_SYS_PTRACE)) | 143 | if (ns_capable(child_cred->user_ns, CAP_SYS_PTRACE)) |
144 | goto out; | 144 | goto out; |
145 | ret = -EPERM; | 145 | ret = -EPERM; |
146 | out: | 146 | out: |
@@ -169,10 +169,10 @@ int cap_ptrace_traceme(struct task_struct *parent) | |||
169 | rcu_read_lock(); | 169 | rcu_read_lock(); |
170 | cred = __task_cred(parent); | 170 | cred = __task_cred(parent); |
171 | child_cred = current_cred(); | 171 | child_cred = current_cred(); |
172 | if (cred->user->user_ns == child_cred->user->user_ns && | 172 | if (cred->user_ns == child_cred->user_ns && |
173 | cap_issubset(child_cred->cap_permitted, cred->cap_permitted)) | 173 | cap_issubset(child_cred->cap_permitted, cred->cap_permitted)) |
174 | goto out; | 174 | goto out; |
175 | if (has_ns_capability(parent, child_cred->user->user_ns, CAP_SYS_PTRACE)) | 175 | if (has_ns_capability(parent, child_cred->user_ns, CAP_SYS_PTRACE)) |
176 | goto out; | 176 | goto out; |
177 | ret = -EPERM; | 177 | ret = -EPERM; |
178 | out: | 178 | out: |
@@ -215,7 +215,7 @@ static inline int cap_inh_is_capped(void) | |||
215 | /* they are so limited unless the current task has the CAP_SETPCAP | 215 | /* they are so limited unless the current task has the CAP_SETPCAP |
216 | * capability | 216 | * capability |
217 | */ | 217 | */ |
218 | if (cap_capable(current_cred(), current_cred()->user->user_ns, | 218 | if (cap_capable(current_cred(), current_cred()->user_ns, |
219 | CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0) | 219 | CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0) |
220 | return 0; | 220 | return 0; |
221 | return 1; | 221 | return 1; |
@@ -473,19 +473,22 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) | |||
473 | struct cred *new = bprm->cred; | 473 | struct cred *new = bprm->cred; |
474 | bool effective, has_cap = false; | 474 | bool effective, has_cap = false; |
475 | int ret; | 475 | int ret; |
476 | kuid_t root_uid; | ||
476 | 477 | ||
477 | effective = false; | 478 | effective = false; |
478 | ret = get_file_caps(bprm, &effective, &has_cap); | 479 | ret = get_file_caps(bprm, &effective, &has_cap); |
479 | if (ret < 0) | 480 | if (ret < 0) |
480 | return ret; | 481 | return ret; |
481 | 482 | ||
483 | root_uid = make_kuid(new->user_ns, 0); | ||
484 | |||
482 | if (!issecure(SECURE_NOROOT)) { | 485 | if (!issecure(SECURE_NOROOT)) { |
483 | /* | 486 | /* |
484 | * If the legacy file capability is set, then don't set privs | 487 | * If the legacy file capability is set, then don't set privs |
485 | * for a setuid root binary run by a non-root user. Do set it | 488 | * for a setuid root binary run by a non-root user. Do set it |
486 | * for a root user just to cause least surprise to an admin. | 489 | * for a root user just to cause least surprise to an admin. |
487 | */ | 490 | */ |
488 | if (has_cap && new->uid != 0 && new->euid == 0) { | 491 | if (has_cap && !uid_eq(new->uid, root_uid) && uid_eq(new->euid, root_uid)) { |
489 | warn_setuid_and_fcaps_mixed(bprm->filename); | 492 | warn_setuid_and_fcaps_mixed(bprm->filename); |
490 | goto skip; | 493 | goto skip; |
491 | } | 494 | } |
@@ -496,12 +499,12 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) | |||
496 | * | 499 | * |
497 | * If only the real uid is 0, we do not set the effective bit. | 500 | * If only the real uid is 0, we do not set the effective bit. |
498 | */ | 501 | */ |
499 | if (new->euid == 0 || new->uid == 0) { | 502 | if (uid_eq(new->euid, root_uid) || uid_eq(new->uid, root_uid)) { |
500 | /* pP' = (cap_bset & ~0) | (pI & ~0) */ | 503 | /* pP' = (cap_bset & ~0) | (pI & ~0) */ |
501 | new->cap_permitted = cap_combine(old->cap_bset, | 504 | new->cap_permitted = cap_combine(old->cap_bset, |
502 | old->cap_inheritable); | 505 | old->cap_inheritable); |
503 | } | 506 | } |
504 | if (new->euid == 0) | 507 | if (uid_eq(new->euid, root_uid)) |
505 | effective = true; | 508 | effective = true; |
506 | } | 509 | } |
507 | skip: | 510 | skip: |
@@ -516,8 +519,8 @@ skip: | |||
516 | * | 519 | * |
517 | * In addition, if NO_NEW_PRIVS, then ensure we get no new privs. | 520 | * In addition, if NO_NEW_PRIVS, then ensure we get no new privs. |
518 | */ | 521 | */ |
519 | if ((new->euid != old->uid || | 522 | if ((!uid_eq(new->euid, old->uid) || |
520 | new->egid != old->gid || | 523 | !gid_eq(new->egid, old->gid) || |
521 | !cap_issubset(new->cap_permitted, old->cap_permitted)) && | 524 | !cap_issubset(new->cap_permitted, old->cap_permitted)) && |
522 | bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) { | 525 | bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) { |
523 | /* downgrade; they get no more than they had, and maybe less */ | 526 | /* downgrade; they get no more than they had, and maybe less */ |
@@ -553,7 +556,7 @@ skip: | |||
553 | */ | 556 | */ |
554 | if (!cap_isclear(new->cap_effective)) { | 557 | if (!cap_isclear(new->cap_effective)) { |
555 | if (!cap_issubset(CAP_FULL_SET, new->cap_effective) || | 558 | if (!cap_issubset(CAP_FULL_SET, new->cap_effective) || |
556 | new->euid != 0 || new->uid != 0 || | 559 | !uid_eq(new->euid, root_uid) || !uid_eq(new->uid, root_uid) || |
557 | issecure(SECURE_NOROOT)) { | 560 | issecure(SECURE_NOROOT)) { |
558 | ret = audit_log_bprm_fcaps(bprm, new, old); | 561 | ret = audit_log_bprm_fcaps(bprm, new, old); |
559 | if (ret < 0) | 562 | if (ret < 0) |
@@ -578,16 +581,17 @@ skip: | |||
578 | int cap_bprm_secureexec(struct linux_binprm *bprm) | 581 | int cap_bprm_secureexec(struct linux_binprm *bprm) |
579 | { | 582 | { |
580 | const struct cred *cred = current_cred(); | 583 | const struct cred *cred = current_cred(); |
584 | kuid_t root_uid = make_kuid(cred->user_ns, 0); | ||
581 | 585 | ||
582 | if (cred->uid != 0) { | 586 | if (!uid_eq(cred->uid, root_uid)) { |
583 | if (bprm->cap_effective) | 587 | if (bprm->cap_effective) |
584 | return 1; | 588 | return 1; |
585 | if (!cap_isclear(cred->cap_permitted)) | 589 | if (!cap_isclear(cred->cap_permitted)) |
586 | return 1; | 590 | return 1; |
587 | } | 591 | } |
588 | 592 | ||
589 | return (cred->euid != cred->uid || | 593 | return (!uid_eq(cred->euid, cred->uid) || |
590 | cred->egid != cred->gid); | 594 | !gid_eq(cred->egid, cred->gid)); |
591 | } | 595 | } |
592 | 596 | ||
593 | /** | 597 | /** |
@@ -677,15 +681,21 @@ int cap_inode_removexattr(struct dentry *dentry, const char *name) | |||
677 | */ | 681 | */ |
678 | static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old) | 682 | static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old) |
679 | { | 683 | { |
680 | if ((old->uid == 0 || old->euid == 0 || old->suid == 0) && | 684 | kuid_t root_uid = make_kuid(old->user_ns, 0); |
681 | (new->uid != 0 && new->euid != 0 && new->suid != 0) && | 685 | |
686 | if ((uid_eq(old->uid, root_uid) || | ||
687 | uid_eq(old->euid, root_uid) || | ||
688 | uid_eq(old->suid, root_uid)) && | ||
689 | (!uid_eq(new->uid, root_uid) && | ||
690 | !uid_eq(new->euid, root_uid) && | ||
691 | !uid_eq(new->suid, root_uid)) && | ||
682 | !issecure(SECURE_KEEP_CAPS)) { | 692 | !issecure(SECURE_KEEP_CAPS)) { |
683 | cap_clear(new->cap_permitted); | 693 | cap_clear(new->cap_permitted); |
684 | cap_clear(new->cap_effective); | 694 | cap_clear(new->cap_effective); |
685 | } | 695 | } |
686 | if (old->euid == 0 && new->euid != 0) | 696 | if (uid_eq(old->euid, root_uid) && !uid_eq(new->euid, root_uid)) |
687 | cap_clear(new->cap_effective); | 697 | cap_clear(new->cap_effective); |
688 | if (old->euid != 0 && new->euid == 0) | 698 | if (!uid_eq(old->euid, root_uid) && uid_eq(new->euid, root_uid)) |
689 | new->cap_effective = new->cap_permitted; | 699 | new->cap_effective = new->cap_permitted; |
690 | } | 700 | } |
691 | 701 | ||
@@ -718,11 +728,12 @@ int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags) | |||
718 | * if not, we might be a bit too harsh here. | 728 | * if not, we might be a bit too harsh here. |
719 | */ | 729 | */ |
720 | if (!issecure(SECURE_NO_SETUID_FIXUP)) { | 730 | if (!issecure(SECURE_NO_SETUID_FIXUP)) { |
721 | if (old->fsuid == 0 && new->fsuid != 0) | 731 | kuid_t root_uid = make_kuid(old->user_ns, 0); |
732 | if (uid_eq(old->fsuid, root_uid) && !uid_eq(new->fsuid, root_uid)) | ||
722 | new->cap_effective = | 733 | new->cap_effective = |
723 | cap_drop_fs_set(new->cap_effective); | 734 | cap_drop_fs_set(new->cap_effective); |
724 | 735 | ||
725 | if (old->fsuid != 0 && new->fsuid == 0) | 736 | if (!uid_eq(old->fsuid, root_uid) && uid_eq(new->fsuid, root_uid)) |
726 | new->cap_effective = | 737 | new->cap_effective = |
727 | cap_raise_fs_set(new->cap_effective, | 738 | cap_raise_fs_set(new->cap_effective, |
728 | new->cap_permitted); | 739 | new->cap_permitted); |
@@ -875,7 +886,7 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
875 | || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ | 886 | || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ |
876 | || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ | 887 | || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ |
877 | || (cap_capable(current_cred(), | 888 | || (cap_capable(current_cred(), |
878 | current_cred()->user->user_ns, CAP_SETPCAP, | 889 | current_cred()->user_ns, CAP_SETPCAP, |
879 | SECURITY_CAP_AUDIT) != 0) /*[4]*/ | 890 | SECURITY_CAP_AUDIT) != 0) /*[4]*/ |
880 | /* | 891 | /* |
881 | * [1] no changing of bits that are locked | 892 | * [1] no changing of bits that are locked |
diff --git a/security/keys/key.c b/security/keys/key.c index c9bf66ac36e0..50d96d4e06f2 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -253,7 +253,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
253 | quotalen = desclen + type->def_datalen; | 253 | quotalen = desclen + type->def_datalen; |
254 | 254 | ||
255 | /* get hold of the key tracking for this user */ | 255 | /* get hold of the key tracking for this user */ |
256 | user = key_user_lookup(uid, cred->user->user_ns); | 256 | user = key_user_lookup(uid, cred->user_ns); |
257 | if (!user) | 257 | if (!user) |
258 | goto no_memory_1; | 258 | goto no_memory_1; |
259 | 259 | ||
diff --git a/security/keys/permission.c b/security/keys/permission.c index 57d96363d7f1..0b4d019e027d 100644 --- a/security/keys/permission.c +++ b/security/keys/permission.c | |||
@@ -36,7 +36,7 @@ int key_task_permission(const key_ref_t key_ref, const struct cred *cred, | |||
36 | 36 | ||
37 | key = key_ref_to_ptr(key_ref); | 37 | key = key_ref_to_ptr(key_ref); |
38 | 38 | ||
39 | if (key->user->user_ns != cred->user->user_ns) | 39 | if (key->user->user_ns != cred->user_ns) |
40 | goto use_other_perms; | 40 | goto use_other_perms; |
41 | 41 | ||
42 | /* use the second 8-bits of permissions for keys the caller owns */ | 42 | /* use the second 8-bits of permissions for keys the caller owns */ |
@@ -53,7 +53,8 @@ int key_task_permission(const key_ref_t key_ref, const struct cred *cred, | |||
53 | goto use_these_perms; | 53 | goto use_these_perms; |
54 | } | 54 | } |
55 | 55 | ||
56 | ret = groups_search(cred->group_info, key->gid); | 56 | ret = groups_search(cred->group_info, |
57 | make_kgid(current_user_ns(), key->gid)); | ||
57 | if (ret) { | 58 | if (ret) { |
58 | kperm = key->perm >> 8; | 59 | kperm = key->perm >> 8; |
59 | goto use_these_perms; | 60 | goto use_these_perms; |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index e137fcd7042c..d71056db7b67 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -860,7 +860,7 @@ void key_replace_session_keyring(void) | |||
860 | new-> sgid = old-> sgid; | 860 | new-> sgid = old-> sgid; |
861 | new->fsgid = old->fsgid; | 861 | new->fsgid = old->fsgid; |
862 | new->user = get_uid(old->user); | 862 | new->user = get_uid(old->user); |
863 | new->user_ns = new->user->user_ns; | 863 | new->user_ns = get_user_ns(new->user_ns); |
864 | new->group_info = get_group_info(old->group_info); | 864 | new->group_info = get_group_info(old->group_info); |
865 | 865 | ||
866 | new->securebits = old->securebits; | 866 | new->securebits = old->securebits; |