1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
24 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
25 * Copyright (c) 2012 by Delphix. All rights reserved.
26 */
27
28 /*
29 * Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
30 * All Rights Reserved
31 */
32
33 #include <sys/param.h>
34 #include <sys/types.h>
35 #include <sys/systm.h>
36 #include <sys/cred.h>
37 #include <sys/buf.h>
38 #include <sys/vfs.h>
39 #include <sys/vfs_opreg.h>
40 #include <sys/vnode.h>
41 #include <sys/uio.h>
42 #include <sys/errno.h>
43 #include <sys/sysmacros.h>
44 #include <sys/statvfs.h>
45 #include <sys/kmem.h>
46 #include <sys/dirent.h>
47 #include <sys/cmn_err.h>
48 #include <sys/debug.h>
49 #include <sys/systeminfo.h>
50 #include <sys/flock.h>
51 #include <sys/pathname.h>
52 #include <sys/nbmlock.h>
53 #include <sys/share.h>
54 #include <sys/atomic.h>
55 #include <sys/policy.h>
56 #include <sys/fem.h>
57 #include <sys/sdt.h>
58 #include <sys/ddi.h>
59 #include <sys/zone.h>
60
61 #include <fs/fs_reparse.h>
62
63 #include <rpc/types.h>
64 #include <rpc/auth.h>
65 #include <rpc/rpcsec_gss.h>
66 #include <rpc/svc.h>
67
68 #include <nfs/nfs.h>
69 #include <nfs/export.h>
70 #include <nfs/nfs_cmd.h>
71 #include <nfs/lm.h>
72 #include <nfs/nfs4.h>
73
74 #include <sys/strsubr.h>
75 #include <sys/strsun.h>
76
77 #include <inet/common.h>
78 #include <inet/ip.h>
79 #include <inet/ip6.h>
80
81 #include <sys/tsol/label.h>
82 #include <sys/tsol/tndb.h>
83
84 #define RFS4_MAXLOCK_TRIES 4 /* Try to get the lock this many times */
85 static int rfs4_maxlock_tries = RFS4_MAXLOCK_TRIES;
86 #define RFS4_LOCK_DELAY 10 /* Milliseconds */
87 static clock_t rfs4_lock_delay = RFS4_LOCK_DELAY;
88 extern struct svc_ops rdma_svc_ops;
89 extern int nfs_loaned_buffers;
90 /* End of Tunables */
91
92 static int rdma_setup_read_data4(READ4args *, READ4res *);
93
94 /*
95 * Used to bump the stateid4.seqid value and show changes in the stateid
96 */
97 #define next_stateid(sp) (++(sp)->bits.chgseq)
98
99 /*
100 * RFS4_MINLEN_ENTRY4: XDR-encoded size of smallest possible dirent.
101 * This is used to return NFS4ERR_TOOSMALL when clients specify
102 * maxcount that isn't large enough to hold the smallest possible
103 * XDR encoded dirent.
104 *
105 * sizeof cookie (8 bytes) +
106 * sizeof name_len (4 bytes) +
107 * sizeof smallest (padded) name (4 bytes) +
108 * sizeof bitmap4_len (12 bytes) + NOTE: we always encode len=2 bm4
109 * sizeof attrlist4_len (4 bytes) +
110 * sizeof next boolean (4 bytes)
111 *
112 * RFS4_MINLEN_RDDIR4: XDR-encoded size of READDIR op reply containing
113 * the smallest possible entry4 (assumes no attrs requested).
114 * sizeof nfsstat4 (4 bytes) +
115 * sizeof verifier4 (8 bytes) +
116 * sizeof entry4list bool (4 bytes) +
117 * sizeof entry4 (36 bytes) +
118 * sizeof eof bool (4 bytes)
119 *
120 * RFS4_MINLEN_RDDIR_BUF: minimum length of buffer server will provide to
121 * VOP_READDIR. Its value is the size of the maximum possible dirent
122 * for solaris. The DIRENT64_RECLEN macro returns the size of dirent
123 * required for a given name length. MAXNAMELEN is the maximum
124 * filename length allowed in Solaris. The first two DIRENT64_RECLEN()
125 * macros are to allow for . and .. entries -- just a minor tweak to try
126 * and guarantee that buffer we give to VOP_READDIR will be large enough
127 * to hold ., .., and the largest possible solaris dirent64.
128 */
129 #define RFS4_MINLEN_ENTRY4 36
130 #define RFS4_MINLEN_RDDIR4 (4 + NFS4_VERIFIER_SIZE + 4 + RFS4_MINLEN_ENTRY4 + 4)
131 #define RFS4_MINLEN_RDDIR_BUF \
132 (DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2) + DIRENT64_RECLEN(MAXNAMELEN))
133
134 /*
135 * It would be better to pad to 4 bytes since that's what XDR would do,
136 * but the dirents UFS gives us are already padded to 8, so just take
137 * what we're given. Dircount is only a hint anyway. Currently the
138 * solaris kernel is ASCII only, so there's no point in calling the
139 * UTF8 functions.
140 *
141 * dirent64: named padded to provide 8 byte struct alignment
142 * d_ino(8) + d_off(8) + d_reclen(2) + d_name(namelen + null(1) + pad)
143 *
144 * cookie: uint64_t + utf8namelen: uint_t + utf8name padded to 8 bytes
145 *
146 */
147 #define DIRENT64_TO_DIRCOUNT(dp) \
148 (3 * BYTES_PER_XDR_UNIT + DIRENT64_NAMELEN((dp)->d_reclen))
149
150 time_t rfs4_start_time; /* Initialized in rfs4_srvrinit */
151
152 static sysid_t lockt_sysid; /* dummy sysid for all LOCKT calls */
153
154 u_longlong_t nfs4_srv_caller_id;
155 uint_t nfs4_srv_vkey = 0;
156
157 verifier4 Write4verf;
158 verifier4 Readdir4verf;
159
160 void rfs4_init_compound_state(struct compound_state *);
161
162 static void nullfree(caddr_t);
163 static void rfs4_op_inval(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
164 struct compound_state *);
165 static void rfs4_op_access(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
166 struct compound_state *);
167 static void rfs4_op_close(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
168 struct compound_state *);
169 static void rfs4_op_commit(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
170 struct compound_state *);
171 static void rfs4_op_create(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
172 struct compound_state *);
173 static void rfs4_op_create_free(nfs_resop4 *resop);
174 static void rfs4_op_delegreturn(nfs_argop4 *, nfs_resop4 *,
175 struct svc_req *, struct compound_state *);
176 static void rfs4_op_delegpurge(nfs_argop4 *, nfs_resop4 *,
177 struct svc_req *, struct compound_state *);
178 static void rfs4_op_getattr(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
179 struct compound_state *);
180 static void rfs4_op_getattr_free(nfs_resop4 *);
181 static void rfs4_op_getfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
182 struct compound_state *);
183 static void rfs4_op_getfh_free(nfs_resop4 *);
184 static void rfs4_op_illegal(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
185 struct compound_state *);
186 static void rfs4_op_link(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
187 struct compound_state *);
188 static void rfs4_op_lock(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
189 struct compound_state *);
190 static void lock_denied_free(nfs_resop4 *);
191 static void rfs4_op_locku(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
192 struct compound_state *);
193 static void rfs4_op_lockt(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
194 struct compound_state *);
195 static void rfs4_op_lookup(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
196 struct compound_state *);
197 static void rfs4_op_lookupp(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
198 struct compound_state *);
199 static void rfs4_op_openattr(nfs_argop4 *argop, nfs_resop4 *resop,
200 struct svc_req *req, struct compound_state *cs);
201 static void rfs4_op_nverify(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
202 struct compound_state *);
203 static void rfs4_op_open(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
204 struct compound_state *);
205 static void rfs4_op_open_confirm(nfs_argop4 *, nfs_resop4 *,
206 struct svc_req *, struct compound_state *);
207 static void rfs4_op_open_downgrade(nfs_argop4 *, nfs_resop4 *,
208 struct svc_req *, struct compound_state *);
209 static void rfs4_op_putfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
210 struct compound_state *);
211 static void rfs4_op_putpubfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
212 struct compound_state *);
213 static void rfs4_op_putrootfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
214 struct compound_state *);
215 static void rfs4_op_read(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
216 struct compound_state *);
217 static void rfs4_op_read_free(nfs_resop4 *);
218 static void rfs4_op_readdir_free(nfs_resop4 *resop);
219 static void rfs4_op_readlink(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
220 struct compound_state *);
221 static void rfs4_op_readlink_free(nfs_resop4 *);
222 static void rfs4_op_release_lockowner(nfs_argop4 *, nfs_resop4 *,
223 struct svc_req *, struct compound_state *);
224 static void rfs4_op_remove(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
225 struct compound_state *);
226 static void rfs4_op_rename(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
227 struct compound_state *);
228 static void rfs4_op_renew(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
229 struct compound_state *);
230 static void rfs4_op_restorefh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
231 struct compound_state *);
232 static void rfs4_op_savefh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
233 struct compound_state *);
234 static void rfs4_op_setattr(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
235 struct compound_state *);
236 static void rfs4_op_verify(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
237 struct compound_state *);
238 static void rfs4_op_write(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
239 struct compound_state *);
240 static void rfs4_op_setclientid(nfs_argop4 *, nfs_resop4 *,
241 struct svc_req *, struct compound_state *);
242 static void rfs4_op_setclientid_confirm(nfs_argop4 *, nfs_resop4 *,
243 struct svc_req *req, struct compound_state *);
244 static void rfs4_op_secinfo(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
245 struct compound_state *);
246 static void rfs4_op_secinfo_free(nfs_resop4 *);
247
248 static nfsstat4 check_open_access(uint32_t,
249 struct compound_state *, struct svc_req *);
250 nfsstat4 rfs4_client_sysid(rfs4_client_t *, sysid_t *);
251 void rfs4_ss_clid(rfs4_client_t *);
252
253 /*
254 * translation table for attrs
255 */
256 struct nfs4_ntov_table {
257 union nfs4_attr_u *na;
258 uint8_t amap[NFS4_MAXNUM_ATTRS];
259 int attrcnt;
260 bool_t vfsstat;
261 };
262
263 static void nfs4_ntov_table_init(struct nfs4_ntov_table *ntovp);
264 static void nfs4_ntov_table_free(struct nfs4_ntov_table *ntovp,
265 struct nfs4_svgetit_arg *sargp);
266
267 static nfsstat4 do_rfs4_set_attrs(bitmap4 *resp, fattr4 *fattrp,
268 struct compound_state *cs, struct nfs4_svgetit_arg *sargp,
269 struct nfs4_ntov_table *ntovp, nfs4_attr_cmd_t cmd);
270
271 fem_t *deleg_rdops;
272 fem_t *deleg_wrops;
273
274 rfs4_servinst_t *rfs4_cur_servinst = NULL; /* current server instance */
275 kmutex_t rfs4_servinst_lock; /* protects linked list */
276 int rfs4_seen_first_compound; /* set first time we see one */
277
278 /*
279 * NFS4 op dispatch table
280 */
281
282 struct rfsv4disp {
283 void (*dis_proc)(); /* proc to call */
284 void (*dis_resfree)(); /* frees space allocated by proc */
285 int dis_flags; /* RPC_IDEMPOTENT, etc... */
286 };
287
288 static struct rfsv4disp rfsv4disptab[] = {
289 /*
290 * NFS VERSION 4
291 */
292
293 /* RFS_NULL = 0 */
294 {rfs4_op_illegal, nullfree, 0},
295
296 /* UNUSED = 1 */
297 {rfs4_op_illegal, nullfree, 0},
298
299 /* UNUSED = 2 */
300 {rfs4_op_illegal, nullfree, 0},
301
302 /* OP_ACCESS = 3 */
303 {rfs4_op_access, nullfree, RPC_IDEMPOTENT},
304
305 /* OP_CLOSE = 4 */
306 {rfs4_op_close, nullfree, 0},
307
308 /* OP_COMMIT = 5 */
309 {rfs4_op_commit, nullfree, RPC_IDEMPOTENT},
310
311 /* OP_CREATE = 6 */
312 {rfs4_op_create, nullfree, 0},
313
314 /* OP_DELEGPURGE = 7 */
315 {rfs4_op_delegpurge, nullfree, 0},
316
317 /* OP_DELEGRETURN = 8 */
318 {rfs4_op_delegreturn, nullfree, 0},
319
320 /* OP_GETATTR = 9 */
321 {rfs4_op_getattr, rfs4_op_getattr_free, RPC_IDEMPOTENT},
322
323 /* OP_GETFH = 10 */
324 {rfs4_op_getfh, rfs4_op_getfh_free, RPC_ALL},
325
326 /* OP_LINK = 11 */
327 {rfs4_op_link, nullfree, 0},
328
329 /* OP_LOCK = 12 */
330 {rfs4_op_lock, lock_denied_free, 0},
331
332 /* OP_LOCKT = 13 */
333 {rfs4_op_lockt, lock_denied_free, 0},
334
335 /* OP_LOCKU = 14 */
336 {rfs4_op_locku, nullfree, 0},
337
338 /* OP_LOOKUP = 15 */
339 {rfs4_op_lookup, nullfree, (RPC_IDEMPOTENT | RPC_PUBLICFH_OK)},
340
341 /* OP_LOOKUPP = 16 */
342 {rfs4_op_lookupp, nullfree, (RPC_IDEMPOTENT | RPC_PUBLICFH_OK)},
343
344 /* OP_NVERIFY = 17 */
345 {rfs4_op_nverify, nullfree, RPC_IDEMPOTENT},
346
347 /* OP_OPEN = 18 */
348 {rfs4_op_open, rfs4_free_reply, 0},
349
350 /* OP_OPENATTR = 19 */
351 {rfs4_op_openattr, nullfree, 0},
352
353 /* OP_OPEN_CONFIRM = 20 */
354 {rfs4_op_open_confirm, nullfree, 0},
355
356 /* OP_OPEN_DOWNGRADE = 21 */
357 {rfs4_op_open_downgrade, nullfree, 0},
358
359 /* OP_OPEN_PUTFH = 22 */
360 {rfs4_op_putfh, nullfree, RPC_ALL},
361
362 /* OP_PUTPUBFH = 23 */
363 {rfs4_op_putpubfh, nullfree, RPC_ALL},
364
365 /* OP_PUTROOTFH = 24 */
366 {rfs4_op_putrootfh, nullfree, RPC_ALL},
367
368 /* OP_READ = 25 */
369 {rfs4_op_read, rfs4_op_read_free, RPC_IDEMPOTENT},
370
371 /* OP_READDIR = 26 */
372 {rfs4_op_readdir, rfs4_op_readdir_free, RPC_IDEMPOTENT},
373
374 /* OP_READLINK = 27 */
375 {rfs4_op_readlink, rfs4_op_readlink_free, RPC_IDEMPOTENT},
376
377 /* OP_REMOVE = 28 */
378 {rfs4_op_remove, nullfree, 0},
379
380 /* OP_RENAME = 29 */
381 {rfs4_op_rename, nullfree, 0},
382
383 /* OP_RENEW = 30 */
384 {rfs4_op_renew, nullfree, 0},
385
386 /* OP_RESTOREFH = 31 */
387 {rfs4_op_restorefh, nullfree, RPC_ALL},
388
389 /* OP_SAVEFH = 32 */
390 {rfs4_op_savefh, nullfree, RPC_ALL},
391
392 /* OP_SECINFO = 33 */
393 {rfs4_op_secinfo, rfs4_op_secinfo_free, 0},
394
395 /* OP_SETATTR = 34 */
396 {rfs4_op_setattr, nullfree, 0},
397
398 /* OP_SETCLIENTID = 35 */
399 {rfs4_op_setclientid, nullfree, 0},
400
401 /* OP_SETCLIENTID_CONFIRM = 36 */
402 {rfs4_op_setclientid_confirm, nullfree, 0},
403
404 /* OP_VERIFY = 37 */
405 {rfs4_op_verify, nullfree, RPC_IDEMPOTENT},
406
407 /* OP_WRITE = 38 */
408 {rfs4_op_write, nullfree, 0},
409
410 /* OP_RELEASE_LOCKOWNER = 39 */
411 {rfs4_op_release_lockowner, nullfree, 0},
412 };
413
414 static uint_t rfsv4disp_cnt = sizeof (rfsv4disptab) / sizeof (rfsv4disptab[0]);
415
416 #define OP_ILLEGAL_IDX (rfsv4disp_cnt)
417
418 #ifdef DEBUG
419
420 int rfs4_fillone_debug = 0;
421 int rfs4_no_stub_access = 1;
422 int rfs4_rddir_debug = 0;
423
424 static char *rfs4_op_string[] = {
425 "rfs4_op_null",
426 "rfs4_op_1 unused",
427 "rfs4_op_2 unused",
428 "rfs4_op_access",
429 "rfs4_op_close",
430 "rfs4_op_commit",
431 "rfs4_op_create",
432 "rfs4_op_delegpurge",
433 "rfs4_op_delegreturn",
434 "rfs4_op_getattr",
435 "rfs4_op_getfh",
436 "rfs4_op_link",
437 "rfs4_op_lock",
438 "rfs4_op_lockt",
439 "rfs4_op_locku",
440 "rfs4_op_lookup",
441 "rfs4_op_lookupp",
442 "rfs4_op_nverify",
443 "rfs4_op_open",
444 "rfs4_op_openattr",
445 "rfs4_op_open_confirm",
446 "rfs4_op_open_downgrade",
447 "rfs4_op_putfh",
448 "rfs4_op_putpubfh",
449 "rfs4_op_putrootfh",
450 "rfs4_op_read",
451 "rfs4_op_readdir",
452 "rfs4_op_readlink",
453 "rfs4_op_remove",
454 "rfs4_op_rename",
455 "rfs4_op_renew",
456 "rfs4_op_restorefh",
457 "rfs4_op_savefh",
458 "rfs4_op_secinfo",
459 "rfs4_op_setattr",
460 "rfs4_op_setclientid",
461 "rfs4_op_setclient_confirm",
462 "rfs4_op_verify",
463 "rfs4_op_write",
464 "rfs4_op_release_lockowner",
465 "rfs4_op_illegal"
466 };
467 #endif
468
469 void rfs4_ss_chkclid(rfs4_client_t *);
470
471 extern size_t strlcpy(char *dst, const char *src, size_t dstsize);
472
473 extern void rfs4_free_fs_locations4(fs_locations4 *);
474
475 #ifdef nextdp
476 #undef nextdp
477 #endif
478 #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
479
480 static const fs_operation_def_t nfs4_rd_deleg_tmpl[] = {
481 VOPNAME_OPEN, { .femop_open = deleg_rd_open },
482 VOPNAME_WRITE, { .femop_write = deleg_rd_write },
483 VOPNAME_SETATTR, { .femop_setattr = deleg_rd_setattr },
484 VOPNAME_RWLOCK, { .femop_rwlock = deleg_rd_rwlock },
485 VOPNAME_SPACE, { .femop_space = deleg_rd_space },
486 VOPNAME_SETSECATTR, { .femop_setsecattr = deleg_rd_setsecattr },
487 VOPNAME_VNEVENT, { .femop_vnevent = deleg_rd_vnevent },
488 NULL, NULL
489 };
490 static const fs_operation_def_t nfs4_wr_deleg_tmpl[] = {
491 VOPNAME_OPEN, { .femop_open = deleg_wr_open },
492 VOPNAME_READ, { .femop_read = deleg_wr_read },
493 VOPNAME_WRITE, { .femop_write = deleg_wr_write },
494 VOPNAME_SETATTR, { .femop_setattr = deleg_wr_setattr },
495 VOPNAME_RWLOCK, { .femop_rwlock = deleg_wr_rwlock },
496 VOPNAME_SPACE, { .femop_space = deleg_wr_space },
497 VOPNAME_SETSECATTR, { .femop_setsecattr = deleg_wr_setsecattr },
498 VOPNAME_VNEVENT, { .femop_vnevent = deleg_wr_vnevent },
499 NULL, NULL
500 };
501
502 int
rfs4_srvrinit(void)503 rfs4_srvrinit(void)
504 {
505 timespec32_t verf;
506 int error;
507 extern void rfs4_attr_init();
508 extern krwlock_t rfs4_deleg_policy_lock;
509
510 /*
511 * The following algorithm attempts to find a unique verifier
512 * to be used as the write verifier returned from the server
513 * to the client. It is important that this verifier change
514 * whenever the server reboots. Of secondary importance, it
515 * is important for the verifier to be unique between two
516 * different servers.
517 *
518 * Thus, an attempt is made to use the system hostid and the
519 * current time in seconds when the nfssrv kernel module is
520 * loaded. It is assumed that an NFS server will not be able
521 * to boot and then to reboot in less than a second. If the
522 * hostid has not been set, then the current high resolution
523 * time is used. This will ensure different verifiers each
524 * time the server reboots and minimize the chances that two
525 * different servers will have the same verifier.
526 * XXX - this is broken on LP64 kernels.
527 */
528 verf.tv_sec = (time_t)zone_get_hostid(NULL);
529 if (verf.tv_sec != 0) {
530 verf.tv_nsec = gethrestime_sec();
531 } else {
532 timespec_t tverf;
533
534 gethrestime(&tverf);
535 verf.tv_sec = (time_t)tverf.tv_sec;
536 verf.tv_nsec = tverf.tv_nsec;
537 }
538
539 Write4verf = *(uint64_t *)&verf;
540
541 rfs4_attr_init();
542 mutex_init(&rfs4_deleg_lock, NULL, MUTEX_DEFAULT, NULL);
543
544 /* Used to manage create/destroy of server state */
545 mutex_init(&rfs4_state_lock, NULL, MUTEX_DEFAULT, NULL);
546
547 /* Used to manage access to server instance linked list */
548 mutex_init(&rfs4_servinst_lock, NULL, MUTEX_DEFAULT, NULL);
549
550 /* Used to manage access to rfs4_deleg_policy */
551 rw_init(&rfs4_deleg_policy_lock, NULL, RW_DEFAULT, NULL);
552
553 error = fem_create("deleg_rdops", nfs4_rd_deleg_tmpl, &deleg_rdops);
554 if (error != 0) {
555 rfs4_disable_delegation();
556 } else {
557 error = fem_create("deleg_wrops", nfs4_wr_deleg_tmpl,
558 &deleg_wrops);
559 if (error != 0) {
560 rfs4_disable_delegation();
561 fem_free(deleg_rdops);
562 }
563 }
564
565 nfs4_srv_caller_id = fs_new_caller_id();
566
567 lockt_sysid = lm_alloc_sysidt();
568
569 vsd_create(&nfs4_srv_vkey, NULL);
570
571 return (0);
572 }
573
574 void
rfs4_srvrfini(void)575 rfs4_srvrfini(void)
576 {
577 extern krwlock_t rfs4_deleg_policy_lock;
578
579 if (lockt_sysid != LM_NOSYSID) {
580 lm_free_sysidt(lockt_sysid);
581 lockt_sysid = LM_NOSYSID;
582 }
583
584 mutex_destroy(&rfs4_deleg_lock);
585 mutex_destroy(&rfs4_state_lock);
586 rw_destroy(&rfs4_deleg_policy_lock);
587
588 fem_free(deleg_rdops);
589 fem_free(deleg_wrops);
590 }
591
592 void
rfs4_init_compound_state(struct compound_state * cs)593 rfs4_init_compound_state(struct compound_state *cs)
594 {
595 bzero(cs, sizeof (*cs));
596 cs->cont = TRUE;
597 cs->access = CS_ACCESS_DENIED;
598 cs->deleg = FALSE;
599 cs->mandlock = FALSE;
600 cs->fh.nfs_fh4_val = cs->fhbuf;
601 }
602
603 void
rfs4_grace_start(rfs4_servinst_t * sip)604 rfs4_grace_start(rfs4_servinst_t *sip)
605 {
606 rw_enter(&sip->rwlock, RW_WRITER);
607 sip->start_time = (time_t)TICK_TO_SEC(ddi_get_lbolt());
608 sip->grace_period = rfs4_grace_period;
609 rw_exit(&sip->rwlock);
610 }
611
612 /*
613 * returns true if the instance's grace period has never been started
614 */
615 int
rfs4_servinst_grace_new(rfs4_servinst_t * sip)616 rfs4_servinst_grace_new(rfs4_servinst_t *sip)
617 {
618 time_t start_time;
619
620 rw_enter(&sip->rwlock, RW_READER);
621 start_time = sip->start_time;
622 rw_exit(&sip->rwlock);
623
624 return (start_time == 0);
625 }
626
627 /*
628 * Indicates if server instance is within the
629 * grace period.
630 */
631 int
rfs4_servinst_in_grace(rfs4_servinst_t * sip)632 rfs4_servinst_in_grace(rfs4_servinst_t *sip)
633 {
634 time_t grace_expiry;
635
636 rw_enter(&sip->rwlock, RW_READER);
637 grace_expiry = sip->start_time + sip->grace_period;
638 rw_exit(&sip->rwlock);
639
640 return (((time_t)TICK_TO_SEC(ddi_get_lbolt())) < grace_expiry);
641 }
642
643 int
rfs4_clnt_in_grace(rfs4_client_t * cp)644 rfs4_clnt_in_grace(rfs4_client_t *cp)
645 {
646 ASSERT(rfs4_dbe_refcnt(cp->rc_dbe) > 0);
647
648 return (rfs4_servinst_in_grace(cp->rc_server_instance));
649 }
650
651 /*
652 * reset all currently active grace periods
653 */
654 void
rfs4_grace_reset_all(void)655 rfs4_grace_reset_all(void)
656 {
657 rfs4_servinst_t *sip;
658
659 mutex_enter(&rfs4_servinst_lock);
660 for (sip = rfs4_cur_servinst; sip != NULL; sip = sip->prev)
661 if (rfs4_servinst_in_grace(sip))
662 rfs4_grace_start(sip);
663 mutex_exit(&rfs4_servinst_lock);
664 }
665
666 /*
667 * start any new instances' grace periods
668 */
669 void
rfs4_grace_start_new(void)670 rfs4_grace_start_new(void)
671 {
672 rfs4_servinst_t *sip;
673
674 mutex_enter(&rfs4_servinst_lock);
675 for (sip = rfs4_cur_servinst; sip != NULL; sip = sip->prev)
676 if (rfs4_servinst_grace_new(sip))
677 rfs4_grace_start(sip);
678 mutex_exit(&rfs4_servinst_lock);
679 }
680
681 static rfs4_dss_path_t *
rfs4_dss_newpath(rfs4_servinst_t * sip,char * path,unsigned index)682 rfs4_dss_newpath(rfs4_servinst_t *sip, char *path, unsigned index)
683 {
684 size_t len;
685 rfs4_dss_path_t *dss_path;
686
687 dss_path = kmem_alloc(sizeof (rfs4_dss_path_t), KM_SLEEP);
688
689 /*
690 * Take a copy of the string, since the original may be overwritten.
691 * Sadly, no strdup() in the kernel.
692 */
693 /* allow for NUL */
694 len = strlen(path) + 1;
695 dss_path->path = kmem_alloc(len, KM_SLEEP);
696 (void) strlcpy(dss_path->path, path, len);
697
698 /* associate with servinst */
699 dss_path->sip = sip;
700 dss_path->index = index;
701
702 /*
703 * Add to list of served paths.
704 * No locking required, as we're only ever called at startup.
705 */
706 if (rfs4_dss_pathlist == NULL) {
707 /* this is the first dss_path_t */
708
709 /* needed for insque/remque */
710 dss_path->next = dss_path->prev = dss_path;
711
712 rfs4_dss_pathlist = dss_path;
713 } else {
714 insque(dss_path, rfs4_dss_pathlist);
715 }
716
717 return (dss_path);
718 }
719
720 /*
721 * Create a new server instance, and make it the currently active instance.
722 * Note that starting the grace period too early will reduce the clients'
723 * recovery window.
724 */
725 void
rfs4_servinst_create(int start_grace,int dss_npaths,char ** dss_paths)726 rfs4_servinst_create(int start_grace, int dss_npaths, char **dss_paths)
727 {
728 unsigned i;
729 rfs4_servinst_t *sip;
730 rfs4_oldstate_t *oldstate;
731
732 sip = kmem_alloc(sizeof (rfs4_servinst_t), KM_SLEEP);
733 rw_init(&sip->rwlock, NULL, RW_DEFAULT, NULL);
734
735 sip->start_time = (time_t)0;
736 sip->grace_period = (time_t)0;
737 sip->next = NULL;
738 sip->prev = NULL;
739
740 rw_init(&sip->oldstate_lock, NULL, RW_DEFAULT, NULL);
741 /*
742 * This initial dummy entry is required to setup for insque/remque.
743 * It must be skipped over whenever the list is traversed.
744 */
745 oldstate = kmem_alloc(sizeof (rfs4_oldstate_t), KM_SLEEP);
746 /* insque/remque require initial list entry to be self-terminated */
747 oldstate->next = oldstate;
748 oldstate->prev = oldstate;
749 sip->oldstate = oldstate;
750
751
752 sip->dss_npaths = dss_npaths;
753 sip->dss_paths = kmem_alloc(dss_npaths *
754 sizeof (rfs4_dss_path_t *), KM_SLEEP);
755
756 for (i = 0; i < dss_npaths; i++) {
757 sip->dss_paths[i] = rfs4_dss_newpath(sip, dss_paths[i], i);
758 }
759
760 mutex_enter(&rfs4_servinst_lock);
761 if (rfs4_cur_servinst != NULL) {
762 /* add to linked list */
763 sip->prev = rfs4_cur_servinst;
764 rfs4_cur_servinst->next = sip;
765 }
766 if (start_grace)
767 rfs4_grace_start(sip);
768 /* make the new instance "current" */
769 rfs4_cur_servinst = sip;
770
771 mutex_exit(&rfs4_servinst_lock);
772 }
773
774 /*
775 * In future, we might add a rfs4_servinst_destroy(sip) but, for now, destroy
776 * all instances directly.
777 */
778 void
rfs4_servinst_destroy_all(void)779 rfs4_servinst_destroy_all(void)
780 {
781 rfs4_servinst_t *sip, *prev, *current;
782 #ifdef DEBUG
783 int n = 0;
784 #endif
785
786 mutex_enter(&rfs4_servinst_lock);
787 ASSERT(rfs4_cur_servinst != NULL);
788 current = rfs4_cur_servinst;
789 rfs4_cur_servinst = NULL;
790 for (sip = current; sip != NULL; sip = prev) {
791 prev = sip->prev;
792 rw_destroy(&sip->rwlock);
793 if (sip->oldstate)
794 kmem_free(sip->oldstate, sizeof (rfs4_oldstate_t));
795 if (sip->dss_paths)
796 kmem_free(sip->dss_paths,
797 sip->dss_npaths * sizeof (rfs4_dss_path_t *));
798 kmem_free(sip, sizeof (rfs4_servinst_t));
799 #ifdef DEBUG
800 n++;
801 #endif
802 }
803 mutex_exit(&rfs4_servinst_lock);
804 }
805
806 /*
807 * Assign the current server instance to a client_t.
808 * Should be called with cp->rc_dbe held.
809 */
810 void
rfs4_servinst_assign(rfs4_client_t * cp,rfs4_servinst_t * sip)811 rfs4_servinst_assign(rfs4_client_t *cp, rfs4_servinst_t *sip)
812 {
813 ASSERT(rfs4_dbe_refcnt(cp->rc_dbe) > 0);
814
815 /*
816 * The lock ensures that if the current instance is in the process
817 * of changing, we will see the new one.
818 */
819 mutex_enter(&rfs4_servinst_lock);
820 cp->rc_server_instance = sip;
821 mutex_exit(&rfs4_servinst_lock);
822 }
823
824 rfs4_servinst_t *
rfs4_servinst(rfs4_client_t * cp)825 rfs4_servinst(rfs4_client_t *cp)
826 {
827 ASSERT(rfs4_dbe_refcnt(cp->rc_dbe) > 0);
828
829 return (cp->rc_server_instance);
830 }
831
832 /* ARGSUSED */
833 static void
nullfree(caddr_t resop)834 nullfree(caddr_t resop)
835 {
836 }
837
838 /*
839 * This is a fall-through for invalid or not implemented (yet) ops
840 */
841 /* ARGSUSED */
842 static void
rfs4_op_inval(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)843 rfs4_op_inval(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
844 struct compound_state *cs)
845 {
846 *cs->statusp = *((nfsstat4 *)&(resop)->nfs_resop4_u) = NFS4ERR_INVAL;
847 }
848
849 /*
850 * Check if the security flavor, nfsnum, is in the flavor_list.
851 */
852 bool_t
in_flavor_list(int nfsnum,int * flavor_list,int count)853 in_flavor_list(int nfsnum, int *flavor_list, int count)
854 {
855 int i;
856
857 for (i = 0; i < count; i++) {
858 if (nfsnum == flavor_list[i])
859 return (TRUE);
860 }
861 return (FALSE);
862 }
863
864 /*
865 * Used by rfs4_op_secinfo to get the security information from the
866 * export structure associated with the component.
867 */
868 /* ARGSUSED */
869 static nfsstat4
do_rfs4_op_secinfo(struct compound_state * cs,char * nm,SECINFO4res * resp)870 do_rfs4_op_secinfo(struct compound_state *cs, char *nm, SECINFO4res *resp)
871 {
872 int error, different_export = 0;
873 vnode_t *dvp, *vp;
874 struct exportinfo *exi = NULL;
875 struct exportinfo *oexi = NULL;
876 fid_t fid;
877 uint_t count, i;
878 secinfo4 *resok_val;
879 struct secinfo *secp;
880 seconfig_t *si;
881 bool_t did_traverse = FALSE;
882 int dotdot, walk;
883
884 dvp = cs->vp;
885 dotdot = (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0');
886
887 /*
888 * If dotdotting, then need to check whether it's above the
889 * root of a filesystem, or above an export point.
890 */
891 if (dotdot) {
892
893 /*
894 * If dotdotting at the root of a filesystem, then
895 * need to traverse back to the mounted-on filesystem
896 * and do the dotdot lookup there.
897 */
898 if (cs->vp->v_flag & VROOT) {
899
900 /*
901 * If at the system root, then can
902 * go up no further.
903 */
904 if (VN_CMP(dvp, rootdir))
905 return (puterrno4(ENOENT));
906
907 /*
908 * Traverse back to the mounted-on filesystem
909 */
910 dvp = untraverse(cs->vp);
911
912 /*
913 * Set the different_export flag so we remember
914 * to pick up a new exportinfo entry for
915 * this new filesystem.
916 */
917 different_export = 1;
918 } else {
919
920 /*
921 * If dotdotting above an export point then set
922 * the different_export to get new export info.
923 */
924 different_export = nfs_exported(cs->exi, cs->vp);
925 }
926 }
927
928 /*
929 * Get the vnode for the component "nm".
930 */
931 error = VOP_LOOKUP(dvp, nm, &vp, NULL, 0, NULL, cs->cr,
932 NULL, NULL, NULL);
933 if (error)
934 return (puterrno4(error));
935
936 /*
937 * If the vnode is in a pseudo filesystem, or if the security flavor
938 * used in the request is valid but not an explicitly shared flavor,
939 * or the access bit indicates that this is a limited access,
940 * check whether this vnode is visible.
941 */
942 if (!different_export &&
943 (PSEUDO(cs->exi) || ! is_exported_sec(cs->nfsflavor, cs->exi) ||
944 cs->access & CS_ACCESS_LIMITED)) {
945 if (! nfs_visible(cs->exi, vp, &different_export)) {
946 VN_RELE(vp);
947 return (puterrno4(ENOENT));
948 }
949 }
950
951 /*
952 * If it's a mountpoint, then traverse it.
953 */
954 if (vn_ismntpt(vp)) {
955 if ((error = traverse(&vp)) != 0) {
956 VN_RELE(vp);
957 return (puterrno4(error));
958 }
959 /* remember that we had to traverse mountpoint */
960 did_traverse = TRUE;
961 different_export = 1;
962 } else if (vp->v_vfsp != dvp->v_vfsp) {
963 /*
964 * If vp isn't a mountpoint and the vfs ptrs aren't the same,
965 * then vp is probably an LOFS object. We don't need the
966 * realvp, we just need to know that we might have crossed
967 * a server fs boundary and need to call checkexport.
968 * (LOFS lookup hides server fs mountpoints, and actually calls
969 * traverse)
970 */
971 different_export = 1;
972 }
973
974 /*
975 * Get the export information for it.
976 */
977 if (different_export) {
978
979 bzero(&fid, sizeof (fid));
980 fid.fid_len = MAXFIDSZ;
981 error = vop_fid_pseudo(vp, &fid);
982 if (error) {
983 VN_RELE(vp);
984 return (puterrno4(error));
985 }
986
987 if (dotdot)
988 oexi = nfs_vptoexi(NULL, vp, cs->cr, &walk, NULL, TRUE);
989 else
990 oexi = checkexport(&vp->v_vfsp->vfs_fsid, &fid, vp);
991
992 if (oexi == NULL) {
993 if (did_traverse == TRUE) {
994 /*
995 * If this vnode is a mounted-on vnode,
996 * but the mounted-on file system is not
997 * exported, send back the secinfo for
998 * the exported node that the mounted-on
999 * vnode lives in.
1000 */
1001 exi = cs->exi;
1002 } else {
1003 VN_RELE(vp);
1004 return (puterrno4(EACCES));
1005 }
1006 } else {
1007 exi = oexi;
1008 }
1009 } else {
1010 exi = cs->exi;
1011 }
1012 ASSERT(exi != NULL);
1013
1014
1015 /*
1016 * Create the secinfo result based on the security information
1017 * from the exportinfo structure (exi).
1018 *
1019 * Return all flavors for a pseudo node.
1020 * For a real export node, return the flavor that the client
1021 * has access with.
1022 */
1023 rw_enter(&exported_lock, RW_READER);
1024 if (PSEUDO(exi)) {
1025 count = exi->exi_export.ex_seccnt; /* total sec count */
1026 resok_val = kmem_alloc(count * sizeof (secinfo4), KM_SLEEP);
1027 secp = exi->exi_export.ex_secinfo;
1028
1029 for (i = 0; i < count; i++) {
1030 si = &secp[i].s_secinfo;
1031 resok_val[i].flavor = si->sc_rpcnum;
1032 if (resok_val[i].flavor == RPCSEC_GSS) {
1033 rpcsec_gss_info *info;
1034
1035 info = &resok_val[i].flavor_info;
1036 info->qop = si->sc_qop;
1037 info->service = (rpc_gss_svc_t)si->sc_service;
1038
1039 /* get oid opaque data */
1040 info->oid.sec_oid4_len =
1041 si->sc_gss_mech_type->length;
1042 info->oid.sec_oid4_val = kmem_alloc(
1043 si->sc_gss_mech_type->length, KM_SLEEP);
1044 bcopy(
1045 si->sc_gss_mech_type->elements,
1046 info->oid.sec_oid4_val,
1047 info->oid.sec_oid4_len);
1048 }
1049 }
1050 resp->SECINFO4resok_len = count;
1051 resp->SECINFO4resok_val = resok_val;
1052 } else {
1053 int ret_cnt = 0, k = 0;
1054 int *flavor_list;
1055
1056 count = exi->exi_export.ex_seccnt; /* total sec count */
1057 secp = exi->exi_export.ex_secinfo;
1058
1059 flavor_list = kmem_alloc(count * sizeof (int), KM_SLEEP);
1060 /* find out which flavors to return */
1061 for (i = 0; i < count; i ++) {
1062 int access, flavor, perm;
1063
1064 flavor = secp[i].s_secinfo.sc_nfsnum;
1065 perm = secp[i].s_flags;
1066
1067 access = nfsauth4_secinfo_access(exi, cs->req,
1068 flavor, perm, cs->basecr);
1069
1070 if (! (access & NFSAUTH_DENIED) &&
1071 ! (access & NFSAUTH_WRONGSEC)) {
1072 flavor_list[ret_cnt] = flavor;
1073 ret_cnt++;
1074 }
1075 }
1076
1077 /* Create the returning SECINFO value */
1078 resok_val = kmem_alloc(ret_cnt * sizeof (secinfo4), KM_SLEEP);
1079
1080 for (i = 0; i < count; i++) {
1081 /*
1082 * If the flavor is in the flavor list,
1083 * fill in resok_val.
1084 */
1085 si = &secp[i].s_secinfo;
1086 if (in_flavor_list(si->sc_nfsnum,
1087 flavor_list, ret_cnt)) {
1088 resok_val[k].flavor = si->sc_rpcnum;
1089 if (resok_val[k].flavor == RPCSEC_GSS) {
1090 rpcsec_gss_info *info;
1091
1092 info = &resok_val[k].flavor_info;
1093 info->qop = si->sc_qop;
1094 info->service = (rpc_gss_svc_t)
1095 si->sc_service;
1096
1097 /* get oid opaque data */
1098 info->oid.sec_oid4_len =
1099 si->sc_gss_mech_type->length;
1100 info->oid.sec_oid4_val = kmem_alloc(
1101 si->sc_gss_mech_type->length,
1102 KM_SLEEP);
1103 bcopy(si->sc_gss_mech_type->elements,
1104 info->oid.sec_oid4_val,
1105 info->oid.sec_oid4_len);
1106 }
1107 k++;
1108 }
1109 if (k >= ret_cnt)
1110 break;
1111 }
1112 resp->SECINFO4resok_len = ret_cnt;
1113 resp->SECINFO4resok_val = resok_val;
1114 kmem_free(flavor_list, count * sizeof (int));
1115 }
1116 rw_exit(&exported_lock);
1117 if (oexi != NULL)
1118 exi_rele(oexi);
1119
1120 VN_RELE(vp);
1121 return (NFS4_OK);
1122 }
1123
1124 /*
1125 * SECINFO (Operation 33): Obtain required security information on
1126 * the component name in the format of (security-mechanism-oid, qop, service)
1127 * triplets.
1128 */
1129 /* ARGSUSED */
1130 static void
rfs4_op_secinfo(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)1131 rfs4_op_secinfo(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1132 struct compound_state *cs)
1133 {
1134 SECINFO4args *args = &argop->nfs_argop4_u.opsecinfo;
1135 SECINFO4res *resp = &resop->nfs_resop4_u.opsecinfo;
1136 utf8string *utfnm = &args->name;
1137 uint_t len;
1138 char *nm;
1139 struct sockaddr *ca;
1140 char *name = NULL;
1141 nfsstat4 status = NFS4_OK;
1142
1143 DTRACE_NFSV4_2(op__secinfo__start, struct compound_state *, cs,
1144 SECINFO4args *, args);
1145
1146 /*
1147 * Current file handle (cfh) should have been set before getting
1148 * into this function. If not, return error.
1149 */
1150 if (cs->vp == NULL) {
1151 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
1152 goto out;
1153 }
1154
1155 if (cs->vp->v_type != VDIR) {
1156 *cs->statusp = resp->status = NFS4ERR_NOTDIR;
1157 goto out;
1158 }
1159
1160 /*
1161 * Verify the component name. If failed, error out, but
1162 * do not error out if the component name is a "..".
1163 * SECINFO will return its parents secinfo data for SECINFO "..".
1164 */
1165 status = utf8_dir_verify(utfnm);
1166 if (status != NFS4_OK) {
1167 if (utfnm->utf8string_len != 2 ||
1168 utfnm->utf8string_val[0] != '.' ||
1169 utfnm->utf8string_val[1] != '.') {
1170 *cs->statusp = resp->status = status;
1171 goto out;
1172 }
1173 }
1174
1175 nm = utf8_to_str(utfnm, &len, NULL);
1176 if (nm == NULL) {
1177 *cs->statusp = resp->status = NFS4ERR_INVAL;
1178 goto out;
1179 }
1180
1181 if (len > MAXNAMELEN) {
1182 *cs->statusp = resp->status = NFS4ERR_NAMETOOLONG;
1183 kmem_free(nm, len);
1184 goto out;
1185 }
1186
1187 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
1188 name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
1189 MAXPATHLEN + 1);
1190
1191 if (name == NULL) {
1192 *cs->statusp = resp->status = NFS4ERR_INVAL;
1193 kmem_free(nm, len);
1194 goto out;
1195 }
1196
1197
1198 *cs->statusp = resp->status = do_rfs4_op_secinfo(cs, name, resp);
1199
1200 if (name != nm)
1201 kmem_free(name, MAXPATHLEN + 1);
1202 kmem_free(nm, len);
1203
1204 out:
1205 DTRACE_NFSV4_2(op__secinfo__done, struct compound_state *, cs,
1206 SECINFO4res *, resp);
1207 }
1208
1209 /*
1210 * Free SECINFO result.
1211 */
1212 /* ARGSUSED */
1213 static void
rfs4_op_secinfo_free(nfs_resop4 * resop)1214 rfs4_op_secinfo_free(nfs_resop4 *resop)
1215 {
1216 SECINFO4res *resp = &resop->nfs_resop4_u.opsecinfo;
1217 int count, i;
1218 secinfo4 *resok_val;
1219
1220 /* If this is not an Ok result, nothing to free. */
1221 if (resp->status != NFS4_OK) {
1222 return;
1223 }
1224
1225 count = resp->SECINFO4resok_len;
1226 resok_val = resp->SECINFO4resok_val;
1227
1228 for (i = 0; i < count; i++) {
1229 if (resok_val[i].flavor == RPCSEC_GSS) {
1230 rpcsec_gss_info *info;
1231
1232 info = &resok_val[i].flavor_info;
1233 kmem_free(info->oid.sec_oid4_val,
1234 info->oid.sec_oid4_len);
1235 }
1236 }
1237 kmem_free(resok_val, count * sizeof (secinfo4));
1238 resp->SECINFO4resok_len = 0;
1239 resp->SECINFO4resok_val = NULL;
1240 }
1241
1242 /* ARGSUSED */
1243 static void
rfs4_op_access(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)1244 rfs4_op_access(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1245 struct compound_state *cs)
1246 {
1247 ACCESS4args *args = &argop->nfs_argop4_u.opaccess;
1248 ACCESS4res *resp = &resop->nfs_resop4_u.opaccess;
1249 int error;
1250 vnode_t *vp;
1251 struct vattr va;
1252 int checkwriteperm;
1253 cred_t *cr = cs->cr;
1254 bslabel_t *clabel, *slabel;
1255 ts_label_t *tslabel;
1256 boolean_t admin_low_client;
1257
1258 DTRACE_NFSV4_2(op__access__start, struct compound_state *, cs,
1259 ACCESS4args *, args);
1260
1261 #if 0 /* XXX allow access even if !cs->access. Eventually only pseudo fs */
1262 if (cs->access == CS_ACCESS_DENIED) {
1263 *cs->statusp = resp->status = NFS4ERR_ACCESS;
1264 goto out;
1265 }
1266 #endif
1267 if (cs->vp == NULL) {
1268 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
1269 goto out;
1270 }
1271
1272 ASSERT(cr != NULL);
1273
1274 vp = cs->vp;
1275
1276 /*
1277 * If the file system is exported read only, it is not appropriate
1278 * to check write permissions for regular files and directories.
1279 * Special files are interpreted by the client, so the underlying
1280 * permissions are sent back to the client for interpretation.
1281 */
1282 if (rdonly4(req, cs) &&
1283 (vp->v_type == VREG || vp->v_type == VDIR))
1284 checkwriteperm = 0;
1285 else
1286 checkwriteperm = 1;
1287
1288 /*
1289 * XXX
1290 * We need the mode so that we can correctly determine access
1291 * permissions relative to a mandatory lock file. Access to
1292 * mandatory lock files is denied on the server, so it might
1293 * as well be reflected to the server during the open.
1294 */
1295 va.va_mask = AT_MODE;
1296 error = VOP_GETATTR(vp, &va, 0, cr, NULL);
1297 if (error) {
1298 *cs->statusp = resp->status = puterrno4(error);
1299 goto out;
1300 }
1301 resp->access = 0;
1302 resp->supported = 0;
1303
1304 if (is_system_labeled()) {
1305 ASSERT(req->rq_label != NULL);
1306 clabel = req->rq_label;
1307 DTRACE_PROBE2(tx__rfs4__log__info__opaccess__clabel, char *,
1308 "got client label from request(1)",
1309 struct svc_req *, req);
1310 if (!blequal(&l_admin_low->tsl_label, clabel)) {
1311 if ((tslabel = nfs_getflabel(vp, cs->exi)) == NULL) {
1312 *cs->statusp = resp->status = puterrno4(EACCES);
1313 goto out;
1314 }
1315 slabel = label2bslabel(tslabel);
1316 DTRACE_PROBE3(tx__rfs4__log__info__opaccess__slabel,
1317 char *, "got server label(1) for vp(2)",
1318 bslabel_t *, slabel, vnode_t *, vp);
1319
1320 admin_low_client = B_FALSE;
1321 } else
1322 admin_low_client = B_TRUE;
1323 }
1324
1325 if (args->access & ACCESS4_READ) {
1326 error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
1327 if (!error && !MANDLOCK(vp, va.va_mode) &&
1328 (!is_system_labeled() || admin_low_client ||
1329 bldominates(clabel, slabel)))
1330 resp->access |= ACCESS4_READ;
1331 resp->supported |= ACCESS4_READ;
1332 }
1333 if ((args->access & ACCESS4_LOOKUP) && vp->v_type == VDIR) {
1334 error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
1335 if (!error && (!is_system_labeled() || admin_low_client ||
1336 bldominates(clabel, slabel)))
1337 resp->access |= ACCESS4_LOOKUP;
1338 resp->supported |= ACCESS4_LOOKUP;
1339 }
1340 if (checkwriteperm &&
1341 (args->access & (ACCESS4_MODIFY|ACCESS4_EXTEND))) {
1342 error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
1343 if (!error && !MANDLOCK(vp, va.va_mode) &&
1344 (!is_system_labeled() || admin_low_client ||
1345 blequal(clabel, slabel)))
1346 resp->access |=
1347 (args->access & (ACCESS4_MODIFY | ACCESS4_EXTEND));
1348 resp->supported |=
1349 resp->access & (ACCESS4_MODIFY | ACCESS4_EXTEND);
1350 }
1351
1352 if (checkwriteperm &&
1353 (args->access & ACCESS4_DELETE) && vp->v_type == VDIR) {
1354 error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
1355 if (!error && (!is_system_labeled() || admin_low_client ||
1356 blequal(clabel, slabel)))
1357 resp->access |= ACCESS4_DELETE;
1358 resp->supported |= ACCESS4_DELETE;
1359 }
1360 if (args->access & ACCESS4_EXECUTE && vp->v_type != VDIR) {
1361 error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
1362 if (!error && !MANDLOCK(vp, va.va_mode) &&
1363 (!is_system_labeled() || admin_low_client ||
1364 bldominates(clabel, slabel)))
1365 resp->access |= ACCESS4_EXECUTE;
1366 resp->supported |= ACCESS4_EXECUTE;
1367 }
1368
1369 if (is_system_labeled() && !admin_low_client)
1370 label_rele(tslabel);
1371
1372 *cs->statusp = resp->status = NFS4_OK;
1373 out:
1374 DTRACE_NFSV4_2(op__access__done, struct compound_state *, cs,
1375 ACCESS4res *, resp);
1376 }
1377
1378 /* ARGSUSED */
1379 static void
rfs4_op_commit(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)1380 rfs4_op_commit(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1381 struct compound_state *cs)
1382 {
1383 COMMIT4args *args = &argop->nfs_argop4_u.opcommit;
1384 COMMIT4res *resp = &resop->nfs_resop4_u.opcommit;
1385 int error;
1386 vnode_t *vp = cs->vp;
1387 cred_t *cr = cs->cr;
1388 vattr_t va;
1389
1390 DTRACE_NFSV4_2(op__commit__start, struct compound_state *, cs,
1391 COMMIT4args *, args);
1392
1393 if (vp == NULL) {
1394 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
1395 goto out;
1396 }
1397 if (cs->access == CS_ACCESS_DENIED) {
1398 *cs->statusp = resp->status = NFS4ERR_ACCESS;
1399 goto out;
1400 }
1401
1402 if (args->offset + args->count < args->offset) {
1403 *cs->statusp = resp->status = NFS4ERR_INVAL;
1404 goto out;
1405 }
1406
1407 va.va_mask = AT_UID;
1408 error = VOP_GETATTR(vp, &va, 0, cr, NULL);
1409
1410 /*
1411 * If we can't get the attributes, then we can't do the
1412 * right access checking. So, we'll fail the request.
1413 */
1414 if (error) {
1415 *cs->statusp = resp->status = puterrno4(error);
1416 goto out;
1417 }
1418 if (rdonly4(req, cs)) {
1419 *cs->statusp = resp->status = NFS4ERR_ROFS;
1420 goto out;
1421 }
1422
1423 if (vp->v_type != VREG) {
1424 if (vp->v_type == VDIR)
1425 resp->status = NFS4ERR_ISDIR;
1426 else
1427 resp->status = NFS4ERR_INVAL;
1428 *cs->statusp = resp->status;
1429 goto out;
1430 }
1431
1432 if (crgetuid(cr) != va.va_uid &&
1433 (error = VOP_ACCESS(vp, VWRITE, 0, cs->cr, NULL))) {
1434 *cs->statusp = resp->status = puterrno4(error);
1435 goto out;
1436 }
1437
1438 error = VOP_FSYNC(vp, FSYNC, cr, NULL);
1439
1440 if (error) {
1441 *cs->statusp = resp->status = puterrno4(error);
1442 goto out;
1443 }
1444
1445 *cs->statusp = resp->status = NFS4_OK;
1446 resp->writeverf = Write4verf;
1447 out:
1448 DTRACE_NFSV4_2(op__commit__done, struct compound_state *, cs,
1449 COMMIT4res *, resp);
1450 }
1451
1452 /*
1453 * rfs4_op_mknod is called from rfs4_op_create after all initial verification
1454 * was completed. It does the nfsv4 create for special files.
1455 */
1456 /* ARGSUSED */
1457 static vnode_t *
do_rfs4_op_mknod(CREATE4args * args,CREATE4res * resp,struct svc_req * req,struct compound_state * cs,vattr_t * vap,char * nm)1458 do_rfs4_op_mknod(CREATE4args *args, CREATE4res *resp, struct svc_req *req,
1459 struct compound_state *cs, vattr_t *vap, char *nm)
1460 {
1461 int error;
1462 cred_t *cr = cs->cr;
1463 vnode_t *dvp = cs->vp;
1464 vnode_t *vp = NULL;
1465 int mode;
1466 enum vcexcl excl;
1467
1468 switch (args->type) {
1469 case NF4CHR:
1470 case NF4BLK:
1471 if (secpolicy_sys_devices(cr) != 0) {
1472 *cs->statusp = resp->status = NFS4ERR_PERM;
1473 return (NULL);
1474 }
1475 if (args->type == NF4CHR)
1476 vap->va_type = VCHR;
1477 else
1478 vap->va_type = VBLK;
1479 vap->va_rdev = makedevice(args->ftype4_u.devdata.specdata1,
1480 args->ftype4_u.devdata.specdata2);
1481 vap->va_mask |= AT_RDEV;
1482 break;
1483 case NF4SOCK:
1484 vap->va_type = VSOCK;
1485 break;
1486 case NF4FIFO:
1487 vap->va_type = VFIFO;
1488 break;
1489 default:
1490 *cs->statusp = resp->status = NFS4ERR_BADTYPE;
1491 return (NULL);
1492 }
1493
1494 /*
1495 * Must specify the mode.
1496 */
1497 if (!(vap->va_mask & AT_MODE)) {
1498 *cs->statusp = resp->status = NFS4ERR_INVAL;
1499 return (NULL);
1500 }
1501
1502 excl = EXCL;
1503
1504 mode = 0;
1505
1506 error = VOP_CREATE(dvp, nm, vap, excl, mode, &vp, cr, 0, NULL, NULL);
1507 if (error) {
1508 *cs->statusp = resp->status = puterrno4(error);
1509 return (NULL);
1510 }
1511 return (vp);
1512 }
1513
1514 /*
1515 * nfsv4 create is used to create non-regular files. For regular files,
1516 * use nfsv4 open.
1517 */
1518 /* ARGSUSED */
1519 static void
rfs4_op_create(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)1520 rfs4_op_create(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1521 struct compound_state *cs)
1522 {
1523 CREATE4args *args = &argop->nfs_argop4_u.opcreate;
1524 CREATE4res *resp = &resop->nfs_resop4_u.opcreate;
1525 int error;
1526 struct vattr bva, iva, iva2, ava, *vap;
1527 cred_t *cr = cs->cr;
1528 vnode_t *dvp = cs->vp;
1529 vnode_t *vp = NULL;
1530 vnode_t *realvp;
1531 char *nm, *lnm;
1532 uint_t len, llen;
1533 int syncval = 0;
1534 struct nfs4_svgetit_arg sarg;
1535 struct nfs4_ntov_table ntov;
1536 struct statvfs64 sb;
1537 nfsstat4 status;
1538 struct sockaddr *ca;
1539 char *name = NULL;
1540 char *lname = NULL;
1541
1542 DTRACE_NFSV4_2(op__create__start, struct compound_state *, cs,
1543 CREATE4args *, args);
1544
1545 resp->attrset = 0;
1546
1547 if (dvp == NULL) {
1548 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
1549 goto out;
1550 }
1551
1552 /*
1553 * If there is an unshared filesystem mounted on this vnode,
1554 * do not allow to create an object in this directory.
1555 */
1556 if (vn_ismntpt(dvp)) {
1557 *cs->statusp = resp->status = NFS4ERR_ACCESS;
1558 goto out;
1559 }
1560
1561 /* Verify that type is correct */
1562 switch (args->type) {
1563 case NF4LNK:
1564 case NF4BLK:
1565 case NF4CHR:
1566 case NF4SOCK:
1567 case NF4FIFO:
1568 case NF4DIR:
1569 break;
1570 default:
1571 *cs->statusp = resp->status = NFS4ERR_BADTYPE;
1572 goto out;
1573 };
1574
1575 if (cs->access == CS_ACCESS_DENIED) {
1576 *cs->statusp = resp->status = NFS4ERR_ACCESS;
1577 goto out;
1578 }
1579 if (dvp->v_type != VDIR) {
1580 *cs->statusp = resp->status = NFS4ERR_NOTDIR;
1581 goto out;
1582 }
1583 status = utf8_dir_verify(&args->objname);
1584 if (status != NFS4_OK) {
1585 *cs->statusp = resp->status = status;
1586 goto out;
1587 }
1588
1589 if (rdonly4(req, cs)) {
1590 *cs->statusp = resp->status = NFS4ERR_ROFS;
1591 goto out;
1592 }
1593
1594 /*
1595 * Name of newly created object
1596 */
1597 nm = utf8_to_fn(&args->objname, &len, NULL);
1598 if (nm == NULL) {
1599 *cs->statusp = resp->status = NFS4ERR_INVAL;
1600 goto out;
1601 }
1602
1603 if (len > MAXNAMELEN) {
1604 *cs->statusp = resp->status = NFS4ERR_NAMETOOLONG;
1605 kmem_free(nm, len);
1606 goto out;
1607 }
1608
1609 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
1610 name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
1611 MAXPATHLEN + 1);
1612
1613 if (name == NULL) {
1614 *cs->statusp = resp->status = NFS4ERR_INVAL;
1615 kmem_free(nm, len);
1616 goto out;
1617 }
1618
1619 resp->attrset = 0;
1620
1621 sarg.sbp = &sb;
1622 sarg.is_referral = B_FALSE;
1623 nfs4_ntov_table_init(&ntov);
1624
1625 status = do_rfs4_set_attrs(&resp->attrset,
1626 &args->createattrs, cs, &sarg, &ntov, NFS4ATTR_SETIT);
1627
1628 if (sarg.vap->va_mask == 0 && status == NFS4_OK)
1629 status = NFS4ERR_INVAL;
1630
1631 if (status != NFS4_OK) {
1632 *cs->statusp = resp->status = status;
1633 if (name != nm)
1634 kmem_free(name, MAXPATHLEN + 1);
1635 kmem_free(nm, len);
1636 nfs4_ntov_table_free(&ntov, &sarg);
1637 resp->attrset = 0;
1638 goto out;
1639 }
1640
1641 /* Get "before" change value */
1642 bva.va_mask = AT_CTIME|AT_SEQ|AT_MODE;
1643 error = VOP_GETATTR(dvp, &bva, 0, cr, NULL);
1644 if (error) {
1645 *cs->statusp = resp->status = puterrno4(error);
1646 if (name != nm)
1647 kmem_free(name, MAXPATHLEN + 1);
1648 kmem_free(nm, len);
1649 nfs4_ntov_table_free(&ntov, &sarg);
1650 resp->attrset = 0;
1651 goto out;
1652 }
1653 NFS4_SET_FATTR4_CHANGE(resp->cinfo.before, bva.va_ctime)
1654
1655 vap = sarg.vap;
1656
1657 /*
1658 * Set the default initial values for attributes when the parent
1659 * directory does not have the VSUID/VSGID bit set and they have
1660 * not been specified in createattrs.
1661 */
1662 if (!(bva.va_mode & VSUID) && (vap->va_mask & AT_UID) == 0) {
1663 vap->va_uid = crgetuid(cr);
1664 vap->va_mask |= AT_UID;
1665 }
1666 if (!(bva.va_mode & VSGID) && (vap->va_mask & AT_GID) == 0) {
1667 vap->va_gid = crgetgid(cr);
1668 vap->va_mask |= AT_GID;
1669 }
1670
1671 vap->va_mask |= AT_TYPE;
1672 switch (args->type) {
1673 case NF4DIR:
1674 vap->va_type = VDIR;
1675 if ((vap->va_mask & AT_MODE) == 0) {
1676 vap->va_mode = 0700; /* default: owner rwx only */
1677 vap->va_mask |= AT_MODE;
1678 }
1679 error = VOP_MKDIR(dvp, name, vap, &vp, cr, NULL, 0, NULL);
1680 if (error)
1681 break;
1682
1683 /*
1684 * Get the initial "after" sequence number, if it fails,
1685 * set to zero
1686 */
1687 iva.va_mask = AT_SEQ;
1688 if (VOP_GETATTR(dvp, &iva, 0, cs->cr, NULL))
1689 iva.va_seq = 0;
1690 break;
1691 case NF4LNK:
1692 vap->va_type = VLNK;
1693 if ((vap->va_mask & AT_MODE) == 0) {
1694 vap->va_mode = 0700; /* default: owner rwx only */
1695 vap->va_mask |= AT_MODE;
1696 }
1697
1698 /*
1699 * symlink names must be treated as data
1700 */
1701 lnm = utf8_to_str((utf8string *)&args->ftype4_u.linkdata,
1702 &llen, NULL);
1703
1704 if (lnm == NULL) {
1705 *cs->statusp = resp->status = NFS4ERR_INVAL;
1706 if (name != nm)
1707 kmem_free(name, MAXPATHLEN + 1);
1708 kmem_free(nm, len);
1709 nfs4_ntov_table_free(&ntov, &sarg);
1710 resp->attrset = 0;
1711 goto out;
1712 }
1713
1714 if (llen > MAXPATHLEN) {
1715 *cs->statusp = resp->status = NFS4ERR_NAMETOOLONG;
1716 if (name != nm)
1717 kmem_free(name, MAXPATHLEN + 1);
1718 kmem_free(nm, len);
1719 kmem_free(lnm, llen);
1720 nfs4_ntov_table_free(&ntov, &sarg);
1721 resp->attrset = 0;
1722 goto out;
1723 }
1724
1725 lname = nfscmd_convname(ca, cs->exi, lnm,
1726 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
1727
1728 if (lname == NULL) {
1729 *cs->statusp = resp->status = NFS4ERR_SERVERFAULT;
1730 if (name != nm)
1731 kmem_free(name, MAXPATHLEN + 1);
1732 kmem_free(nm, len);
1733 kmem_free(lnm, llen);
1734 nfs4_ntov_table_free(&ntov, &sarg);
1735 resp->attrset = 0;
1736 goto out;
1737 }
1738
1739 error = VOP_SYMLINK(dvp, name, vap, lname, cr, NULL, 0);
1740 if (lname != lnm)
1741 kmem_free(lname, MAXPATHLEN + 1);
1742 kmem_free(lnm, llen);
1743 if (error)
1744 break;
1745
1746 /*
1747 * Get the initial "after" sequence number, if it fails,
1748 * set to zero
1749 */
1750 iva.va_mask = AT_SEQ;
1751 if (VOP_GETATTR(dvp, &iva, 0, cs->cr, NULL))
1752 iva.va_seq = 0;
1753
1754 error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr,
1755 NULL, NULL, NULL);
1756 if (error)
1757 break;
1758
1759 /*
1760 * va_seq is not safe over VOP calls, check it again
1761 * if it has changed zero out iva to force atomic = FALSE.
1762 */
1763 iva2.va_mask = AT_SEQ;
1764 if (VOP_GETATTR(dvp, &iva2, 0, cs->cr, NULL) ||
1765 iva2.va_seq != iva.va_seq)
1766 iva.va_seq = 0;
1767 break;
1768 default:
1769 /*
1770 * probably a special file.
1771 */
1772 if ((vap->va_mask & AT_MODE) == 0) {
1773 vap->va_mode = 0600; /* default: owner rw only */
1774 vap->va_mask |= AT_MODE;
1775 }
1776 syncval = FNODSYNC;
1777 /*
1778 * We know this will only generate one VOP call
1779 */
1780 vp = do_rfs4_op_mknod(args, resp, req, cs, vap, name);
1781
1782 if (vp == NULL) {
1783 if (name != nm)
1784 kmem_free(name, MAXPATHLEN + 1);
1785 kmem_free(nm, len);
1786 nfs4_ntov_table_free(&ntov, &sarg);
1787 resp->attrset = 0;
1788 goto out;
1789 }
1790
1791 /*
1792 * Get the initial "after" sequence number, if it fails,
1793 * set to zero
1794 */
1795 iva.va_mask = AT_SEQ;
1796 if (VOP_GETATTR(dvp, &iva, 0, cs->cr, NULL))
1797 iva.va_seq = 0;
1798
1799 break;
1800 }
1801 if (name != nm)
1802 kmem_free(name, MAXPATHLEN + 1);
1803 kmem_free(nm, len);
1804
1805 if (error) {
1806 *cs->statusp = resp->status = puterrno4(error);
1807 }
1808
1809 /*
1810 * Force modified data and metadata out to stable storage.
1811 */
1812 (void) VOP_FSYNC(dvp, 0, cr, NULL);
1813
1814 if (resp->status != NFS4_OK) {
1815 if (vp != NULL)
1816 VN_RELE(vp);
1817 nfs4_ntov_table_free(&ntov, &sarg);
1818 resp->attrset = 0;
1819 goto out;
1820 }
1821
1822 /*
1823 * Finish setup of cinfo response, "before" value already set.
1824 * Get "after" change value, if it fails, simply return the
1825 * before value.
1826 */
1827 ava.va_mask = AT_CTIME|AT_SEQ;
1828 if (VOP_GETATTR(dvp, &ava, 0, cr, NULL)) {
1829 ava.va_ctime = bva.va_ctime;
1830 ava.va_seq = 0;
1831 }
1832 NFS4_SET_FATTR4_CHANGE(resp->cinfo.after, ava.va_ctime);
1833
1834 /*
1835 * True verification that object was created with correct
1836 * attrs is impossible. The attrs could have been changed
1837 * immediately after object creation. If attributes did
1838 * not verify, the only recourse for the server is to
1839 * destroy the object. Maybe if some attrs (like gid)
1840 * are set incorrectly, the object should be destroyed;
1841 * however, seems bad as a default policy. Do we really
1842 * want to destroy an object over one of the times not
1843 * verifying correctly? For these reasons, the server
1844 * currently sets bits in attrset for createattrs
1845 * that were set; however, no verification is done.
1846 *
1847 * vmask_to_nmask accounts for vattr bits set on create
1848 * [do_rfs4_set_attrs() only sets resp bits for
1849 * non-vattr/vfs bits.]
1850 * Mask off any bits set by default so as not to return
1851 * more attrset bits than were requested in createattrs
1852 */
1853 nfs4_vmask_to_nmask(sarg.vap->va_mask, &resp->attrset);
1854 resp->attrset &= args->createattrs.attrmask;
1855 nfs4_ntov_table_free(&ntov, &sarg);
1856
1857 error = makefh4(&cs->fh, vp, cs->exi);
1858 if (error) {
1859 *cs->statusp = resp->status = puterrno4(error);
1860 }
1861
1862 /*
1863 * The cinfo.atomic = TRUE only if we got no errors, we have
1864 * non-zero va_seq's, and it has incremented by exactly one
1865 * during the creation and it didn't change during the VOP_LOOKUP
1866 * or VOP_FSYNC.
1867 */
1868 if (!error && bva.va_seq && iva.va_seq && ava.va_seq &&
1869 iva.va_seq == (bva.va_seq + 1) && iva.va_seq == ava.va_seq)
1870 resp->cinfo.atomic = TRUE;
1871 else
1872 resp->cinfo.atomic = FALSE;
1873
1874 /*
1875 * Force modified metadata out to stable storage.
1876 *
1877 * if a underlying vp exists, pass it to VOP_FSYNC
1878 */
1879 if (VOP_REALVP(vp, &realvp, NULL) == 0)
1880 (void) VOP_FSYNC(realvp, syncval, cr, NULL);
1881 else
1882 (void) VOP_FSYNC(vp, syncval, cr, NULL);
1883
1884 if (resp->status != NFS4_OK) {
1885 VN_RELE(vp);
1886 goto out;
1887 }
1888 if (cs->vp)
1889 VN_RELE(cs->vp);
1890
1891 cs->vp = vp;
1892 *cs->statusp = resp->status = NFS4_OK;
1893 out:
1894 DTRACE_NFSV4_2(op__create__done, struct compound_state *, cs,
1895 CREATE4res *, resp);
1896 }
1897
1898 /*ARGSUSED*/
1899 static void
rfs4_op_delegpurge(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)1900 rfs4_op_delegpurge(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1901 struct compound_state *cs)
1902 {
1903 DTRACE_NFSV4_2(op__delegpurge__start, struct compound_state *, cs,
1904 DELEGPURGE4args *, &argop->nfs_argop4_u.opdelegpurge);
1905
1906 rfs4_op_inval(argop, resop, req, cs);
1907
1908 DTRACE_NFSV4_2(op__delegpurge__done, struct compound_state *, cs,
1909 DELEGPURGE4res *, &resop->nfs_resop4_u.opdelegpurge);
1910 }
1911
1912 /*ARGSUSED*/
1913 static void
rfs4_op_delegreturn(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)1914 rfs4_op_delegreturn(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1915 struct compound_state *cs)
1916 {
1917 DELEGRETURN4args *args = &argop->nfs_argop4_u.opdelegreturn;
1918 DELEGRETURN4res *resp = &resop->nfs_resop4_u.opdelegreturn;
1919 rfs4_deleg_state_t *dsp;
1920 nfsstat4 status;
1921
1922 DTRACE_NFSV4_2(op__delegreturn__start, struct compound_state *, cs,
1923 DELEGRETURN4args *, args);
1924
1925 status = rfs4_get_deleg_state(&args->deleg_stateid, &dsp);
1926 resp->status = *cs->statusp = status;
1927 if (status != NFS4_OK)
1928 goto out;
1929
1930 /* Ensure specified filehandle matches */
1931 if (cs->vp != dsp->rds_finfo->rf_vp) {
1932 resp->status = *cs->statusp = NFS4ERR_BAD_STATEID;
1933 } else
1934 rfs4_return_deleg(dsp, FALSE);
1935
1936 rfs4_update_lease(dsp->rds_client);
1937
1938 rfs4_deleg_state_rele(dsp);
1939 out:
1940 DTRACE_NFSV4_2(op__delegreturn__done, struct compound_state *, cs,
1941 DELEGRETURN4res *, resp);
1942 }
1943
1944 /*
1945 * Check to see if a given "flavor" is an explicitly shared flavor.
1946 * The assumption of this routine is the "flavor" is already a valid
1947 * flavor in the secinfo list of "exi".
1948 *
1949 * e.g.
1950 * # share -o sec=flavor1 /export
1951 * # share -o sec=flavor2 /export/home
1952 *
1953 * flavor2 is not an explicitly shared flavor for /export,
1954 * however it is in the secinfo list for /export thru the
1955 * server namespace setup.
1956 */
1957 int
is_exported_sec(int flavor,struct exportinfo * exi)1958 is_exported_sec(int flavor, struct exportinfo *exi)
1959 {
1960 int i;
1961 struct secinfo *sp;
1962
1963 rw_enter(&exported_lock, RW_READER);
1964 sp = exi->exi_export.ex_secinfo;
1965 for (i = 0; i < exi->exi_export.ex_seccnt; i++) {
1966 if (flavor == sp[i].s_secinfo.sc_nfsnum ||
1967 sp[i].s_secinfo.sc_nfsnum == AUTH_NONE) {
1968 int ret = SEC_REF_EXPORTED(&sp[i]);
1969 rw_exit(&exported_lock);
1970 return (ret);
1971 }
1972 }
1973 rw_exit(&exported_lock);
1974
1975 /* Should not reach this point based on the assumption */
1976 return (0);
1977 }
1978
1979 /*
1980 * Check if the security flavor used in the request matches what is
1981 * required at the export point or at the root pseudo node (exi_root).
1982 *
1983 * returns 1 if there's a match or if exported with AUTH_NONE; 0 otherwise.
1984 *
1985 */
1986 static int
secinfo_match_or_authnone(struct compound_state * cs)1987 secinfo_match_or_authnone(struct compound_state *cs)
1988 {
1989 int i;
1990 struct secinfo *sp;
1991
1992 /*
1993 * Check cs->nfsflavor (from the request) against
1994 * the current export data in cs->exi.
1995 */
1996 rw_enter(&exported_lock, RW_READER);
1997 sp = cs->exi->exi_export.ex_secinfo;
1998 for (i = 0; i < cs->exi->exi_export.ex_seccnt; i++) {
1999 if (cs->nfsflavor == sp[i].s_secinfo.sc_nfsnum ||
2000 sp[i].s_secinfo.sc_nfsnum == AUTH_NONE) {
2001 rw_exit(&exported_lock);
2002 return (1);
2003 }
2004 }
2005 rw_exit(&exported_lock);
2006
2007 return (0);
2008 }
2009
2010 /*
2011 * Check the access authority for the client and return the correct error.
2012 */
2013 nfsstat4
call_checkauth4(struct compound_state * cs,struct svc_req * req)2014 call_checkauth4(struct compound_state *cs, struct svc_req *req)
2015 {
2016 int authres;
2017
2018 /*
2019 * First, check if the security flavor used in the request
2020 * are among the flavors set in the server namespace.
2021 */
2022 if (!secinfo_match_or_authnone(cs)) {
2023 *cs->statusp = NFS4ERR_WRONGSEC;
2024 return (*cs->statusp);
2025 }
2026
2027 authres = checkauth4(cs, req);
2028
2029 if (authres > 0) {
2030 *cs->statusp = NFS4_OK;
2031 if (! (cs->access & CS_ACCESS_LIMITED))
2032 cs->access = CS_ACCESS_OK;
2033 } else if (authres == 0) {
2034 *cs->statusp = NFS4ERR_ACCESS;
2035 } else if (authres == -2) {
2036 *cs->statusp = NFS4ERR_WRONGSEC;
2037 } else {
2038 *cs->statusp = NFS4ERR_DELAY;
2039 }
2040 return (*cs->statusp);
2041 }
2042
2043 /*
2044 * bitmap4_to_attrmask is called by getattr and readdir.
2045 * It sets up the vattr mask and determines whether vfsstat call is needed
2046 * based on the input bitmap.
2047 * Returns nfsv4 status.
2048 */
2049 static nfsstat4
bitmap4_to_attrmask(bitmap4 breq,struct nfs4_svgetit_arg * sargp)2050 bitmap4_to_attrmask(bitmap4 breq, struct nfs4_svgetit_arg *sargp)
2051 {
2052 int i;
2053 uint_t va_mask;
2054 struct statvfs64 *sbp = sargp->sbp;
2055
2056 sargp->sbp = NULL;
2057 sargp->flag = 0;
2058 sargp->rdattr_error = NFS4_OK;
2059 sargp->mntdfid_set = FALSE;
2060 if (sargp->cs->vp)
2061 sargp->xattr = get_fh4_flag(&sargp->cs->fh,
2062 FH4_ATTRDIR | FH4_NAMEDATTR);
2063 else
2064 sargp->xattr = 0;
2065
2066 /*
2067 * Set rdattr_error_req to true if return error per
2068 * failed entry rather than fail the readdir.
2069 */
2070 if (breq & FATTR4_RDATTR_ERROR_MASK)
2071 sargp->rdattr_error_req = 1;
2072 else
2073 sargp->rdattr_error_req = 0;
2074
2075 /*
2076 * generate the va_mask
2077 * Handle the easy cases first
2078 */
2079 switch (breq) {
2080 case NFS4_NTOV_ATTR_MASK:
2081 sargp->vap->va_mask = NFS4_NTOV_ATTR_AT_MASK;
2082 return (NFS4_OK);
2083
2084 case NFS4_FS_ATTR_MASK:
2085 sargp->vap->va_mask = NFS4_FS_ATTR_AT_MASK;
2086 sargp->sbp = sbp;
2087 return (NFS4_OK);
2088
2089 case NFS4_NTOV_ATTR_CACHE_MASK:
2090 sargp->vap->va_mask = NFS4_NTOV_ATTR_CACHE_AT_MASK;
2091 return (NFS4_OK);
2092
2093 case FATTR4_LEASE_TIME_MASK:
2094 sargp->vap->va_mask = 0;
2095 return (NFS4_OK);
2096
2097 default:
2098 va_mask = 0;
2099 for (i = 0; i < nfs4_ntov_map_size; i++) {
2100 if ((breq & nfs4_ntov_map[i].fbit) &&
2101 nfs4_ntov_map[i].vbit)
2102 va_mask |= nfs4_ntov_map[i].vbit;
2103 }
2104
2105 /*
2106 * Check is vfsstat is needed
2107 */
2108 if (breq & NFS4_FS_ATTR_MASK)
2109 sargp->sbp = sbp;
2110
2111 sargp->vap->va_mask = va_mask;
2112 return (NFS4_OK);
2113 }
2114 /* NOTREACHED */
2115 }
2116
2117 /*
2118 * bitmap4_get_sysattrs is called by getattr and readdir.
2119 * It calls both VOP_GETATTR and VFS_STATVFS calls to get the attrs.
2120 * Returns nfsv4 status.
2121 */
2122 static nfsstat4
bitmap4_get_sysattrs(struct nfs4_svgetit_arg * sargp)2123 bitmap4_get_sysattrs(struct nfs4_svgetit_arg *sargp)
2124 {
2125 int error;
2126 struct compound_state *cs = sargp->cs;
2127 vnode_t *vp = cs->vp;
2128
2129 if (sargp->sbp != NULL) {
2130 if (error = VFS_STATVFS(vp->v_vfsp, sargp->sbp)) {
2131 sargp->sbp = NULL; /* to identify error */
2132 return (puterrno4(error));
2133 }
2134 }
2135
2136 return (rfs4_vop_getattr(vp, sargp->vap, 0, cs->cr));
2137 }
2138
2139 static void
nfs4_ntov_table_init(struct nfs4_ntov_table * ntovp)2140 nfs4_ntov_table_init(struct nfs4_ntov_table *ntovp)
2141 {
2142 ntovp->na = kmem_zalloc(sizeof (union nfs4_attr_u) * nfs4_ntov_map_size,
2143 KM_SLEEP);
2144 ntovp->attrcnt = 0;
2145 ntovp->vfsstat = FALSE;
2146 }
2147
2148 static void
nfs4_ntov_table_free(struct nfs4_ntov_table * ntovp,struct nfs4_svgetit_arg * sargp)2149 nfs4_ntov_table_free(struct nfs4_ntov_table *ntovp,
2150 struct nfs4_svgetit_arg *sargp)
2151 {
2152 int i;
2153 union nfs4_attr_u *na;
2154 uint8_t *amap;
2155
2156 /*
2157 * XXX Should do the same checks for whether the bit is set
2158 */
2159 for (i = 0, na = ntovp->na, amap = ntovp->amap;
2160 i < ntovp->attrcnt; i++, na++, amap++) {
2161 (void) (*nfs4_ntov_map[*amap].sv_getit)(
2162 NFS4ATTR_FREEIT, sargp, na);
2163 }
2164 if ((sargp->op == NFS4ATTR_SETIT) || (sargp->op == NFS4ATTR_VERIT)) {
2165 /*
2166 * xdr_free for getattr will be done later
2167 */
2168 for (i = 0, na = ntovp->na, amap = ntovp->amap;
2169 i < ntovp->attrcnt; i++, na++, amap++) {
2170 xdr_free(nfs4_ntov_map[*amap].xfunc, (caddr_t)na);
2171 }
2172 }
2173 kmem_free(ntovp->na, sizeof (union nfs4_attr_u) * nfs4_ntov_map_size);
2174 }
2175
2176 /*
2177 * do_rfs4_op_getattr gets the system attrs and converts into fattr4.
2178 */
2179 static nfsstat4
do_rfs4_op_getattr(bitmap4 breq,fattr4 * fattrp,struct nfs4_svgetit_arg * sargp)2180 do_rfs4_op_getattr(bitmap4 breq, fattr4 *fattrp,
2181 struct nfs4_svgetit_arg *sargp)
2182 {
2183 int error = 0;
2184 int i, k;
2185 struct nfs4_ntov_table ntov;
2186 XDR xdr;
2187 ulong_t xdr_size;
2188 char *xdr_attrs;
2189 nfsstat4 status = NFS4_OK;
2190 nfsstat4 prev_rdattr_error = sargp->rdattr_error;
2191 union nfs4_attr_u *na;
2192 uint8_t *amap;
2193
2194 sargp->op = NFS4ATTR_GETIT;
2195 sargp->flag = 0;
2196
2197 fattrp->attrmask = 0;
2198 /* if no bits requested, then return empty fattr4 */
2199 if (breq == 0) {
2200 fattrp->attrlist4_len = 0;
2201 fattrp->attrlist4 = NULL;
2202 return (NFS4_OK);
2203 }
2204
2205 /*
2206 * return NFS4ERR_INVAL when client requests write-only attrs
2207 */
2208 if (breq & (FATTR4_TIME_ACCESS_SET_MASK | FATTR4_TIME_MODIFY_SET_MASK))
2209 return (NFS4ERR_INVAL);
2210
2211 nfs4_ntov_table_init(&ntov);
2212 na = ntov.na;
2213 amap = ntov.amap;
2214
2215 /*
2216 * Now loop to get or verify the attrs
2217 */
2218 for (i = 0; i < nfs4_ntov_map_size; i++) {
2219 if (breq & nfs4_ntov_map[i].fbit) {
2220 if ((*nfs4_ntov_map[i].sv_getit)(
2221 NFS4ATTR_SUPPORTED, sargp, NULL) == 0) {
2222
2223 error = (*nfs4_ntov_map[i].sv_getit)(
2224 NFS4ATTR_GETIT, sargp, na);
2225
2226 /*
2227 * Possible error values:
2228 * >0 if sv_getit failed to
2229 * get the attr; 0 if succeeded;
2230 * <0 if rdattr_error and the
2231 * attribute cannot be returned.
2232 */
2233 if (error && !(sargp->rdattr_error_req))
2234 goto done;
2235 /*
2236 * If error then just for entry
2237 */
2238 if (error == 0) {
2239 fattrp->attrmask |=
2240 nfs4_ntov_map[i].fbit;
2241 *amap++ =
2242 (uint8_t)nfs4_ntov_map[i].nval;
2243 na++;
2244 (ntov.attrcnt)++;
2245 } else if ((error > 0) &&
2246 (sargp->rdattr_error == NFS4_OK)) {
2247 sargp->rdattr_error = puterrno4(error);
2248 }
2249 error = 0;
2250 }
2251 }
2252 }
2253
2254 /*
2255 * If rdattr_error was set after the return value for it was assigned,
2256 * update it.
2257 */
2258 if (prev_rdattr_error != sargp->rdattr_error) {
2259 na = ntov.na;
2260 amap = ntov.amap;
2261 for (i = 0; i < ntov.attrcnt; i++, na++, amap++) {
2262 k = *amap;
2263 if (k < FATTR4_RDATTR_ERROR) {
2264 continue;
2265 }
2266 if ((k == FATTR4_RDATTR_ERROR) &&
2267 ((*nfs4_ntov_map[k].sv_getit)(
2268 NFS4ATTR_SUPPORTED, sargp, NULL) == 0)) {
2269
2270 (void) (*nfs4_ntov_map[k].sv_getit)(
2271 NFS4ATTR_GETIT, sargp, na);
2272 }
2273 break;
2274 }
2275 }
2276
2277 xdr_size = 0;
2278 na = ntov.na;
2279 amap = ntov.amap;
2280 for (i = 0; i < ntov.attrcnt; i++, na++, amap++) {
2281 xdr_size += xdr_sizeof(nfs4_ntov_map[*amap].xfunc, na);
2282 }
2283
2284 fattrp->attrlist4_len = xdr_size;
2285 if (xdr_size) {
2286 /* freed by rfs4_op_getattr_free() */
2287 fattrp->attrlist4 = xdr_attrs = kmem_zalloc(xdr_size, KM_SLEEP);
2288
2289 xdrmem_create(&xdr, xdr_attrs, xdr_size, XDR_ENCODE);
2290
2291 na = ntov.na;
2292 amap = ntov.amap;
2293 for (i = 0; i < ntov.attrcnt; i++, na++, amap++) {
2294 if (!(*nfs4_ntov_map[*amap].xfunc)(&xdr, na)) {
2295 DTRACE_PROBE1(nfss__e__getattr4_encfail,
2296 int, *amap);
2297 status = NFS4ERR_SERVERFAULT;
2298 break;
2299 }
2300 }
2301 /* xdrmem_destroy(&xdrs); */ /* NO-OP */
2302 } else {
2303 fattrp->attrlist4 = NULL;
2304 }
2305 done:
2306
2307 nfs4_ntov_table_free(&ntov, sargp);
2308
2309 if (error != 0)
2310 status = puterrno4(error);
2311
2312 return (status);
2313 }
2314
2315 /* ARGSUSED */
2316 static void
rfs4_op_getattr(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)2317 rfs4_op_getattr(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
2318 struct compound_state *cs)
2319 {
2320 GETATTR4args *args = &argop->nfs_argop4_u.opgetattr;
2321 GETATTR4res *resp = &resop->nfs_resop4_u.opgetattr;
2322 struct nfs4_svgetit_arg sarg;
2323 struct statvfs64 sb;
2324 nfsstat4 status;
2325
2326 DTRACE_NFSV4_2(op__getattr__start, struct compound_state *, cs,
2327 GETATTR4args *, args);
2328
2329 if (cs->vp == NULL) {
2330 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
2331 goto out;
2332 }
2333
2334 if (cs->access == CS_ACCESS_DENIED) {
2335 *cs->statusp = resp->status = NFS4ERR_ACCESS;
2336 goto out;
2337 }
2338
2339 sarg.sbp = &sb;
2340 sarg.cs = cs;
2341 sarg.is_referral = B_FALSE;
2342
2343 status = bitmap4_to_attrmask(args->attr_request, &sarg);
2344 if (status == NFS4_OK) {
2345
2346 status = bitmap4_get_sysattrs(&sarg);
2347 if (status == NFS4_OK) {
2348
2349 /* Is this a referral? */
2350 if (vn_is_nfs_reparse(cs->vp, cs->cr)) {
2351 /* Older V4 Solaris client sees a link */
2352 if (client_is_downrev(req))
2353 sarg.vap->va_type = VLNK;
2354 else
2355 sarg.is_referral = B_TRUE;
2356 }
2357
2358 status = do_rfs4_op_getattr(args->attr_request,
2359 &resp->obj_attributes, &sarg);
2360 }
2361 }
2362 *cs->statusp = resp->status = status;
2363 out:
2364 DTRACE_NFSV4_2(op__getattr__done, struct compound_state *, cs,
2365 GETATTR4res *, resp);
2366 }
2367
2368 static void
rfs4_op_getattr_free(nfs_resop4 * resop)2369 rfs4_op_getattr_free(nfs_resop4 *resop)
2370 {
2371 GETATTR4res *resp = &resop->nfs_resop4_u.opgetattr;
2372
2373 nfs4_fattr4_free(&resp->obj_attributes);
2374 }
2375
2376 /* ARGSUSED */
2377 static void
rfs4_op_getfh(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)2378 rfs4_op_getfh(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
2379 struct compound_state *cs)
2380 {
2381 GETFH4res *resp = &resop->nfs_resop4_u.opgetfh;
2382
2383 DTRACE_NFSV4_1(op__getfh__start, struct compound_state *, cs);
2384
2385 if (cs->vp == NULL) {
2386 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
2387 goto out;
2388 }
2389 if (cs->access == CS_ACCESS_DENIED) {
2390 *cs->statusp = resp->status = NFS4ERR_ACCESS;
2391 goto out;
2392 }
2393
2394 /* check for reparse point at the share point */
2395 if (cs->exi->exi_moved || vn_is_nfs_reparse(cs->exi->exi_vp, cs->cr)) {
2396 /* it's all bad */
2397 cs->exi->exi_moved = 1;
2398 *cs->statusp = resp->status = NFS4ERR_MOVED;
2399 DTRACE_PROBE2(nfs4serv__func__referral__shared__moved,
2400 vnode_t *, cs->vp, char *, "rfs4_op_getfh");
2401 return;
2402 }
2403
2404 /* check for reparse point at vp */
2405 if (vn_is_nfs_reparse(cs->vp, cs->cr) && !client_is_downrev(req)) {
2406 /* it's not all bad */
2407 *cs->statusp = resp->status = NFS4ERR_MOVED;
2408 DTRACE_PROBE2(nfs4serv__func__referral__moved,
2409 vnode_t *, cs->vp, char *, "rfs4_op_getfh");
2410 return;
2411 }
2412
2413 resp->object.nfs_fh4_val =
2414 kmem_alloc(cs->fh.nfs_fh4_len, KM_SLEEP);
2415 nfs_fh4_copy(&cs->fh, &resp->object);
2416 *cs->statusp = resp->status = NFS4_OK;
2417 out:
2418 DTRACE_NFSV4_2(op__getfh__done, struct compound_state *, cs,
2419 GETFH4res *, resp);
2420 }
2421
2422 static void
rfs4_op_getfh_free(nfs_resop4 * resop)2423 rfs4_op_getfh_free(nfs_resop4 *resop)
2424 {
2425 GETFH4res *resp = &resop->nfs_resop4_u.opgetfh;
2426
2427 if (resp->status == NFS4_OK &&
2428 resp->object.nfs_fh4_val != NULL) {
2429 kmem_free(resp->object.nfs_fh4_val, resp->object.nfs_fh4_len);
2430 resp->object.nfs_fh4_val = NULL;
2431 resp->object.nfs_fh4_len = 0;
2432 }
2433 }
2434
2435 /*
2436 * illegal: args: void
2437 * res : status (NFS4ERR_OP_ILLEGAL)
2438 */
2439 /* ARGSUSED */
2440 static void
rfs4_op_illegal(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)2441 rfs4_op_illegal(nfs_argop4 *argop, nfs_resop4 *resop,
2442 struct svc_req *req, struct compound_state *cs)
2443 {
2444 ILLEGAL4res *resp = &resop->nfs_resop4_u.opillegal;
2445
2446 resop->resop = OP_ILLEGAL;
2447 *cs->statusp = resp->status = NFS4ERR_OP_ILLEGAL;
2448 }
2449
2450 /*
2451 * link: args: SAVED_FH: file, CURRENT_FH: target directory
2452 * res: status. If success - CURRENT_FH unchanged, return change_info
2453 */
2454 /* ARGSUSED */
2455 static void
rfs4_op_link(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)2456 rfs4_op_link(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
2457 struct compound_state *cs)
2458 {
2459 LINK4args *args = &argop->nfs_argop4_u.oplink;
2460 LINK4res *resp = &resop->nfs_resop4_u.oplink;
2461 int error;
2462 vnode_t *vp;
2463 vnode_t *dvp;
2464 struct vattr bdva, idva, adva;
2465 char *nm;
2466 uint_t len;
2467 struct sockaddr *ca;
2468 char *name = NULL;
2469 nfsstat4 status;
2470
2471 DTRACE_NFSV4_2(op__link__start, struct compound_state *, cs,
2472 LINK4args *, args);
2473
2474 /* SAVED_FH: source object */
2475 vp = cs->saved_vp;
2476 if (vp == NULL) {
2477 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
2478 goto out;
2479 }
2480
2481 /* CURRENT_FH: target directory */
2482 dvp = cs->vp;
2483 if (dvp == NULL) {
2484 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
2485 goto out;
2486 }
2487
2488 /*
2489 * If there is a non-shared filesystem mounted on this vnode,
2490 * do not allow to link any file in this directory.
2491 */
2492 if (vn_ismntpt(dvp)) {
2493 *cs->statusp = resp->status = NFS4ERR_ACCESS;
2494 goto out;
2495 }
2496
2497 if (cs->access == CS_ACCESS_DENIED) {
2498 *cs->statusp = resp->status = NFS4ERR_ACCESS;
2499 goto out;
2500 }
2501
2502 /* Check source object's type validity */
2503 if (vp->v_type == VDIR) {
2504 *cs->statusp = resp->status = NFS4ERR_ISDIR;
2505 goto out;
2506 }
2507
2508 /* Check target directory's type */
2509 if (dvp->v_type != VDIR) {
2510 *cs->statusp = resp->status = NFS4ERR_NOTDIR;
2511 goto out;
2512 }
2513
2514 if (cs->saved_exi != cs->exi) {
2515 *cs->statusp = resp->status = NFS4ERR_XDEV;
2516 goto out;
2517 }
2518
2519 status = utf8_dir_verify(&args->newname);
2520 if (status != NFS4_OK) {
2521 *cs->statusp = resp->status = status;
2522 goto out;
2523 }
2524
2525 nm = utf8_to_fn(&args->newname, &len, NULL);
2526 if (nm == NULL) {
2527 *cs->statusp = resp->status = NFS4ERR_INVAL;
2528 goto out;
2529 }
2530
2531 if (len > MAXNAMELEN) {
2532 *cs->statusp = resp->status = NFS4ERR_NAMETOOLONG;
2533 kmem_free(nm, len);
2534 goto out;
2535 }
2536
2537 if (rdonly4(req, cs)) {
2538 *cs->statusp = resp->status = NFS4ERR_ROFS;
2539 kmem_free(nm, len);
2540 goto out;
2541 }
2542
2543 /* Get "before" change value */
2544 bdva.va_mask = AT_CTIME|AT_SEQ;
2545 error = VOP_GETATTR(dvp, &bdva, 0, cs->cr, NULL);
2546 if (error) {
2547 *cs->statusp = resp->status = puterrno4(error);
2548 kmem_free(nm, len);
2549 goto out;
2550 }
2551
2552 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2553 name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
2554 MAXPATHLEN + 1);
2555
2556 if (name == NULL) {
2557 *cs->statusp = resp->status = NFS4ERR_INVAL;
2558 kmem_free(nm, len);
2559 goto out;
2560 }
2561
2562 NFS4_SET_FATTR4_CHANGE(resp->cinfo.before, bdva.va_ctime)
2563
2564 error = VOP_LINK(dvp, vp, name, cs->cr, NULL, 0);
2565
2566 if (nm != name)
2567 kmem_free(name, MAXPATHLEN + 1);
2568 kmem_free(nm, len);
2569
2570 /*
2571 * Get the initial "after" sequence number, if it fails, set to zero
2572 */
2573 idva.va_mask = AT_SEQ;
2574 if (VOP_GETATTR(dvp, &idva, 0, cs->cr, NULL))
2575 idva.va_seq = 0;
2576
2577 /*
2578 * Force modified data and metadata out to stable storage.
2579 */
2580 (void) VOP_FSYNC(vp, FNODSYNC, cs->cr, NULL);
2581 (void) VOP_FSYNC(dvp, 0, cs->cr, NULL);
2582
2583 if (error) {
2584 *cs->statusp = resp->status = puterrno4(error);
2585 goto out;
2586 }
2587
2588 /*
2589 * Get "after" change value, if it fails, simply return the
2590 * before value.
2591 */
2592 adva.va_mask = AT_CTIME|AT_SEQ;
2593 if (VOP_GETATTR(dvp, &adva, 0, cs->cr, NULL)) {
2594 adva.va_ctime = bdva.va_ctime;
2595 adva.va_seq = 0;
2596 }
2597
2598 NFS4_SET_FATTR4_CHANGE(resp->cinfo.after, adva.va_ctime)
2599
2600 /*
2601 * The cinfo.atomic = TRUE only if we have
2602 * non-zero va_seq's, and it has incremented by exactly one
2603 * during the VOP_LINK and it didn't change during the VOP_FSYNC.
2604 */
2605 if (bdva.va_seq && idva.va_seq && adva.va_seq &&
2606 idva.va_seq == (bdva.va_seq + 1) && idva.va_seq == adva.va_seq)
2607 resp->cinfo.atomic = TRUE;
2608 else
2609 resp->cinfo.atomic = FALSE;
2610
2611 *cs->statusp = resp->status = NFS4_OK;
2612 out:
2613 DTRACE_NFSV4_2(op__link__done, struct compound_state *, cs,
2614 LINK4res *, resp);
2615 }
2616
2617 /*
2618 * Used by rfs4_op_lookup and rfs4_op_lookupp to do the actual work.
2619 */
2620
2621 /* ARGSUSED */
2622 static nfsstat4
do_rfs4_op_lookup(char * nm,struct svc_req * req,struct compound_state * cs)2623 do_rfs4_op_lookup(char *nm, struct svc_req *req, struct compound_state *cs)
2624 {
2625 int error;
2626 int different_export = 0;
2627 vnode_t *vp, *pre_tvp = NULL, *oldvp = NULL;
2628 struct exportinfo *exi = NULL, *pre_exi = NULL;
2629 nfsstat4 stat;
2630 fid_t fid;
2631 int attrdir, dotdot, walk;
2632 bool_t is_newvp = FALSE;
2633
2634 if (cs->vp->v_flag & V_XATTRDIR) {
2635 attrdir = 1;
2636 ASSERT(get_fh4_flag(&cs->fh, FH4_ATTRDIR));
2637 } else {
2638 attrdir = 0;
2639 ASSERT(! get_fh4_flag(&cs->fh, FH4_ATTRDIR));
2640 }
2641
2642 dotdot = (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0');
2643
2644 /*
2645 * If dotdotting, then need to check whether it's
2646 * above the root of a filesystem, or above an
2647 * export point.
2648 */
2649 if (dotdot) {
2650
2651 /*
2652 * If dotdotting at the root of a filesystem, then
2653 * need to traverse back to the mounted-on filesystem
2654 * and do the dotdot lookup there.
2655 */
2656 if (cs->vp->v_flag & VROOT) {
2657
2658 /*
2659 * If at the system root, then can
2660 * go up no further.
2661 */
2662 if (VN_CMP(cs->vp, rootdir))
2663 return (puterrno4(ENOENT));
2664
2665 /*
2666 * Traverse back to the mounted-on filesystem
2667 */
2668 cs->vp = untraverse(cs->vp);
2669
2670 /*
2671 * Set the different_export flag so we remember
2672 * to pick up a new exportinfo entry for
2673 * this new filesystem.
2674 */
2675 different_export = 1;
2676 } else {
2677
2678 /*
2679 * If dotdotting above an export point then set
2680 * the different_export to get new export info.
2681 */
2682 different_export = nfs_exported(cs->exi, cs->vp);
2683 }
2684 }
2685
2686 error = VOP_LOOKUP(cs->vp, nm, &vp, NULL, 0, NULL, cs->cr,
2687 NULL, NULL, NULL);
2688 if (error)
2689 return (puterrno4(error));
2690
2691 /*
2692 * If the vnode is in a pseudo filesystem, check whether it is visible.
2693 *
2694 * XXX if the vnode is a symlink and it is not visible in
2695 * a pseudo filesystem, return ENOENT (not following symlink).
2696 * V4 client can not mount such symlink. This is a regression
2697 * from V2/V3.
2698 *
2699 * In the same exported filesystem, if the security flavor used
2700 * is not an explicitly shared flavor, limit the view to the visible
2701 * list entries only. This is not a WRONGSEC case because it's already
2702 * checked via PUTROOTFH/PUTPUBFH or PUTFH.
2703 */
2704 if (!different_export &&
2705 (PSEUDO(cs->exi) || ! is_exported_sec(cs->nfsflavor, cs->exi) ||
2706 cs->access & CS_ACCESS_LIMITED)) {
2707 if (! nfs_visible(cs->exi, vp, &different_export)) {
2708 VN_RELE(vp);
2709 return (puterrno4(ENOENT));
2710 }
2711 }
2712
2713 /*
2714 * If it's a mountpoint, then traverse it.
2715 */
2716 if (vn_ismntpt(vp)) {
2717 pre_exi = cs->exi; /* save pre-traversed exportinfo */
2718 pre_tvp = vp; /* save pre-traversed vnode */
2719
2720 /*
2721 * hold pre_tvp to counteract rele by traverse. We will
2722 * need pre_tvp below if checkexport fails
2723 */
2724 VN_HOLD(pre_tvp);
2725 if ((error = traverse(&vp)) != 0) {
2726 VN_RELE(vp);
2727 VN_RELE(pre_tvp);
2728 return (puterrno4(error));
2729 }
2730 different_export = 1;
2731 } else if (vp->v_vfsp != cs->vp->v_vfsp) {
2732 /*
2733 * The vfsp comparison is to handle the case where
2734 * a LOFS mount is shared. lo_lookup traverses mount points,
2735 * and NFS is unaware of local fs transistions because
2736 * v_vfsmountedhere isn't set. For this special LOFS case,
2737 * the dir and the obj returned by lookup will have different
2738 * vfs ptrs.
2739 */
2740 different_export = 1;
2741 }
2742
2743 if (different_export) {
2744
2745 bzero(&fid, sizeof (fid));
2746 fid.fid_len = MAXFIDSZ;
2747 error = vop_fid_pseudo(vp, &fid);
2748 if (error) {
2749 VN_RELE(vp);
2750 if (pre_tvp)
2751 VN_RELE(pre_tvp);
2752 return (puterrno4(error));
2753 }
2754
2755 if (dotdot)
2756 exi = nfs_vptoexi(NULL, vp, cs->cr, &walk, NULL, TRUE);
2757 else
2758 exi = checkexport(&vp->v_vfsp->vfs_fsid, &fid, vp);
2759
2760 if (exi == NULL) {
2761 if (pre_tvp) {
2762 /*
2763 * If this vnode is a mounted-on vnode,
2764 * but the mounted-on file system is not
2765 * exported, send back the filehandle for
2766 * the mounted-on vnode, not the root of
2767 * the mounted-on file system.
2768 */
2769 VN_RELE(vp);
2770 vp = pre_tvp;
2771 exi = pre_exi;
2772 if (exi != NULL)
2773 exi_hold(exi);
2774 } else {
2775 VN_RELE(vp);
2776 return (puterrno4(EACCES));
2777 }
2778 } else if (pre_tvp) {
2779 /* we're done with pre_tvp now. release extra hold */
2780 VN_RELE(pre_tvp);
2781 }
2782
2783 if (cs->exi != NULL)
2784 exi_rele(cs->exi);
2785 cs->exi = exi;
2786
2787 /*
2788 * Now we do a checkauth4. The reason is that
2789 * this client/user may not have access to the new
2790 * exported file system, and if he does,
2791 * the client/user may be mapped to a different uid.
2792 *
2793 * We start with a new cr, because the checkauth4 done
2794 * in the PUT*FH operation over wrote the cred's uid,
2795 * gid, etc, and we want the real thing before calling
2796 * checkauth4()
2797 */
2798 crfree(cs->cr);
2799 cs->cr = crdup(cs->basecr);
2800
2801 oldvp = cs->vp;
2802 cs->vp = vp;
2803 is_newvp = TRUE;
2804
2805 stat = call_checkauth4(cs, req);
2806 if (stat != NFS4_OK) {
2807 VN_RELE(cs->vp);
2808 cs->vp = oldvp;
2809 return (stat);
2810 }
2811 }
2812
2813 /*
2814 * After various NFS checks, do a label check on the path
2815 * component. The label on this path should either be the
2816 * global zone's label or a zone's label. We are only
2817 * interested in the zone's label because exported files
2818 * in global zone is accessible (though read-only) to
2819 * clients. The exportability/visibility check is already
2820 * done before reaching this code.
2821 */
2822 if (is_system_labeled()) {
2823 bslabel_t *clabel;
2824
2825 ASSERT(req->rq_label != NULL);
2826 clabel = req->rq_label;
2827 DTRACE_PROBE2(tx__rfs4__log__info__oplookup__clabel, char *,
2828 "got client label from request(1)", struct svc_req *, req);
2829
2830 if (!blequal(&l_admin_low->tsl_label, clabel)) {
2831 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
2832 cs->exi)) {
2833 error = EACCES;
2834 goto err_out;
2835 }
2836 } else {
2837 /*
2838 * We grant access to admin_low label clients
2839 * only if the client is trusted, i.e. also
2840 * running Solaris Trusted Extension.
2841 */
2842 struct sockaddr *ca;
2843 int addr_type;
2844 void *ipaddr;
2845 tsol_tpc_t *tp;
2846
2847 ca = (struct sockaddr *)svc_getrpccaller(
2848 req->rq_xprt)->buf;
2849 if (ca->sa_family == AF_INET) {
2850 addr_type = IPV4_VERSION;
2851 ipaddr = &((struct sockaddr_in *)ca)->sin_addr;
2852 } else if (ca->sa_family == AF_INET6) {
2853 addr_type = IPV6_VERSION;
2854 ipaddr = &((struct sockaddr_in6 *)
2855 ca)->sin6_addr;
2856 }
2857 tp = find_tpc(ipaddr, addr_type, B_FALSE);
2858 if (tp == NULL || tp->tpc_tp.tp_doi !=
2859 l_admin_low->tsl_doi || tp->tpc_tp.host_type !=
2860 SUN_CIPSO) {
2861 if (tp != NULL)
2862 TPC_RELE(tp);
2863 error = EACCES;
2864 goto err_out;
2865 }
2866 TPC_RELE(tp);
2867 }
2868 }
2869
2870 error = makefh4(&cs->fh, vp, cs->exi);
2871
2872 err_out:
2873 if (error) {
2874 if (is_newvp) {
2875 VN_RELE(cs->vp);
2876 cs->vp = oldvp;
2877 } else
2878 VN_RELE(vp);
2879 return (puterrno4(error));
2880 }
2881
2882 if (!is_newvp) {
2883 if (cs->vp)
2884 VN_RELE(cs->vp);
2885 cs->vp = vp;
2886 } else if (oldvp)
2887 VN_RELE(oldvp);
2888
2889 /*
2890 * if did lookup on attrdir and didn't lookup .., set named
2891 * attr fh flag
2892 */
2893 if (attrdir && ! dotdot)
2894 set_fh4_flag(&cs->fh, FH4_NAMEDATTR);
2895
2896 /* Assume false for now, open proc will set this */
2897 cs->mandlock = FALSE;
2898
2899 return (NFS4_OK);
2900 }
2901
2902 /* ARGSUSED */
2903 static void
rfs4_op_lookup(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)2904 rfs4_op_lookup(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
2905 struct compound_state *cs)
2906 {
2907 LOOKUP4args *args = &argop->nfs_argop4_u.oplookup;
2908 LOOKUP4res *resp = &resop->nfs_resop4_u.oplookup;
2909 char *nm;
2910 uint_t len;
2911 struct sockaddr *ca;
2912 char *name = NULL;
2913 nfsstat4 status;
2914
2915 DTRACE_NFSV4_2(op__lookup__start, struct compound_state *, cs,
2916 LOOKUP4args *, args);
2917
2918 if (cs->vp == NULL) {
2919 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
2920 goto out;
2921 }
2922
2923 if (cs->vp->v_type == VLNK) {
2924 *cs->statusp = resp->status = NFS4ERR_SYMLINK;
2925 goto out;
2926 }
2927
2928 if (cs->vp->v_type != VDIR) {
2929 *cs->statusp = resp->status = NFS4ERR_NOTDIR;
2930 goto out;
2931 }
2932
2933 status = utf8_dir_verify(&args->objname);
2934 if (status != NFS4_OK) {
2935 *cs->statusp = resp->status = status;
2936 goto out;
2937 }
2938
2939 nm = utf8_to_str(&args->objname, &len, NULL);
2940 if (nm == NULL) {
2941 *cs->statusp = resp->status = NFS4ERR_INVAL;
2942 goto out;
2943 }
2944
2945 if (len > MAXNAMELEN) {
2946 *cs->statusp = resp->status = NFS4ERR_NAMETOOLONG;
2947 kmem_free(nm, len);
2948 goto out;
2949 }
2950
2951 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2952 name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
2953 MAXPATHLEN + 1);
2954
2955 if (name == NULL) {
2956 *cs->statusp = resp->status = NFS4ERR_INVAL;
2957 kmem_free(nm, len);
2958 goto out;
2959 }
2960
2961 *cs->statusp = resp->status = do_rfs4_op_lookup(name, req, cs);
2962
2963 if (name != nm)
2964 kmem_free(name, MAXPATHLEN + 1);
2965 kmem_free(nm, len);
2966
2967 out:
2968 DTRACE_NFSV4_2(op__lookup__done, struct compound_state *, cs,
2969 LOOKUP4res *, resp);
2970 }
2971
2972 /* ARGSUSED */
2973 static void
rfs4_op_lookupp(nfs_argop4 * args,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)2974 rfs4_op_lookupp(nfs_argop4 *args, nfs_resop4 *resop, struct svc_req *req,
2975 struct compound_state *cs)
2976 {
2977 LOOKUPP4res *resp = &resop->nfs_resop4_u.oplookupp;
2978
2979 DTRACE_NFSV4_1(op__lookupp__start, struct compound_state *, cs);
2980
2981 if (cs->vp == NULL) {
2982 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
2983 goto out;
2984 }
2985
2986 if (cs->vp->v_type != VDIR) {
2987 *cs->statusp = resp->status = NFS4ERR_NOTDIR;
2988 goto out;
2989 }
2990
2991 *cs->statusp = resp->status = do_rfs4_op_lookup("..", req, cs);
2992
2993 /*
2994 * From NFSV4 Specification, LOOKUPP should not check for
2995 * NFS4ERR_WRONGSEC. Retrun NFS4_OK instead.
2996 */
2997 if (resp->status == NFS4ERR_WRONGSEC) {
2998 *cs->statusp = resp->status = NFS4_OK;
2999 }
3000
3001 out:
3002 DTRACE_NFSV4_2(op__lookupp__done, struct compound_state *, cs,
3003 LOOKUPP4res *, resp);
3004 }
3005
3006
3007 /*ARGSUSED2*/
3008 static void
rfs4_op_openattr(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)3009 rfs4_op_openattr(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
3010 struct compound_state *cs)
3011 {
3012 OPENATTR4args *args = &argop->nfs_argop4_u.opopenattr;
3013 OPENATTR4res *resp = &resop->nfs_resop4_u.opopenattr;
3014 vnode_t *avp = NULL;
3015 int lookup_flags = LOOKUP_XATTR, error;
3016 int exp_ro = 0;
3017
3018 DTRACE_NFSV4_2(op__openattr__start, struct compound_state *, cs,
3019 OPENATTR4args *, args);
3020
3021 if (cs->vp == NULL) {
3022 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
3023 goto out;
3024 }
3025
3026 if ((cs->vp->v_vfsp->vfs_flag & VFS_XATTR) == 0 &&
3027 !vfs_has_feature(cs->vp->v_vfsp, VFSFT_SYSATTR_VIEWS)) {
3028 *cs->statusp = resp->status = puterrno4(ENOTSUP);
3029 goto out;
3030 }
3031
3032 /*
3033 * If file system supports passing ACE mask to VOP_ACCESS then
3034 * check for ACE_READ_NAMED_ATTRS, otherwise do legacy checks
3035 */
3036
3037 if (vfs_has_feature(cs->vp->v_vfsp, VFSFT_ACEMASKONACCESS))
3038 error = VOP_ACCESS(cs->vp, ACE_READ_NAMED_ATTRS,
3039 V_ACE_MASK, cs->cr, NULL);
3040 else
3041 error = ((VOP_ACCESS(cs->vp, VREAD, 0, cs->cr, NULL) != 0) &&
3042 (VOP_ACCESS(cs->vp, VWRITE, 0, cs->cr, NULL) != 0) &&
3043 (VOP_ACCESS(cs->vp, VEXEC, 0, cs->cr, NULL) != 0));
3044
3045 if (error) {
3046 *cs->statusp = resp->status = puterrno4(EACCES);
3047 goto out;
3048 }
3049
3050 /*
3051 * The CREATE_XATTR_DIR VOP flag cannot be specified if
3052 * the file system is exported read-only -- regardless of
3053 * createdir flag. Otherwise the attrdir would be created
3054 * (assuming server fs isn't mounted readonly locally). If
3055 * VOP_LOOKUP returns ENOENT in this case, the error will
3056 * be translated into EROFS. ENOSYS is mapped to ENOTSUP
3057 * because specfs has no VOP_LOOKUP op, so the macro would
3058 * return ENOSYS. EINVAL is returned by all (current)
3059 * Solaris file system implementations when any of their
3060 * restrictions are violated (xattr(dir) can't have xattrdir).
3061 * Returning NOTSUPP is more appropriate in this case
3062 * because the object will never be able to have an attrdir.
3063 */
3064 if (args->createdir && ! (exp_ro = rdonly4(req, cs)))
3065 lookup_flags |= CREATE_XATTR_DIR;
3066
3067 error = VOP_LOOKUP(cs->vp, "", &avp, NULL, lookup_flags, NULL, cs->cr,
3068 NULL, NULL, NULL);
3069
3070 if (error) {
3071 if (error == ENOENT && args->createdir && exp_ro)
3072 *cs->statusp = resp->status = puterrno4(EROFS);
3073 else if (error == EINVAL || error == ENOSYS)
3074 *cs->statusp = resp->status = puterrno4(ENOTSUP);
3075 else
3076 *cs->statusp = resp->status = puterrno4(error);
3077 goto out;
3078 }
3079
3080 ASSERT(avp->v_flag & V_XATTRDIR);
3081
3082 error = makefh4(&cs->fh, avp, cs->exi);
3083
3084 if (error) {
3085 VN_RELE(avp);
3086 *cs->statusp = resp->status = puterrno4(error);
3087 goto out;
3088 }
3089
3090 VN_RELE(cs->vp);
3091 cs->vp = avp;
3092
3093 /*
3094 * There is no requirement for an attrdir fh flag
3095 * because the attrdir has a vnode flag to distinguish
3096 * it from regular (non-xattr) directories. The
3097 * FH4_ATTRDIR flag is set for future sanity checks.
3098 */
3099 set_fh4_flag(&cs->fh, FH4_ATTRDIR);
3100 *cs->statusp = resp->status = NFS4_OK;
3101
3102 out:
3103 DTRACE_NFSV4_2(op__openattr__done, struct compound_state *, cs,
3104 OPENATTR4res *, resp);
3105 }
3106
3107 static int
do_io(int direction,vnode_t * vp,struct uio * uio,int ioflag,cred_t * cred,caller_context_t * ct)3108 do_io(int direction, vnode_t *vp, struct uio *uio, int ioflag, cred_t *cred,
3109 caller_context_t *ct)
3110 {
3111 int error;
3112 int i;
3113 clock_t delaytime;
3114
3115 delaytime = MSEC_TO_TICK_ROUNDUP(rfs4_lock_delay);
3116
3117 /*
3118 * Don't block on mandatory locks. If this routine returns
3119 * EAGAIN, the caller should return NFS4ERR_LOCKED.
3120 */
3121 uio->uio_fmode = FNONBLOCK;
3122
3123 for (i = 0; i < rfs4_maxlock_tries; i++) {
3124
3125
3126 if (direction == FREAD) {
3127 (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, ct);
3128 error = VOP_READ(vp, uio, ioflag, cred, ct);
3129 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, ct);
3130 } else {
3131 (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, ct);
3132 error = VOP_WRITE(vp, uio, ioflag, cred, ct);
3133 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, ct);
3134 }
3135
3136 if (error != EAGAIN)
3137 break;
3138
3139 if (i < rfs4_maxlock_tries - 1) {
3140 delay(delaytime);
3141 delaytime *= 2;
3142 }
3143 }
3144
3145 return (error);
3146 }
3147
3148 /* ARGSUSED */
3149 static void
rfs4_op_read(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)3150 rfs4_op_read(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
3151 struct compound_state *cs)
3152 {
3153 READ4args *args = &argop->nfs_argop4_u.opread;
3154 READ4res *resp = &resop->nfs_resop4_u.opread;
3155 int error;
3156 int verror;
3157 vnode_t *vp;
3158 struct vattr va;
3159 struct iovec iov, *iovp = NULL;
3160 int iovcnt;
3161 struct uio uio;
3162 u_offset_t offset;
3163 bool_t *deleg = &cs->deleg;
3164 nfsstat4 stat;
3165 int in_crit = 0;
3166 mblk_t *mp = NULL;
3167 int alloc_err = 0;
3168 int rdma_used = 0;
3169 int loaned_buffers;
3170 caller_context_t ct;
3171 struct uio *uiop;
3172
3173 DTRACE_NFSV4_2(op__read__start, struct compound_state *, cs,
3174 READ4args, args);
3175
3176 vp = cs->vp;
3177 if (vp == NULL) {
3178 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
3179 goto out;
3180 }
3181 if (cs->access == CS_ACCESS_DENIED) {
3182 *cs->statusp = resp->status = NFS4ERR_ACCESS;
3183 goto out;
3184 }
3185
3186 if ((stat = rfs4_check_stateid(FREAD, vp, &args->stateid, FALSE,
3187 deleg, TRUE, &ct)) != NFS4_OK) {
3188 *cs->statusp = resp->status = stat;
3189 goto out;
3190 }
3191
3192 /*
3193 * Enter the critical region before calling VOP_RWLOCK
3194 * to avoid a deadlock with write requests.
3195 */
3196 if (nbl_need_check(vp)) {
3197 nbl_start_crit(vp, RW_READER);
3198 in_crit = 1;
3199 if (nbl_conflict(vp, NBL_READ, args->offset, args->count, 0,
3200 &ct)) {
3201 *cs->statusp = resp->status = NFS4ERR_LOCKED;
3202 goto out;
3203 }
3204 }
3205
3206 if ((stat = rfs4_check_stateid(FREAD, vp, &args->stateid, FALSE,
3207 deleg, TRUE, &ct)) != NFS4_OK) {
3208 *cs->statusp = resp->status = stat;
3209 goto out;
3210 }
3211
3212 if (args->wlist) {
3213 if (args->count > clist_len(args->wlist)) {
3214 *cs->statusp = resp->status = NFS4ERR_INVAL;
3215 goto out;
3216 }
3217 rdma_used = 1;
3218 }
3219
3220 /* use loaned buffers for TCP */
3221 loaned_buffers = (nfs_loaned_buffers && !rdma_used) ? 1 : 0;
3222
3223 va.va_mask = AT_MODE|AT_SIZE|AT_UID;
3224 verror = VOP_GETATTR(vp, &va, 0, cs->cr, &ct);
3225
3226 /*
3227 * If we can't get the attributes, then we can't do the
3228 * right access checking. So, we'll fail the request.
3229 */
3230 if (verror) {
3231 *cs->statusp = resp->status = puterrno4(verror);
3232 goto out;
3233 }
3234
3235 if (vp->v_type != VREG) {
3236 *cs->statusp = resp->status =
3237 ((vp->v_type == VDIR) ? NFS4ERR_ISDIR : NFS4ERR_INVAL);
3238 goto out;
3239 }
3240
3241 if (crgetuid(cs->cr) != va.va_uid &&
3242 (error = VOP_ACCESS(vp, VREAD, 0, cs->cr, &ct)) &&
3243 (error = VOP_ACCESS(vp, VEXEC, 0, cs->cr, &ct))) {
3244 *cs->statusp = resp->status = puterrno4(error);
3245 goto out;
3246 }
3247
3248 if (MANDLOCK(vp, va.va_mode)) { /* XXX - V4 supports mand locking */
3249 *cs->statusp = resp->status = NFS4ERR_ACCESS;
3250 goto out;
3251 }
3252
3253 offset = args->offset;
3254 if (offset >= va.va_size) {
3255 *cs->statusp = resp->status = NFS4_OK;
3256 resp->eof = TRUE;
3257 resp->data_len = 0;
3258 resp->data_val = NULL;
3259 resp->mblk = NULL;
3260 /* RDMA */
3261 resp->wlist = args->wlist;
3262 resp->wlist_len = resp->data_len;
3263 *cs->statusp = resp->status = NFS4_OK;
3264 if (resp->wlist)
3265 clist_zero_len(resp->wlist);
3266 goto out;
3267 }
3268
3269 if (args->count == 0) {
3270 *cs->statusp = resp->status = NFS4_OK;
3271 resp->eof = FALSE;
3272 resp->data_len = 0;
3273 resp->data_val = NULL;
3274 resp->mblk = NULL;
3275 /* RDMA */
3276 resp->wlist = args->wlist;
3277 resp->wlist_len = resp->data_len;
3278 if (resp->wlist)
3279 clist_zero_len(resp->wlist);
3280 goto out;
3281 }
3282
3283 /*
3284 * Do not allocate memory more than maximum allowed
3285 * transfer size
3286 */
3287 if (args->count > rfs4_tsize(req))
3288 args->count = rfs4_tsize(req);
3289
3290 if (loaned_buffers) {
3291 uiop = (uio_t *)rfs_setup_xuio(vp);
3292 ASSERT(uiop != NULL);
3293 uiop->uio_segflg = UIO_SYSSPACE;
3294 uiop->uio_loffset = args->offset;
3295 uiop->uio_resid = args->count;
3296
3297 /* Jump to do the read if successful */
3298 if (!VOP_REQZCBUF(vp, UIO_READ, (xuio_t *)uiop, cs->cr, &ct)) {
3299 /*
3300 * Need to hold the vnode until after VOP_RETZCBUF()
3301 * is called.
3302 */
3303 VN_HOLD(vp);
3304 goto doio_read;
3305 }
3306
3307 DTRACE_PROBE2(nfss__i__reqzcbuf_failed, int,
3308 uiop->uio_loffset, int, uiop->uio_resid);
3309
3310 uiop->uio_extflg = 0;
3311
3312 /* failure to setup for zero copy */
3313 rfs_free_xuio((void *)uiop);
3314 loaned_buffers = 0;
3315 }
3316
3317 /*
3318 * If returning data via RDMA Write, then grab the chunk list. If we
3319 * aren't returning READ data w/RDMA_WRITE, then grab a mblk.
3320 */
3321 if (rdma_used) {
3322 mp = NULL;
3323 (void) rdma_get_wchunk(req, &iov, args->wlist);
3324 uio.uio_iov = &iov;
3325 uio.uio_iovcnt = 1;
3326 } else {
3327 /*
3328 * mp will contain the data to be sent out in the read reply.
3329 * It will be freed after the reply has been sent.
3330 */
3331 mp = rfs_read_alloc(args->count, &iovp, &iovcnt);
3332 ASSERT(mp != NULL);
3333 ASSERT(alloc_err == 0);
3334 uio.uio_iov = iovp;
3335 uio.uio_iovcnt = iovcnt;
3336 }
3337
3338 uio.uio_segflg = UIO_SYSSPACE;
3339 uio.uio_extflg = UIO_COPY_CACHED;
3340 uio.uio_loffset = args->offset;
3341 uio.uio_resid = args->count;
3342 uiop = &uio;
3343
3344 doio_read:
3345 error = do_io(FREAD, vp, uiop, 0, cs->cr, &ct);
3346
3347 va.va_mask = AT_SIZE;
3348 verror = VOP_GETATTR(vp, &va, 0, cs->cr, &ct);
3349
3350 if (error) {
3351 if (mp)
3352 freemsg(mp);
3353 *cs->statusp = resp->status = puterrno4(error);
3354 goto out;
3355 }
3356
3357 /* make mblk using zc buffers */
3358 if (loaned_buffers) {
3359 mp = uio_to_mblk(uiop);
3360 ASSERT(mp != NULL);
3361 }
3362
3363 *cs->statusp = resp->status = NFS4_OK;
3364
3365 ASSERT(uiop->uio_resid >= 0);
3366 resp->data_len = args->count - uiop->uio_resid;
3367 if (mp) {
3368 resp->data_val = (char *)mp->b_datap->db_base;
3369 rfs_rndup_mblks(mp, resp->data_len, loaned_buffers);
3370 } else {
3371 resp->data_val = (caddr_t)iov.iov_base;
3372 }
3373
3374 resp->mblk = mp;
3375
3376 if (!verror && offset + resp->data_len == va.va_size)
3377 resp->eof = TRUE;
3378 else
3379 resp->eof = FALSE;
3380
3381 if (rdma_used) {
3382 if (!rdma_setup_read_data4(args, resp)) {
3383 *cs->statusp = resp->status = NFS4ERR_INVAL;
3384 }
3385 } else {
3386 resp->wlist = NULL;
3387 }
3388
3389 out:
3390 if (in_crit)
3391 nbl_end_crit(vp);
3392
3393 if (iovp != NULL)
3394 kmem_free(iovp, iovcnt * sizeof (struct iovec));
3395
3396 DTRACE_NFSV4_2(op__read__done, struct compound_state *, cs,
3397 READ4res *, resp);
3398 }
3399
3400 static void
rfs4_op_read_free(nfs_resop4 * resop)3401 rfs4_op_read_free(nfs_resop4 *resop)
3402 {
3403 READ4res *resp = &resop->nfs_resop4_u.opread;
3404
3405 if (resp->status == NFS4_OK && resp->mblk != NULL) {
3406 freemsg(resp->mblk);
3407 resp->mblk = NULL;
3408 resp->data_val = NULL;
3409 resp->data_len = 0;
3410 }
3411 }
3412
3413 static void
rfs4_op_readdir_free(nfs_resop4 * resop)3414 rfs4_op_readdir_free(nfs_resop4 * resop)
3415 {
3416 READDIR4res *resp = &resop->nfs_resop4_u.opreaddir;
3417
3418 if (resp->status == NFS4_OK && resp->mblk != NULL) {
3419 freeb(resp->mblk);
3420 resp->mblk = NULL;
3421 resp->data_len = 0;
3422 }
3423 }
3424
3425
3426 /* ARGSUSED */
3427 static void
rfs4_op_putpubfh(nfs_argop4 * args,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)3428 rfs4_op_putpubfh(nfs_argop4 *args, nfs_resop4 *resop, struct svc_req *req,
3429 struct compound_state *cs)
3430 {
3431 PUTPUBFH4res *resp = &resop->nfs_resop4_u.opputpubfh;
3432 int error;
3433 vnode_t *vp;
3434 struct exportinfo *exi, *sav_exi;
3435 nfs_fh4_fmt_t *fh_fmtp;
3436
3437 DTRACE_NFSV4_1(op__putpubfh__start, struct compound_state *, cs);
3438
3439 if (cs->vp) {
3440 VN_RELE(cs->vp);
3441 cs->vp = NULL;
3442 }
3443
3444 if (cs->cr)
3445 crfree(cs->cr);
3446
3447 cs->cr = crdup(cs->basecr);
3448
3449 rw_enter(&exported_lock, RW_READER);
3450 exi = exi_public;
3451 exi_hold(exi);
3452 rw_exit(&exported_lock);
3453
3454 vp = exi->exi_vp;
3455 if (vp == NULL) {
3456 exi_rele(exi);
3457 *cs->statusp = resp->status = NFS4ERR_SERVERFAULT;
3458 goto out;
3459 }
3460
3461 error = makefh4(&cs->fh, vp, exi);
3462 if (error != 0) {
3463 exi_rele(exi);
3464 *cs->statusp = resp->status = puterrno4(error);
3465 goto out;
3466 }
3467
3468 sav_exi = cs->exi;
3469 cs->exi = exi;
3470
3471 if (cs->exi == exi_root) {
3472 /*
3473 * No filesystem is actually shared public, so we default
3474 * to exi_root. In this case, we must check whether root
3475 * is exported.
3476 */
3477 fh_fmtp = (nfs_fh4_fmt_t *)cs->fh.nfs_fh4_val;
3478
3479 /*
3480 * if root filesystem is exported, the exportinfo struct that we
3481 * should use is what checkexport returns, because exi_root is
3482 * actually a mostly empty struct.
3483 */
3484 exi = checkexport(&fh_fmtp->fh4_fsid,
3485 (fid_t *)&fh_fmtp->fh4_xlen, NULL);
3486 if (exi != NULL) {
3487 exi_rele(cs->exi);
3488 cs->exi = exi;
3489 }
3490 }
3491
3492 if (is_system_labeled()) {
3493 bslabel_t *clabel;
3494
3495 ASSERT(req->rq_label != NULL);
3496 clabel = req->rq_label;
3497 DTRACE_PROBE2(tx__rfs4__log__info__opputpubfh__clabel, char *,
3498 "got client label from request(1)",
3499 struct svc_req *, req);
3500 if (!blequal(&l_admin_low->tsl_label, clabel)) {
3501 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3502 cs->exi)) {
3503 *cs->statusp = resp->status =
3504 NFS4ERR_SERVERFAULT;
3505 if (sav_exi != NULL)
3506 exi_rele(sav_exi);
3507 goto out;
3508 }
3509 }
3510 }
3511
3512 VN_HOLD(vp);
3513 cs->vp = vp;
3514
3515 if ((resp->status = call_checkauth4(cs, req)) != NFS4_OK) {
3516 VN_RELE(cs->vp);
3517 cs->vp = NULL;
3518 exi_rele(cs->exi);
3519 cs->exi = sav_exi;
3520 goto out;
3521 }
3522 if (sav_exi != NULL)
3523 exi_rele(sav_exi);
3524
3525 *cs->statusp = resp->status = NFS4_OK;
3526 out:
3527 DTRACE_NFSV4_2(op__putpubfh__done, struct compound_state *, cs,
3528 PUTPUBFH4res *, resp);
3529 }
3530
3531 /*
3532 * XXX - issue with put*fh operations. Suppose /export/home is exported.
3533 * Suppose an NFS client goes to mount /export/home/joe. If /export, home,
3534 * or joe have restrictive search permissions, then we shouldn't let
3535 * the client get a file handle. This is easy to enforce. However, we
3536 * don't know what security flavor should be used until we resolve the
3537 * path name. Another complication is uid mapping. If root is
3538 * the user, then it will be mapped to the anonymous user by default,
3539 * but we won't know that till we've resolved the path name. And we won't
3540 * know what the anonymous user is.
3541 * Luckily, SECINFO is specified to take a full filename.
3542 * So what we will have to in rfs4_op_lookup is check that flavor of
3543 * the target object matches that of the request, and if root was the
3544 * caller, check for the root= and anon= options, and if necessary,
3545 * repeat the lookup using the right cred_t. But that's not done yet.
3546 */
3547 /* ARGSUSED */
3548 static void
rfs4_op_putfh(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)3549 rfs4_op_putfh(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
3550 struct compound_state *cs)
3551 {
3552 PUTFH4args *args = &argop->nfs_argop4_u.opputfh;
3553 PUTFH4res *resp = &resop->nfs_resop4_u.opputfh;
3554 nfs_fh4_fmt_t *fh_fmtp;
3555
3556 DTRACE_NFSV4_2(op__putfh__start, struct compound_state *, cs,
3557 PUTFH4args *, args);
3558
3559 if (cs->vp) {
3560 VN_RELE(cs->vp);
3561 cs->vp = NULL;
3562 }
3563
3564 if (cs->cr) {
3565 crfree(cs->cr);
3566 cs->cr = NULL;
3567 }
3568
3569
3570 if (args->object.nfs_fh4_len < NFS_FH4_LEN) {
3571 *cs->statusp = resp->status = NFS4ERR_BADHANDLE;
3572 goto out;
3573 }
3574
3575 fh_fmtp = (nfs_fh4_fmt_t *)args->object.nfs_fh4_val;
3576 if (cs->exi != NULL)
3577 exi_rele(cs->exi);
3578 cs->exi = checkexport(&fh_fmtp->fh4_fsid, (fid_t *)&fh_fmtp->fh4_xlen,
3579 NULL);
3580
3581 if (cs->exi == NULL) {
3582 *cs->statusp = resp->status = NFS4ERR_STALE;
3583 goto out;
3584 }
3585
3586 cs->cr = crdup(cs->basecr);
3587
3588 ASSERT(cs->cr != NULL);
3589
3590 if (! (cs->vp = nfs4_fhtovp(&args->object, cs->exi, &resp->status))) {
3591 *cs->statusp = resp->status;
3592 goto out;
3593 }
3594
3595 if ((resp->status = call_checkauth4(cs, req)) != NFS4_OK) {
3596 VN_RELE(cs->vp);
3597 cs->vp = NULL;
3598 goto out;
3599 }
3600
3601 nfs_fh4_copy(&args->object, &cs->fh);
3602 *cs->statusp = resp->status = NFS4_OK;
3603 cs->deleg = FALSE;
3604
3605 out:
3606 DTRACE_NFSV4_2(op__putfh__done, struct compound_state *, cs,
3607 PUTFH4res *, resp);
3608 }
3609
3610 /* ARGSUSED */
3611 static void
rfs4_op_putrootfh(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)3612 rfs4_op_putrootfh(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
3613 struct compound_state *cs)
3614 {
3615 PUTROOTFH4res *resp = &resop->nfs_resop4_u.opputrootfh;
3616 int error;
3617 fid_t fid;
3618 struct exportinfo *exi, *sav_exi;
3619
3620 DTRACE_NFSV4_1(op__putrootfh__start, struct compound_state *, cs);
3621
3622 if (cs->vp) {
3623 VN_RELE(cs->vp);
3624 cs->vp = NULL;
3625 }
3626
3627 if (cs->cr)
3628 crfree(cs->cr);
3629
3630 cs->cr = crdup(cs->basecr);
3631
3632 /*
3633 * Using rootdir, the system root vnode,
3634 * get its fid.
3635 */
3636 bzero(&fid, sizeof (fid));
3637 fid.fid_len = MAXFIDSZ;
3638 error = vop_fid_pseudo(rootdir, &fid);
3639 if (error != 0) {
3640 *cs->statusp = resp->status = puterrno4(error);
3641 goto out;
3642 }
3643
3644 /*
3645 * Then use the root fsid & fid it to find out if it's exported
3646 *
3647 * If the server root isn't exported directly, then
3648 * it should at least be a pseudo export based on
3649 * one or more exports further down in the server's
3650 * file tree.
3651 */
3652 exi = checkexport(&rootdir->v_vfsp->vfs_fsid, &fid, NULL);
3653 if (exi == NULL || exi->exi_export.ex_flags & EX_PUBLIC) {
3654 NFS4_DEBUG(rfs4_debug,
3655 (CE_WARN, "rfs4_op_putrootfh: export check failure"));
3656 *cs->statusp = resp->status = NFS4ERR_SERVERFAULT;
3657 if (exi != NULL)
3658 exi_rele(exi);
3659 goto out;
3660 }
3661
3662 /*
3663 * Now make a filehandle based on the root
3664 * export and root vnode.
3665 */
3666 error = makefh4(&cs->fh, rootdir, exi);
3667 if (error != 0) {
3668 *cs->statusp = resp->status = puterrno4(error);
3669 exi_rele(exi);
3670 goto out;
3671 }
3672
3673 sav_exi = cs->exi;
3674 cs->exi = exi;
3675
3676 VN_HOLD(rootdir);
3677 cs->vp = rootdir;
3678
3679 if ((resp->status = call_checkauth4(cs, req)) != NFS4_OK) {
3680 VN_RELE(rootdir);
3681 cs->vp = NULL;
3682 exi_rele(exi);
3683 cs->exi = sav_exi;
3684 goto out;
3685 }
3686 if (sav_exi != NULL)
3687 exi_rele(sav_exi);
3688
3689 *cs->statusp = resp->status = NFS4_OK;
3690 cs->deleg = FALSE;
3691 out:
3692 DTRACE_NFSV4_2(op__putrootfh__done, struct compound_state *, cs,
3693 PUTROOTFH4res *, resp);
3694 }
3695
3696 /*
3697 * set_rdattr_params sets up the variables used to manage what information
3698 * to get for each directory entry.
3699 */
3700 static nfsstat4
set_rdattr_params(struct nfs4_svgetit_arg * sargp,bitmap4 attrs,bool_t * need_to_lookup)3701 set_rdattr_params(struct nfs4_svgetit_arg *sargp,
3702 bitmap4 attrs, bool_t *need_to_lookup)
3703 {
3704 uint_t va_mask;
3705 nfsstat4 status;
3706 bitmap4 objbits;
3707
3708 status = bitmap4_to_attrmask(attrs, sargp);
3709 if (status != NFS4_OK) {
3710 /*
3711 * could not even figure attr mask
3712 */
3713 return (status);
3714 }
3715 va_mask = sargp->vap->va_mask;
3716
3717 /*
3718 * dirent's d_ino is always correct value for mounted_on_fileid.
3719 * mntdfid_set is set once here, but mounted_on_fileid is
3720 * set in main dirent processing loop for each dirent.
3721 * The mntdfid_set is a simple optimization that lets the
3722 * server attr code avoid work when caller is readdir.
3723 */
3724 sargp->mntdfid_set = TRUE;
3725
3726 /*
3727 * Lookup entry only if client asked for any of the following:
3728 * a) vattr attrs
3729 * b) vfs attrs
3730 * c) attrs w/per-object scope requested (change, filehandle, etc)
3731 * other than mounted_on_fileid (which we can take from dirent)
3732 */
3733 objbits = attrs ? attrs & NFS4_VP_ATTR_MASK : 0;
3734
3735 if (va_mask || sargp->sbp || (objbits & ~FATTR4_MOUNTED_ON_FILEID_MASK))
3736 *need_to_lookup = TRUE;
3737 else
3738 *need_to_lookup = FALSE;
3739
3740 if (sargp->sbp == NULL)
3741 return (NFS4_OK);
3742
3743 /*
3744 * If filesystem attrs are requested, get them now from the
3745 * directory vp, as most entries will have same filesystem. The only
3746 * exception are mounted over entries but we handle
3747 * those as we go (XXX mounted over detection not yet implemented).
3748 */
3749 sargp->vap->va_mask = 0; /* to avoid VOP_GETATTR */
3750 status = bitmap4_get_sysattrs(sargp);
3751 sargp->vap->va_mask = va_mask;
3752
3753 if ((status != NFS4_OK) && sargp->rdattr_error_req) {
3754 /*
3755 * Failed to get filesystem attributes.
3756 * Return a rdattr_error for each entry, but don't fail.
3757 * However, don't get any obj-dependent attrs.
3758 */
3759 sargp->rdattr_error = status; /* for rdattr_error */
3760 *need_to_lookup = FALSE;
3761 /*
3762 * At least get fileid for regular readdir output
3763 */
3764 sargp->vap->va_mask &= AT_NODEID;
3765 status = NFS4_OK;
3766 }
3767
3768 return (status);
3769 }
3770
3771 /*
3772 * readlink: args: CURRENT_FH.
3773 * res: status. If success - CURRENT_FH unchanged, return linktext.
3774 */
3775
3776 /* ARGSUSED */
3777 static void
rfs4_op_readlink(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)3778 rfs4_op_readlink(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
3779 struct compound_state *cs)
3780 {
3781 READLINK4res *resp = &resop->nfs_resop4_u.opreadlink;
3782 int error;
3783 vnode_t *vp;
3784 struct iovec iov;
3785 struct vattr va;
3786 struct uio uio;
3787 char *data;
3788 struct sockaddr *ca;
3789 char *name = NULL;
3790 int is_referral;
3791
3792 DTRACE_NFSV4_1(op__readlink__start, struct compound_state *, cs);
3793
3794 /* CURRENT_FH: directory */
3795 vp = cs->vp;
3796 if (vp == NULL) {
3797 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
3798 goto out;
3799 }
3800
3801 if (cs->access == CS_ACCESS_DENIED) {
3802 *cs->statusp = resp->status = NFS4ERR_ACCESS;
3803 goto out;
3804 }
3805
3806 /* Is it a referral? */
3807 if (vn_is_nfs_reparse(vp, cs->cr) && client_is_downrev(req)) {
3808
3809 is_referral = 1;
3810
3811 } else {
3812
3813 is_referral = 0;
3814
3815 if (vp->v_type == VDIR) {
3816 *cs->statusp = resp->status = NFS4ERR_ISDIR;
3817 goto out;
3818 }
3819
3820 if (vp->v_type != VLNK) {
3821 *cs->statusp = resp->status = NFS4ERR_INVAL;
3822 goto out;
3823 }
3824
3825 }
3826
3827 va.va_mask = AT_MODE;
3828 error = VOP_GETATTR(vp, &va, 0, cs->cr, NULL);
3829 if (error) {
3830 *cs->statusp = resp->status = puterrno4(error);
3831 goto out;
3832 }
3833
3834 if (MANDLOCK(vp, va.va_mode)) {
3835 *cs->statusp = resp->status = NFS4ERR_ACCESS;
3836 goto out;
3837 }
3838
3839 data = kmem_alloc(MAXPATHLEN + 1, KM_SLEEP);
3840
3841 if (is_referral) {
3842 char *s;
3843 size_t strsz;
3844
3845 /* Get an artificial symlink based on a referral */
3846 s = build_symlink(vp, cs->cr, &strsz);
3847 global_svstat_ptr[4][NFS_REFERLINKS].value.ui64++;
3848 DTRACE_PROBE2(nfs4serv__func__referral__reflink,
3849 vnode_t *, vp, char *, s);
3850 if (s == NULL)
3851 error = EINVAL;
3852 else {
3853 error = 0;
3854 (void) strlcpy(data, s, MAXPATHLEN + 1);
3855 kmem_free(s, strsz);
3856 }
3857
3858 } else {
3859
3860 iov.iov_base = data;
3861 iov.iov_len = MAXPATHLEN;
3862 uio.uio_iov = &iov;
3863 uio.uio_iovcnt = 1;
3864 uio.uio_segflg = UIO_SYSSPACE;
3865 uio.uio_extflg = UIO_COPY_CACHED;
3866 uio.uio_loffset = 0;
3867 uio.uio_resid = MAXPATHLEN;
3868
3869 error = VOP_READLINK(vp, &uio, cs->cr, NULL);
3870
3871 if (!error)
3872 *(data + MAXPATHLEN - uio.uio_resid) = '\0';
3873 }
3874
3875 if (error) {
3876 kmem_free((caddr_t)data, (uint_t)MAXPATHLEN + 1);
3877 *cs->statusp = resp->status = puterrno4(error);
3878 goto out;
3879 }
3880
3881 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3882 name = nfscmd_convname(ca, cs->exi, data, NFSCMD_CONV_OUTBOUND,
3883 MAXPATHLEN + 1);
3884
3885 if (name == NULL) {
3886 /*
3887 * Even though the conversion failed, we return
3888 * something. We just don't translate it.
3889 */
3890 name = data;
3891 }
3892
3893 /*
3894 * treat link name as data
3895 */
3896 (void) str_to_utf8(name, (utf8string *)&resp->link);
3897
3898 if (name != data)
3899 kmem_free(name, MAXPATHLEN + 1);
3900 kmem_free((caddr_t)data, (uint_t)MAXPATHLEN + 1);
3901 *cs->statusp = resp->status = NFS4_OK;
3902
3903 out:
3904 DTRACE_NFSV4_2(op__readlink__done, struct compound_state *, cs,
3905 READLINK4res *, resp);
3906 }
3907
3908 static void
rfs4_op_readlink_free(nfs_resop4 * resop)3909 rfs4_op_readlink_free(nfs_resop4 *resop)
3910 {
3911 READLINK4res *resp = &resop->nfs_resop4_u.opreadlink;
3912 utf8string *symlink = (utf8string *)&resp->link;
3913
3914 if (symlink->utf8string_val) {
3915 UTF8STRING_FREE(*symlink)
3916 }
3917 }
3918
3919 /*
3920 * release_lockowner:
3921 * Release any state associated with the supplied
3922 * lockowner. Note if any lo_state is holding locks we will not
3923 * rele that lo_state and thus the lockowner will not be destroyed.
3924 * A client using lock after the lock owner stateid has been released
3925 * will suffer the consequence of NFS4ERR_BAD_STATEID and would have
3926 * to reissue the lock with new_lock_owner set to TRUE.
3927 * args: lock_owner
3928 * res: status
3929 */
3930 /* ARGSUSED */
3931 static void
rfs4_op_release_lockowner(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)3932 rfs4_op_release_lockowner(nfs_argop4 *argop, nfs_resop4 *resop,
3933 struct svc_req *req, struct compound_state *cs)
3934 {
3935 RELEASE_LOCKOWNER4args *ap = &argop->nfs_argop4_u.oprelease_lockowner;
3936 RELEASE_LOCKOWNER4res *resp = &resop->nfs_resop4_u.oprelease_lockowner;
3937 rfs4_lockowner_t *lo;
3938 rfs4_openowner_t *oo;
3939 rfs4_state_t *sp;
3940 rfs4_lo_state_t *lsp;
3941 rfs4_client_t *cp;
3942 bool_t create = FALSE;
3943 locklist_t *llist;
3944 sysid_t sysid;
3945
3946 DTRACE_NFSV4_2(op__release__lockowner__start, struct compound_state *,
3947 cs, RELEASE_LOCKOWNER4args *, ap);
3948
3949 /* Make sure there is a clientid around for this request */
3950 cp = rfs4_findclient_by_id(ap->lock_owner.clientid, FALSE);
3951
3952 if (cp == NULL) {
3953 *cs->statusp = resp->status =
3954 rfs4_check_clientid(&ap->lock_owner.clientid, 0);
3955 goto out;
3956 }
3957 rfs4_client_rele(cp);
3958
3959 lo = rfs4_findlockowner(&ap->lock_owner, &create);
3960 if (lo == NULL) {
3961 *cs->statusp = resp->status = NFS4_OK;
3962 goto out;
3963 }
3964 ASSERT(lo->rl_client != NULL);
3965
3966 /*
3967 * Check for EXPIRED client. If so will reap state with in a lease
3968 * period or on next set_clientid_confirm step
3969 */
3970 if (rfs4_lease_expired(lo->rl_client)) {
3971 rfs4_lockowner_rele(lo);
3972 *cs->statusp = resp->status = NFS4ERR_EXPIRED;
3973 goto out;
3974 }
3975
3976 /*
3977 * If no sysid has been assigned, then no locks exist; just return.
3978 */
3979 rfs4_dbe_lock(lo->rl_client->rc_dbe);
3980 if (lo->rl_client->rc_sysidt == LM_NOSYSID) {
3981 rfs4_lockowner_rele(lo);
3982 rfs4_dbe_unlock(lo->rl_client->rc_dbe);
3983 goto out;
3984 }
3985
3986 sysid = lo->rl_client->rc_sysidt;
3987 rfs4_dbe_unlock(lo->rl_client->rc_dbe);
3988
3989 /*
3990 * Mark the lockowner invalid.
3991 */
3992 rfs4_dbe_hide(lo->rl_dbe);
3993
3994 /*
3995 * sysid-pid pair should now not be used since the lockowner is
3996 * invalid. If the client were to instantiate the lockowner again
3997 * it would be assigned a new pid. Thus we can get the list of
3998 * current locks.
3999 */
4000
4001 llist = flk_get_active_locks(sysid, lo->rl_pid);
4002 /* If we are still holding locks fail */
4003 if (llist != NULL) {
4004
4005 *cs->statusp = resp->status = NFS4ERR_LOCKS_HELD;
4006
4007 flk_free_locklist(llist);
4008 /*
4009 * We need to unhide the lockowner so the client can
4010 * try it again. The bad thing here is if the client
4011 * has a logic error that took it here in the first place
4012 * he probably has lost accounting of the locks that it
4013 * is holding. So we may have dangling state until the
4014 * open owner state is reaped via close. One scenario
4015 * that could possibly occur is that the client has
4016 * sent the unlock request(s) in separate threads
4017 * and has not waited for the replies before sending the
4018 * RELEASE_LOCKOWNER request. Presumably, it would expect
4019 * and deal appropriately with NFS4ERR_LOCKS_HELD, by
4020 * reissuing the request.
4021 */
4022 rfs4_dbe_unhide(lo->rl_dbe);
4023 rfs4_lockowner_rele(lo);
4024 goto out;
4025 }
4026
4027 /*
4028 * For the corresponding client we need to check each open
4029 * owner for any opens that have lockowner state associated
4030 * with this lockowner.
4031 */
4032
4033 rfs4_dbe_lock(lo->rl_client->rc_dbe);
4034 for (oo = list_head(&lo->rl_client->rc_openownerlist); oo != NULL;
4035 oo = list_next(&lo->rl_client->rc_openownerlist, oo)) {
4036
4037 rfs4_dbe_lock(oo->ro_dbe);
4038 for (sp = list_head(&oo->ro_statelist); sp != NULL;
4039 sp = list_next(&oo->ro_statelist, sp)) {
4040
4041 rfs4_dbe_lock(sp->rs_dbe);
4042 for (lsp = list_head(&sp->rs_lostatelist);
4043 lsp != NULL;
4044 lsp = list_next(&sp->rs_lostatelist, lsp)) {
4045 if (lsp->rls_locker == lo) {
4046 rfs4_dbe_lock(lsp->rls_dbe);
4047 rfs4_dbe_invalidate(lsp->rls_dbe);
4048 rfs4_dbe_unlock(lsp->rls_dbe);
4049 }
4050 }
4051 rfs4_dbe_unlock(sp->rs_dbe);
4052 }
4053 rfs4_dbe_unlock(oo->ro_dbe);
4054 }
4055 rfs4_dbe_unlock(lo->rl_client->rc_dbe);
4056
4057 rfs4_lockowner_rele(lo);
4058
4059 *cs->statusp = resp->status = NFS4_OK;
4060
4061 out:
4062 DTRACE_NFSV4_2(op__release__lockowner__done, struct compound_state *,
4063 cs, RELEASE_LOCKOWNER4res *, resp);
4064 }
4065
4066 /*
4067 * short utility function to lookup a file and recall the delegation
4068 */
4069 static rfs4_file_t *
rfs4_lookup_and_findfile(vnode_t * dvp,char * nm,vnode_t ** vpp,int * lkup_error,cred_t * cr)4070 rfs4_lookup_and_findfile(vnode_t *dvp, char *nm, vnode_t **vpp,
4071 int *lkup_error, cred_t *cr)
4072 {
4073 vnode_t *vp;
4074 rfs4_file_t *fp = NULL;
4075 bool_t fcreate = FALSE;
4076 int error;
4077
4078 if (vpp)
4079 *vpp = NULL;
4080
4081 if ((error = VOP_LOOKUP(dvp, nm, &vp, NULL, 0, NULL, cr, NULL, NULL,
4082 NULL)) == 0) {
4083 if (vp->v_type == VREG)
4084 fp = rfs4_findfile(vp, NULL, &fcreate);
4085 if (vpp)
4086 *vpp = vp;
4087 else
4088 VN_RELE(vp);
4089 }
4090
4091 if (lkup_error)
4092 *lkup_error = error;
4093
4094 return (fp);
4095 }
4096
4097 /*
4098 * remove: args: CURRENT_FH: directory; name.
4099 * res: status. If success - CURRENT_FH unchanged, return change_info
4100 * for directory.
4101 */
4102 /* ARGSUSED */
4103 static void
rfs4_op_remove(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)4104 rfs4_op_remove(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
4105 struct compound_state *cs)
4106 {
4107 REMOVE4args *args = &argop->nfs_argop4_u.opremove;
4108 REMOVE4res *resp = &resop->nfs_resop4_u.opremove;
4109 int error;
4110 vnode_t *dvp, *vp;
4111 struct vattr bdva, idva, adva;
4112 char *nm;
4113 uint_t len;
4114 rfs4_file_t *fp;
4115 int in_crit = 0;
4116 bslabel_t *clabel;
4117 struct sockaddr *ca;
4118 char *name = NULL;
4119 nfsstat4 status;
4120
4121 DTRACE_NFSV4_2(op__remove__start, struct compound_state *, cs,
4122 REMOVE4args *, args);
4123
4124 /* CURRENT_FH: directory */
4125 dvp = cs->vp;
4126 if (dvp == NULL) {
4127 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
4128 goto out;
4129 }
4130
4131 if (cs->access == CS_ACCESS_DENIED) {
4132 *cs->statusp = resp->status = NFS4ERR_ACCESS;
4133 goto out;
4134 }
4135
4136 /*
4137 * If there is an unshared filesystem mounted on this vnode,
4138 * Do not allow to remove anything in this directory.
4139 */
4140 if (vn_ismntpt(dvp)) {
4141 *cs->statusp = resp->status = NFS4ERR_ACCESS;
4142 goto out;
4143 }
4144
4145 if (dvp->v_type != VDIR) {
4146 *cs->statusp = resp->status = NFS4ERR_NOTDIR;
4147 goto out;
4148 }
4149
4150 status = utf8_dir_verify(&args->target);
4151 if (status != NFS4_OK) {
4152 *cs->statusp = resp->status = status;
4153 goto out;
4154 }
4155
4156 /*
4157 * Lookup the file so that we can check if it's a directory
4158 */
4159 nm = utf8_to_fn(&args->target, &len, NULL);
4160 if (nm == NULL) {
4161 *cs->statusp = resp->status = NFS4ERR_INVAL;
4162 goto out;
4163 }
4164
4165 if (len > MAXNAMELEN) {
4166 *cs->statusp = resp->status = NFS4ERR_NAMETOOLONG;
4167 kmem_free(nm, len);
4168 goto out;
4169 }
4170
4171 if (rdonly4(req, cs)) {
4172 *cs->statusp = resp->status = NFS4ERR_ROFS;
4173 kmem_free(nm, len);
4174 goto out;
4175 }
4176
4177 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
4178 name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
4179 MAXPATHLEN + 1);
4180
4181 if (name == NULL) {
4182 *cs->statusp = resp->status = NFS4ERR_INVAL;
4183 kmem_free(nm, len);
4184 goto out;
4185 }
4186
4187 /*
4188 * Lookup the file to determine type and while we are see if
4189 * there is a file struct around and check for delegation.
4190 * We don't need to acquire va_seq before this lookup, if
4191 * it causes an update, cinfo.before will not match, which will
4192 * trigger a cache flush even if atomic is TRUE.
4193 */
4194 if (fp = rfs4_lookup_and_findfile(dvp, name, &vp, &error, cs->cr)) {
4195 if (rfs4_check_delegated_byfp(FWRITE, fp, TRUE, TRUE, TRUE,
4196 NULL)) {
4197 VN_RELE(vp);
4198 rfs4_file_rele(fp);
4199 *cs->statusp = resp->status = NFS4ERR_DELAY;
4200 if (nm != name)
4201 kmem_free(name, MAXPATHLEN + 1);
4202 kmem_free(nm, len);
4203 goto out;
4204 }
4205 }
4206
4207 /* Didn't find anything to remove */
4208 if (vp == NULL) {
4209 *cs->statusp = resp->status = error;
4210 if (nm != name)
4211 kmem_free(name, MAXPATHLEN + 1);
4212 kmem_free(nm, len);
4213 goto out;
4214 }
4215
4216 if (nbl_need_check(vp)) {
4217 nbl_start_crit(vp, RW_READER);
4218 in_crit = 1;
4219 if (nbl_conflict(vp, NBL_REMOVE, 0, 0, 0, NULL)) {
4220 *cs->statusp = resp->status = NFS4ERR_FILE_OPEN;
4221 if (nm != name)
4222 kmem_free(name, MAXPATHLEN + 1);
4223 kmem_free(nm, len);
4224 nbl_end_crit(vp);
4225 VN_RELE(vp);
4226 if (fp) {
4227 rfs4_clear_dont_grant(fp);
4228 rfs4_file_rele(fp);
4229 }
4230 goto out;
4231 }
4232 }
4233
4234 /* check label before allowing removal */
4235 if (is_system_labeled()) {
4236 ASSERT(req->rq_label != NULL);
4237 clabel = req->rq_label;
4238 DTRACE_PROBE2(tx__rfs4__log__info__opremove__clabel, char *,
4239 "got client label from request(1)",
4240 struct svc_req *, req);
4241 if (!blequal(&l_admin_low->tsl_label, clabel)) {
4242 if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
4243 cs->exi)) {
4244 *cs->statusp = resp->status = NFS4ERR_ACCESS;
4245 if (name != nm)
4246 kmem_free(name, MAXPATHLEN + 1);
4247 kmem_free(nm, len);
4248 if (in_crit)
4249 nbl_end_crit(vp);
4250 VN_RELE(vp);
4251 if (fp) {
4252 rfs4_clear_dont_grant(fp);
4253 rfs4_file_rele(fp);
4254 }
4255 goto out;
4256 }
4257 }
4258 }
4259
4260 /* Get dir "before" change value */
4261 bdva.va_mask = AT_CTIME|AT_SEQ;
4262 error = VOP_GETATTR(dvp, &bdva, 0, cs->cr, NULL);
4263 if (error) {
4264 *cs->statusp = resp->status = puterrno4(error);
4265 if (nm != name)
4266 kmem_free(name, MAXPATHLEN + 1);
4267 kmem_free(nm, len);
4268 if (in_crit)
4269 nbl_end_crit(vp);
4270 VN_RELE(vp);
4271 if (fp) {
4272 rfs4_clear_dont_grant(fp);
4273 rfs4_file_rele(fp);
4274 }
4275 goto out;
4276 }
4277 NFS4_SET_FATTR4_CHANGE(resp->cinfo.before, bdva.va_ctime)
4278
4279 /* Actually do the REMOVE operation */
4280 if (vp->v_type == VDIR) {
4281 /*
4282 * Can't remove a directory that has a mounted-on filesystem.
4283 */
4284 if (vn_ismntpt(vp)) {
4285 error = EACCES;
4286 } else {
4287 /*
4288 * System V defines rmdir to return EEXIST,
4289 * not ENOTEMPTY, if the directory is not
4290 * empty. A System V NFS server needs to map
4291 * NFS4ERR_EXIST to NFS4ERR_NOTEMPTY to
4292 * transmit over the wire.
4293 */
4294 if ((error = VOP_RMDIR(dvp, name, rootdir, cs->cr,
4295 NULL, 0)) == EEXIST)
4296 error = ENOTEMPTY;
4297 }
4298
4299 if (in_crit)
4300 nbl_end_crit(vp);
4301 VN_RELE(vp);
4302 } else {
4303 if (!in_crit)
4304 VN_RELE(vp);
4305 if ((error = VOP_REMOVE(dvp, name, cs->cr, NULL, 0)) == 0 &&
4306 fp != NULL) {
4307 struct vattr va;
4308 vnode_t *tvp;
4309
4310 rfs4_dbe_lock(fp->rf_dbe);
4311 tvp = fp->rf_vp;
4312 if (tvp)
4313 VN_HOLD(tvp);
4314 rfs4_dbe_unlock(fp->rf_dbe);
4315
4316 if (tvp) {
4317 /*
4318 * This is va_seq safe because we are not
4319 * manipulating dvp.
4320 */
4321 va.va_mask = AT_NLINK;
4322 if (!VOP_GETATTR(tvp, &va, 0, cs->cr, NULL) &&
4323 va.va_nlink == 0) {
4324 /* Remove state on file remove */
4325 if (in_crit) {
4326 nbl_end_crit(vp);
4327 VN_RELE(vp);
4328 in_crit = 0;
4329 }
4330 rfs4_close_all_state(fp);
4331 }
4332 VN_RELE(tvp);
4333 }
4334 }
4335
4336 if (in_crit) {
4337 nbl_end_crit(vp);
4338 VN_RELE(vp);
4339 }
4340 }
4341
4342 if (fp) {
4343 rfs4_clear_dont_grant(fp);
4344 rfs4_file_rele(fp);
4345 }
4346 if (nm != name)
4347 kmem_free(name, MAXPATHLEN + 1);
4348 kmem_free(nm, len);
4349
4350 if (error) {
4351 *cs->statusp = resp->status = puterrno4(error);
4352 goto out;
4353 }
4354
4355 /*
4356 * Get the initial "after" sequence number, if it fails, set to zero
4357 */
4358 idva.va_mask = AT_SEQ;
4359 if (VOP_GETATTR(dvp, &idva, 0, cs->cr, NULL))
4360 idva.va_seq = 0;
4361
4362 /*
4363 * Force modified data and metadata out to stable storage.
4364 */
4365 (void) VOP_FSYNC(dvp, 0, cs->cr, NULL);
4366
4367 /*
4368 * Get "after" change value, if it fails, simply return the
4369 * before value.
4370 */
4371 adva.va_mask = AT_CTIME|AT_SEQ;
4372 if (VOP_GETATTR(dvp, &adva, 0, cs->cr, NULL)) {
4373 adva.va_ctime = bdva.va_ctime;
4374 adva.va_seq = 0;
4375 }
4376
4377 NFS4_SET_FATTR4_CHANGE(resp->cinfo.after, adva.va_ctime)
4378
4379 /*
4380 * The cinfo.atomic = TRUE only if we have
4381 * non-zero va_seq's, and it has incremented by exactly one
4382 * during the VOP_REMOVE/RMDIR and it didn't change during
4383 * the VOP_FSYNC.
4384 */
4385 if (bdva.va_seq && idva.va_seq && adva.va_seq &&
4386 idva.va_seq == (bdva.va_seq + 1) && idva.va_seq == adva.va_seq)
4387 resp->cinfo.atomic = TRUE;
4388 else
4389 resp->cinfo.atomic = FALSE;
4390
4391 *cs->statusp = resp->status = NFS4_OK;
4392
4393 out:
4394 DTRACE_NFSV4_2(op__remove__done, struct compound_state *, cs,
4395 REMOVE4res *, resp);
4396 }
4397
4398 /*
4399 * rename: args: SAVED_FH: from directory, CURRENT_FH: target directory,
4400 * oldname and newname.
4401 * res: status. If success - CURRENT_FH unchanged, return change_info
4402 * for both from and target directories.
4403 */
4404 /* ARGSUSED */
4405 static void
rfs4_op_rename(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)4406 rfs4_op_rename(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
4407 struct compound_state *cs)
4408 {
4409 RENAME4args *args = &argop->nfs_argop4_u.oprename;
4410 RENAME4res *resp = &resop->nfs_resop4_u.oprename;
4411 int error;
4412 vnode_t *odvp;
4413 vnode_t *ndvp;
4414 vnode_t *srcvp, *targvp;
4415 struct vattr obdva, oidva, oadva;
4416 struct vattr nbdva, nidva, nadva;
4417 char *onm, *nnm;
4418 uint_t olen, nlen;
4419 rfs4_file_t *fp, *sfp;
4420 int in_crit_src, in_crit_targ;
4421 int fp_rele_grant_hold, sfp_rele_grant_hold;
4422 bslabel_t *clabel;
4423 struct sockaddr *ca;
4424 char *converted_onm = NULL;
4425 char *converted_nnm = NULL;
4426 nfsstat4 status;
4427
4428 DTRACE_NFSV4_2(op__rename__start, struct compound_state *, cs,
4429 RENAME4args *, args);
4430
4431 fp = sfp = NULL;
4432 srcvp = targvp = NULL;
4433 in_crit_src = in_crit_targ = 0;
4434 fp_rele_grant_hold = sfp_rele_grant_hold = 0;
4435
4436 /* CURRENT_FH: target directory */
4437 ndvp = cs->vp;
4438 if (ndvp == NULL) {
4439 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
4440 goto out;
4441 }
4442
4443 /* SAVED_FH: from directory */
4444 odvp = cs->saved_vp;
4445 if (odvp == NULL) {
4446 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
4447 goto out;
4448 }
4449
4450 if (cs->access == CS_ACCESS_DENIED) {
4451 *cs->statusp = resp->status = NFS4ERR_ACCESS;
4452 goto out;
4453 }
4454
4455 /*
4456 * If there is an unshared filesystem mounted on this vnode,
4457 * do not allow to rename objects in this directory.
4458 */
4459 if (vn_ismntpt(odvp)) {
4460 *cs->statusp = resp->status = NFS4ERR_ACCESS;
4461 goto out;
4462 }
4463
4464 /*
4465 * If there is an unshared filesystem mounted on this vnode,
4466 * do not allow to rename to this directory.
4467 */
4468 if (vn_ismntpt(ndvp)) {
4469 *cs->statusp = resp->status = NFS4ERR_ACCESS;
4470 goto out;
4471 }
4472
4473 if (odvp->v_type != VDIR || ndvp->v_type != VDIR) {
4474 *cs->statusp = resp->status = NFS4ERR_NOTDIR;
4475 goto out;
4476 }
4477
4478 if (cs->saved_exi != cs->exi) {
4479 *cs->statusp = resp->status = NFS4ERR_XDEV;
4480 goto out;
4481 }
4482
4483 status = utf8_dir_verify(&args->oldname);
4484 if (status != NFS4_OK) {
4485 *cs->statusp = resp->status = status;
4486 goto out;
4487 }
4488
4489 status = utf8_dir_verify(&args->newname);
4490 if (status != NFS4_OK) {
4491 *cs->statusp = resp->status = status;
4492 goto out;
4493 }
4494
4495 onm = utf8_to_fn(&args->oldname, &olen, NULL);
4496 if (onm == NULL) {
4497 *cs->statusp = resp->status = NFS4ERR_INVAL;
4498 goto out;
4499 }
4500 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
4501 nlen = MAXPATHLEN + 1;
4502 converted_onm = nfscmd_convname(ca, cs->exi, onm, NFSCMD_CONV_INBOUND,
4503 nlen);
4504
4505 if (converted_onm == NULL) {
4506 *cs->statusp = resp->status = NFS4ERR_INVAL;
4507 kmem_free(onm, olen);
4508 goto out;
4509 }
4510
4511 nnm = utf8_to_fn(&args->newname, &nlen, NULL);
4512 if (nnm == NULL) {
4513 *cs->statusp = resp->status = NFS4ERR_INVAL;
4514 if (onm != converted_onm)
4515 kmem_free(converted_onm, MAXPATHLEN + 1);
4516 kmem_free(onm, olen);
4517 goto out;
4518 }
4519 converted_nnm = nfscmd_convname(ca, cs->exi, nnm, NFSCMD_CONV_INBOUND,
4520 MAXPATHLEN + 1);
4521
4522 if (converted_nnm == NULL) {
4523 *cs->statusp = resp->status = NFS4ERR_INVAL;
4524 kmem_free(nnm, nlen);
4525 nnm = NULL;
4526 if (onm != converted_onm)
4527 kmem_free(converted_onm, MAXPATHLEN + 1);
4528 kmem_free(onm, olen);
4529 goto out;
4530 }
4531
4532
4533 if (olen > MAXNAMELEN || nlen > MAXNAMELEN) {
4534 *cs->statusp = resp->status = NFS4ERR_NAMETOOLONG;
4535 kmem_free(onm, olen);
4536 kmem_free(nnm, nlen);
4537 goto out;
4538 }
4539
4540
4541 if (rdonly4(req, cs)) {
4542 *cs->statusp = resp->status = NFS4ERR_ROFS;
4543 if (onm != converted_onm)
4544 kmem_free(converted_onm, MAXPATHLEN + 1);
4545 kmem_free(onm, olen);
4546 if (nnm != converted_nnm)
4547 kmem_free(converted_nnm, MAXPATHLEN + 1);
4548 kmem_free(nnm, nlen);
4549 goto out;
4550 }
4551
4552 /* check label of the target dir */
4553 if (is_system_labeled()) {
4554 ASSERT(req->rq_label != NULL);
4555 clabel = req->rq_label;
4556 DTRACE_PROBE2(tx__rfs4__log__info__oprename__clabel, char *,
4557 "got client label from request(1)",
4558 struct svc_req *, req);
4559 if (!blequal(&l_admin_low->tsl_label, clabel)) {
4560 if (!do_rfs_label_check(clabel, ndvp,
4561 EQUALITY_CHECK, cs->exi)) {
4562 *cs->statusp = resp->status = NFS4ERR_ACCESS;
4563 goto err_out;
4564 }
4565 }
4566 }
4567
4568 /*
4569 * Is the source a file and have a delegation?
4570 * We don't need to acquire va_seq before these lookups, if
4571 * it causes an update, cinfo.before will not match, which will
4572 * trigger a cache flush even if atomic is TRUE.
4573 */
4574 if (sfp = rfs4_lookup_and_findfile(odvp, converted_onm, &srcvp,
4575 &error, cs->cr)) {
4576 if (rfs4_check_delegated_byfp(FWRITE, sfp, TRUE, TRUE, TRUE,
4577 NULL)) {
4578 *cs->statusp = resp->status = NFS4ERR_DELAY;
4579 goto err_out;
4580 }
4581 }
4582
4583 if (srcvp == NULL) {
4584 *cs->statusp = resp->status = puterrno4(error);
4585 if (onm != converted_onm)
4586 kmem_free(converted_onm, MAXPATHLEN + 1);
4587 kmem_free(onm, olen);
4588 if (nnm != converted_nnm)
4589 kmem_free(converted_nnm, MAXPATHLEN + 1);
4590 kmem_free(nnm, nlen);
4591 goto out;
4592 }
4593
4594 sfp_rele_grant_hold = 1;
4595
4596 /* Does the destination exist and a file and have a delegation? */
4597 if (fp = rfs4_lookup_and_findfile(ndvp, converted_nnm, &targvp,
4598 NULL, cs->cr)) {
4599 if (rfs4_check_delegated_byfp(FWRITE, fp, TRUE, TRUE, TRUE,
4600 NULL)) {
4601 *cs->statusp = resp->status = NFS4ERR_DELAY;
4602 goto err_out;
4603 }
4604 }
4605 fp_rele_grant_hold = 1;
4606
4607
4608 /* Check for NBMAND lock on both source and target */
4609 if (nbl_need_check(srcvp)) {
4610 nbl_start_crit(srcvp, RW_READER);
4611 in_crit_src = 1;
4612 if (nbl_conflict(srcvp, NBL_RENAME, 0, 0, 0, NULL)) {
4613 *cs->statusp = resp->status = NFS4ERR_FILE_OPEN;
4614 goto err_out;
4615 }
4616 }
4617
4618 if (targvp && nbl_need_check(targvp)) {
4619 nbl_start_crit(targvp, RW_READER);
4620 in_crit_targ = 1;
4621 if (nbl_conflict(targvp, NBL_REMOVE, 0, 0, 0, NULL)) {
4622 *cs->statusp = resp->status = NFS4ERR_FILE_OPEN;
4623 goto err_out;
4624 }
4625 }
4626
4627 /* Get source "before" change value */
4628 obdva.va_mask = AT_CTIME|AT_SEQ;
4629 error = VOP_GETATTR(odvp, &obdva, 0, cs->cr, NULL);
4630 if (!error) {
4631 nbdva.va_mask = AT_CTIME|AT_SEQ;
4632 error = VOP_GETATTR(ndvp, &nbdva, 0, cs->cr, NULL);
4633 }
4634 if (error) {
4635 *cs->statusp = resp->status = puterrno4(error);
4636 goto err_out;
4637 }
4638
4639 NFS4_SET_FATTR4_CHANGE(resp->source_cinfo.before, obdva.va_ctime)
4640 NFS4_SET_FATTR4_CHANGE(resp->target_cinfo.before, nbdva.va_ctime)
4641
4642 if ((error = VOP_RENAME(odvp, converted_onm, ndvp, converted_nnm,
4643 cs->cr, NULL, 0)) == 0 && fp != NULL) {
4644 struct vattr va;
4645 vnode_t *tvp;
4646
4647 rfs4_dbe_lock(fp->rf_dbe);
4648 tvp = fp->rf_vp;
4649 if (tvp)
4650 VN_HOLD(tvp);
4651 rfs4_dbe_unlock(fp->rf_dbe);
4652
4653 if (tvp) {
4654 va.va_mask = AT_NLINK;
4655 if (!VOP_GETATTR(tvp, &va, 0, cs->cr, NULL) &&
4656 va.va_nlink == 0) {
4657 /* The file is gone and so should the state */
4658 if (in_crit_targ) {
4659 nbl_end_crit(targvp);
4660 in_crit_targ = 0;
4661 }
4662 rfs4_close_all_state(fp);
4663 }
4664 VN_RELE(tvp);
4665 }
4666 }
4667 if (error == 0)
4668 vn_renamepath(ndvp, srcvp, nnm, nlen - 1);
4669
4670 if (in_crit_src)
4671 nbl_end_crit(srcvp);
4672 if (srcvp)
4673 VN_RELE(srcvp);
4674 if (in_crit_targ)
4675 nbl_end_crit(targvp);
4676 if (targvp)
4677 VN_RELE(targvp);
4678
4679 if (sfp) {
4680 rfs4_clear_dont_grant(sfp);
4681 rfs4_file_rele(sfp);
4682 }
4683 if (fp) {
4684 rfs4_clear_dont_grant(fp);
4685 rfs4_file_rele(fp);
4686 }
4687
4688 if (converted_onm != onm)
4689 kmem_free(converted_onm, MAXPATHLEN + 1);
4690 kmem_free(onm, olen);
4691 if (converted_nnm != nnm)
4692 kmem_free(converted_nnm, MAXPATHLEN + 1);
4693 kmem_free(nnm, nlen);
4694
4695 /*
4696 * Get the initial "after" sequence number, if it fails, set to zero
4697 */
4698 oidva.va_mask = AT_SEQ;
4699 if (VOP_GETATTR(odvp, &oidva, 0, cs->cr, NULL))
4700 oidva.va_seq = 0;
4701
4702 nidva.va_mask = AT_SEQ;
4703 if (VOP_GETATTR(ndvp, &nidva, 0, cs->cr, NULL))
4704 nidva.va_seq = 0;
4705
4706 /*
4707 * Force modified data and metadata out to stable storage.
4708 */
4709 (void) VOP_FSYNC(odvp, 0, cs->cr, NULL);
4710 (void) VOP_FSYNC(ndvp, 0, cs->cr, NULL);
4711
4712 if (error) {
4713 *cs->statusp = resp->status = puterrno4(error);
4714 goto out;
4715 }
4716
4717 /*
4718 * Get "after" change values, if it fails, simply return the
4719 * before value.
4720 */
4721 oadva.va_mask = AT_CTIME|AT_SEQ;
4722 if (VOP_GETATTR(odvp, &oadva, 0, cs->cr, NULL)) {
4723 oadva.va_ctime = obdva.va_ctime;
4724 oadva.va_seq = 0;
4725 }
4726
4727 nadva.va_mask = AT_CTIME|AT_SEQ;
4728 if (VOP_GETATTR(odvp, &nadva, 0, cs->cr, NULL)) {
4729 nadva.va_ctime = nbdva.va_ctime;
4730 nadva.va_seq = 0;
4731 }
4732
4733 NFS4_SET_FATTR4_CHANGE(resp->source_cinfo.after, oadva.va_ctime)
4734 NFS4_SET_FATTR4_CHANGE(resp->target_cinfo.after, nadva.va_ctime)
4735
4736 /*
4737 * The cinfo.atomic = TRUE only if we have
4738 * non-zero va_seq's, and it has incremented by exactly one
4739 * during the VOP_RENAME and it didn't change during the VOP_FSYNC.
4740 */
4741 if (obdva.va_seq && oidva.va_seq && oadva.va_seq &&
4742 oidva.va_seq == (obdva.va_seq + 1) && oidva.va_seq == oadva.va_seq)
4743 resp->source_cinfo.atomic = TRUE;
4744 else
4745 resp->source_cinfo.atomic = FALSE;
4746
4747 if (nbdva.va_seq && nidva.va_seq && nadva.va_seq &&
4748 nidva.va_seq == (nbdva.va_seq + 1) && nidva.va_seq == nadva.va_seq)
4749 resp->target_cinfo.atomic = TRUE;
4750 else
4751 resp->target_cinfo.atomic = FALSE;
4752
4753 #ifdef VOLATILE_FH_TEST
4754 {
4755 extern void add_volrnm_fh(struct exportinfo *, vnode_t *);
4756
4757 /*
4758 * Add the renamed file handle to the volatile rename list
4759 */
4760 if (cs->exi->exi_export.ex_flags & EX_VOLRNM) {
4761 /* file handles may expire on rename */
4762 vnode_t *vp;
4763
4764 nnm = utf8_to_fn(&args->newname, &nlen, NULL);
4765 /*
4766 * Already know that nnm will be a valid string
4767 */
4768 error = VOP_LOOKUP(ndvp, nnm, &vp, NULL, 0, NULL, cs->cr,
4769 NULL, NULL, NULL);
4770 kmem_free(nnm, nlen);
4771 if (!error) {
4772 add_volrnm_fh(cs->exi, vp);
4773 VN_RELE(vp);
4774 }
4775 }
4776 }
4777 #endif /* VOLATILE_FH_TEST */
4778
4779 *cs->statusp = resp->status = NFS4_OK;
4780 out:
4781 DTRACE_NFSV4_2(op__rename__done, struct compound_state *, cs,
4782 RENAME4res *, resp);
4783 return;
4784
4785 err_out:
4786 if (onm != converted_onm)
4787 kmem_free(converted_onm, MAXPATHLEN + 1);
4788 if (onm != NULL)
4789 kmem_free(onm, olen);
4790 if (nnm != converted_nnm)
4791 kmem_free(converted_nnm, MAXPATHLEN + 1);
4792 if (nnm != NULL)
4793 kmem_free(nnm, nlen);
4794
4795 if (in_crit_src) nbl_end_crit(srcvp);
4796 if (in_crit_targ) nbl_end_crit(targvp);
4797 if (targvp) VN_RELE(targvp);
4798 if (srcvp) VN_RELE(srcvp);
4799 if (sfp) {
4800 if (sfp_rele_grant_hold) rfs4_clear_dont_grant(sfp);
4801 rfs4_file_rele(sfp);
4802 }
4803 if (fp) {
4804 if (fp_rele_grant_hold) rfs4_clear_dont_grant(fp);
4805 rfs4_file_rele(fp);
4806 }
4807
4808 DTRACE_NFSV4_2(op__rename__done, struct compound_state *, cs,
4809 RENAME4res *, resp);
4810 }
4811
4812 /* ARGSUSED */
4813 static void
rfs4_op_renew(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)4814 rfs4_op_renew(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
4815 struct compound_state *cs)
4816 {
4817 RENEW4args *args = &argop->nfs_argop4_u.oprenew;
4818 RENEW4res *resp = &resop->nfs_resop4_u.oprenew;
4819 rfs4_client_t *cp;
4820
4821 DTRACE_NFSV4_2(op__renew__start, struct compound_state *, cs,
4822 RENEW4args *, args);
4823
4824 if ((cp = rfs4_findclient_by_id(args->clientid, FALSE)) == NULL) {
4825 *cs->statusp = resp->status =
4826 rfs4_check_clientid(&args->clientid, 0);
4827 goto out;
4828 }
4829
4830 if (rfs4_lease_expired(cp)) {
4831 rfs4_client_rele(cp);
4832 *cs->statusp = resp->status = NFS4ERR_EXPIRED;
4833 goto out;
4834 }
4835
4836 rfs4_update_lease(cp);
4837
4838 mutex_enter(cp->rc_cbinfo.cb_lock);
4839 if (cp->rc_cbinfo.cb_notified_of_cb_path_down == FALSE) {
4840 cp->rc_cbinfo.cb_notified_of_cb_path_down = TRUE;
4841 *cs->statusp = resp->status = NFS4ERR_CB_PATH_DOWN;
4842 } else {
4843 *cs->statusp = resp->status = NFS4_OK;
4844 }
4845 mutex_exit(cp->rc_cbinfo.cb_lock);
4846
4847 rfs4_client_rele(cp);
4848
4849 out:
4850 DTRACE_NFSV4_2(op__renew__done, struct compound_state *, cs,
4851 RENEW4res *, resp);
4852 }
4853
4854 /* ARGSUSED */
4855 static void
rfs4_op_restorefh(nfs_argop4 * args,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)4856 rfs4_op_restorefh(nfs_argop4 *args, nfs_resop4 *resop, struct svc_req *req,
4857 struct compound_state *cs)
4858 {
4859 RESTOREFH4res *resp = &resop->nfs_resop4_u.oprestorefh;
4860
4861 DTRACE_NFSV4_1(op__restorefh__start, struct compound_state *, cs);
4862
4863 /* No need to check cs->access - we are not accessing any object */
4864 if ((cs->saved_vp == NULL) || (cs->saved_fh.nfs_fh4_val == NULL)) {
4865 *cs->statusp = resp->status = NFS4ERR_RESTOREFH;
4866 goto out;
4867 }
4868 if (cs->vp != NULL) {
4869 VN_RELE(cs->vp);
4870 }
4871 cs->vp = cs->saved_vp;
4872 cs->saved_vp = NULL;
4873 if (cs->exi != NULL)
4874 exi_rele(cs->exi);
4875 cs->exi = cs->saved_exi;
4876 if (cs->exi != NULL)
4877 exi_hold(cs->exi);
4878 nfs_fh4_copy(&cs->saved_fh, &cs->fh);
4879 *cs->statusp = resp->status = NFS4_OK;
4880 cs->deleg = FALSE;
4881
4882 out:
4883 DTRACE_NFSV4_2(op__restorefh__done, struct compound_state *, cs,
4884 RESTOREFH4res *, resp);
4885 }
4886
4887 /* ARGSUSED */
4888 static void
rfs4_op_savefh(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)4889 rfs4_op_savefh(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
4890 struct compound_state *cs)
4891 {
4892 SAVEFH4res *resp = &resop->nfs_resop4_u.opsavefh;
4893
4894 DTRACE_NFSV4_1(op__savefh__start, struct compound_state *, cs);
4895
4896 /* No need to check cs->access - we are not accessing any object */
4897 if (cs->vp == NULL) {
4898 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
4899 goto out;
4900 }
4901 if (cs->saved_vp != NULL) {
4902 VN_RELE(cs->saved_vp);
4903 }
4904 cs->saved_vp = cs->vp;
4905 VN_HOLD(cs->saved_vp);
4906 if (cs->saved_exi != NULL)
4907 exi_rele(cs->saved_exi);
4908 cs->saved_exi = cs->exi;
4909 if (cs->saved_exi != NULL)
4910 exi_hold(cs->saved_exi);
4911 /*
4912 * since SAVEFH is fairly rare, don't alloc space for its fh
4913 * unless necessary.
4914 */
4915 if (cs->saved_fh.nfs_fh4_val == NULL) {
4916 cs->saved_fh.nfs_fh4_val = kmem_alloc(NFS4_FHSIZE, KM_SLEEP);
4917 }
4918 nfs_fh4_copy(&cs->fh, &cs->saved_fh);
4919 *cs->statusp = resp->status = NFS4_OK;
4920
4921 out:
4922 DTRACE_NFSV4_2(op__savefh__done, struct compound_state *, cs,
4923 SAVEFH4res *, resp);
4924 }
4925
4926 /*
4927 * rfs4_verify_attr is called when nfsv4 Setattr failed, but we wish to
4928 * return the bitmap of attrs that were set successfully. It is also
4929 * called by Verify/Nverify to test the vattr/vfsstat attrs. It should
4930 * always be called only after rfs4_do_set_attrs().
4931 *
4932 * Verify that the attributes are same as the expected ones. sargp->vap
4933 * and sargp->sbp contain the input attributes as translated from fattr4.
4934 *
4935 * This function verifies only the attrs that correspond to a vattr or
4936 * vfsstat struct. That is because of the extra step needed to get the
4937 * corresponding system structs. Other attributes have already been set or
4938 * verified by do_rfs4_set_attrs.
4939 *
4940 * Return 0 if all attrs match, -1 if some don't, error if error processing.
4941 */
4942 static int
rfs4_verify_attr(struct nfs4_svgetit_arg * sargp,bitmap4 * resp,struct nfs4_ntov_table * ntovp)4943 rfs4_verify_attr(struct nfs4_svgetit_arg *sargp,
4944 bitmap4 *resp, struct nfs4_ntov_table *ntovp)
4945 {
4946 int error, ret_error = 0;
4947 int i, k;
4948 uint_t sva_mask = sargp->vap->va_mask;
4949 uint_t vbit;
4950 union nfs4_attr_u *na;
4951 uint8_t *amap;
4952 bool_t getsb = ntovp->vfsstat;
4953
4954 if (sva_mask != 0) {
4955 /*
4956 * Okay to overwrite sargp->vap because we verify based
4957 * on the incoming values.
4958 */
4959 ret_error = VOP_GETATTR(sargp->cs->vp, sargp->vap, 0,
4960 sargp->cs->cr, NULL);
4961 if (ret_error) {
4962 if (resp == NULL)
4963 return (ret_error);
4964 /*
4965 * Must return bitmap of successful attrs
4966 */
4967 sva_mask = 0; /* to prevent checking vap later */
4968 } else {
4969 /*
4970 * Some file systems clobber va_mask. it is probably
4971 * wrong of them to do so, nonethless we practice
4972 * defensive coding.
4973 * See bug id 4276830.
4974 */
4975 sargp->vap->va_mask = sva_mask;
4976 }
4977 }
4978
4979 if (getsb) {
4980 /*
4981 * Now get the superblock and loop on the bitmap, as there is
4982 * no simple way of translating from superblock to bitmap4.
4983 */
4984 ret_error = VFS_STATVFS(sargp->cs->vp->v_vfsp, sargp->sbp);
4985 if (ret_error) {
4986 if (resp == NULL)
4987 goto errout;
4988 getsb = FALSE;
4989 }
4990 }
4991
4992 /*
4993 * Now loop and verify each attribute which getattr returned
4994 * whether it's the same as the input.
4995 */
4996 if (resp == NULL && !getsb && (sva_mask == 0))
4997 goto errout;
4998
4999 na = ntovp->na;
5000 amap = ntovp->amap;
5001 k = 0;
5002 for (i = 0; i < ntovp->attrcnt; i++, na++, amap++) {
5003 k = *amap;
5004 ASSERT(nfs4_ntov_map[k].nval == k);
5005 vbit = nfs4_ntov_map[k].vbit;
5006
5007 /*
5008 * If vattr attribute but VOP_GETATTR failed, or it's
5009 * superblock attribute but VFS_STATVFS failed, skip
5010 */
5011 if (vbit) {
5012 if ((vbit & sva_mask) == 0)
5013 continue;
5014 } else if (!(getsb && nfs4_ntov_map[k].vfsstat)) {
5015 continue;
5016 }
5017 error = (*nfs4_ntov_map[k].sv_getit)(NFS4ATTR_VERIT, sargp, na);
5018 if (resp != NULL) {
5019 if (error)
5020 ret_error = -1; /* not all match */
5021 else /* update response bitmap */
5022 *resp |= nfs4_ntov_map[k].fbit;
5023 continue;
5024 }
5025 if (error) {
5026 ret_error = -1; /* not all match */
5027 break;
5028 }
5029 }
5030 errout:
5031 return (ret_error);
5032 }
5033
5034 /*
5035 * Decode the attribute to be set/verified. If the attr requires a sys op
5036 * (VOP_GETATTR, VFS_VFSSTAT), and the request is to verify, then don't
5037 * call the sv_getit function for it, because the sys op hasn't yet been done.
5038 * Return 0 for success, error code if failed.
5039 *
5040 * Note: the decoded arg is not freed here but in nfs4_ntov_table_free.
5041 */
5042 static int
decode_fattr4_attr(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sargp,int k,XDR * xdrp,bitmap4 * resp_bval,union nfs4_attr_u * nap)5043 decode_fattr4_attr(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sargp,
5044 int k, XDR *xdrp, bitmap4 *resp_bval, union nfs4_attr_u *nap)
5045 {
5046 int error = 0;
5047 bool_t set_later;
5048
5049 sargp->vap->va_mask |= nfs4_ntov_map[k].vbit;
5050
5051 if ((*nfs4_ntov_map[k].xfunc)(xdrp, nap)) {
5052 set_later = nfs4_ntov_map[k].vbit || nfs4_ntov_map[k].vfsstat;
5053 /*
5054 * don't verify yet if a vattr or sb dependent attr,
5055 * because we don't have their sys values yet.
5056 * Will be done later.
5057 */
5058 if (! (set_later && (cmd == NFS4ATTR_VERIT))) {
5059 /*
5060 * ACLs are a special case, since setting the MODE
5061 * conflicts with setting the ACL. We delay setting
5062 * the ACL until all other attributes have been set.
5063 * The ACL gets set in do_rfs4_op_setattr().
5064 */
5065 if (nfs4_ntov_map[k].fbit != FATTR4_ACL_MASK) {
5066 error = (*nfs4_ntov_map[k].sv_getit)(cmd,
5067 sargp, nap);
5068 if (error) {
5069 xdr_free(nfs4_ntov_map[k].xfunc,
5070 (caddr_t)nap);
5071 }
5072 }
5073 }
5074 } else {
5075 #ifdef DEBUG
5076 cmn_err(CE_NOTE, "decode_fattr4_attr: error "
5077 "decoding attribute %d\n", k);
5078 #endif
5079 error = EINVAL;
5080 }
5081 if (!error && resp_bval && !set_later) {
5082 *resp_bval |= nfs4_ntov_map[k].fbit;
5083 }
5084
5085 return (error);
5086 }
5087
5088 /*
5089 * Set vattr based on incoming fattr4 attrs - used by setattr.
5090 * Set response mask. Ignore any values that are not writable vattr attrs.
5091 */
5092 static nfsstat4
do_rfs4_set_attrs(bitmap4 * resp,fattr4 * fattrp,struct compound_state * cs,struct nfs4_svgetit_arg * sargp,struct nfs4_ntov_table * ntovp,nfs4_attr_cmd_t cmd)5093 do_rfs4_set_attrs(bitmap4 *resp, fattr4 *fattrp, struct compound_state *cs,
5094 struct nfs4_svgetit_arg *sargp, struct nfs4_ntov_table *ntovp,
5095 nfs4_attr_cmd_t cmd)
5096 {
5097 int error = 0;
5098 int i;
5099 char *attrs = fattrp->attrlist4;
5100 uint32_t attrslen = fattrp->attrlist4_len;
5101 XDR xdr;
5102 nfsstat4 status = NFS4_OK;
5103 vnode_t *vp = cs->vp;
5104 union nfs4_attr_u *na;
5105 uint8_t *amap;
5106
5107 #ifndef lint
5108 /*
5109 * Make sure that maximum attribute number can be expressed as an
5110 * 8 bit quantity.
5111 */
5112 ASSERT(NFS4_MAXNUM_ATTRS <= (UINT8_MAX + 1));
5113 #endif
5114
5115 if (vp == NULL) {
5116 if (resp)
5117 *resp = 0;
5118 return (NFS4ERR_NOFILEHANDLE);
5119 }
5120 if (cs->access == CS_ACCESS_DENIED) {
5121 if (resp)
5122 *resp = 0;
5123 return (NFS4ERR_ACCESS);
5124 }
5125
5126 sargp->op = cmd;
5127 sargp->cs = cs;
5128 sargp->flag = 0; /* may be set later */
5129 sargp->vap->va_mask = 0;
5130 sargp->rdattr_error = NFS4_OK;
5131 sargp->rdattr_error_req = FALSE;
5132 /* sargp->sbp is set by the caller */
5133
5134 xdrmem_create(&xdr, attrs, attrslen, XDR_DECODE);
5135
5136 na = ntovp->na;
5137 amap = ntovp->amap;
5138
5139 /*
5140 * The following loop iterates on the nfs4_ntov_map checking
5141 * if the fbit is set in the requested bitmap.
5142 * If set then we process the arguments using the
5143 * rfs4_fattr4 conversion functions to populate the setattr
5144 * vattr and va_mask. Any settable attrs that are not using vattr
5145 * will be set in this loop.
5146 */
5147 for (i = 0; i < nfs4_ntov_map_size; i++) {
5148 if (!(fattrp->attrmask & nfs4_ntov_map[i].fbit)) {
5149 continue;
5150 }
5151 /*
5152 * If setattr, must be a writable attr.
5153 * If verify/nverify, must be a readable attr.
5154 */
5155 if ((error = (*nfs4_ntov_map[i].sv_getit)(
5156 NFS4ATTR_SUPPORTED, sargp, NULL)) != 0) {
5157 /*
5158 * Client tries to set/verify an
5159 * unsupported attribute, tries to set
5160 * a read only attr or verify a write
5161 * only one - error!
5162 */
5163 break;
5164 }
5165 /*
5166 * Decode the attribute to set/verify
5167 */
5168 error = decode_fattr4_attr(cmd, sargp, nfs4_ntov_map[i].nval,
5169 &xdr, resp ? resp : NULL, na);
5170 if (error)
5171 break;
5172 *amap++ = (uint8_t)nfs4_ntov_map[i].nval;
5173 na++;
5174 (ntovp->attrcnt)++;
5175 if (nfs4_ntov_map[i].vfsstat)
5176 ntovp->vfsstat = TRUE;
5177 }
5178
5179 if (error != 0)
5180 status = (error == ENOTSUP ? NFS4ERR_ATTRNOTSUPP :
5181 puterrno4(error));
5182 /* xdrmem_destroy(&xdrs); */ /* NO-OP */
5183 return (status);
5184 }
5185
5186 static nfsstat4
do_rfs4_op_setattr(bitmap4 * resp,fattr4 * fattrp,struct compound_state * cs,stateid4 * stateid)5187 do_rfs4_op_setattr(bitmap4 *resp, fattr4 *fattrp, struct compound_state *cs,
5188 stateid4 *stateid)
5189 {
5190 int error = 0;
5191 struct nfs4_svgetit_arg sarg;
5192 bool_t trunc;
5193
5194 nfsstat4 status = NFS4_OK;
5195 cred_t *cr = cs->cr;
5196 vnode_t *vp = cs->vp;
5197 struct nfs4_ntov_table ntov;
5198 struct statvfs64 sb;
5199 struct vattr bva;
5200 struct flock64 bf;
5201 int in_crit = 0;
5202 uint_t saved_mask = 0;
5203 caller_context_t ct;
5204
5205 *resp = 0;
5206 sarg.sbp = &sb;
5207 sarg.is_referral = B_FALSE;
5208 nfs4_ntov_table_init(&ntov);
5209 status = do_rfs4_set_attrs(resp, fattrp, cs, &sarg, &ntov,
5210 NFS4ATTR_SETIT);
5211 if (status != NFS4_OK) {
5212 /*
5213 * failed set attrs
5214 */
5215 goto done;
5216 }
5217 if ((sarg.vap->va_mask == 0) &&
5218 (! (fattrp->attrmask & FATTR4_ACL_MASK))) {
5219 /*
5220 * no further work to be done
5221 */
5222 goto done;
5223 }
5224
5225 /*
5226 * If we got a request to set the ACL and the MODE, only
5227 * allow changing VSUID, VSGID, and VSVTX. Attempting
5228 * to change any other bits, along with setting an ACL,
5229 * gives NFS4ERR_INVAL.
5230 */
5231 if ((fattrp->attrmask & FATTR4_ACL_MASK) &&
5232 (fattrp->attrmask & FATTR4_MODE_MASK)) {
5233 vattr_t va;
5234
5235 va.va_mask = AT_MODE;
5236 error = VOP_GETATTR(vp, &va, 0, cs->cr, NULL);
5237 if (error) {
5238 status = puterrno4(error);
5239 goto done;
5240 }
5241 if ((sarg.vap->va_mode ^ va.va_mode) &
5242 ~(VSUID | VSGID | VSVTX)) {
5243 status = NFS4ERR_INVAL;
5244 goto done;
5245 }
5246 }
5247
5248 /* Check stateid only if size has been set */
5249 if (sarg.vap->va_mask & AT_SIZE) {
5250 trunc = (sarg.vap->va_size == 0);
5251 status = rfs4_check_stateid(FWRITE, cs->vp, stateid,
5252 trunc, &cs->deleg, sarg.vap->va_mask & AT_SIZE, &ct);
5253 if (status != NFS4_OK)
5254 goto done;
5255 } else {
5256 ct.cc_sysid = 0;
5257 ct.cc_pid = 0;
5258 ct.cc_caller_id = nfs4_srv_caller_id;
5259 ct.cc_flags = CC_DONTBLOCK;
5260 }
5261
5262 /* XXX start of possible race with delegations */
5263
5264 /*
5265 * We need to specially handle size changes because it is
5266 * possible for the client to create a file with read-only
5267 * modes, but with the file opened for writing. If the client
5268 * then tries to set the file size, e.g. ftruncate(3C),
5269 * fcntl(F_FREESP), the normal access checking done in
5270 * VOP_SETATTR would prevent the client from doing it even though
5271 * it should be allowed to do so. To get around this, we do the
5272 * access checking for ourselves and use VOP_SPACE which doesn't
5273 * do the access checking.
5274 * Also the client should not be allowed to change the file
5275 * size if there is a conflicting non-blocking mandatory lock in
5276 * the region of the change.
5277 */
5278 if (vp->v_type == VREG && (sarg.vap->va_mask & AT_SIZE)) {
5279 u_offset_t offset;
5280 ssize_t length;
5281
5282 /*
5283 * ufs_setattr clears AT_SIZE from vap->va_mask, but
5284 * before returning, sarg.vap->va_mask is used to
5285 * generate the setattr reply bitmap. We also clear
5286 * AT_SIZE below before calling VOP_SPACE. For both
5287 * of these cases, the va_mask needs to be saved here
5288 * and restored after calling VOP_SETATTR.
5289 */
5290 saved_mask = sarg.vap->va_mask;
5291
5292 /*
5293 * Check any possible conflict due to NBMAND locks.
5294 * Get into critical region before VOP_GETATTR, so the
5295 * size attribute is valid when checking conflicts.
5296 */
5297 if (nbl_need_check(vp)) {
5298 nbl_start_crit(vp, RW_READER);
5299 in_crit = 1;
5300 }
5301
5302 bva.va_mask = AT_UID|AT_SIZE;
5303 if (error = VOP_GETATTR(vp, &bva, 0, cr, &ct)) {
5304 status = puterrno4(error);
5305 goto done;
5306 }
5307
5308 if (in_crit) {
5309 if (sarg.vap->va_size < bva.va_size) {
5310 offset = sarg.vap->va_size;
5311 length = bva.va_size - sarg.vap->va_size;
5312 } else {
5313 offset = bva.va_size;
5314 length = sarg.vap->va_size - bva.va_size;
5315 }
5316 if (nbl_conflict(vp, NBL_WRITE, offset, length, 0,
5317 &ct)) {
5318 status = NFS4ERR_LOCKED;
5319 goto done;
5320 }
5321 }
5322
5323 if (crgetuid(cr) == bva.va_uid) {
5324 sarg.vap->va_mask &= ~AT_SIZE;
5325 bf.l_type = F_WRLCK;
5326 bf.l_whence = 0;
5327 bf.l_start = (off64_t)sarg.vap->va_size;
5328 bf.l_len = 0;
5329 bf.l_sysid = 0;
5330 bf.l_pid = 0;
5331 error = VOP_SPACE(vp, F_FREESP, &bf, FWRITE,
5332 (offset_t)sarg.vap->va_size, cr, &ct);
5333 }
5334 }
5335
5336 if (!error && sarg.vap->va_mask != 0)
5337 error = VOP_SETATTR(vp, sarg.vap, sarg.flag, cr, &ct);
5338
5339 /* restore va_mask -- ufs_setattr clears AT_SIZE */
5340 if (saved_mask & AT_SIZE)
5341 sarg.vap->va_mask |= AT_SIZE;
5342
5343 /*
5344 * If an ACL was being set, it has been delayed until now,
5345 * in order to set the mode (via the VOP_SETATTR() above) first.
5346 */
5347 if ((! error) && (fattrp->attrmask & FATTR4_ACL_MASK)) {
5348 int i;
5349
5350 for (i = 0; i < NFS4_MAXNUM_ATTRS; i++)
5351 if (ntov.amap[i] == FATTR4_ACL)
5352 break;
5353 if (i < NFS4_MAXNUM_ATTRS) {
5354 error = (*nfs4_ntov_map[FATTR4_ACL].sv_getit)(
5355 NFS4ATTR_SETIT, &sarg, &ntov.na[i]);
5356 if (error == 0) {
5357 *resp |= FATTR4_ACL_MASK;
5358 } else if (error == ENOTSUP) {
5359 (void) rfs4_verify_attr(&sarg, resp, &ntov);
5360 status = NFS4ERR_ATTRNOTSUPP;
5361 goto done;
5362 }
5363 } else {
5364 NFS4_DEBUG(rfs4_debug,
5365 (CE_NOTE, "do_rfs4_op_setattr: "
5366 "unable to find ACL in fattr4"));
5367 error = EINVAL;
5368 }
5369 }
5370
5371 if (error) {
5372 /* check if a monitor detected a delegation conflict */
5373 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK))
5374 status = NFS4ERR_DELAY;
5375 else
5376 status = puterrno4(error);
5377
5378 /*
5379 * Set the response bitmap when setattr failed.
5380 * If VOP_SETATTR partially succeeded, test by doing a
5381 * VOP_GETATTR on the object and comparing the data
5382 * to the setattr arguments.
5383 */
5384 (void) rfs4_verify_attr(&sarg, resp, &ntov);
5385 } else {
5386 /*
5387 * Force modified metadata out to stable storage.
5388 */
5389 (void) VOP_FSYNC(vp, FNODSYNC, cr, &ct);
5390 /*
5391 * Set response bitmap
5392 */
5393 nfs4_vmask_to_nmask_set(sarg.vap->va_mask, resp);
5394 }
5395
5396 /* Return early and already have a NFSv4 error */
5397 done:
5398 /*
5399 * Except for nfs4_vmask_to_nmask_set(), vattr --> fattr
5400 * conversion sets both readable and writeable NFS4 attrs
5401 * for AT_MTIME and AT_ATIME. The line below masks out
5402 * unrequested attrs from the setattr result bitmap. This
5403 * is placed after the done: label to catch the ATTRNOTSUP
5404 * case.
5405 */
5406 *resp &= fattrp->attrmask;
5407
5408 if (in_crit)
5409 nbl_end_crit(vp);
5410
5411 nfs4_ntov_table_free(&ntov, &sarg);
5412
5413 return (status);
5414 }
5415
5416 /* ARGSUSED */
5417 static void
rfs4_op_setattr(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)5418 rfs4_op_setattr(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
5419 struct compound_state *cs)
5420 {
5421 SETATTR4args *args = &argop->nfs_argop4_u.opsetattr;
5422 SETATTR4res *resp = &resop->nfs_resop4_u.opsetattr;
5423 bslabel_t *clabel;
5424
5425 DTRACE_NFSV4_2(op__setattr__start, struct compound_state *, cs,
5426 SETATTR4args *, args);
5427
5428 if (cs->vp == NULL) {
5429 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
5430 goto out;
5431 }
5432
5433 /*
5434 * If there is an unshared filesystem mounted on this vnode,
5435 * do not allow to setattr on this vnode.
5436 */
5437 if (vn_ismntpt(cs->vp)) {
5438 *cs->statusp = resp->status = NFS4ERR_ACCESS;
5439 goto out;
5440 }
5441
5442 resp->attrsset = 0;
5443
5444 if (rdonly4(req, cs)) {
5445 *cs->statusp = resp->status = NFS4ERR_ROFS;
5446 goto out;
5447 }
5448
5449 /* check label before setting attributes */
5450 if (is_system_labeled()) {
5451 ASSERT(req->rq_label != NULL);
5452 clabel = req->rq_label;
5453 DTRACE_PROBE2(tx__rfs4__log__info__opsetattr__clabel, char *,
5454 "got client label from request(1)",
5455 struct svc_req *, req);
5456 if (!blequal(&l_admin_low->tsl_label, clabel)) {
5457 if (!do_rfs_label_check(clabel, cs->vp,
5458 EQUALITY_CHECK, cs->exi)) {
5459 *cs->statusp = resp->status = NFS4ERR_ACCESS;
5460 goto out;
5461 }
5462 }
5463 }
5464
5465 *cs->statusp = resp->status =
5466 do_rfs4_op_setattr(&resp->attrsset, &args->obj_attributes, cs,
5467 &args->stateid);
5468
5469 out:
5470 DTRACE_NFSV4_2(op__setattr__done, struct compound_state *, cs,
5471 SETATTR4res *, resp);
5472 }
5473
5474 /* ARGSUSED */
5475 static void
rfs4_op_verify(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)5476 rfs4_op_verify(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
5477 struct compound_state *cs)
5478 {
5479 /*
5480 * verify and nverify are exactly the same, except that nverify
5481 * succeeds when some argument changed, and verify succeeds when
5482 * when none changed.
5483 */
5484
5485 VERIFY4args *args = &argop->nfs_argop4_u.opverify;
5486 VERIFY4res *resp = &resop->nfs_resop4_u.opverify;
5487
5488 int error;
5489 struct nfs4_svgetit_arg sarg;
5490 struct statvfs64 sb;
5491 struct nfs4_ntov_table ntov;
5492
5493 DTRACE_NFSV4_2(op__verify__start, struct compound_state *, cs,
5494 VERIFY4args *, args);
5495
5496 if (cs->vp == NULL) {
5497 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
5498 goto out;
5499 }
5500
5501 sarg.sbp = &sb;
5502 sarg.is_referral = B_FALSE;
5503 nfs4_ntov_table_init(&ntov);
5504 resp->status = do_rfs4_set_attrs(NULL, &args->obj_attributes, cs,
5505 &sarg, &ntov, NFS4ATTR_VERIT);
5506 if (resp->status != NFS4_OK) {
5507 /*
5508 * do_rfs4_set_attrs will try to verify systemwide attrs,
5509 * so could return -1 for "no match".
5510 */
5511 if (resp->status == -1)
5512 resp->status = NFS4ERR_NOT_SAME;
5513 goto done;
5514 }
5515 error = rfs4_verify_attr(&sarg, NULL, &ntov);
5516 switch (error) {
5517 case 0:
5518 resp->status = NFS4_OK;
5519 break;
5520 case -1:
5521 resp->status = NFS4ERR_NOT_SAME;
5522 break;
5523 default:
5524 resp->status = puterrno4(error);
5525 break;
5526 }
5527 done:
5528 *cs->statusp = resp->status;
5529 nfs4_ntov_table_free(&ntov, &sarg);
5530 out:
5531 DTRACE_NFSV4_2(op__verify__done, struct compound_state *, cs,
5532 VERIFY4res *, resp);
5533 }
5534
5535 /* ARGSUSED */
5536 static void
rfs4_op_nverify(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)5537 rfs4_op_nverify(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
5538 struct compound_state *cs)
5539 {
5540 /*
5541 * verify and nverify are exactly the same, except that nverify
5542 * succeeds when some argument changed, and verify succeeds when
5543 * when none changed.
5544 */
5545
5546 NVERIFY4args *args = &argop->nfs_argop4_u.opnverify;
5547 NVERIFY4res *resp = &resop->nfs_resop4_u.opnverify;
5548
5549 int error;
5550 struct nfs4_svgetit_arg sarg;
5551 struct statvfs64 sb;
5552 struct nfs4_ntov_table ntov;
5553
5554 DTRACE_NFSV4_2(op__nverify__start, struct compound_state *, cs,
5555 NVERIFY4args *, args);
5556
5557 if (cs->vp == NULL) {
5558 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
5559 DTRACE_NFSV4_2(op__nverify__done, struct compound_state *, cs,
5560 NVERIFY4res *, resp);
5561 return;
5562 }
5563 sarg.sbp = &sb;
5564 sarg.is_referral = B_FALSE;
5565 nfs4_ntov_table_init(&ntov);
5566 resp->status = do_rfs4_set_attrs(NULL, &args->obj_attributes, cs,
5567 &sarg, &ntov, NFS4ATTR_VERIT);
5568 if (resp->status != NFS4_OK) {
5569 /*
5570 * do_rfs4_set_attrs will try to verify systemwide attrs,
5571 * so could return -1 for "no match".
5572 */
5573 if (resp->status == -1)
5574 resp->status = NFS4_OK;
5575 goto done;
5576 }
5577 error = rfs4_verify_attr(&sarg, NULL, &ntov);
5578 switch (error) {
5579 case 0:
5580 resp->status = NFS4ERR_SAME;
5581 break;
5582 case -1:
5583 resp->status = NFS4_OK;
5584 break;
5585 default:
5586 resp->status = puterrno4(error);
5587 break;
5588 }
5589 done:
5590 *cs->statusp = resp->status;
5591 nfs4_ntov_table_free(&ntov, &sarg);
5592
5593 DTRACE_NFSV4_2(op__nverify__done, struct compound_state *, cs,
5594 NVERIFY4res *, resp);
5595 }
5596
5597 /*
5598 * XXX - This should live in an NFS header file.
5599 */
5600 #define MAX_IOVECS 12
5601
5602 /* ARGSUSED */
5603 static void
rfs4_op_write(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)5604 rfs4_op_write(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
5605 struct compound_state *cs)
5606 {
5607 WRITE4args *args = &argop->nfs_argop4_u.opwrite;
5608 WRITE4res *resp = &resop->nfs_resop4_u.opwrite;
5609 int error;
5610 vnode_t *vp;
5611 struct vattr bva;
5612 u_offset_t rlimit;
5613 struct uio uio;
5614 struct iovec iov[MAX_IOVECS];
5615 struct iovec *iovp;
5616 int iovcnt;
5617 int ioflag;
5618 cred_t *savecred, *cr;
5619 bool_t *deleg = &cs->deleg;
5620 nfsstat4 stat;
5621 int in_crit = 0;
5622 caller_context_t ct;
5623
5624 DTRACE_NFSV4_2(op__write__start, struct compound_state *, cs,
5625 WRITE4args *, args);
5626
5627 vp = cs->vp;
5628 if (vp == NULL) {
5629 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
5630 goto out;
5631 }
5632 if (cs->access == CS_ACCESS_DENIED) {
5633 *cs->statusp = resp->status = NFS4ERR_ACCESS;
5634 goto out;
5635 }
5636
5637 cr = cs->cr;
5638
5639 if ((stat = rfs4_check_stateid(FWRITE, vp, &args->stateid, FALSE,
5640 deleg, TRUE, &ct)) != NFS4_OK) {
5641 *cs->statusp = resp->status = stat;
5642 goto out;
5643 }
5644
5645 /*
5646 * We have to enter the critical region before calling VOP_RWLOCK
5647 * to avoid a deadlock with ufs.
5648 */
5649 if (nbl_need_check(vp)) {
5650 nbl_start_crit(vp, RW_READER);
5651 in_crit = 1;
5652 if (nbl_conflict(vp, NBL_WRITE,
5653 args->offset, args->data_len, 0, &ct)) {
5654 *cs->statusp = resp->status = NFS4ERR_LOCKED;
5655 goto out;
5656 }
5657 }
5658
5659 bva.va_mask = AT_MODE | AT_UID;
5660 error = VOP_GETATTR(vp, &bva, 0, cr, &ct);
5661
5662 /*
5663 * If we can't get the attributes, then we can't do the
5664 * right access checking. So, we'll fail the request.
5665 */
5666 if (error) {
5667 *cs->statusp = resp->status = puterrno4(error);
5668 goto out;
5669 }
5670
5671 if (rdonly4(req, cs)) {
5672 *cs->statusp = resp->status = NFS4ERR_ROFS;
5673 goto out;
5674 }
5675
5676 if (vp->v_type != VREG) {
5677 *cs->statusp = resp->status =
5678 ((vp->v_type == VDIR) ? NFS4ERR_ISDIR : NFS4ERR_INVAL);
5679 goto out;
5680 }
5681
5682 if (crgetuid(cr) != bva.va_uid &&
5683 (error = VOP_ACCESS(vp, VWRITE, 0, cr, &ct))) {
5684 *cs->statusp = resp->status = puterrno4(error);
5685 goto out;
5686 }
5687
5688 if (MANDLOCK(vp, bva.va_mode)) {
5689 *cs->statusp = resp->status = NFS4ERR_ACCESS;
5690 goto out;
5691 }
5692
5693 if (args->data_len == 0) {
5694 *cs->statusp = resp->status = NFS4_OK;
5695 resp->count = 0;
5696 resp->committed = args->stable;
5697 resp->writeverf = Write4verf;
5698 goto out;
5699 }
5700
5701 if (args->mblk != NULL) {
5702 mblk_t *m;
5703 uint_t bytes, round_len;
5704
5705 iovcnt = 0;
5706 bytes = 0;
5707 round_len = roundup(args->data_len, BYTES_PER_XDR_UNIT);
5708 for (m = args->mblk;
5709 m != NULL && bytes < round_len;
5710 m = m->b_cont) {
5711 iovcnt++;
5712 bytes += MBLKL(m);
5713 }
5714 #ifdef DEBUG
5715 /* should have ended on an mblk boundary */
5716 if (bytes != round_len) {
5717 printf("bytes=0x%x, round_len=0x%x, req len=0x%x\n",
5718 bytes, round_len, args->data_len);
5719 printf("args=%p, args->mblk=%p, m=%p", (void *)args,
5720 (void *)args->mblk, (void *)m);
5721 ASSERT(bytes == round_len);
5722 }
5723 #endif
5724 if (iovcnt <= MAX_IOVECS) {
5725 iovp = iov;
5726 } else {
5727 iovp = kmem_alloc(sizeof (*iovp) * iovcnt, KM_SLEEP);
5728 }
5729 mblk_to_iov(args->mblk, iovcnt, iovp);
5730 } else if (args->rlist != NULL) {
5731 iovcnt = 1;
5732 iovp = iov;
5733 iovp->iov_base = (char *)((args->rlist)->u.c_daddr3);
5734 iovp->iov_len = args->data_len;
5735 } else {
5736 iovcnt = 1;
5737 iovp = iov;
5738 iovp->iov_base = args->data_val;
5739 iovp->iov_len = args->data_len;
5740 }
5741
5742 uio.uio_iov = iovp;
5743 uio.uio_iovcnt = iovcnt;
5744
5745 uio.uio_segflg = UIO_SYSSPACE;
5746 uio.uio_extflg = UIO_COPY_DEFAULT;
5747 uio.uio_loffset = args->offset;
5748 uio.uio_resid = args->data_len;
5749 uio.uio_llimit = curproc->p_fsz_ctl;
5750 rlimit = uio.uio_llimit - args->offset;
5751 if (rlimit < (u_offset_t)uio.uio_resid)
5752 uio.uio_resid = (int)rlimit;
5753
5754 if (args->stable == UNSTABLE4)
5755 ioflag = 0;
5756 else if (args->stable == FILE_SYNC4)
5757 ioflag = FSYNC;
5758 else if (args->stable == DATA_SYNC4)
5759 ioflag = FDSYNC;
5760 else {
5761 if (iovp != iov)
5762 kmem_free(iovp, sizeof (*iovp) * iovcnt);
5763 *cs->statusp = resp->status = NFS4ERR_INVAL;
5764 goto out;
5765 }
5766
5767 /*
5768 * We're changing creds because VM may fault and we need
5769 * the cred of the current thread to be used if quota
5770 * checking is enabled.
5771 */
5772 savecred = curthread->t_cred;
5773 curthread->t_cred = cr;
5774 error = do_io(FWRITE, vp, &uio, ioflag, cr, &ct);
5775 curthread->t_cred = savecred;
5776
5777 if (iovp != iov)
5778 kmem_free(iovp, sizeof (*iovp) * iovcnt);
5779
5780 if (error) {
5781 *cs->statusp = resp->status = puterrno4(error);
5782 goto out;
5783 }
5784
5785 *cs->statusp = resp->status = NFS4_OK;
5786 resp->count = args->data_len - uio.uio_resid;
5787
5788 if (ioflag == 0)
5789 resp->committed = UNSTABLE4;
5790 else
5791 resp->committed = FILE_SYNC4;
5792
5793 resp->writeverf = Write4verf;
5794
5795 out:
5796 if (in_crit)
5797 nbl_end_crit(vp);
5798
5799 DTRACE_NFSV4_2(op__write__done, struct compound_state *, cs,
5800 WRITE4res *, resp);
5801 }
5802
5803
5804 /* XXX put in a header file */
5805 extern int sec_svc_getcred(struct svc_req *, cred_t *, caddr_t *, int *);
5806
5807 void
rfs4_compound(COMPOUND4args * args,COMPOUND4res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,int * rv)5808 rfs4_compound(COMPOUND4args *args, COMPOUND4res *resp, struct exportinfo *exi,
5809 struct svc_req *req, cred_t *cr, int *rv)
5810 {
5811 uint_t i;
5812 struct compound_state cs;
5813
5814 if (rv != NULL)
5815 *rv = 0;
5816 rfs4_init_compound_state(&cs);
5817 /*
5818 * Form a reply tag by copying over the reqeuest tag.
5819 */
5820 resp->tag.utf8string_val =
5821 kmem_alloc(args->tag.utf8string_len, KM_SLEEP);
5822 resp->tag.utf8string_len = args->tag.utf8string_len;
5823 bcopy(args->tag.utf8string_val, resp->tag.utf8string_val,
5824 resp->tag.utf8string_len);
5825
5826 cs.statusp = &resp->status;
5827 cs.req = req;
5828 resp->array = NULL;
5829 resp->array_len = 0;
5830
5831 /*
5832 * XXX for now, minorversion should be zero
5833 */
5834 if (args->minorversion != NFS4_MINORVERSION) {
5835 DTRACE_NFSV4_2(compound__start, struct compound_state *,
5836 &cs, COMPOUND4args *, args);
5837 resp->status = NFS4ERR_MINOR_VERS_MISMATCH;
5838 DTRACE_NFSV4_2(compound__done, struct compound_state *,
5839 &cs, COMPOUND4res *, resp);
5840 return;
5841 }
5842
5843 if (args->array_len == 0) {
5844 resp->status = NFS4_OK;
5845 return;
5846 }
5847
5848 ASSERT(exi == NULL);
5849 ASSERT(cr == NULL);
5850
5851 cr = crget();
5852 ASSERT(cr != NULL);
5853
5854 if (sec_svc_getcred(req, cr, &cs.principal, &cs.nfsflavor) == 0) {
5855 DTRACE_NFSV4_2(compound__start, struct compound_state *,
5856 &cs, COMPOUND4args *, args);
5857 crfree(cr);
5858 DTRACE_NFSV4_2(compound__done, struct compound_state *,
5859 &cs, COMPOUND4res *, resp);
5860 svcerr_badcred(req->rq_xprt);
5861 if (rv != NULL)
5862 *rv = 1;
5863 return;
5864 }
5865 resp->array_len = args->array_len;
5866 resp->array = kmem_zalloc(args->array_len * sizeof (nfs_resop4),
5867 KM_SLEEP);
5868
5869 cs.basecr = cr;
5870
5871 DTRACE_NFSV4_2(compound__start, struct compound_state *, &cs,
5872 COMPOUND4args *, args);
5873
5874 /*
5875 * If this is the first compound we've seen, we need to start all
5876 * new instances' grace periods.
5877 */
5878 if (rfs4_seen_first_compound == 0) {
5879 rfs4_grace_start_new();
5880 /*
5881 * This must be set after rfs4_grace_start_new(), otherwise
5882 * another thread could proceed past here before the former
5883 * is finished.
5884 */
5885 rfs4_seen_first_compound = 1;
5886 }
5887
5888 for (i = 0; i < args->array_len && cs.cont; i++) {
5889 nfs_argop4 *argop;
5890 nfs_resop4 *resop;
5891 uint_t op;
5892
5893 argop = &args->array[i];
5894 resop = &resp->array[i];
5895 resop->resop = argop->argop;
5896 op = (uint_t)resop->resop;
5897
5898 if (op < rfsv4disp_cnt) {
5899 /*
5900 * Count the individual ops here; NULL and COMPOUND
5901 * are counted in common_dispatch()
5902 */
5903 rfsproccnt_v4_ptr[op].value.ui64++;
5904
5905 NFS4_DEBUG(rfs4_debug > 1,
5906 (CE_NOTE, "Executing %s", rfs4_op_string[op]));
5907 (*rfsv4disptab[op].dis_proc)(argop, resop, req, &cs);
5908 NFS4_DEBUG(rfs4_debug > 1, (CE_NOTE, "%s returned %d",
5909 rfs4_op_string[op], *cs.statusp));
5910 if (*cs.statusp != NFS4_OK)
5911 cs.cont = FALSE;
5912 } else {
5913 /*
5914 * This is effectively dead code since XDR code
5915 * will have already returned BADXDR if op doesn't
5916 * decode to legal value. This only done for a
5917 * day when XDR code doesn't verify v4 opcodes.
5918 */
5919 op = OP_ILLEGAL;
5920 rfsproccnt_v4_ptr[OP_ILLEGAL_IDX].value.ui64++;
5921
5922 rfs4_op_illegal(argop, resop, req, &cs);
5923 cs.cont = FALSE;
5924 }
5925
5926 /*
5927 * If not at last op, and if we are to stop, then
5928 * compact the results array.
5929 */
5930 if ((i + 1) < args->array_len && !cs.cont) {
5931 nfs_resop4 *new_res = kmem_alloc(
5932 (i+1) * sizeof (nfs_resop4), KM_SLEEP);
5933 bcopy(resp->array,
5934 new_res, (i+1) * sizeof (nfs_resop4));
5935 kmem_free(resp->array,
5936 args->array_len * sizeof (nfs_resop4));
5937
5938 resp->array_len = i + 1;
5939 resp->array = new_res;
5940 }
5941 }
5942
5943
5944 DTRACE_NFSV4_2(compound__done, struct compound_state *, &cs,
5945 COMPOUND4res *, resp);
5946
5947 if (cs.exi != NULL)
5948 exi_rele(cs.exi);
5949 if (cs.saved_exi != NULL)
5950 exi_rele(cs.saved_exi);
5951 if (cs.vp != NULL)
5952 VN_RELE(cs.vp);
5953 if (cs.saved_vp != NULL)
5954 VN_RELE(cs.saved_vp);
5955 if (cs.saved_fh.nfs_fh4_val != NULL)
5956 kmem_free(cs.saved_fh.nfs_fh4_val, NFS4_FHSIZE);
5957
5958 if (cs.basecr)
5959 crfree(cs.basecr);
5960 if (cs.cr)
5961 crfree(cs.cr);
5962 /*
5963 * done with this compound request, free the label
5964 */
5965
5966 if (req->rq_label != NULL) {
5967 kmem_free(req->rq_label, sizeof (bslabel_t));
5968 req->rq_label = NULL;
5969 }
5970 }
5971
5972 /*
5973 * XXX because of what appears to be duplicate calls to rfs4_compound_free
5974 * XXX zero out the tag and array values. Need to investigate why the
5975 * XXX calls occur, but at least prevent the panic for now.
5976 */
5977 void
rfs4_compound_free(COMPOUND4res * resp)5978 rfs4_compound_free(COMPOUND4res *resp)
5979 {
5980 uint_t i;
5981
5982 if (resp->tag.utf8string_val) {
5983 UTF8STRING_FREE(resp->tag)
5984 }
5985
5986 for (i = 0; i < resp->array_len; i++) {
5987 nfs_resop4 *resop;
5988 uint_t op;
5989
5990 resop = &resp->array[i];
5991 op = (uint_t)resop->resop;
5992 if (op < rfsv4disp_cnt) {
5993 (*rfsv4disptab[op].dis_resfree)(resop);
5994 }
5995 }
5996 if (resp->array != NULL) {
5997 kmem_free(resp->array, resp->array_len * sizeof (nfs_resop4));
5998 }
5999 }
6000
6001 /*
6002 * Process the value of the compound request rpc flags, as a bit-AND
6003 * of the individual per-op flags (idempotent, allowork, publicfh_ok)
6004 */
6005 void
rfs4_compound_flagproc(COMPOUND4args * args,int * flagp)6006 rfs4_compound_flagproc(COMPOUND4args *args, int *flagp)
6007 {
6008 int i;
6009 int flag = RPC_ALL;
6010
6011 for (i = 0; flag && i < args->array_len; i++) {
6012 uint_t op;
6013
6014 op = (uint_t)args->array[i].argop;
6015
6016 if (op < rfsv4disp_cnt)
6017 flag &= rfsv4disptab[op].dis_flags;
6018 else
6019 flag = 0;
6020 }
6021 *flagp = flag;
6022 }
6023
6024 nfsstat4
rfs4_client_sysid(rfs4_client_t * cp,sysid_t * sp)6025 rfs4_client_sysid(rfs4_client_t *cp, sysid_t *sp)
6026 {
6027 nfsstat4 e;
6028
6029 rfs4_dbe_lock(cp->rc_dbe);
6030
6031 if (cp->rc_sysidt != LM_NOSYSID) {
6032 *sp = cp->rc_sysidt;
6033 e = NFS4_OK;
6034
6035 } else if ((cp->rc_sysidt = lm_alloc_sysidt()) != LM_NOSYSID) {
6036 *sp = cp->rc_sysidt;
6037 e = NFS4_OK;
6038
6039 NFS4_DEBUG(rfs4_debug, (CE_NOTE,
6040 "rfs4_client_sysid: allocated 0x%x\n", *sp));
6041 } else
6042 e = NFS4ERR_DELAY;
6043
6044 rfs4_dbe_unlock(cp->rc_dbe);
6045 return (e);
6046 }
6047
6048 #if defined(DEBUG) && ! defined(lint)
lock_print(char * str,int operation,struct flock64 * flk)6049 static void lock_print(char *str, int operation, struct flock64 *flk)
6050 {
6051 char *op, *type;
6052
6053 switch (operation) {
6054 case F_GETLK: op = "F_GETLK";
6055 break;
6056 case F_SETLK: op = "F_SETLK";
6057 break;
6058 case F_SETLK_NBMAND: op = "F_SETLK_NBMAND";
6059 break;
6060 default: op = "F_UNKNOWN";
6061 break;
6062 }
6063 switch (flk->l_type) {
6064 case F_UNLCK: type = "F_UNLCK";
6065 break;
6066 case F_RDLCK: type = "F_RDLCK";
6067 break;
6068 case F_WRLCK: type = "F_WRLCK";
6069 break;
6070 default: type = "F_UNKNOWN";
6071 break;
6072 }
6073
6074 ASSERT(flk->l_whence == 0);
6075 cmn_err(CE_NOTE, "%s: %s, type = %s, off = %llx len = %llx pid = %d",
6076 str, op, type, (longlong_t)flk->l_start,
6077 flk->l_len ? (longlong_t)flk->l_len : ~0LL, flk->l_pid);
6078 }
6079
6080 #define LOCK_PRINT(d, s, t, f) if (d) lock_print(s, t, f)
6081 #else
6082 #define LOCK_PRINT(d, s, t, f)
6083 #endif
6084
6085 /*ARGSUSED*/
6086 static bool_t
creds_ok(cred_set_t cr_set,struct svc_req * req,struct compound_state * cs)6087 creds_ok(cred_set_t cr_set, struct svc_req *req, struct compound_state *cs)
6088 {
6089 return (TRUE);
6090 }
6091
6092 /*
6093 * Look up the pathname using the vp in cs as the directory vnode.
6094 * cs->vp will be the vnode for the file on success
6095 */
6096
6097 static nfsstat4
rfs4_lookup(component4 * component,struct svc_req * req,struct compound_state * cs)6098 rfs4_lookup(component4 *component, struct svc_req *req,
6099 struct compound_state *cs)
6100 {
6101 char *nm;
6102 uint32_t len;
6103 nfsstat4 status;
6104 struct sockaddr *ca;
6105 char *name;
6106
6107 if (cs->vp == NULL) {
6108 return (NFS4ERR_NOFILEHANDLE);
6109 }
6110 if (cs->vp->v_type != VDIR) {
6111 return (NFS4ERR_NOTDIR);
6112 }
6113
6114 status = utf8_dir_verify(component);
6115 if (status != NFS4_OK)
6116 return (status);
6117
6118 nm = utf8_to_fn(component, &len, NULL);
6119 if (nm == NULL) {
6120 return (NFS4ERR_INVAL);
6121 }
6122
6123 if (len > MAXNAMELEN) {
6124 kmem_free(nm, len);
6125 return (NFS4ERR_NAMETOOLONG);
6126 }
6127
6128 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
6129 name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
6130 MAXPATHLEN + 1);
6131
6132 if (name == NULL) {
6133 kmem_free(nm, len);
6134 return (NFS4ERR_INVAL);
6135 }
6136
6137 status = do_rfs4_op_lookup(name, req, cs);
6138
6139 if (name != nm)
6140 kmem_free(name, MAXPATHLEN + 1);
6141
6142 kmem_free(nm, len);
6143
6144 return (status);
6145 }
6146
6147 static nfsstat4
rfs4_lookupfile(component4 * component,struct svc_req * req,struct compound_state * cs,uint32_t access,change_info4 * cinfo)6148 rfs4_lookupfile(component4 *component, struct svc_req *req,
6149 struct compound_state *cs, uint32_t access, change_info4 *cinfo)
6150 {
6151 nfsstat4 status;
6152 vnode_t *dvp = cs->vp;
6153 vattr_t bva, ava, fva;
6154 int error;
6155
6156 /* Get "before" change value */
6157 bva.va_mask = AT_CTIME|AT_SEQ;
6158 error = VOP_GETATTR(dvp, &bva, 0, cs->cr, NULL);
6159 if (error)
6160 return (puterrno4(error));
6161
6162 /* rfs4_lookup may VN_RELE directory */
6163 VN_HOLD(dvp);
6164
6165 status = rfs4_lookup(component, req, cs);
6166 if (status != NFS4_OK) {
6167 VN_RELE(dvp);
6168 return (status);
6169 }
6170
6171 /*
6172 * Get "after" change value, if it fails, simply return the
6173 * before value.
6174 */
6175 ava.va_mask = AT_CTIME|AT_SEQ;
6176 if (VOP_GETATTR(dvp, &ava, 0, cs->cr, NULL)) {
6177 ava.va_ctime = bva.va_ctime;
6178 ava.va_seq = 0;
6179 }
6180 VN_RELE(dvp);
6181
6182 /*
6183 * Validate the file is a file
6184 */
6185 fva.va_mask = AT_TYPE|AT_MODE;
6186 error = VOP_GETATTR(cs->vp, &fva, 0, cs->cr, NULL);
6187 if (error)
6188 return (puterrno4(error));
6189
6190 if (fva.va_type != VREG) {
6191 if (fva.va_type == VDIR)
6192 return (NFS4ERR_ISDIR);
6193 if (fva.va_type == VLNK)
6194 return (NFS4ERR_SYMLINK);
6195 return (NFS4ERR_INVAL);
6196 }
6197
6198 NFS4_SET_FATTR4_CHANGE(cinfo->before, bva.va_ctime);
6199 NFS4_SET_FATTR4_CHANGE(cinfo->after, ava.va_ctime);
6200
6201 /*
6202 * It is undefined if VOP_LOOKUP will change va_seq, so
6203 * cinfo.atomic = TRUE only if we have
6204 * non-zero va_seq's, and they have not changed.
6205 */
6206 if (bva.va_seq && ava.va_seq && ava.va_seq == bva.va_seq)
6207 cinfo->atomic = TRUE;
6208 else
6209 cinfo->atomic = FALSE;
6210
6211 /* Check for mandatory locking */
6212 cs->mandlock = MANDLOCK(cs->vp, fva.va_mode);
6213 return (check_open_access(access, cs, req));
6214 }
6215
6216 static nfsstat4
create_vnode(vnode_t * dvp,char * nm,vattr_t * vap,createmode4 mode,timespec32_t * mtime,cred_t * cr,vnode_t ** vpp,bool_t * created)6217 create_vnode(vnode_t *dvp, char *nm, vattr_t *vap, createmode4 mode,
6218 timespec32_t *mtime, cred_t *cr, vnode_t **vpp, bool_t *created)
6219 {
6220 int error;
6221 nfsstat4 status = NFS4_OK;
6222 vattr_t va;
6223
6224 tryagain:
6225
6226 /*
6227 * The file open mode used is VWRITE. If the client needs
6228 * some other semantic, then it should do the access checking
6229 * itself. It would have been nice to have the file open mode
6230 * passed as part of the arguments.
6231 */
6232
6233 *created = TRUE;
6234 error = VOP_CREATE(dvp, nm, vap, EXCL, VWRITE, vpp, cr, 0, NULL, NULL);
6235
6236 if (error) {
6237 *created = FALSE;
6238
6239 /*
6240 * If we got something other than file already exists
6241 * then just return this error. Otherwise, we got
6242 * EEXIST. If we were doing a GUARDED create, then
6243 * just return this error. Otherwise, we need to
6244 * make sure that this wasn't a duplicate of an
6245 * exclusive create request.
6246 *
6247 * The assumption is made that a non-exclusive create
6248 * request will never return EEXIST.
6249 */
6250
6251 if (error != EEXIST || mode == GUARDED4) {
6252 status = puterrno4(error);
6253 return (status);
6254 }
6255 error = VOP_LOOKUP(dvp, nm, vpp, NULL, 0, NULL, cr,
6256 NULL, NULL, NULL);
6257
6258 if (error) {
6259 /*
6260 * We couldn't find the file that we thought that
6261 * we just created. So, we'll just try creating
6262 * it again.
6263 */
6264 if (error == ENOENT)
6265 goto tryagain;
6266
6267 status = puterrno4(error);
6268 return (status);
6269 }
6270
6271 if (mode == UNCHECKED4) {
6272 /* existing object must be regular file */
6273 if ((*vpp)->v_type != VREG) {
6274 if ((*vpp)->v_type == VDIR)
6275 status = NFS4ERR_ISDIR;
6276 else if ((*vpp)->v_type == VLNK)
6277 status = NFS4ERR_SYMLINK;
6278 else
6279 status = NFS4ERR_INVAL;
6280 VN_RELE(*vpp);
6281 return (status);
6282 }
6283
6284 return (NFS4_OK);
6285 }
6286
6287 /* Check for duplicate request */
6288 ASSERT(mtime != 0);
6289 va.va_mask = AT_MTIME;
6290 error = VOP_GETATTR(*vpp, &va, 0, cr, NULL);
6291 if (!error) {
6292 /* We found the file */
6293 if (va.va_mtime.tv_sec != mtime->tv_sec ||
6294 va.va_mtime.tv_nsec != mtime->tv_nsec) {
6295 /* but its not our creation */
6296 VN_RELE(*vpp);
6297 return (NFS4ERR_EXIST);
6298 }
6299 *created = TRUE; /* retrans of create == created */
6300 return (NFS4_OK);
6301 }
6302 VN_RELE(*vpp);
6303 return (NFS4ERR_EXIST);
6304 }
6305
6306 return (NFS4_OK);
6307 }
6308
6309 static nfsstat4
check_open_access(uint32_t access,struct compound_state * cs,struct svc_req * req)6310 check_open_access(uint32_t access, struct compound_state *cs,
6311 struct svc_req *req)
6312 {
6313 int error;
6314 vnode_t *vp;
6315 bool_t readonly;
6316 cred_t *cr = cs->cr;
6317
6318 /* For now we don't allow mandatory locking as per V2/V3 */
6319 if (cs->access == CS_ACCESS_DENIED || cs->mandlock) {
6320 return (NFS4ERR_ACCESS);
6321 }
6322
6323 vp = cs->vp;
6324 ASSERT(cr != NULL && vp->v_type == VREG);
6325
6326 /*
6327 * If the file system is exported read only and we are trying
6328 * to open for write, then return NFS4ERR_ROFS
6329 */
6330
6331 readonly = rdonly4(req, cs);
6332
6333 if ((access & OPEN4_SHARE_ACCESS_WRITE) && readonly)
6334 return (NFS4ERR_ROFS);
6335
6336 if (access & OPEN4_SHARE_ACCESS_READ) {
6337 if ((VOP_ACCESS(vp, VREAD, 0, cr, NULL) != 0) &&
6338 (VOP_ACCESS(vp, VEXEC, 0, cr, NULL) != 0)) {
6339 return (NFS4ERR_ACCESS);
6340 }
6341 }
6342
6343 if (access & OPEN4_SHARE_ACCESS_WRITE) {
6344 error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
6345 if (error)
6346 return (NFS4ERR_ACCESS);
6347 }
6348
6349 return (NFS4_OK);
6350 }
6351
6352 static nfsstat4
rfs4_createfile(OPEN4args * args,struct svc_req * req,struct compound_state * cs,change_info4 * cinfo,bitmap4 * attrset,clientid4 clientid)6353 rfs4_createfile(OPEN4args *args, struct svc_req *req, struct compound_state *cs,
6354 change_info4 *cinfo, bitmap4 *attrset, clientid4 clientid)
6355 {
6356 struct nfs4_svgetit_arg sarg;
6357 struct nfs4_ntov_table ntov;
6358
6359 bool_t ntov_table_init = FALSE;
6360 struct statvfs64 sb;
6361 nfsstat4 status;
6362 vnode_t *vp;
6363 vattr_t bva, ava, iva, cva, *vap;
6364 vnode_t *dvp;
6365 timespec32_t *mtime;
6366 char *nm = NULL;
6367 uint_t buflen;
6368 bool_t created;
6369 bool_t setsize = FALSE;
6370 len_t reqsize;
6371 int error;
6372 bool_t trunc;
6373 caller_context_t ct;
6374 component4 *component;
6375 bslabel_t *clabel;
6376 struct sockaddr *ca;
6377 char *name = NULL;
6378
6379 sarg.sbp = &sb;
6380 sarg.is_referral = B_FALSE;
6381
6382 dvp = cs->vp;
6383
6384 /* Check if the file system is read only */
6385 if (rdonly4(req, cs))
6386 return (NFS4ERR_ROFS);
6387
6388 /* check the label of including directory */
6389 if (is_system_labeled()) {
6390 ASSERT(req->rq_label != NULL);
6391 clabel = req->rq_label;
6392 DTRACE_PROBE2(tx__rfs4__log__info__opremove__clabel, char *,
6393 "got client label from request(1)",
6394 struct svc_req *, req);
6395 if (!blequal(&l_admin_low->tsl_label, clabel)) {
6396 if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
6397 cs->exi)) {
6398 return (NFS4ERR_ACCESS);
6399 }
6400 }
6401 }
6402
6403 /*
6404 * Get the last component of path name in nm. cs will reference
6405 * the including directory on success.
6406 */
6407 component = &args->open_claim4_u.file;
6408 status = utf8_dir_verify(component);
6409 if (status != NFS4_OK)
6410 return (status);
6411
6412 nm = utf8_to_fn(component, &buflen, NULL);
6413
6414 if (nm == NULL)
6415 return (NFS4ERR_RESOURCE);
6416
6417 if (buflen > MAXNAMELEN) {
6418 kmem_free(nm, buflen);
6419 return (NFS4ERR_NAMETOOLONG);
6420 }
6421
6422 bva.va_mask = AT_TYPE|AT_CTIME|AT_SEQ;
6423 error = VOP_GETATTR(dvp, &bva, 0, cs->cr, NULL);
6424 if (error) {
6425 kmem_free(nm, buflen);
6426 return (puterrno4(error));
6427 }
6428
6429 if (bva.va_type != VDIR) {
6430 kmem_free(nm, buflen);
6431 return (NFS4ERR_NOTDIR);
6432 }
6433
6434 NFS4_SET_FATTR4_CHANGE(cinfo->before, bva.va_ctime)
6435
6436 switch (args->mode) {
6437 case GUARDED4:
6438 /*FALLTHROUGH*/
6439 case UNCHECKED4:
6440 nfs4_ntov_table_init(&ntov);
6441 ntov_table_init = TRUE;
6442
6443 *attrset = 0;
6444 status = do_rfs4_set_attrs(attrset,
6445 &args->createhow4_u.createattrs,
6446 cs, &sarg, &ntov, NFS4ATTR_SETIT);
6447
6448 if (status == NFS4_OK && (sarg.vap->va_mask & AT_TYPE) &&
6449 sarg.vap->va_type != VREG) {
6450 if (sarg.vap->va_type == VDIR)
6451 status = NFS4ERR_ISDIR;
6452 else if (sarg.vap->va_type == VLNK)
6453 status = NFS4ERR_SYMLINK;
6454 else
6455 status = NFS4ERR_INVAL;
6456 }
6457
6458 if (status != NFS4_OK) {
6459 kmem_free(nm, buflen);
6460 nfs4_ntov_table_free(&ntov, &sarg);
6461 *attrset = 0;
6462 return (status);
6463 }
6464
6465 vap = sarg.vap;
6466 vap->va_type = VREG;
6467 vap->va_mask |= AT_TYPE;
6468
6469 if ((vap->va_mask & AT_MODE) == 0) {
6470 vap->va_mask |= AT_MODE;
6471 vap->va_mode = (mode_t)0600;
6472 }
6473
6474 if (vap->va_mask & AT_SIZE) {
6475
6476 /* Disallow create with a non-zero size */
6477
6478 if ((reqsize = sarg.vap->va_size) != 0) {
6479 kmem_free(nm, buflen);
6480 nfs4_ntov_table_free(&ntov, &sarg);
6481 *attrset = 0;
6482 return (NFS4ERR_INVAL);
6483 }
6484 setsize = TRUE;
6485 }
6486 break;
6487
6488 case EXCLUSIVE4:
6489 /* prohibit EXCL create of named attributes */
6490 if (dvp->v_flag & V_XATTRDIR) {
6491 kmem_free(nm, buflen);
6492 *attrset = 0;
6493 return (NFS4ERR_INVAL);
6494 }
6495
6496 cva.va_mask = AT_TYPE | AT_MTIME | AT_MODE;
6497 cva.va_type = VREG;
6498 /*
6499 * Ensure no time overflows. Assumes underlying
6500 * filesystem supports at least 32 bits.
6501 * Truncate nsec to usec resolution to allow valid
6502 * compares even if the underlying filesystem truncates.
6503 */
6504 mtime = (timespec32_t *)&args->createhow4_u.createverf;
6505 cva.va_mtime.tv_sec = mtime->tv_sec % TIME32_MAX;
6506 cva.va_mtime.tv_nsec = (mtime->tv_nsec / 1000) * 1000;
6507 cva.va_mode = (mode_t)0;
6508 vap = &cva;
6509
6510 /*
6511 * For EXCL create, attrset is set to the server attr
6512 * used to cache the client's verifier.
6513 */
6514 *attrset = FATTR4_TIME_MODIFY_MASK;
6515 break;
6516 }
6517
6518 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
6519 name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
6520 MAXPATHLEN + 1);
6521
6522 if (name == NULL) {
6523 kmem_free(nm, buflen);
6524 return (NFS4ERR_SERVERFAULT);
6525 }
6526
6527 status = create_vnode(dvp, name, vap, args->mode, mtime,
6528 cs->cr, &vp, &created);
6529 if (nm != name)
6530 kmem_free(name, MAXPATHLEN + 1);
6531 kmem_free(nm, buflen);
6532
6533 if (status != NFS4_OK) {
6534 if (ntov_table_init)
6535 nfs4_ntov_table_free(&ntov, &sarg);
6536 *attrset = 0;
6537 return (status);
6538 }
6539
6540 trunc = (setsize && !created);
6541
6542 if (args->mode != EXCLUSIVE4) {
6543 bitmap4 createmask = args->createhow4_u.createattrs.attrmask;
6544
6545 /*
6546 * True verification that object was created with correct
6547 * attrs is impossible. The attrs could have been changed
6548 * immediately after object creation. If attributes did
6549 * not verify, the only recourse for the server is to
6550 * destroy the object. Maybe if some attrs (like gid)
6551 * are set incorrectly, the object should be destroyed;
6552 * however, seems bad as a default policy. Do we really
6553 * want to destroy an object over one of the times not
6554 * verifying correctly? For these reasons, the server
6555 * currently sets bits in attrset for createattrs
6556 * that were set; however, no verification is done.
6557 *
6558 * vmask_to_nmask accounts for vattr bits set on create
6559 * [do_rfs4_set_attrs() only sets resp bits for
6560 * non-vattr/vfs bits.]
6561 * Mask off any bits we set by default so as not to return
6562 * more attrset bits than were requested in createattrs
6563 */
6564 if (created) {
6565 nfs4_vmask_to_nmask(sarg.vap->va_mask, attrset);
6566 *attrset &= createmask;
6567 } else {
6568 /*
6569 * We did not create the vnode (we tried but it
6570 * already existed). In this case, the only createattr
6571 * that the spec allows the server to set is size,
6572 * and even then, it can only be set if it is 0.
6573 */
6574 *attrset = 0;
6575 if (trunc)
6576 *attrset = FATTR4_SIZE_MASK;
6577 }
6578 }
6579 if (ntov_table_init)
6580 nfs4_ntov_table_free(&ntov, &sarg);
6581
6582 /*
6583 * Get the initial "after" sequence number, if it fails,
6584 * set to zero, time to before.
6585 */
6586 iva.va_mask = AT_CTIME|AT_SEQ;
6587 if (VOP_GETATTR(dvp, &iva, 0, cs->cr, NULL)) {
6588 iva.va_seq = 0;
6589 iva.va_ctime = bva.va_ctime;
6590 }
6591
6592 /*
6593 * create_vnode attempts to create the file exclusive,
6594 * if it already exists the VOP_CREATE will fail and
6595 * may not increase va_seq. It is atomic if
6596 * we haven't changed the directory, but if it has changed
6597 * we don't know what changed it.
6598 */
6599 if (!created) {
6600 if (bva.va_seq && iva.va_seq &&
6601 bva.va_seq == iva.va_seq)
6602 cinfo->atomic = TRUE;
6603 else
6604 cinfo->atomic = FALSE;
6605 NFS4_SET_FATTR4_CHANGE(cinfo->after, iva.va_ctime);
6606 } else {
6607 /*
6608 * The entry was created, we need to sync the
6609 * directory metadata.
6610 */
6611 (void) VOP_FSYNC(dvp, 0, cs->cr, NULL);
6612
6613 /*
6614 * Get "after" change value, if it fails, simply return the
6615 * before value.
6616 */
6617 ava.va_mask = AT_CTIME|AT_SEQ;
6618 if (VOP_GETATTR(dvp, &ava, 0, cs->cr, NULL)) {
6619 ava.va_ctime = bva.va_ctime;
6620 ava.va_seq = 0;
6621 }
6622
6623 NFS4_SET_FATTR4_CHANGE(cinfo->after, ava.va_ctime);
6624
6625 /*
6626 * The cinfo->atomic = TRUE only if we have
6627 * non-zero va_seq's, and it has incremented by exactly one
6628 * during the create_vnode and it didn't
6629 * change during the VOP_FSYNC.
6630 */
6631 if (bva.va_seq && iva.va_seq && ava.va_seq &&
6632 iva.va_seq == (bva.va_seq + 1) && iva.va_seq == ava.va_seq)
6633 cinfo->atomic = TRUE;
6634 else
6635 cinfo->atomic = FALSE;
6636 }
6637
6638 /* Check for mandatory locking and that the size gets set. */
6639 cva.va_mask = AT_MODE;
6640 if (setsize)
6641 cva.va_mask |= AT_SIZE;
6642
6643 /* Assume the worst */
6644 cs->mandlock = TRUE;
6645
6646 if (VOP_GETATTR(vp, &cva, 0, cs->cr, NULL) == 0) {
6647 cs->mandlock = MANDLOCK(cs->vp, cva.va_mode);
6648
6649 /*
6650 * Truncate the file if necessary; this would be
6651 * the case for create over an existing file.
6652 */
6653
6654 if (trunc) {
6655 int in_crit = 0;
6656 rfs4_file_t *fp;
6657 bool_t create = FALSE;
6658
6659 /*
6660 * We are writing over an existing file.
6661 * Check to see if we need to recall a delegation.
6662 */
6663 rfs4_hold_deleg_policy();
6664 if ((fp = rfs4_findfile(vp, NULL, &create)) != NULL) {
6665 if (rfs4_check_delegated_byfp(FWRITE, fp,
6666 (reqsize == 0), FALSE, FALSE, &clientid)) {
6667 rfs4_file_rele(fp);
6668 rfs4_rele_deleg_policy();
6669 VN_RELE(vp);
6670 *attrset = 0;
6671 return (NFS4ERR_DELAY);
6672 }
6673 rfs4_file_rele(fp);
6674 }
6675 rfs4_rele_deleg_policy();
6676
6677 if (nbl_need_check(vp)) {
6678 in_crit = 1;
6679
6680 ASSERT(reqsize == 0);
6681
6682 nbl_start_crit(vp, RW_READER);
6683 if (nbl_conflict(vp, NBL_WRITE, 0,
6684 cva.va_size, 0, NULL)) {
6685 in_crit = 0;
6686 nbl_end_crit(vp);
6687 VN_RELE(vp);
6688 *attrset = 0;
6689 return (NFS4ERR_ACCESS);
6690 }
6691 }
6692 ct.cc_sysid = 0;
6693 ct.cc_pid = 0;
6694 ct.cc_caller_id = nfs4_srv_caller_id;
6695 ct.cc_flags = CC_DONTBLOCK;
6696
6697 cva.va_mask = AT_SIZE;
6698 cva.va_size = reqsize;
6699 (void) VOP_SETATTR(vp, &cva, 0, cs->cr, &ct);
6700 if (in_crit)
6701 nbl_end_crit(vp);
6702 }
6703 }
6704
6705 error = makefh4(&cs->fh, vp, cs->exi);
6706
6707 /*
6708 * Force modified data and metadata out to stable storage.
6709 */
6710 (void) VOP_FSYNC(vp, FNODSYNC, cs->cr, NULL);
6711
6712 if (error) {
6713 VN_RELE(vp);
6714 *attrset = 0;
6715 return (puterrno4(error));
6716 }
6717
6718 /* if parent dir is attrdir, set namedattr fh flag */
6719 if (dvp->v_flag & V_XATTRDIR)
6720 set_fh4_flag(&cs->fh, FH4_NAMEDATTR);
6721
6722 if (cs->vp)
6723 VN_RELE(cs->vp);
6724
6725 cs->vp = vp;
6726
6727 /*
6728 * if we did not create the file, we will need to check
6729 * the access bits on the file
6730 */
6731
6732 if (!created) {
6733 if (setsize)
6734 args->share_access |= OPEN4_SHARE_ACCESS_WRITE;
6735 status = check_open_access(args->share_access, cs, req);
6736 if (status != NFS4_OK)
6737 *attrset = 0;
6738 }
6739 return (status);
6740 }
6741
6742 /*ARGSUSED*/
6743 static void
rfs4_do_open(struct compound_state * cs,struct svc_req * req,rfs4_openowner_t * oo,delegreq_t deleg,uint32_t access,uint32_t deny,OPEN4res * resp,int deleg_cur)6744 rfs4_do_open(struct compound_state *cs, struct svc_req *req,
6745 rfs4_openowner_t *oo, delegreq_t deleg,
6746 uint32_t access, uint32_t deny,
6747 OPEN4res *resp, int deleg_cur)
6748 {
6749 /* XXX Currently not using req */
6750 rfs4_state_t *sp;
6751 rfs4_file_t *fp;
6752 bool_t screate = TRUE;
6753 bool_t fcreate = TRUE;
6754 uint32_t open_a, share_a;
6755 uint32_t open_d, share_d;
6756 rfs4_deleg_state_t *dsp;
6757 sysid_t sysid;
6758 nfsstat4 status;
6759 caller_context_t ct;
6760 int fflags = 0;
6761 int recall = 0;
6762 int err;
6763 int first_open;
6764
6765 /* get the file struct and hold a lock on it during initial open */
6766 fp = rfs4_findfile_withlock(cs->vp, &cs->fh, &fcreate);
6767 if (fp == NULL) {
6768 resp->status = NFS4ERR_RESOURCE;
6769 DTRACE_PROBE1(nfss__e__do__open1, nfsstat4, resp->status);
6770 return;
6771 }
6772
6773 sp = rfs4_findstate_by_owner_file(oo, fp, &screate);
6774 if (sp == NULL) {
6775 resp->status = NFS4ERR_RESOURCE;
6776 DTRACE_PROBE1(nfss__e__do__open2, nfsstat4, resp->status);
6777 /* No need to keep any reference */
6778 rw_exit(&fp->rf_file_rwlock);
6779 rfs4_file_rele(fp);
6780 return;
6781 }
6782
6783 /* try to get the sysid before continuing */
6784 if ((status = rfs4_client_sysid(oo->ro_client, &sysid)) != NFS4_OK) {
6785 resp->status = status;
6786 rfs4_file_rele(fp);
6787 /* Not a fully formed open; "close" it */
6788 if (screate == TRUE)
6789 rfs4_state_close(sp, FALSE, FALSE, cs->cr);
6790 rfs4_state_rele(sp);
6791 return;
6792 }
6793
6794 /* Calculate the fflags for this OPEN. */
6795 if (access & OPEN4_SHARE_ACCESS_READ)
6796 fflags |= FREAD;
6797 if (access & OPEN4_SHARE_ACCESS_WRITE)
6798 fflags |= FWRITE;
6799
6800 rfs4_dbe_lock(sp->rs_dbe);
6801
6802 /*
6803 * Calculate the new deny and access mode that this open is adding to
6804 * the file for this open owner;
6805 */
6806 open_d = (deny & ~sp->rs_open_deny);
6807 open_a = (access & ~sp->rs_open_access);
6808
6809 /*
6810 * Calculate the new share access and share deny modes that this open
6811 * is adding to the file for this open owner;
6812 */
6813 share_a = (access & ~sp->rs_share_access);
6814 share_d = (deny & ~sp->rs_share_deny);
6815
6816 first_open = (sp->rs_open_access & OPEN4_SHARE_ACCESS_BOTH) == 0;
6817
6818 /*
6819 * Check to see the client has already sent an open for this
6820 * open owner on this file with the same share/deny modes.
6821 * If so, we don't need to check for a conflict and we don't
6822 * need to add another shrlock. If not, then we need to
6823 * check for conflicts in deny and access before checking for
6824 * conflicts in delegation. We don't want to recall a
6825 * delegation based on an open that will eventually fail based
6826 * on shares modes.
6827 */
6828
6829 if (share_a || share_d) {
6830 if ((err = rfs4_share(sp, access, deny)) != 0) {
6831 rfs4_dbe_unlock(sp->rs_dbe);
6832 resp->status = err;
6833
6834 rfs4_file_rele(fp);
6835 /* Not a fully formed open; "close" it */
6836 if (screate == TRUE)
6837 rfs4_state_close(sp, FALSE, FALSE, cs->cr);
6838 rfs4_state_rele(sp);
6839 return;
6840 }
6841 }
6842
6843 rfs4_dbe_lock(fp->rf_dbe);
6844
6845 /*
6846 * Check to see if this file is delegated and if so, if a
6847 * recall needs to be done.
6848 */
6849 if (rfs4_check_recall(sp, access)) {
6850 rfs4_dbe_unlock(fp->rf_dbe);
6851 rfs4_dbe_unlock(sp->rs_dbe);
6852 rfs4_recall_deleg(fp, FALSE, sp->rs_owner->ro_client);
6853 delay(NFS4_DELEGATION_CONFLICT_DELAY);
6854 rfs4_dbe_lock(sp->rs_dbe);
6855
6856 /* if state closed while lock was dropped */
6857 if (sp->rs_closed) {
6858 if (share_a || share_d)
6859 (void) rfs4_unshare(sp);
6860 rfs4_dbe_unlock(sp->rs_dbe);
6861 rfs4_file_rele(fp);
6862 /* Not a fully formed open; "close" it */
6863 if (screate == TRUE)
6864 rfs4_state_close(sp, FALSE, FALSE, cs->cr);
6865 rfs4_state_rele(sp);
6866 resp->status = NFS4ERR_OLD_STATEID;
6867 return;
6868 }
6869
6870 rfs4_dbe_lock(fp->rf_dbe);
6871 /* Let's see if the delegation was returned */
6872 if (rfs4_check_recall(sp, access)) {
6873 rfs4_dbe_unlock(fp->rf_dbe);
6874 if (share_a || share_d)
6875 (void) rfs4_unshare(sp);
6876 rfs4_dbe_unlock(sp->rs_dbe);
6877 rfs4_file_rele(fp);
6878 rfs4_update_lease(sp->rs_owner->ro_client);
6879
6880 /* Not a fully formed open; "close" it */
6881 if (screate == TRUE)
6882 rfs4_state_close(sp, FALSE, FALSE, cs->cr);
6883 rfs4_state_rele(sp);
6884 resp->status = NFS4ERR_DELAY;
6885 return;
6886 }
6887 }
6888 /*
6889 * the share check passed and any delegation conflict has been
6890 * taken care of, now call vop_open.
6891 * if this is the first open then call vop_open with fflags.
6892 * if not, call vn_open_upgrade with just the upgrade flags.
6893 *
6894 * if the file has been opened already, it will have the current
6895 * access mode in the state struct. if it has no share access, then
6896 * this is a new open.
6897 *
6898 * However, if this is open with CLAIM_DLEGATE_CUR, then don't
6899 * call VOP_OPEN(), just do the open upgrade.
6900 */
6901 if (first_open && !deleg_cur) {
6902 ct.cc_sysid = sysid;
6903 ct.cc_pid = rfs4_dbe_getid(sp->rs_owner->ro_dbe);
6904 ct.cc_caller_id = nfs4_srv_caller_id;
6905 ct.cc_flags = CC_DONTBLOCK;
6906 err = VOP_OPEN(&cs->vp, fflags, cs->cr, &ct);
6907 if (err) {
6908 rfs4_dbe_unlock(fp->rf_dbe);
6909 if (share_a || share_d)
6910 (void) rfs4_unshare(sp);
6911 rfs4_dbe_unlock(sp->rs_dbe);
6912 rfs4_file_rele(fp);
6913
6914 /* Not a fully formed open; "close" it */
6915 if (screate == TRUE)
6916 rfs4_state_close(sp, FALSE, FALSE, cs->cr);
6917 rfs4_state_rele(sp);
6918 /* check if a monitor detected a delegation conflict */
6919 if (err == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK))
6920 resp->status = NFS4ERR_DELAY;
6921 else
6922 resp->status = NFS4ERR_SERVERFAULT;
6923 return;
6924 }
6925 } else { /* open upgrade */
6926 /*
6927 * calculate the fflags for the new mode that is being added
6928 * by this upgrade.
6929 */
6930 fflags = 0;
6931 if (open_a & OPEN4_SHARE_ACCESS_READ)
6932 fflags |= FREAD;
6933 if (open_a & OPEN4_SHARE_ACCESS_WRITE)
6934 fflags |= FWRITE;
6935 vn_open_upgrade(cs->vp, fflags);
6936 }
6937 sp->rs_open_access |= access;
6938 sp->rs_open_deny |= deny;
6939
6940 if (open_d & OPEN4_SHARE_DENY_READ)
6941 fp->rf_deny_read++;
6942 if (open_d & OPEN4_SHARE_DENY_WRITE)
6943 fp->rf_deny_write++;
6944 fp->rf_share_deny |= deny;
6945
6946 if (open_a & OPEN4_SHARE_ACCESS_READ)
6947 fp->rf_access_read++;
6948 if (open_a & OPEN4_SHARE_ACCESS_WRITE)
6949 fp->rf_access_write++;
6950 fp->rf_share_access |= access;
6951
6952 /*
6953 * Check for delegation here. if the deleg argument is not
6954 * DELEG_ANY, then this is a reclaim from a client and
6955 * we must honor the delegation requested. If necessary we can
6956 * set the recall flag.
6957 */
6958
6959 dsp = rfs4_grant_delegation(deleg, sp, &recall);
6960
6961 cs->deleg = (fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_WRITE);
6962
6963 next_stateid(&sp->rs_stateid);
6964
6965 resp->stateid = sp->rs_stateid.stateid;
6966
6967 rfs4_dbe_unlock(fp->rf_dbe);
6968 rfs4_dbe_unlock(sp->rs_dbe);
6969
6970 if (dsp) {
6971 rfs4_set_deleg_response(dsp, &resp->delegation, NULL, recall);
6972 rfs4_deleg_state_rele(dsp);
6973 }
6974
6975 rfs4_file_rele(fp);
6976 rfs4_state_rele(sp);
6977
6978 resp->status = NFS4_OK;
6979 }
6980
6981 /*ARGSUSED*/
6982 static void
rfs4_do_opennull(struct compound_state * cs,struct svc_req * req,OPEN4args * args,rfs4_openowner_t * oo,OPEN4res * resp)6983 rfs4_do_opennull(struct compound_state *cs, struct svc_req *req,
6984 OPEN4args *args, rfs4_openowner_t *oo, OPEN4res *resp)
6985 {
6986 change_info4 *cinfo = &resp->cinfo;
6987 bitmap4 *attrset = &resp->attrset;
6988
6989 if (args->opentype == OPEN4_NOCREATE)
6990 resp->status = rfs4_lookupfile(&args->open_claim4_u.file,
6991 req, cs, args->share_access, cinfo);
6992 else {
6993 /* inhibit delegation grants during exclusive create */
6994
6995 if (args->mode == EXCLUSIVE4)
6996 rfs4_disable_delegation();
6997
6998 resp->status = rfs4_createfile(args, req, cs, cinfo, attrset,
6999 oo->ro_client->rc_clientid);
7000 }
7001
7002 if (resp->status == NFS4_OK) {
7003
7004 /* cs->vp cs->fh now reference the desired file */
7005
7006 rfs4_do_open(cs, req, oo,
7007 oo->ro_need_confirm ? DELEG_NONE : DELEG_ANY,
7008 args->share_access, args->share_deny, resp, 0);
7009
7010 /*
7011 * If rfs4_createfile set attrset, we must
7012 * clear this attrset before the response is copied.
7013 */
7014 if (resp->status != NFS4_OK && resp->attrset) {
7015 resp->attrset = 0;
7016 }
7017 }
7018 else
7019 *cs->statusp = resp->status;
7020
7021 if (args->mode == EXCLUSIVE4)
7022 rfs4_enable_delegation();
7023 }
7024
7025 /*ARGSUSED*/
7026 static void
rfs4_do_openprev(struct compound_state * cs,struct svc_req * req,OPEN4args * args,rfs4_openowner_t * oo,OPEN4res * resp)7027 rfs4_do_openprev(struct compound_state *cs, struct svc_req *req,
7028 OPEN4args *args, rfs4_openowner_t *oo, OPEN4res *resp)
7029 {
7030 change_info4 *cinfo = &resp->cinfo;
7031 vattr_t va;
7032 vtype_t v_type = cs->vp->v_type;
7033 int error = 0;
7034
7035 /* Verify that we have a regular file */
7036 if (v_type != VREG) {
7037 if (v_type == VDIR)
7038 resp->status = NFS4ERR_ISDIR;
7039 else if (v_type == VLNK)
7040 resp->status = NFS4ERR_SYMLINK;
7041 else
7042 resp->status = NFS4ERR_INVAL;
7043 return;
7044 }
7045
7046 va.va_mask = AT_MODE|AT_UID;
7047 error = VOP_GETATTR(cs->vp, &va, 0, cs->cr, NULL);
7048 if (error) {
7049 resp->status = puterrno4(error);
7050 return;
7051 }
7052
7053 cs->mandlock = MANDLOCK(cs->vp, va.va_mode);
7054
7055 /*
7056 * Check if we have access to the file, Note the the file
7057 * could have originally been open UNCHECKED or GUARDED
7058 * with mode bits that will now fail, but there is nothing
7059 * we can really do about that except in the case that the
7060 * owner of the file is the one requesting the open.
7061 */
7062 if (crgetuid(cs->cr) != va.va_uid) {
7063 resp->status = check_open_access(args->share_access, cs, req);
7064 if (resp->status != NFS4_OK) {
7065 return;
7066 }
7067 }
7068
7069 /*
7070 * cinfo on a CLAIM_PREVIOUS is undefined, initialize to zero
7071 */
7072 cinfo->before = 0;
7073 cinfo->after = 0;
7074 cinfo->atomic = FALSE;
7075
7076 rfs4_do_open(cs, req, oo,
7077 NFS4_DELEG4TYPE2REQTYPE(args->open_claim4_u.delegate_type),
7078 args->share_access, args->share_deny, resp, 0);
7079 }
7080
7081 static void
rfs4_do_opendelcur(struct compound_state * cs,struct svc_req * req,OPEN4args * args,rfs4_openowner_t * oo,OPEN4res * resp)7082 rfs4_do_opendelcur(struct compound_state *cs, struct svc_req *req,
7083 OPEN4args *args, rfs4_openowner_t *oo, OPEN4res *resp)
7084 {
7085 int error;
7086 nfsstat4 status;
7087 stateid4 stateid =
7088 args->open_claim4_u.delegate_cur_info.delegate_stateid;
7089 rfs4_deleg_state_t *dsp;
7090
7091 /*
7092 * Find the state info from the stateid and confirm that the
7093 * file is delegated. If the state openowner is the same as
7094 * the supplied openowner we're done. If not, get the file
7095 * info from the found state info. Use that file info to
7096 * create the state for this lock owner. Note solaris doen't
7097 * really need the pathname to find the file. We may want to
7098 * lookup the pathname and make sure that the vp exist and
7099 * matches the vp in the file structure. However it is
7100 * possible that the pathname nolonger exists (local process
7101 * unlinks the file), so this may not be that useful.
7102 */
7103
7104 status = rfs4_get_deleg_state(&stateid, &dsp);
7105 if (status != NFS4_OK) {
7106 resp->status = status;
7107 return;
7108 }
7109
7110 ASSERT(dsp->rds_finfo->rf_dinfo.rd_dtype != OPEN_DELEGATE_NONE);
7111
7112 /*
7113 * New lock owner, create state. Since this was probably called
7114 * in response to a CB_RECALL we set deleg to DELEG_NONE
7115 */
7116
7117 ASSERT(cs->vp != NULL);
7118 VN_RELE(cs->vp);
7119 VN_HOLD(dsp->rds_finfo->rf_vp);
7120 cs->vp = dsp->rds_finfo->rf_vp;
7121
7122 if (error = makefh4(&cs->fh, cs->vp, cs->exi)) {
7123 rfs4_deleg_state_rele(dsp);
7124 *cs->statusp = resp->status = puterrno4(error);
7125 return;
7126 }
7127
7128 /* Mark progress for delegation returns */
7129 dsp->rds_finfo->rf_dinfo.rd_time_lastwrite = gethrestime_sec();
7130 rfs4_deleg_state_rele(dsp);
7131 rfs4_do_open(cs, req, oo, DELEG_NONE,
7132 args->share_access, args->share_deny, resp, 1);
7133 }
7134
7135 /*ARGSUSED*/
7136 static void
rfs4_do_opendelprev(struct compound_state * cs,struct svc_req * req,OPEN4args * args,rfs4_openowner_t * oo,OPEN4res * resp)7137 rfs4_do_opendelprev(struct compound_state *cs, struct svc_req *req,
7138 OPEN4args *args, rfs4_openowner_t *oo, OPEN4res *resp)
7139 {
7140 /*
7141 * Lookup the pathname, it must already exist since this file
7142 * was delegated.
7143 *
7144 * Find the file and state info for this vp and open owner pair.
7145 * check that they are in fact delegated.
7146 * check that the state access and deny modes are the same.
7147 *
7148 * Return the delgation possibly seting the recall flag.
7149 */
7150 rfs4_file_t *fp;
7151 rfs4_state_t *sp;
7152 bool_t create = FALSE;
7153 bool_t dcreate = FALSE;
7154 rfs4_deleg_state_t *dsp;
7155 nfsace4 *ace;
7156
7157 /* Note we ignore oflags */
7158 resp->status = rfs4_lookupfile(&args->open_claim4_u.file_delegate_prev,
7159 req, cs, args->share_access, &resp->cinfo);
7160
7161 if (resp->status != NFS4_OK) {
7162 return;
7163 }
7164
7165 /* get the file struct and hold a lock on it during initial open */
7166 fp = rfs4_findfile_withlock(cs->vp, NULL, &create);
7167 if (fp == NULL) {
7168 resp->status = NFS4ERR_RESOURCE;
7169 DTRACE_PROBE1(nfss__e__do_opendelprev1, nfsstat4, resp->status);
7170 return;
7171 }
7172
7173 sp = rfs4_findstate_by_owner_file(oo, fp, &create);
7174 if (sp == NULL) {
7175 resp->status = NFS4ERR_SERVERFAULT;
7176 DTRACE_PROBE1(nfss__e__do_opendelprev2, nfsstat4, resp->status);
7177 rw_exit(&fp->rf_file_rwlock);
7178 rfs4_file_rele(fp);
7179 return;
7180 }
7181
7182 rfs4_dbe_lock(sp->rs_dbe);
7183 rfs4_dbe_lock(fp->rf_dbe);
7184 if (args->share_access != sp->rs_share_access ||
7185 args->share_deny != sp->rs_share_deny ||
7186 sp->rs_finfo->rf_dinfo.rd_dtype == OPEN_DELEGATE_NONE) {
7187 NFS4_DEBUG(rfs4_debug,
7188 (CE_NOTE, "rfs4_do_opendelprev: state mixup"));
7189 rfs4_dbe_unlock(fp->rf_dbe);
7190 rfs4_dbe_unlock(sp->rs_dbe);
7191 rfs4_file_rele(fp);
7192 rfs4_state_rele(sp);
7193 resp->status = NFS4ERR_SERVERFAULT;
7194 return;
7195 }
7196 rfs4_dbe_unlock(fp->rf_dbe);
7197 rfs4_dbe_unlock(sp->rs_dbe);
7198
7199 dsp = rfs4_finddeleg(sp, &dcreate);
7200 if (dsp == NULL) {
7201 rfs4_state_rele(sp);
7202 rfs4_file_rele(fp);
7203 resp->status = NFS4ERR_SERVERFAULT;
7204 return;
7205 }
7206
7207 next_stateid(&sp->rs_stateid);
7208
7209 resp->stateid = sp->rs_stateid.stateid;
7210
7211 resp->delegation.delegation_type = dsp->rds_dtype;
7212
7213 if (dsp->rds_dtype == OPEN_DELEGATE_READ) {
7214 open_read_delegation4 *rv =
7215 &resp->delegation.open_delegation4_u.read;
7216
7217 rv->stateid = dsp->rds_delegid.stateid;
7218 rv->recall = FALSE; /* no policy in place to set to TRUE */
7219 ace = &rv->permissions;
7220 } else {
7221 open_write_delegation4 *rv =
7222 &resp->delegation.open_delegation4_u.write;
7223
7224 rv->stateid = dsp->rds_delegid.stateid;
7225 rv->recall = FALSE; /* no policy in place to set to TRUE */
7226 ace = &rv->permissions;
7227 rv->space_limit.limitby = NFS_LIMIT_SIZE;
7228 rv->space_limit.nfs_space_limit4_u.filesize = UINT64_MAX;
7229 }
7230
7231 /* XXX For now */
7232 ace->type = ACE4_ACCESS_ALLOWED_ACE_TYPE;
7233 ace->flag = 0;
7234 ace->access_mask = 0;
7235 ace->who.utf8string_len = 0;
7236 ace->who.utf8string_val = 0;
7237
7238 rfs4_deleg_state_rele(dsp);
7239 rfs4_state_rele(sp);
7240 rfs4_file_rele(fp);
7241 }
7242
7243 typedef enum {
7244 NFS4_CHKSEQ_OKAY = 0,
7245 NFS4_CHKSEQ_REPLAY = 1,
7246 NFS4_CHKSEQ_BAD = 2
7247 } rfs4_chkseq_t;
7248
7249 /*
7250 * Generic function for sequence number checks.
7251 */
7252 static rfs4_chkseq_t
rfs4_check_seqid(seqid4 seqid,nfs_resop4 * lastop,seqid4 rqst_seq,nfs_resop4 * resop,bool_t copyres)7253 rfs4_check_seqid(seqid4 seqid, nfs_resop4 *lastop,
7254 seqid4 rqst_seq, nfs_resop4 *resop, bool_t copyres)
7255 {
7256 /* Same sequence ids and matching operations? */
7257 if (seqid == rqst_seq && resop->resop == lastop->resop) {
7258 if (copyres == TRUE) {
7259 rfs4_free_reply(resop);
7260 rfs4_copy_reply(resop, lastop);
7261 }
7262 NFS4_DEBUG(rfs4_debug, (CE_NOTE,
7263 "Replayed SEQID %d\n", seqid));
7264 return (NFS4_CHKSEQ_REPLAY);
7265 }
7266
7267 /* If the incoming sequence is not the next expected then it is bad */
7268 if (rqst_seq != seqid + 1) {
7269 if (rqst_seq == seqid) {
7270 NFS4_DEBUG(rfs4_debug,
7271 (CE_NOTE, "BAD SEQID: Replayed sequence id "
7272 "but last op was %d current op is %d\n",
7273 lastop->resop, resop->resop));
7274 return (NFS4_CHKSEQ_BAD);
7275 }
7276 NFS4_DEBUG(rfs4_debug,
7277 (CE_NOTE, "BAD SEQID: got %u expecting %u\n",
7278 rqst_seq, seqid));
7279 return (NFS4_CHKSEQ_BAD);
7280 }
7281
7282 /* Everything okay -- next expected */
7283 return (NFS4_CHKSEQ_OKAY);
7284 }
7285
7286
7287 static rfs4_chkseq_t
rfs4_check_open_seqid(seqid4 seqid,rfs4_openowner_t * op,nfs_resop4 * resop)7288 rfs4_check_open_seqid(seqid4 seqid, rfs4_openowner_t *op, nfs_resop4 *resop)
7289 {
7290 rfs4_chkseq_t rc;
7291
7292 rfs4_dbe_lock(op->ro_dbe);
7293 rc = rfs4_check_seqid(op->ro_open_seqid, &op->ro_reply, seqid, resop,
7294 TRUE);
7295 rfs4_dbe_unlock(op->ro_dbe);
7296
7297 if (rc == NFS4_CHKSEQ_OKAY)
7298 rfs4_update_lease(op->ro_client);
7299
7300 return (rc);
7301 }
7302
7303 static rfs4_chkseq_t
rfs4_check_olo_seqid(seqid4 olo_seqid,rfs4_openowner_t * op,nfs_resop4 * resop)7304 rfs4_check_olo_seqid(seqid4 olo_seqid, rfs4_openowner_t *op, nfs_resop4 *resop)
7305 {
7306 rfs4_chkseq_t rc;
7307
7308 rfs4_dbe_lock(op->ro_dbe);
7309 rc = rfs4_check_seqid(op->ro_open_seqid, &op->ro_reply,
7310 olo_seqid, resop, FALSE);
7311 rfs4_dbe_unlock(op->ro_dbe);
7312
7313 return (rc);
7314 }
7315
7316 static rfs4_chkseq_t
rfs4_check_lock_seqid(seqid4 seqid,rfs4_lo_state_t * lsp,nfs_resop4 * resop)7317 rfs4_check_lock_seqid(seqid4 seqid, rfs4_lo_state_t *lsp, nfs_resop4 *resop)
7318 {
7319 rfs4_chkseq_t rc = NFS4_CHKSEQ_OKAY;
7320
7321 rfs4_dbe_lock(lsp->rls_dbe);
7322 if (!lsp->rls_skip_seqid_check)
7323 rc = rfs4_check_seqid(lsp->rls_seqid, &lsp->rls_reply, seqid,
7324 resop, TRUE);
7325 rfs4_dbe_unlock(lsp->rls_dbe);
7326
7327 return (rc);
7328 }
7329
7330 static void
rfs4_op_open(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)7331 rfs4_op_open(nfs_argop4 *argop, nfs_resop4 *resop,
7332 struct svc_req *req, struct compound_state *cs)
7333 {
7334 OPEN4args *args = &argop->nfs_argop4_u.opopen;
7335 OPEN4res *resp = &resop->nfs_resop4_u.opopen;
7336 open_owner4 *owner = &args->owner;
7337 open_claim_type4 claim = args->claim;
7338 rfs4_client_t *cp;
7339 rfs4_openowner_t *oo;
7340 bool_t create;
7341 bool_t replay = FALSE;
7342 int can_reclaim;
7343
7344 DTRACE_NFSV4_2(op__open__start, struct compound_state *, cs,
7345 OPEN4args *, args);
7346
7347 if (cs->vp == NULL) {
7348 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
7349 goto end;
7350 }
7351
7352 /*
7353 * Need to check clientid and lease expiration first based on
7354 * error ordering and incrementing sequence id.
7355 */
7356 cp = rfs4_findclient_by_id(owner->clientid, FALSE);
7357 if (cp == NULL) {
7358 *cs->statusp = resp->status =
7359 rfs4_check_clientid(&owner->clientid, 0);
7360 goto end;
7361 }
7362
7363 if (rfs4_lease_expired(cp)) {
7364 rfs4_client_close(cp);
7365 *cs->statusp = resp->status = NFS4ERR_EXPIRED;
7366 goto end;
7367 }
7368 can_reclaim = cp->rc_can_reclaim;
7369
7370 /*
7371 * Find the open_owner for use from this point forward. Take
7372 * care in updating the sequence id based on the type of error
7373 * being returned.
7374 */
7375 retry:
7376 create = TRUE;
7377 oo = rfs4_findopenowner(owner, &create, args->seqid);
7378 if (oo == NULL) {
7379 *cs->statusp = resp->status = NFS4ERR_RESOURCE;
7380 rfs4_client_rele(cp);
7381 goto end;
7382 }
7383
7384 /* Hold off access to the sequence space while the open is done */
7385 rfs4_sw_enter(&oo->ro_sw);
7386
7387 /*
7388 * If the open_owner existed before at the server, then check
7389 * the sequence id.
7390 */
7391 if (!create && !oo->ro_postpone_confirm) {
7392 switch (rfs4_check_open_seqid(args->seqid, oo, resop)) {
7393 case NFS4_CHKSEQ_BAD:
7394 if ((args->seqid > oo->ro_open_seqid) &&
7395 oo->ro_need_confirm) {
7396 rfs4_free_opens(oo, TRUE, FALSE);
7397 rfs4_sw_exit(&oo->ro_sw);
7398 rfs4_openowner_rele(oo);
7399 goto retry;
7400 }
7401 resp->status = NFS4ERR_BAD_SEQID;
7402 goto out;
7403 case NFS4_CHKSEQ_REPLAY: /* replay of previous request */
7404 replay = TRUE;
7405 goto out;
7406 default:
7407 break;
7408 }
7409
7410 /*
7411 * Sequence was ok and open owner exists
7412 * check to see if we have yet to see an
7413 * open_confirm.
7414 */
7415 if (oo->ro_need_confirm) {
7416 rfs4_free_opens(oo, TRUE, FALSE);
7417 rfs4_sw_exit(&oo->ro_sw);
7418 rfs4_openowner_rele(oo);
7419 goto retry;
7420 }
7421 }
7422 /* Grace only applies to regular-type OPENs */
7423 if (rfs4_clnt_in_grace(cp) &&
7424 (claim == CLAIM_NULL || claim == CLAIM_DELEGATE_CUR)) {
7425 *cs->statusp = resp->status = NFS4ERR_GRACE;
7426 goto out;
7427 }
7428
7429 /*
7430 * If previous state at the server existed then can_reclaim
7431 * will be set. If not reply NFS4ERR_NO_GRACE to the
7432 * client.
7433 */
7434 if (rfs4_clnt_in_grace(cp) && claim == CLAIM_PREVIOUS && !can_reclaim) {
7435 *cs->statusp = resp->status = NFS4ERR_NO_GRACE;
7436 goto out;
7437 }
7438
7439
7440 /*
7441 * Reject the open if the client has missed the grace period
7442 */
7443 if (!rfs4_clnt_in_grace(cp) && claim == CLAIM_PREVIOUS) {
7444 *cs->statusp = resp->status = NFS4ERR_NO_GRACE;
7445 goto out;
7446 }
7447
7448 /* Couple of up-front bookkeeping items */
7449 if (oo->ro_need_confirm) {
7450 /*
7451 * If this is a reclaim OPEN then we should not ask
7452 * for a confirmation of the open_owner per the
7453 * protocol specification.
7454 */
7455 if (claim == CLAIM_PREVIOUS)
7456 oo->ro_need_confirm = FALSE;
7457 else
7458 resp->rflags |= OPEN4_RESULT_CONFIRM;
7459 }
7460 resp->rflags |= OPEN4_RESULT_LOCKTYPE_POSIX;
7461
7462 /*
7463 * If there is an unshared filesystem mounted on this vnode,
7464 * do not allow to open/create in this directory.
7465 */
7466 if (vn_ismntpt(cs->vp)) {
7467 *cs->statusp = resp->status = NFS4ERR_ACCESS;
7468 goto out;
7469 }
7470
7471 /*
7472 * access must READ, WRITE, or BOTH. No access is invalid.
7473 * deny can be READ, WRITE, BOTH, or NONE.
7474 * bits not defined for access/deny are invalid.
7475 */
7476 if (! (args->share_access & OPEN4_SHARE_ACCESS_BOTH) ||
7477 (args->share_access & ~OPEN4_SHARE_ACCESS_BOTH) ||
7478 (args->share_deny & ~OPEN4_SHARE_DENY_BOTH)) {
7479 *cs->statusp = resp->status = NFS4ERR_INVAL;
7480 goto out;
7481 }
7482
7483
7484 /*
7485 * make sure attrset is zero before response is built.
7486 */
7487 resp->attrset = 0;
7488
7489 switch (claim) {
7490 case CLAIM_NULL:
7491 rfs4_do_opennull(cs, req, args, oo, resp);
7492 break;
7493 case CLAIM_PREVIOUS:
7494 rfs4_do_openprev(cs, req, args, oo, resp);
7495 break;
7496 case CLAIM_DELEGATE_CUR:
7497 rfs4_do_opendelcur(cs, req, args, oo, resp);
7498 break;
7499 case CLAIM_DELEGATE_PREV:
7500 rfs4_do_opendelprev(cs, req, args, oo, resp);
7501 break;
7502 default:
7503 resp->status = NFS4ERR_INVAL;
7504 break;
7505 }
7506
7507 out:
7508 rfs4_client_rele(cp);
7509
7510 /* Catch sequence id handling here to make it a little easier */
7511 switch (resp->status) {
7512 case NFS4ERR_BADXDR:
7513 case NFS4ERR_BAD_SEQID:
7514 case NFS4ERR_BAD_STATEID:
7515 case NFS4ERR_NOFILEHANDLE:
7516 case NFS4ERR_RESOURCE:
7517 case NFS4ERR_STALE_CLIENTID:
7518 case NFS4ERR_STALE_STATEID:
7519 /*
7520 * The protocol states that if any of these errors are
7521 * being returned, the sequence id should not be
7522 * incremented. Any other return requires an
7523 * increment.
7524 */
7525 break;
7526 default:
7527 /* Always update the lease in this case */
7528 rfs4_update_lease(oo->ro_client);
7529
7530 /* Regular response - copy the result */
7531 if (!replay)
7532 rfs4_update_open_resp(oo, resop, &cs->fh);
7533
7534 /*
7535 * REPLAY case: Only if the previous response was OK
7536 * do we copy the filehandle. If not OK, no
7537 * filehandle to copy.
7538 */
7539 if (replay == TRUE &&
7540 resp->status == NFS4_OK &&
7541 oo->ro_reply_fh.nfs_fh4_val) {
7542 /*
7543 * If this is a replay, we must restore the
7544 * current filehandle/vp to that of what was
7545 * returned originally. Try our best to do
7546 * it.
7547 */
7548 nfs_fh4_fmt_t *fh_fmtp =
7549 (nfs_fh4_fmt_t *)oo->ro_reply_fh.nfs_fh4_val;
7550
7551 if (cs->exi != NULL)
7552 exi_rele(cs->exi);
7553 cs->exi = checkexport(&fh_fmtp->fh4_fsid,
7554 (fid_t *)&fh_fmtp->fh4_xlen, NULL);
7555
7556 if (cs->exi == NULL) {
7557 resp->status = NFS4ERR_STALE;
7558 goto finish;
7559 }
7560
7561 VN_RELE(cs->vp);
7562
7563 cs->vp = nfs4_fhtovp(&oo->ro_reply_fh, cs->exi,
7564 &resp->status);
7565
7566 if (cs->vp == NULL)
7567 goto finish;
7568
7569 nfs_fh4_copy(&oo->ro_reply_fh, &cs->fh);
7570 }
7571
7572 /*
7573 * If this was a replay, no need to update the
7574 * sequence id. If the open_owner was not created on
7575 * this pass, then update. The first use of an
7576 * open_owner will not bump the sequence id.
7577 */
7578 if (replay == FALSE && !create)
7579 rfs4_update_open_sequence(oo);
7580 /*
7581 * If the client is receiving an error and the
7582 * open_owner needs to be confirmed, there is no way
7583 * to notify the client of this fact ignoring the fact
7584 * that the server has no method of returning a
7585 * stateid to confirm. Therefore, the server needs to
7586 * mark this open_owner in a way as to avoid the
7587 * sequence id checking the next time the client uses
7588 * this open_owner.
7589 */
7590 if (resp->status != NFS4_OK && oo->ro_need_confirm)
7591 oo->ro_postpone_confirm = TRUE;
7592 /*
7593 * If OK response then clear the postpone flag and
7594 * reset the sequence id to keep in sync with the
7595 * client.
7596 */
7597 if (resp->status == NFS4_OK && oo->ro_postpone_confirm) {
7598 oo->ro_postpone_confirm = FALSE;
7599 oo->ro_open_seqid = args->seqid;
7600 }
7601 break;
7602 }
7603
7604 finish:
7605 *cs->statusp = resp->status;
7606
7607 rfs4_sw_exit(&oo->ro_sw);
7608 rfs4_openowner_rele(oo);
7609
7610 end:
7611 DTRACE_NFSV4_2(op__open__done, struct compound_state *, cs,
7612 OPEN4res *, resp);
7613 }
7614
7615 /*ARGSUSED*/
7616 void
rfs4_op_open_confirm(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)7617 rfs4_op_open_confirm(nfs_argop4 *argop, nfs_resop4 *resop,
7618 struct svc_req *req, struct compound_state *cs)
7619 {
7620 OPEN_CONFIRM4args *args = &argop->nfs_argop4_u.opopen_confirm;
7621 OPEN_CONFIRM4res *resp = &resop->nfs_resop4_u.opopen_confirm;
7622 rfs4_state_t *sp;
7623 nfsstat4 status;
7624
7625 DTRACE_NFSV4_2(op__open__confirm__start, struct compound_state *, cs,
7626 OPEN_CONFIRM4args *, args);
7627
7628 if (cs->vp == NULL) {
7629 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
7630 goto out;
7631 }
7632
7633 if (cs->vp->v_type != VREG) {
7634 *cs->statusp = resp->status =
7635 cs->vp->v_type == VDIR ? NFS4ERR_ISDIR : NFS4ERR_INVAL;
7636 return;
7637 }
7638
7639 status = rfs4_get_state(&args->open_stateid, &sp, RFS4_DBS_VALID);
7640 if (status != NFS4_OK) {
7641 *cs->statusp = resp->status = status;
7642 goto out;
7643 }
7644
7645 /* Ensure specified filehandle matches */
7646 if (cs->vp != sp->rs_finfo->rf_vp) {
7647 rfs4_state_rele(sp);
7648 *cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
7649 goto out;
7650 }
7651
7652 /* hold off other access to open_owner while we tinker */
7653 rfs4_sw_enter(&sp->rs_owner->ro_sw);
7654
7655 switch (rfs4_check_stateid_seqid(sp, &args->open_stateid)) {
7656 case NFS4_CHECK_STATEID_OKAY:
7657 if (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
7658 resop) != 0) {
7659 *cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
7660 break;
7661 }
7662 /*
7663 * If it is the appropriate stateid and determined to
7664 * be "OKAY" then this means that the stateid does not
7665 * need to be confirmed and the client is in error for
7666 * sending an OPEN_CONFIRM.
7667 */
7668 *cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
7669 break;
7670 case NFS4_CHECK_STATEID_OLD:
7671 *cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
7672 break;
7673 case NFS4_CHECK_STATEID_BAD:
7674 *cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
7675 break;
7676 case NFS4_CHECK_STATEID_EXPIRED:
7677 *cs->statusp = resp->status = NFS4ERR_EXPIRED;
7678 break;
7679 case NFS4_CHECK_STATEID_CLOSED:
7680 *cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
7681 break;
7682 case NFS4_CHECK_STATEID_REPLAY:
7683 switch (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
7684 resop)) {
7685 case NFS4_CHKSEQ_OKAY:
7686 /*
7687 * This is replayed stateid; if seqid matches
7688 * next expected, then client is using wrong seqid.
7689 */
7690 /* fall through */
7691 case NFS4_CHKSEQ_BAD:
7692 *cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
7693 break;
7694 case NFS4_CHKSEQ_REPLAY:
7695 /*
7696 * Note this case is the duplicate case so
7697 * resp->status is already set.
7698 */
7699 *cs->statusp = resp->status;
7700 rfs4_update_lease(sp->rs_owner->ro_client);
7701 break;
7702 }
7703 break;
7704 case NFS4_CHECK_STATEID_UNCONFIRMED:
7705 if (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
7706 resop) != NFS4_CHKSEQ_OKAY) {
7707 *cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
7708 break;
7709 }
7710 *cs->statusp = resp->status = NFS4_OK;
7711
7712 next_stateid(&sp->rs_stateid);
7713 resp->open_stateid = sp->rs_stateid.stateid;
7714 sp->rs_owner->ro_need_confirm = FALSE;
7715 rfs4_update_lease(sp->rs_owner->ro_client);
7716 rfs4_update_open_sequence(sp->rs_owner);
7717 rfs4_update_open_resp(sp->rs_owner, resop, NULL);
7718 break;
7719 default:
7720 ASSERT(FALSE);
7721 *cs->statusp = resp->status = NFS4ERR_SERVERFAULT;
7722 break;
7723 }
7724 rfs4_sw_exit(&sp->rs_owner->ro_sw);
7725 rfs4_state_rele(sp);
7726
7727 out:
7728 DTRACE_NFSV4_2(op__open__confirm__done, struct compound_state *, cs,
7729 OPEN_CONFIRM4res *, resp);
7730 }
7731
7732 /*ARGSUSED*/
7733 void
rfs4_op_open_downgrade(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)7734 rfs4_op_open_downgrade(nfs_argop4 *argop, nfs_resop4 *resop,
7735 struct svc_req *req, struct compound_state *cs)
7736 {
7737 OPEN_DOWNGRADE4args *args = &argop->nfs_argop4_u.opopen_downgrade;
7738 OPEN_DOWNGRADE4res *resp = &resop->nfs_resop4_u.opopen_downgrade;
7739 uint32_t access = args->share_access;
7740 uint32_t deny = args->share_deny;
7741 nfsstat4 status;
7742 rfs4_state_t *sp;
7743 rfs4_file_t *fp;
7744 int fflags = 0;
7745
7746 DTRACE_NFSV4_2(op__open__downgrade__start, struct compound_state *, cs,
7747 OPEN_DOWNGRADE4args *, args);
7748
7749 if (cs->vp == NULL) {
7750 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
7751 goto out;
7752 }
7753
7754 if (cs->vp->v_type != VREG) {
7755 *cs->statusp = resp->status = NFS4ERR_INVAL;
7756 return;
7757 }
7758
7759 status = rfs4_get_state(&args->open_stateid, &sp, RFS4_DBS_VALID);
7760 if (status != NFS4_OK) {
7761 *cs->statusp = resp->status = status;
7762 goto out;
7763 }
7764
7765 /* Ensure specified filehandle matches */
7766 if (cs->vp != sp->rs_finfo->rf_vp) {
7767 rfs4_state_rele(sp);
7768 *cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
7769 goto out;
7770 }
7771
7772 /* hold off other access to open_owner while we tinker */
7773 rfs4_sw_enter(&sp->rs_owner->ro_sw);
7774
7775 switch (rfs4_check_stateid_seqid(sp, &args->open_stateid)) {
7776 case NFS4_CHECK_STATEID_OKAY:
7777 if (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
7778 resop) != NFS4_CHKSEQ_OKAY) {
7779 *cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
7780 goto end;
7781 }
7782 break;
7783 case NFS4_CHECK_STATEID_OLD:
7784 *cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
7785 goto end;
7786 case NFS4_CHECK_STATEID_BAD:
7787 *cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
7788 goto end;
7789 case NFS4_CHECK_STATEID_EXPIRED:
7790 *cs->statusp = resp->status = NFS4ERR_EXPIRED;
7791 goto end;
7792 case NFS4_CHECK_STATEID_CLOSED:
7793 *cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
7794 goto end;
7795 case NFS4_CHECK_STATEID_UNCONFIRMED:
7796 *cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
7797 goto end;
7798 case NFS4_CHECK_STATEID_REPLAY:
7799 /* Check the sequence id for the open owner */
7800 switch (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
7801 resop)) {
7802 case NFS4_CHKSEQ_OKAY:
7803 /*
7804 * This is replayed stateid; if seqid matches
7805 * next expected, then client is using wrong seqid.
7806 */
7807 /* fall through */
7808 case NFS4_CHKSEQ_BAD:
7809 *cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
7810 goto end;
7811 case NFS4_CHKSEQ_REPLAY:
7812 /*
7813 * Note this case is the duplicate case so
7814 * resp->status is already set.
7815 */
7816 *cs->statusp = resp->status;
7817 rfs4_update_lease(sp->rs_owner->ro_client);
7818 goto end;
7819 }
7820 break;
7821 default:
7822 ASSERT(FALSE);
7823 break;
7824 }
7825
7826 rfs4_dbe_lock(sp->rs_dbe);
7827 /*
7828 * Check that the new access modes and deny modes are valid.
7829 * Check that no invalid bits are set.
7830 */
7831 if ((access & ~(OPEN4_SHARE_ACCESS_READ | OPEN4_SHARE_ACCESS_WRITE)) ||
7832 (deny & ~(OPEN4_SHARE_DENY_READ | OPEN4_SHARE_DENY_WRITE))) {
7833 *cs->statusp = resp->status = NFS4ERR_INVAL;
7834 rfs4_update_open_sequence(sp->rs_owner);
7835 rfs4_dbe_unlock(sp->rs_dbe);
7836 goto end;
7837 }
7838
7839 /*
7840 * The new modes must be a subset of the current modes and
7841 * the access must specify at least one mode. To test that
7842 * the new mode is a subset of the current modes we bitwise
7843 * AND them together and check that the result equals the new
7844 * mode. For example:
7845 * New mode, access == R and current mode, sp->rs_open_access == RW
7846 * access & sp->rs_open_access == R == access, so the new access mode
7847 * is valid. Consider access == RW, sp->rs_open_access = R
7848 * access & sp->rs_open_access == R != access, so the new access mode
7849 * is invalid.
7850 */
7851 if ((access & sp->rs_open_access) != access ||
7852 (deny & sp->rs_open_deny) != deny ||
7853 (access &
7854 (OPEN4_SHARE_ACCESS_READ | OPEN4_SHARE_ACCESS_WRITE)) == 0) {
7855 *cs->statusp = resp->status = NFS4ERR_INVAL;
7856 rfs4_update_open_sequence(sp->rs_owner);
7857 rfs4_dbe_unlock(sp->rs_dbe);
7858 goto end;
7859 }
7860
7861 /*
7862 * Release any share locks associated with this stateID.
7863 * Strictly speaking, this violates the spec because the
7864 * spec effectively requires that open downgrade be atomic.
7865 * At present, fs_shrlock does not have this capability.
7866 */
7867 (void) rfs4_unshare(sp);
7868
7869 status = rfs4_share(sp, access, deny);
7870 if (status != NFS4_OK) {
7871 *cs->statusp = resp->status = NFS4ERR_SERVERFAULT;
7872 rfs4_update_open_sequence(sp->rs_owner);
7873 rfs4_dbe_unlock(sp->rs_dbe);
7874 goto end;
7875 }
7876
7877 fp = sp->rs_finfo;
7878 rfs4_dbe_lock(fp->rf_dbe);
7879
7880 /*
7881 * If the current mode has deny read and the new mode
7882 * does not, decrement the number of deny read mode bits
7883 * and if it goes to zero turn off the deny read bit
7884 * on the file.
7885 */
7886 if ((sp->rs_open_deny & OPEN4_SHARE_DENY_READ) &&
7887 (deny & OPEN4_SHARE_DENY_READ) == 0) {
7888 fp->rf_deny_read--;
7889 if (fp->rf_deny_read == 0)
7890 fp->rf_share_deny &= ~OPEN4_SHARE_DENY_READ;
7891 }
7892
7893 /*
7894 * If the current mode has deny write and the new mode
7895 * does not, decrement the number of deny write mode bits
7896 * and if it goes to zero turn off the deny write bit
7897 * on the file.
7898 */
7899 if ((sp->rs_open_deny & OPEN4_SHARE_DENY_WRITE) &&
7900 (deny & OPEN4_SHARE_DENY_WRITE) == 0) {
7901 fp->rf_deny_write--;
7902 if (fp->rf_deny_write == 0)
7903 fp->rf_share_deny &= ~OPEN4_SHARE_DENY_WRITE;
7904 }
7905
7906 /*
7907 * If the current mode has access read and the new mode
7908 * does not, decrement the number of access read mode bits
7909 * and if it goes to zero turn off the access read bit
7910 * on the file. set fflags to FREAD for the call to
7911 * vn_open_downgrade().
7912 */
7913 if ((sp->rs_open_access & OPEN4_SHARE_ACCESS_READ) &&
7914 (access & OPEN4_SHARE_ACCESS_READ) == 0) {
7915 fp->rf_access_read--;
7916 if (fp->rf_access_read == 0)
7917 fp->rf_share_access &= ~OPEN4_SHARE_ACCESS_READ;
7918 fflags |= FREAD;
7919 }
7920
7921 /*
7922 * If the current mode has access write and the new mode
7923 * does not, decrement the number of access write mode bits
7924 * and if it goes to zero turn off the access write bit
7925 * on the file. set fflags to FWRITE for the call to
7926 * vn_open_downgrade().
7927 */
7928 if ((sp->rs_open_access & OPEN4_SHARE_ACCESS_WRITE) &&
7929 (access & OPEN4_SHARE_ACCESS_WRITE) == 0) {
7930 fp->rf_access_write--;
7931 if (fp->rf_access_write == 0)
7932 fp->rf_share_deny &= ~OPEN4_SHARE_ACCESS_WRITE;
7933 fflags |= FWRITE;
7934 }
7935
7936 /* Check that the file is still accessible */
7937 ASSERT(fp->rf_share_access);
7938
7939 rfs4_dbe_unlock(fp->rf_dbe);
7940
7941 /* now set the new open access and deny modes */
7942 sp->rs_open_access = access;
7943 sp->rs_open_deny = deny;
7944
7945 /*
7946 * we successfully downgraded the share lock, now we need to downgrade
7947 * the open. it is possible that the downgrade was only for a deny
7948 * mode and we have nothing else to do.
7949 */
7950 if ((fflags & (FREAD|FWRITE)) != 0)
7951 vn_open_downgrade(cs->vp, fflags);
7952
7953 /* Update the stateid */
7954 next_stateid(&sp->rs_stateid);
7955 resp->open_stateid = sp->rs_stateid.stateid;
7956
7957 rfs4_dbe_unlock(sp->rs_dbe);
7958
7959 *cs->statusp = resp->status = NFS4_OK;
7960 /* Update the lease */
7961 rfs4_update_lease(sp->rs_owner->ro_client);
7962 /* And the sequence */
7963 rfs4_update_open_sequence(sp->rs_owner);
7964 rfs4_update_open_resp(sp->rs_owner, resop, NULL);
7965
7966 end:
7967 rfs4_sw_exit(&sp->rs_owner->ro_sw);
7968 rfs4_state_rele(sp);
7969 out:
7970 DTRACE_NFSV4_2(op__open__downgrade__done, struct compound_state *, cs,
7971 OPEN_DOWNGRADE4res *, resp);
7972 }
7973
7974 static void *
memstr(const void * s1,const char * s2,size_t n)7975 memstr(const void *s1, const char *s2, size_t n)
7976 {
7977 size_t l = strlen(s2);
7978 char *p = (char *)s1;
7979
7980 while (n >= l) {
7981 if (bcmp(p, s2, l) == 0)
7982 return (p);
7983 p++;
7984 n--;
7985 }
7986
7987 return (NULL);
7988 }
7989
7990 /*
7991 * The logic behind this function is detailed in the NFSv4 RFC in the
7992 * SETCLIENTID operation description under IMPLEMENTATION. Refer to
7993 * that section for explicit guidance to server behavior for
7994 * SETCLIENTID.
7995 */
7996 void
rfs4_op_setclientid(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)7997 rfs4_op_setclientid(nfs_argop4 *argop, nfs_resop4 *resop,
7998 struct svc_req *req, struct compound_state *cs)
7999 {
8000 SETCLIENTID4args *args = &argop->nfs_argop4_u.opsetclientid;
8001 SETCLIENTID4res *res = &resop->nfs_resop4_u.opsetclientid;
8002 rfs4_client_t *cp, *newcp, *cp_confirmed, *cp_unconfirmed;
8003 rfs4_clntip_t *ci;
8004 bool_t create;
8005 char *addr, *netid;
8006 int len;
8007
8008 DTRACE_NFSV4_2(op__setclientid__start, struct compound_state *, cs,
8009 SETCLIENTID4args *, args);
8010 retry:
8011 newcp = cp_confirmed = cp_unconfirmed = NULL;
8012
8013 /*
8014 * Save the caller's IP address
8015 */
8016 args->client.cl_addr =
8017 (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
8018
8019 /*
8020 * Record if it is a Solaris client that cannot handle referrals.
8021 */
8022 if (memstr(args->client.id_val, "Solaris", args->client.id_len) &&
8023 !memstr(args->client.id_val, "+referrals", args->client.id_len)) {
8024 /* Add a "yes, it's downrev" record */
8025 create = TRUE;
8026 ci = rfs4_find_clntip(args->client.cl_addr, &create);
8027 ASSERT(ci != NULL);
8028 rfs4_dbe_rele(ci->ri_dbe);
8029 } else {
8030 /* Remove any previous record */
8031 rfs4_invalidate_clntip(args->client.cl_addr);
8032 }
8033
8034 /*
8035 * In search of an EXISTING client matching the incoming
8036 * request to establish a new client identifier at the server
8037 */
8038 create = TRUE;
8039 cp = rfs4_findclient(&args->client, &create, NULL);
8040
8041 /* Should never happen */
8042 ASSERT(cp != NULL);
8043
8044 if (cp == NULL) {
8045 *cs->statusp = res->status = NFS4ERR_SERVERFAULT;
8046 goto out;
8047 }
8048
8049 /*
8050 * Easiest case. Client identifier is newly created and is
8051 * unconfirmed. Also note that for this case, no other
8052 * entries exist for the client identifier. Nothing else to
8053 * check. Just setup the response and respond.
8054 */
8055 if (create) {
8056 *cs->statusp = res->status = NFS4_OK;
8057 res->SETCLIENTID4res_u.resok4.clientid = cp->rc_clientid;
8058 res->SETCLIENTID4res_u.resok4.setclientid_confirm =
8059 cp->rc_confirm_verf;
8060 /* Setup callback information; CB_NULL confirmation later */
8061 rfs4_client_setcb(cp, &args->callback, args->callback_ident);
8062
8063 rfs4_client_rele(cp);
8064 goto out;
8065 }
8066
8067 /*
8068 * An existing, confirmed client may exist but it may not have
8069 * been active for at least one lease period. If so, then
8070 * "close" the client and create a new client identifier
8071 */
8072 if (rfs4_lease_expired(cp)) {
8073 rfs4_client_close(cp);
8074 goto retry;
8075 }
8076
8077 if (cp->rc_need_confirm == TRUE)
8078 cp_unconfirmed = cp;
8079 else
8080 cp_confirmed = cp;
8081
8082 cp = NULL;
8083
8084 /*
8085 * We have a confirmed client, now check for an
8086 * unconfimred entry
8087 */
8088 if (cp_confirmed) {
8089 /* If creds don't match then client identifier is inuse */
8090 if (!creds_ok(cp_confirmed->rc_cr_set, req, cs)) {
8091 rfs4_cbinfo_t *cbp;
8092 /*
8093 * Some one else has established this client
8094 * id. Try and say * who they are. We will use
8095 * the call back address supplied by * the
8096 * first client.
8097 */
8098 *cs->statusp = res->status = NFS4ERR_CLID_INUSE;
8099
8100 addr = netid = NULL;
8101
8102 cbp = &cp_confirmed->rc_cbinfo;
8103 if (cbp->cb_callback.cb_location.r_addr &&
8104 cbp->cb_callback.cb_location.r_netid) {
8105 cb_client4 *cbcp = &cbp->cb_callback;
8106
8107 len = strlen(cbcp->cb_location.r_addr)+1;
8108 addr = kmem_alloc(len, KM_SLEEP);
8109 bcopy(cbcp->cb_location.r_addr, addr, len);
8110 len = strlen(cbcp->cb_location.r_netid)+1;
8111 netid = kmem_alloc(len, KM_SLEEP);
8112 bcopy(cbcp->cb_location.r_netid, netid, len);
8113 }
8114
8115 res->SETCLIENTID4res_u.client_using.r_addr = addr;
8116 res->SETCLIENTID4res_u.client_using.r_netid = netid;
8117
8118 rfs4_client_rele(cp_confirmed);
8119 }
8120
8121 /*
8122 * Confirmed, creds match, and verifier matches; must
8123 * be an update of the callback info
8124 */
8125 if (cp_confirmed->rc_nfs_client.verifier ==
8126 args->client.verifier) {
8127 /* Setup callback information */
8128 rfs4_client_setcb(cp_confirmed, &args->callback,
8129 args->callback_ident);
8130
8131 /* everything okay -- move ahead */
8132 *cs->statusp = res->status = NFS4_OK;
8133 res->SETCLIENTID4res_u.resok4.clientid =
8134 cp_confirmed->rc_clientid;
8135
8136 /* update the confirm_verifier and return it */
8137 rfs4_client_scv_next(cp_confirmed);
8138 res->SETCLIENTID4res_u.resok4.setclientid_confirm =
8139 cp_confirmed->rc_confirm_verf;
8140
8141 rfs4_client_rele(cp_confirmed);
8142 goto out;
8143 }
8144
8145 /*
8146 * Creds match but the verifier doesn't. Must search
8147 * for an unconfirmed client that would be replaced by
8148 * this request.
8149 */
8150 create = FALSE;
8151 cp_unconfirmed = rfs4_findclient(&args->client, &create,
8152 cp_confirmed);
8153 }
8154
8155 /*
8156 * At this point, we have taken care of the brand new client
8157 * struct, INUSE case, update of an existing, and confirmed
8158 * client struct.
8159 */
8160
8161 /*
8162 * check to see if things have changed while we originally
8163 * picked up the client struct. If they have, then return and
8164 * retry the processing of this SETCLIENTID request.
8165 */
8166 if (cp_unconfirmed) {
8167 rfs4_dbe_lock(cp_unconfirmed->rc_dbe);
8168 if (!cp_unconfirmed->rc_need_confirm) {
8169 rfs4_dbe_unlock(cp_unconfirmed->rc_dbe);
8170 rfs4_client_rele(cp_unconfirmed);
8171 if (cp_confirmed)
8172 rfs4_client_rele(cp_confirmed);
8173 goto retry;
8174 }
8175 /* do away with the old unconfirmed one */
8176 rfs4_dbe_invalidate(cp_unconfirmed->rc_dbe);
8177 rfs4_dbe_unlock(cp_unconfirmed->rc_dbe);
8178 rfs4_client_rele(cp_unconfirmed);
8179 cp_unconfirmed = NULL;
8180 }
8181
8182 /*
8183 * This search will temporarily hide the confirmed client
8184 * struct while a new client struct is created as the
8185 * unconfirmed one.
8186 */
8187 create = TRUE;
8188 newcp = rfs4_findclient(&args->client, &create, cp_confirmed);
8189
8190 ASSERT(newcp != NULL);
8191
8192 if (newcp == NULL) {
8193 *cs->statusp = res->status = NFS4ERR_SERVERFAULT;
8194 rfs4_client_rele(cp_confirmed);
8195 goto out;
8196 }
8197
8198 /*
8199 * If one was not created, then a similar request must be in
8200 * process so release and start over with this one
8201 */
8202 if (create != TRUE) {
8203 rfs4_client_rele(newcp);
8204 if (cp_confirmed)
8205 rfs4_client_rele(cp_confirmed);
8206 goto retry;
8207 }
8208
8209 *cs->statusp = res->status = NFS4_OK;
8210 res->SETCLIENTID4res_u.resok4.clientid = newcp->rc_clientid;
8211 res->SETCLIENTID4res_u.resok4.setclientid_confirm =
8212 newcp->rc_confirm_verf;
8213 /* Setup callback information; CB_NULL confirmation later */
8214 rfs4_client_setcb(newcp, &args->callback, args->callback_ident);
8215
8216 newcp->rc_cp_confirmed = cp_confirmed;
8217
8218 rfs4_client_rele(newcp);
8219
8220 out:
8221 DTRACE_NFSV4_2(op__setclientid__done, struct compound_state *, cs,
8222 SETCLIENTID4res *, res);
8223 }
8224
8225 /*ARGSUSED*/
8226 void
rfs4_op_setclientid_confirm(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)8227 rfs4_op_setclientid_confirm(nfs_argop4 *argop, nfs_resop4 *resop,
8228 struct svc_req *req, struct compound_state *cs)
8229 {
8230 SETCLIENTID_CONFIRM4args *args =
8231 &argop->nfs_argop4_u.opsetclientid_confirm;
8232 SETCLIENTID_CONFIRM4res *res =
8233 &resop->nfs_resop4_u.opsetclientid_confirm;
8234 rfs4_client_t *cp, *cptoclose = NULL;
8235
8236 DTRACE_NFSV4_2(op__setclientid__confirm__start,
8237 struct compound_state *, cs,
8238 SETCLIENTID_CONFIRM4args *, args);
8239
8240 *cs->statusp = res->status = NFS4_OK;
8241
8242 cp = rfs4_findclient_by_id(args->clientid, TRUE);
8243
8244 if (cp == NULL) {
8245 *cs->statusp = res->status =
8246 rfs4_check_clientid(&args->clientid, 1);
8247 goto out;
8248 }
8249
8250 if (!creds_ok(cp, req, cs)) {
8251 *cs->statusp = res->status = NFS4ERR_CLID_INUSE;
8252 rfs4_client_rele(cp);
8253 goto out;
8254 }
8255
8256 /* If the verifier doesn't match, the record doesn't match */
8257 if (cp->rc_confirm_verf != args->setclientid_confirm) {
8258 *cs->statusp = res->status = NFS4ERR_STALE_CLIENTID;
8259 rfs4_client_rele(cp);
8260 goto out;
8261 }
8262
8263 rfs4_dbe_lock(cp->rc_dbe);
8264 cp->rc_need_confirm = FALSE;
8265 if (cp->rc_cp_confirmed) {
8266 cptoclose = cp->rc_cp_confirmed;
8267 cptoclose->rc_ss_remove = 1;
8268 cp->rc_cp_confirmed = NULL;
8269 }
8270
8271 /*
8272 * Update the client's associated server instance, if it's changed
8273 * since the client was created.
8274 */
8275 if (rfs4_servinst(cp) != rfs4_cur_servinst)
8276 rfs4_servinst_assign(cp, rfs4_cur_servinst);
8277
8278 /*
8279 * Record clientid in stable storage.
8280 * Must be done after server instance has been assigned.
8281 */
8282 rfs4_ss_clid(cp);
8283
8284 rfs4_dbe_unlock(cp->rc_dbe);
8285
8286 if (cptoclose)
8287 /* don't need to rele, client_close does it */
8288 rfs4_client_close(cptoclose);
8289
8290 /* If needed, initiate CB_NULL call for callback path */
8291 rfs4_deleg_cb_check(cp);
8292 rfs4_update_lease(cp);
8293
8294 /*
8295 * Check to see if client can perform reclaims
8296 */
8297 rfs4_ss_chkclid(cp);
8298
8299 rfs4_client_rele(cp);
8300
8301 out:
8302 DTRACE_NFSV4_2(op__setclientid__confirm__done,
8303 struct compound_state *, cs,
8304 SETCLIENTID_CONFIRM4 *, res);
8305 }
8306
8307
8308 /*ARGSUSED*/
8309 void
rfs4_op_close(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)8310 rfs4_op_close(nfs_argop4 *argop, nfs_resop4 *resop,
8311 struct svc_req *req, struct compound_state *cs)
8312 {
8313 CLOSE4args *args = &argop->nfs_argop4_u.opclose;
8314 CLOSE4res *resp = &resop->nfs_resop4_u.opclose;
8315 rfs4_state_t *sp;
8316 nfsstat4 status;
8317
8318 DTRACE_NFSV4_2(op__close__start, struct compound_state *, cs,
8319 CLOSE4args *, args);
8320
8321 if (cs->vp == NULL) {
8322 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
8323 goto out;
8324 }
8325
8326 status = rfs4_get_state(&args->open_stateid, &sp, RFS4_DBS_INVALID);
8327 if (status != NFS4_OK) {
8328 *cs->statusp = resp->status = status;
8329 goto out;
8330 }
8331
8332 /* Ensure specified filehandle matches */
8333 if (cs->vp != sp->rs_finfo->rf_vp) {
8334 rfs4_state_rele(sp);
8335 *cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
8336 goto out;
8337 }
8338
8339 /* hold off other access to open_owner while we tinker */
8340 rfs4_sw_enter(&sp->rs_owner->ro_sw);
8341
8342 switch (rfs4_check_stateid_seqid(sp, &args->open_stateid)) {
8343 case NFS4_CHECK_STATEID_OKAY:
8344 if (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
8345 resop) != NFS4_CHKSEQ_OKAY) {
8346 *cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
8347 goto end;
8348 }
8349 break;
8350 case NFS4_CHECK_STATEID_OLD:
8351 *cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
8352 goto end;
8353 case NFS4_CHECK_STATEID_BAD:
8354 *cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
8355 goto end;
8356 case NFS4_CHECK_STATEID_EXPIRED:
8357 *cs->statusp = resp->status = NFS4ERR_EXPIRED;
8358 goto end;
8359 case NFS4_CHECK_STATEID_CLOSED:
8360 *cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
8361 goto end;
8362 case NFS4_CHECK_STATEID_UNCONFIRMED:
8363 *cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
8364 goto end;
8365 case NFS4_CHECK_STATEID_REPLAY:
8366 /* Check the sequence id for the open owner */
8367 switch (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
8368 resop)) {
8369 case NFS4_CHKSEQ_OKAY:
8370 /*
8371 * This is replayed stateid; if seqid matches
8372 * next expected, then client is using wrong seqid.
8373 */
8374 /* FALL THROUGH */
8375 case NFS4_CHKSEQ_BAD:
8376 *cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
8377 goto end;
8378 case NFS4_CHKSEQ_REPLAY:
8379 /*
8380 * Note this case is the duplicate case so
8381 * resp->status is already set.
8382 */
8383 *cs->statusp = resp->status;
8384 rfs4_update_lease(sp->rs_owner->ro_client);
8385 goto end;
8386 }
8387 break;
8388 default:
8389 ASSERT(FALSE);
8390 break;
8391 }
8392
8393 rfs4_dbe_lock(sp->rs_dbe);
8394
8395 /* Update the stateid. */
8396 next_stateid(&sp->rs_stateid);
8397 resp->open_stateid = sp->rs_stateid.stateid;
8398
8399 rfs4_dbe_unlock(sp->rs_dbe);
8400
8401 rfs4_update_lease(sp->rs_owner->ro_client);
8402 rfs4_update_open_sequence(sp->rs_owner);
8403 rfs4_update_open_resp(sp->rs_owner, resop, NULL);
8404
8405 rfs4_state_close(sp, FALSE, FALSE, cs->cr);
8406
8407 *cs->statusp = resp->status = status;
8408
8409 end:
8410 rfs4_sw_exit(&sp->rs_owner->ro_sw);
8411 rfs4_state_rele(sp);
8412 out:
8413 DTRACE_NFSV4_2(op__close__done, struct compound_state *, cs,
8414 CLOSE4res *, resp);
8415 }
8416
8417 /*
8418 * Manage the counts on the file struct and close all file locks
8419 */
8420 /*ARGSUSED*/
8421 void
rfs4_release_share_lock_state(rfs4_state_t * sp,cred_t * cr,bool_t close_of_client)8422 rfs4_release_share_lock_state(rfs4_state_t *sp, cred_t *cr,
8423 bool_t close_of_client)
8424 {
8425 rfs4_file_t *fp = sp->rs_finfo;
8426 rfs4_lo_state_t *lsp;
8427 int fflags = 0;
8428
8429 /*
8430 * If this call is part of the larger closing down of client
8431 * state then it is just easier to release all locks
8432 * associated with this client instead of going through each
8433 * individual file and cleaning locks there.
8434 */
8435 if (close_of_client) {
8436 if (sp->rs_owner->ro_client->rc_unlksys_completed == FALSE &&
8437 !list_is_empty(&sp->rs_lostatelist) &&
8438 sp->rs_owner->ro_client->rc_sysidt != LM_NOSYSID) {
8439 /* Is the PxFS kernel module loaded? */
8440 if (lm_remove_file_locks != NULL) {
8441 int new_sysid;
8442
8443 /* Encode the cluster nodeid in new sysid */
8444 new_sysid = sp->rs_owner->ro_client->rc_sysidt;
8445 lm_set_nlmid_flk(&new_sysid);
8446
8447 /*
8448 * This PxFS routine removes file locks for a
8449 * client over all nodes of a cluster.
8450 */
8451 NFS4_DEBUG(rfs4_debug, (CE_NOTE,
8452 "lm_remove_file_locks(sysid=0x%x)\n",
8453 new_sysid));
8454 (*lm_remove_file_locks)(new_sysid);
8455 } else {
8456 struct flock64 flk;
8457
8458 /* Release all locks for this client */
8459 flk.l_type = F_UNLKSYS;
8460 flk.l_whence = 0;
8461 flk.l_start = 0;
8462 flk.l_len = 0;
8463 flk.l_sysid =
8464 sp->rs_owner->ro_client->rc_sysidt;
8465 flk.l_pid = 0;
8466 (void) VOP_FRLOCK(sp->rs_finfo->rf_vp, F_SETLK,
8467 &flk, F_REMOTELOCK | FREAD | FWRITE,
8468 (u_offset_t)0, NULL, CRED(), NULL);
8469 }
8470
8471 sp->rs_owner->ro_client->rc_unlksys_completed = TRUE;
8472 }
8473 }
8474
8475 /*
8476 * Release all locks on this file by this lock owner or at
8477 * least mark the locks as having been released
8478 */
8479 for (lsp = list_head(&sp->rs_lostatelist); lsp != NULL;
8480 lsp = list_next(&sp->rs_lostatelist, lsp)) {
8481 lsp->rls_locks_cleaned = TRUE;
8482
8483 /* Was this already taken care of above? */
8484 if (!close_of_client &&
8485 sp->rs_owner->ro_client->rc_sysidt != LM_NOSYSID)
8486 (void) cleanlocks(sp->rs_finfo->rf_vp,
8487 lsp->rls_locker->rl_pid,
8488 lsp->rls_locker->rl_client->rc_sysidt);
8489 }
8490
8491 /*
8492 * Release any shrlocks associated with this open state ID.
8493 * This must be done before the rfs4_state gets marked closed.
8494 */
8495 if (sp->rs_owner->ro_client->rc_sysidt != LM_NOSYSID)
8496 (void) rfs4_unshare(sp);
8497
8498 if (sp->rs_open_access) {
8499 rfs4_dbe_lock(fp->rf_dbe);
8500
8501 /*
8502 * Decrement the count for each access and deny bit that this
8503 * state has contributed to the file.
8504 * If the file counts go to zero
8505 * clear the appropriate bit in the appropriate mask.
8506 */
8507 if (sp->rs_open_access & OPEN4_SHARE_ACCESS_READ) {
8508 fp->rf_access_read--;
8509 fflags |= FREAD;
8510 if (fp->rf_access_read == 0)
8511 fp->rf_share_access &= ~OPEN4_SHARE_ACCESS_READ;
8512 }
8513 if (sp->rs_open_access & OPEN4_SHARE_ACCESS_WRITE) {
8514 fp->rf_access_write--;
8515 fflags |= FWRITE;
8516 if (fp->rf_access_write == 0)
8517 fp->rf_share_access &=
8518 ~OPEN4_SHARE_ACCESS_WRITE;
8519 }
8520 if (sp->rs_open_deny & OPEN4_SHARE_DENY_READ) {
8521 fp->rf_deny_read--;
8522 if (fp->rf_deny_read == 0)
8523 fp->rf_share_deny &= ~OPEN4_SHARE_DENY_READ;
8524 }
8525 if (sp->rs_open_deny & OPEN4_SHARE_DENY_WRITE) {
8526 fp->rf_deny_write--;
8527 if (fp->rf_deny_write == 0)
8528 fp->rf_share_deny &= ~OPEN4_SHARE_DENY_WRITE;
8529 }
8530
8531 (void) VOP_CLOSE(fp->rf_vp, fflags, 1, (offset_t)0, cr, NULL);
8532
8533 rfs4_dbe_unlock(fp->rf_dbe);
8534
8535 sp->rs_open_access = 0;
8536 sp->rs_open_deny = 0;
8537 }
8538 }
8539
8540 /*
8541 * lock_denied: Fill in a LOCK4deneid structure given an flock64 structure.
8542 */
8543 static nfsstat4
lock_denied(LOCK4denied * dp,struct flock64 * flk)8544 lock_denied(LOCK4denied *dp, struct flock64 *flk)
8545 {
8546 rfs4_lockowner_t *lo;
8547 rfs4_client_t *cp;
8548 uint32_t len;
8549
8550 lo = rfs4_findlockowner_by_pid(flk->l_pid);
8551 if (lo != NULL) {
8552 cp = lo->rl_client;
8553 if (rfs4_lease_expired(cp)) {
8554 rfs4_lockowner_rele(lo);
8555 rfs4_dbe_hold(cp->rc_dbe);
8556 rfs4_client_close(cp);
8557 return (NFS4ERR_EXPIRED);
8558 }
8559 dp->owner.clientid = lo->rl_owner.clientid;
8560 len = lo->rl_owner.owner_len;
8561 dp->owner.owner_val = kmem_alloc(len, KM_SLEEP);
8562 bcopy(lo->rl_owner.owner_val, dp->owner.owner_val, len);
8563 dp->owner.owner_len = len;
8564 rfs4_lockowner_rele(lo);
8565 goto finish;
8566 }
8567
8568 /*
8569 * Its not a NFS4 lock. We take advantage that the upper 32 bits
8570 * of the client id contain the boot time for a NFS4 lock. So we
8571 * fabricate and identity by setting clientid to the sysid, and
8572 * the lock owner to the pid.
8573 */
8574 dp->owner.clientid = flk->l_sysid;
8575 len = sizeof (pid_t);
8576 dp->owner.owner_len = len;
8577 dp->owner.owner_val = kmem_alloc(len, KM_SLEEP);
8578 bcopy(&flk->l_pid, dp->owner.owner_val, len);
8579 finish:
8580 dp->offset = flk->l_start;
8581 dp->length = flk->l_len;
8582
8583 if (flk->l_type == F_RDLCK)
8584 dp->locktype = READ_LT;
8585 else if (flk->l_type == F_WRLCK)
8586 dp->locktype = WRITE_LT;
8587 else
8588 return (NFS4ERR_INVAL); /* no mapping from POSIX ltype to v4 */
8589
8590 return (NFS4_OK);
8591 }
8592
8593 static int
setlock(vnode_t * vp,struct flock64 * flock,int flag,cred_t * cred)8594 setlock(vnode_t *vp, struct flock64 *flock, int flag, cred_t *cred)
8595 {
8596 int error;
8597 struct flock64 flk;
8598 int i;
8599 clock_t delaytime;
8600 int cmd;
8601
8602 cmd = nbl_need_check(vp) ? F_SETLK_NBMAND : F_SETLK;
8603 retry:
8604 delaytime = MSEC_TO_TICK_ROUNDUP(rfs4_lock_delay);
8605
8606 for (i = 0; i < rfs4_maxlock_tries; i++) {
8607 LOCK_PRINT(rfs4_debug, "setlock", cmd, flock);
8608 error = VOP_FRLOCK(vp, cmd,
8609 flock, flag, (u_offset_t)0, NULL, cred, NULL);
8610
8611 if (error != EAGAIN && error != EACCES)
8612 break;
8613
8614 if (i < rfs4_maxlock_tries - 1) {
8615 delay(delaytime);
8616 delaytime *= 2;
8617 }
8618 }
8619
8620 if (error == EAGAIN || error == EACCES) {
8621 /* Get the owner of the lock */
8622 flk = *flock;
8623 LOCK_PRINT(rfs4_debug, "setlock", F_GETLK, &flk);
8624 if (VOP_FRLOCK(vp, F_GETLK, &flk, flag,
8625 (u_offset_t)0, NULL, cred, NULL) == 0) {
8626 if (flk.l_type == F_UNLCK) {
8627 /* No longer locked, retry */
8628 goto retry;
8629 }
8630 *flock = flk;
8631 LOCK_PRINT(rfs4_debug, "setlock(blocking lock)",
8632 F_GETLK, &flk);
8633 }
8634 }
8635
8636 return (error);
8637 }
8638
8639 /*ARGSUSED*/
8640 static nfsstat4
rfs4_do_lock(rfs4_lo_state_t * lsp,nfs_lock_type4 locktype,offset4 offset,length4 length,cred_t * cred,nfs_resop4 * resop)8641 rfs4_do_lock(rfs4_lo_state_t *lsp, nfs_lock_type4 locktype,
8642 offset4 offset, length4 length, cred_t *cred, nfs_resop4 *resop)
8643 {
8644 nfsstat4 status;
8645 rfs4_lockowner_t *lo = lsp->rls_locker;
8646 rfs4_state_t *sp = lsp->rls_state;
8647 struct flock64 flock;
8648 int16_t ltype;
8649 int flag;
8650 int error;
8651 sysid_t sysid;
8652 LOCK4res *lres;
8653
8654 if (rfs4_lease_expired(lo->rl_client)) {
8655 return (NFS4ERR_EXPIRED);
8656 }
8657
8658 if ((status = rfs4_client_sysid(lo->rl_client, &sysid)) != NFS4_OK)
8659 return (status);
8660
8661 /* Check for zero length. To lock to end of file use all ones for V4 */
8662 if (length == 0)
8663 return (NFS4ERR_INVAL);
8664 else if (length == (length4)(~0))
8665 length = 0; /* Posix to end of file */
8666
8667 retry:
8668 rfs4_dbe_lock(sp->rs_dbe);
8669 if (sp->rs_closed) {
8670 rfs4_dbe_unlock(sp->rs_dbe);
8671 return (NFS4ERR_OLD_STATEID);
8672 }
8673
8674 if (resop->resop != OP_LOCKU) {
8675 switch (locktype) {
8676 case READ_LT:
8677 case READW_LT:
8678 if ((sp->rs_share_access
8679 & OPEN4_SHARE_ACCESS_READ) == 0) {
8680 rfs4_dbe_unlock(sp->rs_dbe);
8681
8682 return (NFS4ERR_OPENMODE);
8683 }
8684 ltype = F_RDLCK;
8685 break;
8686 case WRITE_LT:
8687 case WRITEW_LT:
8688 if ((sp->rs_share_access
8689 & OPEN4_SHARE_ACCESS_WRITE) == 0) {
8690 rfs4_dbe_unlock(sp->rs_dbe);
8691
8692 return (NFS4ERR_OPENMODE);
8693 }
8694 ltype = F_WRLCK;
8695 break;
8696 }
8697 } else
8698 ltype = F_UNLCK;
8699
8700 flock.l_type = ltype;
8701 flock.l_whence = 0; /* SEEK_SET */
8702 flock.l_start = offset;
8703 flock.l_len = length;
8704 flock.l_sysid = sysid;
8705 flock.l_pid = lsp->rls_locker->rl_pid;
8706
8707 /* Note that length4 is uint64_t but l_len and l_start are off64_t */
8708 if (flock.l_len < 0 || flock.l_start < 0) {
8709 rfs4_dbe_unlock(sp->rs_dbe);
8710 return (NFS4ERR_INVAL);
8711 }
8712
8713 /*
8714 * N.B. FREAD has the same value as OPEN4_SHARE_ACCESS_READ and
8715 * FWRITE has the same value as OPEN4_SHARE_ACCESS_WRITE.
8716 */
8717 flag = (int)sp->rs_share_access | F_REMOTELOCK;
8718
8719 error = setlock(sp->rs_finfo->rf_vp, &flock, flag, cred);
8720 if (error == 0) {
8721 rfs4_dbe_lock(lsp->rls_dbe);
8722 next_stateid(&lsp->rls_lockid);
8723 rfs4_dbe_unlock(lsp->rls_dbe);
8724 }
8725
8726 rfs4_dbe_unlock(sp->rs_dbe);
8727
8728 /*
8729 * N.B. We map error values to nfsv4 errors. This is differrent
8730 * than puterrno4 routine.
8731 */
8732 switch (error) {
8733 case 0:
8734 status = NFS4_OK;
8735 break;
8736 case EAGAIN:
8737 case EACCES: /* Old value */
8738 /* Can only get here if op is OP_LOCK */
8739 ASSERT(resop->resop == OP_LOCK);
8740 lres = &resop->nfs_resop4_u.oplock;
8741 status = NFS4ERR_DENIED;
8742 if (lock_denied(&lres->LOCK4res_u.denied, &flock)
8743 == NFS4ERR_EXPIRED)
8744 goto retry;
8745 break;
8746 case ENOLCK:
8747 status = NFS4ERR_DELAY;
8748 break;
8749 case EOVERFLOW:
8750 status = NFS4ERR_INVAL;
8751 break;
8752 case EINVAL:
8753 status = NFS4ERR_NOTSUPP;
8754 break;
8755 default:
8756 status = NFS4ERR_SERVERFAULT;
8757 break;
8758 }
8759
8760 return (status);
8761 }
8762
8763 /*ARGSUSED*/
8764 void
rfs4_op_lock(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)8765 rfs4_op_lock(nfs_argop4 *argop, nfs_resop4 *resop,
8766 struct svc_req *req, struct compound_state *cs)
8767 {
8768 LOCK4args *args = &argop->nfs_argop4_u.oplock;
8769 LOCK4res *resp = &resop->nfs_resop4_u.oplock;
8770 nfsstat4 status;
8771 stateid4 *stateid;
8772 rfs4_lockowner_t *lo;
8773 rfs4_client_t *cp;
8774 rfs4_state_t *sp = NULL;
8775 rfs4_lo_state_t *lsp = NULL;
8776 bool_t ls_sw_held = FALSE;
8777 bool_t create = TRUE;
8778 bool_t lcreate = TRUE;
8779 bool_t dup_lock = FALSE;
8780 int rc;
8781
8782 DTRACE_NFSV4_2(op__lock__start, struct compound_state *, cs,
8783 LOCK4args *, args);
8784
8785 if (cs->vp == NULL) {
8786 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
8787 DTRACE_NFSV4_2(op__lock__done, struct compound_state *,
8788 cs, LOCK4res *, resp);
8789 return;
8790 }
8791
8792 if (args->locker.new_lock_owner) {
8793 /* Create a new lockowner for this instance */
8794 open_to_lock_owner4 *olo = &args->locker.locker4_u.open_owner;
8795
8796 NFS4_DEBUG(rfs4_debug, (CE_NOTE, "Creating new lock owner"));
8797
8798 stateid = &olo->open_stateid;
8799 status = rfs4_get_state(stateid, &sp, RFS4_DBS_VALID);
8800 if (status != NFS4_OK) {
8801 NFS4_DEBUG(rfs4_debug,
8802 (CE_NOTE, "Get state failed in lock %d", status));
8803 *cs->statusp = resp->status = status;
8804 DTRACE_NFSV4_2(op__lock__done, struct compound_state *,
8805 cs, LOCK4res *, resp);
8806 return;
8807 }
8808
8809 /* Ensure specified filehandle matches */
8810 if (cs->vp != sp->rs_finfo->rf_vp) {
8811 rfs4_state_rele(sp);
8812 *cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
8813 DTRACE_NFSV4_2(op__lock__done, struct compound_state *,
8814 cs, LOCK4res *, resp);
8815 return;
8816 }
8817
8818 /* hold off other access to open_owner while we tinker */
8819 rfs4_sw_enter(&sp->rs_owner->ro_sw);
8820
8821 switch (rc = rfs4_check_stateid_seqid(sp, stateid)) {
8822 case NFS4_CHECK_STATEID_OLD:
8823 *cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
8824 goto end;
8825 case NFS4_CHECK_STATEID_BAD:
8826 *cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
8827 goto end;
8828 case NFS4_CHECK_STATEID_EXPIRED:
8829 *cs->statusp = resp->status = NFS4ERR_EXPIRED;
8830 goto end;
8831 case NFS4_CHECK_STATEID_UNCONFIRMED:
8832 *cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
8833 goto end;
8834 case NFS4_CHECK_STATEID_CLOSED:
8835 *cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
8836 goto end;
8837 case NFS4_CHECK_STATEID_OKAY:
8838 case NFS4_CHECK_STATEID_REPLAY:
8839 switch (rfs4_check_olo_seqid(olo->open_seqid,
8840 sp->rs_owner, resop)) {
8841 case NFS4_CHKSEQ_OKAY:
8842 if (rc == NFS4_CHECK_STATEID_OKAY)
8843 break;
8844 /*
8845 * This is replayed stateid; if seqid
8846 * matches next expected, then client
8847 * is using wrong seqid.
8848 */
8849 /* FALLTHROUGH */
8850 case NFS4_CHKSEQ_BAD:
8851 *cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
8852 goto end;
8853 case NFS4_CHKSEQ_REPLAY:
8854 /* This is a duplicate LOCK request */
8855 dup_lock = TRUE;
8856
8857 /*
8858 * For a duplicate we do not want to
8859 * create a new lockowner as it should
8860 * already exist.
8861 * Turn off the lockowner create flag.
8862 */
8863 lcreate = FALSE;
8864 }
8865 break;
8866 }
8867
8868 lo = rfs4_findlockowner(&olo->lock_owner, &lcreate);
8869 if (lo == NULL) {
8870 NFS4_DEBUG(rfs4_debug,
8871 (CE_NOTE, "rfs4_op_lock: no lock owner"));
8872 *cs->statusp = resp->status = NFS4ERR_RESOURCE;
8873 goto end;
8874 }
8875
8876 lsp = rfs4_findlo_state_by_owner(lo, sp, &create);
8877 if (lsp == NULL) {
8878 rfs4_update_lease(sp->rs_owner->ro_client);
8879 /*
8880 * Only update theh open_seqid if this is not
8881 * a duplicate request
8882 */
8883 if (dup_lock == FALSE) {
8884 rfs4_update_open_sequence(sp->rs_owner);
8885 }
8886
8887 NFS4_DEBUG(rfs4_debug,
8888 (CE_NOTE, "rfs4_op_lock: no state"));
8889 *cs->statusp = resp->status = NFS4ERR_SERVERFAULT;
8890 rfs4_update_open_resp(sp->rs_owner, resop, NULL);
8891 rfs4_lockowner_rele(lo);
8892 goto end;
8893 }
8894
8895 /*
8896 * This is the new_lock_owner branch and the client is
8897 * supposed to be associating a new lock_owner with
8898 * the open file at this point. If we find that a
8899 * lock_owner/state association already exists and a
8900 * successful LOCK request was returned to the client,
8901 * an error is returned to the client since this is
8902 * not appropriate. The client should be using the
8903 * existing lock_owner branch.
8904 */
8905 if (dup_lock == FALSE && create == FALSE) {
8906 if (lsp->rls_lock_completed == TRUE) {
8907 *cs->statusp =
8908 resp->status = NFS4ERR_BAD_SEQID;
8909 rfs4_lockowner_rele(lo);
8910 goto end;
8911 }
8912 }
8913
8914 rfs4_update_lease(sp->rs_owner->ro_client);
8915
8916 /*
8917 * Only update theh open_seqid if this is not
8918 * a duplicate request
8919 */
8920 if (dup_lock == FALSE) {
8921 rfs4_update_open_sequence(sp->rs_owner);
8922 }
8923
8924 /*
8925 * If this is a duplicate lock request, just copy the
8926 * previously saved reply and return.
8927 */
8928 if (dup_lock == TRUE) {
8929 /* verify that lock_seqid's match */
8930 if (lsp->rls_seqid != olo->lock_seqid) {
8931 NFS4_DEBUG(rfs4_debug,
8932 (CE_NOTE, "rfs4_op_lock: Dup-Lock seqid bad"
8933 "lsp->seqid=%d old->seqid=%d",
8934 lsp->rls_seqid, olo->lock_seqid));
8935 *cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
8936 } else {
8937 rfs4_copy_reply(resop, &lsp->rls_reply);
8938 /*
8939 * Make sure to copy the just
8940 * retrieved reply status into the
8941 * overall compound status
8942 */
8943 *cs->statusp = resp->status;
8944 }
8945 rfs4_lockowner_rele(lo);
8946 goto end;
8947 }
8948
8949 rfs4_dbe_lock(lsp->rls_dbe);
8950
8951 /* Make sure to update the lock sequence id */
8952 lsp->rls_seqid = olo->lock_seqid;
8953
8954 NFS4_DEBUG(rfs4_debug,
8955 (CE_NOTE, "Lock seqid established as %d", lsp->rls_seqid));
8956
8957 /*
8958 * This is used to signify the newly created lockowner
8959 * stateid and its sequence number. The checks for
8960 * sequence number and increment don't occur on the
8961 * very first lock request for a lockowner.
8962 */
8963 lsp->rls_skip_seqid_check = TRUE;
8964
8965 /* hold off other access to lsp while we tinker */
8966 rfs4_sw_enter(&lsp->rls_sw);
8967 ls_sw_held = TRUE;
8968
8969 rfs4_dbe_unlock(lsp->rls_dbe);
8970
8971 rfs4_lockowner_rele(lo);
8972 } else {
8973 stateid = &args->locker.locker4_u.lock_owner.lock_stateid;
8974 /* get lsp and hold the lock on the underlying file struct */
8975 if ((status = rfs4_get_lo_state(stateid, &lsp, TRUE))
8976 != NFS4_OK) {
8977 *cs->statusp = resp->status = status;
8978 DTRACE_NFSV4_2(op__lock__done, struct compound_state *,
8979 cs, LOCK4res *, resp);
8980 return;
8981 }
8982 create = FALSE; /* We didn't create lsp */
8983
8984 /* Ensure specified filehandle matches */
8985 if (cs->vp != lsp->rls_state->rs_finfo->rf_vp) {
8986 rfs4_lo_state_rele(lsp, TRUE);
8987 *cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
8988 DTRACE_NFSV4_2(op__lock__done, struct compound_state *,
8989 cs, LOCK4res *, resp);
8990 return;
8991 }
8992
8993 /* hold off other access to lsp while we tinker */
8994 rfs4_sw_enter(&lsp->rls_sw);
8995 ls_sw_held = TRUE;
8996
8997 switch (rfs4_check_lo_stateid_seqid(lsp, stateid)) {
8998 /*
8999 * The stateid looks like it was okay (expected to be
9000 * the next one)
9001 */
9002 case NFS4_CHECK_STATEID_OKAY:
9003 /*
9004 * The sequence id is now checked. Determine
9005 * if this is a replay or if it is in the
9006 * expected (next) sequence. In the case of a
9007 * replay, there are two replay conditions
9008 * that may occur. The first is the normal
9009 * condition where a LOCK is done with a
9010 * NFS4_OK response and the stateid is
9011 * updated. That case is handled below when
9012 * the stateid is identified as a REPLAY. The
9013 * second is the case where an error is
9014 * returned, like NFS4ERR_DENIED, and the
9015 * sequence number is updated but the stateid
9016 * is not updated. This second case is dealt
9017 * with here. So it may seem odd that the
9018 * stateid is okay but the sequence id is a
9019 * replay but it is okay.
9020 */
9021 switch (rfs4_check_lock_seqid(
9022 args->locker.locker4_u.lock_owner.lock_seqid,
9023 lsp, resop)) {
9024 case NFS4_CHKSEQ_REPLAY:
9025 if (resp->status != NFS4_OK) {
9026 /*
9027 * Here is our replay and need
9028 * to verify that the last
9029 * response was an error.
9030 */
9031 *cs->statusp = resp->status;
9032 goto end;
9033 }
9034 /*
9035 * This is done since the sequence id
9036 * looked like a replay but it didn't
9037 * pass our check so a BAD_SEQID is
9038 * returned as a result.
9039 */
9040 /*FALLTHROUGH*/
9041 case NFS4_CHKSEQ_BAD:
9042 *cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
9043 goto end;
9044 case NFS4_CHKSEQ_OKAY:
9045 /* Everything looks okay move ahead */
9046 break;
9047 }
9048 break;
9049 case NFS4_CHECK_STATEID_OLD:
9050 *cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
9051 goto end;
9052 case NFS4_CHECK_STATEID_BAD:
9053 *cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
9054 goto end;
9055 case NFS4_CHECK_STATEID_EXPIRED:
9056 *cs->statusp = resp->status = NFS4ERR_EXPIRED;
9057 goto end;
9058 case NFS4_CHECK_STATEID_CLOSED:
9059 *cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
9060 goto end;
9061 case NFS4_CHECK_STATEID_REPLAY:
9062 switch (rfs4_check_lock_seqid(
9063 args->locker.locker4_u.lock_owner.lock_seqid,
9064 lsp, resop)) {
9065 case NFS4_CHKSEQ_OKAY:
9066 /*
9067 * This is a replayed stateid; if
9068 * seqid matches the next expected,
9069 * then client is using wrong seqid.
9070 */
9071 case NFS4_CHKSEQ_BAD:
9072 *cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
9073 goto end;
9074 case NFS4_CHKSEQ_REPLAY:
9075 rfs4_update_lease(lsp->rls_locker->rl_client);
9076 *cs->statusp = status = resp->status;
9077 goto end;
9078 }
9079 break;
9080 default:
9081 ASSERT(FALSE);
9082 break;
9083 }
9084
9085 rfs4_update_lock_sequence(lsp);
9086 rfs4_update_lease(lsp->rls_locker->rl_client);
9087 }
9088
9089 /*
9090 * NFS4 only allows locking on regular files, so
9091 * verify type of object.
9092 */
9093 if (cs->vp->v_type != VREG) {
9094 if (cs->vp->v_type == VDIR)
9095 status = NFS4ERR_ISDIR;
9096 else
9097 status = NFS4ERR_INVAL;
9098 goto out;
9099 }
9100
9101 cp = lsp->rls_state->rs_owner->ro_client;
9102
9103 if (rfs4_clnt_in_grace(cp) && !args->reclaim) {
9104 status = NFS4ERR_GRACE;
9105 goto out;
9106 }
9107
9108 if (rfs4_clnt_in_grace(cp) && args->reclaim && !cp->rc_can_reclaim) {
9109 status = NFS4ERR_NO_GRACE;
9110 goto out;
9111 }
9112
9113 if (!rfs4_clnt_in_grace(cp) && args->reclaim) {
9114 status = NFS4ERR_NO_GRACE;
9115 goto out;
9116 }
9117
9118 if (lsp->rls_state->rs_finfo->rf_dinfo.rd_dtype == OPEN_DELEGATE_WRITE)
9119 cs->deleg = TRUE;
9120
9121 status = rfs4_do_lock(lsp, args->locktype,
9122 args->offset, args->length, cs->cr, resop);
9123
9124 out:
9125 lsp->rls_skip_seqid_check = FALSE;
9126
9127 *cs->statusp = resp->status = status;
9128
9129 if (status == NFS4_OK) {
9130 resp->LOCK4res_u.lock_stateid = lsp->rls_lockid.stateid;
9131 lsp->rls_lock_completed = TRUE;
9132 }
9133 /*
9134 * Only update the "OPEN" response here if this was a new
9135 * lock_owner
9136 */
9137 if (sp)
9138 rfs4_update_open_resp(sp->rs_owner, resop, NULL);
9139
9140 rfs4_update_lock_resp(lsp, resop);
9141
9142 end:
9143 if (lsp) {
9144 if (ls_sw_held)
9145 rfs4_sw_exit(&lsp->rls_sw);
9146 /*
9147 * If an sp obtained, then the lsp does not represent
9148 * a lock on the file struct.
9149 */
9150 if (sp != NULL)
9151 rfs4_lo_state_rele(lsp, FALSE);
9152 else
9153 rfs4_lo_state_rele(lsp, TRUE);
9154 }
9155 if (sp) {
9156 rfs4_sw_exit(&sp->rs_owner->ro_sw);
9157 rfs4_state_rele(sp);
9158 }
9159
9160 DTRACE_NFSV4_2(op__lock__done, struct compound_state *, cs,
9161 LOCK4res *, resp);
9162 }
9163
9164 /* free function for LOCK/LOCKT */
9165 static void
lock_denied_free(nfs_resop4 * resop)9166 lock_denied_free(nfs_resop4 *resop)
9167 {
9168 LOCK4denied *dp = NULL;
9169
9170 switch (resop->resop) {
9171 case OP_LOCK:
9172 if (resop->nfs_resop4_u.oplock.status == NFS4ERR_DENIED)
9173 dp = &resop->nfs_resop4_u.oplock.LOCK4res_u.denied;
9174 break;
9175 case OP_LOCKT:
9176 if (resop->nfs_resop4_u.oplockt.status == NFS4ERR_DENIED)
9177 dp = &resop->nfs_resop4_u.oplockt.denied;
9178 break;
9179 default:
9180 break;
9181 }
9182
9183 if (dp)
9184 kmem_free(dp->owner.owner_val, dp->owner.owner_len);
9185 }
9186
9187 /*ARGSUSED*/
9188 void
rfs4_op_locku(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)9189 rfs4_op_locku(nfs_argop4 *argop, nfs_resop4 *resop,
9190 struct svc_req *req, struct compound_state *cs)
9191 {
9192 LOCKU4args *args = &argop->nfs_argop4_u.oplocku;
9193 LOCKU4res *resp = &resop->nfs_resop4_u.oplocku;
9194 nfsstat4 status;
9195 stateid4 *stateid = &args->lock_stateid;
9196 rfs4_lo_state_t *lsp;
9197
9198 DTRACE_NFSV4_2(op__locku__start, struct compound_state *, cs,
9199 LOCKU4args *, args);
9200
9201 if (cs->vp == NULL) {
9202 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
9203 DTRACE_NFSV4_2(op__locku__done, struct compound_state *, cs,
9204 LOCKU4res *, resp);
9205 return;
9206 }
9207
9208 if ((status = rfs4_get_lo_state(stateid, &lsp, TRUE)) != NFS4_OK) {
9209 *cs->statusp = resp->status = status;
9210 DTRACE_NFSV4_2(op__locku__done, struct compound_state *, cs,
9211 LOCKU4res *, resp);
9212 return;
9213 }
9214
9215 /* Ensure specified filehandle matches */
9216 if (cs->vp != lsp->rls_state->rs_finfo->rf_vp) {
9217 rfs4_lo_state_rele(lsp, TRUE);
9218 *cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
9219 DTRACE_NFSV4_2(op__locku__done, struct compound_state *, cs,
9220 LOCKU4res *, resp);
9221 return;
9222 }
9223
9224 /* hold off other access to lsp while we tinker */
9225 rfs4_sw_enter(&lsp->rls_sw);
9226
9227 switch (rfs4_check_lo_stateid_seqid(lsp, stateid)) {
9228 case NFS4_CHECK_STATEID_OKAY:
9229 if (rfs4_check_lock_seqid(args->seqid, lsp, resop)
9230 != NFS4_CHKSEQ_OKAY) {
9231 *cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
9232 goto end;
9233 }
9234 break;
9235 case NFS4_CHECK_STATEID_OLD:
9236 *cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
9237 goto end;
9238 case NFS4_CHECK_STATEID_BAD:
9239 *cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
9240 goto end;
9241 case NFS4_CHECK_STATEID_EXPIRED:
9242 *cs->statusp = resp->status = NFS4ERR_EXPIRED;
9243 goto end;
9244 case NFS4_CHECK_STATEID_CLOSED:
9245 *cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
9246 goto end;
9247 case NFS4_CHECK_STATEID_REPLAY:
9248 switch (rfs4_check_lock_seqid(args->seqid, lsp, resop)) {
9249 case NFS4_CHKSEQ_OKAY:
9250 /*
9251 * This is a replayed stateid; if
9252 * seqid matches the next expected,
9253 * then client is using wrong seqid.
9254 */
9255 case NFS4_CHKSEQ_BAD:
9256 *cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
9257 goto end;
9258 case NFS4_CHKSEQ_REPLAY:
9259 rfs4_update_lease(lsp->rls_locker->rl_client);
9260 *cs->statusp = status = resp->status;
9261 goto end;
9262 }
9263 break;
9264 default:
9265 ASSERT(FALSE);
9266 break;
9267 }
9268
9269 rfs4_update_lock_sequence(lsp);
9270 rfs4_update_lease(lsp->rls_locker->rl_client);
9271
9272 /*
9273 * NFS4 only allows locking on regular files, so
9274 * verify type of object.
9275 */
9276 if (cs->vp->v_type != VREG) {
9277 if (cs->vp->v_type == VDIR)
9278 status = NFS4ERR_ISDIR;
9279 else
9280 status = NFS4ERR_INVAL;
9281 goto out;
9282 }
9283
9284 if (rfs4_clnt_in_grace(lsp->rls_state->rs_owner->ro_client)) {
9285 status = NFS4ERR_GRACE;
9286 goto out;
9287 }
9288
9289 status = rfs4_do_lock(lsp, args->locktype,
9290 args->offset, args->length, cs->cr, resop);
9291
9292 out:
9293 *cs->statusp = resp->status = status;
9294
9295 if (status == NFS4_OK)
9296 resp->lock_stateid = lsp->rls_lockid.stateid;
9297
9298 rfs4_update_lock_resp(lsp, resop);
9299
9300 end:
9301 rfs4_sw_exit(&lsp->rls_sw);
9302 rfs4_lo_state_rele(lsp, TRUE);
9303
9304 DTRACE_NFSV4_2(op__locku__done, struct compound_state *, cs,
9305 LOCKU4res *, resp);
9306 }
9307
9308 /*
9309 * LOCKT is a best effort routine, the client can not be guaranteed that
9310 * the status return is still in effect by the time the reply is received.
9311 * They are numerous race conditions in this routine, but we are not required
9312 * and can not be accurate.
9313 */
9314 /*ARGSUSED*/
9315 void
rfs4_op_lockt(nfs_argop4 * argop,nfs_resop4 * resop,struct svc_req * req,struct compound_state * cs)9316 rfs4_op_lockt(nfs_argop4 *argop, nfs_resop4 *resop,
9317 struct svc_req *req, struct compound_state *cs)
9318 {
9319 LOCKT4args *args = &argop->nfs_argop4_u.oplockt;
9320 LOCKT4res *resp = &resop->nfs_resop4_u.oplockt;
9321 rfs4_lockowner_t *lo;
9322 rfs4_client_t *cp;
9323 bool_t create = FALSE;
9324 struct flock64 flk;
9325 int error;
9326 int flag = FREAD | FWRITE;
9327 int ltype;
9328 length4 posix_length;
9329 sysid_t sysid;
9330 pid_t pid;
9331
9332 DTRACE_NFSV4_2(op__lockt__start, struct compound_state *, cs,
9333 LOCKT4args *, args);
9334
9335 if (cs->vp == NULL) {
9336 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
9337 goto out;
9338 }
9339
9340 /*
9341 * NFS4 only allows locking on regular files, so
9342 * verify type of object.
9343 */
9344 if (cs->vp->v_type != VREG) {
9345 if (cs->vp->v_type == VDIR)
9346 *cs->statusp = resp->status = NFS4ERR_ISDIR;
9347 else
9348 *cs->statusp = resp->status = NFS4ERR_INVAL;
9349 goto out;
9350 }
9351
9352 /*
9353 * Check out the clientid to ensure the server knows about it
9354 * so that we correctly inform the client of a server reboot.
9355 */
9356 if ((cp = rfs4_findclient_by_id(args->owner.clientid, FALSE))
9357 == NULL) {
9358 *cs->statusp = resp->status =
9359 rfs4_check_clientid(&args->owner.clientid, 0);
9360 goto out;
9361 }
9362 if (rfs4_lease_expired(cp)) {
9363 rfs4_client_close(cp);
9364 /*
9365 * Protocol doesn't allow returning NFS4ERR_STALE as
9366 * other operations do on this check so STALE_CLIENTID
9367 * is returned instead
9368 */
9369 *cs->statusp = resp->status = NFS4ERR_STALE_CLIENTID;
9370 goto out;
9371 }
9372
9373 if (rfs4_clnt_in_grace(cp) && !(cp->rc_can_reclaim)) {
9374 *cs->statusp = resp->status = NFS4ERR_GRACE;
9375 rfs4_client_rele(cp);
9376 goto out;
9377 }
9378 rfs4_client_rele(cp);
9379
9380 resp->status = NFS4_OK;
9381
9382 switch (args->locktype) {
9383 case READ_LT:
9384 case READW_LT:
9385 ltype = F_RDLCK;
9386 break;
9387 case WRITE_LT:
9388 case WRITEW_LT:
9389 ltype = F_WRLCK;
9390 break;
9391 }
9392
9393 posix_length = args->length;
9394 /* Check for zero length. To lock to end of file use all ones for V4 */
9395 if (posix_length == 0) {
9396 *cs->statusp = resp->status = NFS4ERR_INVAL;
9397 goto out;
9398 } else if (posix_length == (length4)(~0)) {
9399 posix_length = 0; /* Posix to end of file */
9400 }
9401
9402 /* Find or create a lockowner */
9403 lo = rfs4_findlockowner(&args->owner, &create);
9404
9405 if (lo) {
9406 pid = lo->rl_pid;
9407 if ((resp->status =
9408 rfs4_client_sysid(lo->rl_client, &sysid)) != NFS4_OK)
9409 goto err;
9410 } else {
9411 pid = 0;
9412 sysid = lockt_sysid;
9413 }
9414 retry:
9415 flk.l_type = ltype;
9416 flk.l_whence = 0; /* SEEK_SET */
9417 flk.l_start = args->offset;
9418 flk.l_len = posix_length;
9419 flk.l_sysid = sysid;
9420 flk.l_pid = pid;
9421 flag |= F_REMOTELOCK;
9422
9423 LOCK_PRINT(rfs4_debug, "rfs4_op_lockt", F_GETLK, &flk);
9424
9425 /* Note that length4 is uint64_t but l_len and l_start are off64_t */
9426 if (flk.l_len < 0 || flk.l_start < 0) {
9427 resp->status = NFS4ERR_INVAL;
9428 goto err;
9429 }
9430 error = VOP_FRLOCK(cs->vp, F_GETLK, &flk, flag, (u_offset_t)0,
9431 NULL, cs->cr, NULL);
9432
9433 /*
9434 * N.B. We map error values to nfsv4 errors. This is differrent
9435 * than puterrno4 routine.
9436 */
9437 switch (error) {
9438 case 0:
9439 if (flk.l_type == F_UNLCK)
9440 resp->status = NFS4_OK;
9441 else {
9442 if (lock_denied(&resp->denied, &flk) == NFS4ERR_EXPIRED)
9443 goto retry;
9444 resp->status = NFS4ERR_DENIED;
9445 }
9446 break;
9447 case EOVERFLOW:
9448 resp->status = NFS4ERR_INVAL;
9449 break;
9450 case EINVAL:
9451 resp->status = NFS4ERR_NOTSUPP;
9452 break;
9453 default:
9454 cmn_err(CE_WARN, "rfs4_op_lockt: unexpected errno (%d)",
9455 error);
9456 resp->status = NFS4ERR_SERVERFAULT;
9457 break;
9458 }
9459
9460 err:
9461 if (lo)
9462 rfs4_lockowner_rele(lo);
9463 *cs->statusp = resp->status;
9464 out:
9465 DTRACE_NFSV4_2(op__lockt__done, struct compound_state *, cs,
9466 LOCKT4res *, resp);
9467 }
9468
9469 int
rfs4_share(rfs4_state_t * sp,uint32_t access,uint32_t deny)9470 rfs4_share(rfs4_state_t *sp, uint32_t access, uint32_t deny)
9471 {
9472 int err;
9473 int cmd;
9474 vnode_t *vp;
9475 struct shrlock shr;
9476 struct shr_locowner shr_loco;
9477 int fflags = 0;
9478
9479 ASSERT(rfs4_dbe_islocked(sp->rs_dbe));
9480 ASSERT(sp->rs_owner->ro_client->rc_sysidt != LM_NOSYSID);
9481
9482 if (sp->rs_closed)
9483 return (NFS4ERR_OLD_STATEID);
9484
9485 vp = sp->rs_finfo->rf_vp;
9486 ASSERT(vp);
9487
9488 shr.s_access = shr.s_deny = 0;
9489
9490 if (access & OPEN4_SHARE_ACCESS_READ) {
9491 fflags |= FREAD;
9492 shr.s_access |= F_RDACC;
9493 }
9494 if (access & OPEN4_SHARE_ACCESS_WRITE) {
9495 fflags |= FWRITE;
9496 shr.s_access |= F_WRACC;
9497 }
9498 ASSERT(shr.s_access);
9499
9500 if (deny & OPEN4_SHARE_DENY_READ)
9501 shr.s_deny |= F_RDDNY;
9502 if (deny & OPEN4_SHARE_DENY_WRITE)
9503 shr.s_deny |= F_WRDNY;
9504
9505 shr.s_pid = rfs4_dbe_getid(sp->rs_owner->ro_dbe);
9506 shr.s_sysid = sp->rs_owner->ro_client->rc_sysidt;
9507 shr_loco.sl_pid = shr.s_pid;
9508 shr_loco.sl_id = shr.s_sysid;
9509 shr.s_owner = (caddr_t)&shr_loco;
9510 shr.s_own_len = sizeof (shr_loco);
9511
9512 cmd = nbl_need_check(vp) ? F_SHARE_NBMAND : F_SHARE;
9513
9514 err = VOP_SHRLOCK(vp, cmd, &shr, fflags, CRED(), NULL);
9515 if (err != 0) {
9516 if (err == EAGAIN)
9517 err = NFS4ERR_SHARE_DENIED;
9518 else
9519 err = puterrno4(err);
9520 return (err);
9521 }
9522
9523 sp->rs_share_access |= access;
9524 sp->rs_share_deny |= deny;
9525
9526 return (0);
9527 }
9528
9529 int
rfs4_unshare(rfs4_state_t * sp)9530 rfs4_unshare(rfs4_state_t *sp)
9531 {
9532 int err;
9533 struct shrlock shr;
9534 struct shr_locowner shr_loco;
9535
9536 ASSERT(rfs4_dbe_islocked(sp->rs_dbe));
9537
9538 if (sp->rs_closed || sp->rs_share_access == 0)
9539 return (0);
9540
9541 ASSERT(sp->rs_owner->ro_client->rc_sysidt != LM_NOSYSID);
9542 ASSERT(sp->rs_finfo->rf_vp);
9543
9544 shr.s_access = shr.s_deny = 0;
9545 shr.s_pid = rfs4_dbe_getid(sp->rs_owner->ro_dbe);
9546 shr.s_sysid = sp->rs_owner->ro_client->rc_sysidt;
9547 shr_loco.sl_pid = shr.s_pid;
9548 shr_loco.sl_id = shr.s_sysid;
9549 shr.s_owner = (caddr_t)&shr_loco;
9550 shr.s_own_len = sizeof (shr_loco);
9551
9552 err = VOP_SHRLOCK(sp->rs_finfo->rf_vp, F_UNSHARE, &shr, 0, CRED(),
9553 NULL);
9554 if (err != 0) {
9555 err = puterrno4(err);
9556 return (err);
9557 }
9558
9559 sp->rs_share_access = 0;
9560 sp->rs_share_deny = 0;
9561
9562 return (0);
9563
9564 }
9565
9566 static int
rdma_setup_read_data4(READ4args * args,READ4res * rok)9567 rdma_setup_read_data4(READ4args *args, READ4res *rok)
9568 {
9569 struct clist *wcl;
9570 count4 count = rok->data_len;
9571 int wlist_len;
9572
9573 wcl = args->wlist;
9574 if (rdma_setup_read_chunks(wcl, count, &wlist_len) == FALSE) {
9575 return (FALSE);
9576 }
9577 wcl = args->wlist;
9578 rok->wlist_len = wlist_len;
9579 rok->wlist = wcl;
9580 return (TRUE);
9581 }
9582
9583 /* tunable to disable server referrals */
9584 int rfs4_no_referrals = 0;
9585
9586 /*
9587 * Find an NFS record in reparse point data.
9588 * Returns 0 for success and <0 or an errno value on failure.
9589 */
9590 int
vn_find_nfs_record(vnode_t * vp,nvlist_t ** nvlp,char ** svcp,char ** datap)9591 vn_find_nfs_record(vnode_t *vp, nvlist_t **nvlp, char **svcp, char **datap)
9592 {
9593 int err;
9594 char *stype, *val;
9595 nvlist_t *nvl;
9596 nvpair_t *curr;
9597
9598 if ((nvl = reparse_init()) == NULL)
9599 return (-1);
9600
9601 if ((err = reparse_vnode_parse(vp, nvl)) != 0) {
9602 reparse_free(nvl);
9603 return (err);
9604 }
9605
9606 curr = NULL;
9607 while ((curr = nvlist_next_nvpair(nvl, curr)) != NULL) {
9608 if ((stype = nvpair_name(curr)) == NULL) {
9609 reparse_free(nvl);
9610 return (-2);
9611 }
9612 if (strncasecmp(stype, "NFS", 3) == 0)
9613 break;
9614 }
9615
9616 if ((curr == NULL) ||
9617 (nvpair_value_string(curr, &val))) {
9618 reparse_free(nvl);
9619 return (-3);
9620 }
9621 *nvlp = nvl;
9622 *svcp = stype;
9623 *datap = val;
9624 return (0);
9625 }
9626
9627 int
vn_is_nfs_reparse(vnode_t * vp,cred_t * cr)9628 vn_is_nfs_reparse(vnode_t *vp, cred_t *cr)
9629 {
9630 nvlist_t *nvl;
9631 char *s, *d;
9632
9633 if (rfs4_no_referrals != 0)
9634 return (B_FALSE);
9635
9636 if (vn_is_reparse(vp, cr, NULL) == B_FALSE)
9637 return (B_FALSE);
9638
9639 if (vn_find_nfs_record(vp, &nvl, &s, &d) != 0)
9640 return (B_FALSE);
9641
9642 reparse_free(nvl);
9643
9644 return (B_TRUE);
9645 }
9646
9647 /*
9648 * There is a user-level copy of this routine in ref_subr.c.
9649 * Changes should be kept in sync.
9650 */
9651 static int
nfs4_create_components(char * path,component4 * comp4)9652 nfs4_create_components(char *path, component4 *comp4)
9653 {
9654 int slen, plen, ncomp;
9655 char *ori_path, *nxtc, buf[MAXNAMELEN];
9656
9657 if (path == NULL)
9658 return (0);
9659
9660 plen = strlen(path) + 1; /* include the terminator */
9661 ori_path = path;
9662 ncomp = 0;
9663
9664 /* count number of components in the path */
9665 for (nxtc = path; nxtc < ori_path + plen; nxtc++) {
9666 if (*nxtc == '/' || *nxtc == '\0' || *nxtc == '\n') {
9667 if ((slen = nxtc - path) == 0) {
9668 path = nxtc + 1;
9669 continue;
9670 }
9671
9672 if (comp4 != NULL) {
9673 bcopy(path, buf, slen);
9674 buf[slen] = '\0';
9675 (void) str_to_utf8(buf, &comp4[ncomp]);
9676 }
9677
9678 ncomp++; /* 1 valid component */
9679 path = nxtc + 1;
9680 }
9681 if (*nxtc == '\0' || *nxtc == '\n')
9682 break;
9683 }
9684
9685 return (ncomp);
9686 }
9687
9688 /*
9689 * There is a user-level copy of this routine in ref_subr.c.
9690 * Changes should be kept in sync.
9691 */
9692 static int
make_pathname4(char * path,pathname4 * pathname)9693 make_pathname4(char *path, pathname4 *pathname)
9694 {
9695 int ncomp;
9696 component4 *comp4;
9697
9698 if (pathname == NULL)
9699 return (0);
9700
9701 if (path == NULL) {
9702 pathname->pathname4_val = NULL;
9703 pathname->pathname4_len = 0;
9704 return (0);
9705 }
9706
9707 /* count number of components to alloc buffer */
9708 if ((ncomp = nfs4_create_components(path, NULL)) == 0) {
9709 pathname->pathname4_val = NULL;
9710 pathname->pathname4_len = 0;
9711 return (0);
9712 }
9713 comp4 = kmem_zalloc(ncomp * sizeof (component4), KM_SLEEP);
9714
9715 /* copy components into allocated buffer */
9716 ncomp = nfs4_create_components(path, comp4);
9717
9718 pathname->pathname4_val = comp4;
9719 pathname->pathname4_len = ncomp;
9720
9721 return (ncomp);
9722 }
9723
9724 #define xdr_fs_locations4 xdr_fattr4_fs_locations
9725
9726 fs_locations4 *
fetch_referral(vnode_t * vp,cred_t * cr)9727 fetch_referral(vnode_t *vp, cred_t *cr)
9728 {
9729 nvlist_t *nvl;
9730 char *stype, *sdata;
9731 fs_locations4 *result;
9732 char buf[1024];
9733 size_t bufsize;
9734 XDR xdr;
9735 int err;
9736
9737 /*
9738 * Check attrs to ensure it's a reparse point
9739 */
9740 if (vn_is_reparse(vp, cr, NULL) == B_FALSE)
9741 return (NULL);
9742
9743 /*
9744 * Look for an NFS record and get the type and data
9745 */
9746 if (vn_find_nfs_record(vp, &nvl, &stype, &sdata) != 0)
9747 return (NULL);
9748
9749 /*
9750 * With the type and data, upcall to get the referral
9751 */
9752 bufsize = sizeof (buf);
9753 bzero(buf, sizeof (buf));
9754 err = reparse_kderef((const char *)stype, (const char *)sdata,
9755 buf, &bufsize);
9756 reparse_free(nvl);
9757
9758 DTRACE_PROBE4(nfs4serv__func__referral__upcall,
9759 char *, stype, char *, sdata, char *, buf, int, err);
9760 if (err) {
9761 cmn_err(CE_NOTE,
9762 "reparsed daemon not running: unable to get referral (%d)",
9763 err);
9764 return (NULL);
9765 }
9766
9767 /*
9768 * We get an XDR'ed record back from the kderef call
9769 */
9770 xdrmem_create(&xdr, buf, bufsize, XDR_DECODE);
9771 result = kmem_alloc(sizeof (fs_locations4), KM_SLEEP);
9772 err = xdr_fs_locations4(&xdr, result);
9773 XDR_DESTROY(&xdr);
9774 if (err != TRUE) {
9775 DTRACE_PROBE1(nfs4serv__func__referral__upcall__xdrfail,
9776 int, err);
9777 return (NULL);
9778 }
9779
9780 /*
9781 * Look at path to recover fs_root, ignoring the leading '/'
9782 */
9783 (void) make_pathname4(vp->v_path, &result->fs_root);
9784
9785 return (result);
9786 }
9787
9788 char *
build_symlink(vnode_t * vp,cred_t * cr,size_t * strsz)9789 build_symlink(vnode_t *vp, cred_t *cr, size_t *strsz)
9790 {
9791 fs_locations4 *fsl;
9792 fs_location4 *fs;
9793 char *server, *path, *symbuf;
9794 static char *prefix = "/net/";
9795 int i, size, npaths;
9796 uint_t len;
9797
9798 /* Get the referral */
9799 if ((fsl = fetch_referral(vp, cr)) == NULL)
9800 return (NULL);
9801
9802 /* Deal with only the first location and first server */
9803 fs = &fsl->locations_val[0];
9804 server = utf8_to_str(&fs->server_val[0], &len, NULL);
9805 if (server == NULL) {
9806 rfs4_free_fs_locations4(fsl);
9807 kmem_free(fsl, sizeof (fs_locations4));
9808 return (NULL);
9809 }
9810
9811 /* Figure out size for "/net/" + host + /path/path/path + NULL */
9812 size = strlen(prefix) + len;
9813 for (i = 0; i < fs->rootpath.pathname4_len; i++)
9814 size += fs->rootpath.pathname4_val[i].utf8string_len + 1;
9815
9816 /* Allocate the symlink buffer and fill it */
9817 symbuf = kmem_zalloc(size, KM_SLEEP);
9818 (void) strcat(symbuf, prefix);
9819 (void) strcat(symbuf, server);
9820 kmem_free(server, len);
9821
9822 npaths = 0;
9823 for (i = 0; i < fs->rootpath.pathname4_len; i++) {
9824 path = utf8_to_str(&fs->rootpath.pathname4_val[i], &len, NULL);
9825 if (path == NULL)
9826 continue;
9827 (void) strcat(symbuf, "/");
9828 (void) strcat(symbuf, path);
9829 npaths++;
9830 kmem_free(path, len);
9831 }
9832
9833 rfs4_free_fs_locations4(fsl);
9834 kmem_free(fsl, sizeof (fs_locations4));
9835
9836 if (strsz != NULL)
9837 *strsz = size;
9838 return (symbuf);
9839 }
9840
9841 /*
9842 * Check to see if we have a downrev Solaris client, so that we
9843 * can send it a symlink instead of a referral.
9844 */
9845 int
client_is_downrev(struct svc_req * req)9846 client_is_downrev(struct svc_req *req)
9847 {
9848 struct sockaddr *ca;
9849 rfs4_clntip_t *ci;
9850 bool_t create = FALSE;
9851 int is_downrev;
9852
9853 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
9854 ASSERT(ca);
9855 ci = rfs4_find_clntip(ca, &create);
9856 if (ci == NULL)
9857 return (0);
9858 is_downrev = ci->ri_no_referrals;
9859 rfs4_dbe_rele(ci->ri_dbe);
9860 return (is_downrev);
9861 }
9862