All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/11] Add the "[exports] rootdir" option to nfs.conf
@ 2019-05-28 20:31 Trond Myklebust
  2019-05-28 20:31 ` [PATCH v3 01/11] mountd: Ensure we don't share cache file descriptors among processes Trond Myklebust
  2019-06-10 13:53 ` [PATCH v3 00/11] Add the "[exports] rootdir" option to nfs.conf Steve Dickson
  0 siblings, 2 replies; 24+ messages in thread
From: Trond Myklebust @ 2019-05-28 20:31 UTC (permalink / raw)
  To: SteveD; +Cc: linux-nfs

The following patchset adds support for the "rootdir" configuration
option for nfsd in the "[exports]" section in /etc/nfs.conf.

If a user sets this option to a valid directory path, then nfsd will
act as if it is confined to a chroot jail based on that directory.
All paths in /etc/exports and the exportfs utility are then resolved
relative to that directory.

Trond Myklebust (11):
  mountd: Ensure we don't share cache file descriptors among processes.
  Add a simple workqueue mechanism
  Allow callers to check mountpoint status using a custom lstat function
  Add utilities for resolving nfsd paths and stat()ing them
  Use xstat() with no synchronisation if available
  Add helpers to read/write to a file through the chrooted thread
  Add a helper to return the real path given an export entry
  Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd
  Add support for the "[exports] rootdir" nfs.conf option to exportfs
  Add a helper for resolving symlinked nfsd paths via realpath()
  Fix up symlinked mount path resolution when "[exports] rootdir" is set

 aclocal/libpthread.m4       |  13 +-
 configure.ac                |   6 +-
 nfs.conf                    |   3 +
 support/export/export.c     |  24 +++
 support/include/Makefile.am |   3 +
 support/include/exportfs.h  |   1 +
 support/include/misc.h      |   7 +-
 support/include/nfsd_path.h |  21 +++
 support/include/nfslib.h    |   1 +
 support/include/workqueue.h |  18 +++
 support/include/xstat.h     |  11 ++
 support/misc/Makefile.am    |   3 +-
 support/misc/mountpoint.c   |   8 +-
 support/misc/nfsd_path.c    | 289 ++++++++++++++++++++++++++++++++++++
 support/misc/workqueue.c    | 228 ++++++++++++++++++++++++++++
 support/misc/xstat.c        | 105 +++++++++++++
 support/nfs/exports.c       |   4 +
 systemd/nfs.conf.man        |  20 ++-
 utils/exportfs/Makefile.am  |   2 +-
 utils/exportfs/exportfs.c   |  11 +-
 utils/mountd/Makefile.am    |   3 +-
 utils/mountd/cache.c        |  63 +++++---
 utils/mountd/mountd.c       |  24 +--
 23 files changed, 819 insertions(+), 49 deletions(-)
 create mode 100644 support/include/nfsd_path.h
 create mode 100644 support/include/workqueue.h
 create mode 100644 support/include/xstat.h
 create mode 100644 support/misc/nfsd_path.c
 create mode 100644 support/misc/workqueue.c
 create mode 100644 support/misc/xstat.c

-- 
2.21.0


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 01/11] mountd: Ensure we don't share cache file descriptors among processes.
  2019-05-28 20:31 [PATCH v3 00/11] Add the "[exports] rootdir" option to nfs.conf Trond Myklebust
@ 2019-05-28 20:31 ` Trond Myklebust
  2019-05-28 20:31   ` [PATCH v3 02/11] Add a simple workqueue mechanism Trond Myklebust
  2019-06-10 13:53 ` [PATCH v3 00/11] Add the "[exports] rootdir" option to nfs.conf Steve Dickson
  1 sibling, 1 reply; 24+ messages in thread
From: Trond Myklebust @ 2019-05-28 20:31 UTC (permalink / raw)
  To: SteveD; +Cc: linux-nfs

Sharing cache descriptors without using locking can be very bad.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
---
 utils/mountd/mountd.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c
index fb7bba4cd390..88a207b3a85a 100644
--- a/utils/mountd/mountd.c
+++ b/utils/mountd/mountd.c
@@ -836,8 +836,6 @@ main(int argc, char **argv)
 	if (!foreground)
 		closeall(3);
 
-	cache_open();
-
 	unregister_services();
 	if (version2()) {
 		listeners += nfs_svc_create("mountd", MOUNTPROG,
@@ -888,6 +886,9 @@ main(int argc, char **argv)
 	if (num_threads > 1)
 		fork_workers();
 
+	/* Open files now to avoid sharing descriptors among forked processes */
+	cache_open();
+
 	xlog(L_NOTICE, "Version " VERSION " starting");
 	my_svc_run();
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v3 02/11] Add a simple workqueue mechanism
  2019-05-28 20:31 ` [PATCH v3 01/11] mountd: Ensure we don't share cache file descriptors among processes Trond Myklebust
@ 2019-05-28 20:31   ` Trond Myklebust
  2019-05-28 20:31     ` [PATCH v3 03/11] Allow callers to check mountpoint status using a custom lstat function Trond Myklebust
  0 siblings, 1 reply; 24+ messages in thread
From: Trond Myklebust @ 2019-05-28 20:31 UTC (permalink / raw)
  To: SteveD; +Cc: linux-nfs

Add a simple workqueue mechanism to allow us to run threads that are
subject to chroot(), and have them operate on the knfsd kernel daemon.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
---
 aclocal/libpthread.m4       |  13 +-
 configure.ac                |   6 +-
 support/include/Makefile.am |   1 +
 support/include/workqueue.h |  18 +++
 support/misc/Makefile.am    |   2 +-
 support/misc/workqueue.c    | 228 ++++++++++++++++++++++++++++++++++++
 utils/mountd/Makefile.am    |   3 +-
 7 files changed, 262 insertions(+), 9 deletions(-)
 create mode 100644 support/include/workqueue.h
 create mode 100644 support/misc/workqueue.c

diff --git a/aclocal/libpthread.m4 b/aclocal/libpthread.m4
index e87d2a0c2dc5..55e046e38cd1 100644
--- a/aclocal/libpthread.m4
+++ b/aclocal/libpthread.m4
@@ -3,11 +3,12 @@ dnl
 AC_DEFUN([AC_LIBPTHREAD], [
 
     dnl Check for library, but do not add -lpthreads to LIBS
-    AC_CHECK_LIB([pthread], [pthread_create], [LIBPTHREAD=-lpthread],
-                 [AC_MSG_ERROR([libpthread not found.])])
-  AC_SUBST(LIBPTHREAD)
-
-  AC_CHECK_HEADERS([pthread.h], ,
-                   [AC_MSG_ERROR([libpthread headers not found.])])
+    AC_CHECK_LIB([pthread], [pthread_create],
+		[AC_DEFINE([HAVE_LIBPTHREAD], [1],
+				[Define to 1 if you have libpthread.])
+		AC_CHECK_HEADERS([pthread.h], [],
+				[AC_MSG_ERROR([libpthread headers not found.])])
+		 AC_SUBST([LIBPTHREAD],[-lpthread])],
+                 [$1])
 
 ])dnl
diff --git a/configure.ac b/configure.ac
index 4d7096193d0b..c6c2d73b06dd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -320,6 +320,10 @@ AC_CHECK_FUNC([getservbyname], ,
 
 AC_CHECK_LIB([crypt], [crypt], [LIBCRYPT="-lcrypt"])
 
+AC_CHECK_HEADERS([sched.h], [], [])
+AC_CHECK_FUNCS([unshare], [] , [])
+AC_LIBPTHREAD([])
+
 if test "$enable_nfsv4" = yes; then
   dnl check for libevent libraries and headers
   AC_LIBEVENT
@@ -417,7 +421,7 @@ if test "$enable_gss" = yes; then
   AC_KERBEROS_V5
 
   dnl Check for pthreads
-  AC_LIBPTHREAD
+  AC_LIBPTHREAD([AC_MSG_ERROR([libpthread not found.])])
 
   dnl librpcsecgss already has a dependency on libgssapi,
   dnl but we need to make sure we get the right version
diff --git a/support/include/Makefile.am b/support/include/Makefile.am
index 599f500e2b40..df5e47836d29 100644
--- a/support/include/Makefile.am
+++ b/support/include/Makefile.am
@@ -19,6 +19,7 @@ noinst_HEADERS = \
 	sockaddr.h \
 	tcpwrapper.h \
 	v4root.h \
+	workqueue.h \
 	xio.h \
 	xlog.h \
 	xmalloc.h \
diff --git a/support/include/workqueue.h b/support/include/workqueue.h
new file mode 100644
index 000000000000..518be82f1b34
--- /dev/null
+++ b/support/include/workqueue.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2019 Trond Myklebust <trond.myklebust@hammerspace.com>
+ */
+#ifndef WORKQUEUE_H
+#define WORKQUEUE_H
+
+struct xthread_workqueue;
+
+struct xthread_workqueue *xthread_workqueue_alloc(void);
+void xthread_workqueue_shutdown(struct xthread_workqueue *wq);
+
+void xthread_work_run_sync(struct xthread_workqueue *wq,
+		void (*fn)(void *), void *data);
+
+void xthread_workqueue_chroot(struct xthread_workqueue *wq,
+		const char *path);
+
+#endif
diff --git a/support/misc/Makefile.am b/support/misc/Makefile.am
index 8936b0d64e45..d0bff8feb6ae 100644
--- a/support/misc/Makefile.am
+++ b/support/misc/Makefile.am
@@ -1,6 +1,6 @@
 ## Process this file with automake to produce Makefile.in
 
 noinst_LIBRARIES = libmisc.a
-libmisc_a_SOURCES = tcpwrapper.c from_local.c mountpoint.c file.c
+libmisc_a_SOURCES = tcpwrapper.c from_local.c mountpoint.c file.c workqueue.c
 
 MAINTAINERCLEANFILES = Makefile.in
diff --git a/support/misc/workqueue.c b/support/misc/workqueue.c
new file mode 100644
index 000000000000..b8d03446f2c7
--- /dev/null
+++ b/support/misc/workqueue.c
@@ -0,0 +1,228 @@
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "workqueue.h"
+#include "xlog.h"
+
+#if defined(HAVE_SCHED_H) && defined(HAVE_LIBPTHREAD) && defined(HAVE_UNSHARE)
+#include <sched.h>
+#include <pthread.h>
+
+struct xwork_struct {
+	struct xwork_struct *next;
+	void (*fn)(void *);
+	void *data;
+};
+
+struct xwork_queue {
+	struct xwork_struct *head;
+	struct xwork_struct **tail;
+
+	unsigned char shutdown : 1;
+};
+
+static void xwork_queue_init(struct xwork_queue *queue)
+{
+	queue->head = NULL;
+	queue->tail = &queue->head;
+	queue->shutdown = 0;
+}
+
+static void xwork_enqueue(struct xwork_queue *queue,
+		struct xwork_struct *entry)
+{
+	entry->next = NULL;
+	*queue->tail = entry;
+	queue->tail = &entry->next;
+}
+
+static struct xwork_struct *xwork_dequeue(struct xwork_queue *queue)
+{
+	struct xwork_struct *entry = NULL;
+	if (queue->head) {
+		entry = queue->head;
+		queue->head = entry->next;
+		if (!queue->head)
+			queue->tail = &queue->head;
+	}
+	return entry;
+}
+
+struct xthread_work {
+	struct xwork_struct work;
+
+	pthread_cond_t cond;
+};
+
+struct xthread_workqueue {
+	struct xwork_queue queue;
+
+	pthread_mutex_t mutex;
+	pthread_cond_t cond;
+};
+
+static void xthread_workqueue_init(struct xthread_workqueue *wq)
+{
+	xwork_queue_init(&wq->queue);
+	pthread_mutex_init(&wq->mutex, NULL);
+	pthread_cond_init(&wq->cond, NULL);
+}
+
+static void xthread_workqueue_fini(struct xthread_workqueue *wq)
+{
+	pthread_cond_destroy(&wq->cond);
+	pthread_mutex_destroy(&wq->mutex);
+}
+
+static int xthread_work_enqueue(struct xthread_workqueue *wq,
+		struct xthread_work *work)
+{
+	xwork_enqueue(&wq->queue, &work->work);
+	pthread_cond_signal(&wq->cond);
+	return 0;
+}
+
+static struct xthread_work *xthread_work_dequeue(struct xthread_workqueue *wq)
+{
+	return (struct xthread_work *)xwork_dequeue(&wq->queue);
+}
+
+static void xthread_workqueue_do_work(struct xthread_workqueue *wq)
+{
+	struct xthread_work *work;
+
+	pthread_mutex_lock(&wq->mutex);
+	/* Signal the caller that we're up and running */
+	pthread_cond_signal(&wq->cond);
+	for (;;) {
+		work = xthread_work_dequeue(wq);
+		if (work) {
+			work->work.fn(work->work.data);
+			pthread_cond_signal(&work->cond);
+			continue;
+		}
+		if (wq->queue.shutdown)
+			break;
+		pthread_cond_wait(&wq->cond, &wq->mutex);
+	}
+	pthread_mutex_unlock(&wq->mutex);
+}
+
+void xthread_workqueue_shutdown(struct xthread_workqueue *wq)
+{
+	pthread_mutex_lock(&wq->mutex);
+	wq->queue.shutdown = 1;
+	pthread_cond_signal(&wq->cond);
+	pthread_mutex_unlock(&wq->mutex);
+}
+
+static void xthread_workqueue_free(struct xthread_workqueue *wq)
+{
+	xthread_workqueue_fini(wq);
+	free(wq);
+}
+
+static void xthread_workqueue_cleanup(void *data)
+{
+	xthread_workqueue_free(data);
+}
+
+static void *xthread_workqueue_worker(void *data)
+{
+	pthread_cleanup_push(xthread_workqueue_cleanup, data);
+	xthread_workqueue_do_work(data);
+	pthread_cleanup_pop(1);
+	return NULL;
+}
+
+struct xthread_workqueue *xthread_workqueue_alloc(void)
+{
+	struct xthread_workqueue *ret;
+	pthread_t thread;
+
+	ret = malloc(sizeof(*ret));
+	if (ret) {
+		xthread_workqueue_init(ret);
+
+		pthread_mutex_lock(&ret->mutex);
+		if (pthread_create(&thread, NULL,
+					xthread_workqueue_worker,
+					ret) == 0) {
+			/* Wait for thread to start */
+			pthread_cond_wait(&ret->cond, &ret->mutex);
+			pthread_mutex_unlock(&ret->mutex);
+			return ret;
+		}
+		pthread_mutex_unlock(&ret->mutex);
+		xthread_workqueue_free(ret);
+		ret = NULL;
+	}
+	return NULL;
+}
+
+void xthread_work_run_sync(struct xthread_workqueue *wq,
+		void (*fn)(void *), void *data)
+{
+	struct xthread_work work = {
+		{
+			NULL,
+			fn,
+			data
+		},
+		PTHREAD_COND_INITIALIZER,
+	};
+	pthread_mutex_lock(&wq->mutex);
+	xthread_work_enqueue(wq, &work);
+	pthread_cond_wait(&work.cond, &wq->mutex);
+	pthread_mutex_unlock(&wq->mutex);
+	pthread_cond_destroy(&work.cond);
+}
+
+static void xthread_workqueue_do_chroot(void *data)
+{
+	const char *path = data;
+
+	if (unshare(CLONE_FS) != 0) {
+		xlog_err("unshare() failed: %m");
+		return;
+	}
+	if (chroot(path) != 0)
+		xlog_err("chroot() failed: %m");
+}
+
+void xthread_workqueue_chroot(struct xthread_workqueue *wq,
+		const char *path)
+{
+	xthread_work_run_sync(wq, xthread_workqueue_do_chroot, (void *)path);
+}
+
+#else
+
+struct xthread_workqueue {
+};
+
+static struct xthread_workqueue ret;
+
+struct xthread_workqueue *xthread_workqueue_alloc(void)
+{
+	return &ret;
+}
+
+void xthread_workqueue_shutdown(struct xthread_workqueue *wq)
+{
+}
+
+void xthread_work_run_sync(struct xthread_workqueue *wq,
+		void (*fn)(void *), void *data)
+{
+	fn(data);
+}
+
+void xthread_workqueue_chroot(struct xthread_workqueue *wq,
+		const char *path)
+{
+	xlog_err("Unable to run as chroot");
+}
+
+#endif /* defined(HAVE_SCHED_H) && defined(HAVE_LIBPTHREAD) && defined(HAVE_UNSHARE) */
diff --git a/utils/mountd/Makefile.am b/utils/mountd/Makefile.am
index 73eeb3f35070..18610f18238c 100644
--- a/utils/mountd/Makefile.am
+++ b/utils/mountd/Makefile.am
@@ -19,7 +19,8 @@ mountd_LDADD = ../../support/export/libexport.a \
 	       ../../support/nfs/libnfs.la \
 	       ../../support/misc/libmisc.a \
 	       $(OPTLIBS) \
-	       $(LIBBSD) $(LIBWRAP) $(LIBNSL) $(LIBBLKID) $(LIBTIRPC)
+	       $(LIBBSD) $(LIBWRAP) $(LIBNSL) $(LIBBLKID) $(LIBTIRPC) \
+	       $(LIBPTHREAD)
 mountd_CPPFLAGS = $(AM_CPPFLAGS) $(CPPFLAGS) \
 		  -I$(top_builddir)/support/include \
 		  -I$(top_srcdir)/support/export
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v3 03/11] Allow callers to check mountpoint status using a custom lstat function
  2019-05-28 20:31   ` [PATCH v3 02/11] Add a simple workqueue mechanism Trond Myklebust
@ 2019-05-28 20:31     ` Trond Myklebust
  2019-05-28 20:31       ` [PATCH v3 04/11] Add utilities for resolving nfsd paths and stat()ing them Trond Myklebust
  0 siblings, 1 reply; 24+ messages in thread
From: Trond Myklebust @ 2019-05-28 20:31 UTC (permalink / raw)
  To: SteveD; +Cc: linux-nfs

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
---
 support/include/misc.h    | 7 ++++++-
 support/misc/mountpoint.c | 8 +++++---
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/support/include/misc.h b/support/include/misc.h
index 06e2a0c7b061..2b0fef26cb11 100644
--- a/support/include/misc.h
+++ b/support/include/misc.h
@@ -18,7 +18,12 @@ int	weakrandomkey(unsigned char *keyout, int len);
 char *generic_make_pathname(const char *, const char *);
 _Bool generic_setup_basedir(const char *, const char *, char *, const size_t);
 
-extern int is_mountpoint(char *path);
+struct stat;
+
+extern int check_is_mountpoint(const char *path,
+		int (mystat)(const char *, struct stat *));
+#define is_mountpoint(path) \
+	check_is_mountpoint(path, NULL)
 
 /* size of the file pointer buffers for rpc procfs files */
 #define RPC_CHAN_BUF_SIZE 32768
diff --git a/support/misc/mountpoint.c b/support/misc/mountpoint.c
index 9f9ce44ec1e3..c6217f2458d1 100644
--- a/support/misc/mountpoint.c
+++ b/support/misc/mountpoint.c
@@ -9,8 +9,10 @@
 #include "misc.h"
 
 int
-is_mountpoint(char *path)
+check_is_mountpoint(const char *path, int (mystat)(const char *, struct stat *))
 {
+	if (!mystat)
+		mystat = lstat;
 	/* Check if 'path' is a current mountpoint.
 	 * Possibly we should also check it is the mountpoint of the 
 	 * filesystem holding the target directory, but there doesn't
@@ -26,8 +28,8 @@ is_mountpoint(char *path)
 	dotdot = xmalloc(strlen(path)+4);
 
 	strcat(strcpy(dotdot, path), "/..");
-	if (lstat(path, &stb) != 0 ||
-	    lstat(dotdot, &pstb) != 0)
+	if (mystat(path, &stb) != 0 ||
+	    mystat(dotdot, &pstb) != 0)
 		rv = 0;
 	else
 		if (stb.st_dev != pstb.st_dev ||
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v3 04/11] Add utilities for resolving nfsd paths and stat()ing them
  2019-05-28 20:31     ` [PATCH v3 03/11] Allow callers to check mountpoint status using a custom lstat function Trond Myklebust
