diff options
| author | Trond Myklebust <trondmy@gmail.com> | 2019-04-24 17:46:48 -0400 |
|---|---|---|
| committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2019-04-26 17:26:37 -0400 |
| commit | c207db2f5da5e37e284d87d5196dcf967e84956c (patch) | |
| tree | c0194606b5c853b3ecd1376b8d946f61714d021d | |
| parent | 58002399da65c53f00987623d9ff7c3c2773a0d9 (diff) | |
NFS: Convert NFSv2 to use the container user namespace
When mapping NFS identities, we want to substitute for the uids and
gids on the wire as we would for the AUTH_UNIX creds.
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
| -rw-r--r-- | fs/nfs/nfs2xdr.c | 58 |
1 files changed, 39 insertions, 19 deletions
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index a7ed29de0a40..572794dab4b1 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c | |||
| @@ -76,6 +76,20 @@ static int nfs_stat_to_errno(enum nfs_stat); | |||
| 76 | * or decoded inline. | 76 | * or decoded inline. |
| 77 | */ | 77 | */ |
| 78 | 78 | ||
| 79 | static struct user_namespace *rpc_userns(const struct rpc_clnt *clnt) | ||
| 80 | { | ||
| 81 | if (clnt && clnt->cl_cred) | ||
| 82 | return clnt->cl_cred->user_ns; | ||
| 83 | return &init_user_ns; | ||
| 84 | } | ||
| 85 | |||
| 86 | static struct user_namespace *rpc_rqst_userns(const struct rpc_rqst *rqstp) | ||
| 87 | { | ||
| 88 | if (rqstp->rq_task) | ||
| 89 | return rpc_userns(rqstp->rq_task->tk_client); | ||
| 90 | return &init_user_ns; | ||
| 91 | } | ||
| 92 | |||
| 79 | /* | 93 | /* |
| 80 | * typedef opaque nfsdata<>; | 94 | * typedef opaque nfsdata<>; |
| 81 | */ | 95 | */ |
| @@ -248,7 +262,8 @@ static __be32 *xdr_decode_time(__be32 *p, struct timespec *timep) | |||
| 248 | * }; | 262 | * }; |
| 249 | * | 263 | * |
| 250 | */ | 264 | */ |
| 251 | static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr) | 265 | static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, |
| 266 | struct user_namespace *userns) | ||
| 252 | { | 267 | { |
| 253 | u32 rdev, type; | 268 | u32 rdev, type; |
| 254 | __be32 *p; | 269 | __be32 *p; |
| @@ -263,10 +278,10 @@ static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr) | |||
| 263 | 278 | ||
| 264 | fattr->mode = be32_to_cpup(p++); | 279 | fattr->mode = be32_to_cpup(p++); |
| 265 | fattr->nlink = be32_to_cpup(p++); | 280 | fattr->nlink = be32_to_cpup(p++); |
| 266 | fattr->uid = make_kuid(&init_user_ns, be32_to_cpup(p++)); | 281 | fattr->uid = make_kuid(userns, be32_to_cpup(p++)); |
| 267 | if (!uid_valid(fattr->uid)) | 282 | if (!uid_valid(fattr->uid)) |
| 268 | goto out_uid; | 283 | goto out_uid; |
| 269 | fattr->gid = make_kgid(&init_user_ns, be32_to_cpup(p++)); | 284 | fattr->gid = make_kgid(userns, be32_to_cpup(p++)); |
| 270 | if (!gid_valid(fattr->gid)) | 285 | if (!gid_valid(fattr->gid)) |
| 271 | goto out_gid; | 286 | goto out_gid; |
| 272 | 287 | ||
| @@ -321,7 +336,8 @@ static __be32 *xdr_time_not_set(__be32 *p) | |||
| 321 | return p; | 336 | return p; |
| 322 | } | 337 | } |
| 323 | 338 | ||
| 324 | static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr) | 339 | static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr, |
| 340 | struct user_namespace *userns) | ||
| 325 | { | 341 | { |
| 326 | struct timespec ts; | 342 | struct timespec ts; |
| 327 | __be32 *p; | 343 | __be32 *p; |
| @@ -333,11 +349,11 @@ static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr) | |||
| 333 | else | 349 | else |
| 334 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); | 350 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); |
| 335 | if (attr->ia_valid & ATTR_UID) | 351 | if (attr->ia_valid & ATTR_UID) |
| 336 | *p++ = cpu_to_be32(from_kuid(&init_user_ns, attr->ia_uid)); | 352 | *p++ = cpu_to_be32(from_kuid_munged(userns, attr->ia_uid)); |
| 337 | else | 353 | else |
| 338 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); | 354 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); |
| 339 | if (attr->ia_valid & ATTR_GID) | 355 | if (attr->ia_valid & ATTR_GID) |
| 340 | *p++ = cpu_to_be32(from_kgid(&init_user_ns, attr->ia_gid)); | 356 | *p++ = cpu_to_be32(from_kgid_munged(userns, attr->ia_gid)); |
| 341 | else | 357 | else |
| 342 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); | 358 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); |
| 343 | if (attr->ia_valid & ATTR_SIZE) | 359 | if (attr->ia_valid & ATTR_SIZE) |
| @@ -451,7 +467,8 @@ out_cheating: | |||
| 451 | * }; | 467 | * }; |
| 452 | */ | 468 | */ |
| 453 | static int decode_attrstat(struct xdr_stream *xdr, struct nfs_fattr *result, | 469 | static int decode_attrstat(struct xdr_stream *xdr, struct nfs_fattr *result, |
| 454 | __u32 *op_status) | 470 | __u32 *op_status, |
| 471 | struct user_namespace *userns) | ||
| 455 | { | 472 | { |
| 456 | enum nfs_stat status; | 473 | enum nfs_stat status; |
| 457 | int error; | 474 | int error; |
| @@ -463,7 +480,7 @@ static int decode_attrstat(struct xdr_stream *xdr, struct nfs_fattr *result, | |||
| 463 | *op_status = status; | 480 | *op_status = status; |
| 464 | if (status != NFS_OK) | 481 | if (status != NFS_OK) |
| 465 | goto out_default; | 482 | goto out_default; |
| 466 | error = decode_fattr(xdr, result); | 483 | error = decode_fattr(xdr, result, userns); |
| 467 | out: | 484 | out: |
| 468 | return error; | 485 | return error; |
| 469 | out_default: | 486 | out_default: |
| @@ -498,19 +515,21 @@ static void encode_diropargs(struct xdr_stream *xdr, const struct nfs_fh *fh, | |||
| 498 | * void; | 515 | * void; |
| 499 | * }; | 516 | * }; |
| 500 | */ | 517 | */ |
| 501 | static int decode_diropok(struct xdr_stream *xdr, struct nfs_diropok *result) | 518 | static int decode_diropok(struct xdr_stream *xdr, struct nfs_diropok *result, |
| 519 | struct user_namespace *userns) | ||
| 502 | { | 520 | { |
| 503 | int error; | 521 | int error; |
| 504 | 522 | ||
| 505 | error = decode_fhandle(xdr, result->fh); | 523 | error = decode_fhandle(xdr, result->fh); |
| 506 | if (unlikely(error)) | 524 | if (unlikely(error)) |
| 507 | goto out; | 525 | goto out; |
| 508 | error = decode_fattr(xdr, result->fattr); | 526 | error = decode_fattr(xdr, result->fattr, userns); |
| 509 | out: | 527 | out: |
| 510 | return error; | 528 | return error; |
| 511 | } | 529 | } |
| 512 | 530 | ||
| 513 | static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result) | 531 | static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result, |
| 532 | struct user_namespace *userns) | ||
| 514 | { | 533 | { |
| 515 | enum nfs_stat status; | 534 | enum nfs_stat status; |
| 516 | int error; | 535 | int error; |
| @@ -520,7 +539,7 @@ static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result) | |||
| 520 | goto out; | 539 | goto out; |
| 521 | if (status != NFS_OK) | 540 | if (status != NFS_OK) |
| 522 | goto out_default; | 541 | goto out_default; |
| 523 | error = decode_diropok(xdr, result); | 542 | error = decode_diropok(xdr, result, userns); |
| 524 | out: | 543 | out: |
| 525 | return error; | 544 | return error; |
| 526 | out_default: | 545 | out_default: |
| @@ -559,7 +578,7 @@ static void nfs2_xdr_enc_sattrargs(struct rpc_rqst *req, | |||
| 559 | const struct nfs_sattrargs *args = data; | 578 | const struct nfs_sattrargs *args = data; |
| 560 | 579 | ||
| 561 | encode_fhandle(xdr, args->fh); | 580 | encode_fhandle(xdr, args->fh); |
| 562 | encode_sattr(xdr, args->sattr); | 581 | encode_sattr(xdr, args->sattr, rpc_rqst_userns(req)); |
| 563 | } | 582 | } |
| 564 | 583 | ||
| 565 | static void nfs2_xdr_enc_diropargs(struct rpc_rqst *req, | 584 | static void nfs2_xdr_enc_diropargs(struct rpc_rqst *req, |
| @@ -674,7 +693,7 @@ static void nfs2_xdr_enc_createargs(struct rpc_rqst *req, | |||
| 674 | const struct nfs_createargs *args = data; | 693 | const struct nfs_createargs *args = data; |
| 675 | 694 | ||
| 676 | encode_diropargs(xdr, args->fh, args->name, args->len); | 695 | encode_diropargs(xdr, args->fh, args->name, args->len); |
| 677 | encode_sattr(xdr, args->sattr); | 696 | encode_sattr(xdr, args->sattr, rpc_rqst_userns(req)); |
| 678 | } | 697 | } |
| 679 | 698 | ||
| 680 | static void nfs2_xdr_enc_removeargs(struct rpc_rqst *req, | 699 | static void nfs2_xdr_enc_removeargs(struct rpc_rqst *req, |
| @@ -741,7 +760,7 @@ static void nfs2_xdr_enc_symlinkargs(struct rpc_rqst *req, | |||
| 741 | 760 | ||
| 742 | encode_diropargs(xdr, args->fromfh, args->fromname, args->fromlen); | 761 | encode_diropargs(xdr, args->fromfh, args->fromname, args->fromlen); |
| 743 | encode_path(xdr, args->pages, args->pathlen); | 762 | encode_path(xdr, args->pages, args->pathlen); |
| 744 | encode_sattr(xdr, args->sattr); | 763 | encode_sattr(xdr, args->sattr, rpc_rqst_userns(req)); |
| 745 | } | 764 | } |
| 746 | 765 | ||
| 747 | /* | 766 | /* |
| @@ -803,13 +822,13 @@ out_default: | |||
| 803 | static int nfs2_xdr_dec_attrstat(struct rpc_rqst *req, struct xdr_stream *xdr, | 822 | static int nfs2_xdr_dec_attrstat(struct rpc_rqst *req, struct xdr_stream *xdr, |
| 804 | void *result) | 823 | void *result) |
| 805 | { | 824 | { |
| 806 | return decode_attrstat(xdr, result, NULL); | 825 | return decode_attrstat(xdr, result, NULL, rpc_rqst_userns(req)); |
| 807 | } | 826 | } |
| 808 | 827 | ||
| 809 | static int nfs2_xdr_dec_diropres(struct rpc_rqst *req, struct xdr_stream *xdr, | 828 | static int nfs2_xdr_dec_diropres(struct rpc_rqst *req, struct xdr_stream *xdr, |
| 810 | void *result) | 829 | void *result) |
| 811 | { | 830 | { |
| 812 | return decode_diropres(xdr, result); | 831 | return decode_diropres(xdr, result, rpc_rqst_userns(req)); |
| 813 | } | 832 | } |
| 814 | 833 | ||
| 815 | /* | 834 | /* |
| @@ -864,7 +883,7 @@ static int nfs2_xdr_dec_readres(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
| 864 | result->op_status = status; | 883 | result->op_status = status; |
| 865 | if (status != NFS_OK) | 884 | if (status != NFS_OK) |
| 866 | goto out_default; | 885 | goto out_default; |
| 867 | error = decode_fattr(xdr, result->fattr); | 886 | error = decode_fattr(xdr, result->fattr, rpc_rqst_userns(req)); |
| 868 | if (unlikely(error)) | 887 | if (unlikely(error)) |
| 869 | goto out; | 888 | goto out; |
| 870 | error = decode_nfsdata(xdr, result); | 889 | error = decode_nfsdata(xdr, result); |
| @@ -881,7 +900,8 @@ static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
| 881 | 900 | ||
| 882 | /* All NFSv2 writes are "file sync" writes */ | 901 | /* All NFSv2 writes are "file sync" writes */ |
| 883 | result->verf->committed = NFS_FILE_SYNC; | 902 | result->verf->committed = NFS_FILE_SYNC; |
| 884 | return decode_attrstat(xdr, result->fattr, &result->op_status); | 903 | return decode_attrstat(xdr, result->fattr, &result->op_status, |
| 904 | rpc_rqst_userns(req)); | ||
| 885 | } | 905 | } |
| 886 | 906 | ||
| 887 | /** | 907 | /** |
