diff --git a/SOURCES/nfs-utils-2.5.4-blkmapd-double-free.patch b/SOURCES/nfs-utils-2.5.4-blkmapd-double-free.patch new file mode 100644 index 0000000..8dc82cf --- /dev/null +++ b/SOURCES/nfs-utils-2.5.4-blkmapd-double-free.patch @@ -0,0 +1,89 @@ +commit c1c35487aba2cec828d9b8a1be9043000beadea5 +Author: Lixiaokeng +Date: Mon Oct 24 13:00:50 2022 -0400 + + blkmapd: fix coredump in bl_add_disk + + The serial->data is not malloced separately (just part of + the serial), so it can't be freed. The bl_serial has its + own free function. Use it. + + Signed-off-by: Lixiaokeng + Signed-off-by: Zhiqiang Liu + Signed-off-by: Steve Dickson + +diff --git a/utils/blkmapd/device-discovery.c b/utils/blkmapd/device-discovery.c +index 49935c2e..bd890598 100644 +--- a/utils/blkmapd/device-discovery.c ++++ b/utils/blkmapd/device-discovery.c +@@ -187,10 +187,7 @@ static void bl_add_disk(char *filepath) + } + + if (disk && diskpath) { +- if (serial) { +- free(serial->data); +- free(serial); +- } ++ bl_free_scsi_string(serial); + return; + } + +@@ -228,10 +225,7 @@ static void bl_add_disk(char *filepath) + disk->size = size; + disk->valid_path = path; + } +- if (serial) { +- free(serial->data); +- free(serial); +- } ++ bl_free_scsi_string(serial); + } + return; + +@@ -241,10 +235,7 @@ static void bl_add_disk(char *filepath) + free(path->full_path); + free(path); + } +- if (serial) { +- free(serial->data); +- free(serial); +- } ++ bl_free_scsi_string(serial); + return; + } + +diff --git a/utils/blkmapd/device-discovery.h b/utils/blkmapd/device-discovery.h +index a86eed99..462aa943 100644 +--- a/utils/blkmapd/device-discovery.h ++++ b/utils/blkmapd/device-discovery.h +@@ -151,6 +151,8 @@ uint64_t process_deviceinfo(const char *dev_addr_buf, + + extern ssize_t atomicio(ssize_t(*f) (int, void *, size_t), + int fd, void *_s, size_t n); ++extern struct bl_serial *bl_create_scsi_string(int len, const char *bytes); ++extern void bl_free_scsi_string(struct bl_serial *str); + extern struct bl_serial *bldev_read_serial(int fd, const char *filename); + extern enum bl_path_state_e bldev_read_ap_state(int fd); + extern int bl_discover_devices(void); +diff --git a/utils/blkmapd/device-inq.c b/utils/blkmapd/device-inq.c +index c7952c3e..9e5749ef 100644 +--- a/utils/blkmapd/device-inq.c ++++ b/utils/blkmapd/device-inq.c +@@ -53,7 +53,7 @@ + #define DEF_ALLOC_LEN 255 + #define MX_ALLOC_LEN (0xc000 + 0x80) + +-static struct bl_serial *bl_create_scsi_string(int len, const char *bytes) ++struct bl_serial *bl_create_scsi_string(int len, const char *bytes) + { + struct bl_serial *s; + +@@ -66,7 +66,7 @@ static struct bl_serial *bl_create_scsi_string(int len, const char *bytes) + return s; + } + +-static void bl_free_scsi_string(struct bl_serial *str) ++void bl_free_scsi_string(struct bl_serial *str) + { + if (str) + free(str); diff --git a/SOURCES/nfs-utils-2.5.4-fix-typos-in-messages.patch b/SOURCES/nfs-utils-2.5.4-fix-typos-in-messages.patch new file mode 100644 index 0000000..374a165 --- /dev/null +++ b/SOURCES/nfs-utils-2.5.4-fix-typos-in-messages.patch @@ -0,0 +1,199 @@ +diff --git a/support/export/v4root.c b/support/export/v4root.c +index c12a7d85..826cc219 100644 +--- a/support/export/v4root.c ++++ b/support/export/v4root.c +@@ -135,7 +135,7 @@ v4root_support(void) + if (!warned) { + xlog(L_WARNING, "Kernel does not have pseudo root support."); + xlog(L_WARNING, "NFS v4 mounts will be disabled unless fsid=0"); +- xlog(L_WARNING, "is specfied in /etc/exports file."); ++ xlog(L_WARNING, "is specified in /etc/exports file."); + warned++; + } + return 0; +diff --git a/systemd/nfs-blkmap.service b/systemd/nfs-blkmap.service +index 6aa45ba1..57181632 100644 +--- a/systemd/nfs-blkmap.service ++++ b/systemd/nfs-blkmap.service +@@ -1,5 +1,6 @@ + [Unit] + Description=pNFS block layout mapping daemon ++Documentation=man:blkmapd(8) + DefaultDependencies=no + Conflicts=umount.target + After=rpc_pipefs.target +diff --git a/systemd/nfs-idmapd.service b/systemd/nfs-idmapd.service +index f38fe527..bf6f4ded 100644 +--- a/systemd/nfs-idmapd.service ++++ b/systemd/nfs-idmapd.service +@@ -1,5 +1,6 @@ + [Unit] + Description=NFSv4 ID-name mapping service ++Documentation=man:idmapd(8) + DefaultDependencies=no + Requires=rpc_pipefs.target + After=rpc_pipefs.target local-fs.target +diff --git a/systemd/nfs-mountd.service b/systemd/nfs-mountd.service +index e8ece533..4618fab1 100644 +--- a/systemd/nfs-mountd.service ++++ b/systemd/nfs-mountd.service +@@ -1,5 +1,6 @@ + [Unit] + Description=NFS Mount Daemon ++Documentation=man:rpc.mountd(8) + DefaultDependencies=no + Requires=proc-fs-nfsd.mount + Wants=network-online.target +diff --git a/systemd/nfs-server.service b/systemd/nfs-server.service +index 41479169..58bc0917 100644 +--- a/systemd/nfs-server.service ++++ b/systemd/nfs-server.service +@@ -1,5 +1,6 @@ + [Unit] + Description=NFS server and services ++Documentation=man:rpc.nfsd(8) man:exportfs(8) + DefaultDependencies=no + Requires=network.target proc-fs-nfsd.mount + Requires=nfs-mountd.service +diff --git a/systemd/nfsdcld.service b/systemd/nfsdcld.service +index a32d2430..3ced5658 100644 +--- a/systemd/nfsdcld.service ++++ b/systemd/nfsdcld.service +@@ -1,5 +1,6 @@ + [Unit] + Description=NFSv4 Client Tracking Daemon ++Documentation=man:nfsdcld(8) + DefaultDependencies=no + Conflicts=umount.target + Requires=rpc_pipefs.target proc-fs-nfsd.mount +diff --git a/systemd/rpc-gssd.service.in b/systemd/rpc-gssd.service.in +index 6807db35..38382ed3 100644 +--- a/systemd/rpc-gssd.service.in ++++ b/systemd/rpc-gssd.service.in +@@ -1,5 +1,6 @@ + [Unit] + Description=RPC security service for NFS client and server ++Documentation=man:rpc.gssd(8) + DefaultDependencies=no + Conflicts=umount.target + Requires=rpc_pipefs.target +diff --git a/systemd/rpc-statd-notify.service b/systemd/rpc-statd-notify.service +index aad4c0d2..962f18b2 100644 +--- a/systemd/rpc-statd-notify.service ++++ b/systemd/rpc-statd-notify.service +@@ -1,5 +1,6 @@ + [Unit] + Description=Notify NFS peers of a restart ++Documentation=man:sm-notify(8) man:rpc.statd(8) + DefaultDependencies=no + Wants=network-online.target + After=local-fs.target network-online.target nss-lookup.target +diff --git a/systemd/rpc-statd.service b/systemd/rpc-statd.service +index 392750da..660ed861 100644 +--- a/systemd/rpc-statd.service ++++ b/systemd/rpc-statd.service +@@ -1,5 +1,6 @@ + [Unit] + Description=NFS status monitor for NFSv2/3 locking. ++Documentation=man:rpc.statd(8) + DefaultDependencies=no + Conflicts=umount.target + Requires=nss-lookup.target rpcbind.socket +diff --git a/systemd/rpc-svcgssd.service b/systemd/rpc-svcgssd.service +index cb2bcd4f..401fba11 100644 +--- a/systemd/rpc-svcgssd.service ++++ b/systemd/rpc-svcgssd.service +@@ -1,5 +1,6 @@ + [Unit] + Description=RPC security service for NFS server ++Documentation=man:rpc.svcgssd(8) + DefaultDependencies=no + After=local-fs.target + PartOf=nfs-server.service +diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man +index 83dd6807..e5fb10f5 100644 +--- a/utils/exportfs/exports.man ++++ b/utils/exportfs/exports.man +@@ -298,7 +298,7 @@ set. + + The + .I nocrossmnt +-option can explictly disable ++option can explicitly disable + .I crossmnt + if it was previously set. This is rarely useful. + .TP +diff --git a/utils/mount/mount_libmount.c b/utils/mount/mount_libmount.c +index aa4ac5c3..fd6cb2cb 100644 +--- a/utils/mount/mount_libmount.c ++++ b/utils/mount/mount_libmount.c +@@ -442,7 +442,7 @@ int main(int argc, char *argv[]) + mnt_init_debug(0); + cxt = mnt_new_context(); + if (!cxt) { +- nfs_error(_("Can't initilize libmount: %s"), ++ nfs_error(_("Can't initialize libmount: %s"), + strerror(errno)); + rc = EX_FAIL; + goto done; +diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man +index dfc31a5d..fe1ad354 100644 +--- a/utils/mount/nfs.man ++++ b/utils/mount/nfs.man +@@ -967,7 +967,7 @@ Some server features misbehave in the face of a migration-compatible + identification string. + The + .B nomigration +-option retains the use of a traditional client indentification string ++option retains the use of a traditional client identification string + which is compatible with legacy NFS servers. + This is also the behavior if neither option is specified. + A client's open and lock state cannot be migrated transparently +@@ -1810,7 +1810,7 @@ auxiliary services such as the NLM service can choose + any unused port number at random. + .P + Common firewall configurations block the well-known rpcbind port. +-In the absense of an rpcbind service, ++In the absence of an rpcbind service, + the server administrator fixes the port number + of NFS-related services so that the firewall + can allow access to specific NFS service ports. +diff --git a/utils/mount/nfsmount.conf.man b/utils/mount/nfsmount.conf.man +index 73c3e118..7d4a33c9 100644 +--- a/utils/mount/nfsmount.conf.man ++++ b/utils/mount/nfsmount.conf.man +@@ -43,7 +43,7 @@ and will be shifted to lower case before being passed to the filesystem. + .PP + Boolean mount options which do not need an equals sign must be given as + .RI \[dq] option =True". +-Instead of preceeding such an option with ++Instead of preceding such an option with + .RB \[dq] no \[dq] + its negation must be given as + .RI \[dq] option =False". +diff --git a/utils/nfsdcld/nfsdcld.man b/utils/nfsdcld/nfsdcld.man +index 861f1c49..ee6e9dcf 100644 +--- a/utils/nfsdcld/nfsdcld.man ++++ b/utils/nfsdcld/nfsdcld.man +@@ -198,7 +198,7 @@ initialize client tracking in the following order: First, the \fBnfsdcld\fR upc + the \fBnfsdcltrack\fR usermodehelper upcall. Finally, the legacy client tracking. + .PP + This daemon should be run as root, as the pipe that it uses to communicate +-with the kernel is only accessable by root. The daemon however does drop all ++with the kernel is only accessible by root. The daemon however does drop all + superuser capabilities after starting. Because of this, the \fIstoragedir\fR + should be owned by root, and be readable and writable by owner. + .PP +diff --git a/utils/nfsdcltrack/nfsdcltrack.man b/utils/nfsdcltrack/nfsdcltrack.man +index cc24b7a2..3905ba46 100644 +--- a/utils/nfsdcltrack/nfsdcltrack.man ++++ b/utils/nfsdcltrack/nfsdcltrack.man +@@ -80,7 +80,7 @@ section. For example: + .br + storagedir = /shared/nfs/nfsdcltrack + .in -5 +-Debuging to syslog can also be enabled by setting "debug = 1" in this file. ++Debugging to syslog can also be enabled by setting "debug = 1" in this file. + .SH "LEGACY TRANSITION MECHANISM" + .IX Header "LEGACY TRANSITION MECHANISM" + The Linux kernel NFSv4 server has historically tracked this information diff --git a/SOURCES/nfs-utils-2.5.4-gssd-bad-integ-error-support.patch b/SOURCES/nfs-utils-2.5.4-gssd-bad-integ-error-support.patch new file mode 100644 index 0000000..6966ae2 --- /dev/null +++ b/SOURCES/nfs-utils-2.5.4-gssd-bad-integ-error-support.patch @@ -0,0 +1,239 @@ +diff --git a/aclocal/libtirpc.m4 b/aclocal/libtirpc.m4 +index 27368ff2..4379b14d 100644 +--- a/aclocal/libtirpc.m4 ++++ b/aclocal/libtirpc.m4 +@@ -26,6 +26,11 @@ AC_DEFUN([AC_LIBTIRPC], [ + [Define to 1 if your tirpc library provides libtirpc_set_debug])],, + [${LIBS}])]) + ++ AS_IF([test -n "${LIBTIRPC}"], ++ [AC_CHECK_LIB([tirpc], [rpc_gss_seccreate], ++ [AC_DEFINE([HAVE_TIRPC_GSS_SECCREATE], [1], ++ [Define to 1 if your tirpc library provides rpc_gss_seccreate])],, ++ [${LIBS}])]) + AC_SUBST([AM_CPPFLAGS]) + AC_SUBST(LIBTIRPC) + +diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c +index ae568f15..7629de0b 100644 +--- a/utils/gssd/gssd_proc.c ++++ b/utils/gssd/gssd_proc.c +@@ -70,6 +70,9 @@ + #include + #include + #include ++#ifdef HAVE_TIRPC_GSS_SECCREATE ++#include ++#endif + + #include "gssd.h" + #include "err_util.h" +@@ -330,6 +333,11 @@ create_auth_rpc_client(struct clnt_info *clp, + struct timeval timeout; + struct sockaddr *addr = (struct sockaddr *) &clp->addr; + socklen_t salen; ++#ifdef HAVE_TIRPC_GSS_SECCREATE ++ rpc_gss_options_req_t req; ++ rpc_gss_options_ret_t ret; ++ char mechanism[] = "kerberos_v5"; ++#endif + pthread_t tid = pthread_self(); + + sec.qop = GSS_C_QOP_DEFAULT; +@@ -410,15 +418,43 @@ create_auth_rpc_client(struct clnt_info *clp, + + printerr(3, "create_auth_rpc_client(0x%lx): creating context with server %s\n", + tid, tgtname); ++#ifdef HAVE_TIRPC_GSS_SECCREATE ++ memset(&req, 0, sizeof(req)); ++ req.my_cred = sec.cred; ++ auth = rpc_gss_seccreate(rpc_clnt, tgtname, mechanism, ++ rpcsec_gss_svc_none, NULL, &req, &ret); ++#else + auth = authgss_create_default(rpc_clnt, tgtname, &sec); ++#endif + if (!auth) { ++#ifdef HAVE_TIRPC_GSS_SECCREATE ++ if (ret.minor_status == KRB5KRB_AP_ERR_BAD_INTEGRITY) { ++ printerr(2, "WARNING: server=%s failed context " ++ "creation with KRB5_AP_ERR_BAD_INTEGRITY\n", ++ clp->servername); ++ if (cred == GSS_C_NO_CREDENTIAL) ++ retval = gssd_refresh_krb5_machine_credential(clp->servername, ++ "*", NULL, 1); ++ else ++ retval = gssd_k5_remove_bad_service_cred(clp->servername); ++ if (!retval) { ++ auth = rpc_gss_seccreate(rpc_clnt, tgtname, ++ mechanism, rpcsec_gss_svc_none, ++ NULL, &req, &ret); ++ if (auth) ++ goto success; ++ } ++ } ++#endif + /* Our caller should print appropriate message */ + printerr(2, "WARNING: Failed to create krb5 context for " + "user with uid %d for server %s\n", + uid, tgtname); + goto out_fail; + } +- ++#ifdef HAVE_TIRPC_GSS_SECCREATE ++success: ++#endif + /* Success !!! */ + rpc_clnt->cl_auth = auth; + *clnt_return = rpc_clnt; +@@ -571,7 +607,7 @@ krb5_use_machine_creds(struct clnt_info *clp, uid_t uid, + + do { + gssd_refresh_krb5_machine_credential(clp->servername, +- service, srchost); ++ service, srchost, 0); + /* + * Get a list of credential cache names and try each + * of them until one works or we've tried them all +diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c +index e3f270e9..6f66ef4f 100644 +--- a/utils/gssd/krb5_util.c ++++ b/utils/gssd/krb5_util.c +@@ -165,7 +165,7 @@ 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); ++ krb5_keytab kt, struct gssd_k5_kt_princ *ple, int force_renew); + static int query_krb5_ccache(const char* cred_cache, char **ret_princname, + char **ret_realm); + +@@ -391,7 +391,8 @@ gssd_check_if_cc_exists(struct gssd_k5_kt_princ *ple) + static int + gssd_get_single_krb5_cred(krb5_context context, + krb5_keytab kt, +- struct gssd_k5_kt_princ *ple) ++ struct gssd_k5_kt_princ *ple, ++ int force_renew) + { + #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS + krb5_get_init_creds_opt *init_opts = NULL; +@@ -421,7 +422,7 @@ gssd_get_single_krb5_cred(krb5_context context, + */ + now += 300; + pthread_mutex_lock(&ple_lock); +- if (ple->ccname && ple->endtime > now && !nocache) { ++ if (ple->ccname && ple->endtime > now && !nocache && !force_renew) { + printerr(3, "%s(0x%lx): Credentials in CC '%s' are good until %s", + __func__, tid, ple->ccname, ctime((time_t *)&ple->endtime)); + code = 0; +@@ -1155,7 +1156,8 @@ err_cache: + static int + gssd_refresh_krb5_machine_credential_internal(char *hostname, + struct gssd_k5_kt_princ *ple, +- char *service, char *srchost) ++ char *service, char *srchost, ++ int force_renew) + { + krb5_error_code code = 0; + krb5_context context; +@@ -1221,7 +1223,7 @@ gssd_refresh_krb5_machine_credential_internal(char *hostname, + goto out_free_kt; + } + } +- retval = gssd_get_single_krb5_cred(context, kt, ple); ++ retval = gssd_get_single_krb5_cred(context, kt, ple, force_renew); + out_free_kt: + krb5_kt_close(context, kt); + out_free_context: +@@ -1344,7 +1346,7 @@ gssd_get_krb5_machine_cred_list(char ***list) + pthread_mutex_unlock(&ple_lock); + /* Make sure cred is up-to-date before returning it */ + retval = gssd_refresh_krb5_machine_credential_internal(NULL, ple, +- NULL, NULL); ++ NULL, NULL, 0); + pthread_mutex_lock(&ple_lock); + if (gssd_k5_kt_princ_list == NULL) { + /* Looks like we did shutdown... abort */ +@@ -1456,10 +1458,12 @@ gssd_destroy_krb5_principals(int destroy_machine_creds) + */ + int + gssd_refresh_krb5_machine_credential(char *hostname, +- char *service, char *srchost) ++ char *service, char *srchost, ++ int force_renew) + { + return gssd_refresh_krb5_machine_credential_internal(hostname, NULL, +- service, srchost); ++ service, srchost, ++ force_renew); + } + + /* +@@ -1549,6 +1553,48 @@ gssd_acquire_user_cred(gss_cred_id_t *gss_cred) + return ret; + } + ++/* Removed a service ticket for nfs/ from the ticket cache ++ */ ++int ++gssd_k5_remove_bad_service_cred(char *name) ++{ ++ krb5_creds in_creds, out_creds; ++ krb5_error_code ret; ++ krb5_context context; ++ krb5_ccache cache; ++ krb5_principal principal; ++ int retflags = KRB5_TC_MATCH_SRV_NAMEONLY; ++ char srvname[1024]; ++ ++ ret = krb5_init_context(&context); ++ if (ret) ++ goto out_cred; ++ ret = krb5_cc_default(context, &cache); ++ if (ret) ++ goto out_free_context; ++ ret = krb5_cc_get_principal(context, cache, &principal); ++ if (ret) ++ goto out_close_cache; ++ memset(&in_creds, 0, sizeof(in_creds)); ++ in_creds.client = principal; ++ sprintf(srvname, "nfs/%s", name); ++ ret = krb5_parse_name(context, srvname, &in_creds.server); ++ if (ret) ++ goto out_free_principal; ++ ret = krb5_cc_retrieve_cred(context, cache, retflags, &in_creds, &out_creds); ++ if (ret) ++ goto out_free_principal; ++ ret = krb5_cc_remove_cred(context, cache, 0, &out_creds); ++out_free_principal: ++ krb5_free_principal(context, principal); ++out_close_cache: ++ krb5_cc_close(context, cache); ++out_free_context: ++ krb5_free_context(context); ++out_cred: ++ return ret; ++} ++ + #ifdef HAVE_SET_ALLOWABLE_ENCTYPES + /* + * this routine obtains a credentials handle via gss_acquire_cred() +diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h +index 2415205a..7ef87018 100644 +--- a/utils/gssd/krb5_util.h ++++ b/utils/gssd/krb5_util.h +@@ -16,11 +16,13 @@ int gssd_get_krb5_machine_cred_list(char ***list); + void gssd_free_krb5_machine_cred_list(char **list); + void gssd_destroy_krb5_principals(int destroy_machine_creds); + int gssd_refresh_krb5_machine_credential(char *hostname, +- char *service, char *srchost); ++ char *service, char *srchost, ++ int force_renew); + char *gssd_k5_err_msg(krb5_context context, krb5_error_code code); + void gssd_k5_get_default_realm(char **def_realm); + + int gssd_acquire_user_cred(gss_cred_id_t *gss_cred); ++int gssd_k5_remove_bad_service_cred(char *srvname); + + #ifdef HAVE_SET_ALLOWABLE_ENCTYPES + extern int limit_to_legacy_enctypes; diff --git a/SOURCES/nfs-utils-2.5.4-gssd-dns-failure.patch b/SOURCES/nfs-utils-2.5.4-gssd-dns-failure.patch new file mode 100644 index 0000000..c7620bc --- /dev/null +++ b/SOURCES/nfs-utils-2.5.4-gssd-dns-failure.patch @@ -0,0 +1,110 @@ +commit 75b04a9bff709a49f55326b439851822dd630be6 +Author: Olga Kornievskaia +Date: Mon Oct 16 11:45:54 2023 -0400 + + gssd: fix handling DNS lookup failure + + When the kernel does its first ever lookup for a given server ip it + sends down info for server, protocol, etc. On the gssd side as it + scans the pipefs structure and sees a new entry it reads that info + and creates a clp_info structure. At that time it also does + a DNS lookup of the provided ip to name using getnameinfo(), + this is saved in clp->servername for all other upcalls that is + down under that directory. + + If this 1st getnameinfo() results in a failed resolution for + whatever reason (a temporary DNS resolution problem), this cause + of all other future upcalls to fail. + + As a fix, this patch proposed to (1) save the server info that's + passed only in the initial pipefs new entry creation in the + clp_info structure, then (2) for the upcalls, if clp->servername + is NULL, then do the DNS lookup again and set all the needed + clp_info fields upon successful resolution. + + Signed-off-by: Olga Kornievskaia + Signed-off-by: Steve Dickson + +diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c +index 833d8e0..ca9b326 100644 +--- a/utils/gssd/gssd.c ++++ b/utils/gssd/gssd.c +@@ -365,6 +365,12 @@ gssd_read_service_info(int dirfd, struct clnt_info *clp) + + fail: + printerr(0, "ERROR: failed to parse %s/info\n", clp->relpath); ++ clp->upcall_address = strdup(address); ++ clp->upcall_port = strdup(port); ++ clp->upcall_program = program; ++ clp->upcall_vers = version; ++ clp->upcall_protoname = strdup(protoname); ++ clp->upcall_service = strdup(service); + free(servername); + free(protoname); + clp->servicename = NULL; +@@ -408,6 +414,16 @@ gssd_free_client(struct clnt_info *clp) + free(clp->servicename); + free(clp->servername); + free(clp->protocol); ++ if (!clp->servername) { ++ if (clp->upcall_address) ++ free(clp->upcall_address); ++ if (clp->upcall_port) ++ free(clp->upcall_port); ++ if (clp->upcall_protoname) ++ free(clp->upcall_protoname); ++ if (clp->upcall_service) ++ free(clp->upcall_service); ++ } + free(clp); + } + +@@ -446,6 +462,31 @@ gssd_clnt_gssd_cb(int UNUSED(fd), short UNUSED(which), void *data) + { + struct clnt_info *clp = data; + ++ /* if there was a failure to translate IP to name for this server, ++ * try again ++ */ ++ if (!clp->servername) { ++ if (!gssd_addrstr_to_sockaddr((struct sockaddr *)&clp->addr, ++ clp->upcall_address, clp->upcall_port ? ++ clp->upcall_port : "")) { ++ goto do_upcall; ++ } ++ clp->servername = gssd_get_servername(clp->upcall_address, ++ (struct sockaddr *)&clp->addr, clp->upcall_address); ++ if (!clp->servername) ++ goto do_upcall; ++ ++ if (asprintf(&clp->servicename, "%s@%s", clp->upcall_service, ++ clp->servername) < 0) { ++ free(clp->servername); ++ clp->servername = NULL; ++ goto do_upcall; ++ } ++ clp->prog = clp->upcall_program; ++ clp->vers = clp->upcall_vers; ++ clp->protocol = strdup(clp->upcall_protoname); ++ } ++do_upcall: + handle_gssd_upcall(clp); + } + +diff --git a/utils/gssd/gssd.h b/utils/gssd/gssd.h +index 519dc43..4e070ed 100644 +--- a/utils/gssd/gssd.h ++++ b/utils/gssd/gssd.h +@@ -86,6 +86,12 @@ struct clnt_info { + int gssd_fd; + struct event *gssd_ev; + struct sockaddr_storage addr; ++ char *upcall_address; ++ char *upcall_port; ++ int upcall_program; ++ int upcall_vers; ++ char *upcall_protoname; ++ char *upcall_service; + }; + + struct clnt_upcall_info { diff --git a/SOURCES/nfs-utils-2.5.4-mount-mountconf-typo.patch b/SOURCES/nfs-utils-2.5.4-mount-mountconf-typo.patch new file mode 100644 index 0000000..b09d452 --- /dev/null +++ b/SOURCES/nfs-utils-2.5.4-mount-mountconf-typo.patch @@ -0,0 +1,30 @@ +commit 608591ddf1ee59c4dda82ceca3f27c90486c5618 +Author: Yongcheng Yang +Date: Wed Apr 5 12:11:53 2023 -0400 + + nfsmount.conf: Fix typo of the attribute name + + Signed-off-by: Yongcheng Yang + Signed-off-by: Steve Dickson + +diff --git a/utils/mount/nfsmount.conf b/utils/mount/nfsmount.conf +index 342063f..c498eb8 100644 +--- a/utils/mount/nfsmount.conf ++++ b/utils/mount/nfsmount.conf +@@ -59,13 +59,13 @@ + # acregmin=30 + # + # The Maximum time (in seconds) file attributes are cached +-# acregmin=60 ++# acregmax=60 + # + # The minimum time (in seconds) directory attributes are cached +-# acregmin=30 ++# acdirmin=30 + # + # The Maximum time (in seconds) directory attributes are cached +-# acregmin=60 ++# acdirmax=60 + # + # Enable Access Control Lists + # Acl=False diff --git a/SOURCES/nfs-utils-2.5.4-rpcdebug-check-read-return.patch b/SOURCES/nfs-utils-2.5.4-rpcdebug-check-read-return.patch new file mode 100644 index 0000000..556420d --- /dev/null +++ b/SOURCES/nfs-utils-2.5.4-rpcdebug-check-read-return.patch @@ -0,0 +1,24 @@ +commit a746c35822e557766d1871ec976490a71e6962d9 +Author: Zhi Li +Date: Wed Apr 5 12:08:10 2023 -0400 + + rpcdebug: avoid buffer underflow if read() returns 0 + + Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2176740 + + Signed-off-by: Zhi Li + Signed-off-by: Steve Dickson + +diff --git a/tools/rpcdebug/rpcdebug.c b/tools/rpcdebug/rpcdebug.c +index 68206cc5..ec05179e 100644 +--- a/tools/rpcdebug/rpcdebug.c ++++ b/tools/rpcdebug/rpcdebug.c +@@ -257,7 +257,7 @@ get_flags(char *module) + perror(filename); + exit(1); + } +- if ((len = read(sysfd, buffer, sizeof(buffer))) < 0) { ++ if ((len = read(sysfd, buffer, sizeof(buffer))) <= 0) { + perror("read"); + exit(1); + } diff --git a/SOURCES/nfs-utils-2.5.4-support-for-rpc-with-tls.patch b/SOURCES/nfs-utils-2.5.4-support-for-rpc-with-tls.patch new file mode 100644 index 0000000..f2c61b4 --- /dev/null +++ b/SOURCES/nfs-utils-2.5.4-support-for-rpc-with-tls.patch @@ -0,0 +1,427 @@ +diff --git a/support/export/cache.c b/support/export/cache.c +index a5823e92..396b3b73 100644 +--- a/support/export/cache.c ++++ b/support/export/cache.c +@@ -932,6 +932,7 @@ static void write_fsloc(char **bp, int *blen, struct exportent *ep) + release_replicas(servers); + } + #endif ++ + static void write_secinfo(char **bp, int *blen, struct exportent *ep, int flag_mask) + { + struct sec_entry *p; +@@ -949,7 +950,20 @@ static void write_secinfo(char **bp, int *blen, struct exportent *ep, int flag_m + qword_addint(bp, blen, p->flav->fnum); + qword_addint(bp, blen, p->flags & flag_mask); + } ++} ++ ++static void write_xprtsec(char **bp, int *blen, struct exportent *ep) ++{ ++ struct xprtsec_entry *p; ++ ++ for (p = ep->e_xprtsec; p->info; p++); ++ if (p == ep->e_xprtsec) ++ return; + ++ qword_add(bp, blen, "xprtsec"); ++ qword_addint(bp, blen, p - ep->e_xprtsec); ++ for (p = ep->e_xprtsec; p->info; p++) ++ qword_addint(bp, blen, p->info->number); + } + + static int dump_to_cache(int f, char *buf, int blen, char *domain, +@@ -992,6 +1006,7 @@ static int dump_to_cache(int f, char *buf, int blen, char *domain, + qword_add(&bp, &blen, "uuid"); + qword_addhex(&bp, &blen, u, 16); + } ++ write_xprtsec(&bp, &blen, exp); + xlog(D_AUTH, "granted access to %s for %s", + path, *domain == '$' ? domain+1 : domain); + } else { +diff --git a/support/include/nfs/export.h b/support/include/nfs/export.h +index 0eca828e..be5867cf 100644 +--- a/support/include/nfs/export.h ++++ b/support/include/nfs/export.h +@@ -40,4 +40,18 @@ + #define NFSEXP_OLD_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \ + | NFSEXP_ALLSQUASH) + ++/* ++ * Transport layer security policies that are permitted to access ++ * an export ++ */ ++#define NFSEXP_XPRTSEC_NONE 0x0001 ++#define NFSEXP_XPRTSEC_TLS 0x0002 ++#define NFSEXP_XPRTSEC_MTLS 0x0004 ++ ++#define NFSEXP_XPRTSEC_NUM (3) ++ ++#define NFSEXP_XPRTSEC_ALL (NFSEXP_XPRTSEC_NONE | \ ++ NFSEXP_XPRTSEC_TLS | \ ++ NFSEXP_XPRTSEC_MTLS) ++ + #endif /* _NSF_EXPORT_H */ +diff --git a/support/include/nfslib.h b/support/include/nfslib.h +index 6faba71b..61c19933 100644 +--- a/support/include/nfslib.h ++++ b/support/include/nfslib.h +@@ -62,6 +62,18 @@ struct sec_entry { + int flags; + }; + ++#define XPRTSECMODE_COUNT 3 ++ ++struct xprtsec_info { ++ const char *name; ++ int number; ++}; ++ ++struct xprtsec_entry { ++ const struct xprtsec_info *info; ++ int flags; ++}; ++ + /* + * Data related to a single exports entry as returned by getexportent. + * FIXME: export options should probably be parsed at a later time to +@@ -83,6 +95,7 @@ struct exportent { + char * e_fslocdata; + char * e_uuid; + struct sec_entry e_secinfo[SECFLAVOR_COUNT+1]; ++ struct xprtsec_entry e_xprtsec[XPRTSECMODE_COUNT + 1]; + unsigned int e_ttl; + char * e_realpath; + }; +@@ -99,6 +112,7 @@ struct rmtabent { + void setexportent(char *fname, char *type); + struct exportent * getexportent(int,int); + void secinfo_show(FILE *fp, struct exportent *ep); ++void xprtsecinfo_show(FILE *fp, struct exportent *ep); + void putexportent(struct exportent *xep); + void endexportent(void); + struct exportent * mkexportent(char *hname, char *path, char *opts); +diff --git a/support/nfs/exports.c b/support/nfs/exports.c +index ec6f8013..d36f7664 100644 +--- a/support/nfs/exports.c ++++ b/support/nfs/exports.c +@@ -99,6 +99,7 @@ static void init_exportent (struct exportent *ee, int fromkernel) + ee->e_fslocmethod = FSLOC_NONE; + ee->e_fslocdata = NULL; + ee->e_secinfo[0].flav = NULL; ++ ee->e_xprtsec[0].info = NULL; + ee->e_nsquids = 0; + ee->e_nsqgids = 0; + ee->e_uuid = NULL; +@@ -122,7 +123,7 @@ getexportent(int fromkernel, int fromexports) + if (first || (ok = getexport(exp, sizeof(exp))) == 0) { + has_default_opts = 0; + has_default_subtree_opts = 0; +- ++ + init_exportent(&def_ee, fromkernel); + + ok = getpath(def_ee.e_path, sizeof(def_ee.e_path)); +@@ -146,7 +147,7 @@ getexportent(int fromkernel, int fromexports) + if (exp[0] == '-' && !fromkernel) { + if (parseopts(exp + 1, &def_ee, 0, &has_default_subtree_opts) < 0) + return NULL; +- ++ + has_default_opts = 1; + + ok = getexport(exp, sizeof(exp)); +@@ -239,7 +240,6 @@ void secinfo_show(FILE *fp, struct exportent *ep) + if (ep->e_secinfo[0].flav == NULL) + secinfo_addflavor(find_flavor("sys"), ep); + for (p1=ep->e_secinfo; p1->flav; p1=p2) { +- + fprintf(fp, ",sec=%s", p1->flav->flavour); + for (p2=p1+1; (p2->flav != NULL) && (p1->flags == p2->flags); + p2++) { +@@ -249,6 +249,17 @@ void secinfo_show(FILE *fp, struct exportent *ep) + } + } + ++void xprtsecinfo_show(FILE *fp, struct exportent *ep) ++{ ++ struct xprtsec_entry *p1, *p2; ++ ++ for (p1 = ep->e_xprtsec; p1->info; p1 = p2) { ++ fprintf(fp, ",xprtsec=%s", p1->info->name); ++ for (p2 = p1 + 1; p2->info && (p1->flags == p2->flags); p2++) ++ fprintf(fp, ":%s", p2->info->name); ++ } ++} ++ + static void + fprintpath(FILE *fp, const char *path) + { +@@ -345,6 +356,7 @@ putexportent(struct exportent *ep) + } + fprintf(fp, "anonuid=%d,anongid=%d", ep->e_anonuid, ep->e_anongid); + secinfo_show(fp, ep); ++ xprtsecinfo_show(fp, ep); + fprintf(fp, ")\n"); + } + +@@ -483,6 +495,75 @@ static unsigned int parse_flavors(char *str, struct exportent *ep) + return out; + } + ++static const struct xprtsec_info xprtsec_name2info[] = { ++ { "none", NFSEXP_XPRTSEC_NONE }, ++ { "tls", NFSEXP_XPRTSEC_TLS }, ++ { "mtls", NFSEXP_XPRTSEC_MTLS }, ++ { NULL, 0 } ++}; ++ ++static const struct xprtsec_info *find_xprtsec_info(const char *name) ++{ ++ const struct xprtsec_info *info; ++ ++ for (info = xprtsec_name2info; info->name; info++) ++ if (strcmp(info->name, name) == 0) ++ return info; ++ return NULL; ++} ++ ++/* ++ * Append the given xprtsec mode to the exportent's e_xprtsec array, ++ * or do nothing if it's already there. Returns the index of flavor in ++ * the resulting array in any case. ++ */ ++static int xprtsec_addmode(const struct xprtsec_info *info, struct exportent *ep) ++{ ++ struct xprtsec_entry *p; ++ ++ for (p = ep->e_xprtsec; p->info; p++) ++ if (p->info == info || p->info->number == info->number) ++ return p - ep->e_xprtsec; ++ ++ if (p - ep->e_xprtsec >= XPRTSECMODE_COUNT) { ++ xlog(L_ERROR, "more than %d xprtsec modes on an export\n", ++ XPRTSECMODE_COUNT); ++ return -1; ++ } ++ p->info = info; ++ p->flags = ep->e_flags; ++ (p + 1)->info = NULL; ++ return p - ep->e_xprtsec; ++} ++ ++/* ++ * @str is a colon seperated list of transport layer security modes. ++ * Their order is recorded in @ep, and a bitmap corresponding to the ++ * list is returned. ++ * ++ * A zero return indicates an error. ++ */ ++static unsigned int parse_xprtsec(char *str, struct exportent *ep) ++{ ++ unsigned int out = 0; ++ char *name; ++ ++ while ((name = strsep(&str, ":"))) { ++ const struct xprtsec_info *info = find_xprtsec_info(name); ++ int bit; ++ ++ if (!info) { ++ xlog(L_ERROR, "unknown xprtsec mode %s\n", name); ++ return 0; ++ } ++ bit = xprtsec_addmode(info, ep); ++ if (bit < 0) ++ return 0; ++ out |= 1 << bit; ++ } ++ return out; ++} ++ + /* Sets the bits in @mask for the appropriate security flavor flags. */ + static void setflags(int mask, unsigned int active, struct exportent *ep) + { +@@ -621,7 +702,7 @@ parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr) + ep->e_anonuid = strtol(opt+8, &oe, 10); + if (opt[8]=='\0' || *oe != '\0') { + xlog(L_ERROR, "%s: %d: bad anonuid \"%s\"\n", +- flname, flline, opt); ++ flname, flline, opt); + bad_option: + free(opt); + return -1; +@@ -631,7 +712,7 @@ bad_option: + ep->e_anongid = strtol(opt+8, &oe, 10); + if (opt[8]=='\0' || *oe != '\0') { + xlog(L_ERROR, "%s: %d: bad anongid \"%s\"\n", +- flname, flline, opt); ++ flname, flline, opt); + goto bad_option; + } + } else if (strncmp(opt, "squash_uids=", 12) == 0) { +@@ -649,13 +730,13 @@ bad_option: + setflags(NFSEXP_FSID, active, ep); + } else { + ep->e_fsid = strtoul(opt+5, &oe, 0); +- if (opt[5]!='\0' && *oe == '\0') ++ if (opt[5]!='\0' && *oe == '\0') + setflags(NFSEXP_FSID, active, ep); + else if (valid_uuid(opt+5)) + ep->e_uuid = strdup(opt+5); + else { + xlog(L_ERROR, "%s: %d: bad fsid \"%s\"\n", +- flname, flline, opt); ++ flname, flline, opt); + goto bad_option; + } + } +@@ -688,6 +769,9 @@ bad_option: + active = parse_flavors(opt+4, ep); + if (!active) + goto bad_option; ++ } else if (strncmp(opt, "xprtsec=", 8) == 0) { ++ if (!parse_xprtsec(opt + 8, ep)) ++ goto bad_option; + } else { + xlog(L_ERROR, "%s:%d: unknown keyword \"%s\"\n", + flname, flline, opt); +@@ -709,7 +793,7 @@ out: + if (warn && !had_subtree_opt) + xlog(L_WARNING, "%s [%d]: Neither 'subtree_check' or 'no_subtree_check' specified for export \"%s:%s\".\n" + " Assuming default behaviour ('no_subtree_check').\n" +- " NOTE: this default has changed since nfs-utils version 1.0.x\n", ++ " NOTE: this default has changed since nfs-utils version 1.0.x\n", + + flname, flline, + ep->e_hostname, ep->e_path); +diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c +index 6ba615d1..a87a7806 100644 +--- a/utils/exportfs/exportfs.c ++++ b/utils/exportfs/exportfs.c +@@ -743,6 +743,7 @@ dump(int verbose, int export_format) + #endif + } + secinfo_show(stdout, ep); ++ xprtsecinfo_show(stdout, ep); + printf("%c\n", (c != '(')? ')' : ' '); + } + } +diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man +index 54b3f877..83dd6807 100644 +--- a/utils/exportfs/exports.man ++++ b/utils/exportfs/exports.man +@@ -125,7 +125,55 @@ In that case you may include multiple sec= options, and following options + will be enforced only for access using flavors listed in the immediately + preceding sec= option. The only options that are permitted to vary in + this way are ro, rw, no_root_squash, root_squash, and all_squash. ++.SS Transport layer security ++The Linux NFS server allows the use of RPC-with-TLS (RFC 9289) to ++protect RPC traffic between itself and its clients. ++Alternately, administrators can secure NFS traffic using a VPN, ++or an ssh tunnel or similar mechanism, in a way that is transparent ++to the server. + .PP ++To enable the use of RPC-with-TLS, the server's administrator must ++install and configure ++.BR tlshd ++to handle transport layer security handshake requests from the local ++kernel. ++Clients can then choose to use RPC-with-TLS or they may continue ++operating without it. ++.PP ++Administrators may require the use of RPC-with-TLS to protect access ++to individual exports. ++This is particularly useful when using non-cryptographic security ++flavors such as ++.IR sec=sys . ++The ++.I xprtsec= ++option, followed by an unordered colon-delimited list of security policies, ++can restrict access to the export to only clients that have negotiated ++transport-layer security. ++Currently supported transport layer security policies include: ++.TP ++.IR none ++The server permits clients to access the export ++without the use of transport layer security. ++.TP ++.IR tls ++The server permits clients that have negotiated an RPC-with-TLS session ++without peer authentication (confidentiality only) to access the export. ++Clients are not required to offer an x.509 certificate ++when establishing a transport layer security session. ++.TP ++.IR mtls ++The server permits clients that have negotiated an RPC-with-TLS session ++with peer authentication to access the export. ++The server requires clients to offer an x.509 certificate ++when establishing a transport layer security session. ++.PP ++If RPC-with-TLS is configured and enabled and the ++.I xprtsec= ++option is not specified, the default setting for an export is ++.IR xprtsec=none:tls:mtls . ++With this setting, the server permits clients to use any transport ++layer security mechanism or none at all to access the export. + .SS General Options + .BR exportfs + understands the following export options: +@@ -581,7 +629,8 @@ a character class wildcard match. + .BR netgroup (5), + .BR mountd (8), + .BR nfsd (8), +-.BR showmount (8). ++.BR showmount (8), ++.BR tlshd (8). + .\".SH DIAGNOSTICS + .\"An error parsing the file is reported using syslogd(8) as level NOTICE from + .\"a DAEMON whenever +diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man +index d9f34df3..dfc31a5d 100644 +--- a/utils/mount/nfs.man ++++ b/utils/mount/nfs.man +@@ -574,7 +574,43 @@ The + .B sloppy + option is an alternative to specifying + .BR mount.nfs " -s " option. +- ++.TP 1.5i ++.BI xprtsec= policy ++Specifies the use of transport layer security to protect NFS network ++traffic on behalf of this mount point. ++.I policy ++can be one of ++.BR none , ++.BR tls , ++or ++.BR mtls . ++.IP ++If ++.B none ++is specified, ++transport layer security is forced off, even if the NFS server supports ++transport layer security. ++If ++.B tls ++is specified, the client uses RPC-with-TLS to provide in-transit ++confidentiality. ++If ++.B mtls ++is specified, the client uses RPC-with-TLS to authenticate itself and ++to provide in-transit confidentiality. ++If either ++.B tls ++or ++.B mtls ++is specified and the server does not support RPC-with-TLS or peer ++authentication fails, the mount attempt fails. ++.IP ++If the ++.B xprtsec= ++option is not specified, ++the default behavior depends on the kernel version, ++but is usually equivalent to ++.BR "xprtsec=none" . + .SS "Options for NFS versions 2 and 3 only" + Use these options, along with the options in the above subsection, + for NFS versions 2 and 3 only. diff --git a/SPECS/nfs-utils.spec b/SPECS/nfs-utils.spec index 3ff2f37..a9cefb2 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: 20%{?dist} +Release: 25%{?dist} Epoch: 1 # group all 32bit related archs @@ -48,6 +48,17 @@ Patch016: nfs-utils-2.5.4-covscan-return-value.patch Patch017: nfs-utils-2.5.4-juncs-automount.patch Patch018: nfs-utils-2.5.4-man-nfsconf.patch +# +# RHEL9.4 +# +Patch019: nfs-utils-2.5.4-gssd-dns-failure.patch +Patch020: nfs-utils-2.5.4-gssd-bad-integ-error-support.patch +Patch021: nfs-utils-2.5.4-mount-mountconf-typo.patch +Patch022: nfs-utils-2.5.4-support-for-rpc-with-tls.patch +Patch023: nfs-utils-2.5.4-fix-typos-in-messages.patch +Patch024: nfs-utils-2.5.4-blkmapd-double-free.patch +Patch025: nfs-utils-2.5.4-rpcdebug-check-read-return.patch + Patch100: nfs-utils-1.2.1-statdpath-man.patch Patch101: nfs-utils-1.2.1-exp-subtree-warn-off.patch Patch102: nfs-utils-1.2.5-idmap-errmsg.patch @@ -488,6 +499,25 @@ fi %{_mandir}/*/nfsiostat.8.gz %changelog +* Sun Feb 18 2024 Steve Dickson 2.5.4-25 +- Update: Typos and documentation fixes (RHEL-22654) + +* Fri Feb 16 2024 Pavel Reichl - 2.5.4-24 +- Fix gating (RHEL-25837) + +* Tue Feb 6 2024 Steve Dickson 2.5.4-23 +- Typos and documentation fixes (RHEL-22654) +- blkmapd: fix coredump in bl_add_disk (RHEL-7941) +- rpcdebug: avoid buffer underflow (RHEL-7931) + +* Thu Feb 1 2024 Steve Dickson 2.5.4-22 +- nfsmount.conf: Fix typo of the attribute name (RHEL-7904) +- Update to support for the NFS RPC-with-TLS (RHEL-14754) + +* Thu Jan 11 2024 Steve Dickson 2.5.4-21 +- gssd: fix handling DNS lookup failure (RHEL-15035) +- gssd: handle KRB5_AP_ERR_BAD_INTEGRITY errors (RHEL-15034) + * Mon Aug 7 2023 Steve Dickson 2.5.4-20 - Fixed a regression in the junction code (bz 2213669)