@ 2019-05-28 20:31       ` Trond Myklebust
  2019-05-28 20:31         ` [PATCH v3 05/11] Use xstat() with no synchronisation if available Trond Myklebust
  2019-05-31 15:52         ` [PATCH v3 04/11] Add utilities for resolving nfsd paths and stat()ing them J. Bruce Fields
  0 siblings, 2 replies; 24+ messages in thread
From: Trond Myklebust @ 2019-05-28 20:31 UTC (permalink / raw)
  To: SteveD; +Cc: linux-nfs

Add helper functions that can resolve nfsd paths by prepending the
necessary prefix if the admin has specified a root path in the
nfs.conf file.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
---
 configure.ac                |   2 +-
 support/include/Makefile.am |   2 +
 support/include/nfsd_path.h |  16 ++++
 support/include/xstat.h     |  11 +++
 support/misc/Makefile.am    |   3 +-
 support/misc/nfsd_path.c    | 168 ++++++++++++++++++++++++++++++++++++
 support/misc/xstat.c        |  33 +++++++
 7 files changed, 233 insertions(+), 2 deletions(-)
 create mode 100644 support/include/nfsd_path.h
 create mode 100644 support/include/xstat.h
 create mode 100644 support/misc/nfsd_path.c
 create mode 100644 support/misc/xstat.c

diff --git a/configure.ac b/configure.ac
index c6c2d73b06dd..e870862a8abb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -321,7 +321,7 @@ AC_CHECK_FUNC([getservbyname], ,
 AC_CHECK_LIB([crypt], [crypt], [LIBCRYPT="-lcrypt"])
 
 AC_CHECK_HEADERS([sched.h], [], [])
-AC_CHECK_FUNCS([unshare], [] , [])
+AC_CHECK_FUNCS([unshare fstatat], [] , [])
 AC_LIBPTHREAD([])
 
 if test "$enable_nfsv4" = yes; then
diff --git a/support/include/Makefile.am b/support/include/Makefile.am
index df5e47836d29..1373891a7c76 100644
--- a/support/include/Makefile.am
+++ b/support/include/Makefile.am
@@ -10,6 +10,7 @@ noinst_HEADERS = \
 	misc.h \
 	nfs_mntent.h \
 	nfs_paths.h \
+	nfsd_path.h \
 	nfslib.h \
 	nfsrpc.h \
 	nls.h \
@@ -24,6 +25,7 @@ noinst_HEADERS = \
 	xlog.h \
 	xmalloc.h \
 	xcommon.h \
+	xstat.h \
 	conffile.h
 
 MAINTAINERCLEANFILES = Makefile.in
diff --git a/support/include/nfsd_path.h b/support/include/nfsd_path.h
new file mode 100644
index 000000000000..db9b41a179ad
--- /dev/null
+++ b/support/include/nfsd_path.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2019 Trond Myklebust <trond.myklebust@hammerspace.com>
+ */
+#ifndef NFSD_PATH_H
+#define NFSD_PATH_H
+
+void 		nfsd_path_init(void);
+
+const char *	nfsd_path_nfsd_rootdir(void);
+char *		nfsd_path_strip_root(char *pathname);
+char *		nfsd_path_prepend_dir(const char *dir, const char *pathname);
+
+int 		nfsd_path_stat(const char *pathname, struct stat *statbuf);
+int 		nfsd_path_lstat(const char *pathname, struct stat *statbuf);
+
+#endif
diff --git a/support/include/xstat.h b/support/include/xstat.h
new file mode 100644
index 000000000000..f1241bbfdc0e
--- /dev/null
+++ b/support/include/xstat.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright (C) 2019 Trond Myklebust <trond.myklebust@hammerspace.com>
+ */
+#ifndef XSTAT_H
+#define XSTAT_H
+
+struct stat;
+
+int xlstat(const char *pathname, struct stat *statbuf);
+int xstat(const char *pathname, struct stat *statbuf);
+#endif
diff --git a/support/misc/Makefile.am b/support/misc/Makefile.am
index d0bff8feb6ae..f9993e3ac897 100644
--- a/support/misc/Makefile.am
+++ b/support/misc/Makefile.am
@@ -1,6 +1,7 @@
 ## Process this file with automake to produce Makefile.in
 
 noinst_LIBRARIES = libmisc.a
-libmisc_a_SOURCES = tcpwrapper.c from_local.c mountpoint.c file.c workqueue.c
+libmisc_a_SOURCES = tcpwrapper.c from_local.c mountpoint.c file.c \
+		    nfsd_path.c workqueue.c xstat.c
 
 MAINTAINERCLEANFILES = Makefile.in
diff --git a/support/misc/nfsd_path.c b/support/misc/nfsd_path.c
new file mode 100644
index 000000000000..fe2c011b1521
--- /dev/null
+++ b/support/misc/nfsd_path.c
@@ -0,0 +1,168 @@
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "conffile.h"
+#include "xmalloc.h"
+#include "xlog.h"
+#include "xstat.h"
+#include "nfsd_path.h"
+#include "workqueue.h"
+
+static struct xthread_workqueue *nfsd_wq;
+
+static int
+nfsd_path_isslash(const char *path)
+{
+	return path[0] == '/' && path[1] == '/';
+}
+
+static int
+nfsd_path_isdot(const char *path)
+{
+	return path[0] == '.' && path[1] == '/';
+}
+
+static const char *
+nfsd_path_strip(const char *path)
+{
+	if (!path || *path == '\0')
+		goto out;
+	for (;;) {
+		if (nfsd_path_isslash(path)) {
+			path++;
+			continue;
+		}
+		if (nfsd_path_isdot(path)) {
+			path += 2;
+			continue;
+		}
+		break;
+	}
+out:
+	return path;
+}
+
+const char *
+nfsd_path_nfsd_rootdir(void)
+{
+	const char *rootdir;
+
+	rootdir = nfsd_path_strip(conf_get_str("exports", "rootdir"));
+	if (!rootdir || rootdir[0] ==  '\0')
+		return NULL;
+	if (rootdir[0] == '/' && rootdir[1] == '\0')
+		return NULL;
+	return rootdir;
+}
+
+char *
+nfsd_path_strip_root(char *pathname)
+{
+	const char *dir = nfsd_path_nfsd_rootdir();
+	char *ret;
+
+	ret = strstr(pathname, dir);
+	if (!ret || ret != pathname)
+		return pathname;
+	return pathname + strlen(dir);
+}
+
+char *
+nfsd_path_prepend_dir(const char *dir, const char *pathname)
+{
+	size_t len, dirlen;
+	char *ret;
+
+	dirlen = strlen(dir);
+	while (dirlen > 0 && dir[dirlen - 1] == '/')
+		dirlen--;
+	if (!dirlen)
+		return NULL;
+	len = dirlen + strlen(pathname) + 1;
+	ret = xmalloc(len + 1);
+	snprintf(ret, len, "%.*s/%s", (int)dirlen, dir, pathname);
+	return ret;
+}
+
+static void
+nfsd_setup_workqueue(void)
+{
+	const char *rootdir = nfsd_path_nfsd_rootdir();
+
+	if (!rootdir)
+		return;
+	nfsd_wq = xthread_workqueue_alloc();
+	if (!nfsd_wq)
+		return;
+	xthread_workqueue_chroot(nfsd_wq, rootdir);
+}
+
+void
+nfsd_path_init(void)
+{
+	nfsd_setup_workqueue();
+}
+
+struct nfsd_stat_data {
+	const char *pathname;
+	struct stat *statbuf;
+	int ret;
+	int err;
+};
+
+static void
+nfsd_statfunc(void *data)
+{
+	struct nfsd_stat_data *d = data;
+
+	d->ret = xstat(d->pathname, d->statbuf);
+	if (d->ret < 0)
+		d->err = errno;
+}
+
+static void
+nfsd_lstatfunc(void *data)
+{
+	struct nfsd_stat_data *d = data;
+
+	d->ret = xlstat(d->pathname, d->statbuf);
+	if (d->ret < 0)
+		d->err = errno;
+}
+
+static int
+nfsd_run_stat(struct xthread_workqueue *wq,
+		void (*func)(void *),
+		const char *pathname,
+		struct stat *statbuf)
+{
+	struct nfsd_stat_data data = {
+		pathname,
+		statbuf,
+		0,
+		0
+	};
+	xthread_work_run_sync(wq, func, &data);
+	if (data.ret < 0)
+		errno = data.err;
+	return data.ret;
+}
+
+int
+nfsd_path_stat(const char *pathname, struct stat *statbuf)
+{
+	if (!nfsd_wq)
+		return xstat(pathname, statbuf);
+	return nfsd_run_stat(nfsd_wq, nfsd_statfunc, pathname, statbuf);
+}
+
+int
+nfsd_path_lstat(const char *pathname, struct stat *statbuf)
+{
+	if (!nfsd_wq)
+		return xlstat(pathname, statbuf);
+	return nfsd_run_stat(nfsd_wq, nfsd_lstatfunc, pathname, statbuf);
+}
diff --git a/support/misc/xstat.c b/support/misc/xstat.c
new file mode 100644
index 000000000000..d092f73dfd65
--- /dev/null
+++ b/support/misc/xstat.c
@@ -0,0 +1,33 @@
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "xstat.h"
+
+#ifdef HAVE_FSTATAT
+
+int xlstat(const char *pathname, struct stat *statbuf)
+{
+	return fstatat(AT_FDCWD, pathname, statbuf, AT_NO_AUTOMOUNT |
+			AT_SYMLINK_NOFOLLOW);
+}
+
+int xstat(const char *pathname, struct stat *statbuf)
+{
+	return fstatat(AT_FDCWD, pathname, statbuf, AT_NO_AUTOMOUNT);
+}
+
+#else
+
+int xlstat(const char *pathname, struct stat *statbuf)
+{
+	return lstat(pathname, statbuf);
+}
+
+int xstat(const char *pathname, struct stat *statbuf)
+{
+	return stat(pathname, statbuf);
+}
+#endif
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v3 05/11] Use xstat() with no synchronisation if available
  2019-05-28 20:31       ` [PATCH v3 04/11] Add utilities for resolving nfsd paths and stat()ing them Trond Myklebust
