diff --git a/nfs-utils-2.5.4-Fix-NFSv4-export-of-tmpfs-filesystems.patch b/nfs-utils-2.5.4-Fix-NFSv4-export-of-tmpfs-filesystems.patch new file mode 100644 index 0000000000000000000000000000000000000000..ffa206c59a01b2e391c6e93eb856f704cc05bd8d --- /dev/null +++ b/nfs-utils-2.5.4-Fix-NFSv4-export-of-tmpfs-filesystems.patch @@ -0,0 +1,223 @@ +From 49235a6f1290626333ab4b2af915805f71c60081 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Sat, 22 May 2021 11:03:31 -0400 +Subject: [PATCH] Fix NFSv4 export of tmpfs filesystems + +Some filesystems cannot be exported without an fsid or uuid. +tmpfs is the main example. + +When mountd (or exportd) creates nfsv4 pseudo-root exports for the path +leading down to an export point it exports each directory without any +fsid or uuid. If one of these directories is on tmpfs, that will fail. + +The net result is that exporting a subdirectory of a tmpfs filesystem +will not work over NFSv4 as the parents within the filesystem cannot be +exported. It will either fail, or fall-back to NFSv3 (depending on the +version of the mount.nfs program). + +To fix this we need to provide an fsid or uuid for these pseudo-root +exports. This patch does that by creating an RFC-4122 V5 compatible +UUID based on an arbitrary seed and the path to the export. + +To check if an export needs a uuid, text_export() is moved from exportfs +to libexport.a, modified slightly and renamed to export_test(). + +backport note: +Currently there isn't exportd, attention. + +Reported-by: Petr Vorel +Reviewed-by: Petr Vorel +Tested-by: Petr Vorel +Signed-off-by: NeilBrown +Signed-off-by: Steve Dickson +Signed-off-by: Ferry Meng +--- + support/export/cache.c | 3 ++- + support/export/export.c | 29 +++++++++++++++++++++++++++++ + support/export/v4root.c | 21 +++++++++++++++++++++ + support/include/exportfs.h | 1 + + utils/exportfs/exportfs.c | 33 +++------------------------------ + utils/mountd/Makefile.am | 2 +- + 6 files changed, 57 insertions(+), 32 deletions(-) + +diff --git a/support/export/cache.c b/support/export/cache.c +index 98d5082..b77b608 100644 +--- a/support/export/cache.c ++++ b/support/export/cache.c +@@ -899,7 +899,8 @@ static int dump_to_cache(int f, char *buf, int buflen, char *domain, + write_secinfo(&bp, &blen, exp, flag_mask); + if (exp->e_uuid == NULL || different_fs) { + char u[16]; +- if (uuid_by_path(path, 0, 16, u)) { ++ if ((exp->e_flags & flag_mask & NFSEXP_FSID) == 0 && ++ uuid_by_path(path, 0, 16, u)) { + qword_add(&bp, &blen, "uuid"); + qword_addhex(&bp, &blen, u, 16); + } +diff --git a/support/export/export.c b/support/export/export.c +index fbe68e8..0c4b617 100644 +--- a/support/export/export.c ++++ b/support/export/export.c +@@ -10,9 +10,11 @@ + #include + #endif + ++#include + #include + #include + #include ++#include + #include + #include + #include +@@ -388,3 +390,30 @@ export_hash(char *str) + + return num % HASH_TABLE_SIZE; + } ++ ++int export_test(struct exportent *eep, int with_fsid) ++{ ++ char *path = eep->e_path; ++ int flags = eep->e_flags | (with_fsid ? NFSEXP_FSID : 0); ++ /* beside max path, buf size should take protocol str into account */ ++ char buf[NFS_MAXPATHLEN+1+64] = { 0 }; ++ char *bp = buf; ++ int len = sizeof(buf); ++ int fd, n; ++ ++ n = snprintf(buf, len, "-test-client- "); ++ bp += n; ++ len -= n; ++ qword_add(&bp, &len, path); ++ if (len < 1) ++ return 0; ++ snprintf(bp, len, " 3 %d 65534 65534 0\n", flags); ++ fd = open("/proc/net/rpc/nfsd.export/channel", O_WRONLY); ++ if (fd < 0) ++ return 0; ++ n = write(fd, buf, strlen(buf)); ++ close(fd); ++ if (n < 0) ++ return 0; ++ return 1; ++} +diff --git a/support/export/v4root.c b/support/export/v4root.c +index 3654bd7..fff7f54 100644 +--- a/support/export/v4root.c ++++ b/support/export/v4root.c +@@ -20,6 +20,7 @@ + + #include + #include ++#include + + #include "xlog.h" + #include "exportfs.h" +@@ -89,6 +90,26 @@ v4root_create(char *path, nfs_export *export) + strncpy(eep.e_path, path, sizeof(eep.e_path)-1); + if (strcmp(path, "/") != 0) + eep.e_flags &= ~NFSEXP_FSID; ++ ++ if (strcmp(path, "/") != 0 && ++ !export_test(&eep, 0)) { ++ /* Need a uuid - base it on path using a fixed seed that ++ * was generated randomly. ++ */ ++ const char seed_s[] = "39c6b5c1-3f24-4f4e-977c-7fe6546b8a25"; ++ uuid_t seed, uuid; ++ char uuid_s[UUID_STR_LEN]; ++ unsigned int i, j; ++ ++ uuid_parse(seed_s, seed); ++ uuid_generate_sha1(uuid, seed, path, strlen(path)); ++ uuid_unparse_upper(uuid, uuid_s); ++ /* strip hyhens */ ++ for (i = j = 0; uuid_s[i]; i++) ++ if (uuid_s[i] != '-') ++ uuid_s[j++] = uuid_s[i]; ++ eep.e_uuid = uuid_s; ++ } + set_pseudofs_security(&eep); + exp = export_create(&eep, 0); + if (exp == NULL) +diff --git a/support/include/exportfs.h b/support/include/exportfs.h +index bfae195..301486b 100644 +--- a/support/include/exportfs.h ++++ b/support/include/exportfs.h +@@ -172,5 +172,6 @@ struct export_features { + + struct export_features *get_export_features(void); + void fix_pseudoflavor_flags(struct exportent *ep); ++int export_test(struct exportent *eep, int with_fsid); + + #endif /* EXPORTFS_H */ +diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c +index c162c03..50fbe6c 100644 +--- a/utils/exportfs/exportfs.c ++++ b/utils/exportfs/exportfs.c +@@ -485,33 +485,6 @@ static int can_test(void) + return 1; + } + +-static int test_export(nfs_export *exp, int with_fsid) +-{ +- char *path = exp->m_export.e_path; +- int flags = exp->m_export.e_flags | (with_fsid ? NFSEXP_FSID : 0); +- /* beside max path, buf size should take protocol str into account */ +- char buf[NFS_MAXPATHLEN+1+64] = { 0 }; +- char *bp = buf; +- int len = sizeof(buf); +- int fd, n; +- +- n = snprintf(buf, len, "-test-client- "); +- bp += n; +- len -= n; +- qword_add(&bp, &len, path); +- if (len < 1) +- return 0; +- snprintf(bp, len, " 3 %d 65534 65534 0\n", flags); +- fd = open("/proc/net/rpc/nfsd.export/channel", O_WRONLY); +- if (fd < 0) +- return 0; +- n = write(fd, buf, strlen(buf)); +- close(fd); +- if (n < 0) +- return 0; +- return 1; +-} +- + static void + validate_export(nfs_export *exp) + { +@@ -543,12 +516,12 @@ validate_export(nfs_export *exp) + + if ((exp->m_export.e_flags & NFSEXP_FSID) || exp->m_export.e_uuid || + fs_has_fsid) { +- if ( !test_export(exp, 1)) { ++ if ( !export_test(&exp->m_export, 1)) { + xlog(L_ERROR, "%s does not support NFS export", path); + return; + } +- } else if ( !test_export(exp, 0)) { +- if (test_export(exp, 1)) ++ } else if ( !export_test(&exp->m_export, 0)) { ++ if (export_test(&exp->m_export, 1)) + xlog(L_ERROR, "%s requires fsid= for NFS export", path); + else + xlog(L_ERROR, "%s does not support NFS export", path); +diff --git a/utils/mountd/Makefile.am b/utils/mountd/Makefile.am +index c41f06d..dab9f97 100644 +--- a/utils/mountd/Makefile.am ++++ b/utils/mountd/Makefile.am +@@ -19,7 +19,7 @@ mountd_LDADD = ../../support/export/libexport.a \ + ../../support/nfs/libnfs.la \ + ../../support/misc/libmisc.a \ + $(OPTLIBS) \ +- $(LIBBSD) $(LIBWRAP) $(LIBNSL) $(LIBBLKID) $(LIBTIRPC) ++ $(LIBBSD) $(LIBWRAP) $(LIBNSL) $(LIBBLKID) -luuid $(LIBTIRPC) + mountd_CPPFLAGS = $(AM_CPPFLAGS) $(CPPFLAGS) \ + -I$(top_builddir)/support/include \ + -I$(top_srcdir)/support/export +-- +2.39.3 + diff --git a/nfs-utils-2.5.4-Move-declaration-of-etab-and-rmtab-into-libraries.patch b/nfs-utils-2.5.4-Move-declaration-of-etab-and-rmtab-into-libraries.patch new file mode 100644 index 0000000000000000000000000000000000000000..69bfa6ca98d114ebf611e79ba804054592699c2b --- /dev/null +++ b/nfs-utils-2.5.4-Move-declaration-of-etab-and-rmtab-into-libraries.patch @@ -0,0 +1,138 @@ +From 930f71a4b69c0342c2afdcbdcdad997c92be8167 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Sat, 22 May 2021 11:12:11 -0400 +Subject: [PATCH 3/3] Move declaration of etab and rmtab into libraries + +There are two global "struct stat_paths" structures: etab and rmtab. +They are currently needed by some library code so any program which is +linked with that library code needs to declare the structures even if it +doesn't use the functionality. This is clumsy and error-prone. + +Instead: have the library declare the structure and put the definition +in a header file. Now programs only need to know about these structures +if they use the functionality. + +'rmtab' is now declared in libnfs.a (rmtab.c). 'etab' is declared in +export.a (xtab.c). + +Reviewed-by: Petr Vorel +Signed-off-by: NeilBrown +Signed-off-by: Steve Dickson +Signed-off-by: Ferry Meng +--- + support/export/auth.c | 2 -- + support/export/xtab.c | 2 +- + support/include/exportfs.h | 1 + + support/include/nfslib.h | 1 + + support/nfs/rmtab.c | 2 +- + utils/exportfs/exportfs.c | 2 -- + utils/mountd/mountd.c | 3 --- + utils/mountd/rmtab.c | 2 -- + 8 files changed, 4 insertions(+), 11 deletions(-) + +diff --git a/support/export/auth.c b/support/export/auth.c +index 73ad6f7..318d165 100644 +--- a/support/export/auth.c ++++ b/support/export/auth.c +@@ -41,8 +41,6 @@ static nfs_client my_client; + + extern int use_ipaddr; + +-extern struct state_paths etab; +- + /* + void + auth_init(void) +diff --git a/support/export/xtab.c b/support/export/xtab.c +index 1e1d679..4ca7e91 100644 +--- a/support/export/xtab.c ++++ b/support/export/xtab.c +@@ -27,7 +27,7 @@ + #include "misc.h" + + static char state_base_dirname[PATH_MAX] = NFS_STATEDIR; +-extern struct state_paths etab; ++struct state_paths etab; + + int v4root_needed; + static void cond_rename(char *newfile, char *oldfile); +diff --git a/support/include/exportfs.h b/support/include/exportfs.h +index 301486b..400805d 100644 +--- a/support/include/exportfs.h ++++ b/support/include/exportfs.h +@@ -145,6 +145,7 @@ nfs_export * export_create(struct exportent *, int canonical); + void exportent_release(struct exportent *); + void export_freeall(void); + ++extern struct state_paths etab; + int xtab_export_read(void); + int xtab_export_write(void); + +diff --git a/support/include/nfslib.h b/support/include/nfslib.h +index ab8b2bf..90a27d7 100644 +--- a/support/include/nfslib.h ++++ b/support/include/nfslib.h +@@ -104,6 +104,7 @@ void dupexportent(struct exportent *dst, + struct exportent *src); + int updateexportent(struct exportent *eep, char *options); + ++extern struct state_paths rmtab; + int setrmtabent(char *type); + struct rmtabent * getrmtabent(int log, long *pos); + void putrmtabent(struct rmtabent *xep, long *pos); +diff --git a/support/nfs/rmtab.c b/support/nfs/rmtab.c +index 2ecb2cc..d30e625 100644 +--- a/support/nfs/rmtab.c ++++ b/support/nfs/rmtab.c +@@ -33,7 +33,7 @@ + + static FILE *rmfp = NULL; + +-extern struct state_paths rmtab; ++struct state_paths rmtab; + + int + setrmtabent(char *type) +diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c +index dd19776..2957f41 100644 +--- a/utils/exportfs/exportfs.c ++++ b/utils/exportfs/exportfs.c +@@ -51,8 +51,6 @@ static void release_lockfile(void); + static const char *lockfile = EXP_LOCKFILE; + static int _lockfd = -1; + +-struct state_paths etab; +- + /* + * If we aren't careful, changes made by exportfs can be lost + * when multiple exports process run at once: +diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c +index 2b34237..93d9248 100644 +--- a/utils/mountd/mountd.c ++++ b/utils/mountd/mountd.c +@@ -42,9 +42,6 @@ int reverse_resolve = 0; + int manage_gids; + int use_ipaddr = -1; + +-struct state_paths etab; +-struct state_paths rmtab; +- + /* PRC: a high-availability callout program can be specified with -H + * When this is done, the program will receive callouts whenever clients + * send mount or unmount requests -- the callout is not needed for 2.6 kernel */ +diff --git a/utils/mountd/rmtab.c b/utils/mountd/rmtab.c +index 3ae0dbb..fdaafbc 100644 +--- a/utils/mountd/rmtab.c ++++ b/utils/mountd/rmtab.c +@@ -28,8 +28,6 @@ + + extern int reverse_resolve; + +-extern struct state_paths rmtab; +- + /* If new path is a link do not destroy it but place the + * file where the link points. + */ +-- +2.39.3 + diff --git a/nfs-utils-2.5.4-Remove-force-arg-from-cache_flush.patch b/nfs-utils-2.5.4-Remove-force-arg-from-cache_flush.patch new file mode 100644 index 0000000000000000000000000000000000000000..ebfa5ad5a2c395fba7ee153bfdb47bd82beaa84b --- /dev/null +++ b/nfs-utils-2.5.4-Remove-force-arg-from-cache_flush.patch @@ -0,0 +1,136 @@ +From a0efbb254f6f8703bc4bcaf6b49d49e1a3e7d90f Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Sat, 22 May 2021 11:06:13 -0400 +Subject: [PATCH] Remove 'force' arg from cache_flush() + +Since v4.17 the timestamp written to 'flush' is ignored, +so there isn't much point choosing too precisely. + +For kernels since v4.3-rc3-13-g778620364ef5 it is safe +to write 1 second beyond the current time. + +For earlier kernels, nothing is really safe (even the current +behaviour), but writing one second beyond the current time isn't too bad +in the unlikely case the people use a new nfs-utils on a 5 year old +kernel. + +This remove a dependency for libnfs.a on 'etab' being declare, +so svcgssd no longer needs to declare it. + +Reviewed-by: Petr Vorel +Signed-off-by: NeilBrown +Signed-off-by: Steve Dickson +Signed-off-by: Ferry Meng +--- + support/export/auth.c | 2 +- + support/include/nfslib.h | 2 +- + support/nfs/cacheio.c | 17 ++++++++--------- + utils/exportfs/exportfs.c | 4 ++-- + utils/gssd/svcgssd.c | 1 - + 5 files changed, 12 insertions(+), 14 deletions(-) + +diff --git a/support/export/auth.c b/support/export/auth.c +index 73ad6f7..c5e1b5c 100644 +--- a/support/export/auth.c ++++ b/support/export/auth.c +@@ -80,7 +80,7 @@ check_useipaddr(void) + use_ipaddr = 0; + + if (use_ipaddr != old_use_ipaddr) +- cache_flush(1); ++ cache_flush(); + } + + unsigned int +diff --git a/support/include/nfslib.h b/support/include/nfslib.h +index ab8b2bf..bbe8886 100644 +--- a/support/include/nfslib.h ++++ b/support/include/nfslib.h +@@ -130,7 +130,7 @@ int wildmat(char *text, char *pattern); + + int qword_get(char **bpp, char *dest, int bufsize); + int qword_get_int(char **bpp, int *anint); +-void cache_flush(int force); ++void cache_flush(void); + void qword_add(char **bpp, int *lp, char *str); + void qword_addhex(char **bpp, int *lp, char *buf, int blen); + void qword_addint(char **bpp, int *lp, int n); +diff --git a/support/nfs/cacheio.c b/support/nfs/cacheio.c +index 7c4cf37..c0f19cd 100644 +--- a/support/nfs/cacheio.c ++++ b/support/nfs/cacheio.c +@@ -31,8 +31,6 @@ + #include + #include + +-extern struct state_paths etab; +- + void qword_add(char **bpp, int *lp, char *str) + { + char *bp = *bpp; +@@ -212,7 +210,7 @@ int qword_get_uint(char **bpp, unsigned int *anint) + */ + + void +-cache_flush(int force) ++cache_flush(void) + { + struct stat stb; + int c; +@@ -233,12 +231,13 @@ cache_flush(int force) + NULL + }; + now = time(0); +- if (force || +- stat(etab.statefn, &stb) != 0 || +- stb.st_mtime > now) +- stb.st_mtime = time(0); +- +- sprintf(stime, "%ld\n", stb.st_mtime); ++ ++ /* Since v4.16-rc2-3-g3b68e6ee3cbd the timestamp written is ignored. ++ * It is safest always to flush caches if there is any doubt. ++ * For earlier kernels, writing the next second from now is ++ * the best we can do. ++ */ ++ sprintf(stime, "%ld\n", now+1); + for (c=0; cachelist[c]; c++) { + int fd; + sprintf(path, "/proc/net/rpc/%s/flush", cachelist[c]); +diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c +index 50fbe6c..5a2f6ff 100644 +--- a/utils/exportfs/exportfs.c ++++ b/utils/exportfs/exportfs.c +@@ -170,7 +170,7 @@ main(int argc, char **argv) + return 1; + if (optind == argc && ! f_all) { + if (force_flush) { +- cache_flush(1); ++ cache_flush(); + free_state_path_names(&etab); + return 0; + } else { +@@ -216,7 +216,7 @@ main(int argc, char **argv) + unexportfs(argv[i], f_verbose); + } + xtab_export_write(); +- cache_flush(force_flush); ++ cache_flush(); + free_state_path_names(&etab); + + return export_errno; +diff --git a/utils/gssd/svcgssd.c b/utils/gssd/svcgssd.c +index ec49b61..d728eaf 100644 +--- a/utils/gssd/svcgssd.c ++++ b/utils/gssd/svcgssd.c +@@ -63,7 +63,6 @@ + #include "err_util.h" + #include "conffile.h" + +-struct state_paths etab; + + static void + sig_die(int signal) +-- +2.39.3 + diff --git a/nfs-utils.spec b/nfs-utils.spec index fcb7425870f60425855ec229f2bd06d26650b65d..521e6f3dd06b210f0c93fd454de35c75aa16d4b0 100644 --- a/nfs-utils.spec +++ b/nfs-utils.spec @@ -1,4 +1,4 @@ -%define anolis_release .0.1 +%define anolis_release .0.2 Summary: NFS utilities and supporting clients and daemons for the kernel NFS server Name: nfs-utils URL: http://linux-nfs.org/ @@ -116,6 +116,10 @@ Patch102: nfs-utils-2.3.3-idmap-errmsg.patch Patch103: nfs-utils-2.3.1-systemd-gssproxy-restart.patch Patch104: nfs-utils-2.3.1-systemd-svcgssd-removed.patch +Patch105: nfs-utils-2.5.4-Fix-NFSv4-export-of-tmpfs-filesystems.patch +Patch106: nfs-utils-2.5.4-Remove-force-arg-from-cache_flush.patch +Patch107: nfs-utils-2.5.4-Move-declaration-of-etab-and-rmtab-into-libraries.patch + # Begin: Anolis customized patches Patch1001: 1001-nfs-utils-gcc10.patch # backport patch from upstream @@ -395,6 +399,10 @@ fi %{_libdir}/libnfsidmap.so %changelog +* Thu Jun 29 2023 Ferry Meng 2.3.3-59.0.2 +- Fix NFSv4 export of tmpfs filesystems +- move estab/rmtab into libraries for compiling + * Thu May 25 2023 Weitao Zhou 2.3.3-59.0.1 - use extern in header files when declaring global variables for compatible gcc10 build - allow compilation to succeed with -fno-common