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