summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGyorgy Sarvari <skandigraun@gmail.com>2025-12-16 20:40:05 +0100
committerGyorgy Sarvari <skandigraun@gmail.com>2025-12-17 15:38:00 +0100
commit8611f92c20ba3aab57f3586a6a2e3b9cd1fe00c7 (patch)
treeeeffcc9ca1c2a5d68eacedf4589d71719dec04d1
parent5c3e0fc51613e6de2bf5bfeb7a83fb93dde3afde (diff)
downloadmeta-openembedded-8611f92c20ba3aab57f3586a6a2e3b9cd1fe00c7.tar.gz
proftpd: patch CVE-2024-48651
Details: https://nvd.nist.gov/vuln/detail/CVE-2024-48651 Backport the patch mentioned in the NVD report. Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
-rw-r--r--meta-networking/recipes-daemons/proftpd/files/CVE-2024-48651.patch321
-rw-r--r--meta-networking/recipes-daemons/proftpd/proftpd_1.3.7c.bb3
2 files changed, 323 insertions, 1 deletions
diff --git a/meta-networking/recipes-daemons/proftpd/files/CVE-2024-48651.patch b/meta-networking/recipes-daemons/proftpd/files/CVE-2024-48651.patch
new file mode 100644
index 0000000000..db525c5418
--- /dev/null
+++ b/meta-networking/recipes-daemons/proftpd/files/CVE-2024-48651.patch
@@ -0,0 +1,321 @@
1From 1df9a7b29aaedfc563ba908b52ca2414caddf25f Mon Sep 17 00:00:00 2001
2From: TJ Saunders <tj@castaglia.org>
3Date: Wed, 13 Nov 2024 06:33:35 -0800
4Subject: [PATCH] Issue #1830: When no supplemental groups are provided by the
5 underlying authentication providers, fall back to using the primary
6 group/GID. (#1835)
7
8This prevents surprise due to inheritance of the parent processes' supplemental group membership, which might inadvertently provided undesired access.
9
10CVE: CVE-2024-48651
11Upstream-Status: Backport [https://github.com/proftpd/proftpd/commit/cec01cc0a2523453e5da5a486bc6d977c3768db1]
12Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
13---
14 contrib/mod_sftp/auth.c | 14 +-
15 modules/mod_auth.c | 19 +-
16 src/auth.c | 14 +-
17 .../ProFTPD/Tests/Modules/mod_sql_sqlite.pm | 175 ++++++++++++++++++
18 4 files changed, 210 insertions(+), 12 deletions(-)
19
20diff --git a/contrib/mod_sftp/auth.c b/contrib/mod_sftp/auth.c
21index ede821daa..2854a03cd 100644
22--- a/contrib/mod_sftp/auth.c
23+++ b/contrib/mod_sftp/auth.c
24@@ -382,8 +382,20 @@ static int setup_env(pool *p, const char *user) {
25 session.groups == NULL) {
26 res = pr_auth_getgroups(p, pw->pw_name, &session.gids, &session.groups);
27 if (res < 1) {
28+ /* If no supplemental groups are provided, default to using the process
29+ * primary GID as the supplemental group. This prevents access
30+ * regressions as seen in Issue #1830.
31+ */
32 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
33- "no supplemental groups found for user '%s'", pw->pw_name);
34+ "no supplemental groups found for user '%s', "
35+ "using primary group %s (GID %lu)", pw->pw_name, session.group,
36+ (unsigned long) session.login_gid);
37+
38+ session.gids = make_array(p, 2, sizeof(gid_t));
39+ session.groups = make_array(p, 2, sizeof(char *));
40+
41+ *((gid_t *) push_array(session.gids)) = session.login_gid;
42+ *((char **) push_array(session.groups)) = pstrdup(p, session.group);
43 }
44 }
45
46diff --git a/modules/mod_auth.c b/modules/mod_auth.c
47index e47ed148d..a1b71c0f7 100644
48--- a/modules/mod_auth.c
49+++ b/modules/mod_auth.c
50@@ -1111,8 +1111,8 @@ static int setup_env(pool *p, cmd_rec *cmd, const char *user, char *pass) {
51 session.groups = NULL;
52 }
53
54- if (!session.gids &&
55- !session.groups) {
56+ if (session.gids == NULL &&
57+ session.groups == NULL) {
58 /* Get the supplemental groups. Note that we only look up the
59 * supplemental group credentials if we have not cached the group
60 * credentials before, in session.gids and session.groups.
61@@ -1122,8 +1122,19 @@ static int setup_env(pool *p, cmd_rec *cmd, const char *user, char *pass) {
62 */
63 res = pr_auth_getgroups(p, pw->pw_name, &session.gids, &session.groups);
64 if (res < 1) {
65- pr_log_debug(DEBUG5, "no supplemental groups found for user '%s'",
66- pw->pw_name);
67+ /* If no supplemental groups are provided, default to using the process
68+ * primary GID as the supplemental group. This prevents access
69+ * regressions as seen in Issue #1830.
70+ */
71+ pr_log_debug(DEBUG5, "no supplemental groups found for user '%s', "
72+ "using primary group %s (GID %lu)", pw->pw_name, session.group,
73+ (unsigned long) session.login_gid);
74+
75+ session.gids = make_array(p, 2, sizeof(gid_t));
76+ session.groups = make_array(p, 2, sizeof(char *));
77+
78+ *((gid_t *) push_array(session.gids)) = session.login_gid;
79+ *((char **) push_array(session.groups)) = pstrdup(p, session.group);
80 }
81 }
82
83diff --git a/src/auth.c b/src/auth.c
84index 494a479c0..a6fe9f1c2 100644
85--- a/src/auth.c
86+++ b/src/auth.c
87@@ -1512,12 +1512,12 @@ int pr_auth_getgroups(pool *p, const char *name, array_header **group_ids,
88 }
89
90 /* Allocate memory for the array_headers of GIDs and group names. */
91- if (group_ids) {
92- *group_ids = make_array(permanent_pool, 2, sizeof(gid_t));
93+ if (group_ids != NULL) {
94+ *group_ids = make_array(p, 2, sizeof(gid_t));
95 }
96
97- if (group_names) {
98- *group_names = make_array(permanent_pool, 2, sizeof(char *));
99+ if (group_names != NULL) {
100+ *group_names = make_array(p, 2, sizeof(char *));
101 }
102
103 cmd = make_cmd(p, 3, name, group_ids ? *group_ids : NULL,
104@@ -1536,7 +1536,7 @@ int pr_auth_getgroups(pool *p, const char *name, array_header **group_ids,
105 * for the benefit of auth_getgroup() implementors.
106 */
107
108- if (group_ids) {
109+ if (group_ids != NULL) {
110 register unsigned int i;
111 char *strgids = "";
112 gid_t *gids = (*group_ids)->elts;
113@@ -1552,7 +1552,7 @@ int pr_auth_getgroups(pool *p, const char *name, array_header **group_ids,
114 *strgids ? strgids : "(None; corrupted group file?)");
115 }
116
117- if (group_names) {
118+ if (group_names != NULL) {
119 register unsigned int i;
120 char *strgroups = "";
121 char **groups = (*group_names)->elts;
122@@ -1568,7 +1568,7 @@ int pr_auth_getgroups(pool *p, const char *name, array_header **group_ids,
123 }
124 }
125
126- if (cmd->tmp_pool) {
127+ if (cmd->tmp_pool != NULL) {
128 destroy_pool(cmd->tmp_pool);
129 cmd->tmp_pool = NULL;
130 }
131diff --git a/tests/t/lib/ProFTPD/Tests/Modules/mod_sql_sqlite.pm b/tests/t/lib/ProFTPD/Tests/Modules/mod_sql_sqlite.pm
132index 4abb6eb59..f1ffeef34 100644
133--- a/tests/t/lib/ProFTPD/Tests/Modules/mod_sql_sqlite.pm
134+++ b/tests/t/lib/ProFTPD/Tests/Modules/mod_sql_sqlite.pm
135@@ -467,6 +467,11 @@ my $TESTS = {
136 order => ++$order,
137 test_class => [qw(forking bug mod_tls)],
138 },
139+
140+ sql_user_info_no_suppl_groups_issue1830 => {
141+ order => ++$order,
142+ test_class => [qw(forking bug rootprivs)],
143+ },
144 };
145
146 sub new {
147@@ -15732,4 +15737,174 @@ EOC
148 test_cleanup($setup->{log_file}, $ex);
149 }
150
151+sub sql_user_info_no_suppl_groups_issue1830 {
152+ my $self = shift;
153+ my $tmpdir = $self->{tmpdir};
154+ my $setup = test_setup($tmpdir, 'sqlite');
155+
156+ my $db_file = File::Spec->rel2abs("$tmpdir/proftpd.db");
157+
158+ # Build up sqlite3 command to create users, groups tables and populate them
159+ my $db_script = File::Spec->rel2abs("$tmpdir/proftpd.sql");
160+
161+ if (open(my $fh, "> $db_script")) {
162+ print $fh <<EOS;
163+CREATE TABLE users (
164+ userid TEXT,
165+ passwd TEXT,
166+ uid INTEGER,
167+ gid INTEGER,
168+ homedir TEXT,
169+ shell TEXT
170+);
171+INSERT INTO users (userid, passwd, uid, gid, homedir, shell) VALUES ('$setup->{user}', '$setup->{passwd}', $setup->{uid}, $setup->{gid}, '$setup->{home_dir}', '/bin/bash');
172+
173+CREATE TABLE groups (
174+ groupname TEXT,
175+ gid INTEGER,
176+ members TEXT
177+);
178+INSERT INTO groups (groupname, gid, members) VALUES ('$setup->{group}', $setup->{gid}, '$setup->{user}');
179+EOS
180+
181+ unless (close($fh)) {
182+ die("Can't write $db_script: $!");
183+ }
184+
185+ } else {
186+ die("Can't open $db_script: $!");
187+ }
188+
189+ my $cmd = "sqlite3 $db_file < $db_script";
190+ build_db($cmd, $db_script);
191+
192+ # Make sure that, if we're running as root, the database file has
193+ # the permissions/privs set for use by proftpd
194+ if ($< == 0) {
195+ unless (chmod(0666, $db_file)) {
196+ die("Can't set perms on $db_file to 0666: $!");
197+ }
198+ }
199+
200+ my $config = {
201+ PidFile => $setup->{pid_file},
202+ ScoreboardFile => $setup->{scoreboard_file},
203+ SystemLog => $setup->{log_file},
204+ TraceLog => $setup->{log_file},
205+ Trace => 'auth:20 sql:20',
206+
207+ # Required for logging the expected message
208+ DebugLevel => 5,
209+
210+ IfModules => {
211+ 'mod_delay.c' => {
212+ DelayEngine => 'off',
213+ },
214+
215+ 'mod_sql.c' => {
216+ AuthOrder => 'mod_sql.c',
217+
218+ SQLAuthenticate => 'users',
219+ SQLAuthTypes => 'plaintext',
220+ SQLBackend => 'sqlite3',
221+ SQLConnectInfo => $db_file,
222+ SQLLogFile => $setup->{log_file},
223+
224+ # Set these, so that our lower UID/GID will be used
225+ SQLMinUserUID => 100,
226+ SQLMinUserGID => 100,
227+ },
228+ },
229+ };
230+
231+ my ($port, $config_user, $config_group) = config_write($setup->{config_file},
232+ $config);
233+
234+ # Open pipes, for use between the parent and child processes. Specifically,
235+ # the child will indicate when it's done with its test by writing a message
236+ # to the parent.
237+ my ($rfh, $wfh);
238+ unless (pipe($rfh, $wfh)) {
239+ die("Can't open pipe: $!");
240+ }
241+
242+ my $ex;
243+
244+ # Fork child
245+ $self->handle_sigchld();
246+ defined(my $pid = fork()) or die("Can't fork: $!");
247+ if ($pid) {
248+ eval {
249+ sleep(2);
250+
251+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
252+ $client->login($setup->{user}, $setup->{passwd});
253+
254+ my $resp_msgs = $client->response_msgs();
255+ my $nmsgs = scalar(@$resp_msgs);
256+
257+ my $expected = 1;
258+ $self->assert($expected == $nmsgs,
259+ test_msg("Expected $expected, got $nmsgs"));
260+
261+ $expected = "User $setup->{user} logged in";
262+ $self->assert($expected eq $resp_msgs->[0],
263+ test_msg("Expected response '$expected', got '$resp_msgs->[0]'"));
264+
265+ $client->quit();
266+ };
267+ if ($@) {
268+ $ex = $@;
269+ }
270+
271+ $wfh->print("done\n");
272+ $wfh->flush();
273+
274+ } else {
275+ eval { server_wait($setup->{config_file}, $rfh) };
276+ if ($@) {
277+ warn($@);
278+ exit 1;
279+ }
280+
281+ exit 0;
282+ }
283+
284+ # Stop server
285+ server_stop($setup->{pid_file});
286+ $self->assert_child_ok($pid);
287+
288+ eval {
289+ if (open(my $fh, "< $setup->{log_file}")) {
290+ my $ok = 0;
291+
292+ while (my $line = <$fh>) {
293+ chomp($line);
294+
295+ if ($ENV{TEST_VERBOSE}) {
296+ print STDERR "# $line\n";
297+ }
298+
299+ if ($line =~ /no supplemental groups found for user '$setup->{user}', using primary group/) {
300+ $ok = 1;
301+ last;
302+ }
303+ }
304+
305+ close($fh);
306+
307+ $self->assert($ok, test_msg("Did not see expected log message"));
308+
309+ } else {
310+ die("Can't read $setup->{log_file}: $!");
311+ }
312+ };
313+ if ($@) {
314+ $ex = $@ unless $ex;
315+ }
316+
317+ test_cleanup($setup->{log_file}, $ex);
318+}
319+
320+
321 1;
diff --git a/meta-networking/recipes-daemons/proftpd/proftpd_1.3.7c.bb b/meta-networking/recipes-daemons/proftpd/proftpd_1.3.7c.bb
index c8097a14b0..345c714a52 100644
--- a/meta-networking/recipes-daemons/proftpd/proftpd_1.3.7c.bb
+++ b/meta-networking/recipes-daemons/proftpd/proftpd_1.3.7c.bb
@@ -12,12 +12,13 @@ SRC_URI = "git://github.com/proftpd/proftpd.git;branch=${BRANCH};protocol=https
12 file://proftpd-basic.init \ 12 file://proftpd-basic.init \
13 file://default \ 13 file://default \
14 file://close-RequireValidShell-check.patch \ 14 file://close-RequireValidShell-check.patch \
15 file://contrib.patch \ 15 file://contrib.patch \
16 file://build_fixup.patch \ 16 file://build_fixup.patch \
17 file://proftpd.service \ 17 file://proftpd.service \
18 file://CVE-2023-51713.patch \ 18 file://CVE-2023-51713.patch \
19 file://CVE-2024-57392.patch \ 19 file://CVE-2024-57392.patch \
20 file://CVE-2023-48795.patch \ 20 file://CVE-2023-48795.patch \
21 file://CVE-2024-48651.patch \
21 " 22 "
22 23
23S = "${WORKDIR}/git" 24S = "${WORKDIR}/git"