[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