Browse Source

nfs-util package update

Signed-off-by: basebuilder_pel7ppc64bebuilder0 <basebuilder@powerel.org>
master
basebuilder_pel7ppc64bebuilder0 6 years ago
parent
commit
3e4d6d9c9d
  1. 7
      SOURCES/24-nfs-server.conf
  2. 9
      SOURCES/id_resolver.conf
  3. 22
      SOURCES/lockd.conf
  4. 12
      SOURCES/nfs-utils-1.2.1-exp-subtree-warn-off.patch
  5. 58
      SOURCES/nfs-utils-1.2.1-statdpath-man.patch
  6. 21
      SOURCES/nfs-utils-1.2.3-sm-notify-res_init.patch
  7. 12
      SOURCES/nfs-utils-1.2.5-idmap-errmsg.patch
  8. 94
      SOURCES/nfs-utils-1.2.9-exportfs-badentries.patch
  9. 35
      SOURCES/nfs-utils-1.3.0-blkmapd-loop.patch
  10. 354
      SOURCES/nfs-utils-1.3.0-blkmapd-pnfs.patch
  11. 60
      SOURCES/nfs-utils-1.3.0-blkmapd-usage.patch
  12. 24
      SOURCES/nfs-utils-1.3.0-daemon_init-warning.patch
  13. 46
      SOURCES/nfs-utils-1.3.0-exportfs-NULL-pointer-test.patch
  14. 47
      SOURCES/nfs-utils-1.3.0-exportfs-bufsiz.patch
  15. 119
      SOURCES/nfs-utils-1.3.0-exportfs-empty-exports.patch
  16. 55
      SOURCES/nfs-utils-1.3.0-exportfs-hostnames.patch
  17. 87
      SOURCES/nfs-utils-1.3.0-exportfs-ipv6-arg.patch
  18. 83
      SOURCES/nfs-utils-1.3.0-exportfs-noreaddirplus.patch
  19. 12
      SOURCES/nfs-utils-1.3.0-exportfs-path-comp.patch
  20. 41
      SOURCES/nfs-utils-1.3.0-exportfs-redundant.patch
  21. 64
      SOURCES/nfs-utils-1.3.0-exportfs-securitylabel.patch
  22. 22
      SOURCES/nfs-utils-1.3.0-exportfs-slashes.patch
  23. 35
      SOURCES/nfs-utils-1.3.0-gssd-default-tcp.patch
  24. 27
      SOURCES/nfs-utils-1.3.0-gssd-noclear-retval.patch
  25. 26
      SOURCES/nfs-utils-1.3.0-gssd-rdma-to-tcp.patch
  26. 287
      SOURCES/nfs-utils-1.3.0-gssd-tgt-flood.patch
  27. 69
      SOURCES/nfs-utils-1.3.0-gssd-thread-safe.patch
  28. 60
      SOURCES/nfs-utils-1.3.0-gssproxy.patch
  29. 26
      SOURCES/nfs-utils-1.3.0-hostpton-eainoname.patch
  30. 45
      SOURCES/nfs-utils-1.3.0-libmount-umount-verbose.patch
  31. 30
      SOURCES/nfs-utils-1.3.0-mount-addressfailed.patch
  32. 590
      SOURCES/nfs-utils-1.3.0-mount-default-v42.patch
  33. 13
      SOURCES/nfs-utils-1.3.0-mount-eacces.patch
  34. 46
      SOURCES/nfs-utils-1.3.0-mount-explicit-rback.patch
  35. 61
      SOURCES/nfs-utils-1.3.0-mount-minorversion.patch
  36. 43
      SOURCES/nfs-utils-1.3.0-mount-nfs-types.patch
  37. 36
      SOURCES/nfs-utils-1.3.0-mount-nfsvers.patch
  38. 82
      SOURCES/nfs-utils-1.3.0-mount-prognotreg.patch
  39. 48
      SOURCES/nfs-utils-1.3.0-mount-remount.patch
  40. 156
      SOURCES/nfs-utils-1.3.0-mount-restore-econn.patch
  41. 124
      SOURCES/nfs-utils-1.3.0-mount-t-nfs4.patch
  42. 100
      SOURCES/nfs-utils-1.3.0-mount-uninit-structs.patch
  43. 19
      SOURCES/nfs-utils-1.3.0-mount-usage.patch
  44. 89
      SOURCES/nfs-utils-1.3.0-mount-use-minor-default.patch
  45. 12
      SOURCES/nfs-utils-1.3.0-mount-v41.patch
  46. 45
      SOURCES/nfs-utils-1.3.0-mount-v4arg-fix.patch
  47. 168
      SOURCES/nfs-utils-1.3.0-mountd-dos.patch
  48. 633
      SOURCES/nfs-utils-1.3.0-mountd-filedes.patch
  49. 27
      SOURCES/nfs-utils-1.3.0-mountd-manpage-P.patch
  50. 57
      SOURCES/nfs-utils-1.3.0-mountd-manpage-args.patch
  51. 39
      SOURCES/nfs-utils-1.3.0-mountd-manpage-netconfig.patch
  52. 31
      SOURCES/nfs-utils-1.3.0-mountd-netgroups.patch
  53. 157
      SOURCES/nfs-utils-1.3.0-mountd-root.patch
  54. 29
      SOURCES/nfs-utils-1.3.0-mountd-start-statd-path.patch
  55. 25
      SOURCES/nfs-utils-1.3.0-mountd-usage-error.patch
  56. 14
      SOURCES/nfs-utils-1.3.0-mountd-usage.patch
  57. 102
      SOURCES/nfs-utils-1.3.0-mountd-v4root-sec.patch
  58. 15
      SOURCES/nfs-utils-1.3.0-mountstats-iostats.patch
  59. 36
      SOURCES/nfs-utils-1.3.0-mountstats-manpage-fix.patch
  60. 21
      SOURCES/nfs-utils-1.3.0-mountstats-manpage-fix2.patch
  61. 26
      SOURCES/nfs-utils-1.3.0-mountstats-pnfs.patch
  62. 22
      SOURCES/nfs-utils-1.3.0-mountstats-shebang.patch
  63. 1326
      SOURCES/nfs-utils-1.3.0-mountstats-update.patch
  64. 1892
      SOURCES/nfs-utils-1.3.0-nfs-conf.patch
  65. 12
      SOURCES/nfs-utils-1.3.0-nfs-iostat-no-dev.patch
  66. 103
      SOURCES/nfs-utils-1.3.0-nfs-man-v2.patch
  67. 33
      SOURCES/nfs-utils-1.3.0-nfs_connect_nb-eintr.patch
  68. 12
      SOURCES/nfs-utils-1.3.0-nfsclient-after.patch
  69. 41
      SOURCES/nfs-utils-1.3.0-nfsd-man-correction.patch
  70. 12
      SOURCES/nfs-utils-1.3.0-nfsd-rdma.patch
  71. 26
      SOURCES/nfs-utils-1.3.0-nfsd-warnings.patch
  72. 37
      SOURCES/nfs-utils-1.3.0-nfsdcltrack-errors.patch
  73. 12
      SOURCES/nfs-utils-1.3.0-nfsdcltrack-invalops.patch
  74. 21
      SOURCES/nfs-utils-1.3.0-nfsdcltrack-usage.patch
  75. 154
      SOURCES/nfs-utils-1.3.0-nfsdcltrack-v2schema-update.patch
  76. 850
      SOURCES/nfs-utils-1.3.0-nfsdcltrack-v2schema.patch
  77. 24
      SOURCES/nfs-utils-1.3.0-nfsdcltrack-warning01.patch
  78. 55
      SOURCES/nfs-utils-1.3.0-nfsidmap-h-opt.patch
  79. 22
      SOURCES/nfs-utils-1.3.0-nfsidmap-timeout.patch
  80. 574
      SOURCES/nfs-utils-1.3.0-nfsidmap-update.patch
  81. 74
      SOURCES/nfs-utils-1.3.0-nfsiostat-output.patch
  82. 27
      SOURCES/nfs-utils-1.3.0-nfsman-minorversion.patch
  83. 12
      SOURCES/nfs-utils-1.3.0-nfsstat-mounts.patch
  84. 30
      SOURCES/nfs-utils-1.3.0-nfsstat-retval.patch
  85. 398
      SOURCES/nfs-utils-1.3.0-rpcgssd-acceptor.patch
  86. 2564
      SOURCES/nfs-utils-1.3.0-rpcgssd-debug.patch
  87. 21
      SOURCES/nfs-utils-1.3.0-rpcgssd-errno-typo.patch
  88. 23
      SOURCES/nfs-utils-1.3.0-rpcgssd-findkeytab.patch
  89. 66
      SOURCES/nfs-utils-1.3.0-rpcgssd-maccout-nocase.patch
  90. 594
      SOURCES/nfs-utils-1.3.0-rpcgssd-multithread.patch
  91. 44
      SOURCES/nfs-utils-1.3.0-rpcgssd-noerror-message.patch
  92. 12
      SOURCES/nfs-utils-1.3.0-rpcgssd-preferred-realm.patch
  93. 82
      SOURCES/nfs-utils-1.3.0-rpcgssd-timeout.patch
  94. 97
      SOURCES/nfs-utils-1.3.0-rpcidmapd-usage.patch
  95. 935
      SOURCES/nfs-utils-1.3.0-server-chgrpcpipefs.patch
  96. 467
      SOURCES/nfs-utils-1.3.0-server-generator.patch
  97. 27
      SOURCES/nfs-utils-1.3.0-start-statd-flock.patch
  98. 31
      SOURCES/nfs-utils-1.3.0-start-statd-once.patch
  99. 35
      SOURCES/nfs-utils-1.3.0-start-statd-root.patch
  100. 14
      SOURCES/nfs-utils-1.3.0-startstatd-systemd.patch
  101. Some files were not shown because too many files have changed in this diff Show More

7
SOURCES/24-nfs-server.conf

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
[service/nfs-server]
mechs = krb5
socket = /run/gssproxy.sock
cred_store = keytab:/etc/krb5.keytab
trusted = yes
kernel_nfsd = yes
euid = 0

9
SOURCES/id_resolver.conf

@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
#
# nfsidmap(5) - The NFS idmapper upcall program
# Summary: Used by NFSv4 to map user/group ids into
# user/group names and names into in ids
# Options:
# -v Increases the verbosity of the output to syslog
# -t timeout Set the expiration timer, in seconds, on the key
#
create id_resolver * * /usr/sbin/nfsidmap %k %d

22
SOURCES/lockd.conf

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
#
# Set the NFS lock manager grace period. n is measured in seconds.
#options lockd nlm_grace_period=90
#
# Set the TCP port that the NFS lock manager should use.
# port must be a valid TCP port value (1-65535).
#options lockd nlm_tcpport
#
# Set the UDP port that the NFS lock manager should use.
# port must be a valid UDP port value (1-65535).
#options lockd nlm_udpport
#
# Set the maximum number of outstanding connections
#options lockd nlm_max_connections=1024
#
# Set the default time value for the NFS lock manager
# in seconds. Default is 10 secs (min 3 max 20)
#options lockd nlm_timeout=10
#
# Choose whether to record the caller_name or IP address
# this peer in the local rpc.statd's database.
#options lockd nsm_use_hostnames=0

12
SOURCES/nfs-utils-1.2.1-exp-subtree-warn-off.patch

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
diff -up nfs-utils-1.3.0/support/nfs/exports.c.orig nfs-utils-1.3.0/support/nfs/exports.c
--- nfs-utils-1.3.0/support/nfs/exports.c.orig 2017-04-27 14:09:49.090353525 -0400
+++ nfs-utils-1.3.0/support/nfs/exports.c 2017-04-27 14:10:09.083034672 -0400
@@ -507,7 +507,7 @@ void fix_pseudoflavor_flags(struct expor
static int
parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr)
{
- int had_subtree_opt = 0;
+ int had_subtree_opt = 1;
char *flname = efname?efname:"command line";
int flline = efp?efp->x_line:0;
unsigned int active = 0;

58
SOURCES/nfs-utils-1.2.1-statdpath-man.patch

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
diff -up nfs-utils-1.3.0/utils/statd/sm-notify.man.orig nfs-utils-1.3.0/utils/statd/sm-notify.man
--- nfs-utils-1.3.0/utils/statd/sm-notify.man.orig 2017-04-27 14:08:24.681720773 -0400
+++ nfs-utils-1.3.0/utils/statd/sm-notify.man 2017-04-27 14:09:05.347042274 -0400
@@ -184,7 +184,7 @@ where NSM state information resides.
If this option is not specified,
.B sm-notify
uses
-.I /var/lib/nfs
+.I /var/lib/nfs/statd
by default.
.IP
After starting,
@@ -330,13 +330,13 @@ Currently, the
command supports sending notification only via datagram transport protocols.
.SH FILES
.TP 2.5i
-.I /var/lib/nfs/sm
+.I /var/lib/nfs/statd/sm
directory containing monitor list
.TP 2.5i
-.I /var/lib/nfs/sm.bak
+.I /var/lib/nfs/statd/sm.bak
directory containing notify list
.TP 2.5i
-.I /var/lib/nfs/state
+.I /var/lib/nfs/statd/state
NSM state number for this host
.TP 2.5i
.I /proc/sys/fs/nfs/nsm_local_state
diff -up nfs-utils-1.3.0/utils/statd/statd.man.orig nfs-utils-1.3.0/utils/statd/statd.man
--- nfs-utils-1.3.0/utils/statd/statd.man.orig 2017-04-27 14:08:24.662721095 -0400
+++ nfs-utils-1.3.0/utils/statd/statd.man 2017-04-27 14:09:05.347042274 -0400
@@ -253,7 +253,7 @@ where NSM state information resides.
If this option is not specified,
.B rpc.statd
uses
-.I /var/lib/nfs
+.I /var/lib/nfs/statd
by default.
.IP
After starting,
@@ -425,13 +425,13 @@ If set to a positive integer, has the sa
.IR \-\-no\-notify .
.SH FILES
.TP 2.5i
-.I /var/lib/nfs/sm
+.I /var/lib/nfs/statd/sm
directory containing monitor list
.TP 2.5i
-.I /var/lib/nfs/sm.bak
+.I /var/lib/nfs/statd/sm.bak
directory containing notify list
.TP 2.5i
-.I /var/lib/nfs/state
+.I /var/lib/nfs/statd/state
NSM state number for this host
.TP 2.5i
.I /var/run/run.statd.pid

21
SOURCES/nfs-utils-1.2.3-sm-notify-res_init.patch

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
diff -up nfs-utils-1.3.0/utils/statd/sm-notify.c.orig nfs-utils-1.3.0/utils/statd/sm-notify.c
--- nfs-utils-1.3.0/utils/statd/sm-notify.c.orig 2017-04-27 14:10:28.866713955 -0400
+++ nfs-utils-1.3.0/utils/statd/sm-notify.c 2017-04-27 14:10:50.454363993 -0400
@@ -28,6 +28,9 @@
#include <netdb.h>
#include <errno.h>
#include <grp.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
#include "conffile.h"
#include "sockaddr.h"
@@ -91,6 +94,7 @@ smn_lookup(const char *name)
};
int error;
+ res_init();
error = getaddrinfo(name, NULL, &hint, &ai);
if (error != 0) {
xlog(D_GENERAL, "getaddrinfo(3): %s", gai_strerror(error));

12
SOURCES/nfs-utils-1.2.5-idmap-errmsg.patch

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
diff -up nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c.orig nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c
--- nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c.orig 2017-04-27 14:11:05.788115492 -0400
+++ nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c 2017-04-27 14:11:26.291788824 -0400
@@ -417,7 +417,7 @@ int main(int argc, char **argv)
xlog_stderr(verbose);
if ((argc - optind) != 2) {
- xlog_warn("Bad arg count. Check /etc/request-key.conf");
+ xlog_warn("Bad arg count. Check /etc/request-key.d/request-key.conf");
xlog_warn(usage, progname);
return EXIT_FAILURE;
}

94
SOURCES/nfs-utils-1.2.9-exportfs-badentries.patch

@ -0,0 +1,94 @@ @@ -0,0 +1,94 @@
diff --git a/support/export/client.c b/support/export/client.c
index dbf47b9..0f7b4fe 100644
--- a/support/export/client.c
+++ b/support/export/client.c
@@ -277,7 +277,7 @@ client_lookup(char *hname, int canonical)
if (htype == MCL_FQDN && !canonical) {
ai = host_addrinfo(hname);
if (!ai) {
- xlog(L_ERROR, "Failed to resolve %s", hname);
+ xlog(L_WARNING, "Failed to resolve %s", hname);
goto out;
}
hname = ai->ai_canonname;
diff --git a/support/export/export.c b/support/export/export.c
index 6b1d045..ce714d4 100644
--- a/support/export/export.c
+++ b/support/export/export.c
@@ -76,15 +76,22 @@ export_read(char *fname)
struct exportent *eep;
nfs_export *exp;
+ int volumes = 0;
+
setexportent(fname, "r");
while ((eep = getexportent(0,1)) != NULL) {
exp = export_lookup(eep->e_hostname, eep->e_path, 0);
- if (!exp)
- export_create(eep, 0);
+ if (!exp) {
+ exp = export_create(eep, 0);
+ if (exp)
+ volumes++;
+ }
else
warn_duplicated_exports(exp, eep);
}
endexportent();
+ if (volumes == 0)
+ xlog(L_ERROR, "No file systems exported!");
}
/**
diff --git a/support/export/hostname.c b/support/export/hostname.c
index 5f31aee..cdf9e76 100644
--- a/support/export/hostname.c
+++ b/support/export/hostname.c
@@ -137,11 +137,11 @@ host_pton(const char *paddr)
case EAI_NONAME:
break;
case EAI_SYSTEM:
- xlog(D_GENERAL, "%s: failed to convert %s: (%d) %m",
+ xlog(L_WARNING, "%s: failed to convert %s: (%d) %m",
__func__, paddr, errno);
break;
default:
- xlog(D_GENERAL, "%s: failed to convert %s: %s",
+ xlog(L_WARNING, "%s: failed to convert %s: %s",
__func__, paddr, gai_strerror(error));
break;
}
@@ -179,11 +179,11 @@ host_addrinfo(const char *hostname)
case 0:
return ai;
case EAI_SYSTEM:
- xlog(D_GENERAL, "%s: failed to resolve %s: (%d) %m",
+ xlog(D_PARSE, "%s: failed to resolve %s: (%d) %m",
__func__, hostname, errno);
break;
default:
- xlog(D_GENERAL, "%s: failed to resolve %s: %s",
+ xlog(D_PARSE, "%s: failed to resolve %s: %s",
__func__, hostname, gai_strerror(error));
break;
}
diff --git a/systemd/nfs-server.service b/systemd/nfs-server.service
index f0e456a..7f60f39 100644
--- a/systemd/nfs-server.service
+++ b/systemd/nfs-server.service
@@ -23,13 +23,13 @@ EnvironmentFile=-/run/sysconfig/nfs-utils
Type=oneshot
RemainAfterExit=yes
-ExecStartPre=/usr/sbin/exportfs -r
+ExecStartPre=-/usr/sbin/exportfs -r
ExecStart=/usr/sbin/rpc.nfsd $RPCNFSDARGS
ExecStop=/usr/sbin/rpc.nfsd 0
ExecStopPost=/usr/sbin/exportfs -au
ExecStopPost=/usr/sbin/exportfs -f
-ExecReload=/usr/sbin/exportfs -r
+ExecReload=-/usr/sbin/exportfs -r
[Install]
WantedBy=multi-user.target

35
SOURCES/nfs-utils-1.3.0-blkmapd-loop.patch

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
commit c6b8191374d9ad064eb96423400a6314c2d0102e
Author: Kinglong Mee <kinglongmee@gmail.com>
Date: Tue Jun 30 14:12:38 2015 -0400

blkmapd: Fix infinite loop when reading serial
If (dev_id->ids & 0xf) < current_id, must updates pos when continue.
Otherwise an infinite loop.
No other places use the pos value, just move to the top of while.
Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/blkmapd/device-inq.c b/utils/blkmapd/device-inq.c
index c5bf71f..6b56b67 100644
--- a/utils/blkmapd/device-inq.c
+++ b/utils/blkmapd/device-inq.c
@@ -196,6 +196,8 @@ struct bl_serial *bldev_read_serial(int fd, const char *filename)
while (pos < (len - devid_len)) {
dev_id = (struct bl_dev_id *)&(dev_root->data[pos]);
+ pos += (dev_id->len + devid_len);
+
if ((dev_id->ids & 0xf) < current_id)
continue;
switch (dev_id->ids & 0xf) {
@@ -226,7 +228,6 @@ struct bl_serial *bldev_read_serial(int fd, const char *filename)
}
if (current_id == 3)
break;
- pos += (dev_id->len + devid_len);
}
out:
if (!serial_out)

354
SOURCES/nfs-utils-1.3.0-blkmapd-pnfs.patch

@ -0,0 +1,354 @@ @@ -0,0 +1,354 @@
diff --git a/Makefile.am b/Makefile.am
index ae7cd16..c9e9f87 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,7 +2,7 @@
AUTOMAKE_OPTIONS = foreign
-SUBDIRS = tools support utils linux-nfs tests
+SUBDIRS = tools support utils linux-nfs tests systemd
MAINTAINERCLEANFILES = Makefile.in
diff --git a/configure.ac b/configure.ac
index 7b93de6..4ee4db5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -54,6 +54,16 @@ AC_ARG_WITH(start-statd,
)
AC_SUBST(startstatd)
AC_DEFINE_UNQUOTED(START_STATD, "$startstatd", [Define this to a script which can start statd on mount])
+unitdir=/usr/lib/systemd/system
+AC_ARG_WITH(systemd,
+ [AC_HELP_STRING([--with-systemd@<:@=unit-dir-path@:>@],
+ [install systemd unit files @<:@Default: no, and path defaults to /usr/lib/systemd/system if not given@:>@])],
+ test "$withval" = "no" && use_systemd=0 || unitdir=$withval use_systemd=1
+ use_systemd=0
+ )
+ AM_CONDITIONAL(INSTALL_SYSTEMD, [test "$use_systemd" = 1])
+ AC_SUBST(unitdir)
+
AC_ARG_ENABLE(nfsv4,
[AC_HELP_STRING([--enable-nfsv4],
[enable support for NFSv4 @<:@default=yes@:>@])],
@@ -506,6 +516,7 @@ AC_CONFIG_FILES([
utils/showmount/Makefile
utils/statd/Makefile
utils/osd_login/Makefile
+ systemd/Makefile
tests/Makefile
tests/nsm_client/Makefile])
AC_OUTPUT
diff --git a/support/include/nfs/export.h b/support/include/nfs/export.h
index 2f59e6a..1194255 100644
--- a/support/include/nfs/export.h
+++ b/support/include/nfs/export.h
@@ -26,6 +26,7 @@
#define NFSEXP_CROSSMOUNT 0x4000
#define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */
#define NFSEXP_V4ROOT 0x10000
+#define NFSEXP_PNFS 0x20000
/*
* All flags supported by the kernel before addition of the
* export_features interface:
diff --git a/support/nfs/exports.c b/support/nfs/exports.c
index 5451ed7..9399a12 100644
--- a/support/nfs/exports.c
+++ b/support/nfs/exports.c
@@ -275,6 +275,7 @@ putexportent(struct exportent *ep)
"no_" : "");
if (ep->e_flags & NFSEXP_NOREADDIRPLUS)
fprintf(fp, "nordirplus,");
+ fprintf(fp, "%spnfs,", (ep->e_flags & NFSEXP_PNFS)? "" : "no_");
if (ep->e_flags & NFSEXP_FSID) {
fprintf(fp, "fsid=%d,", ep->e_fsid);
}
@@ -581,6 +582,10 @@ parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr)
clearflags(NFSEXP_NOACL, active, ep);
else if (strcmp(opt, "no_acl") == 0)
setflags(NFSEXP_NOACL, active, ep);
+ else if (!strcmp(opt, "pnfs"))
+ setflags(NFSEXP_PNFS, active, ep);
+ else if (!strcmp(opt, "no_pnfs"))
+ clearflags(NFSEXP_PNFS, active, ep);
else if (strncmp(opt, "anonuid=", 8) == 0) {
char *oe;
ep->e_anonuid = strtol(opt+8, &oe, 10);
diff --git a/systemd/Makefile.am b/systemd/Makefile.am
new file mode 100644
index 0000000..fbcabb1
--- /dev/null
+++ b/systemd/Makefile.am
@@ -0,0 +1,31 @@
+## Process this file with automake to produce Makefile.in
+
+MAINTAINERCLEANFILES = Makefile.in
+
+unit_files = \
+ nfs-client.target \
+ \
+ auth-rpcgss-module.service \
+ nfs-blkmap.service \
+ nfs-config.service \
+ nfs-idmapd.service \
+ nfs-mountd.service \
+ nfs-server.service \
+ nfs-utils.service \
+ rpc-gssd.service \
+ rpc-statd-notify.service \
+ rpc-statd.service \
+ rpc-svcgssd.service \
+ \
+ proc-fs-nfsd.mount \
+ var-lib-nfs-rpc_pipefs.mount
+
+EXTRA_DIST = $(unit_files)
+
+unit_dir = /usr/lib/systemd/system
+
+if INSTALL_SYSTEMD
+install-data-hook: $(unit_files)
+ mkdir -p $(DESTDIR)/$(unitdir)
+ cp $(unit_files) $(DESTDIR)/$(unitdir)
+endif
diff --git a/systemd/README b/systemd/README
index a2a5f06..bbd7790 100644
--- a/systemd/README
+++ b/systemd/README
@@ -24,7 +24,7 @@ by a suitable 'preset' setting:
is started by /usr/sbin/start-statd which mount.nfs will run
if statd is needed.
- nfs-blkmap.target
+ nfs-blkmap.service
If enabled, then blkmapd will be run when nfs-client.target is
started.
diff --git a/systemd/nfs-blkmap.service b/systemd/nfs-blkmap.service
index f470e3d..ddbf4e9 100644
--- a/systemd/nfs-blkmap.service
+++ b/systemd/nfs-blkmap.service
@@ -5,12 +5,13 @@ Conflicts=umount.target
After=var-lib-nfs-rpc_pipefs.mount
Requires=var-lib-nfs-rpc_pipefs.mount
-Requisite=nfs-blkmap.target
-After=nfs-blkmap.target
-
PartOf=nfs-utils.service
[Service]
Type=forking
PIDFile=/var/run/blkmapd.pid
+EnvironmentFile=-/run/sysconfig/nfs-utils
ExecStart=/usr/sbin/blkmapd $BLKMAPDARGS
+
+[Install]
+WantedBy=nfs-client.target
diff --git a/systemd/nfs-blkmap.target b/systemd/nfs-blkmap.target
deleted file mode 100644
index fbcc111..0000000
--- a/systemd/nfs-blkmap.target
+++ /dev/null
@@ -1,8 +0,0 @@
-[Unit]
-Description= PNFS blkmaping enablement.
-# If this target is enabled, then blkmapd will be started
-# as required. If it is not enabled it won't.
-
-[Install]
-WantedBy=remote-fs.target
-WantedBy=multi-user.target
\ No newline at end of file
diff --git a/systemd/nfs-client.target b/systemd/nfs-client.target
index 9b792a3..8a8300a 100644
--- a/systemd/nfs-client.target
+++ b/systemd/nfs-client.target
@@ -5,8 +5,7 @@ Wants=remote-fs-pre.target
# Note: we don't "Wants=rpc-statd.service" as "mount.nfs" will arrange to
# start that on demand if needed.
-Wants=nfs-blkmap.service rpc-statd-notify.service
-After=nfs-blkmap.service
+Wants=rpc-statd-notify.service
# GSS services dependencies and ordering
Wants=auth-rpcgss-module.service
diff --git a/utils/blkmapd/device-discovery.c b/utils/blkmapd/device-discovery.c
index df4627e..b52afe2 100644
--- a/utils/blkmapd/device-discovery.c
+++ b/utils/blkmapd/device-discovery.c
@@ -77,16 +77,6 @@ struct bl_disk_path *bl_get_path(const char *filepath,
return tmp;
}
-/* Check whether valid_path is a substring(partition) of path */
-int bl_is_partition(struct bl_disk_path *valid_path, struct bl_disk_path *path)
-{
- if (!strncmp(valid_path->full_path, path->full_path,
- strlen(valid_path->full_path)))
- return 1;
-
- return 0;
-}
-
/*
* For multipath devices, devices state could be PASSIVE/ACTIVE/PSEUDO,
* where PSEUDO > ACTIVE > PASSIVE. Device with highest state is used to
@@ -95,19 +85,13 @@ int bl_is_partition(struct bl_disk_path *valid_path, struct bl_disk_path *path)
* If device-mapper multipath support is a must, pseudo devices should
* exist for each multipath device. If not, active device path will be
* chosen for device creation.
- * Treat partition as invalid path.
*/
-int bl_update_path(struct bl_disk_path *path, enum bl_path_state_e state,
- struct bl_disk *disk)
+int bl_update_path(enum bl_path_state_e state, struct bl_disk *disk)
{
struct bl_disk_path *valid_path = disk->valid_path;
- if (valid_path) {
- if (valid_path->state >= state) {
- if (bl_is_partition(valid_path, path))
- return 0;
- }
- }
+ if (valid_path && valid_path->state >= state)
+ return 0;
return 1;
}
@@ -164,15 +148,16 @@ void bl_add_disk(char *filepath)
dev = sb.st_rdev;
serial = bldev_read_serial(fd, filepath);
- if (dm_is_dm_major(major(dev)))
+ if (!serial) {
+ BL_LOG_ERR("%s: no serial found for %s\n",
+ __func__, filepath);
+ ap_state = BL_PATH_STATE_PASSIVE;
+ } else if (dm_is_dm_major(major(dev)))
ap_state = BL_PATH_STATE_PSEUDO;
else
ap_state = bldev_read_ap_state(fd);
close(fd);
- if (ap_state != BL_PATH_STATE_ACTIVE)
- return;
-
for (disk = visible_disk_list; disk != NULL; disk = disk->next) {
/* Already scanned or a partition?
* XXX: if released each time, maybe not need to compare
@@ -216,7 +201,7 @@ void bl_add_disk(char *filepath)
path->next = disk->paths;
disk->paths = path;
/* check whether we need to update disk info */
- if (bl_update_path(path, path->state, disk)) {
+ if (bl_update_path(path->state, disk)) {
disk->dev = dev;
disk->size = size;
disk->valid_path = path;
diff --git a/utils/blkmapd/device-inq.c b/utils/blkmapd/device-inq.c
index eabc70c..c5bf71f 100644
--- a/utils/blkmapd/device-inq.c
+++ b/utils/blkmapd/device-inq.c
@@ -179,6 +179,7 @@ struct bl_serial *bldev_read_serial(int fd, const char *filename)
char *buffer;
struct bl_dev_id *dev_root, *dev_id;
unsigned int pos, len, current_id = 0;
+ size_t devid_len = sizeof(struct bl_dev_id) - sizeof(unsigned char);
status = bldev_inquire_pages(fd, 0x83, &buffer);
if (status)
@@ -189,7 +190,11 @@ struct bl_serial *bldev_read_serial(int fd, const char *filename)
pos = 0;
current_id = 0;
len = dev_root->len;
- while (pos < (len - sizeof(struct bl_dev_id) + sizeof(unsigned char))) {
+
+ if (len < devid_len)
+ goto out;
+
+ while (pos < (len - devid_len)) {
dev_id = (struct bl_dev_id *)&(dev_root->data[pos]);
if ((dev_id->ids & 0xf) < current_id)
continue;
@@ -221,8 +226,7 @@ struct bl_serial *bldev_read_serial(int fd, const char *filename)
}
if (current_id == 3)
break;
- pos += (dev_id->len + sizeof(struct bl_dev_id) -
- sizeof(unsigned char));
+ pos += (dev_id->len + devid_len);
}
out:
if (!serial_out)
diff --git a/utils/blkmapd/device-process.c b/utils/blkmapd/device-process.c
index 5fe3dff..f53a616 100644
--- a/utils/blkmapd/device-process.c
+++ b/utils/blkmapd/device-process.c
@@ -181,6 +181,8 @@ static int map_sig_to_device(struct bl_sig *sig, struct bl_volume *vol)
/* FIXME: should we use better algorithm for disk scan? */
mapped = verify_sig(disk, sig);
if (mapped) {
+ BL_LOG_INFO("%s: using device %s\n",
+ __func__, disk->valid_path->full_path);
vol->param.bv_dev = disk->dev;
vol->bv_size = disk->size;
break;
diff --git a/utils/blkmapd/dm-device.c b/utils/blkmapd/dm-device.c
index 0f4f148..24ffcbf 100644
--- a/utils/blkmapd/dm-device.c
+++ b/utils/blkmapd/dm-device.c
@@ -400,6 +400,8 @@ uint64_t dm_device_create(struct bl_volume *vols, int num_vols)
}
dev = node->bv_vols[0]->param.bv_dev;
tmp = table->params;
+ BL_LOG_INFO("%s: major %lu minor %lu", __func__,
+ MAJOR(dev), MINOR(dev));
if (!dm_format_dev(tmp, DM_PARAMS_LEN,
MAJOR(dev), MINOR(dev))) {
free(table);
@@ -459,6 +461,8 @@ uint64_t dm_device_create(struct bl_volume *vols, int num_vols)
strcpy(table->target_type, "linear");
tmp = table->params;
dev = node->bv_vols[i]->param.bv_dev;
+ BL_LOG_INFO("%s: major %lu minor %lu", __func__,
+ MAJOR(dev), MINOR(dev));
if (!dm_format_dev(tmp, DM_PARAMS_LEN,
MAJOR(dev), MINOR(dev))) {
free(table);
diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
index 8391615..53e86ec 100644
--- a/utils/exportfs/exportfs.c
+++ b/utils/exportfs/exportfs.c
@@ -815,6 +815,8 @@ dump(int verbose, int export_format)
c = dumpopt(c, "insecure_locks");
if (ep->e_flags & NFSEXP_NOACL)
c = dumpopt(c, "no_acl");
+ if (ep->e_flags & NFSEXP_PNFS)
+ c = dumpopt(c, "pnfs");
if (ep->e_flags & NFSEXP_FSID)
c = dumpopt(c, "fsid=%d", ep->e_fsid);
if (ep->e_uuid)
diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man
index 3d974d9..59358e6 100644
--- a/utils/exportfs/exports.man
+++ b/utils/exportfs/exports.man
@@ -378,6 +378,15 @@ If the client asks for alternative locations for the export point, it
will be given this list of alternatives. (Note that actual replication
of the filesystem must be handled elsewhere.)
+.TP
+.IR pnfs
+This option allows enables the use of pNFS extension if protocol level
+is NFSv4.1 or higher, and the filesystem supports pNFS exports. With
+pNFS clients can bypass the server and perform I/O directly to storage
+devices. The default can be explicitly requested with the
+.I no_pnfs
+option.
+
.SS User ID Mapping
.PP
.B nfsd

60
SOURCES/nfs-utils-1.3.0-blkmapd-usage.patch

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
diff -up nfs-utils-1.3.0/utils/blkmapd/blkmapd.man.save nfs-utils-1.3.0/utils/blkmapd/blkmapd.man
--- nfs-utils-1.3.0/utils/blkmapd/blkmapd.man.save 2014-03-25 11:12:07.000000000 -0400
+++ nfs-utils-1.3.0/utils/blkmapd/blkmapd.man 2016-05-17 14:12:08.000000000 -0400
@@ -9,7 +9,7 @@
.SH NAME
blkmapd \- pNFS block layout mapping daemon
.SH SYNOPSIS
-.B "blkmapd [-d] [-f]"
+.B "blkmapd [-h] [-d] [-f]"
.SH DESCRIPTION
The
.B blkmapd
@@ -33,6 +33,9 @@ reflect the server topology, and passes
by the pNFS block layout client.
.SH OPTIONS
.TP
+.B -h
+Display usage message.
+.TP
.B -d
Performs device discovery only then exits.
.TP
diff -up nfs-utils-1.3.0/utils/blkmapd/device-discovery.c.save nfs-utils-1.3.0/utils/blkmapd/device-discovery.c
--- nfs-utils-1.3.0/utils/blkmapd/device-discovery.c.save 2016-05-17 14:11:36.000000000 -0400
+++ nfs-utils-1.3.0/utils/blkmapd/device-discovery.c 2016-05-17 14:11:48.000000000 -0400
@@ -427,7 +427,10 @@ void sig_die(int signal)
BL_LOG_ERR("exit on signal(%d)\n", signal);
exit(1);
}
-
+static void usage(void)
+{
+ fprintf(stderr, "Usage: blkmapd [-hdf]\n" );
+}
/* Daemon */
int main(int argc, char **argv)
{
@@ -435,7 +438,7 @@ int main(int argc, char **argv)
struct stat statbuf;
char pidbuf[64];
- while ((opt = getopt(argc, argv, "df")) != -1) {
+ while ((opt = getopt(argc, argv, "hdf")) != -1) {
switch (opt) {
case 'd':
dflag = 1;
@@ -443,6 +446,13 @@ int main(int argc, char **argv)
case 'f':
fg = 1;
break;
+ case 'h':
+ usage();
+ exit(0);
+ default:
+ usage();
+ exit(1);
+
}
}

24
SOURCES/nfs-utils-1.3.0-daemon_init-warning.patch

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
commit 19e6ba690c7e9674dae006cfce89f638c8d8edab
Author: Steve Dickson <steved@redhat.com>
Date: Wed Nov 4 16:25:28 2015 -0500

mydaemon.c: Removed a warning
Commit 273b4647 introduced the following warning:
mydaemon.c:125:2: warning: implicit declaration of function 'closelog'
[-Wimplicit-function-declaration]
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/support/nfs/mydaemon.c b/support/nfs/mydaemon.c
index 701cfd9..343e80b 100644
--- a/support/nfs/mydaemon.c
+++ b/support/nfs/mydaemon.c
@@ -49,6 +49,7 @@
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
+#include <syslog.h>
#include <xlog.h>
#include "nfslib.h"

46
SOURCES/nfs-utils-1.3.0-exportfs-NULL-pointer-test.patch

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
commit d89e3fc7d3b14dea481bd9af0bca996ced689bf6
Author: Natanael Copa <ncopa@alpinelinux.org>
Date: Fri Sep 12 13:19:01 2014 -0400

exportfs: fix test of NULL pointer in host_pton()
This fixes the problem reported in:
https://bugzilla.redhat.com/show_bug.cgi?id=1083018
Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/support/export/hostname.c b/support/export/hostname.c
index ad595d1..d9153e1 100644
--- a/support/export/hostname.c
+++ b/support/export/hostname.c
@@ -115,6 +115,11 @@ host_pton(const char *paddr)
* have a real AF_INET presentation address, before invoking
* getaddrinfo(3) to generate the full addrinfo list.
*/
+ if (paddr == NULL) {
+ xlog(D_GENERAL, "%s: passed a NULL presentation address",
+ __func__);
+ return NULL;
+ }
inet4 = 1;
if (inet_pton(AF_INET, paddr, &sin.sin_addr) == 0)
inet4 = 0;
@@ -123,15 +128,12 @@ host_pton(const char *paddr)
switch (error) {
case 0:
if (!inet4 && ai->ai_addr->sa_family == AF_INET) {
+ xlog(D_GENERAL, "%s: failed to convert %s",
+ __func__, paddr);
freeaddrinfo(ai);
break;
}
return ai;
- case EAI_NONAME:
- if (paddr == NULL)
- xlog(D_GENERAL, "%s: passed a NULL presentation address",
- __func__);
- break;
case EAI_SYSTEM:
xlog(D_GENERAL, "%s: failed to convert %s: (%d) %m",
__func__, paddr, errno);

47
SOURCES/nfs-utils-1.3.0-exportfs-bufsiz.patch

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig 2016-05-03 11:06:55.925043000 -0400
+++ nfs-utils-1.3.0/utils/exportfs/exportfs.c 2016-05-03 11:11:58.680677000 -0400
@@ -508,9 +508,10 @@ unexportfs(char *arg, int verbose)
static int can_test(void)
{
- char buf[1024];
+ char buf[1024] = { 0 };
int fd;
int n;
+ size_t bufsiz = sizeof(buf);
fd = open("/proc/net/rpc/auth.unix.ip/channel", O_WRONLY);
if (fd < 0)
@@ -523,9 +524,9 @@ static int can_test(void)
* commit 2f74f972 (sunrpc: prepare NFS for 2038).
*/
if (time(NULL) > INT_TO_LONG_THRESHOLD_SECS)
- sprintf(buf, "nfsd 0.0.0.0 %ld -test-client-\n", LONG_MAX);
+ snprintf(buf, bufsiz-1, "nfsd 0.0.0.0 %ld -test-client-\n", LONG_MAX);
else
- sprintf(buf, "nfsd 0.0.0.0 %d -test-client-\n", INT_MAX);
+ snprintf(buf, bufsiz-1, "nfsd 0.0.0.0 %d -test-client-\n", INT_MAX);
n = write(fd, buf, strlen(buf));
close(fd);
@@ -541,7 +542,8 @@ static int can_test(void)
static int test_export(char *path, int with_fsid)
{
- char buf[1024];
+ /* 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;
@@ -766,7 +768,8 @@ dumpopt(char c, char *fmt, ...)
static void
dump(int verbose, int export_format)
{
- char buf[1024];
+ /* buf[] size should >= sizeof(struct exportent->e_path) */
+ char buf[NFS_MAXPATHLEN+1] = { 0 };
char *bp;
int len;
nfs_export *exp;

119
SOURCES/nfs-utils-1.3.0-exportfs-empty-exports.patch

@ -0,0 +1,119 @@ @@ -0,0 +1,119 @@
diff --git a/support/export/export.c b/support/export/export.c
index ce714d4..e1bebce 100644
--- a/support/export/export.c
+++ b/support/export/export.c
@@ -69,8 +69,9 @@ static void warn_duplicated_exports(nfs_export *exp, struct exportent *eep)
* export_read - read entries from /etc/exports
* @fname: name of file to read from
*
+ * Returns number of read entries.
*/
-void
+int
export_read(char *fname)
{
struct exportent *eep;
@@ -82,16 +83,16 @@ export_read(char *fname)
while ((eep = getexportent(0,1)) != NULL) {
exp = export_lookup(eep->e_hostname, eep->e_path, 0);
if (!exp) {
- exp = export_create(eep, 0);
- if (exp)
+ if (export_create(eep, 0))
+ /* possible complaints already logged */
volumes++;
}
else
warn_duplicated_exports(exp, eep);
}
endexportent();
- if (volumes == 0)
- xlog(L_ERROR, "No file systems exported!");
+
+ return volumes;
}
/**
diff --git a/support/include/exportfs.h b/support/include/exportfs.h
index 97b2327..faa9f0b 100644
--- a/support/include/exportfs.h
+++ b/support/include/exportfs.h
@@ -133,7 +133,7 @@ struct addrinfo * client_resolve(const struct sockaddr *sap);
int client_member(const char *client,
const char *name);
-void export_read(char *fname);
+int export_read(char *fname);
void export_reset(nfs_export *);
nfs_export * export_lookup(char *hname, char *path, int caconical);
nfs_export * export_find(const struct addrinfo *ai,
diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
index c06f2aa..b7d8578 100644
--- a/utils/exportfs/exportfs.c
+++ b/utils/exportfs/exportfs.c
@@ -47,7 +47,7 @@ static void error(nfs_export *exp, int err);
static void usage(const char *progname, int n);
static void validate_export(nfs_export *exp);
static int matchhostname(const char *hostname1, const char *hostname2);
-static void export_d_read(const char *dname);
+static int export_d_read(const char *dname);
static void grab_lockfile(void);
static void release_lockfile(void);
@@ -185,8 +185,11 @@ main(int argc, char **argv)
atexit(release_lockfile);
if (f_export && ! f_ignore) {
- export_read(_PATH_EXPORTS);
- export_d_read(_PATH_EXPORTS_D);
+ if (! (export_read(_PATH_EXPORTS) +
+ export_d_read(_PATH_EXPORTS_D))) {
+ if (f_verbose)
+ xlog(L_WARNING, "No file systems exported!");
+ }
}
if (f_export) {
if (f_all)
@@ -699,21 +702,22 @@ out:
/* Based on mnt_table_parse_dir() in
util-linux-ng/shlibs/mount/src/tab_parse.c */
-static void
+static int
export_d_read(const char *dname)
{
int n = 0, i;
struct dirent **namelist = NULL;
+ int volumes = 0;
n = scandir(dname, &namelist, NULL, versionsort);
if (n < 0) {
if (errno == ENOENT)
/* Silently return */
- return;
+ return volumes;
xlog(L_NOTICE, "scandir %s: %s", dname, strerror(errno));
} else if (n == 0)
- return;
+ return volumes;
for (i = 0; i < n; i++) {
struct dirent *d = namelist[i];
@@ -743,14 +747,14 @@ export_d_read(const char *dname)
continue;
}
- export_read(fname);
+ volumes += export_read(fname);
}
for (i = 0; i < n; i++)
free(namelist[i]);
free(namelist);
- return;
+ return volumes;
}
static char

55
SOURCES/nfs-utils-1.3.0-exportfs-hostnames.patch

@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
diff --git a/support/export/hostname.c b/support/export/hostname.c
index cdf9e76..816b098 100644
--- a/support/export/hostname.c
+++ b/support/export/hostname.c
@@ -230,7 +230,7 @@ host_canonname(const struct sockaddr *sap)
default:
(void)getnameinfo(sap, salen, buf, (socklen_t)sizeof(buf),
NULL, 0, NI_NUMERICHOST);
- xlog(D_GENERAL, "%s: failed to resolve %s: %s",
+ xlog(D_PARSE, "%s: failed to resolve %s: %s",
__func__, buf, gai_strerror(error));
return NULL;
}
diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
index 614c3dc..bc3f00f 100644
--- a/utils/exportfs/exportfs.c
+++ b/utils/exportfs/exportfs.c
@@ -108,11 +108,14 @@ main(int argc, char **argv)
xlog_stderr(1);
xlog_syslog(0);
- while ((c = getopt(argc, argv, "afhio:ruvs")) != EOF) {
+ while ((c = getopt(argc, argv, "ad:fhio:ruvs")) != EOF) {
switch(c) {
case 'a':
f_all = 1;
break;
+ case 'd':
+ xlog_sconfig(optarg, 1);
+ break;
case 'f':
force_flush = 1;
break;
@@ -869,6 +872,6 @@ error(nfs_export *exp, int err)
static void
usage(const char *progname, int n)
{
- fprintf(stderr, "usage: %s [-afhioruvs] [host:/path]\n", progname);
+ fprintf(stderr, "usage: %s [-adfhioruvs] [host:/path]\n", progname);
exit(n);
}
diff --git a/utils/exportfs/exportfs.man b/utils/exportfs/exportfs.man
index 75d952a..fdf9260 100644
--- a/utils/exportfs/exportfs.man
+++ b/utils/exportfs/exportfs.man
@@ -88,6 +88,9 @@ appropriate export entry for the host given in
to be added to the kernel's export table.
.SH OPTIONS
.TP
+.B \-d kind " or " \-\-debug kind
+Turn on debugging. Valid kinds are: all, auth, call, general and parse.
+.TP
.B -a
Export or unexport all directories.
.TP

87
SOURCES/nfs-utils-1.3.0-exportfs-ipv6-arg.patch

@ -0,0 +1,87 @@ @@ -0,0 +1,87 @@
commit 7f5f7fe118b87fbc6a2c6cc52aff808564d907a4
Author: Todd Vierling <todd.vierling@oracle.com>
Date: Fri Sep 19 10:32:55 2014 -0400

exportfs: Properly parse IPv6 literal strings with null termination
The original implementation was using strncpy() with a truncation
length to an uninitialized stack buffer, leaving a string that
was only null terminated by luck.
While here, change to use no-copy semantics (no extra buffer) to
avoid buffer overflows altogether. exportfs already modifies argv
contents elsewhere, so this doesn't break anything anew.
Fixes: 4663c648 (exportfs: Support raw IPv6 addresses with
"client:/path")
Signed-off-by: Todd Vierling <todd.vierling@oracle.com>
Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
index e7d1ac8..bdea12b 100644
--- a/utils/exportfs/exportfs.c
+++ b/utils/exportfs/exportfs.c
@@ -351,16 +351,15 @@ static int exportfs_generic(char *arg, char *options, int verbose)
static int exportfs_ipv6(char *arg, char *options, int verbose)
{
- char *path, *c, hname[NI_MAXHOST + strlen("/128")];
+ char *path, *c;
arg++;
c = strchr(arg, ']');
if (c == NULL)
return 1;
- strncpy(hname, arg, c - arg);
/* no colon means this is a wildcarded DNS hostname */
- if (strchr(hname, ':') == NULL)
+ if (memchr(arg, ':', c - arg) == NULL)
return exportfs_generic(--arg, options, verbose);
path = strstr(c, ":/");
@@ -370,9 +369,9 @@ static int exportfs_ipv6(char *arg, char *options, int verbose)
/* if there's anything between the closing brace and the
* path separator, it's probably a prefix length */
- strcat(hname, ++c);
+ memmove(c, c + 1, path - c);
- exportfs_parsed(hname, path, options, verbose);
+ exportfs_parsed(arg, path, options, verbose);
return 0;
}
@@ -458,16 +457,15 @@ static int unexportfs_generic(char *arg, int verbose)
static int unexportfs_ipv6(char *arg, int verbose)
{
- char *path, *c, hname[NI_MAXHOST + strlen("/128")];
+ char *path, *c;
arg++;
c = strchr(arg, ']');
if (c == NULL)
return 1;
- strncpy(hname, arg, c - arg);
/* no colon means this is a wildcarded DNS hostname */
- if (strchr(hname, ':') == NULL)
+ if (memchr(arg, ':', c - arg) == NULL)
return unexportfs_generic(--arg, verbose);
path = strstr(c, ":/");
@@ -477,9 +475,9 @@ static int unexportfs_ipv6(char *arg, int verbose)
/* if there's anything between the closing brace and the
* path separator, it's probably a prefix length */
- strcat(hname, ++c);
+ memmove(c, c + 1, path - c);
- unexportfs_parsed(hname, path, verbose);
+ unexportfs_parsed(arg, path, verbose);
return 0;
}

83
SOURCES/nfs-utils-1.3.0-exportfs-noreaddirplus.patch

@ -0,0 +1,83 @@ @@ -0,0 +1,83 @@
commit 4017afe28d640c535109576bd149bc7e0345f075
Author: Rajesh Ghanekar <rajesh_ghanekar@symantec.com>
Date: Wed Aug 20 14:00:59 2014 -0400

nfs-utils: Allow turning off nfsv3 readdir_plus
One of our customer's application only needs file names, not file
attributes. With directories having 10K+ inodes (assuming buffer cache
has directory blocks cached having file names, but inode cache is
limited and hence need eviction of older cached inodes), older inodes
are evicted periodically. So if they keep on doing readdir(2) from NSF
client on multiple directories, some directory's files are periodically
removed from inode cache and hence new readdir(2) on same directory
requires disk access to bring back inodes again to inode cache.
As READDIRPLUS request fetches attributes also, doing getattr on each
file on server, it causes unnecessary disk accesses. If READDIRPLUS on
NFS client is returned with -ENOTSUPP, NFS client uses READDIR request
which just gets the names of the files in a directory, not attributes,
hence avoiding disk accesses on server.
There's already a corresponding client-side mount option, but an export
option reduces the need for configuration across multiple clients.
This flag affects NFSv3 only. If it turns out it's needed for NFSv4 as
well then we may have to figure out how to extend the behavior to NFSv4,
but it's not currently obvious how to do that.
Signed-off-by: Rajesh Ghanekar <rajesh_ghanekar@symantec.com>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/support/include/nfs/export.h b/support/include/nfs/export.h
index 1547a87..2f59e6a 100644
--- a/support/include/nfs/export.h
+++ b/support/include/nfs/export.h
@@ -17,7 +17,8 @@
#define NFSEXP_ALLSQUASH 0x0008
#define NFSEXP_ASYNC 0x0010
#define NFSEXP_GATHERED_WRITES 0x0020
-/* 40, 80, 100 unused */
+#define NFSEXP_NOREADDIRPLUS 0x0040
+/* 80, 100 unused */
#define NFSEXP_NOHIDE 0x0200
#define NFSEXP_NOSUBTREECHECK 0x0400
#define NFSEXP_NOAUTHNLM 0x0800
diff --git a/support/nfs/exports.c b/support/nfs/exports.c
index 819d6c4..eb782b9 100644
--- a/support/nfs/exports.c
+++ b/support/nfs/exports.c
@@ -273,6 +273,8 @@ putexportent(struct exportent *ep)
"in" : "");
fprintf(fp, "%sacl,", (ep->e_flags & NFSEXP_NOACL)?
"no_" : "");
+ if (ep->e_flags & NFSEXP_NOREADDIRPLUS)
+ fprintf(fp, "nordirplus,");
if (ep->e_flags & NFSEXP_FSID) {
fprintf(fp, "fsid=%d,", ep->e_fsid);
}
@@ -539,6 +541,8 @@ parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr)
clearflags(NFSEXP_ASYNC, active, ep);
else if (!strcmp(opt, "async"))
setflags(NFSEXP_ASYNC, active, ep);
+ else if (!strcmp(opt, "nordirplus"))
+ setflags(NFSEXP_NOREADDIRPLUS, active, ep);
else if (!strcmp(opt, "nohide"))
setflags(NFSEXP_NOHIDE, active, ep);
else if (!strcmp(opt, "hide"))
diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man
index e8b29df..3d974d9 100644
--- a/utils/exportfs/exports.man
+++ b/utils/exportfs/exports.man
@@ -360,6 +360,11 @@ supported so the same configuration can be made to work on old and new
kernels alike.
.TP
+.IR nordirplus
+This option will disable READDIRPLUS request handling. When set,
+READDIRPLUS requests from NFS clients return NFS3ERR_NOTSUPP, and
+clients fall back on READDIR. This option affects only NFSv3 clients.
+.TP
.IR refer= path@host[+host][:path@host[+host]]
A client referencing the export point will be directed to choose from
the given list an alternative location for the filesystem.

12
SOURCES/nfs-utils-1.3.0-exportfs-path-comp.patch

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig 2017-06-15 11:28:59.541764508 -0400
+++ nfs-utils-1.3.0/utils/exportfs/exportfs.c 2017-06-15 11:30:04.699701243 -0400
@@ -421,6 +421,8 @@ unexportfs_parsed(char *hname, char *pat
nlen--;
for (exp = exportlist[htype].p_head; exp; exp = exp->m_next) {
+ if (strlen(exp->m_export.e_path) != nlen)
+ continue;
if (path && strncmp(path, exp->m_export.e_path, nlen))
continue;
if (htype != exp->m_client->m_type)

41
SOURCES/nfs-utils-1.3.0-exportfs-redundant.patch

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
diff -up nfs-utils-1.3.0/support/nfs/exports.c.orig nfs-utils-1.3.0/support/nfs/exports.c
--- nfs-utils-1.3.0/support/nfs/exports.c.orig 2017-02-27 18:24:26.485237519 -0500
+++ nfs-utils-1.3.0/support/nfs/exports.c 2017-02-27 18:25:49.296652027 -0500
@@ -197,7 +197,6 @@ static const struct secinfo_flag_display
const char *set;
const char *unset;
} secinfo_flag_displaymap[] = {
- { NFSEXP_READONLY, "ro", "rw" },
{ NFSEXP_INSECURE_PORT, "insecure", "secure" },
{ NFSEXP_ROOTSQUASH, "root_squash", "no_root_squash" },
{ NFSEXP_ALLSQUASH, "all_squash", "no_all_squash" },
diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig 2017-02-27 18:24:26.429237915 -0500
+++ nfs-utils-1.3.0/utils/exportfs/exportfs.c 2017-02-27 18:25:49.297652020 -0500
@@ -814,20 +814,18 @@ dump(int verbose, int export_format)
c = dumpopt(c, "rw");
if (ep->e_flags & NFSEXP_ASYNC)
c = dumpopt(c, "async");
+ else
+ c = dumpopt(c, "sync");
if (ep->e_flags & NFSEXP_GATHERED_WRITES)
c = dumpopt(c, "wdelay");
+ else
+ c = dumpopt(c, "no_wdelay");
if (ep->e_flags & NFSEXP_NOHIDE)
c = dumpopt(c, "nohide");
+ else
+ c = dumpopt(c, "hide");
if (ep->e_flags & NFSEXP_CROSSMOUNT)
c = dumpopt(c, "crossmnt");
- if (ep->e_flags & NFSEXP_INSECURE_PORT)
- c = dumpopt(c, "insecure");
- if (ep->e_flags & NFSEXP_ROOTSQUASH)
- c = dumpopt(c, "root_squash");
- else
- c = dumpopt(c, "no_root_squash");
- if (ep->e_flags & NFSEXP_ALLSQUASH)
- c = dumpopt(c, "all_squash");
if (ep->e_flags & NFSEXP_NOSUBTREECHECK)
c = dumpopt(c, "no_subtree_check");
if (ep->e_flags & NFSEXP_NOAUTHNLM)

64
SOURCES/nfs-utils-1.3.0-exportfs-securitylabel.patch

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
diff -up nfs-utils-1.3.0/support/include/nfs/export.h.orig nfs-utils-1.3.0/support/include/nfs/export.h
--- nfs-utils-1.3.0/support/include/nfs/export.h.orig 2017-03-27 10:07:41.440397336 -0400
+++ nfs-utils-1.3.0/support/include/nfs/export.h 2017-03-27 10:08:57.195772235 -0400
@@ -18,7 +18,8 @@
#define NFSEXP_ASYNC 0x0010
#define NFSEXP_GATHERED_WRITES 0x0020
#define NFSEXP_NOREADDIRPLUS 0x0040
-/* 80, 100 unused */
+#define NFSEXP_SECURITY_LABEL 0x0080
+/* 0x100 unused */
#define NFSEXP_NOHIDE 0x0200
#define NFSEXP_NOSUBTREECHECK 0x0400
#define NFSEXP_NOAUTHNLM 0x0800
diff -up nfs-utils-1.3.0/support/nfs/exports.c.orig nfs-utils-1.3.0/support/nfs/exports.c
--- nfs-utils-1.3.0/support/nfs/exports.c.orig 2017-03-27 10:07:41.549399315 -0400
+++ nfs-utils-1.3.0/support/nfs/exports.c 2017-03-27 10:08:58.441794848 -0400
@@ -274,6 +274,8 @@ putexportent(struct exportent *ep)
"no_" : "");
if (ep->e_flags & NFSEXP_NOREADDIRPLUS)
fprintf(fp, "nordirplus,");
+ if (ep->e_flags & NFSEXP_SECURITY_LABEL)
+ fprintf(fp, "security_label,");
fprintf(fp, "%spnfs,", (ep->e_flags & NFSEXP_PNFS)? "" : "no_");
if (ep->e_flags & NFSEXP_FSID) {
fprintf(fp, "fsid=%d,", ep->e_fsid);
@@ -543,6 +545,8 @@ parseopts(char *cp, struct exportent *ep
setflags(NFSEXP_ASYNC, active, ep);
else if (!strcmp(opt, "nordirplus"))
setflags(NFSEXP_NOREADDIRPLUS, active, ep);
+ else if (!strcmp(opt, "security_label"))
+ setflags(NFSEXP_SECURITY_LABEL, active, ep);
else if (!strcmp(opt, "nohide"))
setflags(NFSEXP_NOHIDE, active, ep);
else if (!strcmp(opt, "hide"))
diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig 2017-03-27 10:08:58.441794848 -0400
+++ nfs-utils-1.3.0/utils/exportfs/exportfs.c 2017-03-27 10:11:00.939046616 -0400
@@ -835,6 +835,8 @@ dump(int verbose, int export_format)
c = dumpopt(c, "no_subtree_check");
if (ep->e_flags & NFSEXP_NOAUTHNLM)
c = dumpopt(c, "insecure_locks");
+ if (ep->e_flags & NFSEXP_SECURITY_LABEL)
+ c = dumpopt(c, "security_label");
if (ep->e_flags & NFSEXP_NOACL)
c = dumpopt(c, "no_acl");
if (ep->e_flags & NFSEXP_PNFS)
diff -up nfs-utils-1.3.0/utils/exportfs/exports.man.orig nfs-utils-1.3.0/utils/exportfs/exports.man
--- nfs-utils-1.3.0/utils/exportfs/exports.man.orig 2017-03-27 10:07:41.515398698 -0400
+++ nfs-utils-1.3.0/utils/exportfs/exports.man 2017-03-27 10:08:58.441794848 -0400
@@ -417,6 +417,14 @@ devices. The default can be explicitly r
.I no_pnfs
option.
+.TP
+.IR security_label
+With this option set, clients using NFSv4.2 or higher will be able to
+set and retrieve security labels (such as those used by SELinux). This
+will only work if all clients use a consistent security policy. Note
+that early kernels did not support this export option, and instead
+enabled security labels by default.
+
.SS User ID Mapping
.PP
.B nfsd

22
SOURCES/nfs-utils-1.3.0-exportfs-slashes.patch

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig 2016-05-03 10:50:17.226864000 -0400
+++ nfs-utils-1.3.0/utils/exportfs/exportfs.c 2016-05-03 10:51:49.848199000 -0400
@@ -402,8 +402,17 @@ unexportfs_parsed(char *hname, char *pat
hname = ai->ai_canonname;
}
+ /*
+ * It's possible the specified path ends with a '/'. But
+ * the entry from exportlist won't has the trailing '/',
+ * so need to deal with it.
+ */
+ size_t nlen = strlen(path);
+ while (path[nlen - 1] == '/')
+ nlen--;
+
for (exp = exportlist[htype].p_head; exp; exp = exp->m_next) {
- if (path && strcmp(path, exp->m_export.e_path))
+ if (path && strncmp(path, exp->m_export.e_path, nlen))
continue;
if (htype != exp->m_client->m_type)
continue;

35
SOURCES/nfs-utils-1.3.0-gssd-default-tcp.patch

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
commit 1ee2184248251ff44ae1ba557f12151cb8cf93ff
Author: Chuck Lever <chuck.lever@oracle.com>
Date: Mon Nov 2 08:47:41 2015 -0500

gssd: Make TCP the default protocol for GSSD connections.
No failure case if gssd doesn't recognize the kernel's requested
protocol. Caught with "protocol=rdma" upcall.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index 11168b2..cee8991 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -348,16 +348,9 @@ create_auth_rpc_client(struct clnt_info *clp,
printerr(2, "creating %s client for server %s\n", clp->protocol,
clp->servername);
- if ((strcmp(clp->protocol, "tcp")) == 0) {
- protocol = IPPROTO_TCP;
- } else if ((strcmp(clp->protocol, "udp")) == 0) {
+ protocol = IPPROTO_TCP;
+ if ((strcmp(clp->protocol, "udp")) == 0)
protocol = IPPROTO_UDP;
- } else {
- printerr(0, "WARNING: unrecognized protocol, '%s', requested "
- "for connection to server %s for user with uid %d\n",
- clp->protocol, clp->servername, uid);
- goto out_fail;
- }
switch (addr->sa_family) {
case AF_INET:

27
SOURCES/nfs-utils-1.3.0-gssd-noclear-retval.patch

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
commit a705076172b274463563416adffe55f129740267
Author: Steve Dickson <steved@redhat.com>
Date: Thu Jul 30 17:06:39 2015 -0400

rpc.gssd: Only clear the retval if it has not been set
In gssd_search_krb5_keytab() an error code can be
cleared by blindly setting retval to zero.
Reported-by: Jianhong Yin <jiyin@redhat.com>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
index f1ebc0d..ecf17a2 100644
--- a/utils/gssd/krb5_util.c
+++ b/utils/gssd/krb5_util.c
@@ -772,7 +772,9 @@ gssd_search_krb5_keytab(krb5_context context, krb5_keytab kt,
"keytab '%s'\n", k5err, kt_name);
}
- retval = 0;
+ /* Only clear the retval if has not been set */
+ if (retval < 0)
+ retval = 0;
out:
free(k5err);
return retval;

26
SOURCES/nfs-utils-1.3.0-gssd-rdma-to-tcp.patch

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
diff -up nfs-utils-1.3.0/utils/gssd/gssd.c.orig nfs-utils-1.3.0/utils/gssd/gssd.c
--- nfs-utils-1.3.0/utils/gssd/gssd.c.orig 2017-02-28 14:24:20.296676493 -0500
+++ nfs-utils-1.3.0/utils/gssd/gssd.c 2017-02-28 14:45:36.140482510 -0500
@@ -305,6 +305,22 @@ gssd_read_service_info(int dirfd, struct
goto fail;
}
+ /*
+ * The user space RPC library has no support for
+ * RPC-over-RDMA at this time, so change 'rdma'
+ * to 'tcp', and '20049' to '2049'.
+ */
+ if (strcmp(protoname, "rdma") == 0) {
+ free(protoname);
+ protoname = strdup("tcp");
+ if (!protoname)
+ goto fail;
+ free(port);
+ port = strdup("2049");
+ if (!port)
+ goto fail;
+ }
+
if (!gssd_addrstr_to_sockaddr((struct sockaddr *)&clp->addr,
address, port ? port : ""))
goto fail;

287
SOURCES/nfs-utils-1.3.0-gssd-tgt-flood.patch

@ -0,0 +1,287 @@ @@ -0,0 +1,287 @@
diff -up nfs-utils-1.3.0/utils/gssd/gssd_proc.c.old nfs-utils-1.3.0/utils/gssd/gssd_proc.c
--- nfs-utils-1.3.0/utils/gssd/gssd_proc.c.old 2015-09-24 09:48:40.833593000 -0400
+++ nfs-utils-1.3.0/utils/gssd/gssd_proc.c 2015-09-24 09:50:58.747069000 -0400
@@ -1023,6 +1023,113 @@ change_identity(uid_t uid)
return 0;
}
+AUTH *
+krb5_not_machine_creds(struct clnt_info *clp, uid_t uid, char *tgtname,
+ int *downcall_err, int *chg_err, CLIENT **rpc_clnt)
+{
+ AUTH *auth = NULL;
+ gss_cred_id_t gss_cred;
+ char **dname;
+ int err, resp = -1;
+
+ printerr(1, "krb5_not_machine_creds: uid %d tgtname %s\n",
+ uid, tgtname);
+
+ *chg_err = change_identity(uid);
+ if (*chg_err) {
+ printerr(0, "WARNING: failed to change identity: %s",
+ strerror(*chg_err));
+ goto out;
+ }
+
+ /** Tell krb5 gss which credentials cache to use.
+ * Try first to acquire credentials directly via GSSAPI
+ */
+ err = gssd_acquire_user_cred(&gss_cred);
+ if (err == 0)
+ resp = create_auth_rpc_client(clp, tgtname, rpc_clnt,
+ &auth, uid,
+ AUTHTYPE_KRB5, gss_cred);
+
+ /** if create_auth_rplc_client fails try the traditional
+ * method of trolling for credentials
+ */
+ for (dname = ccachesearch; resp != 0 && *dname != NULL; dname++) {
+ err = gssd_setup_krb5_user_gss_ccache(uid, clp->servername,
+ *dname);
+ if (err == -EKEYEXPIRED)
+ *downcall_err = -EKEYEXPIRED;
+ else if (err == 0)
+ resp = create_auth_rpc_client(clp, tgtname, rpc_clnt,
+ &auth, uid,AUTHTYPE_KRB5,
+ GSS_C_NO_CREDENTIAL);
+ }
+
+out:
+ return auth;
+}
+
+AUTH *
+krb5_use_machine_creds(struct clnt_info *clp, uid_t uid, char *tgtname,
+ char *service, CLIENT **rpc_clnt)
+{
+ AUTH *auth = NULL;
+ char **credlist = NULL;
+ char **ccname;
+ int nocache = 0;
+ int success = 0;
+
+ printerr(1, "krb5_use_machine_creds: uid %d tgtname %s\n",
+ uid, tgtname);
+
+ do {
+ gssd_refresh_krb5_machine_credential(clp->servername, NULL,
+ service);
+ /*
+ * Get a list of credential cache names and try each
+ * of them until one works or we've tried them all
+ */
+ if (gssd_get_krb5_machine_cred_list(&credlist)) {
+ printerr(0, "ERROR: No credentials found "
+ "for connection to server %s\n",
+ clp->servername);
+ goto out;
+ }
+ for (ccname = credlist; ccname && *ccname; ccname++) {
+ gssd_setup_krb5_machine_gss_ccache(*ccname);
+ if ((create_auth_rpc_client(clp, tgtname, rpc_clnt,
+ &auth, uid,
+ AUTHTYPE_KRB5,
+ GSS_C_NO_CREDENTIAL)) == 0) {
+ /* Success! */
+ success++;
+ break;
+ }
+ printerr(2, "WARNING: Failed to create machine krb5"
+ "context with cred cache %s for server %s\n",
+ *ccname, clp->servername);
+ }
+ gssd_free_krb5_machine_cred_list(credlist);
+ if (!success) {
+ if(nocache == 0) {
+ nocache++;
+ printerr(2, "WARNING: Machine cache prematurely" "expired or corrupted trying to"
+ "recreate cache for server %s\n",
+ clp->servername);
+ } else {
+ printerr(1, "WARNING: Failed to create machine"
+ "krb5 context with any credentials"
+ "cache for server %s\n",
+ clp->servername);
+ goto out;
+ }
+ }
+ } while(!success);
+
+out:
+ return auth;
+}
+
/*
* this code uses the userland rpcsec gss library to create a krb5
* context on behalf of the kernel
@@ -1035,40 +1142,13 @@ process_krb5_upcall(struct clnt_info *cl
AUTH *auth = NULL;
struct authgss_private_data pd;
gss_buffer_desc token;
- char **credlist = NULL;
- char **ccname;
- char **dirname;
- int create_resp = -1;
int err, downcall_err = -EACCES;
- gss_cred_id_t gss_cred;
OM_uint32 maj_stat, min_stat, lifetime_rec;
- pid_t pid;
+ pid_t pid, childpid = -1;
gss_name_t gacceptor = GSS_C_NO_NAME;
gss_OID mech;
gss_buffer_desc acceptor = {0};
- pid = fork();
- switch(pid) {
- case 0:
- /* Child: fall through to rest of function */
- break;
- case -1:
- /* fork() failed! */
- printerr(0, "WARNING: unable to fork() to handle upcall: %s\n",
- strerror(errno));
- return;
- default:
- /* Parent: just wait on child to exit and return */
- do {
- pid = wait(&err);
- } while(pid == -1 && errno != -ECHILD);
-
- if (WIFSIGNALED(err))
- printerr(0, "WARNING: forked child was killed with signal %d\n",
- WTERMSIG(err));
- return;
- }
-
printerr(1, "handling krb5 upcall (%s)\n", clp->dirname);
token.length = 0;
@@ -1101,76 +1181,48 @@ process_krb5_upcall(struct clnt_info *cl
if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0 &&
service == NULL)) {
- err = change_identity(uid);
- if (err) {
- printerr(0, "WARNING: failed to change identity: %s",
- strerror(err));
- goto out_return_error;
- }
+ /* already running as uid 0 */
+ if (uid == 0)
+ goto no_fork;
+
+ pid = fork();
+ switch(pid) {
+ case 0:
+ /* Child: fall through to rest of function */
+ childpid = getpid();
+ unsetenv("KRB5CCNAME");
+ printerr(1, "CHILD forked pid %d \n", childpid);
+ break;
+ case -1:
+ /* fork() failed! */
+ printerr(0, "WARNING: unable to fork() to handle"
+ "upcall: %s\n", strerror(errno));
+ return;
+ default:
+ /* Parent: just wait on child to exit and return */
+ do {
+ pid = wait(&err);
+ } while(pid == -1 && errno != -ECHILD);
- /* Tell krb5 gss which credentials cache to use */
- /* Try first to acquire credentials directly via GSSAPI */
- err = gssd_acquire_user_cred(&gss_cred);
- if (!err)
- create_resp = create_auth_rpc_client(clp, tgtname, &rpc_clnt, &auth, uid,
- AUTHTYPE_KRB5, gss_cred);
- /* if create_auth_rplc_client fails try the traditional method of
- * trolling for credentials */
- for (dirname = ccachesearch; create_resp != 0 && *dirname != NULL; dirname++) {
- err = gssd_setup_krb5_user_gss_ccache(uid, clp->servername, *dirname);
- if (err == -EKEYEXPIRED)
- downcall_err = -EKEYEXPIRED;
- else if (!err)
- create_resp = create_auth_rpc_client(clp, tgtname, &rpc_clnt, &auth, uid,
- AUTHTYPE_KRB5, GSS_C_NO_CREDENTIAL);
+ if (WIFSIGNALED(err))
+ printerr(0, "WARNING: forked child was killed"
+ "with signal %d\n", WTERMSIG(err));
+ return;
}
+no_fork:
+
+ auth = krb5_not_machine_creds(clp, uid, tgtname, &downcall_err,
+ &err, &rpc_clnt);
+ if (err)
+ goto out_return_error;
}
- if (create_resp != 0) {
+ if (auth == NULL) {
if (uid == 0 && (root_uses_machine_creds == 1 ||
service != NULL)) {
- int nocache = 0;
- int success = 0;
- do {
- gssd_refresh_krb5_machine_credential(clp->servername,
- NULL, service);
- /*
- * Get a list of credential cache names and try each
- * of them until one works or we've tried them all
- */
- if (gssd_get_krb5_machine_cred_list(&credlist)) {
- printerr(0, "ERROR: No credentials found "
- "for connection to server %s\n",
- clp->servername);
- goto out_return_error;
- }
- for (ccname = credlist; ccname && *ccname; ccname++) {
- gssd_setup_krb5_machine_gss_ccache(*ccname);
- if ((create_auth_rpc_client(clp, tgtname, &rpc_clnt,
- &auth, uid,
- AUTHTYPE_KRB5,
- GSS_C_NO_CREDENTIAL)) == 0) {
- /* Success! */
- success++;
- break;
- }
- printerr(2, "WARNING: Failed to create machine krb5 context "
- "with credentials cache %s for server %s\n",
- *ccname, clp->servername);
- }
- gssd_free_krb5_machine_cred_list(credlist);
- if (!success) {
- if(nocache == 0) {
- nocache++;
- printerr(2, "WARNING: Machine cache is prematurely expired or corrupted "
- "trying to recreate cache for server %s\n", clp->servername);
- } else {
- printerr(1, "WARNING: Failed to create machine krb5 context "
- "with any credentials cache for server %s\n",
- clp->servername);
- goto out_return_error;
- }
- }
- } while(!success);
+ auth = krb5_use_machine_creds(clp, uid, tgtname,
+ service, &rpc_clnt);
+ if (auth == NULL)
+ goto out_return_error;
} else {
printerr(1, "WARNING: Failed to create krb5 context "
"for user with uid %d for server %s\n",
@@ -1225,7 +1277,12 @@ out:
AUTH_DESTROY(auth);
if (rpc_clnt)
clnt_destroy(rpc_clnt);
- exit(0);
+
+ pid = getpid();
+ if (pid == childpid)
+ exit(0);
+ else
+ return;
out_return_error:
do_error_downcall(fd, uid, downcall_err);

69
SOURCES/nfs-utils-1.3.0-gssd-thread-safe.patch

@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index 646d7e3..14cf7b8 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -728,10 +728,18 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
char *target = NULL;
char *service = NULL;
char *enctypes = NULL;
+ char *upcall_str;
+ char *pbuf = info->lbuf;
printerr(2, "\n%s: '%s' (%s)\n", __func__, info->lbuf, clp->relpath);
- for (p = strtok(info->lbuf, " "); p; p = strtok(NULL, " ")) {
+ upcall_str = strdup(info->lbuf);
+ if (upcall_str == NULL) {
+ printerr(0, "ERROR: malloc failure\n");
+ goto out_nomem;
+ }
+
+ while ((p = strsep(&pbuf, " "))) {
if (!strncmp(p, "mech=", strlen("mech=")))
mech = p + strlen("mech=");
else if (!strncmp(p, "uid=", strlen("uid=")))
@@ -747,7 +755,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
if (!mech || strlen(mech) < 1) {
printerr(0, "WARNING: handle_gssd_upcall: "
"failed to find gss mechanism name "
- "in upcall string '%s'\n", info->lbuf);
+ "in upcall string '%s'\n", upcall_str);
goto out;
}
@@ -760,7 +768,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
if (!uidstr) {
printerr(0, "WARNING: handle_gssd_upcall: "
"failed to find uid "
- "in upcall string '%s'\n", info->lbuf);
+ "in upcall string '%s'\n", upcall_str);
goto out;
}
@@ -773,7 +781,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
if (target && strlen(target) < 1) {
printerr(0, "WARNING: handle_gssd_upcall: "
"failed to parse target name "
- "in upcall string '%s'\n", info->lbuf);
+ "in upcall string '%s'\n", upcall_str);
goto out;
}
@@ -788,7 +796,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
if (service && strlen(service) < 1) {
printerr(0, "WARNING: handle_gssd_upcall: "
"failed to parse service type "
- "in upcall string '%s'\n", info->lbuf);
+ "in upcall string '%s'\n", upcall_str);
goto out;
}
@@ -801,6 +809,8 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
do_error_downcall(clp->gssd_fd, uid, -EACCES);
}
out:
+ free(upcall_str);
+out_nomem:
free(info);
return;
}

60
SOURCES/nfs-utils-1.3.0-gssproxy.patch

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
diff -up nfs-utils-1.3.0/systemd/auth-rpcgss-module.service.orig nfs-utils-1.3.0/systemd/auth-rpcgss-module.service
--- nfs-utils-1.3.0/systemd/auth-rpcgss-module.service.orig 2014-09-30 14:51:14.000000000 -0400
+++ nfs-utils-1.3.0/systemd/auth-rpcgss-module.service 2014-09-30 14:51:14.000000000 -0400
@@ -0,0 +1,15 @@
+# We want to start gss-proxy on kernels that support it and rpc.svcgssd
+# on those that don't. Those services check for support by checking
+# for existence of the path /proc/net/rpc/use-gss-proxy. Before they
+# can perform that check, they need this module loaded. (Unless
+# rpcsec_gss support is built directly into the kernel, in which case this
+# unit will fail. But that's OK.)
+[Unit]
+Description=Kernel Module supporting RPCSEC_GSS
+Before=gssproxy.service rpc-svcgssd.service rpc-gssd.service
+Wants=gssproxy.service rpc-svcgssd.service rpc-gssd.service
+ConditionPathExists=/etc/krb5.keytab
+
+[Service]
+Type=oneshot
+ExecStart=/sbin/modprobe -q auth_rpcgss
diff -up nfs-utils-1.3.0/systemd/nfs-client.target.orig nfs-utils-1.3.0/systemd/nfs-client.target
--- nfs-utils-1.3.0/systemd/nfs-client.target.orig 2014-09-30 14:51:14.000000000 -0400
+++ nfs-utils-1.3.0/systemd/nfs-client.target 2014-09-30 14:51:55.000000000 -0400
@@ -5,9 +5,12 @@ Wants=remote-fs-pre.target
# Note: we don't "Wants=rpc-statd.service" as "mount.nfs" will arrange to
# start that on demand if needed.
-Wants=rpc-gssd.service rpc-svcgssd.service
Wants=nfs-blkmap.service rpc-statd-notify.service
-After=rpc-gssd.service rpc-svcgssd.service nfs-blkmap.service
+After=nfs-blkmap.service
+
+# GSS services dependencies and ordering
+Wants=auth-rpcgss-module.service
+After=rpc-gssd.service rpc-svcgssd.service gssproxy.service
[Install]
WantedBy=multi-user.target
diff -up nfs-utils-1.3.0/systemd/nfs-server.service.orig nfs-utils-1.3.0/systemd/nfs-server.service
--- nfs-utils-1.3.0/systemd/nfs-server.service.orig 2014-03-25 11:12:07.000000000 -0400
+++ nfs-utils-1.3.0/systemd/nfs-server.service 2014-09-30 14:51:14.000000000 -0400
@@ -2,14 +2,17 @@
Description=NFS server and services
Requires= network.target proc-fs-nfsd.mount rpcbind.target
Requires= nfs-mountd.service
-Wants=rpc-statd.service nfs-idmapd.service rpc-gssd.service rpc-svcgssd.service
+Wants=rpc-statd.service nfs-idmapd.service
Wants=rpc-statd-notify.service
After= network.target proc-fs-nfsd.mount rpcbind.target nfs-mountd.service
After= nfs-idmapd.service rpc-statd.service
-After= rpc-gssd.service rpc-svcgssd.service
Before= rpc-statd-notify.service
+# GSS services dependencies and ordering
+Wants=auth-rpcgss-module.service
+After=rpc-gssd.service gssproxy.service rpc-svcgssd.service
+
Wants=nfs-config.service
After=nfs-config.service

26
SOURCES/nfs-utils-1.3.0-hostpton-eainoname.patch

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
commit 23d26f9c9fd94406d0c1f4365e6180d59b744861
Author: Scott Mayhew <smayhew@redhat.com>
Date: Mon Nov 2 08:45:09 2015 -0500

exportfs: Restore the EAI_NONAME check in host_pton()
Commit d89e3fc7 removed the EAI_NONAME check altogether instead of just
moving the NULL check. This causes exportfs -u to incorrectly exit
with 1 whenever there's more than one MCL_FQDN export in the exportlist.
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/support/export/hostname.c b/support/export/hostname.c
index 169baa5..7a44d42 100644
--- a/support/export/hostname.c
+++ b/support/export/hostname.c
@@ -134,6 +134,8 @@ host_pton(const char *paddr)
break;
}
return ai;
+ case EAI_NONAME:
+ break;
case EAI_SYSTEM:
xlog(D_GENERAL, "%s: failed to convert %s: (%d) %m",
__func__, paddr, errno);

45
SOURCES/nfs-utils-1.3.0-libmount-umount-verbose.patch

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
diff -up nfs-utils-1.3.0/utils/mount/mount_libmount.c.orig nfs-utils-1.3.0/utils/mount/mount_libmount.c
--- nfs-utils-1.3.0/utils/mount/mount_libmount.c.orig 2014-03-25 11:12:07.000000000 -0400
+++ nfs-utils-1.3.0/utils/mount/mount_libmount.c 2014-10-24 09:46:11.158190704 -0400
@@ -173,7 +173,7 @@ static int umount_main(struct libmnt_con
{
int rc, c;
char *spec = NULL, *opts = NULL;
- int ret = EX_FAIL;
+ int ret = EX_FAIL, verbose = 0;
static const struct option longopts[] = {
{ "force", 0, 0, 'f' },
@@ -200,6 +200,8 @@ static int umount_main(struct libmnt_con
return EX_USAGE;
}
+ verbose = mnt_context_is_verbose(cxt);
+
if (optind < argc)
spec = argv[optind++];
@@ -227,6 +229,10 @@ static int umount_main(struct libmnt_con
goto err;
}
+ if (verbose)
+ printf(_("%s: %s mount point detected\n"), spec,
+ mnt_context_get_fstype(cxt));
+
opts = retrieve_mount_options(mnt_context_get_fs(cxt));
if (!mnt_context_is_lazy(cxt)) {
@@ -262,6 +268,12 @@ static int umount_main(struct libmnt_con
}
ret = EX_SUCCESS;
err:
+ if (verbose) {
+ if (ret == EX_SUCCESS)
+ printf(_("%s: umounted\n"), spec);
+ else
+ printf(_("%s: umount failed\n"), spec);
+ }
free(opts);
return ret;
}

30
SOURCES/nfs-utils-1.3.0-mount-addressfailed.patch

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
diff -up nfs-utils-1.3.0/utils/nfsd/nfssvc.c.orig nfs-utils-1.3.0/utils/nfsd/nfssvc.c
--- nfs-utils-1.3.0/utils/nfsd/nfssvc.c.orig 2017-10-05 11:34:15.701116069 -0400
+++ nfs-utils-1.3.0/utils/nfsd/nfssvc.c 2017-10-05 11:35:36.493684800 -0400
@@ -112,7 +112,7 @@ static int
nfssvc_setfds(const struct addrinfo *hints, const char *node, const char *port)
{
int fd, on = 1, fac = L_ERROR;
- int sockfd = -1, rc = 0;
+ int sockfd = -1, rc = 0, bounded = 0;
struct addrinfo *addrhead = NULL, *addr;
char *proto, *family;
@@ -234,6 +234,8 @@ nfssvc_setfds(const struct addrinfo *hin
rc = errno;
goto error;
}
+ bounded++;
+
close(fd);
close(sockfd);
sockfd = fd = -1;
@@ -246,7 +248,7 @@ error:
close(sockfd);
if (addrhead)
freeaddrinfo(addrhead);
- return rc;
+ return (bounded ? 0 : rc);
}
int

590
SOURCES/nfs-utils-1.3.0-mount-default-v42.patch

@ -0,0 +1,590 @@ @@ -0,0 +1,590 @@
diff --git a/configure.ac b/configure.ac
index 56f7f3e..802fd58 100644
--- a/configure.ac
+++ b/configure.ac
@@ -172,10 +172,12 @@ AC_ARG_ENABLE(ipv6,
if test "$enable_mount" = yes; then
AC_ARG_ENABLE(mountconfig,
[AC_HELP_STRING([--enable-mountconfig],
- [enable mount to use a configuration file])],
+ [enable mount to use a configuration file @<:@default=yes@:>@])],
mountconfig=$enableval,
- mountconfig=no)
- if test "$enable_mountconfig" = yes; then
+ mountconfig=yes)
+ if test "$enable_mountconfig" = no; then
+ enable_mountconfig=
+ else
AC_DEFINE(MOUNT_CONFIG, 1,
[Define this if you want mount to read a configuration file])
AC_ARG_WITH(mountfile,
@@ -187,8 +189,6 @@ if test "$enable_mount" = yes; then
AC_SUBST(mountfile)
AC_DEFINE_UNQUOTED(MOUNTOPTS_CONFFILE, "$mountfile",
[This defines the location of the NFS mount configuration file])
- else
- enable_mountconfig=
fi
AC_SUBST(enable_mountconfig)
AM_CONDITIONAL(MOUNT_CONFIG, [test "$enable_mountconfig" = "yes"])
diff --git a/utils/mount/configfile.c b/utils/mount/configfile.c
index 39d3741..0a4cc04 100644
--- a/utils/mount/configfile.c
+++ b/utils/mount/configfile.c
@@ -228,37 +228,8 @@ void free_all(void)
free(entry);
}
}
-static char *versions[] = {"v2", "v3", "v4", "vers", "nfsvers", NULL};
-static int
-check_vers(char *mopt, char *field)
-{
- int i, found=0;
-
- /*
- * First check to see if the config setting is one
- * of the many version settings
- */
- for (i=0; versions[i]; i++) {
- if (strcasestr(field, versions[i]) != NULL) {
- found++;
- break;
- }
- }
- if (!found)
- return 0;
- /*
- * It appears the version is being set, now see
- * if the version appears on the command
- */
- for (i=0; versions[i]; i++) {
- if (strcasestr(mopt, versions[i]) != NULL)
- return 1;
- }
-
- return 0;
-}
-unsigned long config_default_vers;
+struct nfs_version config_default_vers;
unsigned long config_default_proto;
extern sa_family_t config_default_family;
@@ -331,11 +302,6 @@ conf_parse_mntopts(char *section, char *arg, char *opts)
snprintf(buf, BUFSIZ, "%s=", node->field);
if (opts && strcasestr(opts, buf) != NULL)
continue;
- /*
- * Protocol verions can be set in a number of ways
- */
- if (opts && check_vers(opts, node->field))
- continue;
if (lookup_entry(node->field) != NULL)
continue;
diff --git a/utils/mount/network.c b/utils/mount/network.c
index 515249b..088caa1 100644
--- a/utils/mount/network.c
+++ b/utils/mount/network.c
@@ -92,9 +92,6 @@ static const char *nfs_version_opttbl[] = {
"v4",
"vers",
"nfsvers",
- "v4.0",
- "v4.1",
- "v4.2",
NULL,
};
@@ -1249,71 +1246,69 @@ nfs_nfs_program(struct mount_options *options, unsigned long *program)
* or FALSE if the option was specified with an invalid value.
*/
int
-nfs_nfs_version(struct mount_options *options, unsigned long *version)
+nfs_nfs_version(struct mount_options *options, struct nfs_version *version)
{
- long tmp;
+ char *version_key, *version_val, *cptr;
+ int i, found = 0;
- switch (po_rightmost(options, nfs_version_opttbl)) {
- case 0: /* v2 */
- *version = 2;
- return 1;
- case 1: /* v3 */
- *version = 3;
- return 1;
- case 2: /* v4 */
- *version = 4;
- return 1;
- case 3: /* vers */
- switch (po_get_numeric(options, "vers", &tmp)) {
- case PO_FOUND:
- if (tmp >= 2 && tmp <= 4) {
- *version = tmp;
- return 1;
- }
- nfs_error(_("%s: parsing error on 'vers=' option\n"),
- progname);
- return 0;
- case PO_NOT_FOUND:
- nfs_error(_("%s: parsing error on 'vers=' option\n"),
- progname);
- return 0;
- case PO_BAD_VALUE:
- nfs_error(_("%s: invalid value for 'vers=' option"),
- progname);
- return 0;
- }
- case 4: /* nfsvers */
- switch (po_get_numeric(options, "nfsvers", &tmp)) {
- case PO_FOUND:
- if (tmp >= 2 && tmp <= 4) {
- *version = tmp;
- return 1;
- }
- nfs_error(_("%s: parsing error on 'nfsvers=' option\n"),
- progname);
- return 0;
- case PO_NOT_FOUND:
- nfs_error(_("%s: parsing error on 'nfsvers=' option\n"),
- progname);
- return 0;
- case PO_BAD_VALUE:
- nfs_error(_("%s: invalid value for 'nfsvers=' option"),
- progname);
- return 0;
+ version->v_mode = V_DEFAULT;
+
+ for (i = 0; nfs_version_opttbl[i]; i++) {
+ if (po_contains_prefix(options, nfs_version_opttbl[i],
+ &version_key) == PO_FOUND) {
+ found++;
+ break;
}
- case 5: /* v4.0 */
- case 6: /* v4.1 */
- case 7: /* v4.2 */
- *version = 4;
+ }
+
+ if (!found)
return 1;
+
+ if (i <= 2 ) {
+ /* v2, v3, v4 */
+ version_val = version_key + 1;
+ version->v_mode = V_SPECIFIC;
+ } else if (i > 2 ) {
+ /* vers=, nfsvers= */
+ version_val = po_get(options, version_key);
}
- /*
- * NFS version wasn't specified. The pmap version value
- * will be filled in later by an rpcbind query in this case.
- */
- *version = 0;
+ if (!version_val)
+ goto ret_error;
+
+ if (!(version->major = strtol(version_val, &cptr, 10)))
+ goto ret_error;
+
+ if (version->major < 4)
+ version->v_mode = V_SPECIFIC;
+
+ if (*cptr == '.') {
+ version_val = ++cptr;
+ if (!(version->minor = strtol(version_val, &cptr, 10)) && cptr == version_val)
+ goto ret_error;
+ version->v_mode = V_SPECIFIC;
+ } else if (version->major > 3 && *cptr == '\0')
+ version->v_mode = V_GENERAL;
+
+ if (*cptr != '\0')
+ goto ret_error;
+
return 1;
+
+ret_error:
+ if (i <= 2 ) {
+ nfs_error(_("%s: parsing error on 'v' option"),
+ progname);
+ } else if (i == 3 ) {
+ nfs_error(_("%s: parsing error on 'vers=' option"),
+ progname);
+ } else if (i == 4) {
+ nfs_error(_("%s: parsing error on 'nfsvers=' option"),
+ progname);
+ }
+ version->v_mode = V_PARSE_ERR;
+ errno = EINVAL;
+ return 0;
}
/*
@@ -1632,10 +1627,13 @@ out_err:
int nfs_options2pmap(struct mount_options *options,
struct pmap *nfs_pmap, struct pmap *mnt_pmap)
{
+ struct nfs_version version;
+
if (!nfs_nfs_program(options, &nfs_pmap->pm_prog))
return 0;
- if (!nfs_nfs_version(options, &nfs_pmap->pm_vers))
+ if (!nfs_nfs_version(options, &version))
return 0;
+ nfs_pmap->pm_vers = version.major;
if (!nfs_nfs_protocol(options, &nfs_pmap->pm_prot))
return 0;
if (!nfs_nfs_port(options, &nfs_pmap->pm_port))
diff --git a/utils/mount/network.h b/utils/mount/network.h
index d7636d7..9cc5dec 100644
--- a/utils/mount/network.h
+++ b/utils/mount/network.h
@@ -57,9 +57,22 @@ int clnt_ping(struct sockaddr_in *, const unsigned long,
struct mount_options;
+enum {
+ V_DEFAULT = 0,
+ V_GENERAL,
+ V_SPECIFIC,
+ V_PARSE_ERR,
+};
+
+struct nfs_version {
+ unsigned long major;
+ unsigned long minor;
+ int v_mode;
+};
+
int nfs_nfs_proto_family(struct mount_options *options, sa_family_t *family);
int nfs_mount_proto_family(struct mount_options *options, sa_family_t *family);
-int nfs_nfs_version(struct mount_options *options, unsigned long *version);
+int nfs_nfs_version(struct mount_options *options, struct nfs_version *version);
int nfs_nfs_protocol(struct mount_options *options, unsigned long *protocol);
int nfs_options2pmap(struct mount_options *,
diff --git a/utils/mount/nfsumount.c b/utils/mount/nfsumount.c
index 3538d88..de284f2 100644
--- a/utils/mount/nfsumount.c
+++ b/utils/mount/nfsumount.c
@@ -179,10 +179,10 @@ static int nfs_umount_is_vers4(const struct mntentchn *mc)
options = po_split(pmc->m.mnt_opts);
if (options != NULL) {
- unsigned long version;
+ struct nfs_version version;
int rc = nfs_nfs_version(options, &version);
po_destroy(options);
- if (rc && version == 4)
+ if (rc && version.major == 4)
goto out_nfs4;
}
diff --git a/utils/mount/parse_opt.c b/utils/mount/parse_opt.c
index 75a0daa..7ba61c4 100644
--- a/utils/mount/parse_opt.c
+++ b/utils/mount/parse_opt.c
@@ -391,7 +391,7 @@ po_return_t po_append(struct mount_options *options, char *str)
}
/**
- * po_contains - check for presense of an option in a group
+ * po_contains - check for presence of an option in a group
* @options: pointer to mount options
* @keyword: pointer to a C string containing option keyword for which to search
*
@@ -410,6 +410,30 @@ po_found_t po_contains(struct mount_options *options, char *keyword)
}
/**
+ * po_contains_prefix - check for presence of an option matching a prefix
+ * @options: pointer to mount options
+ * @prefix: pointer to prefix to match against a keyword
+ * @keyword: pointer to a C string containing the option keyword if found
+ *
+ * On success, *keyword contains the pointer of the matching option's keyword.
+ */
+po_found_t po_contains_prefix(struct mount_options *options,
+ const char *prefix, char **keyword)
+{
+ struct mount_option *option;
+
+ if (options && prefix) {
+ for (option = options->head; option; option = option->next)
+ if (strncmp(option->keyword, prefix, strlen(prefix)) == 0) {
+ *keyword = option->keyword;
+ return PO_FOUND;
+ }
+ }
+
+ return PO_NOT_FOUND;
+}
+
+/**
* po_get - return the value of the rightmost instance of an option
* @options: pointer to mount options
* @keyword: pointer to a C string containing option keyword for which to search
diff --git a/utils/mount/parse_opt.h b/utils/mount/parse_opt.h
index 5037207..0745e0f 100644
--- a/utils/mount/parse_opt.h
+++ b/utils/mount/parse_opt.h
@@ -45,6 +45,8 @@ po_return_t po_join(struct mount_options *, char **);
po_return_t po_append(struct mount_options *, char *);
po_found_t po_contains(struct mount_options *, char *);
+po_found_t po_contains_prefix(struct mount_options *options,
+ const char *prefix, char **keyword);
char * po_get(struct mount_options *, char *);
po_found_t po_get_numeric(struct mount_options *,
char *, long *);
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index 5d80ed7..207a476 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -88,30 +88,50 @@ struct nfsmount_info {
struct mount_options *options; /* parsed mount options */
char **extra_opts; /* string for /etc/mtab */
- unsigned long version; /* NFS version */
+ struct nfs_version version; /* NFS version */
int flags, /* MS_ flags */
fake, /* actually do the mount? */
child; /* forked bg child? */
};
-#ifdef MOUNT_CONFIG
-static void nfs_default_version(struct nfsmount_info *mi);
static void nfs_default_version(struct nfsmount_info *mi)
{
- extern unsigned long config_default_vers;
+#ifdef MOUNT_CONFIG
+ extern struct nfs_version config_default_vers;
/*
* Use the default value set in the config file when
* the version has not been explicitly set.
*/
- if (mi->version == 0 && config_default_vers) {
- if (config_default_vers < 4)
- mi->version = config_default_vers;
+ if (config_default_vers.v_mode == V_PARSE_ERR) {
+ mi->version.v_mode = V_PARSE_ERR;
+ return;
}
-}
-#else
-inline void nfs_default_version(__attribute__ ((unused)) struct nfsmount_info *mi) {}
+
+ if (mi->version.v_mode == V_GENERAL &&
+ config_default_vers.v_mode == V_DEFAULT) {
+ mi->version.v_mode = V_SPECIFIC;
+ return;
+ }
+
+ if (mi->version.v_mode == V_DEFAULT &&
+ config_default_vers.v_mode != V_DEFAULT) {
+ mi->version.major = config_default_vers.major;
+ mi->version.minor = config_default_vers.minor;
+ return;
+ }
+
+ if (mi->version.v_mode == V_GENERAL &&
+ config_default_vers.v_mode != V_DEFAULT) {
+ if (mi->version.major == config_default_vers.major)
+ mi->version.minor = config_default_vers.minor;
+ return;
+ }
+
#endif /* MOUNT_CONFIG */
+ mi->version.major = 4;
+ mi->version.minor = 2;
+}
/*
* Obtain a retry timeout value based on the value of the "retry=" option.
@@ -300,7 +320,7 @@ static int nfs_set_version(struct nfsmount_info *mi)
return 0;
if (strncmp(mi->type, "nfs4", 4) == 0)
- mi->version = 4;
+ mi->version.major = 4;
/*
* Before 2.6.32, the kernel NFS client didn't
@@ -308,28 +328,44 @@ static int nfs_set_version(struct nfsmount_info *mi)
* 4 cannot be included when autonegotiating
* while running on those kernels.
*/
- if (mi->version == 0 &&
- linux_version_code() <= MAKE_VERSION(2, 6, 31))
- mi->version = 3;
+ if (mi->version.v_mode == V_DEFAULT &&
+ linux_version_code() <= MAKE_VERSION(2, 6, 31)) {
+ mi->version.major = 3;
+ mi->version.v_mode = V_SPECIFIC;
+ }
/*
* If we still don't know, check for version-specific
* mount options.
*/
- if (mi->version == 0) {
+ if (mi->version.v_mode == V_DEFAULT) {
if (po_contains(mi->options, "mounthost") ||
po_contains(mi->options, "mountaddr") ||
po_contains(mi->options, "mountvers") ||
- po_contains(mi->options, "mountproto"))
- mi->version = 3;
+ po_contains(mi->options, "mountproto")) {
+ mi->version.major = 3;
+ mi->version.v_mode = V_SPECIFIC;
+ }
}
/*
* If enabled, see if the default version was
* set in the config file
*/
- nfs_default_version(mi);
-
+ if (mi->version.v_mode != V_SPECIFIC) {
+ nfs_default_version(mi);
+ /*
+ * If the version was not specifically set, it will
+ * be set by autonegotiation later, so remove it now:
+ */
+ po_remove_all(mi->options, "v4");
+ po_remove_all(mi->options, "vers");
+ po_remove_all(mi->options, "nfsvers");
+ }
+
+ if (mi->version.v_mode == V_PARSE_ERR)
+ return 0;
+
return 1;
}
@@ -693,6 +729,7 @@ static int nfs_do_mount_v4(struct nfsmount_info *mi,
{
struct mount_options *options = po_dup(mi->options);
int result = 0;
+ char version_opt[16];
char *extra_opts = NULL;
if (!options) {
@@ -700,20 +737,24 @@ static int nfs_do_mount_v4(struct nfsmount_info *mi,
return result;
}
- if (mi->version == 0) {
- if (po_contains(options, "mounthost") ||
- po_contains(options, "mountaddr") ||
- po_contains(options, "mountvers") ||
- po_contains(options, "mountproto")) {
- /*
- * Since these mountd options are set assume version 3
- * is wanted so error out with EPROTONOSUPPORT so the
- * protocol negation starts with v3.
- */
- errno = EPROTONOSUPPORT;
- goto out_fail;
- }
- if (po_append(options, "vers=4") == PO_FAILED) {
+ if (po_contains(options, "mounthost") ||
+ po_contains(options, "mountaddr") ||
+ po_contains(options, "mountvers") ||
+ po_contains(options, "mountproto")) {
+ /*
+ * Since these mountd options are set assume version 3
+ * is wanted so error out with EPROTONOSUPPORT so the
+ * protocol negation starts with v3.
+ */
+ errno = EPROTONOSUPPORT;
+ goto out_fail;
+ }
+
+ if (mi->version.v_mode != V_SPECIFIC) {
+ snprintf(version_opt, sizeof(version_opt) - 1,
+ "vers=%lu.%lu", mi->version.major, mi->version.minor);
+
+ if (po_append(options, version_opt) == PO_FAILED) {
errno = EINVAL;
goto out_fail;
}
@@ -801,14 +842,28 @@ static int nfs_autonegotiate(struct nfsmount_info *mi)
int result;
result = nfs_try_mount_v4(mi);
+check_result:
if (result)
return result;
-check_errno:
switch (errno) {
case EPROTONOSUPPORT:
/* A clear indication that the server or our
- * client does not support NFS version 4. */
+ * client does not support NFS version 4 and minor */
+ case EINVAL:
+ /* A less clear indication that our client
+ * does not support NFSv4 minor version. */
+ if (mi->version.v_mode == V_GENERAL &&
+ mi->version.minor == 0)
+ return result;
+ if (mi->version.v_mode != V_SPECIFIC) {
+ if (mi->version.minor > 0) {
+ mi->version.minor--;
+ result = nfs_try_mount_v4(mi);
+ goto check_result;
+ }
+ }
+
goto fall_back;
case ENOENT:
/* Legacy Linux servers don't export an NFS
@@ -827,7 +882,7 @@ check_errno:
/* v4 server seems to be registered now. */
result = nfs_try_mount_v4(mi);
if (result == 0 && errno != ECONNREFUSED)
- goto check_errno;
+ goto check_result;
}
return result;
default:
@@ -848,19 +903,19 @@ static int nfs_try_mount(struct nfsmount_info *mi)
{
int result = 0;
- switch (mi->version) {
- case 0:
- result = nfs_autonegotiate(mi);
- break;
- case 2:
- case 3:
- result = nfs_try_mount_v3v2(mi, FALSE);
- break;
- case 4:
- result = nfs_try_mount_v4(mi);
- break;
- default:
- errno = EIO;
+ switch (mi->version.major) {
+ case 2:
+ case 3:
+ result = nfs_try_mount_v3v2(mi, FALSE);
+ break;
+ case 4:
+ if (mi->version.v_mode != V_SPECIFIC)
+ result = nfs_autonegotiate(mi);
+ else
+ result = nfs_try_mount_v4(mi);
+ break;
+ default:
+ errno = EIO;
}
return result;

13
SOURCES/nfs-utils-1.3.0-mount-eacces.patch

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
--- nfs-utils-1.3.0/utils/mount/stropts.c.orig 2017-09-19 11:25:13.889948761 -0400
+++ nfs-utils-1.3.0/utils/mount/stropts.c 2017-09-19 11:29:44.454636781 -0400
@@ -851,6 +851,9 @@ check_result:
case EINVAL:
/* A less clear indication that our client
* does not support NFSv4 minor version. */
+ case EACCES:
+ /* An unclear indication that the server
+ * may not support NFSv4 minor version. */
if (mi->version.v_mode != V_SPECIFIC) {
if (mi->version.minor > 0) {
mi->version.minor--;

46
SOURCES/nfs-utils-1.3.0-mount-explicit-rback.patch

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
--- nfs-utils-1.3.0/utils/mount/stropts.c.orig 2017-06-01 11:24:19.925018714 -0400
+++ nfs-utils-1.3.0/utils/mount/stropts.c 2017-06-01 11:25:20.033023121 -0400
@@ -313,9 +313,10 @@ static int nfs_set_version(struct nfsmou
if (!nfs_nfs_version(mi->options, &mi->version))
return 0;
- if (strncmp(mi->type, "nfs4", 4) == 0)
+ if (strncmp(mi->type, "nfs4", 4) == 0) {
mi->version.major = 4;
-
+ mi->version.v_mode = V_GENERAL;
+ }
/*
* Before 2.6.32, the kernel NFS client didn't
* support "-t nfs vers=4" mounts, so NFS version
@@ -856,9 +857,6 @@ check_result:
case EINVAL:
/* A less clear indication that our client
* does not support NFSv4 minor version. */
- if (mi->version.v_mode == V_GENERAL &&
- mi->version.minor == 0)
- return result;
if (mi->version.v_mode != V_SPECIFIC) {
if (mi->version.minor > 0) {
mi->version.minor--;
@@ -880,6 +878,9 @@ check_result:
/* UDP-Only servers won't support v4, but maybe it
* just isn't ready yet. So try v3, but double-check
* with rpcbind for v4. */
+ if (mi->version.v_mode == V_GENERAL)
+ /* Mustn't try v2,v3 */
+ return result;
result = nfs_try_mount_v3v2(mi, TRUE);
if (result == 0 && errno == EAGAIN) {
/* v4 server seems to be registered now. */
@@ -893,6 +894,9 @@ check_result:
}
fall_back:
+ if (mi->version.v_mode == V_GENERAL)
+ /* v2,3 fallback not allowed */
+ return result;
return nfs_try_mount_v3v2(mi, FALSE);
}

61
SOURCES/nfs-utils-1.3.0-mount-minorversion.patch

@ -0,0 +1,61 @@ @@ -0,0 +1,61 @@
commit 845c87b67b7bfd60127e23d1df93a94ceb9d3d18
Author: NeilBrown <neilb@suse.com>
Date: Wed Jul 26 13:51:51 2017 -0400

mount: Fix problems with parsing minorversion=
1/ minorversion=0 is not recognized, as errors from
strtol() are not correctly detected.
2/ when there is an error in the minorversion= value,
no message is presented.
3/ Current code recognizes "minorversion" and sets V_SPECIFIC,
but then because *cptr == '\0', the v_mode is reset to V_GENERAL.
This results in minorversion negotiation, which is not wanted.
This patch addresses all of these.
Signed-off-by: NeilBrown <neilb@suse.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
(cherry picked from commit 050153ef6a86ff5ab06ef65be36336824a323779)

diff --git a/utils/mount/network.c b/utils/mount/network.c
index b2e4374..b64c526 100644
--- a/utils/mount/network.c
+++ b/utils/mount/network.c
@@ -1283,13 +1283,19 @@ nfs_nfs_version(struct mount_options *options, struct nfs_version *version)
if (!version_val)
goto ret_error;
- if (!(version->major = strtol(version_val, &cptr, 10)))
+ version->major = strtol(version_val, &cptr, 10);
+ if (cptr == version_val || (*cptr && *cptr != '.'))
goto ret_error;
-
- if (version->major < 4)
+ if (version->major == 4 && *cptr != '.' &&
+ (version_val = po_get(options, "minorversion")) != NULL) {
+ version->minor = strtol(version_val, &cptr, 10);
+ i = -1;
+ if (*cptr)
+ goto ret_error;
version->v_mode = V_SPECIFIC;
-
- if (*cptr == '.') {
+ } else if (version->major < 4)
+ version->v_mode = V_SPECIFIC;
+ else if (*cptr == '.') {
version_val = ++cptr;
if (!(version->minor = strtol(version_val, &cptr, 10)) && cptr == version_val)
goto ret_error;
@@ -1303,7 +1309,10 @@ nfs_nfs_version(struct mount_options *options, struct nfs_version *version)
return 1;
ret_error:
- if (i <= 2 ) {
+ if (i < 0) {
+ nfs_error(_("%s: parsing error on 'minorversion=' option"),
+ progname);
+ } else if (i <= 2 ) {
nfs_error(_("%s: parsing error on 'v' option"),
progname);
} else if (i == 3 ) {

43
SOURCES/nfs-utils-1.3.0-mount-nfs-types.patch

@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
commit d1f6583a5ff32711a1da1d4a13a29a5700f63504
Author: Ben Hutchings <ben@decadent.org.uk>
Date: Thu Apr 2 11:43:33 2015 -0400

mount.nfs.man, nfs.man: Update distinction between fstypes
From: Ben Hutchings <ben@decadent.org.uk>
this is a resync of the man page updates in the Debian
package with mainline nfs-utils.
Acked-By: J. Bruce Fields <bfields@fieldses.org>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/mount/mount.nfs.man b/utils/mount/mount.nfs.man
index 1a4561b..15a82d5 100644
--- a/utils/mount/mount.nfs.man
+++ b/utils/mount/mount.nfs.man
@@ -15,16 +15,20 @@ is meant to be used by the
.BR mount (8)
command for mounting NFS shares. This subcommand, however, can also be used as a standalone command with limited functionality.
-.BR mount.nfs4
-is used for mounting NFSv4 file system, while
-.BR mount.nfs
-is used to mount NFS file systems versions 3 or 2.
.I remotetarget
is a server share usually in the form of
.BR servername:/path/to/share.
.I dir
is the directory on which the file system is to be mounted.
+Under Linux 2.6.32 and later kernel versions,
+.BR mount.nfs
+can mount all NFS file system versions. Under earlier Linux kernel versions,
+.BR mount.nfs4
+must be used for mounting NFSv4 file systems while
+.BR mount.nfs
+must be used for NFSv3 and v2.
+
.SH OPTIONS
.TP
.BI "\-r"

36
SOURCES/nfs-utils-1.3.0-mount-nfsvers.patch

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
diff -up nfs-utils-1.3.0/utils/mount/configfile.c.orig nfs-utils-1.3.0/utils/mount/configfile.c
--- nfs-utils-1.3.0/utils/mount/configfile.c.orig 2017-10-05 11:44:08.775077208 -0400
+++ nfs-utils-1.3.0/utils/mount/configfile.c 2017-10-05 11:49:50.811349443 -0400
@@ -70,6 +70,7 @@ struct mnt_alias {
{"background", "bg", MNT_NOARG},
{"foreground", "fg", MNT_NOARG},
{"sloppy", "sloppy", MNT_NOARG},
+ {"nfsvers", "vers", MNT_UNSET},
};
int mnt_alias_sz = (sizeof(mnt_alias_tab)/sizeof(mnt_alias_tab[0]));
@@ -296,20 +297,21 @@ conf_parse_mntopts(char *section, char *
list = conf_get_tag_list(section, arg);
TAILQ_FOREACH(node, &list->fields, link) {
+ /* check first if this is an alias for another option */
+ field = mountopts_alias(node->field, &argtype);
/*
* Do not overwrite options if already exists
*/
- snprintf(buf, BUFSIZ, "%s=", node->field);
+ snprintf(buf, BUFSIZ, "%s=", field);
if (opts && strcasestr(opts, buf) != NULL)
continue;
- if (lookup_entry(node->field) != NULL)
+ if (lookup_entry(field) != NULL)
continue;
buf[0] = '\0';
value = conf_get_section(section, arg, node->field);
if (value == NULL)
continue;
- field = mountopts_alias(node->field, &argtype);
if (strcasecmp(value, "false") == 0) {
if (argtype != MNT_NOARG)
snprintf(buf, BUFSIZ, "no%s", field);

82
SOURCES/nfs-utils-1.3.0-mount-prognotreg.patch

@ -0,0 +1,82 @@ @@ -0,0 +1,82 @@
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index bdd7c24..89b90a1 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -931,19 +931,45 @@ static int nfs_try_mount(struct nfsmount_info *mi)
* failed so far, but fail immediately if there is a local
* error (like a bad mount option).
*
- * ESTALE is also a temporary error because some servers
- * return ESTALE when a share is temporarily offline.
+ * If there is a remote error, like ESTALE or RPC_PROGNOTREGISTERED
+ * then it is probably permanent, but there is a small chance
+ * the it is temporary can we caught the server at an awkward
+ * time during start-up. So require that we see three of those
+ * before treating them as permanent.
+ * For ECONNREFUSED, wait a bit longer as there is often a longer
+ * gap between the network being ready and the NFS server starting.
*
* Returns 1 if we should fail immediately, or 0 if we
* should retry.
*/
static int nfs_is_permanent_error(int error)
{
+ static int prev_error;
+ static int rpt_cnt;
+
+ if (error == prev_error)
+ rpt_cnt += 1;
+ else
+ rpt_cnt = 1;
+ prev_error = error;
+
switch (error) {
case ESTALE:
- case ETIMEDOUT:
+ case EOPNOTSUPP: /* aka RPC_PROGNOTREGISTERED */
+ /* If two in a row, assume permanent */
+ return rpt_cnt >= 3;
case ECONNREFUSED:
+ /* Like the above, this can be temporary during a
+ * small window. However it is typically a larger
+ * window than for the others, and we have historically
+ * treated this as a temporary (i.e. long timeout)
+ * error with no complaints, so continue to treat
+ * it as temporary.
+ */
+ return 0; /* temporary */
+ case ETIMEDOUT:
case EHOSTUNREACH:
+ case EAGAIN:
return 0; /* temporary */
default:
return 1; /* permanent */
@@ -987,7 +1013,7 @@ static int nfsmount_fg(struct nfsmount_info *mi)
if (secs > 10)
secs = 10;
}
- };
+ }
mount_error(mi->spec, mi->node, errno);
return EX_FAIL;
@@ -1005,8 +1031,7 @@ static int nfsmount_parent(struct nfsmount_info *mi)
if (nfs_try_mount(mi))
return EX_SUCCESS;
- /* retry background mounts when the server is not up */
- if (nfs_is_permanent_error(errno) && errno != EOPNOTSUPP) {
+ if (nfs_is_permanent_error(errno)) {
mount_error(mi->spec, mi->node, errno);
return EX_FAIL;
}
@@ -1041,8 +1066,7 @@ static int nfsmount_child(struct nfsmount_info *mi)
if (nfs_try_mount(mi))
return EX_SUCCESS;
- /* retry background mounts when the server is not up */
- if (nfs_is_permanent_error(errno) && errno != EOPNOTSUPP)
+ if (nfs_is_permanent_error(errno))
break;
if (time(NULL) > timeout)

48
SOURCES/nfs-utils-1.3.0-mount-remount.patch

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
--- nfs-utils-1.3.0/utils/mount/stropts.c.orig 2014-03-25 11:12:07.000000000 -0400
+++ nfs-utils-1.3.0/utils/mount/stropts.c 2016-04-28 11:18:25.876793000 -0400
@@ -352,13 +352,26 @@ static int nfs_validate_options(struct n
if (!nfs_nfs_proto_family(mi->options, &family))
return 0;
- hint.ai_family = (int)family;
- error = getaddrinfo(mi->hostname, NULL, &hint, &mi->address);
- if (error != 0) {
- nfs_error(_("%s: Failed to resolve server %s: %s"),
- progname, mi->hostname, gai_strerror(error));
- mi->address = NULL;
- return 0;
+ /*
+ * A remount is not going to be able to change the server's address,
+ * nor should we try to resolve another address for the server as we
+ * may end up with a different address.
+ */
+ if (mi->flags & MS_REMOUNT) {
+ po_remove_all(mi->options, "addr");
+ } else {
+ hint.ai_family = (int)family;
+ error = getaddrinfo(mi->hostname, NULL, &hint, &mi->address);
+ if (error != 0) {
+ nfs_error(_("%s: Failed to resolve server %s: %s"),
+ progname, mi->hostname, gai_strerror(error));
+ mi->address = NULL;
+ return 0;
+ }
+
+ if (!nfs_append_addr_option(mi->address->ai_addr,
+ mi->address->ai_addrlen, mi->options))
+ return 0;
}
if (!nfs_set_version(mi))
@@ -367,10 +380,6 @@ static int nfs_validate_options(struct n
if (!nfs_append_sloppy_option(mi->options))
return 0;
- if (!nfs_append_addr_option(mi->address->ai_addr,
- mi->address->ai_addrlen, mi->options))
- return 0;
-
return 1;
}

156
SOURCES/nfs-utils-1.3.0-mount-restore-econn.patch

@ -0,0 +1,156 @@ @@ -0,0 +1,156 @@
diff --git a/utils/mount/network.c b/utils/mount/network.c
index 751f9b8..b2e4374 100644
--- a/utils/mount/network.c
+++ b/utils/mount/network.c
@@ -33,11 +33,13 @@
#include <errno.h>
#include <netdb.h>
#include <time.h>
+#include <grp.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/stat.h>
+#include <linux/in6.h>
#include <netinet/in.h>
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
@@ -802,6 +804,7 @@ int start_statd(void)
pid_t pid = fork();
switch (pid) {
case 0: /* child */
+ setgroups(0, NULL);
setgid(0);
setuid(0);
execle(START_STATD, START_STATD, NULL, envp);
@@ -1112,6 +1115,7 @@ static int nfs_ca_sockname(const struct sockaddr *sap, const socklen_t salen,
.sin6_addr = IN6ADDR_ANY_INIT,
};
int sock, result = 0;
+ int val;
sock = socket(sap->sa_family, SOCK_DGRAM, IPPROTO_UDP);
if (sock < 0)
@@ -1123,6 +1127,9 @@ static int nfs_ca_sockname(const struct sockaddr *sap, const socklen_t salen,
goto out;
break;
case AF_INET6:
+ /* Make sure the call-back address is public/permanent */
+ val = IPV6_PREFER_SRC_PUBLIC;
+ setsockopt(sock, SOL_IPV6, IPV6_ADDR_PREFERENCES, &val, sizeof(val));
if (bind(sock, SAFE_SOCKADDR(&sin6), sizeof(sin6)) < 0)
goto out;
break;
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index fc68d41..57e932f 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -91,6 +91,7 @@ struct nfsmount_info {
*type; /* "nfs" or "nfs4" */
char *hostname; /* server's hostname */
struct addrinfo *address; /* server's addresses */
+ sa_family_t family; /* Address family */
struct mount_options *options; /* parsed mount options */
char **extra_opts; /* string for /etc/mtab */
@@ -388,39 +389,19 @@ static int nfs_set_version(struct nfsmount_info *mi)
*/
static int nfs_validate_options(struct nfsmount_info *mi)
{
- struct addrinfo hint = {
- .ai_protocol = (int)IPPROTO_UDP,
- };
- sa_family_t family;
- int error;
-
if (!nfs_parse_devname(mi->spec, &mi->hostname, NULL))
return 0;
- if (!nfs_nfs_proto_family(mi->options, &family))
+ if (!nfs_nfs_proto_family(mi->options, &mi->family))
return 0;
/*
* A remount is not going to be able to change the server's address,
* nor should we try to resolve another address for the server as we
* may end up with a different address.
+ * A non-remount will set 'addr' from ->hostname
*/
- if (mi->flags & MS_REMOUNT) {
- po_remove_all(mi->options, "addr");
- } else {
- hint.ai_family = (int)family;
- error = getaddrinfo(mi->hostname, NULL, &hint, &mi->address);
- if (error != 0) {
- nfs_error(_("%s: Failed to resolve server %s: %s"),
- progname, mi->hostname, gai_strerror(error));
- mi->address = NULL;
- return 0;
- }
-
- if (!nfs_append_addr_option(mi->address->ai_addr,
- mi->address->ai_addrlen, mi->options))
- return 0;
- }
+ po_remove_all(mi->options, "addr");
if (!nfs_set_version(mi))
return 0;
@@ -900,7 +881,10 @@ check_result:
result = nfs_try_mount_v4(mi);
if (result == 0 && errno != ECONNREFUSED)
goto check_result;
- }
+ } else if (result == 0)
+ /* Restore original errno with v3 failures */
+ errno = ECONNREFUSED;
+
return result;
default:
return result;
@@ -923,6 +907,32 @@ static int nfs_try_mount(struct nfsmount_info *mi)
{
int result = 0;
+ if (mi->address == NULL) {
+ struct addrinfo hint = {
+ .ai_protocol = (int)IPPROTO_UDP,
+ };
+ int error;
+ struct addrinfo *address;
+
+ hint.ai_family = (int)mi->family;
+ error = getaddrinfo(mi->hostname, NULL, &hint, &address);
+ if (error != 0) {
+ if (error == EAI_AGAIN)
+ errno = EAGAIN;
+ else {
+ nfs_error(_("%s: Failed to resolve server %s: %s"),
+ progname, mi->hostname, gai_strerror(error));
+ errno = EALREADY;
+ }
+ return 0;
+ }
+
+ if (!nfs_append_addr_option(address->ai_addr,
+ address->ai_addrlen, mi->options))
+ return 0;
+ mi->address = address;
+ }
+
switch (mi->version.major) {
case 2:
case 3:
@@ -1018,10 +1028,8 @@ static int nfsmount_fg(struct nfsmount_info *mi)
if (nfs_is_permanent_error(errno))
break;
- if (time(NULL) > timeout) {
- errno = ETIMEDOUT;
+ if (time(NULL) > timeout)
break;
- }
if (errno != ETIMEDOUT) {
if (sleep(secs))

124
SOURCES/nfs-utils-1.3.0-mount-t-nfs4.patch

@ -0,0 +1,124 @@ @@ -0,0 +1,124 @@
diff -up nfs-utils-1.3.0/utils/mount/configfile.c.orig nfs-utils-1.3.0/utils/mount/configfile.c
--- nfs-utils-1.3.0/utils/mount/configfile.c.orig 2018-02-22 09:31:57.000000000 -0500
+++ nfs-utils-1.3.0/utils/mount/configfile.c 2018-02-22 09:33:05.000000000 -0500
@@ -265,7 +265,7 @@ default_value(char *mopt)
}
} else if (strncasecmp(field, "vers", strlen("vers")) == 0) {
if ((options = po_split(field)) != NULL) {
- if (!nfs_nfs_version(options, &config_default_vers)) {
+ if (!nfs_nfs_version("nfs", options, &config_default_vers)) {
xlog_warn("Unable to set default version: %s",
strerror(errno));
diff -up nfs-utils-1.3.0/utils/mount/network.c.orig nfs-utils-1.3.0/utils/mount/network.c
--- nfs-utils-1.3.0/utils/mount/network.c.orig 2018-02-22 09:31:57.000000000 -0500
+++ nfs-utils-1.3.0/utils/mount/network.c 2018-02-22 09:33:05.000000000 -0500
@@ -1253,7 +1253,7 @@ nfs_nfs_program(struct mount_options *op
* or FALSE if the option was specified with an invalid value.
*/
int
-nfs_nfs_version(struct mount_options *options, struct nfs_version *version)
+nfs_nfs_version(char *type, struct mount_options *options, struct nfs_version *version)
{
char *version_key, *version_val, *cptr;
int i, found = 0;
@@ -1268,10 +1268,11 @@ nfs_nfs_version(struct mount_options *op
}
}
- if (!found)
+ if (!found && strcmp(type, "nfs4") == 0)
+ version_val = type + 3;
+ else if (!found)
return 1;
-
- if (i <= 2 ) {
+ else if (i <= 2 ) {
/* v2, v3, v4 */
version_val = version_key + 1;
version->v_mode = V_SPECIFIC;
@@ -1648,7 +1649,7 @@ int nfs_options2pmap(struct mount_option
if (!nfs_nfs_program(options, &nfs_pmap->pm_prog))
return 0;
- if (!nfs_nfs_version(options, &version))
+ if (!nfs_nfs_version("nfs", options, &version))
return 0;
nfs_pmap->pm_vers = version.major;
if (!nfs_nfs_protocol(options, &nfs_pmap->pm_prot))
diff -up nfs-utils-1.3.0/utils/mount/network.h.orig nfs-utils-1.3.0/utils/mount/network.h
--- nfs-utils-1.3.0/utils/mount/network.h.orig 2018-02-22 09:31:57.000000000 -0500
+++ nfs-utils-1.3.0/utils/mount/network.h 2018-02-22 09:33:05.000000000 -0500
@@ -72,7 +72,7 @@ struct nfs_version {
int nfs_nfs_proto_family(struct mount_options *options, sa_family_t *family);
int nfs_mount_proto_family(struct mount_options *options, sa_family_t *family);
-int nfs_nfs_version(struct mount_options *options, struct nfs_version *version);
+int nfs_nfs_version(char *type, struct mount_options *options, struct nfs_version *version);
int nfs_nfs_protocol(struct mount_options *options, unsigned long *protocol);
int nfs_options2pmap(struct mount_options *,
diff -up nfs-utils-1.3.0/utils/mount/nfsumount.c.orig nfs-utils-1.3.0/utils/mount/nfsumount.c
--- nfs-utils-1.3.0/utils/mount/nfsumount.c.orig 2018-02-22 09:31:57.000000000 -0500
+++ nfs-utils-1.3.0/utils/mount/nfsumount.c 2018-02-22 09:33:05.000000000 -0500
@@ -180,7 +180,7 @@ static int nfs_umount_is_vers4(const str
options = po_split(pmc->m.mnt_opts);
if (options != NULL) {
struct nfs_version version;
- int rc = nfs_nfs_version(options, &version);
+ int rc = nfs_nfs_version("nfs", options, &version);
po_destroy(options);
if (rc && version.major == 4)
goto out_nfs4;
diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
--- nfs-utils-1.3.0/utils/mount/stropts.c.orig 2018-02-22 09:31:57.000000000 -0500
+++ nfs-utils-1.3.0/utils/mount/stropts.c 2018-02-22 09:33:05.000000000 -0500
@@ -87,8 +87,8 @@ extern int sloppy;
struct nfsmount_info {
const char *spec, /* server:/path */
- *node, /* mounted-on dir */
- *type; /* "nfs" or "nfs4" */
+ *node; /* mounted-on dir */
+ char *type; /* "nfs" or "nfs4" */
char *hostname; /* server's hostname */
struct addrinfo *address; /* server's addresses */
sa_family_t family; /* Address family */
@@ -326,15 +326,9 @@ static int nfs_append_sloppy_option(stru
static int nfs_set_version(struct nfsmount_info *mi)
{
- if (!nfs_nfs_version(mi->options, &mi->version))
+ if (!nfs_nfs_version(mi->type, mi->options, &mi->version))
return 0;
- if (strncmp(mi->type, "nfs4", 4) == 0) {
- /* Set to default values */
- mi->version.major = NFS_DEFAULT_MAJOR;
- mi->version.minor = NFS_DEFAULT_MINOR;
- mi->version.v_mode = V_GENERAL;
- }
/*
* Before 2.6.32, the kernel NFS client didn't
* support "-t nfs vers=4" mounts, so NFS version
@@ -1182,7 +1176,7 @@ static int nfsmount_start(struct nfsmoun
*
* Returns a valid mount command exit code.
*/
-int nfsmount_string(const char *spec, const char *node, const char *type,
+int nfsmount_string(const char *spec, const char *node, char *type,
int flags, char **extra_opts, int fake, int child)
{
struct nfsmount_info mi = {
diff -up nfs-utils-1.3.0/utils/mount/stropts.h.orig nfs-utils-1.3.0/utils/mount/stropts.h
--- nfs-utils-1.3.0/utils/mount/stropts.h.orig 2014-03-25 11:12:07.000000000 -0400
+++ nfs-utils-1.3.0/utils/mount/stropts.h 2018-02-22 09:33:05.000000000 -0500
@@ -24,7 +24,7 @@
#ifndef _NFS_UTILS_MOUNT_STROPTS_H
#define _NFS_UTILS_MOUNT_STROPTS_H
-int nfsmount_string(const char *, const char *, const char *, int,
+int nfsmount_string(const char *, const char *, char *, int,
char **, int, int);
#endif /* _NFS_UTILS_MOUNT_STROPTS_H */

100
SOURCES/nfs-utils-1.3.0-mount-uninit-structs.patch

@ -0,0 +1,100 @@ @@ -0,0 +1,100 @@
commit 0712b5507866d6b3c900623eb1f81fffaec80ae2
Author: Jianhong Yin <yin-jianhong@163.com>
Date: Thu Feb 2 06:21:15 2017 -0500

mount: fix mount fail that caused by uninitialized struct
From: "Jianhong.Yin" <yin-jianhong@163.com>
recent changes of utils/mount cause a regression mount fail:
https://bugzilla.redhat.com/show_bug.cgi?id=1415024
can not reproduce it on x86_64(gcc on x86_64 might do struct
initialize by default, I'm not sure). but it can be reproduced
always on platform ppc64le aarch64.
Signed-off-by: Jianhong Yin <yin-jianhong@163.com>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
index 4d18d35..77125f1 100644
--- a/utils/gssd/gssd.c
+++ b/utils/gssd/gssd.c
@@ -87,6 +87,7 @@ int root_uses_machine_creds = 1;
unsigned int context_timeout = 0;
unsigned int rpc_timeout = 5;
char *preferred_realm = NULL;
+char *ccachedir = NULL;
/* Avoid DNS reverse lookups on server names */
static bool avoid_dns = true;
int thread_started = false;
@@ -837,18 +838,9 @@ usage(char *progname)
exit(1);
}
-int
-main(int argc, char *argv[])
+inline static void
+read_gss_conf(void)
{
- int fg = 0;
- int verbosity = 0;
- int rpc_verbosity = 0;
- int opt;
- int i;
- extern char *optarg;
- char *progname;
- char *ccachedir = NULL;
- struct event sighup_ev;
char *s;
conf_init();
@@ -877,6 +869,22 @@ main(int argc, char *argv[])
if (s)
preferred_realm = s;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int fg = 0;
+ int verbosity = 0;
+ int rpc_verbosity = 0;
+ int opt;
+ int i;
+ extern char *optarg;
+ char *progname;
+ struct event sighup_ev;
+
+ read_gss_conf();
+
while ((opt = getopt(argc, argv, "DfvrlmnMp:k:d:t:T:R:")) != -1) {
switch (opt) {
case 'f':
diff --git a/utils/mount/network.c b/utils/mount/network.c
index 7dceb2d..d1c8fec 100644
--- a/utils/mount/network.c
+++ b/utils/mount/network.c
@@ -1638,6 +1638,7 @@ int nfs_options2pmap(struct mount_options *options,
struct pmap *nfs_pmap, struct pmap *mnt_pmap)
{
struct nfs_version version;
+ memset(&version, 0, sizeof(version));
if (!nfs_nfs_program(options, &nfs_pmap->pm_prog))
return 0;
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index 387d734..a9ff95d 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -517,6 +517,10 @@ nfs_rewrite_pmap_mount_options(struct mount_options *options, int checkv4)
unsigned long protocol;
struct pmap mnt_pmap;
+ /* initialize structs */
+ memset(&nfs_pmap, 0, sizeof(struct pmap));
+ memset(&mnt_pmap, 0, sizeof(struct pmap));
+
/*
* Version and transport negotiation is not required
* and does not work for RDMA mounts.

19
SOURCES/nfs-utils-1.3.0-mount-usage.patch

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
diff -up nfs-utils-1.3.0/utils/mount/mount_libmount.c.orig nfs-utils-1.3.0/utils/mount/mount_libmount.c
--- nfs-utils-1.3.0/utils/mount/mount_libmount.c.orig 2016-06-08 09:48:19.446035537 -0400
+++ nfs-utils-1.3.0/utils/mount/mount_libmount.c 2016-06-08 09:57:58.389518986 -0400
@@ -207,6 +207,7 @@ static int umount_main(struct libmnt_con
if (!spec || (*spec != '/' && strchr(spec,':') == NULL)) {
nfs_error(_("%s: no mount point provided"), progname);
+ umount_usage();
return EX_USAGE;
}
@@ -328,6 +329,7 @@ static int mount_main(struct libmnt_cont
if (!mount_point) {
nfs_error(_("%s: no mount point provided"), progname);
+ mount_usage();
goto err;
}
if (!spec) {

89
SOURCES/nfs-utils-1.3.0-mount-use-minor-default.patch

@ -0,0 +1,89 @@ @@ -0,0 +1,89 @@
diff -up nfs-utils-1.3.0/nfs.conf.orig nfs-utils-1.3.0/nfs.conf
--- nfs-utils-1.3.0/nfs.conf.orig 2017-06-19 11:15:31.661716122 -0400
+++ nfs-utils-1.3.0/nfs.conf 2017-06-19 11:15:51.945058695 -0400
@@ -66,6 +66,3 @@
# outgoing-port=
# outgoing-addr=
# lift-grace=y
-#
-#[svcgssd]
-# principal=
diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
--- nfs-utils-1.3.0/utils/mount/stropts.c.orig 2017-06-19 11:15:31.667716223 -0400
+++ nfs-utils-1.3.0/utils/mount/stropts.c 2017-06-19 11:25:53.000204600 -0400
@@ -73,6 +73,13 @@
#define NFS_DEF_BG_TIMEOUT_MINUTES (10000u)
#endif
+#ifndef NFS_DEFAULT_MAJOR
+#define NFS_DEFAULT_MAJOR 4
+#endif
+#ifndef NFS_DEFAULT_MINOR
+#define NFS_DEFAULT_MINOR 1
+#endif
+
extern int nfs_mount_data_version;
extern char *progname;
extern int verbose;
@@ -111,20 +118,28 @@ static void nfs_default_version(struct n
if (mi->version.v_mode == V_DEFAULT &&
config_default_vers.v_mode != V_DEFAULT) {
mi->version.major = config_default_vers.major;
- mi->version.minor = config_default_vers.minor;
+ if (config_default_vers.v_mode == V_SPECIFIC)
+ mi->version.minor = config_default_vers.minor;
+ else
+ mi->version.minor = NFS_DEFAULT_MINOR;
return;
}
if (mi->version.v_mode == V_GENERAL) {
if (config_default_vers.v_mode != V_DEFAULT &&
- mi->version.major == config_default_vers.major)
- mi->version.minor = config_default_vers.minor;
+ mi->version.major == config_default_vers.major) {
+ if (config_default_vers.v_mode == V_SPECIFIC)
+ mi->version.minor = config_default_vers.minor;
+ else
+ mi->version.minor = NFS_DEFAULT_MINOR;
+ } else
+ mi->version.minor = NFS_DEFAULT_MINOR;
return;
}
#endif /* MOUNT_CONFIG */
- mi->version.major = 4;
- mi->version.minor = 1;
+ mi->version.major = NFS_DEFAULT_MAJOR;
+ mi->version.minor = NFS_DEFAULT_MINOR;
}
/*
@@ -314,7 +329,9 @@ static int nfs_set_version(struct nfsmou
return 0;
if (strncmp(mi->type, "nfs4", 4) == 0) {
- mi->version.major = 4;
+ /* Set to default values */
+ mi->version.major = NFS_DEFAULT_MAJOR;
+ mi->version.minor = NFS_DEFAULT_MINOR;
mi->version.v_mode = V_GENERAL;
}
/*
@@ -750,13 +767,9 @@ static int nfs_do_mount_v4(struct nfsmou
}
if (mi->version.v_mode != V_SPECIFIC) {
- if (mi->version.v_mode == V_GENERAL)
- snprintf(version_opt, sizeof(version_opt) - 1,
- "vers=%lu", mi->version.major);
- else
- snprintf(version_opt, sizeof(version_opt) - 1,
- "vers=%lu.%lu", mi->version.major,
- mi->version.minor);
+ snprintf(version_opt, sizeof(version_opt) - 1,
+ "vers=%lu.%lu", mi->version.major,
+ mi->version.minor);
if (po_append(options, version_opt) == PO_FAILED) {
errno = EINVAL;

12
SOURCES/nfs-utils-1.3.0-mount-v41.patch

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
--- nfs-utils-1.3.0/utils/mount/stropts.c.orig 2017-03-28 11:13:30.000000000 -0400
+++ nfs-utils-1.3.0/utils/mount/stropts.c 2017-03-28 11:24:11.000000000 -0400
@@ -124,7 +124,7 @@ static void nfs_default_version(struct n
#endif /* MOUNT_CONFIG */
mi->version.major = 4;
- mi->version.minor = 2;
+ mi->version.minor = 1;
}
/*

45
SOURCES/nfs-utils-1.3.0-mount-v4arg-fix.patch

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
--- nfs-utils-1.3.0/utils/mount/stropts.c.orig 2016-12-18 10:59:32.526389233 -0500
+++ nfs-utils-1.3.0/utils/mount/stropts.c 2016-12-18 11:02:17.564900647 -0500
@@ -108,12 +108,6 @@ static void nfs_default_version(struct n
return;
}
- if (mi->version.v_mode == V_GENERAL &&
- config_default_vers.v_mode == V_DEFAULT) {
- mi->version.v_mode = V_SPECIFIC;
- return;
- }
-
if (mi->version.v_mode == V_DEFAULT &&
config_default_vers.v_mode != V_DEFAULT) {
mi->version.major = config_default_vers.major;
@@ -121,9 +115,9 @@ static void nfs_default_version(struct n
return;
}
- if (mi->version.v_mode == V_GENERAL &&
- config_default_vers.v_mode != V_DEFAULT) {
- if (mi->version.major == config_default_vers.major)
+ if (mi->version.v_mode == V_GENERAL) {
+ if (config_default_vers.v_mode != V_DEFAULT &&
+ mi->version.major == config_default_vers.major)
mi->version.minor = config_default_vers.minor;
return;
}
@@ -751,8 +745,13 @@ static int nfs_do_mount_v4(struct nfsmou
}
if (mi->version.v_mode != V_SPECIFIC) {
- snprintf(version_opt, sizeof(version_opt) - 1,
- "vers=%lu.%lu", mi->version.major, mi->version.minor);
+ if (mi->version.v_mode == V_GENERAL)
+ snprintf(version_opt, sizeof(version_opt) - 1,
+ "vers=%lu", mi->version.major);
+ else
+ snprintf(version_opt, sizeof(version_opt) - 1,
+ "vers=%lu.%lu", mi->version.major,
+ mi->version.minor);
if (po_append(options, version_opt) == PO_FAILED) {
errno = EINVAL;

168
SOURCES/nfs-utils-1.3.0-mountd-dos.patch

@ -0,0 +1,168 @@ @@ -0,0 +1,168 @@
diff -up nfs-utils-1.3.0/support/include/nfslib.h.orig nfs-utils-1.3.0/support/include/nfslib.h
--- nfs-utils-1.3.0/support/include/nfslib.h.orig 2014-03-25 11:12:07.000000000 -0400
+++ nfs-utils-1.3.0/support/include/nfslib.h 2014-11-14 11:16:06.785633197 -0500
@@ -174,6 +174,7 @@ void closeall(int min);
int svctcp_socket (u_long __number, int __reuse);
int svcudp_socket (u_long __number);
+int svcsock_nonblock (int __sock);
/* Misc shared code prototypes */
size_t strlcat(char *, const char *, size_t);
diff -up nfs-utils-1.3.0/support/nfs/rpcmisc.c.orig nfs-utils-1.3.0/support/nfs/rpcmisc.c
--- nfs-utils-1.3.0/support/nfs/rpcmisc.c.orig 2014-03-25 11:12:07.000000000 -0400
+++ nfs-utils-1.3.0/support/nfs/rpcmisc.c 2014-11-14 11:16:06.785633197 -0500
@@ -104,7 +104,7 @@ makesock(int port, int proto)
return -1;
}
- return sock;
+ return svcsock_nonblock(sock);
}
void
diff -up nfs-utils-1.3.0/support/nfs/svc_create.c.orig nfs-utils-1.3.0/support/nfs/svc_create.c
--- nfs-utils-1.3.0/support/nfs/svc_create.c.orig 2014-03-25 11:12:07.000000000 -0400
+++ nfs-utils-1.3.0/support/nfs/svc_create.c 2014-11-14 11:16:06.785633197 -0500
@@ -49,6 +49,8 @@
#ifdef HAVE_LIBTIRPC
+#include <rpc/rpc_com.h>
+
#define SVC_CREATE_XPRT_CACHE_SIZE (8)
static SVCXPRT *svc_create_xprt_cache[SVC_CREATE_XPRT_CACHE_SIZE] = { NULL, };
@@ -277,6 +279,12 @@ svc_create_nconf_rand_port(const char *n
"(%s, %u, %s)", name, version, nconf->nc_netid);
return 0;
}
+ if (svcsock_nonblock(xprt->xp_fd) < 0) {
+ /* close() already done by svcsock_nonblock() */
+ xprt->xp_fd = RPC_ANYFD;
+ SVC_DESTROY(xprt);
+ return 0;
+ }
if (!svc_reg(xprt, program, version, dispatch, nconf)) {
/* svc_reg(3) destroys @xprt in this case */
@@ -332,6 +340,7 @@ svc_create_nconf_fixed_port(const char *
int fd;
fd = svc_create_sock(ai->ai_addr, ai->ai_addrlen, nconf);
+ fd = svcsock_nonblock(fd);
if (fd == -1)
goto out_free;
@@ -394,6 +403,7 @@ nfs_svc_create(char *name, const rpcprog
const struct sigaction create_sigaction = {
.sa_handler = SIG_IGN,
};
+ int maxrec = RPC_MAXDATASIZE;
unsigned int visible, up, servport;
struct netconfig *nconf;
void *handlep;
@@ -405,6 +415,20 @@ nfs_svc_create(char *name, const rpcprog
*/
(void)sigaction(SIGPIPE, &create_sigaction, NULL);
+ /*
+ * Setting MAXREC also enables non-blocking mode for tcp connections.
+ * This avoids DOS attacks by a client sending many requests but never
+ * reading the reply:
+ * - if a second request already is present for reading in the socket,
+ * after the first request just was read, libtirpc will break the
+ * connection. Thus an attacker can't simply send requests as fast as
+ * he can without waiting for the response.
+ * - if the write buffer of the socket is full, the next write() will
+ * fail with EAGAIN. libtirpc will retry the write in a loop for max.
+ * 2 seconds. If write still fails, the connection will be closed.
+ */
+ rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
+
handlep = setnetconfig();
if (handlep == NULL) {
xlog(L_ERROR, "Failed to access local netconfig database: %s",
diff -up nfs-utils-1.3.0/support/nfs/svc_socket.c.orig nfs-utils-1.3.0/support/nfs/svc_socket.c
--- nfs-utils-1.3.0/support/nfs/svc_socket.c.orig 2014-03-25 11:12:07.000000000 -0400
+++ nfs-utils-1.3.0/support/nfs/svc_socket.c 2014-11-14 11:16:06.785633197 -0500
@@ -67,6 +67,39 @@ int getservport(u_long number, const cha
return 0;
}
+int
+svcsock_nonblock(int sock)
+{
+ int flags;
+
+ if (sock < 0)
+ return sock;
+
+ /* This socket might be shared among multiple processes
+ * if mountd is run multi-threaded. So it is safest to
+ * make it non-blocking, else all threads might wake
+ * one will get the data, and the others will block
+ * indefinitely.
+ * In all cases, transaction on this socket are atomic
+ * (accept for TCP, packet-read and packet-write for UDP)
+ * so O_NONBLOCK will not confuse unprepared code causing
+ * it to corrupt messages.
+ * It generally safest to have O_NONBLOCK when doing an accept
+ * as if we get a RST after the SYN and before accept runs,
+ * we can block despite being told there was an acceptable
+ * connection.
+ */
+ if ((flags = fcntl(sock, F_GETFL)) < 0)
+ perror(_("svc_socket: can't get socket flags"));
+ else if (fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0)
+ perror(_("svc_socket: can't set socket flags"));
+ else
+ return sock;
+
+ (void) __close(sock);
+ return -1;
+}
+
static int
svc_socket (u_long number, int type, int protocol, int reuse)
{
@@ -104,38 +137,7 @@ svc_socket (u_long number, int type, int
sock = -1;
}
- if (sock >= 0)
- {
- /* This socket might be shared among multiple processes
- * if mountd is run multi-threaded. So it is safest to
- * make it non-blocking, else all threads might wake
- * one will get the data, and the others will block
- * indefinitely.
- * In all cases, transaction on this socket are atomic
- * (accept for TCP, packet-read and packet-write for UDP)
- * so O_NONBLOCK will not confuse unprepared code causing
- * it to corrupt messages.
- * It generally safest to have O_NONBLOCK when doing an accept
- * as if we get a RST after the SYN and before accept runs,
- * we can block despite being told there was an acceptable
- * connection.
- */
- int flags;
- if ((flags = fcntl(sock, F_GETFL)) < 0)
- {
- perror (_("svc_socket: can't get socket flags"));
- (void) __close (sock);
- sock = -1;
- }
- else if (fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0)
- {
- perror (_("svc_socket: can't set socket flags"));
- (void) __close (sock);
- sock = -1;
- }
- }
-
- return sock;
+ return svcsock_nonblock(sock);
}
/*

633
SOURCES/nfs-utils-1.3.0-mountd-filedes.patch

@ -0,0 +1,633 @@ @@ -0,0 +1,633 @@
diff -up nfs-utils-1.3.0/utils/mountd/cache.c.orig nfs-utils-1.3.0/utils/mountd/cache.c
--- nfs-utils-1.3.0/utils/mountd/cache.c.orig 2017-01-06 09:31:53.155412013 -0500
+++ nfs-utils-1.3.0/utils/mountd/cache.c 2017-01-06 09:50:52.438190388 -0500
@@ -61,15 +61,13 @@ enum nfsd_fsid {
* Record is terminated with newline.
*
*/
-static int cache_export_ent(char *domain, struct exportent *exp, char *p);
+static int cache_export_ent(char *buf, int buflen, char *domain, struct exportent *exp, char *path);
#define INITIAL_MANAGED_GROUPS 100
-char *lbuf = NULL;
-int lbuflen = 0;
extern int use_ipaddr;
-static void auth_unix_ip(FILE *f)
+static void auth_unix_ip(int f)
{
/* requests are
* class IP-ADDR
@@ -78,23 +76,26 @@ static void auth_unix_ip(FILE *f)
*
* "nfsd" IP-ADDR expiry domainname
*/
- char *cp;
char class[20];
char ipaddr[INET6_ADDRSTRLEN + 1];
char *client = NULL;
struct addrinfo *tmp = NULL;
- if (readline(fileno(f), &lbuf, &lbuflen) != 1)
- return;
+ char buf[RPC_CHAN_BUF_SIZE], *bp;
+ int blen;
+
+ blen = read(f, buf, sizeof(buf));
+ if (blen <= 0 || buf[blen-1] != '\n') return;
+ buf[blen-1] = 0;
- xlog(D_CALL, "auth_unix_ip: inbuf '%s'", lbuf);
+ xlog(D_CALL, "auth_unix_ip: inbuf '%s'", buf);
- cp = lbuf;
+ bp = buf;
- if (qword_get(&cp, class, 20) <= 0 ||
+ if (qword_get(&bp, class, 20) <= 0 ||
strcmp(class, "nfsd") != 0)
return;
- if (qword_get(&cp, ipaddr, sizeof(ipaddr) - 1) <= 0)
+ if (qword_get(&bp, ipaddr, sizeof(ipaddr) - 1) <= 0)
return;
tmp = host_pton(ipaddr);
@@ -113,16 +114,20 @@ static void auth_unix_ip(FILE *f)
freeaddrinfo(ai);
}
}
- qword_print(f, "nfsd");
- qword_print(f, ipaddr);
- qword_printtimefrom(f, DEFAULT_TTL);
+ bp = buf; blen = sizeof(buf);
+ qword_add(&bp, &blen, "nfsd");
+ qword_add(&bp, &blen, ipaddr);
+ qword_adduint(&bp, &blen, time(0) + DEFAULT_TTL);
if (use_ipaddr) {
memmove(ipaddr + 1, ipaddr, strlen(ipaddr) + 1);
ipaddr[0] = '$';
- qword_print(f, ipaddr);
+ qword_add(&bp, &blen, ipaddr);
} else if (client)
- qword_print(f, *client?client:"DEFAULT");
- qword_eol(f);
+ qword_add(&bp, &blen, *client?client:"DEFAULT");
+ qword_addeol(&bp, &blen);
+ if (blen <= 0 || write(f, buf, bp - buf) != bp - buf)
+ xlog(L_ERROR, "auth_unix_ip: error writing reply");
+
xlog(D_CALL, "auth_unix_ip: client %p '%s'", client, client?client: "DEFAULT");
free(client);
@@ -130,7 +135,7 @@ static void auth_unix_ip(FILE *f)
}
-static void auth_unix_gid(FILE *f)
+static void auth_unix_gid(int f)
{
/* Request are
* uid
@@ -144,7 +149,8 @@ static void auth_unix_gid(FILE *f)
gid_t *more_groups;
int ngroups;
int rv, i;
- char *cp;
+ char buf[RPC_CHAN_BUF_SIZE], *bp;
+ int blen;
if (groups_len == 0) {
groups = malloc(sizeof(gid_t) * INITIAL_MANAGED_GROUPS);
@@ -156,11 +162,12 @@ static void auth_unix_gid(FILE *f)
ngroups = groups_len;
- if (readline(fileno(f), &lbuf, &lbuflen) != 1)
- return;
+ blen = read(f, buf, sizeof(buf));
+ if (blen <= 0 || buf[blen-1] != '\n') return;
+ buf[blen-1] = 0;
- cp = lbuf;
- if (qword_get_uint(&cp, &uid) != 0)
+ bp = buf;
+ if (qword_get_uint(&bp, &uid) != 0)
return;
pw = getpwuid(uid);
@@ -180,15 +187,19 @@ static void auth_unix_gid(FILE *f)
}
}
}
- qword_printuint(f, uid);
- qword_printtimefrom(f, DEFAULT_TTL);
+
+ bp = buf; blen = sizeof(buf);
+ qword_adduint(&bp, &blen, uid);
+ qword_adduint(&bp, &blen, time(0) + DEFAULT_TTL);
if (rv >= 0) {
- qword_printuint(f, ngroups);
+ qword_adduint(&bp, &blen, ngroups);
for (i=0; i<ngroups; i++)
- qword_printuint(f, groups[i]);
+ qword_adduint(&bp, &blen, groups[i]);
} else
- qword_printuint(f, 0);
- qword_eol(f);
+ qword_adduint(&bp, &blen, 0);
+ qword_addeol(&bp, &blen);
+ if (blen <= 0 || write(f, buf, bp - buf) != bp - buf)
+ xlog(L_ERROR, "auth_unix_gid: error writing reply");
}
#if USE_BLKID
@@ -578,14 +589,13 @@ static struct addrinfo *lookup_client_ad
return ret;
}
-static void nfsd_fh(FILE *f)
+static void nfsd_fh(int f)
{
/* request are:
* domain fsidtype fsid
* interpret fsid, find export point and options, and write:
* domain fsidtype fsid expiry path
*/
- char *cp;
char *dom;
int fsidtype;
int fsidlen;
@@ -597,24 +607,27 @@ static void nfsd_fh(FILE *f)
nfs_export *exp;
int i;
int dev_missing = 0;
+ char buf[RPC_CHAN_BUF_SIZE], *bp;
+ int blen;
- if (readline(fileno(f), &lbuf, &lbuflen) != 1)
- return;
+ blen = read(f, buf, sizeof(buf));
+ if (blen <= 0 || buf[blen-1] != '\n') return;
+ buf[blen-1] = 0;
- xlog(D_CALL, "nfsd_fh: inbuf '%s'", lbuf);
+ xlog(D_CALL, "nfsd_fh: inbuf '%s'", buf);
- cp = lbuf;
+ bp = buf;
- dom = malloc(strlen(cp));
+ dom = malloc(blen);
if (dom == NULL)
return;
- if (qword_get(&cp, dom, strlen(cp)) <= 0)
+ if (qword_get(&bp, dom, blen) <= 0)
goto out;
- if (qword_get_int(&cp, &fsidtype) != 0)
+ if (qword_get_int(&bp, &fsidtype) != 0)
goto out;
if (fsidtype < 0 || fsidtype > 7)
goto out; /* unknown type */
- if ((fsidlen = qword_get(&cp, fsid, 32)) <= 0)
+ if ((fsidlen = qword_get(&bp, fsid, 32)) <= 0)
goto out;
if (parse_fsid(fsidtype, fsidlen, fsid, &parsed))
goto out;
@@ -715,12 +728,13 @@ static void nfsd_fh(FILE *f)
}
if (found)
- if (cache_export_ent(dom, found, found_path) < 0)
+ if (cache_export_ent(buf, sizeof(buf), dom, found, found_path) < 0)
found = 0;
- qword_print(f, dom);
- qword_printint(f, fsidtype);
- qword_printhex(f, fsid, fsidlen);
+ bp = buf; blen = sizeof(buf);
+ qword_add(&bp, &blen, dom);
+ qword_addint(&bp, &blen, fsidtype);
+ qword_addhex(&bp, &blen, fsid, fsidlen);
/* The fsid -> path lookup can be quite expensive as it
* potentially stats and reads lots of devices, and some of those
* might have spun-down. The Answer is not likely to
@@ -729,20 +743,21 @@ static void nfsd_fh(FILE *f)
* timeout. Maybe this should be configurable on the command
* line.
*/
- qword_printint(f, 0x7fffffff);
+ qword_addint(&bp, &blen, 0x7fffffff);
if (found)
- qword_print(f, found_path);
- qword_eol(f);
- out:
+ qword_add(&bp, &blen, found_path);
+ qword_addeol(&bp, &blen);
+ if (blen <= 0 || write(f, buf, bp - buf) != bp - buf)
+ xlog(L_ERROR, "nfsd_fh: error writing reply");
+out:
if (found_path)
free(found_path);
freeaddrinfo(ai);
free(dom);
xlog(D_CALL, "nfsd_fh: found %p path %s", found, found ? found->e_path : NULL);
- return;
}
-static void write_fsloc(FILE *f, struct exportent *ep)
+static void write_fsloc(char **bp, int *blen, struct exportent *ep)
{
struct servers *servers;
@@ -752,20 +767,20 @@ static void write_fsloc(FILE *f, struct
servers = replicas_lookup(ep->e_fslocmethod, ep->e_fslocdata);
if (!servers)
return;
- qword_print(f, "fsloc");
- qword_printint(f, servers->h_num);
+ qword_add(bp, blen, "fsloc");
+ qword_addint(bp, blen, servers->h_num);
if (servers->h_num >= 0) {
int i;
for (i=0; i<servers->h_num; i++) {
- qword_print(f, servers->h_mp[i]->h_host);
- qword_print(f, servers->h_mp[i]->h_path);
+ qword_add(bp, blen, servers->h_mp[i]->h_host);
+ qword_add(bp, blen, servers->h_mp[i]->h_path);
}
}
- qword_printint(f, servers->h_referral);
+ qword_addint(bp, blen, servers->h_referral);
release_replicas(servers);
}
-static void write_secinfo(FILE *f, struct exportent *ep, int flag_mask)
+static void write_secinfo(char **bp, int *blen, struct exportent *ep, int flag_mask)
{
struct sec_entry *p;
@@ -776,45 +791,52 @@ static void write_secinfo(FILE *f, struc
return;
}
fix_pseudoflavor_flags(ep);
- qword_print(f, "secinfo");
- qword_printint(f, p - ep->e_secinfo);
+ qword_add(bp, blen, "secinfo");
+ qword_addint(bp, blen, p - ep->e_secinfo);
for (p = ep->e_secinfo; p->flav; p++) {
- qword_printint(f, p->flav->fnum);
- qword_printint(f, p->flags & flag_mask);
+ qword_addint(bp, blen, p->flav->fnum);
+ qword_addint(bp, blen, p->flags & flag_mask);
}
}
-static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *exp)
+static int dump_to_cache(int f, char *buf, int buflen, char *domain, char *path, struct exportent *exp)
{
- qword_print(f, domain);
- qword_print(f, path);
+ char *bp = buf;
+ int blen = buflen;
+ time_t now = time(0);
+
+ qword_add(&bp, &blen, domain);
+ qword_add(&bp, &blen, path);
if (exp) {
int different_fs = strcmp(path, exp->e_path) != 0;
int flag_mask = different_fs ? ~NFSEXP_FSID : ~0;
- qword_printtimefrom(f, exp->e_ttl);
- qword_printint(f, exp->e_flags & flag_mask);
- qword_printint(f, exp->e_anonuid);
- qword_printint(f, exp->e_anongid);
- qword_printint(f, exp->e_fsid);
- write_fsloc(f, exp);
- write_secinfo(f, exp, flag_mask);
- if (exp->e_uuid == NULL || different_fs) {
- char u[16];
- if (uuid_by_path(path, 0, 16, u)) {
- qword_print(f, "uuid");
- qword_printhex(f, u, 16);
- }
- } else {
- char u[16];
- get_uuid(exp->e_uuid, 16, u);
- qword_print(f, "uuid");
- qword_printhex(f, u, 16);
- }
+ qword_adduint(&bp, &blen, now + exp->e_ttl);
+ qword_addint(&bp, &blen, exp->e_flags & flag_mask);
+ qword_addint(&bp, &blen, exp->e_anonuid);
+ qword_addint(&bp, &blen, exp->e_anongid);
+ qword_addint(&bp, &blen, exp->e_fsid);
+ write_fsloc(&bp, &blen, exp);
+ 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)) {
+ qword_add(&bp, &blen, "uuid");
+ qword_addhex(&bp, &blen, u, 16);
+ }
+ } else {
+ char u[16];
+ get_uuid(exp->e_uuid, 16, u);
+ qword_add(&bp, &blen, "uuid");
+ qword_addhex(&bp, &blen, u, 16);
+ }
} else
- qword_printtimefrom(f, DEFAULT_TTL);
- return qword_eol(f);
+ qword_adduint(&bp, &blen, now + DEFAULT_TTL);
+ qword_addeol(&bp, &blen);
+ if (blen <= 0) return -1;
+ if (write(f, buf, bp - buf) != bp - buf) return -1;
+ return 0;
}
static nfs_export *
@@ -1164,27 +1186,27 @@ static struct exportent *lookup_junction
return exp;
}
-static void lookup_nonexport(FILE *f, char *dom, char *path,
+static void lookup_nonexport(int f, char *buf, int buflen, char *dom, char *path,
struct addrinfo *ai)
{
struct exportent *eep;
eep = lookup_junction(dom, path, ai);
- dump_to_cache(f, dom, path, eep);
+ dump_to_cache(f, buf, buflen, dom, path, eep);
if (eep == NULL)
return;
exportent_release(eep);
free(eep);
}
#else /* !HAVE_NFS_PLUGIN_H */
-static void lookup_nonexport(FILE *f, char *dom, char *path,
+static void lookup_nonexport(int f, char *buf, int buflen, char *dom, char *path,
struct addrinfo *UNUSED(ai))
{
- dump_to_cache(f, dom, path, NULL);
+ dump_to_cache(f, buf, buflen, dom, path, NULL);
}
#endif /* !HAVE_NFS_PLUGIN_H */
-static void nfsd_export(FILE *f)
+static void nfsd_export(int f)
{
/* requests are:
* domain path
@@ -1192,26 +1214,28 @@ static void nfsd_export(FILE *f)
* domain path expiry flags anonuid anongid fsid
*/
- char *cp;
char *dom, *path;
nfs_export *found = NULL;
struct addrinfo *ai = NULL;
+ char buf[RPC_CHAN_BUF_SIZE], *bp;
+ int blen;
- if (readline(fileno(f), &lbuf, &lbuflen) != 1)
- return;
-
- xlog(D_CALL, "nfsd_export: inbuf '%s'", lbuf);
-
- cp = lbuf;
- dom = malloc(strlen(cp));
- path = malloc(strlen(cp));
+ blen = read(f, buf, sizeof(buf));
+ if (blen <= 0 || buf[blen-1] != '\n') return;
+ buf[blen-1] = 0;
+
+ xlog(D_CALL, "nfsd_export: inbuf '%s'", buf);
+
+ bp = buf;
+ dom = malloc(blen);
+ path = malloc(blen);
if (!dom || !path)
goto out;
- if (qword_get(&cp, dom, strlen(lbuf)) <= 0)
+ if (qword_get(&bp, dom, blen) <= 0)
goto out;
- if (qword_get(&cp, path, strlen(lbuf)) <= 0)
+ if (qword_get(&bp, path, blen) <= 0)
goto out;
auth_reload();
@@ -1225,14 +1249,14 @@ static void nfsd_export(FILE *f)
found = lookup_export(dom, path, ai);
if (found) {
- if (dump_to_cache(f, dom, path, &found->m_export) < 0) {
+ if (dump_to_cache(f, buf, sizeof(buf), dom, path, &found->m_export) < 0) {
xlog(L_WARNING,
"Cannot export %s, possibly unsupported filesystem"
" or fsid= required", path);
- dump_to_cache(f, dom, path, NULL);
+ dump_to_cache(f, buf, sizeof(buf), dom, path, NULL);
}
} else
- lookup_nonexport(f, dom, path, ai);
+ lookup_nonexport(f, buf, sizeof(buf), dom, path, ai);
out:
xlog(D_CALL, "nfsd_export: found %p path %s", found, path ? path : NULL);
@@ -1244,15 +1268,14 @@ static void nfsd_export(FILE *f)
struct {
char *cache_name;
- void (*cache_handle)(FILE *f);
- FILE *f;
- char vbuf[RPC_CHAN_BUF_SIZE];
+ void (*cache_handle)(int f);
+ int f;
} cachelist[] = {
- { "auth.unix.ip", auth_unix_ip, NULL, ""},
- { "auth.unix.gid", auth_unix_gid, NULL, ""},
- { "nfsd.export", nfsd_export, NULL, ""},
- { "nfsd.fh", nfsd_fh, NULL, ""},
- { NULL, NULL, NULL, ""}
+ { "auth.unix.ip", auth_unix_ip, -1 },
+ { "auth.unix.gid", auth_unix_gid, -1 },
+ { "nfsd.export", nfsd_export, -1 },
+ { "nfsd.fh", nfsd_fh, -1 },
+ { NULL, NULL, -1 }
};
extern int manage_gids;
@@ -1269,11 +1292,7 @@ void cache_open(void)
if (!manage_gids && cachelist[i].cache_handle == auth_unix_gid)
continue;
sprintf(path, "/proc/net/rpc/%s/channel", cachelist[i].cache_name);
- cachelist[i].f = fopen(path, "r+");
- if (cachelist[i].f != NULL) {
- setvbuf(cachelist[i].f, cachelist[i].vbuf, _IOLBF,
- RPC_CHAN_BUF_SIZE);
- }
+ cachelist[i].f = open(path, O_RDWR);
}
}
@@ -1285,8 +1304,8 @@ void cache_set_fds(fd_set *fdset)
{
int i;
for (i=0; cachelist[i].cache_name; i++) {
- if (cachelist[i].f)
- FD_SET(fileno(cachelist[i].f), fdset);
+ if (cachelist[i].f >= 0)
+ FD_SET(cachelist[i].f, fdset);
}
}
@@ -1299,11 +1318,11 @@ int cache_process_req(fd_set *readfds)
int i;
int cnt = 0;
for (i=0; cachelist[i].cache_name; i++) {
- if (cachelist[i].f != NULL &&
- FD_ISSET(fileno(cachelist[i].f), readfds)) {
+ if (cachelist[i].f >= 0 &&
+ FD_ISSET(cachelist[i].f, readfds)) {
cnt++;
cachelist[i].cache_handle(cachelist[i].f);
- FD_CLR(fileno(cachelist[i].f), readfds);
+ FD_CLR(cachelist[i].f, readfds);
}
}
return cnt;
@@ -1316,14 +1335,14 @@ int cache_process_req(fd_set *readfds)
* % echo $domain $path $[now+DEFAULT_TTL] $options $anonuid $anongid $fsid > /proc/net/rpc/nfsd.export/channel
*/
-static int cache_export_ent(char *domain, struct exportent *exp, char *path)
+static int cache_export_ent(char *buf, int buflen, char *domain, struct exportent *exp, char *path)
{
- int err;
- FILE *f = fopen("/proc/net/rpc/nfsd.export/channel", "w");
- if (!f)
- return -1;
+ int f, err;
+
+ f = open("/proc/net/rpc/nfsd.export/channel", O_WRONLY);
+ if (f < 0) return -1;
- err = dump_to_cache(f, domain, exp->e_path, exp);
+ err = dump_to_cache(f, buf, buflen, domain, exp->e_path, exp);
if (err) {
xlog(L_WARNING,
"Cannot export %s, possibly unsupported filesystem or"
@@ -1364,13 +1383,13 @@ static int cache_export_ent(char *domain
continue;
dev = stb.st_dev;
path[l] = 0;
- dump_to_cache(f, domain, path, exp);
+ dump_to_cache(f, buf, buflen, domain, path, exp);
path[l] = c;
}
break;
}
- fclose(f);
+ close(f);
return err;
}
@@ -1381,27 +1400,25 @@ static int cache_export_ent(char *domain
*/
int cache_export(nfs_export *exp, char *path)
{
- char buf[INET6_ADDRSTRLEN];
- int err;
- FILE *f;
+ char ip[INET6_ADDRSTRLEN];
+ char buf[RPC_CHAN_BUF_SIZE], *bp;
+ int blen, f;
- f = fopen("/proc/net/rpc/auth.unix.ip/channel", "w");
- if (!f)
+ f = open("/proc/net/rpc/auth.unix.ip/channel", O_WRONLY);
+ if (f < 0)
return -1;
+ bp = buf, blen = sizeof(buf);
+ qword_add(&bp, &blen, "nfsd");
+ qword_add(&bp, &blen, host_ntop(get_addrlist(exp->m_client, 0), ip, sizeof(ip)));
+ 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;
+ close(f);
+ if (blen < 0) return -1;
- qword_print(f, "nfsd");
- qword_print(f,
- host_ntop(get_addrlist(exp->m_client, 0), buf, sizeof(buf)));
- qword_printtimefrom(f, exp->m_export.e_ttl);
- qword_print(f, exp->m_client->m_hostname);
- err = qword_eol(f);
-
- fclose(f);
-
- err = cache_export_ent(exp->m_client->m_hostname, &exp->m_export, path)
- || err;
- return err;
+ return cache_export_ent(buf, sizeof(buf), exp->m_client->m_hostname, &exp->m_export, path);
}
/**
@@ -1420,27 +1437,33 @@ int cache_export(nfs_export *exp, char *
struct nfs_fh_len *
cache_get_filehandle(nfs_export *exp, int len, char *p)
{
- FILE *f = fopen("/proc/fs/nfsd/filehandle", "r+");
- char buf[200];
- char *bp = buf;
- int failed;
static struct nfs_fh_len fh;
+ char buf[RPC_CHAN_BUF_SIZE], *bp;
+ int blen, f;
- if (!f)
- f = fopen("/proc/fs/nfs/filehandle", "r+");
- if (!f)
+ f = open("/proc/fs/nfsd/filehandle", O_RDWR);
+ if (f < 0) {
+ f = open("/proc/fs/nfs/filehandle", O_RDWR);
+ if (f < 0) return NULL;
+ }
+
+ bp = buf, blen = sizeof(buf);
+ qword_add(&bp, &blen, exp->m_client->m_hostname);
+ qword_add(&bp, &blen, p);
+ qword_addint(&bp, &blen, len);
+ qword_addeol(&bp, &blen);
+ if (blen <= 0 || write(f, buf, bp - buf) != bp - buf) {
+ close(f);
return NULL;
+ }
+ bp = buf;
+ blen = read(f, buf, sizeof(buf));
+ close(f);
- qword_print(f, exp->m_client->m_hostname);
- qword_print(f, p);
- qword_printint(f, len);
- failed = qword_eol(f);
-
- if (!failed)
- failed = (fgets(buf, sizeof(buf), f) == NULL);
- fclose(f);
- if (failed)
+ if (blen <= 0 || buf[blen-1] != '\n')
return NULL;
+ buf[blen-1] = 0;
+
memset(fh.fh_handle, 0, sizeof(fh.fh_handle));
fh.fh_size = qword_get(&bp, (char *)fh.fh_handle, NFS3_FHSIZE);
return &fh;

27
SOURCES/nfs-utils-1.3.0-mountd-manpage-P.patch

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
commit d0f9df9761d5fc63327fcaa0bc4515e739ca6f0e
Author: Yongcheng Yang <yongcheng.yang@gmail.com>
Date: Wed Mar 16 12:15:32 2016 -0400

mountd.man: Update to change -P option as an alias for -p
From: Yongcheng Yang <yongcheng.yang@gmail.com>
Signed-off-by: Yongcheng Yang <yongcheng.yang@gmail.com>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/mountd/mountd.man b/utils/mountd/mountd.man
index 7c5bfbe..66e3bba 100644
--- a/utils/mountd/mountd.man
+++ b/utils/mountd/mountd.man
@@ -115,10 +115,7 @@ must be invoked with the option
.B \-n " or " \-\-no-tcp
Don't advertise TCP for mount.
.TP
-.B \-P
-Ignored (compatibility with unfsd??).
-.TP
-.B \-p num " or " \-\-port num
+.B \-p num " or " \-P num " or " \-\-port num
Specifies the port number used for RPC listener sockets.
If this option is not specified,
.B rpc.mountd

57
SOURCES/nfs-utils-1.3.0-mountd-manpage-args.patch

@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
diff -up nfs-utils-1.3.0/utils/mountd/mountd.man.start nfs-utils-1.3.0/utils/mountd/mountd.man
--- nfs-utils-1.3.0/utils/mountd/mountd.man.start 2015-07-14 15:42:00.817994335 -0400
+++ nfs-utils-1.3.0/utils/mountd/mountd.man 2015-07-14 15:42:17.347273962 -0400
@@ -86,7 +86,7 @@ Turn on debugging. Valid kinds are: all,
.B \-F " or " \-\-foreground
Run in foreground (do not daemonize)
.TP
-.B \-f " or " \-\-exports-file
+.B \-f export-file " or " \-\-exports-file export-file
This option specifies the exports file, listing the clients that this
server is prepared to serve and parameters to apply to each
such mount (see
@@ -101,7 +101,7 @@ Display usage message.
Set the limit of the number of open file descriptors to num. The
default is to leave the limit unchanged.
.TP
-.B \-N " or " \-\-no-nfs-version
+.B \-N mountd-version " or " \-\-no-nfs-version mountd-version
This option can be used to request that
.B rpc.mountd
do not offer certain versions of NFS. The current version of
@@ -118,7 +118,7 @@ Don't advertise TCP for mount.
.B \-P
Ignored (compatibility with unfsd??).
.TP
-.B \-p " or " \-\-port num
+.B \-p num " or " \-\-port num
Specifies the port number used for RPC listener sockets.
If this option is not specified,
.B rpc.mountd
@@ -132,7 +132,7 @@ This option can be used to fix the port
listeners when NFS MOUNT requests must traverse a firewall
between clients and servers.
.TP
-.B \-H " or " \-\-ha-callout prog
+.B \-H " prog or " \-\-ha-callout prog
Specify a high availability callout program.
This program receives callouts for all MOUNT and UNMOUNT requests.
This allows
@@ -174,7 +174,7 @@ to perform a reverse lookup on each IP a
Enabling this can have a substantial negative effect on performance
in some situations.
.TP
-.BR "\-t N" " or " "\-\-num\-threads=N"
+.BR "\-t N" " or " "\-\-num\-threads=N " or " \-\-num\-threads N "
This option specifies the number of worker threads that rpc.mountd
spawns. The default is 1 thread, which is probably enough. More
threads are usually only needed for NFS servers which need to handle
@@ -184,7 +184,7 @@ your DNS server is slow or unreliable.
.B \-u " or " \-\-no-udp
Don't advertise UDP for mounting
.TP
-.B \-V " or " \-\-nfs-version
+.B \-V version " or " \-\-nfs-version version
This option can be used to request that
.B rpc.mountd
offer certain versions of NFS. The current version of

39
SOURCES/nfs-utils-1.3.0-mountd-manpage-netconfig.patch

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
diff -up nfs-utils-1.3.0/utils/mount/mount.nfs.man.orig nfs-utils-1.3.0/utils/mount/mount.nfs.man
--- nfs-utils-1.3.0/utils/mount/mount.nfs.man.orig 2014-03-25 11:12:07.000000000 -0400
+++ nfs-utils-1.3.0/utils/mount/mount.nfs.man 2015-06-25 10:27:18.001345779 -0400
@@ -76,10 +76,13 @@ file system table
.TP
.I /etc/mtab
table of mounted file systems
-
+.TP
+.I /etc/nfsmount.conf
+Configuration file for NFS mounts
.PD
.SH "SEE ALSO"
.BR nfs (5),
+.BR nfsmount.conf (5),
.BR mount (8),
.SH "AUTHOR"
diff -up nfs-utils-1.3.0/utils/mount/nfs.man.orig nfs-utils-1.3.0/utils/mount/nfs.man
--- nfs-utils-1.3.0/utils/mount/nfs.man.orig 2014-03-25 11:12:07.000000000 -0400
+++ nfs-utils-1.3.0/utils/mount/nfs.man 2015-06-25 10:27:18.001345779 -0400
@@ -1706,6 +1706,9 @@ with the mount options already saved on
.TP 1.5i
.I /etc/fstab
file system table
+.TP 1.5i
+.I /etc/nfsmount.conf
+Configuration file for NFS mounts
.SH BUGS
Before 2.4.7, the Linux NFS client did not support NFS over TCP.
.P
@@ -1735,6 +1738,7 @@ such as security negotiation, server ref
.BR mount.nfs (5),
.BR umount.nfs (5),
.BR exports (5),
+.BR nfsmount.conf (5),
.BR netconfig (5),
.BR ipv6 (7),
.BR nfsd (8),

31
SOURCES/nfs-utils-1.3.0-mountd-netgroups.patch

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
diff -up nfs-utils-1.3.0/support/export/client.c.save nfs-utils-1.3.0/support/export/client.c
--- nfs-utils-1.3.0/support/export/client.c.save 2016-06-07 14:02:11.244677000 -0400
+++ nfs-utils-1.3.0/support/export/client.c 2016-06-07 14:03:11.380193000 -0400
@@ -635,7 +635,7 @@ check_netgroup(const nfs_client *clp, co
const char *netgroup = clp->m_hostname + 1;
struct addrinfo *tmp = NULL;
struct hostent *hp;
- char *dot, *hname;
+ char *dot, *hname, *ip;
int i, match;
match = 0;
@@ -682,6 +682,18 @@ check_netgroup(const nfs_client *clp, co
}
}
+ /* check whether the IP itself is in the netgroup */
+ ip = calloc(INET6_ADDRSTRLEN, 1);
+ if (inet_ntop(ai->ai_family, &(((struct sockaddr_in *)ai->ai_addr)->sin_addr), ip, INET6_ADDRSTRLEN) == ip) {
+ if (innetgr(netgroup, ip, NULL, NULL)) {
+ free(hname);
+ hname = ip;
+ match = 1;
+ goto out;
+ }
+ }
+ free(ip);
+
/* Okay, strip off the domain (if we have one) */
dot = strchr(hname, '.');
if (dot == NULL)

157
SOURCES/nfs-utils-1.3.0-mountd-root.patch

@ -0,0 +1,157 @@ @@ -0,0 +1,157 @@
commit 710a492fda68092a02d6360d7a185f6a4dcaea85
Author: NeilBrown <neilb@suse.de>
Date: Thu Feb 26 14:10:35 2015 -0500

exports.man: improve documentation of 'nohide' and 'crossmnt'
- note that 'nohide' is irrelevant for NFSv4
- note that children on a 'crossmnt' filesystem cannot be unexported
- note that 'nocrossmnt' is a valid option, but probably not useful.
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man
index 59358e6..9309246 100644
--- a/utils/exportfs/exports.man
+++ b/utils/exportfs/exports.man
@@ -218,16 +218,46 @@ This option can be very useful in some situations, but it should be
used with due care, and only after confirming that the client system
copes with the situation effectively.
-The option can be explicitly disabled with
+The option can be explicitly disabled for NFSv2 and NFSv3 with
.IR hide .
+
+This option is not relevant when NFSv4 is use. NFSv4 never hides
+subordinate filesystems. Any filesystem that is exported will be
+visible where expected when using NFSv4.
.TP
-.IR crossmnt
+.I crossmnt
This option is similar to
.I nohide
-but it makes it possible for clients to move from the filesystem marked
-with crossmnt to exported filesystems mounted on it. Thus when a child
-filesystem "B" is mounted on a parent "A", setting crossmnt on "A" has
-the same effect as setting "nohide" on B.
+but it makes it possible for clients to access all filesystems mounted
+on a filesystem marked with
+.IR crossmnt .
+Thus when a child filesystem "B" is mounted on a parent "A", setting
+crossmnt on "A" has a similar effect to setting "nohide" on B.
+
+With
+.I nohide
+the child filesystem needs to be explicitly exported. With
+.I crossmnt
+it need not. If a child of a
+.I crossmnt
+file is not explicitly exported, then it will be implicitly exported
+with the same export options as the parent, except for
+.IR fsid= .
+This makes it impossible to
+.B not
+export a child of a
+.I crossmnt
+filesystem. If some but not all subordinate filesystems of a parent
+are to be exported, then they must be explicitly exported and the
+parent should not have
+.I crossmnt
+set.
+
+The
+.I nocrossmnt
+option can explictly disable
+.I crossmnt
+if it was previously set. This is rarely useful.
.TP
.IR no_subtree_check
This option disables subtree checking, which has mild security

commit b7341b19d62481504f1820414159009535d37809
Author: NeilBrown <neilb@suse.de>
Date: Wed Feb 25 16:47:56 2015 -0500

mountd: fix next_mnt handling for "/"
If the (exported) path passed to next_mnt() is simply "/", next_mnt()
will not report any children, as none start with "/" followed by a '/'.
So make a special case for strlen(p)==1. In that case, return all
children.
This gives correct handling if only "/" is exported.
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
index 1430aee..23af4a9 100644
--- a/utils/mountd/cache.c
+++ b/utils/mountd/cache.c
@@ -365,7 +365,7 @@ static char *next_mnt(void **v, char *p)
*v = f;
} else
f = *v;
- while ((me = getmntent(f)) != NULL &&
+ while ((me = getmntent(f)) != NULL && l > 1 &&
(strncmp(me->mnt_dir, p, l) != 0 ||
me->mnt_dir[l] != '/'))
;

commit 7e27d4a542bf97e0ddc1036010e1b2d218a01c2b
Author: Vivek Trivedi <t.vivek@samsung.com>
Date: Wed Sep 16 11:14:03 2015 -0400

mountd: fix mount issue due to comparison with uninitialized uuid
Fix mount issue due to comparison of uninitialized variable
u(uuid) with parsed->fhuuid when uuid_by_path return 0.
/tmp/usb
192.168.1.0/16(ro,no_root_squash,no_subtree_check,fsid=0)
/tmp/usb/sda1 192.168.1.0/16(ro,no_root_squash,no_subtree_check)
/tmp/usb/sdb1 192.168.1.0/16(ro,no_root_squash,no_subtree_check)
mount -t nfs -o nolock,nfsvers=3 192.168.1.2:/tmp/usb/sda1 /tmp/sda1
mount -t nfs -o nolock,nfsvers=3 192.168.1.2:/tmp/usb/sdb1 /tmp/sdb1
results in below mountd error:
mountd: /tmp/usb and /tmp/usb/sdb1 have same filehandle for
192.168.1.0/16, using first
when uuid_by_path returned 0, by chance, garbage value of u was same as
parsed->fhuuid(of sdb1), and comparison of these resulted in above
error.
Signed-off-by: Vivek Trivedi <t.vivek@samsung.com>
Reviewed-by: Amit Sahrawat <a.sahrawat@samsung.com>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
index 9a1bb27..1430aee 100644
--- a/utils/mountd/cache.c
+++ b/utils/mountd/cache.c
@@ -547,18 +547,17 @@ static bool match_fsid(struct parsed_fsid *parsed, nfs_export *exp, char *path)
if (!is_mountpoint(path))
return false;
check_uuid:
- if (exp->m_export.e_uuid)
+ if (exp->m_export.e_uuid) {
get_uuid(exp->m_export.e_uuid, parsed->uuidlen, u);
+ if (memcmp(u, parsed->fhuuid, parsed->uuidlen) == 0)
+ return true;
+ }
else
for (type = 0;
uuid_by_path(path, type, parsed->uuidlen, u);
type++)
if (memcmp(u, parsed->fhuuid, parsed->uuidlen) == 0)
return true;
-
- if (memcmp(u, parsed->fhuuid, parsed->uuidlen) != 0)
- return false;
- return true;
}
/* Well, unreachable, actually: */
return false;

29
SOURCES/nfs-utils-1.3.0-mountd-start-statd-path.patch

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
commit edbbbe099bf4d4902f29d087239d6d159ac2187d
Author: Kinglong Mee <kinglongmee@gmail.com>
Date: Fri Apr 25 10:28:47 2014 -0400

systemd: add PATH for finding systemctl
The 1.3.0 release adds a call to systemctl fails for it's in /usr/bin.
[root@localhost nfs-utils]# start-statd
/usr/sbin/start-statd: line 9: systemctl: command not found
Statd service already running!
Reported-by: Allan Duncan <amd1234@fastmail.com.au>
Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/statd/start-statd b/utils/statd/start-statd
index cde3583..8ac3798 100644
--- a/utils/statd/start-statd
+++ b/utils/statd/start-statd
@@ -4,7 +4,7 @@
# /var/run/rpc.statd.pid).
# It should run statd with whatever flags are apropriate for this
# site.
-PATH=/sbin:/usr/sbin
+PATH="/sbin:/usr/sbin:/bin:/usr/bin"
if systemctl start statd.service
then :
else

25
SOURCES/nfs-utils-1.3.0-mountd-usage-error.patch

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
commit 6ec0d58fbff7c1a814a21cf8c7fe0ef5106a04c1
Author: Steve Dickson <steved@redhat.com>
Date: Wed Jan 20 14:16:08 2016 -0500

mountd: print an error message when no versions are specified
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c
index 8aca181..b584afc 100644
--- a/utils/mountd/mountd.c
+++ b/utils/mountd/mountd.c
@@ -794,9 +794,10 @@ main(int argc, char **argv)
}
/* No more arguments allowed. */
- if (optind != argc || !version_any())
+ if (optind != argc || !version_any()) {
+ fprintf(stderr, "%s: No protocol versions specified!\n", progname);
usage(progname, 1);
-
+ }
if (chdir(state_dir)) {
fprintf(stderr, "%s: chdir(%s) failed: %s\n",
progname, state_dir, strerror(errno));

14
SOURCES/nfs-utils-1.3.0-mountd-usage.patch

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
diff -up nfs-utils-1.3.0/utils/mountd/mountd.c.orig nfs-utils-1.3.0/utils/mountd/mountd.c
--- nfs-utils-1.3.0/utils/mountd/mountd.c.orig 2016-02-11 09:57:51.376317000 -0500
+++ nfs-utils-1.3.0/utils/mountd/mountd.c 2016-02-11 10:02:54.377956000 -0500
@@ -911,7 +911,8 @@ usage(const char *prog, int n)
" [-o num|--descriptors num] [-f exports-file|--exports-file=file]\n"
" [-p|--port port] [-V version|--nfs-version version]\n"
" [-N version|--no-nfs-version version] [-n|--no-tcp]\n"
-" [-H ha-callout-prog] [-s|--state-directory-path path]\n"
-" [-g|--manage-gids] [-t num|--num-threads=num] [-u|--no-udp]\n", prog);
+" [-H prog |--ha-callout prog] [-r |--reverse-lookup]\n"
+" [-s|--state-directory-path path] [-g|--manage-gids]\n"
+" [-t num|--num-threads=num] [-u|--no-udp]\n", prog);
exit(n);
}

102
SOURCES/nfs-utils-1.3.0-mountd-v4root-sec.patch

@ -0,0 +1,102 @@ @@ -0,0 +1,102 @@
commit 4a1ad4aa3028d26d830d9a9003ff9e3337b0e0d5
Author: Scott Mayhew <smayhew@redhat.com>
Date: Thu Apr 2 11:15:15 2015 -0400

mountd: Enable all auth flavors on pseudofs exports
With the current mountd code it's possible to craft exports in such a
manner that clients will be unable to mount exports that they *should*
be able to mount.
Consider the following example:
/foo *(rw,insecure,no_root_squash,sec=krb5p)
/bar client.example.com(rw,insecure,no_root_squash)
Initially, client.example.com will be able to mount the /foo export
using sec=krb5p, but attempts to mount /bar using sec=sys will return
EPERM. Once the nfsd.export cache entry expires, client.example.com
will then be able to mount /bar using sec=sys but attempts to mount /foo
using sec=krb5p will return EPERM.
The reason this happens is because the initial nfsd.export cache entry
is actually pre-populated by nfsd_fh(), which is the handler for the
nfsd.fh cache, while later cache requests (once the initial entry
expires) are handled by nfsd_export(). These functions have slightly
different logic in how they select a v4root export from the cache --
nfsd_fh() takes last matching v4root export it finds, while
nfsd_export() (actually lookup_export()) takes the first. Either way
it's wrong because the client should be able to mount both exports.
Both rfc3503bis and rfc5661 say:
A common and convenient practice, unless strong security requirements
dictate otherwise, is to make the entire pseudo file system
accessible by all of the valid security mechanisms.
...so lets do that.
Acked-by: J. Bruce Fields <bfields@fieldses.org>
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/mountd/v4root.c b/utils/mountd/v4root.c
index 34d098a..429ebb8 100644
--- a/utils/mountd/v4root.c
+++ b/utils/mountd/v4root.c
@@ -26,6 +26,7 @@
#include "nfslib.h"
#include "misc.h"
#include "v4root.h"
+#include "pseudoflavors.h"
int v4root_needed;
@@ -56,22 +57,22 @@ static nfs_export pseudo_root = {
};
static void
-set_pseudofs_security(struct exportent *pseudo, struct exportent *source)
+set_pseudofs_security(struct exportent *pseudo, int flags)
{
- struct sec_entry *se;
+ struct flav_info *flav;
int i;
- if (source->e_flags & NFSEXP_INSECURE_PORT)
+ if (flags & NFSEXP_INSECURE_PORT)
pseudo->e_flags |= NFSEXP_INSECURE_PORT;
- if ((source->e_flags & NFSEXP_ROOTSQUASH) == 0)
+ if ((flags & NFSEXP_ROOTSQUASH) == 0)
pseudo->e_flags &= ~NFSEXP_ROOTSQUASH;
- for (se = source->e_secinfo; se->flav; se++) {
+ for (flav = flav_map; flav < flav_map + flav_map_size; flav++) {
struct sec_entry *new;
- i = secinfo_addflavor(se->flav, pseudo);
+ i = secinfo_addflavor(flav, pseudo);
new = &pseudo->e_secinfo[i];
- if (se->flags & NFSEXP_INSECURE_PORT)
+ if (flags & NFSEXP_INSECURE_PORT)
new->flags |= NFSEXP_INSECURE_PORT;
}
}
@@ -91,7 +92,7 @@ v4root_create(char *path, nfs_export *export)
strncpy(eep.e_path, path, sizeof(eep.e_path));
if (strcmp(path, "/") != 0)
eep.e_flags &= ~NFSEXP_FSID;
- set_pseudofs_security(&eep, curexp);
+ set_pseudofs_security(&eep, curexp->e_flags);
exp = export_create(&eep, 0);
if (exp == NULL)
return NULL;
@@ -139,7 +140,7 @@ pseudofs_update(char *hostname, char *path, nfs_export *source)
return 0;
}
/* Update an existing V4ROOT export: */
- set_pseudofs_security(&exp->m_export, &source->m_export);
+ set_pseudofs_security(&exp->m_export, source->m_export.e_flags);
return 0;
}

15
SOURCES/nfs-utils-1.3.0-mountstats-iostats.patch

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
diff -up nfs-utils-1.3.0/tools/mountstats/mountstats.py.orig nfs-utils-1.3.0/tools/mountstats/mountstats.py
--- nfs-utils-1.3.0/tools/mountstats/mountstats.py.orig 2017-04-08 15:23:53.524215286 -0400
+++ nfs-utils-1.3.0/tools/mountstats/mountstats.py 2017-04-08 15:30:45.862043179 -0400
@@ -565,7 +565,10 @@ class DeviceData:
for the nfsstat command.
"""
for op in new_stats.__rpc_data['ops']:
- self.__rpc_data[op] = list(map(add, self.__rpc_data[op], new_stats.__rpc_data[op]))
+ try:
+ self.__rpc_data[op] = list(map(add, self.__rpc_data[op], new_stats.__rpc_data[op]))
+ except KeyError:
+ continue
def __print_rpc_op_stats(self, op, sample_time):
"""Print generic stats for one RPC op

36
SOURCES/nfs-utils-1.3.0-mountstats-manpage-fix.patch

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
commit f2efa15ef8c083926791195ed1037fd47a5e4e41
Author: Scott Mayhew <smayhew@redhat.com>
Date: Wed Sep 16 11:19:41 2015 -0400

mountstats.man: Remove a few bogus .R macros
These have no effect on the rendering of the man page, but they do cause
the following error if you try to pipe or redirect the output:
`R' is a string (producing the registered sign), not a macro.
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/tools/mountstats/mountstats.man b/tools/mountstats/mountstats.man
index bfc4c46..a55130b 100644
--- a/tools/mountstats/mountstats.man
+++ b/tools/mountstats/mountstats.man
@@ -13,13 +13,13 @@ mountstats \- Displays various NFS client per-mount statistics
.RB [ \-S | \-\-since
.IR sincefile ]
.\" .RB [ \-n | \-\-nfs | \-r | \-\-rpc | \-R | \-\-raw ]
-.R [
+[
.RB [ \-n | \-\-nfs ]
-.R |
+|
.RB [ \-r | \-\-rpc ]
-.R |
+|
.RB [ \-R | \-\-raw ]
-.R ]
+]
.RI [ mountpoint ] ...
.P
.B mountstats iostat

21
SOURCES/nfs-utils-1.3.0-mountstats-manpage-fix2.patch

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
commit 8c7d7fe5577b059130d472d4145a09cf9d4a7ea2
Author: Steve Dickson <steved@redhat.com>
Date: Mon Aug 10 09:58:01 2015 -0400

mountstats.man: fixed typo in man page
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/tools/mountstats/mountstats.man b/tools/mountstats/mountstats.man
index a9df1e4..bfc4c46 100644
--- a/tools/mountstats/mountstats.man
+++ b/tools/mountstats/mountstats.man
@@ -115,7 +115,7 @@ options.
Specifies the amount of time in seconds between each report. The first report contains statistics for the time since each file system was mounted. Each subsequent report contains statistics collected during the interval since the previous report. This may not be used with the
.BR \-f | \-\-file
or
-.BR \-s | \-\-since
+.BR \-S | \-\-since
options.
.P
.IP "\fIcount\fP"

26
SOURCES/nfs-utils-1.3.0-mountstats-pnfs.patch

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
commit 3e2ab78a2cfbc2d11c31ced8d3f538d5aae757f1
Author: Scott Mayhew <smayhew@redhat.com>
Date: Thu Sep 22 13:33:33 2016 -0400

mountstats: add pNFS READs and WRITEs
These counters are already in /proc/self/mountstats but the mountstats
program doesn't display them.
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1377740

diff --git a/tools/mountstats/mountstats.py b/tools/mountstats/mountstats.py
index 4ca4bc4..88ccdae 100644
--- a/tools/mountstats/mountstats.py
+++ b/tools/mountstats/mountstats.py
@@ -412,6 +412,8 @@ class DeviceData:
print(' short reads: %d short writes: %d' % \
(self.__nfs_data['shortreads'], self.__nfs_data['shortwrites']))
print(' NFSERR_DELAYs from server: %d' % self.__nfs_data['delay'])
+ print(' pNFS READs: %d' % self.__nfs_data['pnfsreads'])
+ print(' pNFS WRITEs: %d' % self.__nfs_data['pnfswrites'])
def display_nfs_bytes(self):
"""Pretty-print the NFS event counters

22
SOURCES/nfs-utils-1.3.0-mountstats-shebang.patch

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
commit a1f89c17f529b688ce3f686a48a49cb3789807c5
Author: Steve Dickson <steved@redhat.com>
Date: Thu Jul 27 10:35:55 2017 -0400

mountstats: Remove a shebang
There might be an issue that the script is executed with unwanted
version of <lang>.
Signed-off-by: Steve Dickson <steved@redhat.com>
(cherry picked from commit caa59a30b78dedea99a2317da95bb86810360645)

diff --git a/tools/mountstats/mountstats.py b/tools/mountstats/mountstats.py
index 90b15a5..1dd1f1b 100644
--- a/tools/mountstats/mountstats.py
+++ b/tools/mountstats/mountstats.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/python
# -*- python-mode -*-
"""Parse /proc/self/mountstats and display it in human readable form
"""

1326
SOURCES/nfs-utils-1.3.0-mountstats-update.patch

File diff suppressed because it is too large Load Diff

1892
SOURCES/nfs-utils-1.3.0-nfs-conf.patch

File diff suppressed because it is too large Load Diff

12
SOURCES/nfs-utils-1.3.0-nfs-iostat-no-dev.patch

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
diff -up nfs-utils-1.3.0/tools/nfs-iostat/nfs-iostat.py.orig nfs-utils-1.3.0/tools/nfs-iostat/nfs-iostat.py
--- nfs-utils-1.3.0/tools/nfs-iostat/nfs-iostat.py.orig 2017-11-03 09:29:39.000000000 -0400
+++ nfs-utils-1.3.0/tools/nfs-iostat/nfs-iostat.py 2017-11-03 09:34:25.000000000 -0400
@@ -434,6 +434,8 @@ def parse_stats_file(filename):
words = line.split()
if len(words) == 0:
continue
+ if line.startswith("no device mounted") :
+ continue
if words[0] == 'device':
key = words[4]
new = [ line.strip() ]

103
SOURCES/nfs-utils-1.3.0-nfs-man-v2.patch

@ -0,0 +1,103 @@ @@ -0,0 +1,103 @@
diff -up nfs-utils-1.3.0/utils/exportfs/exports.man.orig nfs-utils-1.3.0/utils/exportfs/exports.man
--- nfs-utils-1.3.0/utils/exportfs/exports.man.orig 2017-11-03 07:45:47.000000000 -0400
+++ nfs-utils-1.3.0/utils/exportfs/exports.man 2017-11-03 09:25:47.000000000 -0400
@@ -410,7 +410,7 @@ of the filesystem must be handled elsewh
.TP
.IR pnfs
-This option allows enables the use of pNFS extension if protocol level
+This option enables the use of the pNFS extension if the protocol level
is NFSv4.1 or higher, and the filesystem supports pNFS exports. With
pNFS clients can bypass the server and perform I/O directly to storage
devices. The default can be explicitly requested with the
diff -up nfs-utils-1.3.0/utils/mount/nfs.man.orig nfs-utils-1.3.0/utils/mount/nfs.man
--- nfs-utils-1.3.0/utils/mount/nfs.man.orig 2017-11-03 07:45:47.000000000 -0400
+++ nfs-utils-1.3.0/utils/mount/nfs.man 2017-11-03 09:23:20.000000000 -0400
@@ -11,11 +11,8 @@ NFS is an Internet Standard protocol
created by Sun Microsystems in 1984. NFS was developed
to allow file sharing between systems residing
on a local area network.
-The Linux NFS client supports three versions
-of the NFS protocol:
-NFS version 2 [RFC1094],
-NFS version 3 [RFC1813],
-and NFS version 4 [RFC3530].
+Depending on kernel configuration, the Linux NFS client may
+support NFS versions 2, 3, 4.0, 4.1, or 4.2.
.P
The
.BR mount (8)
@@ -88,9 +85,8 @@ These options are valid to use with any
The NFS protocol version number used to contact the server's NFS service.
If the server does not support the requested version, the mount request
fails.
-If this option is not specified, the client negotiates a suitable version
-with
-the server, trying version 4 first, version 3 second, and version 2 last.
+If this option is not specified, the client tries version 4.1 first,
+then negotiates down until it finds a version supported by the server.
.TP 1.5i
.BI vers= n
This option is an alternative to the
@@ -752,7 +748,7 @@ NOTE: When used together, the 'local_loc
by 'nolock'/'lock' mount option.
.SS "Options for NFS version 4 only"
Use these options, along with the options in the first subsection above,
-for NFS version 4 and newer.
+for NFS version 4.0 and newer.
.TP 1.5i
.BI proto= netid
The
@@ -825,7 +821,7 @@ the behavior of this option in more deta
Specifies a single IPv4 address (in dotted-quad form),
or a non-link-local IPv6 address,
that the NFS client advertises to allow servers
-to perform NFS version 4 callback requests against
+to perform NFS version 4.0 callback requests against
files on this mount point. If the server is unable to
establish callback connections to clients, performance
may degrade, or accesses to files may temporarily hang.
@@ -838,6 +834,11 @@ In the presence of multiple client netwo
special routing policies,
or atypical network topologies,
the exact address to use for callbacks may be nontrivial to determine.
+.IP
+NFS protocol versions 4.1 and 4.2 use the client-established
+TCP connection for callback requests, so do not require the server to
+connect to the client. This option is therefore only affect NFS version
+4.0 mounts.
.TP 1.5i
.BR migration " / " nomigration
Selects whether the client uses an identification string that is compatible
@@ -1726,7 +1727,7 @@ file system table
.TP 1.5i
.I /etc/nfsmount.conf
Configuration file for NFS mounts
-.SH BUGS
+.SH NOTES
Before 2.4.7, the Linux NFS client did not support NFS over TCP.
.P
Before 2.4.20, the Linux NFS client used a heuristic
@@ -1745,9 +1746,9 @@ when the
.BR rsize " and " wsize
settings were smaller than the system's page size.
.P
-The Linux NFS client does not yet support
-certain optional features of the NFS version 4 protocol,
-such as security negotiation, server referrals, and named attributes.
+The Linux client's support for protocol versions depend on whether the
+kernel was built with options CONFIG_NFS_V2, CONFIG_NFS_V3,
+CONFIG_NFS_V4, CONFIG_NFS_V4_1, and CONFIG_NFS_V4_2.
.SH "SEE ALSO"
.BR fstab (5),
.BR mount (8),
@@ -1780,4 +1781,8 @@ RFC 1833 for the RPC bind specification.
.br
RFC 2203 for the RPCSEC GSS API protocol specification.
.br
-RFC 3530 for the NFS version 4 specification.
+RFC 7530 for the NFS version 4.0 specification.
+.br
+RFC 5661 for the NFS version 4.1 specification.
+.br
+RFC 7862 for the NFS version 4.2 specification.

33
SOURCES/nfs-utils-1.3.0-nfs_connect_nb-eintr.patch

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
diff -up nfs-utils-1.3.0/support/nfs/rpc_socket.c.orig nfs-utils-1.3.0/support/nfs/rpc_socket.c
--- nfs-utils-1.3.0/support/nfs/rpc_socket.c.orig 2014-03-25 11:12:07.000000000 -0400
+++ nfs-utils-1.3.0/support/nfs/rpc_socket.c 2016-04-28 11:37:53.694236000 -0400
@@ -215,7 +215,7 @@ static int nfs_connect_nb(const int fd,
* use it later.
*/
ret = connect(fd, sap, salen);
- if (ret < 0 && errno != EINPROGRESS) {
+ if (ret < 0 && errno != EINPROGRESS && errno != EINTR) {
ret = -1;
goto done;
}
@@ -227,10 +227,16 @@ static int nfs_connect_nb(const int fd,
FD_ZERO(&rset);
FD_SET(fd, &rset);
- ret = select(fd + 1, NULL, &rset, NULL, timeout);
- if (ret <= 0) {
- if (ret == 0)
- errno = ETIMEDOUT;
+ while ((ret = select(fd + 1, NULL, &rset, NULL, timeout)) < 0) {
+ if (errno != EINTR) {
+ ret = -1;
+ goto done;
+ } else {
+ continue;
+ }
+ }
+ if (ret == 0) {
+ errno = ETIMEDOUT;
ret = -1;
goto done;
}

12
SOURCES/nfs-utils-1.3.0-nfsclient-after.patch

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
diff -up rhel7/systemd/nfs-client.target.orig rhel7/systemd/nfs-client.target
--- rhel7/systemd/nfs-client.target.orig 2014-03-25 11:12:07.000000000 -0400
+++ rhel7/systemd/nfs-client.target 2014-09-29 11:16:15.470237681 -0400
@@ -7,7 +7,7 @@ Wants=remote-fs-pre.target
# start that on demand if needed.
Wants=rpc-gssd.service rpc-svcgssd.service
Wants=nfs-blkmap.service rpc-statd-notify.service
-Before=rpc-gssd.service rpc-svcgssd.service nfs-blkmap.service
+After=rpc-gssd.service rpc-svcgssd.service nfs-blkmap.service
[Install]
WantedBy=multi-user.target

41
SOURCES/nfs-utils-1.3.0-nfsd-man-correction.patch

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
commit c7896bec9699473959fc51baf3686149a470a30b
Author: Chris Siebenmann <cks.nfs01@cs.toronto.edu>
Date: Tue Mar 14 10:41:39 2017 -0400

Manual page bug: two inaccuracies in nfsd(7)
Here is a patch that deletes the mention of auth.domain and changes the
wording around 'flush' files. I'm not attached to the revised wording;
it's just the best I could manage in something that felt that it was
within the same style and space as the current wording.
Acked-by: NeilBrown <neilb@suse.com>
Signed-off-by: Chris Siebenmann <cks.nfs01@cs.toronto.edu>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/exportfs/nfsd.man b/utils/exportfs/nfsd.man
index 0c516fa..9efa29f 100644
--- a/utils/exportfs/nfsd.man
+++ b/utils/exportfs/nfsd.man
@@ -105,11 +105,6 @@ clients have for different filesystems.
The caches are:
.TP
-.B auth.domain
-This cache maps the name of a client (or domain) to an internal data
-structure. The only access that is possible is to flush the cache.
-
-.TP
.B auth.unix.ip
This cache contains a mapping from IP address to the name of the
authentication domain that the ipaddress should be treated as part of.
@@ -133,7 +128,8 @@ are:
.B flush
When a number of seconds since epoch (1 Jan 1970) is written to this
file, all entries in the cache that were last updated before that file
-become invalidated and will be flushed out. Writing 1 will flush
+become invalidated and will be flushed out. Writing a time in the
+future (in seconds since epoch) will flush
everything. This is the only file that will always be present.
.TP

12
SOURCES/nfs-utils-1.3.0-nfsd-rdma.patch

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
diff -up nfs-utils-1.3.0/utils/nfsd/nfssvc.c.orig nfs-utils-1.3.0/utils/nfsd/nfssvc.c
--- nfs-utils-1.3.0/utils/nfsd/nfssvc.c.orig 2014-03-25 11:12:07.000000000 -0400
+++ nfs-utils-1.3.0/utils/nfsd/nfssvc.c 2016-05-17 10:42:05.000000000 -0400
@@ -278,7 +278,7 @@ nfssvc_set_rdmaport(const char *port)
int fd;
if (sv)
- nport = sv->s_port;
+ nport = ntohs(sv->s_port);
else {
char *ep;
nport = strtol(port, &ep, 10);

26
SOURCES/nfs-utils-1.3.0-nfsd-warnings.patch

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
commit a2e431fdd114f2c2466573471dafef9024392f2d
Author: Steve Dickson <steved@redhat.com>
Date: Wed Apr 30 12:26:06 2014 -0400

nfsd: Remove some warnings nfsd.c
nfsd.c:347:15: warning: comparison between signed and unsigned integer
expressions [-Wsign-compare]
nfsd.c:385:13: warning: comparison between signed and unsigned integer
expressions [-Wsign-compare]
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c
index 73d6a92..03e3c81 100644
--- a/utils/nfsd/nfsd.c
+++ b/utils/nfsd/nfsd.c
@@ -101,7 +101,7 @@ main(int argc, char **argv)
int count = NFSD_NPROC, c, i, error = 0, portnum = 0, fd, found_one;
char *p, *progname, *port, *rdma_port = NULL;
char **haddr = NULL;
- unsigned int hcounter = 0;
+ int hcounter = 0;
int socket_up = 0;
unsigned int minorvers = 0;
unsigned int minorversset = 0;

37
SOURCES/nfs-utils-1.3.0-nfsdcltrack-errors.patch

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
commit 06bbb4ee6f5186e8e83d50767ad5b3b41968e5a6
Author: Jeff Layton <jlayton@redhat.com>
Date: Wed Apr 26 12:13:50 2017 -0400

nfsdcltrack: silence some expected errors
On a new install, we're unable to select from the parameters table, as
it doesn't exist yet. The code is set up to log that fact at L_ERROR
now, but it's an expected situation. Change it to log that at D_GENERAL
instead.
Reported-and-Tested-by: ChunYu Wang <chunwang@redhat.com>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/nfsdcltrack/sqlite.c b/utils/nfsdcltrack/sqlite.c
index 54cd748..1552eba 100644
--- a/utils/nfsdcltrack/sqlite.c
+++ b/utils/nfsdcltrack/sqlite.c
@@ -101,7 +101,7 @@ sqlite_query_schema_version(void)
"SELECT value FROM parameters WHERE key == \"version\";",
-1, &stmt, NULL);
if (ret != SQLITE_OK) {
- xlog(L_ERROR, "Unable to prepare select statement: %s",
+ xlog(D_GENERAL, "Unable to prepare select statement: %s",
sqlite3_errmsg(dbh));
ret = 0;
goto out;
@@ -110,7 +110,7 @@ sqlite_query_schema_version(void)
/* query schema version */
ret = sqlite3_step(stmt);
if (ret != SQLITE_ROW) {
- xlog(L_ERROR, "Select statement execution failed: %s",
+ xlog(D_GENERAL, "Select statement execution failed: %s",
sqlite3_errmsg(dbh));
ret = 0;
goto out;

12
SOURCES/nfs-utils-1.3.0-nfsdcltrack-invalops.patch

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
diff -up nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c.orig nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c
--- nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c.orig 2017-10-12 12:46:02.785182594 -0400
+++ nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c 2017-10-12 13:30:35.756186324 -0400
@@ -591,7 +591,7 @@ main(int argc, char **argv)
break;
default:
usage(progname);
- return 0;
+ return 1;
}
}

21
SOURCES/nfs-utils-1.3.0-nfsdcltrack-usage.patch

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
commit daf0838e30f896d02ca51becc99578713c1be4cb
Author: Steve Dickson <steved@redhat.com>
Date: Wed Dec 7 13:35:49 2016 -0500

Fixed typo in usage string
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/nfsdcltrack/nfsdcltrack.c b/utils/nfsdcltrack/nfsdcltrack.c
index e6e514b..fd64153 100644
--- a/utils/nfsdcltrack/nfsdcltrack.c
+++ b/utils/nfsdcltrack/nfsdcltrack.c
@@ -100,7 +100,7 @@ static unsigned char blob[NFS4_OPAQUE_LIMIT];
static void
usage(char *progname)
{
- printf("%s [ -hfd ] [ -s dir ] < cmd > < arg >\n", progname);
+ printf("Usage: %s [ -hfd ] [ -s dir ] < cmd > < arg >\n", progname);
printf("Where < cmd > is one of the following and takes the following < arg >:\n");
printf(" init\n");
printf(" create <nfs_client_id4>\n");

154
SOURCES/nfs-utils-1.3.0-nfsdcltrack-v2schema-update.patch

@ -0,0 +1,154 @@ @@ -0,0 +1,154 @@
diff -up nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.c.orig nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.c
--- nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.c.orig 2016-02-10 10:46:23.100398000 -0500
+++ nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.c 2016-02-10 10:46:59.540317000 -0500
@@ -29,7 +29,9 @@
*
* clients: an "id" column containing a BLOB with the long-form clientid as
* sent by the client, a "time" column containing a timestamp (in
- * epoch seconds) of when the record was last updated.
+ * epoch seconds) of when the record was last updated, and a
+ * "has_session" column containing a boolean value indicating
+ * whether the client has sessions (v4.1+) or not (v4.0).
*/
#ifdef HAVE_CONFIG_H
@@ -50,7 +52,7 @@
#include "xlog.h"
-#define CLTRACK_SQLITE_LATEST_SCHEMA_VERSION 1
+#define CLTRACK_SQLITE_LATEST_SCHEMA_VERSION 2
/* in milliseconds */
#define CLTRACK_SQLITE_BUSY_TIMEOUT 10000
@@ -120,6 +122,81 @@ out:
return ret;
}
+static int
+sqlite_maindb_update_v1_to_v2(void)
+{
+ int ret, ret2;
+ char *err;
+
+ /* begin transaction */
+ ret = sqlite3_exec(dbh, "BEGIN EXCLUSIVE TRANSACTION;", NULL, NULL,
+ &err);
+ if (ret != SQLITE_OK) {
+ xlog(L_ERROR, "Unable to begin transaction: %s", err);
+ goto rollback;
+ }
+
+ /*
+ * Check schema version again. This time, under an exclusive
+ * transaction to guard against racing DB setup attempts
+ */
+ ret = sqlite_query_schema_version();
+ switch (ret) {
+ case 1:
+ /* Still at v1 -- do conversion */
+ break;
+ case CLTRACK_SQLITE_LATEST_SCHEMA_VERSION:
+ /* Someone else raced in and set it up */
+ ret = 0;
+ goto rollback;
+ default:
+ /* Something went wrong -- fail! */
+ ret = -EINVAL;
+ goto rollback;
+ }
+
+ /* create v2 clients table */
+ ret = sqlite3_exec(dbh, "ALTER TABLE clients ADD COLUMN "
+ "has_session INTEGER;",
+ NULL, NULL, &err);
+ if (ret != SQLITE_OK) {
+ xlog(L_ERROR, "Unable to update clients table: %s", err);
+ goto rollback;
+ }
+
+ ret = snprintf(buf, sizeof(buf), "UPDATE parameters SET value = %d "
+ "WHERE key = \"version\";",
+ CLTRACK_SQLITE_LATEST_SCHEMA_VERSION);
+ if (ret < 0) {
+ xlog(L_ERROR, "sprintf failed!");
+ goto rollback;
+ } else if ((size_t)ret >= sizeof(buf)) {
+ xlog(L_ERROR, "sprintf output too long! (%d chars)", ret);
+ ret = -EINVAL;
+ goto rollback;
+ }
+
+ ret = sqlite3_exec(dbh, (const char *)buf, NULL, NULL, &err);
+ if (ret != SQLITE_OK) {
+ xlog(L_ERROR, "Unable to update schema version: %s", err);
+ goto rollback;
+ }
+
+ ret = sqlite3_exec(dbh, "COMMIT TRANSACTION;", NULL, NULL, &err);
+ if (ret != SQLITE_OK) {
+ xlog(L_ERROR, "Unable to commit transaction: %s", err);
+ goto rollback;
+ }
+out:
+ sqlite3_free(err);
+ return ret;
+rollback:
+ ret2 = sqlite3_exec(dbh, "ROLLBACK TRANSACTION;", NULL, NULL, &err);
+ if (ret2 != SQLITE_OK)
+ xlog(L_ERROR, "Unable to rollback transaction: %s", err);
+ goto out;
+}
+
/*
* Start an exclusive transaction and recheck the DB schema version. If it's
* still zero (indicating a new database) then set it up. If that all works,
@@ -127,9 +204,9 @@ out:
* transaction. On any error, rollback the transaction.
*/
int
-sqlite_maindb_init_v1(void)
+sqlite_maindb_init_v2(void)
{
- int ret;
+ int ret, ret2;
char *err = NULL;
/* Start a transaction */
@@ -169,7 +246,7 @@ sqlite_maindb_init_v1(void)
/* create the "clients" table */
ret = sqlite3_exec(dbh, "CREATE TABLE clients (id BLOB PRIMARY KEY, "
- "time INTEGER);",
+ "time INTEGER, has_session INTEGER);",
NULL, NULL, &err);
if (ret != SQLITE_OK) {
xlog(L_ERROR, "Unable to create clients table: %s", err);
@@ -207,7 +284,9 @@ out:
rollback:
/* Attempt to rollback the transaction */
- sqlite3_exec(dbh, "ROLLBACK TRANSACTION;", NULL, NULL, &err);
+ ret2 = sqlite3_exec(dbh, "ROLLBACK TRANSACTION;", NULL, NULL, &err);
+ if (ret2 != SQLITE_OK)
+ xlog(L_ERROR, "Unable to rollback transaction: %s", err);
goto out;
}
@@ -255,9 +334,15 @@ sqlite_prepare_dbh(const char *topdir)
/* DB is already set up. Do nothing */
ret = 0;
break;
+ case 1:
+ /* Old DB -- update to new schema */
+ ret = sqlite_maindb_update_v1_to_v2();
+ if (ret)
+ goto out_close;
+ break;
case 0:
/* Query failed -- try to set up new DB */
- ret = sqlite_maindb_init_v1();
+ ret = sqlite_maindb_init_v2();
if (ret)
goto out_close;
break;

850
SOURCES/nfs-utils-1.3.0-nfsdcltrack-v2schema.patch

@ -0,0 +1,850 @@ @@ -0,0 +1,850 @@
diff --git a/Makefile.am b/Makefile.am
index c9e9f87..6f3f3d6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,34 +9,6 @@ MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST = \
autogen.sh \
\
- debian/changelog \
- debian/control \
- debian/copyright \
- debian/etc.exports \
- debian/idmapd.conf \
- debian/nfs-common.conffiles \
- debian/nfs-common.default \
- debian/nfs-common.dirs \
- debian/nfs-common.files \
- debian/nfs-common.init \
- debian/nfs-common.install \
- debian/nfs-common.postinst \
- debian/nfs-common.postrm \
- debian/nfs-common.prerm \
- debian/nfs-kernel-server.NEWS \
- debian/nfs-kernel-server.conffiles \
- debian/nfs-kernel-server.default \
- debian/nfs-kernel-server.dirs \
- debian/nfs-kernel-server.init \
- debian/nfs-kernel-server.postinst \
- debian/nfs-kernel-server.postrm \
- debian/nfs-kernel-server.prerm \
- debian/nhfsstone.dirs \
- debian/nhfsstone.files \
- debian/nhfsstone.postinst \
- debian/nhfsstone.prerm \
- debian/rules \
- \
aclocal/bsdsignals.m4 \
aclocal/nfs-utils.m4 \
aclocal/kerberos5.m4 \
diff --git a/support/include/Makefile.am b/support/include/Makefile.am
index 4b33ee9..5c80c8b 100644
--- a/support/include/Makefile.am
+++ b/support/include/Makefile.am
@@ -3,6 +3,7 @@
SUBDIRS = nfs rpcsvc sys
noinst_HEADERS = \
+ cld.h \
exportfs.h \
ha-callout.h \
misc.h \
@@ -10,9 +11,13 @@ noinst_HEADERS = \
nfs_paths.h \
nfslib.h \
nfsrpc.h \
+ nls.h \
nsm.h \
+ pseudoflavors.h \
rpcmisc.h \
+ sockaddr.h \
tcpwrapper.h \
+ v4root.h \
xio.h \
xlog.h \
xmalloc.h \
diff --git a/tests/Makefile.am b/tests/Makefile.am
index faa8197..1f96264 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -11,3 +11,4 @@ SUBDIRS = nsm_client
MAINTAINERCLEANFILES = Makefile.in
TESTS = t0001-statd-basic-mon-unmon.sh
+EXTRA_DIST = test-lib.sh $(TESTS)
diff --git a/tests/nsm_client/Makefile.am b/tests/nsm_client/Makefile.am
index 4c15346..a8fc131 100644
--- a/tests/nsm_client/Makefile.am
+++ b/tests/nsm_client/Makefile.am
@@ -7,6 +7,7 @@ GENFILES_H = nlm_sm_inter.h
GENFILES = $(GENFILES_CLNT) $(GENFILES_SVC) $(GENFILES_XDR) $(GENFILES_H)
+EXTRA_DIST = nlm_sm_inter.x
check_PROGRAMS = nsm_client
nsm_client_SOURCES = $(GENFILES) nsm_client.c
diff --git a/utils/gssd/Makefile.am b/utils/gssd/Makefile.am
index af59791..a4e9c56 100644
--- a/utils/gssd/Makefile.am
+++ b/utils/gssd/Makefile.am
@@ -8,7 +8,6 @@ sbin_PREFIXED = gssd svcgssd
sbin_PROGRAMS = $(sbin_PREFIXED)
EXTRA_DIST = \
- gss_destroy_creds \
$(man8_MANS)
COMMON_SRCS = \
diff --git a/utils/idmapd/Makefile.am b/utils/idmapd/Makefile.am
index 58b33ec..c2f8ba1 100644
--- a/utils/idmapd/Makefile.am
+++ b/utils/idmapd/Makefile.am
@@ -7,8 +7,7 @@ KPREFIX = @kprefix@
sbin_PROGRAMS = idmapd
EXTRA_DIST = \
- $(man8_MANS) \
- idmapd.conf
+ $(man8_MANS)
idmapd_SOURCES = \
idmapd.c \
diff --git a/utils/mount/Makefile.am b/utils/mount/Makefile.am
index 5810936..e24f3bd 100644
--- a/utils/mount/Makefile.am
+++ b/utils/mount/Makefile.am
@@ -8,19 +8,21 @@ man8_MANS = mount.nfs.man umount.nfs.man
man5_MANS = nfs.man
sbin_PROGRAMS = mount.nfs
-EXTRA_DIST = nfsmount.x $(man8_MANS) $(man5_MANS)
+EXTRA_DIST = nfsmount.conf $(man8_MANS) $(man5_MANS)
mount_common = error.c network.c token.c \
parse_opt.c parse_dev.c \
nfsmount.c nfs4mount.c stropts.c\
mount_constants.h error.h network.h token.h \
parse_opt.h parse_dev.h \
- nfs4_mount.h nfs_mount4.h stropts.h version.h \
- mount_config.h utils.c utils.h
+ nfs4_mount.h stropts.h version.h \
+ mount_config.h utils.c utils.h \
+ nfs_mount.h
if MOUNT_CONFIG
mount_common += configfile.c
man5_MANS += nfsmount.conf.man
-EXTRA_DIST += nfsmount.conf
+else
+EXTRA_DIST += nfsmount.conf.man
endif
mount_nfs_LDADD = ../../support/nfs/libnfs.a \
diff --git a/utils/mountd/Makefile.am b/utils/mountd/Makefile.am
index 7db968b..9e1ab5c 100644
--- a/utils/mountd/Makefile.am
+++ b/utils/mountd/Makefile.am
@@ -7,6 +7,7 @@ RPCPREFIX = rpc.
KPREFIX = @kprefix@
sbin_PROGRAMS = mountd
+noinst_HEADERS = fsloc.h
mountd_SOURCES = mountd.c mount_dispatch.c auth.c rmtab.c cache.c \
svc_run.c fsloc.c v4root.c mountd.h
mountd_LDADD = ../../support/export/libexport.a \
diff --git a/utils/nfsd/Makefile.am b/utils/nfsd/Makefile.am
index 1536065..39a6e6f 100644
--- a/utils/nfsd/Makefile.am
+++ b/utils/nfsd/Makefile.am
@@ -7,6 +7,7 @@ RPCPREFIX = rpc.
KPREFIX = @kprefix@
sbin_PROGRAMS = nfsd
+noinst_HEADERS = nfssvc.h
nfsd_SOURCES = nfsd.c nfssvc.c
nfsd_LDADD = ../../support/nfs/libnfs.a $(LIBTIRPC)
diff --git a/utils/nfsdcltrack/Makefile.am b/utils/nfsdcltrack/Makefile.am
index a860ffb..d603f92 100644
--- a/utils/nfsdcltrack/Makefile.am
+++ b/utils/nfsdcltrack/Makefile.am
@@ -6,6 +6,8 @@ EXTRA_DIST = $(man8_MANS)
AM_CFLAGS += -D_LARGEFILE64_SOURCE
sbin_PROGRAMS = nfsdcltrack
+noinst_HEADERS = sqlite.h
+
nfsdcltrack_SOURCES = nfsdcltrack.c sqlite.c
nfsdcltrack_LDADD = ../../support/nfs/libnfs.a $(LIBSQLITE) $(LIBCAP)
diff --git a/utils/nfsdcltrack/nfsdcltrack.c b/utils/nfsdcltrack/nfsdcltrack.c
index 4334340..fcdda7f 100644
--- a/utils/nfsdcltrack/nfsdcltrack.c
+++ b/utils/nfsdcltrack/nfsdcltrack.c
@@ -37,6 +37,7 @@
#include <libgen.h>
#include <sys/inotify.h>
#include <dirent.h>
+#include <limits.h>
#ifdef HAVE_SYS_CAPABILITY_H
#include <sys/prctl.h>
#include <sys/capability.h>
@@ -49,6 +50,8 @@
#define CLD_DEFAULT_STORAGEDIR NFS_STATEDIR "/nfsdcltrack"
#endif
+#define NFSD_END_GRACE_FILE "/proc/fs/nfsd/v4_end_grace"
+
/* defined by RFC 3530 */
#define NFS4_OPAQUE_LIMIT 1024
@@ -210,6 +213,64 @@ cltrack_set_caps(void)
return ret;
}
+/* Inform the kernel that it's OK to lift nfsd's grace period */
+static void
+cltrack_lift_grace_period(void)
+{
+ int fd;
+
+ fd = open(NFSD_END_GRACE_FILE, O_WRONLY);
+ if (fd < 0) {
+ /* Don't warn if file isn't present */
+ if (errno != ENOENT)
+ xlog(L_WARNING, "Unable to open %s: %m",
+ NFSD_END_GRACE_FILE);
+ return;
+ }
+
+ if (write(fd, "Y", 1) < 0)
+ xlog(L_WARNING, "Unable to write to %s: %m",
+ NFSD_END_GRACE_FILE);
+
+ close(fd);
+ return;
+}
+
+/*
+ * Fetch the contents of the NFSDCLTRACK_GRACE_START env var. If it's not set
+ * or there's an error converting it to time_t, then return LONG_MAX.
+ */
+static time_t
+cltrack_get_grace_start(void)
+{
+ time_t grace_start;
+ char *end;
+ char *grace_start_str = getenv("NFSDCLTRACK_GRACE_START");
+
+ if (!grace_start_str)
+ return LONG_MAX;
+
+ errno = 0;
+ grace_start = strtol(grace_start_str, &end, 0);
+ /* Problem converting or value is too large? */
+ if (errno)
+ return LONG_MAX;
+
+ return grace_start;
+}
+
+static bool
+cltrack_reclaims_complete(void)
+{
+ time_t grace_start = cltrack_get_grace_start();
+
+ /* Don't query DB if we didn't get a valid boot time */
+ if (grace_start == LONG_MAX)
+ return false;
+
+ return !sqlite_query_reclaiming(grace_start);
+}
+
static int
cltrack_init(const char __attribute__((unused)) *unused)
{
@@ -241,7 +302,7 @@ cltrack_init(const char __attribute__((unused)) *unused)
}
/* set up storage db */
- ret = sqlite_maindb_init(storagedir);
+ ret = sqlite_prepare_dbh(storagedir);
if (ret) {
xlog(L_ERROR, "Failed to init database: %d", ret);
/*
@@ -250,15 +311,36 @@ cltrack_init(const char __attribute__((unused)) *unused)
* stop upcalling until the problem is resolved.
*/
ret = -EACCES;
+ } else {
+ if (cltrack_reclaims_complete())
+ cltrack_lift_grace_period();
}
+
return ret;
}
+/*
+ * Fetch the contents of the NFSDCLTRACK_CLIENT_HAS_SESSION env var. If
+ * it's set and the first character is 'Y' then return true. Otherwise
+ * return false.
+ */
+static bool
+cltrack_client_has_session(void)
+{
+ char *has_session = getenv("NFSDCLTRACK_CLIENT_HAS_SESSION");
+
+ if (has_session && *has_session == 'Y')
+ return true;
+
+ return false;
+}
+
static int
cltrack_create(const char *id)
{
int ret;
ssize_t len;
+ bool has_session;
xlog(D_GENERAL, "%s: create client record.", __func__);
@@ -270,7 +352,12 @@ cltrack_create(const char *id)
if (len < 0)
return (int)len;
- ret = sqlite_insert_client(blob, len);
+ has_session = cltrack_client_has_session();
+
+ ret = sqlite_insert_client(blob, len, has_session, false);
+
+ if (!ret && has_session && cltrack_reclaims_complete())
+ cltrack_lift_grace_period();
return ret ? -EREMOTEIO : ret;
}
@@ -297,7 +384,8 @@ cltrack_remove(const char *id)
}
static int
-cltrack_check_legacy(const unsigned char *blob, const ssize_t len)
+cltrack_check_legacy(const unsigned char *blob, const ssize_t len,
+ bool has_session)
{
int ret;
struct stat st;
@@ -323,7 +411,7 @@ cltrack_check_legacy(const unsigned char *blob, const ssize_t len)
}
/* Dir exists, try to insert record into db */
- ret = sqlite_insert_client(blob, len);
+ ret = sqlite_insert_client(blob, len, has_session, has_session);
if (ret) {
xlog(D_GENERAL, "Failed to insert client: %d", ret);
return -EREMOTEIO;
@@ -343,6 +431,7 @@ cltrack_check(const char *id)
{
int ret;
ssize_t len;
+ bool has_session;
xlog(D_GENERAL, "%s: check client record", __func__);
@@ -354,9 +443,11 @@ cltrack_check(const char *id)
if (len < 0)
return (int)len;
- ret = sqlite_check_client(blob, len);
+ has_session = cltrack_client_has_session();
+
+ ret = sqlite_check_client(blob, len, has_session);
if (ret)
- ret = cltrack_check_legacy(blob, len);
+ ret = cltrack_check_legacy(blob, len, has_session);
return ret ? -EPERM : ret;
}
diff --git a/utils/nfsdcltrack/sqlite.c b/utils/nfsdcltrack/sqlite.c
index bac6789..eb1711a 100644
--- a/utils/nfsdcltrack/sqlite.c
+++ b/utils/nfsdcltrack/sqlite.c
@@ -21,17 +21,15 @@
* Explanation:
*
* This file contains the code to manage the sqlite backend database for the
- * clstated upcall daemon.
+ * nfsdcltrack usermodehelper upcall program.
*
* The main database is called main.sqlite and contains the following tables:
*
* parameters: simple key/value pairs for storing database info
*
- * clients: one column containing a BLOB with the as sent by the client
- * and a timestamp (in epoch seconds) of when the record was
- * established
- *
- * FIXME: should we also record the fsid being accessed?
+ * clients: an "id" column containing a BLOB with the long-form clientid as
+ * sent by the client, a "time" column containing a timestamp (in
+ * epoch seconds) of when the record was last updated.
*/
#ifdef HAVE_CONFIG_H
@@ -52,10 +50,10 @@
#include "xlog.h"
-#define CLD_SQLITE_SCHEMA_VERSION 1
+#define CLTRACK_SQLITE_LATEST_SCHEMA_VERSION 1
/* in milliseconds */
-#define CLD_SQLITE_BUSY_TIMEOUT 10000
+#define CLTRACK_SQLITE_BUSY_TIMEOUT 10000
/* private data structures */
@@ -90,135 +88,192 @@ mkdir_if_not_exist(const char *dirname)
return ret;
}
-/* Open the database and set up the database handle for it */
-int
-sqlite_prepare_dbh(const char *topdir)
+static int
+sqlite_query_schema_version(void)
{
int ret;
+ sqlite3_stmt *stmt = NULL;
- /* Do nothing if the database handle is already set up */
- if (dbh)
- return 0;
-
- ret = snprintf(buf, PATH_MAX - 1, "%s/main.sqlite", topdir);
- if (ret < 0)
- return ret;
-
- buf[PATH_MAX - 1] = '\0';
-
- ret = sqlite3_open(buf, &dbh);
+ /* prepare select query */
+ ret = sqlite3_prepare_v2(dbh,
+ "SELECT value FROM parameters WHERE key == \"version\";",
+ -1, &stmt, NULL);
if (ret != SQLITE_OK) {
- xlog(L_ERROR, "Unable to open main database: %d", ret);
- dbh = NULL;
- return ret;
+ xlog(L_ERROR, "Unable to prepare select statement: %s",
+ sqlite3_errmsg(dbh));
+ ret = 0;
+ goto out;
}
- ret = sqlite3_busy_timeout(dbh, CLD_SQLITE_BUSY_TIMEOUT);
- if (ret != SQLITE_OK) {
- xlog(L_ERROR, "Unable to set sqlite busy timeout: %d", ret);
- sqlite3_close(dbh);
- dbh = NULL;
+ /* query schema version */
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_ROW) {
+ xlog(L_ERROR, "Select statement execution failed: %s",
+ sqlite3_errmsg(dbh));
+ ret = 0;
+ goto out;
}
+ ret = sqlite3_column_int(stmt, 0);
+out:
+ sqlite3_finalize(stmt);
return ret;
}
/*
- * Open the "main" database, and attempt to initialize it by creating the
- * parameters table and inserting the schema version into it. Ignore any errors
- * from that, and then attempt to select the version out of it again. If the
- * version appears wrong, then assume that the DB is corrupt or has been
- * upgraded, and return an error. If all of that works, then attempt to create
- * the "clients" table.
+ * Start an exclusive transaction and recheck the DB schema version. If it's
+ * still zero (indicating a new database) then set it up. If that all works,
+ * then insert schema version into the parameters table and commit the
+ * transaction. On any error, rollback the transaction.
*/
int
-sqlite_maindb_init(const char *topdir)
+sqlite_maindb_init_v1(void)
{
int ret;
char *err = NULL;
- sqlite3_stmt *stmt = NULL;
- ret = mkdir_if_not_exist(topdir);
- if (ret)
+ /* Start a transaction */
+ ret = sqlite3_exec(dbh, "BEGIN EXCLUSIVE TRANSACTION;", NULL, NULL,
+ &err);
+ if (ret != SQLITE_OK) {
+ xlog(L_ERROR, "Unable to begin transaction: %s", err);
return ret;
+ }
- ret = sqlite_prepare_dbh(topdir);
- if (ret)
- return ret;
+ /*
+ * Check schema version again. This time, under an exclusive
+ * transaction to guard against racing DB setup attempts
+ */
+ ret = sqlite_query_schema_version();
+ switch (ret) {
+ case 0:
+ /* Query failed again -- set up DB */
+ break;
+ case CLTRACK_SQLITE_LATEST_SCHEMA_VERSION:
+ /* Someone else raced in and set it up */
+ ret = 0;
+ goto rollback;
+ default:
+ /* Something went wrong -- fail! */
+ ret = -EINVAL;
+ goto rollback;
+ }
- /* Try to create table */
- ret = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS parameters "
+ ret = sqlite3_exec(dbh, "CREATE TABLE parameters "
"(key TEXT PRIMARY KEY, value TEXT);",
NULL, NULL, &err);
if (ret != SQLITE_OK) {
- xlog(L_ERROR, "Unable to create parameter table: %d", ret);
- goto out_err;
+ xlog(L_ERROR, "Unable to create parameter table: %s", err);
+ goto rollback;
}
- /* insert version into table -- ignore error if it fails */
- ret = snprintf(buf, sizeof(buf),
- "INSERT OR IGNORE INTO parameters values (\"version\", "
- "\"%d\");", CLD_SQLITE_SCHEMA_VERSION);
+ /* create the "clients" table */
+ ret = sqlite3_exec(dbh, "CREATE TABLE clients (id BLOB PRIMARY KEY, "
+ "time INTEGER);",
+ NULL, NULL, &err);
+ if (ret != SQLITE_OK) {
+ xlog(L_ERROR, "Unable to create clients table: %s", err);
+ goto rollback;
+ }
+
+
+ /* insert version into parameters table */
+ ret = snprintf(buf, sizeof(buf), "INSERT OR FAIL INTO parameters "
+ "values (\"version\", \"%d\");",
+ CLTRACK_SQLITE_LATEST_SCHEMA_VERSION);
if (ret < 0) {
- goto out_err;
+ xlog(L_ERROR, "sprintf failed!");
+ goto rollback;
} else if ((size_t)ret >= sizeof(buf)) {
+ xlog(L_ERROR, "sprintf output too long! (%d chars)", ret);
ret = -EINVAL;
- goto out_err;
+ goto rollback;
}
ret = sqlite3_exec(dbh, (const char *)buf, NULL, NULL, &err);
if (ret != SQLITE_OK) {
- xlog(L_ERROR, "Unable to insert into parameter table: %d",
- ret);
- goto out_err;
+ xlog(L_ERROR, "Unable to insert into parameter table: %s", err);
+ goto rollback;
}
- ret = sqlite3_prepare_v2(dbh,
- "SELECT value FROM parameters WHERE key == \"version\";",
- -1, &stmt, NULL);
+ ret = sqlite3_exec(dbh, "COMMIT TRANSACTION;", NULL, NULL, &err);
if (ret != SQLITE_OK) {
- xlog(L_ERROR, "Unable to prepare select statement: %d", ret);
- goto out_err;
+ xlog(L_ERROR, "Unable to commit transaction: %s", err);
+ goto rollback;
}
+out:
+ sqlite3_free(err);
+ return ret;
- /* check schema version */
- ret = sqlite3_step(stmt);
- if (ret != SQLITE_ROW) {
- xlog(L_ERROR, "Select statement execution failed: %s",
+rollback:
+ /* Attempt to rollback the transaction */
+ sqlite3_exec(dbh, "ROLLBACK TRANSACTION;", NULL, NULL, &err);
+ goto out;
+}
+
+/* Open the database and set up the database handle for it */
+int
+sqlite_prepare_dbh(const char *topdir)
+{
+ int ret;
+
+ /* Do nothing if the database handle is already set up */
+ if (dbh)
+ return 0;
+
+ ret = snprintf(buf, PATH_MAX - 1, "%s/main.sqlite", topdir);
+ if (ret < 0)
+ return ret;
+
+ buf[PATH_MAX - 1] = '\0';
+
+ /* open a new DB handle */
+ ret = sqlite3_open(buf, &dbh);
+ if (ret != SQLITE_OK) {
+ /* try to create the dir */
+ ret = mkdir_if_not_exist(topdir);
+ if (ret)
+ goto out_close;
+
+ /* retry open */
+ ret = sqlite3_open(buf, &dbh);
+ if (ret != SQLITE_OK)
+ goto out_close;
+ }
+
+ /* set busy timeout */
+ ret = sqlite3_busy_timeout(dbh, CLTRACK_SQLITE_BUSY_TIMEOUT);
+ if (ret != SQLITE_OK) {
+ xlog(L_ERROR, "Unable to set sqlite busy timeout: %s",
sqlite3_errmsg(dbh));
- goto out_err;
+ goto out_close;
}
- /* process SELECT result */
- ret = sqlite3_column_int(stmt, 0);
- if (ret != CLD_SQLITE_SCHEMA_VERSION) {
+ ret = sqlite_query_schema_version();
+ switch (ret) {
+ case CLTRACK_SQLITE_LATEST_SCHEMA_VERSION:
+ /* DB is already set up. Do nothing */
+ ret = 0;
+ break;
+ case 0:
+ /* Query failed -- try to set up new DB */
+ ret = sqlite_maindb_init_v1();
+ if (ret)
+ goto out_close;
+ break;
+ default:
+ /* Unknown DB version -- downgrade? Fail */
xlog(L_ERROR, "Unsupported database schema version! "
"Expected %d, got %d.",
- CLD_SQLITE_SCHEMA_VERSION, ret);
+ CLTRACK_SQLITE_LATEST_SCHEMA_VERSION, ret);
ret = -EINVAL;
- goto out_err;
- }
-
- /* now create the "clients" table */
- ret = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS clients "
- "(id BLOB PRIMARY KEY, time INTEGER);",
- NULL, NULL, &err);
- if (ret != SQLITE_OK) {
- xlog(L_ERROR, "Unable to create clients table: %s", err);
- goto out_err;
+ goto out_close;
}
- sqlite3_free(err);
- sqlite3_finalize(stmt);
- return 0;
-
-out_err:
- if (err) {
- xlog(L_ERROR, "sqlite error: %s", err);
- sqlite3_free(err);
- }
- sqlite3_finalize(stmt);
+ return ret;
+out_close:
sqlite3_close(dbh);
+ dbh = NULL;
return ret;
}
@@ -228,14 +283,20 @@ out_err:
* Returns a non-zero sqlite error code, or SQLITE_OK (aka 0)
*/
int
-sqlite_insert_client(const unsigned char *clname, const size_t namelen)
+sqlite_insert_client(const unsigned char *clname, const size_t namelen,
+ const bool has_session, const bool zerotime)
{
int ret;
sqlite3_stmt *stmt = NULL;
- ret = sqlite3_prepare_v2(dbh, "INSERT OR REPLACE INTO clients VALUES "
- "(?, strftime('%s', 'now'));", -1,
- &stmt, NULL);
+ if (zerotime)
+ ret = sqlite3_prepare_v2(dbh, "INSERT OR REPLACE INTO clients "
+ "VALUES (?, 0, ?);", -1, &stmt, NULL);
+ else
+ ret = sqlite3_prepare_v2(dbh, "INSERT OR REPLACE INTO clients "
+ "VALUES (?, strftime('%s', 'now'), ?);", -1,
+ &stmt, NULL);
+
if (ret != SQLITE_OK) {
xlog(L_ERROR, "%s: insert statement prepare failed: %s",
__func__, sqlite3_errmsg(dbh));
@@ -250,6 +311,13 @@ sqlite_insert_client(const unsigned char *clname, const size_t namelen)
goto out_err;
}
+ ret = sqlite3_bind_int(stmt, 2, (int)has_session);
+ if (ret != SQLITE_OK) {
+ xlog(L_ERROR, "%s: bind int failed: %s", __func__,
+ sqlite3_errmsg(dbh));
+ goto out_err;
+ }
+
ret = sqlite3_step(stmt);
if (ret == SQLITE_DONE)
ret = SQLITE_OK;
@@ -305,7 +373,8 @@ out_err:
* return an error.
*/
int
-sqlite_check_client(const unsigned char *clname, const size_t namelen)
+sqlite_check_client(const unsigned char *clname, const size_t namelen,
+ const bool has_session)
{
int ret;
sqlite3_stmt *stmt = NULL;
@@ -340,6 +409,12 @@ sqlite_check_client(const unsigned char *clname, const size_t namelen)
goto out_err;
}
+ /* Only update timestamp for v4.0 clients */
+ if (has_session) {
+ ret = SQLITE_OK;
+ goto out_err;
+ }
+
sqlite3_finalize(stmt);
stmt = NULL;
ret = sqlite3_prepare_v2(dbh, "UPDATE OR FAIL clients SET "
@@ -398,3 +473,43 @@ sqlite_remove_unreclaimed(time_t grace_start)
sqlite3_free(err);
return ret;
}
+
+/*
+ * Are there any clients that are possibly still reclaiming? Return a positive
+ * integer (usually number of clients) if so. If not, then return 0. On any
+ * error, return non-zero.
+ */
+int
+sqlite_query_reclaiming(const time_t grace_start)
+{
+ int ret;
+ sqlite3_stmt *stmt = NULL;
+
+ ret = sqlite3_prepare_v2(dbh, "SELECT count(*) FROM clients WHERE "
+ "time < ? OR has_session != 1", -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ xlog(L_ERROR, "%s: unable to prepare select statement: %s",
+ __func__, sqlite3_errmsg(dbh));
+ return ret;
+ }
+
+ ret = sqlite3_bind_int64(stmt, 1, (sqlite3_int64)grace_start);
+ if (ret != SQLITE_OK) {
+ xlog(L_ERROR, "%s: bind int64 failed: %s",
+ __func__, sqlite3_errmsg(dbh));
+ return ret;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_ROW) {
+ xlog(L_ERROR, "%s: unexpected return code from select: %s",
+ __func__, sqlite3_errmsg(dbh));
+ return ret;
+ }
+
+ ret = sqlite3_column_int(stmt, 0);
+ sqlite3_finalize(stmt);
+ xlog(D_GENERAL, "%s: there are %d clients that have not completed "
+ "reclaim", __func__, ret);
+ return ret;
+}
diff --git a/utils/nfsdcltrack/sqlite.h b/utils/nfsdcltrack/sqlite.h
index ebf04c3..06e7c04 100644
--- a/utils/nfsdcltrack/sqlite.h
+++ b/utils/nfsdcltrack/sqlite.h
@@ -21,10 +21,12 @@
#define _SQLITE_H_
int sqlite_prepare_dbh(const char *topdir);
-int sqlite_maindb_init(const char *topdir);
-int sqlite_insert_client(const unsigned char *clname, const size_t namelen);
+int sqlite_insert_client(const unsigned char *clname, const size_t namelen,
+ const bool has_session, const bool zerotime);
int sqlite_remove_client(const unsigned char *clname, const size_t namelen);
-int sqlite_check_client(const unsigned char *clname, const size_t namelen);
+int sqlite_check_client(const unsigned char *clname, const size_t namelen,
+ const bool has_session);
int sqlite_remove_unreclaimed(const time_t grace_start);
+int sqlite_query_reclaiming(const time_t grace_start);
#endif /* _SQLITE_H */
diff --git a/utils/nfsidmap/Makefile.am b/utils/nfsidmap/Makefile.am
index 737a219..91cedfd 100644
--- a/utils/nfsidmap/Makefile.am
+++ b/utils/nfsidmap/Makefile.am
@@ -7,4 +7,4 @@ nfsidmap_SOURCES = nfsidmap.c
nfsidmap_LDADD = $(LIBNFSIDMAP) -lkeyutils ../../support/nfs/libnfs.a
MAINTAINERCLEANFILES = Makefile.in
-EXTRA_DIST = id_resolver.conf
+EXTRA_DIST = id_resolver.conf $(man8_MANS)
diff --git a/utils/osd_login/Makefile.am b/utils/osd_login/Makefile.am
index 20c2d8c..ded1fd3 100644
--- a/utils/osd_login/Makefile.am
+++ b/utils/osd_login/Makefile.am
@@ -4,6 +4,6 @@
# overridden at config time.
sbindir = /sbin
-sbin_SCRIPTS = osd_login
+dist_sbin_SCRIPTS = osd_login
MAINTAINERCLEANFILES = Makefile.in
diff --git a/utils/statd/Makefile.am b/utils/statd/Makefile.am
index dc2bfc4..152b680 100644
--- a/utils/statd/Makefile.am
+++ b/utils/statd/Makefile.am
@@ -8,7 +8,7 @@ sbin_PROGRAMS = statd sm-notify
dist_sbin_SCRIPTS = start-statd
statd_SOURCES = callback.c notlist.c misc.c monitor.c hostname.c \
simu.c stat.c statd.c svc_run.c rmtcall.c \
- notlist.h statd.h system.h version.h
+ notlist.h statd.h system.h
sm_notify_SOURCES = sm-notify.c
BUILT_SOURCES = $(GENFILES)
@@ -20,7 +20,7 @@ sm_notify_LDADD = ../../support/nsm/libnsm.a \
../../support/nfs/libnfs.a \
$(LIBNSL) $(LIBCAP) $(LIBTIRPC)
-EXTRA_DIST = sim_sm_inter.x $(man8_MANS) COPYRIGHT simulate.c
+EXTRA_DIST = sim_sm_inter.x $(man8_MANS) simulate.c
if CONFIG_RPCGEN
RPCGEN = $(top_builddir)/tools/rpcgen/rpcgen

24
SOURCES/nfs-utils-1.3.0-nfsdcltrack-warning01.patch

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
commit d6ee36b8dcc663dc2b797d51e553f390ea2f7e31
Author: Steve Dickson <steved@redhat.com>
Date: Wed Jul 19 16:42:39 2017 -0400

nfsdcltrack.c: remove a warning
nfsdcltrack.c:581:4: warning: this statement may fall through [-Wimplicit-fallthrough=]
Acked-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
(cherry picked from commit f80c9984339da6f689f330b8a83d5ee503126827)

diff --git a/utils/nfsdcltrack/nfsdcltrack.c b/utils/nfsdcltrack/nfsdcltrack.c
index 7af9efb..2f58f96 100644
--- a/utils/nfsdcltrack/nfsdcltrack.c
+++ b/utils/nfsdcltrack/nfsdcltrack.c
@@ -581,6 +581,7 @@ main(int argc, char **argv)
switch (arg) {
case 'd':
xlog_config(D_ALL, 1);
+ break;
case 'f':
xlog_syslog(0);
xlog_stderr(1);

55
SOURCES/nfs-utils-1.3.0-nfsidmap-h-opt.patch

@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
diff -up nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c.orig nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c
--- nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c.orig 2016-06-08 09:59:09.920690710 -0400
+++ nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c 2016-06-08 11:22:01.104971559 -0400
@@ -16,7 +16,7 @@
#include "conffile.h"
int verbose = 0;
-char *usage = "Usage: %s [-v] [-c || [-u|-g|-r key] || -d || -l || [-t timeout] key desc]";
+char *usage = "Usage: %s [-vh] [-c || [-u|-g|-r key] || -d || -l || [-t timeout] key desc]";
#define MAX_ID_LEN 11
#define IDMAP_NAMESZ 128
@@ -355,7 +355,7 @@ int main(int argc, char **argv)
xlog_open(progname);
- while ((opt = getopt(argc, argv, "du:g:r:ct:vl")) != -1) {
+ while ((opt = getopt(argc, argv, "hdu:g:r:ct:vl")) != -1) {
switch (opt) {
case 'd':
display++;
@@ -384,9 +384,10 @@ int main(int argc, char **argv)
case 't':
timeout = atoi(optarg);
break;
+ case 'h':
default:
xlog_warn(usage, progname);
- break;
+ exit(opt == 'h' ? 0 : 1);
}
}
diff -up nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.man.orig nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.man
--- nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.man.orig 2016-06-08 09:59:09.899690366 -0400
+++ nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.man 2016-06-08 11:22:01.104971559 -0400
@@ -15,6 +15,8 @@ nfsidmap \- The NFS idmapper upcall prog
.B "nfsidmap -d"
.br
.B "nfsidmap -l"
+.br
+.B "nfsidmap -h"
.SH DESCRIPTION
The NFSv4 protocol represents the local system's UID and GID values
on the wire as strings of the form
@@ -71,6 +73,9 @@ Display the system's effective NFSv4 dom
.B -g user
Revoke the gid key of the given user.
.TP
+.B -h
+Display usage message.
+.TP
.B -l
Display on
.I stdout

22
SOURCES/nfs-utils-1.3.0-nfsidmap-timeout.patch

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
diff -up nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c.save nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c
--- nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c.save 2015-11-24 09:29:53.332040370 -0500
+++ nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c 2015-11-24 09:30:06.579249849 -0500
@@ -24,7 +24,7 @@ char *usage="Usage: %s [-v] [-c || [-u|-
#define PROCKEYS "/proc/keys"
#ifndef DEFAULT_KEYRING
-#define DEFAULT_KEYRING "id_resolver"
+#define DEFAULT_KEYRING ".id_resolver"
#endif
#ifndef PATH_IDMAPDCONF
@@ -315,6 +315,9 @@ int main(int argc, char **argv)
key, type, value, timeout);
}
+ /* Become a possesor of the to-be-instantiated key to set the key's timeout */
+ request_key("keyring", DEFAULT_KEYRING, NULL, KEY_SPEC_THREAD_KEYRING);
+
if (strcmp(type, "uid") == 0)
rc = id_lookup(value, key, USER);
else if (strcmp(type, "gid") == 0)

574
SOURCES/nfs-utils-1.3.0-nfsidmap-update.patch

@ -0,0 +1,574 @@ @@ -0,0 +1,574 @@
diff --git a/aclocal/keyutils.m4 b/aclocal/keyutils.m4
index a392c0e..16b225d 100644
--- a/aclocal/keyutils.m4
+++ b/aclocal/keyutils.m4
@@ -8,4 +8,8 @@ AC_DEFUN([AC_KEYUTILS], [
AC_CHECK_HEADERS([keyutils.h])
+ AC_CHECK_LIB([keyutils], [find_key_by_type_and_desc],
+ [AC_DEFINE([HAVE_FIND_KEY_BY_TYPE_AND_DESC], [1],
+ [Define to 1 if you have the `find_key_by_type_and_desc' function.])],)
+
])dnl
diff --git a/utils/nfsidmap/nfsidmap.c b/utils/nfsidmap/nfsidmap.c
index 10f69f9..9c49d42 100644
--- a/utils/nfsidmap/nfsidmap.c
+++ b/utils/nfsidmap/nfsidmap.c
@@ -1,3 +1,4 @@
+#include "config.h"
#include <stdarg.h>
#include <stdio.h>
@@ -15,7 +16,7 @@
#include "conffile.h"
int verbose = 0;
-char *usage="Usage: %s [-v] [-c || [-u|-g|-r key] || [-t timeout] key desc]";
+char *usage = "Usage: %s [-v] [-c || [-u|-g|-r key] || -d || -l || [-t timeout] key desc]";
#define MAX_ID_LEN 11
#define IDMAP_NAMESZ 128
@@ -31,15 +32,163 @@ char *usage="Usage: %s [-v] [-c || [-u|-g|-r key] || [-t timeout] key desc]";
#define PATH_IDMAPDCONF "/etc/idmapd.conf"
#endif
-static int keyring_clear(char *keyring);
-
#define UIDKEYS 0x1
#define GIDKEYS 0x2
+#ifndef HAVE_FIND_KEY_BY_TYPE_AND_DESC
+static key_serial_t find_key_by_type_and_desc(const char *type,
+ const char *desc, key_serial_t destringid)
+{
+ char buf[BUFSIZ];
+ key_serial_t key;
+ FILE *fp;
+
+ if ((fp = fopen(PROCKEYS, "r")) == NULL) {
+ xlog_err("fopen(%s) failed: %m", PROCKEYS);
+ return -1;
+ }
+
+ key = -1;
+ while(fgets(buf, BUFSIZ, fp) != NULL) {
+ unsigned int id;
+
+ if (strstr(buf, type) == NULL)
+ continue;
+ if (strstr(buf, desc) == NULL)
+ continue;
+ if (sscanf(buf, "%x %*s", &id) != 1) {
+ xlog_err("Unparsable keyring entry in %s", PROCKEYS);
+ continue;
+ }
+
+ key = (key_serial_t)id;
+ break;
+ }
+
+ fclose(fp);
+ return key;
+}
+#endif
+
+/*
+ * Clear all the keys on the given keyring
+ */
+static int keyring_clear(const char *keyring)
+{
+ key_serial_t key;
+
+ key = find_key_by_type_and_desc("keyring", keyring, 0);
+ if (key == -1) {
+ if (verbose)
+ xlog_warn("'%s' keyring was not found.", keyring);
+ return EXIT_SUCCESS;
+ }
+
+ if (keyctl_clear(key) < 0) {
+ xlog_err("keyctl_clear(0x%x) failed: %m",
+ (unsigned int)key);
+ return EXIT_FAILURE;
+ }
+
+ if (verbose)
+ xlog_warn("'%s' cleared", keyring);
+ return EXIT_SUCCESS;
+}
+
+static int display_default_domain(void)
+{
+ char domain[NFS4_MAX_DOMAIN_LEN];
+ int rc;
+
+ rc = nfs4_get_default_domain(NULL, domain, NFS4_MAX_DOMAIN_LEN);
+ if (rc) {
+ xlog_errno(rc, "nfs4_get_default_domain failed: %m");
+ return EXIT_FAILURE;
+ }
+
+ printf("%s\n", domain);
+ return EXIT_SUCCESS;
+}
+
+static void list_key(key_serial_t key)
+{
+ char *buffer, *c;
+ int rc;
+
+ rc = keyctl_describe_alloc(key, &buffer);
+ if (rc < 0) {
+ switch (errno) {
+ case EKEYEXPIRED:
+ printf("Expired key not displayed\n");
+ break;
+ default:
+ xlog_err("Failed to describe key: %m");
+ }
+ return;
+ }
+
+ c = strrchr(buffer, ';');
+ if (!c) {
+ xlog_err("Unparsable key not displayed\n");
+ goto out_free;
+ }
+ printf(" %s\n", ++c);
+
+out_free:
+ free(buffer);
+}
+
+static void list_keys(const char *ring_name, key_serial_t ring_id)
+{
+ key_serial_t *key;
+ void *keylist;
+ int count;
+
+ count = keyctl_read_alloc(ring_id, &keylist);
+ if (count < 0) {
+ xlog_err("Failed to read keyring %s: %m", ring_name);
+ return;
+ }
+ count /= (int)sizeof(*key);
+
+ switch (count) {
+ case 0:
+ printf("No %s keys found.\n", ring_name);
+ break;
+ case 1:
+ printf("1 %s key found:\n", ring_name);
+ break;
+ default:
+ printf("%u %s keys found:\n", count, ring_name);
+ }
+
+ for (key = keylist; count--; key++)
+ list_key(*key);
+
+ free(keylist);
+}
+
+/*
+ * List all keys on a keyring
+ */
+static int list_keyring(const char *keyring)
+{
+ key_serial_t key;
+
+ key = find_key_by_type_and_desc("keyring", keyring, 0);
+ if (key == -1) {
+ xlog_err("'%s' keyring was not found.", keyring);
+ return EXIT_FAILURE;
+ }
+
+ list_keys(keyring, key);
+ return EXIT_SUCCESS;
+}
+
/*
* Find either a user or group id based on the name@domain string
*/
-int id_lookup(char *name_at_domain, key_serial_t key, int type)
+static int id_lookup(char *name_at_domain, key_serial_t key, int type)
{
char id[MAX_ID_LEN];
uid_t uid = 0;
@@ -53,30 +202,33 @@ int id_lookup(char *name_at_domain, key_serial_t key, int type)
rc = nfs4_group_owner_to_gid(name_at_domain, &gid);
sprintf(id, "%u", gid);
}
- if (rc < 0)
+ if (rc < 0) {
xlog_errno(rc, "id_lookup: %s: failed: %m",
(type == USER ? "nfs4_owner_to_uid" : "nfs4_group_owner_to_gid"));
+ return EXIT_FAILURE;
+ }
- if (rc == 0) {
- rc = keyctl_instantiate(key, id, strlen(id) + 1, 0);
- if (rc < 0) {
- switch(rc) {
- case -EDQUOT:
- case -ENFILE:
- case -ENOMEM:
- /*
- * The keyring is full. Clear the keyring and try again
- */
- rc = keyring_clear(DEFAULT_KEYRING);
- if (rc == 0)
- rc = keyctl_instantiate(key, id, strlen(id) + 1, 0);
- break;
- default:
+ rc = EXIT_SUCCESS;
+ if (keyctl_instantiate(key, id, strlen(id) + 1, 0)) {
+ switch (errno) {
+ case EDQUOT:
+ case ENFILE:
+ case ENOMEM:
+ /*
+ * The keyring is full. Clear the keyring and try again
+ */
+ rc = keyring_clear(DEFAULT_KEYRING);
+ if (rc)
break;
+ if (keyctl_instantiate(key, id, strlen(id) + 1, 0)) {
+ rc = EXIT_FAILURE;
+ xlog_err("id_lookup: keyctl_instantiate failed: %m");
}
+ break;
+ default:
+ rc = EXIT_FAILURE;
+ break;
}
- if (rc < 0)
- xlog_err("id_lookup: keyctl_instantiate failed: %m");
}
return rc;
@@ -85,7 +237,7 @@ int id_lookup(char *name_at_domain, key_serial_t key, int type)
/*
* Find the name@domain string from either a user or group id
*/
-int name_lookup(char *id, key_serial_t key, int type)
+static int name_lookup(char *id, key_serial_t key, int type)
{
char name[IDMAP_NAMESZ];
char domain[NFS4_MAX_DOMAIN_LEN];
@@ -94,11 +246,10 @@ int name_lookup(char *id, key_serial_t key, int type)
int rc;
rc = nfs4_get_default_domain(NULL, domain, NFS4_MAX_DOMAIN_LEN);
- if (rc != 0) {
+ if (rc) {
xlog_errno(rc,
"name_lookup: nfs4_get_default_domain failed: %m");
- rc = -1;
- goto out;
+ return EXIT_FAILURE;
}
if (type == USER) {
@@ -108,61 +259,21 @@ int name_lookup(char *id, key_serial_t key, int type)
gid = atoi(id);
rc = nfs4_gid_to_name(gid, domain, name, IDMAP_NAMESZ);
}
- if (rc < 0)
+ if (rc) {
xlog_errno(rc, "name_lookup: %s: failed: %m",
(type == USER ? "nfs4_uid_to_name" : "nfs4_gid_to_name"));
-
- if (rc == 0) {
- rc = keyctl_instantiate(key, &name, strlen(name), 0);
- if (rc < 0)
- xlog_err("name_lookup: keyctl_instantiate failed: %m");
+ return EXIT_FAILURE;
}
-out:
- return rc;
-}
-/*
- * Clear all the keys on the given keyring
- */
-static int keyring_clear(char *keyring)
-{
- FILE *fp;
- char buf[BUFSIZ];
- key_serial_t key;
- if (keyring == NULL)
- keyring = DEFAULT_KEYRING;
-
- if ((fp = fopen(PROCKEYS, "r")) == NULL) {
- xlog_err("fopen(%s) failed: %m", PROCKEYS);
- return 1;
+ rc = EXIT_SUCCESS;
+ if (keyctl_instantiate(key, &name, strlen(name), 0)) {
+ rc = EXIT_FAILURE;
+ xlog_err("name_lookup: keyctl_instantiate failed: %m");
}
- while(fgets(buf, BUFSIZ, fp) != NULL) {
- if (strstr(buf, "keyring") == NULL)
- continue;
- if (strstr(buf, keyring) == NULL)
- continue;
- if (verbose) {
- *(strchr(buf, '\n')) = '\0';
- xlog_warn("clearing '%s'", buf);
- }
- /*
- * The key is the first arugment in the string
- */
- *(strchr(buf, ' ')) = '\0';
- sscanf(buf, "%x", &key);
- if (keyctl_clear(key) < 0) {
- xlog_err("keyctl_clear(0x%x) failed: %m", key);
- fclose(fp);
- return 1;
- }
- fclose(fp);
- return 0;
- }
- xlog_err("'%s' keyring was not found.", keyring);
- fclose(fp);
- return 1;
+ return rc;
}
+
/*
* Revoke a key
*/
@@ -177,7 +288,7 @@ static int key_invalidate(char *keystr, int keymask)
if ((fp = fopen(PROCKEYS, "r")) == NULL) {
xlog_err("fopen(%s) failed: %m", PROCKEYS);
- return 1;
+ return EXIT_FAILURE;
}
while(fgets(buf, BUFSIZ, fp) != NULL) {
@@ -211,18 +322,18 @@ static int key_invalidate(char *keystr, int keymask)
if (keyctl_invalidate(key) < 0) {
xlog_err("keyctl_invalidate(0x%x) failed: %m", key);
fclose(fp);
- return 1;
+ return EXIT_FAILURE;
}
keymask &= ~mask;
if (keymask == 0) {
fclose(fp);
- return 0;
+ return EXIT_SUCCESS;
}
}
xlog_err("'%s' key was not found.", keystr);
fclose(fp);
- return 1;
+ return EXIT_FAILURE;
}
int main(int argc, char **argv)
@@ -234,7 +345,7 @@ int main(int argc, char **argv)
int timeout = 600;
key_serial_t key;
char *progname, *keystr = NULL;
- int clearing = 0, keymask = 0;
+ int clearing = 0, keymask = 0, display = 0, list = 0;
/* Set the basename */
if ((progname = strrchr(argv[0], '/')) != NULL)
@@ -244,8 +355,14 @@ int main(int argc, char **argv)
xlog_open(progname);
- while ((opt = getopt(argc, argv, "u:g:r:ct:v")) != -1) {
+ while ((opt = getopt(argc, argv, "du:g:r:ct:vl")) != -1) {
switch (opt) {
+ case 'd':
+ display++;
+ break;
+ case 'l':
+ list++;
+ break;
case 'u':
keymask = UIDKEYS;
keystr = strdup(optarg);
@@ -273,28 +390,35 @@ int main(int argc, char **argv)
}
}
+ if (geteuid() != 0) {
+ xlog_err("Must be run as root.");
+ return EXIT_FAILURE;
+ }
+
if ((rc = nfs4_init_name_mapping(PATH_IDMAPDCONF))) {
xlog_errno(rc, "Unable to create name to user id mappings.");
- return 1;
+ return EXIT_FAILURE;
}
if (!verbose)
verbose = conf_get_num("General", "Verbosity", 0);
+ if (display)
+ return display_default_domain();
+ if (list)
+ return list_keyring(DEFAULT_KEYRING);
if (keystr) {
- rc = key_invalidate(keystr, keymask);
- return rc;
+ return key_invalidate(keystr, keymask);
}
if (clearing) {
xlog_syslog(0);
- rc = keyring_clear(DEFAULT_KEYRING);
- return rc;
+ return keyring_clear(DEFAULT_KEYRING);
}
- xlog_stderr(0);
+ xlog_stderr(verbose);
if ((argc - optind) != 2) {
- xlog_err("Bad arg count. Check /etc/request-key.conf");
+ xlog_warn("Bad arg count. Check /etc/request-key.conf");
xlog_warn(usage, progname);
- return 1;
+ return EXIT_FAILURE;
}
if (verbose)
@@ -305,11 +429,15 @@ int main(int argc, char **argv)
arg = strdup(argv[optind]);
if (arg == NULL) {
xlog_err("strdup failed: %m");
- return 1;
+ return EXIT_FAILURE;
}
type = strtok(arg, ":");
value = strtok(NULL, ":");
-
+ if (value == NULL) {
+ free(arg);
+ xlog_err("Error: Null uid/gid value.");
+ return EXIT_FAILURE;
+ }
if (verbose) {
xlog_warn("key: 0x%lx type: %s value: %s timeout %ld",
key, type, value, timeout);
@@ -328,7 +456,7 @@ int main(int argc, char **argv)
rc = name_lookup(value, key, GROUP);
/* Set timeout to 10 (600 seconds) minutes */
- if (rc == 0)
+ if (rc == EXIT_SUCCESS)
keyctl_set_timeout(key, timeout);
free(arg);
diff --git a/utils/nfsidmap/nfsidmap.man b/utils/nfsidmap/nfsidmap.man
index 3a3a523..0275bdf 100644
--- a/utils/nfsidmap/nfsidmap.man
+++ b/utils/nfsidmap/nfsidmap.man
@@ -11,30 +11,72 @@ nfsidmap \- The NFS idmapper upcall program
.B "nfsidmap [-v] [-c]"
.br
.B "nfsidmap [-v] [-u|-g|-r user]"
+.br
+.B "nfsidmap -d"
+.br
+.B "nfsidmap -l"
.SH DESCRIPTION
-The file
+The NFSv4 protocol represents the local system's UID and GID values
+on the wire as strings of the form
+.IR user@domain .
+The process of translating from UID to string and string to UID is
+referred to as "ID mapping."
+.PP
+The system derives the
+.I user
+part of the string by performing a password or group lookup.
+The lookup mechanism is configured in
+.IR /etc/idmapd.conf .
+.PP
+By default, the
+.I domain
+part of the string is the system's DNS domain name.
+It can also be specified in
+.I /etc/idmapd.conf
+if the system is multi-homed,
+or if the system's DNS domain name does
+not match the name of the system's Kerberos realm.
+.PP
+The
.I /usr/sbin/nfsidmap
-is used by the NFS idmapper to translate user and group ids into names, and to
-translate user and group names into ids. Idmapper uses request-key to perform
-the upcall and cache the result.
+program performs translations on behalf of the kernel.
+The kernel uses the request-key mechanism to perform
+an upcall.
.I /usr/sbin/nfsidmap
-is called by /sbin/request-key, and will perform the translation and
-initialize a key with the resulting information.
+is invoked by /sbin/request-key, performs the translation,
+and initializes a key with the resulting information.
+The kernel then caches the translation results in the key.
.PP
.I nfsidmap
-can also used to clear the keyring of all the keys or
-revoke one particular key.
-This is useful when the id mappings have failed to due
-to a lookup error resulting in all the cached uids/gids to be set
-to the user id nobody.
+can also clear cached ID map results in the kernel,
+or revoke one particular key.
+An incorrect cached key can result in file and directory ownership
+reverting to "nobody" on NFSv4 mount points.
+.PP
+In addition, the
+.B -d
+and
+.B -l
+options are available to help diagnose misconfigurations.
+They have no effect on the keyring containing ID mapping results.
.SH OPTIONS
.TP
.B -c
Clear the keyring of all the keys.
.TP
+.B -d
+Display the system's effective NFSv4 domain name on
+.IR stdout .
+.TP
.B -g user
Revoke the gid key of the given user.
.TP
+.B -l
+Display on
+.I stdout
+all keys currently in the keyring used to cache ID mapping results.
+These keys are visible only to the superuser.
+.TP
.B -r user
Revoke both the uid and gid key of the given user.
.TP
@@ -89,5 +131,15 @@ Notice that the new line was added above the line for the generic program.
request-key will find the first matching line and run the corresponding program.
In this case, /some/other/program will handle all uid lookups, and
/usr/sbin/nfsidmap will handle gid, user, and group lookups.
+.SH FILES
+.TP
+.I /etc/idmapd.conf
+ID mapping configuration file
+.TP
+.I /etc/request-key.conf
+Request key configuration file
+.SH "SEE ALSO"
+.BR idmapd.conf (5),
+.BR request-key (8)
.SH AUTHOR
Bryan Schumaker, <bjschuma@netapp.com>

74
SOURCES/nfs-utils-1.3.0-nfsiostat-output.patch

@ -0,0 +1,74 @@ @@ -0,0 +1,74 @@
commit a4793601381656a64abe20ed8c2242f0eb2496e6
Author: Jan Chaloupka <jchaloup@redhat.com>
Date: Mon Jun 16 09:47:32 2014 -0400

nfsiostat: Document the output columns in the manpage
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/tools/nfs-iostat/nfsiostat.man b/tools/nfs-iostat/nfsiostat.man
index 3ec245d..b477a9a 100644
--- a/tools/nfs-iostat/nfsiostat.man
+++ b/tools/nfs-iostat/nfsiostat.man
@@ -38,6 +38,61 @@ If one or more
.I <mount point>
names are specified, statistics for only these mount points will
be displayed. Otherwise, all NFS mount points on the client are listed.
+.TP
+The meaning of each column of \fBnfsiostat\fR's output is the following:
+.RS 8
+- \fBop/s\fR
+.RS
+This is the number of operations per second.
+.RS
+.RE
+.RE
+.RE
+.RS 8
+- \fBrpc bklog\fR
+.RS
+This is the length of the backlog queue.
+.RE
+.RE
+.RE
+.RS 8
+- \fBkB/s\fR
+.RS
+This is the number of kB written/read per second.
+.RE
+.RE
+.RE
+.RS 8
+- \fBkB/op\fR
+.RS
+This is the number of kB written/read per each operation.
+.RE
+.RE
+.RE
+.RS 8
+- \fBretrans\fR
+.RS
+This is the number of retransmissions.
+.RE
+.RE
+.RE
+.RS 8
+- \fBavg RTT (ms)\fR
+.RS
+This is the duration from the time that client's kernel sends the RPC request until the time it receives the reply.
+.RE
+.RE
+.RE
+.RS 8
+- \fBavg exe (ms)\fR
+.RS
+This is the duration from the time that NFS client does the RPC request to its kernel until the RPC request is completed, this includes the RTT time above.
+.RE
+.RE
+.RE
+.TP
+Note that if an interval is used as argument to \fBnfsiostat\fR, then the diffrence from previous interval will be displayed, otherwise the results will be from the time that the share was mounted.
+
.SH OPTIONS
.TP
.B \-a " or " \-\-attr

27
SOURCES/nfs-utils-1.3.0-nfsman-minorversion.patch

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
diff -up nfs-utils-1.3.0/utils/mount/nfs.man.orig nfs-utils-1.3.0/utils/mount/nfs.man
--- nfs-utils-1.3.0/utils/mount/nfs.man.orig 2017-03-31 16:15:33.487985468 -0400
+++ nfs-utils-1.3.0/utils/mount/nfs.man 2017-03-31 16:30:21.321755420 -0400
@@ -769,6 +769,23 @@ so if this mount option is not specified
uses the TCP protocol.
Refer to the TRANSPORT METHODS section for more details.
.TP 1.5i
+.BI minorversion= n
+Specifies the protocol minor version number.
+NFSv4 introduces "minor versioning," where NFS protocol enhancements can
+be introduced without bumping the NFS protocol version number.
+Before kernel 2.6.38, the minor version is always zero, and this
+option is not recognized.
+After this kernel, specifying "minorversion=1" enables a number of
+advanced features, such as NFSv4 sessions.
+.IP
+Recent kernels allow the minor version to be specified using the
+.B vers=
+option.
+For example, specifying
+.B vers=4.1
+is the same as specifying
+.BR vers=4,minorversion=1 .
+.TP 1.5i
.BI port= n
The numeric value of the server's NFS service port.
If the server's NFS service is not available on the specified port,

12
SOURCES/nfs-utils-1.3.0-nfsstat-mounts.patch

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
diff -up nfs-utils-1.3.0/utils/nfsstat/nfsstat.c.orig nfs-utils-1.3.0/utils/nfsstat/nfsstat.c
--- nfs-utils-1.3.0/utils/nfsstat/nfsstat.c.orig 2017-04-09 04:32:28.951729219 -0400
+++ nfs-utils-1.3.0/utils/nfsstat/nfsstat.c 2017-04-09 04:34:49.686756801 -0400
@@ -299,7 +299,7 @@ static struct option longopts[] =
{ "all", 0, 0, 'v' },
{ "auto", 0, 0, '\3' },
{ "client", 0, 0, 'c' },
- { "mounted", 0, 0, 'm' },
+ { "mounts", 0, 0, 'm' },
{ "nfs", 0, 0, 'n' },
{ "rpc", 0, 0, 'r' },
{ "server", 0, 0, 's' },

30
SOURCES/nfs-utils-1.3.0-nfsstat-retval.patch

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
diff -up nfs-utils-1.3.0/utils/nfsstat/nfsstat.c.orig nfs-utils-1.3.0/utils/nfsstat/nfsstat.c
--- nfs-utils-1.3.0/utils/nfsstat/nfsstat.c.orig 2014-03-25 11:12:07.000000000 -0400
+++ nfs-utils-1.3.0/utils/nfsstat/nfsstat.c 2017-03-29 12:10:52.820709442 -0400
@@ -348,7 +348,7 @@ main(int argc, char **argv)
switch (c) {
case 'a':
fprintf(stderr, "nfsstat: nfs acls are not yet supported.\n");
- return -1;
+ return 1;
case 'c':
opt_clt = 1;
break;
@@ -410,7 +410,7 @@ main(int argc, char **argv)
"not yet supported\n");
return 2;
case 'm':
- return mounts(MOUNTSFILE);
+ return ! mounts(MOUNTSFILE);
case '\1':
usage(progname);
return 0;
@@ -419,7 +419,7 @@ main(int argc, char **argv)
return 0;
default:
printf("Try `%s --help' for more information.\n", progname);
- return -1;
+ return 1;
}
}

398
SOURCES/nfs-utils-1.3.0-rpcgssd-acceptor.patch

@ -0,0 +1,398 @@ @@ -0,0 +1,398 @@
diff -up nfs-utils-1.3.0/utils/gssd/gssd_proc.c.orig nfs-utils-1.3.0/utils/gssd/gssd_proc.c
--- nfs-utils-1.3.0/utils/gssd/gssd_proc.c.orig 2014-09-17 14:22:54.003055871 -0400
+++ nfs-utils-1.3.0/utils/gssd/gssd_proc.c 2014-09-17 14:36:02.917808209 -0400
@@ -77,6 +77,7 @@
#include "context.h"
#include "nfsrpc.h"
#include "nfslib.h"
+#include "gss_names.h"
/*
* pollarray:
@@ -681,19 +682,25 @@ parse_enctypes(char *enctypes)
return 0;
}
-static int
+static void
do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
- gss_buffer_desc *context_token, OM_uint32 lifetime_rec)
+ gss_buffer_desc *context_token, OM_uint32 lifetime_rec,
+ gss_buffer_desc *acceptor)
{
char *buf = NULL, *p = NULL, *end = NULL;
unsigned int timeout = context_timeout;
unsigned int buf_size = 0;
- printerr(1, "doing downcall lifetime_rec %u\n", lifetime_rec);
+ printerr(1, "doing downcall: lifetime_rec=%u acceptor=%.*s\n",
+ lifetime_rec, acceptor->length, acceptor->value);
buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) +
sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length +
- sizeof(context_token->length) + context_token->length;
+ sizeof(context_token->length) + context_token->length +
+ sizeof(acceptor->length) + acceptor->length;
p = buf = malloc(buf_size);
+ if (!buf)
+ goto out_err;
+
end = buf + buf_size;
/* context_timeout set by -t option overrides context lifetime */
@@ -704,14 +711,15 @@ do_downcall(int k5_fd, uid_t uid, struct
if (WRITE_BYTES(&p, end, pd->pd_seq_win)) goto out_err;
if (write_buffer(&p, end, &pd->pd_ctx_hndl)) goto out_err;
if (write_buffer(&p, end, context_token)) goto out_err;
+ if (write_buffer(&p, end, acceptor)) goto out_err;
if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
- if (buf) free(buf);
- return 0;
+ free(buf);
+ return;
out_err:
- if (buf) free(buf);
+ free(buf);
printerr(1, "Failed to write downcall!\n");
- return -1;
+ return;
}
static int
@@ -1035,6 +1043,9 @@ process_krb5_upcall(struct clnt_info *cl
gss_cred_id_t gss_cred;
OM_uint32 maj_stat, min_stat, lifetime_rec;
pid_t pid;
+ gss_name_t gacceptor = GSS_C_NO_NAME;
+ gss_OID mech;
+ gss_buffer_desc acceptor = {0};
pid = fork();
switch(pid) {
@@ -1175,15 +1186,24 @@ process_krb5_upcall(struct clnt_info *cl
goto out_return_error;
}
- /* Grab the context lifetime to pass to the kernel. lifetime_rec
- * is set to zero on error */
- maj_stat = gss_inquire_context(&min_stat, pd.pd_ctx, NULL, NULL,
- &lifetime_rec, NULL, NULL, NULL, NULL);
-
- if (maj_stat)
- printerr(1, "WARNING: Failed to inquire context for lifetme "
- "maj_stat %u\n", maj_stat);
+ /* Grab the context lifetime and acceptor name out of the ctx. */
+ maj_stat = gss_inquire_context(&min_stat, pd.pd_ctx, NULL, &gacceptor,
+ &lifetime_rec, &mech, NULL, NULL, NULL);
+
+ if (maj_stat != GSS_S_COMPLETE) {
+ printerr(1, "WARNING: Failed to inquire context "
+ "maj_stat (0x%x)\n", maj_stat);
+ lifetime_rec = 0;
+ } else {
+ get_hostbased_client_buffer(gacceptor, mech, &acceptor);
+ gss_release_name(&min_stat, &gacceptor);
+ }
+ /*
+ * The serialization can mean turning pd.pd_ctx into a lucid context. If
+ * that happens then the pd.pd_ctx will be unusable, so we must never
+ * try to use it after this point.
+ */
if (serialize_context_for_kernel(&pd.pd_ctx, &token, &krb5oid, NULL)) {
printerr(0, "WARNING: Failed to serialize krb5 context for "
"user with uid %d for server %s\n",
@@ -1191,9 +1211,10 @@ process_krb5_upcall(struct clnt_info *cl
goto out_return_error;
}
- do_downcall(fd, uid, &pd, &token, lifetime_rec);
+ do_downcall(fd, uid, &pd, &token, lifetime_rec, &acceptor);
out:
+ gss_release_buffer(&min_stat, &acceptor);
if (token.value)
free(token.value);
#ifdef HAVE_AUTHGSS_FREE_PRIVATE_DATA
diff -up nfs-utils-1.3.0/utils/gssd/gss_names.c.orig nfs-utils-1.3.0/utils/gssd/gss_names.c
--- nfs-utils-1.3.0/utils/gssd/gss_names.c.orig 2014-09-17 14:35:16.646945303 -0400
+++ nfs-utils-1.3.0/utils/gssd/gss_names.c 2014-09-17 14:35:16.646945303 -0400
@@ -0,0 +1,138 @@
+/*
+ Copyright (c) 2000 The Regents of the University of Michigan.
+ All rights reserved.
+
+ Copyright (c) 2002 Bruce Fields <bfields@UMICH.EDU>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the University nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <rpc/rpc.h>
+
+#include <pwd.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <nfsidmap.h>
+#include <nfslib.h>
+#include <time.h>
+
+#include "svcgssd.h"
+#include "gss_util.h"
+#include "err_util.h"
+#include "context.h"
+#include "misc.h"
+#include "gss_oids.h"
+#include "svcgssd_krb5.h"
+
+static int
+get_krb5_hostbased_name(gss_buffer_desc *name, char **hostbased_name)
+{
+ char *p, *sname = NULL;
+ if (strchr(name->value, '@') && strchr(name->value, '/')) {
+ if ((sname = calloc(name->length, 1)) == NULL) {
+ printerr(0, "ERROR: get_krb5_hostbased_name failed "
+ "to allocate %d bytes\n", name->length);
+ return -1;
+ }
+ /* read in name and instance and replace '/' with '@' */
+ sscanf(name->value, "%[^@]", sname);
+ p = strrchr(sname, '/');
+ if (p == NULL) { /* The '@' preceeded the '/' */
+ free(sname);
+ return -1;
+ }
+ *p = '@';
+ }
+ *hostbased_name = sname;
+ return 0;
+}
+
+int
+get_hostbased_client_name(gss_name_t client_name, gss_OID mech,
+ char **hostbased_name)
+{
+ u_int32_t maj_stat, min_stat;
+ gss_buffer_desc name;
+ gss_OID name_type = GSS_C_NO_OID;
+ char *cname;
+ int res = -1;
+
+ *hostbased_name = NULL; /* preset in case we fail */
+
+ /* Get the client's gss authenticated name */
+ maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
+ if (maj_stat != GSS_S_COMPLETE) {
+ pgsserr("get_hostbased_client_name: gss_display_name",
+ maj_stat, min_stat, mech);
+ goto out_err;
+ }
+ if (name.length >= 0xffff) { /* don't overflow */
+ printerr(0, "ERROR: get_hostbased_client_name: "
+ "received gss_name is too long (%d bytes)\n",
+ name.length);
+ goto out_rel_buf;
+ }
+
+ /* For Kerberos, transform the NT_KRB5_PRINCIPAL name to
+ * an NT_HOSTBASED_SERVICE name */
+ if (g_OID_equal(&krb5oid, mech)) {
+ if (get_krb5_hostbased_name(&name, &cname) == 0)
+ *hostbased_name = cname;
+ } else {
+ printerr(1, "WARNING: unknown/unsupport mech OID\n");
+ }
+
+ res = 0;
+out_rel_buf:
+ gss_release_buffer(&min_stat, &name);
+out_err:
+ return res;
+}
+
+void
+get_hostbased_client_buffer(gss_name_t client_name, gss_OID mech,
+ gss_buffer_t buf)
+{
+ char *hname;
+
+ if (!get_hostbased_client_name(client_name, mech, &hname)) {
+ buf->length = strlen(hname) + 1;
+ buf->value = hname;
+ } else {
+ buf->length = 0;
+ buf->value = NULL;
+ }
+}
diff -up nfs-utils-1.3.0/utils/gssd/gss_names.h.orig nfs-utils-1.3.0/utils/gssd/gss_names.h
--- nfs-utils-1.3.0/utils/gssd/gss_names.h.orig 2014-09-17 14:35:16.646945303 -0400
+++ nfs-utils-1.3.0/utils/gssd/gss_names.h 2014-09-17 14:35:16.646945303 -0400
@@ -0,0 +1,36 @@
+/*
+ Copyright (c) 2000 The Regents of the University of Michigan.
+ All rights reserved.
+
+ Copyright (c) 2002 Bruce Fields <bfields@UMICH.EDU>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the University nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+extern int get_hostbased_client_name(gss_name_t client_name, gss_OID mech,
+ char **hostbased_name);
+extern void get_hostbased_client_buffer(gss_name_t client_name,
+ gss_OID mech, gss_buffer_t buf);
diff -up nfs-utils-1.3.0/utils/gssd/Makefile.am.orig nfs-utils-1.3.0/utils/gssd/Makefile.am
--- nfs-utils-1.3.0/utils/gssd/Makefile.am.orig 2014-03-25 11:12:07.000000000 -0400
+++ nfs-utils-1.3.0/utils/gssd/Makefile.am 2014-09-17 14:35:16.645945284 -0400
@@ -18,11 +18,13 @@ COMMON_SRCS = \
context_lucid.c \
gss_util.c \
gss_oids.c \
+ gss_names.c \
err_util.c \
\
context.h \
err_util.h \
gss_oids.h \
+ gss_names.h \
gss_util.h
gssd_SOURCES = \
diff -up nfs-utils-1.3.0/utils/gssd/svcgssd_proc.c.orig nfs-utils-1.3.0/utils/gssd/svcgssd_proc.c
--- nfs-utils-1.3.0/utils/gssd/svcgssd_proc.c.orig 2014-03-25 11:12:07.000000000 -0400
+++ nfs-utils-1.3.0/utils/gssd/svcgssd_proc.c 2014-09-17 14:35:16.646945303 -0400
@@ -59,6 +59,7 @@
#include "misc.h"
#include "gss_oids.h"
#include "svcgssd_krb5.h"
+#include "gss_names.h"
extern char * mech2file(gss_OID mech);
#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel"
@@ -315,71 +316,6 @@ print_hexl(const char *description, unsi
}
#endif
-static int
-get_krb5_hostbased_name (gss_buffer_desc *name, char **hostbased_name)
-{
- char *p, *sname = NULL;
- if (strchr(name->value, '@') && strchr(name->value, '/')) {
- if ((sname = calloc(name->length, 1)) == NULL) {
- printerr(0, "ERROR: get_krb5_hostbased_name failed "
- "to allocate %d bytes\n", name->length);
- return -1;
- }
- /* read in name and instance and replace '/' with '@' */
- sscanf(name->value, "%[^@]", sname);
- p = strrchr(sname, '/');
- if (p == NULL) { /* The '@' preceeded the '/' */
- free(sname);
- return -1;
- }
- *p = '@';
- }
- *hostbased_name = sname;
- return 0;
-}
-
-static int
-get_hostbased_client_name(gss_name_t client_name, gss_OID mech,
- char **hostbased_name)
-{
- u_int32_t maj_stat, min_stat;
- gss_buffer_desc name;
- gss_OID name_type = GSS_C_NO_OID;
- char *cname;
- int res = -1;
-
- *hostbased_name = NULL; /* preset in case we fail */
-
- /* Get the client's gss authenticated name */
- maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
- if (maj_stat != GSS_S_COMPLETE) {
- pgsserr("get_hostbased_client_name: gss_display_name",
- maj_stat, min_stat, mech);
- goto out_err;
- }
- if (name.length >= 0xffff) { /* don't overflow */
- printerr(0, "ERROR: get_hostbased_client_name: "
- "received gss_name is too long (%d bytes)\n",
- name.length);
- goto out_rel_buf;
- }
-
- /* For Kerberos, transform the NT_KRB5_PRINCIPAL name to
- * an NT_HOSTBASED_SERVICE name */
- if (g_OID_equal(&krb5oid, mech)) {
- if (get_krb5_hostbased_name(&name, &cname) == 0)
- *hostbased_name = cname;
- } else {
- printerr(1, "WARNING: unknown/unsupport mech OID\n");
- }
-
- res = 0;
-out_rel_buf:
- gss_release_buffer(&min_stat, &name);
-out_err:
- return res;
-}
-
void
handle_nullreq(FILE *f) {
/* XXX initialize to a random integer to reduce chances of unnecessary

2564
SOURCES/nfs-utils-1.3.0-rpcgssd-debug.patch

File diff suppressed because it is too large Load Diff

21
SOURCES/nfs-utils-1.3.0-rpcgssd-errno-typo.patch

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
commit 404c79c81df0548d50216cddc7d2c4ebfca45c45
Author: Steve Dickson <steved@redhat.com>
Date: Fri Jul 25 10:48:16 2014 -0400

gssd: Fixed errno typo in get_servername()
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index 40ff188..9925dab 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -218,7 +218,7 @@ get_servername(const char *name, const struct sockaddr *sa, const char *addr)
NI_NAMEREQD);
if (err) {
printerr(0, "ERROR: unable to resolve %s to hostname: %s\n",
- addr, err == EAI_SYSTEM ? strerror(err) :
+ addr, err == EAI_SYSTEM ? strerror(errno) :
gai_strerror(err));
return NULL;
}

23
SOURCES/nfs-utils-1.3.0-rpcgssd-findkeytab.patch

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
diff -up nfs-utils-1.3.0/utils/gssd/krb5_util.c.orig nfs-utils-1.3.0/utils/gssd/krb5_util.c
--- nfs-utils-1.3.0/utils/gssd/krb5_util.c.orig 2016-05-16 08:46:45.554915290 -0400
+++ nfs-utils-1.3.0/utils/gssd/krb5_util.c 2016-05-16 09:13:09.479879099 -0400
@@ -768,7 +768,7 @@ find_keytab_entry(krb5_context context,
char **realmnames = NULL;
char myhostname[NI_MAXHOST], targethostname[NI_MAXHOST];
char myhostad[NI_MAXHOST+1];
- int i, j, retval;
+ int i, j, k, retval;
char *default_realm = NULL;
char *realm;
char *k5err = NULL;
@@ -913,8 +913,8 @@ find_keytab_entry(krb5_context context,
* moving on to the svcname
*/
if (strcmp(svcnames[j],"$") == 0 && !tried_upper) {
- for (i = 0; myhostad[i] != '$'; ++i) {
- myhostad[i] = toupper(myhostad[i]);
+ for (k = 0; myhostad[k] != '$'; ++k) {
+ myhostad[k] = toupper(myhostad[k]);
}
j--;
tried_upper = 1;

66
SOURCES/nfs-utils-1.3.0-rpcgssd-maccout-nocase.patch

@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
index 5fde091..990111d 100644
--- a/utils/gssd/krb5_util.c
+++ b/utils/gssd/krb5_util.c
@@ -801,8 +801,10 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname,
char *default_realm = NULL;
char *realm;
char *k5err = NULL;
- int tried_all = 0, tried_default = 0;
+ int tried_all = 0, tried_default = 0, tried_upper = 0;
krb5_principal princ;
+ const char *notsetstr = "not set";
+ char *adhostoverride;
/* Get full target hostname */
@@ -820,13 +822,23 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname,
}
/* Compute the active directory machine name HOST$ */
- strcpy(myhostad, myhostname);
- for (i = 0; myhostad[i] != 0; ++i) {
- if (myhostad[i] == '.') break;
- myhostad[i] = toupper(myhostad[i]);
+ krb5_appdefault_string(context, "nfs", NULL, "ad_principal_name",
+ notsetstr, &adhostoverride);
+ if (strcmp(adhostoverride, notsetstr) != 0) {
+ printerr (1,
+ "AD host string overridden with \"%s\" from appdefaults\n",
+ adhostoverride);
+ /* No overflow: Windows cannot handle strings longer than 19 chars */
+ strcpy(myhostad, adhostoverride);
+ free(adhostoverride);
+ } else {
+ strcpy(myhostad, myhostname);
+ for (i = 0; myhostad[i] != 0; ++i) {
+ if (myhostad[i] == '.') break;
+ }
+ myhostad[i] = '$';
+ myhostad[i+1] = 0;
}
- myhostad[i] = '$';
- myhostad[i+1] = 0;
retval = get_full_hostname(myhostname, myhostname, sizeof(myhostname));
if (retval) {
@@ -923,6 +935,19 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname,
k5err = gssd_k5_err_msg(context, code);
printerr(3, "%s while getting keytab entry for '%s'\n",
k5err, spn);
+ /*
+ * We tried the active directory machine account
+ * with the hostname part as-is and failed...
+ * convert it to uppercase and try again before
+ * moving on to the svcname
+ */
+ if (strcmp(svcnames[j],"$") == 0 && !tried_upper) {
+ for (i = 0; myhostad[i] != '$'; ++i) {
+ myhostad[i] = toupper(myhostad[i]);
+ }
+ j--;
+ tried_upper = 1;
+ }
} else {
printerr(3, "Success getting keytab entry for '%s'\n",spn);
retval = 0;

594
SOURCES/nfs-utils-1.3.0-rpcgssd-multithread.patch

@ -0,0 +1,594 @@ @@ -0,0 +1,594 @@
diff --git a/aclocal/kerberos5.m4 b/aclocal/kerberos5.m4
index 0bf35d3..8a0f3e4 100644
--- a/aclocal/kerberos5.m4
+++ b/aclocal/kerberos5.m4
@@ -43,15 +43,6 @@ AC_DEFUN([AC_KERBEROS_V5],[
-f $dir/lib/libgssapi_krb5.so \) ; then
AC_DEFINE(HAVE_KRB5, 1, [Define this if you have MIT Kerberos libraries])
KRBDIR="$dir"
- dnl If we are using MIT K5 1.3.1 and before, we *MUST* use the
- dnl private function (gss_krb5_ccache_name) to get correct
- dnl behavior of changing the ccache used by gssapi.
- dnl Starting in 1.3.2, we *DO NOT* want to use
- dnl gss_krb5_ccache_name, instead we want to set KRB5CCNAME
- dnl to get gssapi to use a different ccache
- if test $K5VERS -le 131; then
- AC_DEFINE(USE_GSS_KRB5_CCACHE_NAME, 1, [Define this if the private function, gss_krb5_cache_name, must be used to tell the Kerberos library which credentials cache to use. Otherwise, this is done by setting the KRB5CCNAME environment variable])
- fi
gssapi_lib=gssapi_krb5
break
dnl The following ugly hack brought on by the split installation
@@ -92,8 +83,6 @@ AC_DEFUN([AC_KERBEROS_V5],[
AC_DEFINE(HAVE_LUCID_CONTEXT_SUPPORT, 1, [Define this if the Kerberos GSS library supports gss_krb5_export_lucid_sec_context]), ,$KRBLIBS)
AC_CHECK_LIB($gssapi_lib, gss_krb5_set_allowable_enctypes,
AC_DEFINE(HAVE_SET_ALLOWABLE_ENCTYPES, 1, [Define this if the Kerberos GSS library supports gss_krb5_set_allowable_enctypes]), ,$KRBLIBS)
- AC_CHECK_LIB($gssapi_lib, gss_krb5_ccache_name,
- AC_DEFINE(HAVE_GSS_KRB5_CCACHE_NAME, 1, [Define this if the Kerberos GSS library supports gss_krb5_ccache_name]), ,$KRBLIBS)
AC_CHECK_LIB($gssapi_lib, gss_krb5_free_lucid_sec_context,
AC_DEFINE(HAVE_GSS_KRB5_FREE_LUCID_SEC_CONTEXT, 1, [Define this if the Kerberos GSS library supports gss_krb5_free_lucid_sec_context]), ,$KRBLIBS)
diff --git a/aclocal/libpthread.m4 b/aclocal/libpthread.m4
new file mode 100644
index 0000000..e87d2a0
--- /dev/null
+++ b/aclocal/libpthread.m4
@@ -0,0 +1,13 @@
+dnl Checks for pthreads library and headers
+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.])])
+
+])dnl
diff --git a/configure.ac b/configure.ac
index 4ee4db5..56f7f3e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -355,6 +355,9 @@ if test "$enable_gss" = yes; then
dnl Invoked after AC_KERBEROS_V5; AC_LIBRPCSECGSS needs to have KRBLIBS set
AC_LIBRPCSECGSS
+ dnl Check for pthreads
+ AC_LIBPTHREAD
+
dnl librpcsecgss already has a dependency on libgssapi,
dnl but we need to make sure we get the right version
if test "$enable_gss" = yes; then
diff --git a/utils/gssd/Makefile.am b/utils/gssd/Makefile.am
index fd488a1..f387c16 100644
--- a/utils/gssd/Makefile.am
+++ b/utils/gssd/Makefile.am
@@ -42,7 +42,8 @@ gssd_LDADD = \
$(RPCSECGSS_LIBS) \
$(KRBLIBS) \
$(GSSAPI_LIBS) \
- $(LIBTIRPC)
+ $(LIBTIRPC) \
+ $(LIBPTHREAD)
gssd_LDFLAGS = \
$(KRBLDFLAGS)
diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
index 7ba27b1..43fccaf 100644
--- a/utils/gssd/gssd.c
+++ b/utils/gssd/gssd.c
@@ -87,7 +87,9 @@ unsigned int rpc_timeout = 5;
char *preferred_realm = NULL;
/* Avoid DNS reverse lookups on server names */
static bool avoid_dns = true;
-
+int thread_started = false;
+pthread_mutex_t pmutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t pcond = PTHREAD_COND_INITIALIZER;
TAILQ_HEAD(topdir_list_head, topdir) topdir_list;
@@ -361,20 +363,91 @@ gssd_destroy_client(struct clnt_info *clp)
static void gssd_scan(void);
+static int
+start_upcall_thread(void (*func)(struct clnt_upcall_info *), void *info)
+{
+ pthread_attr_t attr;
+ pthread_t th;
+ int ret;
+
+ ret = pthread_attr_init(&attr);
+ if (ret != 0) {
+ printerr(0, "ERROR: failed to init pthread attr: ret %d: %s\n",
+ ret, strerror(errno));
+ return ret;
+ }
+ ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ if (ret != 0) {
+ printerr(0, "ERROR: failed to create pthread attr: ret %d: "
+ "%s\n", ret, strerror(errno));
+ return ret;
+ }
+
+ ret = pthread_create(&th, &attr, (void *)func, (void *)info);
+ if (ret != 0)
+ printerr(0, "ERROR: pthread_create failed: ret %d: %s\n",
+ ret, strerror(errno));
+ return ret;
+}
+
+static struct clnt_upcall_info *alloc_upcall_info(struct clnt_info *clp)
+{
+ struct clnt_upcall_info *info;
+
+ info = malloc(sizeof(struct clnt_upcall_info));
+ if (info == NULL)
+ return NULL;
+ info->clp = clp;
+
+ return info;
+}
+
+/* For each upcall read the upcall info into the buffer, then create a
+ * thread in a detached state so that resources are released back into
+ * the system without the need for a join.
+ */
static void
gssd_clnt_gssd_cb(int UNUSED(fd), short UNUSED(which), void *data)
{
struct clnt_info *clp = data;
+ struct clnt_upcall_info *info;
+
+ info = alloc_upcall_info(clp);
+ if (info == NULL)
+ return;
+
+ info->lbuflen = read(clp->gssd_fd, info->lbuf, sizeof(info->lbuf));
+ if (info->lbuflen <= 0 || info->lbuf[info->lbuflen-1] != '\n') {
+ printerr(0, "WARNING: %s: failed reading request\n", __func__);
+ free(info);
+ return;
+ }
+ info->lbuf[info->lbuflen-1] = 0;
- handle_gssd_upcall(clp);
+ if (start_upcall_thread(handle_gssd_upcall, info))
+ free(info);
}
static void
gssd_clnt_krb5_cb(int UNUSED(fd), short UNUSED(which), void *data)
{
struct clnt_info *clp = data;
+ struct clnt_upcall_info *info;
+
+ info = alloc_upcall_info(clp);
+ if (info == NULL)
+ return;
+
+ if (read(clp->krb5_fd, &info->uid,
+ sizeof(info->uid)) < (ssize_t)sizeof(info->uid)) {
+ printerr(0, "WARNING: %s: failed reading uid from krb5 "
+ "upcall pipe: %s\n", __func__, strerror(errno));
+ free(info);
+ return;
+ }
- handle_krb5_upcall(clp);
+ if (start_upcall_thread(handle_krb5_upcall, info))
+ free(info);
}
static struct clnt_info *
diff --git a/utils/gssd/gssd.h b/utils/gssd/gssd.h
index c6937c5..f4f5975 100644
--- a/utils/gssd/gssd.h
+++ b/utils/gssd/gssd.h
@@ -36,6 +36,7 @@
#include <gssapi/gssapi.h>
#include <event.h>
#include <stdbool.h>
+#include <pthread.h>
#ifndef GSSD_PIPEFS_DIR
#define GSSD_PIPEFS_DIR "/var/lib/nfs/rpc_pipefs"
@@ -48,7 +49,7 @@
#define GSSD_DEFAULT_MACHINE_CRED_SUFFIX "machine"
#define GSSD_DEFAULT_KEYTAB_FILE "/etc/krb5.keytab"
#define GSSD_SERVICE_NAME "nfs"
-
+#define RPC_CHAN_BUF_SIZE 32768
/*
* The gss mechanisms that we can handle
*/
@@ -61,6 +62,10 @@ extern int root_uses_machine_creds;
extern unsigned int context_timeout;
extern unsigned int rpc_timeout;
extern char *preferred_realm;
+extern pthread_mutex_t ple_lock;
+extern pthread_cond_t pcond;
+extern pthread_mutex_t pmutex;
+extern int thread_started;
struct clnt_info {
TAILQ_ENTRY(clnt_info) list;
@@ -80,8 +85,15 @@ struct clnt_info {
struct sockaddr_storage addr;
};
-void handle_krb5_upcall(struct clnt_info *clp);
-void handle_gssd_upcall(struct clnt_info *clp);
+struct clnt_upcall_info {
+ struct clnt_info *clp;
+ char lbuf[RPC_CHAN_BUF_SIZE];
+ int lbuflen;
+ uid_t uid;
+};
+
+void handle_krb5_upcall(struct clnt_upcall_info *clp);
+void handle_gssd_upcall(struct clnt_upcall_info *clp);
#endif /* _RPC_GSSD_H_ */
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index 69c6a34..fda7595 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -69,6 +69,7 @@
#include <netdb.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <syscall.h>
#include "gssd.h"
#include "err_util.h"
@@ -442,7 +443,7 @@ change_identity(uid_t uid)
struct passwd *pw;
/* drop list of supplimentary groups first */
- if (setgroups(0, NULL) != 0) {
+ if (syscall(SYS_setgroups, 0, 0) != 0) {
printerr(0, "WARNING: unable to drop supplimentary groups!");
return errno;
}
@@ -459,20 +460,18 @@ change_identity(uid_t uid)
}
}
- /*
- * Switch the GIDs. Note that we leave the saved-set-gid alone in an
- * attempt to prevent attacks via ptrace()
+ /* Switch the UIDs and GIDs. */
+ /* For the threaded version we have to set uid,gid per thread instead
+ * of per process. glibc setresuid() when called from a thread, it'll
+ * send a signal to all other threads to synchronize the uid in all
+ * other threads. To bypass this, we have to call syscall() directly.
*/
- if (setresgid(pw->pw_gid, pw->pw_gid, -1) != 0) {
+ if (syscall(SYS_setresgid, pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
printerr(0, "WARNING: failed to set gid to %u!\n", pw->pw_gid);
return errno;
}
- /*
- * Switch UIDs, but leave saved-set-uid alone to prevent ptrace() by
- * other processes running with this uid.
- */
- if (setresuid(uid, uid, -1) != 0) {
+ if (syscall(SYS_setresuid, uid, uid, uid) != 0) {
printerr(0, "WARNING: Failed to setuid for user with uid %u\n",
uid);
return errno;
@@ -554,7 +553,15 @@ krb5_use_machine_creds(struct clnt_info *clp, uid_t uid, char *tgtname,
goto out;
}
for (ccname = credlist; ccname && *ccname; ccname++) {
- gssd_setup_krb5_machine_gss_ccache(*ccname);
+ u_int min_stat;
+
+ if (gss_krb5_ccache_name(&min_stat, *ccname, NULL) !=
+ GSS_S_COMPLETE) {
+ printerr(1, "WARNING: gss_krb5_ccache_name "
+ "with name '%s' failed (%s)\n",
+ *ccname, error_message(min_stat));
+ continue;
+ }
if ((create_auth_rpc_client(clp, tgtname, rpc_clnt,
&auth, uid,
AUTHTYPE_KRB5,
@@ -602,7 +609,6 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
gss_buffer_desc token;
int err, downcall_err = -EACCES;
OM_uint32 maj_stat, min_stat, lifetime_rec;
- pid_t pid, childpid = -1;
gss_name_t gacceptor = GSS_C_NO_NAME;
gss_OID mech;
gss_buffer_desc acceptor = {0};
@@ -635,36 +641,6 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0 &&
service == NULL)) {
- /* already running as uid 0 */
- if (uid == 0)
- goto no_fork;
-
- pid = fork();
- switch(pid) {
- case 0:
- /* Child: fall through to rest of function */
- childpid = getpid();
- unsetenv("KRB5CCNAME");
- printerr(2, "CHILD forked pid %d \n", childpid);
- break;
- case -1:
- /* fork() failed! */
- printerr(0, "WARNING: unable to fork() to handle"
- "upcall: %s\n", strerror(errno));
- return;
- default:
- /* Parent: just wait on child to exit and return */
- do {
- pid = wait(&err);
- } while(pid == -1 && errno != -ECHILD);
-
- if (WIFSIGNALED(err))
- printerr(0, "WARNING: forked child was killed"
- "with signal %d\n", WTERMSIG(err));
- return;
- }
-no_fork:
-
auth = krb5_not_machine_creds(clp, uid, tgtname, &downcall_err,
&err, &rpc_clnt);
if (err)
@@ -730,11 +706,7 @@ out:
if (rpc_clnt)
clnt_destroy(rpc_clnt);
- pid = getpid();
- if (pid == childpid)
- exit(0);
- else
- return;
+ return;
out_return_error:
do_error_downcall(fd, uid, downcall_err);
@@ -742,27 +714,21 @@ out_return_error:
}
void
-handle_krb5_upcall(struct clnt_info *clp)
+handle_krb5_upcall(struct clnt_upcall_info *info)
{
- uid_t uid;
-
- if (read(clp->krb5_fd, &uid, sizeof(uid)) < (ssize_t)sizeof(uid)) {
- printerr(0, "WARNING: failed reading uid from krb5 "
- "upcall pipe: %s\n", strerror(errno));
- return;
- }
+ struct clnt_info *clp = info->clp;
- printerr(2, "\n%s: uid %d (%s)\n", __func__, uid, clp->relpath);
+ printerr(2, "\n%s: uid %d (%s)\n", __func__, info->uid, clp->relpath);
- process_krb5_upcall(clp, uid, clp->krb5_fd, NULL, NULL);
+ process_krb5_upcall(clp, info->uid, clp->krb5_fd, NULL, NULL);
+ free(info);
}
void
-handle_gssd_upcall(struct clnt_info *clp)
+handle_gssd_upcall(struct clnt_upcall_info *info)
{
+ struct clnt_info *clp = info->clp;
uid_t uid;
- char *lbuf = NULL;
- int lbuflen = 0;
char *p;
char *mech = NULL;
char *uidstr = NULL;
@@ -770,15 +736,9 @@ handle_gssd_upcall(struct clnt_info *clp)
char *service = NULL;
char *enctypes = NULL;
- if (readline(clp->gssd_fd, &lbuf, &lbuflen) != 1) {
- printerr(0, "WARNING: handle_gssd_upcall: "
- "failed reading request\n");
- return;
- }
-
- printerr(2, "\n%s: '%s' (%s)\n", __func__, lbuf, clp->relpath);
+ printerr(2, "\n%s: '%s' (%s)\n", __func__, info->lbuf, clp->relpath);
- for (p = strtok(lbuf, " "); p; p = strtok(NULL, " ")) {
+ for (p = strtok(info->lbuf, " "); p; p = strtok(NULL, " ")) {
if (!strncmp(p, "mech=", strlen("mech=")))
mech = p + strlen("mech=");
else if (!strncmp(p, "uid=", strlen("uid=")))
@@ -794,8 +754,8 @@ handle_gssd_upcall(struct clnt_info *clp)
if (!mech || strlen(mech) < 1) {
printerr(0, "WARNING: handle_gssd_upcall: "
"failed to find gss mechanism name "
- "in upcall string '%s'\n", lbuf);
- return;
+ "in upcall string '%s'\n", info->lbuf);
+ goto out;
}
if (uidstr) {
@@ -807,21 +767,21 @@ handle_gssd_upcall(struct clnt_info *clp)
if (!uidstr) {
printerr(0, "WARNING: handle_gssd_upcall: "
"failed to find uid "
- "in upcall string '%s'\n", lbuf);
- return;
+ "in upcall string '%s'\n", info->lbuf);
+ goto out;
}
if (enctypes && parse_enctypes(enctypes) != 0) {
printerr(0, "WARNING: handle_gssd_upcall: "
"parsing encryption types failed: errno %d\n", errno);
- return;
+ goto out;
}
if (target && strlen(target) < 1) {
printerr(0, "WARNING: handle_gssd_upcall: "
"failed to parse target name "
- "in upcall string '%s'\n", lbuf);
- return;
+ "in upcall string '%s'\n", info->lbuf);
+ goto out;
}
/*
@@ -835,8 +795,8 @@ handle_gssd_upcall(struct clnt_info *clp)
if (service && strlen(service) < 1) {
printerr(0, "WARNING: handle_gssd_upcall: "
"failed to parse service type "
- "in upcall string '%s'\n", lbuf);
- return;
+ "in upcall string '%s'\n", info->lbuf);
+ goto out;
}
if (strcmp(mech, "krb5") == 0 && clp->servername)
@@ -847,5 +807,8 @@ handle_gssd_upcall(struct clnt_info *clp)
"received unknown gss mech '%s'\n", mech);
do_error_downcall(clp->gssd_fd, uid, -EACCES);
}
+out:
+ free(info);
+ return;
}
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
index 3849b6a..bc29787 100644
--- a/utils/gssd/krb5_util.c
+++ b/utils/gssd/krb5_util.c
@@ -128,6 +128,7 @@
/* Global list of principals/cache file names for machine credentials */
struct gssd_k5_kt_princ *gssd_k5_kt_princ_list = NULL;
+pthread_mutex_t ple_lock = PTHREAD_MUTEX_INITIALIZER;
#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
int limit_to_legacy_enctypes = 0;
@@ -467,37 +468,6 @@ gssd_get_single_krb5_cred(krb5_context context,
}
/*
- * Depending on the version of Kerberos, we either need to use
- * a private function, or simply set the environment variable.
- */
-static void
-gssd_set_krb5_ccache_name(char *ccname)
-{
-#ifdef USE_GSS_KRB5_CCACHE_NAME
- u_int maj_stat, min_stat;
-
- printerr(3, "using gss_krb5_ccache_name to select krb5 ccache %s\n",
- ccname);
- maj_stat = gss_krb5_ccache_name(&min_stat, ccname, NULL);
- if (maj_stat != GSS_S_COMPLETE) {
- printerr(0, "WARNING: gss_krb5_ccache_name with "
- "name '%s' failed (%s)\n",
- ccname, error_message(min_stat));
- }
-#else
- /*
- * Set the KRB5CCNAME environment variable to tell the krb5 code
- * which credentials cache to use. (Instead of using the private
- * function above for which there is no generic gssapi
- * equivalent.)
- */
- printerr(3, "using environment variable to select krb5 ccache %s\n",
- ccname);
- setenv("KRB5CCNAME", ccname, 1);
-#endif
-}
-
-/*
* Given a principal, find a matching ple structure
*/
static struct gssd_k5_kt_princ *
@@ -586,10 +556,12 @@ get_ple_by_princ(krb5_context context, krb5_principal princ)
/* Need to serialize list if we ever become multi-threaded! */
+ pthread_mutex_lock(&ple_lock);
ple = find_ple_by_princ(context, princ);
if (ple == NULL) {
ple = new_ple(context, princ);
}
+ pthread_mutex_unlock(&ple_lock);
return ple;
}
@@ -1091,6 +1063,7 @@ gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername, char *dirpattern)
const char *cctype;
struct dirent *d;
int err, i, j;
+ u_int maj_stat, min_stat;
printerr(3, "looking for client creds with uid %u for "
"server %s in %s\n", uid, servername, dirpattern);
@@ -1126,22 +1099,16 @@ gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername, char *dirpattern)
printerr(2, "using %s as credentials cache for client with "
"uid %u for server %s\n", buf, uid, servername);
- gssd_set_krb5_ccache_name(buf);
- return 0;
-}
-/*
- * Let the gss code know where to find the machine credentials ccache.
- *
- * Returns:
- * void
- */
-void
-gssd_setup_krb5_machine_gss_ccache(char *ccname)
-{
- printerr(2, "using %s as credentials cache for machine creds\n",
- ccname);
- gssd_set_krb5_ccache_name(ccname);
+ printerr(3, "using gss_krb5_ccache_name to select krb5 ccache %s\n",
+ buf);
+ maj_stat = gss_krb5_ccache_name(&min_stat, buf, NULL);
+ if (maj_stat != GSS_S_COMPLETE) {
+ printerr(0, "ERROR: unable to get user cred cache '%s' "
+ "failed (%s)\n", buf, error_message(min_stat));
+ return maj_stat;
+ }
+ return 0;
}
/*
diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h
index a319588..e3bbb07 100644
--- a/utils/gssd/krb5_util.h
+++ b/utils/gssd/krb5_util.h
@@ -27,7 +27,6 @@ int gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername,
char *dirname);
int gssd_get_krb5_machine_cred_list(char ***list);
void gssd_free_krb5_machine_cred_list(char **list);
-void gssd_setup_krb5_machine_gss_ccache(char *servername);
void gssd_destroy_krb5_machine_creds(void);
int gssd_refresh_krb5_machine_credential(char *hostname,
struct gssd_k5_kt_princ *ple,
@@ -55,8 +54,6 @@ int limit_krb5_enctypes(struct rpc_gss_sec *sec);
#define k5_free_unparsed_name(ctx, name) free(name)
#define k5_free_default_realm(ctx, realm) free(realm)
#define k5_free_kt_entry(ctx, kte) krb5_kt_free_entry((ctx),(kte))
-#undef USE_GSS_KRB5_CCACHE_NAME
-#define USE_GSS_KRB5_CCACHE_NAME 1
#endif
#endif /* KRB5_UTIL_H */

44
SOURCES/nfs-utils-1.3.0-rpcgssd-noerror-message.patch

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
commit fe91df5e1d115015b31bb055ef0b4d5dfdc0635c
Author: Steve Dickson <steved@redhat.com>
Date: Tue Jul 8 10:29:52 2014 -0400

gssd: Error out when rpc_pipefs directory is empty
When there is no kernel modules loaded the rpc_pipefs
directory is empty, which cause rpc.gssd to silently
exit.
This patch adds a check to see if the topdirs_list
is empty. If so error out without dropping a core.
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/gssd/gssd_main_loop.c b/utils/gssd/gssd_main_loop.c
index 9970028..6946ab6 100644
--- a/utils/gssd/gssd_main_loop.c
+++ b/utils/gssd/gssd_main_loop.c
@@ -173,6 +173,10 @@ topdirs_init_list(void)
if (ret)
goto out_err;
}
+ if (TAILQ_EMPTY(&topdirs_list)) {
+ printerr(0, "ERROR: rpc_pipefs directory '%s' is empty!\n", pipefs_dir);
+ return -1;
+ }
closedir(pipedir);
return 0;
out_err:
@@ -233,9 +237,10 @@ gssd_run()
sigaddset(&set, DNOTIFY_SIGNAL);
sigprocmask(SIG_UNBLOCK, &set, NULL);
- if (topdirs_init_list() != 0)
- return;
-
+ if (topdirs_init_list() != 0) {
+ /* Error msg is already printed */
+ exit(1);
+ }
init_client_list();
printerr(1, "beginning poll\n");

12
SOURCES/nfs-utils-1.3.0-rpcgssd-preferred-realm.patch

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
diff -up nfs-utils-1.3.0/utils/gssd/krb5_util.c.orig nfs-utils-1.3.0/utils/gssd/krb5_util.c
--- nfs-utils-1.3.0/utils/gssd/krb5_util.c.orig 2017-03-31 16:34:11.775037704 -0400
+++ nfs-utils-1.3.0/utils/gssd/krb5_util.c 2017-04-08 15:18:53.619038636 -0400
@@ -848,7 +848,7 @@ find_keytab_entry(krb5_context context,
i = 0;
realm = realmnames[i];
- if (strcmp (realm, preferred_realm) != 0) {
+ if (preferred_realm && strcmp (realm, preferred_realm) != 0) {
realm = preferred_realm;
/* resetting the realmnames index */
i = -1;

82
SOURCES/nfs-utils-1.3.0-rpcgssd-timeout.patch

@ -0,0 +1,82 @@ @@ -0,0 +1,82 @@
diff -up nfs-utils-1.3.0/utils/gssd/gssd.c.orig nfs-utils-1.3.0/utils/gssd/gssd.c
--- nfs-utils-1.3.0/utils/gssd/gssd.c.orig 2014-09-17 13:00:22.702932025 -0400
+++ nfs-utils-1.3.0/utils/gssd/gssd.c 2014-09-17 13:00:26.575004049 -0400
@@ -64,6 +64,7 @@ char *ccachesearch[GSSD_MAX_CCACHE_SEARC
int use_memcache = 0;
int root_uses_machine_creds = 1;
unsigned int context_timeout = 0;
+unsigned int rpc_timeout = 5;
char *preferred_realm = NULL;
int pipefds[2] = { -1, -1 };
@@ -105,7 +106,7 @@ main(int argc, char *argv[])
char *progname;
memset(ccachesearch, 0, sizeof(ccachesearch));
- while ((opt = getopt(argc, argv, "DfvrlmnMp:k:d:t:R:")) != -1) {
+ while ((opt = getopt(argc, argv, "DfvrlmnMp:k:d:t:T:R:")) != -1) {
switch (opt) {
case 'f':
fg = 1;
@@ -143,6 +144,9 @@ main(int argc, char *argv[])
case 't':
context_timeout = atoi(optarg);
break;
+ case 'T':
+ rpc_timeout = atoi(optarg);
+ break;
case 'R':
preferred_realm = strdup(optarg);
break;
diff -up nfs-utils-1.3.0/utils/gssd/gssd.h.orig nfs-utils-1.3.0/utils/gssd/gssd.h
--- nfs-utils-1.3.0/utils/gssd/gssd.h.orig 2014-09-17 13:00:22.702932025 -0400
+++ nfs-utils-1.3.0/utils/gssd/gssd.h 2014-09-17 13:00:26.575004049 -0400
@@ -66,6 +66,7 @@ extern char *ccachesearch[];
extern int use_memcache;
extern int root_uses_machine_creds;
extern unsigned int context_timeout;
+extern unsigned int rpc_timeout;
extern char *preferred_realm;
extern int pipefds[2];
diff -up nfs-utils-1.3.0/utils/gssd/gssd.man.orig nfs-utils-1.3.0/utils/gssd/gssd.man
--- nfs-utils-1.3.0/utils/gssd/gssd.man.orig 2014-09-17 13:00:22.702932025 -0400
+++ nfs-utils-1.3.0/utils/gssd/gssd.man 2014-09-17 13:00:26.575004049 -0400
@@ -289,6 +289,14 @@ new kernel contexts to be negotiated aft
seconds, which allows changing Kerberos tickets and identities frequently.
The default is no explicit timeout, which means the kernel context will live
the lifetime of the Kerberos service ticket used in its creation.
+.TP
+.B -T timeout
+Timeout, in seconds, to create an RPC connection with a server while
+establishing an authenticated gss context for a user.
+The default timeout is set to 5 seconds.
+If you get messages like "WARNING: can't create tcp rpc_clnt to server
+%servername% for user with uid %uid%: RPC: Remote system error -
+Connection timed out", you should consider an increase of this timeout.
.SH SEE ALSO
.BR rpc.svcgssd (8),
.BR kerberos (1),
diff -up nfs-utils-1.3.0/utils/gssd/gssd_proc.c.orig nfs-utils-1.3.0/utils/gssd/gssd_proc.c
--- nfs-utils-1.3.0/utils/gssd/gssd_proc.c.orig 2014-09-17 13:00:22.702932025 -0400
+++ nfs-utils-1.3.0/utils/gssd/gssd_proc.c 2014-09-17 13:00:26.575004049 -0400
@@ -842,7 +842,7 @@ create_auth_rpc_client(struct clnt_info
OM_uint32 min_stat;
char rpc_errmsg[1024];
int protocol;
- struct timeval timeout = {5, 0};
+ struct timeval timeout;
struct sockaddr *addr = (struct sockaddr *) &clp->addr;
socklen_t salen;
@@ -910,6 +910,10 @@ create_auth_rpc_client(struct clnt_info
if (!populate_port(addr, salen, clp->prog, clp->vers, protocol))
goto out_fail;
+ /* set the timeout according to the requested valued */
+ timeout.tv_sec = (long) rpc_timeout;
+ timeout.tv_usec = (long) 0;
+
rpc_clnt = nfs_get_rpcclient(addr, salen, protocol, clp->prog,
clp->vers, &timeout);
if (!rpc_clnt) {

97
SOURCES/nfs-utils-1.3.0-rpcidmapd-usage.patch

@ -0,0 +1,97 @@ @@ -0,0 +1,97 @@
diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c
index aff89d1..f55d2e1 100644
--- a/utils/idmapd/idmapd.c
+++ b/utils/idmapd/idmapd.c
@@ -199,6 +199,12 @@ flush_nfsd_idmap_cache(void)
return ret;
}
+void usage(char *progname)
+{
+ fprintf(stderr, "Usage: %s [-hfvCS] [-p path] [-c path]\n",
+ basename(progname));
+}
+
int
main(int argc, char **argv)
{
@@ -225,16 +231,18 @@ main(int argc, char **argv)
progname = argv[0];
xlog_open(progname);
-#define GETOPTSTR "vfd:p:U:G:c:CS"
+#define GETOPTSTR "hvfd:p:U:G:c:CS"
opterr=0; /* Turn off error messages */
while ((opt = getopt(argc, argv, GETOPTSTR)) != -1) {
if (opt == 'c')
conf_path = optarg;
if (opt == '?') {
if (strchr(GETOPTSTR, optopt))
- errx(1, "'-%c' option requires an argument.", optopt);
+ warnx("'-%c' option requires an argument.", optopt);
else
- errx(1, "'-%c' is an invalid argument.", optopt);
+ warnx("'-%c' is an invalid argument.", optopt);
+ usage(progname);
+ exit(1);
}
}
optind = 1;
@@ -276,6 +284,9 @@ main(int argc, char **argv)
case 'S':
clientstart = 0;
break;
+ case 'h':
+ usage(progname);
+ exit(0);
default:
break;
}
diff --git a/utils/idmapd/idmapd.man b/utils/idmapd/idmapd.man
index 185cd1b..b9200c7 100644
--- a/utils/idmapd/idmapd.man
+++ b/utils/idmapd/idmapd.man
@@ -10,8 +10,11 @@
.Sh SYNOPSIS
.\" For a program: program [-abc] file ...
.Nm rpc.idmapd
-.Op Fl v
+.Op Fl h
.Op Fl f
+.Op Fl v
+.Op Fl C
+.Op Fl S
.Op Fl p Ar path
.Op Fl c Ar path
.Sh DESCRIPTION
@@ -20,8 +23,20 @@ is the NFSv4 ID <-> name mapping daemon. It provides functionality to
the NFSv4 kernel client and server, to which it communicates via
upcalls, by translating user and group IDs to names, and vice versa.
.Pp
+Note that on more recent kernels only the NFSv4 server uses
+.Nm .
+The NFSv4 client instead uses
+.Xr nfsidmap 8 ,
+and only falls back to
+.Nm
+if there was a problem running the
+.Xr nfsidmap 8
+program.
+.Pp
The options are as follows:
.Bl -tag -width Ds_imagedir
+.It Fl h
+Display usage message.
.It Fl v
Increases the verbosity level (can be specified multiple times).
.It Fl f
@@ -58,7 +73,8 @@ messages to console, and with a verbosity level of 3.
.Sh FILES
.Pa /etc/idmapd.conf
.Sh SEE ALSO
-.Xr idmapd.conf 5
+.Xr idmapd.conf 5 ,
+.Xr nfsidmap 8
.\".Sh SEE ALSO
.\".Xr nylon.conf 4
.\" .Sh COMPATIBILITY

935
SOURCES/nfs-utils-1.3.0-server-chgrpcpipefs.patch

@ -0,0 +1,935 @@ @@ -0,0 +1,935 @@
diff --git a/.gitignore b/.gitignore
index 3d9640d..d26f4be 100644
--- a/.gitignore
+++ b/.gitignore
@@ -70,6 +70,8 @@ tests/nsm_client/nlm_sm_inter_svc.c
tests/nsm_client/nlm_sm_inter_xdr.c
utils/nfsidmap/nfsidmap
systemd/nfs-server-generator
+systemd/rpc-pipefs-generator
+systemd/rpc-gssd.service
# cscope database files
cscope.*
# generic editor backup et al
diff --git a/configure.ac b/configure.ac
index 3bce774..fce0e15 100644
--- a/configure.ac
+++ b/configure.ac
@@ -498,8 +498,14 @@ AC_SUBST([AM_CFLAGS], ["$my_am_cflags"])
# Make sure that $ACLOCAL_FLAGS are used during a rebuild
AC_SUBST([ACLOCAL_AMFLAGS], ["-I $ac_macro_dir \$(ACLOCAL_FLAGS)"])
+# make _sysconfdir available for substituion in config files
+# 2 "evals" needed late to expand variable names.
+AC_SUBST([_sysconfdir])
+AC_CONFIG_COMMANDS_PRE([eval eval _sysconfdir=$sysconfdir])
+
AC_CONFIG_FILES([
Makefile
+ systemd/rpc-gssd.service
linux-nfs/Makefile
support/Makefile
support/export/Makefile
diff --git a/nfs.conf b/nfs.conf
index c907de6..89cf386 100644
--- a/nfs.conf
+++ b/nfs.conf
@@ -1,7 +1,10 @@
#
-# This is a general conifguration for the
+# This is a general configuration for the
# NFS daemons and tools
#
+#[general]
+# pipefs-directory=/var/lib/nfs/rpc_pipefs
+#
#[exportfs]
# debug=0
#
@@ -12,7 +15,6 @@
# limit-to-legacy-enctypes=0
# context-timeout=0
# rpc-timeout=5
-# pipefs-directory=/var/lib/nfs/rpc_pipefs
# keytab-file=/etc/krb5.keytab
# cred-cache-directory=
# preferred-realm=
diff --git a/support/include/xcommon.h b/support/include/xcommon.h
index d1a4b18..23c9a13 100644
--- a/support/include/xcommon.h
+++ b/support/include/xcommon.h
@@ -17,6 +17,12 @@
#include <stdlib.h>
#include <string.h>
+#ifdef MAJOR_IN_MKDEV
+#include <sys/mkdev.h>
+#elif defined(MAJOR_IN_SYSMACROS)
+#include <sys/sysmacros.h>
+#endif
+
#define streq(s, t) (strcmp ((s), (t)) == 0)
/* Functions in sundries.c that are used in mount.c and umount.c */
diff --git a/support/nfs/nfsexport.c b/support/nfs/nfsexport.c
index f129fd2..c1c736e 100644
--- a/support/nfs/nfsexport.c
+++ b/support/nfs/nfsexport.c
@@ -18,6 +18,7 @@
#include <fcntl.h>
#include "nfslib.h"
+#include "xcommon.h"
/* if /proc/net/rpc/... exists, then
* write to it, as that interface is more stable.
diff --git a/systemd/Makefile.am b/systemd/Makefile.am
index b789916..54a3b64 100644
--- a/systemd/Makefile.am
+++ b/systemd/Makefile.am
@@ -8,6 +8,7 @@ unit_files = \
nfs-blkmap.service \
nfs-config.service \
nfs-idmapd.service \
+ rpc_pipefs.target \
nfs-mountd.service \
nfs-server.service \
nfs-utils.service \
@@ -24,14 +25,23 @@ EXTRA_DIST = $(unit_files) $(man5_MANS) $(man7_MANS)
unit_dir = /usr/lib/systemd/system
generator_dir = /usr/lib/systemd/system-generators
-EXTRA_PROGRAMS = nfs-server-generator
+EXTRA_PROGRAMS = nfs-server-generator rpc-pipefs-generator
genexecdir = $(generator_dir)
+
+COMMON_SRCS = systemd.c systemd.h
+
+nfs_server_generator_SOURCES = $(COMMON_SRCS) nfs-server-generator.c
+
+rpc_pipefs_generator_SOURCES = $(COMMON_SRCS) rpc-pipefs-generator.c
+
nfs_server_generator_LDADD = ../support/export/libexport.a \
../support/nfs/libnfs.a \
../support/misc/libmisc.a
+rpc_pipefs_generator_LDADD = ../support/nfs/libnfs.a
+
if INSTALL_SYSTEMD
-genexec_PROGRAMS = nfs-server-generator
+genexec_PROGRAMS = nfs-server-generator rpc-pipefs-generator
install-data-hook: $(unit_files)
mkdir -p $(DESTDIR)/$(unitdir)
cp $(unit_files) $(DESTDIR)/$(unitdir)
diff --git a/systemd/nfs-blkmap.service b/systemd/nfs-blkmap.service
index ddbf4e9..c844e2d 100644
--- a/systemd/nfs-blkmap.service
+++ b/systemd/nfs-blkmap.service
@@ -2,8 +2,8 @@
Description=pNFS block layout mapping daemon
DefaultDependencies=no
Conflicts=umount.target
-After=var-lib-nfs-rpc_pipefs.mount
-Requires=var-lib-nfs-rpc_pipefs.mount
+After=rpc_pipefs.target
+Requires=rpc_pipefs.target
PartOf=nfs-utils.service
diff --git a/systemd/nfs-idmapd.service b/systemd/nfs-idmapd.service
index df3dd9d..38685b6 100644
--- a/systemd/nfs-idmapd.service
+++ b/systemd/nfs-idmapd.service
@@ -1,8 +1,8 @@
[Unit]
Description=NFSv4 ID-name mapping service
DefaultDependencies=no
-Requires=var-lib-nfs-rpc_pipefs.mount
-After=var-lib-nfs-rpc_pipefs.mount local-fs.target
+Requires=rpc_pipefs.target
+After=rpc_pipefs.target local-fs.target
BindsTo=nfs-server.service
diff --git a/systemd/nfs-server-generator.c b/systemd/nfs-server-generator.c
index 4aa6509..737f109 100644
--- a/systemd/nfs-server-generator.c
+++ b/systemd/nfs-server-generator.c
@@ -29,6 +29,7 @@
#include "misc.h"
#include "nfslib.h"
#include "exportfs.h"
+#include "systemd.h"
/* A simple "set of strings" to remove duplicates
* found in /etc/exports
@@ -55,35 +56,6 @@ static int is_unique(struct list **lp, char *path)
return 1;
}
-/* We need to convert a path name to a systemd unit
- * name. This requires some translation ('/' -> '-')
- * and some escaping.
- */
-static void systemd_escape(FILE *f, char *path)
-{
- while (*path == '/')
- path++;
- if (!*path) {
- /* "/" becomes "-", otherwise leading "/" is ignored */
- fputs("-", f);
- return;
- }
- while (*path) {
- char c = *path++;
-
- if (c == '/') {
- /* multiple non-trailing slashes become '-' */
- while (*path == '/')
- path++;
- if (*path)
- fputs("-", f);
- } else if (isalnum(c) || c == ':' || c == '.')
- fputc(c, f);
- else
- fprintf(f, "\\x%02x", c & 0xff);
- }
-}
-
static int has_noauto_flag(char *path)
{
FILE *fstab;
@@ -108,7 +80,7 @@ static int has_noauto_flag(char *path)
int main(int argc, char *argv[])
{
- char *path;
+ char *path, *spath;
char dirbase[] = "/nfs-server.service.d";
char filebase[] = "/order-with-mounts.conf";
nfs_export *exp;
@@ -167,9 +139,15 @@ int main(int argc, char *argv[])
if (strcmp(mnt->mnt_type, "nfs") != 0 &&
strcmp(mnt->mnt_type, "nfs4") != 0)
continue;
- fprintf(f, "Before= ");
- systemd_escape(f, mnt->mnt_dir);
- fprintf(f, ".mount\n");
+
+ spath = systemd_escape(mnt->mnt_dir, ".mount");
+ if (!spath) {
+ fprintf(stderr,
+ "nfs-server-generator: convert path failed: %s\n",
+ mnt->mnt_dir);
+ continue;
+ }
+ fprintf(f, "Before=%s\n", spath);
}
fclose(fstab);
diff --git a/systemd/nfs.conf.man b/systemd/nfs.conf.man
index 938b970..9700586 100644
--- a/systemd/nfs.conf.man
+++ b/systemd/nfs.conf.man
@@ -96,6 +96,18 @@ value, which can be one or more from the list
.BR all .
When a list is given, the members should be comma-separated.
.TP
+.B general
+Recognized values:
+.BR pipefs-directory .
+
+See
+.BR blkmapd (8),
+.BR rpc.idmapd (8),
+and
+.BR rpc.gssd (8)
+for details.
+
+.TP
.B nfsdcltrack
Recognized values:
.BR storagedir .
@@ -198,7 +210,6 @@ Recognized values:
.BR limit-to-legacy-enctypes ,
.BR context-timeout ,
.BR rpc-timeout ,
-.BR pipefs-directory ,
.BR keytab-file ,
.BR cred-cache-directory ,
.BR preferred-realm .
diff --git a/systemd/rpc-gssd.service b/systemd/rpc-gssd.service
deleted file mode 100644
index 5d6d09f..0000000
--- a/systemd/rpc-gssd.service
+++ /dev/null
@@ -1,19 +0,0 @@
-[Unit]
-Description=RPC security service for NFS client and server
-DefaultDependencies=no
-Conflicts=umount.target
-Requires=var-lib-nfs-rpc_pipefs.mount
-After=var-lib-nfs-rpc_pipefs.mount gssproxy.service
-
-ConditionPathExists=/etc/krb5.keytab
-
-PartOf=nfs-utils.service
-
-Wants=nfs-config.service
-After=nfs-config.service
-
-[Service]
-EnvironmentFile=-/run/sysconfig/nfs-utils
-
-Type=forking
-ExecStart=/usr/sbin/rpc.gssd $GSSDARGS
diff --git a/systemd/rpc-gssd.service.in b/systemd/rpc-gssd.service.in
new file mode 100644
index 0000000..c75ccbd
--- /dev/null
+++ b/systemd/rpc-gssd.service.in
@@ -0,0 +1,19 @@
+[Unit]
+Description=RPC security service for NFS client and server
+DefaultDependencies=no
+Conflicts=umount.target
+Requires=rpc_pipefs.target
+After=rpc_pipefs.target gssproxy.service
+
+ConditionPathExists=@_sysconfdir@/krb5.keytab
+
+PartOf=nfs-utils.service
+
+Wants=nfs-config.service
+After=nfs-config.service
+
+[Service]
+EnvironmentFile=-/run/sysconfig/nfs-utils
+
+Type=forking
+ExecStart=/usr/sbin/rpc.gssd $GSSDARGS
diff --git a/systemd/rpc-pipefs-generator.c b/systemd/rpc-pipefs-generator.c
new file mode 100644
index 0000000..66addb9
--- /dev/null
+++ b/systemd/rpc-pipefs-generator.c
@@ -0,0 +1,138 @@
+/*
+ * rpc-pipefs-generator:
+ * systemd generator to create ordering dependencies between
+ * nfs services and the rpc_pipefs mountpoint
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <mntent.h>
+
+#include "nfslib.h"
+#include "conffile.h"
+#include "systemd.h"
+
+#define RPC_PIPEFS_DEFAULT "/var/lib/nfs/rpc_pipefs"
+char *conf_path = NFS_CONFFILE;
+
+static int generate_mount_unit(const char *pipefs_path, const char *pipefs_unit,
+ const char *dirname)
+{
+ char *path;
+ FILE *f;
+
+ path = malloc(strlen(dirname) + 1 + strlen(pipefs_unit));
+ if (!path)
+ return 1;
+ sprintf(path, "%s/%s", dirname, pipefs_unit);
+ f = fopen(path, "w");
+ if (!f)
+ return 1;
+
+ fprintf(f, "# Automatically generated by rpc-pipefs-generator\n\n[Unit]\n");
+ fprintf(f, "Description=RPC Pipe File System\n");
+ fprintf(f, "DefaultDependencies=no\n");
+ fprintf(f, "After=systemd-tmpfiles-setup.service\n");
+ fprintf(f, "Conflicts=umount.target\n");
+ fprintf(f, "\n[Mount]\n");
+ fprintf(f, "What=sunrpc\n");
+ fprintf(f, "Where=%s\n", pipefs_path);
+ fprintf(f, "Type=rpc_pipefs\n");
+
+ fclose(f);
+ return 0;
+}
+
+static
+int generate_target(char *pipefs_path, const char *dirname)
+{
+ char *path;
+ char filebase[] = "/rpc_pipefs.target";
+ char *pipefs_unit;
+ FILE *f;
+ int ret = 0;
+
+ pipefs_unit = systemd_escape(pipefs_path, ".mount");
+ if (!pipefs_unit)
+ return 1;
+
+ ret = generate_mount_unit(pipefs_path, pipefs_unit, dirname);
+ if (ret)
+ return ret;
+
+ path = malloc(strlen(dirname) + 1 + sizeof(filebase));
+ if (!path)
+ return 2;
+ sprintf(path, "%s", dirname);
+ mkdir(path, 0755);
+ strcat(path, filebase);
+ f = fopen(path, "w");
+ if (!f)
+ return 1;
+
+ fprintf(f, "# Automatically generated by rpc-pipefs-generator\n\n[Unit]\n");
+ fprintf(f, "Requires=%s\n", pipefs_unit);
+ fprintf(f, "After=%s\n", pipefs_unit);
+ fclose(f);
+
+ return 0;
+}
+
+static int is_non_pipefs_mountpoint(char *path)
+{
+ FILE *mtab;
+ struct mntent *mnt;
+
+ mtab = setmntent("/etc/mtab", "r");
+ if (!mtab)
+ return 0;
+
+ while ((mnt = getmntent(mtab)) != NULL) {
+ if (strlen(mnt->mnt_dir) != strlen(path))
+ continue;
+ if (strncmp(mnt->mnt_dir, path, strlen(mnt->mnt_dir)))
+ continue;
+ if (strncmp(mnt->mnt_type, "rpc_pipefs", strlen(mnt->mnt_type)))
+ break;
+ }
+ fclose(mtab);
+ return mnt != NULL;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+ char *s;
+
+ /* Avoid using any external services */
+ xlog_syslog(0);
+
+ if (argc != 4 || argv[1][0] != '/') {
+ fprintf(stderr, "rpc-pipefs-generator: create systemd dependencies for nfs services\n");
+ fprintf(stderr, "Usage: normal-dir early-dir late-dir\n");
+ exit(1);
+ }
+
+ conf_init();
+ s = conf_get_str("general", "pipefs-directory");
+ if (!s)
+ exit(0);
+ if (strlen(s) == strlen(RPC_PIPEFS_DEFAULT) &&
+ strcmp(s, RPC_PIPEFS_DEFAULT) == 0)
+ exit(0);
+
+ if (is_non_pipefs_mountpoint(s))
+ exit(1);
+
+ ret = generate_target(s, argv[1]);
+ exit(ret);
+}
diff --git a/systemd/rpc-svcgssd.service b/systemd/rpc-svcgssd.service
index 41177b6..a3a555c 100644
--- a/systemd/rpc-svcgssd.service
+++ b/systemd/rpc-svcgssd.service
@@ -1,8 +1,7 @@
[Unit]
Description=RPC security service for NFS server
DefaultDependencies=no
-Requires=var-lib-nfs-rpc_pipefs.mount
-After=var-lib-nfs-rpc_pipefs.mount local-fs.target
+After=local-fs.target
PartOf=nfs-server.service
PartOf=nfs-utils.service
diff --git a/systemd/rpc_pipefs.target b/systemd/rpc_pipefs.target
new file mode 100644
index 0000000..01d4d27
--- /dev/null
+++ b/systemd/rpc_pipefs.target
@@ -0,0 +1,3 @@
+[Unit]
+Requires=var-lib-nfs-rpc_pipefs.mount
+After=var-lib-nfs-rpc_pipefs.mount
diff --git a/systemd/systemd.c b/systemd/systemd.c
new file mode 100644
index 0000000..17820d4
--- /dev/null
+++ b/systemd/systemd.c
@@ -0,0 +1,133 @@
+/*
+ * Helper functions for systemd generators in nfs-utils.
+ *
+ * Currently just systemd_escape().
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+static const char hex[16] =
+{
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
+};
+
+/*
+ * determine length of the string that systemd_escape() needs to allocate
+ */
+static int systemd_len(char *path)
+{
+ char *p;
+ int len = 0;
+
+ p = path;
+ while (*p == '/')
+ /* multiple leading "/" are ignored */
+ p++;
+
+ if (!*p)
+ /* root directory "/" becomes is encoded as a single "-" */
+ return 1;
+
+ if (*p == '.')
+ /*
+ * replace "." with "\x2d" escape sequence if
+ * it's the first character in escaped path
+ * */
+ len += 4;
+
+ while (*p) {
+ unsigned char c = *p++;
+
+ if (c == '/') {
+ /* multiple non-trailing slashes become '-' */
+ while (*p == '/')
+ p++;
+ if (*p)
+ len++;
+ } else if (isalnum(c) || c == ':' || c == '.' || c == '_')
+ /* these characters are not replaced */
+ len++;
+ else
+ /* replace with "\x2d" escape sequence */
+ len += 4;
+ }
+
+ return len;
+}
+
+/*
+ * convert c to "\x2d" escape sequence and append to string
+ * at position p, advancing p
+ */
+static char *hexify(unsigned char c, char *p)
+{
+ *p++ = '\\';
+ *p++ = 'x';
+ *p++ = hex[c >> 4];
+ *p++ = hex[c & 0xf];
+ return p;
+}
+
+/*
+ * convert a path to a unit name according to the logic in systemd.unit(5):
+ *
+ * Basically, given a path, "/" is replaced by "-", and all other
+ * characters which are not ASCII alphanumerics are replaced by C-style
+ * "\x2d" escapes (except that "_" is never replaced and "." is only
+ * replaced when it would be the first character in the escaped path).
+ * The root directory "/" is encoded as single dash, while otherwise the
+ * initial and ending "/" are removed from all paths during
+ * transformation.
+ *
+ * NB: Although the systemd.unit(5) doesn't mention it, the ':' character
+ * is not escaped.
+ */
+char *systemd_escape(char *path, char *suffix)
+{
+ char *result;
+ char *p;
+ int len;
+
+ len = systemd_len(path);
+ result = malloc(len + strlen(suffix) + 1);
+ p = result;
+ while (*path == '/')
+ /* multiple leading "/" are ignored */
+ path++;
+ if (!*path) {
+ /* root directory "/" becomes is encoded as a single "-" */
+ *p++ = '-';
+ goto out;
+ }
+ if (*path == '.')
+ /*
+ * replace "." with "\x2d" escape sequence if
+ * it's the first character in escaped path
+ * */
+ p = hexify(*path++, p);
+
+ while (*path) {
+ unsigned char c = *path++;
+
+ if (c == '/') {
+ /* multiple non-trailing slashes become '-' */
+ while (*path == '/')
+ path++;
+ if (*path)
+ *p++ = '-';
+ } else if (isalnum(c) || c == ':' || c == '.' || c == '_')
+ /* these characters are not replaced */
+ *p++ = c;
+ else
+ /* replace with "\x2d" escape sequence */
+ p = hexify(c, p);
+ }
+
+out:
+ sprintf(p, "%s", suffix);
+ return result;
+}
diff --git a/systemd/systemd.h b/systemd/systemd.h
new file mode 100644
index 0000000..25235ec
--- /dev/null
+++ b/systemd/systemd.h
@@ -0,0 +1,6 @@
+#ifndef SYSTEMD_H
+#define SYSTEMD_H
+
+char *systemd_escape(char *path, char *suffix);
+
+#endif /* SYSTEMD_H */
diff --git a/utils/blkmapd/blkmapd.man b/utils/blkmapd/blkmapd.man
index 914b80f..4b3d3f0 100644
--- a/utils/blkmapd/blkmapd.man
+++ b/utils/blkmapd/blkmapd.man
@@ -43,9 +43,24 @@ Performs device discovery only then exits.
Runs
.B blkmapd
in the foreground and sends output to stderr (as opposed to syslogd)
+.SH CONFIGURATION FILE
+The
+.B blkmapd
+daemon recognizes the following value from the
+.B [general]
+section of the
+.I /etc/nfs.conf
+configuration file:
+.TP
+.B pipefs-directory
+Tells
+.B blkmapd
+where to look for the rpc_pipefs filesystem. The default value is
+.IR /var/lib/nfs/rpc_pipefs .
.SH SEE ALSO
.BR nfs (5),
-.BR dmsetup (8)
+.BR dmsetup (8),
+.BR nfs.conf (5)
.sp
RFC 5661 for the NFS version 4.1 specification.
.br
diff --git a/utils/blkmapd/device-discovery.c b/utils/blkmapd/device-discovery.c
index b010628..a419947 100644
--- a/utils/blkmapd/device-discovery.c
+++ b/utils/blkmapd/device-discovery.c
@@ -50,19 +50,36 @@
#include <errno.h>
#include <libdevmapper.h>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
#include "device-discovery.h"
+#include "xcommon.h"
+#include "nfslib.h"
+#include "conffile.h"
#define EVENT_SIZE (sizeof(struct inotify_event))
#define EVENT_BUFSIZE (1024 * EVENT_SIZE)
-#define BL_PIPE_FILE "/var/lib/nfs/rpc_pipefs/nfs/blocklayout"
-#define NFSPIPE_DIR "/var/lib/nfs/rpc_pipefs/nfs"
#define RPCPIPE_DIR "/var/lib/nfs/rpc_pipefs"
#define PID_FILE "/var/run/blkmapd.pid"
+#define CONF_SAVE(w, f) do { \
+ char *p = f; \
+ if (p != NULL) \
+ (w) = p; \
+} while (0)
+
+static char bl_pipe_file[PATH_MAX];
+static char nfspipe_dir[PATH_MAX];
+static char rpcpipe_dir[PATH_MAX];
+
struct bl_disk *visible_disk_list;
int bl_watch_fd, bl_pipe_fd, nfs_pipedir_wfd, rpc_pipedir_wfd;
int pidfd = -1;
+char *conf_path = NULL;
+
struct bl_disk_path *bl_get_path(const char *filepath,
struct bl_disk_path *paths)
@@ -357,8 +374,8 @@ static void bl_rpcpipe_cb(void)
continue;
if (event->mask & IN_CREATE) {
BL_LOG_WARNING("nfs pipe dir created\n");
- bl_watch_dir(NFSPIPE_DIR, &nfs_pipedir_wfd);
- bl_pipe_fd = open(BL_PIPE_FILE, O_RDWR);
+ bl_watch_dir(nfspipe_dir, &nfs_pipedir_wfd);
+ bl_pipe_fd = open(bl_pipe_file, O_RDWR);
} else if (event->mask & IN_DELETE) {
BL_LOG_WARNING("nfs pipe dir deleted\n");
inotify_rm_watch(bl_watch_fd, nfs_pipedir_wfd);
@@ -371,7 +388,7 @@ static void bl_rpcpipe_cb(void)
continue;
if (event->mask & IN_CREATE) {
BL_LOG_WARNING("blocklayout pipe file created\n");
- bl_pipe_fd = open(BL_PIPE_FILE, O_RDWR);
+ bl_pipe_fd = open(bl_pipe_file, O_RDWR);
if (bl_pipe_fd < 0)
BL_LOG_ERR("open %s failed: %s\n",
event->name, strerror(errno));
@@ -437,6 +454,19 @@ int main(int argc, char **argv)
int opt, dflag = 0, fg = 0, ret = 1;
struct stat statbuf;
char pidbuf[64];
+ char *xrpcpipe_dir = NULL;
+
+ strncpy(rpcpipe_dir, RPCPIPE_DIR, sizeof(rpcpipe_dir));
+ conf_path = NFS_CONFFILE;
+ conf_init();
+ CONF_SAVE(xrpcpipe_dir, conf_get_str("general", "pipefs-directory"));
+ if (xrpcpipe_dir != NULL)
+ strlcpy(rpcpipe_dir, xrpcpipe_dir, sizeof(rpcpipe_dir));
+
+ strncpy(nfspipe_dir, rpcpipe_dir, sizeof(nfspipe_dir));
+ strlcat(nfspipe_dir, "/nfs", sizeof(nfspipe_dir));
+ strncpy(bl_pipe_file, rpcpipe_dir, sizeof(bl_pipe_file));
+ strlcat(bl_pipe_file, "/nfs/blocklayout", sizeof(bl_pipe_file));
while ((opt = getopt(argc, argv, "hdf")) != -1) {
switch (opt) {
@@ -501,12 +531,12 @@ int main(int argc, char **argv)
}
/* open pipe file */
- bl_watch_dir(RPCPIPE_DIR, &rpc_pipedir_wfd);
- bl_watch_dir(NFSPIPE_DIR, &nfs_pipedir_wfd);
+ bl_watch_dir(rpcpipe_dir, &rpc_pipedir_wfd);
+ bl_watch_dir(nfspipe_dir, &nfs_pipedir_wfd);
- bl_pipe_fd = open(BL_PIPE_FILE, O_RDWR);
+ bl_pipe_fd = open(bl_pipe_file, O_RDWR);
if (bl_pipe_fd < 0)
- BL_LOG_ERR("open pipe file %s failed: %s\n", BL_PIPE_FILE, strerror(errno));
+ BL_LOG_ERR("open pipe file %s failed: %s\n", bl_pipe_file, strerror(errno));
while (1) {
/* discover device when needed */
diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
index c5c03fb..10d50d3 100644
--- a/utils/gssd/gssd.c
+++ b/utils/gssd/gssd.c
@@ -857,6 +857,10 @@ read_gss_conf(void)
s = conf_get_str("gssd", "pipefs-directory");
if (!s)
s = conf_get_str("general", "pipefs-directory");
+ else
+ printerr(0, "WARNING: Specifying pipefs-directory in the [gssd] "
+ "section of %s is deprecated. Use the [general] "
+ "section instead.", NFS_CONFFILE);
if (s)
pipefs_path = s;
s = conf_get_str("gssd", "keytab-file");
diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man
index 87eef02..e620f0d 100644
--- a/utils/gssd/gssd.man
+++ b/utils/gssd/gssd.man
@@ -335,10 +335,6 @@ Equivalent to
Equivalent to
.BR -t .
.TP
-.B pipefs-directory
-Equivalent to
-.BR -p .
-.TP
.B keytab-file
Equivalent to
.BR -k .
@@ -350,6 +346,14 @@ Equivalent to
.B preferred-realm
Equivalent to
.BR -R .
+.P
+In addtion, the following value is recognized from the
+.B [general]
+section:
+.TP
+.B pipefs-directory
+Equivalent to
+.BR -p .
.SH SEE ALSO
.BR rpc.svcgssd (8),
diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c
index f55d2e1..03efbea 100644
--- a/utils/idmapd/idmapd.c
+++ b/utils/idmapd/idmapd.c
@@ -166,7 +166,7 @@ static uid_t nobodyuid;
static gid_t nobodygid;
/* Used by conffile.c in libnfs.a */
-char *conf_path;
+char *conf_path = NULL;
static int
flush_nfsd_cache(char *path, time_t now)
@@ -220,7 +220,6 @@ main(int argc, char **argv)
int ret;
char *progname;
- conf_path = _PATH_IDMAPDCONF;
nobodyuser = NFS4NOBODY_USER;
nobodygroup = NFS4NOBODY_GROUP;
strlcpy(pipefsdir, PIPEFS_DIR, sizeof(pipefsdir));
@@ -234,8 +233,11 @@ main(int argc, char **argv)
#define GETOPTSTR "hvfd:p:U:G:c:CS"
opterr=0; /* Turn off error messages */
while ((opt = getopt(argc, argv, GETOPTSTR)) != -1) {
- if (opt == 'c')
+ if (opt == 'c') {
+ warnx("-c is deprecated and may be removed in the "
+ "future. See idmapd(8).");
conf_path = optarg;
+ }
if (opt == '?') {
if (strchr(GETOPTSTR, optopt))
warnx("'-%c' option requires an argument.", optopt);
@@ -247,17 +249,33 @@ main(int argc, char **argv)
}
optind = 1;
- if (stat(conf_path, &sb) == -1 && (errno == ENOENT || errno == EACCES)) {
- warn("Skipping configuration file \"%s\"", conf_path);
- conf_path = NULL;
+ if (conf_path) { /* deprecated -c option was specified */
+ if (stat(conf_path, &sb) == -1 && (errno == ENOENT || errno == EACCES)) {
+ warn("Skipping configuration file \"%s\"", conf_path);
+ conf_path = NULL;
+ } else {
+ conf_init();
+ verbose = conf_get_num("General", "Verbosity", 0);
+ cache_entry_expiration = conf_get_num("General",
+ "Cache-Expiration", DEFAULT_IDMAP_CACHE_EXPIRY);
+ CONF_SAVE(xpipefsdir, conf_get_str("General", "Pipefs-Directory"));
+ if (xpipefsdir != NULL)
+ strlcpy(pipefsdir, xpipefsdir, sizeof(pipefsdir));
+ CONF_SAVE(nobodyuser, conf_get_str("Mapping", "Nobody-User"));
+ CONF_SAVE(nobodygroup, conf_get_str("Mapping", "Nobody-Group"));
+ }
} else {
+ conf_path = NFS_CONFFILE;
conf_init();
- verbose = conf_get_num("General", "Verbosity", 0);
- cache_entry_expiration = conf_get_num("General",
- "Cache-Expiration", DEFAULT_IDMAP_CACHE_EXPIRY);
CONF_SAVE(xpipefsdir, conf_get_str("General", "Pipefs-Directory"));
if (xpipefsdir != NULL)
strlcpy(pipefsdir, xpipefsdir, sizeof(pipefsdir));
+
+ conf_path = _PATH_IDMAPDCONF;
+ conf_init();
+ verbose = conf_get_num("General", "Verbosity", 0);
+ cache_entry_expiration = conf_get_num("General",
+ "cache-expiration", DEFAULT_IDMAP_CACHE_EXPIRY);
CONF_SAVE(nobodyuser, conf_get_str("Mapping", "Nobody-User"));
CONF_SAVE(nobodygroup, conf_get_str("Mapping", "Nobody-Group"));
}
diff --git a/utils/idmapd/idmapd.man b/utils/idmapd/idmapd.man
index b9200c7..fb5fc1e 100644
--- a/utils/idmapd/idmapd.man
+++ b/utils/idmapd/idmapd.man
@@ -50,11 +50,28 @@ The default value is \&"/var/lib/nfs/rpc_pipefs\&".
.It Fl c Ar path
Use configuration file
.Ar path .
+This option is deprecated.
.It Fl C
Client-only: perform no idmapping for any NFS server, even if one is detected.
.It Fl S
Server-only: perform no idmapping for any NFS client, even if one is detected.
.El
+.Sh CONFIGURATION FILES
+.Nm
+recognizes the following value from the
+.Sy [general]
+section of the
+.Pa /etc/nfs.conf
+configuration file:
+.Bl -tag -width Ds_imagedir
+.It Sy pipefs-directory
+Equivalent to
+.Sy -p .
+.El
+.Pp
+All other settings related to id mapping are found in the
+.Pa /etc/idmapd.conf
+configuration file.
.Sh EXAMPLES
.Cm rpc.idmapd -f -vvv
.Pp
@@ -71,9 +88,11 @@ messages to console, and with a verbosity level of 3.
.\" This next request is for sections 1, 6, 7 & 8 only.
.\" .Sh ENVIRONMENT
.Sh FILES
-.Pa /etc/idmapd.conf
+.Pa /etc/idmapd.conf ,
+.Pa /etc/nfs.conf
.Sh SEE ALSO
.Xr idmapd.conf 5 ,
+.Xr nfs.conf 5 ,
.Xr nfsidmap 8
.\".Sh SEE ALSO
.\".Xr nylon.conf 4
diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
index 3bc13ca..f23fb5a 100644
--- a/utils/mountd/cache.c
+++ b/utils/mountd/cache.c
@@ -31,6 +31,7 @@
#include "mountd.h"
#include "fsloc.h"
#include "pseudoflavors.h"
+#include "xcommon.h"
#ifdef USE_BLKID
#include "blkid/blkid.h"

467
SOURCES/nfs-utils-1.3.0-server-generator.patch

@ -0,0 +1,467 @@ @@ -0,0 +1,467 @@
diff -up nfs-utils-1.3.0/configure.ac.orig nfs-utils-1.3.0/configure.ac
--- nfs-utils-1.3.0/configure.ac.orig 2017-03-31 15:55:05.544831618 -0400
+++ nfs-utils-1.3.0/configure.ac 2017-03-31 15:58:38.833955546 -0400
@@ -64,8 +64,14 @@ unitdir=/usr/lib/systemd/system
AC_ARG_WITH(systemd,
[AC_HELP_STRING([--with-systemd@<:@=unit-dir-path@:>@],
[install systemd unit files @<:@Default: no, and path defaults to /usr/lib/systemd/system if not given@:>@])],
- test "$withval" = "no" && use_systemd=0 || unitdir=$withval use_systemd=1
- use_systemd=0
+ if test "$withval" != "no" ; then
+ use_systemd=1
+ if test "$withval" != "yes" ; then
+ unitdir=$withval
+ fi
+ else
+ use_systemd=0
+ fi
)
AM_CONDITIONAL(INSTALL_SYSTEMD, [test "$use_systemd" = 1])
AC_SUBST(unitdir)
diff -up nfs-utils-1.3.0/.gitignore.orig nfs-utils-1.3.0/.gitignore
--- nfs-utils-1.3.0/.gitignore.orig 2014-03-25 11:12:07.000000000 -0400
+++ nfs-utils-1.3.0/.gitignore 2017-03-31 15:55:47.123245655 -0400
@@ -69,6 +69,7 @@ tests/nsm_client/nlm_sm_inter_clnt.c
tests/nsm_client/nlm_sm_inter_svc.c
tests/nsm_client/nlm_sm_inter_xdr.c
utils/nfsidmap/nfsidmap
+systemd/nfs-server-generator
# cscope database files
cscope.*
# generic editor backup et al
diff -up nfs-utils-1.3.0/support/export/export.c.orig nfs-utils-1.3.0/support/export/export.c
--- nfs-utils-1.3.0/support/export/export.c.orig 2017-03-31 15:55:05.528831459 -0400
+++ nfs-utils-1.3.0/support/export/export.c 2017-03-31 15:55:47.124245665 -0400
@@ -15,6 +15,8 @@
#include <sys/param.h>
#include <netinet/in.h>
#include <stdlib.h>
+#include <dirent.h>
+#include <errno.h>
#include "xmalloc.h"
#include "nfslib.h"
#include "exportfs.h"
@@ -68,11 +70,15 @@ static void warn_duplicated_exports(nfs_
/**
* export_read - read entries from /etc/exports
* @fname: name of file to read from
+ * @ignore_hosts: don't check validity of host names
*
* Returns number of read entries.
+ * @ignore_hosts can be set when the host names won't be used
+ * and when getting delays or errors due to problems with
+ * hostname looking is not acceptable.
*/
int
-export_read(char *fname)
+export_read(char *fname, int ignore_hosts)
{
struct exportent *eep;
nfs_export *exp;
@@ -81,7 +87,7 @@ export_read(char *fname)
setexportent(fname, "r");
while ((eep = getexportent(0,1)) != NULL) {
- exp = export_lookup(eep->e_hostname, eep->e_path, 0);
+ exp = export_lookup(eep->e_hostname, eep->e_path, ignore_hosts);
if (!exp) {
if (export_create(eep, 0))
/* possible complaints already logged */
@@ -94,6 +100,70 @@ export_read(char *fname)
return volumes;
}
+
+/**
+ * export_d_read - read entries from /etc/exports.
+ * @fname: name of directory to read from
+ * @ignore_hosts: don't check validity of host names
+ *
+ * Returns number of read entries.
+ * Based on mnt_table_parse_dir() in
+ * util-linux-ng/shlibs/mount/src/tab_parse.c
+ */
+int
+export_d_read(const char *dname, int ignore_hosts)
+{
+ int n = 0, i;
+ struct dirent **namelist = NULL;
+ int volumes = 0;
+
+
+ n = scandir(dname, &namelist, NULL, versionsort);
+ if (n < 0) {
+ if (errno == ENOENT)
+ /* Silently return */
+ return volumes;
+ xlog(L_NOTICE, "scandir %s: %s", dname, strerror(errno));
+ } else if (n == 0)
+ return volumes;
+
+ for (i = 0; i < n; i++) {
+ struct dirent *d = namelist[i];
+ size_t namesz;
+ char fname[PATH_MAX + 1];
+ int fname_len;
+
+
+ if (d->d_type != DT_UNKNOWN
+ && d->d_type != DT_REG
+ && d->d_type != DT_LNK)
+ continue;
+ if (*d->d_name == '.')
+ continue;
+
+#define _EXT_EXPORT_SIZ (sizeof(_EXT_EXPORT) - 1)
+ namesz = strlen(d->d_name);
+ if (!namesz
+ || namesz < _EXT_EXPORT_SIZ + 1
+ || strcmp(d->d_name + (namesz - _EXT_EXPORT_SIZ),
+ _EXT_EXPORT))
+ continue;
+
+ fname_len = snprintf(fname, PATH_MAX +1, "%s/%s", dname, d->d_name);
+ if (fname_len > PATH_MAX) {
+ xlog(L_WARNING, "Too long file name: %s in %s", d->d_name, dname);
+ continue;
+ }
+
+ volumes += export_read(fname, ignore_hosts);
+ }
+
+ for (i = 0; i < n; i++)
+ free(namelist[i]);
+ free(namelist);
+
+ return volumes;
+}
/**
* export_create - create an in-core nfs_export record from an export entry
diff -up nfs-utils-1.3.0/support/include/exportfs.h.orig nfs-utils-1.3.0/support/include/exportfs.h
--- nfs-utils-1.3.0/support/include/exportfs.h.orig 2017-03-31 15:55:05.528831459 -0400
+++ nfs-utils-1.3.0/support/include/exportfs.h 2017-03-31 15:55:47.124245665 -0400
@@ -133,7 +133,8 @@ struct addrinfo * client_resolve(const
int client_member(const char *client,
const char *name);
-int export_read(char *fname);
+int export_read(char *fname, int ignore_hosts);
+int export_d_read(const char *dname, int ignore_hosts);
void export_reset(nfs_export *);
nfs_export * export_lookup(char *hname, char *path, int caconical);
nfs_export * export_find(const struct addrinfo *ai,
diff -up nfs-utils-1.3.0/systemd/Makefile.am.orig nfs-utils-1.3.0/systemd/Makefile.am
--- nfs-utils-1.3.0/systemd/Makefile.am.orig 2017-03-31 15:55:05.545831628 -0400
+++ nfs-utils-1.3.0/systemd/Makefile.am 2017-03-31 15:55:47.124245665 -0400
@@ -4,7 +4,6 @@ MAINTAINERCLEANFILES = Makefile.in
unit_files = \
nfs-client.target \
- \
auth-rpcgss-module.service \
nfs-blkmap.service \
nfs-config.service \
@@ -15,8 +14,6 @@ unit_files = \
rpc-gssd.service \
rpc-statd-notify.service \
rpc-statd.service \
- rpc-svcgssd.service \
- \
proc-fs-nfsd.mount \
var-lib-nfs-rpc_pipefs.mount
@@ -25,8 +22,16 @@ man7_MANS = nfs.systemd.man
EXTRA_DIST = $(unit_files) $(man5_MANS) $(man7_MANS)
unit_dir = /usr/lib/systemd/system
+generator_dir = /usr/lib/systemd/system-generators
+
+EXTRA_PROGRAMS = nfs-server-generator
+genexecdir = $(generator_dir)
+nfs_server_generator_LDADD = ../support/export/libexport.a \
+ ../support/nfs/libnfs.a \
+ ../support/misc/libmisc.a
if INSTALL_SYSTEMD
+genexec_PROGRAMS = nfs-server-generator
install-data-hook: $(unit_files)
mkdir -p $(DESTDIR)/$(unitdir)
cp $(unit_files) $(DESTDIR)/$(unitdir)
diff -up nfs-utils-1.3.0/systemd/nfs-server-generator.c.orig nfs-utils-1.3.0/systemd/nfs-server-generator.c
--- nfs-utils-1.3.0/systemd/nfs-server-generator.c.orig 2017-03-31 15:55:47.124245665 -0400
+++ nfs-utils-1.3.0/systemd/nfs-server-generator.c 2017-03-31 15:55:47.124245665 -0400
@@ -0,0 +1,179 @@
+/*
+ * nfs-server-generator:
+ * systemd generator to create ordering dependencies between
+ * nfs-server and various filesystem mounts
+ *
+ * 1/ nfs-server should start Before any 'nfs' mountpoints are
+ * mounted, in case they are loop-back mounts. This ordering is particularly
+ * important for the shutdown side, so the nfs-server is stopped
+ * after the filesystems are unmounted.
+ * 2/ nfs-server should start After all exported filesystems are mounted
+ * so there is no risk of exporting the underlying directory.
+ * This is particularly important for _net mounts which
+ * are not caught by "local-fs.target".
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <mntent.h>
+
+#include "misc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+
+/* A simple "set of strings" to remove duplicates
+ * found in /etc/exports
+ */
+struct list {
+ struct list *next;
+ char *name;
+};
+static int is_unique(struct list **lp, char *path)
+{
+ struct list *l = *lp;
+
+ while (l) {
+ if (strcmp(l->name, path) == 0)
+ return 0;
+ l = l->next;
+ }
+ l = malloc(sizeof(*l));
+ if (l == NULL)
+ return 0;
+ l->name = path;
+ l->next = *lp;
+ *lp = l;
+ return 1;
+}
+
+/* We need to convert a path name to a systemd unit
+ * name. This requires some translation ('/' -> '-')
+ * and some escaping.
+ */
+static void systemd_escape(FILE *f, char *path)
+{
+ while (*path == '/')
+ path++;
+ if (!*path) {
+ /* "/" becomes "-", otherwise leading "/" is ignored */
+ fputs("-", f);
+ return;
+ }
+ while (*path) {
+ char c = *path++;
+
+ if (c == '/') {
+ /* multiple non-trailing slashes become '-' */
+ while (*path == '/')
+ path++;
+ if (*path)
+ fputs("-", f);
+ } else if (isalnum(c) || c == ':' || c == '.')
+ fputc(c, f);
+ else
+ fprintf(f, "\\x%02x", c & 0xff);
+ }
+}
+
+static int has_noauto_flag(char *path)
+{
+ FILE *fstab;
+ struct mntent *mnt;
+
+ fstab = setmntent("/etc/fstab", "r");
+ if (!fstab)
+ return 0;
+
+ while ((mnt = getmntent(fstab)) != NULL) {
+ int l = strlen(mnt->mnt_dir);
+ if (strncmp(mnt->mnt_dir, path, l) != 0)
+ continue;
+ if (path[l] && path[l] != '/')
+ continue;
+ if (hasmntopt(mnt, "noauto"))
+ break;
+ }
+ fclose(fstab);
+ return mnt != NULL;
+}
+
+int main(int argc, char *argv[])
+{
+ char *path;
+ char dirbase[] = "/nfs-server.service.d";
+ char filebase[] = "/order-with-mounts.conf";
+ nfs_export *exp;
+ int i;
+ struct list *list = NULL;
+ FILE *f, *fstab;
+ struct mntent *mnt;
+
+ /* Avoid using any external services */
+ xlog_syslog(0);
+
+ if (argc != 4 || argv[1][0] != '/') {
+ fprintf(stderr, "nfs-server-generator: create systemd dependencies for nfs-server\n");
+ fprintf(stderr, "Usage: normal-dir early-dir late-dir\n");
+ exit(1);
+ }
+
+ path = malloc(strlen(argv[1]) + sizeof(dirbase) + sizeof(filebase));
+ if (!path)
+ exit(2);
+ if (export_read(_PATH_EXPORTS, 1) +
+ export_d_read(_PATH_EXPORTS_D, 1) == 0)
+ /* Nothing is exported, so nothing to do */
+ exit(0);
+
+ strcat(strcpy(path, argv[1]), dirbase);
+ mkdir(path, 0755);
+ strcat(path, filebase);
+ f = fopen(path, "w");
+ if (!f)
+ exit(1);
+ fprintf(f, "# Automatically generated by nfs-server-generator\n\n[Unit]\n");
+
+ for (i = 0; i < MCL_MAXTYPES; i++) {
+ for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
+ if (!is_unique(&list, exp->m_export.e_path))
+ continue;
+ if (exp->m_export.e_mountpoint)
+ continue;
+ if (has_noauto_flag(exp->m_export.e_path))
+ continue;
+ if (strchr(exp->m_export.e_path, ' '))
+ fprintf(f, "RequiresMountsFor=\"%s\"\n",
+ exp->m_export.e_path);
+ else
+ fprintf(f, "RequiresMountsFor=%s\n",
+ exp->m_export.e_path);
+ }
+ }
+
+ fstab = setmntent("/etc/fstab", "r");
+ if (!fstab)
+ exit(1);
+
+ while ((mnt = getmntent(fstab)) != NULL) {
+ if (strcmp(mnt->mnt_type, "nfs") != 0 &&
+ strcmp(mnt->mnt_type, "nfs4") != 0)
+ continue;
+ fprintf(f, "Before= ");
+ systemd_escape(f, mnt->mnt_dir);
+ fprintf(f, ".mount\n");
+ }
+
+ fclose(fstab);
+ fclose(f);
+
+ exit(0);
+}
diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig 2017-03-31 15:55:05.553831708 -0400
+++ nfs-utils-1.3.0/utils/exportfs/exportfs.c 2017-03-31 15:55:47.125245675 -0400
@@ -26,7 +26,6 @@
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>
-#include <dirent.h>
#include <limits.h>
#include <time.h>
@@ -48,7 +47,6 @@ static void error(nfs_export *exp, int e
static void usage(const char *progname, int n);
static void validate_export(nfs_export *exp);
static int matchhostname(const char *hostname1, const char *hostname2);
-static int export_d_read(const char *dname);
static void grab_lockfile(void);
static void release_lockfile(void);
@@ -190,8 +188,8 @@ main(int argc, char **argv)
atexit(release_lockfile);
if (f_export && ! f_ignore) {
- if (! (export_read(_PATH_EXPORTS) +
- export_d_read(_PATH_EXPORTS_D))) {
+ if (! (export_read(_PATH_EXPORTS, 0) +
+ export_d_read(_PATH_EXPORTS_D, 0))) {
if (f_verbose)
xlog(L_WARNING, "No file systems exported!");
}
@@ -705,63 +703,6 @@ out:
return result;
}
-/* Based on mnt_table_parse_dir() in
- util-linux-ng/shlibs/mount/src/tab_parse.c */
-static int
-export_d_read(const char *dname)
-{
- int n = 0, i;
- struct dirent **namelist = NULL;
- int volumes = 0;
-
-
- n = scandir(dname, &namelist, NULL, versionsort);
- if (n < 0) {
- if (errno == ENOENT)
- /* Silently return */
- return volumes;
- xlog(L_NOTICE, "scandir %s: %s", dname, strerror(errno));
- } else if (n == 0)
- return volumes;
-
- for (i = 0; i < n; i++) {
- struct dirent *d = namelist[i];
- size_t namesz;
- char fname[PATH_MAX + 1];
- int fname_len;
-
-
- if (d->d_type != DT_UNKNOWN
- && d->d_type != DT_REG
- && d->d_type != DT_LNK)
- continue;
- if (*d->d_name == '.')
- continue;
-
-#define _EXT_EXPORT_SIZ (sizeof(_EXT_EXPORT) - 1)
- namesz = strlen(d->d_name);
- if (!namesz
- || namesz < _EXT_EXPORT_SIZ + 1
- || strcmp(d->d_name + (namesz - _EXT_EXPORT_SIZ),
- _EXT_EXPORT))
- continue;
-
- fname_len = snprintf(fname, PATH_MAX +1, "%s/%s", dname, d->d_name);
- if (fname_len > PATH_MAX) {
- xlog(L_WARNING, "Too long file name: %s in %s", d->d_name, dname);
- continue;
- }
-
- volumes += export_read(fname);
- }
-
- for (i = 0; i < n; i++)
- free(namelist[i]);
- free(namelist);
-
- return volumes;
-}
-
static char
dumpopt(char c, char *fmt, ...)
{

27
SOURCES/nfs-utils-1.3.0-start-statd-flock.patch

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
commit 8fef90084f3d19e90ba1bb22b8cd1d58ddaf6ef3
Author: Steve Dickson <steved@redhat.com>
Date: Tue Jun 21 12:06:06 2016 -0400

start-statd: Use flock to serialize the running of this script
To once and for all stop multiple rpc.statd from
being started (mostly in HA environments), use
flock to serialize the running of the script
Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/statd/start-statd b/utils/statd/start-statd
index 19e6eb2..2fd6039 100755
--- a/utils/statd/start-statd
+++ b/utils/statd/start-statd
@@ -6,6 +6,10 @@
# site.
PATH="/sbin:/usr/sbin:/bin:/usr/bin"
+# Use flock to serialize the running of this script
+exec 200> /var/run/rpc.statd.lock
+flock -e 200
+
if [ -s /var/run/rpc.statd.pid ] &&
[ 1`cat /var/run/rpc.statd.pid` -gt 1 ] &&
kill -0 `cat /var/run/rpc.statd.pid` > /dev/null 2>&1

31
SOURCES/nfs-utils-1.3.0-start-statd-once.patch

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
diff -up nfs-utils-1.3.0/utils/statd/start-statd.orig nfs-utils-1.3.0/utils/statd/start-statd
--- nfs-utils-1.3.0/utils/statd/start-statd.orig 2016-04-14 14:16:47.608999000 -0400
+++ nfs-utils-1.3.0/utils/statd/start-statd 2016-04-26 11:04:26.019962000 -0400
@@ -1,4 +1,4 @@
-#!/bin/bash -p
+#!/bin/sh
# nfsmount calls this script when mounting a filesystem with locking
# enabled, but when statd does not seem to be running (based on
# /var/run/rpc.statd.pid).
@@ -6,11 +6,19 @@
# site.
PATH="/sbin:/usr/sbin:/bin:/usr/bin"
+if [ -s /var/run/rpc.statd.pid ] &&
+ [ 1`cat /var/run/rpc.statd.pid` -gt 1 ] &&
+ kill -0 `cat /var/run/rpc.statd.pid` > /dev/null 2>&1
+then
+ # statd already running - must have been slow to respond.
+ exit 0
+fi
# First try systemd if it's installed.
if [ -d /run/systemd/system ]; then
- # Quit only if the call worked.
- systemctl start rpc-statd.service && exit
+ # Quit only if the call worked.
+ systemctl start rpc-statd.service && exit
fi
+cd /
# Fall back to launching it ourselves.
exec rpc.statd --no-notify

35
SOURCES/nfs-utils-1.3.0-start-statd-root.patch

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
diff --git a/utils/mount/network.c b/utils/mount/network.c
index 4f8c15c..515249b 100644
--- a/utils/mount/network.c
+++ b/utils/mount/network.c
@@ -796,6 +796,8 @@ int start_statd(void)
if (stat(START_STATD, &stb) == 0) {
if (S_ISREG(stb.st_mode) && (stb.st_mode & S_IXUSR)) {
int cnt = STATD_TIMEOUT * 10;
+ int status = 0;
+ char * const envp[1] = { NULL };
const struct timespec ts = {
.tv_sec = 0,
.tv_nsec = 100000000,
@@ -803,14 +805,19 @@ int start_statd(void)
pid_t pid = fork();
switch (pid) {
case 0: /* child */
- execl(START_STATD, START_STATD, NULL);
+ setgid(0);
+ setuid(0);
+ execle(START_STATD, START_STATD, NULL, envp);
exit(1);
case -1: /* error */
nfs_error(_("%s: fork failed: %s"),
progname, strerror(errno));
break;
default: /* parent */
- waitpid(pid, NULL,0);
+ if (waitpid(pid, &status,0) == pid &&
+ status == 0)
+ /* assume it worked */
+ return 1;
break;
}
while (1) {

14
SOURCES/nfs-utils-1.3.0-startstatd-systemd.patch

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
diff -up nfs-utils-1.3.0/utils/statd/start-statd.orig nfs-utils-1.3.0/utils/statd/start-statd
--- nfs-utils-1.3.0/utils/statd/start-statd.orig 2014-09-30 09:17:31.000000000 -0400
+++ nfs-utils-1.3.0/utils/statd/start-statd 2014-09-30 09:15:01.000000000 -0400
@@ -5,8 +5,9 @@
# It should run statd with whatever flags are apropriate for this
# site.
PATH="/sbin:/usr/sbin:/bin:/usr/bin"
-if systemctl start statd.service
+if systemctl start rpc-statd.service
then :
else
exec rpc.statd --no-notify
fi
+

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save