1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Rick Macklem at The University of Guelph. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 */ 35 36 #include <sys/cdefs.h> 37 __FBSDID("$FreeBSD$"); 38 39 #include <sys/capsicum.h> 40 41 /* 42 * Functions that perform the vfs operations required by the routines in 43 * nfsd_serv.c. It is hoped that this change will make the server more 44 * portable. 45 */ 46 47 #include <fs/nfs/nfsport.h> 48 #include <sys/hash.h> 49 #include <sys/sysctl.h> 50 #include <nlm/nlm_prot.h> 51 #include <nlm/nlm.h> 52 53 FEATURE(nfsd, "NFSv4 server"); 54 55 extern u_int32_t newnfs_true, newnfs_false, newnfs_xdrneg1; 56 extern int nfsrv_useacl; 57 extern int newnfs_numnfsd; 58 extern struct mount nfsv4root_mnt; 59 extern struct nfsrv_stablefirst nfsrv_stablefirst; 60 extern void (*nfsd_call_servertimer)(void); 61 extern SVCPOOL *nfsrvd_pool; 62 extern struct nfsv4lock nfsd_suspend_lock; 63 extern struct nfsclienthashhead *nfsclienthash; 64 extern struct nfslockhashhead *nfslockhash; 65 extern struct nfssessionhash *nfssessionhash; 66 extern int nfsrv_sessionhashsize; 67 extern struct nfsstatsv1 nfsstatsv1; 68 struct vfsoptlist nfsv4root_opt, nfsv4root_newopt; 69 NFSDLOCKMUTEX; 70 struct nfsrchash_bucket nfsrchash_table[NFSRVCACHE_HASHSIZE]; 71 struct nfsrchash_bucket nfsrcahash_table[NFSRVCACHE_HASHSIZE]; 72 struct mtx nfsrc_udpmtx; 73 struct mtx nfs_v4root_mutex; 74 struct nfsrvfh nfs_rootfh, nfs_pubfh; 75 int nfs_pubfhset = 0, nfs_rootfhset = 0; 76 struct proc *nfsd_master_proc = NULL; 77 int nfsd_debuglevel = 0; 78 static pid_t nfsd_master_pid = (pid_t)-1; 79 static char nfsd_master_comm[MAXCOMLEN + 1]; 80 static struct timeval nfsd_master_start; 81 static uint32_t nfsv4_sysid = 0; 82 83 static int nfssvc_srvcall(struct thread *, struct nfssvc_args *, 84 struct ucred *); 85 86 int nfsrv_enable_crossmntpt = 1; 87 static int nfs_commit_blks; 88 static int nfs_commit_miss; 89 extern int nfsrv_issuedelegs; 90 extern int nfsrv_dolocallocks; 91 extern int nfsd_enable_stringtouid; 92 93 SYSCTL_NODE(_vfs, OID_AUTO, nfsd, CTLFLAG_RW, 0, "NFS server"); 94 SYSCTL_INT(_vfs_nfsd, OID_AUTO, mirrormnt, CTLFLAG_RW, 95 &nfsrv_enable_crossmntpt, 0, "Enable nfsd to cross mount points"); 96 SYSCTL_INT(_vfs_nfsd, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 97 0, ""); 98 SYSCTL_INT(_vfs_nfsd, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, 99 0, ""); 100 SYSCTL_INT(_vfs_nfsd, OID_AUTO, issue_delegations, CTLFLAG_RW, 101 &nfsrv_issuedelegs, 0, "Enable nfsd to issue delegations"); 102 SYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_locallocks, CTLFLAG_RW, 103 &nfsrv_dolocallocks, 0, "Enable nfsd to acquire local locks on files"); 104 SYSCTL_INT(_vfs_nfsd, OID_AUTO, debuglevel, CTLFLAG_RW, &nfsd_debuglevel, 105 0, "Debug level for NFS server"); 106 SYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_stringtouid, CTLFLAG_RW, 107 &nfsd_enable_stringtouid, 0, "Enable nfsd to accept numeric owner_names"); 108 109 #define MAX_REORDERED_RPC 16 110 #define NUM_HEURISTIC 1031 111 #define NHUSE_INIT 64 112 #define NHUSE_INC 16 113 #define NHUSE_MAX 2048 114 115 static struct nfsheur { 116 struct vnode *nh_vp; /* vp to match (unreferenced pointer) */ 117 off_t nh_nextoff; /* next offset for sequential detection */ 118 int nh_use; /* use count for selection */ 119 int nh_seqcount; /* heuristic */ 120 } nfsheur[NUM_HEURISTIC]; 121 122 123 /* 124 * Heuristic to detect sequential operation. 125 */ 126 static struct nfsheur * 127 nfsrv_sequential_heuristic(struct uio *uio, struct vnode *vp) 128 { 129 struct nfsheur *nh; 130 int hi, try; 131 132 /* Locate best candidate. */ 133 try = 32; 134 hi = ((int)(vm_offset_t)vp / sizeof(struct vnode)) % NUM_HEURISTIC; 135 nh = &nfsheur[hi]; 136 while (try--) { 137 if (nfsheur[hi].nh_vp == vp) { 138 nh = &nfsheur[hi]; 139 break; 140 } 141 if (nfsheur[hi].nh_use > 0) 142 --nfsheur[hi].nh_use; 143 hi = (hi + 1) % NUM_HEURISTIC; 144 if (nfsheur[hi].nh_use < nh->nh_use) 145 nh = &nfsheur[hi]; 146 } 147 148 /* Initialize hint if this is a new file. */ 149 if (nh->nh_vp != vp) { 150 nh->nh_vp = vp; 151 nh->nh_nextoff = uio->uio_offset; 152 nh->nh_use = NHUSE_INIT; 153 if (uio->uio_offset == 0) 154 nh->nh_seqcount = 4; 155 else 156 nh->nh_seqcount = 1; 157 } 158 159 /* Calculate heuristic. */ 160 if ((uio->uio_offset == 0 && nh->nh_seqcount > 0) || 161 uio->uio_offset == nh->nh_nextoff) { 162 /* See comments in vfs_vnops.c:sequential_heuristic(). */ 163 nh->nh_seqcount += howmany(uio->uio_resid, 16384); 164 if (nh->nh_seqcount > IO_SEQMAX) 165 nh->nh_seqcount = IO_SEQMAX; 166 } else if (qabs(uio->uio_offset - nh->nh_nextoff) <= MAX_REORDERED_RPC * 167 imax(vp->v_mount->mnt_stat.f_iosize, uio->uio_resid)) { 168 /* Probably a reordered RPC, leave seqcount alone. */ 169 } else if (nh->nh_seqcount > 1) { 170 nh->nh_seqcount /= 2; 171 } else { 172 nh->nh_seqcount = 0; 173 } 174 nh->nh_use += NHUSE_INC; 175 if (nh->nh_use > NHUSE_MAX) 176 nh->nh_use = NHUSE_MAX; 177 return (nh); 178 } 179 180 /* 181 * Get attributes into nfsvattr structure. 182 */ 183 int 184 nfsvno_getattr(struct vnode *vp, struct nfsvattr *nvap, struct ucred *cred, 185 struct thread *p, int vpislocked) 186 { 187 int error, lockedit = 0; 188 189 if (vpislocked == 0) { 190 /* 191 * When vpislocked == 0, the vnode is either exclusively 192 * locked by this thread or not locked by this thread. 193 * As such, shared lock it, if not exclusively locked. 194 */ 195 if (NFSVOPISLOCKED(vp) != LK_EXCLUSIVE) { 196 lockedit = 1; 197 NFSVOPLOCK(vp, LK_SHARED | LK_RETRY); 198 } 199 } 200 error = VOP_GETATTR(vp, &nvap->na_vattr, cred); 201 if (lockedit != 0) 202 NFSVOPUNLOCK(vp, 0); 203 204 NFSEXITCODE(error); 205 return (error); 206 } 207 208 /* 209 * Get a file handle for a vnode. 210 */ 211 int 212 nfsvno_getfh(struct vnode *vp, fhandle_t *fhp, struct thread *p) 213 { 214 int error; 215 216 NFSBZERO((caddr_t)fhp, sizeof(fhandle_t)); 217 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 218 error = VOP_VPTOFH(vp, &fhp->fh_fid); 219 220 NFSEXITCODE(error); 221 return (error); 222 } 223 224 /* 225 * Perform access checking for vnodes obtained from file handles that would 226 * refer to files already opened by a Unix client. You cannot just use 227 * vn_writechk() and VOP_ACCESSX() for two reasons. 228 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write 229 * case. 230 * 2 - The owner is to be given access irrespective of mode bits for some 231 * operations, so that processes that chmod after opening a file don't 232 * break. 233 */ 234 int 235 nfsvno_accchk(struct vnode *vp, accmode_t accmode, struct ucred *cred, 236 struct nfsexstuff *exp, struct thread *p, int override, int vpislocked, 237 u_int32_t *supportedtypep) 238 { 239 struct vattr vattr; 240 int error = 0, getret = 0; 241 242 if (vpislocked == 0) { 243 if (NFSVOPLOCK(vp, LK_SHARED) != 0) { 244 error = EPERM; 245 goto out; 246 } 247 } 248 if (accmode & VWRITE) { 249 /* Just vn_writechk() changed to check rdonly */ 250 /* 251 * Disallow write attempts on read-only file systems; 252 * unless the file is a socket or a block or character 253 * device resident on the file system. 254 */ 255 if (NFSVNO_EXRDONLY(exp) || 256 (vp->v_mount->mnt_flag & MNT_RDONLY)) { 257 switch (vp->v_type) { 258 case VREG: 259 case VDIR: 260 case VLNK: 261 error = EROFS; 262 default: 263 break; 264 } 265 } 266 /* 267 * If there's shared text associated with 268 * the inode, try to free it up once. If 269 * we fail, we can't allow writing. 270 */ 271 if (VOP_IS_TEXT(vp) && error == 0) 272 error = ETXTBSY; 273 } 274 if (error != 0) { 275 if (vpislocked == 0) 276 NFSVOPUNLOCK(vp, 0); 277 goto out; 278 } 279 280 /* 281 * Should the override still be applied when ACLs are enabled? 282 */ 283 error = VOP_ACCESSX(vp, accmode, cred, p); 284 if (error != 0 && (accmode & (VDELETE | VDELETE_CHILD))) { 285 /* 286 * Try again with VEXPLICIT_DENY, to see if the test for 287 * deletion is supported. 288 */ 289 error = VOP_ACCESSX(vp, accmode | VEXPLICIT_DENY, cred, p); 290 if (error == 0) { 291 if (vp->v_type == VDIR) { 292 accmode &= ~(VDELETE | VDELETE_CHILD); 293 accmode |= VWRITE; 294 error = VOP_ACCESSX(vp, accmode, cred, p); 295 } else if (supportedtypep != NULL) { 296 *supportedtypep &= ~NFSACCESS_DELETE; 297 } 298 } 299 } 300 301 /* 302 * Allow certain operations for the owner (reads and writes 303 * on files that are already open). 304 */ 305 if (override != NFSACCCHK_NOOVERRIDE && 306 (error == EPERM || error == EACCES)) { 307 if (cred->cr_uid == 0 && (override & NFSACCCHK_ALLOWROOT)) 308 error = 0; 309 else if (override & NFSACCCHK_ALLOWOWNER) { 310 getret = VOP_GETATTR(vp, &vattr, cred); 311 if (getret == 0 && cred->cr_uid == vattr.va_uid) 312 error = 0; 313 } 314 } 315 if (vpislocked == 0) 316 NFSVOPUNLOCK(vp, 0); 317 318 out: 319 NFSEXITCODE(error); 320 return (error); 321 } 322 323 /* 324 * Set attribute(s) vnop. 325 */ 326 int 327 nfsvno_setattr(struct vnode *vp, struct nfsvattr *nvap, struct ucred *cred, 328 struct thread *p, struct nfsexstuff *exp) 329 { 330 int error; 331 332 error = VOP_SETATTR(vp, &nvap->na_vattr, cred); 333 NFSEXITCODE(error); 334 return (error); 335 } 336 337 /* 338 * Set up nameidata for a lookup() call and do it. 339 */ 340 int 341 nfsvno_namei(struct nfsrv_descript *nd, struct nameidata *ndp, 342 struct vnode *dp, int islocked, struct nfsexstuff *exp, struct thread *p, 343 struct vnode **retdirp) 344 { 345 struct componentname *cnp = &ndp->ni_cnd; 346 int i; 347 struct iovec aiov; 348 struct uio auio; 349 int lockleaf = (cnp->cn_flags & LOCKLEAF) != 0, linklen; 350 int error = 0, crossmnt; 351 char *cp; 352 353 *retdirp = NULL; 354 cnp->cn_nameptr = cnp->cn_pnbuf; 355 ndp->ni_lcf = 0; 356 /* 357 * Extract and set starting directory. 358 */ 359 if (dp->v_type != VDIR) { 360 if (islocked) 361 vput(dp); 362 else 363 vrele(dp); 364 nfsvno_relpathbuf(ndp); 365 error = ENOTDIR; 366 goto out1; 367 } 368 if (islocked) 369 NFSVOPUNLOCK(dp, 0); 370 VREF(dp); 371 *retdirp = dp; 372 if (NFSVNO_EXRDONLY(exp)) 373 cnp->cn_flags |= RDONLY; 374 ndp->ni_segflg = UIO_SYSSPACE; 375 crossmnt = 1; 376 377 if (nd->nd_flag & ND_PUBLOOKUP) { 378 ndp->ni_loopcnt = 0; 379 if (cnp->cn_pnbuf[0] == '/') { 380 vrele(dp); 381 /* 382 * Check for degenerate pathnames here, since lookup() 383 * panics on them. 384 */ 385 for (i = 1; i < ndp->ni_pathlen; i++) 386 if (cnp->cn_pnbuf[i] != '/') 387 break; 388 if (i == ndp->ni_pathlen) { 389 error = NFSERR_ACCES; 390 goto out; 391 } 392 dp = rootvnode; 393 VREF(dp); 394 } 395 } else if ((nfsrv_enable_crossmntpt == 0 && NFSVNO_EXPORTED(exp)) || 396 (nd->nd_flag & ND_NFSV4) == 0) { 397 /* 398 * Only cross mount points for NFSv4 when doing a 399 * mount while traversing the file system above 400 * the mount point, unless nfsrv_enable_crossmntpt is set. 401 */ 402 cnp->cn_flags |= NOCROSSMOUNT; 403 crossmnt = 0; 404 } 405 406 /* 407 * Initialize for scan, set ni_startdir and bump ref on dp again 408 * because lookup() will dereference ni_startdir. 409 */ 410 411 cnp->cn_thread = p; 412 ndp->ni_startdir = dp; 413 ndp->ni_rootdir = rootvnode; 414 ndp->ni_topdir = NULL; 415 416 if (!lockleaf) 417 cnp->cn_flags |= LOCKLEAF; 418 for (;;) { 419 cnp->cn_nameptr = cnp->cn_pnbuf; 420 /* 421 * Call lookup() to do the real work. If an error occurs, 422 * ndp->ni_vp and ni_dvp are left uninitialized or NULL and 423 * we do not have to dereference anything before returning. 424 * In either case ni_startdir will be dereferenced and NULLed 425 * out. 426 */ 427 error = lookup(ndp); 428 if (error) 429 break; 430 431 /* 432 * Check for encountering a symbolic link. Trivial 433 * termination occurs if no symlink encountered. 434 */ 435 if ((cnp->cn_flags & ISSYMLINK) == 0) { 436 if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0) 437 nfsvno_relpathbuf(ndp); 438 if (ndp->ni_vp && !lockleaf) 439 NFSVOPUNLOCK(ndp->ni_vp, 0); 440 break; 441 } 442 443 /* 444 * Validate symlink 445 */ 446 if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1) 447 NFSVOPUNLOCK(ndp->ni_dvp, 0); 448 if (!(nd->nd_flag & ND_PUBLOOKUP)) { 449 error = EINVAL; 450 goto badlink2; 451 } 452 453 if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { 454 error = ELOOP; 455 goto badlink2; 456 } 457 if (ndp->ni_pathlen > 1) 458 cp = uma_zalloc(namei_zone, M_WAITOK); 459 else 460 cp = cnp->cn_pnbuf; 461 aiov.iov_base = cp; 462 aiov.iov_len = MAXPATHLEN; 463 auio.uio_iov = &aiov; 464 auio.uio_iovcnt = 1; 465 auio.uio_offset = 0; 466 auio.uio_rw = UIO_READ; 467 auio.uio_segflg = UIO_SYSSPACE; 468 auio.uio_td = NULL; 469 auio.uio_resid = MAXPATHLEN; 470 error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred); 471 if (error) { 472 badlink1: 473 if (ndp->ni_pathlen > 1) 474 uma_zfree(namei_zone, cp); 475 badlink2: 476 vrele(ndp->ni_dvp); 477 vput(ndp->ni_vp); 478 break; 479 } 480 linklen = MAXPATHLEN - auio.uio_resid; 481 if (linklen == 0) { 482 error = ENOENT; 483 goto badlink1; 484 } 485 if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { 486 error = ENAMETOOLONG; 487 goto badlink1; 488 } 489 490 /* 491 * Adjust or replace path 492 */ 493 if (ndp->ni_pathlen > 1) { 494 NFSBCOPY(ndp->ni_next, cp + linklen, ndp->ni_pathlen); 495 uma_zfree(namei_zone, cnp->cn_pnbuf); 496 cnp->cn_pnbuf = cp; 497 } else 498 cnp->cn_pnbuf[linklen] = '\0'; 499 ndp->ni_pathlen += linklen; 500 501 /* 502 * Cleanup refs for next loop and check if root directory 503 * should replace current directory. Normally ni_dvp 504 * becomes the new base directory and is cleaned up when 505 * we loop. Explicitly null pointers after invalidation 506 * to clarify operation. 507 */ 508 vput(ndp->ni_vp); 509 ndp->ni_vp = NULL; 510 511 if (cnp->cn_pnbuf[0] == '/') { 512 vrele(ndp->ni_dvp); 513 ndp->ni_dvp = ndp->ni_rootdir; 514 VREF(ndp->ni_dvp); 515 } 516 ndp->ni_startdir = ndp->ni_dvp; 517 ndp->ni_dvp = NULL; 518 } 519 if (!lockleaf) 520 cnp->cn_flags &= ~LOCKLEAF; 521 522 out: 523 if (error) { 524 nfsvno_relpathbuf(ndp); 525 ndp->ni_vp = NULL; 526 ndp->ni_dvp = NULL; 527 ndp->ni_startdir = NULL; 528 } else if ((ndp->ni_cnd.cn_flags & (WANTPARENT|LOCKPARENT)) == 0) { 529 ndp->ni_dvp = NULL; 530 } 531 532 out1: 533 NFSEXITCODE2(error, nd); 534 return (error); 535 } 536 537 /* 538 * Set up a pathname buffer and return a pointer to it and, optionally 539 * set a hash pointer. 540 */ 541 void 542 nfsvno_setpathbuf(struct nameidata *ndp, char **bufpp, u_long **hashpp) 543 { 544 struct componentname *cnp = &ndp->ni_cnd; 545 546 cnp->cn_flags |= (NOMACCHECK | HASBUF); 547 cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK); 548 if (hashpp != NULL) 549 *hashpp = NULL; 550 *bufpp = cnp->cn_pnbuf; 551 } 552 553 /* 554 * Release the above path buffer, if not released by nfsvno_namei(). 555 */ 556 void 557 nfsvno_relpathbuf(struct nameidata *ndp) 558 { 559 560 if ((ndp->ni_cnd.cn_flags & HASBUF) == 0) 561 panic("nfsrelpath"); 562 uma_zfree(namei_zone, ndp->ni_cnd.cn_pnbuf); 563 ndp->ni_cnd.cn_flags &= ~HASBUF; 564 } 565 566 /* 567 * Readlink vnode op into an mbuf list. 568 */ 569 int 570 nfsvno_readlink(struct vnode *vp, struct ucred *cred, struct thread *p, 571 struct mbuf **mpp, struct mbuf **mpendp, int *lenp) 572 { 573 struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN]; 574 struct iovec *ivp = iv; 575 struct uio io, *uiop = &io; 576 struct mbuf *mp, *mp2 = NULL, *mp3 = NULL; 577 int i, len, tlen, error = 0; 578 579 len = 0; 580 i = 0; 581 while (len < NFS_MAXPATHLEN) { 582 NFSMGET(mp); 583 MCLGET(mp, M_WAITOK); 584 mp->m_len = M_SIZE(mp); 585 if (len == 0) { 586 mp3 = mp2 = mp; 587 } else { 588 mp2->m_next = mp; 589 mp2 = mp; 590 } 591 if ((len + mp->m_len) > NFS_MAXPATHLEN) { 592 mp->m_len = NFS_MAXPATHLEN - len; 593 len = NFS_MAXPATHLEN; 594 } else { 595 len += mp->m_len; 596 } 597 ivp->iov_base = mtod(mp, caddr_t); 598 ivp->iov_len = mp->m_len; 599 i++; 600 ivp++; 601 } 602 uiop->uio_iov = iv; 603 uiop->uio_iovcnt = i; 604 uiop->uio_offset = 0; 605 uiop->uio_resid = len; 606 uiop->uio_rw = UIO_READ; 607 uiop->uio_segflg = UIO_SYSSPACE; 608 uiop->uio_td = NULL; 609 error = VOP_READLINK(vp, uiop, cred); 610 if (error) { 611 m_freem(mp3); 612 *lenp = 0; 613 goto out; 614 } 615 if (uiop->uio_resid > 0) { 616 len -= uiop->uio_resid; 617 tlen = NFSM_RNDUP(len); 618 nfsrv_adj(mp3, NFS_MAXPATHLEN - tlen, tlen - len); 619 } 620 *lenp = len; 621 *mpp = mp3; 622 *mpendp = mp; 623 624 out: 625 NFSEXITCODE(error); 626 return (error); 627 } 628 629 /* 630 * Read vnode op call into mbuf list. 631 */ 632 int 633 nfsvno_read(struct vnode *vp, off_t off, int cnt, struct ucred *cred, 634 struct thread *p, struct mbuf **mpp, struct mbuf **mpendp) 635 { 636 struct mbuf *m; 637 int i; 638 struct iovec *iv; 639 struct iovec *iv2; 640 int error = 0, len, left, siz, tlen, ioflag = 0; 641 struct mbuf *m2 = NULL, *m3; 642 struct uio io, *uiop = &io; 643 struct nfsheur *nh; 644 645 len = left = NFSM_RNDUP(cnt); 646 m3 = NULL; 647 /* 648 * Generate the mbuf list with the uio_iov ref. to it. 649 */ 650 i = 0; 651 while (left > 0) { 652 NFSMGET(m); 653 MCLGET(m, M_WAITOK); 654 m->m_len = 0; 655 siz = min(M_TRAILINGSPACE(m), left); 656 left -= siz; 657 i++; 658 if (m3) 659 m2->m_next = m; 660 else 661 m3 = m; 662 m2 = m; 663 } 664 MALLOC(iv, struct iovec *, i * sizeof (struct iovec), 665 M_TEMP, M_WAITOK); 666 uiop->uio_iov = iv2 = iv; 667 m = m3; 668 left = len; 669 i = 0; 670 while (left > 0) { 671 if (m == NULL) 672 panic("nfsvno_read iov"); 673 siz = min(M_TRAILINGSPACE(m), left); 674 if (siz > 0) { 675 iv->iov_base = mtod(m, caddr_t) + m->m_len; 676 iv->iov_len = siz; 677 m->m_len += siz; 678 left -= siz; 679 iv++; 680 i++; 681 } 682 m = m->m_next; 683 } 684 uiop->uio_iovcnt = i; 685 uiop->uio_offset = off; 686 uiop->uio_resid = len; 687 uiop->uio_rw = UIO_READ; 688 uiop->uio_segflg = UIO_SYSSPACE; 689 uiop->uio_td = NULL; 690 nh = nfsrv_sequential_heuristic(uiop, vp); 691 ioflag |= nh->nh_seqcount << IO_SEQSHIFT; 692 /* XXX KDM make this more systematic? */ 693 nfsstatsv1.srvbytes[NFSV4OP_READ] += uiop->uio_resid; 694 error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred); 695 FREE((caddr_t)iv2, M_TEMP); 696 if (error) { 697 m_freem(m3); 698 *mpp = NULL; 699 goto out; 700 } 701 nh->nh_nextoff = uiop->uio_offset; 702 tlen = len - uiop->uio_resid; 703 cnt = cnt < tlen ? cnt : tlen; 704 tlen = NFSM_RNDUP(cnt); 705 if (tlen == 0) { 706 m_freem(m3); 707 m3 = NULL; 708 } else if (len != tlen || tlen != cnt) 709 nfsrv_adj(m3, len - tlen, tlen - cnt); 710 *mpp = m3; 711 *mpendp = m2; 712 713 out: 714 NFSEXITCODE(error); 715 return (error); 716 } 717 718 /* 719 * Write vnode op from an mbuf list. 720 */ 721 int 722 nfsvno_write(struct vnode *vp, off_t off, int retlen, int cnt, int stable, 723 struct mbuf *mp, char *cp, struct ucred *cred, struct thread *p) 724 { 725 struct iovec *ivp; 726 int i, len; 727 struct iovec *iv; 728 int ioflags, error; 729 struct uio io, *uiop = &io; 730 struct nfsheur *nh; 731 732 MALLOC(ivp, struct iovec *, cnt * sizeof (struct iovec), M_TEMP, 733 M_WAITOK); 734 uiop->uio_iov = iv = ivp; 735 uiop->uio_iovcnt = cnt; 736 i = mtod(mp, caddr_t) + mp->m_len - cp; 737 len = retlen; 738 while (len > 0) { 739 if (mp == NULL) 740 panic("nfsvno_write"); 741 if (i > 0) { 742 i = min(i, len); 743 ivp->iov_base = cp; 744 ivp->iov_len = i; 745 ivp++; 746 len -= i; 747 } 748 mp = mp->m_next; 749 if (mp) { 750 i = mp->m_len; 751 cp = mtod(mp, caddr_t); 752 } 753 } 754 755 if (stable == NFSWRITE_UNSTABLE) 756 ioflags = IO_NODELOCKED; 757 else 758 ioflags = (IO_SYNC | IO_NODELOCKED); 759 uiop->uio_resid = retlen; 760 uiop->uio_rw = UIO_WRITE; 761 uiop->uio_segflg = UIO_SYSSPACE; 762 NFSUIOPROC(uiop, p); 763 uiop->uio_offset = off; 764 nh = nfsrv_sequential_heuristic(uiop, vp); 765 ioflags |= nh->nh_seqcount << IO_SEQSHIFT; 766 /* XXX KDM make this more systematic? */ 767 nfsstatsv1.srvbytes[NFSV4OP_WRITE] += uiop->uio_resid; 768 error = VOP_WRITE(vp, uiop, ioflags, cred); 769 if (error == 0) 770 nh->nh_nextoff = uiop->uio_offset; 771 FREE((caddr_t)iv, M_TEMP); 772 773 NFSEXITCODE(error); 774 return (error); 775 } 776 777 /* 778 * Common code for creating a regular file (plus special files for V2). 779 */ 780 int 781 nfsvno_createsub(struct nfsrv_descript *nd, struct nameidata *ndp, 782 struct vnode **vpp, struct nfsvattr *nvap, int *exclusive_flagp, 783 int32_t *cverf, NFSDEV_T rdev, struct thread *p, struct nfsexstuff *exp) 784 { 785 u_quad_t tempsize; 786 int error; 787 788 error = nd->nd_repstat; 789 if (!error && ndp->ni_vp == NULL) { 790 if (nvap->na_type == VREG || nvap->na_type == VSOCK) { 791 vrele(ndp->ni_startdir); 792 error = VOP_CREATE(ndp->ni_dvp, 793 &ndp->ni_vp, &ndp->ni_cnd, &nvap->na_vattr); 794 vput(ndp->ni_dvp); 795 nfsvno_relpathbuf(ndp); 796 if (!error) { 797 if (*exclusive_flagp) { 798 *exclusive_flagp = 0; 799 NFSVNO_ATTRINIT(nvap); 800 nvap->na_atime.tv_sec = cverf[0]; 801 nvap->na_atime.tv_nsec = cverf[1]; 802 error = VOP_SETATTR(ndp->ni_vp, 803 &nvap->na_vattr, nd->nd_cred); 804 if (error != 0) { 805 vput(ndp->ni_vp); 806 ndp->ni_vp = NULL; 807 error = NFSERR_NOTSUPP; 808 } 809 } 810 } 811 /* 812 * NFS V2 Only. nfsrvd_mknod() does this for V3. 813 * (This implies, just get out on an error.) 814 */ 815 } else if (nvap->na_type == VCHR || nvap->na_type == VBLK || 816 nvap->na_type == VFIFO) { 817 if (nvap->na_type == VCHR && rdev == 0xffffffff) 818 nvap->na_type = VFIFO; 819 if (nvap->na_type != VFIFO && 820 (error = priv_check_cred(nd->nd_cred, 821 PRIV_VFS_MKNOD_DEV, 0))) { 822 vrele(ndp->ni_startdir); 823 nfsvno_relpathbuf(ndp); 824 vput(ndp->ni_dvp); 825 goto out; 826 } 827 nvap->na_rdev = rdev; 828 error = VOP_MKNOD(ndp->ni_dvp, &ndp->ni_vp, 829 &ndp->ni_cnd, &nvap->na_vattr); 830 vput(ndp->ni_dvp); 831 nfsvno_relpathbuf(ndp); 832 vrele(ndp->ni_startdir); 833 if (error) 834 goto out; 835 } else { 836 vrele(ndp->ni_startdir); 837 nfsvno_relpathbuf(ndp); 838 vput(ndp->ni_dvp); 839 error = ENXIO; 840 goto out; 841 } 842 *vpp = ndp->ni_vp; 843 } else { 844 /* 845 * Handle cases where error is already set and/or 846 * the file exists. 847 * 1 - clean up the lookup 848 * 2 - iff !error and na_size set, truncate it 849 */ 850 vrele(ndp->ni_startdir); 851 nfsvno_relpathbuf(ndp); 852 *vpp = ndp->ni_vp; 853 if (ndp->ni_dvp == *vpp) 854 vrele(ndp->ni_dvp); 855 else 856 vput(ndp->ni_dvp); 857 if (!error && nvap->na_size != VNOVAL) { 858 error = nfsvno_accchk(*vpp, VWRITE, 859 nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE, 860 NFSACCCHK_VPISLOCKED, NULL); 861 if (!error) { 862 tempsize = nvap->na_size; 863 NFSVNO_ATTRINIT(nvap); 864 nvap->na_size = tempsize; 865 error = VOP_SETATTR(*vpp, 866 &nvap->na_vattr, nd->nd_cred); 867 } 868 } 869 if (error) 870 vput(*vpp); 871 } 872 873 out: 874 NFSEXITCODE(error); 875 return (error); 876 } 877 878 /* 879 * Do a mknod vnode op. 880 */ 881 int 882 nfsvno_mknod(struct nameidata *ndp, struct nfsvattr *nvap, struct ucred *cred, 883 struct thread *p) 884 { 885 int error = 0; 886 enum vtype vtyp; 887 888 vtyp = nvap->na_type; 889 /* 890 * Iff doesn't exist, create it. 891 */ 892 if (ndp->ni_vp) { 893 vrele(ndp->ni_startdir); 894 nfsvno_relpathbuf(ndp); 895 vput(ndp->ni_dvp); 896 vrele(ndp->ni_vp); 897 error = EEXIST; 898 goto out; 899 } 900 if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) { 901 vrele(ndp->ni_startdir); 902 nfsvno_relpathbuf(ndp); 903 vput(ndp->ni_dvp); 904 error = NFSERR_BADTYPE; 905 goto out; 906 } 907 if (vtyp == VSOCK) { 908 vrele(ndp->ni_startdir); 909 error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp, 910 &ndp->ni_cnd, &nvap->na_vattr); 911 vput(ndp->ni_dvp); 912 nfsvno_relpathbuf(ndp); 913 } else { 914 if (nvap->na_type != VFIFO && 915 (error = priv_check_cred(cred, PRIV_VFS_MKNOD_DEV, 0))) { 916 vrele(ndp->ni_startdir); 917 nfsvno_relpathbuf(ndp); 918 vput(ndp->ni_dvp); 919 goto out; 920 } 921 error = VOP_MKNOD(ndp->ni_dvp, &ndp->ni_vp, 922 &ndp->ni_cnd, &nvap->na_vattr); 923 vput(ndp->ni_dvp); 924 nfsvno_relpathbuf(ndp); 925 vrele(ndp->ni_startdir); 926 /* 927 * Since VOP_MKNOD returns the ni_vp, I can't 928 * see any reason to do the lookup. 929 */ 930 } 931 932 out: 933 NFSEXITCODE(error); 934 return (error); 935 } 936 937 /* 938 * Mkdir vnode op. 939 */ 940 int 941 nfsvno_mkdir(struct nameidata *ndp, struct nfsvattr *nvap, uid_t saved_uid, 942 struct ucred *cred, struct thread *p, struct nfsexstuff *exp) 943 { 944 int error = 0; 945 946 if (ndp->ni_vp != NULL) { 947 if (ndp->ni_dvp == ndp->ni_vp) 948 vrele(ndp->ni_dvp); 949 else 950 vput(ndp->ni_dvp); 951 vrele(ndp->ni_vp); 952 nfsvno_relpathbuf(ndp); 953 error = EEXIST; 954 goto out; 955 } 956 error = VOP_MKDIR(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd, 957 &nvap->na_vattr); 958 vput(ndp->ni_dvp); 959 nfsvno_relpathbuf(ndp); 960 961 out: 962 NFSEXITCODE(error); 963 return (error); 964 } 965 966 /* 967 * symlink vnode op. 968 */ 969 int 970 nfsvno_symlink(struct nameidata *ndp, struct nfsvattr *nvap, char *pathcp, 971 int pathlen, int not_v2, uid_t saved_uid, struct ucred *cred, struct thread *p, 972 struct nfsexstuff *exp) 973 { 974 int error = 0; 975 976 if (ndp->ni_vp) { 977 vrele(ndp->ni_startdir); 978 nfsvno_relpathbuf(ndp); 979 if (ndp->ni_dvp == ndp->ni_vp) 980 vrele(ndp->ni_dvp); 981 else 982 vput(ndp->ni_dvp); 983 vrele(ndp->ni_vp); 984 error = EEXIST; 985 goto out; 986 } 987 988 error = VOP_SYMLINK(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd, 989 &nvap->na_vattr, pathcp); 990 vput(ndp->ni_dvp); 991 vrele(ndp->ni_startdir); 992 nfsvno_relpathbuf(ndp); 993 /* 994 * Although FreeBSD still had the lookup code in 995 * it for 7/current, there doesn't seem to be any 996 * point, since VOP_SYMLINK() returns the ni_vp. 997 * Just vput it for v2. 998 */ 999 if (!not_v2 && !error) 1000 vput(ndp->ni_vp); 1001 1002 out: 1003 NFSEXITCODE(error); 1004 return (error); 1005 } 1006 1007 /* 1008 * Parse symbolic link arguments. 1009 * This function has an ugly side effect. It will MALLOC() an area for 1010 * the symlink and set iov_base to point to it, only if it succeeds. 1011 * So, if it returns with uiop->uio_iov->iov_base != NULL, that must 1012 * be FREE'd later. 1013 */ 1014 int 1015 nfsvno_getsymlink(struct nfsrv_descript *nd, struct nfsvattr *nvap, 1016 struct thread *p, char **pathcpp, int *lenp) 1017 { 1018 u_int32_t *tl; 1019 char *pathcp = NULL; 1020 int error = 0, len; 1021 struct nfsv2_sattr *sp; 1022 1023 *pathcpp = NULL; 1024 *lenp = 0; 1025 if ((nd->nd_flag & ND_NFSV3) && 1026 (error = nfsrv_sattr(nd, NULL, nvap, NULL, NULL, p))) 1027 goto nfsmout; 1028 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 1029 len = fxdr_unsigned(int, *tl); 1030 if (len > NFS_MAXPATHLEN || len <= 0) { 1031 error = EBADRPC; 1032 goto nfsmout; 1033 } 1034 MALLOC(pathcp, caddr_t, len + 1, M_TEMP, M_WAITOK); 1035 error = nfsrv_mtostr(nd, pathcp, len); 1036 if (error) 1037 goto nfsmout; 1038 if (nd->nd_flag & ND_NFSV2) { 1039 NFSM_DISSECT(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1040 nvap->na_mode = fxdr_unsigned(u_int16_t, sp->sa_mode); 1041 } 1042 *pathcpp = pathcp; 1043 *lenp = len; 1044 NFSEXITCODE2(0, nd); 1045 return (0); 1046 nfsmout: 1047 if (pathcp) 1048 free(pathcp, M_TEMP); 1049 NFSEXITCODE2(error, nd); 1050 return (error); 1051 } 1052 1053 /* 1054 * Remove a non-directory object. 1055 */ 1056 int 1057 nfsvno_removesub(struct nameidata *ndp, int is_v4, struct ucred *cred, 1058 struct thread *p, struct nfsexstuff *exp) 1059 { 1060 struct vnode *vp; 1061 int error = 0; 1062 1063 vp = ndp->ni_vp; 1064 if (vp->v_type == VDIR) 1065 error = NFSERR_ISDIR; 1066 else if (is_v4) 1067 error = nfsrv_checkremove(vp, 1, p); 1068 if (!error) 1069 error = VOP_REMOVE(ndp->ni_dvp, vp, &ndp->ni_cnd); 1070 if (ndp->ni_dvp == vp) 1071 vrele(ndp->ni_dvp); 1072 else 1073 vput(ndp->ni_dvp); 1074 vput(vp); 1075 if ((ndp->ni_cnd.cn_flags & SAVENAME) != 0) 1076 nfsvno_relpathbuf(ndp); 1077 NFSEXITCODE(error); 1078 return (error); 1079 } 1080 1081 /* 1082 * Remove a directory. 1083 */ 1084 int 1085 nfsvno_rmdirsub(struct nameidata *ndp, int is_v4, struct ucred *cred, 1086 struct thread *p, struct nfsexstuff *exp) 1087 { 1088 struct vnode *vp; 1089 int error = 0; 1090 1091 vp = ndp->ni_vp; 1092 if (vp->v_type != VDIR) { 1093 error = ENOTDIR; 1094 goto out; 1095 } 1096 /* 1097 * No rmdir "." please. 1098 */ 1099 if (ndp->ni_dvp == vp) { 1100 error = EINVAL; 1101 goto out; 1102 } 1103 /* 1104 * The root of a mounted filesystem cannot be deleted. 1105 */ 1106 if (vp->v_vflag & VV_ROOT) 1107 error = EBUSY; 1108 out: 1109 if (!error) 1110 error = VOP_RMDIR(ndp->ni_dvp, vp, &ndp->ni_cnd); 1111 if (ndp->ni_dvp == vp) 1112 vrele(ndp->ni_dvp); 1113 else 1114 vput(ndp->ni_dvp); 1115 vput(vp); 1116 if ((ndp->ni_cnd.cn_flags & SAVENAME) != 0) 1117 nfsvno_relpathbuf(ndp); 1118 NFSEXITCODE(error); 1119 return (error); 1120 } 1121 1122 /* 1123 * Rename vnode op. 1124 */ 1125 int 1126 nfsvno_rename(struct nameidata *fromndp, struct nameidata *tondp, 1127 u_int32_t ndstat, u_int32_t ndflag, struct ucred *cred, struct thread *p) 1128 { 1129 struct vnode *fvp, *tvp, *tdvp; 1130 int error = 0; 1131 1132 fvp = fromndp->ni_vp; 1133 if (ndstat) { 1134 vrele(fromndp->ni_dvp); 1135 vrele(fvp); 1136 error = ndstat; 1137 goto out1; 1138 } 1139 tdvp = tondp->ni_dvp; 1140 tvp = tondp->ni_vp; 1141 if (tvp != NULL) { 1142 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 1143 error = (ndflag & ND_NFSV2) ? EISDIR : EEXIST; 1144 goto out; 1145 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 1146 error = (ndflag & ND_NFSV2) ? ENOTDIR : EEXIST; 1147 goto out; 1148 } 1149 if (tvp->v_type == VDIR && tvp->v_mountedhere) { 1150 error = (ndflag & ND_NFSV2) ? ENOTEMPTY : EXDEV; 1151 goto out; 1152 } 1153 1154 /* 1155 * A rename to '.' or '..' results in a prematurely 1156 * unlocked vnode on FreeBSD5, so I'm just going to fail that 1157 * here. 1158 */ 1159 if ((tondp->ni_cnd.cn_namelen == 1 && 1160 tondp->ni_cnd.cn_nameptr[0] == '.') || 1161 (tondp->ni_cnd.cn_namelen == 2 && 1162 tondp->ni_cnd.cn_nameptr[0] == '.' && 1163 tondp->ni_cnd.cn_nameptr[1] == '.')) { 1164 error = EINVAL; 1165 goto out; 1166 } 1167 } 1168 if (fvp->v_type == VDIR && fvp->v_mountedhere) { 1169 error = (ndflag & ND_NFSV2) ? ENOTEMPTY : EXDEV; 1170 goto out; 1171 } 1172 if (fvp->v_mount != tdvp->v_mount) { 1173 error = (ndflag & ND_NFSV2) ? ENOTEMPTY : EXDEV; 1174 goto out; 1175 } 1176 if (fvp == tdvp) { 1177 error = (ndflag & ND_NFSV2) ? ENOTEMPTY : EINVAL; 1178 goto out; 1179 } 1180 if (fvp == tvp) { 1181 /* 1182 * If source and destination are the same, there is nothing to 1183 * do. Set error to -1 to indicate this. 1184 */ 1185 error = -1; 1186 goto out; 1187 } 1188 if (ndflag & ND_NFSV4) { 1189 if (NFSVOPLOCK(fvp, LK_EXCLUSIVE) == 0) { 1190 error = nfsrv_checkremove(fvp, 0, p); 1191 NFSVOPUNLOCK(fvp, 0); 1192 } else 1193 error = EPERM; 1194 if (tvp && !error) 1195 error = nfsrv_checkremove(tvp, 1, p); 1196 } else { 1197 /* 1198 * For NFSv2 and NFSv3, try to get rid of the delegation, so 1199 * that the NFSv4 client won't be confused by the rename. 1200 * Since nfsd_recalldelegation() can only be called on an 1201 * unlocked vnode at this point and fvp is the file that will 1202 * still exist after the rename, just do fvp. 1203 */ 1204 nfsd_recalldelegation(fvp, p); 1205 } 1206 out: 1207 if (!error) { 1208 error = VOP_RENAME(fromndp->ni_dvp, fromndp->ni_vp, 1209 &fromndp->ni_cnd, tondp->ni_dvp, tondp->ni_vp, 1210 &tondp->ni_cnd); 1211 } else { 1212 if (tdvp == tvp) 1213 vrele(tdvp); 1214 else 1215 vput(tdvp); 1216 if (tvp) 1217 vput(tvp); 1218 vrele(fromndp->ni_dvp); 1219 vrele(fvp); 1220 if (error == -1) 1221 error = 0; 1222 } 1223 vrele(tondp->ni_startdir); 1224 nfsvno_relpathbuf(tondp); 1225 out1: 1226 vrele(fromndp->ni_startdir); 1227 nfsvno_relpathbuf(fromndp); 1228 NFSEXITCODE(error); 1229 return (error); 1230 } 1231 1232 /* 1233 * Link vnode op. 1234 */ 1235 int 1236 nfsvno_link(struct nameidata *ndp, struct vnode *vp, struct ucred *cred, 1237 struct thread *p, struct nfsexstuff *exp) 1238 { 1239 struct vnode *xp; 1240 int error = 0; 1241 1242 xp = ndp->ni_vp; 1243 if (xp != NULL) { 1244 error = EEXIST; 1245 } else { 1246 xp = ndp->ni_dvp; 1247 if (vp->v_mount != xp->v_mount) 1248 error = EXDEV; 1249 } 1250 if (!error) { 1251 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); 1252 if ((vp->v_iflag & VI_DOOMED) == 0) 1253 error = VOP_LINK(ndp->ni_dvp, vp, &ndp->ni_cnd); 1254 else 1255 error = EPERM; 1256 if (ndp->ni_dvp == vp) 1257 vrele(ndp->ni_dvp); 1258 else 1259 vput(ndp->ni_dvp); 1260 NFSVOPUNLOCK(vp, 0); 1261 } else { 1262 if (ndp->ni_dvp == ndp->ni_vp) 1263 vrele(ndp->ni_dvp); 1264 else 1265 vput(ndp->ni_dvp); 1266 if (ndp->ni_vp) 1267 vrele(ndp->ni_vp); 1268 } 1269 nfsvno_relpathbuf(ndp); 1270 NFSEXITCODE(error); 1271 return (error); 1272 } 1273 1274 /* 1275 * Do the fsync() appropriate for the commit. 1276 */ 1277 int 1278 nfsvno_fsync(struct vnode *vp, u_int64_t off, int cnt, struct ucred *cred, 1279 struct thread *td) 1280 { 1281 int error = 0; 1282 1283 /* 1284 * RFC 1813 3.3.21: if count is 0, a flush from offset to the end of 1285 * file is done. At this time VOP_FSYNC does not accept offset and 1286 * byte count parameters so call VOP_FSYNC the whole file for now. 1287 * The same is true for NFSv4: RFC 3530 Sec. 14.2.3. 1288 * File systems that do not use the buffer cache (as indicated 1289 * by MNTK_USES_BCACHE not being set) must use VOP_FSYNC(). 1290 */ 1291 if (cnt == 0 || cnt > MAX_COMMIT_COUNT || 1292 (vp->v_mount->mnt_kern_flag & MNTK_USES_BCACHE) == 0) { 1293 /* 1294 * Give up and do the whole thing 1295 */ 1296 if (vp->v_object && 1297 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) { 1298 VM_OBJECT_WLOCK(vp->v_object); 1299 vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC); 1300 VM_OBJECT_WUNLOCK(vp->v_object); 1301 } 1302 error = VOP_FSYNC(vp, MNT_WAIT, td); 1303 } else { 1304 /* 1305 * Locate and synchronously write any buffers that fall 1306 * into the requested range. Note: we are assuming that 1307 * f_iosize is a power of 2. 1308 */ 1309 int iosize = vp->v_mount->mnt_stat.f_iosize; 1310 int iomask = iosize - 1; 1311 struct bufobj *bo; 1312 daddr_t lblkno; 1313 1314 /* 1315 * Align to iosize boundary, super-align to page boundary. 1316 */ 1317 if (off & iomask) { 1318 cnt += off & iomask; 1319 off &= ~(u_quad_t)iomask; 1320 } 1321 if (off & PAGE_MASK) { 1322 cnt += off & PAGE_MASK; 1323 off &= ~(u_quad_t)PAGE_MASK; 1324 } 1325 lblkno = off / iosize; 1326 1327 if (vp->v_object && 1328 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) { 1329 VM_OBJECT_WLOCK(vp->v_object); 1330 vm_object_page_clean(vp->v_object, off, off + cnt, 1331 OBJPC_SYNC); 1332 VM_OBJECT_WUNLOCK(vp->v_object); 1333 } 1334 1335 bo = &vp->v_bufobj; 1336 BO_LOCK(bo); 1337 while (cnt > 0) { 1338 struct buf *bp; 1339 1340 /* 1341 * If we have a buffer and it is marked B_DELWRI we 1342 * have to lock and write it. Otherwise the prior 1343 * write is assumed to have already been committed. 1344 * 1345 * gbincore() can return invalid buffers now so we 1346 * have to check that bit as well (though B_DELWRI 1347 * should not be set if B_INVAL is set there could be 1348 * a race here since we haven't locked the buffer). 1349 */ 1350 if ((bp = gbincore(&vp->v_bufobj, lblkno)) != NULL) { 1351 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL | 1352 LK_INTERLOCK, BO_LOCKPTR(bo)) == ENOLCK) { 1353 BO_LOCK(bo); 1354 continue; /* retry */ 1355 } 1356 if ((bp->b_flags & (B_DELWRI|B_INVAL)) == 1357 B_DELWRI) { 1358 bremfree(bp); 1359 bp->b_flags &= ~B_ASYNC; 1360 bwrite(bp); 1361 ++nfs_commit_miss; 1362 } else 1363 BUF_UNLOCK(bp); 1364 BO_LOCK(bo); 1365 } 1366 ++nfs_commit_blks; 1367 if (cnt < iosize) 1368 break; 1369 cnt -= iosize; 1370 ++lblkno; 1371 } 1372 BO_UNLOCK(bo); 1373 } 1374 NFSEXITCODE(error); 1375 return (error); 1376 } 1377 1378 /* 1379 * Statfs vnode op. 1380 */ 1381 int 1382 nfsvno_statfs(struct vnode *vp, struct statfs *sf) 1383 { 1384 int error; 1385 1386 error = VFS_STATFS(vp->v_mount, sf); 1387 if (error == 0) { 1388 /* 1389 * Since NFS handles these values as unsigned on the 1390 * wire, there is no way to represent negative values, 1391 * so set them to 0. Without this, they will appear 1392 * to be very large positive values for clients like 1393 * Solaris10. 1394 */ 1395 if (sf->f_bavail < 0) 1396 sf->f_bavail = 0; 1397 if (sf->f_ffree < 0) 1398 sf->f_ffree = 0; 1399 } 1400 NFSEXITCODE(error); 1401 return (error); 1402 } 1403 1404 /* 1405 * Do the vnode op stuff for Open. Similar to nfsvno_createsub(), but 1406 * must handle nfsrv_opencheck() calls after any other access checks. 1407 */ 1408 void 1409 nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp, 1410 nfsquad_t clientid, nfsv4stateid_t *stateidp, struct nfsstate *stp, 1411 int *exclusive_flagp, struct nfsvattr *nvap, int32_t *cverf, int create, 1412 NFSACL_T *aclp, nfsattrbit_t *attrbitp, struct ucred *cred, struct thread *p, 1413 struct nfsexstuff *exp, struct vnode **vpp) 1414 { 1415 struct vnode *vp = NULL; 1416 u_quad_t tempsize; 1417 struct nfsexstuff nes; 1418 1419 if (ndp->ni_vp == NULL) 1420 nd->nd_repstat = nfsrv_opencheck(clientid, 1421 stateidp, stp, NULL, nd, p, nd->nd_repstat); 1422 if (!nd->nd_repstat) { 1423 if (ndp->ni_vp == NULL) { 1424 vrele(ndp->ni_startdir); 1425 nd->nd_repstat = VOP_CREATE(ndp->ni_dvp, 1426 &ndp->ni_vp, &ndp->ni_cnd, &nvap->na_vattr); 1427 vput(ndp->ni_dvp); 1428 nfsvno_relpathbuf(ndp); 1429 if (!nd->nd_repstat) { 1430 if (*exclusive_flagp) { 1431 *exclusive_flagp = 0; 1432 NFSVNO_ATTRINIT(nvap); 1433 nvap->na_atime.tv_sec = cverf[0]; 1434 nvap->na_atime.tv_nsec = cverf[1]; 1435 nd->nd_repstat = VOP_SETATTR(ndp->ni_vp, 1436 &nvap->na_vattr, cred); 1437 if (nd->nd_repstat != 0) { 1438 vput(ndp->ni_vp); 1439 ndp->ni_vp = NULL; 1440 nd->nd_repstat = NFSERR_NOTSUPP; 1441 } else 1442 NFSSETBIT_ATTRBIT(attrbitp, 1443 NFSATTRBIT_TIMEACCESS); 1444 } else { 1445 nfsrv_fixattr(nd, ndp->ni_vp, nvap, 1446 aclp, p, attrbitp, exp); 1447 } 1448 } 1449 vp = ndp->ni_vp; 1450 } else { 1451 if (ndp->ni_startdir) 1452 vrele(ndp->ni_startdir); 1453 nfsvno_relpathbuf(ndp); 1454 vp = ndp->ni_vp; 1455 if (create == NFSV4OPEN_CREATE) { 1456 if (ndp->ni_dvp == vp) 1457 vrele(ndp->ni_dvp); 1458 else 1459 vput(ndp->ni_dvp); 1460 } 1461 if (NFSVNO_ISSETSIZE(nvap) && vp->v_type == VREG) { 1462 if (ndp->ni_cnd.cn_flags & RDONLY) 1463 NFSVNO_SETEXRDONLY(&nes); 1464 else 1465 NFSVNO_EXINIT(&nes); 1466 nd->nd_repstat = nfsvno_accchk(vp, 1467 VWRITE, cred, &nes, p, 1468 NFSACCCHK_NOOVERRIDE, 1469 NFSACCCHK_VPISLOCKED, NULL); 1470 nd->nd_repstat = nfsrv_opencheck(clientid, 1471 stateidp, stp, vp, nd, p, nd->nd_repstat); 1472 if (!nd->nd_repstat) { 1473 tempsize = nvap->na_size; 1474 NFSVNO_ATTRINIT(nvap); 1475 nvap->na_size = tempsize; 1476 nd->nd_repstat = VOP_SETATTR(vp, 1477 &nvap->na_vattr, cred); 1478 } 1479 } else if (vp->v_type == VREG) { 1480 nd->nd_repstat = nfsrv_opencheck(clientid, 1481 stateidp, stp, vp, nd, p, nd->nd_repstat); 1482 } 1483 } 1484 } else { 1485 if (ndp->ni_cnd.cn_flags & HASBUF) 1486 nfsvno_relpathbuf(ndp); 1487 if (ndp->ni_startdir && create == NFSV4OPEN_CREATE) { 1488 vrele(ndp->ni_startdir); 1489 if (ndp->ni_dvp == ndp->ni_vp) 1490 vrele(ndp->ni_dvp); 1491 else 1492 vput(ndp->ni_dvp); 1493 if (ndp->ni_vp) 1494 vput(ndp->ni_vp); 1495 } 1496 } 1497 *vpp = vp; 1498 1499 NFSEXITCODE2(0, nd); 1500 } 1501 1502 /* 1503 * Updates the file rev and sets the mtime and ctime 1504 * to the current clock time, returning the va_filerev and va_Xtime 1505 * values. 1506 * Return ESTALE to indicate the vnode is VI_DOOMED. 1507 */ 1508 int 1509 nfsvno_updfilerev(struct vnode *vp, struct nfsvattr *nvap, 1510 struct ucred *cred, struct thread *p) 1511 { 1512 struct vattr va; 1513 1514 VATTR_NULL(&va); 1515 vfs_timestamp(&va.va_mtime); 1516 if (NFSVOPISLOCKED(vp) != LK_EXCLUSIVE) { 1517 NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY); 1518 if ((vp->v_iflag & VI_DOOMED) != 0) 1519 return (ESTALE); 1520 } 1521 (void) VOP_SETATTR(vp, &va, cred); 1522 (void) nfsvno_getattr(vp, nvap, cred, p, 1); 1523 return (0); 1524 } 1525 1526 /* 1527 * Glue routine to nfsv4_fillattr(). 1528 */ 1529 int 1530 nfsvno_fillattr(struct nfsrv_descript *nd, struct mount *mp, struct vnode *vp, 1531 struct nfsvattr *nvap, fhandle_t *fhp, int rderror, nfsattrbit_t *attrbitp, 1532 struct ucred *cred, struct thread *p, int isdgram, int reterr, 1533 int supports_nfsv4acls, int at_root, uint64_t mounted_on_fileno) 1534 { 1535 int error; 1536 1537 error = nfsv4_fillattr(nd, mp, vp, NULL, &nvap->na_vattr, fhp, rderror, 1538 attrbitp, cred, p, isdgram, reterr, supports_nfsv4acls, at_root, 1539 mounted_on_fileno); 1540 NFSEXITCODE2(0, nd); 1541 return (error); 1542 } 1543 1544 /* Since the Readdir vnode ops vary, put the entire functions in here. */ 1545 /* 1546 * nfs readdir service 1547 * - mallocs what it thinks is enough to read 1548 * count rounded up to a multiple of DIRBLKSIZ <= NFS_MAXREADDIR 1549 * - calls VOP_READDIR() 1550 * - loops around building the reply 1551 * if the output generated exceeds count break out of loop 1552 * The NFSM_CLGET macro is used here so that the reply will be packed 1553 * tightly in mbuf clusters. 1554 * - it trims out records with d_fileno == 0 1555 * this doesn't matter for Unix clients, but they might confuse clients 1556 * for other os'. 1557 * - it trims out records with d_type == DT_WHT 1558 * these cannot be seen through NFS (unless we extend the protocol) 1559 * The alternate call nfsrvd_readdirplus() does lookups as well. 1560 * PS: The NFS protocol spec. does not clarify what the "count" byte 1561 * argument is a count of.. just name strings and file id's or the 1562 * entire reply rpc or ... 1563 * I tried just file name and id sizes and it confused the Sun client, 1564 * so I am using the full rpc size now. The "paranoia.." comment refers 1565 * to including the status longwords that are not a part of the dir. 1566 * "entry" structures, but are in the rpc. 1567 */ 1568 int 1569 nfsrvd_readdir(struct nfsrv_descript *nd, int isdgram, 1570 struct vnode *vp, struct thread *p, struct nfsexstuff *exp) 1571 { 1572 struct dirent *dp; 1573 u_int32_t *tl; 1574 int dirlen; 1575 char *cpos, *cend, *rbuf; 1576 struct nfsvattr at; 1577 int nlen, error = 0, getret = 1; 1578 int siz, cnt, fullsiz, eofflag, ncookies; 1579 u_int64_t off, toff, verf; 1580 u_long *cookies = NULL, *cookiep; 1581 struct uio io; 1582 struct iovec iv; 1583 int is_ufs; 1584 1585 if (nd->nd_repstat) { 1586 nfsrv_postopattr(nd, getret, &at); 1587 goto out; 1588 } 1589 if (nd->nd_flag & ND_NFSV2) { 1590 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1591 off = fxdr_unsigned(u_quad_t, *tl++); 1592 } else { 1593 NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 1594 off = fxdr_hyper(tl); 1595 tl += 2; 1596 verf = fxdr_hyper(tl); 1597 tl += 2; 1598 } 1599 toff = off; 1600 cnt = fxdr_unsigned(int, *tl); 1601 if (cnt > NFS_SRVMAXDATA(nd) || cnt < 0) 1602 cnt = NFS_SRVMAXDATA(nd); 1603 siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); 1604 fullsiz = siz; 1605 if (nd->nd_flag & ND_NFSV3) { 1606 nd->nd_repstat = getret = nfsvno_getattr(vp, &at, nd->nd_cred, 1607 p, 1); 1608 #if 0 1609 /* 1610 * va_filerev is not sufficient as a cookie verifier, 1611 * since it is not supposed to change when entries are 1612 * removed/added unless that offset cookies returned to 1613 * the client are no longer valid. 1614 */ 1615 if (!nd->nd_repstat && toff && verf != at.na_filerev) 1616 nd->nd_repstat = NFSERR_BAD_COOKIE; 1617 #endif 1618 } 1619 if (!nd->nd_repstat && vp->v_type != VDIR) 1620 nd->nd_repstat = NFSERR_NOTDIR; 1621 if (nd->nd_repstat == 0 && cnt == 0) { 1622 if (nd->nd_flag & ND_NFSV2) 1623 /* NFSv2 does not have NFSERR_TOOSMALL */ 1624 nd->nd_repstat = EPERM; 1625 else 1626 nd->nd_repstat = NFSERR_TOOSMALL; 1627 } 1628 if (!nd->nd_repstat) 1629 nd->nd_repstat = nfsvno_accchk(vp, VEXEC, 1630 nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE, 1631 NFSACCCHK_VPISLOCKED, NULL); 1632 if (nd->nd_repstat) { 1633 vput(vp); 1634 if (nd->nd_flag & ND_NFSV3) 1635 nfsrv_postopattr(nd, getret, &at); 1636 goto out; 1637 } 1638 is_ufs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "ufs") == 0; 1639 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 1640 again: 1641 eofflag = 0; 1642 if (cookies) { 1643 free((caddr_t)cookies, M_TEMP); 1644 cookies = NULL; 1645 } 1646 1647 iv.iov_base = rbuf; 1648 iv.iov_len = siz; 1649 io.uio_iov = &iv; 1650 io.uio_iovcnt = 1; 1651 io.uio_offset = (off_t)off; 1652 io.uio_resid = siz; 1653 io.uio_segflg = UIO_SYSSPACE; 1654 io.uio_rw = UIO_READ; 1655 io.uio_td = NULL; 1656 nd->nd_repstat = VOP_READDIR(vp, &io, nd->nd_cred, &eofflag, &ncookies, 1657 &cookies); 1658 off = (u_int64_t)io.uio_offset; 1659 if (io.uio_resid) 1660 siz -= io.uio_resid; 1661 1662 if (!cookies && !nd->nd_repstat) 1663 nd->nd_repstat = NFSERR_PERM; 1664 if (nd->nd_flag & ND_NFSV3) { 1665 getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1); 1666 if (!nd->nd_repstat) 1667 nd->nd_repstat = getret; 1668 } 1669 1670 /* 1671 * Handles the failed cases. nd->nd_repstat == 0 past here. 1672 */ 1673 if (nd->nd_repstat) { 1674 vput(vp); 1675 free((caddr_t)rbuf, M_TEMP); 1676 if (cookies) 1677 free((caddr_t)cookies, M_TEMP); 1678 if (nd->nd_flag & ND_NFSV3) 1679 nfsrv_postopattr(nd, getret, &at); 1680 goto out; 1681 } 1682 /* 1683 * If nothing read, return eof 1684 * rpc reply 1685 */ 1686 if (siz == 0) { 1687 vput(vp); 1688 if (nd->nd_flag & ND_NFSV2) { 1689 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1690 } else { 1691 nfsrv_postopattr(nd, getret, &at); 1692 NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 1693 txdr_hyper(at.na_filerev, tl); 1694 tl += 2; 1695 } 1696 *tl++ = newnfs_false; 1697 *tl = newnfs_true; 1698 FREE((caddr_t)rbuf, M_TEMP); 1699 FREE((caddr_t)cookies, M_TEMP); 1700 goto out; 1701 } 1702 1703 /* 1704 * Check for degenerate cases of nothing useful read. 1705 * If so go try again 1706 */ 1707 cpos = rbuf; 1708 cend = rbuf + siz; 1709 dp = (struct dirent *)cpos; 1710 cookiep = cookies; 1711 1712 /* 1713 * For some reason FreeBSD's ufs_readdir() chooses to back the 1714 * directory offset up to a block boundary, so it is necessary to 1715 * skip over the records that precede the requested offset. This 1716 * requires the assumption that file offset cookies monotonically 1717 * increase. 1718 */ 1719 while (cpos < cend && ncookies > 0 && 1720 (dp->d_fileno == 0 || dp->d_type == DT_WHT || 1721 (is_ufs == 1 && ((u_quad_t)(*cookiep)) <= toff))) { 1722 cpos += dp->d_reclen; 1723 dp = (struct dirent *)cpos; 1724 cookiep++; 1725 ncookies--; 1726 } 1727 if (cpos >= cend || ncookies == 0) { 1728 siz = fullsiz; 1729 toff = off; 1730 goto again; 1731 } 1732 vput(vp); 1733 1734 /* 1735 * dirlen is the size of the reply, including all XDR and must 1736 * not exceed cnt. For NFSv2, RFC1094 didn't clearly indicate 1737 * if the XDR should be included in "count", but to be safe, we do. 1738 * (Include the two booleans at the end of the reply in dirlen now.) 1739 */ 1740 if (nd->nd_flag & ND_NFSV3) { 1741 nfsrv_postopattr(nd, getret, &at); 1742 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1743 txdr_hyper(at.na_filerev, tl); 1744 dirlen = NFSX_V3POSTOPATTR + NFSX_VERF + 2 * NFSX_UNSIGNED; 1745 } else { 1746 dirlen = 2 * NFSX_UNSIGNED; 1747 } 1748 1749 /* Loop through the records and build reply */ 1750 while (cpos < cend && ncookies > 0) { 1751 nlen = dp->d_namlen; 1752 if (dp->d_fileno != 0 && dp->d_type != DT_WHT && 1753 nlen <= NFS_MAXNAMLEN) { 1754 if (nd->nd_flag & ND_NFSV3) 1755 dirlen += (6*NFSX_UNSIGNED + NFSM_RNDUP(nlen)); 1756 else 1757 dirlen += (4*NFSX_UNSIGNED + NFSM_RNDUP(nlen)); 1758 if (dirlen > cnt) { 1759 eofflag = 0; 1760 break; 1761 } 1762 1763 /* 1764 * Build the directory record xdr from 1765 * the dirent entry. 1766 */ 1767 if (nd->nd_flag & ND_NFSV3) { 1768 NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 1769 *tl++ = newnfs_true; 1770 *tl++ = 0; 1771 } else { 1772 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1773 *tl++ = newnfs_true; 1774 } 1775 *tl = txdr_unsigned(dp->d_fileno); 1776 (void) nfsm_strtom(nd, dp->d_name, nlen); 1777 if (nd->nd_flag & ND_NFSV3) { 1778 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1779 *tl++ = 0; 1780 } else 1781 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 1782 *tl = txdr_unsigned(*cookiep); 1783 } 1784 cpos += dp->d_reclen; 1785 dp = (struct dirent *)cpos; 1786 cookiep++; 1787 ncookies--; 1788 } 1789 if (cpos < cend) 1790 eofflag = 0; 1791 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1792 *tl++ = newnfs_false; 1793 if (eofflag) 1794 *tl = newnfs_true; 1795 else 1796 *tl = newnfs_false; 1797 FREE((caddr_t)rbuf, M_TEMP); 1798 FREE((caddr_t)cookies, M_TEMP); 1799 1800 out: 1801 NFSEXITCODE2(0, nd); 1802 return (0); 1803 nfsmout: 1804 vput(vp); 1805 NFSEXITCODE2(error, nd); 1806 return (error); 1807 } 1808 1809 /* 1810 * Readdirplus for V3 and Readdir for V4. 1811 */ 1812 int 1813 nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram, 1814 struct vnode *vp, struct thread *p, struct nfsexstuff *exp) 1815 { 1816 struct dirent *dp; 1817 u_int32_t *tl; 1818 int dirlen; 1819 char *cpos, *cend, *rbuf; 1820 struct vnode *nvp; 1821 fhandle_t nfh; 1822 struct nfsvattr nva, at, *nvap = &nva; 1823 struct mbuf *mb0, *mb1; 1824 struct nfsreferral *refp; 1825 int nlen, r, error = 0, getret = 1, usevget = 1; 1826 int siz, cnt, fullsiz, eofflag, ncookies, entrycnt; 1827 caddr_t bpos0, bpos1; 1828 u_int64_t off, toff, verf; 1829 u_long *cookies = NULL, *cookiep; 1830 nfsattrbit_t attrbits, rderrbits, savbits; 1831 struct uio io; 1832 struct iovec iv; 1833 struct componentname cn; 1834 int at_root, is_ufs, is_zfs, needs_unbusy, supports_nfsv4acls; 1835 struct mount *mp, *new_mp; 1836 uint64_t mounted_on_fileno; 1837 1838 if (nd->nd_repstat) { 1839 nfsrv_postopattr(nd, getret, &at); 1840 goto out; 1841 } 1842 NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED); 1843 off = fxdr_hyper(tl); 1844 toff = off; 1845 tl += 2; 1846 verf = fxdr_hyper(tl); 1847 tl += 2; 1848 siz = fxdr_unsigned(int, *tl++); 1849 cnt = fxdr_unsigned(int, *tl); 1850 1851 /* 1852 * Use the server's maximum data transfer size as the upper bound 1853 * on reply datalen. 1854 */ 1855 if (cnt > NFS_SRVMAXDATA(nd) || cnt < 0) 1856 cnt = NFS_SRVMAXDATA(nd); 1857 1858 /* 1859 * siz is a "hint" of how much directory information (name, fileid, 1860 * cookie) should be in the reply. At least one client "hints" 0, 1861 * so I set it to cnt for that case. I also round it up to the 1862 * next multiple of DIRBLKSIZ. 1863 */ 1864 if (siz <= 0) 1865 siz = cnt; 1866 siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); 1867 1868 if (nd->nd_flag & ND_NFSV4) { 1869 error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL); 1870 if (error) 1871 goto nfsmout; 1872 NFSSET_ATTRBIT(&savbits, &attrbits); 1873 NFSCLRNOTFILLABLE_ATTRBIT(&attrbits); 1874 NFSZERO_ATTRBIT(&rderrbits); 1875 NFSSETBIT_ATTRBIT(&rderrbits, NFSATTRBIT_RDATTRERROR); 1876 } else { 1877 NFSZERO_ATTRBIT(&attrbits); 1878 } 1879 fullsiz = siz; 1880 nd->nd_repstat = getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1); 1881 if (!nd->nd_repstat) { 1882 if (off && verf != at.na_filerev) { 1883 /* 1884 * va_filerev is not sufficient as a cookie verifier, 1885 * since it is not supposed to change when entries are 1886 * removed/added unless that offset cookies returned to 1887 * the client are no longer valid. 1888 */ 1889 #if 0 1890 if (nd->nd_flag & ND_NFSV4) { 1891 nd->nd_repstat = NFSERR_NOTSAME; 1892 } else { 1893 nd->nd_repstat = NFSERR_BAD_COOKIE; 1894 } 1895 #endif 1896 } else if ((nd->nd_flag & ND_NFSV4) && off == 0 && verf != 0) { 1897 nd->nd_repstat = NFSERR_BAD_COOKIE; 1898 } 1899 } 1900 if (!nd->nd_repstat && vp->v_type != VDIR) 1901 nd->nd_repstat = NFSERR_NOTDIR; 1902 if (!nd->nd_repstat && cnt == 0) 1903 nd->nd_repstat = NFSERR_TOOSMALL; 1904 if (!nd->nd_repstat) 1905 nd->nd_repstat = nfsvno_accchk(vp, VEXEC, 1906 nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE, 1907 NFSACCCHK_VPISLOCKED, NULL); 1908 if (nd->nd_repstat) { 1909 vput(vp); 1910 if (nd->nd_flag & ND_NFSV3) 1911 nfsrv_postopattr(nd, getret, &at); 1912 goto out; 1913 } 1914 is_ufs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "ufs") == 0; 1915 is_zfs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "zfs") == 0; 1916 1917 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 1918 again: 1919 eofflag = 0; 1920 if (cookies) { 1921 free((caddr_t)cookies, M_TEMP); 1922 cookies = NULL; 1923 } 1924 1925 iv.iov_base = rbuf; 1926 iv.iov_len = siz; 1927 io.uio_iov = &iv; 1928 io.uio_iovcnt = 1; 1929 io.uio_offset = (off_t)off; 1930 io.uio_resid = siz; 1931 io.uio_segflg = UIO_SYSSPACE; 1932 io.uio_rw = UIO_READ; 1933 io.uio_td = NULL; 1934 nd->nd_repstat = VOP_READDIR(vp, &io, nd->nd_cred, &eofflag, &ncookies, 1935 &cookies); 1936 off = (u_int64_t)io.uio_offset; 1937 if (io.uio_resid) 1938 siz -= io.uio_resid; 1939 1940 getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1); 1941 1942 if (!cookies && !nd->nd_repstat) 1943 nd->nd_repstat = NFSERR_PERM; 1944 if (!nd->nd_repstat) 1945 nd->nd_repstat = getret; 1946 if (nd->nd_repstat) { 1947 vput(vp); 1948 if (cookies) 1949 free((caddr_t)cookies, M_TEMP); 1950 free((caddr_t)rbuf, M_TEMP); 1951 if (nd->nd_flag & ND_NFSV3) 1952 nfsrv_postopattr(nd, getret, &at); 1953 goto out; 1954 } 1955 /* 1956 * If nothing read, return eof 1957 * rpc reply 1958 */ 1959 if (siz == 0) { 1960 vput(vp); 1961 if (nd->nd_flag & ND_NFSV3) 1962 nfsrv_postopattr(nd, getret, &at); 1963 NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 1964 txdr_hyper(at.na_filerev, tl); 1965 tl += 2; 1966 *tl++ = newnfs_false; 1967 *tl = newnfs_true; 1968 free((caddr_t)cookies, M_TEMP); 1969 free((caddr_t)rbuf, M_TEMP); 1970 goto out; 1971 } 1972 1973 /* 1974 * Check for degenerate cases of nothing useful read. 1975 * If so go try again 1976 */ 1977 cpos = rbuf; 1978 cend = rbuf + siz; 1979 dp = (struct dirent *)cpos; 1980 cookiep = cookies; 1981 1982 /* 1983 * For some reason FreeBSD's ufs_readdir() chooses to back the 1984 * directory offset up to a block boundary, so it is necessary to 1985 * skip over the records that precede the requested offset. This 1986 * requires the assumption that file offset cookies monotonically 1987 * increase. 1988 */ 1989 while (cpos < cend && ncookies > 0 && 1990 (dp->d_fileno == 0 || dp->d_type == DT_WHT || 1991 (is_ufs == 1 && ((u_quad_t)(*cookiep)) <= toff) || 1992 ((nd->nd_flag & ND_NFSV4) && 1993 ((dp->d_namlen == 1 && dp->d_name[0] == '.') || 1994 (dp->d_namlen==2 && dp->d_name[0]=='.' && dp->d_name[1]=='.'))))) { 1995 cpos += dp->d_reclen; 1996 dp = (struct dirent *)cpos; 1997 cookiep++; 1998 ncookies--; 1999 } 2000 if (cpos >= cend || ncookies == 0) { 2001 siz = fullsiz; 2002 toff = off; 2003 goto again; 2004 } 2005 2006 /* 2007 * Busy the file system so that the mount point won't go away 2008 * and, as such, VFS_VGET() can be used safely. 2009 */ 2010 mp = vp->v_mount; 2011 vfs_ref(mp); 2012 NFSVOPUNLOCK(vp, 0); 2013 nd->nd_repstat = vfs_busy(mp, 0); 2014 vfs_rel(mp); 2015 if (nd->nd_repstat != 0) { 2016 vrele(vp); 2017 free(cookies, M_TEMP); 2018 free(rbuf, M_TEMP); 2019 if (nd->nd_flag & ND_NFSV3) 2020 nfsrv_postopattr(nd, getret, &at); 2021 goto out; 2022 } 2023 2024 /* 2025 * Check to see if entries in this directory can be safely acquired 2026 * via VFS_VGET() or if a switch to VOP_LOOKUP() is required. 2027 * ZFS snapshot directories need VOP_LOOKUP(), so that any 2028 * automount of the snapshot directory that is required will 2029 * be done. 2030 * This needs to be done here for NFSv4, since NFSv4 never does 2031 * a VFS_VGET() for "." or "..". 2032 */ 2033 if (is_zfs == 1) { 2034 r = VFS_VGET(mp, at.na_fileid, LK_SHARED, &nvp); 2035 if (r == EOPNOTSUPP) { 2036 usevget = 0; 2037 cn.cn_nameiop = LOOKUP; 2038 cn.cn_lkflags = LK_SHARED | LK_RETRY; 2039 cn.cn_cred = nd->nd_cred; 2040 cn.cn_thread = p; 2041 } else if (r == 0) 2042 vput(nvp); 2043 } 2044 2045 /* 2046 * Save this position, in case there is an error before one entry 2047 * is created. 2048 */ 2049 mb0 = nd->nd_mb; 2050 bpos0 = nd->nd_bpos; 2051 2052 /* 2053 * Fill in the first part of the reply. 2054 * dirlen is the reply length in bytes and cannot exceed cnt. 2055 * (Include the two booleans at the end of the reply in dirlen now, 2056 * so we recognize when we have exceeded cnt.) 2057 */ 2058 if (nd->nd_flag & ND_NFSV3) { 2059 dirlen = NFSX_V3POSTOPATTR + NFSX_VERF + 2 * NFSX_UNSIGNED; 2060 nfsrv_postopattr(nd, getret, &at); 2061 } else { 2062 dirlen = NFSX_VERF + 2 * NFSX_UNSIGNED; 2063 } 2064 NFSM_BUILD(tl, u_int32_t *, NFSX_VERF); 2065 txdr_hyper(at.na_filerev, tl); 2066 2067 /* 2068 * Save this position, in case there is an empty reply needed. 2069 */ 2070 mb1 = nd->nd_mb; 2071 bpos1 = nd->nd_bpos; 2072 2073 /* Loop through the records and build reply */ 2074 entrycnt = 0; 2075 while (cpos < cend && ncookies > 0 && dirlen < cnt) { 2076 nlen = dp->d_namlen; 2077 if (dp->d_fileno != 0 && dp->d_type != DT_WHT && 2078 nlen <= NFS_MAXNAMLEN && 2079 ((nd->nd_flag & ND_NFSV3) || nlen > 2 || 2080 (nlen==2 && (dp->d_name[0]!='.' || dp->d_name[1]!='.')) 2081 || (nlen == 1 && dp->d_name[0] != '.'))) { 2082 /* 2083 * Save the current position in the reply, in case 2084 * this entry exceeds cnt. 2085 */ 2086 mb1 = nd->nd_mb; 2087 bpos1 = nd->nd_bpos; 2088 2089 /* 2090 * For readdir_and_lookup get the vnode using 2091 * the file number. 2092 */ 2093 nvp = NULL; 2094 refp = NULL; 2095 r = 0; 2096 at_root = 0; 2097 needs_unbusy = 0; 2098 new_mp = mp; 2099 mounted_on_fileno = (uint64_t)dp->d_fileno; 2100 if ((nd->nd_flag & ND_NFSV3) || 2101 NFSNONZERO_ATTRBIT(&savbits)) { 2102 if (nd->nd_flag & ND_NFSV4) 2103 refp = nfsv4root_getreferral(NULL, 2104 vp, dp->d_fileno); 2105 if (refp == NULL) { 2106 if (usevget) 2107 r = VFS_VGET(mp, dp->d_fileno, 2108 LK_SHARED, &nvp); 2109 else 2110 r = EOPNOTSUPP; 2111 if (r == EOPNOTSUPP) { 2112 if (usevget) { 2113 usevget = 0; 2114 cn.cn_nameiop = LOOKUP; 2115 cn.cn_lkflags = 2116 LK_SHARED | 2117 LK_RETRY; 2118 cn.cn_cred = 2119 nd->nd_cred; 2120 cn.cn_thread = p; 2121 } 2122 cn.cn_nameptr = dp->d_name; 2123 cn.cn_namelen = nlen; 2124 cn.cn_flags = ISLASTCN | 2125 NOFOLLOW | LOCKLEAF; 2126 if (nlen == 2 && 2127 dp->d_name[0] == '.' && 2128 dp->d_name[1] == '.') 2129 cn.cn_flags |= 2130 ISDOTDOT; 2131 if (NFSVOPLOCK(vp, LK_SHARED) 2132 != 0) { 2133 nd->nd_repstat = EPERM; 2134 break; 2135 } 2136 if ((vp->v_vflag & VV_ROOT) != 0 2137 && (cn.cn_flags & ISDOTDOT) 2138 != 0) { 2139 vref(vp); 2140 nvp = vp; 2141 r = 0; 2142 } else { 2143 r = VOP_LOOKUP(vp, &nvp, 2144 &cn); 2145 if (vp != nvp) 2146 NFSVOPUNLOCK(vp, 2147 0); 2148 } 2149 } 2150 2151 /* 2152 * For NFSv4, check to see if nvp is 2153 * a mount point and get the mount 2154 * point vnode, as required. 2155 */ 2156 if (r == 0 && 2157 nfsrv_enable_crossmntpt != 0 && 2158 (nd->nd_flag & ND_NFSV4) != 0 && 2159 nvp->v_type == VDIR && 2160 nvp->v_mountedhere != NULL) { 2161 new_mp = nvp->v_mountedhere; 2162 r = vfs_busy(new_mp, 0); 2163 vput(nvp); 2164 nvp = NULL; 2165 if (r == 0) { 2166 r = VFS_ROOT(new_mp, 2167 LK_SHARED, &nvp); 2168 needs_unbusy = 1; 2169 if (r == 0) 2170 at_root = 1; 2171 } 2172 } 2173 } 2174 if (!r) { 2175 if (refp == NULL && 2176 ((nd->nd_flag & ND_NFSV3) || 2177 NFSNONZERO_ATTRBIT(&attrbits))) { 2178 r = nfsvno_getfh(nvp, &nfh, p); 2179 if (!r) 2180 r = nfsvno_getattr(nvp, nvap, 2181 nd->nd_cred, p, 1); 2182 if (r == 0 && is_zfs == 1 && 2183 nfsrv_enable_crossmntpt != 0 && 2184 (nd->nd_flag & ND_NFSV4) != 0 && 2185 nvp->v_type == VDIR && 2186 vp->v_mount != nvp->v_mount) { 2187 /* 2188 * For a ZFS snapshot, there is a 2189 * pseudo mount that does not set 2190 * v_mountedhere, so it needs to 2191 * be detected via a different 2192 * mount structure. 2193 */ 2194 at_root = 1; 2195 if (new_mp == mp) 2196 new_mp = nvp->v_mount; 2197 } 2198 } 2199 } else { 2200 nvp = NULL; 2201 } 2202 if (r) { 2203 if (!NFSISSET_ATTRBIT(&attrbits, 2204 NFSATTRBIT_RDATTRERROR)) { 2205 if (nvp != NULL) 2206 vput(nvp); 2207 if (needs_unbusy != 0) 2208 vfs_unbusy(new_mp); 2209 nd->nd_repstat = r; 2210 break; 2211 } 2212 } 2213 } 2214 2215 /* 2216 * Build the directory record xdr 2217 */ 2218 if (nd->nd_flag & ND_NFSV3) { 2219 NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2220 *tl++ = newnfs_true; 2221 *tl++ = 0; 2222 *tl = txdr_unsigned(dp->d_fileno); 2223 dirlen += nfsm_strtom(nd, dp->d_name, nlen); 2224 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2225 *tl++ = 0; 2226 *tl = txdr_unsigned(*cookiep); 2227 nfsrv_postopattr(nd, 0, nvap); 2228 dirlen += nfsm_fhtom(nd,(u_int8_t *)&nfh,0,1); 2229 dirlen += (5*NFSX_UNSIGNED+NFSX_V3POSTOPATTR); 2230 if (nvp != NULL) 2231 vput(nvp); 2232 } else { 2233 NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2234 *tl++ = newnfs_true; 2235 *tl++ = 0; 2236 *tl = txdr_unsigned(*cookiep); 2237 dirlen += nfsm_strtom(nd, dp->d_name, nlen); 2238 if (nvp != NULL) { 2239 supports_nfsv4acls = 2240 nfs_supportsnfsv4acls(nvp); 2241 NFSVOPUNLOCK(nvp, 0); 2242 } else 2243 supports_nfsv4acls = 0; 2244 if (refp != NULL) { 2245 dirlen += nfsrv_putreferralattr(nd, 2246 &savbits, refp, 0, 2247 &nd->nd_repstat); 2248 if (nd->nd_repstat) { 2249 if (nvp != NULL) 2250 vrele(nvp); 2251 if (needs_unbusy != 0) 2252 vfs_unbusy(new_mp); 2253 break; 2254 } 2255 } else if (r) { 2256 dirlen += nfsvno_fillattr(nd, new_mp, 2257 nvp, nvap, &nfh, r, &rderrbits, 2258 nd->nd_cred, p, isdgram, 0, 2259 supports_nfsv4acls, at_root, 2260 mounted_on_fileno); 2261 } else { 2262 dirlen += nfsvno_fillattr(nd, new_mp, 2263 nvp, nvap, &nfh, r, &attrbits, 2264 nd->nd_cred, p, isdgram, 0, 2265 supports_nfsv4acls, at_root, 2266 mounted_on_fileno); 2267 } 2268 if (nvp != NULL) 2269 vrele(nvp); 2270 dirlen += (3 * NFSX_UNSIGNED); 2271 } 2272 if (needs_unbusy != 0) 2273 vfs_unbusy(new_mp); 2274 if (dirlen <= cnt) 2275 entrycnt++; 2276 } 2277 cpos += dp->d_reclen; 2278 dp = (struct dirent *)cpos; 2279 cookiep++; 2280 ncookies--; 2281 } 2282 vrele(vp); 2283 vfs_unbusy(mp); 2284 2285 /* 2286 * If dirlen > cnt, we must strip off the last entry. If that 2287 * results in an empty reply, report NFSERR_TOOSMALL. 2288 */ 2289 if (dirlen > cnt || nd->nd_repstat) { 2290 if (!nd->nd_repstat && entrycnt == 0) 2291 nd->nd_repstat = NFSERR_TOOSMALL; 2292 if (nd->nd_repstat) { 2293 newnfs_trimtrailing(nd, mb0, bpos0); 2294 if (nd->nd_flag & ND_NFSV3) 2295 nfsrv_postopattr(nd, getret, &at); 2296 } else 2297 newnfs_trimtrailing(nd, mb1, bpos1); 2298 eofflag = 0; 2299 } else if (cpos < cend) 2300 eofflag = 0; 2301 if (!nd->nd_repstat) { 2302 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2303 *tl++ = newnfs_false; 2304 if (eofflag) 2305 *tl = newnfs_true; 2306 else 2307 *tl = newnfs_false; 2308 } 2309 FREE((caddr_t)cookies, M_TEMP); 2310 FREE((caddr_t)rbuf, M_TEMP); 2311 2312 out: 2313 NFSEXITCODE2(0, nd); 2314 return (0); 2315 nfsmout: 2316 vput(vp); 2317 NFSEXITCODE2(error, nd); 2318 return (error); 2319 } 2320 2321 /* 2322 * Get the settable attributes out of the mbuf list. 2323 * (Return 0 or EBADRPC) 2324 */ 2325 int 2326 nfsrv_sattr(struct nfsrv_descript *nd, vnode_t vp, struct nfsvattr *nvap, 2327 nfsattrbit_t *attrbitp, NFSACL_T *aclp, struct thread *p) 2328 { 2329 u_int32_t *tl; 2330 struct nfsv2_sattr *sp; 2331 int error = 0, toclient = 0; 2332 2333 switch (nd->nd_flag & (ND_NFSV2 | ND_NFSV3 | ND_NFSV4)) { 2334 case ND_NFSV2: 2335 NFSM_DISSECT(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 2336 /* 2337 * Some old clients didn't fill in the high order 16bits. 2338 * --> check the low order 2 bytes for 0xffff 2339 */ 2340 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff) 2341 nvap->na_mode = nfstov_mode(sp->sa_mode); 2342 if (sp->sa_uid != newnfs_xdrneg1) 2343 nvap->na_uid = fxdr_unsigned(uid_t, sp->sa_uid); 2344 if (sp->sa_gid != newnfs_xdrneg1) 2345 nvap->na_gid = fxdr_unsigned(gid_t, sp->sa_gid); 2346 if (sp->sa_size != newnfs_xdrneg1) 2347 nvap->na_size = fxdr_unsigned(u_quad_t, sp->sa_size); 2348 if (sp->sa_atime.nfsv2_sec != newnfs_xdrneg1) { 2349 #ifdef notyet 2350 fxdr_nfsv2time(&sp->sa_atime, &nvap->na_atime); 2351 #else 2352 nvap->na_atime.tv_sec = 2353 fxdr_unsigned(u_int32_t,sp->sa_atime.nfsv2_sec); 2354 nvap->na_atime.tv_nsec = 0; 2355 #endif 2356 } 2357 if (sp->sa_mtime.nfsv2_sec != newnfs_xdrneg1) 2358 fxdr_nfsv2time(&sp->sa_mtime, &nvap->na_mtime); 2359 break; 2360 case ND_NFSV3: 2361 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2362 if (*tl == newnfs_true) { 2363 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2364 nvap->na_mode = nfstov_mode(*tl); 2365 } 2366 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2367 if (*tl == newnfs_true) { 2368 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2369 nvap->na_uid = fxdr_unsigned(uid_t, *tl); 2370 } 2371 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2372 if (*tl == newnfs_true) { 2373 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2374 nvap->na_gid = fxdr_unsigned(gid_t, *tl); 2375 } 2376 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2377 if (*tl == newnfs_true) { 2378 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2379 nvap->na_size = fxdr_hyper(tl); 2380 } 2381 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2382 switch (fxdr_unsigned(int, *tl)) { 2383 case NFSV3SATTRTIME_TOCLIENT: 2384 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2385 fxdr_nfsv3time(tl, &nvap->na_atime); 2386 toclient = 1; 2387 break; 2388 case NFSV3SATTRTIME_TOSERVER: 2389 vfs_timestamp(&nvap->na_atime); 2390 nvap->na_vaflags |= VA_UTIMES_NULL; 2391 break; 2392 } 2393 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2394 switch (fxdr_unsigned(int, *tl)) { 2395 case NFSV3SATTRTIME_TOCLIENT: 2396 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2397 fxdr_nfsv3time(tl, &nvap->na_mtime); 2398 nvap->na_vaflags &= ~VA_UTIMES_NULL; 2399 break; 2400 case NFSV3SATTRTIME_TOSERVER: 2401 vfs_timestamp(&nvap->na_mtime); 2402 if (!toclient) 2403 nvap->na_vaflags |= VA_UTIMES_NULL; 2404 break; 2405 } 2406 break; 2407 case ND_NFSV4: 2408 error = nfsv4_sattr(nd, vp, nvap, attrbitp, aclp, p); 2409 } 2410 nfsmout: 2411 NFSEXITCODE2(error, nd); 2412 return (error); 2413 } 2414 2415 /* 2416 * Handle the setable attributes for V4. 2417 * Returns NFSERR_BADXDR if it can't be parsed, 0 otherwise. 2418 */ 2419 int 2420 nfsv4_sattr(struct nfsrv_descript *nd, vnode_t vp, struct nfsvattr *nvap, 2421 nfsattrbit_t *attrbitp, NFSACL_T *aclp, struct thread *p) 2422 { 2423 u_int32_t *tl; 2424 int attrsum = 0; 2425 int i, j; 2426 int error, attrsize, bitpos, aclsize, aceerr, retnotsup = 0; 2427 int toclient = 0; 2428 u_char *cp, namestr[NFSV4_SMALLSTR + 1]; 2429 uid_t uid; 2430 gid_t gid; 2431 2432 error = nfsrv_getattrbits(nd, attrbitp, NULL, &retnotsup); 2433 if (error) 2434 goto nfsmout; 2435 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2436 attrsize = fxdr_unsigned(int, *tl); 2437 2438 /* 2439 * Loop around getting the setable attributes. If an unsupported 2440 * one is found, set nd_repstat == NFSERR_ATTRNOTSUPP and return. 2441 */ 2442 if (retnotsup) { 2443 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 2444 bitpos = NFSATTRBIT_MAX; 2445 } else { 2446 bitpos = 0; 2447 } 2448 for (; bitpos < NFSATTRBIT_MAX; bitpos++) { 2449 if (attrsum > attrsize) { 2450 error = NFSERR_BADXDR; 2451 goto nfsmout; 2452 } 2453 if (NFSISSET_ATTRBIT(attrbitp, bitpos)) 2454 switch (bitpos) { 2455 case NFSATTRBIT_SIZE: 2456 NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER); 2457 if (vp != NULL && vp->v_type != VREG) { 2458 error = (vp->v_type == VDIR) ? NFSERR_ISDIR : 2459 NFSERR_INVAL; 2460 goto nfsmout; 2461 } 2462 nvap->na_size = fxdr_hyper(tl); 2463 attrsum += NFSX_HYPER; 2464 break; 2465 case NFSATTRBIT_ACL: 2466 error = nfsrv_dissectacl(nd, aclp, &aceerr, &aclsize, 2467 p); 2468 if (error) 2469 goto nfsmout; 2470 if (aceerr && !nd->nd_repstat) 2471 nd->nd_repstat = aceerr; 2472 attrsum += aclsize; 2473 break; 2474 case NFSATTRBIT_ARCHIVE: 2475 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2476 if (!nd->nd_repstat) 2477 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 2478 attrsum += NFSX_UNSIGNED; 2479 break; 2480 case NFSATTRBIT_HIDDEN: 2481 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2482 if (!nd->nd_repstat) 2483 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 2484 attrsum += NFSX_UNSIGNED; 2485 break; 2486 case NFSATTRBIT_MIMETYPE: 2487 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2488 i = fxdr_unsigned(int, *tl); 2489 error = nfsm_advance(nd, NFSM_RNDUP(i), -1); 2490 if (error) 2491 goto nfsmout; 2492 if (!nd->nd_repstat) 2493 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 2494 attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(i)); 2495 break; 2496 case NFSATTRBIT_MODE: 2497 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2498 nvap->na_mode = nfstov_mode(*tl); 2499 attrsum += NFSX_UNSIGNED; 2500 break; 2501 case NFSATTRBIT_OWNER: 2502 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2503 j = fxdr_unsigned(int, *tl); 2504 if (j < 0) { 2505 error = NFSERR_BADXDR; 2506 goto nfsmout; 2507 } 2508 if (j > NFSV4_SMALLSTR) 2509 cp = malloc(j + 1, M_NFSSTRING, M_WAITOK); 2510 else 2511 cp = namestr; 2512 error = nfsrv_mtostr(nd, cp, j); 2513 if (error) { 2514 if (j > NFSV4_SMALLSTR) 2515 free(cp, M_NFSSTRING); 2516 goto nfsmout; 2517 } 2518 if (!nd->nd_repstat) { 2519 nd->nd_repstat = nfsv4_strtouid(nd, cp, j, &uid, 2520 p); 2521 if (!nd->nd_repstat) 2522 nvap->na_uid = uid; 2523 } 2524 if (j > NFSV4_SMALLSTR) 2525 free(cp, M_NFSSTRING); 2526 attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(j)); 2527 break; 2528 case NFSATTRBIT_OWNERGROUP: 2529 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2530 j = fxdr_unsigned(int, *tl); 2531 if (j < 0) { 2532 error = NFSERR_BADXDR; 2533 goto nfsmout; 2534 } 2535 if (j > NFSV4_SMALLSTR) 2536 cp = malloc(j + 1, M_NFSSTRING, M_WAITOK); 2537 else 2538 cp = namestr; 2539 error = nfsrv_mtostr(nd, cp, j); 2540 if (error) { 2541 if (j > NFSV4_SMALLSTR) 2542 free(cp, M_NFSSTRING); 2543 goto nfsmout; 2544 } 2545 if (!nd->nd_repstat) { 2546 nd->nd_repstat = nfsv4_strtogid(nd, cp, j, &gid, 2547 p); 2548 if (!nd->nd_repstat) 2549 nvap->na_gid = gid; 2550 } 2551 if (j > NFSV4_SMALLSTR) 2552 free(cp, M_NFSSTRING); 2553 attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(j)); 2554 break; 2555 case NFSATTRBIT_SYSTEM: 2556 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2557 if (!nd->nd_repstat) 2558 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 2559 attrsum += NFSX_UNSIGNED; 2560 break; 2561 case NFSATTRBIT_TIMEACCESSSET: 2562 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2563 attrsum += NFSX_UNSIGNED; 2564 if (fxdr_unsigned(int, *tl)==NFSV4SATTRTIME_TOCLIENT) { 2565 NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME); 2566 fxdr_nfsv4time(tl, &nvap->na_atime); 2567 toclient = 1; 2568 attrsum += NFSX_V4TIME; 2569 } else { 2570 vfs_timestamp(&nvap->na_atime); 2571 nvap->na_vaflags |= VA_UTIMES_NULL; 2572 } 2573 break; 2574 case NFSATTRBIT_TIMEBACKUP: 2575 NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME); 2576 if (!nd->nd_repstat) 2577 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 2578 attrsum += NFSX_V4TIME; 2579 break; 2580 case NFSATTRBIT_TIMECREATE: 2581 NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME); 2582 if (!nd->nd_repstat) 2583 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 2584 attrsum += NFSX_V4TIME; 2585 break; 2586 case NFSATTRBIT_TIMEMODIFYSET: 2587 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2588 attrsum += NFSX_UNSIGNED; 2589 if (fxdr_unsigned(int, *tl)==NFSV4SATTRTIME_TOCLIENT) { 2590 NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME); 2591 fxdr_nfsv4time(tl, &nvap->na_mtime); 2592 nvap->na_vaflags &= ~VA_UTIMES_NULL; 2593 attrsum += NFSX_V4TIME; 2594 } else { 2595 vfs_timestamp(&nvap->na_mtime); 2596 if (!toclient) 2597 nvap->na_vaflags |= VA_UTIMES_NULL; 2598 } 2599 break; 2600 default: 2601 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 2602 /* 2603 * set bitpos so we drop out of the loop. 2604 */ 2605 bitpos = NFSATTRBIT_MAX; 2606 break; 2607 } 2608 } 2609 2610 /* 2611 * some clients pad the attrlist, so we need to skip over the 2612 * padding. 2613 */ 2614 if (attrsum > attrsize) { 2615 error = NFSERR_BADXDR; 2616 } else { 2617 attrsize = NFSM_RNDUP(attrsize); 2618 if (attrsum < attrsize) 2619 error = nfsm_advance(nd, attrsize - attrsum, -1); 2620 } 2621 nfsmout: 2622 NFSEXITCODE2(error, nd); 2623 return (error); 2624 } 2625 2626 /* 2627 * Check/setup export credentials. 2628 */ 2629 int 2630 nfsd_excred(struct nfsrv_descript *nd, struct nfsexstuff *exp, 2631 struct ucred *credanon) 2632 { 2633 int error = 0; 2634 2635 /* 2636 * Check/setup credentials. 2637 */ 2638 if (nd->nd_flag & ND_GSS) 2639 exp->nes_exflag &= ~MNT_EXPORTANON; 2640 2641 /* 2642 * Check to see if the operation is allowed for this security flavor. 2643 * RFC2623 suggests that the NFSv3 Fsinfo RPC be allowed to 2644 * AUTH_NONE or AUTH_SYS for file systems requiring RPCSEC_GSS. 2645 * Also, allow Secinfo, so that it can acquire the correct flavor(s). 2646 */ 2647 if (nfsvno_testexp(nd, exp) && 2648 nd->nd_procnum != NFSV4OP_SECINFO && 2649 nd->nd_procnum != NFSPROC_FSINFO) { 2650 if (nd->nd_flag & ND_NFSV4) 2651 error = NFSERR_WRONGSEC; 2652 else 2653 error = (NFSERR_AUTHERR | AUTH_TOOWEAK); 2654 goto out; 2655 } 2656 2657 /* 2658 * Check to see if the file system is exported V4 only. 2659 */ 2660 if (NFSVNO_EXV4ONLY(exp) && !(nd->nd_flag & ND_NFSV4)) { 2661 error = NFSERR_PROGNOTV4; 2662 goto out; 2663 } 2664 2665 /* 2666 * Now, map the user credentials. 2667 * (Note that ND_AUTHNONE will only be set for an NFSv3 2668 * Fsinfo RPC. If set for anything else, this code might need 2669 * to change.) 2670 */ 2671 if (NFSVNO_EXPORTED(exp)) { 2672 if (((nd->nd_flag & ND_GSS) == 0 && nd->nd_cred->cr_uid == 0) || 2673 NFSVNO_EXPORTANON(exp) || 2674 (nd->nd_flag & ND_AUTHNONE) != 0) { 2675 nd->nd_cred->cr_uid = credanon->cr_uid; 2676 nd->nd_cred->cr_gid = credanon->cr_gid; 2677 crsetgroups(nd->nd_cred, credanon->cr_ngroups, 2678 credanon->cr_groups); 2679 } else if ((nd->nd_flag & ND_GSS) == 0) { 2680 /* 2681 * If using AUTH_SYS, call nfsrv_getgrpscred() to see 2682 * if there is a replacement credential with a group 2683 * list set up by "nfsuserd -manage-gids". 2684 * If there is no replacement, nfsrv_getgrpscred() 2685 * simply returns its argument. 2686 */ 2687 nd->nd_cred = nfsrv_getgrpscred(nd->nd_cred); 2688 } 2689 } 2690 2691 out: 2692 NFSEXITCODE2(error, nd); 2693 return (error); 2694 } 2695 2696 /* 2697 * Check exports. 2698 */ 2699 int 2700 nfsvno_checkexp(struct mount *mp, struct sockaddr *nam, struct nfsexstuff *exp, 2701 struct ucred **credp) 2702 { 2703 int i, error, *secflavors; 2704 2705 error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp, 2706 &exp->nes_numsecflavor, &secflavors); 2707 if (error) { 2708 if (nfs_rootfhset) { 2709 exp->nes_exflag = 0; 2710 exp->nes_numsecflavor = 0; 2711 error = 0; 2712 } 2713 } else { 2714 /* Copy the security flavors. */ 2715 for (i = 0; i < exp->nes_numsecflavor; i++) 2716 exp->nes_secflavors[i] = secflavors[i]; 2717 } 2718 NFSEXITCODE(error); 2719 return (error); 2720 } 2721 2722 /* 2723 * Get a vnode for a file handle and export stuff. 2724 */ 2725 int 2726 nfsvno_fhtovp(struct mount *mp, fhandle_t *fhp, struct sockaddr *nam, 2727 int lktype, struct vnode **vpp, struct nfsexstuff *exp, 2728 struct ucred **credp) 2729 { 2730 int i, error, *secflavors; 2731 2732 *credp = NULL; 2733 exp->nes_numsecflavor = 0; 2734 error = VFS_FHTOVP(mp, &fhp->fh_fid, lktype, vpp); 2735 if (error != 0) 2736 /* Make sure the server replies ESTALE to the client. */ 2737 error = ESTALE; 2738 if (nam && !error) { 2739 error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp, 2740 &exp->nes_numsecflavor, &secflavors); 2741 if (error) { 2742 if (nfs_rootfhset) { 2743 exp->nes_exflag = 0; 2744 exp->nes_numsecflavor = 0; 2745 error = 0; 2746 } else { 2747 vput(*vpp); 2748 } 2749 } else { 2750 /* Copy the security flavors. */ 2751 for (i = 0; i < exp->nes_numsecflavor; i++) 2752 exp->nes_secflavors[i] = secflavors[i]; 2753 } 2754 } 2755 NFSEXITCODE(error); 2756 return (error); 2757 } 2758 2759 /* 2760 * nfsd_fhtovp() - convert a fh to a vnode ptr 2761 * - look up fsid in mount list (if not found ret error) 2762 * - get vp and export rights by calling nfsvno_fhtovp() 2763 * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon 2764 * for AUTH_SYS 2765 * - if mpp != NULL, return the mount point so that it can 2766 * be used for vn_finished_write() by the caller 2767 */ 2768 void 2769 nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp, int lktype, 2770 struct vnode **vpp, struct nfsexstuff *exp, 2771 struct mount **mpp, int startwrite, struct thread *p) 2772 { 2773 struct mount *mp; 2774 struct ucred *credanon; 2775 fhandle_t *fhp; 2776 2777 fhp = (fhandle_t *)nfp->nfsrvfh_data; 2778 /* 2779 * Check for the special case of the nfsv4root_fh. 2780 */ 2781 mp = vfs_busyfs(&fhp->fh_fsid); 2782 if (mpp != NULL) 2783 *mpp = mp; 2784 if (mp == NULL) { 2785 *vpp = NULL; 2786 nd->nd_repstat = ESTALE; 2787 goto out; 2788 } 2789 2790 if (startwrite) { 2791 vn_start_write(NULL, mpp, V_WAIT); 2792 if (lktype == LK_SHARED && !(MNT_SHARED_WRITES(mp))) 2793 lktype = LK_EXCLUSIVE; 2794 } 2795 nd->nd_repstat = nfsvno_fhtovp(mp, fhp, nd->nd_nam, lktype, vpp, exp, 2796 &credanon); 2797 vfs_unbusy(mp); 2798 2799 /* 2800 * For NFSv4 without a pseudo root fs, unexported file handles 2801 * can be returned, so that Lookup works everywhere. 2802 */ 2803 if (!nd->nd_repstat && exp->nes_exflag == 0 && 2804 !(nd->nd_flag & ND_NFSV4)) { 2805 vput(*vpp); 2806 nd->nd_repstat = EACCES; 2807 } 2808 2809 /* 2810 * Personally, I've never seen any point in requiring a 2811 * reserved port#, since only in the rare case where the 2812 * clients are all boxes with secure system privileges, 2813 * does it provide any enhanced security, but... some people 2814 * believe it to be useful and keep putting this code back in. 2815 * (There is also some "security checker" out there that 2816 * complains if the nfs server doesn't enforce this.) 2817 * However, note the following: 2818 * RFC3530 (NFSv4) specifies that a reserved port# not be 2819 * required. 2820 * RFC2623 recommends that, if a reserved port# is checked for, 2821 * that there be a way to turn that off--> ifdef'd. 2822 */ 2823 #ifdef NFS_REQRSVPORT 2824 if (!nd->nd_repstat) { 2825 struct sockaddr_in *saddr; 2826 struct sockaddr_in6 *saddr6; 2827 2828 saddr = NFSSOCKADDR(nd->nd_nam, struct sockaddr_in *); 2829 saddr6 = NFSSOCKADDR(nd->nd_nam, struct sockaddr_in6 *); 2830 if (!(nd->nd_flag & ND_NFSV4) && 2831 ((saddr->sin_family == AF_INET && 2832 ntohs(saddr->sin_port) >= IPPORT_RESERVED) || 2833 (saddr6->sin6_family == AF_INET6 && 2834 ntohs(saddr6->sin6_port) >= IPPORT_RESERVED))) { 2835 vput(*vpp); 2836 nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK); 2837 } 2838 } 2839 #endif /* NFS_REQRSVPORT */ 2840 2841 /* 2842 * Check/setup credentials. 2843 */ 2844 if (!nd->nd_repstat) { 2845 nd->nd_saveduid = nd->nd_cred->cr_uid; 2846 nd->nd_repstat = nfsd_excred(nd, exp, credanon); 2847 if (nd->nd_repstat) 2848 vput(*vpp); 2849 } 2850 if (credanon != NULL) 2851 crfree(credanon); 2852 if (nd->nd_repstat) { 2853 if (startwrite) 2854 vn_finished_write(mp); 2855 *vpp = NULL; 2856 if (mpp != NULL) 2857 *mpp = NULL; 2858 } 2859 2860 out: 2861 NFSEXITCODE2(0, nd); 2862 } 2863 2864 /* 2865 * glue for fp. 2866 */ 2867 static int 2868 fp_getfvp(struct thread *p, int fd, struct file **fpp, struct vnode **vpp) 2869 { 2870 struct filedesc *fdp; 2871 struct file *fp; 2872 int error = 0; 2873 2874 fdp = p->td_proc->p_fd; 2875 if (fd < 0 || fd >= fdp->fd_nfiles || 2876 (fp = fdp->fd_ofiles[fd].fde_file) == NULL) { 2877 error = EBADF; 2878 goto out; 2879 } 2880 *fpp = fp; 2881 2882 out: 2883 NFSEXITCODE(error); 2884 return (error); 2885 } 2886 2887 /* 2888 * Called from nfssvc() to update the exports list. Just call 2889 * vfs_export(). This has to be done, since the v4 root fake fs isn't 2890 * in the mount list. 2891 */ 2892 int 2893 nfsrv_v4rootexport(void *argp, struct ucred *cred, struct thread *p) 2894 { 2895 struct nfsex_args *nfsexargp = (struct nfsex_args *)argp; 2896 int error = 0; 2897 struct nameidata nd; 2898 fhandle_t fh; 2899 2900 error = vfs_export(&nfsv4root_mnt, &nfsexargp->export); 2901 if ((nfsexargp->export.ex_flags & MNT_DELEXPORT) != 0) 2902 nfs_rootfhset = 0; 2903 else if (error == 0) { 2904 if (nfsexargp->fspec == NULL) { 2905 error = EPERM; 2906 goto out; 2907 } 2908 /* 2909 * If fspec != NULL, this is the v4root path. 2910 */ 2911 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, 2912 nfsexargp->fspec, p); 2913 if ((error = namei(&nd)) != 0) 2914 goto out; 2915 error = nfsvno_getfh(nd.ni_vp, &fh, p); 2916 vrele(nd.ni_vp); 2917 if (!error) { 2918 nfs_rootfh.nfsrvfh_len = NFSX_MYFH; 2919 NFSBCOPY((caddr_t)&fh, 2920 nfs_rootfh.nfsrvfh_data, 2921 sizeof (fhandle_t)); 2922 nfs_rootfhset = 1; 2923 } 2924 } 2925 2926 out: 2927 NFSEXITCODE(error); 2928 return (error); 2929 } 2930 2931 /* 2932 * This function needs to test to see if the system is near its limit 2933 * for memory allocation via malloc() or mget() and return True iff 2934 * either of these resources are near their limit. 2935 * XXX (For now, this is just a stub.) 2936 */ 2937 int nfsrv_testmalloclimit = 0; 2938 int 2939 nfsrv_mallocmget_limit(void) 2940 { 2941 static int printmesg = 0; 2942 static int testval = 1; 2943 2944 if (nfsrv_testmalloclimit && (testval++ % 1000) == 0) { 2945 if ((printmesg++ % 100) == 0) 2946 printf("nfsd: malloc/mget near limit\n"); 2947 return (1); 2948 } 2949 return (0); 2950 } 2951 2952 /* 2953 * BSD specific initialization of a mount point. 2954 */ 2955 void 2956 nfsd_mntinit(void) 2957 { 2958 static int inited = 0; 2959 2960 if (inited) 2961 return; 2962 inited = 1; 2963 nfsv4root_mnt.mnt_flag = (MNT_RDONLY | MNT_EXPORTED); 2964 TAILQ_INIT(&nfsv4root_mnt.mnt_nvnodelist); 2965 TAILQ_INIT(&nfsv4root_mnt.mnt_activevnodelist); 2966 nfsv4root_mnt.mnt_export = NULL; 2967 TAILQ_INIT(&nfsv4root_opt); 2968 TAILQ_INIT(&nfsv4root_newopt); 2969 nfsv4root_mnt.mnt_opt = &nfsv4root_opt; 2970 nfsv4root_mnt.mnt_optnew = &nfsv4root_newopt; 2971 nfsv4root_mnt.mnt_nvnodelistsize = 0; 2972 nfsv4root_mnt.mnt_activevnodelistsize = 0; 2973 } 2974 2975 /* 2976 * Get a vnode for a file handle, without checking exports, etc. 2977 */ 2978 struct vnode * 2979 nfsvno_getvp(fhandle_t *fhp) 2980 { 2981 struct mount *mp; 2982 struct vnode *vp; 2983 int error; 2984 2985 mp = vfs_busyfs(&fhp->fh_fsid); 2986 if (mp == NULL) 2987 return (NULL); 2988 error = VFS_FHTOVP(mp, &fhp->fh_fid, LK_EXCLUSIVE, &vp); 2989 vfs_unbusy(mp); 2990 if (error) 2991 return (NULL); 2992 return (vp); 2993 } 2994 2995 /* 2996 * Do a local VOP_ADVLOCK(). 2997 */ 2998 int 2999 nfsvno_advlock(struct vnode *vp, int ftype, u_int64_t first, 3000 u_int64_t end, struct thread *td) 3001 { 3002 int error = 0; 3003 struct flock fl; 3004 u_int64_t tlen; 3005 3006 if (nfsrv_dolocallocks == 0) 3007 goto out; 3008 ASSERT_VOP_UNLOCKED(vp, "nfsvno_advlock: vp locked"); 3009 3010 fl.l_whence = SEEK_SET; 3011 fl.l_type = ftype; 3012 fl.l_start = (off_t)first; 3013 if (end == NFS64BITSSET) { 3014 fl.l_len = 0; 3015 } else { 3016 tlen = end - first; 3017 fl.l_len = (off_t)tlen; 3018 } 3019 /* 3020 * For FreeBSD8, the l_pid and l_sysid must be set to the same 3021 * values for all calls, so that all locks will be held by the 3022 * nfsd server. (The nfsd server handles conflicts between the 3023 * various clients.) 3024 * Since an NFSv4 lockowner is a ClientID plus an array of up to 1024 3025 * bytes, so it can't be put in l_sysid. 3026 */ 3027 if (nfsv4_sysid == 0) 3028 nfsv4_sysid = nlm_acquire_next_sysid(); 3029 fl.l_pid = (pid_t)0; 3030 fl.l_sysid = (int)nfsv4_sysid; 3031 3032 if (ftype == F_UNLCK) 3033 error = VOP_ADVLOCK(vp, (caddr_t)td->td_proc, F_UNLCK, &fl, 3034 (F_POSIX | F_REMOTE)); 3035 else 3036 error = VOP_ADVLOCK(vp, (caddr_t)td->td_proc, F_SETLK, &fl, 3037 (F_POSIX | F_REMOTE)); 3038 3039 out: 3040 NFSEXITCODE(error); 3041 return (error); 3042 } 3043 3044 /* 3045 * Check the nfsv4 root exports. 3046 */ 3047 int 3048 nfsvno_v4rootexport(struct nfsrv_descript *nd) 3049 { 3050 struct ucred *credanon; 3051 int exflags, error = 0, numsecflavor, *secflavors, i; 3052 3053 error = vfs_stdcheckexp(&nfsv4root_mnt, nd->nd_nam, &exflags, 3054 &credanon, &numsecflavor, &secflavors); 3055 if (error) { 3056 error = NFSERR_PROGUNAVAIL; 3057 goto out; 3058 } 3059 if (credanon != NULL) 3060 crfree(credanon); 3061 for (i = 0; i < numsecflavor; i++) { 3062 if (secflavors[i] == AUTH_SYS) 3063 nd->nd_flag |= ND_EXAUTHSYS; 3064 else if (secflavors[i] == RPCSEC_GSS_KRB5) 3065 nd->nd_flag |= ND_EXGSS; 3066 else if (secflavors[i] == RPCSEC_GSS_KRB5I) 3067 nd->nd_flag |= ND_EXGSSINTEGRITY; 3068 else if (secflavors[i] == RPCSEC_GSS_KRB5P) 3069 nd->nd_flag |= ND_EXGSSPRIVACY; 3070 } 3071 3072 out: 3073 NFSEXITCODE(error); 3074 return (error); 3075 } 3076 3077 /* 3078 * Nfs server pseudo system call for the nfsd's 3079 */ 3080 /* 3081 * MPSAFE 3082 */ 3083 static int 3084 nfssvc_nfsd(struct thread *td, struct nfssvc_args *uap) 3085 { 3086 struct file *fp; 3087 struct nfsd_addsock_args sockarg; 3088 struct nfsd_nfsd_args nfsdarg; 3089 cap_rights_t rights; 3090 int error; 3091 3092 if (uap->flag & NFSSVC_NFSDADDSOCK) { 3093 error = copyin(uap->argp, (caddr_t)&sockarg, sizeof (sockarg)); 3094 if (error) 3095 goto out; 3096 /* 3097 * Since we don't know what rights might be required, 3098 * pretend that we need them all. It is better to be too 3099 * careful than too reckless. 3100 */ 3101 error = fget(td, sockarg.sock, 3102 cap_rights_init(&rights, CAP_SOCK_SERVER), &fp); 3103 if (error != 0) 3104 goto out; 3105 if (fp->f_type != DTYPE_SOCKET) { 3106 fdrop(fp, td); 3107 error = EPERM; 3108 goto out; 3109 } 3110 error = nfsrvd_addsock(fp); 3111 fdrop(fp, td); 3112 } else if (uap->flag & NFSSVC_NFSDNFSD) { 3113 if (uap->argp == NULL) { 3114 error = EINVAL; 3115 goto out; 3116 } 3117 error = copyin(uap->argp, (caddr_t)&nfsdarg, 3118 sizeof (nfsdarg)); 3119 if (error) 3120 goto out; 3121 error = nfsrvd_nfsd(td, &nfsdarg); 3122 } else { 3123 error = nfssvc_srvcall(td, uap, td->td_ucred); 3124 } 3125 3126 out: 3127 NFSEXITCODE(error); 3128 return (error); 3129 } 3130 3131 static int 3132 nfssvc_srvcall(struct thread *p, struct nfssvc_args *uap, struct ucred *cred) 3133 { 3134 struct nfsex_args export; 3135 struct file *fp = NULL; 3136 int stablefd, len; 3137 struct nfsd_clid adminrevoke; 3138 struct nfsd_dumplist dumplist; 3139 struct nfsd_dumpclients *dumpclients; 3140 struct nfsd_dumplocklist dumplocklist; 3141 struct nfsd_dumplocks *dumplocks; 3142 struct nameidata nd; 3143 vnode_t vp; 3144 int error = EINVAL, igotlock; 3145 struct proc *procp; 3146 static int suspend_nfsd = 0; 3147 3148 if (uap->flag & NFSSVC_PUBLICFH) { 3149 NFSBZERO((caddr_t)&nfs_pubfh.nfsrvfh_data, 3150 sizeof (fhandle_t)); 3151 error = copyin(uap->argp, 3152 &nfs_pubfh.nfsrvfh_data, sizeof (fhandle_t)); 3153 if (!error) 3154 nfs_pubfhset = 1; 3155 } else if (uap->flag & NFSSVC_V4ROOTEXPORT) { 3156 error = copyin(uap->argp,(caddr_t)&export, 3157 sizeof (struct nfsex_args)); 3158 if (!error) 3159 error = nfsrv_v4rootexport(&export, cred, p); 3160 } else if (uap->flag & NFSSVC_NOPUBLICFH) { 3161 nfs_pubfhset = 0; 3162 error = 0; 3163 } else if (uap->flag & NFSSVC_STABLERESTART) { 3164 error = copyin(uap->argp, (caddr_t)&stablefd, 3165 sizeof (int)); 3166 if (!error) 3167 error = fp_getfvp(p, stablefd, &fp, &vp); 3168 if (!error && (NFSFPFLAG(fp) & (FREAD | FWRITE)) != (FREAD | FWRITE)) 3169 error = EBADF; 3170 if (!error && newnfs_numnfsd != 0) 3171 error = EPERM; 3172 if (!error) { 3173 nfsrv_stablefirst.nsf_fp = fp; 3174 nfsrv_setupstable(p); 3175 } 3176 } else if (uap->flag & NFSSVC_ADMINREVOKE) { 3177 error = copyin(uap->argp, (caddr_t)&adminrevoke, 3178 sizeof (struct nfsd_clid)); 3179 if (!error) 3180 error = nfsrv_adminrevoke(&adminrevoke, p); 3181 } else if (uap->flag & NFSSVC_DUMPCLIENTS) { 3182 error = copyin(uap->argp, (caddr_t)&dumplist, 3183 sizeof (struct nfsd_dumplist)); 3184 if (!error && (dumplist.ndl_size < 1 || 3185 dumplist.ndl_size > NFSRV_MAXDUMPLIST)) 3186 error = EPERM; 3187 if (!error) { 3188 len = sizeof (struct nfsd_dumpclients) * dumplist.ndl_size; 3189 dumpclients = (struct nfsd_dumpclients *)malloc(len, 3190 M_TEMP, M_WAITOK); 3191 nfsrv_dumpclients(dumpclients, dumplist.ndl_size); 3192 error = copyout(dumpclients, 3193 CAST_USER_ADDR_T(dumplist.ndl_list), len); 3194 free((caddr_t)dumpclients, M_TEMP); 3195 } 3196 } else if (uap->flag & NFSSVC_DUMPLOCKS) { 3197 error = copyin(uap->argp, (caddr_t)&dumplocklist, 3198 sizeof (struct nfsd_dumplocklist)); 3199 if (!error && (dumplocklist.ndllck_size < 1 || 3200 dumplocklist.ndllck_size > NFSRV_MAXDUMPLIST)) 3201 error = EPERM; 3202 if (!error) 3203 error = nfsrv_lookupfilename(&nd, 3204 dumplocklist.ndllck_fname, p); 3205 if (!error) { 3206 len = sizeof (struct nfsd_dumplocks) * 3207 dumplocklist.ndllck_size; 3208 dumplocks = (struct nfsd_dumplocks *)malloc(len, 3209 M_TEMP, M_WAITOK); 3210 nfsrv_dumplocks(nd.ni_vp, dumplocks, 3211 dumplocklist.ndllck_size, p); 3212 vput(nd.ni_vp); 3213 error = copyout(dumplocks, 3214 CAST_USER_ADDR_T(dumplocklist.ndllck_list), len); 3215 free((caddr_t)dumplocks, M_TEMP); 3216 } 3217 } else if (uap->flag & NFSSVC_BACKUPSTABLE) { 3218 procp = p->td_proc; 3219 PROC_LOCK(procp); 3220 nfsd_master_pid = procp->p_pid; 3221 bcopy(procp->p_comm, nfsd_master_comm, MAXCOMLEN + 1); 3222 nfsd_master_start = procp->p_stats->p_start; 3223 nfsd_master_proc = procp; 3224 PROC_UNLOCK(procp); 3225 } else if ((uap->flag & NFSSVC_SUSPENDNFSD) != 0) { 3226 NFSLOCKV4ROOTMUTEX(); 3227 if (suspend_nfsd == 0) { 3228 /* Lock out all nfsd threads */ 3229 do { 3230 igotlock = nfsv4_lock(&nfsd_suspend_lock, 1, 3231 NULL, NFSV4ROOTLOCKMUTEXPTR, NULL); 3232 } while (igotlock == 0 && suspend_nfsd == 0); 3233 suspend_nfsd = 1; 3234 } 3235 NFSUNLOCKV4ROOTMUTEX(); 3236 error = 0; 3237 } else if ((uap->flag & NFSSVC_RESUMENFSD) != 0) { 3238 NFSLOCKV4ROOTMUTEX(); 3239 if (suspend_nfsd != 0) { 3240 nfsv4_unlock(&nfsd_suspend_lock, 0); 3241 suspend_nfsd = 0; 3242 } 3243 NFSUNLOCKV4ROOTMUTEX(); 3244 error = 0; 3245 } 3246 3247 NFSEXITCODE(error); 3248 return (error); 3249 } 3250 3251 /* 3252 * Check exports. 3253 * Returns 0 if ok, 1 otherwise. 3254 */ 3255 int 3256 nfsvno_testexp(struct nfsrv_descript *nd, struct nfsexstuff *exp) 3257 { 3258 int i; 3259 3260 /* 3261 * This seems odd, but allow the case where the security flavor 3262 * list is empty. This happens when NFSv4 is traversing non-exported 3263 * file systems. Exported file systems should always have a non-empty 3264 * security flavor list. 3265 */ 3266 if (exp->nes_numsecflavor == 0) 3267 return (0); 3268 3269 for (i = 0; i < exp->nes_numsecflavor; i++) { 3270 /* 3271 * The tests for privacy and integrity must be first, 3272 * since ND_GSS is set for everything but AUTH_SYS. 3273 */ 3274 if (exp->nes_secflavors[i] == RPCSEC_GSS_KRB5P && 3275 (nd->nd_flag & ND_GSSPRIVACY)) 3276 return (0); 3277 if (exp->nes_secflavors[i] == RPCSEC_GSS_KRB5I && 3278 (nd->nd_flag & ND_GSSINTEGRITY)) 3279 return (0); 3280 if (exp->nes_secflavors[i] == RPCSEC_GSS_KRB5 && 3281 (nd->nd_flag & ND_GSS)) 3282 return (0); 3283 if (exp->nes_secflavors[i] == AUTH_SYS && 3284 (nd->nd_flag & ND_GSS) == 0) 3285 return (0); 3286 } 3287 return (1); 3288 } 3289 3290 /* 3291 * Calculate a hash value for the fid in a file handle. 3292 */ 3293 uint32_t 3294 nfsrv_hashfh(fhandle_t *fhp) 3295 { 3296 uint32_t hashval; 3297 3298 hashval = hash32_buf(&fhp->fh_fid, sizeof(struct fid), 0); 3299 return (hashval); 3300 } 3301 3302 /* 3303 * Calculate a hash value for the sessionid. 3304 */ 3305 uint32_t 3306 nfsrv_hashsessionid(uint8_t *sessionid) 3307 { 3308 uint32_t hashval; 3309 3310 hashval = hash32_buf(sessionid, NFSX_V4SESSIONID, 0); 3311 return (hashval); 3312 } 3313 3314 /* 3315 * Signal the userland master nfsd to backup the stable restart file. 3316 */ 3317 void 3318 nfsrv_backupstable(void) 3319 { 3320 struct proc *procp; 3321 3322 if (nfsd_master_proc != NULL) { 3323 procp = pfind(nfsd_master_pid); 3324 /* Try to make sure it is the correct process. */ 3325 if (procp == nfsd_master_proc && 3326 procp->p_stats->p_start.tv_sec == 3327 nfsd_master_start.tv_sec && 3328 procp->p_stats->p_start.tv_usec == 3329 nfsd_master_start.tv_usec && 3330 strcmp(procp->p_comm, nfsd_master_comm) == 0) 3331 kern_psignal(procp, SIGUSR2); 3332 else 3333 nfsd_master_proc = NULL; 3334 3335 if (procp != NULL) 3336 PROC_UNLOCK(procp); 3337 } 3338 } 3339 3340 extern int (*nfsd_call_nfsd)(struct thread *, struct nfssvc_args *); 3341 3342 /* 3343 * Called once to initialize data structures... 3344 */ 3345 static int 3346 nfsd_modevent(module_t mod, int type, void *data) 3347 { 3348 int error = 0, i; 3349 static int loaded = 0; 3350 3351 switch (type) { 3352 case MOD_LOAD: 3353 if (loaded) 3354 goto out; 3355 newnfs_portinit(); 3356 for (i = 0; i < NFSRVCACHE_HASHSIZE; i++) { 3357 mtx_init(&nfsrchash_table[i].mtx, "nfsrtc", NULL, 3358 MTX_DEF); 3359 mtx_init(&nfsrcahash_table[i].mtx, "nfsrtca", NULL, 3360 MTX_DEF); 3361 } 3362 mtx_init(&nfsrc_udpmtx, "nfsuc", NULL, MTX_DEF); 3363 mtx_init(&nfs_v4root_mutex, "nfs4rt", NULL, MTX_DEF); 3364 mtx_init(&nfsv4root_mnt.mnt_mtx, "nfs4mnt", NULL, MTX_DEF); 3365 lockinit(&nfsv4root_mnt.mnt_explock, PVFS, "explock", 0, 0); 3366 nfsrvd_initcache(); 3367 nfsd_init(); 3368 NFSD_LOCK(); 3369 nfsrvd_init(0); 3370 NFSD_UNLOCK(); 3371 nfsd_mntinit(); 3372 #ifdef VV_DISABLEDELEG 3373 vn_deleg_ops.vndeleg_recall = nfsd_recalldelegation; 3374 vn_deleg_ops.vndeleg_disable = nfsd_disabledelegation; 3375 #endif 3376 nfsd_call_servertimer = nfsrv_servertimer; 3377 nfsd_call_nfsd = nfssvc_nfsd; 3378 loaded = 1; 3379 break; 3380 3381 case MOD_UNLOAD: 3382 if (newnfs_numnfsd != 0) { 3383 error = EBUSY; 3384 break; 3385 } 3386 3387 #ifdef VV_DISABLEDELEG 3388 vn_deleg_ops.vndeleg_recall = NULL; 3389 vn_deleg_ops.vndeleg_disable = NULL; 3390 #endif 3391 nfsd_call_servertimer = NULL; 3392 nfsd_call_nfsd = NULL; 3393 3394 /* Clean out all NFSv4 state. */ 3395 nfsrv_throwawayallstate(curthread); 3396 3397 /* Clean the NFS server reply cache */ 3398 nfsrvd_cleancache(); 3399 3400 /* Free up the krpc server pool. */ 3401 if (nfsrvd_pool != NULL) 3402 svcpool_destroy(nfsrvd_pool); 3403 3404 /* and get rid of the locks */ 3405 for (i = 0; i < NFSRVCACHE_HASHSIZE; i++) { 3406 mtx_destroy(&nfsrchash_table[i].mtx); 3407 mtx_destroy(&nfsrcahash_table[i].mtx); 3408 } 3409 mtx_destroy(&nfsrc_udpmtx); 3410 mtx_destroy(&nfs_v4root_mutex); 3411 mtx_destroy(&nfsv4root_mnt.mnt_mtx); 3412 for (i = 0; i < nfsrv_sessionhashsize; i++) 3413 mtx_destroy(&nfssessionhash[i].mtx); 3414 lockdestroy(&nfsv4root_mnt.mnt_explock); 3415 free(nfsclienthash, M_NFSDCLIENT); 3416 free(nfslockhash, M_NFSDLOCKFILE); 3417 free(nfssessionhash, M_NFSDSESSION); 3418 loaded = 0; 3419 break; 3420 default: 3421 error = EOPNOTSUPP; 3422 break; 3423 } 3424 3425 out: 3426 NFSEXITCODE(error); 3427 return (error); 3428 } 3429 static moduledata_t nfsd_mod = { 3430 "nfsd", 3431 nfsd_modevent, 3432 NULL, 3433 }; 3434 DECLARE_MODULE(nfsd, nfsd_mod, SI_SUB_VFS, SI_ORDER_ANY); 3435 3436 /* So that loader and kldload(2) can find us, wherever we are.. */ 3437 MODULE_VERSION(nfsd, 1); 3438 MODULE_DEPEND(nfsd, nfscommon, 1, 1, 1); 3439 MODULE_DEPEND(nfsd, nfslock, 1, 1, 1); 3440 MODULE_DEPEND(nfsd, nfslockd, 1, 1, 1); 3441 MODULE_DEPEND(nfsd, krpc, 1, 1, 1); 3442 MODULE_DEPEND(nfsd, nfssvc, 1, 1, 1); 3443 3444