History

NFSD: Handle new xprtsec= export option

Enable administrators to require clients to use transport layer security when accessing particular exports.

Chuck Lever committed 3 years ago

Commit 9280c571 parent b3cbf983 files · +62 −3Browse files

Unified · Split

3 files
  1. fs/nfsd/export.c +48 −3
  2. fs/nfsd/export.h +1 −0
  3. include/uapi/linux/nfsd/export.h +13 −0
fs/nfsd/export.c+48−3
@@ -439,7 +439,6 @@ static int check_export(struct path *path, int *flags, unsigned char *uuid) · 438 unmodified lines
439439 return -EINVAL;
440440 }
441441 return 0;
442−
443442 }
444443
445444 #ifdef CONFIG_NFSD_V4
@@ -546,6 +545,29 @@ static inline int · 100 unmodified lines
546545 secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; }
547546 #endif
548547
548+static int xprtsec_parse(char **mesg, char *buf, struct svc_export *exp)
549+{
550+ unsigned int i, mode, listsize;
551+ int err;
552+
553+ err = get_uint(mesg, &listsize);
554+ if (err)
555+ return err;
556+ if (listsize > NFSEXP_XPRTSEC_NUM)
557+ return -EINVAL;
558+
559+ exp->ex_xprtsec_modes = 0;
560+ for (i = 0; i < listsize; i++) {
561+ err = get_uint(mesg, &mode);
562+ if (err)
563+ return err;
564+ if (mode > NFSEXP_XPRTSEC_MTLS)
565+ return -EINVAL;
566+ exp->ex_xprtsec_modes |= mode;
567+ }
568+ return 0;
569+}
570+
549571 static inline int
550572 nfsd_uuid_parse(char **mesg, char *buf, unsigned char **puuid)
551573 {
@@ -608,6 +630,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) · 56 unmodified lines
608630 exp.ex_client = dom;
609631 exp.cd = cd;
610632 exp.ex_devid_map = NULL;
633+ exp.ex_xprtsec_modes = NFSEXP_XPRTSEC_ALL;
611634
612635 /* expiry */
613636 err = get_expiry(&mesg, &exp.h.expiry_time);
@@ -649,6 +672,8 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) · 35 unmodified lines
649672 err = nfsd_uuid_parse(&mesg, buf, &exp.ex_uuid);
650673 else if (strcmp(buf, "secinfo") == 0)
651674 err = secinfo_parse(&mesg, buf, &exp);
675+ else if (strcmp(buf, "xprtsec") == 0)
676+ err = xprtsec_parse(&mesg, buf, &exp);
652677 else
653678 /* quietly ignore unknown words and anything
654679 * following. Newer user-space can try to set
@@ -662,6 +687,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) · 7 unmodified lines
662687 err = check_export(&exp.ex_path, &exp.ex_flags, exp.ex_uuid);
663688 if (err)
664689 goto out4;
690+
665691 /*
666692 * No point caching this if it would immediately expire.
667693 * Also, this protects exportfs's dummy export from the
@@ -823,6 +849,7 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem) · 155 unmodified lines
823849 for (i = 0; i < MAX_SECINFO_LIST; i++) {
824850 new->ex_flavors[i] = item->ex_flavors[i];
825851 }
852+ new->ex_xprtsec_modes = item->ex_xprtsec_modes;
826853 }
827854
828855 static struct cache_head *svc_export_alloc(void)
@@ -1034,9 +1061,26 @@ static struct svc_export *exp_find(struct cache_detail *cd, · 205 unmodified lines
10341061
10351062 __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
10361063 {
1037− struct exp_flavor_info *f;
1038− struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
1064+ struct exp_flavor_info *f, *end = exp->ex_flavors + exp->ex_nflavors;
1065+ struct svc_xprt *xprt = rqstp->rq_xprt;
1066+
1067+ if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_NONE) {
1068+ if (!test_bit(XPT_TLS_SESSION, &xprt->xpt_flags))
1069+ goto ok;
1070+ }
1071+ if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_TLS) {
1072+ if (test_bit(XPT_TLS_SESSION, &xprt->xpt_flags) &&
1073+ !test_bit(XPT_PEER_AUTH, &xprt->xpt_flags))
1074+ goto ok;
1075+ }
1076+ if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_MTLS) {
1077+ if (test_bit(XPT_TLS_SESSION, &xprt->xpt_flags) &&
1078+ test_bit(XPT_PEER_AUTH, &xprt->xpt_flags))
1079+ goto ok;
1080+ }
1081+ goto denied;
10391082
1083+ok:
10401084 /* legacy gss-only clients are always OK: */
10411085 if (exp->ex_client == rqstp->rq_gssclient)
10421086 return 0;
@@ -1061,6 +1105,7 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp) · 18 unmodified lines
10611105 if (nfsd4_spo_must_allow(rqstp))
10621106 return 0;
10631107
1108+denied:
10641109 return rqstp->rq_vers < 4 ? nfserr_acces : nfserr_wrongsec;
10651110 }
10661111
fs/nfsd/export.h+1−0
@@ -77,6 +77,7 @@ struct svc_export { · 76 unmodified lines
7777 struct cache_detail *cd;
7878 struct rcu_head ex_rcu;
7979 struct export_stats ex_stats;
80+ unsigned long ex_xprtsec_modes;
8081 };
8182
8283 /* an "export key" (expkey) maps a filehandlefragement to an
include/uapi/linux/nfsd/export.h+13−0
@@ -62,5 +62,18 @@ · 61 unmodified lines
6262 | NFSEXP_ALLSQUASH \
6363 | NFSEXP_INSECURE_PORT)
6464
65+/*
66+ * Transport layer security policies that are permitted to access
67+ * an export
68+ */
69+#define NFSEXP_XPRTSEC_NONE 0x0001
70+#define NFSEXP_XPRTSEC_TLS 0x0002
71+#define NFSEXP_XPRTSEC_MTLS 0x0004
72+
73+#define NFSEXP_XPRTSEC_NUM (3)
74+
75+#define NFSEXP_XPRTSEC_ALL (NFSEXP_XPRTSEC_NONE | \
76+ NFSEXP_XPRTSEC_TLS | \
77+ NFSEXP_XPRTSEC_MTLS)
6578
6679 #endif /* _UAPINFSD_EXPORT_H */