Re:Fw:[PATCH] inet: add boundary check to prevent bof and inet/tst-ruserpass [BZ #33881]
c.colonna
c.colonna@itdoctor.it
Thu Mar 12 11:10:16 GMT 2026
As an update,
following the indication received in the irssi chat, pointing me to this repo https://gitlab.com/djdelorie/glibc-cicd.
I managed to replicate the cicd locally and reproduce the exact same error.
As a next step I try to make some cli script to automate running the ci in glibc-cicd locally on a patch and try to isolate exactly the failing test.
This could speed up the troubleshooting problem and moreover ensure that the code is reproduced exactly in the same environment
From "c.colonna" c.colonna@itdoctor.it
To arjun@redhat.com
Cc
Date Wed, 11 Mar 2026 14:55:11 +0100
Subject Fw:[PATCH] inet: add boundary check to prevent bof and inet/tst-ruserpass [BZ #33881]
Good morning,
I submitted this patch for glibc.
I encountered some errors during CI:
https://patchwork.sourceware.org/project/glibc/patch/20260306135229.2082046-1-c.colonna@itdoctor.it/
one of them is a simple lint failure on the Makefile:
https://www.delorie.com/trybots/32bit/58484/lint-makefiles.out
FAIL: lint-makefiles
original exit status 1
--- /home/tcwg-build/workspace/tcwg_gnu_4/glibc/inet/Makefile.expected
+++ /home/tcwg-build/workspace/tcwg_gnu_4/glibc/inet/Makefile 2026-03-06 17:27:16.587191199 +0000
@@ -97,8 +97,8 @@
tst-inet6_rth \
tst-network \
tst-ntoa \
- tst-ruserpass \
tst-sockaddr \
+ tst-ruserpass \
# tests
I can fix this easily.
The other one is a problem in the test itself:
https://www.delorie.com/trybots/32bit/58484/inet-tst-ruserpass.out
Didn't expect signal from child: got `Aborted'
I saw this message is produced by the test harness. I can suppose that something or someone aborted the test.
One of my hypothesis is that maybe the failure on the other test (the lint), stopped the CI and cause this test being aborted. This is only a supposition I've no complete view of what ci do.
In my local environment the test pass.
Another problem might be that the test code tweaks with test files (e.g. .netrc) and env to trigger the logic the fix was written for. E.g. $HOME env var is set to point to the temporary file. Not knowing how much are isolated these tests, I cannot exclude that what pass in local environment fails in the CI maybe due to concurrent test execution in same environment.
I wonder if, can I fix the Makefile lint error and submit the patch again to check if the other error disappear?
This would at least exclude the correlation between those two regressions.
Meanwhile, i'm also playing with ci code https://gitlab.com/djdelorie/glibc-cicd
trying to reproduce locally the exact same env and code that lead to the regression.
In that case I could debug the abortion in a local env.
Thanks
From "Christian Colonna" c.colonna@itdoctor.it
To libc-alpha@sourceware.org
Cc "Christian Colonna" c.colonna@itdoctor.it
Date Fri, 6 Mar 2026 14:52:29 +0100
Subject [PATCH] inet: add boundary check to prevent bof and inet/tst-ruserpass [BZ #33881]
Add boundary checks in the token function parsing .netrc config file.
If token was too long, the buffer storing token could overflow.
Add test creating .netrc file with a long token and verify that ruserpass doesn't cause SEGFAULT.
Add additional test to verify that when permission of .netrc are not 0600 ruserpass returns -1.
Signed-off-by: Christian Colonna <c.colonna@itdoctor.it>
---
inet/Makefile | 1 +
inet/ruserpass.c | 12 ++++--
inet/tst-ruserpass.c | 87 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 96 insertions(+), 4 deletions(-)
create mode 100644 inet/tst-ruserpass.c
diff --git a/inet/Makefile b/inet/Makefile
index 613f61d290..caeb1b0801 100644
--- a/inet/Makefile
+++ b/inet/Makefile
@@ -98,6 +98,7 @@ tests := \
tst-network \
tst-ntoa \
tst-sockaddr \
+ tst-ruserpass \
# tests
# tst-deadline must be linked statically so that we can access
diff --git a/inet/ruserpass.c b/inet/ruserpass.c
index be4e024203..22d835a0c1 100644
--- a/inet/ruserpass.c
+++ b/inet/ruserpass.c
@@ -54,7 +54,9 @@ static FILE *cfile;
#define ID 10
#define MACHINE 11
-static char tokval[100];
+#define TOKVAL_SIZE 100
+
+static char tokval[TOKVAL_SIZE];
static const char tokstr[] =
{
@@ -229,7 +231,8 @@ token (void)
while ((c = getc_unlocked(cfile)) != EOF && c != '"') {
if (c == '\\')
c = getc_unlocked(cfile);
- *cp++ = c;
+ if (cp-tokval < TOKVAL_SIZE)
+ *cp++ = c;
}
} else {
*cp++ = c;
@@ -237,7 +240,8 @@ token (void)
&& c != '\n' && c != '\t' && c != ' ' && c != ',') {
if (c == '\\')
c = getc_unlocked(cfile);
- *cp++ = c;
+ if (cp-tokval < TOKVAL_SIZE)
+ *cp++ = c;
}
}
*cp = 0;
@@ -247,4 +251,4 @@ token (void)
if (!strcmp(&tokstr[toktab[i].tokstr_off], tokval))
return toktab[i].tval;
return (ID);
-}
+}
\ No newline at end of file
diff --git a/inet/tst-ruserpass.c b/inet/tst-ruserpass.c
new file mode 100644
index 0000000000..7edcf56434
--- /dev/null
+++ b/inet/tst-ruserpass.c
@@ -0,0 +1,87 @@
+/* Test for ruserpass.
+ Copyright (C) 2026-2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/temp_file.h>
+
+
+static char *temp_home_dir;
+static char *temp_netrc;
+
+extern int ruserpass (const char *host, const char **aname, const char **apass);
+
+static void
+generate_string_a (char * str, size_t len)
+{
+ memset (str, 'a', len);
+ str[len] = '\0';
+}
+
+static void
+do_prepare (int argc, char **argv)
+{
+ char temp_password[200];
+
+ // creating a .netrc file for testing. In ruserpass the file is accessed relative to $HOME env, we will tweak $HOME to use our test file
+ temp_home_dir = support_create_temp_directory ("tst-ruserpass-");
+ temp_netrc = xasprintf ("%s/.netrc", temp_home_dir);
+ add_temp_file (temp_netrc);
+
+ generate_string_a(temp_password, sizeof(temp_password) - 1);
+
+ char * netrc_content = xasprintf ("machine foo.gnu login foo password %s\n", temp_password);
+
+ support_write_file_string (temp_netrc, netrc_content);
+
+ free (netrc_content);
+}
+
+#define PREPARE do_prepare
+
+static int
+do_test (void)
+{
+ const char *orig_name = NULL;
+ const char *orig_pass = NULL;
+
+ if (access (temp_netrc, R_OK) != 0)
+ FAIL_EXIT1 ("File .netrc is not readable");
+ setenv ("HOME", temp_home_dir, 1);
+
+ // function should returns -1 if .netrc file permission is readable by others
+ TEST_COMPARE (ruserpass ("foo.gnu", &orig_name, &orig_pass), -1);
+
+
+ if (chmod (temp_netrc, S_IRUSR | S_IWUSR) != 0)
+ FAIL_EXIT1 ("Impossible to set .netrc permissions. We need it to be 0600 else ruserpass will exit -1.");
+
+ // ruserpass should not segfault if password is longer than password tokval buffer
+ TEST_COMPARE (ruserpass ("foo.gnu", &orig_name, &orig_pass), EXIT_SUCCESS);
+
+ free (temp_home_dir);
+ free (temp_netrc);
+
+ return EXIT_SUCCESS;
+}
+
+#include <support/test-driver.c>
\ No newline at end of file
--
2.39.5
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20260312/29b600ca/attachment-0001.htm>
More information about the Libc-alpha
mailing list