aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2013-04-09 11:34:36 -0400
committerJ. Bruce Fields <bfields@redhat.com>2013-04-09 16:53:56 -0400
commit06b332a52293a45324320b6b446a7fa677fb6702 (patch)
tree4629ff4b2eb7bdf85593db7d24f362a5561c9e59 /fs/nfsd
parent55c760cfc40d75b4d8a17d56580ec306db2ab14f (diff)
nfsd4: check backchannel attributes on create_session
Make sure the client gives us an adequate backchannel. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4callback.c25
-rw-r--r--fs/nfsd/nfs4state.c25
-rw-r--r--fs/nfsd/xdr4cb.h23
3 files changed, 49 insertions, 24 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index be3ff0f3ff68..7f05cd140de3 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -37,6 +37,7 @@
37#include "nfsd.h" 37#include "nfsd.h"
38#include "state.h" 38#include "state.h"
39#include "netns.h" 39#include "netns.h"
40#include "xdr4cb.h"
40 41
41#define NFSDDBG_FACILITY NFSDDBG_PROC 42#define NFSDDBG_FACILITY NFSDDBG_PROC
42 43
@@ -53,30 +54,6 @@ enum {
53 NFSPROC4_CLNT_CB_SEQUENCE, 54 NFSPROC4_CLNT_CB_SEQUENCE,
54}; 55};
55 56
56#define NFS4_MAXTAGLEN 20
57
58#define NFS4_enc_cb_null_sz 0
59#define NFS4_dec_cb_null_sz 0
60#define cb_compound_enc_hdr_sz 4
61#define cb_compound_dec_hdr_sz (3 + (NFS4_MAXTAGLEN >> 2))
62#define sessionid_sz (NFS4_MAX_SESSIONID_LEN >> 2)
63#define cb_sequence_enc_sz (sessionid_sz + 4 + \
64 1 /* no referring calls list yet */)
65#define cb_sequence_dec_sz (op_dec_sz + sessionid_sz + 4)
66
67#define op_enc_sz 1
68#define op_dec_sz 2
69#define enc_nfs4_fh_sz (1 + (NFS4_FHSIZE >> 2))
70#define enc_stateid_sz (NFS4_STATEID_SIZE >> 2)
71#define NFS4_enc_cb_recall_sz (cb_compound_enc_hdr_sz + \
72 cb_sequence_enc_sz + \
73 1 + enc_stateid_sz + \
74 enc_nfs4_fh_sz)
75
76#define NFS4_dec_cb_recall_sz (cb_compound_dec_hdr_sz + \
77 cb_sequence_dec_sz + \
78 op_dec_sz)
79
80struct nfs4_cb_compound_hdr { 57struct nfs4_cb_compound_hdr {
81 /* args */ 58 /* args */
82 u32 ident; /* minorversion 0 only */ 59 u32 ident; /* minorversion 0 only */
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 036d5f16fd7f..67017fcebb21 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -42,6 +42,7 @@
42#include <linux/sunrpc/svcauth_gss.h> 42#include <linux/sunrpc/svcauth_gss.h>
43#include <linux/sunrpc/addr.h> 43#include <linux/sunrpc/addr.h>
44#include "xdr4.h" 44#include "xdr4.h"
45#include "xdr4cb.h"
45#include "vfs.h" 46#include "vfs.h"
46#include "current_stateid.h" 47#include "current_stateid.h"
47 48
@@ -1794,6 +1795,27 @@ static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs *ca, struct nfs
1794 return nfs_ok; 1795 return nfs_ok;
1795} 1796}
1796 1797
1798static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca)
1799{
1800 ca->headerpadsz = 0;
1801
1802 /*
1803 * These RPC_MAX_HEADER macros are overkill, especially since we
1804 * don't even do gss on the backchannel yet. But this is still
1805 * less than 1k. Tighten up this estimate in the unlikely event
1806 * it turns out to be a problem for some client:
1807 */
1808 if (ca->maxreq_sz < NFS4_enc_cb_recall_sz + RPC_MAX_HEADER_WITH_AUTH)
1809 return nfserr_toosmall;
1810 if (ca->maxresp_sz < NFS4_dec_cb_recall_sz + RPC_MAX_REPHEADER_WITH_AUTH)
1811 return nfserr_toosmall;
1812 ca->maxresp_cached = 0;
1813 if (ca->maxops < 2)
1814 return nfserr_toosmall;
1815
1816 return nfs_ok;
1817}
1818
1797__be32 1819__be32
1798nfsd4_create_session(struct svc_rqst *rqstp, 1820nfsd4_create_session(struct svc_rqst *rqstp,
1799 struct nfsd4_compound_state *cstate, 1821 struct nfsd4_compound_state *cstate,
@@ -1812,6 +1834,9 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1812 status = check_forechannel_attrs(&cr_ses->fore_channel, nn); 1834 status = check_forechannel_attrs(&cr_ses->fore_channel, nn);
1813 if (status) 1835 if (status)
1814 return status; 1836 return status;
1837 status = check_backchannel_attrs(&cr_ses->back_channel);
1838 if (status)
1839 return status;
1815 status = nfserr_jukebox; 1840 status = nfserr_jukebox;
1816 new = alloc_session(&cr_ses->fore_channel); 1841 new = alloc_session(&cr_ses->fore_channel);
1817 if (!new) 1842 if (!new)
diff --git a/fs/nfsd/xdr4cb.h b/fs/nfsd/xdr4cb.h
new file mode 100644
index 000000000000..c5c55dfb91a9
--- /dev/null
+++ b/fs/nfsd/xdr4cb.h
@@ -0,0 +1,23 @@
1#define NFS4_MAXTAGLEN 20
2
3#define NFS4_enc_cb_null_sz 0
4#define NFS4_dec_cb_null_sz 0
5#define cb_compound_enc_hdr_sz 4
6#define cb_compound_dec_hdr_sz (3 + (NFS4_MAXTAGLEN >> 2))
7#define sessionid_sz (NFS4_MAX_SESSIONID_LEN >> 2)
8#define cb_sequence_enc_sz (sessionid_sz + 4 + \
9 1 /* no referring calls list yet */)
10#define cb_sequence_dec_sz (op_dec_sz + sessionid_sz + 4)
11
12#define op_enc_sz 1
13#define op_dec_sz 2
14#define enc_nfs4_fh_sz (1 + (NFS4_FHSIZE >> 2))
15#define enc_stateid_sz (NFS4_STATEID_SIZE >> 2)
16#define NFS4_enc_cb_recall_sz (cb_compound_enc_hdr_sz + \
17 cb_sequence_enc_sz + \
18 1 + enc_stateid_sz + \
19 enc_nfs4_fh_sz)
20
21#define NFS4_dec_cb_recall_sz (cb_compound_dec_hdr_sz + \
22 cb_sequence_dec_sz + \
23 op_dec_sz)