Skip to content

Commit 9280c57

Browse files
committed
NFSD: Handle new xprtsec= export option
Enable administrators to require clients to use transport layer security when accessing particular exports. Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent b3cbf98 commit 9280c57

3 files changed

Lines changed: 62 additions & 3 deletions

File tree

fs/nfsd/export.c

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,6 @@ static int check_export(struct path *path, int *flags, unsigned char *uuid)
439439
return -EINVAL;
440440
}
441441
return 0;
442-
443442
}
444443

445444
#ifdef CONFIG_NFSD_V4
@@ -546,6 +545,29 @@ static inline int
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)
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)
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)
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)
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,
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)
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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ struct svc_export {
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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,18 @@
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 */

0 commit comments

Comments
 (0)