From c14176b6b81b669c5fa53d320220deb4f64854e6e73c1f2809e806b9abd1caa3 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Thu, 23 Jun 2011 05:52:18 +0000 Subject: [PATCH] - nfs.init,nfsserver.init,sysconfig.nfs - Add support for configuring NFS for a fail-over configuration with shared state. (bnc#689622) - rpc.mountd-segfault-fix; fix possible segfault caused by "showmount -e" usage. (bnc#693189) - do-not-error-when-address-family-not-supported - suppress socket error when IPv6 is not loaded (bnc#670449) - addmntent.fix - error check writes to /etc/mtab and cope accordingly. (bnc#689799) - mount-catch-signals - don't abort on SIGXSFZ or other signals while mtab is locked (bnc#689799) - mountd-auth-fix - fix bug that could give away incorrect access to NFS exported filesystems. (bnc#701702) OBS-URL: https://build.opensuse.org/package/show/Base:System/nfs-utils?expand=0&rev=52 --- addmntent.fix | 52 +++++++++ ...ot-error-when-address-family-not-supported | 38 ++++++ mount-catch-signals | 83 +++++++++++++ mountd-auth-fix | 110 ++++++++++++++++++ nfs-utils.changes | 18 +++ nfs-utils.spec | 10 ++ nfs.init | 12 +- nfsserver.init | 16 ++- rpc.mountd-segfault-fix | 30 +++++ sysconfig.nfs | 32 +++++ 10 files changed, 391 insertions(+), 10 deletions(-) create mode 100644 addmntent.fix create mode 100644 do-not-error-when-address-family-not-supported create mode 100644 mount-catch-signals create mode 100644 mountd-auth-fix create mode 100644 rpc.mountd-segfault-fix diff --git a/addmntent.fix b/addmntent.fix new file mode 100644 index 0000000..297fae1 --- /dev/null +++ b/addmntent.fix @@ -0,0 +1,52 @@ +From a47739bf3b89432e112d1d2ed9bbdaf1e09d450a Mon Sep 17 00:00:00 2001 +From: Neil Brown +Date: Tue, 17 May 2011 14:36:21 +1000 +Subject: [PATCH] Remove risk of nfs_addmntent corrupting mtab + +nfs_addmntent is used to append directly to /etc/mtab. +If the write partially fail, e.g. due to RLIMIT_FSIZE, +truncate back to original size and return an error. + +See also https://bugzilla.redhat.com/show_bug.cgi?id=697975 + (CVE-2011-1749) CVE-2011-1749 nfs-utils: mount.nfs fails to anticipate RLIMIT_FSIZE + +Signed-off-by: NeilBrown +--- + support/nfs/nfs_mntent.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- nfs-utils-1.2.1.orig/support/nfs/nfs_mntent.c ++++ nfs-utils-1.2.1/support/nfs/nfs_mntent.c +@@ -12,6 +12,7 @@ + #include /* for index */ + #include /* for isdigit */ + #include /* for umask */ ++#include /* for ftruncate */ + + #include "nfs_mntent.h" + #include "nls.h" +@@ -127,9 +128,11 @@ int + nfs_addmntent (mntFILE *mfp, struct mntent *mnt) { + char *m1, *m2, *m3, *m4; + int res; ++ off_t length; + + if (fseek (mfp->mntent_fp, 0, SEEK_END)) + return 1; /* failure */ ++ length = ftell(mfp->mntent_fp); + + m1 = mangle(mnt->mnt_fsname); + m2 = mangle(mnt->mnt_dir); +@@ -143,6 +146,12 @@ nfs_addmntent (mntFILE *mfp, struct mnte + free(m2); + free(m3); + free(m4); ++ if (res >= 0) ++ res = fflush(mfp->mntent_fp); ++ if (res < 0) ++ /* Avoid leaving a corrupt mtab file */ ++ ftruncate(fileno(mfp->mntent_fp), length); ++ + return (res < 0) ? 1 : 0; + } + diff --git a/do-not-error-when-address-family-not-supported b/do-not-error-when-address-family-not-supported new file mode 100644 index 0000000..3bb5eb5 --- /dev/null +++ b/do-not-error-when-address-family-not-supported @@ -0,0 +1,38 @@ +From: Suresh Jayaraman +Subject: [PATCH] supress socket error when address family is not supported +Patch-mainline: No +References: bnc#670449 + +It was observed that when ipv6 module was not loaded and cannot be auto-loaded, +when starting NFS server, the following error occurs: + "rpc.nfsd: unable to create inet6 TCP socket: errno 97 (Address + family not supported by protocol)" + +This is obviously a true message, but does not represent an "error" when ipv6 +is not enabled. Rather, it is an expected condition. As such, it can be +confusing / misleading / distracting to display it in this scenario. + +This patch instead of throwing error when a socket call fails with +EAFNOSUPPORT, makes it as a NOTICE. + +Signed-off-by: Suresh Jayaraman +--- + utils/nfsd/nfssvc.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- nfs-utils-1.2.1.orig/utils/nfsd/nfssvc.c ++++ nfs-utils-1.2.1/utils/nfsd/nfssvc.c +@@ -137,7 +137,12 @@ nfssvc_setfds(const struct addrinfo *hin + sockfd = socket(addr->ai_family, addr->ai_socktype, + addr->ai_protocol); + if (sockfd < 0) { +- xlog(L_ERROR, "unable to create %s %s socket: " ++ if (errno == EAFNOSUPPORT) ++ xlog(L_NOTICE, "address family %s not " ++ "supported by protocol %s", ++ family, proto); ++ else ++ xlog(L_ERROR, "unable to create %s %s socket: " + "errno %d (%m)", family, proto, errno); + rc = errno; + goto error; diff --git a/mount-catch-signals b/mount-catch-signals new file mode 100644 index 0000000..aad7fb0 --- /dev/null +++ b/mount-catch-signals @@ -0,0 +1,83 @@ +Subject: [PATCH] mount: improve signal management when locking mtab. +References: bnc#689799 + +As mount.nfs can run setuid it must be careful about how the user can +interact with in. In particular it needs to ensure it does not +respond badly to any signals that the user might be able to generate. + +This is particularly an issue while updating /etc/mtab (when that is +not linked to /proc/mounts). If the user can generate a signal which +kills mount.nfs while /etc/mtab is locked, then it will leave the file +locked, and could possibly corrupt mtab (particularly if 'ulimit 1' +was previously issued). + +Currently lock_mtab does set some handlers for signals, but not +enough. It arranges for every signal up to (but not including) +SIGCHLD to cause mount.nfs to unlock mdadm promptly exit ... even if +the default behaviour would be to ignore the signal. SIGALRM is +handled specially, and signals after SIGCHLD are left with their +default behaviour. This includes for example SIGXFSZ which can be +generated by the user running "ulimit 1". + +So: change this so that some signals are left unchanged, SIGALRM is +handled as required, and all signals that the user can generate are +explicitly ignored. + +The remainder still cause mount.nfs to print a message, unlock mtab, and exit. + +Signed-off-by: NeilBrown +--- + utils/mount/fstab.c | 37 ++++++++++++++++++++++++++++++++----- + 1 file changed, 32 insertions(+), 5 deletions(-) + +--- nfs-utils-1.2.1.orig/utils/mount/fstab.c ++++ nfs-utils-1.2.1/utils/mount/fstab.c +@@ -331,16 +331,43 @@ lock_mtab (void) { + int sig = 0; + struct sigaction sa; + +- sa.sa_handler = handler; + sa.sa_flags = 0; + sigfillset (&sa.sa_mask); + +- while (sigismember (&sa.sa_mask, ++sig) != -1 +- && sig != SIGCHLD) { +- if (sig == SIGALRM) ++ while (sigismember (&sa.sa_mask, ++sig) != -1) { ++ switch(sig) { ++ case SIGCHLD: ++ case SIGKILL: ++ case SIGCONT: ++ case SIGSTOP: ++ /* These cannot be caught, or should not, ++ * so don't even try. ++ */ ++ continue; ++ case SIGALRM: + sa.sa_handler = setlkw_timeout; +- else ++ break; ++ case SIGHUP: ++ case SIGINT: ++ case SIGQUIT: ++ case SIGWINCH: ++ case SIGTSTP: ++ case SIGTTIN: ++ case SIGTTOU: ++ case SIGPIPE: ++ case SIGXFSZ: ++ case SIGXCPU: ++ /* non-priv user can cause these to be ++ * generated, so ignore them. ++ */ ++ sa.sa_handler = SIG_IGN; ++ break; ++ default: ++ /* The rest should not be possible, so just ++ * print a message and unlock mtab. ++ */ + sa.sa_handler = handler; ++ } + sigaction (sig, &sa, (struct sigaction *) 0); + } + signals_have_been_setup = 1; diff --git a/mountd-auth-fix b/mountd-auth-fix new file mode 100644 index 0000000..ee1efec --- /dev/null +++ b/mountd-auth-fix @@ -0,0 +1,110 @@ +From b50ad13298b3e9519a9bdecb8c146c9ecf39cef8 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Wed, 22 Jun 2011 14:51:38 -0400 +Subject: [PATCH] nfs: fix host_reliable_addrinfo +References: bnc#701702 + +According to Neil Brown: + + The point of the word 'reliable' is to check that the name we get + really does belong to the host in question - ie that both the + forward and reverse maps agree. + + But the new code doesn't do that check at all. Rather it simply + maps the address to a name, then discards the address and maps the + name back to a list of addresses and uses that list of addresses as + "where the request came from" for permission checking. + +This bug is exploitable via the following scenario and could allow an +attacker access to data that they shouldn't be able to access. + + Suppose you export a filesystem to some subnet or FQDN and also to a + wildcard or netgroup, and I know the details of this (maybe + showmount -e tells me) Suppose further that I can get IP packets to + your server.. + + Then I create a reverse mapping for my ipaddress to a domain that I + own, say "black.hat.org", and a forward mapping from that domain to + my IP address, and one of your IP addresses. + + Then I try to mount your filesystem. The IP address gets correctly + mapped to "black.hat.org" and then mapped to both my IP address and + your IP address. + + Then you search through all of your exports and find that one of the + addresses: yours - is allowed to access the filesystem. + + So you create an export based on the addrinfo you have which allows + my IP address the same access as your IP address. + +Fix this by instead using the forward lookup of the hostname just to +verify that the original address is in the list. Then do a numeric +lookup using the address and stick the hostname in the ai_canonname. + +Reviewed-by: NeilBrown +Signed-off-by: Jeff Layton +Signed-off-by: Steve Dickson +--- + support/export/hostname.c | 36 ++++++++++++++++++++++++++++++------ + 1 file changed, 30 insertions(+), 6 deletions(-) + +--- nfs-utils-1.2.3.orig/support/export/hostname.c ++++ nfs-utils-1.2.3/support/export/hostname.c +@@ -262,17 +262,19 @@ host_canonname(const struct sockaddr *sa + * @sap: pointer to socket address to look up + * + * Reverse and forward lookups are performed to ensure the address has +- * proper forward and reverse mappings. ++ * matching forward and reverse mappings. + * +- * Returns address info structure with ai_canonname filled in, or NULL +- * if no information is available for @sap. Caller must free the returned +- * structure with freeaddrinfo(3). ++ * Returns addrinfo structure with just the provided address with ++ * ai_canonname filled in. If there is a problem with resolution or ++ * the resolved records don't match up properly then it returns NULL ++ * ++ * Caller must free the returned structure with freeaddrinfo(3). + */ + __attribute_malloc__ + struct addrinfo * + host_reliable_addrinfo(const struct sockaddr *sap) + { +- struct addrinfo *ai; ++ struct addrinfo *ai, *a; + char *hostname; + + hostname = host_canonname(sap); +@@ -280,9 +282,31 @@ host_reliable_addrinfo(const struct sock + return NULL; + + ai = host_addrinfo(hostname); ++ if (!ai) ++ goto out_free_hostname; + +- free(hostname); ++ /* make sure there's a matching address in the list */ ++ for (a = ai; a; a = a->ai_next) ++ if (nfs_compare_sockaddr(a->ai_addr, sap)) ++ break; ++ ++ freeaddrinfo(ai); ++ if (!a) ++ goto out_free_hostname; ++ ++ /* get addrinfo with just the original address */ ++ ai = host_numeric_addrinfo(sap); ++ if (!ai) ++ goto out_free_hostname; ++ ++ /* and populate its ai_canonname field */ ++ free(ai->ai_canonname); ++ ai->ai_canonname = hostname; + return ai; ++ ++out_free_hostname: ++ free(hostname); ++ return NULL; + } + + /** diff --git a/nfs-utils.changes b/nfs-utils.changes index 8a9cf05..7114a05 100644 --- a/nfs-utils.changes +++ b/nfs-utils.changes @@ -1,3 +1,21 @@ +------------------------------------------------------------------- +Thu Jun 23 05:41:25 UTC 2011 - nfbrown@novell.com + +- nfs.init,nfsserver.init,sysconfig.nfs - Add support + for configuring NFS for a fail-over configuration + with shared state. (bnc#689622) +- rpc.mountd-segfault-fix; fix possible segfault caused + by "showmount -e" usage. (bnc#693189) +- do-not-error-when-address-family-not-supported - + suppress socket error when IPv6 is not loaded + (bnc#670449) +- addmntent.fix - error check writes to /etc/mtab and + cope accordingly. (bnc#689799) +- mount-catch-signals - don't abort on SIGXSFZ or other + signals while mtab is locked (bnc#689799) +- mountd-auth-fix - fix bug that could give away incorrect + access to NFS exported filesystems. (bnc#701702) + ------------------------------------------------------------------- Fri Jun 17 14:12:19 UTC 2011 - aj@suse.de diff --git a/nfs-utils.spec b/nfs-utils.spec index df4298d..005a3e2 100644 --- a/nfs-utils.spec +++ b/nfs-utils.spec @@ -56,6 +56,11 @@ Patch2: nfs-utils-clear-mountd-reg Patch3: nfs-utils-allow-port-number-sharing Patch4: nfs-utils-improve-v4-umount Patch5: nfs-utils-fix-remount +Patch6: rpc.mountd-segfault-fix +Patch7: do-not-error-when-address-family-not-supported +Patch8: addmntent.fix +Patch9: mount-catch-signals +Patch10: mountd-auth-fix Suggests: python-base %description @@ -139,6 +144,11 @@ Authors: %patch3 -p1 %patch4 -p1 %patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 cp %{S:6} . %build diff --git a/nfs.init b/nfs.init index 8624062..70f2cc5 100644 --- a/nfs.init +++ b/nfs.init @@ -32,6 +32,10 @@ STATD_BIN=/usr/sbin/rpc.statd IDMAPD_CLIENT_STATE=/var/run/nfs/nfs-rpc.idmapd IDMAPD_SERVER_STATE=/var/run/nfs/nfsserver-rpc.idmapd +if [ -z "$RPC_PIPEFS_DIR" ]; then + RPC_PIPEFS_DIR=/var/lib/nfs/rpc_pipefs +fi + NEED_IDMAPD=no NEED_GSSD=no NEED_LDCONFIG=no @@ -116,18 +120,18 @@ fi mount_rpc_pipefs() { # See if the file system is there yet - case `stat -c "%t" -f /var/lib/nfs/rpc_pipefs` in + case `stat -c "%t" -f "$RPC_PIPEFS_DIR"` in *67596969*) return 0;; esac - mount -t rpc_pipefs rpc_pipefs /var/lib/nfs/rpc_pipefs + mount -t rpc_pipefs rpc_pipefs "$RPC_PIPEFS_DIR" } umount_rpc_pipefs() { # See if the file system is there - case `stat -c "%t" -f /var/lib/nfs/rpc_pipefs` in + case `stat -c "%t" -f "$RPC_PIPEFS_DIR"` in *67596969*) - umount /var/lib/nfs/rpc_pipefs + umount "$RPC_PIPEFS_DIR" esac } diff --git a/nfsserver.init b/nfsserver.init index 6f626a8..8e62f9d 100644 --- a/nfsserver.init +++ b/nfsserver.init @@ -79,6 +79,10 @@ if [ "$NFS4_SUPPORT" = yes ]; then NEED_IDMAPD=yes fi +if [ -z "$RPC_PIPEFS_DIR" ]; then + RPC_PIPEFS_DIR=/var/lib/nfs/rpc_pipefs +fi + check_for_nfsdfs() { HAVE_NFSDFS="no" while read dummy type ; do @@ -117,19 +121,19 @@ nfs4_unbind_mounts() { mount_rpc_pipefs() { # See if the file system is there yet - case `stat -c "%t" -f /var/lib/nfs/rpc_pipefs` in + case `stat -c "%t" -f "$RPC_PIPEFS_DIR"` in *67596969*) return 0;; esac - mount -t rpc_pipefs rpc_pipefs /var/lib/nfs/rpc_pipefs + mount -t rpc_pipefs rpc_pipefs "$RPC_PIPEFS_DIR" } umount_rpc_pipefs() { - case `stat -c "%t" -f /var/lib/nfs/rpc_pipefs` in + case `stat -c "%t" -f "$RPC_PIPEFS_DIR"` in *67596969*) - umount /var/lib/nfs/rpc_pipefs;; + umount "$RPC_PIPEFS_DIR";; esac } @@ -139,7 +143,7 @@ do_start_svcgssd() { done mount_rpc_pipefs - startproc $SVCGSSD_BIN + startproc $SVCGSSD_BIN $SVCGSSD_OPTIONS return $? } @@ -232,7 +236,7 @@ case "$1" in fi # rpc.nfsd echo -n " nfsd" - $NFSD_BIN $PARAMS $VERSION_PARAMS || { + $NFSD_BIN $NFSD_OPTIONS $PARAMS $VERSION_PARAMS || { rc_status -v rc_exit } diff --git a/rpc.mountd-segfault-fix b/rpc.mountd-segfault-fix new file mode 100644 index 0000000..72ee142 --- /dev/null +++ b/rpc.mountd-segfault-fix @@ -0,0 +1,30 @@ +From 730f6986f86873513fa021a450eb55ccd0f2fbff Mon Sep 17 00:00:00 2001 +From: Steve Dickson +Date: Wed, 26 Jan 2011 07:49:19 -0500 +Subject: [PATCH] Fixed segfault in rpc.mountd + +A unallocated piece of memory, instead of a NULL point, was being +used to initialize a ->next point in the mount link list which +caused a segfault after a few remote accesses via the showmount +command. + +Signed-off-by: Steve Dickson +--- + utils/mountd/rmtab.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/utils/mountd/rmtab.c b/utils/mountd/rmtab.c +index d339296..527377f 100644 +--- a/utils/mountd/rmtab.c ++++ b/utils/mountd/rmtab.c +@@ -205,6 +205,7 @@ mountlist_list(void) + } + if (stb.st_mtime != last_mtime) { + mountlist_freeall(mlist); ++ mlist = NULL; + last_mtime = stb.st_mtime; + + setrmtabent("r"); +-- +1.7.3.4 + diff --git a/sysconfig.nfs b/sysconfig.nfs index a819ae0..fb4e67c 100644 --- a/sysconfig.nfs +++ b/sysconfig.nfs @@ -100,3 +100,35 @@ STATD_OPTIONS="" # in a fail-over configuration with all clients on well connected # low latency links. NFSV4LEASETIME="" + +## Path: Network/File systems/NFS server +## Description: Alternate mount point for rpc_pipefs filesystem +## Type: string +## Default: "" +# +# In a high-availabilty configuration it is possible that /var/lib/nfs +# is redirected so some shared storage and so it is not convenient to +# mount the rpc_pipefs filesystem at /var/lib/nfs/rpc_pipefs. In that +# case an alternate mount point can be given here. +RPC_PIPEFS_DIR="" + +## Path: Network/File systems/NFS server +## Description: Options for svcgssd +## Type: string +## Default: "" +# +# Normally svcgssd does not require any option. However in a +# high-availabilty configuration it can be useful to pass "-n" +# to guide the choice of default credential. To allow for that +# case or any other requiring options ot svcgssd, they can +# be specified here. +SVCGSSD_OPTIONS="" + +## Path: Network/File systems/NFS server +## Description: Extra options for nfsd +## Type: string +## Default: "" +# +# This setting allows extra options to be specified for NFSD, such as +# -H in a high-availability configuration. +NFSD_OPTIONS=""