1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Process version 3 NFS requests.
4 *
5 * Copyright (C) 1996, 1997, 1998 Olaf Kirch <okir@monad.swb.de>
6 */
7
8 #include <linux/fs.h>
9 #include <linux/ext2_fs.h>
10 #include <linux/magic.h>
11 #include <linux/namei.h>
12
13 #include "cache.h"
14 #include "xdr3.h"
15 #include "vfs.h"
16 #include "filecache.h"
17 #include "trace.h"
18
19 #define NFSDDBG_FACILITY NFSDDBG_PROC
20
21 static int nfs3_ftypes[] = {
22 0, /* NF3NON */
23 S_IFREG, /* NF3REG */
24 S_IFDIR, /* NF3DIR */
25 S_IFBLK, /* NF3BLK */
26 S_IFCHR, /* NF3CHR */
27 S_IFLNK, /* NF3LNK */
28 S_IFSOCK, /* NF3SOCK */
29 S_IFIFO, /* NF3FIFO */
30 };
31
32 /*
33 * Reject a client-supplied atime or mtime whose nanoseconds field is out
34 * of range. Such a value is well-formed on the wire but is not a valid
35 * timespec64, and storing it verbatim can corrupt on-disk timestamps.
36 * tv_nsec is a long, so it is cast to unsigned long (the same width) to
37 * catch both an over-large value and one that became negative when an
38 * out-of-range u32 wire nseconds was assigned to a 32-bit long.
39 */
nfsd3_time_in_range(const struct iattr * iap)40 static bool nfsd3_time_in_range(const struct iattr *iap)
41 {
42 if ((iap->ia_valid & ATTR_ATIME_SET) &&
43 (unsigned long)iap->ia_atime.tv_nsec >= NSEC_PER_SEC)
44 return false;
45 if ((iap->ia_valid & ATTR_MTIME_SET) &&
46 (unsigned long)iap->ia_mtime.tv_nsec >= NSEC_PER_SEC)
47 return false;
48 return true;
49 }
50
nfsd3_map_status(__be32 status)51 static __be32 nfsd3_map_status(__be32 status)
52 {
53 switch (status) {
54 case nfs_ok:
55 break;
56 case nfserr_nofilehandle:
57 status = nfserr_badhandle;
58 break;
59 case nfserr_wrongsec:
60 case nfserr_file_open:
61 status = nfserr_acces;
62 break;
63 case nfserr_symlink_not_dir:
64 status = nfserr_notdir;
65 break;
66 case nfserr_symlink:
67 case nfserr_wrong_type:
68 status = nfserr_inval;
69 break;
70 }
71 return status;
72 }
73
74 /*
75 * NULL call.
76 */
77 static __be32
nfsd3_proc_null(struct svc_rqst * rqstp)78 nfsd3_proc_null(struct svc_rqst *rqstp)
79 {
80 return rpc_success;
81 }
82
83 /*
84 * Get a file's attributes
85 */
86 static __be32
nfsd3_proc_getattr(struct svc_rqst * rqstp)87 nfsd3_proc_getattr(struct svc_rqst *rqstp)
88 {
89 struct nfsd_fhandle *argp = rqstp->rq_argp;
90 struct nfsd3_attrstat *resp = rqstp->rq_resp;
91
92 trace_nfsd_vfs_getattr(rqstp, &argp->fh);
93
94 fh_copy(&resp->fh, &argp->fh);
95 resp->status = fh_verify(rqstp, &resp->fh, 0,
96 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
97 if (resp->status != nfs_ok)
98 goto out;
99
100 resp->status = fh_getattr(&resp->fh, &resp->stat);
101 out:
102 resp->status = nfsd3_map_status(resp->status);
103 return rpc_success;
104 }
105
106 /*
107 * Set a file's attributes
108 */
109 static __be32
nfsd3_proc_setattr(struct svc_rqst * rqstp)110 nfsd3_proc_setattr(struct svc_rqst *rqstp)
111 {
112 struct nfsd3_sattrargs *argp = rqstp->rq_argp;
113 struct nfsd3_attrstat *resp = rqstp->rq_resp;
114 struct nfsd_attrs attrs = {
115 .na_iattr = &argp->attrs,
116 };
117 const struct timespec64 *guardtime = NULL;
118
119 dprintk("nfsd: SETATTR(3) %s\n",
120 SVCFH_fmt(&argp->fh));
121
122 fh_copy(&resp->fh, &argp->fh);
123 if (!nfsd3_time_in_range(&argp->attrs)) {
124 resp->status = nfserr_inval;
125 goto out;
126 }
127 if (argp->check_guard)
128 guardtime = &argp->guardtime;
129 resp->status = nfsd_setattr(rqstp, &resp->fh, &attrs, guardtime);
130 out:
131 resp->status = nfsd3_map_status(resp->status);
132 return rpc_success;
133 }
134
135 /*
136 * Look up a path name component
137 */
138 static __be32
nfsd3_proc_lookup(struct svc_rqst * rqstp)139 nfsd3_proc_lookup(struct svc_rqst *rqstp)
140 {
141 struct nfsd3_diropargs *argp = rqstp->rq_argp;
142 struct nfsd3_diropres *resp = rqstp->rq_resp;
143
144 dprintk("nfsd: LOOKUP(3) %s %.*s\n",
145 SVCFH_fmt(&argp->fh),
146 argp->len,
147 argp->name);
148
149 fh_copy(&resp->dirfh, &argp->fh);
150 fh_init(&resp->fh, NFS3_FHSIZE);
151
152 resp->status = nfsd_lookup(rqstp, &resp->dirfh,
153 argp->name, argp->len,
154 &resp->fh);
155 resp->status = nfsd3_map_status(resp->status);
156 return rpc_success;
157 }
158
159 /*
160 * Check file access
161 */
162 static __be32
nfsd3_proc_access(struct svc_rqst * rqstp)163 nfsd3_proc_access(struct svc_rqst *rqstp)
164 {
165 struct nfsd3_accessargs *argp = rqstp->rq_argp;
166 struct nfsd3_accessres *resp = rqstp->rq_resp;
167
168 dprintk("nfsd: ACCESS(3) %s 0x%x\n",
169 SVCFH_fmt(&argp->fh),
170 argp->access);
171
172 fh_copy(&resp->fh, &argp->fh);
173 resp->access = argp->access;
174 resp->status = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
175 resp->status = nfsd3_map_status(resp->status);
176 return rpc_success;
177 }
178
179 /*
180 * Read a symlink.
181 */
182 static __be32
nfsd3_proc_readlink(struct svc_rqst * rqstp)183 nfsd3_proc_readlink(struct svc_rqst *rqstp)
184 {
185 struct nfsd_fhandle *argp = rqstp->rq_argp;
186 struct nfsd3_readlinkres *resp = rqstp->rq_resp;
187
188 dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
189
190 /* Read the symlink. */
191 fh_copy(&resp->fh, &argp->fh);
192 resp->len = NFS3_MAXPATHLEN;
193 resp->pages = rqstp->rq_next_page++;
194 resp->status = nfsd_readlink(rqstp, &resp->fh,
195 page_address(*resp->pages), &resp->len);
196 resp->status = nfsd3_map_status(resp->status);
197 return rpc_success;
198 }
199
200 /*
201 * Read a portion of a file.
202 */
203 static __be32
nfsd3_proc_read(struct svc_rqst * rqstp)204 nfsd3_proc_read(struct svc_rqst *rqstp)
205 {
206 struct nfsd3_readargs *argp = rqstp->rq_argp;
207 struct nfsd3_readres *resp = rqstp->rq_resp;
208
209 dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n",
210 SVCFH_fmt(&argp->fh),
211 (unsigned long) argp->count,
212 (unsigned long long) argp->offset);
213
214 argp->count = min_t(u32, argp->count, svc_max_payload(rqstp));
215 argp->count = min_t(u32, argp->count, rqstp->rq_res.buflen);
216 if (argp->offset > (u64)OFFSET_MAX)
217 argp->offset = (u64)OFFSET_MAX;
218 if (argp->offset + argp->count > (u64)OFFSET_MAX)
219 argp->count = (u64)OFFSET_MAX - argp->offset;
220
221 resp->pages = rqstp->rq_next_page;
222
223 /* Obtain buffer pointer for payload.
224 * 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof)
225 * + 1 (xdr opaque byte count) = 26
226 */
227 resp->count = argp->count;
228 svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3) << 2) +
229 resp->count + 4);
230
231 fh_copy(&resp->fh, &argp->fh);
232 resp->status = nfsd_read(rqstp, &resp->fh, argp->offset,
233 &resp->count, &resp->eof);
234 resp->status = nfsd3_map_status(resp->status);
235 return rpc_success;
236 }
237
238 /*
239 * Write data to a file
240 */
241 static __be32
nfsd3_proc_write(struct svc_rqst * rqstp)242 nfsd3_proc_write(struct svc_rqst *rqstp)
243 {
244 struct nfsd3_writeargs *argp = rqstp->rq_argp;
245 struct nfsd3_writeres *resp = rqstp->rq_resp;
246 unsigned long cnt = argp->len;
247
248 dprintk("nfsd: WRITE(3) %s %d bytes at %Lu%s\n",
249 SVCFH_fmt(&argp->fh),
250 argp->len,
251 (unsigned long long) argp->offset,
252 argp->stable ? " stable" : "");
253
254 resp->status = nfserr_fbig;
255 if (argp->offset > (u64)OFFSET_MAX ||
256 argp->offset + argp->len > (u64)OFFSET_MAX)
257 return rpc_success;
258
259 fh_copy(&resp->fh, &argp->fh);
260 resp->committed = argp->stable;
261 resp->status = nfsd_write(rqstp, &resp->fh, argp->offset,
262 &argp->payload, &cnt,
263 resp->committed, resp->verf);
264 resp->count = cnt;
265 resp->status = nfsd3_map_status(resp->status);
266 return rpc_success;
267 }
268
269 /*
270 * Implement NFSv3's unchecked, guarded, and exclusive CREATE
271 * semantics for regular files. Except for the created file,
272 * this operation is stateless on the server.
273 *
274 * Upon return, caller must release @fhp and @resfhp.
275 */
276 static __be32
nfsd3_create_file(struct svc_rqst * rqstp,struct svc_fh * fhp,struct svc_fh * resfhp,struct nfsd3_createargs * argp)277 nfsd3_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
278 struct svc_fh *resfhp, struct nfsd3_createargs *argp)
279 {
280 struct iattr *iap = &argp->attrs;
281 struct dentry *parent, *child;
282 struct nfsd_attrs attrs = {
283 .na_iattr = iap,
284 };
285 __u32 v_mtime, v_atime;
286 struct inode *inode;
287 __be32 status;
288 int host_err;
289
290 trace_nfsd_vfs_create(rqstp, fhp, S_IFREG, argp->name, argp->len);
291
292 if (!nfsd3_time_in_range(iap))
293 return nfserr_inval;
294 if (name_is_dot_dotdot(argp->name, argp->len))
295 return nfserr_exist;
296 if (!(iap->ia_valid & ATTR_MODE))
297 iap->ia_mode = 0;
298
299 status = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
300 if (status != nfs_ok)
301 return status;
302
303 parent = fhp->fh_dentry;
304 inode = d_inode(parent);
305
306 host_err = fh_want_write(fhp);
307 if (host_err)
308 return nfserrno(host_err);
309
310 child = start_creating(&nop_mnt_idmap, parent,
311 &QSTR_LEN(argp->name, argp->len));
312 if (IS_ERR(child)) {
313 status = nfserrno(PTR_ERR(child));
314 goto out_write;
315 }
316
317 if (d_really_is_negative(child)) {
318 status = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
319 if (status != nfs_ok)
320 goto out;
321 }
322
323 status = fh_compose(resfhp, fhp->fh_export, child, fhp);
324 if (status != nfs_ok)
325 goto out;
326
327 v_mtime = 0;
328 v_atime = 0;
329 if (argp->createmode == NFS3_CREATE_EXCLUSIVE) {
330 u32 *verifier = (u32 *)argp->verf;
331
332 /*
333 * Solaris 7 gets confused (bugid 4218508) if these have
334 * the high bit set, as do xfs filesystems without the
335 * "bigtime" feature. So just clear the high bits.
336 */
337 v_mtime = verifier[0] & 0x7fffffff;
338 v_atime = verifier[1] & 0x7fffffff;
339 }
340
341 if (d_really_is_positive(child)) {
342 status = nfs_ok;
343
344 switch (argp->createmode) {
345 case NFS3_CREATE_UNCHECKED:
346 if (!d_is_reg(child))
347 break;
348 iap->ia_valid &= ATTR_SIZE;
349 goto set_attr;
350 case NFS3_CREATE_GUARDED:
351 status = nfserr_exist;
352 break;
353 case NFS3_CREATE_EXCLUSIVE:
354 if (inode_get_mtime_sec(d_inode(child)) == v_mtime &&
355 inode_get_atime_sec(d_inode(child)) == v_atime &&
356 d_inode(child)->i_size == 0) {
357 break;
358 }
359 status = nfserr_exist;
360 }
361 goto out;
362 }
363
364 if (!IS_POSIXACL(inode))
365 iap->ia_mode &= ~current_umask();
366
367 status = fh_fill_pre_attrs(fhp);
368 if (status != nfs_ok)
369 goto out;
370 host_err = vfs_create(&nop_mnt_idmap, child, iap->ia_mode, NULL);
371 if (host_err < 0) {
372 status = nfserrno(host_err);
373 goto out;
374 }
375 fh_fill_post_attrs(fhp);
376
377 /* A newly created file already has a file size of zero. */
378 if ((iap->ia_valid & ATTR_SIZE) && (iap->ia_size == 0))
379 iap->ia_valid &= ~ATTR_SIZE;
380 if (argp->createmode == NFS3_CREATE_EXCLUSIVE) {
381 iap->ia_valid = ATTR_MTIME | ATTR_ATIME |
382 ATTR_MTIME_SET | ATTR_ATIME_SET;
383 iap->ia_mtime.tv_sec = v_mtime;
384 iap->ia_atime.tv_sec = v_atime;
385 iap->ia_mtime.tv_nsec = 0;
386 iap->ia_atime.tv_nsec = 0;
387 }
388
389 set_attr:
390 status = nfsd_create_setattr(rqstp, fhp, resfhp, &attrs);
391
392 out:
393 end_creating(child);
394 out_write:
395 fh_drop_write(fhp);
396 return status;
397 }
398
399 static __be32
nfsd3_proc_create(struct svc_rqst * rqstp)400 nfsd3_proc_create(struct svc_rqst *rqstp)
401 {
402 struct nfsd3_createargs *argp = rqstp->rq_argp;
403 struct nfsd3_diropres *resp = rqstp->rq_resp;
404 svc_fh *dirfhp, *newfhp;
405
406 dirfhp = fh_copy(&resp->dirfh, &argp->fh);
407 newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
408
409 resp->status = nfsd3_create_file(rqstp, dirfhp, newfhp, argp);
410 resp->status = nfsd3_map_status(resp->status);
411 return rpc_success;
412 }
413
414 /*
415 * Make directory. This operation is not idempotent.
416 */
417 static __be32
nfsd3_proc_mkdir(struct svc_rqst * rqstp)418 nfsd3_proc_mkdir(struct svc_rqst *rqstp)
419 {
420 struct nfsd3_createargs *argp = rqstp->rq_argp;
421 struct nfsd3_diropres *resp = rqstp->rq_resp;
422 struct nfsd_attrs attrs = {
423 .na_iattr = &argp->attrs,
424 };
425
426 argp->attrs.ia_valid &= ~ATTR_SIZE;
427 fh_copy(&resp->dirfh, &argp->fh);
428 fh_init(&resp->fh, NFS3_FHSIZE);
429 if (!nfsd3_time_in_range(&argp->attrs)) {
430 resp->status = nfserr_inval;
431 goto out;
432 }
433 resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
434 &attrs, S_IFDIR, 0, &resp->fh);
435 out:
436 resp->status = nfsd3_map_status(resp->status);
437 return rpc_success;
438 }
439
440 static __be32
nfsd3_proc_symlink(struct svc_rqst * rqstp)441 nfsd3_proc_symlink(struct svc_rqst *rqstp)
442 {
443 struct nfsd3_symlinkargs *argp = rqstp->rq_argp;
444 struct nfsd3_diropres *resp = rqstp->rq_resp;
445 struct nfsd_attrs attrs = {
446 .na_iattr = &argp->attrs,
447 };
448
449 if (!nfsd3_time_in_range(&argp->attrs)) {
450 resp->status = nfserr_inval;
451 goto out;
452 }
453 if (argp->tlen == 0) {
454 resp->status = nfserr_inval;
455 goto out;
456 }
457 if (argp->tlen > NFS3_MAXPATHLEN) {
458 resp->status = nfserr_nametoolong;
459 goto out;
460 }
461
462 argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
463 page_address(rqstp->rq_arg.pages[0]),
464 argp->tlen);
465 if (IS_ERR(argp->tname)) {
466 resp->status = nfserrno(PTR_ERR(argp->tname));
467 goto out;
468 }
469
470 fh_copy(&resp->dirfh, &argp->ffh);
471 fh_init(&resp->fh, NFS3_FHSIZE);
472 resp->status = nfsd_symlink(rqstp, &resp->dirfh, argp->fname,
473 argp->flen, argp->tname, &attrs, &resp->fh);
474 kfree(argp->tname);
475 out:
476 resp->status = nfsd3_map_status(resp->status);
477 return rpc_success;
478 }
479
480 /*
481 * Make socket/fifo/device.
482 */
483 static __be32
nfsd3_proc_mknod(struct svc_rqst * rqstp)484 nfsd3_proc_mknod(struct svc_rqst *rqstp)
485 {
486 struct nfsd3_mknodargs *argp = rqstp->rq_argp;
487 struct nfsd3_diropres *resp = rqstp->rq_resp;
488 struct nfsd_attrs attrs = {
489 .na_iattr = &argp->attrs,
490 };
491 int type;
492 dev_t rdev = 0;
493
494 fh_copy(&resp->dirfh, &argp->fh);
495 fh_init(&resp->fh, NFS3_FHSIZE);
496
497 if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
498 rdev = MKDEV(argp->major, argp->minor);
499 if (MAJOR(rdev) != argp->major ||
500 MINOR(rdev) != argp->minor) {
501 resp->status = nfserr_inval;
502 goto out;
503 }
504 } else if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO) {
505 resp->status = nfserr_badtype;
506 goto out;
507 }
508
509 if (!nfsd3_time_in_range(&argp->attrs)) {
510 resp->status = nfserr_inval;
511 goto out;
512 }
513
514 type = nfs3_ftypes[argp->ftype];
515 resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
516 &attrs, type, rdev, &resp->fh);
517 out:
518 resp->status = nfsd3_map_status(resp->status);
519 return rpc_success;
520 }
521
522 /*
523 * Remove file/fifo/socket etc.
524 */
525 static __be32
nfsd3_proc_remove(struct svc_rqst * rqstp)526 nfsd3_proc_remove(struct svc_rqst *rqstp)
527 {
528 struct nfsd3_diropargs *argp = rqstp->rq_argp;
529 struct nfsd3_attrstat *resp = rqstp->rq_resp;
530
531 /* Unlink. -S_IFDIR means file must not be a directory */
532 fh_copy(&resp->fh, &argp->fh);
533 resp->status = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR,
534 argp->name, argp->len);
535 resp->status = nfsd3_map_status(resp->status);
536 return rpc_success;
537 }
538
539 /*
540 * Remove a directory
541 */
542 static __be32
nfsd3_proc_rmdir(struct svc_rqst * rqstp)543 nfsd3_proc_rmdir(struct svc_rqst *rqstp)
544 {
545 struct nfsd3_diropargs *argp = rqstp->rq_argp;
546 struct nfsd3_attrstat *resp = rqstp->rq_resp;
547
548 fh_copy(&resp->fh, &argp->fh);
549 resp->status = nfsd_unlink(rqstp, &resp->fh, S_IFDIR,
550 argp->name, argp->len);
551 resp->status = nfsd3_map_status(resp->status);
552 return rpc_success;
553 }
554
555 static __be32
nfsd3_proc_rename(struct svc_rqst * rqstp)556 nfsd3_proc_rename(struct svc_rqst *rqstp)
557 {
558 struct nfsd3_renameargs *argp = rqstp->rq_argp;
559 struct nfsd3_renameres *resp = rqstp->rq_resp;
560
561 fh_copy(&resp->ffh, &argp->ffh);
562 fh_copy(&resp->tfh, &argp->tfh);
563 resp->status = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
564 &resp->tfh, argp->tname, argp->tlen);
565 resp->status = nfsd3_map_status(resp->status);
566 return rpc_success;
567 }
568
569 static __be32
nfsd3_proc_link(struct svc_rqst * rqstp)570 nfsd3_proc_link(struct svc_rqst *rqstp)
571 {
572 struct nfsd3_linkargs *argp = rqstp->rq_argp;
573 struct nfsd3_linkres *resp = rqstp->rq_resp;
574
575 fh_copy(&resp->fh, &argp->ffh);
576 fh_copy(&resp->tfh, &argp->tfh);
577 resp->status = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
578 &resp->fh);
579 resp->status = nfsd3_map_status(resp->status);
580 return rpc_success;
581 }
582
nfsd3_init_dirlist_pages(struct svc_rqst * rqstp,struct nfsd3_readdirres * resp,u32 count)583 static void nfsd3_init_dirlist_pages(struct svc_rqst *rqstp,
584 struct nfsd3_readdirres *resp,
585 u32 count)
586 {
587 struct xdr_buf *buf = &resp->dirlist;
588 struct xdr_stream *xdr = &resp->xdr;
589 unsigned int sendbuf = min_t(unsigned int, rqstp->rq_res.buflen,
590 svc_max_payload(rqstp));
591
592 memset(buf, 0, sizeof(*buf));
593
594 /* Reserve room for the NULL ptr & eof flag (-2 words) */
595 buf->buflen = clamp(count, (u32)(XDR_UNIT * 2), sendbuf);
596 buf->buflen -= XDR_UNIT * 2;
597 buf->pages = rqstp->rq_next_page;
598 rqstp->rq_next_page += (buf->buflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
599
600 xdr_init_encode_pages(xdr, buf);
601 }
602
603 /*
604 * Read a portion of a directory.
605 */
606 static __be32
nfsd3_proc_readdir(struct svc_rqst * rqstp)607 nfsd3_proc_readdir(struct svc_rqst *rqstp)
608 {
609 struct nfsd3_readdirargs *argp = rqstp->rq_argp;
610 struct nfsd3_readdirres *resp = rqstp->rq_resp;
611 loff_t offset;
612
613 trace_nfsd_vfs_readdir(rqstp, &argp->fh, argp->count, argp->cookie);
614
615 nfsd3_init_dirlist_pages(rqstp, resp, argp->count);
616
617 fh_copy(&resp->fh, &argp->fh);
618 resp->common.err = nfs_ok;
619 resp->cookie_offset = 0;
620 resp->rqstp = rqstp;
621 offset = argp->cookie;
622 resp->status = nfsd_readdir(rqstp, &resp->fh, &offset,
623 &resp->common, nfs3svc_encode_entry3);
624 memcpy(resp->verf, argp->verf, 8);
625 nfs3svc_encode_cookie3(resp, offset);
626
627 /* Recycle only pages that were part of the reply */
628 rqstp->rq_next_page = resp->xdr.page_ptr + 1;
629
630 resp->status = nfsd3_map_status(resp->status);
631 return rpc_success;
632 }
633
634 /*
635 * Read a portion of a directory, including file handles and attrs.
636 * For now, we choose to ignore the dircount parameter.
637 */
638 static __be32
nfsd3_proc_readdirplus(struct svc_rqst * rqstp)639 nfsd3_proc_readdirplus(struct svc_rqst *rqstp)
640 {
641 struct nfsd3_readdirargs *argp = rqstp->rq_argp;
642 struct nfsd3_readdirres *resp = rqstp->rq_resp;
643 loff_t offset;
644
645 trace_nfsd_vfs_readdir(rqstp, &argp->fh, argp->count, argp->cookie);
646
647 nfsd3_init_dirlist_pages(rqstp, resp, argp->count);
648
649 fh_copy(&resp->fh, &argp->fh);
650 resp->common.err = nfs_ok;
651 resp->cookie_offset = 0;
652 resp->rqstp = rqstp;
653 offset = argp->cookie;
654
655 resp->status = fh_verify(rqstp, &resp->fh, S_IFDIR, NFSD_MAY_NOP);
656 if (resp->status != nfs_ok)
657 goto out;
658
659 if (resp->fh.fh_export->ex_flags & NFSEXP_NOREADDIRPLUS) {
660 resp->status = nfserr_notsupp;
661 goto out;
662 }
663
664 resp->status = nfsd_readdir(rqstp, &resp->fh, &offset,
665 &resp->common, nfs3svc_encode_entryplus3);
666 memcpy(resp->verf, argp->verf, 8);
667 nfs3svc_encode_cookie3(resp, offset);
668
669 /* Recycle only pages that were part of the reply */
670 rqstp->rq_next_page = resp->xdr.page_ptr + 1;
671
672 out:
673 resp->status = nfsd3_map_status(resp->status);
674 return rpc_success;
675 }
676
677 /*
678 * Get file system stats
679 */
680 static __be32
nfsd3_proc_fsstat(struct svc_rqst * rqstp)681 nfsd3_proc_fsstat(struct svc_rqst *rqstp)
682 {
683 struct nfsd_fhandle *argp = rqstp->rq_argp;
684 struct nfsd3_fsstatres *resp = rqstp->rq_resp;
685
686 resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);
687 fh_put(&argp->fh);
688 resp->status = nfsd3_map_status(resp->status);
689 return rpc_success;
690 }
691
692 /*
693 * Get file system info
694 */
695 static __be32
nfsd3_proc_fsinfo(struct svc_rqst * rqstp)696 nfsd3_proc_fsinfo(struct svc_rqst *rqstp)
697 {
698 struct nfsd_fhandle *argp = rqstp->rq_argp;
699 struct nfsd3_fsinfores *resp = rqstp->rq_resp;
700 u32 max_blocksize = svc_max_payload(rqstp);
701
702 dprintk("nfsd: FSINFO(3) %s\n",
703 SVCFH_fmt(&argp->fh));
704
705 resp->f_rtmax = max_blocksize;
706 resp->f_rtpref = max_blocksize;
707 resp->f_rtmult = PAGE_SIZE;
708 resp->f_wtmax = max_blocksize;
709 resp->f_wtpref = max_blocksize;
710 resp->f_wtmult = PAGE_SIZE;
711 resp->f_dtpref = max_blocksize;
712 resp->f_maxfilesize = ~(u32) 0;
713 resp->f_properties = NFS3_FSF_DEFAULT;
714
715 resp->status = fh_verify(rqstp, &argp->fh, 0,
716 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
717
718 /* Check special features of the file system. May request
719 * different read/write sizes for file systems known to have
720 * problems with large blocks */
721 if (resp->status == nfs_ok) {
722 struct super_block *sb = argp->fh.fh_dentry->d_sb;
723
724 /* Note that we don't care for remote fs's here */
725 if (sb->s_magic == MSDOS_SUPER_MAGIC) {
726 resp->f_properties = NFS3_FSF_BILLYBOY;
727 }
728 resp->f_maxfilesize = sb->s_maxbytes;
729 }
730
731 fh_put(&argp->fh);
732 resp->status = nfsd3_map_status(resp->status);
733 return rpc_success;
734 }
735
736 /*
737 * Get pathconf info for the specified file
738 */
739 static __be32
nfsd3_proc_pathconf(struct svc_rqst * rqstp)740 nfsd3_proc_pathconf(struct svc_rqst *rqstp)
741 {
742 struct nfsd_fhandle *argp = rqstp->rq_argp;
743 struct nfsd3_pathconfres *resp = rqstp->rq_resp;
744
745 dprintk("nfsd: PATHCONF(3) %s\n",
746 SVCFH_fmt(&argp->fh));
747
748 /* Set default pathconf */
749 resp->p_link_max = 255; /* at least */
750 resp->p_name_max = 255; /* at least */
751 resp->p_no_trunc = 0;
752 resp->p_chown_restricted = 1;
753 resp->p_case_insensitive = false;
754 resp->p_case_preserving = true;
755
756 resp->status = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
757
758 if (resp->status == nfs_ok) {
759 struct super_block *sb = argp->fh.fh_dentry->d_sb;
760 int err;
761
762 if (sb->s_magic == EXT2_SUPER_MAGIC) {
763 resp->p_link_max = EXT2_LINK_MAX;
764 resp->p_name_max = EXT2_NAME_LEN;
765 }
766
767 err = nfsd_get_case_info(argp->fh.fh_dentry,
768 &resp->p_case_insensitive,
769 &resp->p_case_preserving);
770 /*
771 * RFC 1813 lists NFS3ERR_STALE, NFS3ERR_BADHANDLE, and
772 * NFS3ERR_SERVERFAULT as the only PATHCONF errors.
773 */
774 switch (err) {
775 case 0:
776 case -EOPNOTSUPP:
777 /* Both arms leave the output booleans valid. */
778 break;
779 case -EACCES:
780 case -EPERM:
781 /*
782 * Policy denied the query. Report STALE so the
783 * handle is unusable without implying a server
784 * malfunction.
785 */
786 resp->status = nfserr_stale;
787 break;
788 case -ESTALE:
789 resp->status = nfserr_stale;
790 break;
791 default:
792 resp->status = nfserr_serverfault;
793 break;
794 }
795 }
796
797 fh_put(&argp->fh);
798 resp->status = nfsd3_map_status(resp->status);
799 return rpc_success;
800 }
801
802 /*
803 * Commit a file (range) to stable storage.
804 */
805 static __be32
nfsd3_proc_commit(struct svc_rqst * rqstp)806 nfsd3_proc_commit(struct svc_rqst *rqstp)
807 {
808 struct nfsd3_commitargs *argp = rqstp->rq_argp;
809 struct nfsd3_commitres *resp = rqstp->rq_resp;
810 struct nfsd_file *nf;
811
812 dprintk("nfsd: COMMIT(3) %s %u@%Lu\n",
813 SVCFH_fmt(&argp->fh),
814 argp->count,
815 (unsigned long long) argp->offset);
816
817 fh_copy(&resp->fh, &argp->fh);
818 resp->status = nfsd_file_acquire_gc(rqstp, &resp->fh, NFSD_MAY_WRITE |
819 NFSD_MAY_NOT_BREAK_LEASE, &nf);
820 if (resp->status)
821 goto out;
822 resp->status = nfsd_commit(rqstp, &resp->fh, nf, argp->offset,
823 argp->count, resp->verf);
824 nfsd_file_put(nf);
825 out:
826 resp->status = nfsd3_map_status(resp->status);
827 return rpc_success;
828 }
829
830
831 /*
832 * NFSv3 Server procedures.
833 * Only the results of non-idempotent operations are cached.
834 */
835 #define nfs3svc_encode_attrstatres nfs3svc_encode_attrstat
836 #define nfs3svc_encode_wccstatres nfs3svc_encode_wccstat
837 #define nfsd3_mkdirargs nfsd3_createargs
838 #define nfsd3_readdirplusargs nfsd3_readdirargs
839 #define nfsd3_fhandleargs nfsd_fhandle
840 #define nfsd3_attrstatres nfsd3_attrstat
841 #define nfsd3_wccstatres nfsd3_attrstat
842 #define nfsd3_createres nfsd3_diropres
843
844 #define ST 1 /* status*/
845 #define FH 17 /* filehandle with length */
846 #define AT 21 /* attributes */
847 #define pAT (1+AT) /* post attributes - conditional */
848 #define WC (7+pAT) /* WCC attributes */
849
850 static const struct svc_procedure nfsd_procedures3[22] = {
851 [NFS3PROC_NULL] = {
852 .pc_func = nfsd3_proc_null,
853 .pc_decode = nfssvc_decode_voidarg,
854 .pc_encode = nfssvc_encode_voidres,
855 .pc_argsize = sizeof(struct nfsd_voidargs),
856 .pc_argzero = sizeof(struct nfsd_voidargs),
857 .pc_ressize = sizeof(struct nfsd_voidres),
858 .pc_cachetype = RC_NOCACHE,
859 .pc_xdrressize = ST,
860 .pc_name = "NULL",
861 },
862 [NFS3PROC_GETATTR] = {
863 .pc_func = nfsd3_proc_getattr,
864 .pc_decode = nfs3svc_decode_fhandleargs,
865 .pc_encode = nfs3svc_encode_getattrres,
866 .pc_release = nfs3svc_release_fhandle,
867 .pc_argsize = sizeof(struct nfsd_fhandle),
868 .pc_argzero = sizeof(struct nfsd_fhandle),
869 .pc_ressize = sizeof(struct nfsd3_attrstatres),
870 .pc_cachetype = RC_NOCACHE,
871 .pc_xdrressize = ST+AT,
872 .pc_name = "GETATTR",
873 },
874 [NFS3PROC_SETATTR] = {
875 .pc_func = nfsd3_proc_setattr,
876 .pc_decode = nfs3svc_decode_sattrargs,
877 .pc_encode = nfs3svc_encode_wccstatres,
878 .pc_release = nfs3svc_release_fhandle,
879 .pc_argsize = sizeof(struct nfsd3_sattrargs),
880 .pc_argzero = sizeof(struct nfsd3_sattrargs),
881 .pc_ressize = sizeof(struct nfsd3_wccstatres),
882 .pc_cachetype = RC_REPLBUFF,
883 .pc_xdrressize = ST+WC,
884 .pc_name = "SETATTR",
885 },
886 [NFS3PROC_LOOKUP] = {
887 .pc_func = nfsd3_proc_lookup,
888 .pc_decode = nfs3svc_decode_diropargs,
889 .pc_encode = nfs3svc_encode_lookupres,
890 .pc_release = nfs3svc_release_fhandle2,
891 .pc_argsize = sizeof(struct nfsd3_diropargs),
892 .pc_argzero = sizeof(struct nfsd3_diropargs),
893 .pc_ressize = sizeof(struct nfsd3_diropres),
894 .pc_cachetype = RC_NOCACHE,
895 .pc_xdrressize = ST+FH+pAT+pAT,
896 .pc_name = "LOOKUP",
897 },
898 [NFS3PROC_ACCESS] = {
899 .pc_func = nfsd3_proc_access,
900 .pc_decode = nfs3svc_decode_accessargs,
901 .pc_encode = nfs3svc_encode_accessres,
902 .pc_release = nfs3svc_release_fhandle,
903 .pc_argsize = sizeof(struct nfsd3_accessargs),
904 .pc_argzero = sizeof(struct nfsd3_accessargs),
905 .pc_ressize = sizeof(struct nfsd3_accessres),
906 .pc_cachetype = RC_NOCACHE,
907 .pc_xdrressize = ST+pAT+1,
908 .pc_name = "ACCESS",
909 },
910 [NFS3PROC_READLINK] = {
911 .pc_func = nfsd3_proc_readlink,
912 .pc_decode = nfs3svc_decode_fhandleargs,
913 .pc_encode = nfs3svc_encode_readlinkres,
914 .pc_release = nfs3svc_release_fhandle,
915 .pc_argsize = sizeof(struct nfsd_fhandle),
916 .pc_argzero = sizeof(struct nfsd_fhandle),
917 .pc_ressize = sizeof(struct nfsd3_readlinkres),
918 .pc_cachetype = RC_NOCACHE,
919 .pc_xdrressize = ST+pAT+1+NFS3_MAXPATHLEN/4,
920 .pc_name = "READLINK",
921 },
922 [NFS3PROC_READ] = {
923 .pc_func = nfsd3_proc_read,
924 .pc_decode = nfs3svc_decode_readargs,
925 .pc_encode = nfs3svc_encode_readres,
926 .pc_release = nfs3svc_release_fhandle,
927 .pc_argsize = sizeof(struct nfsd3_readargs),
928 .pc_argzero = sizeof(struct nfsd3_readargs),
929 .pc_ressize = sizeof(struct nfsd3_readres),
930 .pc_cachetype = RC_NOCACHE,
931 .pc_xdrressize = ST+pAT+4+NFSSVC_MAXBLKSIZE/4,
932 .pc_name = "READ",
933 },
934 [NFS3PROC_WRITE] = {
935 .pc_func = nfsd3_proc_write,
936 .pc_decode = nfs3svc_decode_writeargs,
937 .pc_encode = nfs3svc_encode_writeres,
938 .pc_release = nfs3svc_release_fhandle,
939 .pc_argsize = sizeof(struct nfsd3_writeargs),
940 .pc_argzero = sizeof(struct nfsd3_writeargs),
941 .pc_ressize = sizeof(struct nfsd3_writeres),
942 .pc_cachetype = RC_REPLBUFF,
943 .pc_xdrressize = ST+WC+4,
944 .pc_name = "WRITE",
945 },
946 [NFS3PROC_CREATE] = {
947 .pc_func = nfsd3_proc_create,
948 .pc_decode = nfs3svc_decode_createargs,
949 .pc_encode = nfs3svc_encode_createres,
950 .pc_release = nfs3svc_release_fhandle2,
951 .pc_argsize = sizeof(struct nfsd3_createargs),
952 .pc_argzero = sizeof(struct nfsd3_createargs),
953 .pc_ressize = sizeof(struct nfsd3_createres),
954 .pc_cachetype = RC_REPLBUFF,
955 .pc_xdrressize = ST+(1+FH+pAT)+WC,
956 .pc_name = "CREATE",
957 },
958 [NFS3PROC_MKDIR] = {
959 .pc_func = nfsd3_proc_mkdir,
960 .pc_decode = nfs3svc_decode_mkdirargs,
961 .pc_encode = nfs3svc_encode_createres,
962 .pc_release = nfs3svc_release_fhandle2,
963 .pc_argsize = sizeof(struct nfsd3_mkdirargs),
964 .pc_argzero = sizeof(struct nfsd3_mkdirargs),
965 .pc_ressize = sizeof(struct nfsd3_createres),
966 .pc_cachetype = RC_REPLBUFF,
967 .pc_xdrressize = ST+(1+FH+pAT)+WC,
968 .pc_name = "MKDIR",
969 },
970 [NFS3PROC_SYMLINK] = {
971 .pc_func = nfsd3_proc_symlink,
972 .pc_decode = nfs3svc_decode_symlinkargs,
973 .pc_encode = nfs3svc_encode_createres,
974 .pc_release = nfs3svc_release_fhandle2,
975 .pc_argsize = sizeof(struct nfsd3_symlinkargs),
976 .pc_argzero = sizeof(struct nfsd3_symlinkargs),
977 .pc_ressize = sizeof(struct nfsd3_createres),
978 .pc_cachetype = RC_REPLBUFF,
979 .pc_xdrressize = ST+(1+FH+pAT)+WC,
980 .pc_name = "SYMLINK",
981 },
982 [NFS3PROC_MKNOD] = {
983 .pc_func = nfsd3_proc_mknod,
984 .pc_decode = nfs3svc_decode_mknodargs,
985 .pc_encode = nfs3svc_encode_createres,
986 .pc_release = nfs3svc_release_fhandle2,
987 .pc_argsize = sizeof(struct nfsd3_mknodargs),
988 .pc_argzero = sizeof(struct nfsd3_mknodargs),
989 .pc_ressize = sizeof(struct nfsd3_createres),
990 .pc_cachetype = RC_REPLBUFF,
991 .pc_xdrressize = ST+(1+FH+pAT)+WC,
992 .pc_name = "MKNOD",
993 },
994 [NFS3PROC_REMOVE] = {
995 .pc_func = nfsd3_proc_remove,
996 .pc_decode = nfs3svc_decode_diropargs,
997 .pc_encode = nfs3svc_encode_wccstatres,
998 .pc_release = nfs3svc_release_fhandle,
999 .pc_argsize = sizeof(struct nfsd3_diropargs),
1000 .pc_argzero = sizeof(struct nfsd3_diropargs),
1001 .pc_ressize = sizeof(struct nfsd3_wccstatres),
1002 .pc_cachetype = RC_REPLBUFF,
1003 .pc_xdrressize = ST+WC,
1004 .pc_name = "REMOVE",
1005 },
1006 [NFS3PROC_RMDIR] = {
1007 .pc_func = nfsd3_proc_rmdir,
1008 .pc_decode = nfs3svc_decode_diropargs,
1009 .pc_encode = nfs3svc_encode_wccstatres,
1010 .pc_release = nfs3svc_release_fhandle,
1011 .pc_argsize = sizeof(struct nfsd3_diropargs),
1012 .pc_argzero = sizeof(struct nfsd3_diropargs),
1013 .pc_ressize = sizeof(struct nfsd3_wccstatres),
1014 .pc_cachetype = RC_REPLBUFF,
1015 .pc_xdrressize = ST+WC,
1016 .pc_name = "RMDIR",
1017 },
1018 [NFS3PROC_RENAME] = {
1019 .pc_func = nfsd3_proc_rename,
1020 .pc_decode = nfs3svc_decode_renameargs,
1021 .pc_encode = nfs3svc_encode_renameres,
1022 .pc_release = nfs3svc_release_fhandle2,
1023 .pc_argsize = sizeof(struct nfsd3_renameargs),
1024 .pc_argzero = sizeof(struct nfsd3_renameargs),
1025 .pc_ressize = sizeof(struct nfsd3_renameres),
1026 .pc_cachetype = RC_REPLBUFF,
1027 .pc_xdrressize = ST+WC+WC,
1028 .pc_name = "RENAME",
1029 },
1030 [NFS3PROC_LINK] = {
1031 .pc_func = nfsd3_proc_link,
1032 .pc_decode = nfs3svc_decode_linkargs,
1033 .pc_encode = nfs3svc_encode_linkres,
1034 .pc_release = nfs3svc_release_fhandle2,
1035 .pc_argsize = sizeof(struct nfsd3_linkargs),
1036 .pc_argzero = sizeof(struct nfsd3_linkargs),
1037 .pc_ressize = sizeof(struct nfsd3_linkres),
1038 .pc_cachetype = RC_REPLBUFF,
1039 .pc_xdrressize = ST+pAT+WC,
1040 .pc_name = "LINK",
1041 },
1042 [NFS3PROC_READDIR] = {
1043 .pc_func = nfsd3_proc_readdir,
1044 .pc_decode = nfs3svc_decode_readdirargs,
1045 .pc_encode = nfs3svc_encode_readdirres,
1046 .pc_release = nfs3svc_release_fhandle,
1047 .pc_argsize = sizeof(struct nfsd3_readdirargs),
1048 .pc_argzero = sizeof(struct nfsd3_readdirargs),
1049 .pc_ressize = sizeof(struct nfsd3_readdirres),
1050 .pc_cachetype = RC_NOCACHE,
1051 .pc_name = "READDIR",
1052 },
1053 [NFS3PROC_READDIRPLUS] = {
1054 .pc_func = nfsd3_proc_readdirplus,
1055 .pc_decode = nfs3svc_decode_readdirplusargs,
1056 .pc_encode = nfs3svc_encode_readdirres,
1057 .pc_release = nfs3svc_release_fhandle,
1058 .pc_argsize = sizeof(struct nfsd3_readdirplusargs),
1059 .pc_argzero = sizeof(struct nfsd3_readdirplusargs),
1060 .pc_ressize = sizeof(struct nfsd3_readdirres),
1061 .pc_cachetype = RC_NOCACHE,
1062 .pc_name = "READDIRPLUS",
1063 },
1064 [NFS3PROC_FSSTAT] = {
1065 .pc_func = nfsd3_proc_fsstat,
1066 .pc_decode = nfs3svc_decode_fhandleargs,
1067 .pc_encode = nfs3svc_encode_fsstatres,
1068 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
1069 .pc_argzero = sizeof(struct nfsd3_fhandleargs),
1070 .pc_ressize = sizeof(struct nfsd3_fsstatres),
1071 .pc_cachetype = RC_NOCACHE,
1072 .pc_xdrressize = ST+pAT+2*6+1,
1073 .pc_name = "FSSTAT",
1074 },
1075 [NFS3PROC_FSINFO] = {
1076 .pc_func = nfsd3_proc_fsinfo,
1077 .pc_decode = nfs3svc_decode_fhandleargs,
1078 .pc_encode = nfs3svc_encode_fsinfores,
1079 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
1080 .pc_argzero = sizeof(struct nfsd3_fhandleargs),
1081 .pc_ressize = sizeof(struct nfsd3_fsinfores),
1082 .pc_cachetype = RC_NOCACHE,
1083 .pc_xdrressize = ST+pAT+12,
1084 .pc_name = "FSINFO",
1085 },
1086 [NFS3PROC_PATHCONF] = {
1087 .pc_func = nfsd3_proc_pathconf,
1088 .pc_decode = nfs3svc_decode_fhandleargs,
1089 .pc_encode = nfs3svc_encode_pathconfres,
1090 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
1091 .pc_argzero = sizeof(struct nfsd3_fhandleargs),
1092 .pc_ressize = sizeof(struct nfsd3_pathconfres),
1093 .pc_cachetype = RC_NOCACHE,
1094 .pc_xdrressize = ST+pAT+6,
1095 .pc_name = "PATHCONF",
1096 },
1097 [NFS3PROC_COMMIT] = {
1098 .pc_func = nfsd3_proc_commit,
1099 .pc_decode = nfs3svc_decode_commitargs,
1100 .pc_encode = nfs3svc_encode_commitres,
1101 .pc_release = nfs3svc_release_fhandle,
1102 .pc_argsize = sizeof(struct nfsd3_commitargs),
1103 .pc_argzero = sizeof(struct nfsd3_commitargs),
1104 .pc_ressize = sizeof(struct nfsd3_commitres),
1105 .pc_cachetype = RC_NOCACHE,
1106 .pc_xdrressize = ST+WC+2,
1107 .pc_name = "COMMIT",
1108 },
1109 };
1110
1111 const struct svc_version nfsd_version3 = {
1112 .vs_vers = 3,
1113 .vs_nproc = ARRAY_SIZE(nfsd_procedures3),
1114 .vs_proc = nfsd_procedures3,
1115 .vs_dispatch = nfsd_dispatch,
1116 .vs_xdrsize = NFS3_SVC_XDRSIZE,
1117 };
1118