···439439 return -EINVAL;440440 }441441 return 0;442442-443442}444443445444#ifdef CONFIG_NFSD_V4···545546secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; }546547#endif547548549549+static int xprtsec_parse(char **mesg, char *buf, struct svc_export *exp)550550+{551551+ unsigned int i, mode, listsize;552552+ int err;553553+554554+ err = get_uint(mesg, &listsize);555555+ if (err)556556+ return err;557557+ if (listsize > NFSEXP_XPRTSEC_NUM)558558+ return -EINVAL;559559+560560+ exp->ex_xprtsec_modes = 0;561561+ for (i = 0; i < listsize; i++) {562562+ err = get_uint(mesg, &mode);563563+ if (err)564564+ return err;565565+ if (mode > NFSEXP_XPRTSEC_MTLS)566566+ return -EINVAL;567567+ exp->ex_xprtsec_modes |= mode;568568+ }569569+ return 0;570570+}571571+548572static inline int549573nfsd_uuid_parse(char **mesg, char *buf, unsigned char **puuid)550574{···630608 exp.ex_client = dom;631609 exp.cd = cd;632610 exp.ex_devid_map = NULL;611611+ exp.ex_xprtsec_modes = NFSEXP_XPRTSEC_ALL;633612634613 /* expiry */635614 err = get_expiry(&mesg, &exp.h.expiry_time);···672649 err = nfsd_uuid_parse(&mesg, buf, &exp.ex_uuid);673650 else if (strcmp(buf, "secinfo") == 0)674651 err = secinfo_parse(&mesg, buf, &exp);652652+ else if (strcmp(buf, "xprtsec") == 0)653653+ err = xprtsec_parse(&mesg, buf, &exp);675654 else676655 /* quietly ignore unknown words and anything677656 * following. Newer user-space can try to set···687662 err = check_export(&exp.ex_path, &exp.ex_flags, exp.ex_uuid);688663 if (err)689664 goto out4;665665+690666 /*691667 * No point caching this if it would immediately expire.692668 * Also, this protects exportfs's dummy export from the···849823 for (i = 0; i < MAX_SECINFO_LIST; i++) {850824 new->ex_flavors[i] = item->ex_flavors[i];851825 }826826+ new->ex_xprtsec_modes = item->ex_xprtsec_modes;852827}853828854829static struct cache_head *svc_export_alloc(void)···1061103410621035__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)10631036{10641064- struct exp_flavor_info *f;10651065- struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;10371037+ struct exp_flavor_info *f, *end = exp->ex_flavors + exp->ex_nflavors;10381038+ struct svc_xprt *xprt = rqstp->rq_xprt;1066103910401040+ if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_NONE) {10411041+ if (!test_bit(XPT_TLS_SESSION, &xprt->xpt_flags))10421042+ goto ok;10431043+ }10441044+ if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_TLS) {10451045+ if (test_bit(XPT_TLS_SESSION, &xprt->xpt_flags) &&10461046+ !test_bit(XPT_PEER_AUTH, &xprt->xpt_flags))10471047+ goto ok;10481048+ }10491049+ if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_MTLS) {10501050+ if (test_bit(XPT_TLS_SESSION, &xprt->xpt_flags) &&10511051+ test_bit(XPT_PEER_AUTH, &xprt->xpt_flags))10521052+ goto ok;10531053+ }10541054+ goto denied;10551055+10561056+ok:10671057 /* legacy gss-only clients are always OK: */10681058 if (exp->ex_client == rqstp->rq_gssclient)10691059 return 0;···11051061 if (nfsd4_spo_must_allow(rqstp))11061062 return 0;1107106310641064+denied:11081065 return rqstp->rq_vers < 4 ? nfserr_acces : nfserr_wrongsec;11091066}11101067
+1
fs/nfsd/export.h
···7777 struct cache_detail *cd;7878 struct rcu_head ex_rcu;7979 struct export_stats ex_stats;8080+ unsigned long ex_xprtsec_modes;8081};81828283/* an "export key" (expkey) maps a filehandlefragement to an
+13
include/uapi/linux/nfsd/export.h
···6262 | NFSEXP_ALLSQUASH \6363 | NFSEXP_INSECURE_PORT)64646565+/*6666+ * Transport layer security policies that are permitted to access6767+ * an export6868+ */6969+#define NFSEXP_XPRTSEC_NONE 0x00017070+#define NFSEXP_XPRTSEC_TLS 0x00027171+#define NFSEXP_XPRTSEC_MTLS 0x00047272+7373+#define NFSEXP_XPRTSEC_NUM (3)7474+7575+#define NFSEXP_XPRTSEC_ALL (NFSEXP_XPRTSEC_NONE | \7676+ NFSEXP_XPRTSEC_TLS | \7777+ NFSEXP_XPRTSEC_MTLS)65786679#endif /* _UAPINFSD_EXPORT_H */