2.0.x kernel denial of service via VFAT longnames

Vitaly Fedrushkov (willy@snowyowl.csu.ac.ru)
Mon, 28 Sep 1998 14:50:51 +0600 (CHEL)


Good $daytime,

Sorry but I'm not a kernel expert. Not sure if this one is already
known...

I found a way to commit kernel denial of service via certain (strictly
legal) file operation(s) on vfat fs.

| willy@snowyowl:~$ uname -a
| Linux snowyowl 2.0.35 #2 Sat Aug 1 14:05:10 CHEL 1998 i586 unknown
| willy@snowyowl:~$ mount -v
| /dev/hda3 on / type ext2 (rw)
| none on /proc type proc (rw)
| /dev/hda1 on /mnt/dos/C type vfat (rw,noexec,nosuid,gid=50,umask=007,iocharset=koi8-r,codepage=866,quiet)
| /dev/hda4 on /mnt/dos/D type vfat (rw,noexec,nosuid,gid=50,umask=007,iocharset=koi8-r,codepage=866,quiet)
| willy@snowyowl:~$ (cd /tmp; time tar xzvf ~/ugu.tar.gz)
| ugu/showIresumes0002F1111111111GY.html
[snip 345 lines]
| ugu/showIresumes0591F1111111111GY.html
|
| real 0m5.510s
| user 0m0.570s
| sys 0m1.310s
[OK so far]
| willy@snowyowl:~$ (cd /mnt/dos/D/tmp; time tar xzvf ~/ugu.tar.gz)
| ugu/showIresumes0002F1111111111GY.html
[snip 345 lines]
| ugu/showIresumes0591F1111111111GY.html
|
| real 13m16.465s
| user 0m0.400s
| sys 12m23.520s

Rinning the latter, system was in very poor condition for some 13
minutes. Symptoms include almost frozen X Window (one mouse step in
30 secs), troubles with serial communications, poor response at
'nice -20'd shell, load meter at 8 to 10, and so on, you name it.

I did not attach tarball here but you surely got an idea of what it
is. File contents really doesn't matter -- only the name does. tar
is not involved either -- 'cp /tmp/ugu/* /mnt/dos/D/tmp/' will do the
same.

fs/vfat/namei.c says, around line 860:
--- 8< ---
/* Given a valid longname, create a unique shortname. Make sure the
* shortname does not exist
*/
static int vfat_create_shortname(struct inode *dir, const char *name,
int len, char *name_res, int utf8)
{
...
while (res > -1) {
/* Create the next shortname to try */
i++;
if (i == 10000000) return -EEXIST;
...
res = vfat_find(dir, msdos_name, totlen, 0, 0, 0, &sinfo);
}
--- 8< ---

Looks like it takes a somewhat long time (O(N^2) == O(N) here times
O(N) in vfat_find()) for N files with very similar long names.

Of course I checked it under (insert epithet here) Windose 95, and it
did not reproduce.

I can't think of what should be done to stop this but schedule() comes
to mind first.

Regards,
Willy.

--
"No easy hope or lies        | Vitaly "Willy the Pooh" Fedrushkov
 Shall bring us to our goal, | Information Technology Division
 But iron sacrifice          | Chelyabinsk State University
 Of Body, Will and Soul."    | mailto:willy@csu.ac.ru  +7 3512 156770
                   R.Kipling | http://www.csu.ac.ru/~willy  VVF1-RIPE

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/