@ 2019-05-28 20:31         ` Trond Myklebust
  2019-05-28 20:31           ` [PATCH v3 06/11] Add helpers to read/write to a file through the chrooted thread Trond Myklebust
  2019-05-31 15:52         ` [PATCH v3 04/11] Add utilities for resolving nfsd paths and stat()ing them J. Bruce Fields
  1 sibling, 1 reply; 24+ messages in thread
From: Trond Myklebust @ 2019-05-28 20:31 UTC (permalink / raw)
  To: SteveD; +Cc: linux-nfs

We normally expect the exported system to be stable, so don't
revalidate attributes.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
---
 configure.ac         |  2 +-
 support/misc/xstat.c | 72 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index e870862a8abb..50002b4a5677 100644
--- a/configure.ac
+++ b/configure.ac
@@ -321,7 +321,7 @@ AC_CHECK_FUNC([getservbyname], ,
 AC_CHECK_LIB([crypt], [crypt], [LIBCRYPT="-lcrypt"])
 
 AC_CHECK_HEADERS([sched.h], [], [])
-AC_CHECK_FUNCS([unshare fstatat], [] , [])
+AC_CHECK_FUNCS([unshare fstatat statx], [] , [])
 AC_LIBPTHREAD([])
 
 if test "$enable_nfsv4" = yes; then
diff --git a/support/misc/xstat.c b/support/misc/xstat.c
index d092f73dfd65..fa047880cfd0 100644
--- a/support/misc/xstat.c
+++ b/support/misc/xstat.c
@@ -1,21 +1,93 @@
+#include <errno.h>
 #include <sys/types.h>
 #include <fcntl.h>
 #include <sys/stat.h>
+#include <sys/sysmacros.h>
 #include <unistd.h>
 
 #include "config.h"
 #include "xstat.h"
 
 #ifdef HAVE_FSTATAT
+#ifdef HAVE_STATX
+
+static void
+statx_copy(struct stat *stbuf, const struct statx *stxbuf)
+{
+	stbuf->st_dev = makedev(stxbuf->stx_dev_major, stxbuf->stx_dev_minor);
+	stbuf->st_ino = stxbuf->stx_ino;
+	stbuf->st_mode = stxbuf->stx_mode;
+	stbuf->st_nlink = stxbuf->stx_nlink;
+	stbuf->st_uid = stxbuf->stx_uid;
+	stbuf->st_gid = stxbuf->stx_gid;
+	stbuf->st_rdev = makedev(stxbuf->stx_rdev_major, stxbuf->stx_rdev_minor);
+	stbuf->st_size = stxbuf->stx_size;
+	stbuf->st_blksize = stxbuf->stx_blksize;
+	stbuf->st_blocks = stxbuf->stx_blocks;
+	stbuf->st_atim.tv_sec = stxbuf->stx_atime.tv_sec;
+	stbuf->st_atim.tv_nsec = stxbuf->stx_atime.tv_nsec;
+	stbuf->st_mtim.tv_sec = stxbuf->stx_mtime.tv_sec;
+	stbuf->st_mtim.tv_nsec = stxbuf->stx_mtime.tv_nsec;
+	stbuf->st_ctim.tv_sec = stxbuf->stx_ctime.tv_sec;
+	stbuf->st_ctim.tv_nsec = stxbuf->stx_ctime.tv_nsec;
+}
+
+static int
+statx_do_stat(int fd, const char *pathname, struct stat *statbuf, int flags)
+{
+	static int statx_supported = 1;
+	struct statx stxbuf;
+	int ret;
+
+	if (statx_supported) {
+		ret = statx(fd, pathname, flags,
+				STATX_BASIC_STATS,
+				&stxbuf);
+		if (ret == 0) {
+			statx_copy(statbuf, &stxbuf);
+			return 0;
+		}
+		if (errno == ENOSYS)
+			statx_supported = 0;
+	} else
+		errno = ENOSYS;
+	return -1;
+}
+
+static int
+statx_stat_nosync(int fd, const char *pathname, struct stat *statbuf, int flags)
+{
+	return statx_do_stat(fd, pathname, statbuf, flags | AT_STATX_DONT_SYNC);
+}
+
+#else
+
+static int
+statx_stat_nosync(int fd, const char *pathname, struct stat *statbuf, int flags)
+{
+	errno = ENOSYS;
+	return -1;
+}
+
+#endif /* HAVE_STATX */
 
 int xlstat(const char *pathname, struct stat *statbuf)
 {
+	if (statx_stat_nosync(AT_FDCWD, pathname, statbuf, AT_NO_AUTOMOUNT|
+				AT_SYMLINK_NOFOLLOW) == 0)
+		return 0;
+	else if (errno != ENOSYS)
+		return -1;
 	return fstatat(AT_FDCWD, pathname, statbuf, AT_NO_AUTOMOUNT |
 			AT_SYMLINK_NOFOLLOW);
 }
 
 int xstat(const char *pathname, struct stat *statbuf)
 {
+	if (statx_stat_nosync(AT_FDCWD, pathname, statbuf, AT_NO_AUTOMOUNT) == 0)
+		return 0;
+	else if (errno != ENOSYS)
+		return -1;
 	return fstatat(AT_FDCWD, pathname, statbuf, AT_NO_AUTOMOUNT);
 }
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v3 06/11] Add helpers to read/write to a file through the chrooted thread
  2019-05-28 20:31         ` [PATCH v3 05/11] Use xstat() with no synchronisation if available Trond Myklebust
@ 2019-05-28 20:31           ` Trond Myklebust
  2019-05-28 20:31             ` [PATCH v3 07/11] Add a helper to return the real path given an export entry Trond Myklebust
  0 siblings, 1 reply; 24+ messages in thread
From: Trond Myklebust @ 2019-05-28 20:31 UTC (permalink / raw)
  To: SteveD; +Cc: linux-nfs

Add helper functions to do synchronous I/O to a nfsd filesystem pseudofile
from inside the chrooted environment. This ensures that calls to kern_path()
in knfsd resolves to paths that are relative to the nfsd root directory.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
---
 support/include/nfsd_path.h |  3 ++
 support/misc/nfsd_path.c    | 84 +++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+)

diff --git a/support/include/nfsd_path.h b/support/include/nfsd_path.h
index db9b41a179ad..f4a7f0a4337f 100644
--- a/support/include/nfsd_path.h
+++ b/support/include/nfsd_path.h
@@ -13,4 +13,7 @@ char *		nfsd_path_prepend_dir(const char *dir, const char *pathname);
 int 		nfsd_path_stat(const char *pathname, struct stat *statbuf);
 int 		nfsd_path_lstat(const char *pathname, struct stat *statbuf);
 
+ssize_t		nfsd_path_read(int fd, char *buf, size_t len);
+ssize_t		nfsd_path_write(int fd, const char *buf, size_t len);
+
 #endif
diff --git a/support/misc/nfsd_path.c b/support/misc/nfsd_path.c
index fe2c011b1521..55bca9bdf4bd 100644
--- a/support/misc/nfsd_path.c
+++ b/support/misc/nfsd_path.c
@@ -166,3 +166,87 @@ nfsd_path_lstat(const char *pathname, struct stat *statbuf)
 		return xlstat(pathname, statbuf);
 	return nfsd_run_stat(nfsd_wq, nfsd_lstatfunc, pathname, statbuf);
 }
+
+struct nfsd_read_data {
+	int fd;
+	char *buf;
+	size_t len;
+	ssize_t ret;
+	int err;
+};
+
+static void
+nfsd_readfunc(void *data)
+{
+	struct nfsd_read_data *d = data;
+
+	d->ret = read(d->fd, d->buf, d->len);
+	if (d->ret < 0)
+		d->err = errno;
+}
+
+static ssize_t
+nfsd_run_read(struct xthread_workqueue *wq, int fd, char *buf, size_t len)
+{
+	struct nfsd_read_data data = {
+		fd,
+		buf,
+		len,
+		0,
+		0
+	};
+	xthread_work_run_sync(wq, nfsd_readfunc, &data);
+	if (data.ret < 0)
+		errno = data.err;
+	return data.ret;
+}
+
+ssize_t
+nfsd_path_read(int fd, char *buf, size_t len)
+{
+	if (!nfsd_wq)
+		return read(fd, buf, len);
+	return nfsd_run_read(nfsd_wq, fd, buf, len);
+}
+
+struct nfsd_write_data {
+	int fd;
+	const char *buf;
+	size_t len;
+	ssize_t ret;
+	int err;
+};
+
+static void
+nfsd_writefunc(void *data)
+{
+	struct nfsd_write_data *d = data;
+
+	d->ret = write(d->fd, d->buf, d->len);
+	if (d->ret < 0)
+		d->err = errno;
+}
+
+static ssize_t
+nfsd_run_write(struct xthread_workqueue *wq, int fd, const char *buf, size_t len)
+{
+	struct nfsd_write_data data = {
+		fd,
+		buf,
+		len,
+		0,
+		0
+	};
+	xthread_work_run_sync(wq, nfsd_writefunc, &data);
+	if (data.ret < 0)
+		errno = data.err;
+	return data.ret;
+}
+
+ssize_t
+nfsd_path_write(int fd, const char *buf, size_t len)
+{
+	if (!nfsd_wq)
+		return write(fd, buf, len);
+	return nfsd_run_write(nfsd_wq, fd, buf, len);
+}
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v3 07/11] Add a helper to return the real path given an export entry
  2019-05-28 20:31           ` [PATCH v3 06/11] Add helpers to read/write to a file through the chrooted thread Trond Myklebust
@ 2019-05-28 20:31             ` Trond Myklebust
  2019-05-28 20:31               ` [PATCH v3 08/11] Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd Trond Myklebust
  2019-05-29 14:38               ` [PATCH v3 07/11] Add a helper to return the real path given an export entry Steve Dickson
  0 siblings, 2 replies; 24+ messages in thread
From: Trond Myklebust @ 2019-05-28 20:31 UTC (permalink / raw)
  To: SteveD; +Cc: linux-nfs

Add a helper that can prepend the nfsd root directory path in order
to allow mountd to perform its comparisons with mtab etc.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
---
 support/export/export.c    | 24 ++++++++++++++++++++++++
 support/include/exportfs.h |  1 +
 support/include/nfslib.h   |  1 +
 support/misc/nfsd_path.c   |  4 +++-
 support/nfs/exports.c      |  4 ++++
 5 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/support/export/export.c b/support/export/export.c
index fbe68e84e5b3..82bbb54c5e9e 100644
--- a/support/export/export.c
+++ b/support/export/export.c
@@ -20,6 +20,7 @@
 #include "xmalloc.h"
 #include "nfslib.h"
 #include "exportfs.h"
+#include "nfsd_path.h"
 
 exp_hash_table exportlist[MCL_MAXTYPES] = {{NULL, {{NULL,NULL}, }}, }; 
 static int export_hash(char *);
@@ -30,6 +31,28 @@ static void	export_add(nfs_export *exp);
 static int	export_check(const nfs_export *exp, const struct addrinfo *ai,
 				const char *path);
 
+/* Return a real path for the export. */
+static void
+exportent_mkrealpath(struct exportent *eep)
+{
+	const char *chroot = nfsd_path_nfsd_rootdir();
+	char *ret = NULL;
+
+	if (chroot)
+		ret = nfsd_path_prepend_dir(chroot, eep->e_path);
+	if (!ret)
+		ret = xstrdup(eep->e_path);
+	eep->e_realpath = ret;
+}
+
+char *
+exportent_realpath(struct exportent *eep)
+{
+	if (!eep->e_realpath)
+		exportent_mkrealpath(eep);
+	return eep->e_realpath;
+}
+
 void
 exportent_release(struct exportent *eep)
 {
@@ -39,6 +62,7 @@ exportent_release(struct exportent *eep)
 	free(eep->e_fslocdata);
 	free(eep->e_uuid);
 	xfree(eep->e_hostname);
+	xfree(eep->e_realpath);
 }
 
 static void
diff --git a/support/include/exportfs.h b/support/include/exportfs.h
index 4e0d9d132b4c..daa7e2a06d82 100644
--- a/support/include/exportfs.h
+++ b/support/include/exportfs.h
@@ -171,5 +171,6 @@ struct export_features {
 
 struct export_features *get_export_features(void);
 void fix_pseudoflavor_flags(struct exportent *ep);
+char *exportent_realpath(struct exportent *eep);
 
 #endif /* EXPORTFS_H */
diff --git a/support/include/nfslib.h b/support/include/nfslib.h
index b09fce42e677..84d8270b330f 100644
--- a/support/include/nfslib.h
+++ b/support/include/nfslib.h
@@ -84,6 +84,7 @@ struct exportent {
 	char *		e_uuid;
 	struct sec_entry e_secinfo[SECFLAVOR_COUNT+1];
 	unsigned int	e_ttl;
+	char *		e_realpath;
 };
 
 struct rmtabent {
diff --git a/support/misc/nfsd_path.c b/support/misc/nfsd_path.c
index 55bca9bdf4bd..8ddafd65ab76 100644
--- a/support/misc/nfsd_path.c
+++ b/support/misc/nfsd_path.c
@@ -81,9 +81,11 @@ nfsd_path_prepend_dir(const char *dir, const char *pathname)
 		dirlen--;
 	if (!dirlen)
 		return NULL;
+	while (pathname[0] == '/')
+		pathname++;
 	len = dirlen + strlen(pathname) + 1;
 	ret = xmalloc(len + 1);
-	snprintf(ret, len, "%.*s/%s", (int)dirlen, dir, pathname);
+	snprintf(ret, len+1, "%.*s/%s", (int)dirlen, dir, pathname);
 	return ret;
 }
 
diff --git a/support/nfs/exports.c b/support/nfs/exports.c
index 5f4cb9568814..3ecfde797e3b 100644
--- a/support/nfs/exports.c
+++ b/support/nfs/exports.c
@@ -155,6 +155,7 @@ getexportent(int fromkernel, int fromexports)
 	}
 
 	xfree(ee.e_hostname);
+	xfree(ee.e_realpath);
 	ee = def_ee;
 
 	/* Check for default client */
@@ -358,6 +359,7 @@ dupexportent(struct exportent *dst, struct exportent *src)
 	if (src->e_uuid)
 		dst->e_uuid = strdup(src->e_uuid);
 	dst->e_hostname = NULL;
+	dst->e_realpath = NULL;
 }
 
 struct exportent *
@@ -369,6 +371,8 @@ mkexportent(char *hname, char *path, char *options)
 
 	xfree(ee.e_hostname);
 	ee.e_hostname = xstrdup(hname);
