diff options
author | Florian Weimer <fweimer@redhat.com> | 2017-02-27 19:05:13 +0100 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2017-02-27 19:05:13 +0100 |
commit | d42eed4a044e5e10dfb885cf9891c2518a72a491 (patch) | |
tree | 29deb103217e1b09902f05cf49029a93cb76ad1a /sunrpc/tst-udp-error.c | |
parent | 963394a22b38c4ec92b6875a6c06d3b15d5c0d21 (diff) | |
download | glibc-d42eed4a044e5e10dfb885cf9891c2518a72a491.tar.gz |
sunrpc: Avoid use-after-free read access in clntudp_call [BZ #21115]
After commit bc779a1a5b3035133024b21e2f339fe4219fb11c
(CVE-2016-4429: sunrpc: Do not use alloca in clntudp_call
[BZ #20112]), ancillary data is stored on the heap,
but it is accessed after it has been freed.
The test case must be run under a heap debugger such as valgrind
to observe the invalid access. A malloc implementation which
immediately calls munmap on free would catch this bug as well.
Diffstat (limited to 'sunrpc/tst-udp-error.c')
-rw-r--r-- | sunrpc/tst-udp-error.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/sunrpc/tst-udp-error.c b/sunrpc/tst-udp-error.c new file mode 100644 index 0000000000..1efc02f5c6 --- /dev/null +++ b/sunrpc/tst-udp-error.c @@ -0,0 +1,62 @@ +/* Check for use-after-free in clntudp_call (bug 21115). + Copyright (C) 2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <netinet/in.h> +#include <rpc/clnt.h> +#include <rpc/svc.h> +#include <support/check.h> +#include <support/namespace.h> +#include <support/xsocket.h> +#include <unistd.h> + +static int +do_test (void) +{ + support_become_root (); + support_enter_network_namespace (); + + /* Obtain a likely-unused port number. */ + struct sockaddr_in sin = + { + .sin_family = AF_INET, + .sin_addr.s_addr = htonl (INADDR_LOOPBACK), + }; + { + int fd = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + xbind (fd, (struct sockaddr *) &sin, sizeof (sin)); + socklen_t sinlen = sizeof (sin); + xgetsockname (fd, (struct sockaddr *) &sin, &sinlen); + /* Close the socket, so that we will receive an error below. */ + close (fd); + } + + int sock = RPC_ANYSOCK; + CLIENT *clnt = clntudp_create + (&sin, 1, 2, (struct timeval) { 1, 0 }, &sock); + TEST_VERIFY_EXIT (clnt != NULL); + TEST_VERIFY (clnt_call (clnt, 3, + (xdrproc_t) xdr_void, NULL, + (xdrproc_t) xdr_void, NULL, + ((struct timeval) { 3, 0 })) + == RPC_CANTRECV); + clnt_destroy (clnt); + + return 0; +} + +#include <support/test-driver.c> |