Skip to content
Permalink
Browse files

nfsd: add export option root_uid

We're exporting ZFS datasets with uidmap/gidmap set. When these exports
are mounted and passed on to containers with the respective user
namespace mapping, the container's root user is not recognized and is
treated as a common unprivileged user. So he cannot access and
manipulate files which he does not have explicit permission on.

This patch introduces a new export option root_uid. It can be used to
specify which user should be recognized as root, in addition to the
global root.

Mapping of user/group IDs could also be done on the client side, based
on which user namespace the mount belongs to. AFAIK, that wouldn't
help us because we're mounting the shares on the host and then just
bind mount them to containers. In addition, NFS mounts from user
namespace AFAIK don't work as of yet.
See https://patchwork.kernel.org/patch/10534963/
  • Loading branch information...
aither64 committed Mar 16, 2019
1 parent 1f6f316 commit ab987ee27f0a57f0dae3f0847db2ce4da3fc183c
Showing with 20 additions and 1 deletion.
  1. +7 −1 fs/nfsd/auth.c
  2. +11 −0 fs/nfsd/export.c
  3. +1 −0 fs/nfsd/export.h
  4. +1 −0 include/uapi/linux/nfsd/export.h
@@ -76,7 +76,13 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
set_groups(new, gi);
put_group_info(gi);

if (!uid_eq(new->fsuid, GLOBAL_ROOT_UID))
#if 0
printk("nfsd: auth: fsuid=%u, root_uid=%u\n",
__kuid_val(new->fsuid), __kuid_val(exp->ex_root_uid));
#endif

if (!uid_eq(new->fsuid, GLOBAL_ROOT_UID)
&& !uid_eq(new->fsuid, exp->ex_root_uid))
new->cap_effective = cap_drop_nfsd_set(new->cap_effective);
else
new->cap_effective = cap_raise_nfsd_set(new->cap_effective,
@@ -517,6 +517,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
struct auth_domain *dom = NULL;
struct svc_export exp = {}, *expp;
int an_int;
unsigned int an_uint;

if (mesg[mlen-1] != '\n')
return -EINVAL;
@@ -584,6 +585,15 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
goto out3;
exp.ex_fsid = an_int;

/* root_uid */
err = get_uint(&mesg, &an_uint);
if (err)
goto out3;
exp.ex_root_uid = KUIDT_INIT(an_uint);
#if 0
printk("nfsd: got root_uid=%u\n", an_uint);
#endif

while ((len = qword_get(&mesg, buf, PAGE_SIZE)) > 0) {
if (strcmp(buf, "fsloc") == 0)
err = fsloc_parse(&mesg, buf, &exp.ex_fslocs);
@@ -723,6 +733,7 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem)
new->ex_anon_uid = item->ex_anon_uid;
new->ex_anon_gid = item->ex_anon_gid;
new->ex_fsid = item->ex_fsid;
new->ex_root_uid = item->ex_root_uid;
new->ex_devid_map = item->ex_devid_map;
item->ex_devid_map = NULL;
new->ex_uuid = item->ex_uuid;
@@ -62,6 +62,7 @@ struct svc_export {
struct nfsd4_deviceid_map *ex_devid_map;
struct cache_detail *cd;
struct rcu_head ex_rcu;
kuid_t ex_root_uid;
};

/* an "export key" (expkey) maps a filehandlefragement to an
@@ -53,6 +53,7 @@
*/
#define NFSEXP_V4ROOT 0x10000
#define NFSEXP_PNFS 0x20000
#define NFSEXP_ROOTUID 0x40000

/* All flags that we claim to support. (Note we don't support NOACL.) */
#define NFSEXP_ALLFLAGS 0x3FEFF

0 comments on commit ab987ee

Please sign in to comment.
You can’t perform that action at this time.