+	xfree(ee.e_realpath);
+	ee.e_realpath = NULL;
 
 	if (strlen(path) >= sizeof(ee.e_path)) {
 		xlog(L_ERROR, "path name %s too long", path);
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v3 08/11] Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd
  2019-05-28 20:31             ` [PATCH v3 07/11] Add a helper to return the real path given an export entry Trond Myklebust
@ 2019-05-28 20:31               ` Trond Myklebust
  2019-05-28 20:31                 ` [PATCH v3 09/11] Add support for the "[exports] rootdir" nfs.conf option to exportfs Trond Myklebust
  2019-05-31 16:02                 ` [PATCH v3 08/11] Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd J. Bruce Fields
  2019-05-29 14:38               ` [PATCH v3 07/11] Add a helper to return the real path given an export entry Steve Dickson
  1 sibling, 2 replies; 24+ messages in thread
From: Trond Myklebust @ 2019-05-28 20:31 UTC (permalink / raw)
  To: SteveD; +Cc: linux-nfs

Ensure that I/O to those pseudo files that resolve filehandles and exports
go through the chrooted threads, so that we can use paths that are relative
to the nfsd root directory.
Ensure that any stat() or lstat() calls go through their nfsd_path_*
equivalent so that they too can be resolved correctly.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
---
 nfs.conf              |  3 +++
 systemd/nfs.conf.man  | 20 +++++++++++++-
 utils/mountd/cache.c  | 63 ++++++++++++++++++++++++++++---------------
 utils/mountd/mountd.c | 13 +++++----
 4 files changed, 71 insertions(+), 28 deletions(-)

diff --git a/nfs.conf b/nfs.conf
index 27e962c8a2a9..85097fd197c0 100644
--- a/nfs.conf
+++ b/nfs.conf
@@ -5,6 +5,9 @@
 [general]
 # pipefs-directory=/var/lib/nfs/rpc_pipefs
 #
+[exports]
+# rootdir=/export
+#
 [exportfs]
 # debug=0
 #
diff --git a/systemd/nfs.conf.man b/systemd/nfs.conf.man
index e3654a3c2c2b..d375bcc1d5a7 100644
--- a/systemd/nfs.conf.man
+++ b/systemd/nfs.conf.man
@@ -107,6 +107,24 @@ and
 .BR rpc.gssd (8)
 for details.
 
+.TP
+.B exports
+Recognized values:
+.BR rootdir .
+
+Setting
+.B rootdir
+to a valid path causes the nfs server to act as if the
+supplied path is being prefixed to all the exported entries. For
+instance, if
+.BR rootdir=/my/root ,
+and there is an entry in /etc/exports for
+.BR /filesystem ,
+then the client will be able to mount the path as
+.BR /filesystem ,
+but on the server, this will resolve to the path
+.BR /my/root/filesystem .
+
 .TP
 .B nfsdcltrack
 Recognized values:
@@ -136,7 +154,7 @@ Recognized values:
 .BR vers4.0 ,
 .BR vers4.1 ,
 .BR vers4.2 ,
-.BR rdma .
+.BR rdma ,
 
 Version and protocol values are Boolean values as described above,
 and are also used by
diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
index bdbd1904eb76..d818c971bded 100644
--- a/utils/mountd/cache.c
+++ b/utils/mountd/cache.c
@@ -27,6 +27,7 @@
 #include <grp.h>
 #include <mntent.h>
 #include "misc.h"
+#include "nfsd_path.h"
 #include "nfslib.h"
 #include "exportfs.h"
 #include "mountd.h"
@@ -55,6 +56,22 @@ enum nfsd_fsid {
 	FSID_UUID16_INUM,
 };
 
+#undef is_mountpoint
+static int is_mountpoint(char *path)
+{
+	return check_is_mountpoint(path, nfsd_path_lstat);
+}
+
+static ssize_t cache_read(int fd, char *buf, size_t len)
+{
+	return nfsd_path_read(fd, buf, len);
+}
+
+static ssize_t cache_write(int fd, const char *buf, size_t len)
+{
+	return nfsd_path_write(fd, buf, len);
+}
+
 /*
  * Support routines for text-based upcalls.
  * Fields are separated by spaces.
@@ -221,7 +238,7 @@ static const char *get_uuid_blkdev(char *path)
 	if (cache == NULL)
 		blkid_get_cache(&cache, NULL);
 
-	if (stat(path, &stb) != 0)
+	if (nfsd_path_stat(path, &stb) != 0)
 		return NULL;
 	devname = blkid_devno_to_devname(stb.st_dev);
 	if (!devname)
@@ -373,21 +390,22 @@ static char *next_mnt(void **v, char *p)
 	FILE *f;
 	struct mntent *me;
 	size_t l = strlen(p);
+	char *mnt_dir = NULL;
+
 	if (*v == NULL) {
 		f = setmntent("/etc/mtab", "r");
 		*v = f;
 	} else
 		f = *v;
-	while ((me = getmntent(f)) != NULL && l > 1 &&
-	       (strncmp(me->mnt_dir, p, l) != 0 ||
-		me->mnt_dir[l] != '/'))
-		;
-	if (me == NULL) {
-		endmntent(f);
-		*v = NULL;
-		return NULL;
+	while ((me = getmntent(f)) != NULL && l > 1) {
+		mnt_dir = nfsd_path_strip_root(me->mnt_dir);
+
+		if (strncmp(mnt_dir, p, l) == 0 && mnt_dir[l] != '/')
+			return mnt_dir;
 	}
-	return me->mnt_dir;
+	endmntent(f);
+	*v = NULL;
+	return NULL;
 }
 
 /* same_path() check is two paths refer to the same directory.
@@ -458,9 +476,9 @@ fallback:
 	 * bind-mounted in two places and both are exported, it
 	 * could give a false positive
 	 */
-	if (lstat(p, &sc) != 0)
+	if (nfsd_path_lstat(p, &sc) != 0)
 		return 0;
-	if (lstat(parent, &sp) != 0)
+	if (nfsd_path_lstat(parent, &sp) != 0)
 		return 0;
 	if (sc.st_dev != sp.st_dev)
 		return 0;
@@ -610,7 +628,7 @@ static bool match_fsid(struct parsed_fsid *parsed, nfs_export *exp, char *path)
 	int type;
 	char u[16];
 
-	if (stat(path, &stb) != 0)
+	if (nfsd_path_stat(path, &stb) != 0)
 		return false;
 	if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode))
 		return false;
@@ -692,7 +710,7 @@ static void nfsd_fh(int f)
 	char buf[RPC_CHAN_BUF_SIZE], *bp;
 	int blen;
 
-	blen = read(f, buf, sizeof(buf));
+	blen = cache_read(f, buf, sizeof(buf));
 	if (blen <= 0 || buf[blen-1] != '\n') return;
 	buf[blen-1] = 0;
 
@@ -829,7 +847,7 @@ static void nfsd_fh(int f)
 	if (found)
 		qword_add(&bp, &blen, found_path);
 	qword_addeol(&bp, &blen);
-	if (blen <= 0 || write(f, buf, bp - buf) != bp - buf)
+	if (blen <= 0 || cache_write(f, buf, bp - buf) != bp - buf)
 		xlog(L_ERROR, "nfsd_fh: error writing reply");
 out:
 	if (found_path)
@@ -921,7 +939,7 @@ static int dump_to_cache(int f, char *buf, int buflen, char *domain,
 		qword_adduint(&bp, &blen, now + ttl);
 	qword_addeol(&bp, &blen);
 	if (blen <= 0) return -1;
-	if (write(f, buf, bp - buf) != bp - buf) return -1;
+	if (cache_write(f, buf, bp - buf) != bp - buf) return -1;
 	return 0;
 }
 
@@ -1298,7 +1316,7 @@ static void nfsd_export(int f)
 	char buf[RPC_CHAN_BUF_SIZE], *bp;
 	int blen;
 
-	blen = read(f, buf, sizeof(buf));
+	blen = cache_read(f, buf, sizeof(buf));
 	if (blen <= 0 || buf[blen-1] != '\n') return;
 	buf[blen-1] = 0;
 
@@ -1381,6 +1399,7 @@ extern int manage_gids;
 void cache_open(void) 
 {
 	int i;
+
 	for (i=0; cachelist[i].cache_name; i++ ) {
 		char path[100];
 		if (!manage_gids && cachelist[i].cache_handle == auth_unix_gid)
@@ -1456,7 +1475,7 @@ static int cache_export_ent(char *buf, int buflen, char *domain, struct exporten
 		if (strlen(path) <= l || path[l] != '/' ||
 		    strncmp(exp->e_path, path, l) != 0)
 			break;
-		if (stat(exp->e_path, &stb) != 0)
+		if (nfsd_path_stat(exp->e_path, &stb) != 0)
 			break;
 		dev = stb.st_dev;
 		while(path[l] == '/') {
@@ -1469,7 +1488,7 @@ static int cache_export_ent(char *buf, int buflen, char *domain, struct exporten
 				l++;
 			c = path[l];
 			path[l] = 0;
-			err2 = lstat(path, &stb);
+			err2 = nfsd_path_lstat(path, &stb);
 			path[l] = c;
 			if (err2 < 0)
 				break;
@@ -1508,7 +1527,7 @@ int cache_export(nfs_export *exp, char *path)
 	qword_adduint(&bp, &blen, time(0) + exp->m_export.e_ttl);
 	qword_add(&bp, &blen, exp->m_client->m_hostname);
 	qword_addeol(&bp, &blen);
-	if (blen <= 0 || write(f, buf, bp - buf) != bp - buf) blen = -1;
+	if (blen <= 0 || cache_write(f, buf, bp - buf) != bp - buf) blen = -1;
 	close(f);
 	if (blen < 0) return -1;
 
@@ -1546,12 +1565,12 @@ cache_get_filehandle(nfs_export *exp, int len, char *p)
 	qword_add(&bp, &blen, p);
 	qword_addint(&bp, &blen, len);
 	qword_addeol(&bp, &blen);
-	if (blen <= 0 || write(f, buf, bp - buf) != bp - buf) {
+	if (blen <= 0 || cache_write(f, buf, bp - buf) != bp - buf) {
 		close(f);
 		return NULL;
 	}
 	bp = buf;
-	blen = read(f, buf, sizeof(buf));
+	blen = cache_read(f, buf, sizeof(buf));
 	close(f);
 
 	if (blen <= 0 || buf[blen-1] != '\n')
diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c
index 88a207b3a85a..f062cac28be4 100644
--- a/utils/mountd/mountd.c
+++ b/utils/mountd/mountd.c
@@ -29,6 +29,7 @@
 #include "mountd.h"
 #include "rpcmisc.h"
 #include "pseudoflavors.h"
+#include "nfsd_path.h"
 #include "nfslib.h"
 
 extern void my_svc_run(void);
@@ -374,7 +375,7 @@ mount_pathconf_2_svc(struct svc_req *rqstp, dirpath *path, ppathcnf *res)
 	exp = auth_authenticate("pathconf", sap, p);
 	if (exp == NULL)
 		return 1;
-	else if (stat(p, &stb) < 0) {
+	else if (nfsd_path_stat(p, &stb) < 0) {
 		xlog(L_WARNING, "can't stat exported dir %s: %s",
 				p, strerror(errno));
 		return 1;
@@ -483,7 +484,7 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, nfs_export **expret,
 		*error = MNT3ERR_ACCES;
 		return NULL;
 	}
-	if (stat(p, &stb) < 0) {
+	if (nfsd_path_stat(p, &stb) < 0) {
 		xlog(L_WARNING, "can't stat exported dir %s: %s",
 				p, strerror(errno));
 		if (errno == ENOENT)
@@ -497,7 +498,7 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, nfs_export **expret,
 		*error = MNT3ERR_NOTDIR;
 		return NULL;
 	}
-	if (stat(exp->m_export.e_path, &estb) < 0) {
+	if (nfsd_path_stat(exp->m_export.e_path, &estb) < 0) {
 		xlog(L_WARNING, "can't stat export point %s: %s",
 		     p, strerror(errno));
 		*error = MNT3ERR_NOENT;
@@ -511,9 +512,10 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, nfs_export **expret,
 		return NULL;
 	}
 	if (exp->m_export.e_mountpoint &&
-		   !is_mountpoint(exp->m_export.e_mountpoint[0]?
+		   !check_is_mountpoint(exp->m_export.e_mountpoint[0]?
 				  exp->m_export.e_mountpoint:
-				  exp->m_export.e_path)) {
+				  exp->m_export.e_path,
+				  nfsd_path_lstat)) {
 		xlog(L_WARNING, "request to export an unmounted filesystem: %s",
 		     p);
 		*error = MNT3ERR_NOENT;
@@ -886,6 +888,7 @@ main(int argc, char **argv)
 	if (num_threads > 1)
 		fork_workers();
 
+	nfsd_path_init();
 	/* Open files now to avoid sharing descriptors among forked processes */
 	cache_open();
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v3 09/11] Add support for the "[exports] rootdir" nfs.conf option to exportfs
  2019-05-28 20:31               ` [PATCH v3 08/11] Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd Trond Myklebust
@ 2019-05-28 20:31                 ` Trond Myklebust
  2019-05-28 20:31                   ` [PATCH v3 10/11] Add a helper for resolving symlinked nfsd paths via realpath() Trond Myklebust
  2019-05-31 16:02                 ` [PATCH v3 08/11] Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd J. Bruce Fields
  1 sibling, 1 reply; 24+ messages in thread
From: Trond Myklebust @ 2019-05-28 20:31 UTC (permalink / raw)
  To: SteveD; +Cc: linux-nfs

Ensure that exportfs also resolves paths relative to the nfsd root
directory

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
---
 utils/exportfs/Makefile.am |  2 +-
 utils/exportfs/exportfs.c  | 11 +++++++++--
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/utils/exportfs/Makefile.am b/utils/exportfs/Makefile.am
index 4b291610d19b..96524c729359 100644
--- a/utils/exportfs/Makefile.am
+++ b/utils/exportfs/Makefile.am
@@ -10,6 +10,6 @@ exportfs_SOURCES = exportfs.c
 exportfs_LDADD = ../../support/export/libexport.a \
 	       	 ../../support/nfs/libnfs.la \
 		 ../../support/misc/libmisc.a \
-		 $(LIBWRAP) $(LIBNSL)
+		 $(LIBWRAP) $(LIBNSL) $(LIBPTHREAD)
 
 MAINTAINERCLEANFILES = Makefile.in
diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
index 333eadcd0228..5cca4175e73a 100644
--- a/utils/exportfs/exportfs.c
+++ b/utils/exportfs/exportfs.c
@@ -33,6 +33,7 @@
 
 #include "sockaddr.h"
 #include "misc.h"
+#include "nfsd_path.h"
 #include "nfslib.h"
 #include "exportfs.h"
 #include "xlog.h"
@@ -53,6 +54,11 @@ static int _lockfd = -1;
 
 struct state_paths etab;
 
+static ssize_t exportfs_write(int fd, const char *buf, size_t len)
+{
+	return nfsd_path_write(fd, buf, len);
+}
+
 /*
  * If we aren't careful, changes made by exportfs can be lost
  * when multiple exports process run at once:
@@ -109,6 +115,7 @@ main(int argc, char **argv)
 
 	conf_init_file(NFS_CONFFILE);
 	xlog_from_conffile("exportfs");
+	nfsd_path_init();
 
 	/* NOTE: following uses "mountd" section of nfs.conf !!!! */
 	s = conf_get_str("mountd", "state-directory-path");
@@ -505,7 +512,7 @@ static int test_export(nfs_export *exp, int with_fsid)
 	fd = open("/proc/net/rpc/nfsd.export/channel", O_WRONLY);
 	if (fd < 0)
 		return 0;
-	n = write(fd, buf, strlen(buf));
+	n = exportfs_write(fd, buf, strlen(buf));
 	close(fd);
 	if (n < 0)
 		return 0;
@@ -521,7 +528,7 @@ validate_export(nfs_export *exp)
 	 * otherwise trial-export to '-test-client-' and check for failure.
 	 */
 	struct stat stb;
-	char *path = exp->m_export.e_path;
+	char *path = exportent_realpath(&exp->m_export);
 	struct statfs64 stf;
 	int fs_has_fsid = 0;
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v3 10/11] Add a helper for resolving symlinked nfsd paths via realpath()
  2019-05-28 20:31                 ` [PATCH v3 09/11] Add support for the "[exports] rootdir" nfs.conf option to exportfs Trond Myklebust
@ 2019-05-28 20:31                   ` Trond Myklebust
  2019-05-28 20:31                     ` [PATCH v3 11/11] Fix up symlinked mount path resolution when "[exports] rootdir" is set Trond Myklebust
  0 siblings, 1 reply; 24+ messages in thread
From: Trond Myklebust @ 2019-05-28 20:31 UTC (permalink / raw)
  To: SteveD; +Cc: linux-nfs

Add a helper to resolve symlinked nfsd paths when the user has set the
"[exports] rootdir" nfs.conf option.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
---
 support/include/nfsd_path.h |  2 ++
 support/misc/nfsd_path.c    | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/support/include/nfsd_path.h b/support/include/nfsd_path.h
index f4a7f0a4337f..ca2570a92e68 100644
--- a/support/include/nfsd_path.h
+++ b/support/include/nfsd_path.h
@@ -13,6 +13,8 @@ char *		nfsd_path_prepend_dir(const char *dir, const char *pathname);
 int 		nfsd_path_stat(const char *pathname, struct stat *statbuf);
 int 		nfsd_path_lstat(const char *pathname, struct stat *statbuf);
 
