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