2019-05-28 20:38:20

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH v3 07/11] Add a helper to return the real path given an export entry

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 <[email protected]>
---
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


2019-05-28 20:38:21

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH v3 08/11] Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd

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 <[email protected]>
---
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

2019-05-29 14:39:18

by Steve Dickson

[permalink] [raw]
Subject: Re: [PATCH v3 07/11] Add a helper to return the real path given an export entry

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 <[email protected]>
> ---
> 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.

2019-05-29 14:56:23

by Trond Myklebust

[permalink] [raw]
Subject: Re: [PATCH v3 07/11] Add a helper to return the real path given an export entry

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 <[email protected]>
> > ---
> > 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
[email protected]


2019-05-29 16:03:51

by Steve Dickson

[permalink] [raw]
Subject: Re: [PATCH v3 07/11] Add a helper to return the real path given an export entry



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 <[email protected]>
>>> ---
>>> 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.

2019-05-29 16:14:47

by Trond Myklebust

[permalink] [raw]
Subject: Re: [PATCH v3 07/11] Add a helper to return the real path given an export entry

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 <[email protected]
> > > > >
> > > > ---
> > > > 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
[email protected]


2019-05-29 17:17:55

by Steve Dickson

[permalink] [raw]
Subject: Re: [PATCH v3 07/11] Add a helper to return the real path given an export entry

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.

2019-05-31 16:05:33

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH v3 08/11] Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd

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.

2019-06-03 14:22:04

by Steve Dickson

[permalink] [raw]
Subject: Re: [PATCH v3 08/11] Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd



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.

2019-06-03 17:48:08

by Trond Myklebust

[permalink] [raw]
Subject: Re: [PATCH v3 08/11] Add support for the "[exports] rootdir" nfs.conf option to rpc.mountd

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
[email protected]