+char *		nfsd_realpath(const char *path, char *resolved_path);
+
 ssize_t		nfsd_path_read(int fd, char *buf, size_t len);
 ssize_t		nfsd_path_write(int fd, const char *buf, size_t len);
 
diff --git a/support/misc/nfsd_path.c b/support/misc/nfsd_path.c
index 8ddafd65ab76..2f41a793c534 100644
--- a/support/misc/nfsd_path.c
+++ b/support/misc/nfsd_path.c
@@ -1,6 +1,7 @@
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <stdlib.h>
 #include <unistd.h>
 
 #include "config.h"
@@ -169,6 +170,40 @@ nfsd_path_lstat(const char *pathname, struct stat *statbuf)
 	return nfsd_run_stat(nfsd_wq, nfsd_lstatfunc, pathname, statbuf);
 }
 
+struct nfsd_realpath_data {
+	const char *pathname;
+	char *resolved;
+	int err;
+};
+
+static void
+nfsd_realpathfunc(void *data)
+{
+	struct nfsd_realpath_data *d = data;
+
+	d->resolved = realpath(d->pathname, d->resolved);
+	if (!d->resolved)
+		d->err = errno;
+}
+
+char *
+nfsd_realpath(const char *path, char *resolved_path)
+{
+	struct nfsd_realpath_data data = {
+		path,
+		resolved_path,
+		0
+	};
+
+	if (!nfsd_wq)
+		return realpath(path, resolved_path);
+
+	xthread_work_run_sync(nfsd_wq, nfsd_realpathfunc, &data);
+	if (!data.resolved)
+		errno = data.err;
+	return data.resolved;
+}
+
 struct nfsd_read_data {
 	int fd;
 	char *buf;
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v3 11/11] Fix up symlinked mount path resolution when "[exports] rootdir" is set
  2019-05-28 20:31                   ` [PATCH v3 10/11] Add a helper for resolving symlinked nfsd paths via realpath() Trond Myklebust
@ 2019-05-28 20:31                     ` Trond Myklebust
  0 siblings, 0 replies; 24+ messages in thread
From: Trond Myklebust @ 2019-05-28 20:31 UTC (permalink / raw)
  To: SteveD; +Cc: linux-nfs

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
---
 utils/mountd/mountd.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c
index f062cac28be4..33571ecbd401 100644
--- a/utils/mountd/mountd.c
+++ b/utils/mountd/mountd.c
@@ -272,7 +272,7 @@ mount_umnt_1_svc(struct svc_req *rqstp, dirpath *argp, void *UNUSED(resp))
 	if (*p == '\0')
 		p = "/";
 
-	if (realpath(p, rpath) != NULL) {
+	if (nfsd_realpath(p, rpath) != NULL) {
 		rpath[sizeof (rpath) - 1] = '\0';
 		p = rpath;
 	}
@@ -363,7 +363,7 @@ mount_pathconf_2_svc(struct svc_req *rqstp, dirpath *path, ppathcnf *res)
 	auth_reload();
 
 	/* Resolve symlinks */
-	if (realpath(p, rpath) != NULL) {
+	if (nfsd_realpath(p, rpath) != NULL) {
 		rpath[sizeof (rpath) - 1] = '\0';
 		p = rpath;
 	}
@@ -473,7 +473,7 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, nfs_export **expret,
 	auth_reload();
 
 	/* Resolve symlinks */
-	if (realpath(p, rpath) != NULL) {
+	if (nfsd_realpath(p, rpath) != NULL) {
 		rpath[sizeof (rpath) - 1] = '\0';
 		p = rpath;
 	}
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 07/11] Add a helper to return the real path given an export entry
  2019-05-28 20:31             ` [PATCH v3 07/11] Add a helper to return the real path given an export entry Trond Myklebust
  2019-05-28 20:31               ` [PATCH v3 08/11] Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd Trond Myklebust
@ 2019-05-29 14:38               ` Steve Dickson
  2019-05-29 14:55                 ` Trond Myklebust
  1 sibling, 1 reply; 24+ messages in thread
From: Steve Dickson @ 2019-05-29 14:38 UTC (permalink / raw)
  To: Trond Myklebust; +Cc: linux-nfs

Hey Trond,

On 5/28/19 4:31 PM, Trond Myklebust wrote:
> Add a helper that can prepend the nfsd root directory path in order
> to allow mountd to perform its comparisons with mtab etc.
> 
> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
> ---
>  support/export/export.c    | 24 ++++++++++++++++++++++++
>  support/include/exportfs.h |  1 +
>  support/include/nfslib.h   |  1 +
>  support/misc/nfsd_path.c   |  4 +++-
>  support/nfs/exports.c      |  4 ++++
>  5 files changed, 33 insertions(+), 1 deletion(-)
> 
> diff --git a/support/export/export.c b/support/export/export.c
> index fbe68e84e5b3..82bbb54c5e9e 100644
> --- a/support/export/export.c
> +++ b/support/export/export.c
> @@ -20,6 +20,7 @@
>  #include "xmalloc.h"
>  #include "nfslib.h"
>  #include "exportfs.h"
> +#include "nfsd_path.h"
>  
>  exp_hash_table exportlist[MCL_MAXTYPES] = {{NULL, {{NULL,NULL}, }}, }; 
>  static int export_hash(char *);
> @@ -30,6 +31,28 @@ static void	export_add(nfs_export *exp);
>  static int	export_check(const nfs_export *exp, const struct addrinfo *ai,
>  				const char *path);
>  
> +/* Return a real path for the export. */
> +static void
> +exportent_mkrealpath(struct exportent *eep)
> +{
> +	const char *chroot = nfsd_path_nfsd_rootdir();
> +	char *ret = NULL;
> +
> +	if (chroot)
> +		ret = nfsd_path_prepend_dir(chroot, eep->e_path);
> +	if (!ret)
> +		ret = xstrdup(eep->e_path);
> +	eep->e_realpath = ret;
> +}
> +
> +char *
> +exportent_realpath(struct exportent *eep)
> +{
> +	if (!eep->e_realpath)
> +		exportent_mkrealpath(eep);
> +	return eep->e_realpath;
> +}
> +
>  void
>  exportent_release(struct exportent *eep)
>  {
> @@ -39,6 +62,7 @@ exportent_release(struct exportent *eep)
>  	free(eep->e_fslocdata);
>  	free(eep->e_uuid);
>  	xfree(eep->e_hostname);
> +	xfree(eep->e_realpath);
>  }
>  
>  static void
> diff --git a/support/include/exportfs.h b/support/include/exportfs.h
> index 4e0d9d132b4c..daa7e2a06d82 100644
> --- a/support/include/exportfs.h
> +++ b/support/include/exportfs.h
> @@ -171,5 +171,6 @@ struct export_features {
>  
>  struct export_features *get_export_features(void);
>  void fix_pseudoflavor_flags(struct exportent *ep);
> +char *exportent_realpath(struct exportent *eep);
>  
>  #endif /* EXPORTFS_H */
> diff --git a/support/include/nfslib.h b/support/include/nfslib.h
> index b09fce42e677..84d8270b330f 100644
> --- a/support/include/nfslib.h
> +++ b/support/include/nfslib.h
> @@ -84,6 +84,7 @@ struct exportent {
>  	char *		e_uuid;
>  	struct sec_entry e_secinfo[SECFLAVOR_COUNT+1];
>  	unsigned int	e_ttl;
> +	char *		e_realpath;
>  };
>  
>  struct rmtabent {
> diff --git a/support/misc/nfsd_path.c b/support/misc/nfsd_path.c
> index 55bca9bdf4bd..8ddafd65ab76 100644
> --- a/support/misc/nfsd_path.c
> +++ b/support/misc/nfsd_path.c
> @@ -81,9 +81,11 @@ nfsd_path_prepend_dir(const char *dir, const char *pathname)
>  		dirlen--;
>  	if (!dirlen)
>  		return NULL;
> +	while (pathname[0] == '/')
> +		pathname++;
>  	len = dirlen + strlen(pathname) + 1;
>  	ret = xmalloc(len + 1);
> -	snprintf(ret, len, "%.*s/%s", (int)dirlen, dir, pathname);
> +	snprintf(ret, len+1, "%.*s/%s", (int)dirlen, dir, pathname);
>  	return ret;
>  }
>  
> diff --git a/support/nfs/exports.c b/support/nfs/exports.c
> index 5f4cb9568814..3ecfde797e3b 100644
> --- a/support/nfs/exports.c
> +++ b/support/nfs/exports.c
> @@ -155,6 +155,7 @@ getexportent(int fromkernel, int fromexports)
>  	}
>  
>  	xfree(ee.e_hostname);
> +	xfree(ee.e_realpath);
>  	ee = def_ee;
>  
>  	/* Check for default client */
> @@ -358,6 +359,7 @@ dupexportent(struct exportent *dst, struct exportent *src)
>  	if (src->e_uuid)
>  		dst->e_uuid = strdup(src->e_uuid);
>  	dst->e_hostname = NULL;
> +	dst->e_realpath = NULL;
>  }
>  
>  struct exportent *
> @@ -369,6 +371,8 @@ mkexportent(char *hname, char *path, char *options)
>  
>  	xfree(ee.e_hostname);
>  	ee.e_hostname = xstrdup(hname);
> +	xfree(ee.e_realpath);
> +	ee.e_realpath = NULL;
>  
>  	if (strlen(path) >= sizeof(ee.e_path)) {
>  		xlog(L_ERROR, "path name %s too long", path);
> 
I'm not really sure why this is happening on this patch and how
I missed this in the first version.. but I'm getting the following
linking error after applying this patch

/usr/bin/ld: ../../support/misc/libmisc.a(workqueue.o): in function `xthread_workqueue_worker':
/home/src/up/nfs-utils/support/misc/workqueue.c:133: undefined reference to `__pthread_register_cancel'
/usr/bin/ld: /home/src/up/nfs-utils/support/misc/workqueue.c:135: undefined reference to `__pthread_unregister_cancel'
/usr/bin/ld: ../../support/misc/libmisc.a(workqueue.o): in function `xthread_workqueue_alloc':
/home/src/up/nfs-utils/support/misc/workqueue.c:149: undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status

To get things to link I need this patch

diff --git a/systemd/Makefile.am b/systemd/Makefile.am
index d54518b..590258a 100644
--- a/systemd/Makefile.am
+++ b/systemd/Makefile.am
@@ -54,7 +54,8 @@ rpc_pipefs_generator_SOURCES = $(COMMON_SRCS) rpc-pipefs-generator.c
 
 nfs_server_generator_LDADD = ../support/export/libexport.a \
 			     ../support/nfs/libnfs.la \
-			     ../support/misc/libmisc.a
+			     ../support/misc/libmisc.a \
+			     $(LIBPTHREAD)
 
 rpc_pipefs_generator_LDADD = ../support/nfs/libnfs.la
 
diff --git a/utils/exportfs/Makefile.am b/utils/exportfs/Makefile.am
index 4b29161..96524c7 100644
--- a/utils/exportfs/Makefile.am
+++ b/utils/exportfs/Makefile.am
@@ -10,6 +10,6 @@ exportfs_SOURCES = exportfs.c
 exportfs_LDADD = ../../support/export/libexport.a \
 	       	 ../../support/nfs/libnfs.la \
 		 ../../support/misc/libmisc.a \
-		 $(LIBWRAP) $(LIBNSL)
+		 $(LIBWRAP) $(LIBNSL) $(LIBPTHREAD)
 
 MAINTAINERCLEANFILES = Makefile.in

I would think I should have seen this early when threads
was added to libmisc.a via the [Add a simple workqueue mechanism] 
patch but I didn't...

steved. 

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 07/11] Add a helper to return the real path given an export entry
  2019-05-29 14:38               ` [PATCH v3 07/11] Add a helper to return the real path given an export entry Steve Dickson
@ 2019-05-29 14:55                 ` Trond Myklebust
  2019-05-29 16:03                   ` Steve Dickson
  0 siblings, 1 reply; 24+ messages in thread
From: Trond Myklebust @ 2019-05-29 14:55 UTC (permalink / raw)
  To: SteveD; +Cc: linux-nfs

On Wed, 2019-05-29 at 10:38 -0400, Steve Dickson wrote:
> Hey Trond,
> 
> On 5/28/19 4:31 PM, Trond Myklebust wrote:
> > Add a helper that can prepend the nfsd root directory path in order
> > to allow mountd to perform its comparisons with mtab etc.
> > 
> > Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
> > ---
> >  support/export/export.c    | 24 ++++++++++++++++++++++++
> >  support/include/exportfs.h |  1 +
> >  support/include/nfslib.h   |  1 +
> >  support/misc/nfsd_path.c   |  4 +++-
> >  support/nfs/exports.c      |  4 ++++
> >  5 files changed, 33 insertions(+), 1 deletion(-)
> > 
> > diff --git a/support/export/export.c b/support/export/export.c
> > index fbe68e84e5b3..82bbb54c5e9e 100644
> > --- a/support/export/export.c
> > +++ b/support/export/export.c
> > @@ -20,6 +20,7 @@
> >  #include "xmalloc.h"
> >  #include "nfslib.h"
> >  #include "exportfs.h"
> > +#include "nfsd_path.h"
> >  
> >  exp_hash_table exportlist[MCL_MAXTYPES] = {{NULL, {{NULL,NULL},
> > }}, }; 
> >  static int export_hash(char *);
> > @@ -30,6 +31,28 @@ static void	export_add(nfs_export *exp);
> >  static int	export_check(const nfs_export *exp, const struct
> > addrinfo *ai,
> >  				const char *path);
> >  
> > +/* Return a real path for the export. */
> > +static void
> > +exportent_mkrealpath(struct exportent *eep)
> > +{
> > +	const char *chroot = nfsd_path_nfsd_rootdir();
> > +	char *ret = NULL;
> > +
> > +	if (chroot)
> > +		ret = nfsd_path_prepend_dir(chroot, eep->e_path);
> > +	if (!ret)
> > +		ret = xstrdup(eep->e_path);
> > +	eep->e_realpath = ret;
> > +}
> > +
> > +char *
> > +exportent_realpath(struct exportent *eep)
> > +{
> > +	if (!eep->e_realpath)
> > +		exportent_mkrealpath(eep);
> > +	return eep->e_realpath;
> > +}
> > +
> >  void
> >  exportent_release(struct exportent *eep)
> >  {
> > @@ -39,6 +62,7 @@ exportent_release(struct exportent *eep)
> >  	free(eep->e_fslocdata);
> >  	free(eep->e_uuid);
> >  	xfree(eep->e_hostname);
> > +	xfree(eep->e_realpath);
> >  }
> >  
> >  static void
> > diff --git a/support/include/exportfs.h
> > b/support/include/exportfs.h
> > index 4e0d9d132b4c..daa7e2a06d82 100644
> > --- a/support/include/exportfs.h
> > +++ b/support/include/exportfs.h
> > @@ -171,5 +171,6 @@ struct export_features {
> >  
> >  struct export_features *get_export_features(void);
> >  void fix_pseudoflavor_flags(struct exportent *ep);
> > +char *exportent_realpath(struct exportent *eep);
> >  
> >  #endif /* EXPORTFS_H */
> > diff --git a/support/include/nfslib.h b/support/include/nfslib.h
> > index b09fce42e677..84d8270b330f 100644
> > --- a/support/include/nfslib.h
> > +++ b/support/include/nfslib.h
> > @@ -84,6 +84,7 @@ struct exportent {
> >  	char *		e_uuid;
> >  	struct sec_entry e_secinfo[SECFLAVOR_COUNT+1];
> >  	unsigned int	e_ttl;
> > +	char *		e_realpath;
> >  };
> >  
> >  struct rmtabent {
> > diff --git a/support/misc/nfsd_path.c b/support/misc/nfsd_path.c
> > index 55bca9bdf4bd..8ddafd65ab76 100644
> > --- a/support/misc/nfsd_path.c
> > +++ b/support/misc/nfsd_path.c
> > @@ -81,9 +81,11 @@ nfsd_path_prepend_dir(const char *dir, const
> > char *pathname)
> >  		dirlen--;
> >  	if (!dirlen)
> >  		return NULL;
> > +	while (pathname[0] == '/')
> > +		pathname++;
> >  	len = dirlen + strlen(pathname) + 1;
> >  	ret = xmalloc(len + 1);
> > -	snprintf(ret, len, "%.*s/%s", (int)dirlen, dir, pathname);
> > +	snprintf(ret, len+1, "%.*s/%s", (int)dirlen, dir, pathname);
> >  	return ret;
> >  }
> >  
> > diff --git a/support/nfs/exports.c b/support/nfs/exports.c
> > index 5f4cb9568814..3ecfde797e3b 100644
> > --- a/support/nfs/exports.c
> > +++ b/support/nfs/exports.c
> > @@ -155,6 +155,7 @@ getexportent(int fromkernel, int fromexports)
> >  	}
> >  
> >  	xfree(ee.e_hostname);
> > +	xfree(ee.e_realpath);
> >  	ee = def_ee;
> >  
> >  	/* Check for default client */
> > @@ -358,6 +359,7 @@ dupexportent(struct exportent *dst, struct
> > exportent *src)
> >  	if (src->e_uuid)
> >  		dst->e_uuid = strdup(src->e_uuid);
> >  	dst->e_hostname = NULL;
> > +	dst->e_realpath = NULL;
> >  }
> >  
> >  struct exportent *
> > @@ -369,6 +371,8 @@ mkexportent(char *hname, char *path, char
> > *options)
> >  
> >  	xfree(ee.e_hostname);
> >  	ee.e_hostname = xstrdup(hname);
> > +	xfree(ee.e_realpath);
> > +	ee.e_realpath = NULL;
> >  
> >  	if (strlen(path) >= sizeof(ee.e_path)) {
> >  		xlog(L_ERROR, "path name %s too long", path);
> > 
> I'm not really sure why this is happening on this patch and how
> I missed this in the first version.. but I'm getting the following
> linking error after applying this patch
> 
> /usr/bin/ld: ../../support/misc/libmisc.a(workqueue.o): in function
> `xthread_workqueue_worker':
> /home/src/up/nfs-utils/support/misc/workqueue.c:133: undefined
> reference to `__pthread_register_cancel'
> /usr/bin/ld: /home/src/up/nfs-utils/support/misc/workqueue.c:135:
> undefined reference to `__pthread_unregister_cancel'
> /usr/bin/ld: ../../support/misc/libmisc.a(workqueue.o): in function
> `xthread_workqueue_alloc':
> /home/src/up/nfs-utils/support/misc/workqueue.c:149: undefined
> reference to `pthread_create'
> collect2: error: ld returned 1 exit status
> 
> To get things to link I need this patch
> 

Huh, that's weird... I've been compiling this over and over and have
yet to see that compile error.

Do you want me to integrate your fix and resend, or do you prefer just
to apply your fix to the existing series as a separate commit
immediately before this patch?

Cheers
  Trond

-- 
Trond Myklebust
Linux NFS client maintainer, Hammerspace
trond.myklebust@hammerspace.com



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 07/11] Add a helper to return the real path given an export entry
  2019-05-29 14:55                 ` Trond Myklebust
@ 2019-05-29 16:03                   ` Steve Dickson
  2019-05-29 16:12                     ` Trond Myklebust
  0 siblings, 1 reply; 24+ messages in thread
From: Steve Dickson @ 2019-05-29 16:03 UTC (permalink / raw)
  To: Trond Myklebust; +Cc: linux-nfs



On 5/29/19 10:55 AM, Trond Myklebust wrote:
> On Wed, 2019-05-29 at 10:38 -0400, Steve Dickson wrote:
>> Hey Trond,
>>
>> On 5/28/19 4:31 PM, Trond Myklebust wrote:
>>> Add a helper that can prepend the nfsd root directory path in order
>>> to allow mountd to perform its comparisons with mtab etc.
>>>
>>> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
>>> ---
>>>  support/export/export.c    | 24 ++++++++++++++++++++++++
>>>  support/include/exportfs.h |  1 +
>>>  support/include/nfslib.h   |  1 +
>>>  support/misc/nfsd_path.c   |  4 +++-
>>>  support/nfs/exports.c      |  4 ++++
>>>  5 files changed, 33 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/support/export/export.c b/support/export/export.c
>>> index fbe68e84e5b3..82bbb54c5e9e 100644
>>> --- a/support/export/export.c
>>> +++ b/support/export/export.c
>>> @@ -20,6 +20,7 @@
>>>  #include "xmalloc.h"
>>>  #include "nfslib.h"
>>>  #include "exportfs.h"
>>> +#include "nfsd_path.h"
>>>  
>>>  exp_hash_table exportlist[MCL_MAXTYPES] = {{NULL, {{NULL,NULL},
>>> }}, }; 
>>>  static int export_hash(char *);
>>> @@ -30,6 +31,28 @@ static void	export_add(nfs_export *exp);
>>>  static int	export_check(const nfs_export *exp, const struct
>>> addrinfo *ai,
>>>  				const char *path);
>>>  
>>> +/* Return a real path for the export. */
>>> +static void
>>> +exportent_mkrealpath(struct exportent *eep)
>>> +{
>>> +	const char *chroot = nfsd_path_nfsd_rootdir();
>>> +	char *ret = NULL;
>>> +
>>> +	if (chroot)
>>> +		ret = nfsd_path_prepend_dir(chroot, eep->e_path);
>>> +	if (!ret)
>>> +		ret = xstrdup(eep->e_path);
>>> +	eep->e_realpath = ret;
>>> +}
>>> +
>>> +char *
>>> +exportent_realpath(struct exportent *eep)
>>> +{
>>> +	if (!eep->e_realpath)
>>> +		exportent_mkrealpath(eep);
>>> +	return eep->e_realpath;
>>> +}
>>> +
>>>  void
>>>  exportent_release(struct exportent *eep)
>>>  {
>>> @@ -39,6 +62,7 @@ exportent_release(struct exportent *eep)
>>>  	free(eep->e_fslocdata);
>>>  	free(eep->e_uuid);
>>>  	xfree(eep->e_hostname);
>>> +	xfree(eep->e_realpath);
>>>  }
>>>  
>>>  static void
>>> diff --git a/support/include/exportfs.h
>>> b/support/include/exportfs.h
>>> index 4e0d9d132b4c..daa7e2a06d82 100644
>>> --- a/support/include/exportfs.h
>>> +++ b/support/include/exportfs.h
>>> @@ -171,5 +171,6 @@ struct export_features {
>>>  
>>>  struct export_features *get_export_features(void);
>>>  void fix_pseudoflavor_flags(struct exportent *ep);
>>> +char *exportent_realpath(struct exportent *eep);
>>>  
>>>  #endif /* EXPORTFS_H */
>>> diff --git a/support/include/nfslib.h b/support/include/nfslib.h
>>> index b09fce42e677..84d8270b330f 100644
>>> --- a/support/include/nfslib.h
>>> +++ b/support/include/nfslib.h
>>> @@ -84,6 +84,7 @@ struct exportent {
>>>  	char *		e_uuid;
>>>  	struct sec_entry e_secinfo[SECFLAVOR_COUNT+1];
>>>  	unsigned int	e_ttl;
>>> +	char *		e_realpath;
>>>  };
>>>  
>>>  struct rmtabent {
>>> diff --git a/support/misc/nfsd_path.c b/support/misc/nfsd_path.c
>>> index 55bca9bdf4bd..8ddafd65ab76 100644
>>> --- a/support/misc/nfsd_path.c
>>> +++ b/support/misc/nfsd_path.c
>>> @@ -81,9 +81,11 @@ nfsd_path_prepend_dir(const char *dir, const
>>> char *pathname)
>>>  		dirlen--;
>>>  	if (!dirlen)
>>>  		return NULL;
>>> +	while (pathname[0] == '/')
>>> +		pathname++;
>>>  	len = dirlen + strlen(pathname) + 1;
>>>  	ret = xmalloc(len + 1);
>>> -	snprintf(ret, len, "%.*s/%s", (int)dirlen, dir, pathname);
>>> +	snprintf(ret, len+1, "%.*s/%s", (int)dirlen, dir, pathname);
>>>  	return ret;
>>>  }
>>>  
>>> diff --git a/support/nfs/exports.c b/support/nfs/exports.c
>>> index 5f4cb9568814..3ecfde797e3b 100644
>>> --- a/support/nfs/exports.c
>>> +++ b/support/nfs/exports.c
>>> @@ -155,6 +155,7 @@ getexportent(int fromkernel, int fromexports)
>>>  	}
>>>  
>>>  	xfree(ee.e_hostname);
>>> +	xfree(ee.e_realpath);
>>>  	ee = def_ee;
>>>  
>>>  	/* Check for default client */
>>> @@ -358,6 +359,7 @@ dupexportent(struct exportent *dst, struct
>>> exportent *src)
>>>  	if (src->e_uuid)
>>>  		dst->e_uuid = strdup(src->e_uuid);
>>>  	dst->e_hostname = NULL;
>>> +	dst->e_realpath = NULL;
>>>  }
>>>  
>>>  struct exportent *
>>> @@ -369,6 +371,8 @@ mkexportent(char *hname, char *path, char
>>> *options)
>>>  
>>>  	xfree(ee.e_hostname);
>>>  	ee.e_hostname = xstrdup(hname);
>>> +	xfree(ee.e_realpath);
>>> +	ee.e_realpath = NULL;
>>>  
>>>  	if (strlen(path) >= sizeof(ee.e_path)) {
>>>  		xlog(L_ERROR, "path name %s too long", path);
>>>
>> I'm not really sure why this is happening on this patch and how
>> I missed this in the first version.. but I'm getting the following
>> linking error after applying this patch
>>
>> /usr/bin/ld: ../../support/misc/libmisc.a(workqueue.o): in function
>> `xthread_workqueue_worker':
>> /home/src/up/nfs-utils/support/misc/workqueue.c:133: undefined
>> reference to `__pthread_register_cancel'
>> /usr/bin/ld: /home/src/up/nfs-utils/support/misc/workqueue.c:135:
>> undefined reference to `__pthread_unregister_cancel'
>> /usr/bin/ld: ../../support/misc/libmisc.a(workqueue.o): in function
>> `xthread_workqueue_alloc':
>> /home/src/up/nfs-utils/support/misc/workqueue.c:149: undefined
>> reference to `pthread_create'
>> collect2: error: ld returned 1 exit status
>>
>> To get things to link I need this patch
>>
> 
> Huh, that's weird... I've been compiling this over and over and have
> yet to see that compile error.
I do a "make clean distclean" then use a RHEL8 configuration.... 
Maybe that has something to do with it.
 
