diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-10 12:28:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-10 12:28:55 -0400 |
commit | 2dbd3cac87250a0d44e07acc86c4224a08522709 (patch) | |
tree | 4f31fdf50bfe64616aca1c4e2405930fd5b15e84 | |
parent | a77c005887a6d6f318117176791efa0ef7fcca80 (diff) | |
parent | 7255e716b1757dc10fa5e3a4d2eaab303ff9f7b6 (diff) |
Merge branch 'for-3.10' of git://linux-nfs.org/~bfields/linux
Pull nfsd fixes from Bruce Fields:
"Small fixes for two bugs and two warnings"
* 'for-3.10' of git://linux-nfs.org/~bfields/linux:
nfsd: fix oops when legacy_recdir_name_error is passed a -ENOENT error
SUNRPC: fix decoding of optional gss-proxy xdr fields
SUNRPC: Refactor gssx_dec_option_array() to kill uninitialized warning
nfsd4: don't allow owner override on 4.1 CLAIM_FH opens
-rw-r--r-- | fs/nfsd/nfs4proc.c | 15 | ||||
-rw-r--r-- | fs/nfsd/nfs4recover.c | 12 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_rpc_xdr.c | 58 |
3 files changed, 48 insertions, 37 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 8ae5abfe6ba2..27d74a294515 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -279,6 +279,7 @@ do_open_fhandle(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, str | |||
279 | { | 279 | { |
280 | struct svc_fh *current_fh = &cstate->current_fh; | 280 | struct svc_fh *current_fh = &cstate->current_fh; |
281 | __be32 status; | 281 | __be32 status; |
282 | int accmode = 0; | ||
282 | 283 | ||
283 | /* We don't know the target directory, and therefore can not | 284 | /* We don't know the target directory, and therefore can not |
284 | * set the change info | 285 | * set the change info |
@@ -290,9 +291,19 @@ do_open_fhandle(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, str | |||
290 | 291 | ||
291 | open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) && | 292 | open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) && |
292 | (open->op_iattr.ia_size == 0); | 293 | (open->op_iattr.ia_size == 0); |
294 | /* | ||
295 | * In the delegation case, the client is telling us about an | ||
296 | * open that it *already* performed locally, some time ago. We | ||
297 | * should let it succeed now if possible. | ||
298 | * | ||
299 | * In the case of a CLAIM_FH open, on the other hand, the client | ||
300 | * may be counting on us to enforce permissions (the Linux 4.1 | ||
301 | * client uses this for normal opens, for example). | ||
302 | */ | ||
303 | if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEG_CUR_FH) | ||
304 | accmode = NFSD_MAY_OWNER_OVERRIDE; | ||
293 | 305 | ||
294 | status = do_open_permission(rqstp, current_fh, open, | 306 | status = do_open_permission(rqstp, current_fh, open, accmode); |
295 | NFSD_MAY_OWNER_OVERRIDE); | ||
296 | 307 | ||
297 | return status; | 308 | return status; |
298 | } | 309 | } |
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 899ca26dd194..4e9a21db867a 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c | |||
@@ -146,7 +146,7 @@ out_no_tfm: | |||
146 | * then disable recovery tracking. | 146 | * then disable recovery tracking. |
147 | */ | 147 | */ |
148 | static void | 148 | static void |
149 | legacy_recdir_name_error(int error) | 149 | legacy_recdir_name_error(struct nfs4_client *clp, int error) |
150 | { | 150 | { |
151 | printk(KERN_ERR "NFSD: unable to generate recoverydir " | 151 | printk(KERN_ERR "NFSD: unable to generate recoverydir " |
152 | "name (%d).\n", error); | 152 | "name (%d).\n", error); |
@@ -159,9 +159,7 @@ legacy_recdir_name_error(int error) | |||
159 | if (error == -ENOENT) { | 159 | if (error == -ENOENT) { |
160 | printk(KERN_ERR "NFSD: disabling legacy clientid tracking. " | 160 | printk(KERN_ERR "NFSD: disabling legacy clientid tracking. " |
161 | "Reboot recovery will not function correctly!\n"); | 161 | "Reboot recovery will not function correctly!\n"); |
162 | 162 | nfsd4_client_tracking_exit(clp->net); | |
163 | /* the argument is ignored by the legacy exit function */ | ||
164 | nfsd4_client_tracking_exit(NULL); | ||
165 | } | 163 | } |
166 | } | 164 | } |
167 | 165 | ||
@@ -184,7 +182,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp) | |||
184 | 182 | ||
185 | status = nfs4_make_rec_clidname(dname, &clp->cl_name); | 183 | status = nfs4_make_rec_clidname(dname, &clp->cl_name); |
186 | if (status) | 184 | if (status) |
187 | return legacy_recdir_name_error(status); | 185 | return legacy_recdir_name_error(clp, status); |
188 | 186 | ||
189 | status = nfs4_save_creds(&original_cred); | 187 | status = nfs4_save_creds(&original_cred); |
190 | if (status < 0) | 188 | if (status < 0) |
@@ -341,7 +339,7 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp) | |||
341 | 339 | ||
342 | status = nfs4_make_rec_clidname(dname, &clp->cl_name); | 340 | status = nfs4_make_rec_clidname(dname, &clp->cl_name); |
343 | if (status) | 341 | if (status) |
344 | return legacy_recdir_name_error(status); | 342 | return legacy_recdir_name_error(clp, status); |
345 | 343 | ||
346 | status = mnt_want_write_file(nn->rec_file); | 344 | status = mnt_want_write_file(nn->rec_file); |
347 | if (status) | 345 | if (status) |
@@ -601,7 +599,7 @@ nfsd4_check_legacy_client(struct nfs4_client *clp) | |||
601 | 599 | ||
602 | status = nfs4_make_rec_clidname(dname, &clp->cl_name); | 600 | status = nfs4_make_rec_clidname(dname, &clp->cl_name); |
603 | if (status) { | 601 | if (status) { |
604 | legacy_recdir_name_error(status); | 602 | legacy_recdir_name_error(clp, status); |
605 | return status; | 603 | return status; |
606 | } | 604 | } |
607 | 605 | ||
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c index 5c4c61d527e2..357f613df7ff 100644 --- a/net/sunrpc/auth_gss/gss_rpc_xdr.c +++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c | |||
@@ -21,16 +21,6 @@ | |||
21 | #include <linux/sunrpc/svcauth.h> | 21 | #include <linux/sunrpc/svcauth.h> |
22 | #include "gss_rpc_xdr.h" | 22 | #include "gss_rpc_xdr.h" |
23 | 23 | ||
24 | static bool gssx_check_pointer(struct xdr_stream *xdr) | ||
25 | { | ||
26 | __be32 *p; | ||
27 | |||
28 | p = xdr_reserve_space(xdr, 4); | ||
29 | if (unlikely(p == NULL)) | ||
30 | return -ENOSPC; | ||
31 | return *p?true:false; | ||
32 | } | ||
33 | |||
34 | static int gssx_enc_bool(struct xdr_stream *xdr, int v) | 24 | static int gssx_enc_bool(struct xdr_stream *xdr, int v) |
35 | { | 25 | { |
36 | __be32 *p; | 26 | __be32 *p; |
@@ -264,25 +254,27 @@ static int gssx_dec_option_array(struct xdr_stream *xdr, | |||
264 | if (unlikely(p == NULL)) | 254 | if (unlikely(p == NULL)) |
265 | return -ENOSPC; | 255 | return -ENOSPC; |
266 | count = be32_to_cpup(p++); | 256 | count = be32_to_cpup(p++); |
267 | if (count != 0) { | 257 | if (!count) |
268 | /* we recognize only 1 currently: CREDS_VALUE */ | 258 | return 0; |
269 | oa->count = 1; | ||
270 | 259 | ||
271 | oa->data = kmalloc(sizeof(struct gssx_option), GFP_KERNEL); | 260 | /* we recognize only 1 currently: CREDS_VALUE */ |
272 | if (!oa->data) | 261 | oa->count = 1; |
273 | return -ENOMEM; | ||
274 | 262 | ||
275 | creds = kmalloc(sizeof(struct svc_cred), GFP_KERNEL); | 263 | oa->data = kmalloc(sizeof(struct gssx_option), GFP_KERNEL); |
276 | if (!creds) { | 264 | if (!oa->data) |
277 | kfree(oa->data); | 265 | return -ENOMEM; |
278 | return -ENOMEM; | ||
279 | } | ||
280 | 266 | ||
281 | oa->data[0].option.data = CREDS_VALUE; | 267 | creds = kmalloc(sizeof(struct svc_cred), GFP_KERNEL); |
282 | oa->data[0].option.len = sizeof(CREDS_VALUE); | 268 | if (!creds) { |
283 | oa->data[0].value.data = (void *)creds; | 269 | kfree(oa->data); |
284 | oa->data[0].value.len = 0; | 270 | return -ENOMEM; |
285 | } | 271 | } |
272 | |||
273 | oa->data[0].option.data = CREDS_VALUE; | ||
274 | oa->data[0].option.len = sizeof(CREDS_VALUE); | ||
275 | oa->data[0].value.data = (void *)creds; | ||
276 | oa->data[0].value.len = 0; | ||
277 | |||
286 | for (i = 0; i < count; i++) { | 278 | for (i = 0; i < count; i++) { |
287 | gssx_buffer dummy = { 0, NULL }; | 279 | gssx_buffer dummy = { 0, NULL }; |
288 | u32 length; | 280 | u32 length; |
@@ -800,6 +792,7 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, | |||
800 | struct xdr_stream *xdr, | 792 | struct xdr_stream *xdr, |
801 | struct gssx_res_accept_sec_context *res) | 793 | struct gssx_res_accept_sec_context *res) |
802 | { | 794 | { |
795 | u32 value_follows; | ||
803 | int err; | 796 | int err; |
804 | 797 | ||
805 | /* res->status */ | 798 | /* res->status */ |
@@ -808,7 +801,10 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, | |||
808 | return err; | 801 | return err; |
809 | 802 | ||
810 | /* res->context_handle */ | 803 | /* res->context_handle */ |
811 | if (gssx_check_pointer(xdr)) { | 804 | err = gssx_dec_bool(xdr, &value_follows); |
805 | if (err) | ||
806 | return err; | ||
807 | if (value_follows) { | ||
812 | err = gssx_dec_ctx(xdr, res->context_handle); | 808 | err = gssx_dec_ctx(xdr, res->context_handle); |
813 | if (err) | 809 | if (err) |
814 | return err; | 810 | return err; |
@@ -817,7 +813,10 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, | |||
817 | } | 813 | } |
818 | 814 | ||
819 | /* res->output_token */ | 815 | /* res->output_token */ |
820 | if (gssx_check_pointer(xdr)) { | 816 | err = gssx_dec_bool(xdr, &value_follows); |
817 | if (err) | ||
818 | return err; | ||
819 | if (value_follows) { | ||
821 | err = gssx_dec_buffer(xdr, res->output_token); | 820 | err = gssx_dec_buffer(xdr, res->output_token); |
822 | if (err) | 821 | if (err) |
823 | return err; | 822 | return err; |
@@ -826,7 +825,10 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, | |||
826 | } | 825 | } |
827 | 826 | ||
828 | /* res->delegated_cred_handle */ | 827 | /* res->delegated_cred_handle */ |
829 | if (gssx_check_pointer(xdr)) { | 828 | err = gssx_dec_bool(xdr, &value_follows); |
829 | if (err) | ||
830 | return err; | ||
831 | if (value_follows) { | ||
830 | /* we do not support upcall servers sending this data. */ | 832 | /* we do not support upcall servers sending this data. */ |
831 | return -EINVAL; | 833 | return -EINVAL; |
832 | } | 834 | } |