diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2009-06-17 21:02:13 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-06-17 21:02:13 -0400 |
commit | 8e02f6b9aae9b265064f929c6df15222b9baf256 (patch) | |
tree | b5f018180a6b130731c085ee6ae7c060decfe538 /fs/nfs | |
parent | a14017db2852f9393a401a0f64053c331003babf (diff) |
NFS: Update MNT and MNT3 reply decoding functions
Solder xdr_stream-based XDR decoding functions into the in-kernel mountd
client that are more careful about checking data types and watching for
buffer overflows. The new MNT3 decoder includes support for auth-flavor
list decoding.
The "_sz" macro for MNT3 replies was missing the size of the file handle.
I've added this back, and included the size of the auth flavor array.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/internal.h | 2 | ||||
-rw-r--r-- | fs/nfs/mount_clnt.c | 63 | ||||
-rw-r--r-- | fs/nfs/nfsroot.c | 2 | ||||
-rw-r--r-- | fs/nfs/super.c | 2 |
4 files changed, 55 insertions, 14 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 0207758de44a..10cf1110df48 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -83,6 +83,8 @@ struct nfs_mount_request { | |||
83 | unsigned short protocol; | 83 | unsigned short protocol; |
84 | struct nfs_fh *fh; | 84 | struct nfs_fh *fh; |
85 | int noresvport; | 85 | int noresvport; |
86 | unsigned int *auth_flav_len; | ||
87 | rpc_authflavor_t *auth_flavs; | ||
86 | }; | 88 | }; |
87 | 89 | ||
88 | extern int nfs_mount(struct nfs_mount_request *info); | 90 | extern int nfs_mount(struct nfs_mount_request *info); |
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index ed0a27ed538d..618d815c3093 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c | |||
@@ -39,6 +39,9 @@ | |||
39 | * XDR argument and result sizes | 39 | * XDR argument and result sizes |
40 | */ | 40 | */ |
41 | #define MNT_enc_dirpath_sz encode_dirpath_sz | 41 | #define MNT_enc_dirpath_sz encode_dirpath_sz |
42 | #define MNT_dec_mountres_sz (MNT_status_sz + MNT_fhandle_sz) | ||
43 | #define MNT_dec_mountres3_sz (MNT_status_sz + MNT_fhandle_sz + \ | ||
44 | MNT_authflav3_sz) | ||
42 | 45 | ||
43 | /* | 46 | /* |
44 | * Defined by RFC 1094, section A.5 | 47 | * Defined by RFC 1094, section A.5 |
@@ -140,8 +143,10 @@ struct mnt_fhstatus { | |||
140 | */ | 143 | */ |
141 | int nfs_mount(struct nfs_mount_request *info) | 144 | int nfs_mount(struct nfs_mount_request *info) |
142 | { | 145 | { |
143 | struct mnt_fhstatus result = { | 146 | struct mountres result = { |
144 | .fh = info->fh | 147 | .fh = info->fh, |
148 | .auth_count = info->auth_flav_len, | ||
149 | .auth_flavors = info->auth_flavs, | ||
145 | }; | 150 | }; |
146 | struct rpc_message msg = { | 151 | struct rpc_message msg = { |
147 | .rpc_argp = info->dirpath, | 152 | .rpc_argp = info->dirpath, |
@@ -180,7 +185,7 @@ int nfs_mount(struct nfs_mount_request *info) | |||
180 | 185 | ||
181 | if (status < 0) | 186 | if (status < 0) |
182 | goto out_call_err; | 187 | goto out_call_err; |
183 | if (result.status != 0) | 188 | if (result.errno != 0) |
184 | goto out_mnt_err; | 189 | goto out_mnt_err; |
185 | 190 | ||
186 | dprintk("NFS: MNT request succeeded\n"); | 191 | dprintk("NFS: MNT request succeeded\n"); |
@@ -191,16 +196,16 @@ out: | |||
191 | 196 | ||
192 | out_clnt_err: | 197 | out_clnt_err: |
193 | status = PTR_ERR(mnt_clnt); | 198 | status = PTR_ERR(mnt_clnt); |
194 | dprintk("NFS: failed to create RPC client, status=%d\n", status); | 199 | dprintk("NFS: failed to create MNT RPC client, status=%d\n", status); |
195 | goto out; | 200 | goto out; |
196 | 201 | ||
197 | out_call_err: | 202 | out_call_err: |
198 | dprintk("NFS: failed to start MNT request, status=%d\n", status); | 203 | dprintk("NFS: MNT request failed, status=%d\n", status); |
199 | goto out; | 204 | goto out; |
200 | 205 | ||
201 | out_mnt_err: | 206 | out_mnt_err: |
202 | dprintk("NFS: MNT server returned result %d\n", result.status); | 207 | dprintk("NFS: MNT server returned result %d\n", result.errno); |
203 | status = nfs_stat_to_errno(result.status); | 208 | status = result.errno; |
204 | goto out; | 209 | goto out; |
205 | } | 210 | } |
206 | 211 | ||
@@ -291,6 +296,20 @@ static int decode_fhandle(struct xdr_stream *xdr, struct mountres *res) | |||
291 | return 0; | 296 | return 0; |
292 | } | 297 | } |
293 | 298 | ||
299 | static int mnt_dec_mountres(struct rpc_rqst *req, __be32 *p, | ||
300 | struct mountres *res) | ||
301 | { | ||
302 | struct xdr_stream xdr; | ||
303 | int status; | ||
304 | |||
305 | xdr_init_decode(&xdr, &req->rq_rcv_buf, p); | ||
306 | |||
307 | status = decode_status(&xdr, res); | ||
308 | if (unlikely(status != 0 || res->errno != 0)) | ||
309 | return status; | ||
310 | return decode_fhandle(&xdr, res); | ||
311 | } | ||
312 | |||
294 | static int decode_fhs_status(struct xdr_stream *xdr, struct mountres *res) | 313 | static int decode_fhs_status(struct xdr_stream *xdr, struct mountres *res) |
295 | { | 314 | { |
296 | unsigned int i; | 315 | unsigned int i; |
@@ -371,6 +390,25 @@ static int decode_auth_flavors(struct xdr_stream *xdr, struct mountres *res) | |||
371 | return 0; | 390 | return 0; |
372 | } | 391 | } |
373 | 392 | ||
393 | static int mnt_dec_mountres3(struct rpc_rqst *req, __be32 *p, | ||
394 | struct mountres *res) | ||
395 | { | ||
396 | struct xdr_stream xdr; | ||
397 | int status; | ||
398 | |||
399 | xdr_init_decode(&xdr, &req->rq_rcv_buf, p); | ||
400 | |||
401 | status = decode_fhs_status(&xdr, res); | ||
402 | if (unlikely(status != 0 || res->errno != 0)) | ||
403 | return status; | ||
404 | status = decode_fhandle3(&xdr, res); | ||
405 | if (unlikely(status != 0)) { | ||
406 | res->errno = -EBADHANDLE; | ||
407 | return 0; | ||
408 | } | ||
409 | return decode_auth_flavors(&xdr, res); | ||
410 | } | ||
411 | |||
374 | static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p, | 412 | static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p, |
375 | struct mnt_fhstatus *res) | 413 | struct mnt_fhstatus *res) |
376 | { | 414 | { |
@@ -388,16 +426,13 @@ static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p, | |||
388 | return 0; | 426 | return 0; |
389 | } | 427 | } |
390 | 428 | ||
391 | #define MNT_fhstatus_sz (1 + 8) | ||
392 | #define MNT_fhstatus3_sz (1 + 16) | ||
393 | |||
394 | static struct rpc_procinfo mnt_procedures[] = { | 429 | static struct rpc_procinfo mnt_procedures[] = { |
395 | [MOUNTPROC_MNT] = { | 430 | [MOUNTPROC_MNT] = { |
396 | .p_proc = MOUNTPROC_MNT, | 431 | .p_proc = MOUNTPROC_MNT, |
397 | .p_encode = (kxdrproc_t)mnt_enc_dirpath, | 432 | .p_encode = (kxdrproc_t)mnt_enc_dirpath, |
398 | .p_decode = (kxdrproc_t) xdr_decode_fhstatus, | 433 | .p_decode = (kxdrproc_t)mnt_dec_mountres, |
399 | .p_arglen = MNT_enc_dirpath_sz, | 434 | .p_arglen = MNT_enc_dirpath_sz, |
400 | .p_replen = MNT_fhstatus_sz, | 435 | .p_replen = MNT_dec_mountres_sz, |
401 | .p_statidx = MOUNTPROC_MNT, | 436 | .p_statidx = MOUNTPROC_MNT, |
402 | .p_name = "MOUNT", | 437 | .p_name = "MOUNT", |
403 | }, | 438 | }, |
@@ -407,9 +442,9 @@ static struct rpc_procinfo mnt3_procedures[] = { | |||
407 | [MOUNTPROC3_MNT] = { | 442 | [MOUNTPROC3_MNT] = { |
408 | .p_proc = MOUNTPROC3_MNT, | 443 | .p_proc = MOUNTPROC3_MNT, |
409 | .p_encode = (kxdrproc_t)mnt_enc_dirpath, | 444 | .p_encode = (kxdrproc_t)mnt_enc_dirpath, |
410 | .p_decode = (kxdrproc_t) xdr_decode_fhstatus3, | 445 | .p_decode = (kxdrproc_t)mnt_dec_mountres3, |
411 | .p_arglen = MNT_enc_dirpath_sz, | 446 | .p_arglen = MNT_enc_dirpath_sz, |
412 | .p_replen = MNT_fhstatus3_sz, | 447 | .p_replen = MNT_dec_mountres3_sz, |
413 | .p_statidx = MOUNTPROC3_MNT, | 448 | .p_statidx = MOUNTPROC3_MNT, |
414 | .p_name = "MOUNT", | 449 | .p_name = "MOUNT", |
415 | }, | 450 | }, |
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index 24c1b93874c4..8c55b27c0de4 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c | |||
@@ -490,6 +490,7 @@ static int __init root_nfs_get_handle(void) | |||
490 | { | 490 | { |
491 | struct nfs_fh fh; | 491 | struct nfs_fh fh; |
492 | struct sockaddr_in sin; | 492 | struct sockaddr_in sin; |
493 | unsigned int auth_flav_len = 0; | ||
493 | struct nfs_mount_request request = { | 494 | struct nfs_mount_request request = { |
494 | .sap = (struct sockaddr *)&sin, | 495 | .sap = (struct sockaddr *)&sin, |
495 | .salen = sizeof(sin), | 496 | .salen = sizeof(sin), |
@@ -499,6 +500,7 @@ static int __init root_nfs_get_handle(void) | |||
499 | .protocol = (nfs_data.flags & NFS_MOUNT_TCP) ? | 500 | .protocol = (nfs_data.flags & NFS_MOUNT_TCP) ? |
500 | XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP, | 501 | XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP, |
501 | .fh = &fh, | 502 | .fh = &fh, |
503 | .auth_flav_len = &auth_flav_len, | ||
502 | }; | 504 | }; |
503 | int status; | 505 | int status; |
504 | 506 | ||
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 539a61a0887b..0b72357cdc41 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -1380,6 +1380,7 @@ out_security_failure: | |||
1380 | static int nfs_try_mount(struct nfs_parsed_mount_data *args, | 1380 | static int nfs_try_mount(struct nfs_parsed_mount_data *args, |
1381 | struct nfs_fh *root_fh) | 1381 | struct nfs_fh *root_fh) |
1382 | { | 1382 | { |
1383 | unsigned int auth_flavor_len = 0; | ||
1383 | struct nfs_mount_request request = { | 1384 | struct nfs_mount_request request = { |
1384 | .sap = (struct sockaddr *) | 1385 | .sap = (struct sockaddr *) |
1385 | &args->mount_server.address, | 1386 | &args->mount_server.address, |
@@ -1387,6 +1388,7 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args, | |||
1387 | .protocol = args->mount_server.protocol, | 1388 | .protocol = args->mount_server.protocol, |
1388 | .fh = root_fh, | 1389 | .fh = root_fh, |
1389 | .noresvport = args->flags & NFS_MOUNT_NORESVPORT, | 1390 | .noresvport = args->flags & NFS_MOUNT_NORESVPORT, |
1391 | .auth_flav_len = &auth_flavor_len, | ||
1390 | }; | 1392 | }; |
1391 | int status; | 1393 | int status; |
1392 | 1394 | ||