diff --git a/SOURCES/nfs-utils-2.5.4-gssd-dup-cachecreds.patch b/SOURCES/nfs-utils-2.5.4-gssd-dup-cachecreds.patch new file mode 100644 index 0000000..7174dcc --- /dev/null +++ b/SOURCES/nfs-utils-2.5.4-gssd-dup-cachecreds.patch @@ -0,0 +1,213 @@ +diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c +index 57b3cf8a..4f3a196a 100644 +--- a/utils/gssd/krb5_util.c ++++ b/utils/gssd/krb5_util.c +@@ -168,7 +168,8 @@ static int select_krb5_ccache(const struct dirent *d); + static int gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, + const char **cctype, struct dirent **d); + static int gssd_get_single_krb5_cred(krb5_context context, +- krb5_keytab kt, struct gssd_k5_kt_princ *ple, int force_renew); ++ krb5_keytab kt, struct gssd_k5_kt_princ *ple, int force_renew, ++ krb5_ccache ccache); + static int query_krb5_ccache(const char* cred_cache, char **ret_princname, + char **ret_realm); + +@@ -395,21 +396,14 @@ static int + gssd_get_single_krb5_cred(krb5_context context, + krb5_keytab kt, + struct gssd_k5_kt_princ *ple, +- int force_renew) ++ int force_renew, ++ krb5_ccache ccache) + { +-#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS +- krb5_get_init_creds_opt *init_opts = NULL; +-#else +- krb5_get_init_creds_opt options; +-#endif +- krb5_get_init_creds_opt *opts; ++ krb5_get_init_creds_opt *opts = NULL; + krb5_creds my_creds; +- krb5_ccache ccache = NULL; + char kt_name[BUFSIZ]; +- char cc_name[BUFSIZ]; + int code; + time_t now = time(0); +- char *cache_type; + char *pname = NULL; + char *k5err = NULL; + int nocache = 0; +@@ -443,35 +437,33 @@ gssd_get_single_krb5_cred(krb5_context context, + if ((krb5_unparse_name(context, ple->princ, &pname))) + pname = NULL; + +-#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS +- code = krb5_get_init_creds_opt_alloc(context, &init_opts); ++ code = krb5_get_init_creds_opt_alloc(context, &opts); + if (code) { + k5err = gssd_k5_err_msg(context, code); + printerr(0, "ERROR: %s allocating gic options\n", k5err); + goto out; + } +- if (krb5_get_init_creds_opt_set_addressless(context, init_opts, 1)) ++#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS ++ if (krb5_get_init_creds_opt_set_addressless(context, opts, 1)) + printerr(1, "WARNING: Unable to set option for addressless " + "tickets. May have problems behind a NAT.\n"); +-#ifdef TEST_SHORT_LIFETIME +- /* set a short lifetime (for debugging only!) */ +- printerr(1, "WARNING: Using (debug) short machine cred lifetime!\n"); +- krb5_get_init_creds_opt_set_tkt_life(init_opts, 5*60); ++#else ++ krb5_get_init_creds_opt_set_address_list(opts, NULL); + #endif +- opts = init_opts; +- +-#else /* HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS */ +- +- krb5_get_init_creds_opt_init(&options); +- krb5_get_init_creds_opt_set_address_list(&options, NULL); + #ifdef TEST_SHORT_LIFETIME + /* set a short lifetime (for debugging only!) */ +- printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n"); +- krb5_get_init_creds_opt_set_tkt_life(&options, 5*60); +-#endif +- opts = &options; ++ printerr(1, "WARNING: Using (debug) short machine cred lifetime!\n"); ++ krb5_get_init_creds_opt_set_tkt_life(opts, 5*60); + #endif + ++ if ((code = krb5_get_init_creds_opt_set_out_ccache(context, opts, ++ ccache))) { ++ k5err = gssd_k5_err_msg(context, code); ++ printerr(1, "WARNING: %s while initializing ccache for " ++ "principal '%s' using keytab '%s'\n", k5err, ++ pname ? pname : "", kt_name); ++ goto out; ++ } + if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ, + kt, 0, NULL, opts))) { + k5err = gssd_k5_err_msg(context, code); +@@ -481,63 +473,18 @@ gssd_get_single_krb5_cred(krb5_context context, + goto out; + } + +- /* +- * Initialize cache file which we're going to be using +- */ +- + pthread_mutex_lock(&ple_lock); +- if (use_memcache) +- cache_type = "MEMORY"; +- else +- cache_type = "FILE"; +- snprintf(cc_name, sizeof(cc_name), "%s:%s/%s%s_%s", +- cache_type, +- ccachesearch[0], GSSD_DEFAULT_CRED_PREFIX, +- GSSD_DEFAULT_MACHINE_CRED_SUFFIX, ple->realm); + ple->endtime = my_creds.times.endtime; +- if (ple->ccname == NULL || strcmp(ple->ccname, cc_name) != 0) { +- free(ple->ccname); +- ple->ccname = strdup(cc_name); +- if (ple->ccname == NULL) { +- printerr(0, "ERROR: no storage to duplicate credentials " +- "cache name '%s'\n", cc_name); +- code = ENOMEM; +- pthread_mutex_unlock(&ple_lock); +- goto out; +- } +- } + pthread_mutex_unlock(&ple_lock); +- if ((code = krb5_cc_resolve(context, cc_name, &ccache))) { +- k5err = gssd_k5_err_msg(context, code); +- printerr(0, "ERROR: %s while opening credential cache '%s'\n", +- k5err, cc_name); +- goto out; +- } +- if ((code = krb5_cc_initialize(context, ccache, ple->princ))) { +- k5err = gssd_k5_err_msg(context, code); +- printerr(0, "ERROR: %s while initializing credential " +- "cache '%s'\n", k5err, cc_name); +- goto out; +- } +- if ((code = krb5_cc_store_cred(context, ccache, &my_creds))) { +- k5err = gssd_k5_err_msg(context, code); +- printerr(0, "ERROR: %s while storing credentials in '%s'\n", +- k5err, cc_name); +- goto out; +- } + + code = 0; +- printerr(2, "%s(0x%lx): principal '%s' ccache:'%s'\n", +- __func__, tid, pname, cc_name); ++ printerr(2, "%s(0x%lx): principal '%s' ccache:'%s'\n", ++ __func__, tid, pname, ple->ccname); + out: +-#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS +- if (init_opts) +- krb5_get_init_creds_opt_free(context, init_opts); +-#endif ++ if (opts) ++ krb5_get_init_creds_opt_free(context, opts); + if (pname) + k5_free_unparsed_name(context, pname); +- if (ccache) +- krb5_cc_close(context, ccache); + krb5_free_cred_contents(context, &my_creds); + free(k5err); + return (code); +@@ -1164,10 +1111,12 @@ gssd_refresh_krb5_machine_credential_internal(char *hostname, + { + krb5_error_code code = 0; + krb5_context context; +- krb5_keytab kt = NULL;; ++ krb5_keytab kt = NULL; ++ krb5_ccache ccache = NULL; + int retval = 0; +- char *k5err = NULL; ++ char *k5err = NULL, *cache_type; + const char *svcnames[] = { "$", "root", "nfs", "host", NULL }; ++ char cc_name[BUFSIZ]; + + /* + * If a specific service name was specified, use it. +@@ -1226,7 +1175,38 @@ gssd_refresh_krb5_machine_credential_internal(char *hostname, + goto out_free_kt; + } + } +- retval = gssd_get_single_krb5_cred(context, kt, ple, force_renew); ++ ++ if (use_memcache) ++ cache_type = "MEMORY"; ++ else ++ cache_type = "FILE"; ++ snprintf(cc_name, sizeof(cc_name), "%s:%s/%s%s_%s", ++ cache_type, ++ ccachesearch[0], GSSD_DEFAULT_CRED_PREFIX, ++ GSSD_DEFAULT_MACHINE_CRED_SUFFIX, ple->realm); ++ ++ pthread_mutex_lock(&ple_lock); ++ if (ple->ccname == NULL || strcmp(ple->ccname, cc_name) != 0) { ++ free(ple->ccname); ++ ple->ccname = strdup(cc_name); ++ if (ple->ccname == NULL) { ++ printerr(0, "ERROR: no storage to duplicate credentials " ++ "cache name '%s'\n", cc_name); ++ code = ENOMEM; ++ pthread_mutex_unlock(&ple_lock); ++ goto out_free_kt; ++ } ++ } ++ pthread_mutex_unlock(&ple_lock); ++ if ((code = krb5_cc_resolve(context, cc_name, &ccache))) { ++ k5err = gssd_k5_err_msg(context, code); ++ printerr(0, "ERROR: %s while opening credential cache '%s'\n", ++ k5err, cc_name); ++ goto out_free_kt; ++ } ++ ++ retval = gssd_get_single_krb5_cred(context, kt, ple, force_renew, ccache); ++ krb5_cc_close(context, ccache); + out_free_kt: + krb5_kt_close(context, kt); + out_free_context: diff --git a/SOURCES/nfs-utils-2.5.4-gssd-man-gssproxy.patch b/SOURCES/nfs-utils-2.5.4-gssd-man-gssproxy.patch new file mode 100644 index 0000000..98b10dd --- /dev/null +++ b/SOURCES/nfs-utils-2.5.4-gssd-man-gssproxy.patch @@ -0,0 +1,41 @@ +commit 7511a77fc7eb7bd3ae38fcf54d49a47c25c3ed50 +Author: Scott Mayhew +Date: Mon Mar 24 08:59:24 2025 -0400 + + gssd.man: add documentation for use-gss-proxy nfs.conf option + + Signed-off-by: Scott Mayhew + Signed-off-by: Steve Dickson + +diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man +index c735eff6..4a75b056 100644 +--- a/utils/gssd/gssd.man ++++ b/utils/gssd/gssd.man +@@ -392,6 +392,17 @@ Setting to + is equivalent to providing the + .B -H + flag. ++.TP ++.B use-gss-proxy ++Setting this to 1 allows ++.BR gssproxy (8) ++to intercept GSSAPI calls and service them on behalf of ++.BR rpc.gssd , ++enabling certain features such as keytab-based client initiation. ++Note that this is unrelated to the functionality that ++.BR gssproxy (8) ++provides on behalf of the NFS server. For more information, see ++.BR https://github.com/gssapi/gssproxy/blob/main/docs/NFS.md#nfs-client . + .P + In addtion, the following value is recognized from the + .B [general] +@@ -405,7 +416,8 @@ Equivalent to + .BR rpc.svcgssd (8), + .BR kerberos (1), + .BR kinit (1), +-.BR krb5.conf (5) ++.BR krb5.conf (5), ++.BR gssproxy (8) + .SH AUTHORS + .br + Dug Song diff --git a/SOURCES/nfs-utils-2.5.4-nfsd-64conns.patch b/SOURCES/nfs-utils-2.5.4-nfsd-64conns.patch new file mode 100644 index 0000000..fd1979a --- /dev/null +++ b/SOURCES/nfs-utils-2.5.4-nfsd-64conns.patch @@ -0,0 +1,34 @@ +commit 0470fd526cb15ace1241f8c60fb98fedef74307b +Author: Trond Myklebust +Date: Fri May 10 09:09:28 2024 -0400 + + nfsd: allow more than 64 backlogged connections + + When creating a listener socket to be handed to /proc/fs/nfsd/portlist, + we currently limit the number of backlogged connections to 64. Since + that value was chosen in 2006, the scale at which data centres operate + has changed significantly. Given a modern server with many thousands of + clients, a limit of 64 connections can create bottlenecks, particularly + at at boot time. + Let's use the POSIX-sanctioned maximum value of SOMAXCONN. + + Reviewed-by: Jeff Layton + Acked-by: Chuck Lever + Tested-by: Chen Hanxiao + Signed-off-by: Trond Myklebust + Signed-off-by: Steve Dickson + +diff --git a/utils/nfsd/nfssvc.c b/utils/nfsd/nfssvc.c +index 46452d97..9650cece 100644 +--- a/utils/nfsd/nfssvc.c ++++ b/utils/nfsd/nfssvc.c +@@ -205,7 +205,8 @@ nfssvc_setfds(const struct addrinfo *hints, const char *node, const char *port) + rc = errno; + goto error; + } +- if (addr->ai_protocol == IPPROTO_TCP && listen(sockfd, 64)) { ++ if (addr->ai_protocol == IPPROTO_TCP && ++ listen(sockfd, SOMAXCONN)) { + xlog(L_ERROR, "unable to create listening socket: " + "errno %d (%m)", errno); + rc = errno; diff --git a/SOURCES/nfs-utils-2.5.4-rdirplus-man.patch b/SOURCES/nfs-utils-2.5.4-rdirplus-man.patch new file mode 100644 index 0000000..792f63e --- /dev/null +++ b/SOURCES/nfs-utils-2.5.4-rdirplus-man.patch @@ -0,0 +1,25 @@ +diff -up nfs-utils-2.5.4/utils/mount/nfs.man.orig nfs-utils-2.5.4/utils/mount/nfs.man +--- nfs-utils-2.5.4/utils/mount/nfs.man.orig 2025-04-14 11:05:21.218916553 -0400 ++++ nfs-utils-2.5.4/utils/mount/nfs.man 2025-04-14 11:06:50.822741625 -0400 +@@ -430,11 +430,16 @@ created network transport, the client wi + list of available transports for that RPC client. + .TP 1.5i + .BR rdirplus " / " nordirplus +-Selects whether to use NFS v3 or v4 READDIRPLUS requests. +-If this option is not specified, the NFS client uses READDIRPLUS requests +-on NFS v3 or v4 mounts to read small directories. +-Some applications perform better if the client uses only READDIR requests +-for all directories. ++Selects whether to use NFS v3 or v4 READDIRPLUS requests. If this option is ++not specified, the NFS client uses a heuristic to optimize performance by ++choosing READDIR vs READDIRPLUS based on how often the calling process uses ++the additional attributes returned from READDIRPLUS. Some applications ++perform better if the client uses only READDIR requests for all directories. ++.TP 1.5i ++.BR rdirplus={none|force} ++If set to "force", the NFS client always attempts to use READDIRPLUS ++requests. If set to "none", the behavior is the same as ++.B nordirplus. + .TP 1.5i + .BI retry= n + The number of minutes that the diff --git a/SPECS/nfs-utils.spec b/SPECS/nfs-utils.spec index 8e2c878..8ca02ea 100644 --- a/SPECS/nfs-utils.spec +++ b/SPECS/nfs-utils.spec @@ -2,7 +2,7 @@ Summary: NFS utilities and supporting clients and daemons for the kernel NFS ser Name: nfs-utils URL: http://linux-nfs.org/ Version: 2.5.4 -Release: 34%{?dist} +Release: 38%{?dist} Epoch: 1 # group all 32bit related archs @@ -73,7 +73,15 @@ Patch029: nfs-utils-2.5.4-mount-writable.patch Patch030: nfs-utils-2.5.4-mount-v3-retry.patch Patch031: nfs-utils-2.5.4-conffile-argument.patch Patch032: nfs-utils-2.5.4-fix-nfsdcld-starting-too-early.patch -Patch033: nfs-utils-2.5.4-nfsiostat-fixes.patch + +# +# RHEL9.7 +# +Patch033: nfs-utils-2.5.4-rdirplus-man.patch +Patch034: nfs-utils-2.5.4-nfsd-64conns.patch +Patch035: nfs-utils-2.5.4-nfsiostat-fixes.patch +Patch036: nfs-utils-2.5.4-gssd-man-gssproxy.patch +Patch037: nfs-utils-2.5.4-gssd-dup-cachecreds.patch Patch100: nfs-utils-1.2.1-statdpath-man.patch Patch101: nfs-utils-1.2.1-exp-subtree-warn-off.patch @@ -330,6 +338,11 @@ fi if [ $1 -eq 0 ]; then %systemd_preun nfs-client.target %systemd_preun nfs-server.service + %systemd_preun auth-rpcgss-module.service + %systemd_preun nfs-blkmap.service + %systemd_preun rpc-gssd.service + %systemd_preun rpc-statd-notify.service + %systemd_preun var-lib-nfs-rpc_pipefs.mount fi %preun -n nfsv4-client-utils @@ -515,6 +528,20 @@ fi %{_mandir}/*/nfsiostat.8.gz %changelog +* Thu Jun 12 2025 Scott Mayhew 2.5.4-38 +- ensure services are stopped when nfs-utils is uninstalled (RHEL-88422) + +* Sat Apr 26 2025 Steve Dickson 2.5.4-37 +- gssd.man: add documentation for use-gss-proxy nfs.conf option (RHEL-85408) +- gssd: do not use krb5_cc_initialize (RHEL-85412) + +* Fri Apr 25 2025 Steve Dickson 2.5.4-36 +- mountstats: verify that old and new types are the same (RHEL-88553) + +* Tue Apr 22 2025 Steve Dickson 2.5.4-35 +- nfs(5): Add new rdirplus functionality, clarify (RHEL-87143) +- nfsd: allow more than 64 backlogged connections (RHEL-87752) + * Sun Feb 16 2025 Steve Dickson 2.5.4-34 - mountstats/nfsiostat: bugfixes for iostat (RHEL-72243)