From db7d4daea91e105e3859cf461d7e53b9b77454b2 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 13 Jun 1999 16:29:25 +0000 Subject: Merge with Linux 2.2.8. --- fs/fat/dir.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'fs/fat/dir.c') diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 1c44247a0..b6d6fb405 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -9,6 +9,7 @@ * * VFAT extensions by Gordon Chaffee * Merged with msdos fs by Henrik Storner + * Plugged buffer overrun in readdir(). AV */ #define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S)) @@ -59,6 +60,7 @@ struct file_operations fat_dir_operations = { * characters are a sort of uuencoded 16 bit Unicode value. This lets * us do a full dump and restore of Unicode filenames. We could get * into some trouble with long Unicode names, but ignore that right now. + * Ahem... Stack smashing in ring 0 isn't fun. Fixed. */ static int uni16_to_x8(unsigned char *ascii, unsigned char *uni, int uni_xlate, @@ -93,6 +95,11 @@ uni16_to_x8(unsigned char *ascii, unsigned char *uni, int uni_xlate, *op++ = '?'; } } + /* We have some slack there, so it's OK */ + if (op>ascii+256) { + op = ascii + 256; + break; + } } *op = 0; return (op - ascii); @@ -138,8 +145,6 @@ int fat_readdirx( unsigned char *unicode = NULL; struct nls_table *nls = MSDOS_SB(sb)->nls_io; - if (!inode || !S_ISDIR(inode->i_mode)) - return -EBADF; /* Fake . and .. for the root directory. */ if (inode->i_ino == MSDOS_ROOT_INO) { while (oldpos < 2) { @@ -186,9 +191,17 @@ int fat_readdirx( id = ds->id; if (id & 0x40) { slots = id & ~0x40; - long_slots = slots; - is_long = 1; - alias_checksum = ds->alias_checksum; + /* + * Dirty, but not dirtier than the original, + * and plugs the hole. + */ + if (slots > 20) + slots = 0; + else { + long_slots = slots; + is_long = 1; + alias_checksum = ds->alias_checksum; + } } get_new_entry = 1; -- cgit v1.2.3