diff options
47 files changed, 2078 insertions, 1581 deletions
diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c index 214a2fa1f1e3..7df6324ccb8a 100644 --- a/fs/lockd/clnt4xdr.c +++ b/fs/lockd/clnt4xdr.c | |||
@@ -75,17 +75,6 @@ static void nlm4_compute_offsets(const struct nlm_lock *lock, | |||
75 | } | 75 | } |
76 | 76 | ||
77 | /* | 77 | /* |
78 | * Handle decode buffer overflows out-of-line. | ||
79 | */ | ||
80 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | ||
81 | { | ||
82 | dprintk("lockd: %s prematurely hit the end of our receive buffer. " | ||
83 | "Remaining buffer length is %tu words.\n", | ||
84 | func, xdr->end - xdr->p); | ||
85 | } | ||
86 | |||
87 | |||
88 | /* | ||
89 | * Encode/decode NLMv4 basic data types | 78 | * Encode/decode NLMv4 basic data types |
90 | * | 79 | * |
91 | * Basic NLMv4 data types are defined in Appendix II, section 6.1.4 | 80 | * Basic NLMv4 data types are defined in Appendix II, section 6.1.4 |
@@ -176,7 +165,6 @@ out_size: | |||
176 | dprintk("NFS: returned cookie was too long: %u\n", length); | 165 | dprintk("NFS: returned cookie was too long: %u\n", length); |
177 | return -EIO; | 166 | return -EIO; |
178 | out_overflow: | 167 | out_overflow: |
179 | print_overflow_msg(__func__, xdr); | ||
180 | return -EIO; | 168 | return -EIO; |
181 | } | 169 | } |
182 | 170 | ||
@@ -236,7 +224,6 @@ out_bad_xdr: | |||
236 | __func__, be32_to_cpup(p)); | 224 | __func__, be32_to_cpup(p)); |
237 | return -EIO; | 225 | return -EIO; |
238 | out_overflow: | 226 | out_overflow: |
239 | print_overflow_msg(__func__, xdr); | ||
240 | return -EIO; | 227 | return -EIO; |
241 | } | 228 | } |
242 | 229 | ||
@@ -309,7 +296,6 @@ static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result) | |||
309 | out: | 296 | out: |
310 | return error; | 297 | return error; |
311 | out_overflow: | 298 | out_overflow: |
312 | print_overflow_msg(__func__, xdr); | ||
313 | return -EIO; | 299 | return -EIO; |
314 | } | 300 | } |
315 | 301 | ||
diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c index 747b9c8c940a..4df62f635529 100644 --- a/fs/lockd/clntxdr.c +++ b/fs/lockd/clntxdr.c | |||
@@ -71,17 +71,6 @@ static void nlm_compute_offsets(const struct nlm_lock *lock, | |||
71 | } | 71 | } |
72 | 72 | ||
73 | /* | 73 | /* |
74 | * Handle decode buffer overflows out-of-line. | ||
75 | */ | ||
76 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | ||
77 | { | ||
78 | dprintk("lockd: %s prematurely hit the end of our receive buffer. " | ||
79 | "Remaining buffer length is %tu words.\n", | ||
80 | func, xdr->end - xdr->p); | ||
81 | } | ||
82 | |||
83 | |||
84 | /* | ||
85 | * Encode/decode NLMv3 basic data types | 74 | * Encode/decode NLMv3 basic data types |
86 | * | 75 | * |
87 | * Basic NLMv3 data types are not defined in an IETF standards | 76 | * Basic NLMv3 data types are not defined in an IETF standards |
@@ -173,7 +162,6 @@ out_size: | |||
173 | dprintk("NFS: returned cookie was too long: %u\n", length); | 162 | dprintk("NFS: returned cookie was too long: %u\n", length); |
174 | return -EIO; | 163 | return -EIO; |
175 | out_overflow: | 164 | out_overflow: |
176 | print_overflow_msg(__func__, xdr); | ||
177 | return -EIO; | 165 | return -EIO; |
178 | } | 166 | } |
179 | 167 | ||
@@ -231,7 +219,6 @@ out_enum: | |||
231 | __func__, be32_to_cpup(p)); | 219 | __func__, be32_to_cpup(p)); |
232 | return -EIO; | 220 | return -EIO; |
233 | out_overflow: | 221 | out_overflow: |
234 | print_overflow_msg(__func__, xdr); | ||
235 | return -EIO; | 222 | return -EIO; |
236 | } | 223 | } |
237 | 224 | ||
@@ -303,7 +290,6 @@ static int decode_nlm_holder(struct xdr_stream *xdr, struct nlm_res *result) | |||
303 | out: | 290 | out: |
304 | return error; | 291 | return error; |
305 | out_overflow: | 292 | out_overflow: |
306 | print_overflow_msg(__func__, xdr); | ||
307 | return -EIO; | 293 | return -EIO; |
308 | } | 294 | } |
309 | 295 | ||
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index a87a56273407..06233bfa6d73 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c | |||
@@ -72,16 +72,6 @@ static int nfs4_encode_void(struct svc_rqst *rqstp, __be32 *p) | |||
72 | return xdr_ressize_check(rqstp, p); | 72 | return xdr_ressize_check(rqstp, p); |
73 | } | 73 | } |
74 | 74 | ||
75 | static __be32 *read_buf(struct xdr_stream *xdr, size_t nbytes) | ||
76 | { | ||
77 | __be32 *p; | ||
78 | |||
79 | p = xdr_inline_decode(xdr, nbytes); | ||
80 | if (unlikely(p == NULL)) | ||
81 | printk(KERN_WARNING "NFS: NFSv4 callback reply buffer overflowed!\n"); | ||
82 | return p; | ||
83 | } | ||
84 | |||
85 | static __be32 decode_string(struct xdr_stream *xdr, unsigned int *len, | 75 | static __be32 decode_string(struct xdr_stream *xdr, unsigned int *len, |
86 | const char **str, size_t maxlen) | 76 | const char **str, size_t maxlen) |
87 | { | 77 | { |
@@ -98,13 +88,13 @@ static __be32 decode_fh(struct xdr_stream *xdr, struct nfs_fh *fh) | |||
98 | { | 88 | { |
99 | __be32 *p; | 89 | __be32 *p; |
100 | 90 | ||
101 | p = read_buf(xdr, 4); | 91 | p = xdr_inline_decode(xdr, 4); |
102 | if (unlikely(p == NULL)) | 92 | if (unlikely(p == NULL)) |
103 | return htonl(NFS4ERR_RESOURCE); | 93 | return htonl(NFS4ERR_RESOURCE); |
104 | fh->size = ntohl(*p); | 94 | fh->size = ntohl(*p); |
105 | if (fh->size > NFS4_FHSIZE) | 95 | if (fh->size > NFS4_FHSIZE) |
106 | return htonl(NFS4ERR_BADHANDLE); | 96 | return htonl(NFS4ERR_BADHANDLE); |
107 | p = read_buf(xdr, fh->size); | 97 | p = xdr_inline_decode(xdr, fh->size); |
108 | if (unlikely(p == NULL)) | 98 | if (unlikely(p == NULL)) |
109 | return htonl(NFS4ERR_RESOURCE); | 99 | return htonl(NFS4ERR_RESOURCE); |
110 | memcpy(&fh->data[0], p, fh->size); | 100 | memcpy(&fh->data[0], p, fh->size); |
@@ -117,11 +107,11 @@ static __be32 decode_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) | |||
117 | __be32 *p; | 107 | __be32 *p; |
118 | unsigned int attrlen; | 108 | unsigned int attrlen; |
119 | 109 | ||
120 | p = read_buf(xdr, 4); | 110 | p = xdr_inline_decode(xdr, 4); |
121 | if (unlikely(p == NULL)) | 111 | if (unlikely(p == NULL)) |
122 | return htonl(NFS4ERR_RESOURCE); | 112 | return htonl(NFS4ERR_RESOURCE); |
123 | attrlen = ntohl(*p); | 113 | attrlen = ntohl(*p); |
124 | p = read_buf(xdr, attrlen << 2); | 114 | p = xdr_inline_decode(xdr, attrlen << 2); |
125 | if (unlikely(p == NULL)) | 115 | if (unlikely(p == NULL)) |
126 | return htonl(NFS4ERR_RESOURCE); | 116 | return htonl(NFS4ERR_RESOURCE); |
127 | if (likely(attrlen > 0)) | 117 | if (likely(attrlen > 0)) |
@@ -135,7 +125,7 @@ static __be32 decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) | |||
135 | { | 125 | { |
136 | __be32 *p; | 126 | __be32 *p; |
137 | 127 | ||
138 | p = read_buf(xdr, NFS4_STATEID_SIZE); | 128 | p = xdr_inline_decode(xdr, NFS4_STATEID_SIZE); |
139 | if (unlikely(p == NULL)) | 129 | if (unlikely(p == NULL)) |
140 | return htonl(NFS4ERR_RESOURCE); | 130 | return htonl(NFS4ERR_RESOURCE); |
141 | memcpy(stateid->data, p, NFS4_STATEID_SIZE); | 131 | memcpy(stateid->data, p, NFS4_STATEID_SIZE); |
@@ -156,7 +146,7 @@ static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound | |||
156 | status = decode_string(xdr, &hdr->taglen, &hdr->tag, CB_OP_TAGLEN_MAXSZ); | 146 | status = decode_string(xdr, &hdr->taglen, &hdr->tag, CB_OP_TAGLEN_MAXSZ); |
157 | if (unlikely(status != 0)) | 147 | if (unlikely(status != 0)) |
158 | return status; | 148 | return status; |
159 | p = read_buf(xdr, 12); | 149 | p = xdr_inline_decode(xdr, 12); |
160 | if (unlikely(p == NULL)) | 150 | if (unlikely(p == NULL)) |
161 | return htonl(NFS4ERR_RESOURCE); | 151 | return htonl(NFS4ERR_RESOURCE); |
162 | hdr->minorversion = ntohl(*p++); | 152 | hdr->minorversion = ntohl(*p++); |
@@ -176,7 +166,7 @@ static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound | |||
176 | static __be32 decode_op_hdr(struct xdr_stream *xdr, unsigned int *op) | 166 | static __be32 decode_op_hdr(struct xdr_stream *xdr, unsigned int *op) |
177 | { | 167 | { |
178 | __be32 *p; | 168 | __be32 *p; |
179 | p = read_buf(xdr, 4); | 169 | p = xdr_inline_decode(xdr, 4); |
180 | if (unlikely(p == NULL)) | 170 | if (unlikely(p == NULL)) |
181 | return htonl(NFS4ERR_RESOURCE_HDR); | 171 | return htonl(NFS4ERR_RESOURCE_HDR); |
182 | *op = ntohl(*p); | 172 | *op = ntohl(*p); |
@@ -205,7 +195,7 @@ static __be32 decode_recall_args(struct svc_rqst *rqstp, | |||
205 | status = decode_delegation_stateid(xdr, &args->stateid); | 195 | status = decode_delegation_stateid(xdr, &args->stateid); |
206 | if (unlikely(status != 0)) | 196 | if (unlikely(status != 0)) |
207 | return status; | 197 | return status; |
208 | p = read_buf(xdr, 4); | 198 | p = xdr_inline_decode(xdr, 4); |
209 | if (unlikely(p == NULL)) | 199 | if (unlikely(p == NULL)) |
210 | return htonl(NFS4ERR_RESOURCE); | 200 | return htonl(NFS4ERR_RESOURCE); |
211 | args->truncate = ntohl(*p); | 201 | args->truncate = ntohl(*p); |
@@ -227,7 +217,7 @@ static __be32 decode_layoutrecall_args(struct svc_rqst *rqstp, | |||
227 | __be32 status = 0; | 217 | __be32 status = 0; |
228 | uint32_t iomode; | 218 | uint32_t iomode; |
229 | 219 | ||
230 | p = read_buf(xdr, 4 * sizeof(uint32_t)); | 220 | p = xdr_inline_decode(xdr, 4 * sizeof(uint32_t)); |
231 | if (unlikely(p == NULL)) | 221 | if (unlikely(p == NULL)) |
232 | return htonl(NFS4ERR_BADXDR); | 222 | return htonl(NFS4ERR_BADXDR); |
233 | 223 | ||
@@ -245,14 +235,14 @@ static __be32 decode_layoutrecall_args(struct svc_rqst *rqstp, | |||
245 | if (unlikely(status != 0)) | 235 | if (unlikely(status != 0)) |
246 | return status; | 236 | return status; |
247 | 237 | ||
248 | p = read_buf(xdr, 2 * sizeof(uint64_t)); | 238 | p = xdr_inline_decode(xdr, 2 * sizeof(uint64_t)); |
249 | if (unlikely(p == NULL)) | 239 | if (unlikely(p == NULL)) |
250 | return htonl(NFS4ERR_BADXDR); | 240 | return htonl(NFS4ERR_BADXDR); |
251 | p = xdr_decode_hyper(p, &args->cbl_range.offset); | 241 | p = xdr_decode_hyper(p, &args->cbl_range.offset); |
252 | p = xdr_decode_hyper(p, &args->cbl_range.length); | 242 | p = xdr_decode_hyper(p, &args->cbl_range.length); |
253 | return decode_layout_stateid(xdr, &args->cbl_stateid); | 243 | return decode_layout_stateid(xdr, &args->cbl_stateid); |
254 | } else if (args->cbl_recall_type == RETURN_FSID) { | 244 | } else if (args->cbl_recall_type == RETURN_FSID) { |
255 | p = read_buf(xdr, 2 * sizeof(uint64_t)); | 245 | p = xdr_inline_decode(xdr, 2 * sizeof(uint64_t)); |
256 | if (unlikely(p == NULL)) | 246 | if (unlikely(p == NULL)) |
257 | return htonl(NFS4ERR_BADXDR); | 247 | return htonl(NFS4ERR_BADXDR); |
258 | p = xdr_decode_hyper(p, &args->cbl_fsid.major); | 248 | p = xdr_decode_hyper(p, &args->cbl_fsid.major); |
@@ -275,7 +265,7 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp, | |||
275 | args->ndevs = 0; | 265 | args->ndevs = 0; |
276 | 266 | ||
277 | /* Num of device notifications */ | 267 | /* Num of device notifications */ |
278 | p = read_buf(xdr, sizeof(uint32_t)); | 268 | p = xdr_inline_decode(xdr, sizeof(uint32_t)); |
279 | if (unlikely(p == NULL)) { | 269 | if (unlikely(p == NULL)) { |
280 | status = htonl(NFS4ERR_BADXDR); | 270 | status = htonl(NFS4ERR_BADXDR); |
281 | goto out; | 271 | goto out; |
@@ -298,7 +288,8 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp, | |||
298 | for (i = 0; i < n; i++) { | 288 | for (i = 0; i < n; i++) { |
299 | struct cb_devicenotifyitem *dev = &args->devs[i]; | 289 | struct cb_devicenotifyitem *dev = &args->devs[i]; |
300 | 290 | ||
301 | p = read_buf(xdr, (4 * sizeof(uint32_t)) + NFS4_DEVICEID4_SIZE); | 291 | p = xdr_inline_decode(xdr, (4 * sizeof(uint32_t)) + |
292 | NFS4_DEVICEID4_SIZE); | ||
302 | if (unlikely(p == NULL)) { | 293 | if (unlikely(p == NULL)) { |
303 | status = htonl(NFS4ERR_BADXDR); | 294 | status = htonl(NFS4ERR_BADXDR); |
304 | goto err; | 295 | goto err; |
@@ -329,7 +320,7 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp, | |||
329 | p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE); | 320 | p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE); |
330 | 321 | ||
331 | if (dev->cbd_layout_type == NOTIFY_DEVICEID4_CHANGE) { | 322 | if (dev->cbd_layout_type == NOTIFY_DEVICEID4_CHANGE) { |
332 | p = read_buf(xdr, sizeof(uint32_t)); | 323 | p = xdr_inline_decode(xdr, sizeof(uint32_t)); |
333 | if (unlikely(p == NULL)) { | 324 | if (unlikely(p == NULL)) { |
334 | status = htonl(NFS4ERR_BADXDR); | 325 | status = htonl(NFS4ERR_BADXDR); |
335 | goto err; | 326 | goto err; |
@@ -359,7 +350,7 @@ static __be32 decode_sessionid(struct xdr_stream *xdr, | |||
359 | { | 350 | { |
360 | __be32 *p; | 351 | __be32 *p; |
361 | 352 | ||
362 | p = read_buf(xdr, NFS4_MAX_SESSIONID_LEN); | 353 | p = xdr_inline_decode(xdr, NFS4_MAX_SESSIONID_LEN); |
363 | if (unlikely(p == NULL)) | 354 | if (unlikely(p == NULL)) |
364 | return htonl(NFS4ERR_RESOURCE); | 355 | return htonl(NFS4ERR_RESOURCE); |
365 | 356 | ||
@@ -379,13 +370,13 @@ static __be32 decode_rc_list(struct xdr_stream *xdr, | |||
379 | goto out; | 370 | goto out; |
380 | 371 | ||
381 | status = htonl(NFS4ERR_RESOURCE); | 372 | status = htonl(NFS4ERR_RESOURCE); |
382 | p = read_buf(xdr, sizeof(uint32_t)); | 373 | p = xdr_inline_decode(xdr, sizeof(uint32_t)); |
383 | if (unlikely(p == NULL)) | 374 | if (unlikely(p == NULL)) |
384 | goto out; | 375 | goto out; |
385 | 376 | ||
386 | rc_list->rcl_nrefcalls = ntohl(*p++); | 377 | rc_list->rcl_nrefcalls = ntohl(*p++); |
387 | if (rc_list->rcl_nrefcalls) { | 378 | if (rc_list->rcl_nrefcalls) { |
388 | p = read_buf(xdr, | 379 | p = xdr_inline_decode(xdr, |
389 | rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t)); | 380 | rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t)); |
390 | if (unlikely(p == NULL)) | 381 | if (unlikely(p == NULL)) |
391 | goto out; | 382 | goto out; |
@@ -418,7 +409,7 @@ static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp, | |||
418 | if (status) | 409 | if (status) |
419 | return status; | 410 | return status; |
420 | 411 | ||
421 | p = read_buf(xdr, 5 * sizeof(uint32_t)); | 412 | p = xdr_inline_decode(xdr, 5 * sizeof(uint32_t)); |
422 | if (unlikely(p == NULL)) | 413 | if (unlikely(p == NULL)) |
423 | return htonl(NFS4ERR_RESOURCE); | 414 | return htonl(NFS4ERR_RESOURCE); |
424 | 415 | ||
@@ -461,7 +452,7 @@ static __be32 decode_recallany_args(struct svc_rqst *rqstp, | |||
461 | uint32_t bitmap[2]; | 452 | uint32_t bitmap[2]; |
462 | __be32 *p, status; | 453 | __be32 *p, status; |
463 | 454 | ||
464 | p = read_buf(xdr, 4); | 455 | p = xdr_inline_decode(xdr, 4); |
465 | if (unlikely(p == NULL)) | 456 | if (unlikely(p == NULL)) |
466 | return htonl(NFS4ERR_BADXDR); | 457 | return htonl(NFS4ERR_BADXDR); |
467 | args->craa_objs_to_keep = ntohl(*p++); | 458 | args->craa_objs_to_keep = ntohl(*p++); |
@@ -480,7 +471,7 @@ static __be32 decode_recallslot_args(struct svc_rqst *rqstp, | |||
480 | struct cb_recallslotargs *args = argp; | 471 | struct cb_recallslotargs *args = argp; |
481 | __be32 *p; | 472 | __be32 *p; |
482 | 473 | ||
483 | p = read_buf(xdr, 4); | 474 | p = xdr_inline_decode(xdr, 4); |
484 | if (unlikely(p == NULL)) | 475 | if (unlikely(p == NULL)) |
485 | return htonl(NFS4ERR_BADXDR); | 476 | return htonl(NFS4ERR_BADXDR); |
486 | args->crsa_target_highest_slotid = ntohl(*p++); | 477 | args->crsa_target_highest_slotid = ntohl(*p++); |
@@ -492,14 +483,14 @@ static __be32 decode_lockowner(struct xdr_stream *xdr, struct cb_notify_lock_arg | |||
492 | __be32 *p; | 483 | __be32 *p; |
493 | unsigned int len; | 484 | unsigned int len; |
494 | 485 | ||
495 | p = read_buf(xdr, 12); | 486 | p = xdr_inline_decode(xdr, 12); |
496 | if (unlikely(p == NULL)) | 487 | if (unlikely(p == NULL)) |
497 | return htonl(NFS4ERR_BADXDR); | 488 | return htonl(NFS4ERR_BADXDR); |
498 | 489 | ||
499 | p = xdr_decode_hyper(p, &args->cbnl_owner.clientid); | 490 | p = xdr_decode_hyper(p, &args->cbnl_owner.clientid); |
500 | len = be32_to_cpu(*p); | 491 | len = be32_to_cpu(*p); |
501 | 492 | ||
502 | p = read_buf(xdr, len); | 493 | p = xdr_inline_decode(xdr, len); |
503 | if (unlikely(p == NULL)) | 494 | if (unlikely(p == NULL)) |
504 | return htonl(NFS4ERR_BADXDR); | 495 | return htonl(NFS4ERR_BADXDR); |
505 | 496 | ||
@@ -537,7 +528,7 @@ static __be32 decode_write_response(struct xdr_stream *xdr, | |||
537 | __be32 *p; | 528 | __be32 *p; |
538 | 529 | ||
539 | /* skip the always zero field */ | 530 | /* skip the always zero field */ |
540 | p = read_buf(xdr, 4); | 531 | p = xdr_inline_decode(xdr, 4); |
541 | if (unlikely(!p)) | 532 | if (unlikely(!p)) |
542 | goto out; | 533 | goto out; |
543 | p++; | 534 | p++; |
@@ -577,7 +568,7 @@ static __be32 decode_offload_args(struct svc_rqst *rqstp, | |||
577 | return status; | 568 | return status; |
578 | 569 | ||
579 | /* decode status */ | 570 | /* decode status */ |
580 | p = read_buf(xdr, 4); | 571 | p = xdr_inline_decode(xdr, 4); |
581 | if (unlikely(!p)) | 572 | if (unlikely(!p)) |
582 | goto out; | 573 | goto out; |
583 | args->error = ntohl(*p++); | 574 | args->error = ntohl(*p++); |
@@ -943,10 +934,11 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp) | |||
943 | }; | 934 | }; |
944 | unsigned int nops = 0; | 935 | unsigned int nops = 0; |
945 | 936 | ||
946 | xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base); | 937 | xdr_init_decode(&xdr_in, &rqstp->rq_arg, |
938 | rqstp->rq_arg.head[0].iov_base, NULL); | ||
947 | 939 | ||
948 | p = (__be32*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len); | 940 | p = (__be32*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len); |
949 | xdr_init_encode(&xdr_out, &rqstp->rq_res, p); | 941 | xdr_init_encode(&xdr_out, &rqstp->rq_res, p, NULL); |
950 | 942 | ||
951 | status = decode_compound_hdr_arg(&xdr_in, &hdr_arg); | 943 | status = decode_compound_hdr_arg(&xdr_in, &hdr_arg); |
952 | if (status == htonl(NFS4ERR_RESOURCE)) | 944 | if (status == htonl(NFS4ERR_RESOURCE)) |
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index 63abe705f4ca..32701b6a9566 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c | |||
@@ -2036,7 +2036,7 @@ ff_layout_encode_layoutreturn(struct xdr_stream *xdr, | |||
2036 | 2036 | ||
2037 | dprintk("%s: Begin\n", __func__); | 2037 | dprintk("%s: Begin\n", __func__); |
2038 | 2038 | ||
2039 | xdr_init_encode(&tmp_xdr, &tmp_buf, NULL); | 2039 | xdr_init_encode(&tmp_xdr, &tmp_buf, NULL, NULL); |
2040 | 2040 | ||
2041 | ff_layout_encode_ioerr(&tmp_xdr, args, ff_args); | 2041 | ff_layout_encode_ioerr(&tmp_xdr, args, ff_args); |
2042 | ff_layout_encode_iostats_array(&tmp_xdr, args, ff_args); | 2042 | ff_layout_encode_iostats_array(&tmp_xdr, args, ff_args); |
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index 350675e3ed47..a7ed29de0a40 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/nfs.h> | 22 | #include <linux/nfs.h> |
23 | #include <linux/nfs2.h> | 23 | #include <linux/nfs2.h> |
24 | #include <linux/nfs_fs.h> | 24 | #include <linux/nfs_fs.h> |
25 | #include "nfstrace.h" | ||
25 | #include "internal.h" | 26 | #include "internal.h" |
26 | 27 | ||
27 | #define NFSDBG_FACILITY NFSDBG_XDR | 28 | #define NFSDBG_FACILITY NFSDBG_XDR |
@@ -55,42 +56,16 @@ | |||
55 | 56 | ||
56 | #define NFS_attrstat_sz (1+NFS_fattr_sz) | 57 | #define NFS_attrstat_sz (1+NFS_fattr_sz) |
57 | #define NFS_diropres_sz (1+NFS_fhandle_sz+NFS_fattr_sz) | 58 | #define NFS_diropres_sz (1+NFS_fhandle_sz+NFS_fattr_sz) |
58 | #define NFS_readlinkres_sz (2) | 59 | #define NFS_readlinkres_sz (2+1) |
59 | #define NFS_readres_sz (1+NFS_fattr_sz+1) | 60 | #define NFS_readres_sz (1+NFS_fattr_sz+1+1) |
60 | #define NFS_writeres_sz (NFS_attrstat_sz) | 61 | #define NFS_writeres_sz (NFS_attrstat_sz) |
61 | #define NFS_stat_sz (1) | 62 | #define NFS_stat_sz (1) |
62 | #define NFS_readdirres_sz (1) | 63 | #define NFS_readdirres_sz (1+1) |
63 | #define NFS_statfsres_sz (1+NFS_info_sz) | 64 | #define NFS_statfsres_sz (1+NFS_info_sz) |
64 | 65 | ||
65 | static int nfs_stat_to_errno(enum nfs_stat); | 66 | static int nfs_stat_to_errno(enum nfs_stat); |
66 | 67 | ||
67 | /* | 68 | /* |
68 | * While encoding arguments, set up the reply buffer in advance to | ||
69 | * receive reply data directly into the page cache. | ||
70 | */ | ||
71 | static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages, | ||
72 | unsigned int base, unsigned int len, | ||
73 | unsigned int bufsize) | ||
74 | { | ||
75 | struct rpc_auth *auth = req->rq_cred->cr_auth; | ||
76 | unsigned int replen; | ||
77 | |||
78 | replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize; | ||
79 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len); | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Handle decode buffer overflows out-of-line. | ||
84 | */ | ||
85 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | ||
86 | { | ||
87 | dprintk("NFS: %s prematurely hit the end of our receive buffer. " | ||
88 | "Remaining buffer length is %tu words.\n", | ||
89 | func, xdr->end - xdr->p); | ||
90 | } | ||
91 | |||
92 | |||
93 | /* | ||
94 | * Encode/decode NFSv2 basic data types | 69 | * Encode/decode NFSv2 basic data types |
95 | * | 70 | * |
96 | * Basic NFSv2 data types are defined in section 2.3 of RFC 1094: | 71 | * Basic NFSv2 data types are defined in section 2.3 of RFC 1094: |
@@ -110,8 +85,8 @@ static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_pgio_res *result) | |||
110 | __be32 *p; | 85 | __be32 *p; |
111 | 86 | ||
112 | p = xdr_inline_decode(xdr, 4); | 87 | p = xdr_inline_decode(xdr, 4); |
113 | if (unlikely(p == NULL)) | 88 | if (unlikely(!p)) |
114 | goto out_overflow; | 89 | return -EIO; |
115 | count = be32_to_cpup(p); | 90 | count = be32_to_cpup(p); |
116 | recvd = xdr_read_pages(xdr, count); | 91 | recvd = xdr_read_pages(xdr, count); |
117 | if (unlikely(count > recvd)) | 92 | if (unlikely(count > recvd)) |
@@ -125,9 +100,6 @@ out_cheating: | |||
125 | "count %u > recvd %u\n", count, recvd); | 100 | "count %u > recvd %u\n", count, recvd); |
126 | count = recvd; | 101 | count = recvd; |
127 | goto out; | 102 | goto out; |
128 | out_overflow: | ||
129 | print_overflow_msg(__func__, xdr); | ||
130 | return -EIO; | ||
131 | } | 103 | } |
132 | 104 | ||
133 | /* | 105 | /* |
@@ -157,13 +129,16 @@ static int decode_stat(struct xdr_stream *xdr, enum nfs_stat *status) | |||
157 | __be32 *p; | 129 | __be32 *p; |
158 | 130 | ||
159 | p = xdr_inline_decode(xdr, 4); | 131 | p = xdr_inline_decode(xdr, 4); |
160 | if (unlikely(p == NULL)) | 132 | if (unlikely(!p)) |
161 | goto out_overflow; | 133 | return -EIO; |
134 | if (unlikely(*p != cpu_to_be32(NFS_OK))) | ||
135 | goto out_status; | ||
136 | *status = 0; | ||
137 | return 0; | ||
138 | out_status: | ||
162 | *status = be32_to_cpup(p); | 139 | *status = be32_to_cpup(p); |
140 | trace_nfs_xdr_status((int)*status); | ||
163 | return 0; | 141 | return 0; |
164 | out_overflow: | ||
165 | print_overflow_msg(__func__, xdr); | ||
166 | return -EIO; | ||
167 | } | 142 | } |
168 | 143 | ||
169 | /* | 144 | /* |
@@ -205,14 +180,11 @@ static int decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh) | |||
205 | __be32 *p; | 180 | __be32 *p; |
206 | 181 | ||
207 | p = xdr_inline_decode(xdr, NFS2_FHSIZE); | 182 | p = xdr_inline_decode(xdr, NFS2_FHSIZE); |
208 | if (unlikely(p == NULL)) | 183 | if (unlikely(!p)) |
209 | goto out_overflow; | 184 | return -EIO; |
210 | fh->size = NFS2_FHSIZE; | 185 | fh->size = NFS2_FHSIZE; |
211 | memcpy(fh->data, p, NFS2_FHSIZE); | 186 | memcpy(fh->data, p, NFS2_FHSIZE); |
212 | return 0; | 187 | return 0; |
213 | out_overflow: | ||
214 | print_overflow_msg(__func__, xdr); | ||
215 | return -EIO; | ||
216 | } | 188 | } |
217 | 189 | ||
218 | /* | 190 | /* |
@@ -282,8 +254,8 @@ static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr) | |||
282 | __be32 *p; | 254 | __be32 *p; |
283 | 255 | ||
284 | p = xdr_inline_decode(xdr, NFS_fattr_sz << 2); | 256 | p = xdr_inline_decode(xdr, NFS_fattr_sz << 2); |
285 | if (unlikely(p == NULL)) | 257 | if (unlikely(!p)) |
286 | goto out_overflow; | 258 | return -EIO; |
287 | 259 | ||
288 | fattr->valid |= NFS_ATTR_FATTR_V2; | 260 | fattr->valid |= NFS_ATTR_FATTR_V2; |
289 | 261 | ||
@@ -325,9 +297,6 @@ out_uid: | |||
325 | out_gid: | 297 | out_gid: |
326 | dprintk("NFS: returned invalid gid\n"); | 298 | dprintk("NFS: returned invalid gid\n"); |
327 | return -EINVAL; | 299 | return -EINVAL; |
328 | out_overflow: | ||
329 | print_overflow_msg(__func__, xdr); | ||
330 | return -EIO; | ||
331 | } | 300 | } |
332 | 301 | ||
333 | /* | 302 | /* |
@@ -416,23 +385,20 @@ static int decode_filename_inline(struct xdr_stream *xdr, | |||
416 | u32 count; | 385 | u32 count; |
417 | 386 | ||
418 | p = xdr_inline_decode(xdr, 4); | 387 | p = xdr_inline_decode(xdr, 4); |
419 | if (unlikely(p == NULL)) | 388 | if (unlikely(!p)) |
420 | goto out_overflow; | 389 | return -EIO; |
421 | count = be32_to_cpup(p); | 390 | count = be32_to_cpup(p); |
422 | if (count > NFS3_MAXNAMLEN) | 391 | if (count > NFS3_MAXNAMLEN) |
423 | goto out_nametoolong; | 392 | goto out_nametoolong; |
424 | p = xdr_inline_decode(xdr, count); | 393 | p = xdr_inline_decode(xdr, count); |
425 | if (unlikely(p == NULL)) | 394 | if (unlikely(!p)) |
426 | goto out_overflow; | 395 | return -EIO; |
427 | *name = (const char *)p; | 396 | *name = (const char *)p; |
428 | *length = count; | 397 | *length = count; |
429 | return 0; | 398 | return 0; |
430 | out_nametoolong: | 399 | out_nametoolong: |
431 | dprintk("NFS: returned filename too long: %u\n", count); | 400 | dprintk("NFS: returned filename too long: %u\n", count); |
432 | return -ENAMETOOLONG; | 401 | return -ENAMETOOLONG; |
433 | out_overflow: | ||
434 | print_overflow_msg(__func__, xdr); | ||
435 | return -EIO; | ||
436 | } | 402 | } |
437 | 403 | ||
438 | /* | 404 | /* |
@@ -455,8 +421,8 @@ static int decode_path(struct xdr_stream *xdr) | |||
455 | __be32 *p; | 421 | __be32 *p; |
456 | 422 | ||
457 | p = xdr_inline_decode(xdr, 4); | 423 | p = xdr_inline_decode(xdr, 4); |
458 | if (unlikely(p == NULL)) | 424 | if (unlikely(!p)) |
459 | goto out_overflow; | 425 | return -EIO; |
460 | length = be32_to_cpup(p); | 426 | length = be32_to_cpup(p); |
461 | if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN)) | 427 | if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN)) |
462 | goto out_size; | 428 | goto out_size; |
@@ -472,9 +438,6 @@ out_cheating: | |||
472 | dprintk("NFS: server cheating in pathname result: " | 438 | dprintk("NFS: server cheating in pathname result: " |
473 | "length %u > received %u\n", length, recvd); | 439 | "length %u > received %u\n", length, recvd); |
474 | return -EIO; | 440 | return -EIO; |
475 | out_overflow: | ||
476 | print_overflow_msg(__func__, xdr); | ||
477 | return -EIO; | ||
478 | } | 441 | } |
479 | 442 | ||
480 | /* | 443 | /* |
@@ -615,8 +578,8 @@ static void nfs2_xdr_enc_readlinkargs(struct rpc_rqst *req, | |||
615 | const struct nfs_readlinkargs *args = data; | 578 | const struct nfs_readlinkargs *args = data; |
616 | 579 | ||
617 | encode_fhandle(xdr, args->fh); | 580 | encode_fhandle(xdr, args->fh); |
618 | prepare_reply_buffer(req, args->pages, args->pgbase, | 581 | rpc_prepare_reply_pages(req, args->pages, args->pgbase, |
619 | args->pglen, NFS_readlinkres_sz); | 582 | args->pglen, NFS_readlinkres_sz); |
620 | } | 583 | } |
621 | 584 | ||
622 | /* | 585 | /* |
@@ -651,8 +614,8 @@ static void nfs2_xdr_enc_readargs(struct rpc_rqst *req, | |||
651 | const struct nfs_pgio_args *args = data; | 614 | const struct nfs_pgio_args *args = data; |
652 | 615 | ||
653 | encode_readargs(xdr, args); | 616 | encode_readargs(xdr, args); |
654 | prepare_reply_buffer(req, args->pages, args->pgbase, | 617 | rpc_prepare_reply_pages(req, args->pages, args->pgbase, |
655 | args->count, NFS_readres_sz); | 618 | args->count, NFS_readres_sz); |
656 | req->rq_rcv_buf.flags |= XDRBUF_READ; | 619 | req->rq_rcv_buf.flags |= XDRBUF_READ; |
657 | } | 620 | } |
658 | 621 | ||
@@ -809,8 +772,8 @@ static void nfs2_xdr_enc_readdirargs(struct rpc_rqst *req, | |||
809 | const struct nfs_readdirargs *args = data; | 772 | const struct nfs_readdirargs *args = data; |
810 | 773 | ||
811 | encode_readdirargs(xdr, args); | 774 | encode_readdirargs(xdr, args); |
812 | prepare_reply_buffer(req, args->pages, 0, | 775 | rpc_prepare_reply_pages(req, args->pages, 0, |
813 | args->count, NFS_readdirres_sz); | 776 | args->count, NFS_readdirres_sz); |
814 | } | 777 | } |
815 | 778 | ||
816 | /* | 779 | /* |
@@ -951,12 +914,12 @@ int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
951 | int error; | 914 | int error; |
952 | 915 | ||
953 | p = xdr_inline_decode(xdr, 4); | 916 | p = xdr_inline_decode(xdr, 4); |
954 | if (unlikely(p == NULL)) | 917 | if (unlikely(!p)) |
955 | goto out_overflow; | 918 | return -EAGAIN; |
956 | if (*p++ == xdr_zero) { | 919 | if (*p++ == xdr_zero) { |
957 | p = xdr_inline_decode(xdr, 4); | 920 | p = xdr_inline_decode(xdr, 4); |
958 | if (unlikely(p == NULL)) | 921 | if (unlikely(!p)) |
959 | goto out_overflow; | 922 | return -EAGAIN; |
960 | if (*p++ == xdr_zero) | 923 | if (*p++ == xdr_zero) |
961 | return -EAGAIN; | 924 | return -EAGAIN; |
962 | entry->eof = 1; | 925 | entry->eof = 1; |
@@ -964,8 +927,8 @@ int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
964 | } | 927 | } |
965 | 928 | ||
966 | p = xdr_inline_decode(xdr, 4); | 929 | p = xdr_inline_decode(xdr, 4); |
967 | if (unlikely(p == NULL)) | 930 | if (unlikely(!p)) |
968 | goto out_overflow; | 931 | return -EAGAIN; |
969 | entry->ino = be32_to_cpup(p); | 932 | entry->ino = be32_to_cpup(p); |
970 | 933 | ||
971 | error = decode_filename_inline(xdr, &entry->name, &entry->len); | 934 | error = decode_filename_inline(xdr, &entry->name, &entry->len); |
@@ -978,17 +941,13 @@ int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
978 | */ | 941 | */ |
979 | entry->prev_cookie = entry->cookie; | 942 | entry->prev_cookie = entry->cookie; |
980 | p = xdr_inline_decode(xdr, 4); | 943 | p = xdr_inline_decode(xdr, 4); |
981 | if (unlikely(p == NULL)) | 944 | if (unlikely(!p)) |
982 | goto out_overflow; | 945 | return -EAGAIN; |
983 | entry->cookie = be32_to_cpup(p); | 946 | entry->cookie = be32_to_cpup(p); |
984 | 947 | ||
985 | entry->d_type = DT_UNKNOWN; | 948 | entry->d_type = DT_UNKNOWN; |
986 | 949 | ||
987 | return 0; | 950 | return 0; |
988 | |||
989 | out_overflow: | ||
990 | print_overflow_msg(__func__, xdr); | ||
991 | return -EAGAIN; | ||
992 | } | 951 | } |
993 | 952 | ||
994 | /* | 953 | /* |
@@ -1052,17 +1011,14 @@ static int decode_info(struct xdr_stream *xdr, struct nfs2_fsstat *result) | |||
1052 | __be32 *p; | 1011 | __be32 *p; |
1053 | 1012 | ||
1054 | p = xdr_inline_decode(xdr, NFS_info_sz << 2); | 1013 | p = xdr_inline_decode(xdr, NFS_info_sz << 2); |
1055 | if (unlikely(p == NULL)) | 1014 | if (unlikely(!p)) |
1056 | goto out_overflow; | 1015 | return -EIO; |
1057 | result->tsize = be32_to_cpup(p++); | 1016 | result->tsize = be32_to_cpup(p++); |
1058 | result->bsize = be32_to_cpup(p++); | 1017 | result->bsize = be32_to_cpup(p++); |
1059 | result->blocks = be32_to_cpup(p++); | 1018 | result->blocks = be32_to_cpup(p++); |
1060 | result->bfree = be32_to_cpup(p++); | 1019 | result->bfree = be32_to_cpup(p++); |
1061 | result->bavail = be32_to_cpup(p); | 1020 | result->bavail = be32_to_cpup(p); |
1062 | return 0; | 1021 | return 0; |
1063 | out_overflow: | ||
1064 | print_overflow_msg(__func__, xdr); | ||
1065 | return -EIO; | ||
1066 | } | 1022 | } |
1067 | 1023 | ||
1068 | static int nfs2_xdr_dec_statfsres(struct rpc_rqst *req, struct xdr_stream *xdr, | 1024 | static int nfs2_xdr_dec_statfsres(struct rpc_rqst *req, struct xdr_stream *xdr, |
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 78df4eb60f85..110358f4986d 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/nfs3.h> | 21 | #include <linux/nfs3.h> |
22 | #include <linux/nfs_fs.h> | 22 | #include <linux/nfs_fs.h> |
23 | #include <linux/nfsacl.h> | 23 | #include <linux/nfsacl.h> |
24 | #include "nfstrace.h" | ||
24 | #include "internal.h" | 25 | #include "internal.h" |
25 | 26 | ||
26 | #define NFSDBG_FACILITY NFSDBG_XDR | 27 | #define NFSDBG_FACILITY NFSDBG_XDR |
@@ -68,13 +69,13 @@ | |||
68 | #define NFS3_removeres_sz (NFS3_setattrres_sz) | 69 | #define NFS3_removeres_sz (NFS3_setattrres_sz) |
69 | #define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz)) | 70 | #define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz)) |
70 | #define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1) | 71 | #define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1) |
71 | #define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1) | 72 | #define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1+1) |
72 | #define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3) | 73 | #define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3+1) |
73 | #define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4) | 74 | #define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4) |
74 | #define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) | 75 | #define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) |
75 | #define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz)) | 76 | #define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz)) |
76 | #define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) | 77 | #define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) |
77 | #define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2) | 78 | #define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2+1) |
78 | #define NFS3_fsstatres_sz (1+NFS3_post_op_attr_sz+13) | 79 | #define NFS3_fsstatres_sz (1+NFS3_post_op_attr_sz+13) |
79 | #define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12) | 80 | #define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12) |
80 | #define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6) | 81 | #define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6) |
@@ -84,7 +85,7 @@ | |||
84 | #define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \ | 85 | #define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \ |
85 | XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE)) | 86 | XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE)) |
86 | #define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \ | 87 | #define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \ |
87 | XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE)) | 88 | XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE)+1) |
88 | #define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz) | 89 | #define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz) |
89 | 90 | ||
90 | static int nfs3_stat_to_errno(enum nfs_stat); | 91 | static int nfs3_stat_to_errno(enum nfs_stat); |
@@ -104,32 +105,6 @@ static const umode_t nfs_type2fmt[] = { | |||
104 | }; | 105 | }; |
105 | 106 | ||
106 | /* | 107 | /* |
107 | * While encoding arguments, set up the reply buffer in advance to | ||
108 | * receive reply data directly into the page cache. | ||
109 | */ | ||
110 | static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages, | ||
111 | unsigned int base, unsigned int len, | ||
112 | unsigned int bufsize) | ||
113 | { | ||
114 | struct rpc_auth *auth = req->rq_cred->cr_auth; | ||
115 | unsigned int replen; | ||
116 | |||
117 | replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize; | ||
118 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len); | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * Handle decode buffer overflows out-of-line. | ||
123 | */ | ||
124 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | ||
125 | { | ||
126 | dprintk("NFS: %s prematurely hit the end of our receive buffer. " | ||
127 | "Remaining buffer length is %tu words.\n", | ||
128 | func, xdr->end - xdr->p); | ||
129 | } | ||
130 | |||
131 | |||
132 | /* | ||
133 | * Encode/decode NFSv3 basic data types | 108 | * Encode/decode NFSv3 basic data types |
134 | * | 109 | * |
135 | * Basic NFSv3 data types are defined in section 2.5 of RFC 1813: | 110 | * Basic NFSv3 data types are defined in section 2.5 of RFC 1813: |
@@ -151,13 +126,10 @@ static int decode_uint32(struct xdr_stream *xdr, u32 *value) | |||
151 | __be32 *p; | 126 | __be32 *p; |
152 | 127 | ||
153 | p = xdr_inline_decode(xdr, 4); | 128 | p = xdr_inline_decode(xdr, 4); |
154 | if (unlikely(p == NULL)) | 129 | if (unlikely(!p)) |
155 | goto out_overflow; | 130 | return -EIO; |
156 | *value = be32_to_cpup(p); | 131 | *value = be32_to_cpup(p); |
157 | return 0; | 132 | return 0; |
158 | out_overflow: | ||
159 | print_overflow_msg(__func__, xdr); | ||
160 | return -EIO; | ||
161 | } | 133 | } |
162 | 134 | ||
163 | static int decode_uint64(struct xdr_stream *xdr, u64 *value) | 135 | static int decode_uint64(struct xdr_stream *xdr, u64 *value) |
@@ -165,13 +137,10 @@ static int decode_uint64(struct xdr_stream *xdr, u64 *value) | |||
165 | __be32 *p; | 137 | __be32 *p; |
166 | 138 | ||
167 | p = xdr_inline_decode(xdr, 8); | 139 | p = xdr_inline_decode(xdr, 8); |
168 | if (unlikely(p == NULL)) | 140 | if (unlikely(!p)) |
169 | goto out_overflow; | 141 | return -EIO; |
170 | xdr_decode_hyper(p, value); | 142 | xdr_decode_hyper(p, value); |
171 | return 0; | 143 | return 0; |
172 | out_overflow: | ||
173 | print_overflow_msg(__func__, xdr); | ||
174 | return -EIO; | ||
175 | } | 144 | } |
176 | 145 | ||
177 | /* | 146 | /* |
@@ -211,14 +180,14 @@ static int decode_inline_filename3(struct xdr_stream *xdr, | |||
211 | u32 count; | 180 | u32 count; |
212 | 181 | ||
213 | p = xdr_inline_decode(xdr, 4); | 182 | p = xdr_inline_decode(xdr, 4); |
214 | if (unlikely(p == NULL)) | 183 | if (unlikely(!p)) |
215 | goto out_overflow; | 184 | return -EIO; |
216 | count = be32_to_cpup(p); | 185 | count = be32_to_cpup(p); |
217 | if (count > NFS3_MAXNAMLEN) | 186 | if (count > NFS3_MAXNAMLEN) |
218 | goto out_nametoolong; | 187 | goto out_nametoolong; |
219 | p = xdr_inline_decode(xdr, count); | 188 | p = xdr_inline_decode(xdr, count); |
220 | if (unlikely(p == NULL)) | 189 | if (unlikely(!p)) |
221 | goto out_overflow; | 190 | return -EIO; |
222 | *name = (const char *)p; | 191 | *name = (const char *)p; |
223 | *length = count; | 192 | *length = count; |
224 | return 0; | 193 | return 0; |
@@ -226,9 +195,6 @@ static int decode_inline_filename3(struct xdr_stream *xdr, | |||
226 | out_nametoolong: | 195 | out_nametoolong: |
227 | dprintk("NFS: returned filename too long: %u\n", count); | 196 | dprintk("NFS: returned filename too long: %u\n", count); |
228 | return -ENAMETOOLONG; | 197 | return -ENAMETOOLONG; |
229 | out_overflow: | ||
230 | print_overflow_msg(__func__, xdr); | ||
231 | return -EIO; | ||
232 | } | 198 | } |
233 | 199 | ||
234 | /* | 200 | /* |
@@ -249,8 +215,8 @@ static int decode_nfspath3(struct xdr_stream *xdr) | |||
249 | __be32 *p; | 215 | __be32 *p; |
250 | 216 | ||
251 | p = xdr_inline_decode(xdr, 4); | 217 | p = xdr_inline_decode(xdr, 4); |
252 | if (unlikely(p == NULL)) | 218 | if (unlikely(!p)) |
253 | goto out_overflow; | 219 | return -EIO; |
254 | count = be32_to_cpup(p); | 220 | count = be32_to_cpup(p); |
255 | if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN)) | 221 | if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN)) |
256 | goto out_nametoolong; | 222 | goto out_nametoolong; |
@@ -267,9 +233,6 @@ out_cheating: | |||
267 | dprintk("NFS: server cheating in pathname result: " | 233 | dprintk("NFS: server cheating in pathname result: " |
268 | "count %u > recvd %u\n", count, recvd); | 234 | "count %u > recvd %u\n", count, recvd); |
269 | return -EIO; | 235 | return -EIO; |
270 | out_overflow: | ||
271 | print_overflow_msg(__func__, xdr); | ||
272 | return -EIO; | ||
273 | } | 236 | } |
274 | 237 | ||
275 | /* | 238 | /* |
@@ -303,13 +266,10 @@ static int decode_cookieverf3(struct xdr_stream *xdr, __be32 *verifier) | |||
303 | __be32 *p; | 266 | __be32 *p; |
304 | 267 | ||
305 | p = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE); | 268 | p = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE); |
306 | if (unlikely(p == NULL)) | 269 | if (unlikely(!p)) |
307 | goto out_overflow; | 270 | return -EIO; |
308 | memcpy(verifier, p, NFS3_COOKIEVERFSIZE); | 271 | memcpy(verifier, p, NFS3_COOKIEVERFSIZE); |
309 | return 0; | 272 | return 0; |
310 | out_overflow: | ||
311 | print_overflow_msg(__func__, xdr); | ||
312 | return -EIO; | ||
313 | } | 273 | } |
314 | 274 | ||
315 | /* | 275 | /* |
@@ -330,13 +290,10 @@ static int decode_writeverf3(struct xdr_stream *xdr, struct nfs_write_verifier * | |||
330 | __be32 *p; | 290 | __be32 *p; |
331 | 291 | ||
332 | p = xdr_inline_decode(xdr, NFS3_WRITEVERFSIZE); | 292 | p = xdr_inline_decode(xdr, NFS3_WRITEVERFSIZE); |
333 | if (unlikely(p == NULL)) | 293 | if (unlikely(!p)) |
334 | goto out_overflow; | 294 | return -EIO; |
335 | memcpy(verifier->data, p, NFS3_WRITEVERFSIZE); | 295 | memcpy(verifier->data, p, NFS3_WRITEVERFSIZE); |
336 | return 0; | 296 | return 0; |
337 | out_overflow: | ||
338 | print_overflow_msg(__func__, xdr); | ||
339 | return -EIO; | ||
340 | } | 297 | } |
341 | 298 | ||
342 | /* | 299 | /* |
@@ -364,13 +321,16 @@ static int decode_nfsstat3(struct xdr_stream *xdr, enum nfs_stat *status) | |||
364 | __be32 *p; | 321 | __be32 *p; |
365 | 322 | ||
366 | p = xdr_inline_decode(xdr, 4); | 323 | p = xdr_inline_decode(xdr, 4); |
367 | if (unlikely(p == NULL)) | 324 | if (unlikely(!p)) |
368 | goto out_overflow; | 325 | return -EIO; |
326 | if (unlikely(*p != cpu_to_be32(NFS3_OK))) | ||
327 | goto out_status; | ||
328 | *status = 0; | ||
329 | return 0; | ||
330 | out_status: | ||
369 | *status = be32_to_cpup(p); | 331 | *status = be32_to_cpup(p); |
332 | trace_nfs_xdr_status((int)*status); | ||
370 | return 0; | 333 | return 0; |
371 | out_overflow: | ||
372 | print_overflow_msg(__func__, xdr); | ||
373 | return -EIO; | ||
374 | } | 334 | } |
375 | 335 | ||
376 | /* | 336 | /* |
@@ -453,23 +413,20 @@ static int decode_nfs_fh3(struct xdr_stream *xdr, struct nfs_fh *fh) | |||
453 | __be32 *p; | 413 | __be32 *p; |
454 | 414 | ||
455 | p = xdr_inline_decode(xdr, 4); | 415 | p = xdr_inline_decode(xdr, 4); |
456 | if (unlikely(p == NULL)) | 416 | if (unlikely(!p)) |
457 | goto out_overflow; | 417 | return -EIO; |
458 | length = be32_to_cpup(p++); | 418 | length = be32_to_cpup(p++); |
459 | if (unlikely(length > NFS3_FHSIZE)) | 419 | if (unlikely(length > NFS3_FHSIZE)) |
460 | goto out_toobig; | 420 | goto out_toobig; |
461 | p = xdr_inline_decode(xdr, length); | 421 | p = xdr_inline_decode(xdr, length); |
462 | if (unlikely(p == NULL)) | 422 | if (unlikely(!p)) |
463 | goto out_overflow; | 423 | return -EIO; |
464 | fh->size = length; | 424 | fh->size = length; |
465 | memcpy(fh->data, p, length); | 425 | memcpy(fh->data, p, length); |
466 | return 0; | 426 | return 0; |
467 | out_toobig: | 427 | out_toobig: |
468 | dprintk("NFS: file handle size (%u) too big\n", length); | 428 | dprintk("NFS: file handle size (%u) too big\n", length); |
469 | return -E2BIG; | 429 | return -E2BIG; |
470 | out_overflow: | ||
471 | print_overflow_msg(__func__, xdr); | ||
472 | return -EIO; | ||
473 | } | 430 | } |
474 | 431 | ||
475 | static void zero_nfs_fh3(struct nfs_fh *fh) | 432 | static void zero_nfs_fh3(struct nfs_fh *fh) |
@@ -655,8 +612,8 @@ static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr) | |||
655 | __be32 *p; | 612 | __be32 *p; |
656 | 613 | ||
657 | p = xdr_inline_decode(xdr, NFS3_fattr_sz << 2); | 614 | p = xdr_inline_decode(xdr, NFS3_fattr_sz << 2); |
658 | if (unlikely(p == NULL)) | 615 | if (unlikely(!p)) |
659 | goto out_overflow; | 616 | return -EIO; |
660 | 617 | ||
661 | p = xdr_decode_ftype3(p, &fmode); | 618 | p = xdr_decode_ftype3(p, &fmode); |
662 | 619 | ||
@@ -690,9 +647,6 @@ out_uid: | |||
690 | out_gid: | 647 | out_gid: |
691 | dprintk("NFS: returned invalid gid\n"); | 648 | dprintk("NFS: returned invalid gid\n"); |
692 | return -EINVAL; | 649 | return -EINVAL; |
693 | out_overflow: | ||
694 | print_overflow_msg(__func__, xdr); | ||
695 | return -EIO; | ||
696 | } | 650 | } |
697 | 651 | ||
698 | /* | 652 | /* |
@@ -710,14 +664,11 @@ static int decode_post_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr) | |||
710 | __be32 *p; | 664 | __be32 *p; |
711 | 665 | ||
712 | p = xdr_inline_decode(xdr, 4); | 666 | p = xdr_inline_decode(xdr, 4); |
713 | if (unlikely(p == NULL)) | 667 | if (unlikely(!p)) |
714 | goto out_overflow; | 668 | return -EIO; |
715 | if (*p != xdr_zero) | 669 | if (*p != xdr_zero) |
716 | return decode_fattr3(xdr, fattr); | 670 | return decode_fattr3(xdr, fattr); |
717 | return 0; | 671 | return 0; |
718 | out_overflow: | ||
719 | print_overflow_msg(__func__, xdr); | ||
720 | return -EIO; | ||
721 | } | 672 | } |
722 | 673 | ||
723 | /* | 674 | /* |
@@ -733,8 +684,8 @@ static int decode_wcc_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr) | |||
733 | __be32 *p; | 684 | __be32 *p; |
734 | 685 | ||
735 | p = xdr_inline_decode(xdr, NFS3_wcc_attr_sz << 2); | 686 | p = xdr_inline_decode(xdr, NFS3_wcc_attr_sz << 2); |
736 | if (unlikely(p == NULL)) | 687 | if (unlikely(!p)) |
737 | goto out_overflow; | 688 | return -EIO; |
738 | 689 | ||
739 | fattr->valid |= NFS_ATTR_FATTR_PRESIZE | 690 | fattr->valid |= NFS_ATTR_FATTR_PRESIZE |
740 | | NFS_ATTR_FATTR_PRECHANGE | 691 | | NFS_ATTR_FATTR_PRECHANGE |
@@ -747,9 +698,6 @@ static int decode_wcc_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr) | |||
747 | fattr->pre_change_attr = nfs_timespec_to_change_attr(&fattr->pre_ctime); | 698 | fattr->pre_change_attr = nfs_timespec_to_change_attr(&fattr->pre_ctime); |
748 | 699 | ||
749 | return 0; | 700 | return 0; |
750 | out_overflow: | ||
751 | print_overflow_msg(__func__, xdr); | ||
752 | return -EIO; | ||
753 | } | 701 | } |
754 | 702 | ||
755 | /* | 703 | /* |
@@ -773,14 +721,11 @@ static int decode_pre_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr) | |||
773 | __be32 *p; | 721 | __be32 *p; |
774 | 722 | ||
775 | p = xdr_inline_decode(xdr, 4); | 723 | p = xdr_inline_decode(xdr, 4); |
776 | if (unlikely(p == NULL)) | 724 | if (unlikely(!p)) |
777 | goto out_overflow; | 725 | return -EIO; |
778 | if (*p != xdr_zero) | 726 | if (*p != xdr_zero) |
779 | return decode_wcc_attr(xdr, fattr); | 727 | return decode_wcc_attr(xdr, fattr); |
780 | return 0; | 728 | return 0; |
781 | out_overflow: | ||
782 | print_overflow_msg(__func__, xdr); | ||
783 | return -EIO; | ||
784 | } | 729 | } |
785 | 730 | ||
786 | static int decode_wcc_data(struct xdr_stream *xdr, struct nfs_fattr *fattr) | 731 | static int decode_wcc_data(struct xdr_stream *xdr, struct nfs_fattr *fattr) |
@@ -808,15 +753,12 @@ out: | |||
808 | static int decode_post_op_fh3(struct xdr_stream *xdr, struct nfs_fh *fh) | 753 | static int decode_post_op_fh3(struct xdr_stream *xdr, struct nfs_fh *fh) |
809 | { | 754 | { |
810 | __be32 *p = xdr_inline_decode(xdr, 4); | 755 | __be32 *p = xdr_inline_decode(xdr, 4); |
811 | if (unlikely(p == NULL)) | 756 | if (unlikely(!p)) |
812 | goto out_overflow; | 757 | return -EIO; |
813 | if (*p != xdr_zero) | 758 | if (*p != xdr_zero) |
814 | return decode_nfs_fh3(xdr, fh); | 759 | return decode_nfs_fh3(xdr, fh); |
815 | zero_nfs_fh3(fh); | 760 | zero_nfs_fh3(fh); |
816 | return 0; | 761 | return 0; |
817 | out_overflow: | ||
818 | print_overflow_msg(__func__, xdr); | ||
819 | return -EIO; | ||
820 | } | 762 | } |
821 | 763 | ||
822 | /* | 764 | /* |
@@ -953,8 +895,8 @@ static void nfs3_xdr_enc_readlink3args(struct rpc_rqst *req, | |||
953 | const struct nfs3_readlinkargs *args = data; | 895 | const struct nfs3_readlinkargs *args = data; |
954 | 896 | ||
955 | encode_nfs_fh3(xdr, args->fh); | 897 | encode_nfs_fh3(xdr, args->fh); |
956 | prepare_reply_buffer(req, args->pages, args->pgbase, | 898 | rpc_prepare_reply_pages(req, args->pages, args->pgbase, |
957 | args->pglen, NFS3_readlinkres_sz); | 899 | args->pglen, NFS3_readlinkres_sz); |
958 | } | 900 | } |
959 | 901 | ||
960 | /* | 902 | /* |
@@ -986,8 +928,8 @@ static void nfs3_xdr_enc_read3args(struct rpc_rqst *req, | |||
986 | unsigned int replen = args->replen ? args->replen : NFS3_readres_sz; | 928 | unsigned int replen = args->replen ? args->replen : NFS3_readres_sz; |
987 | 929 | ||
988 | encode_read3args(xdr, args); | 930 | encode_read3args(xdr, args); |
989 | prepare_reply_buffer(req, args->pages, args->pgbase, | 931 | rpc_prepare_reply_pages(req, args->pages, args->pgbase, |
990 | args->count, replen); | 932 | args->count, replen); |
991 | req->rq_rcv_buf.flags |= XDRBUF_READ; | 933 | req->rq_rcv_buf.flags |= XDRBUF_READ; |
992 | } | 934 | } |
993 | 935 | ||
@@ -1279,7 +1221,7 @@ static void nfs3_xdr_enc_readdir3args(struct rpc_rqst *req, | |||
1279 | const struct nfs3_readdirargs *args = data; | 1221 | const struct nfs3_readdirargs *args = data; |
1280 | 1222 | ||
1281 | encode_readdir3args(xdr, args); | 1223 | encode_readdir3args(xdr, args); |
1282 | prepare_reply_buffer(req, args->pages, 0, | 1224 | rpc_prepare_reply_pages(req, args->pages, 0, |
1283 | args->count, NFS3_readdirres_sz); | 1225 | args->count, NFS3_readdirres_sz); |
1284 | } | 1226 | } |
1285 | 1227 | ||
@@ -1321,7 +1263,7 @@ static void nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req, | |||
1321 | const struct nfs3_readdirargs *args = data; | 1263 | const struct nfs3_readdirargs *args = data; |
1322 | 1264 | ||
1323 | encode_readdirplus3args(xdr, args); | 1265 | encode_readdirplus3args(xdr, args); |
1324 | prepare_reply_buffer(req, args->pages, 0, | 1266 | rpc_prepare_reply_pages(req, args->pages, 0, |
1325 | args->count, NFS3_readdirres_sz); | 1267 | args->count, NFS3_readdirres_sz); |
1326 | } | 1268 | } |
1327 | 1269 | ||
@@ -1366,7 +1308,7 @@ static void nfs3_xdr_enc_getacl3args(struct rpc_rqst *req, | |||
1366 | encode_nfs_fh3(xdr, args->fh); | 1308 | encode_nfs_fh3(xdr, args->fh); |
1367 | encode_uint32(xdr, args->mask); | 1309 | encode_uint32(xdr, args->mask); |
1368 | if (args->mask & (NFS_ACL | NFS_DFACL)) { | 1310 | if (args->mask & (NFS_ACL | NFS_DFACL)) { |
1369 | prepare_reply_buffer(req, args->pages, 0, | 1311 | rpc_prepare_reply_pages(req, args->pages, 0, |
1370 | NFSACL_MAXPAGES << PAGE_SHIFT, | 1312 | NFSACL_MAXPAGES << PAGE_SHIFT, |
1371 | ACL3_getaclres_sz); | 1313 | ACL3_getaclres_sz); |
1372 | req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES; | 1314 | req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES; |
@@ -1643,8 +1585,8 @@ static int decode_read3resok(struct xdr_stream *xdr, | |||
1643 | __be32 *p; | 1585 | __be32 *p; |
1644 | 1586 | ||
1645 | p = xdr_inline_decode(xdr, 4 + 4 + 4); | 1587 | p = xdr_inline_decode(xdr, 4 + 4 + 4); |
1646 | if (unlikely(p == NULL)) | 1588 | if (unlikely(!p)) |
1647 | goto out_overflow; | 1589 | return -EIO; |
1648 | count = be32_to_cpup(p++); | 1590 | count = be32_to_cpup(p++); |
1649 | eof = be32_to_cpup(p++); | 1591 | eof = be32_to_cpup(p++); |
1650 | ocount = be32_to_cpup(p++); | 1592 | ocount = be32_to_cpup(p++); |
@@ -1667,9 +1609,6 @@ out_cheating: | |||
1667 | count = recvd; | 1609 | count = recvd; |
1668 | eof = 0; | 1610 | eof = 0; |
1669 | goto out; | 1611 | goto out; |
1670 | out_overflow: | ||
1671 | print_overflow_msg(__func__, xdr); | ||
1672 | return -EIO; | ||
1673 | } | 1612 | } |
1674 | 1613 | ||
1675 | static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr, | 1614 | static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr, |
@@ -1690,7 +1629,7 @@ static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
1690 | result->op_status = status; | 1629 | result->op_status = status; |
1691 | if (status != NFS3_OK) | 1630 | if (status != NFS3_OK) |
1692 | goto out_status; | 1631 | goto out_status; |
1693 | result->replen = 3 + ((xdr_stream_pos(xdr) - pos) >> 2); | 1632 | result->replen = 4 + ((xdr_stream_pos(xdr) - pos) >> 2); |
1694 | error = decode_read3resok(xdr, result); | 1633 | error = decode_read3resok(xdr, result); |
1695 | out: | 1634 | out: |
1696 | return error; | 1635 | return error; |
@@ -1731,22 +1670,18 @@ static int decode_write3resok(struct xdr_stream *xdr, | |||
1731 | __be32 *p; | 1670 | __be32 *p; |
1732 | 1671 | ||
1733 | p = xdr_inline_decode(xdr, 4 + 4); | 1672 | p = xdr_inline_decode(xdr, 4 + 4); |
1734 | if (unlikely(p == NULL)) | 1673 | if (unlikely(!p)) |
1735 | goto out_overflow; | 1674 | return -EIO; |
1736 | result->count = be32_to_cpup(p++); | 1675 | result->count = be32_to_cpup(p++); |
1737 | result->verf->committed = be32_to_cpup(p++); | 1676 | result->verf->committed = be32_to_cpup(p++); |
1738 | if (unlikely(result->verf->committed > NFS_FILE_SYNC)) | 1677 | if (unlikely(result->verf->committed > NFS_FILE_SYNC)) |
1739 | goto out_badvalue; | 1678 | goto out_badvalue; |
1740 | if (decode_writeverf3(xdr, &result->verf->verifier)) | 1679 | if (decode_writeverf3(xdr, &result->verf->verifier)) |
1741 | goto out_eio; | 1680 | return -EIO; |
1742 | return result->count; | 1681 | return result->count; |
1743 | out_badvalue: | 1682 | out_badvalue: |
1744 | dprintk("NFS: bad stable_how value: %u\n", result->verf->committed); | 1683 | dprintk("NFS: bad stable_how value: %u\n", result->verf->committed); |
1745 | return -EIO; | 1684 | return -EIO; |
1746 | out_overflow: | ||
1747 | print_overflow_msg(__func__, xdr); | ||
1748 | out_eio: | ||
1749 | return -EIO; | ||
1750 | } | 1685 | } |
1751 | 1686 | ||
1752 | static int nfs3_xdr_dec_write3res(struct rpc_rqst *req, struct xdr_stream *xdr, | 1687 | static int nfs3_xdr_dec_write3res(struct rpc_rqst *req, struct xdr_stream *xdr, |
@@ -2010,12 +1945,12 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
2010 | u64 new_cookie; | 1945 | u64 new_cookie; |
2011 | 1946 | ||
2012 | p = xdr_inline_decode(xdr, 4); | 1947 | p = xdr_inline_decode(xdr, 4); |
2013 | if (unlikely(p == NULL)) | 1948 | if (unlikely(!p)) |
2014 | goto out_overflow; | 1949 | return -EAGAIN; |
2015 | if (*p == xdr_zero) { | 1950 | if (*p == xdr_zero) { |
2016 | p = xdr_inline_decode(xdr, 4); | 1951 | p = xdr_inline_decode(xdr, 4); |
2017 | if (unlikely(p == NULL)) | 1952 | if (unlikely(!p)) |
2018 | goto out_overflow; | 1953 | return -EAGAIN; |
2019 | if (*p == xdr_zero) | 1954 | if (*p == xdr_zero) |
2020 | return -EAGAIN; | 1955 | return -EAGAIN; |
2021 | entry->eof = 1; | 1956 | entry->eof = 1; |
@@ -2051,8 +1986,8 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
2051 | 1986 | ||
2052 | /* In fact, a post_op_fh3: */ | 1987 | /* In fact, a post_op_fh3: */ |
2053 | p = xdr_inline_decode(xdr, 4); | 1988 | p = xdr_inline_decode(xdr, 4); |
2054 | if (unlikely(p == NULL)) | 1989 | if (unlikely(!p)) |
2055 | goto out_overflow; | 1990 | return -EAGAIN; |
2056 | if (*p != xdr_zero) { | 1991 | if (*p != xdr_zero) { |
2057 | error = decode_nfs_fh3(xdr, entry->fh); | 1992 | error = decode_nfs_fh3(xdr, entry->fh); |
2058 | if (unlikely(error)) { | 1993 | if (unlikely(error)) { |
@@ -2069,9 +2004,6 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
2069 | 2004 | ||
2070 | return 0; | 2005 | return 0; |
2071 | 2006 | ||
2072 | out_overflow: | ||
2073 | print_overflow_msg(__func__, xdr); | ||
2074 | return -EAGAIN; | ||
2075 | out_truncated: | 2007 | out_truncated: |
2076 | dprintk("NFS: directory entry contains invalid file handle\n"); | 2008 | dprintk("NFS: directory entry contains invalid file handle\n"); |
2077 | *entry = old; | 2009 | *entry = old; |
@@ -2183,8 +2115,8 @@ static int decode_fsstat3resok(struct xdr_stream *xdr, | |||
2183 | __be32 *p; | 2115 | __be32 *p; |
2184 | 2116 | ||
2185 | p = xdr_inline_decode(xdr, 8 * 6 + 4); | 2117 | p = xdr_inline_decode(xdr, 8 * 6 + 4); |
2186 | if (unlikely(p == NULL)) | 2118 | if (unlikely(!p)) |
2187 | goto out_overflow; | 2119 | return -EIO; |
2188 | p = xdr_decode_size3(p, &result->tbytes); | 2120 | p = xdr_decode_size3(p, &result->tbytes); |
2189 | p = xdr_decode_size3(p, &result->fbytes); | 2121 | p = xdr_decode_size3(p, &result->fbytes); |
2190 | p = xdr_decode_size3(p, &result->abytes); | 2122 | p = xdr_decode_size3(p, &result->abytes); |
@@ -2193,9 +2125,6 @@ static int decode_fsstat3resok(struct xdr_stream *xdr, | |||
2193 | xdr_decode_size3(p, &result->afiles); | 2125 | xdr_decode_size3(p, &result->afiles); |
2194 | /* ignore invarsec */ | 2126 | /* ignore invarsec */ |
2195 | return 0; | 2127 | return 0; |
2196 | out_overflow: | ||
2197 | print_overflow_msg(__func__, xdr); | ||
2198 | return -EIO; | ||
2199 | } | 2128 | } |
2200 | 2129 | ||
2201 | static int nfs3_xdr_dec_fsstat3res(struct rpc_rqst *req, | 2130 | static int nfs3_xdr_dec_fsstat3res(struct rpc_rqst *req, |
@@ -2255,8 +2184,8 @@ static int decode_fsinfo3resok(struct xdr_stream *xdr, | |||
2255 | __be32 *p; | 2184 | __be32 *p; |
2256 | 2185 | ||
2257 | p = xdr_inline_decode(xdr, 4 * 7 + 8 + 8 + 4); | 2186 | p = xdr_inline_decode(xdr, 4 * 7 + 8 + 8 + 4); |
2258 | if (unlikely(p == NULL)) | 2187 | if (unlikely(!p)) |
2259 | goto out_overflow; | 2188 | return -EIO; |
2260 | result->rtmax = be32_to_cpup(p++); | 2189 | result->rtmax = be32_to_cpup(p++); |
2261 | result->rtpref = be32_to_cpup(p++); | 2190 | result->rtpref = be32_to_cpup(p++); |
2262 | result->rtmult = be32_to_cpup(p++); | 2191 | result->rtmult = be32_to_cpup(p++); |
@@ -2270,9 +2199,6 @@ static int decode_fsinfo3resok(struct xdr_stream *xdr, | |||
2270 | /* ignore properties */ | 2199 | /* ignore properties */ |
2271 | result->lease_time = 0; | 2200 | result->lease_time = 0; |
2272 | return 0; | 2201 | return 0; |
2273 | out_overflow: | ||
2274 | print_overflow_msg(__func__, xdr); | ||
2275 | return -EIO; | ||
2276 | } | 2202 | } |
2277 | 2203 | ||
2278 | static int nfs3_xdr_dec_fsinfo3res(struct rpc_rqst *req, | 2204 | static int nfs3_xdr_dec_fsinfo3res(struct rpc_rqst *req, |
@@ -2328,15 +2254,12 @@ static int decode_pathconf3resok(struct xdr_stream *xdr, | |||
2328 | __be32 *p; | 2254 | __be32 *p; |
2329 | 2255 | ||
2330 | p = xdr_inline_decode(xdr, 4 * 6); | 2256 | p = xdr_inline_decode(xdr, 4 * 6); |
2331 | if (unlikely(p == NULL)) | 2257 | if (unlikely(!p)) |
2332 | goto out_overflow; | 2258 | return -EIO; |
2333 | result->max_link = be32_to_cpup(p++); | 2259 | result->max_link = be32_to_cpup(p++); |
2334 | result->max_namelen = be32_to_cpup(p); | 2260 | result->max_namelen = be32_to_cpup(p); |
2335 | /* ignore remaining fields */ | 2261 | /* ignore remaining fields */ |
2336 | return 0; | 2262 | return 0; |
2337 | out_overflow: | ||
2338 | print_overflow_msg(__func__, xdr); | ||
2339 | return -EIO; | ||
2340 | } | 2263 | } |
2341 | 2264 | ||
2342 | static int nfs3_xdr_dec_pathconf3res(struct rpc_rqst *req, | 2265 | static int nfs3_xdr_dec_pathconf3res(struct rpc_rqst *req, |
diff --git a/fs/nfs/nfs42xdr.c b/fs/nfs/nfs42xdr.c index 69f72ed2bf87..22b3425df08f 100644 --- a/fs/nfs/nfs42xdr.c +++ b/fs/nfs/nfs42xdr.c | |||
@@ -394,7 +394,7 @@ static int decode_write_response(struct xdr_stream *xdr, | |||
394 | 394 | ||
395 | p = xdr_inline_decode(xdr, 4); | 395 | p = xdr_inline_decode(xdr, 4); |
396 | if (unlikely(!p)) | 396 | if (unlikely(!p)) |
397 | goto out_overflow; | 397 | return -EIO; |
398 | count = be32_to_cpup(p); | 398 | count = be32_to_cpup(p); |
399 | if (count > 1) | 399 | if (count > 1) |
400 | return -EREMOTEIO; | 400 | return -EREMOTEIO; |
@@ -402,18 +402,14 @@ static int decode_write_response(struct xdr_stream *xdr, | |||
402 | status = decode_opaque_fixed(xdr, &res->stateid, | 402 | status = decode_opaque_fixed(xdr, &res->stateid, |
403 | NFS4_STATEID_SIZE); | 403 | NFS4_STATEID_SIZE); |
404 | if (unlikely(status)) | 404 | if (unlikely(status)) |
405 | goto out_overflow; | 405 | return -EIO; |
406 | } | 406 | } |
407 | p = xdr_inline_decode(xdr, 8 + 4); | 407 | p = xdr_inline_decode(xdr, 8 + 4); |
408 | if (unlikely(!p)) | 408 | if (unlikely(!p)) |
409 | goto out_overflow; | 409 | return -EIO; |
410 | p = xdr_decode_hyper(p, &res->count); | 410 | p = xdr_decode_hyper(p, &res->count); |
411 | res->verifier.committed = be32_to_cpup(p); | 411 | res->verifier.committed = be32_to_cpup(p); |
412 | return decode_verifier(xdr, &res->verifier.verifier); | 412 | return decode_verifier(xdr, &res->verifier.verifier); |
413 | |||
414 | out_overflow: | ||
415 | print_overflow_msg(__func__, xdr); | ||
416 | return -EIO; | ||
417 | } | 413 | } |
418 | 414 | ||
419 | static int decode_copy_requirements(struct xdr_stream *xdr, | 415 | static int decode_copy_requirements(struct xdr_stream *xdr, |
@@ -422,14 +418,11 @@ static int decode_copy_requirements(struct xdr_stream *xdr, | |||
422 | 418 | ||
423 | p = xdr_inline_decode(xdr, 4 + 4); | 419 | p = xdr_inline_decode(xdr, 4 + 4); |
424 | if (unlikely(!p)) | 420 | if (unlikely(!p)) |
425 | goto out_overflow; | 421 | return -EIO; |
426 | 422 | ||
427 | res->consecutive = be32_to_cpup(p++); | 423 | res->consecutive = be32_to_cpup(p++); |
428 | res->synchronous = be32_to_cpup(p++); | 424 | res->synchronous = be32_to_cpup(p++); |
429 | return 0; | 425 | return 0; |
430 | out_overflow: | ||
431 | print_overflow_msg(__func__, xdr); | ||
432 | return -EIO; | ||
433 | } | 426 | } |
434 | 427 | ||
435 | static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res) | 428 | static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res) |
@@ -474,15 +467,11 @@ static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res) | |||
474 | 467 | ||
475 | p = xdr_inline_decode(xdr, 4 + 8); | 468 | p = xdr_inline_decode(xdr, 4 + 8); |
476 | if (unlikely(!p)) | 469 | if (unlikely(!p)) |
477 | goto out_overflow; | 470 | return -EIO; |
478 | 471 | ||
479 | res->sr_eof = be32_to_cpup(p++); | 472 | res->sr_eof = be32_to_cpup(p++); |
480 | p = xdr_decode_hyper(p, &res->sr_offset); | 473 | p = xdr_decode_hyper(p, &res->sr_offset); |
481 | return 0; | 474 | return 0; |
482 | |||
483 | out_overflow: | ||
484 | print_overflow_msg(__func__, xdr); | ||
485 | return -EIO; | ||
486 | } | 475 | } |
487 | 476 | ||
488 | static int decode_layoutstats(struct xdr_stream *xdr) | 477 | static int decode_layoutstats(struct xdr_stream *xdr) |
diff --git a/fs/nfs/nfs4trace.h b/fs/nfs/nfs4trace.h index b4557cf685fb..cd1a5c08da9a 100644 --- a/fs/nfs/nfs4trace.h +++ b/fs/nfs/nfs4trace.h | |||
@@ -524,6 +524,31 @@ TRACE_EVENT(nfs4_setup_sequence, | |||
524 | ) | 524 | ) |
525 | ); | 525 | ); |
526 | 526 | ||
527 | TRACE_EVENT(nfs4_xdr_status, | ||
528 | TP_PROTO( | ||
529 | u32 op, | ||
530 | int error | ||
531 | ), | ||
532 | |||
533 | TP_ARGS(op, error), | ||
534 | |||
535 | TP_STRUCT__entry( | ||
536 | __field(u32, op) | ||
537 | __field(int, error) | ||
538 | ), | ||
539 | |||
540 | TP_fast_assign( | ||
541 | __entry->op = op; | ||
542 | __entry->error = -error; | ||
543 | ), | ||
544 | |||
545 | TP_printk( | ||
546 | "operation %d: nfs status %d (%s)", | ||
547 | __entry->op, | ||
548 | __entry->error, show_nfsv4_errors(__entry->error) | ||
549 | ) | ||
550 | ); | ||
551 | |||
527 | DECLARE_EVENT_CLASS(nfs4_open_event, | 552 | DECLARE_EVENT_CLASS(nfs4_open_event, |
528 | TP_PROTO( | 553 | TP_PROTO( |
529 | const struct nfs_open_context *ctx, | 554 | const struct nfs_open_context *ctx, |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 2fc8f6fa25e4..6d9d5e2f6308 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -54,6 +54,7 @@ | |||
54 | #include <linux/nfs_fs.h> | 54 | #include <linux/nfs_fs.h> |
55 | 55 | ||
56 | #include "nfs4_fs.h" | 56 | #include "nfs4_fs.h" |
57 | #include "nfs4trace.h" | ||
57 | #include "internal.h" | 58 | #include "internal.h" |
58 | #include "nfs4idmap.h" | 59 | #include "nfs4idmap.h" |
59 | #include "nfs4session.h" | 60 | #include "nfs4session.h" |
@@ -214,14 +215,14 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
214 | nfs4_fattr_bitmap_maxsz) | 215 | nfs4_fattr_bitmap_maxsz) |
215 | #define encode_read_maxsz (op_encode_hdr_maxsz + \ | 216 | #define encode_read_maxsz (op_encode_hdr_maxsz + \ |
216 | encode_stateid_maxsz + 3) | 217 | encode_stateid_maxsz + 3) |
217 | #define decode_read_maxsz (op_decode_hdr_maxsz + 2) | 218 | #define decode_read_maxsz (op_decode_hdr_maxsz + 2 + 1) |
218 | #define encode_readdir_maxsz (op_encode_hdr_maxsz + \ | 219 | #define encode_readdir_maxsz (op_encode_hdr_maxsz + \ |
219 | 2 + encode_verifier_maxsz + 5 + \ | 220 | 2 + encode_verifier_maxsz + 5 + \ |
220 | nfs4_label_maxsz) | 221 | nfs4_label_maxsz) |
221 | #define decode_readdir_maxsz (op_decode_hdr_maxsz + \ | 222 | #define decode_readdir_maxsz (op_decode_hdr_maxsz + \ |
222 | decode_verifier_maxsz) | 223 | decode_verifier_maxsz + 1) |
223 | #define encode_readlink_maxsz (op_encode_hdr_maxsz) | 224 | #define encode_readlink_maxsz (op_encode_hdr_maxsz) |
224 | #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1) | 225 | #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1 + 1) |
225 | #define encode_write_maxsz (op_encode_hdr_maxsz + \ | 226 | #define encode_write_maxsz (op_encode_hdr_maxsz + \ |
226 | encode_stateid_maxsz + 4) | 227 | encode_stateid_maxsz + 4) |
227 | #define decode_write_maxsz (op_decode_hdr_maxsz + \ | 228 | #define decode_write_maxsz (op_decode_hdr_maxsz + \ |
@@ -283,14 +284,14 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
283 | #define decode_delegreturn_maxsz (op_decode_hdr_maxsz) | 284 | #define decode_delegreturn_maxsz (op_decode_hdr_maxsz) |
284 | #define encode_getacl_maxsz (encode_getattr_maxsz) | 285 | #define encode_getacl_maxsz (encode_getattr_maxsz) |
285 | #define decode_getacl_maxsz (op_decode_hdr_maxsz + \ | 286 | #define decode_getacl_maxsz (op_decode_hdr_maxsz + \ |
286 | nfs4_fattr_bitmap_maxsz + 1) | 287 | nfs4_fattr_bitmap_maxsz + 1 + 1) |
287 | #define encode_setacl_maxsz (op_encode_hdr_maxsz + \ | 288 | #define encode_setacl_maxsz (op_encode_hdr_maxsz + \ |
288 | encode_stateid_maxsz + 3) | 289 | encode_stateid_maxsz + 3) |
289 | #define decode_setacl_maxsz (decode_setattr_maxsz) | 290 | #define decode_setacl_maxsz (decode_setattr_maxsz) |
290 | #define encode_fs_locations_maxsz \ | 291 | #define encode_fs_locations_maxsz \ |
291 | (encode_getattr_maxsz) | 292 | (encode_getattr_maxsz) |
292 | #define decode_fs_locations_maxsz \ | 293 | #define decode_fs_locations_maxsz \ |
293 | (0) | 294 | (1) |
294 | #define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) | 295 | #define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) |
295 | #define decode_secinfo_maxsz (op_decode_hdr_maxsz + 1 + ((NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)) / 4)) | 296 | #define decode_secinfo_maxsz (op_decode_hdr_maxsz + 1 + ((NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)) / 4)) |
296 | 297 | ||
@@ -391,12 +392,13 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
391 | 1 /* opaque devaddr4 length */ + \ | 392 | 1 /* opaque devaddr4 length */ + \ |
392 | /* devaddr4 payload is read into page */ \ | 393 | /* devaddr4 payload is read into page */ \ |
393 | 1 /* notification bitmap length */ + \ | 394 | 1 /* notification bitmap length */ + \ |
394 | 1 /* notification bitmap, word 0 */) | 395 | 1 /* notification bitmap, word 0 */ + \ |
396 | 1 /* possible XDR padding */) | ||
395 | #define encode_layoutget_maxsz (op_encode_hdr_maxsz + 10 + \ | 397 | #define encode_layoutget_maxsz (op_encode_hdr_maxsz + 10 + \ |
396 | encode_stateid_maxsz) | 398 | encode_stateid_maxsz) |
397 | #define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \ | 399 | #define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \ |
398 | decode_stateid_maxsz + \ | 400 | decode_stateid_maxsz + \ |
399 | XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE)) | 401 | XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE) + 1) |
400 | #define encode_layoutcommit_maxsz (op_encode_hdr_maxsz + \ | 402 | #define encode_layoutcommit_maxsz (op_encode_hdr_maxsz + \ |
401 | 2 /* offset */ + \ | 403 | 2 /* offset */ + \ |
402 | 2 /* length */ + \ | 404 | 2 /* length */ + \ |
@@ -1015,12 +1017,11 @@ static void encode_compound_hdr(struct xdr_stream *xdr, | |||
1015 | struct compound_hdr *hdr) | 1017 | struct compound_hdr *hdr) |
1016 | { | 1018 | { |
1017 | __be32 *p; | 1019 | __be32 *p; |
1018 | struct rpc_auth *auth = req->rq_cred->cr_auth; | ||
1019 | 1020 | ||
1020 | /* initialize running count of expected bytes in reply. | 1021 | /* initialize running count of expected bytes in reply. |
1021 | * NOTE: the replied tag SHOULD be the same is the one sent, | 1022 | * NOTE: the replied tag SHOULD be the same is the one sent, |
1022 | * but this is not required as a MUST for the server to do so. */ | 1023 | * but this is not required as a MUST for the server to do so. */ |
1023 | hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen; | 1024 | hdr->replen = 3 + hdr->taglen; |
1024 | 1025 | ||
1025 | WARN_ON_ONCE(hdr->taglen > NFS4_MAXTAGLEN); | 1026 | WARN_ON_ONCE(hdr->taglen > NFS4_MAXTAGLEN); |
1026 | encode_string(xdr, hdr->taglen, hdr->tag); | 1027 | encode_string(xdr, hdr->taglen, hdr->tag); |
@@ -2340,9 +2341,9 @@ static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
2340 | encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr); | 2341 | encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr); |
2341 | if (args->lg_args) { | 2342 | if (args->lg_args) { |
2342 | encode_layoutget(xdr, args->lg_args, &hdr); | 2343 | encode_layoutget(xdr, args->lg_args, &hdr); |
2343 | xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, | 2344 | rpc_prepare_reply_pages(req, args->lg_args->layout.pages, 0, |
2344 | args->lg_args->layout.pages, | 2345 | args->lg_args->layout.pglen, |
2345 | 0, args->lg_args->layout.pglen); | 2346 | hdr.replen); |
2346 | } | 2347 | } |
2347 | encode_nops(&hdr); | 2348 | encode_nops(&hdr); |
2348 | } | 2349 | } |
@@ -2386,9 +2387,9 @@ static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, | |||
2386 | encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr); | 2387 | encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr); |
2387 | if (args->lg_args) { | 2388 | if (args->lg_args) { |
2388 | encode_layoutget(xdr, args->lg_args, &hdr); | 2389 | encode_layoutget(xdr, args->lg_args, &hdr); |
2389 | xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, | 2390 | rpc_prepare_reply_pages(req, args->lg_args->layout.pages, 0, |
2390 | args->lg_args->layout.pages, | 2391 | args->lg_args->layout.pglen, |
2391 | 0, args->lg_args->layout.pglen); | 2392 | hdr.replen); |
2392 | } | 2393 | } |
2393 | encode_nops(&hdr); | 2394 | encode_nops(&hdr); |
2394 | } | 2395 | } |
@@ -2498,8 +2499,8 @@ static void nfs4_xdr_enc_readlink(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
2498 | encode_putfh(xdr, args->fh, &hdr); | 2499 | encode_putfh(xdr, args->fh, &hdr); |
2499 | encode_readlink(xdr, args, req, &hdr); | 2500 | encode_readlink(xdr, args, req, &hdr); |
2500 | 2501 | ||
2501 | xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages, | 2502 | rpc_prepare_reply_pages(req, args->pages, args->pgbase, |
2502 | args->pgbase, args->pglen); | 2503 | args->pglen, hdr.replen); |
2503 | encode_nops(&hdr); | 2504 | encode_nops(&hdr); |
2504 | } | 2505 | } |
2505 | 2506 | ||
@@ -2519,11 +2520,8 @@ static void nfs4_xdr_enc_readdir(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
2519 | encode_putfh(xdr, args->fh, &hdr); | 2520 | encode_putfh(xdr, args->fh, &hdr); |
2520 | encode_readdir(xdr, args, req, &hdr); | 2521 | encode_readdir(xdr, args, req, &hdr); |
2521 | 2522 | ||
2522 | xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages, | 2523 | rpc_prepare_reply_pages(req, args->pages, args->pgbase, |
2523 | args->pgbase, args->count); | 2524 | args->count, hdr.replen); |
2524 | dprintk("%s: inlined page args = (%u, %p, %u, %u)\n", | ||
2525 | __func__, hdr.replen << 2, args->pages, | ||
2526 | args->pgbase, args->count); | ||
2527 | encode_nops(&hdr); | 2525 | encode_nops(&hdr); |
2528 | } | 2526 | } |
2529 | 2527 | ||
@@ -2543,8 +2541,8 @@ static void nfs4_xdr_enc_read(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
2543 | encode_putfh(xdr, args->fh, &hdr); | 2541 | encode_putfh(xdr, args->fh, &hdr); |
2544 | encode_read(xdr, args, &hdr); | 2542 | encode_read(xdr, args, &hdr); |
2545 | 2543 | ||
2546 | xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, | 2544 | rpc_prepare_reply_pages(req, args->pages, args->pgbase, |
2547 | args->pages, args->pgbase, args->count); | 2545 | args->count, hdr.replen); |
2548 | req->rq_rcv_buf.flags |= XDRBUF_READ; | 2546 | req->rq_rcv_buf.flags |= XDRBUF_READ; |
2549 | encode_nops(&hdr); | 2547 | encode_nops(&hdr); |
2550 | } | 2548 | } |
@@ -2590,9 +2588,8 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
2590 | encode_getattr(xdr, nfs4_acl_bitmap, NULL, | 2588 | encode_getattr(xdr, nfs4_acl_bitmap, NULL, |
2591 | ARRAY_SIZE(nfs4_acl_bitmap), &hdr); | 2589 | ARRAY_SIZE(nfs4_acl_bitmap), &hdr); |
2592 | 2590 | ||
2593 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, | 2591 | rpc_prepare_reply_pages(req, args->acl_pages, 0, |
2594 | args->acl_pages, 0, args->acl_len); | 2592 | args->acl_len, replen); |
2595 | |||
2596 | encode_nops(&hdr); | 2593 | encode_nops(&hdr); |
2597 | } | 2594 | } |
2598 | 2595 | ||
@@ -2813,9 +2810,8 @@ static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, | |||
2813 | encode_fs_locations(xdr, args->bitmask, &hdr); | 2810 | encode_fs_locations(xdr, args->bitmask, &hdr); |
2814 | } | 2811 | } |
2815 | 2812 | ||
2816 | /* Set up reply kvec to capture returned fs_locations array. */ | 2813 | rpc_prepare_reply_pages(req, (struct page **)&args->page, 0, |
2817 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, | 2814 | PAGE_SIZE, replen); |
2818 | (struct page **)&args->page, 0, PAGE_SIZE); | ||
2819 | encode_nops(&hdr); | 2815 | encode_nops(&hdr); |
2820 | } | 2816 | } |
2821 | 2817 | ||
@@ -3017,10 +3013,8 @@ static void nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req, | |||
3017 | 3013 | ||
3018 | /* set up reply kvec. Subtract notification bitmap max size (2) | 3014 | /* set up reply kvec. Subtract notification bitmap max size (2) |
3019 | * so that notification bitmap is put in xdr_buf tail */ | 3015 | * so that notification bitmap is put in xdr_buf tail */ |
3020 | xdr_inline_pages(&req->rq_rcv_buf, (hdr.replen - 2) << 2, | 3016 | rpc_prepare_reply_pages(req, args->pdev->pages, args->pdev->pgbase, |
3021 | args->pdev->pages, args->pdev->pgbase, | 3017 | args->pdev->pglen, hdr.replen - 2); |
3022 | args->pdev->pglen); | ||
3023 | |||
3024 | encode_nops(&hdr); | 3018 | encode_nops(&hdr); |
3025 | } | 3019 | } |
3026 | 3020 | ||
@@ -3041,9 +3035,8 @@ static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req, | |||
3041 | encode_putfh(xdr, NFS_FH(args->inode), &hdr); | 3035 | encode_putfh(xdr, NFS_FH(args->inode), &hdr); |
3042 | encode_layoutget(xdr, args, &hdr); | 3036 | encode_layoutget(xdr, args, &hdr); |
3043 | 3037 | ||
3044 | xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, | 3038 | rpc_prepare_reply_pages(req, args->layout.pages, 0, |
3045 | args->layout.pages, 0, args->layout.pglen); | 3039 | args->layout.pglen, hdr.replen); |
3046 | |||
3047 | encode_nops(&hdr); | 3040 | encode_nops(&hdr); |
3048 | } | 3041 | } |
3049 | 3042 | ||
@@ -3144,22 +3137,12 @@ static void nfs4_xdr_enc_free_stateid(struct rpc_rqst *req, | |||
3144 | } | 3137 | } |
3145 | #endif /* CONFIG_NFS_V4_1 */ | 3138 | #endif /* CONFIG_NFS_V4_1 */ |
3146 | 3139 | ||
3147 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | ||
3148 | { | ||
3149 | dprintk("nfs: %s: prematurely hit end of receive buffer. " | ||
3150 | "Remaining buffer length is %tu words.\n", | ||
3151 | func, xdr->end - xdr->p); | ||
3152 | } | ||
3153 | |||
3154 | static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string) | 3140 | static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string) |
3155 | { | 3141 | { |
3156 | ssize_t ret = xdr_stream_decode_opaque_inline(xdr, (void **)string, | 3142 | ssize_t ret = xdr_stream_decode_opaque_inline(xdr, (void **)string, |
3157 | NFS4_OPAQUE_LIMIT); | 3143 | NFS4_OPAQUE_LIMIT); |
3158 | if (unlikely(ret < 0)) { | 3144 | if (unlikely(ret < 0)) |
3159 | if (ret == -EBADMSG) | ||
3160 | print_overflow_msg(__func__, xdr); | ||
3161 | return -EIO; | 3145 | return -EIO; |
3162 | } | ||
3163 | *len = ret; | 3146 | *len = ret; |
3164 | return 0; | 3147 | return 0; |
3165 | } | 3148 | } |
@@ -3170,22 +3153,19 @@ static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) | |||
3170 | 3153 | ||
3171 | p = xdr_inline_decode(xdr, 8); | 3154 | p = xdr_inline_decode(xdr, 8); |
3172 | if (unlikely(!p)) | 3155 | if (unlikely(!p)) |
3173 | goto out_overflow; | 3156 | return -EIO; |
3174 | hdr->status = be32_to_cpup(p++); | 3157 | hdr->status = be32_to_cpup(p++); |
3175 | hdr->taglen = be32_to_cpup(p); | 3158 | hdr->taglen = be32_to_cpup(p); |
3176 | 3159 | ||
3177 | p = xdr_inline_decode(xdr, hdr->taglen + 4); | 3160 | p = xdr_inline_decode(xdr, hdr->taglen + 4); |
3178 | if (unlikely(!p)) | 3161 | if (unlikely(!p)) |
3179 | goto out_overflow; | 3162 | return -EIO; |
3180 | hdr->tag = (char *)p; | 3163 | hdr->tag = (char *)p; |
3181 | p += XDR_QUADLEN(hdr->taglen); | 3164 | p += XDR_QUADLEN(hdr->taglen); |
3182 | hdr->nops = be32_to_cpup(p); | 3165 | hdr->nops = be32_to_cpup(p); |
3183 | if (unlikely(hdr->nops < 1)) | 3166 | if (unlikely(hdr->nops < 1)) |
3184 | return nfs4_stat_to_errno(hdr->status); | 3167 | return nfs4_stat_to_errno(hdr->status); |
3185 | return 0; | 3168 | return 0; |
3186 | out_overflow: | ||
3187 | print_overflow_msg(__func__, xdr); | ||
3188 | return -EIO; | ||
3189 | } | 3169 | } |
3190 | 3170 | ||
3191 | static bool __decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected, | 3171 | static bool __decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected, |
@@ -3201,11 +3181,14 @@ static bool __decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected, | |||
3201 | opnum = be32_to_cpup(p++); | 3181 | opnum = be32_to_cpup(p++); |
3202 | if (unlikely(opnum != expected)) | 3182 | if (unlikely(opnum != expected)) |
3203 | goto out_bad_operation; | 3183 | goto out_bad_operation; |
3184 | if (unlikely(*p != cpu_to_be32(NFS_OK))) | ||
3185 | goto out_status; | ||
3186 | *nfs_retval = 0; | ||
3187 | return true; | ||
3188 | out_status: | ||
3204 | nfserr = be32_to_cpup(p); | 3189 | nfserr = be32_to_cpup(p); |
3205 | if (nfserr == NFS_OK) | 3190 | trace_nfs4_xdr_status(opnum, nfserr); |
3206 | *nfs_retval = 0; | 3191 | *nfs_retval = nfs4_stat_to_errno(nfserr); |
3207 | else | ||
3208 | *nfs_retval = nfs4_stat_to_errno(nfserr); | ||
3209 | return true; | 3192 | return true; |
3210 | out_bad_operation: | 3193 | out_bad_operation: |
3211 | dprintk("nfs: Server returned operation" | 3194 | dprintk("nfs: Server returned operation" |
@@ -3214,7 +3197,6 @@ out_bad_operation: | |||
3214 | *nfs_retval = -EREMOTEIO; | 3197 | *nfs_retval = -EREMOTEIO; |
3215 | return false; | 3198 | return false; |
3216 | out_overflow: | 3199 | out_overflow: |
3217 | print_overflow_msg(__func__, xdr); | ||
3218 | *nfs_retval = -EIO; | 3200 | *nfs_retval = -EIO; |
3219 | return false; | 3201 | return false; |
3220 | } | 3202 | } |
@@ -3235,10 +3217,9 @@ static int decode_ace(struct xdr_stream *xdr, void *ace) | |||
3235 | char *str; | 3217 | char *str; |
3236 | 3218 | ||
3237 | p = xdr_inline_decode(xdr, 12); | 3219 | p = xdr_inline_decode(xdr, 12); |
3238 | if (likely(p)) | 3220 | if (unlikely(!p)) |
3239 | return decode_opaque_inline(xdr, &strlen, &str); | 3221 | return -EIO; |
3240 | print_overflow_msg(__func__, xdr); | 3222 | return decode_opaque_inline(xdr, &strlen, &str); |
3241 | return -EIO; | ||
3242 | } | 3223 | } |
3243 | 3224 | ||
3244 | static ssize_t | 3225 | static ssize_t |
@@ -3249,10 +3230,9 @@ decode_bitmap4(struct xdr_stream *xdr, uint32_t *bitmap, size_t sz) | |||
3249 | ret = xdr_stream_decode_uint32_array(xdr, bitmap, sz); | 3230 | ret = xdr_stream_decode_uint32_array(xdr, bitmap, sz); |
3250 | if (likely(ret >= 0)) | 3231 | if (likely(ret >= 0)) |
3251 | return ret; | 3232 | return ret; |
3252 | if (ret == -EMSGSIZE) | 3233 | if (ret != -EMSGSIZE) |
3253 | return sz; | 3234 | return -EIO; |
3254 | print_overflow_msg(__func__, xdr); | 3235 | return sz; |
3255 | return -EIO; | ||
3256 | } | 3236 | } |
3257 | 3237 | ||
3258 | static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) | 3238 | static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) |
@@ -3268,13 +3248,10 @@ static int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, unsigne | |||
3268 | 3248 | ||
3269 | p = xdr_inline_decode(xdr, 4); | 3249 | p = xdr_inline_decode(xdr, 4); |
3270 | if (unlikely(!p)) | 3250 | if (unlikely(!p)) |
3271 | goto out_overflow; | 3251 | return -EIO; |
3272 | *attrlen = be32_to_cpup(p); | 3252 | *attrlen = be32_to_cpup(p); |
3273 | *savep = xdr_stream_pos(xdr); | 3253 | *savep = xdr_stream_pos(xdr); |
3274 | return 0; | 3254 | return 0; |
3275 | out_overflow: | ||
3276 | print_overflow_msg(__func__, xdr); | ||
3277 | return -EIO; | ||
3278 | } | 3255 | } |
3279 | 3256 | ||
3280 | static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask) | 3257 | static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask) |
@@ -3303,7 +3280,7 @@ static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t * | |||
3303 | if (likely(bitmap[0] & FATTR4_WORD0_TYPE)) { | 3280 | if (likely(bitmap[0] & FATTR4_WORD0_TYPE)) { |
3304 | p = xdr_inline_decode(xdr, 4); | 3281 | p = xdr_inline_decode(xdr, 4); |
3305 | if (unlikely(!p)) | 3282 | if (unlikely(!p)) |
3306 | goto out_overflow; | 3283 | return -EIO; |
3307 | *type = be32_to_cpup(p); | 3284 | *type = be32_to_cpup(p); |
3308 | if (*type < NF4REG || *type > NF4NAMEDATTR) { | 3285 | if (*type < NF4REG || *type > NF4NAMEDATTR) { |
3309 | dprintk("%s: bad type %d\n", __func__, *type); | 3286 | dprintk("%s: bad type %d\n", __func__, *type); |
@@ -3314,9 +3291,6 @@ static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t * | |||
3314 | } | 3291 | } |
3315 | dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type]); | 3292 | dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type]); |
3316 | return ret; | 3293 | return ret; |
3317 | out_overflow: | ||
3318 | print_overflow_msg(__func__, xdr); | ||
3319 | return -EIO; | ||
3320 | } | 3294 | } |
3321 | 3295 | ||
3322 | static int decode_attr_fh_expire_type(struct xdr_stream *xdr, | 3296 | static int decode_attr_fh_expire_type(struct xdr_stream *xdr, |
@@ -3330,15 +3304,12 @@ static int decode_attr_fh_expire_type(struct xdr_stream *xdr, | |||
3330 | if (likely(bitmap[0] & FATTR4_WORD0_FH_EXPIRE_TYPE)) { | 3304 | if (likely(bitmap[0] & FATTR4_WORD0_FH_EXPIRE_TYPE)) { |
3331 | p = xdr_inline_decode(xdr, 4); | 3305 | p = xdr_inline_decode(xdr, 4); |
3332 | if (unlikely(!p)) | 3306 | if (unlikely(!p)) |
3333 | goto out_overflow; | 3307 | return -EIO; |
3334 | *type = be32_to_cpup(p); | 3308 | *type = be32_to_cpup(p); |
3335 | bitmap[0] &= ~FATTR4_WORD0_FH_EXPIRE_TYPE; | 3309 | bitmap[0] &= ~FATTR4_WORD0_FH_EXPIRE_TYPE; |
3336 | } | 3310 | } |
3337 | dprintk("%s: expire type=0x%x\n", __func__, *type); | 3311 | dprintk("%s: expire type=0x%x\n", __func__, *type); |
3338 | return 0; | 3312 | return 0; |
3339 | out_overflow: | ||
3340 | print_overflow_msg(__func__, xdr); | ||
3341 | return -EIO; | ||
3342 | } | 3313 | } |
3343 | 3314 | ||
3344 | static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change) | 3315 | static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change) |
@@ -3352,7 +3323,7 @@ static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t | |||
3352 | if (likely(bitmap[0] & FATTR4_WORD0_CHANGE)) { | 3323 | if (likely(bitmap[0] & FATTR4_WORD0_CHANGE)) { |
3353 | p = xdr_inline_decode(xdr, 8); | 3324 | p = xdr_inline_decode(xdr, 8); |
3354 | if (unlikely(!p)) | 3325 | if (unlikely(!p)) |
3355 | goto out_overflow; | 3326 | return -EIO; |
3356 | xdr_decode_hyper(p, change); | 3327 | xdr_decode_hyper(p, change); |
3357 | bitmap[0] &= ~FATTR4_WORD0_CHANGE; | 3328 | bitmap[0] &= ~FATTR4_WORD0_CHANGE; |
3358 | ret = NFS_ATTR_FATTR_CHANGE; | 3329 | ret = NFS_ATTR_FATTR_CHANGE; |
@@ -3360,9 +3331,6 @@ static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t | |||
3360 | dprintk("%s: change attribute=%Lu\n", __func__, | 3331 | dprintk("%s: change attribute=%Lu\n", __func__, |
3361 | (unsigned long long)*change); | 3332 | (unsigned long long)*change); |
3362 | return ret; | 3333 | return ret; |
3363 | out_overflow: | ||
3364 | print_overflow_msg(__func__, xdr); | ||
3365 | return -EIO; | ||
3366 | } | 3334 | } |
3367 | 3335 | ||
3368 | static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size) | 3336 | static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size) |
@@ -3376,16 +3344,13 @@ static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t * | |||
3376 | if (likely(bitmap[0] & FATTR4_WORD0_SIZE)) { | 3344 | if (likely(bitmap[0] & FATTR4_WORD0_SIZE)) { |
3377 | p = xdr_inline_decode(xdr, 8); | 3345 | p = xdr_inline_decode(xdr, 8); |
3378 | if (unlikely(!p)) | 3346 | if (unlikely(!p)) |
3379 | goto out_overflow; | 3347 | return -EIO; |
3380 | xdr_decode_hyper(p, size); | 3348 | xdr_decode_hyper(p, size); |
3381 | bitmap[0] &= ~FATTR4_WORD0_SIZE; | 3349 | bitmap[0] &= ~FATTR4_WORD0_SIZE; |
3382 | ret = NFS_ATTR_FATTR_SIZE; | 3350 | ret = NFS_ATTR_FATTR_SIZE; |
3383 | } | 3351 | } |
3384 | dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size); | 3352 | dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size); |
3385 | return ret; | 3353 | return ret; |
3386 | out_overflow: | ||
3387 | print_overflow_msg(__func__, xdr); | ||
3388 | return -EIO; | ||
3389 | } | 3354 | } |
3390 | 3355 | ||
3391 | static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) | 3356 | static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) |
@@ -3398,15 +3363,12 @@ static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, ui | |||
3398 | if (likely(bitmap[0] & FATTR4_WORD0_LINK_SUPPORT)) { | 3363 | if (likely(bitmap[0] & FATTR4_WORD0_LINK_SUPPORT)) { |
3399 | p = xdr_inline_decode(xdr, 4); | 3364 | p = xdr_inline_decode(xdr, 4); |
3400 | if (unlikely(!p)) | 3365 | if (unlikely(!p)) |
3401 | goto out_overflow; | 3366 | return -EIO; |
3402 | *res = be32_to_cpup(p); | 3367 | *res = be32_to_cpup(p); |
3403 | bitmap[0] &= ~FATTR4_WORD0_LINK_SUPPORT; | 3368 | bitmap[0] &= ~FATTR4_WORD0_LINK_SUPPORT; |
3404 | } | 3369 | } |
3405 | dprintk("%s: link support=%s\n", __func__, *res == 0 ? "false" : "true"); | 3370 | dprintk("%s: link support=%s\n", __func__, *res == 0 ? "false" : "true"); |
3406 | return 0; | 3371 | return 0; |
3407 | out_overflow: | ||
3408 | print_overflow_msg(__func__, xdr); | ||
3409 | return -EIO; | ||
3410 | } | 3372 | } |
3411 | 3373 | ||
3412 | static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) | 3374 | static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) |
@@ -3419,15 +3381,12 @@ static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, | |||
3419 | if (likely(bitmap[0] & FATTR4_WORD0_SYMLINK_SUPPORT)) { | 3381 | if (likely(bitmap[0] & FATTR4_WORD0_SYMLINK_SUPPORT)) { |
3420 | p = xdr_inline_decode(xdr, 4); | 3382 | p = xdr_inline_decode(xdr, 4); |
3421 | if (unlikely(!p)) | 3383 | if (unlikely(!p)) |
3422 | goto out_overflow; | 3384 | return -EIO; |
3423 | *res = be32_to_cpup(p); | 3385 | *res = be32_to_cpup(p); |
3424 | bitmap[0] &= ~FATTR4_WORD0_SYMLINK_SUPPORT; | 3386 | bitmap[0] &= ~FATTR4_WORD0_SYMLINK_SUPPORT; |
3425 | } | 3387 | } |
3426 | dprintk("%s: symlink support=%s\n", __func__, *res == 0 ? "false" : "true"); | 3388 | dprintk("%s: symlink support=%s\n", __func__, *res == 0 ? "false" : "true"); |
3427 | return 0; | 3389 | return 0; |
3428 | out_overflow: | ||
3429 | print_overflow_msg(__func__, xdr); | ||
3430 | return -EIO; | ||
3431 | } | 3390 | } |
3432 | 3391 | ||
3433 | static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid) | 3392 | static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid) |
@@ -3442,7 +3401,7 @@ static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs | |||
3442 | if (likely(bitmap[0] & FATTR4_WORD0_FSID)) { | 3401 | if (likely(bitmap[0] & FATTR4_WORD0_FSID)) { |
3443 | p = xdr_inline_decode(xdr, 16); | 3402 | p = xdr_inline_decode(xdr, 16); |
3444 | if (unlikely(!p)) | 3403 | if (unlikely(!p)) |
3445 | goto out_overflow; | 3404 | return -EIO; |
3446 | p = xdr_decode_hyper(p, &fsid->major); | 3405 | p = xdr_decode_hyper(p, &fsid->major); |
3447 | xdr_decode_hyper(p, &fsid->minor); | 3406 | xdr_decode_hyper(p, &fsid->minor); |
3448 | bitmap[0] &= ~FATTR4_WORD0_FSID; | 3407 | bitmap[0] &= ~FATTR4_WORD0_FSID; |
@@ -3452,9 +3411,6 @@ static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs | |||
3452 | (unsigned long long)fsid->major, | 3411 | (unsigned long long)fsid->major, |
3453 | (unsigned long long)fsid->minor); | 3412 | (unsigned long long)fsid->minor); |
3454 | return ret; | 3413 | return ret; |
3455 | out_overflow: | ||
3456 | print_overflow_msg(__func__, xdr); | ||
3457 | return -EIO; | ||
3458 | } | 3414 | } |
3459 | 3415 | ||
3460 | static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) | 3416 | static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) |
@@ -3467,15 +3423,12 @@ static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint | |||
3467 | if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) { | 3423 | if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) { |
3468 | p = xdr_inline_decode(xdr, 4); | 3424 | p = xdr_inline_decode(xdr, 4); |
3469 | if (unlikely(!p)) | 3425 | if (unlikely(!p)) |
3470 | goto out_overflow; | 3426 | return -EIO; |
3471 | *res = be32_to_cpup(p); | 3427 | *res = be32_to_cpup(p); |
3472 | bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME; | 3428 | bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME; |
3473 | } | 3429 | } |
3474 | dprintk("%s: file size=%u\n", __func__, (unsigned int)*res); | 3430 | dprintk("%s: file size=%u\n", __func__, (unsigned int)*res); |
3475 | return 0; | 3431 | return 0; |
3476 | out_overflow: | ||
3477 | print_overflow_msg(__func__, xdr); | ||
3478 | return -EIO; | ||
3479 | } | 3432 | } |
3480 | 3433 | ||
3481 | static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *res) | 3434 | static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *res) |
@@ -3487,14 +3440,11 @@ static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t * | |||
3487 | if (likely(bitmap[0] & FATTR4_WORD0_RDATTR_ERROR)) { | 3440 | if (likely(bitmap[0] & FATTR4_WORD0_RDATTR_ERROR)) { |
3488 | p = xdr_inline_decode(xdr, 4); | 3441 | p = xdr_inline_decode(xdr, 4); |
3489 | if (unlikely(!p)) | 3442 | if (unlikely(!p)) |
3490 | goto out_overflow; | 3443 | return -EIO; |
3491 | bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; | 3444 | bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; |
3492 | *res = -be32_to_cpup(p); | 3445 | *res = -be32_to_cpup(p); |
3493 | } | 3446 | } |
3494 | return 0; | 3447 | return 0; |
3495 | out_overflow: | ||
3496 | print_overflow_msg(__func__, xdr); | ||
3497 | return -EIO; | ||
3498 | } | 3448 | } |
3499 | 3449 | ||
3500 | static int decode_attr_exclcreat_supported(struct xdr_stream *xdr, | 3450 | static int decode_attr_exclcreat_supported(struct xdr_stream *xdr, |
@@ -3526,13 +3476,13 @@ static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, stru | |||
3526 | if (likely(bitmap[0] & FATTR4_WORD0_FILEHANDLE)) { | 3476 | if (likely(bitmap[0] & FATTR4_WORD0_FILEHANDLE)) { |
3527 | p = xdr_inline_decode(xdr, 4); | 3477 | p = xdr_inline_decode(xdr, 4); |
3528 | if (unlikely(!p)) | 3478 | if (unlikely(!p)) |
3529 | goto out_overflow; | 3479 | return -EIO; |
3530 | len = be32_to_cpup(p); | 3480 | len = be32_to_cpup(p); |
3531 | if (len > NFS4_FHSIZE) | 3481 | if (len > NFS4_FHSIZE) |
3532 | return -EIO; | 3482 | return -EIO; |
3533 | p = xdr_inline_decode(xdr, len); | 3483 | p = xdr_inline_decode(xdr, len); |
3534 | if (unlikely(!p)) | 3484 | if (unlikely(!p)) |
3535 | goto out_overflow; | 3485 | return -EIO; |
3536 | if (fh != NULL) { | 3486 | if (fh != NULL) { |
3537 | memcpy(fh->data, p, len); | 3487 | memcpy(fh->data, p, len); |
3538 | fh->size = len; | 3488 | fh->size = len; |
@@ -3540,9 +3490,6 @@ static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, stru | |||
3540 | bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE; | 3490 | bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE; |
3541 | } | 3491 | } |
3542 | return 0; | 3492 | return 0; |
3543 | out_overflow: | ||
3544 | print_overflow_msg(__func__, xdr); | ||
3545 | return -EIO; | ||
3546 | } | 3493 | } |
3547 | 3494 | ||
3548 | static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) | 3495 | static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) |
@@ -3555,15 +3502,12 @@ static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint | |||
3555 | if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) { | 3502 | if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) { |
3556 | p = xdr_inline_decode(xdr, 4); | 3503 | p = xdr_inline_decode(xdr, 4); |
3557 | if (unlikely(!p)) | 3504 | if (unlikely(!p)) |
3558 | goto out_overflow; | 3505 | return -EIO; |
3559 | *res = be32_to_cpup(p); | 3506 | *res = be32_to_cpup(p); |
3560 | bitmap[0] &= ~FATTR4_WORD0_ACLSUPPORT; | 3507 | bitmap[0] &= ~FATTR4_WORD0_ACLSUPPORT; |
3561 | } | 3508 | } |
3562 | dprintk("%s: ACLs supported=%u\n", __func__, (unsigned int)*res); | 3509 | dprintk("%s: ACLs supported=%u\n", __func__, (unsigned int)*res); |
3563 | return 0; | 3510 | return 0; |
3564 | out_overflow: | ||
3565 | print_overflow_msg(__func__, xdr); | ||
3566 | return -EIO; | ||
3567 | } | 3511 | } |
3568 | 3512 | ||
3569 | static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) | 3513 | static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) |
@@ -3577,16 +3521,13 @@ static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t | |||
3577 | if (likely(bitmap[0] & FATTR4_WORD0_FILEID)) { | 3521 | if (likely(bitmap[0] & FATTR4_WORD0_FILEID)) { |
3578 | p = xdr_inline_decode(xdr, 8); | 3522 | p = xdr_inline_decode(xdr, 8); |
3579 | if (unlikely(!p)) | 3523 | if (unlikely(!p)) |
3580 | goto out_overflow; | 3524 | return -EIO; |
3581 | xdr_decode_hyper(p, fileid); | 3525 | xdr_decode_hyper(p, fileid); |
3582 | bitmap[0] &= ~FATTR4_WORD0_FILEID; | 3526 | bitmap[0] &= ~FATTR4_WORD0_FILEID; |
3583 | ret = NFS_ATTR_FATTR_FILEID; | 3527 | ret = NFS_ATTR_FATTR_FILEID; |
3584 | } | 3528 | } |
3585 | dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); | 3529 | dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); |
3586 | return ret; | 3530 | return ret; |
3587 | out_overflow: | ||
3588 | print_overflow_msg(__func__, xdr); | ||
3589 | return -EIO; | ||
3590 | } | 3531 | } |
3591 | 3532 | ||
3592 | static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) | 3533 | static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) |
@@ -3600,16 +3541,13 @@ static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitma | |||
3600 | if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) { | 3541 | if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) { |
3601 | p = xdr_inline_decode(xdr, 8); | 3542 | p = xdr_inline_decode(xdr, 8); |
3602 | if (unlikely(!p)) | 3543 | if (unlikely(!p)) |
3603 | goto out_overflow; | 3544 | return -EIO; |
3604 | xdr_decode_hyper(p, fileid); | 3545 | xdr_decode_hyper(p, fileid); |
3605 | bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; | 3546 | bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; |
3606 | ret = NFS_ATTR_FATTR_MOUNTED_ON_FILEID; | 3547 | ret = NFS_ATTR_FATTR_MOUNTED_ON_FILEID; |
3607 | } | 3548 | } |
3608 | dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); | 3549 | dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); |
3609 | return ret; | 3550 | return ret; |
3610 | out_overflow: | ||
3611 | print_overflow_msg(__func__, xdr); | ||
3612 | return -EIO; | ||
3613 | } | 3551 | } |
3614 | 3552 | ||
3615 | static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) | 3553 | static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) |
@@ -3623,15 +3561,12 @@ static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uin | |||
3623 | if (likely(bitmap[0] & FATTR4_WORD0_FILES_AVAIL)) { | 3561 | if (likely(bitmap[0] & FATTR4_WORD0_FILES_AVAIL)) { |
3624 | p = xdr_inline_decode(xdr, 8); | 3562 | p = xdr_inline_decode(xdr, 8); |
3625 | if (unlikely(!p)) | 3563 | if (unlikely(!p)) |
3626 | goto out_overflow; | 3564 | return -EIO; |
3627 | xdr_decode_hyper(p, res); | 3565 | xdr_decode_hyper(p, res); |
3628 | bitmap[0] &= ~FATTR4_WORD0_FILES_AVAIL; | 3566 | bitmap[0] &= ~FATTR4_WORD0_FILES_AVAIL; |
3629 | } | 3567 | } |
3630 | dprintk("%s: files avail=%Lu\n", __func__, (unsigned long long)*res); | 3568 | dprintk("%s: files avail=%Lu\n", __func__, (unsigned long long)*res); |
3631 | return status; | 3569 | return status; |
3632 | out_overflow: | ||
3633 | print_overflow_msg(__func__, xdr); | ||
3634 | return -EIO; | ||
3635 | } | 3570 | } |
3636 | 3571 | ||
3637 | static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) | 3572 | static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) |
@@ -3645,15 +3580,12 @@ static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint | |||
3645 | if (likely(bitmap[0] & FATTR4_WORD0_FILES_FREE)) { | 3580 | if (likely(bitmap[0] & FATTR4_WORD0_FILES_FREE)) { |
3646 | p = xdr_inline_decode(xdr, 8); | 3581 | p = xdr_inline_decode(xdr, 8); |
3647 | if (unlikely(!p)) | 3582 | if (unlikely(!p)) |
3648 | goto out_overflow; | 3583 | return -EIO; |
3649 | xdr_decode_hyper(p, res); | 3584 | xdr_decode_hyper(p, res); |
3650 | bitmap[0] &= ~FATTR4_WORD0_FILES_FREE; | 3585 | bitmap[0] &= ~FATTR4_WORD0_FILES_FREE; |
3651 | } | 3586 | } |
3652 | dprintk("%s: files free=%Lu\n", __func__, (unsigned long long)*res); | 3587 | dprintk("%s: files free=%Lu\n", __func__, (unsigned long long)*res); |
3653 | return status; | 3588 | return status; |
3654 | out_overflow: | ||
3655 | print_overflow_msg(__func__, xdr); | ||
3656 | return -EIO; | ||
3657 | } | 3589 | } |
3658 | 3590 | ||
3659 | static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) | 3591 | static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) |
@@ -3667,15 +3599,12 @@ static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uin | |||
3667 | if (likely(bitmap[0] & FATTR4_WORD0_FILES_TOTAL)) { | 3599 | if (likely(bitmap[0] & FATTR4_WORD0_FILES_TOTAL)) { |
3668 | p = xdr_inline_decode(xdr, 8); | 3600 | p = xdr_inline_decode(xdr, 8); |
3669 | if (unlikely(!p)) | 3601 | if (unlikely(!p)) |
3670 | goto out_overflow; | 3602 | return -EIO; |
3671 | xdr_decode_hyper(p, res); | 3603 | xdr_decode_hyper(p, res); |
3672 | bitmap[0] &= ~FATTR4_WORD0_FILES_TOTAL; | 3604 | bitmap[0] &= ~FATTR4_WORD0_FILES_TOTAL; |
3673 | } | 3605 | } |
3674 | dprintk("%s: files total=%Lu\n", __func__, (unsigned long long)*res); | 3606 | dprintk("%s: files total=%Lu\n", __func__, (unsigned long long)*res); |
3675 | return status; | 3607 | return status; |
3676 | out_overflow: | ||
3677 | print_overflow_msg(__func__, xdr); | ||
3678 | return -EIO; | ||
3679 | } | 3608 | } |
3680 | 3609 | ||
3681 | static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path) | 3610 | static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path) |
@@ -3686,7 +3615,7 @@ static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path) | |||
3686 | 3615 | ||
3687 | p = xdr_inline_decode(xdr, 4); | 3616 | p = xdr_inline_decode(xdr, 4); |
3688 | if (unlikely(!p)) | 3617 | if (unlikely(!p)) |
3689 | goto out_overflow; | 3618 | return -EIO; |
3690 | n = be32_to_cpup(p); | 3619 | n = be32_to_cpup(p); |
3691 | if (n == 0) | 3620 | if (n == 0) |
3692 | goto root_path; | 3621 | goto root_path; |
@@ -3718,9 +3647,6 @@ out_eio: | |||
3718 | dprintk(" status %d", status); | 3647 | dprintk(" status %d", status); |
3719 | status = -EIO; | 3648 | status = -EIO; |
3720 | goto out; | 3649 | goto out; |
3721 | out_overflow: | ||
3722 | print_overflow_msg(__func__, xdr); | ||
3723 | return -EIO; | ||
3724 | } | 3650 | } |
3725 | 3651 | ||
3726 | static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res) | 3652 | static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res) |
@@ -3745,7 +3671,7 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st | |||
3745 | goto out; | 3671 | goto out; |
3746 | p = xdr_inline_decode(xdr, 4); | 3672 | p = xdr_inline_decode(xdr, 4); |
3747 | if (unlikely(!p)) | 3673 | if (unlikely(!p)) |
3748 | goto out_overflow; | 3674 | goto out_eio; |
3749 | n = be32_to_cpup(p); | 3675 | n = be32_to_cpup(p); |
3750 | if (n <= 0) | 3676 | if (n <= 0) |
3751 | goto out_eio; | 3677 | goto out_eio; |
@@ -3758,7 +3684,7 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st | |||
3758 | loc = &res->locations[res->nlocations]; | 3684 | loc = &res->locations[res->nlocations]; |
3759 | p = xdr_inline_decode(xdr, 4); | 3685 | p = xdr_inline_decode(xdr, 4); |
3760 | if (unlikely(!p)) | 3686 | if (unlikely(!p)) |
3761 | goto out_overflow; | 3687 | goto out_eio; |
3762 | m = be32_to_cpup(p); | 3688 | m = be32_to_cpup(p); |
3763 | 3689 | ||
3764 | dprintk("%s: servers:\n", __func__); | 3690 | dprintk("%s: servers:\n", __func__); |
@@ -3796,8 +3722,6 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st | |||
3796 | out: | 3722 | out: |
3797 | dprintk("%s: fs_locations done, error = %d\n", __func__, status); | 3723 | dprintk("%s: fs_locations done, error = %d\n", __func__, status); |
3798 | return status; | 3724 | return status; |
3799 | out_overflow: | ||
3800 | print_overflow_msg(__func__, xdr); | ||
3801 | out_eio: | 3725 | out_eio: |
3802 | status = -EIO; | 3726 | status = -EIO; |
3803 | goto out; | 3727 | goto out; |
@@ -3814,15 +3738,12 @@ static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uin | |||
3814 | if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) { | 3738 | if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) { |
3815 | p = xdr_inline_decode(xdr, 8); | 3739 | p = xdr_inline_decode(xdr, 8); |
3816 | if (unlikely(!p)) | 3740 | if (unlikely(!p)) |
3817 | goto out_overflow; | 3741 | return -EIO; |
3818 | xdr_decode_hyper(p, res); | 3742 | xdr_decode_hyper(p, res); |
3819 | bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE; | 3743 | bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE; |
3820 | } | 3744 | } |
3821 | dprintk("%s: maxfilesize=%Lu\n", __func__, (unsigned long long)*res); | 3745 | dprintk("%s: maxfilesize=%Lu\n", __func__, (unsigned long long)*res); |
3822 | return status; | 3746 | return status; |
3823 | out_overflow: | ||
3824 | print_overflow_msg(__func__, xdr); | ||
3825 | return -EIO; | ||
3826 | } | 3747 | } |
3827 | 3748 | ||
3828 | static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink) | 3749 | static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink) |
@@ -3836,15 +3757,12 @@ static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_ | |||
3836 | if (likely(bitmap[0] & FATTR4_WORD0_MAXLINK)) { | 3757 | if (likely(bitmap[0] & FATTR4_WORD0_MAXLINK)) { |
3837 | p = xdr_inline_decode(xdr, 4); | 3758 | p = xdr_inline_decode(xdr, 4); |
3838 | if (unlikely(!p)) | 3759 | if (unlikely(!p)) |
3839 | goto out_overflow; | 3760 | return -EIO; |
3840 | *maxlink = be32_to_cpup(p); | 3761 | *maxlink = be32_to_cpup(p); |
3841 | bitmap[0] &= ~FATTR4_WORD0_MAXLINK; | 3762 | bitmap[0] &= ~FATTR4_WORD0_MAXLINK; |
3842 | } | 3763 | } |
3843 | dprintk("%s: maxlink=%u\n", __func__, *maxlink); | 3764 | dprintk("%s: maxlink=%u\n", __func__, *maxlink); |
3844 | return status; | 3765 | return status; |
3845 | out_overflow: | ||
3846 | print_overflow_msg(__func__, xdr); | ||
3847 | return -EIO; | ||
3848 | } | 3766 | } |
3849 | 3767 | ||
3850 | static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname) | 3768 | static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname) |
@@ -3858,15 +3776,12 @@ static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_ | |||
3858 | if (likely(bitmap[0] & FATTR4_WORD0_MAXNAME)) { | 3776 | if (likely(bitmap[0] & FATTR4_WORD0_MAXNAME)) { |
3859 | p = xdr_inline_decode(xdr, 4); | 3777 | p = xdr_inline_decode(xdr, 4); |
3860 | if (unlikely(!p)) | 3778 | if (unlikely(!p)) |
3861 | goto out_overflow; | 3779 | return -EIO; |
3862 | *maxname = be32_to_cpup(p); | 3780 | *maxname = be32_to_cpup(p); |
3863 | bitmap[0] &= ~FATTR4_WORD0_MAXNAME; | 3781 | bitmap[0] &= ~FATTR4_WORD0_MAXNAME; |
3864 | } | 3782 | } |
3865 | dprintk("%s: maxname=%u\n", __func__, *maxname); | 3783 | dprintk("%s: maxname=%u\n", __func__, *maxname); |
3866 | return status; | 3784 | return status; |
3867 | out_overflow: | ||
3868 | print_overflow_msg(__func__, xdr); | ||
3869 | return -EIO; | ||
3870 | } | 3785 | } |
3871 | 3786 | ||
3872 | static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) | 3787 | static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) |
@@ -3881,7 +3796,7 @@ static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_ | |||
3881 | uint64_t maxread; | 3796 | uint64_t maxread; |
3882 | p = xdr_inline_decode(xdr, 8); | 3797 | p = xdr_inline_decode(xdr, 8); |
3883 | if (unlikely(!p)) | 3798 | if (unlikely(!p)) |
3884 | goto out_overflow; | 3799 | return -EIO; |
3885 | xdr_decode_hyper(p, &maxread); | 3800 | xdr_decode_hyper(p, &maxread); |
3886 | if (maxread > 0x7FFFFFFF) | 3801 | if (maxread > 0x7FFFFFFF) |
3887 | maxread = 0x7FFFFFFF; | 3802 | maxread = 0x7FFFFFFF; |
@@ -3890,9 +3805,6 @@ static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_ | |||
3890 | } | 3805 | } |
3891 | dprintk("%s: maxread=%lu\n", __func__, (unsigned long)*res); | 3806 | dprintk("%s: maxread=%lu\n", __func__, (unsigned long)*res); |
3892 | return status; | 3807 | return status; |
3893 | out_overflow: | ||
3894 | print_overflow_msg(__func__, xdr); | ||
3895 | return -EIO; | ||
3896 | } | 3808 | } |
3897 | 3809 | ||
3898 | static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) | 3810 | static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) |
@@ -3907,7 +3819,7 @@ static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32 | |||
3907 | uint64_t maxwrite; | 3819 | uint64_t maxwrite; |
3908 | p = xdr_inline_decode(xdr, 8); | 3820 | p = xdr_inline_decode(xdr, 8); |
3909 | if (unlikely(!p)) | 3821 | if (unlikely(!p)) |
3910 | goto out_overflow; | 3822 | return -EIO; |
3911 | xdr_decode_hyper(p, &maxwrite); | 3823 | xdr_decode_hyper(p, &maxwrite); |
3912 | if (maxwrite > 0x7FFFFFFF) | 3824 | if (maxwrite > 0x7FFFFFFF) |
3913 | maxwrite = 0x7FFFFFFF; | 3825 | maxwrite = 0x7FFFFFFF; |
@@ -3916,9 +3828,6 @@ static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32 | |||
3916 | } | 3828 | } |
3917 | dprintk("%s: maxwrite=%lu\n", __func__, (unsigned long)*res); | 3829 | dprintk("%s: maxwrite=%lu\n", __func__, (unsigned long)*res); |
3918 | return status; | 3830 | return status; |
3919 | out_overflow: | ||
3920 | print_overflow_msg(__func__, xdr); | ||
3921 | return -EIO; | ||
3922 | } | 3831 | } |
3923 | 3832 | ||
3924 | static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *mode) | 3833 | static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *mode) |
@@ -3933,7 +3842,7 @@ static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *m | |||
3933 | if (likely(bitmap[1] & FATTR4_WORD1_MODE)) { | 3842 | if (likely(bitmap[1] & FATTR4_WORD1_MODE)) { |
3934 | p = xdr_inline_decode(xdr, 4); | 3843 | p = xdr_inline_decode(xdr, 4); |
3935 | if (unlikely(!p)) | 3844 | if (unlikely(!p)) |
3936 | goto out_overflow; | 3845 | return -EIO; |
3937 | tmp = be32_to_cpup(p); | 3846 | tmp = be32_to_cpup(p); |
3938 | *mode = tmp & ~S_IFMT; | 3847 | *mode = tmp & ~S_IFMT; |
3939 | bitmap[1] &= ~FATTR4_WORD1_MODE; | 3848 | bitmap[1] &= ~FATTR4_WORD1_MODE; |
@@ -3941,9 +3850,6 @@ static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *m | |||
3941 | } | 3850 | } |
3942 | dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode); | 3851 | dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode); |
3943 | return ret; | 3852 | return ret; |
3944 | out_overflow: | ||
3945 | print_overflow_msg(__func__, xdr); | ||
3946 | return -EIO; | ||
3947 | } | 3853 | } |
3948 | 3854 | ||
3949 | static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink) | 3855 | static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink) |
@@ -3957,16 +3863,13 @@ static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t | |||
3957 | if (likely(bitmap[1] & FATTR4_WORD1_NUMLINKS)) { | 3863 | if (likely(bitmap[1] & FATTR4_WORD1_NUMLINKS)) { |
3958 | p = xdr_inline_decode(xdr, 4); | 3864 | p = xdr_inline_decode(xdr, 4); |
3959 | if (unlikely(!p)) | 3865 | if (unlikely(!p)) |
3960 | goto out_overflow; | 3866 | return -EIO; |
3961 | *nlink = be32_to_cpup(p); | 3867 | *nlink = be32_to_cpup(p); |
3962 | bitmap[1] &= ~FATTR4_WORD1_NUMLINKS; | 3868 | bitmap[1] &= ~FATTR4_WORD1_NUMLINKS; |
3963 | ret = NFS_ATTR_FATTR_NLINK; | 3869 | ret = NFS_ATTR_FATTR_NLINK; |
3964 | } | 3870 | } |
3965 | dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink); | 3871 | dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink); |
3966 | return ret; | 3872 | return ret; |
3967 | out_overflow: | ||
3968 | print_overflow_msg(__func__, xdr); | ||
3969 | return -EIO; | ||
3970 | } | 3873 | } |
3971 | 3874 | ||
3972 | static ssize_t decode_nfs4_string(struct xdr_stream *xdr, | 3875 | static ssize_t decode_nfs4_string(struct xdr_stream *xdr, |
@@ -4011,10 +3914,9 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4011 | return NFS_ATTR_FATTR_OWNER; | 3914 | return NFS_ATTR_FATTR_OWNER; |
4012 | } | 3915 | } |
4013 | out: | 3916 | out: |
4014 | if (len != -EBADMSG) | 3917 | if (len == -EBADMSG) |
4015 | return 0; | 3918 | return -EIO; |
4016 | print_overflow_msg(__func__, xdr); | 3919 | return 0; |
4017 | return -EIO; | ||
4018 | } | 3920 | } |
4019 | 3921 | ||
4020 | static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, | 3922 | static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, |
@@ -4046,10 +3948,9 @@ static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4046 | return NFS_ATTR_FATTR_GROUP; | 3948 | return NFS_ATTR_FATTR_GROUP; |
4047 | } | 3949 | } |
4048 | out: | 3950 | out: |
4049 | if (len != -EBADMSG) | 3951 | if (len == -EBADMSG) |
4050 | return 0; | 3952 | return -EIO; |
4051 | print_overflow_msg(__func__, xdr); | 3953 | return 0; |
4052 | return -EIO; | ||
4053 | } | 3954 | } |
4054 | 3955 | ||
4055 | static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev) | 3956 | static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev) |
@@ -4066,7 +3967,7 @@ static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rde | |||
4066 | 3967 | ||
4067 | p = xdr_inline_decode(xdr, 8); | 3968 | p = xdr_inline_decode(xdr, 8); |
4068 | if (unlikely(!p)) | 3969 | if (unlikely(!p)) |
4069 | goto out_overflow; | 3970 | return -EIO; |
4070 | major = be32_to_cpup(p++); | 3971 | major = be32_to_cpup(p++); |
4071 | minor = be32_to_cpup(p); | 3972 | minor = be32_to_cpup(p); |
4072 | tmp = MKDEV(major, minor); | 3973 | tmp = MKDEV(major, minor); |
@@ -4077,9 +3978,6 @@ static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rde | |||
4077 | } | 3978 | } |
4078 | dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor); | 3979 | dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor); |
4079 | return ret; | 3980 | return ret; |
4080 | out_overflow: | ||
4081 | print_overflow_msg(__func__, xdr); | ||
4082 | return -EIO; | ||
4083 | } | 3981 | } |
4084 | 3982 | ||
4085 | static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) | 3983 | static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) |
@@ -4093,15 +3991,12 @@ static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uin | |||
4093 | if (likely(bitmap[1] & FATTR4_WORD1_SPACE_AVAIL)) { | 3991 | if (likely(bitmap[1] & FATTR4_WORD1_SPACE_AVAIL)) { |
4094 | p = xdr_inline_decode(xdr, 8); | 3992 | p = xdr_inline_decode(xdr, 8); |
4095 | if (unlikely(!p)) | 3993 | if (unlikely(!p)) |
4096 | goto out_overflow; | 3994 | return -EIO; |
4097 | xdr_decode_hyper(p, res); | 3995 | xdr_decode_hyper(p, res); |
4098 | bitmap[1] &= ~FATTR4_WORD1_SPACE_AVAIL; | 3996 | bitmap[1] &= ~FATTR4_WORD1_SPACE_AVAIL; |
4099 | } | 3997 | } |
4100 | dprintk("%s: space avail=%Lu\n", __func__, (unsigned long long)*res); | 3998 | dprintk("%s: space avail=%Lu\n", __func__, (unsigned long long)*res); |
4101 | return status; | 3999 | return status; |
4102 | out_overflow: | ||
4103 | print_overflow_msg(__func__, xdr); | ||
4104 | return -EIO; | ||
4105 | } | 4000 | } |
4106 | 4001 | ||
4107 | static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) | 4002 | static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) |
@@ -4115,15 +4010,12 @@ static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint | |||
4115 | if (likely(bitmap[1] & FATTR4_WORD1_SPACE_FREE)) { | 4010 | if (likely(bitmap[1] & FATTR4_WORD1_SPACE_FREE)) { |
4116 | p = xdr_inline_decode(xdr, 8); | 4011 | p = xdr_inline_decode(xdr, 8); |
4117 | if (unlikely(!p)) | 4012 | if (unlikely(!p)) |
4118 | goto out_overflow; | 4013 | return -EIO; |
4119 | xdr_decode_hyper(p, res); | 4014 | xdr_decode_hyper(p, res); |
4120 | bitmap[1] &= ~FATTR4_WORD1_SPACE_FREE; | 4015 | bitmap[1] &= ~FATTR4_WORD1_SPACE_FREE; |
4121 | } | 4016 | } |
4122 | dprintk("%s: space free=%Lu\n", __func__, (unsigned long long)*res); | 4017 | dprintk("%s: space free=%Lu\n", __func__, (unsigned long long)*res); |
4123 | return status; | 4018 | return status; |
4124 | out_overflow: | ||
4125 | print_overflow_msg(__func__, xdr); | ||
4126 | return -EIO; | ||
4127 | } | 4019 | } |
4128 | 4020 | ||
4129 | static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) | 4021 | static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) |
@@ -4137,15 +4029,12 @@ static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uin | |||
4137 | if (likely(bitmap[1] & FATTR4_WORD1_SPACE_TOTAL)) { | 4029 | if (likely(bitmap[1] & FATTR4_WORD1_SPACE_TOTAL)) { |
4138 | p = xdr_inline_decode(xdr, 8); | 4030 | p = xdr_inline_decode(xdr, 8); |
4139 | if (unlikely(!p)) | 4031 | if (unlikely(!p)) |
4140 | goto out_overflow; | 4032 | return -EIO; |
4141 | xdr_decode_hyper(p, res); | 4033 | xdr_decode_hyper(p, res); |
4142 | bitmap[1] &= ~FATTR4_WORD1_SPACE_TOTAL; | 4034 | bitmap[1] &= ~FATTR4_WORD1_SPACE_TOTAL; |
4143 | } | 4035 | } |
4144 | dprintk("%s: space total=%Lu\n", __func__, (unsigned long long)*res); | 4036 | dprintk("%s: space total=%Lu\n", __func__, (unsigned long long)*res); |
4145 | return status; | 4037 | return status; |
4146 | out_overflow: | ||
4147 | print_overflow_msg(__func__, xdr); | ||
4148 | return -EIO; | ||
4149 | } | 4038 | } |
4150 | 4039 | ||
4151 | static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used) | 4040 | static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used) |
@@ -4159,7 +4048,7 @@ static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint | |||
4159 | if (likely(bitmap[1] & FATTR4_WORD1_SPACE_USED)) { | 4048 | if (likely(bitmap[1] & FATTR4_WORD1_SPACE_USED)) { |
4160 | p = xdr_inline_decode(xdr, 8); | 4049 | p = xdr_inline_decode(xdr, 8); |
4161 | if (unlikely(!p)) | 4050 | if (unlikely(!p)) |
4162 | goto out_overflow; | 4051 | return -EIO; |
4163 | xdr_decode_hyper(p, used); | 4052 | xdr_decode_hyper(p, used); |
4164 | bitmap[1] &= ~FATTR4_WORD1_SPACE_USED; | 4053 | bitmap[1] &= ~FATTR4_WORD1_SPACE_USED; |
4165 | ret = NFS_ATTR_FATTR_SPACE_USED; | 4054 | ret = NFS_ATTR_FATTR_SPACE_USED; |
@@ -4167,9 +4056,6 @@ static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint | |||
4167 | dprintk("%s: space used=%Lu\n", __func__, | 4056 | dprintk("%s: space used=%Lu\n", __func__, |
4168 | (unsigned long long)*used); | 4057 | (unsigned long long)*used); |
4169 | return ret; | 4058 | return ret; |
4170 | out_overflow: | ||
4171 | print_overflow_msg(__func__, xdr); | ||
4172 | return -EIO; | ||
4173 | } | 4059 | } |
4174 | 4060 | ||
4175 | static __be32 * | 4061 | static __be32 * |
@@ -4189,12 +4075,9 @@ static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time) | |||
4189 | 4075 | ||
4190 | p = xdr_inline_decode(xdr, nfstime4_maxsz << 2); | 4076 | p = xdr_inline_decode(xdr, nfstime4_maxsz << 2); |
4191 | if (unlikely(!p)) | 4077 | if (unlikely(!p)) |
4192 | goto out_overflow; | 4078 | return -EIO; |
4193 | xdr_decode_nfstime4(p, time); | 4079 | xdr_decode_nfstime4(p, time); |
4194 | return 0; | 4080 | return 0; |
4195 | out_overflow: | ||
4196 | print_overflow_msg(__func__, xdr); | ||
4197 | return -EIO; | ||
4198 | } | 4081 | } |
4199 | 4082 | ||
4200 | static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) | 4083 | static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) |
@@ -4265,19 +4148,19 @@ static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4265 | if (likely(bitmap[2] & FATTR4_WORD2_SECURITY_LABEL)) { | 4148 | if (likely(bitmap[2] & FATTR4_WORD2_SECURITY_LABEL)) { |
4266 | p = xdr_inline_decode(xdr, 4); | 4149 | p = xdr_inline_decode(xdr, 4); |
4267 | if (unlikely(!p)) | 4150 | if (unlikely(!p)) |
4268 | goto out_overflow; | 4151 | return -EIO; |
4269 | lfs = be32_to_cpup(p++); | 4152 | lfs = be32_to_cpup(p++); |
4270 | p = xdr_inline_decode(xdr, 4); | 4153 | p = xdr_inline_decode(xdr, 4); |
4271 | if (unlikely(!p)) | 4154 | if (unlikely(!p)) |
4272 | goto out_overflow; | 4155 | return -EIO; |
4273 | pi = be32_to_cpup(p++); | 4156 | pi = be32_to_cpup(p++); |
4274 | p = xdr_inline_decode(xdr, 4); | 4157 | p = xdr_inline_decode(xdr, 4); |
4275 | if (unlikely(!p)) | 4158 | if (unlikely(!p)) |
4276 | goto out_overflow; | 4159 | return -EIO; |
4277 | len = be32_to_cpup(p++); | 4160 | len = be32_to_cpup(p++); |
4278 | p = xdr_inline_decode(xdr, len); | 4161 | p = xdr_inline_decode(xdr, len); |
4279 | if (unlikely(!p)) | 4162 | if (unlikely(!p)) |
4280 | goto out_overflow; | 4163 | return -EIO; |
4281 | if (len < NFS4_MAXLABELLEN) { | 4164 | if (len < NFS4_MAXLABELLEN) { |
4282 | if (label) { | 4165 | if (label) { |
4283 | memcpy(label->label, p, len); | 4166 | memcpy(label->label, p, len); |
@@ -4295,10 +4178,6 @@ static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4295 | dprintk("%s: label=%s, len=%d, PI=%d, LFS=%d\n", __func__, | 4178 | dprintk("%s: label=%s, len=%d, PI=%d, LFS=%d\n", __func__, |
4296 | (char *)label->label, label->len, label->pi, label->lfs); | 4179 | (char *)label->label, label->len, label->pi, label->lfs); |
4297 | return status; | 4180 | return status; |
4298 | |||
4299 | out_overflow: | ||
4300 | print_overflow_msg(__func__, xdr); | ||
4301 | return -EIO; | ||
4302 | } | 4181 | } |
4303 | 4182 | ||
4304 | static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) | 4183 | static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) |
@@ -4342,14 +4221,11 @@ static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *c | |||
4342 | 4221 | ||
4343 | p = xdr_inline_decode(xdr, 20); | 4222 | p = xdr_inline_decode(xdr, 20); |
4344 | if (unlikely(!p)) | 4223 | if (unlikely(!p)) |
4345 | goto out_overflow; | 4224 | return -EIO; |
4346 | cinfo->atomic = be32_to_cpup(p++); | 4225 | cinfo->atomic = be32_to_cpup(p++); |
4347 | p = xdr_decode_hyper(p, &cinfo->before); | 4226 | p = xdr_decode_hyper(p, &cinfo->before); |
4348 | xdr_decode_hyper(p, &cinfo->after); | 4227 | xdr_decode_hyper(p, &cinfo->after); |
4349 | return 0; | 4228 | return 0; |
4350 | out_overflow: | ||
4351 | print_overflow_msg(__func__, xdr); | ||
4352 | return -EIO; | ||
4353 | } | 4229 | } |
4354 | 4230 | ||
4355 | static int decode_access(struct xdr_stream *xdr, u32 *supported, u32 *access) | 4231 | static int decode_access(struct xdr_stream *xdr, u32 *supported, u32 *access) |
@@ -4363,24 +4239,19 @@ static int decode_access(struct xdr_stream *xdr, u32 *supported, u32 *access) | |||
4363 | return status; | 4239 | return status; |
4364 | p = xdr_inline_decode(xdr, 8); | 4240 | p = xdr_inline_decode(xdr, 8); |
4365 | if (unlikely(!p)) | 4241 | if (unlikely(!p)) |
4366 | goto out_overflow; | 4242 | return -EIO; |
4367 | supp = be32_to_cpup(p++); | 4243 | supp = be32_to_cpup(p++); |
4368 | acc = be32_to_cpup(p); | 4244 | acc = be32_to_cpup(p); |
4369 | *supported = supp; | 4245 | *supported = supp; |
4370 | *access = acc; | 4246 | *access = acc; |
4371 | return 0; | 4247 | return 0; |
4372 | out_overflow: | ||
4373 | print_overflow_msg(__func__, xdr); | ||
4374 | return -EIO; | ||
4375 | } | 4248 | } |
4376 | 4249 | ||
4377 | static int decode_opaque_fixed(struct xdr_stream *xdr, void *buf, size_t len) | 4250 | static int decode_opaque_fixed(struct xdr_stream *xdr, void *buf, size_t len) |
4378 | { | 4251 | { |
4379 | ssize_t ret = xdr_stream_decode_opaque_fixed(xdr, buf, len); | 4252 | ssize_t ret = xdr_stream_decode_opaque_fixed(xdr, buf, len); |
4380 | if (unlikely(ret < 0)) { | 4253 | if (unlikely(ret < 0)) |
4381 | print_overflow_msg(__func__, xdr); | ||
4382 | return -EIO; | 4254 | return -EIO; |
4383 | } | ||
4384 | return 0; | 4255 | return 0; |
4385 | } | 4256 | } |
4386 | 4257 | ||
@@ -4460,13 +4331,11 @@ static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) | |||
4460 | return status; | 4331 | return status; |
4461 | p = xdr_inline_decode(xdr, 4); | 4332 | p = xdr_inline_decode(xdr, 4); |
4462 | if (unlikely(!p)) | 4333 | if (unlikely(!p)) |
4463 | goto out_overflow; | 4334 | return -EIO; |
4464 | bmlen = be32_to_cpup(p); | 4335 | bmlen = be32_to_cpup(p); |
4465 | p = xdr_inline_decode(xdr, bmlen << 2); | 4336 | p = xdr_inline_decode(xdr, bmlen << 2); |
4466 | if (likely(p)) | 4337 | if (likely(p)) |
4467 | return 0; | 4338 | return 0; |
4468 | out_overflow: | ||
4469 | print_overflow_msg(__func__, xdr); | ||
4470 | return -EIO; | 4339 | return -EIO; |
4471 | } | 4340 | } |
4472 | 4341 | ||
@@ -4574,13 +4443,10 @@ static int decode_threshold_hint(struct xdr_stream *xdr, | |||
4574 | if (likely(bitmap[0] & hint_bit)) { | 4443 | if (likely(bitmap[0] & hint_bit)) { |
4575 | p = xdr_inline_decode(xdr, 8); | 4444 | p = xdr_inline_decode(xdr, 8); |
4576 | if (unlikely(!p)) | 4445 | if (unlikely(!p)) |
4577 | goto out_overflow; | 4446 | return -EIO; |
4578 | xdr_decode_hyper(p, res); | 4447 | xdr_decode_hyper(p, res); |
4579 | } | 4448 | } |
4580 | return 0; | 4449 | return 0; |
4581 | out_overflow: | ||
4582 | print_overflow_msg(__func__, xdr); | ||
4583 | return -EIO; | ||
4584 | } | 4450 | } |
4585 | 4451 | ||
4586 | static int decode_first_threshold_item4(struct xdr_stream *xdr, | 4452 | static int decode_first_threshold_item4(struct xdr_stream *xdr, |
@@ -4593,10 +4459,8 @@ static int decode_first_threshold_item4(struct xdr_stream *xdr, | |||
4593 | 4459 | ||
4594 | /* layout type */ | 4460 | /* layout type */ |
4595 | p = xdr_inline_decode(xdr, 4); | 4461 | p = xdr_inline_decode(xdr, 4); |
4596 | if (unlikely(!p)) { | 4462 | if (unlikely(!p)) |
4597 | print_overflow_msg(__func__, xdr); | ||
4598 | return -EIO; | 4463 | return -EIO; |
4599 | } | ||
4600 | res->l_type = be32_to_cpup(p); | 4464 | res->l_type = be32_to_cpup(p); |
4601 | 4465 | ||
4602 | /* thi_hintset bitmap */ | 4466 | /* thi_hintset bitmap */ |
@@ -4654,7 +4518,7 @@ static int decode_attr_mdsthreshold(struct xdr_stream *xdr, | |||
4654 | return -EREMOTEIO; | 4518 | return -EREMOTEIO; |
4655 | p = xdr_inline_decode(xdr, 4); | 4519 | p = xdr_inline_decode(xdr, 4); |
4656 | if (unlikely(!p)) | 4520 | if (unlikely(!p)) |
4657 | goto out_overflow; | 4521 | return -EIO; |
4658 | num = be32_to_cpup(p); | 4522 | num = be32_to_cpup(p); |
4659 | if (num == 0) | 4523 | if (num == 0) |
4660 | return 0; | 4524 | return 0; |
@@ -4667,9 +4531,6 @@ static int decode_attr_mdsthreshold(struct xdr_stream *xdr, | |||
4667 | bitmap[2] &= ~FATTR4_WORD2_MDSTHRESHOLD; | 4531 | bitmap[2] &= ~FATTR4_WORD2_MDSTHRESHOLD; |
4668 | } | 4532 | } |
4669 | return status; | 4533 | return status; |
4670 | out_overflow: | ||
4671 | print_overflow_msg(__func__, xdr); | ||
4672 | return -EIO; | ||
4673 | } | 4534 | } |
4674 | 4535 | ||
4675 | static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | 4536 | static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, |
@@ -4857,7 +4718,7 @@ static int decode_pnfs_layout_types(struct xdr_stream *xdr, | |||
4857 | 4718 | ||
4858 | p = xdr_inline_decode(xdr, 4); | 4719 | p = xdr_inline_decode(xdr, 4); |
4859 | if (unlikely(!p)) | 4720 | if (unlikely(!p)) |
4860 | goto out_overflow; | 4721 | return -EIO; |
4861 | fsinfo->nlayouttypes = be32_to_cpup(p); | 4722 | fsinfo->nlayouttypes = be32_to_cpup(p); |
4862 | 4723 | ||
4863 | /* pNFS is not supported by the underlying file system */ | 4724 | /* pNFS is not supported by the underlying file system */ |
@@ -4867,7 +4728,7 @@ static int decode_pnfs_layout_types(struct xdr_stream *xdr, | |||
4867 | /* Decode and set first layout type, move xdr->p past unused types */ | 4728 | /* Decode and set first layout type, move xdr->p past unused types */ |
4868 | p = xdr_inline_decode(xdr, fsinfo->nlayouttypes * 4); | 4729 | p = xdr_inline_decode(xdr, fsinfo->nlayouttypes * 4); |
4869 | if (unlikely(!p)) | 4730 | if (unlikely(!p)) |
4870 | goto out_overflow; | 4731 | return -EIO; |
4871 | 4732 | ||
4872 | /* If we get too many, then just cap it at the max */ | 4733 | /* If we get too many, then just cap it at the max */ |
4873 | if (fsinfo->nlayouttypes > NFS_MAX_LAYOUT_TYPES) { | 4734 | if (fsinfo->nlayouttypes > NFS_MAX_LAYOUT_TYPES) { |
@@ -4879,9 +4740,6 @@ static int decode_pnfs_layout_types(struct xdr_stream *xdr, | |||
4879 | for(i = 0; i < fsinfo->nlayouttypes; ++i) | 4740 | for(i = 0; i < fsinfo->nlayouttypes; ++i) |
4880 | fsinfo->layouttype[i] = be32_to_cpup(p++); | 4741 | fsinfo->layouttype[i] = be32_to_cpup(p++); |
4881 | return 0; | 4742 | return 0; |
4882 | out_overflow: | ||
4883 | print_overflow_msg(__func__, xdr); | ||
4884 | return -EIO; | ||
4885 | } | 4743 | } |
4886 | 4744 | ||
4887 | /* | 4745 | /* |
@@ -4915,10 +4773,8 @@ static int decode_attr_layout_blksize(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4915 | *res = 0; | 4773 | *res = 0; |
4916 | if (bitmap[2] & FATTR4_WORD2_LAYOUT_BLKSIZE) { | 4774 | if (bitmap[2] & FATTR4_WORD2_LAYOUT_BLKSIZE) { |
4917 | p = xdr_inline_decode(xdr, 4); | 4775 | p = xdr_inline_decode(xdr, 4); |
4918 | if (unlikely(!p)) { | 4776 | if (unlikely(!p)) |
4919 | print_overflow_msg(__func__, xdr); | ||
4920 | return -EIO; | 4777 | return -EIO; |
4921 | } | ||
4922 | *res = be32_to_cpup(p); | 4778 | *res = be32_to_cpup(p); |
4923 | bitmap[2] &= ~FATTR4_WORD2_LAYOUT_BLKSIZE; | 4779 | bitmap[2] &= ~FATTR4_WORD2_LAYOUT_BLKSIZE; |
4924 | } | 4780 | } |
@@ -4937,10 +4793,8 @@ static int decode_attr_clone_blksize(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4937 | *res = 0; | 4793 | *res = 0; |
4938 | if (bitmap[2] & FATTR4_WORD2_CLONE_BLKSIZE) { | 4794 | if (bitmap[2] & FATTR4_WORD2_CLONE_BLKSIZE) { |
4939 | p = xdr_inline_decode(xdr, 4); | 4795 | p = xdr_inline_decode(xdr, 4); |
4940 | if (unlikely(!p)) { | 4796 | if (unlikely(!p)) |
4941 | print_overflow_msg(__func__, xdr); | ||
4942 | return -EIO; | 4797 | return -EIO; |
4943 | } | ||
4944 | *res = be32_to_cpup(p); | 4798 | *res = be32_to_cpup(p); |
4945 | bitmap[2] &= ~FATTR4_WORD2_CLONE_BLKSIZE; | 4799 | bitmap[2] &= ~FATTR4_WORD2_CLONE_BLKSIZE; |
4946 | } | 4800 | } |
@@ -5016,19 +4870,16 @@ static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh) | |||
5016 | 4870 | ||
5017 | p = xdr_inline_decode(xdr, 4); | 4871 | p = xdr_inline_decode(xdr, 4); |
5018 | if (unlikely(!p)) | 4872 | if (unlikely(!p)) |
5019 | goto out_overflow; | 4873 | return -EIO; |
5020 | len = be32_to_cpup(p); | 4874 | len = be32_to_cpup(p); |
5021 | if (len > NFS4_FHSIZE) | 4875 | if (len > NFS4_FHSIZE) |
5022 | return -EIO; | 4876 | return -EIO; |
5023 | fh->size = len; | 4877 | fh->size = len; |
5024 | p = xdr_inline_decode(xdr, len); | 4878 | p = xdr_inline_decode(xdr, len); |
5025 | if (unlikely(!p)) | 4879 | if (unlikely(!p)) |
5026 | goto out_overflow; | 4880 | return -EIO; |
5027 | memcpy(fh->data, p, len); | 4881 | memcpy(fh->data, p, len); |
5028 | return 0; | 4882 | return 0; |
5029 | out_overflow: | ||
5030 | print_overflow_msg(__func__, xdr); | ||
5031 | return -EIO; | ||
5032 | } | 4883 | } |
5033 | 4884 | ||
5034 | static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) | 4885 | static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) |
@@ -5052,7 +4903,7 @@ static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl) | |||
5052 | 4903 | ||
5053 | p = xdr_inline_decode(xdr, 32); /* read 32 bytes */ | 4904 | p = xdr_inline_decode(xdr, 32); /* read 32 bytes */ |
5054 | if (unlikely(!p)) | 4905 | if (unlikely(!p)) |
5055 | goto out_overflow; | 4906 | return -EIO; |
5056 | p = xdr_decode_hyper(p, &offset); /* read 2 8-byte long words */ | 4907 | p = xdr_decode_hyper(p, &offset); /* read 2 8-byte long words */ |
5057 | p = xdr_decode_hyper(p, &length); | 4908 | p = xdr_decode_hyper(p, &length); |
5058 | type = be32_to_cpup(p++); /* 4 byte read */ | 4909 | type = be32_to_cpup(p++); /* 4 byte read */ |
@@ -5069,11 +4920,9 @@ static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl) | |||
5069 | p = xdr_decode_hyper(p, &clientid); /* read 8 bytes */ | 4920 | p = xdr_decode_hyper(p, &clientid); /* read 8 bytes */ |
5070 | namelen = be32_to_cpup(p); /* read 4 bytes */ /* have read all 32 bytes now */ | 4921 | namelen = be32_to_cpup(p); /* read 4 bytes */ /* have read all 32 bytes now */ |
5071 | p = xdr_inline_decode(xdr, namelen); /* variable size field */ | 4922 | p = xdr_inline_decode(xdr, namelen); /* variable size field */ |
5072 | if (likely(p)) | 4923 | if (likely(!p)) |
5073 | return -NFS4ERR_DENIED; | 4924 | return -EIO; |
5074 | out_overflow: | 4925 | return -NFS4ERR_DENIED; |
5075 | print_overflow_msg(__func__, xdr); | ||
5076 | return -EIO; | ||
5077 | } | 4926 | } |
5078 | 4927 | ||
5079 | static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res) | 4928 | static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res) |
@@ -5142,7 +4991,7 @@ static int decode_space_limit(struct xdr_stream *xdr, | |||
5142 | 4991 | ||
5143 | p = xdr_inline_decode(xdr, 12); | 4992 | p = xdr_inline_decode(xdr, 12); |
5144 | if (unlikely(!p)) | 4993 | if (unlikely(!p)) |
5145 | goto out_overflow; | 4994 | return -EIO; |
5146 | limit_type = be32_to_cpup(p++); | 4995 | limit_type = be32_to_cpup(p++); |
5147 | switch (limit_type) { | 4996 | switch (limit_type) { |
5148 | case NFS4_LIMIT_SIZE: | 4997 | case NFS4_LIMIT_SIZE: |
@@ -5156,9 +5005,6 @@ static int decode_space_limit(struct xdr_stream *xdr, | |||
5156 | maxsize >>= PAGE_SHIFT; | 5005 | maxsize >>= PAGE_SHIFT; |
5157 | *pagemod_limit = min_t(u64, maxsize, ULONG_MAX); | 5006 | *pagemod_limit = min_t(u64, maxsize, ULONG_MAX); |
5158 | return 0; | 5007 | return 0; |
5159 | out_overflow: | ||
5160 | print_overflow_msg(__func__, xdr); | ||
5161 | return -EIO; | ||
5162 | } | 5008 | } |
5163 | 5009 | ||
5164 | static int decode_rw_delegation(struct xdr_stream *xdr, | 5010 | static int decode_rw_delegation(struct xdr_stream *xdr, |
@@ -5173,7 +5019,7 @@ static int decode_rw_delegation(struct xdr_stream *xdr, | |||
5173 | return status; | 5019 | return status; |
5174 | p = xdr_inline_decode(xdr, 4); | 5020 | p = xdr_inline_decode(xdr, 4); |
5175 | if (unlikely(!p)) | 5021 | if (unlikely(!p)) |
5176 | goto out_overflow; | 5022 | return -EIO; |
5177 | res->do_recall = be32_to_cpup(p); | 5023 | res->do_recall = be32_to_cpup(p); |
5178 | 5024 | ||
5179 | switch (delegation_type) { | 5025 | switch (delegation_type) { |
@@ -5186,9 +5032,6 @@ static int decode_rw_delegation(struct xdr_stream *xdr, | |||
5186 | return -EIO; | 5032 | return -EIO; |
5187 | } | 5033 | } |
5188 | return decode_ace(xdr, NULL); | 5034 | return decode_ace(xdr, NULL); |
5189 | out_overflow: | ||
5190 | print_overflow_msg(__func__, xdr); | ||
5191 | return -EIO; | ||
5192 | } | 5035 | } |
5193 | 5036 | ||
5194 | static int decode_no_delegation(struct xdr_stream *xdr, struct nfs_openres *res) | 5037 | static int decode_no_delegation(struct xdr_stream *xdr, struct nfs_openres *res) |
@@ -5198,7 +5041,7 @@ static int decode_no_delegation(struct xdr_stream *xdr, struct nfs_openres *res) | |||
5198 | 5041 | ||
5199 | p = xdr_inline_decode(xdr, 4); | 5042 | p = xdr_inline_decode(xdr, 4); |
5200 | if (unlikely(!p)) | 5043 | if (unlikely(!p)) |
5201 | goto out_overflow; | 5044 | return -EIO; |
5202 | why_no_delegation = be32_to_cpup(p); | 5045 | why_no_delegation = be32_to_cpup(p); |
5203 | switch (why_no_delegation) { | 5046 | switch (why_no_delegation) { |
5204 | case WND4_CONTENTION: | 5047 | case WND4_CONTENTION: |
@@ -5207,9 +5050,6 @@ static int decode_no_delegation(struct xdr_stream *xdr, struct nfs_openres *res) | |||
5207 | /* Ignore for now */ | 5050 | /* Ignore for now */ |
5208 | } | 5051 | } |
5209 | return 0; | 5052 | return 0; |
5210 | out_overflow: | ||
5211 | print_overflow_msg(__func__, xdr); | ||
5212 | return -EIO; | ||
5213 | } | 5053 | } |
5214 | 5054 | ||
5215 | static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) | 5055 | static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) |
@@ -5219,7 +5059,7 @@ static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) | |||
5219 | 5059 | ||
5220 | p = xdr_inline_decode(xdr, 4); | 5060 | p = xdr_inline_decode(xdr, 4); |
5221 | if (unlikely(!p)) | 5061 | if (unlikely(!p)) |
5222 | goto out_overflow; | 5062 | return -EIO; |
5223 | delegation_type = be32_to_cpup(p); | 5063 | delegation_type = be32_to_cpup(p); |
5224 | res->delegation_type = 0; | 5064 | res->delegation_type = 0; |
5225 | switch (delegation_type) { | 5065 | switch (delegation_type) { |
@@ -5232,9 +5072,6 @@ static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) | |||
5232 | return decode_no_delegation(xdr, res); | 5072 | return decode_no_delegation(xdr, res); |
5233 | } | 5073 | } |
5234 | return -EIO; | 5074 | return -EIO; |
5235 | out_overflow: | ||
5236 | print_overflow_msg(__func__, xdr); | ||
5237 | return -EIO; | ||
5238 | } | 5075 | } |
5239 | 5076 | ||
5240 | static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) | 5077 | static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) |
@@ -5256,7 +5093,7 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) | |||
5256 | 5093 | ||
5257 | p = xdr_inline_decode(xdr, 8); | 5094 | p = xdr_inline_decode(xdr, 8); |
5258 | if (unlikely(!p)) | 5095 | if (unlikely(!p)) |
5259 | goto out_overflow; | 5096 | return -EIO; |
5260 | res->rflags = be32_to_cpup(p++); | 5097 | res->rflags = be32_to_cpup(p++); |
5261 | bmlen = be32_to_cpup(p); | 5098 | bmlen = be32_to_cpup(p); |
5262 | if (bmlen > 10) | 5099 | if (bmlen > 10) |
@@ -5264,7 +5101,7 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) | |||
5264 | 5101 | ||
5265 | p = xdr_inline_decode(xdr, bmlen << 2); | 5102 | p = xdr_inline_decode(xdr, bmlen << 2); |
5266 | if (unlikely(!p)) | 5103 | if (unlikely(!p)) |
5267 | goto out_overflow; | 5104 | return -EIO; |
5268 | savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE); | 5105 | savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE); |
5269 | for (i = 0; i < savewords; ++i) | 5106 | for (i = 0; i < savewords; ++i) |
5270 | res->attrset[i] = be32_to_cpup(p++); | 5107 | res->attrset[i] = be32_to_cpup(p++); |
@@ -5275,9 +5112,6 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) | |||
5275 | xdr_error: | 5112 | xdr_error: |
5276 | dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen); | 5113 | dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen); |
5277 | return -EIO; | 5114 | return -EIO; |
5278 | out_overflow: | ||
5279 | print_overflow_msg(__func__, xdr); | ||
5280 | return -EIO; | ||
5281 | } | 5115 | } |
5282 | 5116 | ||
5283 | static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res) | 5117 | static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res) |
@@ -5326,7 +5160,7 @@ static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
5326 | return status; | 5160 | return status; |
5327 | p = xdr_inline_decode(xdr, 8); | 5161 | p = xdr_inline_decode(xdr, 8); |
5328 | if (unlikely(!p)) | 5162 | if (unlikely(!p)) |
5329 | goto out_overflow; | 5163 | return -EIO; |
5330 | eof = be32_to_cpup(p++); | 5164 | eof = be32_to_cpup(p++); |
5331 | count = be32_to_cpup(p); | 5165 | count = be32_to_cpup(p); |
5332 | recvd = xdr_read_pages(xdr, count); | 5166 | recvd = xdr_read_pages(xdr, count); |
@@ -5339,9 +5173,6 @@ static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
5339 | res->eof = eof; | 5173 | res->eof = eof; |
5340 | res->count = count; | 5174 | res->count = count; |
5341 | return 0; | 5175 | return 0; |
5342 | out_overflow: | ||
5343 | print_overflow_msg(__func__, xdr); | ||
5344 | return -EIO; | ||
5345 | } | 5176 | } |
5346 | 5177 | ||
5347 | static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir) | 5178 | static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir) |
@@ -5374,7 +5205,7 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req) | |||
5374 | /* Convert length of symlink */ | 5205 | /* Convert length of symlink */ |
5375 | p = xdr_inline_decode(xdr, 4); | 5206 | p = xdr_inline_decode(xdr, 4); |
5376 | if (unlikely(!p)) | 5207 | if (unlikely(!p)) |
5377 | goto out_overflow; | 5208 | return -EIO; |
5378 | len = be32_to_cpup(p); | 5209 | len = be32_to_cpup(p); |
5379 | if (len >= rcvbuf->page_len || len <= 0) { | 5210 | if (len >= rcvbuf->page_len || len <= 0) { |
5380 | dprintk("nfs: server returned giant symlink!\n"); | 5211 | dprintk("nfs: server returned giant symlink!\n"); |
@@ -5395,9 +5226,6 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req) | |||
5395 | */ | 5226 | */ |
5396 | xdr_terminate_string(rcvbuf, len); | 5227 | xdr_terminate_string(rcvbuf, len); |
5397 | return 0; | 5228 | return 0; |
5398 | out_overflow: | ||
5399 | print_overflow_msg(__func__, xdr); | ||
5400 | return -EIO; | ||
5401 | } | 5229 | } |
5402 | 5230 | ||
5403 | static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) | 5231 | static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) |
@@ -5500,7 +5328,6 @@ static int decode_setattr(struct xdr_stream *xdr) | |||
5500 | return status; | 5328 | return status; |
5501 | if (decode_bitmap4(xdr, NULL, 0) >= 0) | 5329 | if (decode_bitmap4(xdr, NULL, 0) >= 0) |
5502 | return 0; | 5330 | return 0; |
5503 | print_overflow_msg(__func__, xdr); | ||
5504 | return -EIO; | 5331 | return -EIO; |
5505 | } | 5332 | } |
5506 | 5333 | ||
@@ -5512,7 +5339,7 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_re | |||
5512 | 5339 | ||
5513 | p = xdr_inline_decode(xdr, 8); | 5340 | p = xdr_inline_decode(xdr, 8); |
5514 | if (unlikely(!p)) | 5341 | if (unlikely(!p)) |
5515 | goto out_overflow; | 5342 | return -EIO; |
5516 | opnum = be32_to_cpup(p++); | 5343 | opnum = be32_to_cpup(p++); |
5517 | if (opnum != OP_SETCLIENTID) { | 5344 | if (opnum != OP_SETCLIENTID) { |
5518 | dprintk("nfs: decode_setclientid: Server returned operation" | 5345 | dprintk("nfs: decode_setclientid: Server returned operation" |
@@ -5523,7 +5350,7 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_re | |||
5523 | if (nfserr == NFS_OK) { | 5350 | if (nfserr == NFS_OK) { |
5524 | p = xdr_inline_decode(xdr, 8 + NFS4_VERIFIER_SIZE); | 5351 | p = xdr_inline_decode(xdr, 8 + NFS4_VERIFIER_SIZE); |
5525 | if (unlikely(!p)) | 5352 | if (unlikely(!p)) |
5526 | goto out_overflow; | 5353 | return -EIO; |
5527 | p = xdr_decode_hyper(p, &res->clientid); | 5354 | p = xdr_decode_hyper(p, &res->clientid); |
5528 | memcpy(res->confirm.data, p, NFS4_VERIFIER_SIZE); | 5355 | memcpy(res->confirm.data, p, NFS4_VERIFIER_SIZE); |
5529 | } else if (nfserr == NFSERR_CLID_INUSE) { | 5356 | } else if (nfserr == NFSERR_CLID_INUSE) { |
@@ -5532,28 +5359,25 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_re | |||
5532 | /* skip netid string */ | 5359 | /* skip netid string */ |
5533 | p = xdr_inline_decode(xdr, 4); | 5360 | p = xdr_inline_decode(xdr, 4); |
5534 | if (unlikely(!p)) | 5361 | if (unlikely(!p)) |
5535 | goto out_overflow; | 5362 | return -EIO; |
5536 | len = be32_to_cpup(p); | 5363 | len = be32_to_cpup(p); |
5537 | p = xdr_inline_decode(xdr, len); | 5364 | p = xdr_inline_decode(xdr, len); |
5538 | if (unlikely(!p)) | 5365 | if (unlikely(!p)) |
5539 | goto out_overflow; | 5366 | return -EIO; |
5540 | 5367 | ||
5541 | /* skip uaddr string */ | 5368 | /* skip uaddr string */ |
5542 | p = xdr_inline_decode(xdr, 4); | 5369 | p = xdr_inline_decode(xdr, 4); |
5543 | if (unlikely(!p)) | 5370 | if (unlikely(!p)) |
5544 | goto out_overflow; | 5371 | return -EIO; |
5545 | len = be32_to_cpup(p); | 5372 | len = be32_to_cpup(p); |
5546 | p = xdr_inline_decode(xdr, len); | 5373 | p = xdr_inline_decode(xdr, len); |
5547 | if (unlikely(!p)) | 5374 | if (unlikely(!p)) |
5548 | goto out_overflow; | 5375 | return -EIO; |
5549 | return -NFSERR_CLID_INUSE; | 5376 | return -NFSERR_CLID_INUSE; |
5550 | } else | 5377 | } else |
5551 | return nfs4_stat_to_errno(nfserr); | 5378 | return nfs4_stat_to_errno(nfserr); |
5552 | 5379 | ||
5553 | return 0; | 5380 | return 0; |
5554 | out_overflow: | ||
5555 | print_overflow_msg(__func__, xdr); | ||
5556 | return -EIO; | ||
5557 | } | 5381 | } |
5558 | 5382 | ||
5559 | static int decode_setclientid_confirm(struct xdr_stream *xdr) | 5383 | static int decode_setclientid_confirm(struct xdr_stream *xdr) |
@@ -5572,13 +5396,10 @@ static int decode_write(struct xdr_stream *xdr, struct nfs_pgio_res *res) | |||
5572 | 5396 | ||
5573 | p = xdr_inline_decode(xdr, 8); | 5397 | p = xdr_inline_decode(xdr, 8); |
5574 | if (unlikely(!p)) | 5398 | if (unlikely(!p)) |
5575 | goto out_overflow; | 5399 | return -EIO; |
5576 | res->count = be32_to_cpup(p++); | 5400 | res->count = be32_to_cpup(p++); |
5577 | res->verf->committed = be32_to_cpup(p++); | 5401 | res->verf->committed = be32_to_cpup(p++); |
5578 | return decode_write_verifier(xdr, &res->verf->verifier); | 5402 | return decode_write_verifier(xdr, &res->verf->verifier); |
5579 | out_overflow: | ||
5580 | print_overflow_msg(__func__, xdr); | ||
5581 | return -EIO; | ||
5582 | } | 5403 | } |
5583 | 5404 | ||
5584 | static int decode_delegreturn(struct xdr_stream *xdr) | 5405 | static int decode_delegreturn(struct xdr_stream *xdr) |
@@ -5594,30 +5415,24 @@ static int decode_secinfo_gss(struct xdr_stream *xdr, | |||
5594 | 5415 | ||
5595 | p = xdr_inline_decode(xdr, 4); | 5416 | p = xdr_inline_decode(xdr, 4); |
5596 | if (unlikely(!p)) | 5417 | if (unlikely(!p)) |
5597 | goto out_overflow; | 5418 | return -EIO; |
5598 | oid_len = be32_to_cpup(p); | 5419 | oid_len = be32_to_cpup(p); |
5599 | if (oid_len > GSS_OID_MAX_LEN) | 5420 | if (oid_len > GSS_OID_MAX_LEN) |
5600 | goto out_err; | 5421 | return -EINVAL; |
5601 | 5422 | ||
5602 | p = xdr_inline_decode(xdr, oid_len); | 5423 | p = xdr_inline_decode(xdr, oid_len); |
5603 | if (unlikely(!p)) | 5424 | if (unlikely(!p)) |
5604 | goto out_overflow; | 5425 | return -EIO; |
5605 | memcpy(flavor->flavor_info.oid.data, p, oid_len); | 5426 | memcpy(flavor->flavor_info.oid.data, p, oid_len); |
5606 | flavor->flavor_info.oid.len = oid_len; | 5427 | flavor->flavor_info.oid.len = oid_len; |
5607 | 5428 | ||
5608 | p = xdr_inline_decode(xdr, 8); | 5429 | p = xdr_inline_decode(xdr, 8); |
5609 | if (unlikely(!p)) | 5430 | if (unlikely(!p)) |
5610 | goto out_overflow; | 5431 | return -EIO; |
5611 | flavor->flavor_info.qop = be32_to_cpup(p++); | 5432 | flavor->flavor_info.qop = be32_to_cpup(p++); |
5612 | flavor->flavor_info.service = be32_to_cpup(p); | 5433 | flavor->flavor_info.service = be32_to_cpup(p); |
5613 | 5434 | ||
5614 | return 0; | 5435 | return 0; |
5615 | |||
5616 | out_overflow: | ||
5617 | print_overflow_msg(__func__, xdr); | ||
5618 | return -EIO; | ||
5619 | out_err: | ||
5620 | return -EINVAL; | ||
5621 | } | 5436 | } |
5622 | 5437 | ||
5623 | static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | 5438 | static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) |
@@ -5629,7 +5444,7 @@ static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res | |||
5629 | 5444 | ||
5630 | p = xdr_inline_decode(xdr, 4); | 5445 | p = xdr_inline_decode(xdr, 4); |
5631 | if (unlikely(!p)) | 5446 | if (unlikely(!p)) |
5632 | goto out_overflow; | 5447 | return -EIO; |
5633 | 5448 | ||
5634 | res->flavors->num_flavors = 0; | 5449 | res->flavors->num_flavors = 0; |
5635 | num_flavors = be32_to_cpup(p); | 5450 | num_flavors = be32_to_cpup(p); |
@@ -5641,7 +5456,7 @@ static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res | |||
5641 | 5456 | ||
5642 | p = xdr_inline_decode(xdr, 4); | 5457 | p = xdr_inline_decode(xdr, 4); |
5643 | if (unlikely(!p)) | 5458 | if (unlikely(!p)) |
5644 | goto out_overflow; | 5459 | return -EIO; |
5645 | sec_flavor->flavor = be32_to_cpup(p); | 5460 | sec_flavor->flavor = be32_to_cpup(p); |
5646 | 5461 | ||
5647 | if (sec_flavor->flavor == RPC_AUTH_GSS) { | 5462 | if (sec_flavor->flavor == RPC_AUTH_GSS) { |
@@ -5655,9 +5470,6 @@ static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res | |||
5655 | status = 0; | 5470 | status = 0; |
5656 | out: | 5471 | out: |
5657 | return status; | 5472 | return status; |
5658 | out_overflow: | ||
5659 | print_overflow_msg(__func__, xdr); | ||
5660 | return -EIO; | ||
5661 | } | 5473 | } |
5662 | 5474 | ||
5663 | static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | 5475 | static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) |
@@ -5711,11 +5523,11 @@ static int decode_exchange_id(struct xdr_stream *xdr, | |||
5711 | 5523 | ||
5712 | p = xdr_inline_decode(xdr, 8); | 5524 | p = xdr_inline_decode(xdr, 8); |
5713 | if (unlikely(!p)) | 5525 | if (unlikely(!p)) |
5714 | goto out_overflow; | 5526 | return -EIO; |
5715 | xdr_decode_hyper(p, &res->clientid); | 5527 | xdr_decode_hyper(p, &res->clientid); |
5716 | p = xdr_inline_decode(xdr, 12); | 5528 | p = xdr_inline_decode(xdr, 12); |
5717 | if (unlikely(!p)) | 5529 | if (unlikely(!p)) |
5718 | goto out_overflow; | 5530 | return -EIO; |
5719 | res->seqid = be32_to_cpup(p++); | 5531 | res->seqid = be32_to_cpup(p++); |
5720 | res->flags = be32_to_cpup(p++); | 5532 | res->flags = be32_to_cpup(p++); |
5721 | 5533 | ||
@@ -5739,7 +5551,7 @@ static int decode_exchange_id(struct xdr_stream *xdr, | |||
5739 | /* server_owner4.so_minor_id */ | 5551 | /* server_owner4.so_minor_id */ |
5740 | p = xdr_inline_decode(xdr, 8); | 5552 | p = xdr_inline_decode(xdr, 8); |
5741 | if (unlikely(!p)) | 5553 | if (unlikely(!p)) |
5742 | goto out_overflow; | 5554 | return -EIO; |
5743 | p = xdr_decode_hyper(p, &res->server_owner->minor_id); | 5555 | p = xdr_decode_hyper(p, &res->server_owner->minor_id); |
5744 | 5556 | ||
5745 | /* server_owner4.so_major_id */ | 5557 | /* server_owner4.so_major_id */ |
@@ -5759,7 +5571,7 @@ static int decode_exchange_id(struct xdr_stream *xdr, | |||
5759 | /* Implementation Id */ | 5571 | /* Implementation Id */ |
5760 | p = xdr_inline_decode(xdr, 4); | 5572 | p = xdr_inline_decode(xdr, 4); |
5761 | if (unlikely(!p)) | 5573 | if (unlikely(!p)) |
5762 | goto out_overflow; | 5574 | return -EIO; |
5763 | impl_id_count = be32_to_cpup(p++); | 5575 | impl_id_count = be32_to_cpup(p++); |
5764 | 5576 | ||
5765 | if (impl_id_count) { | 5577 | if (impl_id_count) { |
@@ -5778,16 +5590,13 @@ static int decode_exchange_id(struct xdr_stream *xdr, | |||
5778 | /* nii_date */ | 5590 | /* nii_date */ |
5779 | p = xdr_inline_decode(xdr, 12); | 5591 | p = xdr_inline_decode(xdr, 12); |
5780 | if (unlikely(!p)) | 5592 | if (unlikely(!p)) |
5781 | goto out_overflow; | 5593 | return -EIO; |
5782 | p = xdr_decode_hyper(p, &res->impl_id->date.seconds); | 5594 | p = xdr_decode_hyper(p, &res->impl_id->date.seconds); |
5783 | res->impl_id->date.nseconds = be32_to_cpup(p); | 5595 | res->impl_id->date.nseconds = be32_to_cpup(p); |
5784 | 5596 | ||
5785 | /* if there's more than one entry, ignore the rest */ | 5597 | /* if there's more than one entry, ignore the rest */ |
5786 | } | 5598 | } |
5787 | return 0; | 5599 | return 0; |
5788 | out_overflow: | ||
5789 | print_overflow_msg(__func__, xdr); | ||
5790 | return -EIO; | ||
5791 | } | 5600 | } |
5792 | 5601 | ||
5793 | static int decode_chan_attrs(struct xdr_stream *xdr, | 5602 | static int decode_chan_attrs(struct xdr_stream *xdr, |
@@ -5798,7 +5607,7 @@ static int decode_chan_attrs(struct xdr_stream *xdr, | |||
5798 | 5607 | ||
5799 | p = xdr_inline_decode(xdr, 28); | 5608 | p = xdr_inline_decode(xdr, 28); |
5800 | if (unlikely(!p)) | 5609 | if (unlikely(!p)) |
5801 | goto out_overflow; | 5610 | return -EIO; |
5802 | val = be32_to_cpup(p++); /* headerpadsz */ | 5611 | val = be32_to_cpup(p++); /* headerpadsz */ |
5803 | if (val) | 5612 | if (val) |
5804 | return -EINVAL; /* no support for header padding yet */ | 5613 | return -EINVAL; /* no support for header padding yet */ |
@@ -5816,12 +5625,9 @@ static int decode_chan_attrs(struct xdr_stream *xdr, | |||
5816 | if (nr_attrs == 1) { | 5625 | if (nr_attrs == 1) { |
5817 | p = xdr_inline_decode(xdr, 4); /* skip rdma_attrs */ | 5626 | p = xdr_inline_decode(xdr, 4); /* skip rdma_attrs */ |
5818 | if (unlikely(!p)) | 5627 | if (unlikely(!p)) |
5819 | goto out_overflow; | 5628 | return -EIO; |
5820 | } | 5629 | } |
5821 | return 0; | 5630 | return 0; |
5822 | out_overflow: | ||
5823 | print_overflow_msg(__func__, xdr); | ||
5824 | return -EIO; | ||
5825 | } | 5631 | } |
5826 | 5632 | ||
5827 | static int decode_sessionid(struct xdr_stream *xdr, struct nfs4_sessionid *sid) | 5633 | static int decode_sessionid(struct xdr_stream *xdr, struct nfs4_sessionid *sid) |
@@ -5844,7 +5650,7 @@ static int decode_bind_conn_to_session(struct xdr_stream *xdr, | |||
5844 | /* dir flags, rdma mode bool */ | 5650 | /* dir flags, rdma mode bool */ |
5845 | p = xdr_inline_decode(xdr, 8); | 5651 | p = xdr_inline_decode(xdr, 8); |
5846 | if (unlikely(!p)) | 5652 | if (unlikely(!p)) |
5847 | goto out_overflow; | 5653 | return -EIO; |
5848 | 5654 | ||
5849 | res->dir = be32_to_cpup(p++); | 5655 | res->dir = be32_to_cpup(p++); |
5850 | if (res->dir == 0 || res->dir > NFS4_CDFS4_BOTH) | 5656 | if (res->dir == 0 || res->dir > NFS4_CDFS4_BOTH) |
@@ -5855,9 +5661,6 @@ static int decode_bind_conn_to_session(struct xdr_stream *xdr, | |||
5855 | res->use_conn_in_rdma_mode = true; | 5661 | res->use_conn_in_rdma_mode = true; |
5856 | 5662 | ||
5857 | return 0; | 5663 | return 0; |
5858 | out_overflow: | ||
5859 | print_overflow_msg(__func__, xdr); | ||
5860 | return -EIO; | ||
5861 | } | 5664 | } |
5862 | 5665 | ||
5863 | static int decode_create_session(struct xdr_stream *xdr, | 5666 | static int decode_create_session(struct xdr_stream *xdr, |
@@ -5875,7 +5678,7 @@ static int decode_create_session(struct xdr_stream *xdr, | |||
5875 | /* seqid, flags */ | 5678 | /* seqid, flags */ |
5876 | p = xdr_inline_decode(xdr, 8); | 5679 | p = xdr_inline_decode(xdr, 8); |
5877 | if (unlikely(!p)) | 5680 | if (unlikely(!p)) |
5878 | goto out_overflow; | 5681 | return -EIO; |
5879 | res->seqid = be32_to_cpup(p++); | 5682 | res->seqid = be32_to_cpup(p++); |
5880 | res->flags = be32_to_cpup(p); | 5683 | res->flags = be32_to_cpup(p); |
5881 | 5684 | ||
@@ -5884,9 +5687,6 @@ static int decode_create_session(struct xdr_stream *xdr, | |||
5884 | if (!status) | 5687 | if (!status) |
5885 | status = decode_chan_attrs(xdr, &res->bc_attrs); | 5688 | status = decode_chan_attrs(xdr, &res->bc_attrs); |
5886 | return status; | 5689 | return status; |
5887 | out_overflow: | ||
5888 | print_overflow_msg(__func__, xdr); | ||
5889 | return -EIO; | ||
5890 | } | 5690 | } |
5891 | 5691 | ||
5892 | static int decode_destroy_session(struct xdr_stream *xdr, void *dummy) | 5692 | static int decode_destroy_session(struct xdr_stream *xdr, void *dummy) |
@@ -5967,7 +5767,6 @@ out_err: | |||
5967 | res->sr_status = status; | 5767 | res->sr_status = status; |
5968 | return status; | 5768 | return status; |
5969 | out_overflow: | 5769 | out_overflow: |
5970 | print_overflow_msg(__func__, xdr); | ||
5971 | status = -EIO; | 5770 | status = -EIO; |
5972 | goto out_err; | 5771 | goto out_err; |
5973 | #else /* CONFIG_NFS_V4_1 */ | 5772 | #else /* CONFIG_NFS_V4_1 */ |
@@ -5995,7 +5794,7 @@ static int decode_getdeviceinfo(struct xdr_stream *xdr, | |||
5995 | if (status == -ETOOSMALL) { | 5794 | if (status == -ETOOSMALL) { |
5996 | p = xdr_inline_decode(xdr, 4); | 5795 | p = xdr_inline_decode(xdr, 4); |
5997 | if (unlikely(!p)) | 5796 | if (unlikely(!p)) |
5998 | goto out_overflow; | 5797 | return -EIO; |
5999 | pdev->mincount = be32_to_cpup(p); | 5798 | pdev->mincount = be32_to_cpup(p); |
6000 | dprintk("%s: Min count too small. mincnt = %u\n", | 5799 | dprintk("%s: Min count too small. mincnt = %u\n", |
6001 | __func__, pdev->mincount); | 5800 | __func__, pdev->mincount); |
@@ -6005,7 +5804,7 @@ static int decode_getdeviceinfo(struct xdr_stream *xdr, | |||
6005 | 5804 | ||
6006 | p = xdr_inline_decode(xdr, 8); | 5805 | p = xdr_inline_decode(xdr, 8); |
6007 | if (unlikely(!p)) | 5806 | if (unlikely(!p)) |
6008 | goto out_overflow; | 5807 | return -EIO; |
6009 | type = be32_to_cpup(p++); | 5808 | type = be32_to_cpup(p++); |
6010 | if (type != pdev->layout_type) { | 5809 | if (type != pdev->layout_type) { |
6011 | dprintk("%s: layout mismatch req: %u pdev: %u\n", | 5810 | dprintk("%s: layout mismatch req: %u pdev: %u\n", |
@@ -6019,19 +5818,19 @@ static int decode_getdeviceinfo(struct xdr_stream *xdr, | |||
6019 | */ | 5818 | */ |
6020 | pdev->mincount = be32_to_cpup(p); | 5819 | pdev->mincount = be32_to_cpup(p); |
6021 | if (xdr_read_pages(xdr, pdev->mincount) != pdev->mincount) | 5820 | if (xdr_read_pages(xdr, pdev->mincount) != pdev->mincount) |
6022 | goto out_overflow; | 5821 | return -EIO; |
6023 | 5822 | ||
6024 | /* Parse notification bitmap, verifying that it is zero. */ | 5823 | /* Parse notification bitmap, verifying that it is zero. */ |
6025 | p = xdr_inline_decode(xdr, 4); | 5824 | p = xdr_inline_decode(xdr, 4); |
6026 | if (unlikely(!p)) | 5825 | if (unlikely(!p)) |
6027 | goto out_overflow; | 5826 | return -EIO; |
6028 | len = be32_to_cpup(p); | 5827 | len = be32_to_cpup(p); |
6029 | if (len) { | 5828 | if (len) { |
6030 | uint32_t i; | 5829 | uint32_t i; |
6031 | 5830 | ||
6032 | p = xdr_inline_decode(xdr, 4 * len); | 5831 | p = xdr_inline_decode(xdr, 4 * len); |
6033 | if (unlikely(!p)) | 5832 | if (unlikely(!p)) |
6034 | goto out_overflow; | 5833 | return -EIO; |
6035 | 5834 | ||
6036 | res->notification = be32_to_cpup(p++); | 5835 | res->notification = be32_to_cpup(p++); |
6037 | for (i = 1; i < len; i++) { | 5836 | for (i = 1; i < len; i++) { |
@@ -6043,9 +5842,6 @@ static int decode_getdeviceinfo(struct xdr_stream *xdr, | |||
6043 | } | 5842 | } |
6044 | } | 5843 | } |
6045 | return 0; | 5844 | return 0; |
6046 | out_overflow: | ||
6047 | print_overflow_msg(__func__, xdr); | ||
6048 | return -EIO; | ||
6049 | } | 5845 | } |
6050 | 5846 | ||
6051 | static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, | 5847 | static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, |
@@ -6115,7 +5911,6 @@ out: | |||
6115 | res->status = status; | 5911 | res->status = status; |
6116 | return status; | 5912 | return status; |
6117 | out_overflow: | 5913 | out_overflow: |
6118 | print_overflow_msg(__func__, xdr); | ||
6119 | status = -EIO; | 5914 | status = -EIO; |
6120 | goto out; | 5915 | goto out; |
6121 | } | 5916 | } |
@@ -6131,16 +5926,13 @@ static int decode_layoutreturn(struct xdr_stream *xdr, | |||
6131 | return status; | 5926 | return status; |
6132 | p = xdr_inline_decode(xdr, 4); | 5927 | p = xdr_inline_decode(xdr, 4); |
6133 | if (unlikely(!p)) | 5928 | if (unlikely(!p)) |
6134 | goto out_overflow; | 5929 | return -EIO; |
6135 | res->lrs_present = be32_to_cpup(p); | 5930 | res->lrs_present = be32_to_cpup(p); |
6136 | if (res->lrs_present) | 5931 | if (res->lrs_present) |
6137 | status = decode_layout_stateid(xdr, &res->stateid); | 5932 | status = decode_layout_stateid(xdr, &res->stateid); |
6138 | else | 5933 | else |
6139 | nfs4_stateid_copy(&res->stateid, &invalid_stateid); | 5934 | nfs4_stateid_copy(&res->stateid, &invalid_stateid); |
6140 | return status; | 5935 | return status; |
6141 | out_overflow: | ||
6142 | print_overflow_msg(__func__, xdr); | ||
6143 | return -EIO; | ||
6144 | } | 5936 | } |
6145 | 5937 | ||
6146 | static int decode_layoutcommit(struct xdr_stream *xdr, | 5938 | static int decode_layoutcommit(struct xdr_stream *xdr, |
@@ -6158,19 +5950,16 @@ static int decode_layoutcommit(struct xdr_stream *xdr, | |||
6158 | 5950 | ||
6159 | p = xdr_inline_decode(xdr, 4); | 5951 | p = xdr_inline_decode(xdr, 4); |
6160 | if (unlikely(!p)) | 5952 | if (unlikely(!p)) |
6161 | goto out_overflow; | 5953 | return -EIO; |
6162 | sizechanged = be32_to_cpup(p); | 5954 | sizechanged = be32_to_cpup(p); |
6163 | 5955 | ||
6164 | if (sizechanged) { | 5956 | if (sizechanged) { |
6165 | /* throw away new size */ | 5957 | /* throw away new size */ |
6166 | p = xdr_inline_decode(xdr, 8); | 5958 | p = xdr_inline_decode(xdr, 8); |
6167 | if (unlikely(!p)) | 5959 | if (unlikely(!p)) |
6168 | goto out_overflow; | 5960 | return -EIO; |
6169 | } | 5961 | } |
6170 | return 0; | 5962 | return 0; |
6171 | out_overflow: | ||
6172 | print_overflow_msg(__func__, xdr); | ||
6173 | return -EIO; | ||
6174 | } | 5963 | } |
6175 | 5964 | ||
6176 | static int decode_test_stateid(struct xdr_stream *xdr, | 5965 | static int decode_test_stateid(struct xdr_stream *xdr, |
@@ -6186,21 +5975,17 @@ static int decode_test_stateid(struct xdr_stream *xdr, | |||
6186 | 5975 | ||
6187 | p = xdr_inline_decode(xdr, 4); | 5976 | p = xdr_inline_decode(xdr, 4); |
6188 | if (unlikely(!p)) | 5977 | if (unlikely(!p)) |
6189 | goto out_overflow; | 5978 | return -EIO; |
6190 | num_res = be32_to_cpup(p++); | 5979 | num_res = be32_to_cpup(p++); |
6191 | if (num_res != 1) | 5980 | if (num_res != 1) |
6192 | goto out; | 5981 | return -EIO; |
6193 | 5982 | ||
6194 | p = xdr_inline_decode(xdr, 4); | 5983 | p = xdr_inline_decode(xdr, 4); |
6195 | if (unlikely(!p)) | 5984 | if (unlikely(!p)) |
6196 | goto out_overflow; | 5985 | return -EIO; |
6197 | res->status = be32_to_cpup(p++); | 5986 | res->status = be32_to_cpup(p++); |
6198 | 5987 | ||
6199 | return status; | 5988 | return status; |
6200 | out_overflow: | ||
6201 | print_overflow_msg(__func__, xdr); | ||
6202 | out: | ||
6203 | return -EIO; | ||
6204 | } | 5989 | } |
6205 | 5990 | ||
6206 | static int decode_free_stateid(struct xdr_stream *xdr, | 5991 | static int decode_free_stateid(struct xdr_stream *xdr, |
@@ -7570,11 +7355,11 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
7570 | uint64_t new_cookie; | 7355 | uint64_t new_cookie; |
7571 | __be32 *p = xdr_inline_decode(xdr, 4); | 7356 | __be32 *p = xdr_inline_decode(xdr, 4); |
7572 | if (unlikely(!p)) | 7357 | if (unlikely(!p)) |
7573 | goto out_overflow; | 7358 | return -EAGAIN; |
7574 | if (*p == xdr_zero) { | 7359 | if (*p == xdr_zero) { |
7575 | p = xdr_inline_decode(xdr, 4); | 7360 | p = xdr_inline_decode(xdr, 4); |
7576 | if (unlikely(!p)) | 7361 | if (unlikely(!p)) |
7577 | goto out_overflow; | 7362 | return -EAGAIN; |
7578 | if (*p == xdr_zero) | 7363 | if (*p == xdr_zero) |
7579 | return -EAGAIN; | 7364 | return -EAGAIN; |
7580 | entry->eof = 1; | 7365 | entry->eof = 1; |
@@ -7583,13 +7368,13 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
7583 | 7368 | ||
7584 | p = xdr_inline_decode(xdr, 12); | 7369 | p = xdr_inline_decode(xdr, 12); |
7585 | if (unlikely(!p)) | 7370 | if (unlikely(!p)) |
7586 | goto out_overflow; | 7371 | return -EAGAIN; |
7587 | p = xdr_decode_hyper(p, &new_cookie); | 7372 | p = xdr_decode_hyper(p, &new_cookie); |
7588 | entry->len = be32_to_cpup(p); | 7373 | entry->len = be32_to_cpup(p); |
7589 | 7374 | ||
7590 | p = xdr_inline_decode(xdr, entry->len); | 7375 | p = xdr_inline_decode(xdr, entry->len); |
7591 | if (unlikely(!p)) | 7376 | if (unlikely(!p)) |
7592 | goto out_overflow; | 7377 | return -EAGAIN; |
7593 | entry->name = (const char *) p; | 7378 | entry->name = (const char *) p; |
7594 | 7379 | ||
7595 | /* | 7380 | /* |
@@ -7601,14 +7386,14 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
7601 | entry->fattr->valid = 0; | 7386 | entry->fattr->valid = 0; |
7602 | 7387 | ||
7603 | if (decode_attr_bitmap(xdr, bitmap) < 0) | 7388 | if (decode_attr_bitmap(xdr, bitmap) < 0) |
7604 | goto out_overflow; | 7389 | return -EAGAIN; |
7605 | 7390 | ||
7606 | if (decode_attr_length(xdr, &len, &savep) < 0) | 7391 | if (decode_attr_length(xdr, &len, &savep) < 0) |
7607 | goto out_overflow; | 7392 | return -EAGAIN; |
7608 | 7393 | ||
7609 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, | 7394 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, |
7610 | NULL, entry->label, entry->server) < 0) | 7395 | NULL, entry->label, entry->server) < 0) |
7611 | goto out_overflow; | 7396 | return -EAGAIN; |
7612 | if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) | 7397 | if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) |
7613 | entry->ino = entry->fattr->mounted_on_fileid; | 7398 | entry->ino = entry->fattr->mounted_on_fileid; |
7614 | else if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) | 7399 | else if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) |
@@ -7622,10 +7407,6 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
7622 | entry->cookie = new_cookie; | 7407 | entry->cookie = new_cookie; |
7623 | 7408 | ||
7624 | return 0; | 7409 | return 0; |
7625 | |||
7626 | out_overflow: | ||
7627 | print_overflow_msg(__func__, xdr); | ||
7628 | return -EAGAIN; | ||
7629 | } | 7410 | } |
7630 | 7411 | ||
7631 | /* | 7412 | /* |
diff --git a/fs/nfs/nfstrace.c b/fs/nfs/nfstrace.c index b60d5fbd7727..a90b363500c2 100644 --- a/fs/nfs/nfstrace.c +++ b/fs/nfs/nfstrace.c | |||
@@ -11,3 +11,4 @@ | |||
11 | 11 | ||
12 | EXPORT_TRACEPOINT_SYMBOL_GPL(nfs_fsync_enter); | 12 | EXPORT_TRACEPOINT_SYMBOL_GPL(nfs_fsync_enter); |
13 | EXPORT_TRACEPOINT_SYMBOL_GPL(nfs_fsync_exit); | 13 | EXPORT_TRACEPOINT_SYMBOL_GPL(nfs_fsync_exit); |
14 | EXPORT_TRACEPOINT_SYMBOL_GPL(nfs_xdr_status); | ||
diff --git a/fs/nfs/nfstrace.h b/fs/nfs/nfstrace.h index bd60f8d1e181..a0d6910aa03a 100644 --- a/fs/nfs/nfstrace.h +++ b/fs/nfs/nfstrace.h | |||
@@ -969,6 +969,91 @@ TRACE_EVENT(nfs_commit_done, | |||
969 | ) | 969 | ) |
970 | ); | 970 | ); |
971 | 971 | ||
972 | TRACE_DEFINE_ENUM(NFS_OK); | ||
973 | TRACE_DEFINE_ENUM(NFSERR_PERM); | ||
974 | TRACE_DEFINE_ENUM(NFSERR_NOENT); | ||
975 | TRACE_DEFINE_ENUM(NFSERR_IO); | ||
976 | TRACE_DEFINE_ENUM(NFSERR_NXIO); | ||
977 | TRACE_DEFINE_ENUM(NFSERR_ACCES); | ||
978 | TRACE_DEFINE_ENUM(NFSERR_EXIST); | ||
979 | TRACE_DEFINE_ENUM(NFSERR_XDEV); | ||
980 | TRACE_DEFINE_ENUM(NFSERR_NODEV); | ||
981 | TRACE_DEFINE_ENUM(NFSERR_NOTDIR); | ||
982 | TRACE_DEFINE_ENUM(NFSERR_ISDIR); | ||
983 | TRACE_DEFINE_ENUM(NFSERR_INVAL); | ||
984 | TRACE_DEFINE_ENUM(NFSERR_FBIG); | ||
985 | TRACE_DEFINE_ENUM(NFSERR_NOSPC); | ||
986 | TRACE_DEFINE_ENUM(NFSERR_ROFS); | ||
987 | TRACE_DEFINE_ENUM(NFSERR_MLINK); | ||
988 | TRACE_DEFINE_ENUM(NFSERR_NAMETOOLONG); | ||
989 | TRACE_DEFINE_ENUM(NFSERR_NOTEMPTY); | ||
990 | TRACE_DEFINE_ENUM(NFSERR_DQUOT); | ||
991 | TRACE_DEFINE_ENUM(NFSERR_STALE); | ||
992 | TRACE_DEFINE_ENUM(NFSERR_REMOTE); | ||
993 | TRACE_DEFINE_ENUM(NFSERR_WFLUSH); | ||
994 | TRACE_DEFINE_ENUM(NFSERR_BADHANDLE); | ||
995 | TRACE_DEFINE_ENUM(NFSERR_NOT_SYNC); | ||
996 | TRACE_DEFINE_ENUM(NFSERR_BAD_COOKIE); | ||
997 | TRACE_DEFINE_ENUM(NFSERR_NOTSUPP); | ||
998 | TRACE_DEFINE_ENUM(NFSERR_TOOSMALL); | ||
999 | TRACE_DEFINE_ENUM(NFSERR_SERVERFAULT); | ||
1000 | TRACE_DEFINE_ENUM(NFSERR_BADTYPE); | ||
1001 | TRACE_DEFINE_ENUM(NFSERR_JUKEBOX); | ||
1002 | |||
1003 | #define nfs_show_status(x) \ | ||
1004 | __print_symbolic(x, \ | ||
1005 | { NFS_OK, "OK" }, \ | ||
1006 | { NFSERR_PERM, "PERM" }, \ | ||
1007 | { NFSERR_NOENT, "NOENT" }, \ | ||
1008 | { NFSERR_IO, "IO" }, \ | ||
1009 | { NFSERR_NXIO, "NXIO" }, \ | ||
1010 | { NFSERR_ACCES, "ACCES" }, \ | ||
1011 | { NFSERR_EXIST, "EXIST" }, \ | ||
1012 | { NFSERR_XDEV, "XDEV" }, \ | ||
1013 | { NFSERR_NODEV, "NODEV" }, \ | ||
1014 | { NFSERR_NOTDIR, "NOTDIR" }, \ | ||
1015 | { NFSERR_ISDIR, "ISDIR" }, \ | ||
1016 | { NFSERR_INVAL, "INVAL" }, \ | ||
1017 | { NFSERR_FBIG, "FBIG" }, \ | ||
1018 | { NFSERR_NOSPC, "NOSPC" }, \ | ||
1019 | { NFSERR_ROFS, "ROFS" }, \ | ||
1020 | { NFSERR_MLINK, "MLINK" }, \ | ||
1021 | { NFSERR_NAMETOOLONG, "NAMETOOLONG" }, \ | ||
1022 | { NFSERR_NOTEMPTY, "NOTEMPTY" }, \ | ||
1023 | { NFSERR_DQUOT, "DQUOT" }, \ | ||
1024 | { NFSERR_STALE, "STALE" }, \ | ||
1025 | { NFSERR_REMOTE, "REMOTE" }, \ | ||
1026 | { NFSERR_WFLUSH, "WFLUSH" }, \ | ||
1027 | { NFSERR_BADHANDLE, "BADHANDLE" }, \ | ||
1028 | { NFSERR_NOT_SYNC, "NOTSYNC" }, \ | ||
1029 | { NFSERR_BAD_COOKIE, "BADCOOKIE" }, \ | ||
1030 | { NFSERR_NOTSUPP, "NOTSUPP" }, \ | ||
1031 | { NFSERR_TOOSMALL, "TOOSMALL" }, \ | ||
1032 | { NFSERR_SERVERFAULT, "REMOTEIO" }, \ | ||
1033 | { NFSERR_BADTYPE, "BADTYPE" }, \ | ||
1034 | { NFSERR_JUKEBOX, "JUKEBOX" }) | ||
1035 | |||
1036 | TRACE_EVENT(nfs_xdr_status, | ||
1037 | TP_PROTO( | ||
1038 | int error | ||
1039 | ), | ||
1040 | |||
1041 | TP_ARGS(error), | ||
1042 | |||
1043 | TP_STRUCT__entry( | ||
1044 | __field(int, error) | ||
1045 | ), | ||
1046 | |||
1047 | TP_fast_assign( | ||
1048 | __entry->error = error; | ||
1049 | ), | ||
1050 | |||
1051 | TP_printk( | ||
1052 | "error=%d (%s)", | ||
1053 | __entry->error, nfs_show_status(__entry->error) | ||
1054 | ) | ||
1055 | ); | ||
1056 | |||
972 | #endif /* _TRACE_NFS_H */ | 1057 | #endif /* _TRACE_NFS_H */ |
973 | 1058 | ||
974 | #undef TRACE_INCLUDE_PATH | 1059 | #undef TRACE_INCLUDE_PATH |
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index c74e4538d0eb..a9d24d5a967c 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -60,16 +60,6 @@ struct nfs4_cb_compound_hdr { | |||
60 | int status; | 60 | int status; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | /* | ||
64 | * Handle decode buffer overflows out-of-line. | ||
65 | */ | ||
66 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | ||
67 | { | ||
68 | dprintk("NFS: %s prematurely hit the end of our receive buffer. " | ||
69 | "Remaining buffer length is %tu words.\n", | ||
70 | func, xdr->end - xdr->p); | ||
71 | } | ||
72 | |||
73 | static __be32 *xdr_encode_empty_array(__be32 *p) | 63 | static __be32 *xdr_encode_empty_array(__be32 *p) |
74 | { | 64 | { |
75 | *p++ = xdr_zero; | 65 | *p++ = xdr_zero; |
@@ -240,7 +230,6 @@ static int decode_cb_op_status(struct xdr_stream *xdr, | |||
240 | *status = nfs_cb_stat_to_errno(be32_to_cpup(p)); | 230 | *status = nfs_cb_stat_to_errno(be32_to_cpup(p)); |
241 | return 0; | 231 | return 0; |
242 | out_overflow: | 232 | out_overflow: |
243 | print_overflow_msg(__func__, xdr); | ||
244 | return -EIO; | 233 | return -EIO; |
245 | out_unexpected: | 234 | out_unexpected: |
246 | dprintk("NFSD: Callback server returned operation %d but " | 235 | dprintk("NFSD: Callback server returned operation %d but " |
@@ -309,7 +298,6 @@ static int decode_cb_compound4res(struct xdr_stream *xdr, | |||
309 | hdr->nops = be32_to_cpup(p); | 298 | hdr->nops = be32_to_cpup(p); |
310 | return 0; | 299 | return 0; |
311 | out_overflow: | 300 | out_overflow: |
312 | print_overflow_msg(__func__, xdr); | ||
313 | return -EIO; | 301 | return -EIO; |
314 | } | 302 | } |
315 | 303 | ||
@@ -437,7 +425,6 @@ out: | |||
437 | cb->cb_seq_status = status; | 425 | cb->cb_seq_status = status; |
438 | return status; | 426 | return status; |
439 | out_overflow: | 427 | out_overflow: |
440 | print_overflow_msg(__func__, xdr); | ||
441 | status = -EIO; | 428 | status = -EIO; |
442 | goto out; | 429 | goto out; |
443 | } | 430 | } |
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index eed3cb16ccf1..5f9076fdb090 100644 --- a/include/linux/sunrpc/auth.h +++ b/include/linux/sunrpc/auth.h | |||
@@ -74,14 +74,12 @@ struct rpc_cred_cache; | |||
74 | struct rpc_authops; | 74 | struct rpc_authops; |
75 | struct rpc_auth { | 75 | struct rpc_auth { |
76 | unsigned int au_cslack; /* call cred size estimate */ | 76 | unsigned int au_cslack; /* call cred size estimate */ |
77 | /* guess at number of u32's auth adds before | 77 | unsigned int au_rslack; /* reply cred size estimate */ |
78 | * reply data; normally the verifier size: */ | 78 | unsigned int au_verfsize; /* size of reply verifier */ |
79 | unsigned int au_rslack; | 79 | unsigned int au_ralign; /* words before UL header */ |
80 | /* for gss, used to calculate au_rslack: */ | 80 | |
81 | unsigned int au_verfsize; | 81 | unsigned int au_flags; |
82 | 82 | const struct rpc_authops *au_ops; | |
83 | unsigned int au_flags; /* various flags */ | ||
84 | const struct rpc_authops *au_ops; /* operations */ | ||
85 | rpc_authflavor_t au_flavor; /* pseudoflavor (note may | 83 | rpc_authflavor_t au_flavor; /* pseudoflavor (note may |
86 | * differ from the flavor in | 84 | * differ from the flavor in |
87 | * au_ops->au_flavor in gss | 85 | * au_ops->au_flavor in gss |
@@ -131,13 +129,15 @@ struct rpc_credops { | |||
131 | void (*crdestroy)(struct rpc_cred *); | 129 | void (*crdestroy)(struct rpc_cred *); |
132 | 130 | ||
133 | int (*crmatch)(struct auth_cred *, struct rpc_cred *, int); | 131 | int (*crmatch)(struct auth_cred *, struct rpc_cred *, int); |
134 | __be32 * (*crmarshal)(struct rpc_task *, __be32 *); | 132 | int (*crmarshal)(struct rpc_task *task, |
133 | struct xdr_stream *xdr); | ||
135 | int (*crrefresh)(struct rpc_task *); | 134 | int (*crrefresh)(struct rpc_task *); |
136 | __be32 * (*crvalidate)(struct rpc_task *, __be32 *); | 135 | int (*crvalidate)(struct rpc_task *task, |
137 | int (*crwrap_req)(struct rpc_task *, kxdreproc_t, | 136 | struct xdr_stream *xdr); |
138 | void *, __be32 *, void *); | 137 | int (*crwrap_req)(struct rpc_task *task, |
139 | int (*crunwrap_resp)(struct rpc_task *, kxdrdproc_t, | 138 | struct xdr_stream *xdr); |
140 | void *, __be32 *, void *); | 139 | int (*crunwrap_resp)(struct rpc_task *task, |
140 | struct xdr_stream *xdr); | ||
141 | int (*crkey_timeout)(struct rpc_cred *); | 141 | int (*crkey_timeout)(struct rpc_cred *); |
142 | char * (*crstringify_acceptor)(struct rpc_cred *); | 142 | char * (*crstringify_acceptor)(struct rpc_cred *); |
143 | bool (*crneed_reencode)(struct rpc_task *); | 143 | bool (*crneed_reencode)(struct rpc_task *); |
@@ -165,10 +165,18 @@ struct rpc_cred * rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred * | |||
165 | void rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *); | 165 | void rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *); |
166 | struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, int); | 166 | struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, int); |
167 | void put_rpccred(struct rpc_cred *); | 167 | void put_rpccred(struct rpc_cred *); |
168 | __be32 * rpcauth_marshcred(struct rpc_task *, __be32 *); | 168 | int rpcauth_marshcred(struct rpc_task *task, |
169 | __be32 * rpcauth_checkverf(struct rpc_task *, __be32 *); | 169 | struct xdr_stream *xdr); |
170 | int rpcauth_wrap_req(struct rpc_task *task, kxdreproc_t encode, void *rqstp, __be32 *data, void *obj); | 170 | int rpcauth_checkverf(struct rpc_task *task, |
171 | int rpcauth_unwrap_resp(struct rpc_task *task, kxdrdproc_t decode, void *rqstp, __be32 *data, void *obj); | 171 | struct xdr_stream *xdr); |
172 | int rpcauth_wrap_req_encode(struct rpc_task *task, | ||
173 | struct xdr_stream *xdr); | ||
174 | int rpcauth_wrap_req(struct rpc_task *task, | ||
175 | struct xdr_stream *xdr); | ||
176 | int rpcauth_unwrap_resp_decode(struct rpc_task *task, | ||
177 | struct xdr_stream *xdr); | ||
178 | int rpcauth_unwrap_resp(struct rpc_task *task, | ||
179 | struct xdr_stream *xdr); | ||
172 | bool rpcauth_xmit_need_reencode(struct rpc_task *task); | 180 | bool rpcauth_xmit_need_reencode(struct rpc_task *task); |
173 | int rpcauth_refreshcred(struct rpc_task *); | 181 | int rpcauth_refreshcred(struct rpc_task *); |
174 | void rpcauth_invalcred(struct rpc_task *); | 182 | void rpcauth_invalcred(struct rpc_task *); |
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index 1c441714d569..98bc9883b230 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h | |||
@@ -169,6 +169,9 @@ int rpcb_v4_register(struct net *net, const u32 program, | |||
169 | const char *netid); | 169 | const char *netid); |
170 | void rpcb_getport_async(struct rpc_task *); | 170 | void rpcb_getport_async(struct rpc_task *); |
171 | 171 | ||
172 | void rpc_prepare_reply_pages(struct rpc_rqst *req, struct page **pages, | ||
173 | unsigned int base, unsigned int len, | ||
174 | unsigned int hdrsize); | ||
172 | void rpc_call_start(struct rpc_task *); | 175 | void rpc_call_start(struct rpc_task *); |
173 | int rpc_call_async(struct rpc_clnt *clnt, | 176 | int rpc_call_async(struct rpc_clnt *clnt, |
174 | const struct rpc_message *msg, int flags, | 177 | const struct rpc_message *msg, int flags, |
diff --git a/include/linux/sunrpc/gss_krb5_enctypes.h b/include/linux/sunrpc/gss_krb5_enctypes.h index ec6234eee89c..981c89cef19d 100644 --- a/include/linux/sunrpc/gss_krb5_enctypes.h +++ b/include/linux/sunrpc/gss_krb5_enctypes.h | |||
@@ -1,4 +1,44 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Dumb way to share this static piece of information with nfsd | 3 | * Define the string that exports the set of kernel-supported |
4 | * Kerberos enctypes. This list is sent via upcall to gssd, and | ||
5 | * is also exposed via the nfsd /proc API. The consumers generally | ||
6 | * treat this as an ordered list, where the first item in the list | ||
7 | * is the most preferred. | ||
8 | */ | ||
9 | |||
10 | #ifndef _LINUX_SUNRPC_GSS_KRB5_ENCTYPES_H | ||
11 | #define _LINUX_SUNRPC_GSS_KRB5_ENCTYPES_H | ||
12 | |||
13 | #ifdef CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES | ||
14 | |||
15 | /* | ||
16 | * NB: This list includes encryption types that were deprecated | ||
17 | * by RFC 8429 (DES3_CBC_SHA1 and ARCFOUR_HMAC). | ||
18 | * | ||
19 | * ENCTYPE_AES256_CTS_HMAC_SHA1_96 | ||
20 | * ENCTYPE_AES128_CTS_HMAC_SHA1_96 | ||
21 | * ENCTYPE_DES3_CBC_SHA1 | ||
22 | * ENCTYPE_ARCFOUR_HMAC | ||
23 | */ | ||
24 | #define KRB5_SUPPORTED_ENCTYPES "18,17,16,23" | ||
25 | |||
26 | #else /* CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES */ | ||
27 | |||
28 | /* | ||
29 | * NB: This list includes encryption types that were deprecated | ||
30 | * by RFC 8429 and RFC 6649. | ||
31 | * | ||
32 | * ENCTYPE_AES256_CTS_HMAC_SHA1_96 | ||
33 | * ENCTYPE_AES128_CTS_HMAC_SHA1_96 | ||
34 | * ENCTYPE_DES3_CBC_SHA1 | ||
35 | * ENCTYPE_ARCFOUR_HMAC | ||
36 | * ENCTYPE_DES_CBC_MD5 | ||
37 | * ENCTYPE_DES_CBC_CRC | ||
38 | * ENCTYPE_DES_CBC_MD4 | ||
3 | */ | 39 | */ |
4 | #define KRB5_SUPPORTED_ENCTYPES "18,17,16,23,3,1,2" | 40 | #define KRB5_SUPPORTED_ENCTYPES "18,17,16,23,3,1,2" |
41 | |||
42 | #endif /* CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES */ | ||
43 | |||
44 | #endif /* _LINUX_SUNRPC_GSS_KRB5_ENCTYPES_H */ | ||
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index 2ec128060239..9ee3970ba59c 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h | |||
@@ -87,6 +87,16 @@ xdr_buf_init(struct xdr_buf *buf, void *start, size_t len) | |||
87 | #define xdr_one cpu_to_be32(1) | 87 | #define xdr_one cpu_to_be32(1) |
88 | #define xdr_two cpu_to_be32(2) | 88 | #define xdr_two cpu_to_be32(2) |
89 | 89 | ||
90 | #define rpc_auth_null cpu_to_be32(RPC_AUTH_NULL) | ||
91 | #define rpc_auth_unix cpu_to_be32(RPC_AUTH_UNIX) | ||
92 | #define rpc_auth_short cpu_to_be32(RPC_AUTH_SHORT) | ||
93 | #define rpc_auth_gss cpu_to_be32(RPC_AUTH_GSS) | ||
94 | |||
95 | #define rpc_call cpu_to_be32(RPC_CALL) | ||
96 | #define rpc_reply cpu_to_be32(RPC_REPLY) | ||
97 | |||
98 | #define rpc_msg_accepted cpu_to_be32(RPC_MSG_ACCEPTED) | ||
99 | |||
90 | #define rpc_success cpu_to_be32(RPC_SUCCESS) | 100 | #define rpc_success cpu_to_be32(RPC_SUCCESS) |
91 | #define rpc_prog_unavail cpu_to_be32(RPC_PROG_UNAVAIL) | 101 | #define rpc_prog_unavail cpu_to_be32(RPC_PROG_UNAVAIL) |
92 | #define rpc_prog_mismatch cpu_to_be32(RPC_PROG_MISMATCH) | 102 | #define rpc_prog_mismatch cpu_to_be32(RPC_PROG_MISMATCH) |
@@ -95,6 +105,9 @@ xdr_buf_init(struct xdr_buf *buf, void *start, size_t len) | |||
95 | #define rpc_system_err cpu_to_be32(RPC_SYSTEM_ERR) | 105 | #define rpc_system_err cpu_to_be32(RPC_SYSTEM_ERR) |
96 | #define rpc_drop_reply cpu_to_be32(RPC_DROP_REPLY) | 106 | #define rpc_drop_reply cpu_to_be32(RPC_DROP_REPLY) |
97 | 107 | ||
108 | #define rpc_mismatch cpu_to_be32(RPC_MISMATCH) | ||
109 | #define rpc_auth_error cpu_to_be32(RPC_AUTH_ERROR) | ||
110 | |||
98 | #define rpc_auth_ok cpu_to_be32(RPC_AUTH_OK) | 111 | #define rpc_auth_ok cpu_to_be32(RPC_AUTH_OK) |
99 | #define rpc_autherr_badcred cpu_to_be32(RPC_AUTH_BADCRED) | 112 | #define rpc_autherr_badcred cpu_to_be32(RPC_AUTH_BADCRED) |
100 | #define rpc_autherr_rejectedcred cpu_to_be32(RPC_AUTH_REJECTEDCRED) | 113 | #define rpc_autherr_rejectedcred cpu_to_be32(RPC_AUTH_REJECTEDCRED) |
@@ -103,7 +116,6 @@ xdr_buf_init(struct xdr_buf *buf, void *start, size_t len) | |||
103 | #define rpc_autherr_tooweak cpu_to_be32(RPC_AUTH_TOOWEAK) | 116 | #define rpc_autherr_tooweak cpu_to_be32(RPC_AUTH_TOOWEAK) |
104 | #define rpcsec_gsserr_credproblem cpu_to_be32(RPCSEC_GSS_CREDPROBLEM) | 117 | #define rpcsec_gsserr_credproblem cpu_to_be32(RPCSEC_GSS_CREDPROBLEM) |
105 | #define rpcsec_gsserr_ctxproblem cpu_to_be32(RPCSEC_GSS_CTXPROBLEM) | 118 | #define rpcsec_gsserr_ctxproblem cpu_to_be32(RPCSEC_GSS_CTXPROBLEM) |
106 | #define rpc_autherr_oldseqnum cpu_to_be32(101) | ||
107 | 119 | ||
108 | /* | 120 | /* |
109 | * Miscellaneous XDR helper functions | 121 | * Miscellaneous XDR helper functions |
@@ -167,7 +179,6 @@ xdr_adjust_iovec(struct kvec *iov, __be32 *p) | |||
167 | extern void xdr_shift_buf(struct xdr_buf *, size_t); | 179 | extern void xdr_shift_buf(struct xdr_buf *, size_t); |
168 | extern void xdr_buf_from_iov(struct kvec *, struct xdr_buf *); | 180 | extern void xdr_buf_from_iov(struct kvec *, struct xdr_buf *); |
169 | extern int xdr_buf_subsegment(struct xdr_buf *, struct xdr_buf *, unsigned int, unsigned int); | 181 | extern int xdr_buf_subsegment(struct xdr_buf *, struct xdr_buf *, unsigned int, unsigned int); |
170 | extern void xdr_buf_trim(struct xdr_buf *, unsigned int); | ||
171 | extern int xdr_buf_read_netobj(struct xdr_buf *, struct xdr_netobj *, unsigned int); | 182 | extern int xdr_buf_read_netobj(struct xdr_buf *, struct xdr_netobj *, unsigned int); |
172 | extern int read_bytes_from_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int); | 183 | extern int read_bytes_from_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int); |
173 | extern int write_bytes_to_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int); | 184 | extern int write_bytes_to_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int); |
@@ -217,6 +228,8 @@ struct xdr_stream { | |||
217 | struct kvec scratch; /* Scratch buffer */ | 228 | struct kvec scratch; /* Scratch buffer */ |
218 | struct page **page_ptr; /* pointer to the current page */ | 229 | struct page **page_ptr; /* pointer to the current page */ |
219 | unsigned int nwords; /* Remaining decode buffer length */ | 230 | unsigned int nwords; /* Remaining decode buffer length */ |
231 | |||
232 | struct rpc_rqst *rqst; /* For debugging */ | ||
220 | }; | 233 | }; |
221 | 234 | ||
222 | /* | 235 | /* |
@@ -227,7 +240,8 @@ typedef void (*kxdreproc_t)(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
227 | typedef int (*kxdrdproc_t)(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 240 | typedef int (*kxdrdproc_t)(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
228 | void *obj); | 241 | void *obj); |
229 | 242 | ||
230 | extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p); | 243 | extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, |
244 | __be32 *p, struct rpc_rqst *rqst); | ||
231 | extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes); | 245 | extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes); |
232 | extern void xdr_commit_encode(struct xdr_stream *xdr); | 246 | extern void xdr_commit_encode(struct xdr_stream *xdr); |
233 | extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len); | 247 | extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len); |
@@ -235,7 +249,8 @@ extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen); | |||
235 | extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages, | 249 | extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages, |
236 | unsigned int base, unsigned int len); | 250 | unsigned int base, unsigned int len); |
237 | extern unsigned int xdr_stream_pos(const struct xdr_stream *xdr); | 251 | extern unsigned int xdr_stream_pos(const struct xdr_stream *xdr); |
238 | extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p); | 252 | extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, |
253 | __be32 *p, struct rpc_rqst *rqst); | ||
239 | extern void xdr_init_decode_pages(struct xdr_stream *xdr, struct xdr_buf *buf, | 254 | extern void xdr_init_decode_pages(struct xdr_stream *xdr, struct xdr_buf *buf, |
240 | struct page **pages, unsigned int len); | 255 | struct page **pages, unsigned int len); |
241 | extern void xdr_set_scratch_buffer(struct xdr_stream *xdr, void *buf, size_t buflen); | 256 | extern void xdr_set_scratch_buffer(struct xdr_stream *xdr, void *buf, size_t buflen); |
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index ad7e910b119d..3a391544299e 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h | |||
@@ -196,8 +196,6 @@ struct rpc_xprt { | |||
196 | 196 | ||
197 | size_t max_payload; /* largest RPC payload size, | 197 | size_t max_payload; /* largest RPC payload size, |
198 | in bytes */ | 198 | in bytes */ |
199 | unsigned int tsh_size; /* size of transport specific | ||
200 | header */ | ||
201 | 199 | ||
202 | struct rpc_wait_queue binding; /* requests waiting on rpcbind */ | 200 | struct rpc_wait_queue binding; /* requests waiting on rpcbind */ |
203 | struct rpc_wait_queue sending; /* requests waiting to send */ | 201 | struct rpc_wait_queue sending; /* requests waiting to send */ |
@@ -362,11 +360,6 @@ struct rpc_xprt * xprt_alloc(struct net *net, size_t size, | |||
362 | unsigned int max_req); | 360 | unsigned int max_req); |
363 | void xprt_free(struct rpc_xprt *); | 361 | void xprt_free(struct rpc_xprt *); |
364 | 362 | ||
365 | static inline __be32 *xprt_skip_transport_header(struct rpc_xprt *xprt, __be32 *p) | ||
366 | { | ||
367 | return p + xprt->tsh_size; | ||
368 | } | ||
369 | |||
370 | static inline int | 363 | static inline int |
371 | xprt_enable_swap(struct rpc_xprt *xprt) | 364 | xprt_enable_swap(struct rpc_xprt *xprt) |
372 | { | 365 | { |
diff --git a/include/trace/events/rpcgss.h b/include/trace/events/rpcgss.h new file mode 100644 index 000000000000..d1f7fe1b6fe4 --- /dev/null +++ b/include/trace/events/rpcgss.h | |||
@@ -0,0 +1,361 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * Copyright (c) 2018 Oracle. All rights reserved. | ||
4 | * | ||
5 | * Trace point definitions for the "rpcgss" subsystem. | ||
6 | */ | ||
7 | |||
8 | #undef TRACE_SYSTEM | ||
9 | #define TRACE_SYSTEM rpcgss | ||
10 | |||
11 | #if !defined(_TRACE_RPCRDMA_H) || defined(TRACE_HEADER_MULTI_READ) | ||
12 | #define _TRACE_RPCGSS_H | ||
13 | |||
14 | #include <linux/tracepoint.h> | ||
15 | |||
16 | /** | ||
17 | ** GSS-API related trace events | ||
18 | **/ | ||
19 | |||
20 | TRACE_DEFINE_ENUM(GSS_S_BAD_MECH); | ||
21 | TRACE_DEFINE_ENUM(GSS_S_BAD_NAME); | ||
22 | TRACE_DEFINE_ENUM(GSS_S_BAD_NAMETYPE); | ||
23 | TRACE_DEFINE_ENUM(GSS_S_BAD_BINDINGS); | ||
24 | TRACE_DEFINE_ENUM(GSS_S_BAD_STATUS); | ||
25 | TRACE_DEFINE_ENUM(GSS_S_BAD_SIG); | ||
26 | TRACE_DEFINE_ENUM(GSS_S_NO_CRED); | ||
27 | TRACE_DEFINE_ENUM(GSS_S_NO_CONTEXT); | ||
28 | TRACE_DEFINE_ENUM(GSS_S_DEFECTIVE_TOKEN); | ||
29 | TRACE_DEFINE_ENUM(GSS_S_DEFECTIVE_CREDENTIAL); | ||
30 | TRACE_DEFINE_ENUM(GSS_S_CREDENTIALS_EXPIRED); | ||
31 | TRACE_DEFINE_ENUM(GSS_S_CONTEXT_EXPIRED); | ||
32 | TRACE_DEFINE_ENUM(GSS_S_FAILURE); | ||
33 | TRACE_DEFINE_ENUM(GSS_S_BAD_QOP); | ||
34 | TRACE_DEFINE_ENUM(GSS_S_UNAUTHORIZED); | ||
35 | TRACE_DEFINE_ENUM(GSS_S_UNAVAILABLE); | ||
36 | TRACE_DEFINE_ENUM(GSS_S_DUPLICATE_ELEMENT); | ||
37 | TRACE_DEFINE_ENUM(GSS_S_NAME_NOT_MN); | ||
38 | TRACE_DEFINE_ENUM(GSS_S_CONTINUE_NEEDED); | ||
39 | TRACE_DEFINE_ENUM(GSS_S_DUPLICATE_TOKEN); | ||
40 | TRACE_DEFINE_ENUM(GSS_S_OLD_TOKEN); | ||
41 | TRACE_DEFINE_ENUM(GSS_S_UNSEQ_TOKEN); | ||
42 | TRACE_DEFINE_ENUM(GSS_S_GAP_TOKEN); | ||
43 | |||
44 | #define show_gss_status(x) \ | ||
45 | __print_flags(x, "|", \ | ||
46 | { GSS_S_BAD_MECH, "GSS_S_BAD_MECH" }, \ | ||
47 | { GSS_S_BAD_NAME, "GSS_S_BAD_NAME" }, \ | ||
48 | { GSS_S_BAD_NAMETYPE, "GSS_S_BAD_NAMETYPE" }, \ | ||
49 | { GSS_S_BAD_BINDINGS, "GSS_S_BAD_BINDINGS" }, \ | ||
50 | { GSS_S_BAD_STATUS, "GSS_S_BAD_STATUS" }, \ | ||
51 | { GSS_S_BAD_SIG, "GSS_S_BAD_SIG" }, \ | ||
52 | { GSS_S_NO_CRED, "GSS_S_NO_CRED" }, \ | ||
53 | { GSS_S_NO_CONTEXT, "GSS_S_NO_CONTEXT" }, \ | ||
54 | { GSS_S_DEFECTIVE_TOKEN, "GSS_S_DEFECTIVE_TOKEN" }, \ | ||
55 | { GSS_S_DEFECTIVE_CREDENTIAL, "GSS_S_DEFECTIVE_CREDENTIAL" }, \ | ||
56 | { GSS_S_CREDENTIALS_EXPIRED, "GSS_S_CREDENTIALS_EXPIRED" }, \ | ||
57 | { GSS_S_CONTEXT_EXPIRED, "GSS_S_CONTEXT_EXPIRED" }, \ | ||
58 | { GSS_S_FAILURE, "GSS_S_FAILURE" }, \ | ||
59 | { GSS_S_BAD_QOP, "GSS_S_BAD_QOP" }, \ | ||
60 | { GSS_S_UNAUTHORIZED, "GSS_S_UNAUTHORIZED" }, \ | ||
61 | { GSS_S_UNAVAILABLE, "GSS_S_UNAVAILABLE" }, \ | ||
62 | { GSS_S_DUPLICATE_ELEMENT, "GSS_S_DUPLICATE_ELEMENT" }, \ | ||
63 | { GSS_S_NAME_NOT_MN, "GSS_S_NAME_NOT_MN" }, \ | ||
64 | { GSS_S_CONTINUE_NEEDED, "GSS_S_CONTINUE_NEEDED" }, \ | ||
65 | { GSS_S_DUPLICATE_TOKEN, "GSS_S_DUPLICATE_TOKEN" }, \ | ||
66 | { GSS_S_OLD_TOKEN, "GSS_S_OLD_TOKEN" }, \ | ||
67 | { GSS_S_UNSEQ_TOKEN, "GSS_S_UNSEQ_TOKEN" }, \ | ||
68 | { GSS_S_GAP_TOKEN, "GSS_S_GAP_TOKEN" }) | ||
69 | |||
70 | |||
71 | DECLARE_EVENT_CLASS(rpcgss_gssapi_event, | ||
72 | TP_PROTO( | ||
73 | const struct rpc_task *task, | ||
74 | u32 maj_stat | ||
75 | ), | ||
76 | |||
77 | TP_ARGS(task, maj_stat), | ||
78 | |||
79 | TP_STRUCT__entry( | ||
80 | __field(unsigned int, task_id) | ||
81 | __field(unsigned int, client_id) | ||
82 | __field(u32, maj_stat) | ||
83 | |||
84 | ), | ||
85 | |||
86 | TP_fast_assign( | ||
87 | __entry->task_id = task->tk_pid; | ||
88 | __entry->client_id = task->tk_client->cl_clid; | ||
89 | __entry->maj_stat = maj_stat; | ||
90 | ), | ||
91 | |||
92 | TP_printk("task:%u@%u maj_stat=%s", | ||
93 | __entry->task_id, __entry->client_id, | ||
94 | __entry->maj_stat == 0 ? | ||
95 | "GSS_S_COMPLETE" : show_gss_status(__entry->maj_stat)) | ||
96 | ); | ||
97 | |||
98 | #define DEFINE_GSSAPI_EVENT(name) \ | ||
99 | DEFINE_EVENT(rpcgss_gssapi_event, rpcgss_##name, \ | ||
100 | TP_PROTO( \ | ||
101 | const struct rpc_task *task, \ | ||
102 | u32 maj_stat \ | ||
103 | ), \ | ||
104 | TP_ARGS(task, maj_stat)) | ||
105 | |||
106 | TRACE_EVENT(rpcgss_import_ctx, | ||
107 | TP_PROTO( | ||
108 | int status | ||
109 | ), | ||
110 | |||
111 | TP_ARGS(status), | ||
112 | |||
113 | TP_STRUCT__entry( | ||
114 | __field(int, status) | ||
115 | ), | ||
116 | |||
117 | TP_fast_assign( | ||
118 | __entry->status = status; | ||
119 | ), | ||
120 | |||
121 | TP_printk("status=%d", __entry->status) | ||
122 | ); | ||
123 | |||
124 | DEFINE_GSSAPI_EVENT(get_mic); | ||
125 | DEFINE_GSSAPI_EVENT(verify_mic); | ||
126 | DEFINE_GSSAPI_EVENT(wrap); | ||
127 | DEFINE_GSSAPI_EVENT(unwrap); | ||
128 | |||
129 | |||
130 | /** | ||
131 | ** GSS auth unwrap failures | ||
132 | **/ | ||
133 | |||
134 | TRACE_EVENT(rpcgss_unwrap_failed, | ||
135 | TP_PROTO( | ||
136 | const struct rpc_task *task | ||
137 | ), | ||
138 | |||
139 | TP_ARGS(task), | ||
140 | |||
141 | TP_STRUCT__entry( | ||
142 | __field(unsigned int, task_id) | ||
143 | __field(unsigned int, client_id) | ||
144 | ), | ||
145 | |||
146 | TP_fast_assign( | ||
147 | __entry->task_id = task->tk_pid; | ||
148 | __entry->client_id = task->tk_client->cl_clid; | ||
149 | ), | ||
150 | |||
151 | TP_printk("task:%u@%u", __entry->task_id, __entry->client_id) | ||
152 | ); | ||
153 | |||
154 | TRACE_EVENT(rpcgss_bad_seqno, | ||
155 | TP_PROTO( | ||
156 | const struct rpc_task *task, | ||
157 | u32 expected, | ||
158 | u32 received | ||
159 | ), | ||
160 | |||
161 | TP_ARGS(task, expected, received), | ||
162 | |||
163 | TP_STRUCT__entry( | ||
164 | __field(unsigned int, task_id) | ||
165 | __field(unsigned int, client_id) | ||
166 | __field(u32, expected) | ||
167 | __field(u32, received) | ||
168 | ), | ||
169 | |||
170 | TP_fast_assign( | ||
171 | __entry->task_id = task->tk_pid; | ||
172 | __entry->client_id = task->tk_client->cl_clid; | ||
173 | __entry->expected = expected; | ||
174 | __entry->received = received; | ||
175 | ), | ||
176 | |||
177 | TP_printk("task:%u@%u expected seqno %u, received seqno %u", | ||
178 | __entry->task_id, __entry->client_id, | ||
179 | __entry->expected, __entry->received) | ||
180 | ); | ||
181 | |||
182 | TRACE_EVENT(rpcgss_seqno, | ||
183 | TP_PROTO( | ||
184 | const struct rpc_task *task | ||
185 | ), | ||
186 | |||
187 | TP_ARGS(task), | ||
188 | |||
189 | TP_STRUCT__entry( | ||
190 | __field(unsigned int, task_id) | ||
191 | __field(unsigned int, client_id) | ||
192 | __field(u32, xid) | ||
193 | __field(u32, seqno) | ||
194 | ), | ||
195 | |||
196 | TP_fast_assign( | ||
197 | const struct rpc_rqst *rqst = task->tk_rqstp; | ||
198 | |||
199 | __entry->task_id = task->tk_pid; | ||
200 | __entry->client_id = task->tk_client->cl_clid; | ||
201 | __entry->xid = be32_to_cpu(rqst->rq_xid); | ||
202 | __entry->seqno = rqst->rq_seqno; | ||
203 | ), | ||
204 | |||
205 | TP_printk("task:%u@%u xid=0x%08x seqno=%u", | ||
206 | __entry->task_id, __entry->client_id, | ||
207 | __entry->xid, __entry->seqno) | ||
208 | ); | ||
209 | |||
210 | TRACE_EVENT(rpcgss_need_reencode, | ||
211 | TP_PROTO( | ||
212 | const struct rpc_task *task, | ||
213 | u32 seq_xmit, | ||
214 | bool ret | ||
215 | ), | ||
216 | |||
217 | TP_ARGS(task, seq_xmit, ret), | ||
218 | |||
219 | TP_STRUCT__entry( | ||
220 | __field(unsigned int, task_id) | ||
221 | __field(unsigned int, client_id) | ||
222 | __field(u32, xid) | ||
223 | __field(u32, seq_xmit) | ||
224 | __field(u32, seqno) | ||
225 | __field(bool, ret) | ||
226 | ), | ||
227 | |||
228 | TP_fast_assign( | ||
229 | __entry->task_id = task->tk_pid; | ||
230 | __entry->client_id = task->tk_client->cl_clid; | ||
231 | __entry->xid = be32_to_cpu(task->tk_rqstp->rq_xid); | ||
232 | __entry->seq_xmit = seq_xmit; | ||
233 | __entry->seqno = task->tk_rqstp->rq_seqno; | ||
234 | __entry->ret = ret; | ||
235 | ), | ||
236 | |||
237 | TP_printk("task:%u@%u xid=0x%08x rq_seqno=%u seq_xmit=%u reencode %sneeded", | ||
238 | __entry->task_id, __entry->client_id, | ||
239 | __entry->xid, __entry->seqno, __entry->seq_xmit, | ||
240 | __entry->ret ? "" : "un") | ||
241 | ); | ||
242 | |||
243 | /** | ||
244 | ** gssd upcall related trace events | ||
245 | **/ | ||
246 | |||
247 | TRACE_EVENT(rpcgss_upcall_msg, | ||
248 | TP_PROTO( | ||
249 | const char *buf | ||
250 | ), | ||
251 | |||
252 | TP_ARGS(buf), | ||
253 | |||
254 | TP_STRUCT__entry( | ||
255 | __string(msg, buf) | ||
256 | ), | ||
257 | |||
258 | TP_fast_assign( | ||
259 | __assign_str(msg, buf) | ||
260 | ), | ||
261 | |||
262 | TP_printk("msg='%s'", __get_str(msg)) | ||
263 | ); | ||
264 | |||
265 | TRACE_EVENT(rpcgss_upcall_result, | ||
266 | TP_PROTO( | ||
267 | u32 uid, | ||
268 | int result | ||
269 | ), | ||
270 | |||
271 | TP_ARGS(uid, result), | ||
272 | |||
273 | TP_STRUCT__entry( | ||
274 | __field(u32, uid) | ||
275 | __field(int, result) | ||
276 | |||
277 | ), | ||
278 | |||
279 | TP_fast_assign( | ||
280 | __entry->uid = uid; | ||
281 | __entry->result = result; | ||
282 | ), | ||
283 | |||
284 | TP_printk("for uid %u, result=%d", __entry->uid, __entry->result) | ||
285 | ); | ||
286 | |||
287 | TRACE_EVENT(rpcgss_context, | ||
288 | TP_PROTO( | ||
289 | unsigned long expiry, | ||
290 | unsigned long now, | ||
291 | unsigned int timeout, | ||
292 | unsigned int len, | ||
293 | const u8 *data | ||
294 | ), | ||
295 | |||
296 | TP_ARGS(expiry, now, timeout, len, data), | ||
297 | |||
298 | TP_STRUCT__entry( | ||
299 | __field(unsigned long, expiry) | ||
300 | __field(unsigned long, now) | ||
301 | __field(unsigned int, timeout) | ||
302 | __field(int, len) | ||
303 | __string(acceptor, data) | ||
304 | ), | ||
305 | |||
306 | TP_fast_assign( | ||
307 | __entry->expiry = expiry; | ||
308 | __entry->now = now; | ||
309 | __entry->timeout = timeout; | ||
310 | __entry->len = len; | ||
311 | strncpy(__get_str(acceptor), data, len); | ||
312 | ), | ||
313 | |||
314 | TP_printk("gc_expiry=%lu now=%lu timeout=%u acceptor=%.*s", | ||
315 | __entry->expiry, __entry->now, __entry->timeout, | ||
316 | __entry->len, __get_str(acceptor)) | ||
317 | ); | ||
318 | |||
319 | |||
320 | /** | ||
321 | ** Miscellaneous events | ||
322 | */ | ||
323 | |||
324 | TRACE_DEFINE_ENUM(RPC_AUTH_GSS_KRB5); | ||
325 | TRACE_DEFINE_ENUM(RPC_AUTH_GSS_KRB5I); | ||
326 | TRACE_DEFINE_ENUM(RPC_AUTH_GSS_KRB5P); | ||
327 | |||
328 | #define show_pseudoflavor(x) \ | ||
329 | __print_symbolic(x, \ | ||
330 | { RPC_AUTH_GSS_KRB5, "RPC_AUTH_GSS_KRB5" }, \ | ||
331 | { RPC_AUTH_GSS_KRB5I, "RPC_AUTH_GSS_KRB5I" }, \ | ||
332 | { RPC_AUTH_GSS_KRB5P, "RPC_AUTH_GSS_KRB5P" }) | ||
333 | |||
334 | |||
335 | TRACE_EVENT(rpcgss_createauth, | ||
336 | TP_PROTO( | ||
337 | unsigned int flavor, | ||
338 | int error | ||
339 | ), | ||
340 | |||
341 | TP_ARGS(flavor, error), | ||
342 | |||
343 | TP_STRUCT__entry( | ||
344 | __field(unsigned int, flavor) | ||
345 | __field(int, error) | ||
346 | |||
347 | ), | ||
348 | |||
349 | TP_fast_assign( | ||
350 | __entry->flavor = flavor; | ||
351 | __entry->error = error; | ||
352 | ), | ||
353 | |||
354 | TP_printk("flavor=%s error=%d", | ||
355 | show_pseudoflavor(__entry->flavor), __entry->error) | ||
356 | ); | ||
357 | |||
358 | |||
359 | #endif /* _TRACE_RPCGSS_H */ | ||
360 | |||
361 | #include <trace/define_trace.h> | ||
diff --git a/include/trace/events/rpcrdma.h b/include/trace/events/rpcrdma.h index 399b1aedc927..962975b4313f 100644 --- a/include/trace/events/rpcrdma.h +++ b/include/trace/events/rpcrdma.h | |||
@@ -521,12 +521,18 @@ TRACE_EVENT(xprtrdma_post_send, | |||
521 | 521 | ||
522 | TP_STRUCT__entry( | 522 | TP_STRUCT__entry( |
523 | __field(const void *, req) | 523 | __field(const void *, req) |
524 | __field(unsigned int, task_id) | ||
525 | __field(unsigned int, client_id) | ||
524 | __field(int, num_sge) | 526 | __field(int, num_sge) |
525 | __field(int, signaled) | 527 | __field(int, signaled) |
526 | __field(int, status) | 528 | __field(int, status) |
527 | ), | 529 | ), |
528 | 530 | ||
529 | TP_fast_assign( | 531 | TP_fast_assign( |
532 | const struct rpc_rqst *rqst = &req->rl_slot; | ||
533 | |||
534 | __entry->task_id = rqst->rq_task->tk_pid; | ||
535 | __entry->client_id = rqst->rq_task->tk_client->cl_clid; | ||
530 | __entry->req = req; | 536 | __entry->req = req; |
531 | __entry->num_sge = req->rl_sendctx->sc_wr.num_sge; | 537 | __entry->num_sge = req->rl_sendctx->sc_wr.num_sge; |
532 | __entry->signaled = req->rl_sendctx->sc_wr.send_flags & | 538 | __entry->signaled = req->rl_sendctx->sc_wr.send_flags & |
@@ -534,9 +540,11 @@ TRACE_EVENT(xprtrdma_post_send, | |||
534 | __entry->status = status; | 540 | __entry->status = status; |
535 | ), | 541 | ), |
536 | 542 | ||
537 | TP_printk("req=%p, %d SGEs%s, status=%d", | 543 | TP_printk("task:%u@%u req=%p (%d SGE%s) %sstatus=%d", |
544 | __entry->task_id, __entry->client_id, | ||
538 | __entry->req, __entry->num_sge, | 545 | __entry->req, __entry->num_sge, |
539 | (__entry->signaled ? ", signaled" : ""), | 546 | (__entry->num_sge == 1 ? "" : "s"), |
547 | (__entry->signaled ? "signaled " : ""), | ||
540 | __entry->status | 548 | __entry->status |
541 | ) | 549 | ) |
542 | ); | 550 | ); |
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h index 0d5d0d91f861..8451f30c6a0f 100644 --- a/include/trace/events/sunrpc.h +++ b/include/trace/events/sunrpc.h | |||
@@ -77,6 +77,50 @@ TRACE_EVENT(rpc_request, | |||
77 | ) | 77 | ) |
78 | ); | 78 | ); |
79 | 79 | ||
80 | TRACE_DEFINE_ENUM(RPC_TASK_ASYNC); | ||
81 | TRACE_DEFINE_ENUM(RPC_TASK_SWAPPER); | ||
82 | TRACE_DEFINE_ENUM(RPC_CALL_MAJORSEEN); | ||
83 | TRACE_DEFINE_ENUM(RPC_TASK_ROOTCREDS); | ||
84 | TRACE_DEFINE_ENUM(RPC_TASK_DYNAMIC); | ||
85 | TRACE_DEFINE_ENUM(RPC_TASK_KILLED); | ||
86 | TRACE_DEFINE_ENUM(RPC_TASK_SOFT); | ||
87 | TRACE_DEFINE_ENUM(RPC_TASK_SOFTCONN); | ||
88 | TRACE_DEFINE_ENUM(RPC_TASK_SENT); | ||
89 | TRACE_DEFINE_ENUM(RPC_TASK_TIMEOUT); | ||
90 | TRACE_DEFINE_ENUM(RPC_TASK_NOCONNECT); | ||
91 | TRACE_DEFINE_ENUM(RPC_TASK_NO_RETRANS_TIMEOUT); | ||
92 | |||
93 | #define rpc_show_task_flags(flags) \ | ||
94 | __print_flags(flags, "|", \ | ||
95 | { RPC_TASK_ASYNC, "ASYNC" }, \ | ||
96 | { RPC_TASK_SWAPPER, "SWAPPER" }, \ | ||
97 | { RPC_CALL_MAJORSEEN, "MAJORSEEN" }, \ | ||
98 | { RPC_TASK_ROOTCREDS, "ROOTCREDS" }, \ | ||
99 | { RPC_TASK_DYNAMIC, "DYNAMIC" }, \ | ||
100 | { RPC_TASK_KILLED, "KILLED" }, \ | ||
101 | { RPC_TASK_SOFT, "SOFT" }, \ | ||
102 | { RPC_TASK_SOFTCONN, "SOFTCONN" }, \ | ||
103 | { RPC_TASK_SENT, "SENT" }, \ | ||
104 | { RPC_TASK_TIMEOUT, "TIMEOUT" }, \ | ||
105 | { RPC_TASK_NOCONNECT, "NOCONNECT" }, \ | ||
106 | { RPC_TASK_NO_RETRANS_TIMEOUT, "NORTO" }) | ||
107 | |||
108 | TRACE_DEFINE_ENUM(RPC_TASK_RUNNING); | ||
109 | TRACE_DEFINE_ENUM(RPC_TASK_QUEUED); | ||
110 | TRACE_DEFINE_ENUM(RPC_TASK_ACTIVE); | ||
111 | TRACE_DEFINE_ENUM(RPC_TASK_NEED_XMIT); | ||
112 | TRACE_DEFINE_ENUM(RPC_TASK_NEED_RECV); | ||
113 | TRACE_DEFINE_ENUM(RPC_TASK_MSG_PIN_WAIT); | ||
114 | |||
115 | #define rpc_show_runstate(flags) \ | ||
116 | __print_flags(flags, "|", \ | ||
117 | { (1UL << RPC_TASK_RUNNING), "RUNNING" }, \ | ||
118 | { (1UL << RPC_TASK_QUEUED), "QUEUED" }, \ | ||
119 | { (1UL << RPC_TASK_ACTIVE), "ACTIVE" }, \ | ||
120 | { (1UL << RPC_TASK_NEED_XMIT), "NEED_XMIT" }, \ | ||
121 | { (1UL << RPC_TASK_NEED_RECV), "NEED_RECV" }, \ | ||
122 | { (1UL << RPC_TASK_MSG_PIN_WAIT), "MSG_PIN_WAIT" }) | ||
123 | |||
80 | DECLARE_EVENT_CLASS(rpc_task_running, | 124 | DECLARE_EVENT_CLASS(rpc_task_running, |
81 | 125 | ||
82 | TP_PROTO(const struct rpc_task *task, const void *action), | 126 | TP_PROTO(const struct rpc_task *task, const void *action), |
@@ -102,10 +146,10 @@ DECLARE_EVENT_CLASS(rpc_task_running, | |||
102 | __entry->flags = task->tk_flags; | 146 | __entry->flags = task->tk_flags; |
103 | ), | 147 | ), |
104 | 148 | ||
105 | TP_printk("task:%u@%d flags=%4.4x state=%4.4lx status=%d action=%pf", | 149 | TP_printk("task:%u@%d flags=%s runstate=%s status=%d action=%pf", |
106 | __entry->task_id, __entry->client_id, | 150 | __entry->task_id, __entry->client_id, |
107 | __entry->flags, | 151 | rpc_show_task_flags(__entry->flags), |
108 | __entry->runstate, | 152 | rpc_show_runstate(__entry->runstate), |
109 | __entry->status, | 153 | __entry->status, |
110 | __entry->action | 154 | __entry->action |
111 | ) | 155 | ) |
@@ -149,10 +193,10 @@ DECLARE_EVENT_CLASS(rpc_task_queued, | |||
149 | __assign_str(q_name, rpc_qname(q)); | 193 | __assign_str(q_name, rpc_qname(q)); |
150 | ), | 194 | ), |
151 | 195 | ||
152 | TP_printk("task:%u@%d flags=%4.4x state=%4.4lx status=%d timeout=%lu queue=%s", | 196 | TP_printk("task:%u@%d flags=%s runstate=%s status=%d timeout=%lu queue=%s", |
153 | __entry->task_id, __entry->client_id, | 197 | __entry->task_id, __entry->client_id, |
154 | __entry->flags, | 198 | rpc_show_task_flags(__entry->flags), |
155 | __entry->runstate, | 199 | rpc_show_runstate(__entry->runstate), |
156 | __entry->status, | 200 | __entry->status, |
157 | __entry->timeout, | 201 | __entry->timeout, |
158 | __get_str(q_name) | 202 | __get_str(q_name) |
@@ -169,6 +213,87 @@ DECLARE_EVENT_CLASS(rpc_task_queued, | |||
169 | DEFINE_RPC_QUEUED_EVENT(sleep); | 213 | DEFINE_RPC_QUEUED_EVENT(sleep); |
170 | DEFINE_RPC_QUEUED_EVENT(wakeup); | 214 | DEFINE_RPC_QUEUED_EVENT(wakeup); |
171 | 215 | ||
216 | DECLARE_EVENT_CLASS(rpc_failure, | ||
217 | |||
218 | TP_PROTO(const struct rpc_task *task), | ||
219 | |||
220 | TP_ARGS(task), | ||
221 | |||
222 | TP_STRUCT__entry( | ||
223 | __field(unsigned int, task_id) | ||
224 | __field(unsigned int, client_id) | ||
225 | ), | ||
226 | |||
227 | TP_fast_assign( | ||
228 | __entry->task_id = task->tk_pid; | ||
229 | __entry->client_id = task->tk_client->cl_clid; | ||
230 | ), | ||
231 | |||
232 | TP_printk("task:%u@%u", | ||
233 | __entry->task_id, __entry->client_id) | ||
234 | ); | ||
235 | |||
236 | #define DEFINE_RPC_FAILURE(name) \ | ||
237 | DEFINE_EVENT(rpc_failure, rpc_bad_##name, \ | ||
238 | TP_PROTO( \ | ||
239 | const struct rpc_task *task \ | ||
240 | ), \ | ||
241 | TP_ARGS(task)) | ||
242 | |||
243 | DEFINE_RPC_FAILURE(callhdr); | ||
244 | DEFINE_RPC_FAILURE(verifier); | ||
245 | |||
246 | DECLARE_EVENT_CLASS(rpc_reply_event, | ||
247 | |||
248 | TP_PROTO( | ||
249 | const struct rpc_task *task | ||
250 | ), | ||
251 | |||
252 | TP_ARGS(task), | ||
253 | |||
254 | TP_STRUCT__entry( | ||
255 | __field(unsigned int, task_id) | ||
256 | __field(unsigned int, client_id) | ||
257 | __field(u32, xid) | ||
258 | __string(progname, task->tk_client->cl_program->name) | ||
259 | __field(u32, version) | ||
260 | __string(procname, rpc_proc_name(task)) | ||
261 | __string(servername, task->tk_xprt->servername) | ||
262 | ), | ||
263 | |||
264 | TP_fast_assign( | ||
265 | __entry->task_id = task->tk_pid; | ||
266 | __entry->client_id = task->tk_client->cl_clid; | ||
267 | __entry->xid = be32_to_cpu(task->tk_rqstp->rq_xid); | ||
268 | __assign_str(progname, task->tk_client->cl_program->name) | ||
269 | __entry->version = task->tk_client->cl_vers; | ||
270 | __assign_str(procname, rpc_proc_name(task)) | ||
271 | __assign_str(servername, task->tk_xprt->servername) | ||
272 | ), | ||
273 | |||
274 | TP_printk("task:%u@%d server=%s xid=0x%08x %sv%d %s", | ||
275 | __entry->task_id, __entry->client_id, __get_str(servername), | ||
276 | __entry->xid, __get_str(progname), __entry->version, | ||
277 | __get_str(procname)) | ||
278 | ) | ||
279 | |||
280 | #define DEFINE_RPC_REPLY_EVENT(name) \ | ||
281 | DEFINE_EVENT(rpc_reply_event, rpc__##name, \ | ||
282 | TP_PROTO( \ | ||
283 | const struct rpc_task *task \ | ||
284 | ), \ | ||
285 | TP_ARGS(task)) | ||
286 | |||
287 | DEFINE_RPC_REPLY_EVENT(prog_unavail); | ||
288 | DEFINE_RPC_REPLY_EVENT(prog_mismatch); | ||
289 | DEFINE_RPC_REPLY_EVENT(proc_unavail); | ||
290 | DEFINE_RPC_REPLY_EVENT(garbage_args); | ||
291 | DEFINE_RPC_REPLY_EVENT(unparsable); | ||
292 | DEFINE_RPC_REPLY_EVENT(mismatch); | ||
293 | DEFINE_RPC_REPLY_EVENT(stale_creds); | ||
294 | DEFINE_RPC_REPLY_EVENT(bad_creds); | ||
295 | DEFINE_RPC_REPLY_EVENT(auth_tooweak); | ||
296 | |||
172 | TRACE_EVENT(rpc_stats_latency, | 297 | TRACE_EVENT(rpc_stats_latency, |
173 | 298 | ||
174 | TP_PROTO( | 299 | TP_PROTO( |
@@ -210,6 +335,169 @@ TRACE_EVENT(rpc_stats_latency, | |||
210 | __entry->backlog, __entry->rtt, __entry->execute) | 335 | __entry->backlog, __entry->rtt, __entry->execute) |
211 | ); | 336 | ); |
212 | 337 | ||
338 | TRACE_EVENT(rpc_xdr_overflow, | ||
339 | TP_PROTO( | ||
340 | const struct xdr_stream *xdr, | ||
341 | size_t requested | ||
342 | ), | ||
343 | |||
344 | TP_ARGS(xdr, requested), | ||
345 | |||
346 | TP_STRUCT__entry( | ||
347 | __field(unsigned int, task_id) | ||
348 | __field(unsigned int, client_id) | ||
349 | __field(int, version) | ||
350 | __field(size_t, requested) | ||
351 | __field(const void *, end) | ||
352 | __field(const void *, p) | ||
353 | __field(const void *, head_base) | ||
354 | __field(size_t, head_len) | ||
355 | __field(const void *, tail_base) | ||
356 | __field(size_t, tail_len) | ||
357 | __field(unsigned int, page_len) | ||
358 | __field(unsigned int, len) | ||
359 | __string(progname, | ||
360 | xdr->rqst->rq_task->tk_client->cl_program->name) | ||
361 | __string(procedure, | ||
362 | xdr->rqst->rq_task->tk_msg.rpc_proc->p_name) | ||
363 | ), | ||
364 | |||
365 | TP_fast_assign( | ||
366 | if (xdr->rqst) { | ||
367 | const struct rpc_task *task = xdr->rqst->rq_task; | ||
368 | |||
369 | __entry->task_id = task->tk_pid; | ||
370 | __entry->client_id = task->tk_client->cl_clid; | ||
371 | __assign_str(progname, | ||
372 | task->tk_client->cl_program->name) | ||
373 | __entry->version = task->tk_client->cl_vers; | ||
374 | __assign_str(procedure, task->tk_msg.rpc_proc->p_name) | ||
375 | } else { | ||
376 | __entry->task_id = 0; | ||
377 | __entry->client_id = 0; | ||
378 | __assign_str(progname, "unknown") | ||
379 | __entry->version = 0; | ||
380 | __assign_str(procedure, "unknown") | ||
381 | } | ||
382 | __entry->requested = requested; | ||
383 | __entry->end = xdr->end; | ||
384 | __entry->p = xdr->p; | ||
385 | __entry->head_base = xdr->buf->head[0].iov_base, | ||
386 | __entry->head_len = xdr->buf->head[0].iov_len, | ||
387 | __entry->page_len = xdr->buf->page_len, | ||
388 | __entry->tail_base = xdr->buf->tail[0].iov_base, | ||
389 | __entry->tail_len = xdr->buf->tail[0].iov_len, | ||
390 | __entry->len = xdr->buf->len; | ||
391 | ), | ||
392 | |||
393 | TP_printk( | ||
394 | "task:%u@%u %sv%d %s requested=%zu p=%p end=%p xdr=[%p,%zu]/%u/[%p,%zu]/%u\n", | ||
395 | __entry->task_id, __entry->client_id, | ||
396 | __get_str(progname), __entry->version, __get_str(procedure), | ||
397 | __entry->requested, __entry->p, __entry->end, | ||
398 | __entry->head_base, __entry->head_len, | ||
399 | __entry->page_len, | ||
400 | __entry->tail_base, __entry->tail_len, | ||
401 | __entry->len | ||
402 | ) | ||
403 | ); | ||
404 | |||
405 | TRACE_EVENT(rpc_xdr_alignment, | ||
406 | TP_PROTO( | ||
407 | const struct xdr_stream *xdr, | ||
408 | size_t offset, | ||
409 | unsigned int copied | ||
410 | ), | ||
411 | |||
412 | TP_ARGS(xdr, offset, copied), | ||
413 | |||
414 | TP_STRUCT__entry( | ||
415 | __field(unsigned int, task_id) | ||
416 | __field(unsigned int, client_id) | ||
417 | __field(int, version) | ||
418 | __field(size_t, offset) | ||
419 | __field(unsigned int, copied) | ||
420 | __field(const void *, head_base) | ||
421 | __field(size_t, head_len) | ||
422 | __field(const void *, tail_base) | ||
423 | __field(size_t, tail_len) | ||
424 | __field(unsigned int, page_len) | ||
425 | __field(unsigned int, len) | ||
426 | __string(progname, | ||
427 | xdr->rqst->rq_task->tk_client->cl_program->name) | ||
428 | __string(procedure, | ||
429 | xdr->rqst->rq_task->tk_msg.rpc_proc->p_name) | ||
430 | ), | ||
431 | |||
432 | TP_fast_assign( | ||
433 | const struct rpc_task *task = xdr->rqst->rq_task; | ||
434 | |||
435 | __entry->task_id = task->tk_pid; | ||
436 | __entry->client_id = task->tk_client->cl_clid; | ||
437 | __assign_str(progname, | ||
438 | task->tk_client->cl_program->name) | ||
439 | __entry->version = task->tk_client->cl_vers; | ||
440 | __assign_str(procedure, task->tk_msg.rpc_proc->p_name) | ||
441 | |||
442 | __entry->offset = offset; | ||
443 | __entry->copied = copied; | ||
444 | __entry->head_base = xdr->buf->head[0].iov_base, | ||
445 | __entry->head_len = xdr->buf->head[0].iov_len, | ||
446 | __entry->page_len = xdr->buf->page_len, | ||
447 | __entry->tail_base = xdr->buf->tail[0].iov_base, | ||
448 | __entry->tail_len = xdr->buf->tail[0].iov_len, | ||
449 | __entry->len = xdr->buf->len; | ||
450 | ), | ||
451 | |||
452 | TP_printk( | ||
453 | "task:%u@%u %sv%d %s offset=%zu copied=%u xdr=[%p,%zu]/%u/[%p,%zu]/%u\n", | ||
454 | __entry->task_id, __entry->client_id, | ||
455 | __get_str(progname), __entry->version, __get_str(procedure), | ||
456 | __entry->offset, __entry->copied, | ||
457 | __entry->head_base, __entry->head_len, | ||
458 | __entry->page_len, | ||
459 | __entry->tail_base, __entry->tail_len, | ||
460 | __entry->len | ||
461 | ) | ||
462 | ); | ||
463 | |||
464 | TRACE_EVENT(rpc_reply_pages, | ||
465 | TP_PROTO( | ||
466 | const struct rpc_rqst *req | ||
467 | ), | ||
468 | |||
469 | TP_ARGS(req), | ||
470 | |||
471 | TP_STRUCT__entry( | ||
472 | __field(unsigned int, task_id) | ||
473 | __field(unsigned int, client_id) | ||
474 | __field(const void *, head_base) | ||
475 | __field(size_t, head_len) | ||
476 | __field(const void *, tail_base) | ||
477 | __field(size_t, tail_len) | ||
478 | __field(unsigned int, page_len) | ||
479 | ), | ||
480 | |||
481 | TP_fast_assign( | ||
482 | __entry->task_id = req->rq_task->tk_pid; | ||
483 | __entry->client_id = req->rq_task->tk_client->cl_clid; | ||
484 | |||
485 | __entry->head_base = req->rq_rcv_buf.head[0].iov_base; | ||
486 | __entry->head_len = req->rq_rcv_buf.head[0].iov_len; | ||
487 | __entry->page_len = req->rq_rcv_buf.page_len; | ||
488 | __entry->tail_base = req->rq_rcv_buf.tail[0].iov_base; | ||
489 | __entry->tail_len = req->rq_rcv_buf.tail[0].iov_len; | ||
490 | ), | ||
491 | |||
492 | TP_printk( | ||
493 | "task:%u@%u xdr=[%p,%zu]/%u/[%p,%zu]\n", | ||
494 | __entry->task_id, __entry->client_id, | ||
495 | __entry->head_base, __entry->head_len, | ||
496 | __entry->page_len, | ||
497 | __entry->tail_base, __entry->tail_len | ||
498 | ) | ||
499 | ); | ||
500 | |||
213 | /* | 501 | /* |
214 | * First define the enums in the below macros to be exported to userspace | 502 | * First define the enums in the below macros to be exported to userspace |
215 | * via TRACE_DEFINE_ENUM(). | 503 | * via TRACE_DEFINE_ENUM(). |
@@ -404,9 +692,68 @@ DECLARE_EVENT_CLASS(rpc_xprt_event, | |||
404 | 692 | ||
405 | DEFINE_RPC_XPRT_EVENT(timer); | 693 | DEFINE_RPC_XPRT_EVENT(timer); |
406 | DEFINE_RPC_XPRT_EVENT(lookup_rqst); | 694 | DEFINE_RPC_XPRT_EVENT(lookup_rqst); |
407 | DEFINE_RPC_XPRT_EVENT(transmit); | ||
408 | DEFINE_RPC_XPRT_EVENT(complete_rqst); | 695 | DEFINE_RPC_XPRT_EVENT(complete_rqst); |
409 | 696 | ||
697 | TRACE_EVENT(xprt_transmit, | ||
698 | TP_PROTO( | ||
699 | const struct rpc_rqst *rqst, | ||
700 | int status | ||
701 | ), | ||
702 | |||
703 | TP_ARGS(rqst, status), | ||
704 | |||
705 | TP_STRUCT__entry( | ||
706 | __field(unsigned int, task_id) | ||
707 | __field(unsigned int, client_id) | ||
708 | __field(u32, xid) | ||
709 | __field(u32, seqno) | ||
710 | __field(int, status) | ||
711 | ), | ||
712 | |||
713 | TP_fast_assign( | ||
714 | __entry->task_id = rqst->rq_task->tk_pid; | ||
715 | __entry->client_id = rqst->rq_task->tk_client->cl_clid; | ||
716 | __entry->xid = be32_to_cpu(rqst->rq_xid); | ||
717 | __entry->seqno = rqst->rq_seqno; | ||
718 | __entry->status = status; | ||
719 | ), | ||
720 | |||
721 | TP_printk( | ||
722 | "task:%u@%u xid=0x%08x seqno=%u status=%d", | ||
723 | __entry->task_id, __entry->client_id, __entry->xid, | ||
724 | __entry->seqno, __entry->status) | ||
725 | ); | ||
726 | |||
727 | TRACE_EVENT(xprt_enq_xmit, | ||
728 | TP_PROTO( | ||
729 | const struct rpc_task *task, | ||
730 | int stage | ||
731 | ), | ||
732 | |||
733 | TP_ARGS(task, stage), | ||
734 | |||
735 | TP_STRUCT__entry( | ||
736 | __field(unsigned int, task_id) | ||
737 | __field(unsigned int, client_id) | ||
738 | __field(u32, xid) | ||
739 | __field(u32, seqno) | ||
740 | __field(int, stage) | ||
741 | ), | ||
742 | |||
743 | TP_fast_assign( | ||
744 | __entry->task_id = task->tk_pid; | ||
745 | __entry->client_id = task->tk_client->cl_clid; | ||
746 | __entry->xid = be32_to_cpu(task->tk_rqstp->rq_xid); | ||
747 | __entry->seqno = task->tk_rqstp->rq_seqno; | ||
748 | __entry->stage = stage; | ||
749 | ), | ||
750 | |||
751 | TP_printk( | ||
752 | "task:%u@%u xid=0x%08x seqno=%u stage=%d", | ||
753 | __entry->task_id, __entry->client_id, __entry->xid, | ||
754 | __entry->seqno, __entry->stage) | ||
755 | ); | ||
756 | |||
410 | TRACE_EVENT(xprt_ping, | 757 | TRACE_EVENT(xprt_ping, |
411 | TP_PROTO(const struct rpc_xprt *xprt, int status), | 758 | TP_PROTO(const struct rpc_xprt *xprt, int status), |
412 | 759 | ||
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index ac09ca803296..83f5617bae07 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig | |||
@@ -34,6 +34,22 @@ config RPCSEC_GSS_KRB5 | |||
34 | 34 | ||
35 | If unsure, say Y. | 35 | If unsure, say Y. |
36 | 36 | ||
37 | config CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES | ||
38 | bool "Secure RPC: Disable insecure Kerberos encryption types" | ||
39 | depends on RPCSEC_GSS_KRB5 | ||
40 | default n | ||
41 | help | ||
42 | Choose Y here to disable the use of deprecated encryption types | ||
43 | with the Kerberos version 5 GSS-API mechanism (RFC 1964). The | ||
44 | deprecated encryption types include DES-CBC-MD5, DES-CBC-CRC, | ||
45 | and DES-CBC-MD4. These types were deprecated by RFC 6649 because | ||
46 | they were found to be insecure. | ||
47 | |||
48 | N is the default because many sites have deployed KDCs and | ||
49 | keytabs that contain only these deprecated encryption types. | ||
50 | Choosing Y prevents the use of known-insecure encryption types | ||
51 | but might result in compatibility problems. | ||
52 | |||
37 | config SUNRPC_DEBUG | 53 | config SUNRPC_DEBUG |
38 | bool "RPC: Enable dprintk debugging" | 54 | bool "RPC: Enable dprintk debugging" |
39 | depends on SUNRPC && SYSCTL | 55 | depends on SUNRPC && SYSCTL |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index f3023bbc0b7f..e7861026b9e5 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -17,9 +17,7 @@ | |||
17 | #include <linux/sunrpc/gss_api.h> | 17 | #include <linux/sunrpc/gss_api.h> |
18 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
19 | 19 | ||
20 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) | 20 | #include <trace/events/sunrpc.h> |
21 | # define RPCDBG_FACILITY RPCDBG_AUTH | ||
22 | #endif | ||
23 | 21 | ||
24 | #define RPC_CREDCACHE_DEFAULT_HASHBITS (4) | 22 | #define RPC_CREDCACHE_DEFAULT_HASHBITS (4) |
25 | struct rpc_cred_cache { | 23 | struct rpc_cred_cache { |
@@ -267,8 +265,6 @@ rpcauth_list_flavors(rpc_authflavor_t *array, int size) | |||
267 | } | 265 | } |
268 | } | 266 | } |
269 | rcu_read_unlock(); | 267 | rcu_read_unlock(); |
270 | |||
271 | dprintk("RPC: %s returns %d\n", __func__, result); | ||
272 | return result; | 268 | return result; |
273 | } | 269 | } |
274 | EXPORT_SYMBOL_GPL(rpcauth_list_flavors); | 270 | EXPORT_SYMBOL_GPL(rpcauth_list_flavors); |
@@ -636,9 +632,6 @@ rpcauth_lookupcred(struct rpc_auth *auth, int flags) | |||
636 | struct rpc_cred *ret; | 632 | struct rpc_cred *ret; |
637 | const struct cred *cred = current_cred(); | 633 | const struct cred *cred = current_cred(); |
638 | 634 | ||
639 | dprintk("RPC: looking up %s cred\n", | ||
640 | auth->au_ops->au_name); | ||
641 | |||
642 | memset(&acred, 0, sizeof(acred)); | 635 | memset(&acred, 0, sizeof(acred)); |
643 | acred.cred = cred; | 636 | acred.cred = cred; |
644 | ret = auth->au_ops->lookup_cred(auth, &acred, flags); | 637 | ret = auth->au_ops->lookup_cred(auth, &acred, flags); |
@@ -670,8 +663,6 @@ rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags) | |||
670 | }; | 663 | }; |
671 | struct rpc_cred *ret; | 664 | struct rpc_cred *ret; |
672 | 665 | ||
673 | dprintk("RPC: %5u looking up %s cred\n", | ||
674 | task->tk_pid, task->tk_client->cl_auth->au_ops->au_name); | ||
675 | ret = auth->au_ops->lookup_cred(auth, &acred, lookupflags); | 666 | ret = auth->au_ops->lookup_cred(auth, &acred, lookupflags); |
676 | put_cred(acred.cred); | 667 | put_cred(acred.cred); |
677 | return ret; | 668 | return ret; |
@@ -688,8 +679,6 @@ rpcauth_bind_machine_cred(struct rpc_task *task, int lookupflags) | |||
688 | 679 | ||
689 | if (!acred.principal) | 680 | if (!acred.principal) |
690 | return NULL; | 681 | return NULL; |
691 | dprintk("RPC: %5u looking up %s machine cred\n", | ||
692 | task->tk_pid, task->tk_client->cl_auth->au_ops->au_name); | ||
693 | return auth->au_ops->lookup_cred(auth, &acred, lookupflags); | 682 | return auth->au_ops->lookup_cred(auth, &acred, lookupflags); |
694 | } | 683 | } |
695 | 684 | ||
@@ -698,8 +687,6 @@ rpcauth_bind_new_cred(struct rpc_task *task, int lookupflags) | |||
698 | { | 687 | { |
699 | struct rpc_auth *auth = task->tk_client->cl_auth; | 688 | struct rpc_auth *auth = task->tk_client->cl_auth; |
700 | 689 | ||
701 | dprintk("RPC: %5u looking up %s cred\n", | ||
702 | task->tk_pid, auth->au_ops->au_name); | ||
703 | return rpcauth_lookupcred(auth, lookupflags); | 690 | return rpcauth_lookupcred(auth, lookupflags); |
704 | } | 691 | } |
705 | 692 | ||
@@ -771,75 +758,102 @@ destroy: | |||
771 | } | 758 | } |
772 | EXPORT_SYMBOL_GPL(put_rpccred); | 759 | EXPORT_SYMBOL_GPL(put_rpccred); |
773 | 760 | ||
774 | __be32 * | 761 | /** |
775 | rpcauth_marshcred(struct rpc_task *task, __be32 *p) | 762 | * rpcauth_marshcred - Append RPC credential to end of @xdr |
763 | * @task: controlling RPC task | ||
764 | * @xdr: xdr_stream containing initial portion of RPC Call header | ||
765 | * | ||
766 | * On success, an appropriate verifier is added to @xdr, @xdr is | ||
767 | * updated to point past the verifier, and zero is returned. | ||
768 | * Otherwise, @xdr is in an undefined state and a negative errno | ||
769 | * is returned. | ||
770 | */ | ||
771 | int rpcauth_marshcred(struct rpc_task *task, struct xdr_stream *xdr) | ||
776 | { | 772 | { |
777 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; | 773 | const struct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops; |
778 | 774 | ||
779 | dprintk("RPC: %5u marshaling %s cred %p\n", | 775 | return ops->crmarshal(task, xdr); |
780 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); | ||
781 | |||
782 | return cred->cr_ops->crmarshal(task, p); | ||
783 | } | 776 | } |
784 | 777 | ||
785 | __be32 * | 778 | /** |
786 | rpcauth_checkverf(struct rpc_task *task, __be32 *p) | 779 | * rpcauth_wrap_req_encode - XDR encode the RPC procedure |
780 | * @task: controlling RPC task | ||
781 | * @xdr: stream where on-the-wire bytes are to be marshalled | ||
782 | * | ||
783 | * On success, @xdr contains the encoded and wrapped message. | ||
784 | * Otherwise, @xdr is in an undefined state. | ||
785 | */ | ||
786 | int rpcauth_wrap_req_encode(struct rpc_task *task, struct xdr_stream *xdr) | ||
787 | { | 787 | { |
788 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; | 788 | kxdreproc_t encode = task->tk_msg.rpc_proc->p_encode; |
789 | 789 | ||
790 | dprintk("RPC: %5u validating %s cred %p\n", | 790 | encode(task->tk_rqstp, xdr, task->tk_msg.rpc_argp); |
791 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); | 791 | return 0; |
792 | |||
793 | return cred->cr_ops->crvalidate(task, p); | ||
794 | } | 792 | } |
793 | EXPORT_SYMBOL_GPL(rpcauth_wrap_req_encode); | ||
795 | 794 | ||
796 | static void rpcauth_wrap_req_encode(kxdreproc_t encode, struct rpc_rqst *rqstp, | 795 | /** |
797 | __be32 *data, void *obj) | 796 | * rpcauth_wrap_req - XDR encode and wrap the RPC procedure |
797 | * @task: controlling RPC task | ||
798 | * @xdr: stream where on-the-wire bytes are to be marshalled | ||
799 | * | ||
800 | * On success, @xdr contains the encoded and wrapped message, | ||
801 | * and zero is returned. Otherwise, @xdr is in an undefined | ||
802 | * state and a negative errno is returned. | ||
803 | */ | ||
804 | int rpcauth_wrap_req(struct rpc_task *task, struct xdr_stream *xdr) | ||
798 | { | 805 | { |
799 | struct xdr_stream xdr; | 806 | const struct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops; |
800 | 807 | ||
801 | xdr_init_encode(&xdr, &rqstp->rq_snd_buf, data); | 808 | return ops->crwrap_req(task, xdr); |
802 | encode(rqstp, &xdr, obj); | ||
803 | } | 809 | } |
804 | 810 | ||
811 | /** | ||
812 | * rpcauth_checkverf - Validate verifier in RPC Reply header | ||
813 | * @task: controlling RPC task | ||
814 | * @xdr: xdr_stream containing RPC Reply header | ||
815 | * | ||
816 | * On success, @xdr is updated to point past the verifier and | ||
817 | * zero is returned. Otherwise, @xdr is in an undefined state | ||
818 | * and a negative errno is returned. | ||
819 | */ | ||
805 | int | 820 | int |
806 | rpcauth_wrap_req(struct rpc_task *task, kxdreproc_t encode, void *rqstp, | 821 | rpcauth_checkverf(struct rpc_task *task, struct xdr_stream *xdr) |
807 | __be32 *data, void *obj) | ||
808 | { | 822 | { |
809 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; | 823 | const struct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops; |
810 | 824 | ||
811 | dprintk("RPC: %5u using %s cred %p to wrap rpc data\n", | 825 | return ops->crvalidate(task, xdr); |
812 | task->tk_pid, cred->cr_ops->cr_name, cred); | ||
813 | if (cred->cr_ops->crwrap_req) | ||
814 | return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj); | ||
815 | /* By default, we encode the arguments normally. */ | ||
816 | rpcauth_wrap_req_encode(encode, rqstp, data, obj); | ||
817 | return 0; | ||
818 | } | 826 | } |
819 | 827 | ||
820 | static int | 828 | /** |
821 | rpcauth_unwrap_req_decode(kxdrdproc_t decode, struct rpc_rqst *rqstp, | 829 | * rpcauth_unwrap_resp_decode - Invoke XDR decode function |
822 | __be32 *data, void *obj) | 830 | * @task: controlling RPC task |
831 | * @xdr: stream where the Reply message resides | ||
832 | * | ||
833 | * Returns zero on success; otherwise a negative errno is returned. | ||
834 | */ | ||
835 | int | ||
836 | rpcauth_unwrap_resp_decode(struct rpc_task *task, struct xdr_stream *xdr) | ||
823 | { | 837 | { |
824 | struct xdr_stream xdr; | 838 | kxdrdproc_t decode = task->tk_msg.rpc_proc->p_decode; |
825 | 839 | ||
826 | xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, data); | 840 | return decode(task->tk_rqstp, xdr, task->tk_msg.rpc_resp); |
827 | return decode(rqstp, &xdr, obj); | ||
828 | } | 841 | } |
842 | EXPORT_SYMBOL_GPL(rpcauth_unwrap_resp_decode); | ||
829 | 843 | ||
844 | /** | ||
845 | * rpcauth_unwrap_resp - Invoke unwrap and decode function for the cred | ||
846 | * @task: controlling RPC task | ||
847 | * @xdr: stream where the Reply message resides | ||
848 | * | ||
849 | * Returns zero on success; otherwise a negative errno is returned. | ||
850 | */ | ||
830 | int | 851 | int |
831 | rpcauth_unwrap_resp(struct rpc_task *task, kxdrdproc_t decode, void *rqstp, | 852 | rpcauth_unwrap_resp(struct rpc_task *task, struct xdr_stream *xdr) |
832 | __be32 *data, void *obj) | ||
833 | { | 853 | { |
834 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; | 854 | const struct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops; |
835 | 855 | ||
836 | dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n", | 856 | return ops->crunwrap_resp(task, xdr); |
837 | task->tk_pid, cred->cr_ops->cr_name, cred); | ||
838 | if (cred->cr_ops->crunwrap_resp) | ||
839 | return cred->cr_ops->crunwrap_resp(task, decode, rqstp, | ||
840 | data, obj); | ||
841 | /* By default, we decode the arguments normally. */ | ||
842 | return rpcauth_unwrap_req_decode(decode, rqstp, data, obj); | ||
843 | } | 857 | } |
844 | 858 | ||
845 | bool | 859 | bool |
@@ -865,8 +879,6 @@ rpcauth_refreshcred(struct rpc_task *task) | |||
865 | goto out; | 879 | goto out; |
866 | cred = task->tk_rqstp->rq_cred; | 880 | cred = task->tk_rqstp->rq_cred; |
867 | } | 881 | } |
868 | dprintk("RPC: %5u refreshing %s cred %p\n", | ||
869 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); | ||
870 | 882 | ||
871 | err = cred->cr_ops->crrefresh(task); | 883 | err = cred->cr_ops->crrefresh(task); |
872 | out: | 884 | out: |
@@ -880,8 +892,6 @@ rpcauth_invalcred(struct rpc_task *task) | |||
880 | { | 892 | { |
881 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; | 893 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
882 | 894 | ||
883 | dprintk("RPC: %5u invalidating %s cred %p\n", | ||
884 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); | ||
885 | if (cred) | 895 | if (cred) |
886 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); | 896 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
887 | } | 897 | } |
diff --git a/net/sunrpc/auth_gss/Makefile b/net/sunrpc/auth_gss/Makefile index c374268b008f..4a29f4c5dac4 100644 --- a/net/sunrpc/auth_gss/Makefile +++ b/net/sunrpc/auth_gss/Makefile | |||
@@ -7,7 +7,7 @@ obj-$(CONFIG_SUNRPC_GSS) += auth_rpcgss.o | |||
7 | 7 | ||
8 | auth_rpcgss-y := auth_gss.o gss_generic_token.o \ | 8 | auth_rpcgss-y := auth_gss.o gss_generic_token.o \ |
9 | gss_mech_switch.o svcauth_gss.o \ | 9 | gss_mech_switch.o svcauth_gss.o \ |
10 | gss_rpc_upcall.o gss_rpc_xdr.o | 10 | gss_rpc_upcall.o gss_rpc_xdr.o trace.o |
11 | 11 | ||
12 | obj-$(CONFIG_RPCSEC_GSS_KRB5) += rpcsec_gss_krb5.o | 12 | obj-$(CONFIG_RPCSEC_GSS_KRB5) += rpcsec_gss_krb5.o |
13 | 13 | ||
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 1531b0219344..c67e2ad151ae 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: BSD-3-Clause | ||
1 | /* | 2 | /* |
2 | * linux/net/sunrpc/auth_gss/auth_gss.c | 3 | * linux/net/sunrpc/auth_gss/auth_gss.c |
3 | * | 4 | * |
@@ -8,34 +9,8 @@ | |||
8 | * | 9 | * |
9 | * Dug Song <dugsong@monkey.org> | 10 | * Dug Song <dugsong@monkey.org> |
10 | * Andy Adamson <andros@umich.edu> | 11 | * Andy Adamson <andros@umich.edu> |
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * | ||
16 | * 1. Redistributions of source code must retain the above copyright | ||
17 | * notice, this list of conditions and the following disclaimer. | ||
18 | * 2. Redistributions in binary form must reproduce the above copyright | ||
19 | * notice, this list of conditions and the following disclaimer in the | ||
20 | * documentation and/or other materials provided with the distribution. | ||
21 | * 3. Neither the name of the University nor the names of its | ||
22 | * contributors may be used to endorse or promote products derived | ||
23 | * from this software without specific prior written permission. | ||
24 | * | ||
25 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
26 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
27 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
28 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
32 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
33 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
34 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
35 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
36 | */ | 12 | */ |
37 | 13 | ||
38 | |||
39 | #include <linux/module.h> | 14 | #include <linux/module.h> |
40 | #include <linux/init.h> | 15 | #include <linux/init.h> |
41 | #include <linux/types.h> | 16 | #include <linux/types.h> |
@@ -55,6 +30,8 @@ | |||
55 | 30 | ||
56 | #include "../netns.h" | 31 | #include "../netns.h" |
57 | 32 | ||
33 | #include <trace/events/rpcgss.h> | ||
34 | |||
58 | static const struct rpc_authops authgss_ops; | 35 | static const struct rpc_authops authgss_ops; |
59 | 36 | ||
60 | static const struct rpc_credops gss_credops; | 37 | static const struct rpc_credops gss_credops; |
@@ -260,6 +237,7 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct | |||
260 | } | 237 | } |
261 | ret = gss_import_sec_context(p, seclen, gm, &ctx->gc_gss_ctx, NULL, GFP_NOFS); | 238 | ret = gss_import_sec_context(p, seclen, gm, &ctx->gc_gss_ctx, NULL, GFP_NOFS); |
262 | if (ret < 0) { | 239 | if (ret < 0) { |
240 | trace_rpcgss_import_ctx(ret); | ||
263 | p = ERR_PTR(ret); | 241 | p = ERR_PTR(ret); |
264 | goto err; | 242 | goto err; |
265 | } | 243 | } |
@@ -275,12 +253,9 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct | |||
275 | if (IS_ERR(p)) | 253 | if (IS_ERR(p)) |
276 | goto err; | 254 | goto err; |
277 | done: | 255 | done: |
278 | dprintk("RPC: %s Success. gc_expiry %lu now %lu timeout %u acceptor %.*s\n", | 256 | trace_rpcgss_context(ctx->gc_expiry, now, timeout, |
279 | __func__, ctx->gc_expiry, now, timeout, ctx->gc_acceptor.len, | 257 | ctx->gc_acceptor.len, ctx->gc_acceptor.data); |
280 | ctx->gc_acceptor.data); | ||
281 | return p; | ||
282 | err: | 258 | err: |
283 | dprintk("RPC: %s returns error %ld\n", __func__, -PTR_ERR(p)); | ||
284 | return p; | 259 | return p; |
285 | } | 260 | } |
286 | 261 | ||
@@ -354,10 +329,8 @@ __gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid, const struct gss_auth *auth | |||
354 | if (auth && pos->auth->service != auth->service) | 329 | if (auth && pos->auth->service != auth->service) |
355 | continue; | 330 | continue; |
356 | refcount_inc(&pos->count); | 331 | refcount_inc(&pos->count); |
357 | dprintk("RPC: %s found msg %p\n", __func__, pos); | ||
358 | return pos; | 332 | return pos; |
359 | } | 333 | } |
360 | dprintk("RPC: %s found nothing\n", __func__); | ||
361 | return NULL; | 334 | return NULL; |
362 | } | 335 | } |
363 | 336 | ||
@@ -456,7 +429,7 @@ static int gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, | |||
456 | size_t buflen = sizeof(gss_msg->databuf); | 429 | size_t buflen = sizeof(gss_msg->databuf); |
457 | int len; | 430 | int len; |
458 | 431 | ||
459 | len = scnprintf(p, buflen, "mech=%s uid=%d ", mech->gm_name, | 432 | len = scnprintf(p, buflen, "mech=%s uid=%d", mech->gm_name, |
460 | from_kuid(&init_user_ns, gss_msg->uid)); | 433 | from_kuid(&init_user_ns, gss_msg->uid)); |
461 | buflen -= len; | 434 | buflen -= len; |
462 | p += len; | 435 | p += len; |
@@ -467,7 +440,7 @@ static int gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, | |||
467 | * identity that we are authenticating to. | 440 | * identity that we are authenticating to. |
468 | */ | 441 | */ |
469 | if (target_name) { | 442 | if (target_name) { |
470 | len = scnprintf(p, buflen, "target=%s ", target_name); | 443 | len = scnprintf(p, buflen, " target=%s", target_name); |
471 | buflen -= len; | 444 | buflen -= len; |
472 | p += len; | 445 | p += len; |
473 | gss_msg->msg.len += len; | 446 | gss_msg->msg.len += len; |
@@ -487,11 +460,11 @@ static int gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, | |||
487 | char *c = strchr(service_name, '@'); | 460 | char *c = strchr(service_name, '@'); |
488 | 461 | ||
489 | if (!c) | 462 | if (!c) |
490 | len = scnprintf(p, buflen, "service=%s ", | 463 | len = scnprintf(p, buflen, " service=%s", |
491 | service_name); | 464 | service_name); |
492 | else | 465 | else |
493 | len = scnprintf(p, buflen, | 466 | len = scnprintf(p, buflen, |
494 | "service=%.*s srchost=%s ", | 467 | " service=%.*s srchost=%s", |
495 | (int)(c - service_name), | 468 | (int)(c - service_name), |
496 | service_name, c + 1); | 469 | service_name, c + 1); |
497 | buflen -= len; | 470 | buflen -= len; |
@@ -500,17 +473,17 @@ static int gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, | |||
500 | } | 473 | } |
501 | 474 | ||
502 | if (mech->gm_upcall_enctypes) { | 475 | if (mech->gm_upcall_enctypes) { |
503 | len = scnprintf(p, buflen, "enctypes=%s ", | 476 | len = scnprintf(p, buflen, " enctypes=%s", |
504 | mech->gm_upcall_enctypes); | 477 | mech->gm_upcall_enctypes); |
505 | buflen -= len; | 478 | buflen -= len; |
506 | p += len; | 479 | p += len; |
507 | gss_msg->msg.len += len; | 480 | gss_msg->msg.len += len; |
508 | } | 481 | } |
482 | trace_rpcgss_upcall_msg(gss_msg->databuf); | ||
509 | len = scnprintf(p, buflen, "\n"); | 483 | len = scnprintf(p, buflen, "\n"); |
510 | if (len == 0) | 484 | if (len == 0) |
511 | goto out_overflow; | 485 | goto out_overflow; |
512 | gss_msg->msg.len += len; | 486 | gss_msg->msg.len += len; |
513 | |||
514 | gss_msg->msg.data = gss_msg->databuf; | 487 | gss_msg->msg.data = gss_msg->databuf; |
515 | return 0; | 488 | return 0; |
516 | out_overflow: | 489 | out_overflow: |
@@ -603,8 +576,6 @@ gss_refresh_upcall(struct rpc_task *task) | |||
603 | struct rpc_pipe *pipe; | 576 | struct rpc_pipe *pipe; |
604 | int err = 0; | 577 | int err = 0; |
605 | 578 | ||
606 | dprintk("RPC: %5u %s for uid %u\n", | ||
607 | task->tk_pid, __func__, from_kuid(&init_user_ns, cred->cr_cred->fsuid)); | ||
608 | gss_msg = gss_setup_upcall(gss_auth, cred); | 579 | gss_msg = gss_setup_upcall(gss_auth, cred); |
609 | if (PTR_ERR(gss_msg) == -EAGAIN) { | 580 | if (PTR_ERR(gss_msg) == -EAGAIN) { |
610 | /* XXX: warning on the first, under the assumption we | 581 | /* XXX: warning on the first, under the assumption we |
@@ -612,7 +583,8 @@ gss_refresh_upcall(struct rpc_task *task) | |||
612 | warn_gssd(); | 583 | warn_gssd(); |
613 | task->tk_timeout = 15*HZ; | 584 | task->tk_timeout = 15*HZ; |
614 | rpc_sleep_on(&pipe_version_rpc_waitqueue, task, NULL); | 585 | rpc_sleep_on(&pipe_version_rpc_waitqueue, task, NULL); |
615 | return -EAGAIN; | 586 | err = -EAGAIN; |
587 | goto out; | ||
616 | } | 588 | } |
617 | if (IS_ERR(gss_msg)) { | 589 | if (IS_ERR(gss_msg)) { |
618 | err = PTR_ERR(gss_msg); | 590 | err = PTR_ERR(gss_msg); |
@@ -635,9 +607,8 @@ gss_refresh_upcall(struct rpc_task *task) | |||
635 | spin_unlock(&pipe->lock); | 607 | spin_unlock(&pipe->lock); |
636 | gss_release_msg(gss_msg); | 608 | gss_release_msg(gss_msg); |
637 | out: | 609 | out: |
638 | dprintk("RPC: %5u %s for uid %u result %d\n", | 610 | trace_rpcgss_upcall_result(from_kuid(&init_user_ns, |
639 | task->tk_pid, __func__, | 611 | cred->cr_cred->fsuid), err); |
640 | from_kuid(&init_user_ns, cred->cr_cred->fsuid), err); | ||
641 | return err; | 612 | return err; |
642 | } | 613 | } |
643 | 614 | ||
@@ -652,14 +623,13 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) | |||
652 | DEFINE_WAIT(wait); | 623 | DEFINE_WAIT(wait); |
653 | int err; | 624 | int err; |
654 | 625 | ||
655 | dprintk("RPC: %s for uid %u\n", | ||
656 | __func__, from_kuid(&init_user_ns, cred->cr_cred->fsuid)); | ||
657 | retry: | 626 | retry: |
658 | err = 0; | 627 | err = 0; |
659 | /* if gssd is down, just skip upcalling altogether */ | 628 | /* if gssd is down, just skip upcalling altogether */ |
660 | if (!gssd_running(net)) { | 629 | if (!gssd_running(net)) { |
661 | warn_gssd(); | 630 | warn_gssd(); |
662 | return -EACCES; | 631 | err = -EACCES; |
632 | goto out; | ||
663 | } | 633 | } |
664 | gss_msg = gss_setup_upcall(gss_auth, cred); | 634 | gss_msg = gss_setup_upcall(gss_auth, cred); |
665 | if (PTR_ERR(gss_msg) == -EAGAIN) { | 635 | if (PTR_ERR(gss_msg) == -EAGAIN) { |
@@ -700,8 +670,8 @@ out_intr: | |||
700 | finish_wait(&gss_msg->waitqueue, &wait); | 670 | finish_wait(&gss_msg->waitqueue, &wait); |
701 | gss_release_msg(gss_msg); | 671 | gss_release_msg(gss_msg); |
702 | out: | 672 | out: |
703 | dprintk("RPC: %s for uid %u result %d\n", | 673 | trace_rpcgss_upcall_result(from_kuid(&init_user_ns, |
704 | __func__, from_kuid(&init_user_ns, cred->cr_cred->fsuid), err); | 674 | cred->cr_cred->fsuid), err); |
705 | return err; | 675 | return err; |
706 | } | 676 | } |
707 | 677 | ||
@@ -794,7 +764,6 @@ err_put_ctx: | |||
794 | err: | 764 | err: |
795 | kfree(buf); | 765 | kfree(buf); |
796 | out: | 766 | out: |
797 | dprintk("RPC: %s returning %zd\n", __func__, err); | ||
798 | return err; | 767 | return err; |
799 | } | 768 | } |
800 | 769 | ||
@@ -863,8 +832,6 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) | |||
863 | struct gss_upcall_msg *gss_msg = container_of(msg, struct gss_upcall_msg, msg); | 832 | struct gss_upcall_msg *gss_msg = container_of(msg, struct gss_upcall_msg, msg); |
864 | 833 | ||
865 | if (msg->errno < 0) { | 834 | if (msg->errno < 0) { |
866 | dprintk("RPC: %s releasing msg %p\n", | ||
867 | __func__, gss_msg); | ||
868 | refcount_inc(&gss_msg->count); | 835 | refcount_inc(&gss_msg->count); |
869 | gss_unhash_msg(gss_msg); | 836 | gss_unhash_msg(gss_msg); |
870 | if (msg->errno == -ETIMEDOUT) | 837 | if (msg->errno == -ETIMEDOUT) |
@@ -1024,8 +991,6 @@ gss_create_new(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt) | |||
1024 | struct rpc_auth * auth; | 991 | struct rpc_auth * auth; |
1025 | int err = -ENOMEM; /* XXX? */ | 992 | int err = -ENOMEM; /* XXX? */ |
1026 | 993 | ||
1027 | dprintk("RPC: creating GSS authenticator for client %p\n", clnt); | ||
1028 | |||
1029 | if (!try_module_get(THIS_MODULE)) | 994 | if (!try_module_get(THIS_MODULE)) |
1030 | return ERR_PTR(err); | 995 | return ERR_PTR(err); |
1031 | if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL))) | 996 | if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL))) |
@@ -1041,10 +1006,8 @@ gss_create_new(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt) | |||
1041 | gss_auth->net = get_net(rpc_net_ns(clnt)); | 1006 | gss_auth->net = get_net(rpc_net_ns(clnt)); |
1042 | err = -EINVAL; | 1007 | err = -EINVAL; |
1043 | gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor); | 1008 | gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor); |
1044 | if (!gss_auth->mech) { | 1009 | if (!gss_auth->mech) |
1045 | dprintk("RPC: Pseudoflavor %d not found!\n", flavor); | ||
1046 | goto err_put_net; | 1010 | goto err_put_net; |
1047 | } | ||
1048 | gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor); | 1011 | gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor); |
1049 | if (gss_auth->service == 0) | 1012 | if (gss_auth->service == 0) |
1050 | goto err_put_mech; | 1013 | goto err_put_mech; |
@@ -1053,6 +1016,8 @@ gss_create_new(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt) | |||
1053 | auth = &gss_auth->rpc_auth; | 1016 | auth = &gss_auth->rpc_auth; |
1054 | auth->au_cslack = GSS_CRED_SLACK >> 2; | 1017 | auth->au_cslack = GSS_CRED_SLACK >> 2; |
1055 | auth->au_rslack = GSS_VERF_SLACK >> 2; | 1018 | auth->au_rslack = GSS_VERF_SLACK >> 2; |
1019 | auth->au_verfsize = GSS_VERF_SLACK >> 2; | ||
1020 | auth->au_ralign = GSS_VERF_SLACK >> 2; | ||
1056 | auth->au_flags = 0; | 1021 | auth->au_flags = 0; |
1057 | auth->au_ops = &authgss_ops; | 1022 | auth->au_ops = &authgss_ops; |
1058 | auth->au_flavor = flavor; | 1023 | auth->au_flavor = flavor; |
@@ -1099,6 +1064,7 @@ err_free: | |||
1099 | kfree(gss_auth); | 1064 | kfree(gss_auth); |
1100 | out_dec: | 1065 | out_dec: |
1101 | module_put(THIS_MODULE); | 1066 | module_put(THIS_MODULE); |
1067 | trace_rpcgss_createauth(flavor, err); | ||
1102 | return ERR_PTR(err); | 1068 | return ERR_PTR(err); |
1103 | } | 1069 | } |
1104 | 1070 | ||
@@ -1135,9 +1101,6 @@ gss_destroy(struct rpc_auth *auth) | |||
1135 | struct gss_auth *gss_auth = container_of(auth, | 1101 | struct gss_auth *gss_auth = container_of(auth, |
1136 | struct gss_auth, rpc_auth); | 1102 | struct gss_auth, rpc_auth); |
1137 | 1103 | ||
1138 | dprintk("RPC: destroying GSS authenticator %p flavor %d\n", | ||
1139 | auth, auth->au_flavor); | ||
1140 | |||
1141 | if (hash_hashed(&gss_auth->hash)) { | 1104 | if (hash_hashed(&gss_auth->hash)) { |
1142 | spin_lock(&gss_auth_hash_lock); | 1105 | spin_lock(&gss_auth_hash_lock); |
1143 | hash_del(&gss_auth->hash); | 1106 | hash_del(&gss_auth->hash); |
@@ -1300,8 +1263,6 @@ gss_send_destroy_context(struct rpc_cred *cred) | |||
1300 | static void | 1263 | static void |
1301 | gss_do_free_ctx(struct gss_cl_ctx *ctx) | 1264 | gss_do_free_ctx(struct gss_cl_ctx *ctx) |
1302 | { | 1265 | { |
1303 | dprintk("RPC: %s\n", __func__); | ||
1304 | |||
1305 | gss_delete_sec_context(&ctx->gc_gss_ctx); | 1266 | gss_delete_sec_context(&ctx->gc_gss_ctx); |
1306 | kfree(ctx->gc_wire_ctx.data); | 1267 | kfree(ctx->gc_wire_ctx.data); |
1307 | kfree(ctx->gc_acceptor.data); | 1268 | kfree(ctx->gc_acceptor.data); |
@@ -1324,7 +1285,6 @@ gss_free_ctx(struct gss_cl_ctx *ctx) | |||
1324 | static void | 1285 | static void |
1325 | gss_free_cred(struct gss_cred *gss_cred) | 1286 | gss_free_cred(struct gss_cred *gss_cred) |
1326 | { | 1287 | { |
1327 | dprintk("RPC: %s cred=%p\n", __func__, gss_cred); | ||
1328 | kfree(gss_cred); | 1288 | kfree(gss_cred); |
1329 | } | 1289 | } |
1330 | 1290 | ||
@@ -1381,10 +1341,6 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags, gfp_t | |||
1381 | struct gss_cred *cred = NULL; | 1341 | struct gss_cred *cred = NULL; |
1382 | int err = -ENOMEM; | 1342 | int err = -ENOMEM; |
1383 | 1343 | ||
1384 | dprintk("RPC: %s for uid %d, flavor %d\n", | ||
1385 | __func__, from_kuid(&init_user_ns, acred->cred->fsuid), | ||
1386 | auth->au_flavor); | ||
1387 | |||
1388 | if (!(cred = kzalloc(sizeof(*cred), gfp))) | 1344 | if (!(cred = kzalloc(sizeof(*cred), gfp))) |
1389 | goto out_err; | 1345 | goto out_err; |
1390 | 1346 | ||
@@ -1400,7 +1356,6 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags, gfp_t | |||
1400 | return &cred->gc_base; | 1356 | return &cred->gc_base; |
1401 | 1357 | ||
1402 | out_err: | 1358 | out_err: |
1403 | dprintk("RPC: %s failed with error %d\n", __func__, err); | ||
1404 | return ERR_PTR(err); | 1359 | return ERR_PTR(err); |
1405 | } | 1360 | } |
1406 | 1361 | ||
@@ -1526,69 +1481,84 @@ out: | |||
1526 | } | 1481 | } |
1527 | 1482 | ||
1528 | /* | 1483 | /* |
1529 | * Marshal credentials. | 1484 | * Marshal credentials. |
1530 | * Maybe we should keep a cached credential for performance reasons. | 1485 | * |
1531 | */ | 1486 | * The expensive part is computing the verifier. We can't cache a |
1532 | static __be32 * | 1487 | * pre-computed version of the verifier because the seqno, which |
1533 | gss_marshal(struct rpc_task *task, __be32 *p) | 1488 | * is different every time, is included in the MIC. |
1489 | */ | ||
1490 | static int gss_marshal(struct rpc_task *task, struct xdr_stream *xdr) | ||
1534 | { | 1491 | { |
1535 | struct rpc_rqst *req = task->tk_rqstp; | 1492 | struct rpc_rqst *req = task->tk_rqstp; |
1536 | struct rpc_cred *cred = req->rq_cred; | 1493 | struct rpc_cred *cred = req->rq_cred; |
1537 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, | 1494 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, |
1538 | gc_base); | 1495 | gc_base); |
1539 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); | 1496 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
1540 | __be32 *cred_len; | 1497 | __be32 *p, *cred_len; |
1541 | u32 maj_stat = 0; | 1498 | u32 maj_stat = 0; |
1542 | struct xdr_netobj mic; | 1499 | struct xdr_netobj mic; |
1543 | struct kvec iov; | 1500 | struct kvec iov; |
1544 | struct xdr_buf verf_buf; | 1501 | struct xdr_buf verf_buf; |
1502 | int status; | ||
1545 | 1503 | ||
1546 | dprintk("RPC: %5u %s\n", task->tk_pid, __func__); | 1504 | /* Credential */ |
1547 | 1505 | ||
1548 | *p++ = htonl(RPC_AUTH_GSS); | 1506 | p = xdr_reserve_space(xdr, 7 * sizeof(*p) + |
1507 | ctx->gc_wire_ctx.len); | ||
1508 | if (!p) | ||
1509 | goto marshal_failed; | ||
1510 | *p++ = rpc_auth_gss; | ||
1549 | cred_len = p++; | 1511 | cred_len = p++; |
1550 | 1512 | ||
1551 | spin_lock(&ctx->gc_seq_lock); | 1513 | spin_lock(&ctx->gc_seq_lock); |
1552 | req->rq_seqno = (ctx->gc_seq < MAXSEQ) ? ctx->gc_seq++ : MAXSEQ; | 1514 | req->rq_seqno = (ctx->gc_seq < MAXSEQ) ? ctx->gc_seq++ : MAXSEQ; |
1553 | spin_unlock(&ctx->gc_seq_lock); | 1515 | spin_unlock(&ctx->gc_seq_lock); |
1554 | if (req->rq_seqno == MAXSEQ) | 1516 | if (req->rq_seqno == MAXSEQ) |
1555 | goto out_expired; | 1517 | goto expired; |
1518 | trace_rpcgss_seqno(task); | ||
1556 | 1519 | ||
1557 | *p++ = htonl((u32) RPC_GSS_VERSION); | 1520 | *p++ = cpu_to_be32(RPC_GSS_VERSION); |
1558 | *p++ = htonl((u32) ctx->gc_proc); | 1521 | *p++ = cpu_to_be32(ctx->gc_proc); |
1559 | *p++ = htonl((u32) req->rq_seqno); | 1522 | *p++ = cpu_to_be32(req->rq_seqno); |
1560 | *p++ = htonl((u32) gss_cred->gc_service); | 1523 | *p++ = cpu_to_be32(gss_cred->gc_service); |
1561 | p = xdr_encode_netobj(p, &ctx->gc_wire_ctx); | 1524 | p = xdr_encode_netobj(p, &ctx->gc_wire_ctx); |
1562 | *cred_len = htonl((p - (cred_len + 1)) << 2); | 1525 | *cred_len = cpu_to_be32((p - (cred_len + 1)) << 2); |
1526 | |||
1527 | /* Verifier */ | ||
1563 | 1528 | ||
1564 | /* We compute the checksum for the verifier over the xdr-encoded bytes | 1529 | /* We compute the checksum for the verifier over the xdr-encoded bytes |
1565 | * starting with the xid and ending at the end of the credential: */ | 1530 | * starting with the xid and ending at the end of the credential: */ |
1566 | iov.iov_base = xprt_skip_transport_header(req->rq_xprt, | 1531 | iov.iov_base = req->rq_snd_buf.head[0].iov_base; |
1567 | req->rq_snd_buf.head[0].iov_base); | ||
1568 | iov.iov_len = (u8 *)p - (u8 *)iov.iov_base; | 1532 | iov.iov_len = (u8 *)p - (u8 *)iov.iov_base; |
1569 | xdr_buf_from_iov(&iov, &verf_buf); | 1533 | xdr_buf_from_iov(&iov, &verf_buf); |
1570 | 1534 | ||
1571 | /* set verifier flavor*/ | 1535 | p = xdr_reserve_space(xdr, sizeof(*p)); |
1572 | *p++ = htonl(RPC_AUTH_GSS); | 1536 | if (!p) |
1573 | 1537 | goto marshal_failed; | |
1538 | *p++ = rpc_auth_gss; | ||
1574 | mic.data = (u8 *)(p + 1); | 1539 | mic.data = (u8 *)(p + 1); |
1575 | maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic); | 1540 | maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic); |
1576 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) { | 1541 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
1577 | goto out_expired; | 1542 | goto expired; |
1578 | } else if (maj_stat != 0) { | 1543 | else if (maj_stat != 0) |
1579 | pr_warn("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat); | 1544 | goto bad_mic; |
1580 | task->tk_status = -EIO; | 1545 | if (xdr_stream_encode_opaque_inline(xdr, (void **)&p, mic.len) < 0) |
1581 | goto out_put_ctx; | 1546 | goto marshal_failed; |
1582 | } | 1547 | status = 0; |
1583 | p = xdr_encode_opaque(p, NULL, mic.len); | 1548 | out: |
1584 | gss_put_ctx(ctx); | 1549 | gss_put_ctx(ctx); |
1585 | return p; | 1550 | return status; |
1586 | out_expired: | 1551 | expired: |
1587 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); | 1552 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
1588 | task->tk_status = -EKEYEXPIRED; | 1553 | status = -EKEYEXPIRED; |
1589 | out_put_ctx: | 1554 | goto out; |
1590 | gss_put_ctx(ctx); | 1555 | marshal_failed: |
1591 | return NULL; | 1556 | status = -EMSGSIZE; |
1557 | goto out; | ||
1558 | bad_mic: | ||
1559 | trace_rpcgss_get_mic(task, maj_stat); | ||
1560 | status = -EIO; | ||
1561 | goto out; | ||
1592 | } | 1562 | } |
1593 | 1563 | ||
1594 | static int gss_renew_cred(struct rpc_task *task) | 1564 | static int gss_renew_cred(struct rpc_task *task) |
@@ -1662,116 +1632,105 @@ gss_refresh_null(struct rpc_task *task) | |||
1662 | return 0; | 1632 | return 0; |
1663 | } | 1633 | } |
1664 | 1634 | ||
1665 | static __be32 * | 1635 | static int |
1666 | gss_validate(struct rpc_task *task, __be32 *p) | 1636 | gss_validate(struct rpc_task *task, struct xdr_stream *xdr) |
1667 | { | 1637 | { |
1668 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; | 1638 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
1669 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); | 1639 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
1670 | __be32 *seq = NULL; | 1640 | __be32 *p, *seq = NULL; |
1671 | struct kvec iov; | 1641 | struct kvec iov; |
1672 | struct xdr_buf verf_buf; | 1642 | struct xdr_buf verf_buf; |
1673 | struct xdr_netobj mic; | 1643 | struct xdr_netobj mic; |
1674 | u32 flav,len; | 1644 | u32 len, maj_stat; |
1675 | u32 maj_stat; | 1645 | int status; |
1676 | __be32 *ret = ERR_PTR(-EIO); | ||
1677 | 1646 | ||
1678 | dprintk("RPC: %5u %s\n", task->tk_pid, __func__); | 1647 | p = xdr_inline_decode(xdr, 2 * sizeof(*p)); |
1648 | if (!p) | ||
1649 | goto validate_failed; | ||
1650 | if (*p++ != rpc_auth_gss) | ||
1651 | goto validate_failed; | ||
1652 | len = be32_to_cpup(p); | ||
1653 | if (len > RPC_MAX_AUTH_SIZE) | ||
1654 | goto validate_failed; | ||
1655 | p = xdr_inline_decode(xdr, len); | ||
1656 | if (!p) | ||
1657 | goto validate_failed; | ||
1679 | 1658 | ||
1680 | flav = ntohl(*p++); | ||
1681 | if ((len = ntohl(*p++)) > RPC_MAX_AUTH_SIZE) | ||
1682 | goto out_bad; | ||
1683 | if (flav != RPC_AUTH_GSS) | ||
1684 | goto out_bad; | ||
1685 | seq = kmalloc(4, GFP_NOFS); | 1659 | seq = kmalloc(4, GFP_NOFS); |
1686 | if (!seq) | 1660 | if (!seq) |
1687 | goto out_bad; | 1661 | goto validate_failed; |
1688 | *seq = htonl(task->tk_rqstp->rq_seqno); | 1662 | *seq = cpu_to_be32(task->tk_rqstp->rq_seqno); |
1689 | iov.iov_base = seq; | 1663 | iov.iov_base = seq; |
1690 | iov.iov_len = 4; | 1664 | iov.iov_len = 4; |
1691 | xdr_buf_from_iov(&iov, &verf_buf); | 1665 | xdr_buf_from_iov(&iov, &verf_buf); |
1692 | mic.data = (u8 *)p; | 1666 | mic.data = (u8 *)p; |
1693 | mic.len = len; | 1667 | mic.len = len; |
1694 | |||
1695 | ret = ERR_PTR(-EACCES); | ||
1696 | maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic); | 1668 | maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic); |
1697 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) | 1669 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
1698 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); | 1670 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
1699 | if (maj_stat) { | 1671 | if (maj_stat) |
1700 | dprintk("RPC: %5u %s: gss_verify_mic returned error 0x%08x\n", | 1672 | goto bad_mic; |
1701 | task->tk_pid, __func__, maj_stat); | 1673 | |
1702 | goto out_bad; | ||
1703 | } | ||
1704 | /* We leave it to unwrap to calculate au_rslack. For now we just | 1674 | /* We leave it to unwrap to calculate au_rslack. For now we just |
1705 | * calculate the length of the verifier: */ | 1675 | * calculate the length of the verifier: */ |
1706 | cred->cr_auth->au_verfsize = XDR_QUADLEN(len) + 2; | 1676 | cred->cr_auth->au_verfsize = XDR_QUADLEN(len) + 2; |
1677 | status = 0; | ||
1678 | out: | ||
1707 | gss_put_ctx(ctx); | 1679 | gss_put_ctx(ctx); |
1708 | dprintk("RPC: %5u %s: gss_verify_mic succeeded.\n", | ||
1709 | task->tk_pid, __func__); | ||
1710 | kfree(seq); | ||
1711 | return p + XDR_QUADLEN(len); | ||
1712 | out_bad: | ||
1713 | gss_put_ctx(ctx); | ||
1714 | dprintk("RPC: %5u %s failed ret %ld.\n", task->tk_pid, __func__, | ||
1715 | PTR_ERR(ret)); | ||
1716 | kfree(seq); | 1680 | kfree(seq); |
1717 | return ret; | 1681 | return status; |
1718 | } | ||
1719 | |||
1720 | static void gss_wrap_req_encode(kxdreproc_t encode, struct rpc_rqst *rqstp, | ||
1721 | __be32 *p, void *obj) | ||
1722 | { | ||
1723 | struct xdr_stream xdr; | ||
1724 | 1682 | ||
1725 | xdr_init_encode(&xdr, &rqstp->rq_snd_buf, p); | 1683 | validate_failed: |
1726 | encode(rqstp, &xdr, obj); | 1684 | status = -EIO; |
1685 | goto out; | ||
1686 | bad_mic: | ||
1687 | trace_rpcgss_verify_mic(task, maj_stat); | ||
1688 | status = -EACCES; | ||
1689 | goto out; | ||
1727 | } | 1690 | } |
1728 | 1691 | ||
1729 | static inline int | 1692 | static int gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx, |
1730 | gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx, | 1693 | struct rpc_task *task, struct xdr_stream *xdr) |
1731 | kxdreproc_t encode, struct rpc_rqst *rqstp, | ||
1732 | __be32 *p, void *obj) | ||
1733 | { | 1694 | { |
1734 | struct xdr_buf *snd_buf = &rqstp->rq_snd_buf; | 1695 | struct rpc_rqst *rqstp = task->tk_rqstp; |
1735 | struct xdr_buf integ_buf; | 1696 | struct xdr_buf integ_buf, *snd_buf = &rqstp->rq_snd_buf; |
1736 | __be32 *integ_len = NULL; | ||
1737 | struct xdr_netobj mic; | 1697 | struct xdr_netobj mic; |
1738 | u32 offset; | 1698 | __be32 *p, *integ_len; |
1739 | __be32 *q; | 1699 | u32 offset, maj_stat; |
1740 | struct kvec *iov; | ||
1741 | u32 maj_stat = 0; | ||
1742 | int status = -EIO; | ||
1743 | 1700 | ||
1701 | p = xdr_reserve_space(xdr, 2 * sizeof(*p)); | ||
1702 | if (!p) | ||
1703 | goto wrap_failed; | ||
1744 | integ_len = p++; | 1704 | integ_len = p++; |
1745 | offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base; | 1705 | *p = cpu_to_be32(rqstp->rq_seqno); |
1746 | *p++ = htonl(rqstp->rq_seqno); | ||
1747 | 1706 | ||
1748 | gss_wrap_req_encode(encode, rqstp, p, obj); | 1707 | if (rpcauth_wrap_req_encode(task, xdr)) |
1708 | goto wrap_failed; | ||
1749 | 1709 | ||
1710 | offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base; | ||
1750 | if (xdr_buf_subsegment(snd_buf, &integ_buf, | 1711 | if (xdr_buf_subsegment(snd_buf, &integ_buf, |
1751 | offset, snd_buf->len - offset)) | 1712 | offset, snd_buf->len - offset)) |
1752 | return status; | 1713 | goto wrap_failed; |
1753 | *integ_len = htonl(integ_buf.len); | 1714 | *integ_len = cpu_to_be32(integ_buf.len); |
1754 | 1715 | ||
1755 | /* guess whether we're in the head or the tail: */ | 1716 | p = xdr_reserve_space(xdr, 0); |
1756 | if (snd_buf->page_len || snd_buf->tail[0].iov_len) | 1717 | if (!p) |
1757 | iov = snd_buf->tail; | 1718 | goto wrap_failed; |
1758 | else | ||
1759 | iov = snd_buf->head; | ||
1760 | p = iov->iov_base + iov->iov_len; | ||
1761 | mic.data = (u8 *)(p + 1); | 1719 | mic.data = (u8 *)(p + 1); |
1762 | |||
1763 | maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic); | 1720 | maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic); |
1764 | status = -EIO; /* XXX? */ | ||
1765 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) | 1721 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
1766 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); | 1722 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
1767 | else if (maj_stat) | 1723 | else if (maj_stat) |
1768 | return status; | 1724 | goto bad_mic; |
1769 | q = xdr_encode_opaque(p, NULL, mic.len); | 1725 | /* Check that the trailing MIC fit in the buffer, after the fact */ |
1770 | 1726 | if (xdr_stream_encode_opaque_inline(xdr, (void **)&p, mic.len) < 0) | |
1771 | offset = (u8 *)q - (u8 *)p; | 1727 | goto wrap_failed; |
1772 | iov->iov_len += offset; | ||
1773 | snd_buf->len += offset; | ||
1774 | return 0; | 1728 | return 0; |
1729 | wrap_failed: | ||
1730 | return -EMSGSIZE; | ||
1731 | bad_mic: | ||
1732 | trace_rpcgss_get_mic(task, maj_stat); | ||
1733 | return -EIO; | ||
1775 | } | 1734 | } |
1776 | 1735 | ||
1777 | static void | 1736 | static void |
@@ -1822,61 +1781,62 @@ out: | |||
1822 | return -EAGAIN; | 1781 | return -EAGAIN; |
1823 | } | 1782 | } |
1824 | 1783 | ||
1825 | static inline int | 1784 | static int gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx, |
1826 | gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx, | 1785 | struct rpc_task *task, struct xdr_stream *xdr) |
1827 | kxdreproc_t encode, struct rpc_rqst *rqstp, | ||
1828 | __be32 *p, void *obj) | ||
1829 | { | 1786 | { |
1787 | struct rpc_rqst *rqstp = task->tk_rqstp; | ||
1830 | struct xdr_buf *snd_buf = &rqstp->rq_snd_buf; | 1788 | struct xdr_buf *snd_buf = &rqstp->rq_snd_buf; |
1831 | u32 offset; | 1789 | u32 pad, offset, maj_stat; |
1832 | u32 maj_stat; | ||
1833 | int status; | 1790 | int status; |
1834 | __be32 *opaque_len; | 1791 | __be32 *p, *opaque_len; |
1835 | struct page **inpages; | 1792 | struct page **inpages; |
1836 | int first; | 1793 | int first; |
1837 | int pad; | ||
1838 | struct kvec *iov; | 1794 | struct kvec *iov; |
1839 | char *tmp; | ||
1840 | 1795 | ||
1796 | status = -EIO; | ||
1797 | p = xdr_reserve_space(xdr, 2 * sizeof(*p)); | ||
1798 | if (!p) | ||
1799 | goto wrap_failed; | ||
1841 | opaque_len = p++; | 1800 | opaque_len = p++; |
1842 | offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base; | 1801 | *p = cpu_to_be32(rqstp->rq_seqno); |
1843 | *p++ = htonl(rqstp->rq_seqno); | ||
1844 | 1802 | ||
1845 | gss_wrap_req_encode(encode, rqstp, p, obj); | 1803 | if (rpcauth_wrap_req_encode(task, xdr)) |
1804 | goto wrap_failed; | ||
1846 | 1805 | ||
1847 | status = alloc_enc_pages(rqstp); | 1806 | status = alloc_enc_pages(rqstp); |
1848 | if (status) | 1807 | if (unlikely(status)) |
1849 | return status; | 1808 | goto wrap_failed; |
1850 | first = snd_buf->page_base >> PAGE_SHIFT; | 1809 | first = snd_buf->page_base >> PAGE_SHIFT; |
1851 | inpages = snd_buf->pages + first; | 1810 | inpages = snd_buf->pages + first; |
1852 | snd_buf->pages = rqstp->rq_enc_pages; | 1811 | snd_buf->pages = rqstp->rq_enc_pages; |
1853 | snd_buf->page_base -= first << PAGE_SHIFT; | 1812 | snd_buf->page_base -= first << PAGE_SHIFT; |
1854 | /* | 1813 | /* |
1855 | * Give the tail its own page, in case we need extra space in the | 1814 | * Move the tail into its own page, in case gss_wrap needs |
1856 | * head when wrapping: | 1815 | * more space in the head when wrapping. |
1857 | * | 1816 | * |
1858 | * call_allocate() allocates twice the slack space required | 1817 | * Still... Why can't gss_wrap just slide the tail down? |
1859 | * by the authentication flavor to rq_callsize. | ||
1860 | * For GSS, slack is GSS_CRED_SLACK. | ||
1861 | */ | 1818 | */ |
1862 | if (snd_buf->page_len || snd_buf->tail[0].iov_len) { | 1819 | if (snd_buf->page_len || snd_buf->tail[0].iov_len) { |
1820 | char *tmp; | ||
1821 | |||
1863 | tmp = page_address(rqstp->rq_enc_pages[rqstp->rq_enc_pages_num - 1]); | 1822 | tmp = page_address(rqstp->rq_enc_pages[rqstp->rq_enc_pages_num - 1]); |
1864 | memcpy(tmp, snd_buf->tail[0].iov_base, snd_buf->tail[0].iov_len); | 1823 | memcpy(tmp, snd_buf->tail[0].iov_base, snd_buf->tail[0].iov_len); |
1865 | snd_buf->tail[0].iov_base = tmp; | 1824 | snd_buf->tail[0].iov_base = tmp; |
1866 | } | 1825 | } |
1826 | offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base; | ||
1867 | maj_stat = gss_wrap(ctx->gc_gss_ctx, offset, snd_buf, inpages); | 1827 | maj_stat = gss_wrap(ctx->gc_gss_ctx, offset, snd_buf, inpages); |
1868 | /* slack space should prevent this ever happening: */ | 1828 | /* slack space should prevent this ever happening: */ |
1869 | BUG_ON(snd_buf->len > snd_buf->buflen); | 1829 | if (unlikely(snd_buf->len > snd_buf->buflen)) |
1870 | status = -EIO; | 1830 | goto wrap_failed; |
1871 | /* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was | 1831 | /* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was |
1872 | * done anyway, so it's safe to put the request on the wire: */ | 1832 | * done anyway, so it's safe to put the request on the wire: */ |
1873 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) | 1833 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
1874 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); | 1834 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
1875 | else if (maj_stat) | 1835 | else if (maj_stat) |
1876 | return status; | 1836 | goto bad_wrap; |
1877 | 1837 | ||
1878 | *opaque_len = htonl(snd_buf->len - offset); | 1838 | *opaque_len = cpu_to_be32(snd_buf->len - offset); |
1879 | /* guess whether we're in the head or the tail: */ | 1839 | /* guess whether the pad goes into the head or the tail: */ |
1880 | if (snd_buf->page_len || snd_buf->tail[0].iov_len) | 1840 | if (snd_buf->page_len || snd_buf->tail[0].iov_len) |
1881 | iov = snd_buf->tail; | 1841 | iov = snd_buf->tail; |
1882 | else | 1842 | else |
@@ -1888,118 +1848,154 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx, | |||
1888 | snd_buf->len += pad; | 1848 | snd_buf->len += pad; |
1889 | 1849 | ||
1890 | return 0; | 1850 | return 0; |
1851 | wrap_failed: | ||
1852 | return status; | ||
1853 | bad_wrap: | ||
1854 | trace_rpcgss_wrap(task, maj_stat); | ||
1855 | return -EIO; | ||
1891 | } | 1856 | } |
1892 | 1857 | ||
1893 | static int | 1858 | static int gss_wrap_req(struct rpc_task *task, struct xdr_stream *xdr) |
1894 | gss_wrap_req(struct rpc_task *task, | ||
1895 | kxdreproc_t encode, void *rqstp, __be32 *p, void *obj) | ||
1896 | { | 1859 | { |
1897 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; | 1860 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
1898 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, | 1861 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, |
1899 | gc_base); | 1862 | gc_base); |
1900 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); | 1863 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
1901 | int status = -EIO; | 1864 | int status; |
1902 | 1865 | ||
1903 | dprintk("RPC: %5u %s\n", task->tk_pid, __func__); | 1866 | status = -EIO; |
1904 | if (ctx->gc_proc != RPC_GSS_PROC_DATA) { | 1867 | if (ctx->gc_proc != RPC_GSS_PROC_DATA) { |
1905 | /* The spec seems a little ambiguous here, but I think that not | 1868 | /* The spec seems a little ambiguous here, but I think that not |
1906 | * wrapping context destruction requests makes the most sense. | 1869 | * wrapping context destruction requests makes the most sense. |
1907 | */ | 1870 | */ |
1908 | gss_wrap_req_encode(encode, rqstp, p, obj); | 1871 | status = rpcauth_wrap_req_encode(task, xdr); |
1909 | status = 0; | ||
1910 | goto out; | 1872 | goto out; |
1911 | } | 1873 | } |
1912 | switch (gss_cred->gc_service) { | 1874 | switch (gss_cred->gc_service) { |
1913 | case RPC_GSS_SVC_NONE: | 1875 | case RPC_GSS_SVC_NONE: |
1914 | gss_wrap_req_encode(encode, rqstp, p, obj); | 1876 | status = rpcauth_wrap_req_encode(task, xdr); |
1915 | status = 0; | ||
1916 | break; | 1877 | break; |
1917 | case RPC_GSS_SVC_INTEGRITY: | 1878 | case RPC_GSS_SVC_INTEGRITY: |
1918 | status = gss_wrap_req_integ(cred, ctx, encode, rqstp, p, obj); | 1879 | status = gss_wrap_req_integ(cred, ctx, task, xdr); |
1919 | break; | 1880 | break; |
1920 | case RPC_GSS_SVC_PRIVACY: | 1881 | case RPC_GSS_SVC_PRIVACY: |
1921 | status = gss_wrap_req_priv(cred, ctx, encode, rqstp, p, obj); | 1882 | status = gss_wrap_req_priv(cred, ctx, task, xdr); |
1922 | break; | 1883 | break; |
1884 | default: | ||
1885 | status = -EIO; | ||
1923 | } | 1886 | } |
1924 | out: | 1887 | out: |
1925 | gss_put_ctx(ctx); | 1888 | gss_put_ctx(ctx); |
1926 | dprintk("RPC: %5u %s returning %d\n", task->tk_pid, __func__, status); | ||
1927 | return status; | 1889 | return status; |
1928 | } | 1890 | } |
1929 | 1891 | ||
1930 | static inline int | 1892 | static int |
1931 | gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx, | 1893 | gss_unwrap_resp_auth(struct rpc_cred *cred) |
1932 | struct rpc_rqst *rqstp, __be32 **p) | ||
1933 | { | 1894 | { |
1934 | struct xdr_buf *rcv_buf = &rqstp->rq_rcv_buf; | 1895 | struct rpc_auth *auth = cred->cr_auth; |
1935 | struct xdr_buf integ_buf; | 1896 | |
1897 | auth->au_rslack = auth->au_verfsize; | ||
1898 | auth->au_ralign = auth->au_verfsize; | ||
1899 | return 0; | ||
1900 | } | ||
1901 | |||
1902 | static int | ||
1903 | gss_unwrap_resp_integ(struct rpc_task *task, struct rpc_cred *cred, | ||
1904 | struct gss_cl_ctx *ctx, struct rpc_rqst *rqstp, | ||
1905 | struct xdr_stream *xdr) | ||
1906 | { | ||
1907 | struct xdr_buf integ_buf, *rcv_buf = &rqstp->rq_rcv_buf; | ||
1908 | u32 data_offset, mic_offset, integ_len, maj_stat; | ||
1909 | struct rpc_auth *auth = cred->cr_auth; | ||
1936 | struct xdr_netobj mic; | 1910 | struct xdr_netobj mic; |
1937 | u32 data_offset, mic_offset; | 1911 | __be32 *p; |
1938 | u32 integ_len; | ||
1939 | u32 maj_stat; | ||
1940 | int status = -EIO; | ||
1941 | 1912 | ||
1942 | integ_len = ntohl(*(*p)++); | 1913 | p = xdr_inline_decode(xdr, 2 * sizeof(*p)); |
1914 | if (unlikely(!p)) | ||
1915 | goto unwrap_failed; | ||
1916 | integ_len = be32_to_cpup(p++); | ||
1943 | if (integ_len & 3) | 1917 | if (integ_len & 3) |
1944 | return status; | 1918 | goto unwrap_failed; |
1945 | data_offset = (u8 *)(*p) - (u8 *)rcv_buf->head[0].iov_base; | 1919 | data_offset = (u8 *)(p) - (u8 *)rcv_buf->head[0].iov_base; |
1946 | mic_offset = integ_len + data_offset; | 1920 | mic_offset = integ_len + data_offset; |
1947 | if (mic_offset > rcv_buf->len) | 1921 | if (mic_offset > rcv_buf->len) |
1948 | return status; | 1922 | goto unwrap_failed; |
1949 | if (ntohl(*(*p)++) != rqstp->rq_seqno) | 1923 | if (be32_to_cpup(p) != rqstp->rq_seqno) |
1950 | return status; | 1924 | goto bad_seqno; |
1951 | |||
1952 | if (xdr_buf_subsegment(rcv_buf, &integ_buf, data_offset, | ||
1953 | mic_offset - data_offset)) | ||
1954 | return status; | ||
1955 | 1925 | ||
1926 | if (xdr_buf_subsegment(rcv_buf, &integ_buf, data_offset, integ_len)) | ||
1927 | goto unwrap_failed; | ||
1956 | if (xdr_buf_read_netobj(rcv_buf, &mic, mic_offset)) | 1928 | if (xdr_buf_read_netobj(rcv_buf, &mic, mic_offset)) |
1957 | return status; | 1929 | goto unwrap_failed; |
1958 | |||
1959 | maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic); | 1930 | maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic); |
1960 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) | 1931 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
1961 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); | 1932 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
1962 | if (maj_stat != GSS_S_COMPLETE) | 1933 | if (maj_stat != GSS_S_COMPLETE) |
1963 | return status; | 1934 | goto bad_mic; |
1935 | |||
1936 | auth->au_rslack = auth->au_verfsize + 2 + 1 + XDR_QUADLEN(mic.len); | ||
1937 | auth->au_ralign = auth->au_verfsize + 2; | ||
1964 | return 0; | 1938 | return 0; |
1939 | unwrap_failed: | ||
1940 | trace_rpcgss_unwrap_failed(task); | ||
1941 | return -EIO; | ||
1942 | bad_seqno: | ||
1943 | trace_rpcgss_bad_seqno(task, rqstp->rq_seqno, be32_to_cpup(p)); | ||
1944 | return -EIO; | ||
1945 | bad_mic: | ||
1946 | trace_rpcgss_verify_mic(task, maj_stat); | ||
1947 | return -EIO; | ||
1965 | } | 1948 | } |
1966 | 1949 | ||
1967 | static inline int | 1950 | static int |
1968 | gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx, | 1951 | gss_unwrap_resp_priv(struct rpc_task *task, struct rpc_cred *cred, |
1969 | struct rpc_rqst *rqstp, __be32 **p) | 1952 | struct gss_cl_ctx *ctx, struct rpc_rqst *rqstp, |
1970 | { | 1953 | struct xdr_stream *xdr) |
1971 | struct xdr_buf *rcv_buf = &rqstp->rq_rcv_buf; | 1954 | { |
1972 | u32 offset; | 1955 | struct xdr_buf *rcv_buf = &rqstp->rq_rcv_buf; |
1973 | u32 opaque_len; | 1956 | struct kvec *head = rqstp->rq_rcv_buf.head; |
1974 | u32 maj_stat; | 1957 | struct rpc_auth *auth = cred->cr_auth; |
1975 | int status = -EIO; | 1958 | unsigned int savedlen = rcv_buf->len; |
1976 | 1959 | u32 offset, opaque_len, maj_stat; | |
1977 | opaque_len = ntohl(*(*p)++); | 1960 | __be32 *p; |
1978 | offset = (u8 *)(*p) - (u8 *)rcv_buf->head[0].iov_base; | 1961 | |
1962 | p = xdr_inline_decode(xdr, 2 * sizeof(*p)); | ||
1963 | if (unlikely(!p)) | ||
1964 | goto unwrap_failed; | ||
1965 | opaque_len = be32_to_cpup(p++); | ||
1966 | offset = (u8 *)(p) - (u8 *)head->iov_base; | ||
1979 | if (offset + opaque_len > rcv_buf->len) | 1967 | if (offset + opaque_len > rcv_buf->len) |
1980 | return status; | 1968 | goto unwrap_failed; |
1981 | /* remove padding: */ | ||
1982 | rcv_buf->len = offset + opaque_len; | 1969 | rcv_buf->len = offset + opaque_len; |
1983 | 1970 | ||
1984 | maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf); | 1971 | maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf); |
1985 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) | 1972 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
1986 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); | 1973 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
1987 | if (maj_stat != GSS_S_COMPLETE) | 1974 | if (maj_stat != GSS_S_COMPLETE) |
1988 | return status; | 1975 | goto bad_unwrap; |
1989 | if (ntohl(*(*p)++) != rqstp->rq_seqno) | 1976 | /* gss_unwrap decrypted the sequence number */ |
1990 | return status; | 1977 | if (be32_to_cpup(p++) != rqstp->rq_seqno) |
1978 | goto bad_seqno; | ||
1991 | 1979 | ||
1992 | return 0; | 1980 | /* gss_unwrap redacts the opaque blob from the head iovec. |
1993 | } | 1981 | * rcv_buf has changed, thus the stream needs to be reset. |
1994 | 1982 | */ | |
1995 | static int | 1983 | xdr_init_decode(xdr, rcv_buf, p, rqstp); |
1996 | gss_unwrap_req_decode(kxdrdproc_t decode, struct rpc_rqst *rqstp, | ||
1997 | __be32 *p, void *obj) | ||
1998 | { | ||
1999 | struct xdr_stream xdr; | ||
2000 | 1984 | ||
2001 | xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); | 1985 | auth->au_rslack = auth->au_verfsize + 2 + |
2002 | return decode(rqstp, &xdr, obj); | 1986 | XDR_QUADLEN(savedlen - rcv_buf->len); |
1987 | auth->au_ralign = auth->au_verfsize + 2 + | ||
1988 | XDR_QUADLEN(savedlen - rcv_buf->len); | ||
1989 | return 0; | ||
1990 | unwrap_failed: | ||
1991 | trace_rpcgss_unwrap_failed(task); | ||
1992 | return -EIO; | ||
1993 | bad_seqno: | ||
1994 | trace_rpcgss_bad_seqno(task, rqstp->rq_seqno, be32_to_cpup(--p)); | ||
1995 | return -EIO; | ||
1996 | bad_unwrap: | ||
1997 | trace_rpcgss_unwrap(task, maj_stat); | ||
1998 | return -EIO; | ||
2003 | } | 1999 | } |
2004 | 2000 | ||
2005 | static bool | 2001 | static bool |
@@ -2014,14 +2010,14 @@ gss_xmit_need_reencode(struct rpc_task *task) | |||
2014 | struct rpc_rqst *req = task->tk_rqstp; | 2010 | struct rpc_rqst *req = task->tk_rqstp; |
2015 | struct rpc_cred *cred = req->rq_cred; | 2011 | struct rpc_cred *cred = req->rq_cred; |
2016 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); | 2012 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
2017 | u32 win, seq_xmit; | 2013 | u32 win, seq_xmit = 0; |
2018 | bool ret = true; | 2014 | bool ret = true; |
2019 | 2015 | ||
2020 | if (!ctx) | 2016 | if (!ctx) |
2021 | return true; | 2017 | goto out; |
2022 | 2018 | ||
2023 | if (gss_seq_is_newer(req->rq_seqno, READ_ONCE(ctx->gc_seq))) | 2019 | if (gss_seq_is_newer(req->rq_seqno, READ_ONCE(ctx->gc_seq))) |
2024 | goto out; | 2020 | goto out_ctx; |
2025 | 2021 | ||
2026 | seq_xmit = READ_ONCE(ctx->gc_seq_xmit); | 2022 | seq_xmit = READ_ONCE(ctx->gc_seq_xmit); |
2027 | while (gss_seq_is_newer(req->rq_seqno, seq_xmit)) { | 2023 | while (gss_seq_is_newer(req->rq_seqno, seq_xmit)) { |
@@ -2030,56 +2026,51 @@ gss_xmit_need_reencode(struct rpc_task *task) | |||
2030 | seq_xmit = cmpxchg(&ctx->gc_seq_xmit, tmp, req->rq_seqno); | 2026 | seq_xmit = cmpxchg(&ctx->gc_seq_xmit, tmp, req->rq_seqno); |
2031 | if (seq_xmit == tmp) { | 2027 | if (seq_xmit == tmp) { |
2032 | ret = false; | 2028 | ret = false; |
2033 | goto out; | 2029 | goto out_ctx; |
2034 | } | 2030 | } |
2035 | } | 2031 | } |
2036 | 2032 | ||
2037 | win = ctx->gc_win; | 2033 | win = ctx->gc_win; |
2038 | if (win > 0) | 2034 | if (win > 0) |
2039 | ret = !gss_seq_is_newer(req->rq_seqno, seq_xmit - win); | 2035 | ret = !gss_seq_is_newer(req->rq_seqno, seq_xmit - win); |
2040 | out: | 2036 | |
2037 | out_ctx: | ||
2041 | gss_put_ctx(ctx); | 2038 | gss_put_ctx(ctx); |
2039 | out: | ||
2040 | trace_rpcgss_need_reencode(task, seq_xmit, ret); | ||
2042 | return ret; | 2041 | return ret; |
2043 | } | 2042 | } |
2044 | 2043 | ||
2045 | static int | 2044 | static int |
2046 | gss_unwrap_resp(struct rpc_task *task, | 2045 | gss_unwrap_resp(struct rpc_task *task, struct xdr_stream *xdr) |
2047 | kxdrdproc_t decode, void *rqstp, __be32 *p, void *obj) | ||
2048 | { | 2046 | { |
2049 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; | 2047 | struct rpc_rqst *rqstp = task->tk_rqstp; |
2048 | struct rpc_cred *cred = rqstp->rq_cred; | ||
2050 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, | 2049 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, |
2051 | gc_base); | 2050 | gc_base); |
2052 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); | 2051 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
2053 | __be32 *savedp = p; | 2052 | int status = -EIO; |
2054 | struct kvec *head = ((struct rpc_rqst *)rqstp)->rq_rcv_buf.head; | ||
2055 | int savedlen = head->iov_len; | ||
2056 | int status = -EIO; | ||
2057 | 2053 | ||
2058 | if (ctx->gc_proc != RPC_GSS_PROC_DATA) | 2054 | if (ctx->gc_proc != RPC_GSS_PROC_DATA) |
2059 | goto out_decode; | 2055 | goto out_decode; |
2060 | switch (gss_cred->gc_service) { | 2056 | switch (gss_cred->gc_service) { |
2061 | case RPC_GSS_SVC_NONE: | 2057 | case RPC_GSS_SVC_NONE: |
2058 | status = gss_unwrap_resp_auth(cred); | ||
2062 | break; | 2059 | break; |
2063 | case RPC_GSS_SVC_INTEGRITY: | 2060 | case RPC_GSS_SVC_INTEGRITY: |
2064 | status = gss_unwrap_resp_integ(cred, ctx, rqstp, &p); | 2061 | status = gss_unwrap_resp_integ(task, cred, ctx, rqstp, xdr); |
2065 | if (status) | ||
2066 | goto out; | ||
2067 | break; | 2062 | break; |
2068 | case RPC_GSS_SVC_PRIVACY: | 2063 | case RPC_GSS_SVC_PRIVACY: |
2069 | status = gss_unwrap_resp_priv(cred, ctx, rqstp, &p); | 2064 | status = gss_unwrap_resp_priv(task, cred, ctx, rqstp, xdr); |
2070 | if (status) | ||
2071 | goto out; | ||
2072 | break; | 2065 | break; |
2073 | } | 2066 | } |
2074 | /* take into account extra slack for integrity and privacy cases: */ | 2067 | if (status) |
2075 | cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + (p - savedp) | 2068 | goto out; |
2076 | + (savedlen - head->iov_len); | 2069 | |
2077 | out_decode: | 2070 | out_decode: |
2078 | status = gss_unwrap_req_decode(decode, rqstp, p, obj); | 2071 | status = rpcauth_unwrap_resp_decode(task, xdr); |
2079 | out: | 2072 | out: |
2080 | gss_put_ctx(ctx); | 2073 | gss_put_ctx(ctx); |
2081 | dprintk("RPC: %5u %s returning %d\n", | ||
2082 | task->tk_pid, __func__, status); | ||
2083 | return status; | 2074 | return status; |
2084 | } | 2075 | } |
2085 | 2076 | ||
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index eab71fc7af3e..56cc85c5bc06 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: BSD-3-Clause | ||
1 | /* | 2 | /* |
2 | * linux/net/sunrpc/gss_krb5_mech.c | 3 | * linux/net/sunrpc/gss_krb5_mech.c |
3 | * | 4 | * |
@@ -6,32 +7,6 @@ | |||
6 | * | 7 | * |
7 | * Andy Adamson <andros@umich.edu> | 8 | * Andy Adamson <andros@umich.edu> |
8 | * J. Bruce Fields <bfields@umich.edu> | 9 | * J. Bruce Fields <bfields@umich.edu> |
9 | * | ||
10 | * Redistribution and use in source and binary forms, with or without | ||
11 | * modification, are permitted provided that the following conditions | ||
12 | * are met: | ||
13 | * | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer. | ||
16 | * 2. Redistributions in binary form must reproduce the above copyright | ||
17 | * notice, this list of conditions and the following disclaimer in the | ||
18 | * documentation and/or other materials provided with the distribution. | ||
19 | * 3. Neither the name of the University nor the names of its | ||
20 | * contributors may be used to endorse or promote products derived | ||
21 | * from this software without specific prior written permission. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
24 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
25 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
26 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
27 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
30 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
31 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
32 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
33 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
34 | * | ||
35 | */ | 10 | */ |
36 | 11 | ||
37 | #include <crypto/hash.h> | 12 | #include <crypto/hash.h> |
@@ -53,6 +28,7 @@ | |||
53 | static struct gss_api_mech gss_kerberos_mech; /* forward declaration */ | 28 | static struct gss_api_mech gss_kerberos_mech; /* forward declaration */ |
54 | 29 | ||
55 | static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { | 30 | static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { |
31 | #ifndef CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES | ||
56 | /* | 32 | /* |
57 | * DES (All DES enctypes are mapped to the same gss functionality) | 33 | * DES (All DES enctypes are mapped to the same gss functionality) |
58 | */ | 34 | */ |
@@ -74,6 +50,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { | |||
74 | .cksumlength = 8, | 50 | .cksumlength = 8, |
75 | .keyed_cksum = 0, | 51 | .keyed_cksum = 0, |
76 | }, | 52 | }, |
53 | #endif /* CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES */ | ||
77 | /* | 54 | /* |
78 | * RC4-HMAC | 55 | * RC4-HMAC |
79 | */ | 56 | */ |
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 5cdde6cb703a..14a0aff0cd84 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c | |||
@@ -570,14 +570,16 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) | |||
570 | */ | 570 | */ |
571 | movelen = min_t(unsigned int, buf->head[0].iov_len, buf->len); | 571 | movelen = min_t(unsigned int, buf->head[0].iov_len, buf->len); |
572 | movelen -= offset + GSS_KRB5_TOK_HDR_LEN + headskip; | 572 | movelen -= offset + GSS_KRB5_TOK_HDR_LEN + headskip; |
573 | BUG_ON(offset + GSS_KRB5_TOK_HDR_LEN + headskip + movelen > | 573 | if (offset + GSS_KRB5_TOK_HDR_LEN + headskip + movelen > |
574 | buf->head[0].iov_len); | 574 | buf->head[0].iov_len) |
575 | return GSS_S_FAILURE; | ||
575 | memmove(ptr, ptr + GSS_KRB5_TOK_HDR_LEN + headskip, movelen); | 576 | memmove(ptr, ptr + GSS_KRB5_TOK_HDR_LEN + headskip, movelen); |
576 | buf->head[0].iov_len -= GSS_KRB5_TOK_HDR_LEN + headskip; | 577 | buf->head[0].iov_len -= GSS_KRB5_TOK_HDR_LEN + headskip; |
577 | buf->len -= GSS_KRB5_TOK_HDR_LEN + headskip; | 578 | buf->len -= GSS_KRB5_TOK_HDR_LEN + headskip; |
578 | 579 | ||
579 | /* Trim off the trailing "extra count" and checksum blob */ | 580 | /* Trim off the trailing "extra count" and checksum blob */ |
580 | xdr_buf_trim(buf, ec + GSS_KRB5_TOK_HDR_LEN + tailskip); | 581 | buf->len -= ec + GSS_KRB5_TOK_HDR_LEN + tailskip; |
582 | |||
581 | return GSS_S_COMPLETE; | 583 | return GSS_S_COMPLETE; |
582 | } | 584 | } |
583 | 585 | ||
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c index 379318dff534..82060099a429 100644 --- a/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/net/sunrpc/auth_gss/gss_mech_switch.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: BSD-3-Clause | ||
1 | /* | 2 | /* |
2 | * linux/net/sunrpc/gss_mech_switch.c | 3 | * linux/net/sunrpc/gss_mech_switch.c |
3 | * | 4 | * |
@@ -5,32 +6,6 @@ | |||
5 | * All rights reserved. | 6 | * All rights reserved. |
6 | * | 7 | * |
7 | * J. Bruce Fields <bfields@umich.edu> | 8 | * J. Bruce Fields <bfields@umich.edu> |
8 | * | ||
9 | * Redistribution and use in source and binary forms, with or without | ||
10 | * modification, are permitted provided that the following conditions | ||
11 | * are met: | ||
12 | * | ||
13 | * 1. Redistributions of source code must retain the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer. | ||
15 | * 2. Redistributions in binary form must reproduce the above copyright | ||
16 | * notice, this list of conditions and the following disclaimer in the | ||
17 | * documentation and/or other materials provided with the distribution. | ||
18 | * 3. Neither the name of the University nor the names of its | ||
19 | * contributors may be used to endorse or promote products derived | ||
20 | * from this software without specific prior written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
23 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
24 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
25 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
29 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
30 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
31 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | */ | 9 | */ |
35 | 10 | ||
36 | #include <linux/types.h> | 11 | #include <linux/types.h> |
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c index 73dcda060335..0349f455a862 100644 --- a/net/sunrpc/auth_gss/gss_rpc_upcall.c +++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c | |||
@@ -1,21 +1,8 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
1 | /* | 2 | /* |
2 | * linux/net/sunrpc/gss_rpc_upcall.c | 3 | * linux/net/sunrpc/gss_rpc_upcall.c |
3 | * | 4 | * |
4 | * Copyright (C) 2012 Simo Sorce <simo@redhat.com> | 5 | * Copyright (C) 2012 Simo Sorce <simo@redhat.com> |
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | 6 | */ |
20 | 7 | ||
21 | #include <linux/types.h> | 8 | #include <linux/types.h> |
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.h b/net/sunrpc/auth_gss/gss_rpc_upcall.h index 1e542aded90a..31e96344167e 100644 --- a/net/sunrpc/auth_gss/gss_rpc_upcall.h +++ b/net/sunrpc/auth_gss/gss_rpc_upcall.h | |||
@@ -1,21 +1,8 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0+ */ | ||
1 | /* | 2 | /* |
2 | * linux/net/sunrpc/gss_rpc_upcall.h | 3 | * linux/net/sunrpc/gss_rpc_upcall.h |
3 | * | 4 | * |
4 | * Copyright (C) 2012 Simo Sorce <simo@redhat.com> | 5 | * Copyright (C) 2012 Simo Sorce <simo@redhat.com> |
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | 6 | */ |
20 | 7 | ||
21 | #ifndef _GSS_RPC_UPCALL_H | 8 | #ifndef _GSS_RPC_UPCALL_H |
@@ -45,4 +32,5 @@ void gssp_free_upcall_data(struct gssp_upcall_data *data); | |||
45 | void init_gssp_clnt(struct sunrpc_net *); | 32 | void init_gssp_clnt(struct sunrpc_net *); |
46 | int set_gssp_clnt(struct net *); | 33 | int set_gssp_clnt(struct net *); |
47 | void clear_gssp_clnt(struct sunrpc_net *); | 34 | void clear_gssp_clnt(struct sunrpc_net *); |
35 | |||
48 | #endif /* _GSS_RPC_UPCALL_H */ | 36 | #endif /* _GSS_RPC_UPCALL_H */ |
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c index 006062ad5f58..2ff7b7083eba 100644 --- a/net/sunrpc/auth_gss/gss_rpc_xdr.c +++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c | |||
@@ -1,21 +1,8 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
1 | /* | 2 | /* |
2 | * GSS Proxy upcall module | 3 | * GSS Proxy upcall module |
3 | * | 4 | * |
4 | * Copyright (C) 2012 Simo Sorce <simo@redhat.com> | 5 | * Copyright (C) 2012 Simo Sorce <simo@redhat.com> |
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | 6 | */ |
20 | 7 | ||
21 | #include <linux/sunrpc/svcauth.h> | 8 | #include <linux/sunrpc/svcauth.h> |
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.h b/net/sunrpc/auth_gss/gss_rpc_xdr.h index 146c31032917..3f17411b7e65 100644 --- a/net/sunrpc/auth_gss/gss_rpc_xdr.h +++ b/net/sunrpc/auth_gss/gss_rpc_xdr.h | |||
@@ -1,21 +1,8 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0+ */ | ||
1 | /* | 2 | /* |
2 | * GSS Proxy upcall module | 3 | * GSS Proxy upcall module |
3 | * | 4 | * |
4 | * Copyright (C) 2012 Simo Sorce <simo@redhat.com> | 5 | * Copyright (C) 2012 Simo Sorce <simo@redhat.com> |
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | 6 | */ |
20 | 7 | ||
21 | #ifndef _LINUX_GSS_RPC_XDR_H | 8 | #ifndef _LINUX_GSS_RPC_XDR_H |
@@ -262,6 +249,4 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, | |||
262 | #define GSSX_ARG_wrap_size_limit_sz 0 | 249 | #define GSSX_ARG_wrap_size_limit_sz 0 |
263 | #define GSSX_RES_wrap_size_limit_sz 0 | 250 | #define GSSX_RES_wrap_size_limit_sz 0 |
264 | 251 | ||
265 | |||
266 | |||
267 | #endif /* _LINUX_GSS_RPC_XDR_H */ | 252 | #endif /* _LINUX_GSS_RPC_XDR_H */ |
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 152790ed309c..0c5d7896d6dd 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Neil Brown <neilb@cse.unsw.edu.au> | 3 | * Neil Brown <neilb@cse.unsw.edu.au> |
3 | * J. Bruce Fields <bfields@umich.edu> | 4 | * J. Bruce Fields <bfields@umich.edu> |
@@ -896,7 +897,7 @@ unwrap_integ_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct g | |||
896 | if (svc_getnl(&buf->head[0]) != seq) | 897 | if (svc_getnl(&buf->head[0]) != seq) |
897 | goto out; | 898 | goto out; |
898 | /* trim off the mic and padding at the end before returning */ | 899 | /* trim off the mic and padding at the end before returning */ |
899 | xdr_buf_trim(buf, round_up_to_quad(mic.len) + 4); | 900 | buf->len -= 4 + round_up_to_quad(mic.len); |
900 | stat = 0; | 901 | stat = 0; |
901 | out: | 902 | out: |
902 | kfree(mic.data); | 903 | kfree(mic.data); |
diff --git a/net/sunrpc/auth_gss/trace.c b/net/sunrpc/auth_gss/trace.c new file mode 100644 index 000000000000..5576f1e66de9 --- /dev/null +++ b/net/sunrpc/auth_gss/trace.c | |||
@@ -0,0 +1,11 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Copyright (c) 2018, 2019 Oracle. All rights reserved. | ||
4 | */ | ||
5 | |||
6 | #include <linux/sunrpc/clnt.h> | ||
7 | #include <linux/sunrpc/sched.h> | ||
8 | #include <linux/sunrpc/gss_err.h> | ||
9 | |||
10 | #define CREATE_TRACE_POINTS | ||
11 | #include <trace/events/rpcgss.h> | ||
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c index d0ceac57c06e..41a633a4049e 100644 --- a/net/sunrpc/auth_null.c +++ b/net/sunrpc/auth_null.c | |||
@@ -59,15 +59,21 @@ nul_match(struct auth_cred *acred, struct rpc_cred *cred, int taskflags) | |||
59 | /* | 59 | /* |
60 | * Marshal credential. | 60 | * Marshal credential. |
61 | */ | 61 | */ |
62 | static __be32 * | 62 | static int |
63 | nul_marshal(struct rpc_task *task, __be32 *p) | 63 | nul_marshal(struct rpc_task *task, struct xdr_stream *xdr) |
64 | { | 64 | { |
65 | *p++ = htonl(RPC_AUTH_NULL); | 65 | __be32 *p; |
66 | *p++ = 0; | 66 | |
67 | *p++ = htonl(RPC_AUTH_NULL); | 67 | p = xdr_reserve_space(xdr, 4 * sizeof(*p)); |
68 | *p++ = 0; | 68 | if (!p) |
69 | 69 | return -EMSGSIZE; | |
70 | return p; | 70 | /* Credential */ |
71 | *p++ = rpc_auth_null; | ||
72 | *p++ = xdr_zero; | ||
73 | /* Verifier */ | ||
74 | *p++ = rpc_auth_null; | ||
75 | *p = xdr_zero; | ||
76 | return 0; | ||
71 | } | 77 | } |
72 | 78 | ||
73 | /* | 79 | /* |
@@ -80,25 +86,19 @@ nul_refresh(struct rpc_task *task) | |||
80 | return 0; | 86 | return 0; |
81 | } | 87 | } |
82 | 88 | ||
83 | static __be32 * | 89 | static int |
84 | nul_validate(struct rpc_task *task, __be32 *p) | 90 | nul_validate(struct rpc_task *task, struct xdr_stream *xdr) |
85 | { | 91 | { |
86 | rpc_authflavor_t flavor; | 92 | __be32 *p; |
87 | u32 size; | 93 | |
88 | 94 | p = xdr_inline_decode(xdr, 2 * sizeof(*p)); | |
89 | flavor = ntohl(*p++); | 95 | if (!p) |
90 | if (flavor != RPC_AUTH_NULL) { | 96 | return -EIO; |
91 | printk("RPC: bad verf flavor: %u\n", flavor); | 97 | if (*p++ != rpc_auth_null) |
92 | return ERR_PTR(-EIO); | 98 | return -EIO; |
93 | } | 99 | if (*p != xdr_zero) |
94 | 100 | return -EIO; | |
95 | size = ntohl(*p++); | 101 | return 0; |
96 | if (size != 0) { | ||
97 | printk("RPC: bad verf size: %u\n", size); | ||
98 | return ERR_PTR(-EIO); | ||
99 | } | ||
100 | |||
101 | return p; | ||
102 | } | 102 | } |
103 | 103 | ||
104 | const struct rpc_authops authnull_ops = { | 104 | const struct rpc_authops authnull_ops = { |
@@ -114,6 +114,8 @@ static | |||
114 | struct rpc_auth null_auth = { | 114 | struct rpc_auth null_auth = { |
115 | .au_cslack = NUL_CALLSLACK, | 115 | .au_cslack = NUL_CALLSLACK, |
116 | .au_rslack = NUL_REPLYSLACK, | 116 | .au_rslack = NUL_REPLYSLACK, |
117 | .au_verfsize = NUL_REPLYSLACK, | ||
118 | .au_ralign = NUL_REPLYSLACK, | ||
117 | .au_ops = &authnull_ops, | 119 | .au_ops = &authnull_ops, |
118 | .au_flavor = RPC_AUTH_NULL, | 120 | .au_flavor = RPC_AUTH_NULL, |
119 | .au_count = REFCOUNT_INIT(1), | 121 | .au_count = REFCOUNT_INIT(1), |
@@ -125,8 +127,10 @@ const struct rpc_credops null_credops = { | |||
125 | .crdestroy = nul_destroy_cred, | 127 | .crdestroy = nul_destroy_cred, |
126 | .crmatch = nul_match, | 128 | .crmatch = nul_match, |
127 | .crmarshal = nul_marshal, | 129 | .crmarshal = nul_marshal, |
130 | .crwrap_req = rpcauth_wrap_req_encode, | ||
128 | .crrefresh = nul_refresh, | 131 | .crrefresh = nul_refresh, |
129 | .crvalidate = nul_validate, | 132 | .crvalidate = nul_validate, |
133 | .crunwrap_resp = rpcauth_unwrap_resp_decode, | ||
130 | }; | 134 | }; |
131 | 135 | ||
132 | static | 136 | static |
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 770e338a9b11..d4018e5a24c5 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c | |||
@@ -28,8 +28,6 @@ static mempool_t *unix_pool; | |||
28 | static struct rpc_auth * | 28 | static struct rpc_auth * |
29 | unx_create(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt) | 29 | unx_create(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt) |
30 | { | 30 | { |
31 | dprintk("RPC: creating UNIX authenticator for client %p\n", | ||
32 | clnt); | ||
33 | refcount_inc(&unix_auth.au_count); | 31 | refcount_inc(&unix_auth.au_count); |
34 | return &unix_auth; | 32 | return &unix_auth; |
35 | } | 33 | } |
@@ -37,7 +35,6 @@ unx_create(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt) | |||
37 | static void | 35 | static void |
38 | unx_destroy(struct rpc_auth *auth) | 36 | unx_destroy(struct rpc_auth *auth) |
39 | { | 37 | { |
40 | dprintk("RPC: destroying UNIX authenticator %p\n", auth); | ||
41 | } | 38 | } |
42 | 39 | ||
43 | /* | 40 | /* |
@@ -48,10 +45,6 @@ unx_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
48 | { | 45 | { |
49 | struct rpc_cred *ret = mempool_alloc(unix_pool, GFP_NOFS); | 46 | struct rpc_cred *ret = mempool_alloc(unix_pool, GFP_NOFS); |
50 | 47 | ||
51 | dprintk("RPC: allocating UNIX cred for uid %d gid %d\n", | ||
52 | from_kuid(&init_user_ns, acred->cred->fsuid), | ||
53 | from_kgid(&init_user_ns, acred->cred->fsgid)); | ||
54 | |||
55 | rpcauth_init_cred(ret, acred, auth, &unix_credops); | 48 | rpcauth_init_cred(ret, acred, auth, &unix_credops); |
56 | ret->cr_flags = 1UL << RPCAUTH_CRED_UPTODATE; | 49 | ret->cr_flags = 1UL << RPCAUTH_CRED_UPTODATE; |
57 | return ret; | 50 | return ret; |
@@ -61,7 +54,7 @@ static void | |||
61 | unx_free_cred_callback(struct rcu_head *head) | 54 | unx_free_cred_callback(struct rcu_head *head) |
62 | { | 55 | { |
63 | struct rpc_cred *rpc_cred = container_of(head, struct rpc_cred, cr_rcu); | 56 | struct rpc_cred *rpc_cred = container_of(head, struct rpc_cred, cr_rcu); |
64 | dprintk("RPC: unx_free_cred %p\n", rpc_cred); | 57 | |
65 | put_cred(rpc_cred->cr_cred); | 58 | put_cred(rpc_cred->cr_cred); |
66 | mempool_free(rpc_cred, unix_pool); | 59 | mempool_free(rpc_cred, unix_pool); |
67 | } | 60 | } |
@@ -106,37 +99,55 @@ unx_match(struct auth_cred *acred, struct rpc_cred *cred, int flags) | |||
106 | * Marshal credentials. | 99 | * Marshal credentials. |
107 | * Maybe we should keep a cached credential for performance reasons. | 100 | * Maybe we should keep a cached credential for performance reasons. |
108 | */ | 101 | */ |
109 | static __be32 * | 102 | static int |
110 | unx_marshal(struct rpc_task *task, __be32 *p) | 103 | unx_marshal(struct rpc_task *task, struct xdr_stream *xdr) |
111 | { | 104 | { |
112 | struct rpc_clnt *clnt = task->tk_client; | 105 | struct rpc_clnt *clnt = task->tk_client; |
113 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; | 106 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
114 | __be32 *base, *hold; | 107 | __be32 *p, *cred_len, *gidarr_len; |
115 | int i; | 108 | int i; |
116 | struct group_info *gi = cred->cr_cred->group_info; | 109 | struct group_info *gi = cred->cr_cred->group_info; |
117 | 110 | ||
118 | *p++ = htonl(RPC_AUTH_UNIX); | 111 | /* Credential */ |
119 | base = p++; | 112 | |
120 | *p++ = htonl(jiffies/HZ); | 113 | p = xdr_reserve_space(xdr, 3 * sizeof(*p)); |
121 | 114 | if (!p) | |
122 | /* | 115 | goto marshal_failed; |
123 | * Copy the UTS nodename captured when the client was created. | 116 | *p++ = rpc_auth_unix; |
124 | */ | 117 | cred_len = p++; |
125 | p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen); | 118 | *p++ = xdr_zero; /* stamp */ |
126 | 119 | if (xdr_stream_encode_opaque(xdr, clnt->cl_nodename, | |
127 | *p++ = htonl((u32) from_kuid(&init_user_ns, cred->cr_cred->fsuid)); | 120 | clnt->cl_nodelen) < 0) |
128 | *p++ = htonl((u32) from_kgid(&init_user_ns, cred->cr_cred->fsgid)); | 121 | goto marshal_failed; |
129 | hold = p++; | 122 | p = xdr_reserve_space(xdr, 3 * sizeof(*p)); |
123 | if (!p) | ||
124 | goto marshal_failed; | ||
125 | *p++ = cpu_to_be32(from_kuid(&init_user_ns, cred->cr_cred->fsuid)); | ||
126 | *p++ = cpu_to_be32(from_kgid(&init_user_ns, cred->cr_cred->fsgid)); | ||
127 | |||
128 | gidarr_len = p++; | ||
130 | if (gi) | 129 | if (gi) |
131 | for (i = 0; i < UNX_NGROUPS && i < gi->ngroups; i++) | 130 | for (i = 0; i < UNX_NGROUPS && i < gi->ngroups; i++) |
132 | *p++ = htonl((u32) from_kgid(&init_user_ns, gi->gid[i])); | 131 | *p++ = cpu_to_be32(from_kgid(&init_user_ns, |
133 | *hold = htonl(p - hold - 1); /* gid array length */ | 132 | gi->gid[i])); |
134 | *base = htonl((p - base - 1) << 2); /* cred length */ | 133 | *gidarr_len = cpu_to_be32(p - gidarr_len - 1); |
134 | *cred_len = cpu_to_be32((p - cred_len - 1) << 2); | ||
135 | p = xdr_reserve_space(xdr, (p - gidarr_len - 1) << 2); | ||
136 | if (!p) | ||
137 | goto marshal_failed; | ||
138 | |||
139 | /* Verifier */ | ||
140 | |||
141 | p = xdr_reserve_space(xdr, 2 * sizeof(*p)); | ||
142 | if (!p) | ||
143 | goto marshal_failed; | ||
144 | *p++ = rpc_auth_null; | ||
145 | *p = xdr_zero; | ||
135 | 146 | ||
136 | *p++ = htonl(RPC_AUTH_NULL); | 147 | return 0; |
137 | *p++ = htonl(0); | ||
138 | 148 | ||
139 | return p; | 149 | marshal_failed: |
150 | return -EMSGSIZE; | ||
140 | } | 151 | } |
141 | 152 | ||
142 | /* | 153 | /* |
@@ -149,29 +160,35 @@ unx_refresh(struct rpc_task *task) | |||
149 | return 0; | 160 | return 0; |
150 | } | 161 | } |
151 | 162 | ||
152 | static __be32 * | 163 | static int |
153 | unx_validate(struct rpc_task *task, __be32 *p) | 164 | unx_validate(struct rpc_task *task, struct xdr_stream *xdr) |
154 | { | 165 | { |
155 | rpc_authflavor_t flavor; | 166 | struct rpc_auth *auth = task->tk_rqstp->rq_cred->cr_auth; |
156 | u32 size; | 167 | __be32 *p; |
157 | 168 | u32 size; | |
158 | flavor = ntohl(*p++); | 169 | |
159 | if (flavor != RPC_AUTH_NULL && | 170 | p = xdr_inline_decode(xdr, 2 * sizeof(*p)); |
160 | flavor != RPC_AUTH_UNIX && | 171 | if (!p) |
161 | flavor != RPC_AUTH_SHORT) { | 172 | return -EIO; |
162 | printk("RPC: bad verf flavor: %u\n", flavor); | 173 | switch (*p++) { |
163 | return ERR_PTR(-EIO); | 174 | case rpc_auth_null: |
164 | } | 175 | case rpc_auth_unix: |
165 | 176 | case rpc_auth_short: | |
166 | size = ntohl(*p++); | 177 | break; |
167 | if (size > RPC_MAX_AUTH_SIZE) { | 178 | default: |
168 | printk("RPC: giant verf size: %u\n", size); | 179 | return -EIO; |
169 | return ERR_PTR(-EIO); | ||
170 | } | 180 | } |
171 | task->tk_rqstp->rq_cred->cr_auth->au_rslack = (size >> 2) + 2; | 181 | size = be32_to_cpup(p); |
172 | p += (size >> 2); | 182 | if (size > RPC_MAX_AUTH_SIZE) |
173 | 183 | return -EIO; | |
174 | return p; | 184 | p = xdr_inline_decode(xdr, size); |
185 | if (!p) | ||
186 | return -EIO; | ||
187 | |||
188 | auth->au_verfsize = XDR_QUADLEN(size) + 2; | ||
189 | auth->au_rslack = XDR_QUADLEN(size) + 2; | ||
190 | auth->au_ralign = XDR_QUADLEN(size) + 2; | ||
191 | return 0; | ||
175 | } | 192 | } |
176 | 193 | ||
177 | int __init rpc_init_authunix(void) | 194 | int __init rpc_init_authunix(void) |
@@ -198,6 +215,7 @@ static | |||
198 | struct rpc_auth unix_auth = { | 215 | struct rpc_auth unix_auth = { |
199 | .au_cslack = UNX_CALLSLACK, | 216 | .au_cslack = UNX_CALLSLACK, |
200 | .au_rslack = NUL_REPLYSLACK, | 217 | .au_rslack = NUL_REPLYSLACK, |
218 | .au_verfsize = NUL_REPLYSLACK, | ||
201 | .au_ops = &authunix_ops, | 219 | .au_ops = &authunix_ops, |
202 | .au_flavor = RPC_AUTH_UNIX, | 220 | .au_flavor = RPC_AUTH_UNIX, |
203 | .au_count = REFCOUNT_INIT(1), | 221 | .au_count = REFCOUNT_INIT(1), |
@@ -209,6 +227,8 @@ const struct rpc_credops unix_credops = { | |||
209 | .crdestroy = unx_destroy_cred, | 227 | .crdestroy = unx_destroy_cred, |
210 | .crmatch = unx_match, | 228 | .crmatch = unx_match, |
211 | .crmarshal = unx_marshal, | 229 | .crmarshal = unx_marshal, |
230 | .crwrap_req = rpcauth_wrap_req_encode, | ||
212 | .crrefresh = unx_refresh, | 231 | .crrefresh = unx_refresh, |
213 | .crvalidate = unx_validate, | 232 | .crvalidate = unx_validate, |
233 | .crunwrap_resp = rpcauth_unwrap_resp_decode, | ||
214 | }; | 234 | }; |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index d7ec6132c046..241e8423fd0c 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -77,8 +77,10 @@ static void call_timeout(struct rpc_task *task); | |||
77 | static void call_connect(struct rpc_task *task); | 77 | static void call_connect(struct rpc_task *task); |
78 | static void call_connect_status(struct rpc_task *task); | 78 | static void call_connect_status(struct rpc_task *task); |
79 | 79 | ||
80 | static __be32 *rpc_encode_header(struct rpc_task *task); | 80 | static int rpc_encode_header(struct rpc_task *task, |
81 | static __be32 *rpc_verify_header(struct rpc_task *task); | 81 | struct xdr_stream *xdr); |
82 | static int rpc_decode_header(struct rpc_task *task, | ||
83 | struct xdr_stream *xdr); | ||
82 | static int rpc_ping(struct rpc_clnt *clnt); | 84 | static int rpc_ping(struct rpc_clnt *clnt); |
83 | 85 | ||
84 | static void rpc_register_client(struct rpc_clnt *clnt) | 86 | static void rpc_register_client(struct rpc_clnt *clnt) |
@@ -1162,6 +1164,29 @@ struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req) | |||
1162 | } | 1164 | } |
1163 | #endif /* CONFIG_SUNRPC_BACKCHANNEL */ | 1165 | #endif /* CONFIG_SUNRPC_BACKCHANNEL */ |
1164 | 1166 | ||
1167 | /** | ||
1168 | * rpc_prepare_reply_pages - Prepare to receive a reply data payload into pages | ||
1169 | * @req: RPC request to prepare | ||
1170 | * @pages: vector of struct page pointers | ||
1171 | * @base: offset in first page where receive should start, in bytes | ||
1172 | * @len: expected size of the upper layer data payload, in bytes | ||
1173 | * @hdrsize: expected size of upper layer reply header, in XDR words | ||
1174 | * | ||
1175 | */ | ||
1176 | void rpc_prepare_reply_pages(struct rpc_rqst *req, struct page **pages, | ||
1177 | unsigned int base, unsigned int len, | ||
1178 | unsigned int hdrsize) | ||
1179 | { | ||
1180 | /* Subtract one to force an extra word of buffer space for the | ||
1181 | * payload's XDR pad to fall into the rcv_buf's tail iovec. | ||
1182 | */ | ||
1183 | hdrsize += RPC_REPHDRSIZE + req->rq_cred->cr_auth->au_ralign - 1; | ||
1184 | |||
1185 | xdr_inline_pages(&req->rq_rcv_buf, hdrsize << 2, pages, base, len); | ||
1186 | trace_rpc_reply_pages(req); | ||
1187 | } | ||
1188 | EXPORT_SYMBOL_GPL(rpc_prepare_reply_pages); | ||
1189 | |||
1165 | void | 1190 | void |
1166 | rpc_call_start(struct rpc_task *task) | 1191 | rpc_call_start(struct rpc_task *task) |
1167 | { | 1192 | { |
@@ -1665,7 +1690,7 @@ call_refreshresult(struct rpc_task *task) | |||
1665 | static void | 1690 | static void |
1666 | call_allocate(struct rpc_task *task) | 1691 | call_allocate(struct rpc_task *task) |
1667 | { | 1692 | { |
1668 | unsigned int slack = task->tk_rqstp->rq_cred->cr_auth->au_cslack; | 1693 | const struct rpc_auth *auth = task->tk_rqstp->rq_cred->cr_auth; |
1669 | struct rpc_rqst *req = task->tk_rqstp; | 1694 | struct rpc_rqst *req = task->tk_rqstp; |
1670 | struct rpc_xprt *xprt = req->rq_xprt; | 1695 | struct rpc_xprt *xprt = req->rq_xprt; |
1671 | const struct rpc_procinfo *proc = task->tk_msg.rpc_proc; | 1696 | const struct rpc_procinfo *proc = task->tk_msg.rpc_proc; |
@@ -1690,9 +1715,10 @@ call_allocate(struct rpc_task *task) | |||
1690 | * and reply headers, and convert both values | 1715 | * and reply headers, and convert both values |
1691 | * to byte sizes. | 1716 | * to byte sizes. |
1692 | */ | 1717 | */ |
1693 | req->rq_callsize = RPC_CALLHDRSIZE + (slack << 1) + proc->p_arglen; | 1718 | req->rq_callsize = RPC_CALLHDRSIZE + (auth->au_cslack << 1) + |
1719 | proc->p_arglen; | ||
1694 | req->rq_callsize <<= 2; | 1720 | req->rq_callsize <<= 2; |
1695 | req->rq_rcvsize = RPC_REPHDRSIZE + slack + proc->p_replen; | 1721 | req->rq_rcvsize = RPC_REPHDRSIZE + auth->au_rslack + proc->p_replen; |
1696 | req->rq_rcvsize <<= 2; | 1722 | req->rq_rcvsize <<= 2; |
1697 | 1723 | ||
1698 | status = xprt->ops->buf_alloc(task); | 1724 | status = xprt->ops->buf_alloc(task); |
@@ -1728,10 +1754,7 @@ static void | |||
1728 | rpc_xdr_encode(struct rpc_task *task) | 1754 | rpc_xdr_encode(struct rpc_task *task) |
1729 | { | 1755 | { |
1730 | struct rpc_rqst *req = task->tk_rqstp; | 1756 | struct rpc_rqst *req = task->tk_rqstp; |
1731 | kxdreproc_t encode; | 1757 | struct xdr_stream xdr; |
1732 | __be32 *p; | ||
1733 | |||
1734 | dprint_status(task); | ||
1735 | 1758 | ||
1736 | xdr_buf_init(&req->rq_snd_buf, | 1759 | xdr_buf_init(&req->rq_snd_buf, |
1737 | req->rq_buffer, | 1760 | req->rq_buffer, |
@@ -1740,18 +1763,13 @@ rpc_xdr_encode(struct rpc_task *task) | |||
1740 | req->rq_rbuffer, | 1763 | req->rq_rbuffer, |
1741 | req->rq_rcvsize); | 1764 | req->rq_rcvsize); |
1742 | 1765 | ||
1743 | p = rpc_encode_header(task); | 1766 | req->rq_snd_buf.head[0].iov_len = 0; |
1744 | if (p == NULL) | 1767 | xdr_init_encode(&xdr, &req->rq_snd_buf, |
1745 | return; | 1768 | req->rq_snd_buf.head[0].iov_base, req); |
1746 | 1769 | if (rpc_encode_header(task, &xdr)) | |
1747 | encode = task->tk_msg.rpc_proc->p_encode; | ||
1748 | if (encode == NULL) | ||
1749 | return; | 1770 | return; |
1750 | 1771 | ||
1751 | task->tk_status = rpcauth_wrap_req(task, encode, req, p, | 1772 | task->tk_status = rpcauth_wrap_req(task, &xdr); |
1752 | task->tk_msg.rpc_argp); | ||
1753 | if (task->tk_status == 0) | ||
1754 | xprt_request_prepare(req); | ||
1755 | } | 1773 | } |
1756 | 1774 | ||
1757 | /* | 1775 | /* |
@@ -1762,6 +1780,7 @@ call_encode(struct rpc_task *task) | |||
1762 | { | 1780 | { |
1763 | if (!rpc_task_need_encode(task)) | 1781 | if (!rpc_task_need_encode(task)) |
1764 | goto out; | 1782 | goto out; |
1783 | dprint_status(task); | ||
1765 | /* Encode here so that rpcsec_gss can use correct sequence number. */ | 1784 | /* Encode here so that rpcsec_gss can use correct sequence number. */ |
1766 | rpc_xdr_encode(task); | 1785 | rpc_xdr_encode(task); |
1767 | /* Did the encode result in an error condition? */ | 1786 | /* Did the encode result in an error condition? */ |
@@ -1779,6 +1798,8 @@ call_encode(struct rpc_task *task) | |||
1779 | rpc_exit(task, task->tk_status); | 1798 | rpc_exit(task, task->tk_status); |
1780 | } | 1799 | } |
1781 | return; | 1800 | return; |
1801 | } else { | ||
1802 | xprt_request_prepare(task->tk_rqstp); | ||
1782 | } | 1803 | } |
1783 | 1804 | ||
1784 | /* Add task to reply queue before transmission to avoid races */ | 1805 | /* Add task to reply queue before transmission to avoid races */ |
@@ -2255,12 +2276,11 @@ call_decode(struct rpc_task *task) | |||
2255 | { | 2276 | { |
2256 | struct rpc_clnt *clnt = task->tk_client; | 2277 | struct rpc_clnt *clnt = task->tk_client; |
2257 | struct rpc_rqst *req = task->tk_rqstp; | 2278 | struct rpc_rqst *req = task->tk_rqstp; |
2258 | kxdrdproc_t decode = task->tk_msg.rpc_proc->p_decode; | 2279 | struct xdr_stream xdr; |
2259 | __be32 *p; | ||
2260 | 2280 | ||
2261 | dprint_status(task); | 2281 | dprint_status(task); |
2262 | 2282 | ||
2263 | if (!decode) { | 2283 | if (!task->tk_msg.rpc_proc->p_decode) { |
2264 | task->tk_action = rpc_exit_task; | 2284 | task->tk_action = rpc_exit_task; |
2265 | return; | 2285 | return; |
2266 | } | 2286 | } |
@@ -2296,212 +2316,190 @@ call_decode(struct rpc_task *task) | |||
2296 | goto out_retry; | 2316 | goto out_retry; |
2297 | } | 2317 | } |
2298 | 2318 | ||
2299 | p = rpc_verify_header(task); | 2319 | xdr_init_decode(&xdr, &req->rq_rcv_buf, |
2300 | if (IS_ERR(p)) { | 2320 | req->rq_rcv_buf.head[0].iov_base, req); |
2301 | if (p == ERR_PTR(-EAGAIN)) | 2321 | switch (rpc_decode_header(task, &xdr)) { |
2302 | goto out_retry; | 2322 | case 0: |
2323 | task->tk_action = rpc_exit_task; | ||
2324 | task->tk_status = rpcauth_unwrap_resp(task, &xdr); | ||
2325 | dprintk("RPC: %5u %s result %d\n", | ||
2326 | task->tk_pid, __func__, task->tk_status); | ||
2303 | return; | 2327 | return; |
2304 | } | 2328 | case -EAGAIN: |
2305 | task->tk_action = rpc_exit_task; | ||
2306 | |||
2307 | task->tk_status = rpcauth_unwrap_resp(task, decode, req, p, | ||
2308 | task->tk_msg.rpc_resp); | ||
2309 | |||
2310 | dprintk("RPC: %5u call_decode result %d\n", task->tk_pid, | ||
2311 | task->tk_status); | ||
2312 | return; | ||
2313 | out_retry: | 2329 | out_retry: |
2314 | task->tk_status = 0; | 2330 | task->tk_status = 0; |
2315 | /* Note: rpc_verify_header() may have freed the RPC slot */ | 2331 | /* Note: rpc_decode_header() may have freed the RPC slot */ |
2316 | if (task->tk_rqstp == req) { | 2332 | if (task->tk_rqstp == req) { |
2317 | xdr_free_bvec(&req->rq_rcv_buf); | 2333 | xdr_free_bvec(&req->rq_rcv_buf); |
2318 | req->rq_reply_bytes_recvd = req->rq_rcv_buf.len = 0; | 2334 | req->rq_reply_bytes_recvd = 0; |
2319 | if (task->tk_client->cl_discrtry) | 2335 | req->rq_rcv_buf.len = 0; |
2320 | xprt_conditional_disconnect(req->rq_xprt, | 2336 | if (task->tk_client->cl_discrtry) |
2321 | req->rq_connect_cookie); | 2337 | xprt_conditional_disconnect(req->rq_xprt, |
2338 | req->rq_connect_cookie); | ||
2339 | } | ||
2322 | } | 2340 | } |
2323 | } | 2341 | } |
2324 | 2342 | ||
2325 | static __be32 * | 2343 | static int |
2326 | rpc_encode_header(struct rpc_task *task) | 2344 | rpc_encode_header(struct rpc_task *task, struct xdr_stream *xdr) |
2327 | { | 2345 | { |
2328 | struct rpc_clnt *clnt = task->tk_client; | 2346 | struct rpc_clnt *clnt = task->tk_client; |
2329 | struct rpc_rqst *req = task->tk_rqstp; | 2347 | struct rpc_rqst *req = task->tk_rqstp; |
2330 | __be32 *p = req->rq_svec[0].iov_base; | 2348 | __be32 *p; |
2331 | 2349 | int error; | |
2332 | /* FIXME: check buffer size? */ | 2350 | |
2333 | 2351 | error = -EMSGSIZE; | |
2334 | p = xprt_skip_transport_header(req->rq_xprt, p); | 2352 | p = xdr_reserve_space(xdr, RPC_CALLHDRSIZE << 2); |
2335 | *p++ = req->rq_xid; /* XID */ | 2353 | if (!p) |
2336 | *p++ = htonl(RPC_CALL); /* CALL */ | 2354 | goto out_fail; |
2337 | *p++ = htonl(RPC_VERSION); /* RPC version */ | 2355 | *p++ = req->rq_xid; |
2338 | *p++ = htonl(clnt->cl_prog); /* program number */ | 2356 | *p++ = rpc_call; |
2339 | *p++ = htonl(clnt->cl_vers); /* program version */ | 2357 | *p++ = cpu_to_be32(RPC_VERSION); |
2340 | *p++ = htonl(task->tk_msg.rpc_proc->p_proc); /* procedure */ | 2358 | *p++ = cpu_to_be32(clnt->cl_prog); |
2341 | p = rpcauth_marshcred(task, p); | 2359 | *p++ = cpu_to_be32(clnt->cl_vers); |
2342 | if (p) | 2360 | *p = cpu_to_be32(task->tk_msg.rpc_proc->p_proc); |
2343 | req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p); | 2361 | |
2344 | return p; | 2362 | error = rpcauth_marshcred(task, xdr); |
2363 | if (error < 0) | ||
2364 | goto out_fail; | ||
2365 | return 0; | ||
2366 | out_fail: | ||
2367 | trace_rpc_bad_callhdr(task); | ||
2368 | rpc_exit(task, error); | ||
2369 | return error; | ||
2345 | } | 2370 | } |
2346 | 2371 | ||
2347 | static __be32 * | 2372 | static noinline int |
2348 | rpc_verify_header(struct rpc_task *task) | 2373 | rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr) |
2349 | { | 2374 | { |
2350 | struct rpc_clnt *clnt = task->tk_client; | 2375 | struct rpc_clnt *clnt = task->tk_client; |
2351 | struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0]; | ||
2352 | int len = task->tk_rqstp->rq_rcv_buf.len >> 2; | ||
2353 | __be32 *p = iov->iov_base; | ||
2354 | u32 n; | ||
2355 | int error = -EACCES; | 2376 | int error = -EACCES; |
2377 | __be32 *p; | ||
2356 | 2378 | ||
2357 | if ((task->tk_rqstp->rq_rcv_buf.len & 3) != 0) { | 2379 | /* RFC-1014 says that the representation of XDR data must be a |
2358 | /* RFC-1014 says that the representation of XDR data must be a | 2380 | * multiple of four bytes |
2359 | * multiple of four bytes | 2381 | * - if it isn't pointer subtraction in the NFS client may give |
2360 | * - if it isn't pointer subtraction in the NFS client may give | 2382 | * undefined results |
2361 | * undefined results | 2383 | */ |
2362 | */ | 2384 | if (task->tk_rqstp->rq_rcv_buf.len & 3) |
2363 | dprintk("RPC: %5u %s: XDR representation not a multiple of" | 2385 | goto out_badlen; |
2364 | " 4 bytes: 0x%x\n", task->tk_pid, __func__, | 2386 | |
2365 | task->tk_rqstp->rq_rcv_buf.len); | 2387 | p = xdr_inline_decode(xdr, 3 * sizeof(*p)); |
2366 | error = -EIO; | 2388 | if (!p) |
2367 | goto out_err; | 2389 | goto out_unparsable; |
2368 | } | 2390 | p++; /* skip XID */ |
2369 | if ((len -= 3) < 0) | 2391 | if (*p++ != rpc_reply) |
2370 | goto out_overflow; | 2392 | goto out_unparsable; |
2371 | 2393 | if (*p++ != rpc_msg_accepted) | |
2372 | p += 1; /* skip XID */ | 2394 | goto out_msg_denied; |
2373 | if ((n = ntohl(*p++)) != RPC_REPLY) { | 2395 | |
2374 | dprintk("RPC: %5u %s: not an RPC reply: %x\n", | 2396 | error = rpcauth_checkverf(task, xdr); |
2375 | task->tk_pid, __func__, n); | 2397 | if (error) |
2376 | error = -EIO; | 2398 | goto out_verifier; |
2377 | goto out_garbage; | 2399 | |
2378 | } | 2400 | p = xdr_inline_decode(xdr, sizeof(*p)); |
2379 | 2401 | if (!p) | |
2380 | if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { | 2402 | goto out_unparsable; |
2381 | if (--len < 0) | 2403 | switch (*p) { |
2382 | goto out_overflow; | 2404 | case rpc_success: |
2383 | switch ((n = ntohl(*p++))) { | 2405 | return 0; |
2384 | case RPC_AUTH_ERROR: | 2406 | case rpc_prog_unavail: |
2385 | break; | 2407 | trace_rpc__prog_unavail(task); |
2386 | case RPC_MISMATCH: | ||
2387 | dprintk("RPC: %5u %s: RPC call version mismatch!\n", | ||
2388 | task->tk_pid, __func__); | ||
2389 | error = -EPROTONOSUPPORT; | ||
2390 | goto out_err; | ||
2391 | default: | ||
2392 | dprintk("RPC: %5u %s: RPC call rejected, " | ||
2393 | "unknown error: %x\n", | ||
2394 | task->tk_pid, __func__, n); | ||
2395 | error = -EIO; | ||
2396 | goto out_err; | ||
2397 | } | ||
2398 | if (--len < 0) | ||
2399 | goto out_overflow; | ||
2400 | switch ((n = ntohl(*p++))) { | ||
2401 | case RPC_AUTH_REJECTEDCRED: | ||
2402 | case RPC_AUTH_REJECTEDVERF: | ||
2403 | case RPCSEC_GSS_CREDPROBLEM: | ||
2404 | case RPCSEC_GSS_CTXPROBLEM: | ||
2405 | if (!task->tk_cred_retry) | ||
2406 | break; | ||
2407 | task->tk_cred_retry--; | ||
2408 | dprintk("RPC: %5u %s: retry stale creds\n", | ||
2409 | task->tk_pid, __func__); | ||
2410 | rpcauth_invalcred(task); | ||
2411 | /* Ensure we obtain a new XID! */ | ||
2412 | xprt_release(task); | ||
2413 | task->tk_action = call_reserve; | ||
2414 | goto out_retry; | ||
2415 | case RPC_AUTH_BADCRED: | ||
2416 | case RPC_AUTH_BADVERF: | ||
2417 | /* possibly garbled cred/verf? */ | ||
2418 | if (!task->tk_garb_retry) | ||
2419 | break; | ||
2420 | task->tk_garb_retry--; | ||
2421 | dprintk("RPC: %5u %s: retry garbled creds\n", | ||
2422 | task->tk_pid, __func__); | ||
2423 | task->tk_action = call_encode; | ||
2424 | goto out_retry; | ||
2425 | case RPC_AUTH_TOOWEAK: | ||
2426 | printk(KERN_NOTICE "RPC: server %s requires stronger " | ||
2427 | "authentication.\n", | ||
2428 | task->tk_xprt->servername); | ||
2429 | break; | ||
2430 | default: | ||
2431 | dprintk("RPC: %5u %s: unknown auth error: %x\n", | ||
2432 | task->tk_pid, __func__, n); | ||
2433 | error = -EIO; | ||
2434 | } | ||
2435 | dprintk("RPC: %5u %s: call rejected %d\n", | ||
2436 | task->tk_pid, __func__, n); | ||
2437 | goto out_err; | ||
2438 | } | ||
2439 | p = rpcauth_checkverf(task, p); | ||
2440 | if (IS_ERR(p)) { | ||
2441 | error = PTR_ERR(p); | ||
2442 | dprintk("RPC: %5u %s: auth check failed with %d\n", | ||
2443 | task->tk_pid, __func__, error); | ||
2444 | goto out_garbage; /* bad verifier, retry */ | ||
2445 | } | ||
2446 | len = p - (__be32 *)iov->iov_base - 1; | ||
2447 | if (len < 0) | ||
2448 | goto out_overflow; | ||
2449 | switch ((n = ntohl(*p++))) { | ||
2450 | case RPC_SUCCESS: | ||
2451 | return p; | ||
2452 | case RPC_PROG_UNAVAIL: | ||
2453 | dprintk("RPC: %5u %s: program %u is unsupported " | ||
2454 | "by server %s\n", task->tk_pid, __func__, | ||
2455 | (unsigned int)clnt->cl_prog, | ||
2456 | task->tk_xprt->servername); | ||
2457 | error = -EPFNOSUPPORT; | 2408 | error = -EPFNOSUPPORT; |
2458 | goto out_err; | 2409 | goto out_err; |
2459 | case RPC_PROG_MISMATCH: | 2410 | case rpc_prog_mismatch: |
2460 | dprintk("RPC: %5u %s: program %u, version %u unsupported " | 2411 | trace_rpc__prog_mismatch(task); |
2461 | "by server %s\n", task->tk_pid, __func__, | ||
2462 | (unsigned int)clnt->cl_prog, | ||
2463 | (unsigned int)clnt->cl_vers, | ||
2464 | task->tk_xprt->servername); | ||
2465 | error = -EPROTONOSUPPORT; | 2412 | error = -EPROTONOSUPPORT; |
2466 | goto out_err; | 2413 | goto out_err; |
2467 | case RPC_PROC_UNAVAIL: | 2414 | case rpc_proc_unavail: |
2468 | dprintk("RPC: %5u %s: proc %s unsupported by program %u, " | 2415 | trace_rpc__proc_unavail(task); |
2469 | "version %u on server %s\n", | ||
2470 | task->tk_pid, __func__, | ||
2471 | rpc_proc_name(task), | ||
2472 | clnt->cl_prog, clnt->cl_vers, | ||
2473 | task->tk_xprt->servername); | ||
2474 | error = -EOPNOTSUPP; | 2416 | error = -EOPNOTSUPP; |
2475 | goto out_err; | 2417 | goto out_err; |
2476 | case RPC_GARBAGE_ARGS: | 2418 | case rpc_garbage_args: |
2477 | dprintk("RPC: %5u %s: server saw garbage\n", | 2419 | trace_rpc__garbage_args(task); |
2478 | task->tk_pid, __func__); | 2420 | break; |
2479 | break; /* retry */ | ||
2480 | default: | 2421 | default: |
2481 | dprintk("RPC: %5u %s: server accept status: %x\n", | 2422 | trace_rpc__unparsable(task); |
2482 | task->tk_pid, __func__, n); | ||
2483 | /* Also retry */ | ||
2484 | } | 2423 | } |
2485 | 2424 | ||
2486 | out_garbage: | 2425 | out_garbage: |
2487 | clnt->cl_stats->rpcgarbage++; | 2426 | clnt->cl_stats->rpcgarbage++; |
2488 | if (task->tk_garb_retry) { | 2427 | if (task->tk_garb_retry) { |
2489 | task->tk_garb_retry--; | 2428 | task->tk_garb_retry--; |
2490 | dprintk("RPC: %5u %s: retrying\n", | ||
2491 | task->tk_pid, __func__); | ||
2492 | task->tk_action = call_encode; | 2429 | task->tk_action = call_encode; |
2493 | out_retry: | 2430 | return -EAGAIN; |
2494 | return ERR_PTR(-EAGAIN); | ||
2495 | } | 2431 | } |
2496 | out_err: | 2432 | out_err: |
2497 | rpc_exit(task, error); | 2433 | rpc_exit(task, error); |
2498 | dprintk("RPC: %5u %s: call failed with error %d\n", task->tk_pid, | 2434 | return error; |
2499 | __func__, error); | 2435 | |
2500 | return ERR_PTR(error); | 2436 | out_badlen: |
2501 | out_overflow: | 2437 | trace_rpc__unparsable(task); |
2502 | dprintk("RPC: %5u %s: server reply was truncated.\n", task->tk_pid, | 2438 | error = -EIO; |
2503 | __func__); | 2439 | goto out_err; |
2440 | |||
2441 | out_unparsable: | ||
2442 | trace_rpc__unparsable(task); | ||
2443 | error = -EIO; | ||
2444 | goto out_garbage; | ||
2445 | |||
2446 | out_verifier: | ||
2447 | trace_rpc_bad_verifier(task); | ||
2504 | goto out_garbage; | 2448 | goto out_garbage; |
2449 | |||
2450 | out_msg_denied: | ||
2451 | p = xdr_inline_decode(xdr, sizeof(*p)); | ||
2452 | if (!p) | ||
2453 | goto out_unparsable; | ||
2454 | switch (*p++) { | ||
2455 | case rpc_auth_error: | ||
2456 | break; | ||
2457 | case rpc_mismatch: | ||
2458 | trace_rpc__mismatch(task); | ||
2459 | error = -EPROTONOSUPPORT; | ||
2460 | goto out_err; | ||
2461 | default: | ||
2462 | trace_rpc__unparsable(task); | ||
2463 | error = -EIO; | ||
2464 | goto out_err; | ||
2465 | } | ||
2466 | |||
2467 | p = xdr_inline_decode(xdr, sizeof(*p)); | ||
2468 | if (!p) | ||
2469 | goto out_unparsable; | ||
2470 | switch (*p++) { | ||
2471 | case rpc_autherr_rejectedcred: | ||
2472 | case rpc_autherr_rejectedverf: | ||
2473 | case rpcsec_gsserr_credproblem: | ||
2474 | case rpcsec_gsserr_ctxproblem: | ||
2475 | if (!task->tk_cred_retry) | ||
2476 | break; | ||
2477 | task->tk_cred_retry--; | ||
2478 | trace_rpc__stale_creds(task); | ||
2479 | rpcauth_invalcred(task); | ||
2480 | /* Ensure we obtain a new XID! */ | ||
2481 | xprt_release(task); | ||
2482 | task->tk_action = call_reserve; | ||
2483 | return -EAGAIN; | ||
2484 | case rpc_autherr_badcred: | ||
2485 | case rpc_autherr_badverf: | ||
2486 | /* possibly garbled cred/verf? */ | ||
2487 | if (!task->tk_garb_retry) | ||
2488 | break; | ||
2489 | task->tk_garb_retry--; | ||
2490 | trace_rpc__bad_creds(task); | ||
2491 | task->tk_action = call_encode; | ||
2492 | return -EAGAIN; | ||
2493 | case rpc_autherr_tooweak: | ||
2494 | trace_rpc__auth_tooweak(task); | ||
2495 | pr_warn("RPC: server %s requires stronger authentication.\n", | ||
2496 | task->tk_xprt->servername); | ||
2497 | break; | ||
2498 | default: | ||
2499 | trace_rpc__unparsable(task); | ||
2500 | error = -EIO; | ||
2501 | } | ||
2502 | goto out_err; | ||
2505 | } | 2503 | } |
2506 | 2504 | ||
2507 | static void rpcproc_encode_null(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 2505 | static void rpcproc_encode_null(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index e87ddb9f7feb..dbd19697ee38 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -1145,17 +1145,6 @@ static __printf(2,3) void svc_printk(struct svc_rqst *rqstp, const char *fmt, .. | |||
1145 | #endif | 1145 | #endif |
1146 | 1146 | ||
1147 | /* | 1147 | /* |
1148 | * Setup response header for TCP, it has a 4B record length field. | ||
1149 | */ | ||
1150 | static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp) | ||
1151 | { | ||
1152 | struct kvec *resv = &rqstp->rq_res.head[0]; | ||
1153 | |||
1154 | /* tcp needs a space for the record length... */ | ||
1155 | svc_putnl(resv, 0); | ||
1156 | } | ||
1157 | |||
1158 | /* | ||
1159 | * Common routine for processing the RPC request. | 1148 | * Common routine for processing the RPC request. |
1160 | */ | 1149 | */ |
1161 | static int | 1150 | static int |
@@ -1182,10 +1171,6 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) | |||
1182 | set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags); | 1171 | set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags); |
1183 | clear_bit(RQ_DROPME, &rqstp->rq_flags); | 1172 | clear_bit(RQ_DROPME, &rqstp->rq_flags); |
1184 | 1173 | ||
1185 | /* Setup reply header */ | ||
1186 | if (rqstp->rq_prot == IPPROTO_TCP) | ||
1187 | svc_tcp_prep_reply_hdr(rqstp); | ||
1188 | |||
1189 | svc_putu32(resv, rqstp->rq_xid); | 1174 | svc_putu32(resv, rqstp->rq_xid); |
1190 | 1175 | ||
1191 | vers = svc_getnl(argv); | 1176 | vers = svc_getnl(argv); |
@@ -1443,6 +1428,10 @@ svc_process(struct svc_rqst *rqstp) | |||
1443 | goto out_drop; | 1428 | goto out_drop; |
1444 | } | 1429 | } |
1445 | 1430 | ||
1431 | /* Reserve space for the record marker */ | ||
1432 | if (rqstp->rq_prot == IPPROTO_TCP) | ||
1433 | svc_putnl(resv, 0); | ||
1434 | |||
1446 | /* Returns 1 for send, 0 for drop */ | 1435 | /* Returns 1 for send, 0 for drop */ |
1447 | if (likely(svc_process_common(rqstp, argv, resv))) | 1436 | if (likely(svc_process_common(rqstp, argv, resv))) |
1448 | return svc_send(rqstp); | 1437 | return svc_send(rqstp); |
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index f302c6eb8779..aa8177ddcbda 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/sunrpc/xdr.h> | 16 | #include <linux/sunrpc/xdr.h> |
17 | #include <linux/sunrpc/msg_prot.h> | 17 | #include <linux/sunrpc/msg_prot.h> |
18 | #include <linux/bvec.h> | 18 | #include <linux/bvec.h> |
19 | #include <trace/events/sunrpc.h> | ||
19 | 20 | ||
20 | /* | 21 | /* |
21 | * XDR functions for basic NFS types | 22 | * XDR functions for basic NFS types |
@@ -162,6 +163,15 @@ xdr_free_bvec(struct xdr_buf *buf) | |||
162 | buf->bvec = NULL; | 163 | buf->bvec = NULL; |
163 | } | 164 | } |
164 | 165 | ||
166 | /** | ||
167 | * xdr_inline_pages - Prepare receive buffer for a large reply | ||
168 | * @xdr: xdr_buf into which reply will be placed | ||
169 | * @offset: expected offset where data payload will start, in bytes | ||
170 | * @pages: vector of struct page pointers | ||
171 | * @base: offset in first page where receive should start, in bytes | ||
172 | * @len: expected size of the upper layer data payload, in bytes | ||
173 | * | ||
174 | */ | ||
165 | void | 175 | void |
166 | xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset, | 176 | xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset, |
167 | struct page **pages, unsigned int base, unsigned int len) | 177 | struct page **pages, unsigned int base, unsigned int len) |
@@ -179,6 +189,8 @@ xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset, | |||
179 | 189 | ||
180 | tail->iov_base = buf + offset; | 190 | tail->iov_base = buf + offset; |
181 | tail->iov_len = buflen - offset; | 191 | tail->iov_len = buflen - offset; |
192 | if ((xdr->page_len & 3) == 0) | ||
193 | tail->iov_len -= sizeof(__be32); | ||
182 | 194 | ||
183 | xdr->buflen += len; | 195 | xdr->buflen += len; |
184 | } | 196 | } |
@@ -346,13 +358,15 @@ EXPORT_SYMBOL_GPL(_copy_from_pages); | |||
346 | * 'len' bytes. The extra data is not lost, but is instead | 358 | * 'len' bytes. The extra data is not lost, but is instead |
347 | * moved into the inlined pages and/or the tail. | 359 | * moved into the inlined pages and/or the tail. |
348 | */ | 360 | */ |
349 | static void | 361 | static unsigned int |
350 | xdr_shrink_bufhead(struct xdr_buf *buf, size_t len) | 362 | xdr_shrink_bufhead(struct xdr_buf *buf, size_t len) |
351 | { | 363 | { |
352 | struct kvec *head, *tail; | 364 | struct kvec *head, *tail; |
353 | size_t copy, offs; | 365 | size_t copy, offs; |
354 | unsigned int pglen = buf->page_len; | 366 | unsigned int pglen = buf->page_len; |
367 | unsigned int result; | ||
355 | 368 | ||
369 | result = 0; | ||
356 | tail = buf->tail; | 370 | tail = buf->tail; |
357 | head = buf->head; | 371 | head = buf->head; |
358 | 372 | ||
@@ -366,6 +380,7 @@ xdr_shrink_bufhead(struct xdr_buf *buf, size_t len) | |||
366 | copy = tail->iov_len - len; | 380 | copy = tail->iov_len - len; |
367 | memmove((char *)tail->iov_base + len, | 381 | memmove((char *)tail->iov_base + len, |
368 | tail->iov_base, copy); | 382 | tail->iov_base, copy); |
383 | result += copy; | ||
369 | } | 384 | } |
370 | /* Copy from the inlined pages into the tail */ | 385 | /* Copy from the inlined pages into the tail */ |
371 | copy = len; | 386 | copy = len; |
@@ -376,11 +391,13 @@ xdr_shrink_bufhead(struct xdr_buf *buf, size_t len) | |||
376 | copy = 0; | 391 | copy = 0; |
377 | else if (copy > tail->iov_len - offs) | 392 | else if (copy > tail->iov_len - offs) |
378 | copy = tail->iov_len - offs; | 393 | copy = tail->iov_len - offs; |
379 | if (copy != 0) | 394 | if (copy != 0) { |
380 | _copy_from_pages((char *)tail->iov_base + offs, | 395 | _copy_from_pages((char *)tail->iov_base + offs, |
381 | buf->pages, | 396 | buf->pages, |
382 | buf->page_base + pglen + offs - len, | 397 | buf->page_base + pglen + offs - len, |
383 | copy); | 398 | copy); |
399 | result += copy; | ||
400 | } | ||
384 | /* Do we also need to copy data from the head into the tail ? */ | 401 | /* Do we also need to copy data from the head into the tail ? */ |
385 | if (len > pglen) { | 402 | if (len > pglen) { |
386 | offs = copy = len - pglen; | 403 | offs = copy = len - pglen; |
@@ -390,6 +407,7 @@ xdr_shrink_bufhead(struct xdr_buf *buf, size_t len) | |||
390 | (char *)head->iov_base + | 407 | (char *)head->iov_base + |
391 | head->iov_len - offs, | 408 | head->iov_len - offs, |
392 | copy); | 409 | copy); |
410 | result += copy; | ||
393 | } | 411 | } |
394 | } | 412 | } |
395 | /* Now handle pages */ | 413 | /* Now handle pages */ |
@@ -405,12 +423,15 @@ xdr_shrink_bufhead(struct xdr_buf *buf, size_t len) | |||
405 | _copy_to_pages(buf->pages, buf->page_base, | 423 | _copy_to_pages(buf->pages, buf->page_base, |
406 | (char *)head->iov_base + head->iov_len - len, | 424 | (char *)head->iov_base + head->iov_len - len, |
407 | copy); | 425 | copy); |
426 | result += copy; | ||
408 | } | 427 | } |
409 | head->iov_len -= len; | 428 | head->iov_len -= len; |
410 | buf->buflen -= len; | 429 | buf->buflen -= len; |
411 | /* Have we truncated the message? */ | 430 | /* Have we truncated the message? */ |
412 | if (buf->len > buf->buflen) | 431 | if (buf->len > buf->buflen) |
413 | buf->len = buf->buflen; | 432 | buf->len = buf->buflen; |
433 | |||
434 | return result; | ||
414 | } | 435 | } |
415 | 436 | ||
416 | /** | 437 | /** |
@@ -422,14 +443,16 @@ xdr_shrink_bufhead(struct xdr_buf *buf, size_t len) | |||
422 | * 'len' bytes. The extra data is not lost, but is instead | 443 | * 'len' bytes. The extra data is not lost, but is instead |
423 | * moved into the tail. | 444 | * moved into the tail. |
424 | */ | 445 | */ |
425 | static void | 446 | static unsigned int |
426 | xdr_shrink_pagelen(struct xdr_buf *buf, size_t len) | 447 | xdr_shrink_pagelen(struct xdr_buf *buf, size_t len) |
427 | { | 448 | { |
428 | struct kvec *tail; | 449 | struct kvec *tail; |
429 | size_t copy; | 450 | size_t copy; |
430 | unsigned int pglen = buf->page_len; | 451 | unsigned int pglen = buf->page_len; |
431 | unsigned int tailbuf_len; | 452 | unsigned int tailbuf_len; |
453 | unsigned int result; | ||
432 | 454 | ||
455 | result = 0; | ||
433 | tail = buf->tail; | 456 | tail = buf->tail; |
434 | BUG_ON (len > pglen); | 457 | BUG_ON (len > pglen); |
435 | 458 | ||
@@ -447,18 +470,22 @@ xdr_shrink_pagelen(struct xdr_buf *buf, size_t len) | |||
447 | if (tail->iov_len > len) { | 470 | if (tail->iov_len > len) { |
448 | char *p = (char *)tail->iov_base + len; | 471 | char *p = (char *)tail->iov_base + len; |
449 | memmove(p, tail->iov_base, tail->iov_len - len); | 472 | memmove(p, tail->iov_base, tail->iov_len - len); |
473 | result += tail->iov_len - len; | ||
450 | } else | 474 | } else |
451 | copy = tail->iov_len; | 475 | copy = tail->iov_len; |
452 | /* Copy from the inlined pages into the tail */ | 476 | /* Copy from the inlined pages into the tail */ |
453 | _copy_from_pages((char *)tail->iov_base, | 477 | _copy_from_pages((char *)tail->iov_base, |
454 | buf->pages, buf->page_base + pglen - len, | 478 | buf->pages, buf->page_base + pglen - len, |
455 | copy); | 479 | copy); |
480 | result += copy; | ||
456 | } | 481 | } |
457 | buf->page_len -= len; | 482 | buf->page_len -= len; |
458 | buf->buflen -= len; | 483 | buf->buflen -= len; |
459 | /* Have we truncated the message? */ | 484 | /* Have we truncated the message? */ |
460 | if (buf->len > buf->buflen) | 485 | if (buf->len > buf->buflen) |
461 | buf->len = buf->buflen; | 486 | buf->len = buf->buflen; |
487 | |||
488 | return result; | ||
462 | } | 489 | } |
463 | 490 | ||
464 | void | 491 | void |
@@ -483,6 +510,7 @@ EXPORT_SYMBOL_GPL(xdr_stream_pos); | |||
483 | * @xdr: pointer to xdr_stream struct | 510 | * @xdr: pointer to xdr_stream struct |
484 | * @buf: pointer to XDR buffer in which to encode data | 511 | * @buf: pointer to XDR buffer in which to encode data |
485 | * @p: current pointer inside XDR buffer | 512 | * @p: current pointer inside XDR buffer |
513 | * @rqst: pointer to controlling rpc_rqst, for debugging | ||
486 | * | 514 | * |
487 | * Note: at the moment the RPC client only passes the length of our | 515 | * Note: at the moment the RPC client only passes the length of our |
488 | * scratch buffer in the xdr_buf's header kvec. Previously this | 516 | * scratch buffer in the xdr_buf's header kvec. Previously this |
@@ -491,7 +519,8 @@ EXPORT_SYMBOL_GPL(xdr_stream_pos); | |||
491 | * of the buffer length, and takes care of adjusting the kvec | 519 | * of the buffer length, and takes care of adjusting the kvec |
492 | * length for us. | 520 | * length for us. |
493 | */ | 521 | */ |
494 | void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p) | 522 | void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p, |
523 | struct rpc_rqst *rqst) | ||
495 | { | 524 | { |
496 | struct kvec *iov = buf->head; | 525 | struct kvec *iov = buf->head; |
497 | int scratch_len = buf->buflen - buf->page_len - buf->tail[0].iov_len; | 526 | int scratch_len = buf->buflen - buf->page_len - buf->tail[0].iov_len; |
@@ -513,6 +542,7 @@ void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p) | |||
513 | buf->len += len; | 542 | buf->len += len; |
514 | iov->iov_len += len; | 543 | iov->iov_len += len; |
515 | } | 544 | } |
545 | xdr->rqst = rqst; | ||
516 | } | 546 | } |
517 | EXPORT_SYMBOL_GPL(xdr_init_encode); | 547 | EXPORT_SYMBOL_GPL(xdr_init_encode); |
518 | 548 | ||
@@ -551,9 +581,9 @@ static __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, | |||
551 | int frag1bytes, frag2bytes; | 581 | int frag1bytes, frag2bytes; |
552 | 582 | ||
553 | if (nbytes > PAGE_SIZE) | 583 | if (nbytes > PAGE_SIZE) |
554 | return NULL; /* Bigger buffers require special handling */ | 584 | goto out_overflow; /* Bigger buffers require special handling */ |
555 | if (xdr->buf->len + nbytes > xdr->buf->buflen) | 585 | if (xdr->buf->len + nbytes > xdr->buf->buflen) |
556 | return NULL; /* Sorry, we're totally out of space */ | 586 | goto out_overflow; /* Sorry, we're totally out of space */ |
557 | frag1bytes = (xdr->end - xdr->p) << 2; | 587 | frag1bytes = (xdr->end - xdr->p) << 2; |
558 | frag2bytes = nbytes - frag1bytes; | 588 | frag2bytes = nbytes - frag1bytes; |
559 | if (xdr->iov) | 589 | if (xdr->iov) |
@@ -582,6 +612,9 @@ static __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, | |||
582 | xdr->buf->page_len += frag2bytes; | 612 | xdr->buf->page_len += frag2bytes; |
583 | xdr->buf->len += nbytes; | 613 | xdr->buf->len += nbytes; |
584 | return p; | 614 | return p; |
615 | out_overflow: | ||
616 | trace_rpc_xdr_overflow(xdr, nbytes); | ||
617 | return NULL; | ||
585 | } | 618 | } |
586 | 619 | ||
587 | /** | 620 | /** |
@@ -819,8 +852,10 @@ static bool xdr_set_next_buffer(struct xdr_stream *xdr) | |||
819 | * @xdr: pointer to xdr_stream struct | 852 | * @xdr: pointer to xdr_stream struct |
820 | * @buf: pointer to XDR buffer from which to decode data | 853 | * @buf: pointer to XDR buffer from which to decode data |
821 | * @p: current pointer inside XDR buffer | 854 | * @p: current pointer inside XDR buffer |
855 | * @rqst: pointer to controlling rpc_rqst, for debugging | ||
822 | */ | 856 | */ |
823 | void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p) | 857 | void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p, |
858 | struct rpc_rqst *rqst) | ||
824 | { | 859 | { |
825 | xdr->buf = buf; | 860 | xdr->buf = buf; |
826 | xdr->scratch.iov_base = NULL; | 861 | xdr->scratch.iov_base = NULL; |
@@ -836,6 +871,7 @@ void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p) | |||
836 | xdr->nwords -= p - xdr->p; | 871 | xdr->nwords -= p - xdr->p; |
837 | xdr->p = p; | 872 | xdr->p = p; |
838 | } | 873 | } |
874 | xdr->rqst = rqst; | ||
839 | } | 875 | } |
840 | EXPORT_SYMBOL_GPL(xdr_init_decode); | 876 | EXPORT_SYMBOL_GPL(xdr_init_decode); |
841 | 877 | ||
@@ -854,7 +890,7 @@ void xdr_init_decode_pages(struct xdr_stream *xdr, struct xdr_buf *buf, | |||
854 | buf->page_len = len; | 890 | buf->page_len = len; |
855 | buf->buflen = len; | 891 | buf->buflen = len; |
856 | buf->len = len; | 892 | buf->len = len; |
857 | xdr_init_decode(xdr, buf, NULL); | 893 | xdr_init_decode(xdr, buf, NULL, NULL); |
858 | } | 894 | } |
859 | EXPORT_SYMBOL_GPL(xdr_init_decode_pages); | 895 | EXPORT_SYMBOL_GPL(xdr_init_decode_pages); |
860 | 896 | ||
@@ -896,20 +932,23 @@ static __be32 *xdr_copy_to_scratch(struct xdr_stream *xdr, size_t nbytes) | |||
896 | size_t cplen = (char *)xdr->end - (char *)xdr->p; | 932 | size_t cplen = (char *)xdr->end - (char *)xdr->p; |
897 | 933 | ||
898 | if (nbytes > xdr->scratch.iov_len) | 934 | if (nbytes > xdr->scratch.iov_len) |
899 | return NULL; | 935 | goto out_overflow; |
900 | p = __xdr_inline_decode(xdr, cplen); | 936 | p = __xdr_inline_decode(xdr, cplen); |
901 | if (p == NULL) | 937 | if (p == NULL) |
902 | return NULL; | 938 | return NULL; |
903 | memcpy(cpdest, p, cplen); | 939 | memcpy(cpdest, p, cplen); |
940 | if (!xdr_set_next_buffer(xdr)) | ||
941 | goto out_overflow; | ||
904 | cpdest += cplen; | 942 | cpdest += cplen; |
905 | nbytes -= cplen; | 943 | nbytes -= cplen; |
906 | if (!xdr_set_next_buffer(xdr)) | ||
907 | return NULL; | ||
908 | p = __xdr_inline_decode(xdr, nbytes); | 944 | p = __xdr_inline_decode(xdr, nbytes); |
909 | if (p == NULL) | 945 | if (p == NULL) |
910 | return NULL; | 946 | return NULL; |
911 | memcpy(cpdest, p, nbytes); | 947 | memcpy(cpdest, p, nbytes); |
912 | return xdr->scratch.iov_base; | 948 | return xdr->scratch.iov_base; |
949 | out_overflow: | ||
950 | trace_rpc_xdr_overflow(xdr, nbytes); | ||
951 | return NULL; | ||
913 | } | 952 | } |
914 | 953 | ||
915 | /** | 954 | /** |
@@ -926,14 +965,17 @@ __be32 * xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes) | |||
926 | { | 965 | { |
927 | __be32 *p; | 966 | __be32 *p; |
928 | 967 | ||
929 | if (nbytes == 0) | 968 | if (unlikely(nbytes == 0)) |
930 | return xdr->p; | 969 | return xdr->p; |
931 | if (xdr->p == xdr->end && !xdr_set_next_buffer(xdr)) | 970 | if (xdr->p == xdr->end && !xdr_set_next_buffer(xdr)) |
932 | return NULL; | 971 | goto out_overflow; |
933 | p = __xdr_inline_decode(xdr, nbytes); | 972 | p = __xdr_inline_decode(xdr, nbytes); |
934 | if (p != NULL) | 973 | if (p != NULL) |
935 | return p; | 974 | return p; |
936 | return xdr_copy_to_scratch(xdr, nbytes); | 975 | return xdr_copy_to_scratch(xdr, nbytes); |
976 | out_overflow: | ||
977 | trace_rpc_xdr_overflow(xdr, nbytes); | ||
978 | return NULL; | ||
937 | } | 979 | } |
938 | EXPORT_SYMBOL_GPL(xdr_inline_decode); | 980 | EXPORT_SYMBOL_GPL(xdr_inline_decode); |
939 | 981 | ||
@@ -943,13 +985,17 @@ static unsigned int xdr_align_pages(struct xdr_stream *xdr, unsigned int len) | |||
943 | struct kvec *iov; | 985 | struct kvec *iov; |
944 | unsigned int nwords = XDR_QUADLEN(len); | 986 | unsigned int nwords = XDR_QUADLEN(len); |
945 | unsigned int cur = xdr_stream_pos(xdr); | 987 | unsigned int cur = xdr_stream_pos(xdr); |
988 | unsigned int copied, offset; | ||
946 | 989 | ||
947 | if (xdr->nwords == 0) | 990 | if (xdr->nwords == 0) |
948 | return 0; | 991 | return 0; |
992 | |||
949 | /* Realign pages to current pointer position */ | 993 | /* Realign pages to current pointer position */ |
950 | iov = buf->head; | 994 | iov = buf->head; |
951 | if (iov->iov_len > cur) { | 995 | if (iov->iov_len > cur) { |
952 | xdr_shrink_bufhead(buf, iov->iov_len - cur); | 996 | offset = iov->iov_len - cur; |
997 | copied = xdr_shrink_bufhead(buf, offset); | ||
998 | trace_rpc_xdr_alignment(xdr, offset, copied); | ||
953 | xdr->nwords = XDR_QUADLEN(buf->len - cur); | 999 | xdr->nwords = XDR_QUADLEN(buf->len - cur); |
954 | } | 1000 | } |
955 | 1001 | ||
@@ -961,7 +1007,9 @@ static unsigned int xdr_align_pages(struct xdr_stream *xdr, unsigned int len) | |||
961 | len = buf->page_len; | 1007 | len = buf->page_len; |
962 | else if (nwords < xdr->nwords) { | 1008 | else if (nwords < xdr->nwords) { |
963 | /* Truncate page data and move it into the tail */ | 1009 | /* Truncate page data and move it into the tail */ |
964 | xdr_shrink_pagelen(buf, buf->page_len - len); | 1010 | offset = buf->page_len - len; |
1011 | copied = xdr_shrink_pagelen(buf, offset); | ||
1012 | trace_rpc_xdr_alignment(xdr, offset, copied); | ||
965 | xdr->nwords = XDR_QUADLEN(buf->len - cur); | 1013 | xdr->nwords = XDR_QUADLEN(buf->len - cur); |
966 | } | 1014 | } |
967 | return len; | 1015 | return len; |
@@ -1102,47 +1150,6 @@ xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf, | |||
1102 | } | 1150 | } |
1103 | EXPORT_SYMBOL_GPL(xdr_buf_subsegment); | 1151 | EXPORT_SYMBOL_GPL(xdr_buf_subsegment); |
1104 | 1152 | ||
1105 | /** | ||
1106 | * xdr_buf_trim - lop at most "len" bytes off the end of "buf" | ||
1107 | * @buf: buf to be trimmed | ||
1108 | * @len: number of bytes to reduce "buf" by | ||
1109 | * | ||
1110 | * Trim an xdr_buf by the given number of bytes by fixing up the lengths. Note | ||
1111 | * that it's possible that we'll trim less than that amount if the xdr_buf is | ||
1112 | * too small, or if (for instance) it's all in the head and the parser has | ||
1113 | * already read too far into it. | ||
1114 | */ | ||
1115 | void xdr_buf_trim(struct xdr_buf *buf, unsigned int len) | ||
1116 | { | ||
1117 | size_t cur; | ||
1118 | unsigned int trim = len; | ||
1119 | |||
1120 | if (buf->tail[0].iov_len) { | ||
1121 | cur = min_t(size_t, buf->tail[0].iov_len, trim); | ||
1122 | buf->tail[0].iov_len -= cur; | ||
1123 | trim -= cur; | ||
1124 | if (!trim) | ||
1125 | goto fix_len; | ||
1126 | } | ||
1127 | |||
1128 | if (buf->page_len) { | ||
1129 | cur = min_t(unsigned int, buf->page_len, trim); | ||
1130 | buf->page_len -= cur; | ||
1131 | trim -= cur; | ||
1132 | if (!trim) | ||
1133 | goto fix_len; | ||
1134 | } | ||
1135 | |||
1136 | if (buf->head[0].iov_len) { | ||
1137 | cur = min_t(size_t, buf->head[0].iov_len, trim); | ||
1138 | buf->head[0].iov_len -= cur; | ||
1139 | trim -= cur; | ||
1140 | } | ||
1141 | fix_len: | ||
1142 | buf->len -= (len - trim); | ||
1143 | } | ||
1144 | EXPORT_SYMBOL_GPL(xdr_buf_trim); | ||
1145 | |||
1146 | static void __read_bytes_from_xdr_buf(struct xdr_buf *subbuf, void *obj, unsigned int len) | 1153 | static void __read_bytes_from_xdr_buf(struct xdr_buf *subbuf, void *obj, unsigned int len) |
1147 | { | 1154 | { |
1148 | unsigned int this_len; | 1155 | unsigned int this_len; |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 2af6be9d6574..1cf4e379be7b 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -1168,6 +1168,7 @@ xprt_request_enqueue_transmit(struct rpc_task *task) | |||
1168 | /* Note: req is added _before_ pos */ | 1168 | /* Note: req is added _before_ pos */ |
1169 | list_add_tail(&req->rq_xmit, &pos->rq_xmit); | 1169 | list_add_tail(&req->rq_xmit, &pos->rq_xmit); |
1170 | INIT_LIST_HEAD(&req->rq_xmit2); | 1170 | INIT_LIST_HEAD(&req->rq_xmit2); |
1171 | trace_xprt_enq_xmit(task, 1); | ||
1171 | goto out; | 1172 | goto out; |
1172 | } | 1173 | } |
1173 | } else if (RPC_IS_SWAPPER(task)) { | 1174 | } else if (RPC_IS_SWAPPER(task)) { |
@@ -1179,6 +1180,7 @@ xprt_request_enqueue_transmit(struct rpc_task *task) | |||
1179 | /* Note: req is added _before_ pos */ | 1180 | /* Note: req is added _before_ pos */ |
1180 | list_add_tail(&req->rq_xmit, &pos->rq_xmit); | 1181 | list_add_tail(&req->rq_xmit, &pos->rq_xmit); |
1181 | INIT_LIST_HEAD(&req->rq_xmit2); | 1182 | INIT_LIST_HEAD(&req->rq_xmit2); |
1183 | trace_xprt_enq_xmit(task, 2); | ||
1182 | goto out; | 1184 | goto out; |
1183 | } | 1185 | } |
1184 | } else if (!req->rq_seqno) { | 1186 | } else if (!req->rq_seqno) { |
@@ -1187,11 +1189,13 @@ xprt_request_enqueue_transmit(struct rpc_task *task) | |||
1187 | continue; | 1189 | continue; |
1188 | list_add_tail(&req->rq_xmit2, &pos->rq_xmit2); | 1190 | list_add_tail(&req->rq_xmit2, &pos->rq_xmit2); |
1189 | INIT_LIST_HEAD(&req->rq_xmit); | 1191 | INIT_LIST_HEAD(&req->rq_xmit); |
1192 | trace_xprt_enq_xmit(task, 3); | ||
1190 | goto out; | 1193 | goto out; |
1191 | } | 1194 | } |
1192 | } | 1195 | } |
1193 | list_add_tail(&req->rq_xmit, &xprt->xmit_queue); | 1196 | list_add_tail(&req->rq_xmit, &xprt->xmit_queue); |
1194 | INIT_LIST_HEAD(&req->rq_xmit2); | 1197 | INIT_LIST_HEAD(&req->rq_xmit2); |
1198 | trace_xprt_enq_xmit(task, 4); | ||
1195 | out: | 1199 | out: |
1196 | set_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate); | 1200 | set_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate); |
1197 | spin_unlock(&xprt->queue_lock); | 1201 | spin_unlock(&xprt->queue_lock); |
@@ -1316,8 +1320,6 @@ xprt_request_transmit(struct rpc_rqst *req, struct rpc_task *snd_task) | |||
1316 | int is_retrans = RPC_WAS_SENT(task); | 1320 | int is_retrans = RPC_WAS_SENT(task); |
1317 | int status; | 1321 | int status; |
1318 | 1322 | ||
1319 | dprintk("RPC: %5u xprt_transmit(%u)\n", task->tk_pid, req->rq_slen); | ||
1320 | |||
1321 | if (!req->rq_bytes_sent) { | 1323 | if (!req->rq_bytes_sent) { |
1322 | if (xprt_request_data_received(task)) { | 1324 | if (xprt_request_data_received(task)) { |
1323 | status = 0; | 1325 | status = 0; |
@@ -1339,9 +1341,9 @@ xprt_request_transmit(struct rpc_rqst *req, struct rpc_task *snd_task) | |||
1339 | 1341 | ||
1340 | connect_cookie = xprt->connect_cookie; | 1342 | connect_cookie = xprt->connect_cookie; |
1341 | status = xprt->ops->send_request(req); | 1343 | status = xprt->ops->send_request(req); |
1342 | trace_xprt_transmit(xprt, req->rq_xid, status); | ||
1343 | if (status != 0) { | 1344 | if (status != 0) { |
1344 | req->rq_ntrans--; | 1345 | req->rq_ntrans--; |
1346 | trace_xprt_transmit(req, status); | ||
1345 | return status; | 1347 | return status; |
1346 | } | 1348 | } |
1347 | 1349 | ||
@@ -1350,7 +1352,6 @@ xprt_request_transmit(struct rpc_rqst *req, struct rpc_task *snd_task) | |||
1350 | 1352 | ||
1351 | xprt_inject_disconnect(xprt); | 1353 | xprt_inject_disconnect(xprt); |
1352 | 1354 | ||
1353 | dprintk("RPC: %5u xmit complete\n", task->tk_pid); | ||
1354 | task->tk_flags |= RPC_TASK_SENT; | 1355 | task->tk_flags |= RPC_TASK_SENT; |
1355 | spin_lock_bh(&xprt->transport_lock); | 1356 | spin_lock_bh(&xprt->transport_lock); |
1356 | 1357 | ||
@@ -1363,6 +1364,7 @@ xprt_request_transmit(struct rpc_rqst *req, struct rpc_task *snd_task) | |||
1363 | 1364 | ||
1364 | req->rq_connect_cookie = connect_cookie; | 1365 | req->rq_connect_cookie = connect_cookie; |
1365 | out_dequeue: | 1366 | out_dequeue: |
1367 | trace_xprt_transmit(req, status); | ||
1366 | xprt_request_dequeue_transmit(task); | 1368 | xprt_request_dequeue_transmit(task); |
1367 | rpc_wake_up_queued_task_set_status(&xprt->sending, task, status); | 1369 | rpc_wake_up_queued_task_set_status(&xprt->sending, task, status); |
1368 | return status; | 1370 | return status; |
diff --git a/net/sunrpc/xprtrdma/backchannel.c b/net/sunrpc/xprtrdma/backchannel.c index 749452724e6e..d79b18c1f4cd 100644 --- a/net/sunrpc/xprtrdma/backchannel.c +++ b/net/sunrpc/xprtrdma/backchannel.c | |||
@@ -123,7 +123,7 @@ static int rpcrdma_bc_marshal_reply(struct rpc_rqst *rqst) | |||
123 | 123 | ||
124 | rpcrdma_set_xdrlen(&req->rl_hdrbuf, 0); | 124 | rpcrdma_set_xdrlen(&req->rl_hdrbuf, 0); |
125 | xdr_init_encode(&req->rl_stream, &req->rl_hdrbuf, | 125 | xdr_init_encode(&req->rl_stream, &req->rl_hdrbuf, |
126 | req->rl_rdmabuf->rg_base); | 126 | req->rl_rdmabuf->rg_base, rqst); |
127 | 127 | ||
128 | p = xdr_reserve_space(&req->rl_stream, 28); | 128 | p = xdr_reserve_space(&req->rl_stream, 28); |
129 | if (unlikely(!p)) | 129 | if (unlikely(!p)) |
diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c index 6a561056b538..52cb6c1b0c2b 100644 --- a/net/sunrpc/xprtrdma/frwr_ops.c +++ b/net/sunrpc/xprtrdma/frwr_ops.c | |||
@@ -391,7 +391,7 @@ frwr_wc_localinv_wake(struct ib_cq *cq, struct ib_wc *wc) | |||
391 | */ | 391 | */ |
392 | struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt, | 392 | struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt, |
393 | struct rpcrdma_mr_seg *seg, | 393 | struct rpcrdma_mr_seg *seg, |
394 | int nsegs, bool writing, u32 xid, | 394 | int nsegs, bool writing, __be32 xid, |
395 | struct rpcrdma_mr **out) | 395 | struct rpcrdma_mr **out) |
396 | { | 396 | { |
397 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; | 397 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; |
@@ -446,7 +446,7 @@ struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt, | |||
446 | goto out_mapmr_err; | 446 | goto out_mapmr_err; |
447 | 447 | ||
448 | ibmr->iova &= 0x00000000ffffffff; | 448 | ibmr->iova &= 0x00000000ffffffff; |
449 | ibmr->iova |= ((u64)cpu_to_be32(xid)) << 32; | 449 | ibmr->iova |= ((u64)be32_to_cpu(xid)) << 32; |
450 | key = (u8)(ibmr->rkey & 0x000000FF); | 450 | key = (u8)(ibmr->rkey & 0x000000FF); |
451 | ib_update_fast_reg_key(ibmr, ++key); | 451 | ib_update_fast_reg_key(ibmr, ++key); |
452 | 452 | ||
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index d18614e02b4e..6c1fb270f127 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c | |||
@@ -164,6 +164,21 @@ static bool rpcrdma_results_inline(struct rpcrdma_xprt *r_xprt, | |||
164 | return rqst->rq_rcv_buf.buflen <= ia->ri_max_inline_read; | 164 | return rqst->rq_rcv_buf.buflen <= ia->ri_max_inline_read; |
165 | } | 165 | } |
166 | 166 | ||
167 | /* The client is required to provide a Reply chunk if the maximum | ||
168 | * size of the non-payload part of the RPC Reply is larger than | ||
169 | * the inline threshold. | ||
170 | */ | ||
171 | static bool | ||
172 | rpcrdma_nonpayload_inline(const struct rpcrdma_xprt *r_xprt, | ||
173 | const struct rpc_rqst *rqst) | ||
174 | { | ||
175 | const struct xdr_buf *buf = &rqst->rq_rcv_buf; | ||
176 | const struct rpcrdma_ia *ia = &r_xprt->rx_ia; | ||
177 | |||
178 | return buf->head[0].iov_len + buf->tail[0].iov_len < | ||
179 | ia->ri_max_inline_read; | ||
180 | } | ||
181 | |||
167 | /* Split @vec on page boundaries into SGEs. FMR registers pages, not | 182 | /* Split @vec on page boundaries into SGEs. FMR registers pages, not |
168 | * a byte range. Other modes coalesce these SGEs into a single MR | 183 | * a byte range. Other modes coalesce these SGEs into a single MR |
169 | * when they can. | 184 | * when they can. |
@@ -733,7 +748,7 @@ rpcrdma_marshal_req(struct rpcrdma_xprt *r_xprt, struct rpc_rqst *rqst) | |||
733 | 748 | ||
734 | rpcrdma_set_xdrlen(&req->rl_hdrbuf, 0); | 749 | rpcrdma_set_xdrlen(&req->rl_hdrbuf, 0); |
735 | xdr_init_encode(xdr, &req->rl_hdrbuf, | 750 | xdr_init_encode(xdr, &req->rl_hdrbuf, |
736 | req->rl_rdmabuf->rg_base); | 751 | req->rl_rdmabuf->rg_base, rqst); |
737 | 752 | ||
738 | /* Fixed header fields */ | 753 | /* Fixed header fields */ |
739 | ret = -EMSGSIZE; | 754 | ret = -EMSGSIZE; |
@@ -762,7 +777,8 @@ rpcrdma_marshal_req(struct rpcrdma_xprt *r_xprt, struct rpc_rqst *rqst) | |||
762 | */ | 777 | */ |
763 | if (rpcrdma_results_inline(r_xprt, rqst)) | 778 | if (rpcrdma_results_inline(r_xprt, rqst)) |
764 | wtype = rpcrdma_noch; | 779 | wtype = rpcrdma_noch; |
765 | else if (ddp_allowed && rqst->rq_rcv_buf.flags & XDRBUF_READ) | 780 | else if ((ddp_allowed && rqst->rq_rcv_buf.flags & XDRBUF_READ) && |
781 | rpcrdma_nonpayload_inline(r_xprt, rqst)) | ||
766 | wtype = rpcrdma_writech; | 782 | wtype = rpcrdma_writech; |
767 | else | 783 | else |
768 | wtype = rpcrdma_replych; | 784 | wtype = rpcrdma_replych; |
@@ -1313,7 +1329,7 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep) | |||
1313 | 1329 | ||
1314 | /* Fixed transport header fields */ | 1330 | /* Fixed transport header fields */ |
1315 | xdr_init_decode(&rep->rr_stream, &rep->rr_hdrbuf, | 1331 | xdr_init_decode(&rep->rr_stream, &rep->rr_hdrbuf, |
1316 | rep->rr_hdrbuf.head[0].iov_base); | 1332 | rep->rr_hdrbuf.head[0].iov_base, NULL); |
1317 | p = xdr_inline_decode(&rep->rr_stream, 4 * sizeof(*p)); | 1333 | p = xdr_inline_decode(&rep->rr_stream, 4 * sizeof(*p)); |
1318 | if (unlikely(!p)) | 1334 | if (unlikely(!p)) |
1319 | goto out_shortreply; | 1335 | goto out_shortreply; |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c index b908f2ca08fd..907464c2a9f0 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c +++ b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c | |||
@@ -304,7 +304,6 @@ xprt_setup_rdma_bc(struct xprt_create *args) | |||
304 | xprt->idle_timeout = RPCRDMA_IDLE_DISC_TO; | 304 | xprt->idle_timeout = RPCRDMA_IDLE_DISC_TO; |
305 | 305 | ||
306 | xprt->prot = XPRT_TRANSPORT_BC_RDMA; | 306 | xprt->prot = XPRT_TRANSPORT_BC_RDMA; |
307 | xprt->tsh_size = 0; | ||
308 | xprt->ops = &xprt_rdma_bc_procs; | 307 | xprt->ops = &xprt_rdma_bc_procs; |
309 | 308 | ||
310 | memcpy(&xprt->addr, args->dstaddr, args->addrlen); | 309 | memcpy(&xprt->addr, args->dstaddr, args->addrlen); |
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 3c490172d383..5d261353bd90 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c | |||
@@ -332,7 +332,6 @@ xprt_setup_rdma(struct xprt_create *args) | |||
332 | xprt->idle_timeout = RPCRDMA_IDLE_DISC_TO; | 332 | xprt->idle_timeout = RPCRDMA_IDLE_DISC_TO; |
333 | 333 | ||
334 | xprt->resvport = 0; /* privileged port not needed */ | 334 | xprt->resvport = 0; /* privileged port not needed */ |
335 | xprt->tsh_size = 0; /* RPC-RDMA handles framing */ | ||
336 | xprt->ops = &xprt_rdma_procs; | 335 | xprt->ops = &xprt_rdma_procs; |
337 | 336 | ||
338 | /* | 337 | /* |
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 21113bfd4eca..89a63391d4d4 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -1481,6 +1481,8 @@ rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp) | |||
1481 | if (ep->rep_receive_count > needed) | 1481 | if (ep->rep_receive_count > needed) |
1482 | goto out; | 1482 | goto out; |
1483 | needed -= ep->rep_receive_count; | 1483 | needed -= ep->rep_receive_count; |
1484 | if (!temp) | ||
1485 | needed += RPCRDMA_MAX_RECV_BATCH; | ||
1484 | 1486 | ||
1485 | count = 0; | 1487 | count = 0; |
1486 | wr = NULL; | 1488 | wr = NULL; |
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index 5a18472f2c9c..10f6593e1a6a 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h | |||
@@ -205,6 +205,16 @@ struct rpcrdma_rep { | |||
205 | struct ib_recv_wr rr_recv_wr; | 205 | struct ib_recv_wr rr_recv_wr; |
206 | }; | 206 | }; |
207 | 207 | ||
208 | /* To reduce the rate at which a transport invokes ib_post_recv | ||
209 | * (and thus the hardware doorbell rate), xprtrdma posts Receive | ||
210 | * WRs in batches. | ||
211 | * | ||
212 | * Setting this to zero disables Receive post batching. | ||
213 | */ | ||
214 | enum { | ||
215 | RPCRDMA_MAX_RECV_BATCH = 7, | ||
216 | }; | ||
217 | |||
208 | /* struct rpcrdma_sendctx - DMA mapped SGEs to unmap after Send completes | 218 | /* struct rpcrdma_sendctx - DMA mapped SGEs to unmap after Send completes |
209 | */ | 219 | */ |
210 | struct rpcrdma_req; | 220 | struct rpcrdma_req; |
@@ -577,7 +587,7 @@ void frwr_release_mr(struct rpcrdma_mr *mr); | |||
577 | size_t frwr_maxpages(struct rpcrdma_xprt *r_xprt); | 587 | size_t frwr_maxpages(struct rpcrdma_xprt *r_xprt); |
578 | struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt, | 588 | struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt, |
579 | struct rpcrdma_mr_seg *seg, | 589 | struct rpcrdma_mr_seg *seg, |
580 | int nsegs, bool writing, u32 xid, | 590 | int nsegs, bool writing, __be32 xid, |
581 | struct rpcrdma_mr **mr); | 591 | struct rpcrdma_mr **mr); |
582 | int frwr_send(struct rpcrdma_ia *ia, struct rpcrdma_req *req); | 592 | int frwr_send(struct rpcrdma_ia *ia, struct rpcrdma_req *req); |
583 | void frwr_reminv(struct rpcrdma_rep *rep, struct list_head *mrs); | 593 | void frwr_reminv(struct rpcrdma_rep *rep, struct list_head *mrs); |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 8fa74c8a4fd8..53de72d2dded 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -769,6 +769,29 @@ static int xs_send_pagedata(struct socket *sock, struct msghdr *msg, struct xdr_ | |||
769 | return xs_sendmsg(sock, msg, base + xdr->page_base); | 769 | return xs_sendmsg(sock, msg, base + xdr->page_base); |
770 | } | 770 | } |
771 | 771 | ||
772 | #define xs_record_marker_len() sizeof(rpc_fraghdr) | ||
773 | |||
774 | /* Common case: | ||
775 | * - stream transport | ||
776 | * - sending from byte 0 of the message | ||
777 | * - the message is wholly contained in @xdr's head iovec | ||
778 | */ | ||
779 | static int xs_send_rm_and_kvec(struct socket *sock, struct msghdr *msg, | ||
780 | rpc_fraghdr marker, struct kvec *vec, size_t base) | ||
781 | { | ||
782 | struct kvec iov[2] = { | ||
783 | [0] = { | ||
784 | .iov_base = &marker, | ||
785 | .iov_len = sizeof(marker) | ||
786 | }, | ||
787 | [1] = *vec, | ||
788 | }; | ||
789 | size_t len = iov[0].iov_len + iov[1].iov_len; | ||
790 | |||
791 | iov_iter_kvec(&msg->msg_iter, WRITE, iov, 2, len); | ||
792 | return xs_sendmsg(sock, msg, base); | ||
793 | } | ||
794 | |||
772 | /** | 795 | /** |
773 | * xs_sendpages - write pages directly to a socket | 796 | * xs_sendpages - write pages directly to a socket |
774 | * @sock: socket to send on | 797 | * @sock: socket to send on |
@@ -776,34 +799,42 @@ static int xs_send_pagedata(struct socket *sock, struct msghdr *msg, struct xdr_ | |||
776 | * @addrlen: UDP only -- length of destination address | 799 | * @addrlen: UDP only -- length of destination address |
777 | * @xdr: buffer containing this request | 800 | * @xdr: buffer containing this request |
778 | * @base: starting position in the buffer | 801 | * @base: starting position in the buffer |
802 | * @rm: stream record marker field | ||
779 | * @sent_p: return the total number of bytes successfully queued for sending | 803 | * @sent_p: return the total number of bytes successfully queued for sending |
780 | * | 804 | * |
781 | */ | 805 | */ |
782 | static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, int *sent_p) | 806 | static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, rpc_fraghdr rm, int *sent_p) |
783 | { | 807 | { |
784 | struct msghdr msg = { | 808 | struct msghdr msg = { |
785 | .msg_name = addr, | 809 | .msg_name = addr, |
786 | .msg_namelen = addrlen, | 810 | .msg_namelen = addrlen, |
787 | .msg_flags = XS_SENDMSG_FLAGS | MSG_MORE, | 811 | .msg_flags = XS_SENDMSG_FLAGS | MSG_MORE, |
788 | }; | 812 | }; |
789 | unsigned int remainder = xdr->len - base; | 813 | unsigned int rmsize = rm ? sizeof(rm) : 0; |
814 | unsigned int remainder = rmsize + xdr->len - base; | ||
815 | unsigned int want; | ||
790 | int err = 0; | 816 | int err = 0; |
791 | 817 | ||
792 | if (unlikely(!sock)) | 818 | if (unlikely(!sock)) |
793 | return -ENOTSOCK; | 819 | return -ENOTSOCK; |
794 | 820 | ||
795 | if (base < xdr->head[0].iov_len) { | 821 | want = xdr->head[0].iov_len + rmsize; |
796 | unsigned int len = xdr->head[0].iov_len - base; | 822 | if (base < want) { |
823 | unsigned int len = want - base; | ||
797 | remainder -= len; | 824 | remainder -= len; |
798 | if (remainder == 0) | 825 | if (remainder == 0) |
799 | msg.msg_flags &= ~MSG_MORE; | 826 | msg.msg_flags &= ~MSG_MORE; |
800 | err = xs_send_kvec(sock, &msg, &xdr->head[0], base); | 827 | if (rmsize) |
828 | err = xs_send_rm_and_kvec(sock, &msg, rm, | ||
829 | &xdr->head[0], base); | ||
830 | else | ||
831 | err = xs_send_kvec(sock, &msg, &xdr->head[0], base); | ||
801 | if (remainder == 0 || err != len) | 832 | if (remainder == 0 || err != len) |
802 | goto out; | 833 | goto out; |
803 | *sent_p += err; | 834 | *sent_p += err; |
804 | base = 0; | 835 | base = 0; |
805 | } else | 836 | } else |
806 | base -= xdr->head[0].iov_len; | 837 | base -= want; |
807 | 838 | ||
808 | if (base < xdr->page_len) { | 839 | if (base < xdr->page_len) { |
809 | unsigned int len = xdr->page_len - base; | 840 | unsigned int len = xdr->page_len - base; |
@@ -891,13 +922,14 @@ xs_send_request_was_aborted(struct sock_xprt *transport, struct rpc_rqst *req) | |||
891 | } | 922 | } |
892 | 923 | ||
893 | /* | 924 | /* |
894 | * Construct a stream transport record marker in @buf. | 925 | * Return the stream record marker field for a record of length < 2^31-1 |
895 | */ | 926 | */ |
896 | static inline void xs_encode_stream_record_marker(struct xdr_buf *buf) | 927 | static rpc_fraghdr |
928 | xs_stream_record_marker(struct xdr_buf *xdr) | ||
897 | { | 929 | { |
898 | u32 reclen = buf->len - sizeof(rpc_fraghdr); | 930 | if (!xdr->len) |
899 | rpc_fraghdr *base = buf->head[0].iov_base; | 931 | return 0; |
900 | *base = cpu_to_be32(RPC_LAST_STREAM_FRAGMENT | reclen); | 932 | return cpu_to_be32(RPC_LAST_STREAM_FRAGMENT | (u32)xdr->len); |
901 | } | 933 | } |
902 | 934 | ||
903 | /** | 935 | /** |
@@ -926,14 +958,13 @@ static int xs_local_send_request(struct rpc_rqst *req) | |||
926 | return -ENOTCONN; | 958 | return -ENOTCONN; |
927 | } | 959 | } |
928 | 960 | ||
929 | xs_encode_stream_record_marker(&req->rq_snd_buf); | ||
930 | |||
931 | xs_pktdump("packet data:", | 961 | xs_pktdump("packet data:", |
932 | req->rq_svec->iov_base, req->rq_svec->iov_len); | 962 | req->rq_svec->iov_base, req->rq_svec->iov_len); |
933 | 963 | ||
934 | req->rq_xtime = ktime_get(); | 964 | req->rq_xtime = ktime_get(); |
935 | status = xs_sendpages(transport->sock, NULL, 0, xdr, | 965 | status = xs_sendpages(transport->sock, NULL, 0, xdr, |
936 | transport->xmit.offset, | 966 | transport->xmit.offset, |
967 | xs_stream_record_marker(xdr), | ||
937 | &sent); | 968 | &sent); |
938 | dprintk("RPC: %s(%u) = %d\n", | 969 | dprintk("RPC: %s(%u) = %d\n", |
939 | __func__, xdr->len - transport->xmit.offset, status); | 970 | __func__, xdr->len - transport->xmit.offset, status); |
@@ -1001,7 +1032,7 @@ static int xs_udp_send_request(struct rpc_rqst *req) | |||
1001 | 1032 | ||
1002 | req->rq_xtime = ktime_get(); | 1033 | req->rq_xtime = ktime_get(); |
1003 | status = xs_sendpages(transport->sock, xs_addr(xprt), xprt->addrlen, | 1034 | status = xs_sendpages(transport->sock, xs_addr(xprt), xprt->addrlen, |
1004 | xdr, 0, &sent); | 1035 | xdr, 0, 0, &sent); |
1005 | 1036 | ||
1006 | dprintk("RPC: xs_udp_send_request(%u) = %d\n", | 1037 | dprintk("RPC: xs_udp_send_request(%u) = %d\n", |
1007 | xdr->len, status); | 1038 | xdr->len, status); |
@@ -1076,8 +1107,6 @@ static int xs_tcp_send_request(struct rpc_rqst *req) | |||
1076 | return -ENOTCONN; | 1107 | return -ENOTCONN; |
1077 | } | 1108 | } |
1078 | 1109 | ||
1079 | xs_encode_stream_record_marker(&req->rq_snd_buf); | ||
1080 | |||
1081 | xs_pktdump("packet data:", | 1110 | xs_pktdump("packet data:", |
1082 | req->rq_svec->iov_base, | 1111 | req->rq_svec->iov_base, |
1083 | req->rq_svec->iov_len); | 1112 | req->rq_svec->iov_len); |
@@ -1093,6 +1122,7 @@ static int xs_tcp_send_request(struct rpc_rqst *req) | |||
1093 | sent = 0; | 1122 | sent = 0; |
1094 | status = xs_sendpages(transport->sock, NULL, 0, xdr, | 1123 | status = xs_sendpages(transport->sock, NULL, 0, xdr, |
1095 | transport->xmit.offset, | 1124 | transport->xmit.offset, |
1125 | xs_stream_record_marker(xdr), | ||
1096 | &sent); | 1126 | &sent); |
1097 | 1127 | ||
1098 | dprintk("RPC: xs_tcp_send_request(%u) = %d\n", | 1128 | dprintk("RPC: xs_tcp_send_request(%u) = %d\n", |
@@ -2547,26 +2577,35 @@ static int bc_sendto(struct rpc_rqst *req) | |||
2547 | { | 2577 | { |
2548 | int len; | 2578 | int len; |
2549 | struct xdr_buf *xbufp = &req->rq_snd_buf; | 2579 | struct xdr_buf *xbufp = &req->rq_snd_buf; |
2550 | struct rpc_xprt *xprt = req->rq_xprt; | ||
2551 | struct sock_xprt *transport = | 2580 | struct sock_xprt *transport = |
2552 | container_of(xprt, struct sock_xprt, xprt); | 2581 | container_of(req->rq_xprt, struct sock_xprt, xprt); |
2553 | struct socket *sock = transport->sock; | ||
2554 | unsigned long headoff; | 2582 | unsigned long headoff; |
2555 | unsigned long tailoff; | 2583 | unsigned long tailoff; |
2584 | struct page *tailpage; | ||
2585 | struct msghdr msg = { | ||
2586 | .msg_flags = MSG_MORE | ||
2587 | }; | ||
2588 | rpc_fraghdr marker = cpu_to_be32(RPC_LAST_STREAM_FRAGMENT | | ||
2589 | (u32)xbufp->len); | ||
2590 | struct kvec iov = { | ||
2591 | .iov_base = &marker, | ||
2592 | .iov_len = sizeof(marker), | ||
2593 | }; | ||
2556 | 2594 | ||
2557 | xs_encode_stream_record_marker(xbufp); | 2595 | len = kernel_sendmsg(transport->sock, &msg, &iov, 1, iov.iov_len); |
2596 | if (len != iov.iov_len) | ||
2597 | return -EAGAIN; | ||
2558 | 2598 | ||
2599 | tailpage = NULL; | ||
2600 | if (xbufp->tail[0].iov_len) | ||
2601 | tailpage = virt_to_page(xbufp->tail[0].iov_base); | ||
2559 | tailoff = (unsigned long)xbufp->tail[0].iov_base & ~PAGE_MASK; | 2602 | tailoff = (unsigned long)xbufp->tail[0].iov_base & ~PAGE_MASK; |
2560 | headoff = (unsigned long)xbufp->head[0].iov_base & ~PAGE_MASK; | 2603 | headoff = (unsigned long)xbufp->head[0].iov_base & ~PAGE_MASK; |
2561 | len = svc_send_common(sock, xbufp, | 2604 | len = svc_send_common(transport->sock, xbufp, |
2562 | virt_to_page(xbufp->head[0].iov_base), headoff, | 2605 | virt_to_page(xbufp->head[0].iov_base), headoff, |
2563 | xbufp->tail[0].iov_base, tailoff); | 2606 | tailpage, tailoff); |
2564 | 2607 | if (len != xbufp->len) | |
2565 | if (len != xbufp->len) { | 2608 | return -EAGAIN; |
2566 | printk(KERN_NOTICE "Error sending entire callback!\n"); | ||
2567 | len = -EAGAIN; | ||
2568 | } | ||
2569 | |||
2570 | return len; | 2609 | return len; |
2571 | } | 2610 | } |
2572 | 2611 | ||
@@ -2806,7 +2845,6 @@ static struct rpc_xprt *xs_setup_local(struct xprt_create *args) | |||
2806 | transport = container_of(xprt, struct sock_xprt, xprt); | 2845 | transport = container_of(xprt, struct sock_xprt, xprt); |
2807 | 2846 | ||
2808 | xprt->prot = 0; | 2847 | xprt->prot = 0; |
2809 | xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); | ||
2810 | xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; | 2848 | xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; |
2811 | 2849 | ||
2812 | xprt->bind_timeout = XS_BIND_TO; | 2850 | xprt->bind_timeout = XS_BIND_TO; |
@@ -2875,7 +2913,6 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args) | |||
2875 | transport = container_of(xprt, struct sock_xprt, xprt); | 2913 | transport = container_of(xprt, struct sock_xprt, xprt); |
2876 | 2914 | ||
2877 | xprt->prot = IPPROTO_UDP; | 2915 | xprt->prot = IPPROTO_UDP; |
2878 | xprt->tsh_size = 0; | ||
2879 | /* XXX: header size can vary due to auth type, IPv6, etc. */ | 2916 | /* XXX: header size can vary due to auth type, IPv6, etc. */ |
2880 | xprt->max_payload = (1U << 16) - (MAX_HEADER << 3); | 2917 | xprt->max_payload = (1U << 16) - (MAX_HEADER << 3); |
2881 | 2918 | ||
@@ -2955,7 +2992,6 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args) | |||
2955 | transport = container_of(xprt, struct sock_xprt, xprt); | 2992 | transport = container_of(xprt, struct sock_xprt, xprt); |
2956 | 2993 | ||
2957 | xprt->prot = IPPROTO_TCP; | 2994 | xprt->prot = IPPROTO_TCP; |
2958 | xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); | ||
2959 | xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; | 2995 | xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; |
2960 | 2996 | ||
2961 | xprt->bind_timeout = XS_BIND_TO; | 2997 | xprt->bind_timeout = XS_BIND_TO; |
@@ -3028,7 +3064,6 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args) | |||
3028 | transport = container_of(xprt, struct sock_xprt, xprt); | 3064 | transport = container_of(xprt, struct sock_xprt, xprt); |
3029 | 3065 | ||
3030 | xprt->prot = IPPROTO_TCP; | 3066 | xprt->prot = IPPROTO_TCP; |
3031 | xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); | ||
3032 | xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; | 3067 | xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; |
3033 | xprt->timeout = &xs_tcp_default_timeout; | 3068 | xprt->timeout = &xs_tcp_default_timeout; |
3034 | 3069 | ||