glibc/sysdeps/unix/sysv/linux
Siddhesh Poyarekar 23e0e8f5f1 getcwd: Set errno to ERANGE for size == 1 (CVE-2021-3999)
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>
2022-01-24 11:00:17 +05:30
..
aarch64
alpha
arc
arm
bits
csky
generic
hppa
i386
ia64
include
m68k
microblaze
mips
net
netash
netatalk
netax25
neteconet
netinet
netipx
netiucv
netpacket
netrom
netrose
nfs
nios2
or1k
powerpc
riscv
s390
scsi
sh
sparc
sys
wordsize-64
x86
x86_64
Implies
Makefile getcwd: Set errno to ERANGE for size == 1 (CVE-2021-3999) 2022-01-24 11:00:17 +05:30
Versions
_G_config.h
_exit.c
a.out.h
accept.c
accept4.c
access.c
adjtime.c
adjtimex.c
aio_misc.h
aio_sigqueue.c
alphasort64.c
arch-fd_to_filename.h
arch-fork.h
bind.c
brk.c
check_native.c
check_pf.c
clock.c
clock_adjtime.c
clock_getcpuclockid.c
clock_getres.c
clock_gettime.c
clock_nanosleep.c
clock_settime.c
clone-internal.c
clone3.c
clone3.h
close.c
close_nocancel.c
closedir.c
closefrom_fallback.c
cmsg_nxthdr.c
cnd_timedwait.c
configure
configure.ac
connect.c
convert_scm_timestamps.c
copy_file_range.c
creat.c
creat64.c
default-sched.h
device-nrs.h
dirfd.c
dirstream.h
dl-diagnostics-kernel.c
dl-execstack.c
dl-execve.h
dl-fxstatat64.c
dl-getcwd.c
dl-librecon.h
dl-openat64.c
dl-opendir.c
dl-origin.c
dl-osinfo.h
dl-sbrk.c
dl-sysdep.c
dl-sysdep.h
dl-vdso-setup.c
dl-vdso-setup.h
dl-vdso.h
dl-write.c
dl-writev.h
epoll_pwait.c
epoll_pwait2.c
epoll_wait.c
errlist-compat.c
errlist-compat.h
errqueue.h
eventfd_read.c
eventfd_write.c
execveat.c
faccessat.c
fallocate.c
fallocate64.c
fanotify_mark.c
fatal-prepare.h
fchmodat.c
fcntl.c
fcntl64.c
fcntl_nocancel.c
fdatasync.c
fdopendir.c
features-time64.h
fexecve.c
filter-nr-syscalls.awk
fips-private.h
fixup-asm-unistd.h
fpathconf.c
fstat.c
fstat64.c
fstatat.c
fstatat64.c
fstatfs.c
fstatfs64.c
fstatvfs.c
fstatvfs64.c
fsync.c
ftime.c
ftruncate.c
ftruncate64.c
futimens.c
futimes.c
futimesat.c
fxstat.c
fxstat64.c
fxstatat.c
fxstatat64.c
gai_sigqueue.c
gen-syscall-h.awk
gentempfd.c
getclktck.c
getcpu.c
getcwd.c
getdents.c
getdents64.c
getdirentries.c
getdirentries64.c
getdtsz.c
getentropy.c
gethostid.c
getipv4sourcefilter.c
getitimer.c
getloadavg.c
getlogin.c
getlogin_r.c
getpagesize.c
getpeername.c
getpriority.c
getpt.c
getrandom.c
getrlimit.c
getrlimit64.c
getrusage.c
getsockname.c
getsockopt.c
getsourcefilter.c
getsourcefilter.h
getsysstats.c
gettimeofday.c
glibcsyscalls.py
glob-lstat-compat.c
glob.c
glob64-lstat-compat.c
glob64-time64.c
glob64.c
globfree.c
globfree64-time64.c
globfree64.c
grantpt.c
if_index.c
ifaddrs.c
ifreq.c
internal-ioctl.h
internal-signals.h
internal_statvfs.c
internal_statvfs.h
ioctl.c
ipc_ops.h
ipc_priv.h
kernel-features.h
kernel-posix-cpu-timers.h
kernel-posix-timers.h
kernel_sigaction.h
kernel_stat.h
kernel_termios.h
kstat_cp.h
ldd-rewrite.sed
lddlibc4.c
ldsodefs.h
libc-vdso.h
libc_fatal.c
libc_sigaction.c
librt-compat.c
linux_fsinfo.h
listen.c
local-setxid.h
lseek.c
lseek64.c
lstat.c
lstat64.c
lutimes.c
lxstat.c
lxstat64.c
machine-sp.h
malloc-hugepages.c
malloc-sysdep.h
mknodat.c
mlock2.c
mmap.c
mmap64.c
mmap_internal.h
mq_close.c
mq_getattr.c
mq_notify.c
mq_open.c
mq_receive.c
mq_send.c
mq_setattr.c
mq_timedreceive.c
mq_timedsend.c
mq_unlink.c
mremap.c
msgctl.c
msgget.c
msgrcv.c
msgsnd.c
msync.c
mtx_timedlock.c
nanosleep.c
netlink_assert_response.c
netlinkaccess.h
nice.c
not-cancel.h
not-errno.h
nscd_setup_thread.c
ntp_gettime.c
ntp_gettimex.c
olddirent.h
oldglob.c
open.c
open64.c
open64_nocancel.c
open_by_handle_at.c
open_nocancel.c
openat.c
openat64.c
openat64_nocancel.c
openat_nocancel.c
opendir.c
pathconf.c
pathconf.h
paths.h
pause.c
personality.c
pipe.c
pkey_get.c
pkey_mprotect.c
pkey_set.c
poll.c
posix_fadvise.c
posix_fadvise64.c
posix_fallocate.c
posix_fallocate64.c
posix_madvise.c
ppoll.c
prctl.c
pread.c
pread64.c
pread64_nocancel.c
preadv.c
preadv2.c
preadv64.c
preadv64v2.c
prlimit.c
prlimit64.c
process_vm_readv.c
process_vm_writev.c
prof-freq.c
profil-counter.h
profil.c
pselect.c
pselect32.c
ptrace.c
ptsname.c
pwrite.c
pwrite64.c
pwritev.c
pwritev2.c
pwritev64.c
pwritev64v2.c
read.c
read_nocancel.c
readahead.c
readdir.c
readdir64.c
readdir64_r.c
readdir_r.c
readonly-area.c
readv.c
reboot.c
recv.c
recvfrom.c
recvmmsg.c
recvmsg.c
remove.c
rename.c
renameat.c
renameat2.c
rewinddir.c
rseq-internal.h
sa_len.c
safe-fatal.h
scandir64.c
sched_getaffinity.c
sched_getcpu.c
sched_rr_gi.c
sched_setaffinity.c
seekdir.c
select.c
semctl.c
semget.c
semop.c
semtimedop.c
send.c
sendmmsg.c
sendmsg.c
sendto.c
setegid.c
seteuid.c
setgid.c
setgroups.c
sethostid.c
setipv4sourcefilter.c
setitimer.c
setregid.c
setresgid.c
setresuid.c
setreuid.c
setrlimit.c
setrlimit64.c
setsockopt.c
setsourcefilter.c
settimeofday.c
settimezone.c
setuid.c
shlib-versions
shmat.c
shmctl.c
shmdt.c
shmget.c
shutdown.c
siglist-compat.c
signal.c
signalfd.c
sigpending.c
sigprocmask.c
sigqueue.c
sigreturn.c
sigset-cvt-mask.h
sigsetops.h
sigstack.c
sigsuspend.c
sigtimedwait.c
sigwait.c
sigwaitinfo.c
single-thread.h
sizes.h
socket-constants-time64.h
socket.c
socketcall.h
socketpair.c
spawn_int_def.h
spawni.c
speed.c
splice.c
stat.c
stat64.c
stat_t64_cp.c
stat_t64_cp.h
statfs.c
statfs64.c
statvfs.c
statvfs64.c
statx.c
statx_cp.c
statx_cp.h
struct_kernel_msqid64_ds.h
struct_kernel_semid64_ds.h
struct_kernel_shmid64_ds.h
struct_stat_time64.h
sync_file_range.c
syscall-names.list
syscall.c
syscalls.list
sysconf-pthread_stack_min.h
sysconf-sigstksz.h
sysconf.c
sysctl.c
sysdep-cancel.h
sysdep-vdso.h
sysdep.h
tcdrain.c
tcflow.c
tcflush.c
tcgetattr.c
tcgetpgrp.c
tcsendbrk.c
tcsetattr.c
tcsetpgrp.c
tee.c
telldir.c
termio.h
test-errno-linux.c
thrd_priv.h
thrd_sleep.c
time-clockid.h
time.c
timer_create.c
timer_delete.c
timer_getoverr.c
timer_gettime.c
timer_routines.c
timer_settime.c
timer_t_was_int_compat.h
timerfd_gettime.c
timerfd_settime.c
times.c
timespec_get.c
timespec_getres.c
tls-internal.c
tls-internal.h
truncate.c
truncate64.c
tst-adjtimex-time64.c
tst-adjtimex.c
tst-affinity-pid.c
tst-affinity-static.c
tst-affinity.c
tst-align-clone-internal.c
tst-align-clone.c
tst-clock_adjtime-time64.c
tst-clock_adjtime.c
tst-clock_gettime-clobber.c
tst-clone.c
tst-clone2-internal.c
tst-clone2.c
tst-clone3-internal.c
tst-clone3.c
tst-epoll-time64.c
tst-epoll.c
tst-fallocate-common.c
tst-fallocate.c
tst-fallocate64.c
tst-fanotify.c
tst-getcwd-smallbuff.c
tst-getdents64.c
tst-getpid1-internal.c
tst-getpid1.c
tst-gettid-kill.c
tst-gettid.c
tst-gettimeofday-clobber.c
tst-glibcsyscalls.py
tst-memfd_create.c
tst-misalign-clone-internal.c
tst-misalign-clone.c
tst-mlock2.c
tst-mman-consts.py
tst-ntp_adjtime-time64.c
tst-ntp_adjtime.c
tst-ntp_gettime-time64.c
tst-ntp_gettime.c
tst-ntp_gettimex-time64.c
tst-ntp_gettimex.c
tst-o_path-locks.c
tst-ofdlocks-compat.c
tst-ofdlocks.c
tst-personality.c
tst-pkey.c
tst-ppoll-time64.c
tst-ppoll.c
tst-prctl-time64.c
tst-prctl.c
tst-quota.c
tst-readdir64-compat.c
tst-rlimit-infinity.c
tst-rseq-disable.c
tst-rseq-nptl.c
tst-rseq.c
tst-rseq.h
tst-scm_rights-time64.c
tst-scm_rights.c
tst-sigcontext-get_pc.c
tst-signal-numbers.py
tst-sigtimedwait-time64.c
tst-sigtimedwait.c
tst-skeleton-affinity.c
tst-skeleton-thread-affinity.c
tst-socket-consts.py
tst-sync_file_range.c
tst-syscall-list.sh
tst-sysconf-iov_max-uapi.c
tst-sysconf-iov_max.c
tst-sysvmsg-linux.c
tst-sysvsem-linux.c
tst-sysvshm-linux.c
tst-tgkill.c
tst-time-clobber.c
tst-timerfd-time64.c
tst-timerfd.c
tst-ttyname.c
ttyname.c
ttyname.h
ttyname_r.c
tv32-compat.h
ualarm.c
umount.c
umount2.c
unlockpt.c
update-syscall-lists.py
updwtmp.c
ustat.c
utime.c
utimensat.c
utimes.c
utmp_file.c
versionsort64.c
vfork.c
vmsplice.c
wait3.c
wait4.c
waitid.c
write.c
write_nocancel.c
writev.c
xmknod.c
xmknodat.c
xstat.c
xstat64.c
xstatconv.c
xstatconv.h
xstatover.h
xstatver.h