1
0
Fork 0

nfsd: knfsd must use the container user namespace

Convert knfsd to use the user namespace of the container that started
the server processes.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
hifive-unleashed-5.2
Trond Myklebust 2019-04-09 12:13:42 -04:00 committed by J. Bruce Fields
parent e6667c73a2
commit e45d1a1835
6 changed files with 44 additions and 32 deletions

View File

@ -570,13 +570,13 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
err = get_int(&mesg, &an_int); err = get_int(&mesg, &an_int);
if (err) if (err)
goto out3; goto out3;
exp.ex_anon_uid= make_kuid(&init_user_ns, an_int); exp.ex_anon_uid= make_kuid(current_user_ns(), an_int);
/* anon gid */ /* anon gid */
err = get_int(&mesg, &an_int); err = get_int(&mesg, &an_int);
if (err) if (err)
goto out3; goto out3;
exp.ex_anon_gid= make_kgid(&init_user_ns, an_int); exp.ex_anon_gid= make_kgid(current_user_ns(), an_int);
/* fsid */ /* fsid */
err = get_int(&mesg, &an_int); err = get_int(&mesg, &an_int);
@ -1170,15 +1170,17 @@ static void show_secinfo(struct seq_file *m, struct svc_export *exp)
static void exp_flags(struct seq_file *m, int flag, int fsid, static void exp_flags(struct seq_file *m, int flag, int fsid,
kuid_t anonu, kgid_t anong, struct nfsd4_fs_locations *fsloc) kuid_t anonu, kgid_t anong, struct nfsd4_fs_locations *fsloc)
{ {
struct user_namespace *userns = m->file->f_cred->user_ns;
show_expflags(m, flag, NFSEXP_ALLFLAGS); show_expflags(m, flag, NFSEXP_ALLFLAGS);
if (flag & NFSEXP_FSID) if (flag & NFSEXP_FSID)
seq_printf(m, ",fsid=%d", fsid); seq_printf(m, ",fsid=%d", fsid);
if (!uid_eq(anonu, make_kuid(&init_user_ns, (uid_t)-2)) && if (!uid_eq(anonu, make_kuid(userns, (uid_t)-2)) &&
!uid_eq(anonu, make_kuid(&init_user_ns, 0x10000-2))) !uid_eq(anonu, make_kuid(userns, 0x10000-2)))
seq_printf(m, ",anonuid=%u", from_kuid(&init_user_ns, anonu)); seq_printf(m, ",anonuid=%u", from_kuid_munged(userns, anonu));
if (!gid_eq(anong, make_kgid(&init_user_ns, (gid_t)-2)) && if (!gid_eq(anong, make_kgid(userns, (gid_t)-2)) &&
!gid_eq(anong, make_kgid(&init_user_ns, 0x10000-2))) !gid_eq(anong, make_kgid(userns, 0x10000-2)))
seq_printf(m, ",anongid=%u", from_kgid(&init_user_ns, anong)); seq_printf(m, ",anongid=%u", from_kgid_munged(userns, anong));
if (fsloc && fsloc->locations_count > 0) { if (fsloc && fsloc->locations_count > 0) {
char *loctype = (fsloc->migrated) ? "refer" : "replicas"; char *loctype = (fsloc->migrated) ? "refer" : "replicas";
int i; int i;

View File

@ -96,7 +96,7 @@ decode_filename(__be32 *p, char **namp, unsigned int *lenp)
} }
static __be32 * static __be32 *
decode_sattr3(__be32 *p, struct iattr *iap) decode_sattr3(__be32 *p, struct iattr *iap, struct user_namespace *userns)
{ {
u32 tmp; u32 tmp;
@ -107,12 +107,12 @@ decode_sattr3(__be32 *p, struct iattr *iap)
iap->ia_mode = ntohl(*p++); iap->ia_mode = ntohl(*p++);
} }
if (*p++) { if (*p++) {
iap->ia_uid = make_kuid(&init_user_ns, ntohl(*p++)); iap->ia_uid = make_kuid(userns, ntohl(*p++));
if (uid_valid(iap->ia_uid)) if (uid_valid(iap->ia_uid))
iap->ia_valid |= ATTR_UID; iap->ia_valid |= ATTR_UID;
} }
if (*p++) { if (*p++) {
iap->ia_gid = make_kgid(&init_user_ns, ntohl(*p++)); iap->ia_gid = make_kgid(userns, ntohl(*p++));
if (gid_valid(iap->ia_gid)) if (gid_valid(iap->ia_gid))
iap->ia_valid |= ATTR_GID; iap->ia_valid |= ATTR_GID;
} }
@ -165,12 +165,13 @@ static __be32 *
encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
struct kstat *stat) struct kstat *stat)
{ {
struct user_namespace *userns = nfsd_user_namespace(rqstp);
struct timespec ts; struct timespec ts;
*p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]); *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
*p++ = htonl((u32) (stat->mode & S_IALLUGO)); *p++ = htonl((u32) (stat->mode & S_IALLUGO));
*p++ = htonl((u32) stat->nlink); *p++ = htonl((u32) stat->nlink);
*p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); *p++ = htonl((u32) from_kuid_munged(userns, stat->uid));
*p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); *p++ = htonl((u32) from_kgid_munged(userns, stat->gid));
if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) { if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) {
p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN); p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
} else { } else {
@ -325,7 +326,7 @@ nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p)
p = decode_fh(p, &args->fh); p = decode_fh(p, &args->fh);
if (!p) if (!p)
return 0; return 0;
p = decode_sattr3(p, &args->attrs); p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));
if ((args->check_guard = ntohl(*p++)) != 0) { if ((args->check_guard = ntohl(*p++)) != 0) {
struct timespec time; struct timespec time;
@ -455,7 +456,7 @@ nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p)
switch (args->createmode = ntohl(*p++)) { switch (args->createmode = ntohl(*p++)) {
case NFS3_CREATE_UNCHECKED: case NFS3_CREATE_UNCHECKED:
case NFS3_CREATE_GUARDED: case NFS3_CREATE_GUARDED:
p = decode_sattr3(p, &args->attrs); p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));
break; break;
case NFS3_CREATE_EXCLUSIVE: case NFS3_CREATE_EXCLUSIVE:
args->verf = p; args->verf = p;
@ -476,7 +477,7 @@ nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p)
if (!(p = decode_fh(p, &args->fh)) || if (!(p = decode_fh(p, &args->fh)) ||
!(p = decode_filename(p, &args->name, &args->len))) !(p = decode_filename(p, &args->name, &args->len)))
return 0; return 0;
p = decode_sattr3(p, &args->attrs); p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));
return xdr_argsize_check(rqstp, p); return xdr_argsize_check(rqstp, p);
} }
@ -491,7 +492,7 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p)
if (!(p = decode_fh(p, &args->ffh)) || if (!(p = decode_fh(p, &args->ffh)) ||
!(p = decode_filename(p, &args->fname, &args->flen))) !(p = decode_filename(p, &args->fname, &args->flen)))
return 0; return 0;
p = decode_sattr3(p, &args->attrs); p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));
args->tlen = ntohl(*p++); args->tlen = ntohl(*p++);
@ -519,7 +520,7 @@ nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p)
if (args->ftype == NF3BLK || args->ftype == NF3CHR if (args->ftype == NF3BLK || args->ftype == NF3CHR
|| args->ftype == NF3SOCK || args->ftype == NF3FIFO) || args->ftype == NF3SOCK || args->ftype == NF3FIFO)
p = decode_sattr3(p, &args->attrs); p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));
if (args->ftype == NF3BLK || args->ftype == NF3CHR) { if (args->ftype == NF3BLK || args->ftype == NF3CHR) {
args->major = ntohl(*p++); args->major = ntohl(*p++);

View File

@ -634,7 +634,7 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
return nfserr_inval; return nfserr_inval;
status = do_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, &id); status = do_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, &id);
*uid = make_kuid(&init_user_ns, id); *uid = make_kuid(nfsd_user_namespace(rqstp), id);
if (!uid_valid(*uid)) if (!uid_valid(*uid))
status = nfserr_badowner; status = nfserr_badowner;
return status; return status;
@ -651,7 +651,7 @@ nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
return nfserr_inval; return nfserr_inval;
status = do_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, &id); status = do_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, &id);
*gid = make_kgid(&init_user_ns, id); *gid = make_kgid(nfsd_user_namespace(rqstp), id);
if (!gid_valid(*gid)) if (!gid_valid(*gid))
status = nfserr_badowner; status = nfserr_badowner;
return status; return status;
@ -660,13 +660,13 @@ nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
__be32 nfsd4_encode_user(struct xdr_stream *xdr, struct svc_rqst *rqstp, __be32 nfsd4_encode_user(struct xdr_stream *xdr, struct svc_rqst *rqstp,
kuid_t uid) kuid_t uid)
{ {
u32 id = from_kuid(&init_user_ns, uid); u32 id = from_kuid_munged(nfsd_user_namespace(rqstp), uid);
return encode_name_from_id(xdr, rqstp, IDMAP_TYPE_USER, id); return encode_name_from_id(xdr, rqstp, IDMAP_TYPE_USER, id);
} }
__be32 nfsd4_encode_group(struct xdr_stream *xdr, struct svc_rqst *rqstp, __be32 nfsd4_encode_group(struct xdr_stream *xdr, struct svc_rqst *rqstp,
kgid_t gid) kgid_t gid)
{ {
u32 id = from_kgid(&init_user_ns, gid); u32 id = from_kgid_munged(nfsd_user_namespace(rqstp), gid);
return encode_name_from_id(xdr, rqstp, IDMAP_TYPE_GROUP, id); return encode_name_from_id(xdr, rqstp, IDMAP_TYPE_GROUP, id);
} }

