.. | .. |
---|
18 | 18 | #include "callback.h" |
---|
19 | 19 | #include "internal.h" |
---|
20 | 20 | #include "nfs4session.h" |
---|
| 21 | +#include "nfs4trace.h" |
---|
21 | 22 | |
---|
22 | 23 | #define CB_OP_TAGLEN_MAXSZ (512) |
---|
23 | 24 | #define CB_OP_HDR_RES_MAXSZ (2 * 4) // opcode, status |
---|
.. | .. |
---|
72 | 73 | return xdr_ressize_check(rqstp, p); |
---|
73 | 74 | } |
---|
74 | 75 | |
---|
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 | 76 | static __be32 decode_string(struct xdr_stream *xdr, unsigned int *len, |
---|
86 | 77 | const char **str, size_t maxlen) |
---|
87 | 78 | { |
---|
.. | .. |
---|
98 | 89 | { |
---|
99 | 90 | __be32 *p; |
---|
100 | 91 | |
---|
101 | | - p = read_buf(xdr, 4); |
---|
| 92 | + p = xdr_inline_decode(xdr, 4); |
---|
102 | 93 | if (unlikely(p == NULL)) |
---|
103 | 94 | return htonl(NFS4ERR_RESOURCE); |
---|
104 | 95 | fh->size = ntohl(*p); |
---|
105 | 96 | if (fh->size > NFS4_FHSIZE) |
---|
106 | 97 | return htonl(NFS4ERR_BADHANDLE); |
---|
107 | | - p = read_buf(xdr, fh->size); |
---|
| 98 | + p = xdr_inline_decode(xdr, fh->size); |
---|
108 | 99 | if (unlikely(p == NULL)) |
---|
109 | 100 | return htonl(NFS4ERR_RESOURCE); |
---|
110 | 101 | memcpy(&fh->data[0], p, fh->size); |
---|
.. | .. |
---|
117 | 108 | __be32 *p; |
---|
118 | 109 | unsigned int attrlen; |
---|
119 | 110 | |
---|
120 | | - p = read_buf(xdr, 4); |
---|
| 111 | + p = xdr_inline_decode(xdr, 4); |
---|
121 | 112 | if (unlikely(p == NULL)) |
---|
122 | 113 | return htonl(NFS4ERR_RESOURCE); |
---|
123 | 114 | attrlen = ntohl(*p); |
---|
124 | | - p = read_buf(xdr, attrlen << 2); |
---|
| 115 | + p = xdr_inline_decode(xdr, attrlen << 2); |
---|
125 | 116 | if (unlikely(p == NULL)) |
---|
126 | 117 | return htonl(NFS4ERR_RESOURCE); |
---|
127 | 118 | if (likely(attrlen > 0)) |
---|
.. | .. |
---|
135 | 126 | { |
---|
136 | 127 | __be32 *p; |
---|
137 | 128 | |
---|
138 | | - p = read_buf(xdr, NFS4_STATEID_SIZE); |
---|
| 129 | + p = xdr_inline_decode(xdr, NFS4_STATEID_SIZE); |
---|
139 | 130 | if (unlikely(p == NULL)) |
---|
140 | 131 | return htonl(NFS4ERR_RESOURCE); |
---|
141 | 132 | memcpy(stateid->data, p, NFS4_STATEID_SIZE); |
---|
.. | .. |
---|
156 | 147 | status = decode_string(xdr, &hdr->taglen, &hdr->tag, CB_OP_TAGLEN_MAXSZ); |
---|
157 | 148 | if (unlikely(status != 0)) |
---|
158 | 149 | return status; |
---|
159 | | - p = read_buf(xdr, 12); |
---|
| 150 | + p = xdr_inline_decode(xdr, 12); |
---|
160 | 151 | if (unlikely(p == NULL)) |
---|
161 | 152 | return htonl(NFS4ERR_RESOURCE); |
---|
162 | 153 | hdr->minorversion = ntohl(*p++); |
---|
.. | .. |
---|
176 | 167 | static __be32 decode_op_hdr(struct xdr_stream *xdr, unsigned int *op) |
---|
177 | 168 | { |
---|
178 | 169 | __be32 *p; |
---|
179 | | - p = read_buf(xdr, 4); |
---|
| 170 | + p = xdr_inline_decode(xdr, 4); |
---|
180 | 171 | if (unlikely(p == NULL)) |
---|
181 | 172 | return htonl(NFS4ERR_RESOURCE_HDR); |
---|
182 | 173 | *op = ntohl(*p); |
---|
.. | .. |
---|
205 | 196 | status = decode_delegation_stateid(xdr, &args->stateid); |
---|
206 | 197 | if (unlikely(status != 0)) |
---|
207 | 198 | return status; |
---|
208 | | - p = read_buf(xdr, 4); |
---|
| 199 | + p = xdr_inline_decode(xdr, 4); |
---|
209 | 200 | if (unlikely(p == NULL)) |
---|
210 | 201 | return htonl(NFS4ERR_RESOURCE); |
---|
211 | 202 | args->truncate = ntohl(*p); |
---|
.. | .. |
---|
227 | 218 | __be32 status = 0; |
---|
228 | 219 | uint32_t iomode; |
---|
229 | 220 | |
---|
230 | | - p = read_buf(xdr, 4 * sizeof(uint32_t)); |
---|
| 221 | + p = xdr_inline_decode(xdr, 4 * sizeof(uint32_t)); |
---|
231 | 222 | if (unlikely(p == NULL)) |
---|
232 | 223 | return htonl(NFS4ERR_BADXDR); |
---|
233 | 224 | |
---|
.. | .. |
---|
245 | 236 | if (unlikely(status != 0)) |
---|
246 | 237 | return status; |
---|
247 | 238 | |
---|
248 | | - p = read_buf(xdr, 2 * sizeof(uint64_t)); |
---|
| 239 | + p = xdr_inline_decode(xdr, 2 * sizeof(uint64_t)); |
---|
249 | 240 | if (unlikely(p == NULL)) |
---|
250 | 241 | return htonl(NFS4ERR_BADXDR); |
---|
251 | 242 | p = xdr_decode_hyper(p, &args->cbl_range.offset); |
---|
252 | 243 | p = xdr_decode_hyper(p, &args->cbl_range.length); |
---|
253 | 244 | return decode_layout_stateid(xdr, &args->cbl_stateid); |
---|
254 | 245 | } else if (args->cbl_recall_type == RETURN_FSID) { |
---|
255 | | - p = read_buf(xdr, 2 * sizeof(uint64_t)); |
---|
| 246 | + p = xdr_inline_decode(xdr, 2 * sizeof(uint64_t)); |
---|
256 | 247 | if (unlikely(p == NULL)) |
---|
257 | 248 | return htonl(NFS4ERR_BADXDR); |
---|
258 | 249 | p = xdr_decode_hyper(p, &args->cbl_fsid.major); |
---|
.. | .. |
---|
273 | 264 | __be32 status = 0; |
---|
274 | 265 | |
---|
275 | 266 | /* Num of device notifications */ |
---|
276 | | - p = read_buf(xdr, sizeof(uint32_t)); |
---|
| 267 | + p = xdr_inline_decode(xdr, sizeof(uint32_t)); |
---|
277 | 268 | if (unlikely(p == NULL)) { |
---|
278 | 269 | status = htonl(NFS4ERR_BADXDR); |
---|
279 | 270 | goto out; |
---|
.. | .. |
---|
281 | 272 | n = ntohl(*p++); |
---|
282 | 273 | if (n == 0) |
---|
283 | 274 | goto out; |
---|
284 | | - if (n > ULONG_MAX / sizeof(*args->devs)) { |
---|
285 | | - status = htonl(NFS4ERR_BADXDR); |
---|
286 | | - goto out; |
---|
287 | | - } |
---|
288 | 275 | |
---|
289 | 276 | args->devs = kmalloc_array(n, sizeof(*args->devs), GFP_KERNEL); |
---|
290 | 277 | if (!args->devs) { |
---|
.. | .. |
---|
296 | 283 | for (i = 0; i < n; i++) { |
---|
297 | 284 | struct cb_devicenotifyitem *dev = &args->devs[i]; |
---|
298 | 285 | |
---|
299 | | - p = read_buf(xdr, (4 * sizeof(uint32_t)) + NFS4_DEVICEID4_SIZE); |
---|
| 286 | + p = xdr_inline_decode(xdr, (4 * sizeof(uint32_t)) + |
---|
| 287 | + NFS4_DEVICEID4_SIZE); |
---|
300 | 288 | if (unlikely(p == NULL)) { |
---|
301 | 289 | status = htonl(NFS4ERR_BADXDR); |
---|
302 | 290 | goto err; |
---|
.. | .. |
---|
327 | 315 | p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE); |
---|
328 | 316 | |
---|
329 | 317 | if (dev->cbd_layout_type == NOTIFY_DEVICEID4_CHANGE) { |
---|
330 | | - p = read_buf(xdr, sizeof(uint32_t)); |
---|
| 318 | + p = xdr_inline_decode(xdr, sizeof(uint32_t)); |
---|
331 | 319 | if (unlikely(p == NULL)) { |
---|
332 | 320 | status = htonl(NFS4ERR_BADXDR); |
---|
333 | 321 | goto err; |
---|
.. | .. |
---|
359 | 347 | { |
---|
360 | 348 | __be32 *p; |
---|
361 | 349 | |
---|
362 | | - p = read_buf(xdr, NFS4_MAX_SESSIONID_LEN); |
---|
| 350 | + p = xdr_inline_decode(xdr, NFS4_MAX_SESSIONID_LEN); |
---|
363 | 351 | if (unlikely(p == NULL)) |
---|
364 | 352 | return htonl(NFS4ERR_RESOURCE); |
---|
365 | 353 | |
---|
.. | .. |
---|
379 | 367 | goto out; |
---|
380 | 368 | |
---|
381 | 369 | status = htonl(NFS4ERR_RESOURCE); |
---|
382 | | - p = read_buf(xdr, sizeof(uint32_t)); |
---|
| 370 | + p = xdr_inline_decode(xdr, sizeof(uint32_t)); |
---|
383 | 371 | if (unlikely(p == NULL)) |
---|
384 | 372 | goto out; |
---|
385 | 373 | |
---|
386 | 374 | rc_list->rcl_nrefcalls = ntohl(*p++); |
---|
387 | 375 | if (rc_list->rcl_nrefcalls) { |
---|
388 | | - p = read_buf(xdr, |
---|
| 376 | + p = xdr_inline_decode(xdr, |
---|
389 | 377 | rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t)); |
---|
390 | 378 | if (unlikely(p == NULL)) |
---|
391 | 379 | goto out; |
---|
.. | .. |
---|
418 | 406 | if (status) |
---|
419 | 407 | return status; |
---|
420 | 408 | |
---|
421 | | - p = read_buf(xdr, 5 * sizeof(uint32_t)); |
---|
| 409 | + p = xdr_inline_decode(xdr, 5 * sizeof(uint32_t)); |
---|
422 | 410 | if (unlikely(p == NULL)) |
---|
423 | 411 | return htonl(NFS4ERR_RESOURCE); |
---|
424 | 412 | |
---|
.. | .. |
---|
461 | 449 | uint32_t bitmap[2]; |
---|
462 | 450 | __be32 *p, status; |
---|
463 | 451 | |
---|
464 | | - p = read_buf(xdr, 4); |
---|
| 452 | + p = xdr_inline_decode(xdr, 4); |
---|
465 | 453 | if (unlikely(p == NULL)) |
---|
466 | 454 | return htonl(NFS4ERR_BADXDR); |
---|
467 | 455 | args->craa_objs_to_keep = ntohl(*p++); |
---|
.. | .. |
---|
480 | 468 | struct cb_recallslotargs *args = argp; |
---|
481 | 469 | __be32 *p; |
---|
482 | 470 | |
---|
483 | | - p = read_buf(xdr, 4); |
---|
| 471 | + p = xdr_inline_decode(xdr, 4); |
---|
484 | 472 | if (unlikely(p == NULL)) |
---|
485 | 473 | return htonl(NFS4ERR_BADXDR); |
---|
486 | 474 | args->crsa_target_highest_slotid = ntohl(*p++); |
---|
.. | .. |
---|
492 | 480 | __be32 *p; |
---|
493 | 481 | unsigned int len; |
---|
494 | 482 | |
---|
495 | | - p = read_buf(xdr, 12); |
---|
| 483 | + p = xdr_inline_decode(xdr, 12); |
---|
496 | 484 | if (unlikely(p == NULL)) |
---|
497 | 485 | return htonl(NFS4ERR_BADXDR); |
---|
498 | 486 | |
---|
499 | 487 | p = xdr_decode_hyper(p, &args->cbnl_owner.clientid); |
---|
500 | 488 | len = be32_to_cpu(*p); |
---|
501 | 489 | |
---|
502 | | - p = read_buf(xdr, len); |
---|
| 490 | + p = xdr_inline_decode(xdr, len); |
---|
503 | 491 | if (unlikely(p == NULL)) |
---|
504 | 492 | return htonl(NFS4ERR_BADXDR); |
---|
505 | 493 | |
---|
.. | .. |
---|
537 | 525 | __be32 *p; |
---|
538 | 526 | |
---|
539 | 527 | /* skip the always zero field */ |
---|
540 | | - p = read_buf(xdr, 4); |
---|
| 528 | + p = xdr_inline_decode(xdr, 4); |
---|
541 | 529 | if (unlikely(!p)) |
---|
542 | 530 | goto out; |
---|
543 | 531 | p++; |
---|
.. | .. |
---|
577 | 565 | return status; |
---|
578 | 566 | |
---|
579 | 567 | /* decode status */ |
---|
580 | | - p = read_buf(xdr, 4); |
---|
| 568 | + p = xdr_inline_decode(xdr, 4); |
---|
581 | 569 | if (unlikely(!p)) |
---|
582 | 570 | goto out; |
---|
583 | 571 | args->error = ntohl(*p++); |
---|
.. | .. |
---|
636 | 624 | return 0; |
---|
637 | 625 | } |
---|
638 | 626 | |
---|
639 | | -static __be32 encode_attr_time(struct xdr_stream *xdr, const struct timespec *time) |
---|
| 627 | +static __be32 encode_attr_time(struct xdr_stream *xdr, const struct timespec64 *time) |
---|
640 | 628 | { |
---|
641 | 629 | __be32 *p; |
---|
642 | 630 | |
---|
.. | .. |
---|
648 | 636 | return 0; |
---|
649 | 637 | } |
---|
650 | 638 | |
---|
651 | | -static __be32 encode_attr_ctime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec *time) |
---|
| 639 | +static __be32 encode_attr_ctime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec64 *time) |
---|
652 | 640 | { |
---|
653 | 641 | if (!(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) |
---|
654 | 642 | return 0; |
---|
655 | 643 | return encode_attr_time(xdr,time); |
---|
656 | 644 | } |
---|
657 | 645 | |
---|
658 | | -static __be32 encode_attr_mtime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec *time) |
---|
| 646 | +static __be32 encode_attr_mtime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec64 *time) |
---|
659 | 647 | { |
---|
660 | 648 | if (!(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) |
---|
661 | 649 | return 0; |
---|
.. | .. |
---|
943 | 931 | }; |
---|
944 | 932 | unsigned int nops = 0; |
---|
945 | 933 | |
---|
946 | | - xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base); |
---|
| 934 | + xdr_init_decode(&xdr_in, &rqstp->rq_arg, |
---|
| 935 | + rqstp->rq_arg.head[0].iov_base, NULL); |
---|
947 | 936 | |
---|
948 | 937 | 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); |
---|
| 938 | + xdr_init_encode(&xdr_out, &rqstp->rq_res, p, NULL); |
---|
950 | 939 | |
---|
951 | 940 | status = decode_compound_hdr_arg(&xdr_in, &hdr_arg); |
---|
952 | 941 | if (status == htonl(NFS4ERR_RESOURCE)) |
---|
.. | .. |
---|
954 | 943 | |
---|
955 | 944 | if (hdr_arg.minorversion == 0) { |
---|
956 | 945 | cps.clp = nfs4_find_client_ident(SVC_NET(rqstp), hdr_arg.cb_ident); |
---|
957 | | - if (!cps.clp || !check_gss_callback_principal(cps.clp, rqstp)) { |
---|
958 | | - if (cps.clp) |
---|
959 | | - nfs_put_client(cps.clp); |
---|
| 946 | + if (!cps.clp) { |
---|
| 947 | + trace_nfs_cb_no_clp(rqstp->rq_xid, hdr_arg.cb_ident); |
---|
| 948 | + goto out_invalidcred; |
---|
| 949 | + } |
---|
| 950 | + if (!check_gss_callback_principal(cps.clp, rqstp)) { |
---|
| 951 | + trace_nfs_cb_badprinc(rqstp->rq_xid, hdr_arg.cb_ident); |
---|
| 952 | + nfs_put_client(cps.clp); |
---|
960 | 953 | goto out_invalidcred; |
---|
961 | 954 | } |
---|
962 | 955 | } |
---|