@@ -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
546545secinfo_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+
549571static inline int
550572nfsd_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
828855static 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
0 commit comments