diff options
author | Peter Marko <peter.marko@siemens.com> | 2025-08-15 22:27:47 +0200 |
---|---|---|
committer | Steve Sakoman <steve@sakoman.com> | 2025-08-22 05:59:54 -0700 |
commit | 40999c1bbd2634cca2f28d60993e1bc765774068 (patch) | |
tree | 4fd0e2694ef0e1004dad7ba1c0134b142868b21c | |
parent | 00ade479effbcd0a8574669252686bccd91a8f14 (diff) | |
download | poky-40999c1bbd2634cca2f28d60993e1bc765774068.tar.gz |
dropbear: patch CVE-2025-47203
Based on Debian patch for this CVE, pick the same commits as mentioned
in kirkstone for this CVE except those already included in 2022.83.
https://salsa.debian.org/debian/dropbear/-/commit/7f48e75892c40cfc6336137d62581d2c4ca7d84c
(From OE-Core rev: 6d287785611c344aa0c97048c3bfc280b1787ff5)
Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
6 files changed, 572 insertions, 0 deletions
diff --git a/meta/recipes-core/dropbear/dropbear/0001-Avoid-unused-variable-with-DROPBEAR_CLI_PUBKEY_AUTH-.patch b/meta/recipes-core/dropbear/dropbear/0001-Avoid-unused-variable-with-DROPBEAR_CLI_PUBKEY_AUTH-.patch new file mode 100644 index 0000000000..fbe200151e --- /dev/null +++ b/meta/recipes-core/dropbear/dropbear/0001-Avoid-unused-variable-with-DROPBEAR_CLI_PUBKEY_AUTH-.patch | |||
@@ -0,0 +1,27 @@ | |||
1 | From d59436a4d56de58b856142a5d489a4a8fc7382ed Mon Sep 17 00:00:00 2001 | ||
2 | From: Matt Johnston <matt@ucc.asn.au> | ||
3 | Date: Mon, 8 Apr 2024 22:01:21 +0800 | ||
4 | Subject: [PATCH] Avoid unused variable with DROPBEAR_CLI_PUBKEY_AUTH 0 | ||
5 | |||
6 | Fixes PR #291 | ||
7 | |||
8 | Upstream-Status: Backport [https://github.com/mkj/dropbear/commit/d59436a4d56de58b856142a5d489a4a8fc7382ed] | ||
9 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
10 | --- | ||
11 | cli-runopts.c | 2 ++ | ||
12 | 1 file changed, 2 insertions(+) | ||
13 | |||
14 | diff --git a/cli-runopts.c b/cli-runopts.c | ||
15 | index b853a13..6668aee 100644 | ||
16 | --- a/cli-runopts.c | ||
17 | +++ b/cli-runopts.c | ||
18 | @@ -533,7 +533,9 @@ static void loadidentityfile(const char* filename, int warnfail) { | ||
19 | static char* multihop_passthrough_args(void) { | ||
20 | char *args = NULL; | ||
21 | unsigned int len, total; | ||
22 | +#if DROPBEAR_CLI_PUBKEY_AUTH | ||
23 | m_list_elem *iter; | ||
24 | +#endif | ||
25 | /* Sufficient space for non-string args */ | ||
26 | len = 100; | ||
27 | |||
diff --git a/meta/recipes-core/dropbear/dropbear/0001-Handle-arbitrary-length-paths-and-commands-in-multih.patch b/meta/recipes-core/dropbear/dropbear/0001-Handle-arbitrary-length-paths-and-commands-in-multih.patch new file mode 100644 index 0000000000..062f215398 --- /dev/null +++ b/meta/recipes-core/dropbear/dropbear/0001-Handle-arbitrary-length-paths-and-commands-in-multih.patch | |||
@@ -0,0 +1,63 @@ | |||
1 | From 697b1f86c0b2b0caf12e9e32bab29161093ab5d4 Mon Sep 17 00:00:00 2001 | ||
2 | From: Matt Johnston <matt@ucc.asn.au> | ||
3 | Date: Mon, 1 Apr 2024 11:50:26 +0800 | ||
4 | Subject: [PATCH] Handle arbitrary length paths and commands in | ||
5 | multihop_passthrough_args() | ||
6 | |||
7 | Upstream-Status: Backport [https://github.com/mkj/dropbear/commit/697b1f86c0b2b0caf12e9e32bab29161093ab5d4] | ||
8 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
9 | --- | ||
10 | cli-runopts.c | 30 +++++++++++++++++++++--------- | ||
11 | 1 file changed, 21 insertions(+), 9 deletions(-) | ||
12 | |||
13 | diff --git a/cli-runopts.c b/cli-runopts.c | ||
14 | index 37ea61d..219fc53 100644 | ||
15 | --- a/cli-runopts.c | ||
16 | +++ b/cli-runopts.c | ||
17 | @@ -528,15 +528,29 @@ static void loadidentityfile(const char* filename, int warnfail) { | ||
18 | |||
19 | #if DROPBEAR_CLI_MULTIHOP | ||
20 | |||
21 | -static char* | ||
22 | -multihop_passthrough_args() { | ||
23 | - char *ret, args[256]; | ||
24 | +/* Fill out -i, -y, -W options that make sense for all | ||
25 | + * the intermediate processes */ | ||
26 | +static char* multihop_passthrough_args(void) { | ||
27 | + char *args = NULL; | ||
28 | unsigned int len, total; | ||
29 | m_list_elem *iter; | ||
30 | - /* Fill out -i, -y, -W options that make sense for all | ||
31 | - * the intermediate processes */ | ||
32 | + /* Sufficient space for non-string args */ | ||
33 | + len = 100; | ||
34 | + | ||
35 | + /* String arguments have arbitrary length, so determine space required */ | ||
36 | + if (cli_opts.proxycmd) { | ||
37 | + len += strlen(cli_opts.proxycmd); | ||
38 | + } | ||
39 | + for (iter = cli_opts.privkeys->first; iter; iter = iter->next) | ||
40 | + { | ||
41 | + sign_key * key = (sign_key*)iter->item; | ||
42 | + len += 4 + strlen(key->filename); | ||
43 | + } | ||
44 | + | ||
45 | + args = m_malloc(len); | ||
46 | total = 0; | ||
47 | - len = 255; | ||
48 | + | ||
49 | + /* Create new argument string */ | ||
50 | |||
51 | if (cli_opts.quiet) { | ||
52 | total += m_snprintf(args+total, len-total, "-q "); | ||
53 | @@ -564,9 +578,7 @@ multihop_passthrough_args() { | ||
54 | } | ||
55 | #endif /* DROPBEAR_CLI_PUBKEY_AUTH */ | ||
56 | |||
57 | - ret = m_malloc(total + 1); | ||
58 | - strcpy(ret,args); | ||
59 | - return ret; | ||
60 | + return args; | ||
61 | } | ||
62 | |||
63 | /* Sets up 'onion-forwarding' connections. This will spawn | ||
diff --git a/meta/recipes-core/dropbear/dropbear/0001-add-o-BatchMode-and-also-forward-this-when-multihop-.patch b/meta/recipes-core/dropbear/dropbear/0001-add-o-BatchMode-and-also-forward-this-when-multihop-.patch new file mode 100644 index 0000000000..c15da6e099 --- /dev/null +++ b/meta/recipes-core/dropbear/dropbear/0001-add-o-BatchMode-and-also-forward-this-when-multihop-.patch | |||
@@ -0,0 +1,81 @@ | |||
1 | From 2f1177e55f33afd676e08c9449ab7ab517fc3b30 Mon Sep 17 00:00:00 2001 | ||
2 | From: HansH111 <hans@atbas.org> | ||
3 | Date: Sat, 24 Feb 2024 08:29:30 +0000 | ||
4 | Subject: [PATCH] add -o BatchMode and also forward this when multihop | ||
5 | destination is used | ||
6 | |||
7 | Upstream-Status: Backport [https://github.com/mkj/dropbear/commit/2f1177e55f33afd676e08c9449ab7ab517fc3b30] | ||
8 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
9 | --- | ||
10 | cli-runopts.c | 33 +++++++++++---------------------- | ||
11 | 1 file changed, 11 insertions(+), 22 deletions(-) | ||
12 | |||
13 | diff --git a/cli-runopts.c b/cli-runopts.c | ||
14 | index 38a73f7..37ea61d 100644 | ||
15 | --- a/cli-runopts.c | ||
16 | +++ b/cli-runopts.c | ||
17 | @@ -530,53 +530,42 @@ static void loadidentityfile(const char* filename, int warnfail) { | ||
18 | |||
19 | static char* | ||
20 | multihop_passthrough_args() { | ||
21 | - char *ret; | ||
22 | + char *ret, args[256]; | ||
23 | unsigned int len, total; | ||
24 | m_list_elem *iter; | ||
25 | /* Fill out -i, -y, -W options that make sense for all | ||
26 | - * the intermediate processes */ | ||
27 | - len = 30; /* space for "-q -y -y -W <size>\0" */ | ||
28 | -#if DROPBEAR_CLI_PUBKEY_AUTH | ||
29 | - for (iter = cli_opts.privkeys->first; iter; iter = iter->next) | ||
30 | - { | ||
31 | - sign_key * key = (sign_key*)iter->item; | ||
32 | - len += 3 + strlen(key->filename); | ||
33 | - } | ||
34 | -#endif /* DROPBEAR_CLI_PUBKEY_AUTH */ | ||
35 | - if (cli_opts.proxycmd) { | ||
36 | - /* "-J 'cmd'" */ | ||
37 | - len += 6 + strlen(cli_opts.proxycmd); | ||
38 | - } | ||
39 | - | ||
40 | - ret = m_malloc(len); | ||
41 | + * the intermediate processes */ | ||
42 | total = 0; | ||
43 | + len = 255; | ||
44 | |||
45 | if (cli_opts.quiet) { | ||
46 | - total += m_snprintf(ret+total, len-total, "-q "); | ||
47 | + total += m_snprintf(args+total, len-total, "-q "); | ||
48 | } | ||
49 | |||
50 | if (cli_opts.no_hostkey_check) { | ||
51 | - total += m_snprintf(ret+total, len-total, "-y -y "); | ||
52 | + total += m_snprintf(args+total, len-total, "-y -y "); | ||
53 | } else if (cli_opts.always_accept_key) { | ||
54 | - total += m_snprintf(ret+total, len-total, "-y "); | ||
55 | + total += m_snprintf(args+total, len-total, "-y "); | ||
56 | } | ||
57 | |||
58 | if (cli_opts.proxycmd) { | ||
59 | - total += m_snprintf(ret+total, len-total, "-J '%s' ", cli_opts.proxycmd); | ||
60 | + total += m_snprintf(args+total, len-total, "-J '%s' ", cli_opts.proxycmd); | ||
61 | } | ||
62 | |||
63 | if (opts.recv_window != DEFAULT_RECV_WINDOW) { | ||
64 | - total += m_snprintf(ret+total, len-total, "-W %u ", opts.recv_window); | ||
65 | + total += m_snprintf(args+total, len-total, "-W %u ", opts.recv_window); | ||
66 | } | ||
67 | |||
68 | #if DROPBEAR_CLI_PUBKEY_AUTH | ||
69 | for (iter = cli_opts.privkeys->first; iter; iter = iter->next) | ||
70 | { | ||
71 | sign_key * key = (sign_key*)iter->item; | ||
72 | - total += m_snprintf(ret+total, len-total, "-i %s ", key->filename); | ||
73 | + total += m_snprintf(args+total, len-total, "-i %s ", key->filename); | ||
74 | } | ||
75 | #endif /* DROPBEAR_CLI_PUBKEY_AUTH */ | ||
76 | |||
77 | + ret = m_malloc(total + 1); | ||
78 | + strcpy(ret,args); | ||
79 | return ret; | ||
80 | } | ||
81 | |||
diff --git a/meta/recipes-core/dropbear/dropbear/0001-cli-runopts.c-add-missing-DROPBEAR_CLI_PUBKEY_AUTH.patch b/meta/recipes-core/dropbear/dropbear/0001-cli-runopts.c-add-missing-DROPBEAR_CLI_PUBKEY_AUTH.patch new file mode 100644 index 0000000000..da7de00389 --- /dev/null +++ b/meta/recipes-core/dropbear/dropbear/0001-cli-runopts.c-add-missing-DROPBEAR_CLI_PUBKEY_AUTH.patch | |||
@@ -0,0 +1,29 @@ | |||
1 | From dd03da772bfad6174425066ff9752b60e25ed183 Mon Sep 17 00:00:00 2001 | ||
2 | From: Sergey Ponomarev <stokito@gmail.com> | ||
3 | Date: Sun, 7 Apr 2024 21:16:50 +0300 | ||
4 | Subject: [PATCH] cli-runopts.c add missing DROPBEAR_CLI_PUBKEY_AUTH | ||
5 | |||
6 | Upstream-Status: Backport [https://github.com/mkj/dropbear/commit/dd03da772bfad6174425066ff9752b60e25ed183] | ||
7 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
8 | --- | ||
9 | cli-runopts.c | 2 ++ | ||
10 | 1 file changed, 2 insertions(+) | ||
11 | |||
12 | diff --git a/cli-runopts.c b/cli-runopts.c | ||
13 | index 219fc53..b853a13 100644 | ||
14 | --- a/cli-runopts.c | ||
15 | +++ b/cli-runopts.c | ||
16 | @@ -541,11 +541,13 @@ static char* multihop_passthrough_args(void) { | ||
17 | if (cli_opts.proxycmd) { | ||
18 | len += strlen(cli_opts.proxycmd); | ||
19 | } | ||
20 | +#if DROPBEAR_CLI_PUBKEY_AUTH | ||
21 | for (iter = cli_opts.privkeys->first; iter; iter = iter->next) | ||
22 | { | ||
23 | sign_key * key = (sign_key*)iter->item; | ||
24 | len += 4 + strlen(key->filename); | ||
25 | } | ||
26 | +#endif | ||
27 | |||
28 | args = m_malloc(len); | ||
29 | total = 0; | ||
diff --git a/meta/recipes-core/dropbear/dropbear/CVE-2025-47203.patch b/meta/recipes-core/dropbear/dropbear/CVE-2025-47203.patch new file mode 100644 index 0000000000..513fbafce0 --- /dev/null +++ b/meta/recipes-core/dropbear/dropbear/CVE-2025-47203.patch | |||
@@ -0,0 +1,367 @@ | |||
1 | From e5a0ef27c227f7ae69d9a9fec98a056494409b9b Mon Sep 17 00:00:00 2001 | ||
2 | From: Matt Johnston <matt@ucc.asn.au> | ||
3 | Date: Mon, 5 May 2025 23:14:19 +0800 | ||
4 | Subject: [PATCH] Execute multihop commands directly, no shell | ||
5 | |||
6 | This avoids problems with shell escaping if arguments contain special | ||
7 | characters. | ||
8 | |||
9 | CVE: CVE-2025-47203 | ||
10 | Upstream-Status: Backport [https://github.com/mkj/dropbear/commit/e5a0ef27c227f7ae69d9a9fec98a056494409b9b] | ||
11 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
12 | --- | ||
13 | cli-main.c | 59 +++++++++++++++++++---------- | ||
14 | cli-runopts.c | 100 +++++++++++++++++++++++++++++--------------------- | ||
15 | dbutil.c | 9 ++++- | ||
16 | dbutil.h | 1 + | ||
17 | runopts.h | 5 +++ | ||
18 | 5 files changed, 112 insertions(+), 62 deletions(-) | ||
19 | |||
20 | diff --git a/cli-main.c b/cli-main.c | ||
21 | index 065fd76..2fafa88 100644 | ||
22 | --- a/cli-main.c | ||
23 | +++ b/cli-main.c | ||
24 | @@ -77,9 +77,8 @@ int main(int argc, char ** argv) { | ||
25 | } | ||
26 | |||
27 | #if DROPBEAR_CLI_PROXYCMD | ||
28 | - if (cli_opts.proxycmd) { | ||
29 | + if (cli_opts.proxycmd || cli_opts.proxyexec) { | ||
30 | cli_proxy_cmd(&sock_in, &sock_out, &proxy_cmd_pid); | ||
31 | - m_free(cli_opts.proxycmd); | ||
32 | if (signal(SIGINT, kill_proxy_sighandler) == SIG_ERR || | ||
33 | signal(SIGTERM, kill_proxy_sighandler) == SIG_ERR || | ||
34 | signal(SIGHUP, kill_proxy_sighandler) == SIG_ERR) { | ||
35 | @@ -101,7 +100,8 @@ int main(int argc, char ** argv) { | ||
36 | } | ||
37 | #endif /* DBMULTI stuff */ | ||
38 | |||
39 | -static void exec_proxy_cmd(const void *user_data_cmd) { | ||
40 | +#if DROPBEAR_CLI_PROXYCMD | ||
41 | +static void shell_proxy_cmd(const void *user_data_cmd) { | ||
42 | const char *cmd = user_data_cmd; | ||
43 | char *usershell; | ||
44 | |||
45 | @@ -110,41 +110,62 @@ static void exec_proxy_cmd(const void *user_data_cmd) { | ||
46 | dropbear_exit("Failed to run '%s'\n", cmd); | ||
47 | } | ||
48 | |||
49 | -#if DROPBEAR_CLI_PROXYCMD | ||
50 | +static void exec_proxy_cmd(const void *unused) { | ||
51 | + (void)unused; | ||
52 | + run_command(cli_opts.proxyexec[0], cli_opts.proxyexec, ses.maxfd); | ||
53 | + dropbear_exit("Failed to run '%s'\n", cli_opts.proxyexec[0]); | ||
54 | +} | ||
55 | + | ||
56 | static void cli_proxy_cmd(int *sock_in, int *sock_out, pid_t *pid_out) { | ||
57 | - char * ex_cmd = NULL; | ||
58 | - size_t ex_cmdlen; | ||
59 | + char * cmd_arg = NULL; | ||
60 | + void (*exec_fn)(const void *user_data) = NULL; | ||
61 | int ret; | ||
62 | |||
63 | + /* exactly one of cli_opts.proxycmd or cli_opts.proxyexec should be set */ | ||
64 | + | ||
65 | /* File descriptor "-j &3" */ | ||
66 | - if (*cli_opts.proxycmd == '&') { | ||
67 | + if (cli_opts.proxycmd && *cli_opts.proxycmd == '&') { | ||
68 | char *p = cli_opts.proxycmd + 1; | ||
69 | int sock = strtoul(p, &p, 10); | ||
70 | /* must be a single number, and not stdin/stdout/stderr */ | ||
71 | if (sock > 2 && sock < 1024 && *p == '\0') { | ||
72 | *sock_in = sock; | ||
73 | *sock_out = sock; | ||
74 | - return; | ||
75 | + goto cleanup; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | - /* Normal proxycommand */ | ||
80 | + if (cli_opts.proxycmd) { | ||
81 | + /* Normal proxycommand */ | ||
82 | + size_t shell_cmdlen; | ||
83 | + /* So that spawn_command knows which shell to run */ | ||
84 | + fill_passwd(cli_opts.own_user); | ||
85 | |||
86 | - /* So that spawn_command knows which shell to run */ | ||
87 | - fill_passwd(cli_opts.own_user); | ||
88 | + shell_cmdlen = strlen(cli_opts.proxycmd) + 6; /* "exec " + command + '\0' */ | ||
89 | + cmd_arg = m_malloc(shell_cmdlen); | ||
90 | + snprintf(cmd_arg, shell_cmdlen, "exec %s", cli_opts.proxycmd); | ||
91 | + exec_fn = shell_proxy_cmd; | ||
92 | + } else { | ||
93 | + /* No shell */ | ||
94 | + exec_fn = exec_proxy_cmd; | ||
95 | + } | ||
96 | |||
97 | - ex_cmdlen = strlen(cli_opts.proxycmd) + 6; /* "exec " + command + '\0' */ | ||
98 | - ex_cmd = m_malloc(ex_cmdlen); | ||
99 | - snprintf(ex_cmd, ex_cmdlen, "exec %s", cli_opts.proxycmd); | ||
100 | - | ||
101 | - ret = spawn_command(exec_proxy_cmd, ex_cmd, | ||
102 | - sock_out, sock_in, NULL, pid_out); | ||
103 | - DEBUG1(("cmd: %s pid=%d", ex_cmd,*pid_out)) | ||
104 | - m_free(ex_cmd); | ||
105 | + ret = spawn_command(exec_fn, cmd_arg, sock_out, sock_in, NULL, pid_out); | ||
106 | if (ret == DROPBEAR_FAILURE) { | ||
107 | dropbear_exit("Failed running proxy command"); | ||
108 | *sock_in = *sock_out = -1; | ||
109 | } | ||
110 | + | ||
111 | +cleanup: | ||
112 | + m_free(cli_opts.proxycmd); | ||
113 | + m_free(cmd_arg); | ||
114 | + if (cli_opts.proxyexec) { | ||
115 | + char **a = NULL; | ||
116 | + for (a = cli_opts.proxyexec; *a; a++) { | ||
117 | + m_free_direct(*a); | ||
118 | + } | ||
119 | + m_free(cli_opts.proxyexec); | ||
120 | + } | ||
121 | } | ||
122 | |||
123 | static void kill_proxy_sighandler(int UNUSED(signo)) { | ||
124 | diff --git a/cli-runopts.c b/cli-runopts.c | ||
125 | index 6668aee..b9add84 100644 | ||
126 | --- a/cli-runopts.c | ||
127 | +++ b/cli-runopts.c | ||
128 | @@ -530,58 +530,81 @@ static void loadidentityfile(const char* filename, int warnfail) { | ||
129 | |||
130 | /* Fill out -i, -y, -W options that make sense for all | ||
131 | * the intermediate processes */ | ||
132 | -static char* multihop_passthrough_args(void) { | ||
133 | - char *args = NULL; | ||
134 | - unsigned int len, total; | ||
135 | +static char** multihop_args(const char* argv0, const char* prior_hops) { | ||
136 | + /* null terminated array */ | ||
137 | + char **args = NULL; | ||
138 | + size_t max_args = 14, pos = 0, len; | ||
139 | #if DROPBEAR_CLI_PUBKEY_AUTH | ||
140 | m_list_elem *iter; | ||
141 | #endif | ||
142 | - /* Sufficient space for non-string args */ | ||
143 | - len = 100; | ||
144 | |||
145 | - /* String arguments have arbitrary length, so determine space required */ | ||
146 | - if (cli_opts.proxycmd) { | ||
147 | - len += strlen(cli_opts.proxycmd); | ||
148 | - } | ||
149 | #if DROPBEAR_CLI_PUBKEY_AUTH | ||
150 | for (iter = cli_opts.privkeys->first; iter; iter = iter->next) | ||
151 | { | ||
152 | - sign_key * key = (sign_key*)iter->item; | ||
153 | - len += 4 + strlen(key->filename); | ||
154 | + /* "-i file" for each */ | ||
155 | + max_args += 2; | ||
156 | } | ||
157 | #endif | ||
158 | |||
159 | - args = m_malloc(len); | ||
160 | - total = 0; | ||
161 | + args = m_malloc(sizeof(char*) * max_args); | ||
162 | + pos = 0; | ||
163 | |||
164 | - /* Create new argument string */ | ||
165 | + args[pos] = m_strdup(argv0); | ||
166 | + pos++; | ||
167 | |||
168 | if (cli_opts.quiet) { | ||
169 | - total += m_snprintf(args+total, len-total, "-q "); | ||
170 | + args[pos] = m_strdup("-q"); | ||
171 | + pos++; | ||
172 | } | ||
173 | |||
174 | if (cli_opts.no_hostkey_check) { | ||
175 | - total += m_snprintf(args+total, len-total, "-y -y "); | ||
176 | + args[pos] = m_strdup("-y"); | ||
177 | + pos++; | ||
178 | + args[pos] = m_strdup("-y"); | ||
179 | + pos++; | ||
180 | } else if (cli_opts.always_accept_key) { | ||
181 | - total += m_snprintf(args+total, len-total, "-y "); | ||
182 | + args[pos] = m_strdup("-y"); | ||
183 | + pos++; | ||
184 | } | ||
185 | |||
186 | if (cli_opts.proxycmd) { | ||
187 | - total += m_snprintf(args+total, len-total, "-J '%s' ", cli_opts.proxycmd); | ||
188 | + args[pos] = m_strdup("-J"); | ||
189 | + pos++; | ||
190 | + args[pos] = m_strdup(cli_opts.proxycmd); | ||
191 | + pos++; | ||
192 | } | ||
193 | |||
194 | if (opts.recv_window != DEFAULT_RECV_WINDOW) { | ||
195 | - total += m_snprintf(args+total, len-total, "-W %u ", opts.recv_window); | ||
196 | + args[pos] = m_strdup("-W"); | ||
197 | + pos++; | ||
198 | + args[pos] = m_malloc(11); | ||
199 | + m_snprintf(args[pos], 11, "%u", opts.recv_window); | ||
200 | + pos++; | ||
201 | } | ||
202 | |||
203 | #if DROPBEAR_CLI_PUBKEY_AUTH | ||
204 | for (iter = cli_opts.privkeys->first; iter; iter = iter->next) | ||
205 | { | ||
206 | sign_key * key = (sign_key*)iter->item; | ||
207 | - total += m_snprintf(args+total, len-total, "-i %s ", key->filename); | ||
208 | + args[pos] = m_strdup("-i"); | ||
209 | + pos++; | ||
210 | + args[pos] = m_strdup(key->filename); | ||
211 | + pos++; | ||
212 | } | ||
213 | #endif /* DROPBEAR_CLI_PUBKEY_AUTH */ | ||
214 | |||
215 | + /* last hop */ | ||
216 | + args[pos] = m_strdup("-B"); | ||
217 | + pos++; | ||
218 | + len = strlen(cli_opts.remotehost) + strlen(cli_opts.remoteport) + 2; | ||
219 | + args[pos] = m_malloc(len); | ||
220 | + snprintf(args[pos], len, "%s:%s", cli_opts.remotehost, cli_opts.remoteport); | ||
221 | + pos++; | ||
222 | + | ||
223 | + /* hostnames of prior hops */ | ||
224 | + args[pos] = m_strdup(prior_hops); | ||
225 | + pos++; | ||
226 | + | ||
227 | return args; | ||
228 | } | ||
229 | |||
230 | @@ -596,7 +619,7 @@ static char* multihop_passthrough_args(void) { | ||
231 | * etc for as many hosts as we want. | ||
232 | * | ||
233 | * Note that "-J" arguments aren't actually used, instead | ||
234 | - * below sets cli_opts.proxycmd directly. | ||
235 | + * below sets cli_opts.proxyexec directly. | ||
236 | * | ||
237 | * Ports for hosts can be specified as host/port. | ||
238 | */ | ||
239 | @@ -604,7 +627,7 @@ static void parse_multihop_hostname(const char* orighostarg, const char* argv0) | ||
240 | char *userhostarg = NULL; | ||
241 | char *hostbuf = NULL; | ||
242 | char *last_hop = NULL; | ||
243 | - char *remainder = NULL; | ||
244 | + char *prior_hops = NULL; | ||
245 | |||
246 | /* both scp and rsync parse a user@host argument | ||
247 | * and turn it into "-l user host". This breaks | ||
248 | @@ -622,6 +645,8 @@ static void parse_multihop_hostname(const char* orighostarg, const char* argv0) | ||
249 | } | ||
250 | userhostarg = hostbuf; | ||
251 | |||
252 | + /* Split off any last hostname and use that as remotehost/remoteport. | ||
253 | + * That is used for authorized_keys checking etc */ | ||
254 | last_hop = strrchr(userhostarg, ','); | ||
255 | if (last_hop) { | ||
256 | if (last_hop == userhostarg) { | ||
257 | @@ -629,35 +654,28 @@ static void parse_multihop_hostname(const char* orighostarg, const char* argv0) | ||
258 | } | ||
259 | *last_hop = '\0'; | ||
260 | last_hop++; | ||
261 | - remainder = userhostarg; | ||
262 | + prior_hops = userhostarg; | ||
263 | userhostarg = last_hop; | ||
264 | } | ||
265 | |||
266 | + /* Update cli_opts.remotehost and cli_opts.remoteport */ | ||
267 | parse_hostname(userhostarg); | ||
268 | |||
269 | - if (last_hop) { | ||
270 | - /* Set up the proxycmd */ | ||
271 | - unsigned int cmd_len = 0; | ||
272 | - char *passthrough_args = multihop_passthrough_args(); | ||
273 | - if (cli_opts.remoteport == NULL) { | ||
274 | - cli_opts.remoteport = "22"; | ||
275 | + /* Construct any multihop proxy command. Use proxyexec to | ||
276 | + * avoid worrying about shell escaping. */ | ||
277 | + if (prior_hops) { | ||
278 | + cli_opts.proxyexec = multihop_args(argv0, prior_hops); | ||
279 | + /* Any -J argument has been copied to proxyexec */ | ||
280 | + if (cli_opts.proxycmd) { | ||
281 | + m_free(cli_opts.proxycmd); | ||
282 | } | ||
283 | - cmd_len = strlen(argv0) + strlen(remainder) | ||
284 | - + strlen(cli_opts.remotehost) + strlen(cli_opts.remoteport) | ||
285 | - + strlen(passthrough_args) | ||
286 | - + 30; | ||
287 | - /* replace proxycmd. old -J arguments have been copied | ||
288 | - to passthrough_args */ | ||
289 | - cli_opts.proxycmd = m_realloc(cli_opts.proxycmd, cmd_len); | ||
290 | - m_snprintf(cli_opts.proxycmd, cmd_len, "%s -B %s:%s %s %s", | ||
291 | - argv0, cli_opts.remotehost, cli_opts.remoteport, | ||
292 | - passthrough_args, remainder); | ||
293 | + | ||
294 | #ifndef DISABLE_ZLIB | ||
295 | - /* The stream will be incompressible since it's encrypted. */ | ||
296 | + /* This outer stream will be incompressible since it's encrypted. */ | ||
297 | opts.compress_mode = DROPBEAR_COMPRESS_OFF; | ||
298 | #endif | ||
299 | - m_free(passthrough_args); | ||
300 | } | ||
301 | + | ||
302 | m_free(hostbuf); | ||
303 | } | ||
304 | #endif /* !DROPBEAR_CLI_MULTIHOP */ | ||
305 | diff --git a/dbutil.c b/dbutil.c | ||
306 | index bd66454..910fa27 100644 | ||
307 | --- a/dbutil.c | ||
308 | +++ b/dbutil.c | ||
309 | @@ -371,7 +371,6 @@ int spawn_command(void(*exec_fn)(const void *user_data), const void *exec_data, | ||
310 | void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell) { | ||
311 | char * argv[4]; | ||
312 | char * baseshell = NULL; | ||
313 | - unsigned int i; | ||
314 | |||
315 | baseshell = basename(usershell); | ||
316 | |||
317 | @@ -393,6 +392,12 @@ void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell) { | ||
318 | argv[1] = NULL; | ||
319 | } | ||
320 | |||
321 | + run_command(usershell, argv, maxfd); | ||
322 | +} | ||
323 | + | ||
324 | +void run_command(const char* argv0, char** args, unsigned int maxfd) { | ||
325 | + unsigned int i; | ||
326 | + | ||
327 | /* Re-enable SIGPIPE for the executed process */ | ||
328 | if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) { | ||
329 | dropbear_exit("signal() error"); | ||
330 | @@ -404,7 +409,7 @@ void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell) { | ||
331 | m_close(i); | ||
332 | } | ||
333 | |||
334 | - execv(usershell, argv); | ||
335 | + execv(argv0, args); | ||
336 | } | ||
337 | |||
338 | #if DEBUG_TRACE | ||
339 | diff --git a/dbutil.h b/dbutil.h | ||
340 | index 64af170..bfc1f1f 100644 | ||
341 | --- a/dbutil.h | ||
342 | +++ b/dbutil.h | ||
343 | @@ -63,6 +63,7 @@ char * stripcontrol(const char * text); | ||
344 | int spawn_command(void(*exec_fn)(const void *user_data), const void *exec_data, | ||
345 | int *writefd, int *readfd, int *errfd, pid_t *pid); | ||
346 | void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell); | ||
347 | +void run_command(const char* argv0, char** args, unsigned int maxfd); | ||
348 | #if ENABLE_CONNECT_UNIX | ||
349 | int connect_unix(const char* addr); | ||
350 | #endif | ||
351 | diff --git a/runopts.h b/runopts.h | ||
352 | index 1675836..11c3ef2 100644 | ||
353 | --- a/runopts.h | ||
354 | +++ b/runopts.h | ||
355 | @@ -188,7 +188,12 @@ typedef struct cli_runopts { | ||
356 | unsigned int netcat_port; | ||
357 | #endif | ||
358 | #if DROPBEAR_CLI_PROXYCMD | ||
359 | + /* A proxy command to run via the user's shell */ | ||
360 | char *proxycmd; | ||
361 | +#endif | ||
362 | +#if DROPBEAR_CLI_MULTIHOP | ||
363 | + /* Similar to proxycmd, but is arguments for execve(), not shell */ | ||
364 | + char **proxyexec; | ||
365 | #endif | ||
366 | char *bind_address; | ||
367 | char *bind_port; | ||
diff --git a/meta/recipes-core/dropbear/dropbear_2022.83.bb b/meta/recipes-core/dropbear/dropbear_2022.83.bb index 772e08eaed..2ed8d2c2a1 100644 --- a/meta/recipes-core/dropbear/dropbear_2022.83.bb +++ b/meta/recipes-core/dropbear/dropbear_2022.83.bb | |||
@@ -24,6 +24,11 @@ SRC_URI = "http://matt.ucc.asn.au/dropbear/releases/dropbear-${PV}.tar.bz2 \ | |||
24 | ${@bb.utils.contains('PACKAGECONFIG', 'disable-weak-ciphers', 'file://dropbear-disable-weak-ciphers.patch', '', d)} \ | 24 | ${@bb.utils.contains('PACKAGECONFIG', 'disable-weak-ciphers', 'file://dropbear-disable-weak-ciphers.patch', '', d)} \ |
25 | file://CVE-2023-36328.patch \ | 25 | file://CVE-2023-36328.patch \ |
26 | file://CVE-2023-48795.patch \ | 26 | file://CVE-2023-48795.patch \ |
27 | file://0001-add-o-BatchMode-and-also-forward-this-when-multihop-.patch \ | ||
28 | file://0001-Handle-arbitrary-length-paths-and-commands-in-multih.patch \ | ||
29 | file://0001-cli-runopts.c-add-missing-DROPBEAR_CLI_PUBKEY_AUTH.patch \ | ||
30 | file://0001-Avoid-unused-variable-with-DROPBEAR_CLI_PUBKEY_AUTH-.patch \ | ||
31 | file://CVE-2025-47203.patch \ | ||
27 | " | 32 | " |
28 | 33 | ||
29 | SRC_URI[sha256sum] = "bc5a121ffbc94b5171ad5ebe01be42746d50aa797c9549a4639894a16749443b" | 34 | SRC_URI[sha256sum] = "bc5a121ffbc94b5171ad5ebe01be42746d50aa797c9549a4639894a16749443b" |