> 
> Do you want me to integrate your fix and resend, or do you prefer just
> to apply your fix to the existing series as a separate commit
> immediately before this patch?
No... I'll just apply the patch to this patch and move on... 

I was just curious if you were seeing this as well... 

steved.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 07/11] Add a helper to return the real path given an export entry
  2019-05-29 16:03                   ` Steve Dickson
@ 2019-05-29 16:12                     ` Trond Myklebust
  2019-05-29 17:17                       ` Steve Dickson
  0 siblings, 1 reply; 24+ messages in thread
From: Trond Myklebust @ 2019-05-29 16:12 UTC (permalink / raw)
  To: SteveD; +Cc: linux-nfs

On Wed, 2019-05-29 at 12:03 -0400, Steve Dickson wrote:
> 
> On 5/29/19 10:55 AM, Trond Myklebust wrote:
> > On Wed, 2019-05-29 at 10:38 -0400, Steve Dickson wrote:
> > > Hey Trond,
> > > 
> > > On 5/28/19 4:31 PM, Trond Myklebust wrote:
> > > > Add a helper that can prepend the nfsd root directory path in
> > > > order
> > > > to allow mountd to perform its comparisons with mtab etc.
> > > > 
> > > > Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com
> > > > >
> > > > ---
> > > >  support/export/export.c    | 24 ++++++++++++++++++++++++
> > > >  support/include/exportfs.h |  1 +
> > > >  support/include/nfslib.h   |  1 +
> > > >  support/misc/nfsd_path.c   |  4 +++-
> > > >  support/nfs/exports.c      |  4 ++++
> > > >  5 files changed, 33 insertions(+), 1 deletion(-)
> > > > 
> > > > diff --git a/support/export/export.c b/support/export/export.c
> > > > index fbe68e84e5b3..82bbb54c5e9e 100644
> > > > --- a/support/export/export.c
> > > > +++ b/support/export/export.c
> > > > @@ -20,6 +20,7 @@
> > > >  #include "xmalloc.h"
> > > >  #include "nfslib.h"
> > > >  #include "exportfs.h"
> > > > +#include "nfsd_path.h"
> > > >  
> > > >  exp_hash_table exportlist[MCL_MAXTYPES] = {{NULL,
> > > > {{NULL,NULL},
> > > > }}, }; 
> > > >  static int export_hash(char *);
> > > > @@ -30,6 +31,28 @@ static void	export_add(nfs_export *exp);
> > > >  static int	export_check(const nfs_export *exp, const
> > > > struct
> > > > addrinfo *ai,
> > > >  				const char *path);
> > > >  
> > > > +/* Return a real path for the export. */
> > > > +static void
> > > > +exportent_mkrealpath(struct exportent *eep)
> > > > +{
> > > > +	const char *chroot = nfsd_path_nfsd_rootdir();
> > > > +	char *ret = NULL;
> > > > +
> > > > +	if (chroot)
> > > > +		ret = nfsd_path_prepend_dir(chroot, eep-
> > > > >e_path);
> > > > +	if (!ret)
> > > > +		ret = xstrdup(eep->e_path);
> > > > +	eep->e_realpath = ret;
> > > > +}
> > > > +
> > > > +char *
> > > > +exportent_realpath(struct exportent *eep)
> > > > +{
> > > > +	if (!eep->e_realpath)
> > > > +		exportent_mkrealpath(eep);
> > > > +	return eep->e_realpath;
> > > > +}
> > > > +
> > > >  void
> > > >  exportent_release(struct exportent *eep)
> > > >  {
> > > > @@ -39,6 +62,7 @@ exportent_release(struct exportent *eep)
> > > >  	free(eep->e_fslocdata);
> > > >  	free(eep->e_uuid);
> > > >  	xfree(eep->e_hostname);
> > > > +	xfree(eep->e_realpath);
> > > >  }
> > > >  
> > > >  static void
> > > > diff --git a/support/include/exportfs.h
> > > > b/support/include/exportfs.h
> > > > index 4e0d9d132b4c..daa7e2a06d82 100644
> > > > --- a/support/include/exportfs.h
> > > > +++ b/support/include/exportfs.h
> > > > @@ -171,5 +171,6 @@ struct export_features {
> > > >  
> > > >  struct export_features *get_export_features(void);
> > > >  void fix_pseudoflavor_flags(struct exportent *ep);
> > > > +char *exportent_realpath(struct exportent *eep);
> > > >  
> > > >  #endif /* EXPORTFS_H */
> > > > diff --git a/support/include/nfslib.h
> > > > b/support/include/nfslib.h
> > > > index b09fce42e677..84d8270b330f 100644
> > > > --- a/support/include/nfslib.h
> > > > +++ b/support/include/nfslib.h
> > > > @@ -84,6 +84,7 @@ struct exportent {
> > > >  	char *		e_uuid;
> > > >  	struct sec_entry e_secinfo[SECFLAVOR_COUNT+1];
> > > >  	unsigned int	e_ttl;
> > > > +	char *		e_realpath;
> > > >  };
> > > >  
> > > >  struct rmtabent {
> > > > diff --git a/support/misc/nfsd_path.c
> > > > b/support/misc/nfsd_path.c
> > > > index 55bca9bdf4bd..8ddafd65ab76 100644
> > > > --- a/support/misc/nfsd_path.c
> > > > +++ b/support/misc/nfsd_path.c
> > > > @@ -81,9 +81,11 @@ nfsd_path_prepend_dir(const char *dir, const
> > > > char *pathname)
> > > >  		dirlen--;
> > > >  	if (!dirlen)
> > > >  		return NULL;
> > > > +	while (pathname[0] == '/')
> > > > +		pathname++;
> > > >  	len = dirlen + strlen(pathname) + 1;
> > > >  	ret = xmalloc(len + 1);
> > > > -	snprintf(ret, len, "%.*s/%s", (int)dirlen, dir,
> > > > pathname);
> > > > +	snprintf(ret, len+1, "%.*s/%s", (int)dirlen, dir,
> > > > pathname);
> > > >  	return ret;
> > > >  }
> > > >  
> > > > diff --git a/support/nfs/exports.c b/support/nfs/exports.c
> > > > index 5f4cb9568814..3ecfde797e3b 100644
> > > > --- a/support/nfs/exports.c
> > > > +++ b/support/nfs/exports.c
> > > > @@ -155,6 +155,7 @@ getexportent(int fromkernel, int
> > > > fromexports)
> > > >  	}
> > > >  
> > > >  	xfree(ee.e_hostname);
> > > > +	xfree(ee.e_realpath);
> > > >  	ee = def_ee;
> > > >  
> > > >  	/* Check for default client */
> > > > @@ -358,6 +359,7 @@ dupexportent(struct exportent *dst, struct
> > > > exportent *src)
> > > >  	if (src->e_uuid)
> > > >  		dst->e_uuid = strdup(src->e_uuid);
> > > >  	dst->e_hostname = NULL;
> > > > +	dst->e_realpath = NULL;
> > > >  }
> > > >  
> > > >  struct exportent *
> > > > @@ -369,6 +371,8 @@ mkexportent(char *hname, char *path, char
> > > > *options)
> > > >  
> > > >  	xfree(ee.e_hostname);
> > > >  	ee.e_hostname = xstrdup(hname);
> > > > +	xfree(ee.e_realpath);
> > > > +	ee.e_realpath = NULL;
> > > >  
> > > >  	if (strlen(path) >= sizeof(ee.e_path)) {
> > > >  		xlog(L_ERROR, "path name %s too long", path);
> > > > 
> > > I'm not really sure why this is happening on this patch and how
> > > I missed this in the first version.. but I'm getting the
> > > following
> > > linking error after applying this patch
> > > 
> > > /usr/bin/ld: ../../support/misc/libmisc.a(workqueue.o): in
> > > function
> > > `xthread_workqueue_worker':
> > > /home/src/up/nfs-utils/support/misc/workqueue.c:133: undefined
> > > reference to `__pthread_register_cancel'
> > > /usr/bin/ld: /home/src/up/nfs-utils/support/misc/workqueue.c:135:
> > > undefined reference to `__pthread_unregister_cancel'
> > > /usr/bin/ld: ../../support/misc/libmisc.a(workqueue.o): in
> > > function
> > > `xthread_workqueue_alloc':
> > > /home/src/up/nfs-utils/support/misc/workqueue.c:149: undefined
> > > reference to `pthread_create'
> > > collect2: error: ld returned 1 exit status
> > > 
> > > To get things to link I need this patch
> > > 
> > 
> > Huh, that's weird... I've been compiling this over and over and
> > have
> > yet to see that compile error.
> I do a "make clean distclean" then use a RHEL8 configuration.... 
> Maybe that has something to do with it.

