Print this page
NEX-3524 CLONE - Port NEX-3505 "wrong authentication" messages with root=@0.0.0.0/0 set, result in loss of client access
Reviewed by: Marcel Telka <marcel.telka@nexenta.com>
NEX-3533 CLONE - Port NEX-3019 NFSv3 writes underneath mounted filesystem to directory
Reviewed by: Dan Fields <dan.fields@nexenta.com>
re #13613 rb4516 Tunables needs volatile keyword

*** 16,32 **** * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* ! * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2016, 2017 by Delphix. All rights reserved. */ #include <sys/param.h> #include <sys/types.h> --- 16,33 ---- * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ + /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* ! * Copyright 2015 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2016, 2017 by Delphix. All rights reserved. */ #include <sys/param.h> #include <sys/types.h>
*** 129,139 **** static rhashq_t *rtable; static kmutex_t rpfreelist_lock; static rnode_t *rpfreelist = NULL; static long rnew = 0; ! long nrnode = 0; static int rtablesize; static int rtablemask; static int hashlen = 4; --- 130,140 ---- static rhashq_t *rtable; static kmutex_t rpfreelist_lock; static rnode_t *rpfreelist = NULL; static long rnew = 0; ! volatile long nrnode = 0; static int rtablesize; static int rtablemask; static int hashlen = 4;
*** 147,164 **** */ kmutex_t nfs_minor_lock; int nfs_major; int nfs_minor; ! /* Do we allow preepoch (negative) time values otw? */ ! bool_t nfs_allow_preepoch_time = FALSE; /* default: do not allow preepoch */ /* * Access cache */ static acache_hash_t *acache; ! static long nacache; /* used strictly to size the number of hash queues */ static int acachesize; static int acachemask; static struct kmem_cache *acache_cache; --- 148,168 ---- */ kmutex_t nfs_minor_lock; int nfs_major; int nfs_minor; ! /* ! * Do we allow preepoch (negative) time values otw? ! * default: do not allow preepoch ! */ ! volatile bool_t nfs_allow_preepoch_time = FALSE; /* * Access cache */ static acache_hash_t *acache; ! volatile long nacache; /* used strictly to size the number of hash queues */ static int acachesize; static int acachemask; static struct kmem_cache *acache_cache;
*** 226,236 **** * Some servers do not properly update the attributes of the * directory when changes are made. To allow interoperability * with these broken servers, the nfs_disable_rddir_cache * parameter must be set in /etc/system */ ! int nfs_disable_rddir_cache = 0; int clget(clinfo_t *, servinfo_t *, cred_t *, CLIENT **, struct chtab **); void clfree(CLIENT *, struct chtab *); static int acl_clget(mntinfo_t *, servinfo_t *, cred_t *, CLIENT **, --- 230,240 ---- * Some servers do not properly update the attributes of the * directory when changes are made. To allow interoperability * with these broken servers, the nfs_disable_rddir_cache * parameter must be set in /etc/system */ ! volatile int nfs_disable_rddir_cache = 0; int clget(clinfo_t *, servinfo_t *, cred_t *, CLIENT **, struct chtab **); void clfree(CLIENT *, struct chtab *); static int acl_clget(mntinfo_t *, servinfo_t *, cred_t *, CLIENT **,
*** 862,872 **** return (rpcerror); } #define NFS3_JUKEBOX_DELAY 10 * hz ! static clock_t nfs3_jukebox_delay = 0; #ifdef DEBUG static int rfs3call_hits = 0; static int rfs3call_misses = 0; #endif --- 866,876 ---- return (rpcerror); } #define NFS3_JUKEBOX_DELAY 10 * hz ! volatile clock_t nfs3_jukebox_delay = 0; #ifdef DEBUG static int rfs3call_hits = 0; static int rfs3call_misses = 0; #endif
*** 5217,5222 **** --- 5221,5309 ---- *valp = 1; break; } kmem_free(dbuf, dlen); return (0); + } + + /* + * Return non-zero in a case the vp is an empty directory used as a ZFS mount + * point. The NFSv2 and NFSv3 servers should not allow to write to such + * directories. + */ + int + protect_zfs_mntpt(vnode_t *vp) + { + int error; + vfs_t *vfsp; + struct uio uio; + struct iovec iov; + int eof; + size_t len = 8 * 1024; + char *buf; + + if (vp->v_type != VDIR || vn_ismntpt(vp) == 0) + return (0); + + error = vn_vfsrlock_wait(vp); + if (error != 0) + return (error); + + /* + * We protect ZFS mount points only + */ + if ((vfsp = vn_mountedvfs(vp)) == NULL || + strncmp(vfssw[vfsp->vfs_fstype].vsw_name, "zfs", 3) != 0) { + vn_vfsunlock(vp); + return (0); + } + + vn_vfsunlock(vp); + + buf = kmem_alloc(len, KM_SLEEP); + + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_fmode = 0; + uio.uio_extflg = UIO_COPY_CACHED; + uio.uio_loffset = 0; + uio.uio_llimit = MAXOFFSET_T; + + eof = 0; + + do { + size_t rlen; + dirent64_t *dp; + + uio.uio_resid = len; + iov.iov_base = buf; + iov.iov_len = len; + + (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL); + error = VOP_READDIR(vp, &uio, kcred, &eof, NULL, 0); + VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); + + if (error != 0) + break; + + error = EBUSY; + + rlen = len - uio.uio_resid; + if (rlen == 0) + break; + + for (dp = (dirent64_t *)buf; + (intptr_t)dp < (intptr_t)buf + rlen; + dp = (dirent64_t *)((intptr_t)dp + dp->d_reclen)) { + if (strcmp(dp->d_name, ".") != 0 && + strcmp(dp->d_name, "..") != 0) { + error = 0; + break; + } + } + } while (eof == 0 && error != 0); + + kmem_free(buf, len); + + return (error); }