From 46ba229a89d7eb37b135e8cc5b15884baed5d4e1bfebb187ab379c5bb872098c Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Sun, 17 Nov 2013 23:07:43 +0000 Subject: [PATCH 1/3] - gssd-mount-hang-fix: An nfs mount will hang indefinitely if mounted by IP address and there is no reverse mapping available. This is caused by a bug in gssd. (bnc#833543) OBS-URL: https://build.opensuse.org/package/show/Base:System/nfs-utils?expand=0&rev=101 --- gssd-mount-hang-fix | 88 +++++++++++++++++++++++++++++++++++++++++++++ nfs-utils.changes | 9 +++++ nfs-utils.spec | 3 ++ 3 files changed, 100 insertions(+) create mode 100644 gssd-mount-hang-fix diff --git a/gssd-mount-hang-fix b/gssd-mount-hang-fix new file mode 100644 index 0000000..9c6630e --- /dev/null +++ b/gssd-mount-hang-fix @@ -0,0 +1,88 @@ +From: Neil Brown +Date: Thu, 14 Nov 2013 11:50:38 +1100 +Subject: [PATCH] gssd: always reply to rpc-pipe requests from kernel. +References: bnc#833543 + +Sometimes gssd will open a new rpc-pipe but never read requests from it +or reply to them. This causes the kernel to wait forever for a reply. + +In particular, if a filesystem is mounted by IP, and the IP has no +hostname recorded in /etc/hosts or DNS, then gssd will not listen to +requests and the mount will hang indefinitely. + +The comment in process_clnt_dir() for the "fail_keep_client:" branch +suggests that it is for the case where we couldn't open some +subdirectories. However it is currently also taken if reverse DNS +lookup fails (as well as some other lookup failures). Those failures +should not be treated the same as failure-to-open directories. + +So this patch causes a failure from read_service_info() to *not* be +reported by process_clnt_dir_files. This ensures that insert_clnt_poll() +will be called and requests will be handled. + +In handle_gssd_upcall, the current error path (taken when the mech is +not "krb5") does not reply to the upcall. This is wrong. A reply is +always appropriate. The only replies which aren't treated as +transient errors are EACCES and EKEYEXPIRED, so we return the former. + +If read_service_info() fails then ->servicename will be NULL which will +cause process_krb5_upcall() (quite reasonably) to become confused. So +in that case we don't even try to process the up-call but just reply +with EACCES. + +As clp->servicename==NULL is no longer treated as fatal, it is not +appropraite to use it to test if read_service_info() has been already +called on a client. Instread test clp->prog. + +Finally, the error path of read_service_info() will close 'fd' if it +isn't -1, so when we close it, we should set fd to -1. + +Signed-off-by: NeilBrown + +diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c +index b48d1637cd36..00b4bc779b7c 100644 +--- a/utils/gssd/gssd_proc.c ++++ b/utils/gssd/gssd_proc.c +@@ -256,6 +256,7 @@ read_service_info(char *info_file_name, char **servicename, char **servername, + if ((nbytes = read(fd, buf, INFOBUFLEN)) == -1) + goto fail; + close(fd); ++ fd = -1; + buf[nbytes] = '\0'; + + numfields = sscanf(buf,"RPC server: %127s\n" +@@ -403,11 +404,10 @@ process_clnt_dir_files(struct clnt_info * clp) + return -1; + snprintf(info_file_name, sizeof(info_file_name), "%s/info", + clp->dirname); +- if ((clp->servicename == NULL) && +- read_service_info(info_file_name, &clp->servicename, +- &clp->servername, &clp->prog, &clp->vers, +- &clp->protocol, (struct sockaddr *) &clp->addr)) +- return -1; ++ if (clp->prog == 0) ++ read_service_info(info_file_name, &clp->servicename, ++ &clp->servername, &clp->prog, &clp->vers, ++ &clp->protocol, (struct sockaddr *) &clp->addr); + return 0; + } + +@@ -1320,11 +1320,14 @@ handle_gssd_upcall(struct clnt_info *clp) + } + } + +- if (strcmp(mech, "krb5") == 0) ++ if (strcmp(mech, "krb5") == 0 && clp->servername) + process_krb5_upcall(clp, uid, clp->gssd_fd, target, service); +- else +- printerr(0, "WARNING: handle_gssd_upcall: " +- "received unknown gss mech '%s'\n", mech); ++ else { ++ if (clp->servername) ++ printerr(0, "WARNING: handle_gssd_upcall: " ++ "received unknown gss mech '%s'\n", mech); ++ do_error_downcall(clp->gssd_fd, uid, -EACCES); ++ } + + out: + free(lbuf); diff --git a/nfs-utils.changes b/nfs-utils.changes index b959f73..31f690e 100644 --- a/nfs-utils.changes +++ b/nfs-utils.changes @@ -1,3 +1,12 @@ +------------------------------------------------------------------- +Sun Nov 17 23:06:16 UTC 2013 - nfbrown@suse.com + +- gssd-mount-hang-fix: An nfs mount will hang + indefinitely if mounted by IP address and there + is no reverse mapping available. This is + caused by a bug in gssd. + (bnc#833543) + ------------------------------------------------------------------- Wed Nov 6 02:06:45 UTC 2013 - nfbrown@suse.com diff --git a/nfs-utils.spec b/nfs-utils.spec index 16e9101..ef3f1b3 100644 --- a/nfs-utils.spec +++ b/nfs-utils.spec @@ -81,6 +81,8 @@ Patch8: mountd-fix-bug-affecting-exports-of-dirs-with-64bit-.patch Patch9: exportfs-exit-with-error-code-if-there-was-any-error.patch # PATCH-FIX_UPSTREAM exportfs-report-failure-if-asked-to-unexport-somethi.patch nfbrown@suse.de Patch10: exportfs-report-failure-if-asked-to-unexport-somethi.patch +# PATCH-FIX-UPSTRAM gssd-mount-hang-fix bnc#833543 nfbrown@suse.de +Patch11: gssd-mount-hang-fix Suggests: python-base %description @@ -141,6 +143,7 @@ This package contains additional NFS documentation. %patch8 -p1 %patch9 -p1 %patch10 -p1 +%patch11 -p1 cp %{S:6} . %build From 3c16b1ce9dee4ff4ddc072010e5206a9c8db3abebc9e951677fe7e7dc662c1d8 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 18 Nov 2013 03:36:58 +0000 Subject: [PATCH 2/3] - nfsserver.init: fix typo in "--nfs-version 4". (bnc#849476) OBS-URL: https://build.opensuse.org/package/show/Base:System/nfs-utils?expand=0&rev=102 --- nfs-utils.changes | 6 ++++++ nfsserver.init | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/nfs-utils.changes b/nfs-utils.changes index 31f690e..2e953f0 100644 --- a/nfs-utils.changes +++ b/nfs-utils.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Mon Nov 18 03:35:45 UTC 2013 - nfbrown@suse.com + +- nfsserver.init: fix typo in "--nfs-version 4". + (bnc#849476) + ------------------------------------------------------------------- Sun Nov 17 23:06:16 UTC 2013 - nfbrown@suse.com diff --git a/nfsserver.init b/nfsserver.init index 6b93e7e..56a315a 100644 --- a/nfsserver.init +++ b/nfsserver.init @@ -205,7 +205,7 @@ case "$1" in VERSION_PARAMS="--no-nfs-version 4" fi if [ "$NFS4_SERVER_MINOR_VERSION" != "0" ]; then - VERSION_PARAMS="$VERSION_PARAMS -nfs-version 4 -nfs-version 4.$NFS4_SERVER_MINOR_VERSION" + VERSION_PARAMS="$VERSION_PARAMS --nfs-version 4 -nfs-version 4.$NFS4_SERVER_MINOR_VERSION" fi if [ -n "$NFSV4LEASETIME" -a -f /proc/fs/nfsd/nfsv4leasetime ]; then echo "$NFSV4LEASETIME" > /proc/fs/nfsd/nfsv4leasetime From 38549f2307585bdd8a9762cdc48b5a9b62f916118b5bdeeeb6b060ce8f4d6d3e Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 18 Nov 2013 03:39:57 +0000 Subject: [PATCH 3/3] Another small fix to nfsserver.init OBS-URL: https://build.opensuse.org/package/show/Base:System/nfs-utils?expand=0&rev=103 --- nfsserver.init | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nfsserver.init b/nfsserver.init index 56a315a..3063962 100644 --- a/nfsserver.init +++ b/nfsserver.init @@ -87,6 +87,11 @@ if [ -z "$RPC_PIPEFS_DIR" ]; then RPC_PIPEFS_DIR=/var/lib/nfs/rpc_pipefs fi +case "$NFS4_SERVER_MINOR_VERSION" in + [0123456789] ) ;; + * ) NFS4_SERVER_MINOR_VERSION=0 +esac + check_for_nfsdfs() { HAVE_NFSDFS="no" while read dummy type ; do