Yes, I'm using Fedora 30, so this is likely due to the difference in
binutils packages (and hence which 'ld' linker versions) that we're
compiling with.

> > Do you want me to integrate your fix and resend, or do you prefer
> > just
> > to apply your fix to the existing series as a separate commit
> > immediately before this patch?
> No... I'll just apply the patch to this patch and move on... 
> 
> I was just curious if you were seeing this as well... 
> 

Cool. Thanks!

-- 
Trond Myklebust
Linux NFS client maintainer, Hammerspace
trond.myklebust@hammerspace.com



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 07/11] Add a helper to return the real path given an export entry
  2019-05-29 16:12                     ` Trond Myklebust
@ 2019-05-29 17:17                       ` Steve Dickson
  0 siblings, 0 replies; 24+ messages in thread
From: Steve Dickson @ 2019-05-29 17:17 UTC (permalink / raw)
  To: Trond Myklebust; +Cc: linux-nfs

On 5/29/19 12:12 PM, Trond Myklebust wrote:
>>>> I'm not really sure why this is happening on this patch and how
>>>> I missed this in the first version.. but I'm getting the
>>>> following
>>>> linking error after applying this patch
>>>>
>>>> /usr/bin/ld: ../../support/misc/libmisc.a(workqueue.o): in
>>>> function
>>>> `xthread_workqueue_worker':
>>>> /home/src/up/nfs-utils/support/misc/workqueue.c:133: undefined
>>>> reference to `__pthread_register_cancel'
>>>> /usr/bin/ld: /home/src/up/nfs-utils/support/misc/workqueue.c:135:
>>>> undefined reference to `__pthread_unregister_cancel'
>>>> /usr/bin/ld: ../../support/misc/libmisc.a(workqueue.o): in
>>>> function
>>>> `xthread_workqueue_alloc':
>>>> /home/src/up/nfs-utils/support/misc/workqueue.c:149: undefined
>>>> reference to `pthread_create'
>>>> collect2: error: ld returned 1 exit status
>>>>
>>>> To get things to link I need this patch
>>>>
>>> Huh, that's weird... I've been compiling this over and over and
>>> have
>>> yet to see that compile error.
FYI... It turns out enabling systemd (aka --with-systemd) cause the
error... 

steved.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 04/11] Add utilities for resolving nfsd paths and stat()ing them
  2019-05-28 20:31       ` [PATCH v3 04/11] Add utilities for resolving nfsd paths and stat()ing them Trond Myklebust
  2019-05-28 20:31         ` [PATCH v3 05/11] Use xstat() with no synchronisation if available Trond Myklebust
@ 2019-05-31 15:52         ` J. Bruce Fields
  2019-06-03 14:21           ` Steve Dickson
  1 sibling, 1 reply; 24+ messages in thread
From: J. Bruce Fields @ 2019-05-31 15:52 UTC (permalink / raw)
  To: Trond Myklebust; +Cc: SteveD, linux-nfs

On Tue, May 28, 2019 at 04:31:15PM -0400, Trond Myklebust wrote:
> +char *
> +nfsd_path_strip_root(char *pathname)
> +{
> +	const char *dir = nfsd_path_nfsd_rootdir();
> +	char *ret;
> +
> +	ret = strstr(pathname, dir);
> +	if (!ret || ret != pathname)
> +		return pathname;

Shouldn't we return NULL or an error or something here?  It seems a
little strange not to care if the path began with root or not.  I guess
I need to look at the caller....

--b.

> +	return pathname + strlen(dir);
> +}
> +
> +char *
> +nfsd_path_prepend_dir(const char *dir, const char *pathname)
> +{
> +	size_t len, dirlen;
> +	char *ret;
> +
> +	dirlen = strlen(dir);
> +	while (dirlen > 0 && dir[dirlen - 1] == '/')
> +		dirlen--;
> +	if (!dirlen)
> +		return NULL;
> +	len = dirlen + strlen(pathname) + 1;
> +	ret = xmalloc(len + 1);
> +	snprintf(ret, len, "%.*s/%s", (int)dirlen, dir, pathname);
> +	return ret;
> +}
> +
> +static void
> +nfsd_setup_workqueue(void)
> +{
> +	const char *rootdir = nfsd_path_nfsd_rootdir();
> +
> +	if (!rootdir)
> +		return;
> +	nfsd_wq = xthread_workqueue_alloc();
> +	if (!nfsd_wq)
> +		return;
> +	xthread_workqueue_chroot(nfsd_wq, rootdir);
> +}
> +
> +void
> +nfsd_path_init(void)
> +{
> +	nfsd_setup_workqueue();
> +}
> +
> +struct nfsd_stat_data {
> +	const char *pathname;
> +	struct stat *statbuf;
> +	int ret;
> +	int err;
> +};
> +
> +static void
> +nfsd_statfunc(void *data)
> +{
> +	struct nfsd_stat_data *d = data;
> +
> +	d->ret = xstat(d->pathname, d->statbuf);
> +	if (d->ret < 0)
> +		d->err = errno;
> +}
> +
> +static void
> +nfsd_lstatfunc(void *data)
> +{
> +	struct nfsd_stat_data *d = data;
> +
> +	d->ret = xlstat(d->pathname, d->statbuf);
> +	if (d->ret < 0)
> +		d->err = errno;
> +}
> +
> +static int
> +nfsd_run_stat(struct xthread_workqueue *wq,
> +		void (*func)(void *),
> +		const char *pathname,
> +		struct stat *statbuf)
> +{
> +	struct nfsd_stat_data data = {
> +		pathname,
> +		statbuf,
> +		0,
> +		0
> +	};
> +	xthread_work_run_sync(wq, func, &data);
> +	if (data.ret < 0)
> +		errno = data.err;
> +	return data.ret;
> +}
> +
> +int
> +nfsd_path_stat(const char *pathname, struct stat *statbuf)
> +{
> +	if (!nfsd_wq)
> +		return xstat(pathname, statbuf);
> +	return nfsd_run_stat(nfsd_wq, nfsd_statfunc, pathname, statbuf);
> +}
> +
> +int
> +nfsd_path_lstat(const char *pathname, struct stat *statbuf)
> +{
> +	if (!nfsd_wq)
> +		return xlstat(pathname, statbuf);
> +	return nfsd_run_stat(nfsd_wq, nfsd_lstatfunc, pathname, statbuf);
> +}
> diff --git a/support/misc/xstat.c b/support/misc/xstat.c
> new file mode 100644
> index 000000000000..d092f73dfd65
> --- /dev/null
> +++ b/support/misc/xstat.c
> @@ -0,0 +1,33 @@
> +#include <sys/types.h>
> +#include <fcntl.h>
> +#include <sys/stat.h>
> +#include <unistd.h>
> +
> +#include "config.h"
> +#include "xstat.h"
> +
> +#ifdef HAVE_FSTATAT
> +
> +int xlstat(const char *pathname, struct stat *statbuf)
> +{
> +	return fstatat(AT_FDCWD, pathname, statbuf, AT_NO_AUTOMOUNT |
> +			AT_SYMLINK_NOFOLLOW);
> +}
> +
> +int xstat(const char *pathname, struct stat *statbuf)
> +{
> +	return fstatat(AT_FDCWD, pathname, statbuf, AT_NO_AUTOMOUNT);
> +}
> +
> +#else
> +
> +int xlstat(const char *pathname, struct stat *statbuf)
> +{
> +	return lstat(pathname, statbuf);
> +}
> +
> +int xstat(const char *pathname, struct stat *statbuf)
> +{
> +	return stat(pathname, statbuf);
> +}
> +#endif
> -- 
> 2.21.0

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 08/11] Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd
  2019-05-28 20:31               ` [PATCH v3 08/11] Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd Trond Myklebust
  2019-05-28 20:31                 ` [PATCH v3 09/11] Add support for the "[exports] rootdir" nfs.conf option to exportfs Trond Myklebust
@ 2019-05-31 16:02                 ` J. Bruce Fields
  2019-06-03 14:18                   ` Steve Dickson
  1 sibling, 1 reply; 24+ messages in thread
From: J. Bruce Fields @ 2019-05-31 16:02 UTC (permalink / raw)
  To: Trond Myklebust; +Cc: SteveD, linux-nfs

On Tue, May 28, 2019 at 04:31:19PM -0400, Trond Myklebust wrote:
> @@ -373,21 +390,22 @@ static char *next_mnt(void **v, char *p)
>  	FILE *f;
>  	struct mntent *me;
>  	size_t l = strlen(p);
> +	char *mnt_dir = NULL;
> +
>  	if (*v == NULL) {
>  		f = setmntent("/etc/mtab", "r");
>  		*v = f;
>  	} else
>  		f = *v;
> -	while ((me = getmntent(f)) != NULL && l > 1 &&
> -	       (strncmp(me->mnt_dir, p, l) != 0 ||
> -		me->mnt_dir[l] != '/'))
> -		;
> -	if (me == NULL) {
> -		endmntent(f);
> -		*v = NULL;
> -		return NULL;
> +	while ((me = getmntent(f)) != NULL && l > 1) {
> +		mnt_dir = nfsd_path_strip_root(me->mnt_dir);
> +
> +		if (strncmp(mnt_dir, p, l) == 0 && mnt_dir[l] != '/')
> +			return mnt_dir;

That should be "mnt_dir[l] == '/'", right?

--b.

>  	}
> -	return me->mnt_dir;
> +	endmntent(f);
> +	*v = NULL;
> +	return NULL;
>  }
>  
>  /* same_path() check is two paths refer to the same directory.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 08/11] Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd
  2019-05-31 16:02                 ` [PATCH v3 08/11] Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd J. Bruce Fields
@ 2019-06-03 14:18                   ` Steve Dickson
  2019-06-03 16:30                     ` Trond Myklebust
  0 siblings, 1 reply; 24+ messages in thread
From: Steve Dickson @ 2019-06-03 14:18 UTC (permalink / raw)
  To: J. Bruce Fields, Trond Myklebust; +Cc: linux-nfs



