mirror of
git://sourceware.org/git/glibc.git
synced 2025-03-06 20:58:33 +01:00
nss: Improve network number parsers (bz 32573, 32575)
Make sure that numbers never overflow uint32_t in inet_network to properly validate octets encountered in IPv4 addresses. Avoid malloca in NSS networks file code because /etc/networks lines can be arbitrarily long. Instead of handcrafting the input for inet_network by adding ".0" octets if they are missing, just left shift the result. Also, do not accept invalid entries, but ignore the line instead. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
This commit is contained in:
parent
991febc2f4
commit
6a3cb6b1bd
6 changed files with 109 additions and 14 deletions
|
@ -69,6 +69,8 @@ again:
|
||||||
if (*cp == 'x' || *cp == 'X')
|
if (*cp == 'x' || *cp == 'X')
|
||||||
digit = 0, base = 16, cp++;
|
digit = 0, base = 16, cp++;
|
||||||
while ((c = *cp) != 0) {
|
while ((c = *cp) != 0) {
|
||||||
|
if (val > 0xff)
|
||||||
|
return (INADDR_NONE);
|
||||||
if (isdigit(c)) {
|
if (isdigit(c)) {
|
||||||
if (base == 8 && (c == '8' || c == '9'))
|
if (base == 8 && (c == '8' || c == '9'))
|
||||||
return (INADDR_NONE);
|
return (INADDR_NONE);
|
||||||
|
|
|
@ -367,6 +367,7 @@ tests += tst-nss-files-hosts-multi
|
||||||
tests += tst-nss-files-hosts-getent
|
tests += tst-nss-files-hosts-getent
|
||||||
tests += tst-nss-files-alias-leak
|
tests += tst-nss-files-alias-leak
|
||||||
tests += tst-nss-files-alias-truncated
|
tests += tst-nss-files-alias-truncated
|
||||||
|
tests += tst-nss-files-network
|
||||||
# tst_fgetgrent currently only works with shared libraries
|
# tst_fgetgrent currently only works with shared libraries
|
||||||
test-srcs := tst_fgetgrent
|
test-srcs := tst_fgetgrent
|
||||||
ifeq ($(run-built-tests),yes)
|
ifeq ($(run-built-tests),yes)
|
||||||
|
|
|
@ -42,7 +42,8 @@ LINE_PARSER
|
||||||
|
|
||||||
STRING_FIELD (addr, isspace, 1);
|
STRING_FIELD (addr, isspace, 1);
|
||||||
/* 'inet_network' does not add zeroes at the end if the network number
|
/* 'inet_network' does not add zeroes at the end if the network number
|
||||||
does not four byte values. We add them ourselves if necessary. */
|
does not contain four byte values. We shift result ourselves if
|
||||||
|
necessary. */
|
||||||
cp = strchr (addr, '.');
|
cp = strchr (addr, '.');
|
||||||
if (cp != NULL)
|
if (cp != NULL)
|
||||||
{
|
{
|
||||||
|
@ -56,20 +57,11 @@ LINE_PARSER
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (n < 4)
|
|
||||||
{
|
|
||||||
char *newp = (char *) alloca (strlen (addr) + (4 - n) * 2 + 1);
|
|
||||||
cp = stpcpy (newp, addr);
|
|
||||||
do
|
|
||||||
{
|
|
||||||
*cp++ = '.';
|
|
||||||
*cp++ = '0';
|
|
||||||
}
|
|
||||||
while (++n < 4);
|
|
||||||
*cp = '\0';
|
|
||||||
addr = newp;
|
|
||||||
}
|
|
||||||
result->n_net = __inet_network (addr);
|
result->n_net = __inet_network (addr);
|
||||||
|
if (result->n_net == INADDR_NONE)
|
||||||
|
return 0;
|
||||||
|
if (n < 4)
|
||||||
|
result->n_net <<= 8 * (4 - n);
|
||||||
result->n_addrtype = AF_INET;
|
result->n_addrtype = AF_INET;
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
96
nss/tst-nss-files-network.c
Normal file
96
nss/tst-nss-files-network.c
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/* Test long entries and truncated numbers in /etc/networks (bug 32573/32575).
|
||||||
|
Copyright (C) 2025 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 <netdb.h>
|
||||||
|
#include <gnu/lib-names.h>
|
||||||
|
#include <nss.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <support/check.h>
|
||||||
|
#include <support/check_nss.h>
|
||||||
|
#include <support/namespace.h>
|
||||||
|
#include <support/test-driver.h>
|
||||||
|
#include <support/xdlfcn.h>
|
||||||
|
#include <support/xunistd.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
|
||||||
|
#define STACK_LIM 1048576
|
||||||
|
#define STRING_SIZE (2 * STACK_LIM)
|
||||||
|
|
||||||
|
struct support_chroot *chroot_env;
|
||||||
|
|
||||||
|
static void
|
||||||
|
prepare (int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char *content;
|
||||||
|
char *entry = malloc (STRING_SIZE);
|
||||||
|
struct rlimit lim;
|
||||||
|
getrlimit (RLIMIT_STACK, &lim);
|
||||||
|
lim.rlim_cur = STACK_LIM;
|
||||||
|
setrlimit (RLIMIT_STACK, &lim);
|
||||||
|
if (entry == NULL)
|
||||||
|
{
|
||||||
|
puts ("malloc failed, cannot test");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
memset (entry, 'A', STRING_SIZE);
|
||||||
|
entry[STRING_SIZE - 1] = 0;
|
||||||
|
ret = asprintf (&content, "%s\n%s\nnet3 %s\n",
|
||||||
|
"net1 x0000000000Ff.077", /* legal 255.63.0.0 */
|
||||||
|
"net2 xFF00000000.0.0.0", /* illegal */
|
||||||
|
entry /* illegal */);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
puts ("asprintf failed, cannot test");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
free (entry);
|
||||||
|
chroot_env = support_chroot_create
|
||||||
|
((struct support_chroot_configuration)
|
||||||
|
{
|
||||||
|
.networks = content
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
support_become_root ();
|
||||||
|
if (!support_can_chroot ())
|
||||||
|
return EXIT_UNSUPPORTED;
|
||||||
|
|
||||||
|
__nss_configure_lookup ("networks", "files");
|
||||||
|
xdlopen (LIBNSS_FILES_SO, RTLD_NOW);
|
||||||
|
|
||||||
|
xchroot (chroot_env->path_chroot);
|
||||||
|
|
||||||
|
check_netent ("net1", getnetbyname ("net1"),
|
||||||
|
"name: net1\n"
|
||||||
|
"net: 0xff3f0000\n");
|
||||||
|
check_netent ("net2", getnetbyname ("net2"), "error: HOST_NOT_FOUND\n");
|
||||||
|
|
||||||
|
support_chroot_free (chroot_env);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PREPARE prepare
|
||||||
|
#include <support/test-driver.c>
|
|
@ -75,6 +75,7 @@ struct support_chroot_configuration
|
||||||
const char *hosts; /* /etc/hosts. */
|
const char *hosts; /* /etc/hosts. */
|
||||||
const char *host_conf; /* /etc/host.conf. */
|
const char *host_conf; /* /etc/host.conf. */
|
||||||
const char *aliases; /* /etc/aliases. */
|
const char *aliases; /* /etc/aliases. */
|
||||||
|
const char *networks; /* /etc/networks. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The result of the creation of a chroot. */
|
/* The result of the creation of a chroot. */
|
||||||
|
@ -92,6 +93,7 @@ struct support_chroot
|
||||||
char *path_hosts; /* /etc/hosts. */
|
char *path_hosts; /* /etc/hosts. */
|
||||||
char *path_host_conf; /* /etc/host.conf. */
|
char *path_host_conf; /* /etc/host.conf. */
|
||||||
char *path_aliases; /* /etc/aliases. */
|
char *path_aliases; /* /etc/aliases. */
|
||||||
|
char *path_networks; /* /etc/networks. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Create a chroot environment. The returned data should be freed
|
/* Create a chroot environment. The returned data should be freed
|
||||||
|
|
|
@ -57,6 +57,7 @@ support_chroot_create (struct support_chroot_configuration conf)
|
||||||
write_file (path_etc, "hosts", conf.hosts, &chroot->path_hosts);
|
write_file (path_etc, "hosts", conf.hosts, &chroot->path_hosts);
|
||||||
write_file (path_etc, "host.conf", conf.host_conf, &chroot->path_host_conf);
|
write_file (path_etc, "host.conf", conf.host_conf, &chroot->path_host_conf);
|
||||||
write_file (path_etc, "aliases", conf.aliases, &chroot->path_aliases);
|
write_file (path_etc, "aliases", conf.aliases, &chroot->path_aliases);
|
||||||
|
write_file (path_etc, "networks", conf.networks, &chroot->path_networks);
|
||||||
|
|
||||||
free (path_etc);
|
free (path_etc);
|
||||||
|
|
||||||
|
@ -79,5 +80,6 @@ support_chroot_free (struct support_chroot *chroot)
|
||||||
free (chroot->path_hosts);
|
free (chroot->path_hosts);
|
||||||
free (chroot->path_host_conf);
|
free (chroot->path_host_conf);
|
||||||
free (chroot->path_aliases);
|
free (chroot->path_aliases);
|
||||||
|
free (chroot->path_networks);
|
||||||
free (chroot);
|
free (chroot);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue