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);
}