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