nfsd4: check backchannel attributes on create_session
authorJ. Bruce Fields <bfields@redhat.com>
Tue, 9 Apr 2013 15:34:36 +0000 (11:34 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Tue, 9 Apr 2013 20:53:56 +0000 (16:53 -0400)
Make sure the client gives us an adequate backchannel.

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4state.c
fs/nfsd/xdr4cb.h [new file with mode: 0644]
include/linux/sunrpc/msg_prot.h

index be3ff0f3ff686bf51a3e6a04612373b90eb9409b..7f05cd140de3cb2a8c75665bdbcad8bb3d823582 100644 (file)
@@ -37,6 +37,7 @@
 #include "nfsd.h"
 #include "state.h"
 #include "netns.h"
+#include "xdr4cb.h"
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
@@ -53,30 +54,6 @@ enum {
        NFSPROC4_CLNT_CB_SEQUENCE,
 };
 
-#define NFS4_MAXTAGLEN         20
-
-#define NFS4_enc_cb_null_sz            0
-#define NFS4_dec_cb_null_sz            0
-#define cb_compound_enc_hdr_sz         4
-#define cb_compound_dec_hdr_sz         (3 + (NFS4_MAXTAGLEN >> 2))
-#define sessionid_sz                   (NFS4_MAX_SESSIONID_LEN >> 2)
-#define cb_sequence_enc_sz             (sessionid_sz + 4 +             \
-                                       1 /* no referring calls list yet */)
-#define cb_sequence_dec_sz             (op_dec_sz + sessionid_sz + 4)
-
-#define op_enc_sz                      1
-#define op_dec_sz                      2
-#define enc_nfs4_fh_sz                 (1 + (NFS4_FHSIZE >> 2))
-#define enc_stateid_sz                 (NFS4_STATEID_SIZE >> 2)
-#define NFS4_enc_cb_recall_sz          (cb_compound_enc_hdr_sz +       \
-                                       cb_sequence_enc_sz +            \
-                                       1 + enc_stateid_sz +            \
-                                       enc_nfs4_fh_sz)
-
-#define NFS4_dec_cb_recall_sz          (cb_compound_dec_hdr_sz  +      \
-                                       cb_sequence_dec_sz +            \
-                                       op_dec_sz)
-
 struct nfs4_cb_compound_hdr {
        /* args */
        u32             ident;  /* minorversion 0 only */
index 036d5f16fd7f764af76b909d191f9e9150ab708d..67017fcebb21f99c90256cb635163d858f30d836 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/sunrpc/svcauth_gss.h>
 #include <linux/sunrpc/addr.h>
 #include "xdr4.h"
+#include "xdr4cb.h"
 #include "vfs.h"
 #include "current_stateid.h"
 
@@ -1794,6 +1795,27 @@ static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs *ca, struct nfs
        return nfs_ok;
 }
 
+static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca)
+{
+       ca->headerpadsz = 0;
+
+       /*
+        * These RPC_MAX_HEADER macros are overkill, especially since we
+        * don't even do gss on the backchannel yet.  But this is still
+        * less than 1k.  Tighten up this estimate in the unlikely event
+        * it turns out to be a problem for some client:
+        */
+       if (ca->maxreq_sz < NFS4_enc_cb_recall_sz + RPC_MAX_HEADER_WITH_AUTH)
+               return nfserr_toosmall;
+       if (ca->maxresp_sz < NFS4_dec_cb_recall_sz + RPC_MAX_REPHEADER_WITH_AUTH)
+               return nfserr_toosmall;
+       ca->maxresp_cached = 0;
+       if (ca->maxops < 2)
+               return nfserr_toosmall;
+
+       return nfs_ok;
+}
+
 __be32
 nfsd4_create_session(struct svc_rqst *rqstp,
                     struct nfsd4_compound_state *cstate,
@@ -1810,6 +1832,9 @@ nfsd4_create_session(struct svc_rqst *rqstp,
        if (cr_ses->flags & ~SESSION4_FLAG_MASK_A)
                return nfserr_inval;
        status = check_forechannel_attrs(&cr_ses->fore_channel, nn);
+       if (status)
+               return status;
+       status = check_backchannel_attrs(&cr_ses->back_channel);
        if (status)
                return status;
        status = nfserr_jukebox;
diff --git a/fs/nfsd/xdr4cb.h b/fs/nfsd/xdr4cb.h
new file mode 100644 (file)
index 0000000..c5c55df
--- /dev/null
@@ -0,0 +1,23 @@
+#define NFS4_MAXTAGLEN         20
+
+#define NFS4_enc_cb_null_sz            0
+#define NFS4_dec_cb_null_sz            0
+#define cb_compound_enc_hdr_sz         4
+#define cb_compound_dec_hdr_sz         (3 + (NFS4_MAXTAGLEN >> 2))
+#define sessionid_sz                   (NFS4_MAX_SESSIONID_LEN >> 2)
+#define cb_sequence_enc_sz             (sessionid_sz + 4 +             \
+                                       1 /* no referring calls list yet */)
+#define cb_sequence_dec_sz             (op_dec_sz + sessionid_sz + 4)
+
+#define op_enc_sz                      1
+#define op_dec_sz                      2
+#define enc_nfs4_fh_sz                 (1 + (NFS4_FHSIZE >> 2))
+#define enc_stateid_sz                 (NFS4_STATEID_SIZE >> 2)
+#define NFS4_enc_cb_recall_sz          (cb_compound_enc_hdr_sz +       \
+                                       cb_sequence_enc_sz +            \
+                                       1 + enc_stateid_sz +            \
+                                       enc_nfs4_fh_sz)
+
+#define NFS4_dec_cb_recall_sz          (cb_compound_dec_hdr_sz  +      \
+                                       cb_sequence_dec_sz +            \
+                                       op_dec_sz)
index c68a147939a63ef9a6b04e08c9aef27e97621c31..aadc6a04e1acb91bb4baa40b545237d4822dfaee 100644 (file)
@@ -138,6 +138,9 @@ typedef __be32      rpc_fraghdr;
 #define RPC_MAX_HEADER_WITH_AUTH \
        (RPC_CALLHDRSIZE + 2*(2+RPC_MAX_AUTH_SIZE/4))
 
+#define RPC_MAX_REPHEADER_WITH_AUTH \
+       (RPC_REPHDRSIZE + (2 + RPC_MAX_AUTH_SIZE/4))
+
 /*
  * RFC1833/RFC3530 rpcbind (v3+) well-known netid's.
  */