mirror of
https://abf.rosa.ru/djam/glibc.git
synced 2025-02-23 15:02:47 +00:00
67 lines
2.5 KiB
Diff
67 lines
2.5 KiB
Diff
From 52a713fdd0a30e1bd79818e2e3c4ab44ddca1a94 Mon Sep 17 00:00:00 2001
|
|
From: "Dmitry V. Levin" <ldv@altlinux.org>
|
|
Date: Sun, 7 Jan 2018 02:03:41 +0000
|
|
Subject: [PATCH] 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.
|
|
---
|
|
ChangeLog | 9 ++++++
|
|
NEWS | 4 +++
|
|
io/Makefile | 2 +-
|
|
io/tst-getcwd-abspath.c | 66 ++++++++++++++++++++++++++++++++++++++++
|
|
sysdeps/unix/sysv/linux/getcwd.c | 8 ++---
|
|
5 files changed, 84 insertions(+), 5 deletions(-)
|
|
create mode 100644 io/tst-getcwd-abspath.c
|
|
|
|
diff --git a/sysdeps/unix/sysv/linux/getcwd.c b/sysdeps/unix/sysv/linux/getcwd.c
|
|
index f545106..866b9d2 100644
|
|
--- a/sysdeps/unix/sysv/linux/getcwd.c
|
|
+++ b/sysdeps/unix/sysv/linux/getcwd.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)
|
|
--
|
|
2.9.3
|
|
|