mirror of
git://sourceware.org/git/glibc.git
synced 2024-12-09 04:11:27 +08:00
472e799a5f
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>
(cherry picked from commit
|
||
---|---|---|
.. | ||
alarm.c | ||
clock_getres.c | ||
clock.c | ||
ctermid.c | ||
cuserid.c | ||
dl-fileid.h | ||
dup2.c | ||
dup.c | ||
euidaccess.c | ||
flock.c | ||
fpathconf.c | ||
gai_strerror-strs.h | ||
gai_strerror.c | ||
getaddrinfo.c | ||
getcwd.c | ||
getdtsz.c | ||
gethostname.c | ||
getpagesize.c | ||
isatty.c | ||
isfdtype.c | ||
killpg.c | ||
libc_fatal.c | ||
Makefile | ||
mkfifo.c | ||
mkfifoat.c | ||
nice.c | ||
open64.c | ||
pathconf.c | ||
pause.c | ||
posix_fallocate64.c | ||
posix_fallocate.c | ||
pread64.c | ||
pread.c | ||
preadv2.c | ||
preadv64.c | ||
preadv64v2.c | ||
preadv_common.c | ||
preadv.c | ||
profil.c | ||
pwrite64.c | ||
pwrite.c | ||
pwritev2.c | ||
pwritev64.c | ||
pwritev64v2.c | ||
pwritev_common.c | ||
pwritev.c | ||
raise.c | ||
readv.c | ||
remove.c | ||
rename.c | ||
sigblock.c | ||
sigignore.c | ||
sigintr.c | ||
signal.c | ||
sigpause.c | ||
sigset.c | ||
sigsetmask.c | ||
sigsuspend.c | ||
sigwait.c | ||
sleep.c | ||
spawni.c | ||
sprofil.c | ||
Subdirs | ||
sysconf-pthread_stack_min.h | ||
sysconf.c | ||
system.c | ||
sysv_signal.c | ||
tempname.c | ||
truncate.c | ||
ttyname_r.c | ||
ttyname.c | ||
ulimit.c | ||
usleep.c | ||
utime.c | ||
utimes.c | ||
writev_nocancel.c | ||
writev.c |