getcwd: Set errno to ERANGE for size == 1 (CVE-2021-3999)

Cherry-picked from 23e0e8f5f1 in main branch.
Test included with this commit is not cherry-picked because it requires more
changes.

No valid path returned by getcwd would fit into 1 byte, so reject the
size early and return NULL with errno set to ERANGE.  This change is
prompted by CVE-2021-3999, which describes a single byte buffer
underflow and overflow when all of the following conditions are met:

- The buffer size (i.e. the second argument of getcwd) is 1 byte
- The current working directory is too long
- '/' is also mounted on the current working directory

Sequence of events:

- In sysdeps/unix/sysv/linux/getcwd.c, the syscall returns ENAMETOOLONG
  because the linux kernel checks for name length before it checks
  buffer size

- The code falls back to the generic getcwd in sysdeps/posix

- In the generic func, the buf[0] is set to '\0' on line 250

- this while loop on line 262 is bypassed:

    while (!(thisdev == rootdev && thisino == rootino))

  since the rootfs (/) is bind mounted onto the directory and the flow
  goes on to line 449, where it puts a '/' in the byte before the
  buffer.

- Finally on line 458, it moves 2 bytes (the underflowed byte and the
  '\0') to the buf[0] and buf[1], resulting in a 1 byte buffer overflow.

- buf is returned on line 469 and errno is not set.

This resolves BZ #28769.

Reviewed-by: Andreas Schwab <schwab@linux-m68k.org>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
Signed-off-by: Qualys Security Advisory <qsa@qualys.com>
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
This commit is contained in:
Siddhesh Poyarekar 2022-01-21 23:32:56 +05:30 committed by Pranav Kant
parent ac5b880423
commit 5643a977d0
2 changed files with 14 additions and 0 deletions

6
NEWS
View File

@ -28,6 +28,12 @@ Deprecated and removed features, and other changes affecting compatibility:
Security related changes: Security related changes:
CVE-2021-3999: Passing a buffer of size exactly 1 byte to the getcwd
function may result in an off-by-one buffer underflow and overflow
when the current working directory is longer than PATH_MAX and also
corresponds to the / directory through an unprivileged mount
namespace. Reported by Qualys.
CVE-2016-10739: The getaddrinfo function could successfully parse IPv4 CVE-2016-10739: The getaddrinfo function could successfully parse IPv4
addresses with arbitrary trailing characters, potentially leading to data addresses with arbitrary trailing characters, potentially leading to data
or command injection issues in applications. or command injection issues in applications.

View File

@ -241,6 +241,14 @@ __getcwd (char *buf, size_t size)
char *path; char *path;
#ifndef NO_ALLOCATION #ifndef NO_ALLOCATION
size_t allocated = size; size_t allocated = size;
/* A size of 1 byte is never useful. */
if (allocated == 1)
{
__set_errno (ERANGE);
return NULL;
}
if (size == 0) if (size == 0)
{ {
if (buf != NULL) if (buf != NULL)