aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4xdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r--fs/nfsd/nfs4xdr.c109
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
1710static 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,
2661static __be32 2623static __be32
2662nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close) 2624nfsd4_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
2762static __be32 2721static __be32
2763nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock) 2722nfsd4_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
2784static __be32 2740static __be32
2785nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku) 2741nfsd4_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
2812nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open) 2765nfsd4_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 */
2886out: 2838out:
2887 encode_seqid_op_tail(resp, save, nfserr);
2888 return nfserr; 2839 return nfserr;
2889} 2840}
2890 2841
2891static __be32 2842static __be32
2892nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc) 2843nfsd4_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
2903static __be32 2851static __be32
2904nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od) 2852nfsd4_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
3140nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp, 3085nfsd4_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
3197out: 3150out:
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)
3564void 3517void
3565nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) 3518nfsd4_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 }
3583status: 3542status:
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;