[v2] inet: add boundary check to prevent bof and inet/tst-ruserpass [BZ #33881]
Checks
| Context |
Check |
Description |
| redhat-pt-bot/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
| linaro-tcwg-bot/tcwg_glibc_build--master-arm |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_glibc_check--master-arm |
success
|
Test passed
|
| redhat-pt-bot/TryBot-32bit |
success
|
Build for i686
|
| linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 |
success
|
Test passed
|
Commit Message
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 | 10 ++++--
inet/tst-ruserpass.c | 86 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 94 insertions(+), 3 deletions(-)
create mode 100644 inet/tst-ruserpass.c
@@ -97,6 +97,7 @@ tests := \
tst-inet6_rth \
tst-network \
tst-ntoa \
+ tst-ruserpass \
tst-sockaddr \
# tests
@@ -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 - 1)
+ *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 - 1)
+ *cp++ = c;
}
}
*cp = 0;
new file mode 100644
@@ -0,0 +1,86 @@
+/* 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