diff options
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 109 |
1 files changed, 34 insertions, 75 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 2502951714b1..6cd86e0fe450 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -344,10 +344,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, | |||
344 | all 32 bits of 'nseconds'. */ | 344 | all 32 bits of 'nseconds'. */ |
345 | READ_BUF(12); | 345 | READ_BUF(12); |
346 | len += 12; | 346 | len += 12; |
347 | READ32(dummy32); | 347 | READ64(iattr->ia_atime.tv_sec); |
348 | if (dummy32) | ||
349 | return nfserr_inval; | ||
350 | READ32(iattr->ia_atime.tv_sec); | ||
351 | READ32(iattr->ia_atime.tv_nsec); | 348 | READ32(iattr->ia_atime.tv_nsec); |
352 | if (iattr->ia_atime.tv_nsec >= (u32)1000000000) | 349 | if (iattr->ia_atime.tv_nsec >= (u32)1000000000) |
353 | return nfserr_inval; | 350 | return nfserr_inval; |
@@ -370,10 +367,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, | |||
370 | all 32 bits of 'nseconds'. */ | 367 | all 32 bits of 'nseconds'. */ |
371 | READ_BUF(12); | 368 | READ_BUF(12); |
372 | len += 12; | 369 | len += 12; |
373 | READ32(dummy32); | 370 | READ64(iattr->ia_mtime.tv_sec); |
374 | if (dummy32) | ||
375 | return nfserr_inval; | ||
376 | READ32(iattr->ia_mtime.tv_sec); | ||
377 | READ32(iattr->ia_mtime.tv_nsec); | 371 | READ32(iattr->ia_mtime.tv_nsec); |
378 | if (iattr->ia_mtime.tv_nsec >= (u32)1000000000) | 372 | if (iattr->ia_mtime.tv_nsec >= (u32)1000000000) |
379 | return nfserr_inval; | 373 | return nfserr_inval; |
@@ -804,6 +798,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) | |||
804 | open->op_iattr.ia_valid = 0; | 798 | open->op_iattr.ia_valid = 0; |
805 | open->op_openowner = NULL; | 799 | open->op_openowner = NULL; |
806 | 800 | ||
801 | open->op_xdr_error = 0; | ||
807 | /* seqid, share_access, share_deny, clientid, ownerlen */ | 802 | /* seqid, share_access, share_deny, clientid, ownerlen */ |
808 | READ_BUF(4); | 803 | READ_BUF(4); |
809 | READ32(open->op_seqid); | 804 | READ32(open->op_seqid); |
@@ -1692,36 +1687,6 @@ static void write_cinfo(__be32 **p, struct nfsd4_change_info *c) | |||
1692 | } while (0) | 1687 | } while (0) |
1693 | #define ADJUST_ARGS() resp->p = p | 1688 | #define ADJUST_ARGS() resp->p = p |
1694 | 1689 | ||
1695 | /* | ||
1696 | * Header routine to setup seqid operation replay cache | ||
1697 | */ | ||
1698 | #define ENCODE_SEQID_OP_HEAD \ | ||
1699 | __be32 *save; \ | ||
1700 | \ | ||
1701 | save = resp->p; | ||
1702 | |||
1703 | /* | ||
1704 | * Routine for encoding the result of a "seqid-mutating" NFSv4 operation. This | ||
1705 | * is where sequence id's are incremented, and the replay cache is filled. | ||
1706 | * Note that we increment sequence id's here, at the last moment, so we're sure | ||
1707 | * we know whether the error to be returned is a sequence id mutating error. | ||
1708 | */ | ||
1709 | |||
1710 | static void encode_seqid_op_tail(struct nfsd4_compoundres *resp, __be32 *save, __be32 nfserr) | ||
1711 | { | ||
1712 | struct nfs4_stateowner *stateowner = resp->cstate.replay_owner; | ||
1713 | |||
1714 | if (seqid_mutating_err(ntohl(nfserr)) && stateowner) { | ||
1715 | stateowner->so_seqid++; | ||
1716 | stateowner->so_replay.rp_status = nfserr; | ||
1717 | stateowner->so_replay.rp_buflen = | ||
1718 | (char *)resp->p - (char *)save; | ||
1719 | memcpy(stateowner->so_replay.rp_buf, save, | ||
1720 | stateowner->so_replay.rp_buflen); | ||
1721 | nfsd4_purge_closed_stateid(stateowner); | ||
1722 | } | ||
1723 | } | ||
1724 | |||
1725 | /* Encode as an array of strings the string given with components | 1690 | /* Encode as an array of strings the string given with components |
1726 | * separated @sep, escaped with esc_enter and esc_exit. | 1691 | * separated @sep, escaped with esc_enter and esc_exit. |
1727 | */ | 1692 | */ |
@@ -2401,8 +2366,7 @@ out_acl: | |||
2401 | if (bmval1 & FATTR4_WORD1_TIME_ACCESS) { | 2366 | if (bmval1 & FATTR4_WORD1_TIME_ACCESS) { |
2402 | if ((buflen -= 12) < 0) | 2367 | if ((buflen -= 12) < 0) |
2403 | goto out_resource; | 2368 | goto out_resource; |
2404 | WRITE32(0); | 2369 | WRITE64((s64)stat.atime.tv_sec); |
2405 | WRITE32(stat.atime.tv_sec); | ||
2406 | WRITE32(stat.atime.tv_nsec); | 2370 | WRITE32(stat.atime.tv_nsec); |
2407 | } | 2371 | } |
2408 | if (bmval1 & FATTR4_WORD1_TIME_DELTA) { | 2372 | if (bmval1 & FATTR4_WORD1_TIME_DELTA) { |
@@ -2415,15 +2379,13 @@ out_acl: | |||
2415 | if (bmval1 & FATTR4_WORD1_TIME_METADATA) { | 2379 | if (bmval1 & FATTR4_WORD1_TIME_METADATA) { |
2416 | if ((buflen -= 12) < 0) | 2380 | if ((buflen -= 12) < 0) |
2417 | goto out_resource; | 2381 | goto out_resource; |
2418 | WRITE32(0); | 2382 | WRITE64((s64)stat.ctime.tv_sec); |
2419 | WRITE32(stat.ctime.tv_sec); | ||
2420 | WRITE32(stat.ctime.tv_nsec); | 2383 | WRITE32(stat.ctime.tv_nsec); |
2421 | } | 2384 | } |
2422 | if (bmval1 & FATTR4_WORD1_TIME_MODIFY) { | 2385 | if (bmval1 & FATTR4_WORD1_TIME_MODIFY) { |
2423 | if ((buflen -= 12) < 0) | 2386 | if ((buflen -= 12) < 0) |
2424 | goto out_resource; | 2387 | goto out_resource; |
2425 | WRITE32(0); | 2388 | WRITE64((s64)stat.mtime.tv_sec); |
2426 | WRITE32(stat.mtime.tv_sec); | ||
2427 | WRITE32(stat.mtime.tv_nsec); | 2389 | WRITE32(stat.mtime.tv_nsec); |
2428 | } | 2390 | } |
2429 | if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { | 2391 | if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { |
@@ -2661,12 +2623,9 @@ static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, | |||
2661 | static __be32 | 2623 | static __be32 |
2662 | nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close) | 2624 | nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close) |
2663 | { | 2625 | { |
2664 | ENCODE_SEQID_OP_HEAD; | ||
2665 | |||
2666 | if (!nfserr) | 2626 | if (!nfserr) |
2667 | nfsd4_encode_stateid(resp, &close->cl_stateid); | 2627 | nfsd4_encode_stateid(resp, &close->cl_stateid); |
2668 | 2628 | ||
2669 | encode_seqid_op_tail(resp, save, nfserr); | ||
2670 | return nfserr; | 2629 | return nfserr; |
2671 | } | 2630 | } |
2672 | 2631 | ||
@@ -2762,14 +2721,11 @@ nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denie | |||
2762 | static __be32 | 2721 | static __be32 |
2763 | nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock) | 2722 | nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock) |
2764 | { | 2723 | { |
2765 | ENCODE_SEQID_OP_HEAD; | ||
2766 | |||
2767 | if (!nfserr) | 2724 | if (!nfserr) |
2768 | nfsd4_encode_stateid(resp, &lock->lk_resp_stateid); | 2725 | nfsd4_encode_stateid(resp, &lock->lk_resp_stateid); |
2769 | else if (nfserr == nfserr_denied) | 2726 | else if (nfserr == nfserr_denied) |
2770 | nfsd4_encode_lock_denied(resp, &lock->lk_denied); | 2727 | nfsd4_encode_lock_denied(resp, &lock->lk_denied); |
2771 | 2728 | ||
2772 | encode_seqid_op_tail(resp, save, nfserr); | ||
2773 | return nfserr; | 2729 | return nfserr; |
2774 | } | 2730 | } |
2775 | 2731 | ||
@@ -2784,12 +2740,9 @@ nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_l | |||
2784 | static __be32 | 2740 | static __be32 |
2785 | nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku) | 2741 | nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku) |
2786 | { | 2742 | { |
2787 | ENCODE_SEQID_OP_HEAD; | ||
2788 | |||
2789 | if (!nfserr) | 2743 | if (!nfserr) |
2790 | nfsd4_encode_stateid(resp, &locku->lu_stateid); | 2744 | nfsd4_encode_stateid(resp, &locku->lu_stateid); |
2791 | 2745 | ||
2792 | encode_seqid_op_tail(resp, save, nfserr); | ||
2793 | return nfserr; | 2746 | return nfserr; |
2794 | } | 2747 | } |
2795 | 2748 | ||
@@ -2812,7 +2765,6 @@ static __be32 | |||
2812 | nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open) | 2765 | nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open) |
2813 | { | 2766 | { |
2814 | __be32 *p; | 2767 | __be32 *p; |
2815 | ENCODE_SEQID_OP_HEAD; | ||
2816 | 2768 | ||
2817 | if (nfserr) | 2769 | if (nfserr) |
2818 | goto out; | 2770 | goto out; |
@@ -2884,31 +2836,24 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op | |||
2884 | } | 2836 | } |
2885 | /* XXX save filehandle here */ | 2837 | /* XXX save filehandle here */ |
2886 | out: | 2838 | out: |
2887 | encode_seqid_op_tail(resp, save, nfserr); | ||
2888 | return nfserr; | 2839 | return nfserr; |
2889 | } | 2840 | } |
2890 | 2841 | ||
2891 | static __be32 | 2842 | static __be32 |
2892 | nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc) | 2843 | nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc) |
2893 | { | 2844 | { |
2894 | ENCODE_SEQID_OP_HEAD; | ||
2895 | |||
2896 | if (!nfserr) | 2845 | if (!nfserr) |
2897 | nfsd4_encode_stateid(resp, &oc->oc_resp_stateid); | 2846 | nfsd4_encode_stateid(resp, &oc->oc_resp_stateid); |
2898 | 2847 | ||
2899 | encode_seqid_op_tail(resp, save, nfserr); | ||
2900 | return nfserr; | 2848 | return nfserr; |
2901 | } | 2849 | } |
2902 | 2850 | ||
2903 | static __be32 | 2851 | static __be32 |
2904 | nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od) | 2852 | nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od) |
2905 | { | 2853 | { |
2906 | ENCODE_SEQID_OP_HEAD; | ||
2907 | |||
2908 | if (!nfserr) | 2854 | if (!nfserr) |
2909 | nfsd4_encode_stateid(resp, &od->od_stateid); | 2855 | nfsd4_encode_stateid(resp, &od->od_stateid); |
2910 | 2856 | ||
2911 | encode_seqid_op_tail(resp, save, nfserr); | ||
2912 | return nfserr; | 2857 | return nfserr; |
2913 | } | 2858 | } |
2914 | 2859 | ||
@@ -3140,10 +3085,11 @@ static __be32 | |||
3140 | nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp, | 3085 | nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp, |
3141 | __be32 nfserr, struct svc_export *exp) | 3086 | __be32 nfserr, struct svc_export *exp) |
3142 | { | 3087 | { |
3143 | u32 i, nflavs; | 3088 | u32 i, nflavs, supported; |
3144 | struct exp_flavor_info *flavs; | 3089 | struct exp_flavor_info *flavs; |
3145 | struct exp_flavor_info def_flavs[2]; | 3090 | struct exp_flavor_info def_flavs[2]; |
3146 | __be32 *p; | 3091 | __be32 *p, *flavorsp; |
3092 | static bool report = true; | ||
3147 | 3093 | ||
3148 | if (nfserr) | 3094 | if (nfserr) |
3149 | goto out; | 3095 | goto out; |
@@ -3167,33 +3113,40 @@ nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp, | |||
3167 | } | 3113 | } |
3168 | } | 3114 | } |
3169 | 3115 | ||
3116 | supported = 0; | ||
3170 | RESERVE_SPACE(4); | 3117 | RESERVE_SPACE(4); |
3171 | WRITE32(nflavs); | 3118 | flavorsp = p++; /* to be backfilled later */ |
3172 | ADJUST_ARGS(); | 3119 | ADJUST_ARGS(); |
3120 | |||
3173 | for (i = 0; i < nflavs; i++) { | 3121 | for (i = 0; i < nflavs; i++) { |
3122 | rpc_authflavor_t pf = flavs[i].pseudoflavor; | ||
3174 | struct rpcsec_gss_info info; | 3123 | struct rpcsec_gss_info info; |
3175 | 3124 | ||
3176 | if (rpcauth_get_gssinfo(flavs[i].pseudoflavor, &info) == 0) { | 3125 | if (rpcauth_get_gssinfo(pf, &info) == 0) { |
3177 | RESERVE_SPACE(4); | 3126 | supported++; |
3127 | RESERVE_SPACE(4 + 4 + info.oid.len + 4 + 4); | ||
3178 | WRITE32(RPC_AUTH_GSS); | 3128 | WRITE32(RPC_AUTH_GSS); |
3179 | ADJUST_ARGS(); | ||
3180 | RESERVE_SPACE(4 + info.oid.len); | ||
3181 | WRITE32(info.oid.len); | 3129 | WRITE32(info.oid.len); |
3182 | WRITEMEM(info.oid.data, info.oid.len); | 3130 | WRITEMEM(info.oid.data, info.oid.len); |
3183 | ADJUST_ARGS(); | ||
3184 | RESERVE_SPACE(4); | ||
3185 | WRITE32(info.qop); | 3131 | WRITE32(info.qop); |
3186 | ADJUST_ARGS(); | ||
3187 | RESERVE_SPACE(4); | ||
3188 | WRITE32(info.service); | 3132 | WRITE32(info.service); |
3189 | ADJUST_ARGS(); | 3133 | ADJUST_ARGS(); |
3190 | } else { | 3134 | } else if (pf < RPC_AUTH_MAXFLAVOR) { |
3135 | supported++; | ||
3191 | RESERVE_SPACE(4); | 3136 | RESERVE_SPACE(4); |
3192 | WRITE32(flavs[i].pseudoflavor); | 3137 | WRITE32(pf); |
3193 | ADJUST_ARGS(); | 3138 | ADJUST_ARGS(); |
3139 | } else { | ||
3140 | if (report) | ||
3141 | pr_warn("NFS: SECINFO: security flavor %u " | ||
3142 | "is not supported\n", pf); | ||
3194 | } | 3143 | } |
3195 | } | 3144 | } |
3196 | 3145 | ||
3146 | if (nflavs != supported) | ||
3147 | report = false; | ||
3148 | *flavorsp = htonl(supported); | ||
3149 | |||
3197 | out: | 3150 | out: |
3198 | if (exp) | 3151 | if (exp) |
3199 | exp_put(exp); | 3152 | exp_put(exp); |
@@ -3564,6 +3517,7 @@ __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 pad) | |||
3564 | void | 3517 | void |
3565 | nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) | 3518 | nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) |
3566 | { | 3519 | { |
3520 | struct nfs4_stateowner *so = resp->cstate.replay_owner; | ||
3567 | __be32 *statp; | 3521 | __be32 *statp; |
3568 | __be32 *p; | 3522 | __be32 *p; |
3569 | 3523 | ||
@@ -3580,6 +3534,11 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) | |||
3580 | /* nfsd4_check_drc_limit guarantees enough room for error status */ | 3534 | /* nfsd4_check_drc_limit guarantees enough room for error status */ |
3581 | if (!op->status) | 3535 | if (!op->status) |
3582 | op->status = nfsd4_check_resp_size(resp, 0); | 3536 | op->status = nfsd4_check_resp_size(resp, 0); |
3537 | if (so) { | ||
3538 | so->so_replay.rp_status = op->status; | ||
3539 | so->so_replay.rp_buflen = (char *)resp->p - (char *)(statp+1); | ||
3540 | memcpy(so->so_replay.rp_buf, statp+1, so->so_replay.rp_buflen); | ||
3541 | } | ||
3583 | status: | 3542 | status: |
3584 | /* | 3543 | /* |
3585 | * Note: We write the status directly, instead of using WRITE32(), | 3544 | * Note: We write the status directly, instead of using WRITE32(), |
@@ -3681,7 +3640,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo | |||
3681 | cs->slot->sl_flags &= ~NFSD4_SLOT_INUSE; | 3640 | cs->slot->sl_flags &= ~NFSD4_SLOT_INUSE; |
3682 | } | 3641 | } |
3683 | /* Renew the clientid on success and on replay */ | 3642 | /* Renew the clientid on success and on replay */ |
3684 | release_session_client(cs->session); | 3643 | put_client_renew(cs->session->se_client); |
3685 | nfsd4_put_session(cs->session); | 3644 | nfsd4_put_session(cs->session); |
3686 | } | 3645 | } |
3687 | return 1; | 3646 | return 1; |