default_llseek():
* allows 32-bit overflows
* allows file pointers larger than supported by the filesystem.
* prevents negativ file pointers
ext2_file_lseek() is the exact opposite:
* prevents 32-bit overflows.
* prevents files offsets larger than supported by the fs.
* allows negativ values on 64-bit platforms.
* doesn't allow negativ values on 32-bit platform.
What's by other OS'es, what's required by SUS/POSIX?
-- Manfred PS: Here is my current (alpha) patch: >>>>>>>>>>>>>>>>>> // Kernel Version: // VERSION = 2 // PATCHLEVEL = 3 // SUBLEVEL = 14 // EXTRAVERSION = diff -r -u -P -x CVS -x *,v 2.3/fs/ext2/file.c build-2.3/fs/ext2/file.c --- 2.3/fs/ext2/file.c Thu Jul 1 14:11:44 1999 +++ build-2.3/fs/ext2/file.c Fri Aug 20 20:53:13 1999 @@ -37,58 +37,9 @@ #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) -static long long ext2_file_lseek(struct file *, long long, int); #if BITS_PER_LONG < 64 static int ext2_open_file (struct inode *, struct file *); - -#else - -#define EXT2_MAX_SIZE(bits) \ - (((EXT2_NDIR_BLOCKS + (1LL << (bits - 2)) + \ - (1LL << (bits - 2)) * (1LL << (bits - 2)) + \ - (1LL << (bits - 2)) * (1LL << (bits - 2)) * (1LL << (bits - 2))) * \ - (1LL << bits)) - 1) - -static long long ext2_max_sizes[] = { -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -EXT2_MAX_SIZE(10), EXT2_MAX_SIZE(11), EXT2_MAX_SIZE(12), EXT2_MAX_SIZE(13) -}; - -#endif - - -/* - * Make sure the offset never goes beyond the 32-bit mark.. - */ -static long long ext2_file_lseek( - struct file *file, - long long offset, - int origin) -{ - struct inode *inode = file->f_dentry->d_inode; - - switch (origin) { - case 2: - offset += inode->i_size; - break; - case 1: - offset += file->f_pos; - } - if (((unsigned long long) offset >> 32) != 0) { -#if BITS_PER_LONG < 64 - return -EINVAL; -#else - if (offset > ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(inode->i_sb)]) - return -EINVAL; #endif - } - if (offset != file->f_pos) { - file->f_pos = offset; - file->f_reada = 0; - file->f_version = ++event; - } - return offset; -} static inline void remove_suid(struct inode *inode) { @@ -154,7 +105,7 @@ * the ext2 filesystem. */ static struct file_operations ext2_file_operations = { - ext2_file_lseek, /* lseek */ + NULL, /* lseek */ generic_file_read, /* read */ ext2_file_write, /* write */ NULL, /* readdir - bad */ diff -r -u -P -x CVS -x *,v 2.3/fs/ext2/super.c build-2.3/fs/ext2/super.c --- 2.3/fs/ext2/super.c Tue Jun 15 20:15:05 1999 +++ build-2.3/fs/ext2/super.c Fri Aug 20 20:52:10 1999 @@ -376,6 +376,18 @@ #define log2(n) ffz(~(n)) +#define EXT2_MAX_SIZE(bits) \ + (((EXT2_NDIR_BLOCKS + (1LL << (bits - 2)) + \ + (1LL << (bits - 2)) * (1LL << (bits - 2)) + \ + (1LL << (bits - 2)) * (1LL << (bits - 2)) * (1LL << (bits - 2))) * \ + (1LL << bits)) - 1) + +static long long ext2_max_sizes[] = { +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +EXT2_MAX_SIZE(10), EXT2_MAX_SIZE(11), EXT2_MAX_SIZE(12), EXT2_MAX_SIZE(13) +}; + + struct super_block * ext2_read_super (struct super_block * sb, void * data, int silent) { @@ -470,6 +482,7 @@ } sb->s_blocksize_bits = le32_to_cpu(sb->u.ext2_sb.s_es->s_log_block_size) + 10; sb->s_blocksize = 1 << sb->s_blocksize_bits; + sb->s_maxfilesize = ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(sb)]; if (sb->s_blocksize != BLOCK_SIZE && (sb->s_blocksize == 1024 || sb->s_blocksize == 2048 || sb->s_blocksize == 4096)) { diff -r -u -P -x CVS -x *,v 2.3/fs/read_write.c build-2.3/fs/read_write.c --- 2.3/fs/read_write.c Thu Jul 1 14:11:46 1999 +++ build-2.3/fs/read_write.c Fri Aug 20 21:53:29 1999 @@ -16,6 +16,7 @@ static loff_t default_llseek(struct file *file, loff_t offset, int origin) { long long retval; + long long max; switch (origin) { case 2: @@ -24,8 +25,18 @@ case 1: offset += file->f_pos; } + max = ((long long)(~0ULL>>1)); + if(S_ISREG(file->f_dentry->d_inode->i_mode) && file->f_dentry->d_inode->i_sb) + { + if(file->f_dentry->d_inode->i_sb->s_maxfilesize!=0) + max = file->f_dentry->d_inode->i_sb->s_maxfilesize; + } +#if BITS_PER_LONG < 64 + if(max > INT_MAX) + max = INT_MAX; +#endif retval = -EINVAL; - if (offset >= 0) { + if (offset >= 0 && offset <= max) { if (offset != file->f_pos) { file->f_pos = offset; file->f_reada = 0; diff -r -u -P -x CVS -x *,v 2.3/include/linux/fs.h build-2.3/include/linux/fs.h --- 2.3/include/linux/fs.h Mon Aug 9 23:58:27 1999 +++ build-2.3/include/linux/fs.h Fri Aug 20 19:35:54 1999 @@ -519,6 +519,7 @@ kdev_t s_dev; unsigned long s_blocksize; unsigned char s_blocksize_bits; + loff_t s_maxfilesize; unsigned char s_lock; unsigned char s_rd_only; unsigned char s_dirt; <<<<<<<<<<<<<<<<<<
- 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/