summaryrefslogtreecommitdiffstats
path: root/utils/mountd
diff options
context:
space:
mode:
authorSteve Dickson <steved@redhat.com>2009-12-01 07:16:13 -0500
committerSteve Dickson <steved@redhat.com>2010-01-13 15:39:14 -0500
commit3b777b084a438f55482c8bf7508903ff4c30e1db (patch)
tree579f61ea0d057e7f4a579d5d34b3168d6fb80659 /utils/mountd
parent7f39d93b2cac65467999375e4a09bc5debb730e6 (diff)
downloadnfs-utils-3b777b084a438f55482c8bf7508903ff4c30e1db.tar.gz
nfs-utils-3b777b084a438f55482c8bf7508903ff4c30e1db.tar.xz
nfs-utils-3b777b084a438f55482c8bf7508903ff4c30e1db.zip
exports: NFSv4 pseudoroot support routines
Create v4root exports for each directory that is a parent of an explicit export. Give each the minimal security required to traverse to any of its children. Signed-off-by: Steve Dickson <steved@redhat.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'utils/mountd')
-rw-r--r--utils/mountd/Makefile.am2
-rw-r--r--utils/mountd/v4root.c180
2 files changed, 181 insertions, 1 deletions
diff --git a/utils/mountd/Makefile.am b/utils/mountd/Makefile.am
index 1e76cf8..eba81fc 100644
--- a/utils/mountd/Makefile.am
+++ b/utils/mountd/Makefile.am
@@ -8,7 +8,7 @@ KPREFIX = @kprefix@
sbin_PROGRAMS = mountd
mountd_SOURCES = mountd.c mount_dispatch.c auth.c rmtab.c cache.c \
- svc_run.c fsloc.c mountd.h
+ svc_run.c fsloc.c v4root.c mountd.h
mountd_LDADD = ../../support/export/libexport.a \
../../support/nfs/libnfs.a \
../../support/misc/libmisc.a \
diff --git a/utils/mountd/v4root.c b/utils/mountd/v4root.c
new file mode 100644
index 0000000..d890181
--- /dev/null
+++ b/utils/mountd/v4root.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2009 Red Hat <nfs@redhat.com>
+ *
+ * support/export/v4root.c
+ *
+ * Routines used to support NFSv4 pseudo roots
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/queue.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "xlog.h"
+#include "exportfs.h"
+#include "nfslib.h"
+#include "misc.h"
+#include "v4root.h"
+
+int v4root_needed;
+
+static nfs_export pseudo_root = {
+ .m_next = NULL,
+ .m_client = NULL,
+ .m_export = {
+ .e_hostname = "*",
+ .e_path = "/",
+ .e_flags = NFSEXP_READONLY | NFSEXP_ROOTSQUASH
+ | NFSEXP_NOSUBTREECHECK | NFSEXP_FSID
+ | NFSEXP_V4ROOT,
+ .e_anonuid = 65534,
+ .e_anongid = 65534,
+ .e_squids = NULL,
+ .e_nsquids = 0,
+ .e_sqgids = NULL,
+ .e_nsqgids = 0,
+ .e_fsid = 0,
+ .e_mountpoint = NULL,
+ },
+ .m_exported = 0,
+ .m_xtabent = 1,
+ .m_mayexport = 1,
+ .m_changed = 0,
+ .m_warned = 0,
+};
+
+void set_pseudofs_security(struct exportent *pseudo, struct exportent *source)
+{
+ struct sec_entry *se;
+ int i;
+
+ if (source->e_flags & NFSEXP_INSECURE_PORT)
+ pseudo->e_flags |= NFSEXP_INSECURE_PORT;
+ for (se = source->e_secinfo; se->flav; se++) {
+ struct sec_entry *new;
+
+ i = secinfo_addflavor(se->flav, pseudo);
+ new = &pseudo->e_secinfo[i];
+
+ if (se->flags & NFSEXP_INSECURE_PORT)
+ new->flags |= NFSEXP_INSECURE_PORT;
+ }
+}
+
+/*
+ * Create a pseudo export
+ */
+static struct exportent *
+v4root_create(char *path, nfs_export *export)
+{
+ nfs_export *exp;
+ struct exportent eep;
+ struct exportent *curexp = &export->m_export;
+
+ dupexportent(&eep, &pseudo_root.m_export);
+ eep.e_hostname = strdup(curexp->e_hostname);
+ strncpy(eep.e_path, path, sizeof(eep.e_path));
+ if (strcmp(path, "/") != 0)
+ eep.e_flags &= ~NFSEXP_FSID;
+ set_pseudofs_security(&eep, curexp);
+ exp = export_create(&eep, 0);
+ if (exp == NULL)
+ return NULL;
+ xlog(D_CALL, "v4root_create: path '%s'", exp->m_export.e_path);
+ return &exp->m_export;
+}
+
+/*
+ * Make sure the kernel has pseudo root support.
+ */
+static int
+v4root_support(void)
+{
+ struct export_features *ef;
+ static int warned = 0;
+
+ ef = get_export_features();
+
+ if (ef->flags & NFSEXP_V4ROOT)
+ return 1;
+ if (!warned) {
+ xlog(L_WARNING, "Kernel does not have pseudo root support.");
+ xlog(L_WARNING, "NFS v4 mounts will be disabled unless fsid=0");
+ xlog(L_WARNING, "is specfied in /etc/exports file.");
+ warned++;
+ }
+ return 0;
+}
+
+int pseudofs_update(char *hostname, char *path, nfs_export *source)
+{
+ nfs_export *exp;
+
+ exp = export_lookup(hostname, path, 0);
+ if (exp && !(exp->m_export.e_flags & NFSEXP_V4ROOT))
+ return 0;
+ if (!exp) {
+ if (v4root_create(path, source) == NULL) {
+ xlog(L_WARNING, "v4root_set: Unable to create "
+ "pseudo export for '%s'", path);
+ return -ENOMEM;
+ }
+ return 0;
+ }
+ /* Update an existing V4ROOT export: */
+ set_pseudofs_security(&exp->m_export, &source->m_export);
+ return 0;
+}
+
+/*
+ * Create pseudo exports by running through the real export
+ * looking at the components of the path that make up the export.
+ * Those path components, if not exported, will become pseudo
+ * exports allowing them to be found when the kernel does an upcall
+ * looking for components of the v4 mount.
+ */
+void
+v4root_set()
+{
+ nfs_export *exp, *nxt;
+ int i;
+ char *path, *ptr;
+ char *hostname;
+
+ if (!v4root_needed)
+ return;
+ if (!v4root_support())
+ return;
+
+ for (i = 0; i < MCL_MAXTYPES; i++) {
+ for (exp = exportlist[i].p_head; exp; exp = nxt) {
+ nxt = exp->m_next;
+ hostname = exp->m_export.e_hostname;
+
+ path = strdup(exp->m_export.e_path);
+ for (ptr = path + 1; ptr; ptr = strchr(ptr, '/')) {
+ int ret;
+ char saved;
+
+ saved = *ptr;
+ *ptr = '\0';
+ ret = pseudofs_update(hostname, path, exp);
+ /* XXX: error handling */
+ *ptr = saved;
+ ptr++;
+ }
+ free(path);
+ }
+ }
+}