From d778309abd38fcd6a240448606192b9ef3411565 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 14 Dec 2009 17:07:19 -0500 Subject: [PATCH] exports: let kernel decide which flags vary by flavor Query the kernel to ask which flavors vary by pseudoflavor, and use that instead of a fixed constant. To allow the possibility of more flags varying by pseudoflavor, use the set/clear_flags functions for all options instead of setting some by hand. Signed-off-by: J. Bruce Fields --- support/include/exportfs.h | 7 +++ support/include/nfs/export.h | 12 +++++- support/nfs/exports.c | 83 +++++++++++++++++++++++++----------- 3 files changed, 75 insertions(+), 27 deletions(-) diff --git a/support/include/exportfs.h b/support/include/exportfs.h index a5cf482..ce7eac0 100644 --- a/support/include/exportfs.h +++ b/support/include/exportfs.h @@ -103,6 +103,13 @@ int rmtab_read(void); struct nfskey * key_lookup(char *hname); +struct export_features { + unsigned int flags; + unsigned int secinfo_flags; +}; + +struct export_features *get_export_features(void); + /* Record export error. */ extern int export_errno; diff --git a/support/include/nfs/export.h b/support/include/nfs/export.h index f7a99ba..d3e188c 100644 --- a/support/include/nfs/export.h +++ b/support/include/nfs/export.h @@ -24,6 +24,16 @@ #define NFSEXP_FSID 0x2000 #define NFSEXP_CROSSMOUNT 0x4000 #define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */ -#define NFSEXP_ALLFLAGS 0xFFFF +/* + * All flags supported by the kernel before addition of the + * export_features interface: + */ +#define NFSEXP_OLDFLAGS 0x7E3F +/* + * Flags that can vary per flavor, for kernels before addition of the + * export_features interface: + */ +#define NFSEXP_OLD_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \ + | NFSEXP_ALLSQUASH) #endif /* _NSF_EXPORT_H */ diff --git a/support/nfs/exports.c b/support/nfs/exports.c index f1ca632..ef31a85 100644 --- a/support/nfs/exports.c +++ b/support/nfs/exports.c @@ -467,9 +467,6 @@ static void clearflags(int mask, unsigned int active, struct exportent *ep) } } -/* options that can vary per flavor: */ -#define NFSEXP_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \ - | NFSEXP_ALLSQUASH) /* * For those flags which are not allowed to vary by pseudoflavor, * ensure that the export flags agree with the flags on each @@ -477,10 +474,12 @@ static void clearflags(int mask, unsigned int active, struct exportent *ep) */ static void fix_pseudoflavor_flags(struct exportent *ep) { + struct export_features *ef; struct sec_entry *p; + ef = get_export_features(); for (p = ep->e_secinfo; p->flav; p++) - p->flags |= ep->e_flags & ~NFSEXP_SECINFO_FLAGS; + p->flags |= ep->e_flags & ~ef->secinfo_flags; } /* @@ -518,25 +517,25 @@ parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr) else if (strcmp(opt, "rw") == 0) clearflags(NFSEXP_READONLY, active, ep); else if (!strcmp(opt, "secure")) - ep->e_flags &= ~NFSEXP_INSECURE_PORT; + clearflags(NFSEXP_INSECURE_PORT, active, ep); else if (!strcmp(opt, "insecure")) - ep->e_flags |= NFSEXP_INSECURE_PORT; + setflags(NFSEXP_INSECURE_PORT, active, ep); else if (!strcmp(opt, "sync")) - ep->e_flags &= ~NFSEXP_ASYNC; + clearflags(NFSEXP_ASYNC, active, ep); else if (!strcmp(opt, "async")) - ep->e_flags |= NFSEXP_ASYNC; + setflags(NFSEXP_ASYNC, active, ep); else if (!strcmp(opt, "nohide")) - ep->e_flags |= NFSEXP_NOHIDE; + setflags(NFSEXP_NOHIDE, active, ep); else if (!strcmp(opt, "hide")) - ep->e_flags &= ~NFSEXP_NOHIDE; + clearflags(NFSEXP_NOHIDE, active, ep); else if (!strcmp(opt, "crossmnt")) - ep->e_flags |= NFSEXP_CROSSMOUNT; + setflags(NFSEXP_CROSSMOUNT, active, ep); else if (!strcmp(opt, "nocrossmnt")) - ep->e_flags &= ~NFSEXP_CROSSMOUNT; + clearflags(NFSEXP_CROSSMOUNT, active, ep); else if (!strcmp(opt, "wdelay")) - ep->e_flags |= NFSEXP_GATHERED_WRITES; + setflags(NFSEXP_GATHERED_WRITES, active, ep); else if (!strcmp(opt, "no_wdelay")) - ep->e_flags &= ~NFSEXP_GATHERED_WRITES; + clearflags(NFSEXP_GATHERED_WRITES, active, ep); else if (strcmp(opt, "root_squash") == 0) setflags(NFSEXP_ROOTSQUASH, active, ep); else if (!strcmp(opt, "no_root_squash")) @@ -547,22 +546,22 @@ parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr) clearflags(NFSEXP_ALLSQUASH, active, ep); else if (strcmp(opt, "subtree_check") == 0) { had_subtree_opt = 1; - ep->e_flags &= ~NFSEXP_NOSUBTREECHECK; + clearflags(NFSEXP_NOSUBTREECHECK, active, ep); } else if (strcmp(opt, "no_subtree_check") == 0) { had_subtree_opt = 1; - ep->e_flags |= NFSEXP_NOSUBTREECHECK; + setflags(NFSEXP_NOSUBTREECHECK, active, ep); } else if (strcmp(opt, "auth_nlm") == 0) - ep->e_flags &= ~NFSEXP_NOAUTHNLM; + clearflags(NFSEXP_NOAUTHNLM, active, ep); else if (strcmp(opt, "no_auth_nlm") == 0) - ep->e_flags |= NFSEXP_NOAUTHNLM; + setflags(NFSEXP_NOAUTHNLM, active, ep); else if (strcmp(opt, "secure_locks") == 0) - ep->e_flags &= ~NFSEXP_NOAUTHNLM; + clearflags(NFSEXP_NOAUTHNLM, active, ep); else if (strcmp(opt, "insecure_locks") == 0) - ep->e_flags |= NFSEXP_NOAUTHNLM; + setflags(NFSEXP_NOAUTHNLM, active, ep); else if (strcmp(opt, "acl") == 0) - ep->e_flags &= ~NFSEXP_NOACL; + clearflags(NFSEXP_NOACL, active, ep); else if (strcmp(opt, "no_acl") == 0) - ep->e_flags |= NFSEXP_NOACL; + setflags(NFSEXP_NOACL, active, ep); else if (strncmp(opt, "anonuid=", 8) == 0) { char *oe; ep->e_anonuid = strtol(opt+8, &oe, 10); @@ -594,11 +593,11 @@ bad_option: char *oe; if (strcmp(opt+5, "root") == 0) { ep->e_fsid = 0; - ep->e_flags |= NFSEXP_FSID; + setflags(NFSEXP_FSID, active, ep); } else { ep->e_fsid = strtoul(opt+5, &oe, 0); if (opt[5]!='\0' && *oe == '\0') - ep->e_flags |= NFSEXP_FSID; + setflags(NFSEXP_FSID, active, ep); else if (valid_uuid(opt+5)) ep->e_uuid = strdup(opt+5); else { @@ -639,19 +638,20 @@ bad_option: } else { xlog(L_ERROR, "%s:%d: unknown keyword \"%s\"\n", flname, flline, opt); - ep->e_flags |= NFSEXP_ALLSQUASH | NFSEXP_READONLY; + setflags(NFSEXP_ALLSQUASH | NFSEXP_READONLY, active, ep); goto bad_option; } free(opt); while (isblank(*cp)) cp++; } + /* * Turn on nohide which will allow this export to cross over * the 'mount --bind' mount point. */ if (ep->e_fslocdata) - ep->e_flags |= NFSEXP_NOHIDE; + setflags(NFSEXP_NOHIDE, active, ep); fix_pseudoflavor_flags(ep); ep->e_squids = squids; ep->e_sqgids = sqgids; @@ -769,3 +769,34 @@ syntaxerr(char *msg) xlog(L_ERROR, "%s:%d: syntax error: %s", efname, efp?efp->x_line:0, msg); } +struct export_features *get_export_features(void) +{ + static char *path = "/proc/fs/nfsd/export_features"; + static struct export_features ef; + static int cached = 0; + char buf[50]; + int c; + int fd; + + if (cached) + return &ef; + + ef.flags = NFSEXP_OLDFLAGS; + ef.secinfo_flags = NFSEXP_OLD_SECINFO_FLAGS; + + fd = open(path, O_RDONLY); + if (fd == -1) + goto good; + fd = read(fd, buf, 50); + if (fd == -1) + goto err; + c = sscanf(buf, "%x %x", &ef.flags, &ef.secinfo_flags); + if (c != 2) + goto err; +good: + cached = 1; + return &ef; +err: + xlog(L_WARNING, "unexpected error reading %s", path); + return &ef; +} -- 2.39.5