From 82aba2541d06e0de580b2178755bf75b710b7573 Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Wed, 4 Feb 2026 11:52:29 -0300 Subject: [PATCH] resolves: RHEL-146310 - Enable debug logs in cifs.upcall Signed-off-by: Paulo Alcantara --- .gitignore | 1 + cifs-utils.spec | 7 +- cifs.upcall-Adjust-log-level.patch | 41 ++ ...call-add-option-to-enable-debug-logs.patch | 68 +++ ...x-parsing-of-commands-and-parameters.patch | 82 ---- docs-Enable-debug-logs.patch | 41 ++ docs-update-echo_interval-description.patch | 34 -- mount-crash-fix.patch | 40 -- sources | 2 +- upcall-fix.patch | 429 ------------------ 10 files changed, 156 insertions(+), 589 deletions(-) create mode 100644 cifs.upcall-Adjust-log-level.patch create mode 100644 cifs.upcall-add-option-to-enable-debug-logs.patch delete mode 100644 cifscreds-fix-parsing-of-commands-and-parameters.patch create mode 100644 docs-Enable-debug-logs.patch delete mode 100644 docs-update-echo_interval-description.patch delete mode 100644 mount-crash-fix.patch delete mode 100644 upcall-fix.patch diff --git a/.gitignore b/.gitignore index c610338..4f7d724 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ cifs-utils-4.6.tar.bz2 /cifs-utils-7.1.tar.bz2 /cifs-utils-7.2.tar.bz2 /cifs-utils-7.4.tar.bz2 +/cifs-utils-7.5.tar.bz2 diff --git a/cifs-utils.spec b/cifs-utils.spec index 9aa8807..ec3c894 100644 --- a/cifs-utils.spec +++ b/cifs-utils.spec @@ -4,7 +4,7 @@ %global bash_completion_dir %(pkg-config --variable=completionsdir bash-completion || echo /etc/bash_completion.d) Name: cifs-utils -Version: 7.4 +Version: 7.5 Release: %autorelease Summary: Utilities for mounting and managing CIFS mounts @@ -24,8 +24,9 @@ Recommends: %{name}-info%{?_isa} = %{version}-%{release} Source0: https://download.samba.org/pub/linux-cifs/cifs-utils/%{name}-%{version}.tar.bz2 -Patch0: cifscreds-fix-parsing-of-commands-and-parameters.patch -Patch1: docs-update-echo_interval-description.patch +Patch0: cifs.upcall-add-option-to-enable-debug-logs.patch +Patch1: docs-Enable-debug-logs.patch +Patch2: cifs.upcall-Adjust-log-level.patch %description The SMB/CIFS protocol is a standard file sharing protocol widely deployed diff --git a/cifs.upcall-Adjust-log-level.patch b/cifs.upcall-Adjust-log-level.patch new file mode 100644 index 0000000..8732668 --- /dev/null +++ b/cifs.upcall-Adjust-log-level.patch @@ -0,0 +1,41 @@ +From 927123ede36fab4a68aea6f6a3495ad909430ed1 Mon Sep 17 00:00:00 2001 +From: Pierguido Lambri +Date: Fri, 30 Jan 2026 14:11:28 +0000 +Subject: [PATCH 3/3] cifs.upcall: Adjust log level + +Because now only error message are logged, let's switch some messages +from DEBUG to ERROR level. +This will help see when an error occurred with cifs.upcall and +eventually turn on the debug mode. + +Signed-off-by: Pierguido Lambri +Reviewed-by: Paulo Alcantara (Red Hat) +--- + cifs.upcall.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/cifs.upcall.c b/cifs.upcall.c +index b57a48c743e4..9d0eecf3aa11 100644 +--- a/cifs.upcall.c ++++ b/cifs.upcall.c +@@ -1618,7 +1618,7 @@ int main(const int argc, char *const argv[]) + __func__); + } else { + if (!get_tgt_time(ccache)) { +- syslog(LOG_DEBUG, "%s: valid TGT is not present in credential cache", ++ syslog(LOG_ERR, "%s: valid TGT is not present in credential cache", + __func__); + krb5_cc_close(context, ccache); + ccache = NULL; +@@ -1721,7 +1721,7 @@ retry_new_hostname: + } + + if (rc) { +- syslog(LOG_DEBUG, "Unable to obtain service ticket"); ++ syslog(LOG_ERR, "Unable to obtain service ticket"); + goto out; + } + +-- +2.52.0 + diff --git a/cifs.upcall-add-option-to-enable-debug-logs.patch b/cifs.upcall-add-option-to-enable-debug-logs.patch new file mode 100644 index 0000000..8b8f7af --- /dev/null +++ b/cifs.upcall-add-option-to-enable-debug-logs.patch @@ -0,0 +1,68 @@ +From 3047b9ccefdcf6327bf060ebf0d40864c5b1a11e Mon Sep 17 00:00:00 2001 +From: Pierguido Lambri +Date: Fri, 30 Jan 2026 14:11:26 +0000 +Subject: [PATCH 1/3] cifs.upcall: add option to enable debug logs + +cifs.upcall uses two levels of logs, DEBUG and ERR. +However, when using systemd, these logs will always be recorded. +When the system does a lot of upcalls, the journal could be filled +with debug logs, which may not be useful at that time. +Added then a new option '-d' to enable debug logs only when needed. +This will set a logmask up to LOG_DEBUG instead of the default +of LOG_ERR, thus reducing the amount of logs when no debug is needed. + +Signed-off-by: Pierguido Lambri +Reviewed-by: Paulo Alcantara (Red Hat) +--- + cifs.upcall.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/cifs.upcall.c b/cifs.upcall.c +index 69e27a34f637..b57a48c743e4 100644 +--- a/cifs.upcall.c ++++ b/cifs.upcall.c +@@ -1356,10 +1356,11 @@ lowercase_string(char *c) + + static void usage(void) + { +- fprintf(stderr, "Usage: %s [ -K /path/to/keytab] [-k /path/to/krb5.conf] [-E] [-t] [-v] [-l] [-e nsecs] key_serial\n", prog); ++ fprintf(stderr, "Usage: %s [ -K /path/to/keytab] [-k /path/to/krb5.conf] [-d] [-E] [-t] [-v] [-l] [-e nsecs] key_serial\n", prog); + } + + static const struct option long_options[] = { ++ {"debug", 0, NULL, 'd'}, + {"no-env-probe", 0, NULL, 'E'}, + {"krb5conf", 1, NULL, 'k'}, + {"legacy-uid", 0, NULL, 'l'}, +@@ -1379,6 +1380,7 @@ int main(const int argc, char *const argv[]) + size_t datalen; + long rc = 1; + int c; ++ int mask; + bool try_dns = false, legacy_uid = false , env_probe = true; + char *buf; + char hostbuf[NI_MAXHOST], *host; +@@ -1395,12 +1397,19 @@ int main(const int argc, char *const argv[]) + hostbuf[0] = '\0'; + + openlog(prog, 0, LOG_DAEMON); ++ mask = LOG_UPTO(LOG_ERR); ++ setlogmask(mask); + +- while ((c = getopt_long(argc, argv, "cEk:K:ltve:", long_options, NULL)) != -1) { ++ while ((c = getopt_long(argc, argv, "cdEk:K:ltve:", long_options, NULL)) != -1) { + switch (c) { + case 'c': + /* legacy option -- skip it */ + break; ++ case 'd': ++ /* enable debug logs */ ++ mask = LOG_UPTO(LOG_DEBUG); ++ setlogmask(mask); ++ break; + case 'E': + /* skip probing initiating process env */ + env_probe = false; +-- +2.52.0 + diff --git a/cifscreds-fix-parsing-of-commands-and-parameters.patch b/cifscreds-fix-parsing-of-commands-and-parameters.patch deleted file mode 100644 index 2f2e9df..0000000 --- a/cifscreds-fix-parsing-of-commands-and-parameters.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 828cb25224cd88b3599d5ca79a7c9435491896db Mon Sep 17 00:00:00 2001 -From: Paulo Alcantara -Date: Tue, 25 Nov 2025 16:30:27 -0300 -Subject: [PATCH 1/2] cifscreds: fix parsing of commands and parameters - -Fix the parsing of '--username' and '--timeout' options as both -require an argument by fixing the value passed in @optstring when -calling getopt_long(3). - -Also fix the matching of commands by breaking the loop when an exact -match is found. Otherwise `cifscreds clear ...` would return -"Ambiguous command" due to "clearall" command. - -* Before patch - -$ ./cifscreds add -u testuser w22-root2.zelda.test -error: Could not resolve address for testuser -$ ./cifscreds add -u testuser -d ZELDA -Password: -$ grep 'cifs:[ad]' /proc/keys -198de7a1 I--Q--- 1 perm 0d0d0000 0 0 logon cifs:d:testuser: 13 - ^^ wrong desc -$ ./cifscreds clear -u testuser w22-root2.zelda.test -Ambiguous command -$ ./cifscreds clear -u testuser -d ZELDA -Ambiguous command - -* After patch - -$ ./cifscreds add -u testuser w22-root2.zelda.test -Password: -$ ./cifscreds add -u testuser -d ZELDA -Password: -$ grep 'cifs:[ad]' /proc/keys -089183a9 I--Q--- 1 perm 0d0d0000 0 0 logon cifs:a:192.168.124.32: 17 -0ca5ed80 I--Q--- 1 perm 0d0d0000 0 0 logon cifs:d:ZELDA: 17 -$ ./cifscreds clear -u testuser w22-root2.zelda.test -$ ./cifscreds clear -u testuser -d ZELDA - -Reported-by: Xiaoli Feng -Reported-by: Jay Shin -Signed-off-by: Paulo Alcantara (Red Hat) -Cc: Steve French -Cc: linux-cifs@vger.kernel.org ---- - cifscreds.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/cifscreds.c b/cifscreds.c -index 295059f9683d..e8713be23d71 100644 ---- a/cifscreds.c -+++ b/cifscreds.c -@@ -71,7 +71,7 @@ static struct command commands[] = { - static struct option longopts[] = { - {"username", 1, NULL, 'u'}, - {"domain", 0, NULL, 'd' }, -- {"timeout", 0, NULL, 't' }, -+ {"timeout", 1, NULL, 't' }, - {NULL, 0, NULL, 0} - }; - -@@ -477,7 +477,7 @@ int main(int argc, char **argv) - if (argc == 1) - return usage(); - -- while((n = getopt_long(argc, argv, "dut:", longopts, NULL)) != -1) { -+ while((n = getopt_long(argc, argv, "du:t:", longopts, NULL)) != -1) { - switch (n) { - case 'd': - arg.keytype = (char) n; -@@ -507,7 +507,7 @@ int main(int argc, char **argv) - if (cmd->name[n] == 0) { - /* exact match */ - best = cmd; -- continue; -+ break; - } - - /* partial match */ --- -2.51.1 - diff --git a/docs-Enable-debug-logs.patch b/docs-Enable-debug-logs.patch new file mode 100644 index 0000000..08c829b --- /dev/null +++ b/docs-Enable-debug-logs.patch @@ -0,0 +1,41 @@ +From 224512b9e62c886fd8d9802bc50a7702c4fe4517 Mon Sep 17 00:00:00 2001 +From: Pierguido Lambri +Date: Fri, 30 Jan 2026 14:11:27 +0000 +Subject: [PATCH 2/3] docs: Enable debug logs + +Documented a new option '-d' to enable debug logs. +By default only error logs are enabled, with this new option +debug logs can be enabled when needed. + +Signed-off-by: Pierguido Lambri +Reviewed-by: Paulo Alcantara (Red Hat) +--- + cifs.upcall.rst.in | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/cifs.upcall.rst.in b/cifs.upcall.rst.in +index 09d0503591d6..895efc53ef50 100644 +--- a/cifs.upcall.rst.in ++++ b/cifs.upcall.rst.in +@@ -11,7 +11,7 @@ Userspace upcall helper for Common Internet File System (CIFS) + SYNOPSIS + ******** + +- cifs.upcall [--trust-dns|-t] [--version|-v] [--legacy-uid|-l] ++ cifs.upcall [--trust-dns|-t] [--version|-v] [--legacy-uid|-l] [--debug|-d] + [--krb5conf=/path/to/krb5.conf|-k /path/to/krb5.conf] + [--keytab=/path/to/keytab|-K /path/to/keytab] [--expire|-e nsecs] {keyid} + +@@ -38,6 +38,9 @@ OPTIONS + -c + This option is deprecated and is currently ignored. + ++--debug|-d ++ Enable debug logs. By default no debug messages are logged, only errors. ++ + --no-env-probe|-E + Normally, ``cifs.upcall`` will probe the environment variable space of + the process that initiated the upcall in order to fetch the value of +-- +2.52.0 + diff --git a/docs-update-echo_interval-description.patch b/docs-update-echo_interval-description.patch deleted file mode 100644 index 790edf4..0000000 --- a/docs-update-echo_interval-description.patch +++ /dev/null @@ -1,34 +0,0 @@ -From b9680e868d4bdf9337e542b08a559e9ca5ea6cc0 Mon Sep 17 00:00:00 2001 -From: Paulo Alcantara -Date: Tue, 25 Nov 2025 17:54:04 -0300 -Subject: [PATCH 2/2] docs: update echo_interval description - -It is '3 * echo_interval' since upstream commit f2caf901c1b7 ("cifs: -Fix a race condition with cifs_echo_request"). - -Reported-by: Alexandros Panagiotou -Signed-off-by: Paulo Alcantara (Red Hat) -Cc: Steve French -Cc: linux-cifs@vger.kernel.org ---- - mount.cifs.rst | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/mount.cifs.rst b/mount.cifs.rst -index d4890706a0fe..4b6d47447c0e 100644 ---- a/mount.cifs.rst -+++ b/mount.cifs.rst -@@ -483,8 +483,8 @@ echo_interval=n - sets the interval at which echo requests are sent to the server on an - idling connection. This setting also affects the time required for a - connection to an unresponsive server to timeout. Here n is the echo -- interval in seconds. The reconnection happens at twice the value of the -- echo_interval set for an unresponsive server. -+ interval in seconds. The reconnection happens at three times the -+ value of the echo_interval set for an unresponsive server. - If this option is not given then the default value of 60 seconds is used. - The minimum tunable value is 1 second and maximum can go up to 600 seconds. - --- -2.51.1 - diff --git a/mount-crash-fix.patch b/mount-crash-fix.patch deleted file mode 100644 index de96d4f..0000000 --- a/mount-crash-fix.patch +++ /dev/null @@ -1,40 +0,0 @@ -diff --git a/mount.cifs.c b/mount.cifs.c -index 7f898bbd215a..84274c98ddf5 100644 ---- a/mount.cifs.c -+++ b/mount.cifs.c -@@ -1996,9 +1996,9 @@ acquire_mountpoint(char **mountpointp) - */ - realuid = getuid(); - if (realuid == 0) { -- dacrc = toggle_dac_capability(0, 1); -- if (dacrc) -- return dacrc; -+ rc = toggle_dac_capability(0, 1); -+ if (rc) -+ goto out; - } else { - oldfsuid = setfsuid(realuid); - oldfsgid = setfsgid(getgid()); -@@ -2019,7 +2019,6 @@ acquire_mountpoint(char **mountpointp) - rc = EX_SYSERR; - } - -- *mountpointp = mountpoint; - restore_privs: - if (realuid == 0) { - dacrc = toggle_dac_capability(0, 0); -@@ -2030,9 +2029,13 @@ restore_privs: - gid_t __attribute__((unused)) gignore = setfsgid(oldfsgid); - } - -- if (rc) -+out: -+ if (rc) { - free(mountpoint); -+ mountpoint = NULL; -+ } - -+ *mountpointp = mountpoint; - return rc; - } - diff --git a/sources b/sources index 1503a0e..a5832e3 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (cifs-utils-7.4.tar.bz2) = 36fb64ed531e983752be243be488392ba52c3797ac638147a75998b8965448009e95d7ccda187c7d50d753b0ddb87a464a83044064b099d49fffe03a0b6ba739 +SHA512 (cifs-utils-7.5.tar.bz2) = d44b26ca3224160bcb4fc712eb6c6d09fcfee196197d46481e95333494eaae1a4851712fba9b922c203e3cd301c481b433ff49ec396428c12ff7db3c628ce9e9 diff --git a/upcall-fix.patch b/upcall-fix.patch deleted file mode 100644 index 6ab2c10..0000000 --- a/upcall-fix.patch +++ /dev/null @@ -1,429 +0,0 @@ -diff --git a/cifs.upcall.c b/cifs.upcall.c -index e4139349fea7..ad0430157958 100644 ---- a/cifs.upcall.c -+++ b/cifs.upcall.c -@@ -52,6 +52,9 @@ - #include - #include - #include -+#include -+#include -+#include - - #include "data_blob.h" - #include "spnego.h" -@@ -787,6 +790,25 @@ handle_krb5_mech(const char *oid, const char *host, DATA_BLOB * secblob, - return retval; - } - -+ -+ -+struct decoded_args { -+ int ver; -+ char hostname[NI_MAXHOST + 1]; -+ char ip[NI_MAXHOST + 1]; -+ -+/* Max user name length. */ -+#define MAX_USERNAME_SIZE 256 -+ char username[MAX_USERNAME_SIZE + 1]; -+ -+ uid_t uid; -+ uid_t creduid; -+ pid_t pid; -+ sectype_t sec; -+ -+/* -+ * Flags to keep track of what was provided -+ */ - #define DKD_HAVE_HOSTNAME 0x1 - #define DKD_HAVE_VERSION 0x2 - #define DKD_HAVE_SEC 0x4 -@@ -796,23 +818,13 @@ handle_krb5_mech(const char *oid, const char *host, DATA_BLOB * secblob, - #define DKD_HAVE_CREDUID 0x40 - #define DKD_HAVE_USERNAME 0x80 - #define DKD_MUSTHAVE_SET (DKD_HAVE_HOSTNAME|DKD_HAVE_VERSION|DKD_HAVE_SEC) -- --struct decoded_args { -- int ver; -- char *hostname; -- char *ip; -- char *username; -- uid_t uid; -- uid_t creduid; -- pid_t pid; -- sectype_t sec; -+ int have; - }; - - static unsigned int --decode_key_description(const char *desc, struct decoded_args *arg) -+__decode_key_description(const char *desc, struct decoded_args *arg) - { -- int len; -- int retval = 0; -+ size_t len; - char *pos; - const char *tkn = desc; - -@@ -826,13 +838,13 @@ decode_key_description(const char *desc, struct decoded_args *arg) - len = pos - tkn; - - len -= 5; -- free(arg->hostname); -- arg->hostname = strndup(tkn + 5, len); -- if (arg->hostname == NULL) { -- syslog(LOG_ERR, "Unable to allocate memory"); -+ if (len > sizeof(arg->hostname)-1) { -+ syslog(LOG_ERR, "host= value too long for buffer"); - return 1; - } -- retval |= DKD_HAVE_HOSTNAME; -+ memset(arg->hostname, 0, sizeof(arg->hostname)); -+ strncpy(arg->hostname, tkn + 5, len); -+ arg->have |= DKD_HAVE_HOSTNAME; - syslog(LOG_DEBUG, "host=%s", arg->hostname); - } else if (!strncmp(tkn, "ip4=", 4) || !strncmp(tkn, "ip6=", 4)) { - if (pos == NULL) -@@ -841,13 +853,13 @@ decode_key_description(const char *desc, struct decoded_args *arg) - len = pos - tkn; - - len -= 4; -- free(arg->ip); -- arg->ip = strndup(tkn + 4, len); -- if (arg->ip == NULL) { -- syslog(LOG_ERR, "Unable to allocate memory"); -+ if (len > sizeof(arg->ip)-1) { -+ syslog(LOG_ERR, "ip[46]= value too long for buffer"); - return 1; - } -- retval |= DKD_HAVE_IP; -+ memset(arg->ip, 0, sizeof(arg->ip)); -+ strncpy(arg->ip, tkn + 4, len); -+ arg->have |= DKD_HAVE_IP; - syslog(LOG_DEBUG, "ip=%s", arg->ip); - } else if (strncmp(tkn, "user=", 5) == 0) { - if (pos == NULL) -@@ -856,13 +868,13 @@ decode_key_description(const char *desc, struct decoded_args *arg) - len = pos - tkn; - - len -= 5; -- free(arg->username); -- arg->username = strndup(tkn + 5, len); -- if (arg->username == NULL) { -- syslog(LOG_ERR, "Unable to allocate memory"); -+ if (len > sizeof(arg->username)-1) { -+ syslog(LOG_ERR, "user= value too long for buffer"); - return 1; - } -- retval |= DKD_HAVE_USERNAME; -+ memset(arg->username, 0, sizeof(arg->username)); -+ strncpy(arg->username, tkn + 5, len); -+ arg->have |= DKD_HAVE_USERNAME; - syslog(LOG_DEBUG, "user=%s", arg->username); - } else if (strncmp(tkn, "pid=", 4) == 0) { - errno = 0; -@@ -873,13 +885,13 @@ decode_key_description(const char *desc, struct decoded_args *arg) - return 1; - } - syslog(LOG_DEBUG, "pid=%u", arg->pid); -- retval |= DKD_HAVE_PID; -+ arg->have |= DKD_HAVE_PID; - } else if (strncmp(tkn, "sec=", 4) == 0) { - if (strncmp(tkn + 4, "krb5", 4) == 0) { -- retval |= DKD_HAVE_SEC; -+ arg->have |= DKD_HAVE_SEC; - arg->sec = KRB5; - } else if (strncmp(tkn + 4, "mskrb5", 6) == 0) { -- retval |= DKD_HAVE_SEC; -+ arg->have |= DKD_HAVE_SEC; - arg->sec = MS_KRB5; - } - syslog(LOG_DEBUG, "sec=%d", arg->sec); -@@ -891,7 +903,7 @@ decode_key_description(const char *desc, struct decoded_args *arg) - strerror(errno)); - return 1; - } -- retval |= DKD_HAVE_UID; -+ arg->have |= DKD_HAVE_UID; - syslog(LOG_DEBUG, "uid=%u", arg->uid); - } else if (strncmp(tkn, "creduid=", 8) == 0) { - errno = 0; -@@ -901,7 +913,7 @@ decode_key_description(const char *desc, struct decoded_args *arg) - strerror(errno)); - return 1; - } -- retval |= DKD_HAVE_CREDUID; -+ arg->have |= DKD_HAVE_CREDUID; - syslog(LOG_DEBUG, "creduid=%u", arg->creduid); - } else if (strncmp(tkn, "ver=", 4) == 0) { /* if version */ - errno = 0; -@@ -911,14 +923,56 @@ decode_key_description(const char *desc, struct decoded_args *arg) - strerror(errno)); - return 1; - } -- retval |= DKD_HAVE_VERSION; -+ arg->have |= DKD_HAVE_VERSION; - syslog(LOG_DEBUG, "ver=%d", arg->ver); - } - if (pos == NULL) - break; - tkn = pos + 1; - } while (tkn); -- return retval; -+ return 0; -+} -+ -+static unsigned int -+decode_key_description(const char *desc, struct decoded_args **arg) -+{ -+ pid_t pid; -+ pid_t rc; -+ int status; -+ -+ /* -+ * Do all the decoding/string processing in a child process -+ * with low privileges. -+ */ -+ -+ *arg = mmap(NULL, sizeof(struct decoded_args), PROT_READ | PROT_WRITE, -+ MAP_ANONYMOUS | MAP_SHARED, -1, 0); -+ if (*arg == MAP_FAILED) { -+ syslog(LOG_ERR, "%s: mmap failed: %s", __func__, strerror(errno)); -+ return -1; -+ } -+ -+ pid = fork(); -+ if (pid < 0) { -+ syslog(LOG_ERR, "%s: fork failed: %s", __func__, strerror(errno)); -+ munmap(*arg, sizeof(struct decoded_args)); -+ *arg = NULL; -+ return -1; -+ } -+ if (pid == 0) { -+ /* do the parsing in child */ -+ drop_all_capabilities(); -+ exit(__decode_key_description(desc, *arg)); -+ } -+ -+ rc = waitpid(pid, &status, 0); -+ if (rc < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) { -+ munmap(*arg, sizeof(struct decoded_args)); -+ *arg = NULL; -+ return 1; -+ } -+ -+ return 0; - } - - static int setup_key(const key_serial_t key, const void *data, size_t datalen) -@@ -1098,7 +1152,7 @@ int main(const int argc, char *const argv[]) - bool try_dns = false, legacy_uid = false , env_probe = true; - char *buf; - char hostbuf[NI_MAXHOST], *host; -- struct decoded_args arg; -+ struct decoded_args *arg = NULL; - const char *oid; - uid_t uid; - char *keytab_name = NULL; -@@ -1109,7 +1163,6 @@ int main(const int argc, char *const argv[]) - const char *key_descr = NULL; - - hostbuf[0] = '\0'; -- memset(&arg, 0, sizeof(arg)); - - openlog(prog, 0, LOG_DAEMON); - -@@ -1150,9 +1203,6 @@ int main(const int argc, char *const argv[]) - } - } - -- if (trim_capabilities(env_probe)) -- goto out; -- - /* is there a key? */ - if (argc <= optind) { - usage(); -@@ -1178,6 +1228,10 @@ int main(const int argc, char *const argv[]) - - syslog(LOG_DEBUG, "key description: %s", buf); - -+ /* -+ * If we are requested a simple DNS query, do it and exit -+ */ -+ - if (strncmp(buf, "cifs.resolver", sizeof("cifs.resolver") - 1) == 0) - key_descr = ".cifs.resolver"; - else if (strncmp(buf, "dns_resolver", sizeof("dns_resolver") - 1) == 0) -@@ -1187,33 +1241,42 @@ int main(const int argc, char *const argv[]) - goto out; - } - -- have = decode_key_description(buf, &arg); -+ /* -+ * Otherwise, it's a spnego key request -+ */ -+ -+ rc = decode_key_description(buf, &arg); - free(buf); -- if ((have & DKD_MUSTHAVE_SET) != DKD_MUSTHAVE_SET) { -+ if (rc) { -+ syslog(LOG_ERR, "failed to decode key description"); -+ goto out; -+ } -+ -+ if ((arg->have & DKD_MUSTHAVE_SET) != DKD_MUSTHAVE_SET) { - syslog(LOG_ERR, "unable to get necessary params from key " - "description (0x%x)", have); - rc = 1; - goto out; - } - -- if (arg.ver > CIFS_SPNEGO_UPCALL_VERSION) { -+ if (arg->ver > CIFS_SPNEGO_UPCALL_VERSION) { - syslog(LOG_ERR, "incompatible kernel upcall version: 0x%x", -- arg.ver); -+ arg->ver); - rc = 1; - goto out; - } - -- if (strlen(arg.hostname) >= NI_MAXHOST) { -+ if (strlen(arg->hostname) >= NI_MAXHOST) { - syslog(LOG_ERR, "hostname provided by kernel is too long"); - rc = 1; - goto out; - - } - -- if (!legacy_uid && (have & DKD_HAVE_CREDUID)) -- uid = arg.creduid; -- else if (have & DKD_HAVE_UID) -- uid = arg.uid; -+ if (!legacy_uid && (arg->have & DKD_HAVE_CREDUID)) -+ uid = arg->creduid; -+ else if (arg->have & DKD_HAVE_UID) -+ uid = arg->uid; - else { - /* no uid= or creduid= parm -- something is wrong */ - syslog(LOG_ERR, "No uid= or creduid= parm specified"); -@@ -1221,6 +1284,21 @@ int main(const int argc, char *const argv[]) - goto out; - } - -+ /* -+ * Change to the process's namespace. This means that things will work -+ * acceptably in containers, because we'll be looking at the correct -+ * filesystem and have the correct network configuration. -+ */ -+ rc = switch_to_process_ns(arg->pid); -+ if (rc == -1) { -+ syslog(LOG_ERR, "unable to switch to process namespace: %s", strerror(errno)); -+ rc = 1; -+ goto out; -+ } -+ -+ if (trim_capabilities(env_probe)) -+ goto out; -+ - /* - * The kernel doesn't pass down the gid, so we resort here to scraping - * one out of the passwd nss db. Note that this might not reflect the -@@ -1266,20 +1344,7 @@ int main(const int argc, char *const argv[]) - * look at the environ file. - */ - env_cachename = -- get_cachename_from_process_env(env_probe ? arg.pid : 0); -- -- /* -- * Change to the process's namespace. This means that things will work -- * acceptably in containers, because we'll be looking at the correct -- * filesystem and have the correct network configuration. -- */ -- rc = switch_to_process_ns(arg.pid); -- if (rc == -1) { -- syslog(LOG_ERR, "unable to switch to process namespace: %s", -- strerror(errno)); -- rc = 1; -- goto out; -- } -+ get_cachename_from_process_env(env_probe ? arg->pid : 0); - - rc = setuid(uid); - if (rc == -1) { -@@ -1301,18 +1366,18 @@ int main(const int argc, char *const argv[]) - - ccache = get_existing_cc(env_cachename); - /* Couldn't find credcache? Try to use keytab */ -- if (ccache == NULL && arg.username != NULL) -- ccache = init_cc_from_keytab(keytab_name, arg.username); -+ if (ccache == NULL && arg->username[0] != '\0') -+ ccache = init_cc_from_keytab(keytab_name, arg->username); - - if (ccache == NULL) { - rc = 1; - goto out; - } - -- host = arg.hostname; -+ host = arg->hostname; - - // do mech specific authorization -- switch (arg.sec) { -+ switch (arg->sec) { - case MS_KRB5: - case KRB5: - /* -@@ -1328,7 +1393,7 @@ int main(const int argc, char *const argv[]) - * TRY only: - * cifs/bar.example.com@REALM - */ -- if (arg.sec == MS_KRB5) -+ if (arg->sec == MS_KRB5) - oid = OID_KERBEROS5_OLD; - else - oid = OID_KERBEROS5; -@@ -1385,10 +1450,10 @@ retry_new_hostname: - break; - } - -- if (!try_dns || !(have & DKD_HAVE_IP)) -+ if (!try_dns || !(arg->have & DKD_HAVE_IP)) - break; - -- rc = ip_to_fqdn(arg.ip, hostbuf, sizeof(hostbuf)); -+ rc = ip_to_fqdn(arg->ip, hostbuf, sizeof(hostbuf)); - if (rc) - break; - -@@ -1396,7 +1461,7 @@ retry_new_hostname: - host = hostbuf; - goto retry_new_hostname; - default: -- syslog(LOG_ERR, "sectype: %d is not implemented", arg.sec); -+ syslog(LOG_ERR, "sectype: %d is not implemented", arg->sec); - rc = 1; - break; - } -@@ -1414,7 +1479,7 @@ retry_new_hostname: - rc = 1; - goto out; - } -- keydata->version = arg.ver; -+ keydata->version = arg->ver; - keydata->flags = 0; - keydata->sesskey_len = sess_key.length; - keydata->secblob_len = secblob.length; -@@ -1440,11 +1505,10 @@ out: - krb5_cc_close(context, ccache); - if (context) - krb5_free_context(context); -- free(arg.hostname); -- free(arg.ip); -- free(arg.username); - free(keydata); - free(env_cachename); -+ if (arg) -+ munmap(arg, sizeof(*arg)); - syslog(LOG_DEBUG, "Exit status %ld", rc); - return rc; - }