Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFSD: Update the SETATTR3args decoder to use struct xdr_stream

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

+127 -17
+121 -17
fs/nfsd/nfs3xdr.c
··· 39 39 return p; 40 40 } 41 41 42 - static __be32 * 43 - decode_time3(__be32 *p, struct timespec64 *time) 42 + static bool 43 + svcxdr_decode_nfstime3(struct xdr_stream *xdr, struct timespec64 *timep) 44 44 { 45 - time->tv_sec = ntohl(*p++); 46 - time->tv_nsec = ntohl(*p++); 47 - return p; 45 + __be32 *p; 46 + 47 + p = xdr_inline_decode(xdr, XDR_UNIT * 2); 48 + if (!p) 49 + return false; 50 + timep->tv_sec = be32_to_cpup(p++); 51 + timep->tv_nsec = be32_to_cpup(p); 52 + 53 + return true; 48 54 } 49 55 50 56 static bool ··· 154 148 { 155 149 return svcxdr_decode_nfs_fh3(xdr, fhp) && 156 150 svcxdr_decode_filename3(xdr, name, len); 151 + } 152 + 153 + static bool 154 + svcxdr_decode_sattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr, 155 + struct iattr *iap) 156 + { 157 + u32 set_it; 158 + 159 + iap->ia_valid = 0; 160 + 161 + if (xdr_stream_decode_bool(xdr, &set_it) < 0) 162 + return false; 163 + if (set_it) { 164 + u32 mode; 165 + 166 + if (xdr_stream_decode_u32(xdr, &mode) < 0) 167 + return false; 168 + iap->ia_valid |= ATTR_MODE; 169 + iap->ia_mode = mode; 170 + } 171 + if (xdr_stream_decode_bool(xdr, &set_it) < 0) 172 + return false; 173 + if (set_it) { 174 + u32 uid; 175 + 176 + if (xdr_stream_decode_u32(xdr, &uid) < 0) 177 + return false; 178 + iap->ia_uid = make_kuid(nfsd_user_namespace(rqstp), uid); 179 + if (uid_valid(iap->ia_uid)) 180 + iap->ia_valid |= ATTR_UID; 181 + } 182 + if (xdr_stream_decode_bool(xdr, &set_it) < 0) 183 + return false; 184 + if (set_it) { 185 + u32 gid; 186 + 187 + if (xdr_stream_decode_u32(xdr, &gid) < 0) 188 + return false; 189 + iap->ia_gid = make_kgid(nfsd_user_namespace(rqstp), gid); 190 + if (gid_valid(iap->ia_gid)) 191 + iap->ia_valid |= ATTR_GID; 192 + } 193 + if (xdr_stream_decode_bool(xdr, &set_it) < 0) 194 + return false; 195 + if (set_it) { 196 + u64 newsize; 197 + 198 + if (xdr_stream_decode_u64(xdr, &newsize) < 0) 199 + return false; 200 + iap->ia_valid |= ATTR_SIZE; 201 + iap->ia_size = min_t(u64, newsize, NFS_OFFSET_MAX); 202 + } 203 + if (xdr_stream_decode_u32(xdr, &set_it) < 0) 204 + return false; 205 + switch (set_it) { 206 + case DONT_CHANGE: 207 + break; 208 + case SET_TO_SERVER_TIME: 209 + iap->ia_valid |= ATTR_ATIME; 210 + break; 211 + case SET_TO_CLIENT_TIME: 212 + if (!svcxdr_decode_nfstime3(xdr, &iap->ia_atime)) 213 + return false; 214 + iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET; 215 + break; 216 + default: 217 + return false; 218 + } 219 + if (xdr_stream_decode_u32(xdr, &set_it) < 0) 220 + return false; 221 + switch (set_it) { 222 + case DONT_CHANGE: 223 + break; 224 + case SET_TO_SERVER_TIME: 225 + iap->ia_valid |= ATTR_MTIME; 226 + break; 227 + case SET_TO_CLIENT_TIME: 228 + if (!svcxdr_decode_nfstime3(xdr, &iap->ia_mtime)) 229 + return false; 230 + iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET; 231 + break; 232 + default: 233 + return false; 234 + } 235 + 236 + return true; 237 + } 238 + 239 + static bool 240 + svcxdr_decode_sattrguard3(struct xdr_stream *xdr, struct nfsd3_sattrargs *args) 241 + { 242 + __be32 *p; 243 + u32 check; 244 + 245 + if (xdr_stream_decode_bool(xdr, &check) < 0) 246 + return false; 247 + if (check) { 248 + p = xdr_inline_decode(xdr, XDR_UNIT * 2); 249 + if (!p) 250 + return false; 251 + args->check_guard = 1; 252 + args->guardtime = be32_to_cpup(p); 253 + } else 254 + args->check_guard = 0; 255 + 256 + return true; 157 257 } 158 258 159 259 static __be32 * ··· 489 377 int 490 378 nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p) 491 379 { 380 + struct xdr_stream *xdr = &rqstp->rq_arg_stream; 492 381 struct nfsd3_sattrargs *args = rqstp->rq_argp; 493 382 494 - p = decode_fh(p, &args->fh); 495 - if (!p) 496 - return 0; 497 - p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp)); 498 - 499 - if ((args->check_guard = ntohl(*p++)) != 0) { 500 - struct timespec64 time; 501 - p = decode_time3(p, &time); 502 - args->guardtime = time.tv_sec; 503 - } 504 - 505 - return xdr_argsize_check(rqstp, p); 383 + return svcxdr_decode_nfs_fh3(xdr, &args->fh) && 384 + svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) && 385 + svcxdr_decode_sattrguard3(xdr, args); 506 386 } 507 387 508 388 int
+6
include/uapi/linux/nfs3.h
··· 63 63 NF3BAD = 8 64 64 }; 65 65 66 + enum nfs3_time_how { 67 + DONT_CHANGE = 0, 68 + SET_TO_SERVER_TIME = 1, 69 + SET_TO_CLIENT_TIME = 2, 70 + }; 71 + 66 72 struct nfs3_fh { 67 73 unsigned short size; 68 74 unsigned char data[NFS3_FHSIZE];