View File

@ -521,6 +521,7 @@ nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access
static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs) static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs)
{ {
DECODE_HEAD; DECODE_HEAD;
struct user_namespace *userns = nfsd_user_namespace(argp->rqstp);
u32 dummy, uid, gid; u32 dummy, uid, gid;
char *machine_name; char *machine_name;
int i; int i;
@ -563,8 +564,8 @@ static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_
dummy = be32_to_cpup(p++); dummy = be32_to_cpup(p++);
READ_BUF(dummy * 4); READ_BUF(dummy * 4);
if (cbs->flavor == (u32)(-1)) { if (cbs->flavor == (u32)(-1)) {
kuid_t kuid = make_kuid(&init_user_ns, uid); kuid_t kuid = make_kuid(userns, uid);
kgid_t kgid = make_kgid(&init_user_ns, gid); kgid_t kgid = make_kgid(userns, gid);
if (uid_valid(kuid) && gid_valid(kgid)) { if (uid_valid(kuid) && gid_valid(kgid)) {
cbs->uid = kuid; cbs->uid = kuid;
cbs->gid = kgid; cbs->gid = kgid;

View File

@ -17,6 +17,7 @@
#include <linux/nfs3.h> #include <linux/nfs3.h>
#include <linux/nfs4.h> #include <linux/nfs4.h>
#include <linux/sunrpc/svc.h> #include <linux/sunrpc/svc.h>
#include <linux/sunrpc/svc_xprt.h>
#include <linux/sunrpc/msg_prot.h> #include <linux/sunrpc/msg_prot.h>
#include <uapi/linux/nfsd/debug.h> #include <uapi/linux/nfsd/debug.h>
@ -112,6 +113,12 @@ static inline int nfsd_v4client(struct svc_rqst *rq)
{ {
return rq->rq_prog == NFS_PROGRAM && rq->rq_vers == 4; return rq->rq_prog == NFS_PROGRAM && rq->rq_vers == 4;
} }
static inline struct user_namespace *
nfsd_user_namespace(const struct svc_rqst *rqstp)
{
const struct cred *cred = rqstp->rq_xprt->xpt_cred;
return cred ? cred->user_ns : &init_user_ns;
}
/* /*
* NFSv4 State * NFSv4 State

View File

@ -71,7 +71,7 @@ decode_filename(__be32 *p, char **namp, unsigned int *lenp)
} }
static __be32 * static __be32 *
decode_sattr(__be32 *p, struct iattr *iap) decode_sattr(__be32 *p, struct iattr *iap, struct user_namespace *userns)
{ {
u32 tmp, tmp1; u32 tmp, tmp1;
@ -86,12 +86,12 @@ decode_sattr(__be32 *p, struct iattr *iap)
iap->ia_mode = tmp; iap->ia_mode = tmp;
} }
if ((tmp = ntohl(*p++)) != (u32)-1) { if ((tmp = ntohl(*p++)) != (u32)-1) {
iap->ia_uid = make_kuid(&init_user_ns, tmp); iap->ia_uid = make_kuid(userns, tmp);
if (uid_valid(iap->ia_uid)) if (uid_valid(iap->ia_uid))
iap->ia_valid |= ATTR_UID; iap->ia_valid |= ATTR_UID;
} }
if ((tmp = ntohl(*p++)) != (u32)-1) { if ((tmp = ntohl(*p++)) != (u32)-1) {
iap->ia_gid = make_kgid(&init_user_ns, tmp); iap->ia_gid = make_kgid(userns, tmp);
if (gid_valid(iap->ia_gid)) if (gid_valid(iap->ia_gid))
iap->ia_valid |= ATTR_GID; iap->ia_valid |= ATTR_GID;
} }
@ -129,6 +129,7 @@ static __be32 *
encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
struct kstat *stat) struct kstat *stat)
{ {
struct user_namespace *userns = nfsd_user_namespace(rqstp);
struct dentry *dentry = fhp->fh_dentry; struct dentry *dentry = fhp->fh_dentry;
int type; int type;
struct timespec64 time; struct timespec64 time;
@ -139,8 +140,8 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
*p++ = htonl(nfs_ftypes[type >> 12]); *p++ = htonl(nfs_ftypes[type >> 12]);
*p++ = htonl((u32) stat->mode); *p++ = htonl((u32) stat->mode);
*p++ = htonl((u32) stat->nlink); *p++ = htonl((u32) stat->nlink);
*p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); *p++ = htonl((u32) from_kuid_munged(userns, stat->uid));
*p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); *p++ = htonl((u32) from_kgid_munged(userns, stat->gid));
if (S_ISLNK(type) && stat->size > NFS_MAXPATHLEN) { if (S_ISLNK(type) && stat->size > NFS_MAXPATHLEN) {
*p++ = htonl(NFS_MAXPATHLEN); *p++ = htonl(NFS_MAXPATHLEN);
@ -216,7 +217,7 @@ nfssvc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p)
p = decode_fh(p, &args->fh); p = decode_fh(p, &args->fh);
if (!p) if (!p)
return 0; return 0;
p = decode_sattr(p, &args->attrs); p = decode_sattr(p, &args->attrs, nfsd_user_namespace(rqstp));
return xdr_argsize_check(rqstp, p); return xdr_argsize_check(rqstp, p);
} }
@ -319,7 +320,7 @@ nfssvc_decode_createargs(struct svc_rqst *rqstp, __be32 *p)
if ( !(p = decode_fh(p, &args->fh)) if ( !(p = decode_fh(p, &args->fh))
|| !(p = decode_filename(p, &args->name, &args->len))) || !(p = decode_filename(p, &args->name, &args->len)))
return 0; return 0;
p = decode_sattr(p, &args->attrs); p = decode_sattr(p, &args->attrs, nfsd_user_namespace(rqstp));
return xdr_argsize_check(rqstp, p); return xdr_argsize_check(rqstp, p);
} }
@ -398,7 +399,7 @@ nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p)
return 0; return 0;
p += xdrlen; p += xdrlen;
} }
decode_sattr(p, &args->attrs); decode_sattr(p, &args->attrs, nfsd_user_namespace(rqstp));
return 1; return 1;
} }