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

coda: Restrict coda messages to the initial user namespace

Remove the slight chance that uids and gids in coda messages will be
interpreted in the wrong user namespace.

- Only allow processes in the initial user namespace to open the coda
character device to communicate with coda filesystems.
- Explicitly convert the uids in the coda header into the initial user
namespace.
- In coda_vattr_to_attr make kuids and kgids from the initial user
namespace uids and gids in struct coda_vattr that just came from
userspace.
- In coda_iattr_to_vattr convert kuids and kgids into uids and gids
in the intial user namespace and store them in struct coda_vattr for
sending to coda userspace programs.

Nothing needs to be changed with mounts as coda does not support
being mounted in anything other than the initial user namespace.

Cc: Jan Harkes <jaharkes@cs.cmu.edu>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

+11 -8
+4 -4
fs/coda/coda_linux.c
··· 100 100 if (attr->va_mode != (u_short) -1) 101 101 inode->i_mode = attr->va_mode | inode_type; 102 102 if (attr->va_uid != -1) 103 - inode->i_uid = (uid_t) attr->va_uid; 103 + inode->i_uid = make_kuid(&init_user_ns, (uid_t) attr->va_uid); 104 104 if (attr->va_gid != -1) 105 - inode->i_gid = (gid_t) attr->va_gid; 105 + inode->i_gid = make_kgid(&init_user_ns, (gid_t) attr->va_gid); 106 106 if (attr->va_nlink != -1) 107 107 set_nlink(inode, attr->va_nlink); 108 108 if (attr->va_size != -1) ··· 171 171 vattr->va_mode = iattr->ia_mode; 172 172 } 173 173 if ( valid & ATTR_UID ) { 174 - vattr->va_uid = (vuid_t) iattr->ia_uid; 174 + vattr->va_uid = (vuid_t) from_kuid(&init_user_ns, iattr->ia_uid); 175 175 } 176 176 if ( valid & ATTR_GID ) { 177 - vattr->va_gid = (vgid_t) iattr->ia_gid; 177 + vattr->va_gid = (vgid_t) from_kgid(&init_user_ns, iattr->ia_gid); 178 178 } 179 179 if ( valid & ATTR_SIZE ) { 180 180 vattr->va_size = iattr->ia_size;
+3
fs/coda/psdev.c
··· 270 270 if (task_active_pid_ns(current) != &init_pid_ns) 271 271 return -EINVAL; 272 272 273 + if (current_user_ns() != &init_user_ns) 274 + return -EINVAL; 275 + 273 276 idx = iminor(inode); 274 277 if (idx < 0 || idx >= MAX_CODADEVS) 275 278 return -ENODEV;
+3 -3
fs/coda/upcall.c
··· 52 52 inp->ih.opcode = opcode; 53 53 inp->ih.pid = task_pid_nr_ns(current, &init_pid_ns); 54 54 inp->ih.pgid = task_pgrp_nr_ns(current, &init_pid_ns); 55 - inp->ih.uid = current_fsuid(); 55 + inp->ih.uid = from_kuid(&init_user_ns, current_fsuid()); 56 56 57 57 return (void*)inp; 58 58 } ··· 157 157 } 158 158 159 159 int venus_close(struct super_block *sb, struct CodaFid *fid, int flags, 160 - vuid_t uid) 160 + kuid_t uid) 161 161 { 162 162 union inputArgs *inp; 163 163 union outputArgs *outp; ··· 166 166 insize = SIZE(release); 167 167 UPARG(CODA_CLOSE); 168 168 169 - inp->ih.uid = uid; 169 + inp->ih.uid = from_kuid(&init_user_ns, uid); 170 170 inp->coda_close.VFid = *fid; 171 171 inp->coda_close.flags = flags; 172 172
+1 -1
include/linux/coda_psdev.h
··· 34 34 const char *name, int length, int *type, 35 35 struct CodaFid *resfid); 36 36 int venus_close(struct super_block *sb, struct CodaFid *fid, int flags, 37 - vuid_t uid); 37 + kuid_t uid); 38 38 int venus_open(struct super_block *sb, struct CodaFid *fid, int flags, 39 39 struct file **f); 40 40 int venus_mkdir(struct super_block *sb, struct CodaFid *dirfid,