The Samba-Bugzilla – Attachment 18925 Details for
Bug 16033
CVE-2026-4480 [SECURITY] Unauthenticated Remote Code Execution
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
patch that prevents splitting of job names into many arguments
bug-16033.patch (text/plain), 8.06 KB, created by
Douglas Bagnall
on 2026-03-26 01:57:05 UTC
(
hide
)
Description:
patch that prevents splitting of job names into many arguments
Filename:
MIME Type:
Creator:
Douglas Bagnall
Created:
2026-03-26 01:57:05 UTC
Size:
8.06 KB
patch
obsolete
>From 47952b62a3582b248932e5ccaf67c8d54d48f529 Mon Sep 17 00:00:00 2001 >From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz> >Date: Thu, 26 Mar 2026 14:01:03 +1300 >Subject: [PATCH 1/2] CVE-2026-4480: Add a function to escape a single shell > word > >The existing escape_shell_string() function tries to escape an entire >command, making it safe from embedded redirection and control >operators. It does not escape spaces and tabs though, so the number of >string words may not be as expected. For example, > > printf("ls %s", escape_shell_string("a b c"))) > >will result in "ls a b c". > >This function uses strict quoting so all characters are treated as a >single word. Thus > > printf("ls %s", escape_shell_word(mem_ctx, "a b c"))) > >will result in "ls 'a b c'", which runs ls with a single argument. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=16033 > >Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz> >--- > selftest/tests.py | 2 + > source3/include/proto.h | 1 + > source3/lib/test_util_str.c | 80 +++++++++++++++++++++++++++++++++++++ > source3/lib/util_str.c | 43 ++++++++++++++++++++ > source3/wscript_build | 5 +++ > 5 files changed, 131 insertions(+) > create mode 100644 source3/lib/test_util_str.c > >diff --git a/selftest/tests.py b/selftest/tests.py >index 7eace3cbced..c6919661791 100644 >--- a/selftest/tests.py >+++ b/selftest/tests.py >@@ -596,6 +596,8 @@ if ("HAVE_TCP_USER_TIMEOUT" in config_hash): > environ={'SOCKET_WRAPPER_DIR': ''}) > plantestsuite("samba.unittests.adouble", "none", > [os.path.join(bindir(), "test_adouble")]) >+plantestsuite("samba.unittests.s3_util_str", "none", >+ [os.path.join(bindir(), "test_util_str")]) > plantestsuite("samba.unittests.gnutls_aead_aes_256_cbc_hmac_sha512", "none", > [os.path.join(bindir(), "test_gnutls_aead_aes_256_cbc_hmac_sha512")]) > plantestsuite("samba.unittests.gnutls_sp800_108", "none", >diff --git a/source3/include/proto.h b/source3/include/proto.h >index ca659235697..567c91a26d9 100644 >--- a/source3/include/proto.h >+++ b/source3/include/proto.h >@@ -549,6 +549,7 @@ bool validate_net_name( const char *name, > const char *invalid_chars, > int max_len); > char *escape_shell_string(const char *src); >+char *escape_shell_word(TALLOC_CTX *mem_ctx, const char *src); > ssize_t full_path_tos(const char *dir, const char *name, > char *tmpbuf, size_t tmpbuf_len, > char **pdst, char **to_free); >diff --git a/source3/lib/test_util_str.c b/source3/lib/test_util_str.c >new file mode 100644 >index 00000000000..116fdc023b1 >--- /dev/null >+++ b/source3/lib/test_util_str.c >@@ -0,0 +1,80 @@ >+/* >+ * Unix SMB/CIFS implementation. >+ * >+ * Copyright (C) 2018 Andreas Schneider <asn@samba.org> >+ * Copyright (C) 2024 Douglas Bagnall <dbagnall@samba.org> >+ * >+ * This program is free software; you can redistribute it and/or modify >+ * it under the terms of the GNU General Public License as published by >+ * the Free Software Foundation; either version 3 of the License, or >+ * (at your option) any later version. >+ * >+ * This program is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ * GNU General Public License for more details. >+ * >+ * You should have received a copy of the GNU General Public License >+ * along with this program. If not, see <http://www.gnu.org/licenses/>. >+ */ >+ >+#include "util_str.c" >+#include <cmocka.h> >+ >+#define debug_message(...) do { \ >+ if (isatty(1)) { \ >+ print_message(__VA_ARGS__); \ >+ } \ >+ } while(0) >+ >+ >+static void test_escape_shell_word(void **state) >+{ >+ TALLOC_CTX *tmp_ctx = talloc_new(NULL); >+ size_t i; >+ struct { >+ const char *before; >+ const char *after; >+ } cases[] = { >+ { >+ "hello", >+ "'hello'" >+ }, >+ { >+ "trailing space ", >+ "'trailing space '" >+ }, >+ { >+ "quote\"quote'quote'''", >+ "'quote\"quote'\\''quote'\\'''\\'''\\'''" >+ }, >+ { >+ "", >+ "''" >+ }, >+ { >+ ">|& '' && \n $foo", >+ "'>|& '\\'''\\'' && \n $foo'", >+ }, >+ }; >+ >+ for (i = 0; i < ARRAY_SIZE(cases); i++) { >+ const char *result = escape_shell_word(tmp_ctx, cases[i].before); >+ size_t len = strlen(result); >+ debug_message("expecting «%s» -> «%s», got «%s»\n", >+ cases[i].before, cases[i].after, result); >+ assert_int_equal(len, strlen(cases[i].after)); >+ assert_memory_equal(result, cases[i].after, strlen(cases[i].after)); >+ } >+} >+ >+ >+int main(void) { >+ const struct CMUnitTest tests[] = { >+ cmocka_unit_test(test_escape_shell_word), >+ }; >+ if (!isatty(1)) { >+ cmocka_set_message_output(CM_OUTPUT_SUBUNIT); >+ } >+ return cmocka_run_group_tests(tests, NULL, NULL); >+} >diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c >index 68be9a0ec09..ecb770b0171 100644 >--- a/source3/lib/util_str.c >+++ b/source3/lib/util_str.c >@@ -660,6 +660,49 @@ char *escape_shell_string(const char *src) > return ret; > } > >+/* >+ * Convert a string into a form that will cause it to be treated as a >+ * single word in shell. We encase everything in single quotes, except >+ * for single quotes themselves. >+ * >+ * For example, >+ * "won't split on spaces" becomes "'won'\''t split on spaces'". >+ */ >+ >+char *escape_shell_word(TALLOC_CTX *mem_ctx, const char *src) >+{ >+ size_t srclen = strlen(src); >+ char *dest_start = talloc_array(mem_ctx, char, (srclen * 4) + 3); >+ char *dest = dest_start; >+ if (dest_start == NULL) { >+ return NULL; >+ } >+ >+ *dest++ = '\''; >+ >+ while (*src) { >+ /* >+ * If it isn't a single quote, we can copy it. >+ */ >+ if (*src != '\'') { >+ *dest++ = *src++; >+ continue; >+ } >+ /* >+ * We need to jump out of single-quote mode, add the >+ * quote, and jump back in. >+ */ >+ *dest++ = '\''; >+ *dest++ = '\\'; >+ *dest++ = *src++; >+ *dest++ = '\''; >+ } >+ *dest++ = '\''; >+ *dest++ = '\0'; >+ return dest_start; >+} >+ >+ > /* > * This routine improves performance for operations temporarily acting on a > * full path. It is equivalent to the much more expensive >diff --git a/source3/wscript_build b/source3/wscript_build >index e4a595dd180..ee2af36ee99 100644 >--- a/source3/wscript_build >+++ b/source3/wscript_build >@@ -1121,6 +1121,11 @@ bld.SAMBA3_BINARY('test_adouble', > deps='smbd_base STRING_REPLACE cmocka', > for_selftest=True) > >+bld.SAMBA3_BINARY('test_util_str', >+ source='lib/test_util_str.c', >+ deps='smbd_base STRING_REPLACE cmocka', >+ for_selftest=True) >+ > bld.SAMBA3_SUBSYSTEM('STRING_REPLACE', > source='lib/string_replace.c') > >-- >2.43.0 > > >From b11ea60560d7c2f08d5954112fe34a1bfa1948b7 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Sun, 15 Mar 2026 19:15:14 +0100 >Subject: [PATCH 2/2] printing: Shell-sanitize jobname passed as %J to "print > command" > >Fix an unauthenticated remote code execution vulnerability with >printing set to anything *but* cups and iprint, for example "lprng", >so that "print command" is executed upon job submission. If the >client-controlled job name is handed to the "print command" via "%J", >rpcd_spoolssd passes this to the shell without escaping critical >characters. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=16033 > >Signed-off-by: Volker Lendecke <vl@samba.org> >Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz> >--- > source3/printing/print_generic.c | 14 +++++++++----- > 1 file changed, 9 insertions(+), 5 deletions(-) > >diff --git a/source3/printing/print_generic.c b/source3/printing/print_generic.c >index 855de4ca1f3..380ef0536bc 100644 >--- a/source3/printing/print_generic.c >+++ b/source3/printing/print_generic.c >@@ -254,13 +254,17 @@ static int generic_job_submit(int snum, struct printjob *pjob, > if (chdir(print_directory) != 0) { > return -1; > } >+ { >+ char *tmpname = talloc_string_sub(ctx, pjob->jobname, "'", "_"); >+ if (tmpname == NULL) { >+ ret = -1; >+ goto out; >+ } >+ jobname = escape_shell_word(ctx, tmpname); > >- jobname = talloc_strdup(ctx, pjob->jobname); >- if (!jobname) { >- ret = -1; >- goto out; >+ TALLOC_FREE(tmpname); > } >- jobname = talloc_string_sub(ctx, jobname, "'", "_"); >+ > if (!jobname) { > ret = -1; > goto out; >-- >2.43.0 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
metze
:
review-
Actions:
View
Attachments on
bug 16033
:
18903
|
18905
|
18915
|
18916
|
18917
|
18918
|
18919
|
18925
|
18962
|
18968
|
18969
|
18972
|
18973
|
18974
|
18975