| .. | .. | 
|---|
| 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 | } | 
|---|