]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
nfs/nfsd/sunrpc: enforce transport requirements for NFSv4
authorJeff Layton <jlayton@redhat.com>
Fri, 24 Feb 2017 18:25:24 +0000 (13:25 -0500)
committerJ. Bruce Fields <bfields@redhat.com>
Fri, 24 Feb 2017 22:03:34 +0000 (17:03 -0500)
NFSv4 requires a transport "that is specified to avoid network
congestion" (RFC 7530, section 3.1, paragraph 2).  In practical terms,
that means that you should not run NFSv4 over UDP. The server has never
enforced that requirement, however.

This patchset fixes this by adding a new flag to the svc_version that
states that it has these transport requirements. With that, we can check
that the transport has XPT_CONG_CTRL set before processing an RPC. If it
doesn't we reject it with RPC_PROG_MISMATCH.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfs/callback_xdr.c
fs/nfsd/nfs4proc.c
include/linux/sunrpc/svc.h
net/sunrpc/svc.c

index e9836f611d9c3cdc381b5da0679211cbfb03950f..fd0284c1dc328b92520aa0c39b4ca2a4b9899915 100644 (file)
@@ -1084,6 +1084,7 @@ struct svc_version nfs4_callback_version1 = {
        .vs_xdrsize = NFS4_CALLBACK_XDRSIZE,
        .vs_dispatch = NULL,
        .vs_hidden = true,
+       .vs_need_cong_ctrl = true,
 };
 
 struct svc_version nfs4_callback_version4 = {
@@ -1093,4 +1094,5 @@ struct svc_version nfs4_callback_version4 = {
        .vs_xdrsize = NFS4_CALLBACK_XDRSIZE,
        .vs_dispatch = NULL,
        .vs_hidden = true,
+       .vs_need_cong_ctrl = true,
 };
index 89e582fa58cd1bd187f05fd51caf34703ff1c463..cbeeda1e94a2fbbba61e2adeeb4f9ba89287eaf9 100644 (file)
@@ -2537,12 +2537,13 @@ static struct svc_procedure             nfsd_procedures4[2] = {
 };
 
 struct svc_version     nfsd_version4 = {
-               .vs_vers        = 4,
-               .vs_nproc       = 2,
-               .vs_proc        = nfsd_procedures4,
-               .vs_dispatch    = nfsd_dispatch,
-               .vs_xdrsize     = NFS4_SVC_XDRSIZE,
-               .vs_rpcb_optnl  = true,
+       .vs_vers                = 4,
+       .vs_nproc               = 2,
+       .vs_proc                = nfsd_procedures4,
+       .vs_dispatch            = nfsd_dispatch,
+       .vs_xdrsize             = NFS4_SVC_XDRSIZE,
+       .vs_rpcb_optnl          = true,
+       .vs_need_cong_ctrl      = true,
 };
 
 /*
index 96467c95f02e81cb347ed09f4d97b22472387aa3..e770abeed32d7117c4f2d363f9d7370a60d2c55f 100644 (file)
@@ -406,6 +406,9 @@ struct svc_version {
        /* Don't care if the rpcbind registration fails */
        bool                    vs_rpcb_optnl;
 
+       /* Need xprt with congestion control */
+       bool                    vs_need_cong_ctrl;
+
        /* Override dispatch function (e.g. when caching replies).
         * A return value of 0 means drop the request. 
         * vs_dispatch == NULL means use default dispatcher.
index 85bcdea67a3f7ca12bda0c9321c0d44544aa0482..1fc3ff8221689e1c12e33f55dfbe6d56b688c2c1 100644 (file)
@@ -1169,6 +1169,21 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
          !(versp = progp->pg_vers[vers]))
                goto err_bad_vers;
 
+       /*
+        * Some protocol versions (namely NFSv4) require some form of
+        * congestion control.  (See RFC 7530 section 3.1 paragraph 2)
+        * In other words, UDP is not allowed. We mark those when setting
+        * up the svc_xprt, and verify that here.
+        *
+        * The spec is not very clear about what error should be returned
+        * when someone tries to access a server that is listening on UDP
+        * for lower versions. RPC_PROG_MISMATCH seems to be the closest
+        * fit.
+        */
+       if (versp->vs_need_cong_ctrl &&
+           !test_bit(XPT_CONG_CTRL, &rqstp->rq_xprt->xpt_flags))
+               goto err_bad_vers;
+
        procp = versp->vs_proc + proc;
        if (proc >= versp->vs_nproc || !procp->pc_func)
                goto err_bad_proc;