mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-08 14:20:07 +00:00
linux: make getcwd(3) fail if it cannot obtain an absolute path [BZ #22679]
Currently getcwd(3) can succeed without returning an absolute path because the underlying getcwd syscall, starting with linux commit v2.6.36-rc1~96^2~2, may succeed without returning an absolute path. This is a conformance issue because "The getcwd() function shall place an absolute pathname of the current working directory in the array pointed to by buf, and return buf". This is also a security issue because a non-absolute path returned by getcwd(3) causes a buffer underflow in realpath(3). Fix this by checking the path returned by getcwd syscall and falling back to generic_getcwd if the path is not absolute, effectively making getcwd(3) fail with ENOENT. The error code is chosen for consistency with the case when the current directory is unlinked. [BZ #22679] CVE-2018-1000001 * sysdeps/unix/sysv/linux/getcwd.c (__getcwd): Fall back to generic_getcwd if the path returned by getcwd syscall is not absolute. * io/tst-getcwd-abspath.c: New test. * io/Makefile (tests): Add tst-getcwd-abspath.
This commit is contained in:
parent
249a5895f1
commit
52a713fdd0
@ -1,3 +1,12 @@
|
||||
2018-01-12 Dmitry V. Levin <ldv@altlinux.org>
|
||||
|
||||
[BZ #22679]
|
||||
CVE-2018-1000001
|
||||
* sysdeps/unix/sysv/linux/getcwd.c (__getcwd): Fall back to
|
||||
generic_getcwd if the path returned by getcwd syscall is not absolute.
|
||||
* io/tst-getcwd-abspath.c: New test.
|
||||
* io/Makefile (tests): Add tst-getcwd-abspath.
|
||||
|
||||
2018-01-12 Istvan Kurucsai <pistukem@gmail.com>
|
||||
|
||||
* malloc/malloc.c (malloc_consolidate): Add size check.
|
||||
|
4
NEWS
4
NEWS
@ -199,6 +199,10 @@ Security related changes:
|
||||
for AT_SECURE or SUID binaries could be used to load libraries from the
|
||||
current directory.
|
||||
|
||||
CVE-2018-1000001: Buffer underflow in realpath function when getcwd function
|
||||
succeeds without returning an absolute path due to unexpected behaviour
|
||||
of the Linux kernel getcwd syscall. Reported by halfdog.
|
||||
|
||||
The following bugs are resolved with this release:
|
||||
|
||||
[The release manager will add the list generated by
|
||||
|
@ -71,7 +71,7 @@ tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \
|
||||
tst-mknodat tst-mkfifoat tst-ttyname_r bug-ftw5 \
|
||||
tst-posix_fallocate tst-posix_fallocate64 \
|
||||
tst-fts tst-fts-lfs tst-open-tmpfile \
|
||||
tst-copy_file_range \
|
||||
tst-copy_file_range tst-getcwd-abspath \
|
||||
|
||||
# This test includes the compat implementation of copy_file_range,
|
||||
# which uses internal, unexported libc functions.
|
||||
|
66
io/tst-getcwd-abspath.c
Normal file
66
io/tst-getcwd-abspath.c
Normal file
@ -0,0 +1,66 @@
|
||||
/* BZ #22679 getcwd(3) should not succeed without returning an absolute path.
|
||||
|
||||
Copyright (C) 2018 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 <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <support/check.h>
|
||||
#include <support/namespace.h>
|
||||
#include <support/support.h>
|
||||
#include <support/temp_file.h>
|
||||
#include <support/test-driver.h>
|
||||
#include <support/xunistd.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static char *chroot_dir;
|
||||
|
||||
/* The actual test. Run it in a subprocess, so that the test harness
|
||||
can remove the temporary directory in --direct mode. */
|
||||
static void
|
||||
getcwd_callback (void *closure)
|
||||
{
|
||||
xchroot (chroot_dir);
|
||||
|
||||
errno = 0;
|
||||
char *cwd = getcwd (NULL, 0);
|
||||
TEST_COMPARE (errno, ENOENT);
|
||||
TEST_VERIFY (cwd == NULL);
|
||||
|
||||
errno = 0;
|
||||
cwd = realpath (".", NULL);
|
||||
TEST_COMPARE (errno, ENOENT);
|
||||
TEST_VERIFY (cwd == NULL);
|
||||
|
||||
_exit (0);
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
support_become_root ();
|
||||
if (!support_can_chroot ())
|
||||
return EXIT_UNSUPPORTED;
|
||||
|
||||
chroot_dir = support_create_temp_directory ("tst-getcwd-abspath-");
|
||||
support_isolate_in_subprocess (getcwd_callback, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
@ -76,7 +76,7 @@ __getcwd (char *buf, size_t size)
|
||||
int retval;
|
||||
|
||||
retval = INLINE_SYSCALL (getcwd, 2, path, alloc_size);
|
||||
if (retval >= 0)
|
||||
if (retval > 0 && path[0] == '/')
|
||||
{
|
||||
#ifndef NO_ALLOCATION
|
||||
if (buf == NULL && size == 0)
|
||||
@ -92,10 +92,10 @@ __getcwd (char *buf, size_t size)
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* The system call cannot handle paths longer than a page.
|
||||
Neither can the magic symlink in /proc/self. Just use the
|
||||
/* The system call either cannot handle paths longer than a page
|
||||
or can succeed without returning an absolute path. Just use the
|
||||
generic implementation right away. */
|
||||
if (errno == ENAMETOOLONG)
|
||||
if (retval >= 0 || errno == ENAMETOOLONG)
|
||||
{
|
||||
#ifndef NO_ALLOCATION
|
||||
if (buf == NULL && size == 0)
|
||||
|
Loading…
Reference in New Issue
Block a user