On 5/31/19 12:02 PM, J. Bruce Fields wrote:
> On Tue, May 28, 2019 at 04:31:19PM -0400, Trond Myklebust wrote:
>> @@ -373,21 +390,22 @@ static char *next_mnt(void **v, char *p)
>>  	FILE *f;
>>  	struct mntent *me;
>>  	size_t l = strlen(p);
>> +	char *mnt_dir = NULL;
>> +
>>  	if (*v == NULL) {
>>  		f = setmntent("/etc/mtab", "r");
>>  		*v = f;
>>  	} else
>>  		f = *v;
>> -	while ((me = getmntent(f)) != NULL && l > 1 &&
>> -	       (strncmp(me->mnt_dir, p, l) != 0 ||
>> -		me->mnt_dir[l] != '/'))
>> -		;
>> -	if (me == NULL) {
>> -		endmntent(f);
>> -		*v = NULL;
>> -		return NULL;
>> +	while ((me = getmntent(f)) != NULL && l > 1) {
>> +		mnt_dir = nfsd_path_strip_root(me->mnt_dir);
>> +
>> +		if (strncmp(mnt_dir, p, l) == 0 && mnt_dir[l] != '/')
>> +			return mnt_dir;
> 
> That should be "mnt_dir[l] == '/'", right?
Comment says
/* Iterate through /etc/mtab, finding mountpoints
 * at or below a given path
 */

So I don't think the actual '/' should returned, Trond?

steved.
> 
> --b.
> 
>>  	}
>> -	return me->mnt_dir;
>> +	endmntent(f);
>> +	*v = NULL;
>> +	return NULL;
>>  }
>>  
>>  /* same_path() check is two paths refer to the same directory.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 04/11] Add utilities for resolving nfsd paths and stat()ing them
  2019-05-31 15:52         ` [PATCH v3 04/11] Add utilities for resolving nfsd paths and stat()ing them J. Bruce Fields
@ 2019-06-03 14:21           ` Steve Dickson
  2019-06-03 16:32             ` Trond Myklebust
  0 siblings, 1 reply; 24+ messages in thread
From: Steve Dickson @ 2019-06-03 14:21 UTC (permalink / raw)
  To: J. Bruce Fields, Trond Myklebust; +Cc: linux-nfs



On 5/31/19 11:52 AM, J. Bruce Fields wrote:
> On Tue, May 28, 2019 at 04:31:15PM -0400, Trond Myklebust wrote:
>> +char *
>> +nfsd_path_strip_root(char *pathname)
>> +{
>> +	const char *dir = nfsd_path_nfsd_rootdir();
>> +	char *ret;
>> +
>> +	ret = strstr(pathname, dir);
>> +	if (!ret || ret != pathname)
>> +		return pathname;
> 
> Shouldn't we return NULL or an error or something here?  It seems a
> little strange not to care if the path began with root or not.  I guess
> I need to look at the caller....
Well pathname will never be NULL... It is returning what is passed in, 
but it might be nice to know about the memory failure.

steved.

> 
> --b.
> 
>> +	return pathname + strlen(dir);
>> +}
>> +
>> +char *
>> +nfsd_path_prepend_dir(const char *dir, const char *pathname)
>> +{
>> +	size_t len, dirlen;
>> +	char *ret;
>> +
>> +	dirlen = strlen(dir);
>> +	while (dirlen > 0 && dir[dirlen - 1] == '/')
>> +		dirlen--;
>> +	if (!dirlen)
>> +		return NULL;
>> +	len = dirlen + strlen(pathname) + 1;
>> +	ret = xmalloc(len + 1);
>> +	snprintf(ret, len, "%.*s/%s", (int)dirlen, dir, pathname);
>> +	return ret;
>> +}
>> +
>> +static void
>> +nfsd_setup_workqueue(void)
>> +{
>> +	const char *rootdir = nfsd_path_nfsd_rootdir();
>> +
>> +	if (!rootdir)
>> +		return;
>> +	nfsd_wq = xthread_workqueue_alloc();
>> +	if (!nfsd_wq)
>> +		return;
>> +	xthread_workqueue_chroot(nfsd_wq, rootdir);
>> +}
>> +
>> +void
>> +nfsd_path_init(void)
>> +{
>> +	nfsd_setup_workqueue();
>> +}
>> +
>> +struct nfsd_stat_data {
>> +	const char *pathname;
>> +	struct stat *statbuf;
>> +	int ret;
>> +	int err;
>> +};
>> +
>> +static void
>> +nfsd_statfunc(void *data)
>> +{
>> +	struct nfsd_stat_data *d = data;
>> +
>> +	d->ret = xstat(d->pathname, d->statbuf);
>> +	if (d->ret < 0)
>> +		d->err = errno;
>> +}
>> +
>> +static void
>> +nfsd_lstatfunc(void *data)
>> +{
>> +	struct nfsd_stat_data *d = data;
>> +
>> +	d->ret = xlstat(d->pathname, d->statbuf);
>> +	if (d->ret < 0)
>> +		d->err = errno;
>> +}
>> +
>> +static int
>> +nfsd_run_stat(struct xthread_workqueue *wq,
>> +		void (*func)(void *),
>> +		const char *pathname,
>> +		struct stat *statbuf)
>> +{
>> +	struct nfsd_stat_data data = {
>> +		pathname,
>> +		statbuf,
>> +		0,
>> +		0
>> +	};
>> +	xthread_work_run_sync(wq, func, &data);
>> +	if (data.ret < 0)
>> +		errno = data.err;
>> +	return data.ret;
>> +}
>> +
>> +int
>> +nfsd_path_stat(const char *pathname, struct stat *statbuf)
>> +{
>> +	if (!nfsd_wq)
>> +		return xstat(pathname, statbuf);
>> +	return nfsd_run_stat(nfsd_wq, nfsd_statfunc, pathname, statbuf);
>> +}
>> +
>> +int
>> +nfsd_path_lstat(const char *pathname, struct stat *statbuf)
>> +{
>> +	if (!nfsd_wq)
>> +		return xlstat(pathname, statbuf);
>> +	return nfsd_run_stat(nfsd_wq, nfsd_lstatfunc, pathname, statbuf);
>> +}
>> diff --git a/support/misc/xstat.c b/support/misc/xstat.c
>> new file mode 100644
>> index 000000000000..d092f73dfd65
>> --- /dev/null
>> +++ b/support/misc/xstat.c
>> @@ -0,0 +1,33 @@
>> +#include <sys/types.h>
>> +#include <fcntl.h>
>> +#include <sys/stat.h>
>> +#include <unistd.h>
>> +
>> +#include "config.h"
>> +#include "xstat.h"
>> +
>> +#ifdef HAVE_FSTATAT
>> +
>> +int xlstat(const char *pathname, struct stat *statbuf)
>> +{
>> +	return fstatat(AT_FDCWD, pathname, statbuf, AT_NO_AUTOMOUNT |
>> +			AT_SYMLINK_NOFOLLOW);
>> +}
>> +
>> +int xstat(const char *pathname, struct stat *statbuf)
>> +{
>> +	return fstatat(AT_FDCWD, pathname, statbuf, AT_NO_AUTOMOUNT);
>> +}
>> +
>> +#else
>> +
>> +int xlstat(const char *pathname, struct stat *statbuf)
>> +{
>> +	return lstat(pathname, statbuf);
>> +}
>> +
>> +int xstat(const char *pathname, struct stat *statbuf)
>> +{
>> +	return stat(pathname, statbuf);
>> +}
>> +#endif
>> -- 
>> 2.21.0

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 08/11] Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd
  2019-06-03 14:18                   ` Steve Dickson
@ 2019-06-03 16:30                     ` Trond Myklebust
  0 siblings, 0 replies; 24+ messages in thread
From: Trond Myklebust @ 2019-06-03 16:30 UTC (permalink / raw)
  To: bfields, SteveD; +Cc: linux-nfs

On Mon, 2019-06-03 at 10:18 -0400, Steve Dickson wrote:
> 
> On 5/31/19 12:02 PM, J. Bruce Fields wrote:
> > On Tue, May 28, 2019 at 04:31:19PM -0400, Trond Myklebust wrote:
> > > @@ -373,21 +390,22 @@ static char *next_mnt(void **v, char *p)
> > >  	FILE *f;
> > >  	struct mntent *me;
> > >  	size_t l = strlen(p);
> > > +	char *mnt_dir = NULL;
> > > +
> > >  	if (*v == NULL) {
> > >  		f = setmntent("/etc/mtab", "r");
> > >  		*v = f;
> > >  	} else
> > >  		f = *v;
> > > -	while ((me = getmntent(f)) != NULL && l > 1 &&
> > > -	       (strncmp(me->mnt_dir, p, l) != 0 ||
> > > -		me->mnt_dir[l] != '/'))
> > > -		;
> > > -	if (me == NULL) {
> > > -		endmntent(f);
> > > -		*v = NULL;
> > > -		return NULL;
> > > +	while ((me = getmntent(f)) != NULL && l > 1) {
> > > +		mnt_dir = nfsd_path_strip_root(me->mnt_dir);
> > > +
> > > +		if (strncmp(mnt_dir, p, l) == 0 && mnt_dir[l] != '/')
> > > +			return mnt_dir;
> > 
> > That should be "mnt_dir[l] == '/'", right?
> Comment says
> /* Iterate through /etc/mtab, finding mountpoints
>  * at or below a given path
>  */
> 
> So I don't think the actual '/' should returned, Trond?

Yep. You're both right. I've got an incremental patch to fix this.

-- 
Trond Myklebust
Linux NFS client maintainer, Hammerspace
trond.myklebust@hammerspace.com



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 04/11] Add utilities for resolving nfsd paths and stat()ing them
  2019-06-03 14:21           ` Steve Dickson
@ 2019-06-03 16:32             ` Trond Myklebust
  0 siblings, 0 replies; 24+ messages in thread
From: Trond Myklebust @ 2019-06-03 16:32 UTC (permalink / raw)
  To: bfields, SteveD; +Cc: linux-nfs

On Mon, 2019-06-03 at 10:21 -0400, Steve Dickson wrote:
> 
> On 5/31/19 11:52 AM, J. Bruce Fields wrote:
> > On Tue, May 28, 2019 at 04:31:15PM -0400, Trond Myklebust wrote:
> > > +char *
> > > +nfsd_path_strip_root(char *pathname)
> > > +{
> > > +	const char *dir = nfsd_path_nfsd_rootdir();
> > > +	char *ret;
> > > +
> > > +	ret = strstr(pathname, dir);
> > > +	if (!ret || ret != pathname)
> > > +		return pathname;
> > 
> > Shouldn't we return NULL or an error or something here?  It seems a
> > little strange not to care if the path began with root or not.  I
> > guess
> > I need to look at the caller....
> Well pathname will never be NULL... It is returning what is passed
> in, 
> but it might be nice to know about the memory failure.
> 

Either way, I figure we also want to canonicalise 'dir' before we apply
it, just in case people have amused themselves by composing rootdir
values of the form '/foo/./bar/./../bar/'.
Another patch forthcoming for this.

-- 
Trond Myklebust
Linux NFS client maintainer, Hammerspace
trond.myklebust@hammerspace.com



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 00/11] Add the "[exports] rootdir" option to nfs.conf
  2019-05-28 20:31 [PATCH v3 00/11] Add the "[exports] rootdir" option to nfs.conf Trond Myklebust
  2019-05-28 20:31 ` [PATCH v3 01/11] mountd: Ensure we don't share cache file descriptors among processes Trond Myklebust
@ 2019-06-10 13:53 ` Steve Dickson
  1 sibling, 0 replies; 24+ messages in thread
From: Steve Dickson @ 2019-06-10 13:53 UTC (permalink / raw)
  To: Trond Myklebust; +Cc: linux-nfs



On 5/28/19 4:31 PM, Trond Myklebust wrote:
> The following patchset adds support for the "rootdir" configuration
> option for nfsd in the "[exports]" section in /etc/nfs.conf.
> 
> If a user sets this option to a valid directory path, then nfsd will
> act as if it is confined to a chroot jail based on that directory.
> All paths in /etc/exports and the exportfs utility are then resolved
> relative to that directory.
> 
> Trond Myklebust (11):
>   mountd: Ensure we don't share cache file descriptors among processes.
>   Add a simple workqueue mechanism
>   Allow callers to check mountpoint status using a custom lstat function
>   Add utilities for resolving nfsd paths and stat()ing them
>   Use xstat() with no synchronisation if available
>   Add helpers to read/write to a file through the chrooted thread
>   Add a helper to return the real path given an export entry
>   Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd
>   Add support for the "[exports] rootdir" nfs.conf option to exportfs
>   Add a helper for resolving symlinked nfsd paths via realpath()
>   Fix up symlinked mount path resolution when "[exports] rootdir" is set
> 
>  aclocal/libpthread.m4       |  13 +-
>  configure.ac                |   6 +-
>  nfs.conf                    |   3 +
>  support/export/export.c     |  24 +++
>  support/include/Makefile.am |   3 +
>  support/include/exportfs.h  |   1 +
>  support/include/misc.h      |   7 +-
>  support/include/nfsd_path.h |  21 +++
>  support/include/nfslib.h    |   1 +
>  support/include/workqueue.h |  18 +++
>  support/include/xstat.h     |  11 ++
>  support/misc/Makefile.am    |   3 +-
>  support/misc/mountpoint.c   |   8 +-
>  support/misc/nfsd_path.c    | 289 ++++++++++++++++++++++++++++++++++++
>  support/misc/workqueue.c    | 228 ++++++++++++++++++++++++++++
>  support/misc/xstat.c        | 105 +++++++++++++
>  support/nfs/exports.c       |   4 +
>  systemd/nfs.conf.man        |  20 ++-
>  utils/exportfs/Makefile.am  |   2 +-
>  utils/exportfs/exportfs.c   |  11 +-
>  utils/mountd/Makefile.am    |   3 +-
>  utils/mountd/cache.c        |  63 +++++---
>  utils/mountd/mountd.c       |  24 +--
>  23 files changed, 819 insertions(+), 49 deletions(-)
>  create mode 100644 support/include/nfsd_path.h
>  create mode 100644 support/include/workqueue.h
>  create mode 100644 support/include/xstat.h
>  create mode 100644 support/misc/nfsd_path.c
>  create mode 100644 support/misc/workqueue.c
>  create mode 100644 support/misc/xstat.c
> 
Committed!

steved.

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2019-06-10 13:53 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-28 20:31 [PATCH v3 00/11] Add the "[exports] rootdir" option to nfs.conf Trond Myklebust
2019-05-28 20:31 ` [PATCH v3 01/11] mountd: Ensure we don't share cache file descriptors among processes Trond Myklebust
2019-05-28 20:31   ` [PATCH v3 02/11] Add a simple workqueue mechanism Trond Myklebust
2019-05-28 20:31     ` [PATCH v3 03/11] Allow callers to check mountpoint status using a custom lstat function Trond Myklebust
2019-05-28 20:31       ` [PATCH v3 04/11] Add utilities for resolving nfsd paths and stat()ing them Trond Myklebust
2019-05-28 20:31         ` [PATCH v3 05/11] Use xstat() with no synchronisation if available Trond Myklebust
2019-05-28 20:31           ` [PATCH v3 06/11] Add helpers to read/write to a file through the chrooted thread Trond Myklebust
2019-05-28 20:31             ` [PATCH v3 07/11] Add a helper to return the real path given an export entry Trond Myklebust
2019-05-28 20:31               ` [PATCH v3 08/11] Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd Trond Myklebust
2019-05-28 20:31                 ` [PATCH v3 09/11] Add support for the "[exports] rootdir" nfs.conf option to exportfs Trond Myklebust
2019-05-28 20:31                   ` [PATCH v3 10/11] Add a helper for resolving symlinked nfsd paths via realpath() Trond Myklebust
2019-05-28 20:31                     ` [PATCH v3 11/11] Fix up symlinked mount path resolution when "[exports] rootdir" is set Trond Myklebust
2019-05-31 16:02                 ` [PATCH v3 08/11] Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd J. Bruce Fields
2019-06-03 14:18                   ` Steve Dickson
2019-06-03 16:30                     ` Trond Myklebust
2019-05-29 14:38               ` [PATCH v3 07/11] Add a helper to return the real path given an export entry Steve Dickson
2019-05-29 14:55                 ` Trond Myklebust
2019-05-29 16:03                   ` Steve Dickson
2019-05-29 16:12                     ` Trond Myklebust
2019-05-29 17:17                       ` Steve Dickson
2019-05-31 15:52         ` [PATCH v3 04/11] Add utilities for resolving nfsd paths and stat()ing them J. Bruce Fields
2019-06-03 14:21           ` Steve Dickson
2019-06-03 16:32             ` Trond Myklebust
2019-06-10 13:53 ` [PATCH v3 00/11] Add the "[exports] rootdir" option to nfs.conf Steve Dickson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.