[PATCH 3/3] getcwd: Set errno to ERANGE for size == 1 (CVE-2021-3999)
Siddhesh Poyarekar
siddhesh@sourceware.org
Tue Jan 18 14:40:41 GMT 2022
On 18/01/2022 19:27, Andreas Schwab wrote:
> On Jan 18 2022, Siddhesh Poyarekar wrote:
>
>> Without the patch
>
> What's your point? I don't understand what you are trying to say.
>
Let me start over.
getcwd in its current form may underflow and overflow the user supplied
buffer 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 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 fix avoids the underflow+overflow by shortcircuiting early and
returns NULL, setting errno to ERANGE for 1 byte buffers because they
can never be reasonably used to return a valid path.
Siddhesh
More information about the Libc-alpha
mailing list