diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-07-28 22:58:42 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-07-28 22:58:42 +0000 |
commit | eed6b7c84cc33f229f6fecd884d9a22af5bec514 (patch) | |
tree | 422a7a49328c59053f4fb11805adb753523c2f2c /fs | |
parent | a3b90e3c6976551acbac09f5aacd736a1658aaa8 (diff) |
Merge with Linux 2.4.0-test5-pre6.
Diffstat (limited to 'fs')
-rw-r--r-- | fs/coda/pioctl.c | 2 | ||||
-rw-r--r-- | fs/dquot.c | 2 | ||||
-rw-r--r-- | fs/ext2/inode.c | 25 | ||||
-rw-r--r-- | fs/fat/cache.c | 2 | ||||
-rw-r--r-- | fs/jffs/inode-v23.c | 17 | ||||
-rw-r--r-- | fs/minix/inode.c | 50 | ||||
-rw-r--r-- | fs/namei.c | 12 | ||||
-rw-r--r-- | fs/smbfs/ChangeLog | 4 | ||||
-rw-r--r-- | fs/smbfs/proc.c | 87 | ||||
-rw-r--r-- | fs/sysv/inode.c | 25 | ||||
-rw-r--r-- | fs/udf/inode.c | 17 | ||||
-rw-r--r-- | fs/ufs/inode.c | 25 |
12 files changed, 73 insertions, 195 deletions
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index 711beee06..99ead4e51 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c @@ -85,7 +85,7 @@ static int coda_pioctl(struct inode * inode, struct file * filp, target_inode = nd.dentry->d_inode; } - CDEBUG(D_PIOCTL, "target ino: 0x%ld, dev: 0x%d\n", + CDEBUG(D_PIOCTL, "target ino: 0x%ld, dev: 0x%x\n", target_inode->i_ino, target_inode->i_dev); /* return if it is not a Coda inode */ diff --git a/fs/dquot.c b/fs/dquot.c index 42d91c35f..15f7dad8f 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -732,7 +732,7 @@ put_it: /* Free list of dquots - called from inode.c */ void put_dquot_list(struct list_head *tofree_head) { - struct list_head *act_head = tofree_head.next; + struct list_head *act_head = tofree_head->next; struct dquot *dquot; /* So now we have dquots on the list... Just free them */ diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 70e806b02..4580c87e0 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -223,20 +223,6 @@ repeat: return NULL; } } - *err = -EFBIG; - - /* Check file limits.. */ - { - unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit < RLIM_INFINITY) { - limit >>= EXT2_BLOCK_SIZE_BITS(inode->i_sb); - if (new_block >= limit) { - send_sig(SIGXFSZ, current, 0); - *err = -EFBIG; - return NULL; - } - } - } if (inode->u.ext2_i.i_next_alloc_block == new_block) goal = inode->u.ext2_i.i_next_alloc_goal; @@ -320,7 +306,6 @@ static struct buffer_head * block_getblk (struct inode * inode, u32 * p; struct buffer_head * result; int blocksize = inode->i_sb->s_blocksize; - unsigned long limit; result = NULL; if (!bh) @@ -347,16 +332,6 @@ repeat: goto out; } } - *err = -EFBIG; - - limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit < RLIM_INFINITY) { - limit >>= EXT2_BLOCK_SIZE_BITS(inode->i_sb); - if (new_block >= limit) { - send_sig(SIGXFSZ, current, 0); - goto out; - } - } if (inode->u.ext2_i.i_next_alloc_block == new_block) goal = inode->u.ext2_i.i_next_alloc_goal; diff --git a/fs/fat/cache.c b/fs/fat/cache.c index 038773b94..cabb08f76 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c @@ -75,7 +75,7 @@ int default_fat_access(struct super_block *sb,int nr,int new_value) /* Fscking Microsoft marketing department. Their "32" is 28. */ next &= 0xfffffff; if (next >= 0xffffff7) next = -1; - PRINTK(("fat_bread: 0x%x, nr=0x%x, first=0x%x, next=0x%d\n", b, nr, first, next)); + PRINTK(("fat_bread: 0x%x, nr=0x%x, first=0x%x, next=0x%x\n", b, nr, first, next)); } else if (MSDOS_SB(sb)->fat_bits == 16) { p_first = p_last = NULL; /* GCC needs that stuff */ diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index 1447554ed..b1973918d 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -1225,7 +1225,6 @@ jffs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos) struct jffs_node *node; struct dentry *dentry = filp->f_dentry; struct inode *inode = dentry->d_inode; - unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur; int written = 0; loff_t pos; int err; @@ -1282,22 +1281,6 @@ jffs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos) if (filp->f_flags & O_APPEND) pos = inode->i_size; - - /* - * Check whether we've reached the file size limit. - */ - err = -EFBIG; - if (limit != RLIM_INFINITY) { - if (pos >= limit) { - send_sig(SIGXFSZ, current, 0); - goto out; - } - if (count > limit - pos) { - send_sig(SIGXFSZ, current, 0); - count = limit - pos; - } - } - /* Things are going to be written so we could allocate and initialize the necessary data structures now. */ if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node), diff --git a/fs/minix/inode.c b/fs/minix/inode.c index fac903800..b49626923 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -505,20 +505,6 @@ repeat: return NULL; } } - *err = -EFBIG; - - /* Check file limits.. */ - { - unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit < RLIM_INFINITY) { - limit >>= BLOCK_SIZE_BITS; - if (new_block >= limit) { - send_sig(SIGXFSZ, current, 0); - *err = -EFBIG; - return NULL; - } - } - } tmp = minix_new_block(inode); if (!tmp) { @@ -564,7 +550,6 @@ static struct buffer_head * V1_block_getblk(struct inode * inode, int tmp; unsigned short *p; struct buffer_head * result; - unsigned long limit; result = NULL; if (!bh) @@ -590,16 +575,6 @@ repeat: goto out; } } - *err = -EFBIG; - - limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit < RLIM_INFINITY) { - limit >>= BLOCK_SIZE_BITS; - if (new_block >= limit) { - send_sig(SIGXFSZ, current, 0); - goto out; - } - } tmp = minix_new_block(inode); if (!tmp) @@ -741,20 +716,6 @@ repeat: return NULL; } } - *err = -EFBIG; - - /* Check file limits.. */ - { - unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit < RLIM_INFINITY) { - limit >>= BLOCK_SIZE_BITS; - if (new_block >= limit) { - send_sig(SIGXFSZ, current, 0); - *err = -EFBIG; - return NULL; - } - } - } tmp = minix_new_block(inode); if (!tmp) { @@ -800,7 +761,6 @@ static struct buffer_head * V2_block_getblk(struct inode * inode, int tmp; unsigned int *p; struct buffer_head * result; - unsigned long limit; result = NULL; if (!bh) @@ -826,16 +786,6 @@ repeat: goto out; } } - *err = -EFBIG; - - limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit < RLIM_INFINITY) { - limit >>= BLOCK_SIZE_BITS; - if (new_block >= limit) { - send_sig(SIGXFSZ, current, 0); - goto out; - } - } tmp = minix_new_block(inode); if (!tmp) diff --git a/fs/namei.c b/fs/namei.c index 8653e20ab..b85a6419d 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -292,13 +292,15 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, i /* * Uhhuh! Nasty case: the cache was re-populated while - * we waited on the semaphore. Need to revalidate, but - * we're going to return this entry regardless (same - * as if it was busy). + * we waited on the semaphore. Need to revalidate. */ up(&dir->i_sem); - if (result->d_op && result->d_op->d_revalidate) - result->d_op->d_revalidate(result, flags); + if (result->d_op && result->d_op->d_revalidate) { + if (!result->d_op->d_revalidate(result, flags) && !d_invalidate(result)) { + dput(result); + result = ERR_PTR(-ENOENT); + } + } return result; } diff --git a/fs/smbfs/ChangeLog b/fs/smbfs/ChangeLog index c47cc1417..893890334 100644 --- a/fs/smbfs/ChangeLog +++ b/fs/smbfs/ChangeLog @@ -1,5 +1,9 @@ ChangeLog for smbfs. +2000-07-25 Urban Widmark <urban@svenskatest.se> + + * proc.c: fix 3 places where bad server responses could cause an Oops. + 2000-07-15 Urban Widmark <urban@svenskatest.se> * *.c: more debug (%.*s) & indent fixes diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c index 68922335c..e969320b7 100644 --- a/fs/smbfs/proc.c +++ b/fs/smbfs/proc.c @@ -947,7 +947,7 @@ smb_proc_read(struct dentry *dentry, off_t offset, int count, char *data) { struct smb_sb_info *server = server_from_dentry(dentry); __u16 returned_count, data_len; - char *buf; + unsigned char *buf; int result; smb_lock_server(server); @@ -965,10 +965,19 @@ smb_proc_read(struct dentry *dentry, off_t offset, int count, char *data) buf = SMB_BUF(server->packet); data_len = WVAL(buf, 1); + + /* we can NOT simply trust the data_len given by the server ... */ + if (data_len > server->packet_size - (buf+3 - server->packet)) { + printk(KERN_ERR "smb_proc_read: invalid data length!! " + "%d > %d - (%p - %p)\n", + data_len, server->packet_size, buf+3, server->packet); + result = -EIO; + goto out; + } + memcpy(data, buf+3, data_len); - if (returned_count != data_len) - { + if (returned_count != data_len) { printk(KERN_NOTICE "smb_proc_read: returned != data_len\n"); printk(KERN_NOTICE "smb_proc_read: ret_c=%d, data_len=%d\n", returned_count, data_len); @@ -1288,9 +1297,8 @@ smb_decode_dirent(struct smb_sb_info *server, __u8 *p, entry->name = p + 9; len = strlen(entry->name); if (len > 12) - { len = 12; - } + /* * Trim trailing blanks for Pathworks servers */ @@ -1298,8 +1306,7 @@ smb_decode_dirent(struct smb_sb_info *server, __u8 *p, len--; entry->len = len; - switch (server->opt.case_handling) - { + switch (server->opt.case_handling) { case SMB_CASE_UPPER: str_upper(entry->name, len); break; @@ -1309,7 +1316,7 @@ smb_decode_dirent(struct smb_sb_info *server, __u8 *p, default: break; } - DEBUG1("len=%d, name=%s\n", len, entry->name); + DEBUG1("len=%d, name=%.*s\n", len, len, entry->name); return p + 22; } @@ -1321,7 +1328,7 @@ static int smb_proc_readdir_short(struct smb_sb_info *server, struct dentry *dir, int fpos, void *cachep) { - char *p; + unsigned char *p; int result; int i, first, entries_seen, entries; int entries_asked = (server->opt.max_xmit - 100) / SMB_DIRINFO_SIZE; @@ -1329,26 +1336,25 @@ smb_proc_readdir_short(struct smb_sb_info *server, struct dentry *dir, int fpos, __u16 count; char status[SMB_STATUS_SIZE]; static struct qstr mask = { "*.*", 3, 0 }; + unsigned char *last_status; VERBOSE("%s/%s, pos=%d\n", DENTRY_PATH(dir), fpos); smb_lock_server(server); /* N.B. We need to reinitialize the cache to restart */ - retry: +retry: smb_init_dircache(cachep); first = 1; entries = 0; entries_seen = 2; /* implicit . and .. */ - while (1) - { + while (1) { p = smb_setup_header(server, SMBsearch, 2, 0); WSET(server->packet, smb_vwv0, entries_asked); WSET(server->packet, smb_vwv1, aDIR); *p++ = 4; - if (first == 1) - { + if (first == 1) { p = smb_encode_path(server, p, dir, &mask); *p++ = 5; WSET(p, 0, 0); @@ -1366,8 +1372,7 @@ smb_proc_readdir_short(struct smb_sb_info *server, struct dentry *dir, int fpos, smb_setup_bcc(server, p); result = smb_request_ok(server, SMBsearch, 1, -1); - if (result < 0) - { + if (result < 0) { if ((server->rcls == ERRDOS) && (server->err == ERRnofiles)) break; @@ -1386,28 +1391,39 @@ smb_proc_readdir_short(struct smb_sb_info *server, struct dentry *dir, int fpos, goto unlock_return; p += 7; + + /* Make sure the response fits in the buffer. Fixed sized + entries means we don't have to check in the decode loop. */ + + last_status = SMB_BUF(server->packet) + 3 + (count - 1) * + SMB_DIRINFO_SIZE; + + if (last_status + SMB_DIRINFO_SIZE >= + server->packet + server->packet_size) { + printk(KERN_ERR "smb_proc_readdir_short: " + "last dir entry outside buffer! " + "%d@%p %d@%p\n", SMB_DIRINFO_SIZE, last_status, + server->packet_size, server->packet); + goto unlock_return; + } + /* Read the last entry into the status field. */ - memcpy(status, - SMB_BUF(server->packet) + 3 + - (count - 1) * SMB_DIRINFO_SIZE, - SMB_STATUS_SIZE); + memcpy(status, last_status, SMB_STATUS_SIZE); + /* Now we are ready to parse smb directory entries. */ - for (i = 0; i < count; i++) - { + for (i = 0; i < count; i++) { struct cache_dirent this_ent, *entry = &this_ent; p = smb_decode_dirent(server, p, entry); - if (entries_seen == 2 && entry->name[0] == '.') - { + if (entries_seen == 2 && entry->name[0] == '.') { if (entry->len == 1) continue; if (entry->name[1] == '.' && entry->len == 2) continue; } - if (entries_seen >= fpos) - { + if (entries_seen >= fpos) { DEBUG1("fpos=%u\n", entries_seen); smb_add_to_cache(cachep, entry, entries_seen); entries++; @@ -1420,7 +1436,7 @@ smb_proc_readdir_short(struct smb_sb_info *server, struct dentry *dir, int fpos, } result = entries; - unlock_return: +unlock_return: smb_unlock_server(server); return result; } @@ -1511,7 +1527,8 @@ static int smb_proc_readdir_long(struct smb_sb_info *server, struct dentry *dir, int fpos, void *cachep) { - char *p, *mask, *lastname, *param = server->temp_buf; + unsigned char *p; + char *mask, *lastname, *param = server->temp_buf; __u16 command; int first, entries, entries_seen; @@ -1539,7 +1556,7 @@ smb_proc_readdir_long(struct smb_sb_info *server, struct dentry *dir, int fpos, smb_lock_server(server); - retry: +retry: /* * Encode the initial path */ @@ -1665,6 +1682,17 @@ smb_proc_readdir_long(struct smb_sb_info *server, struct dentry *dir, int fpos, for (i = 0; i < ff_searchcount; i++) { struct cache_dirent this_ent, *entry = &this_ent; + /* make sure we stay within the buffer */ + if (p >= resp_data + resp_data_len) { + printk(KERN_ERR "smb_proc_readdir_long: " + "dirent pointer outside buffer! " + "%p %d@%p %d@%p\n", + p, resp_data_len, resp_data, + server->packet_size, server->packet); + result = -EIO; /* always a comm. error? */ + goto unlock_return; + } + p = smb_decode_long_dirent(server, p, entry, info_level); @@ -1688,6 +1716,7 @@ smb_proc_readdir_long(struct smb_sb_info *server, struct dentry *dir, int fpos, loop_count = 0; } +unlock_return: smb_unlock_server(server); return entries; } diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index e1d594f0b..b7a1068ce 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -685,20 +685,6 @@ repeat: return NULL; } } - *err = -EFBIG; - - /* Check file limits.. */ - { - unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit < RLIM_INFINITY) { - limit >>= sb->sv_block_size_bits; - if (new_block >= limit) { - send_sig(SIGXFSZ, current, 0); - *err = -EFBIG; - return NULL; - } - } - } tmp = sysv_new_block(sb); if (!tmp) { @@ -742,7 +728,6 @@ static struct buffer_head *block_getblk(struct inode *inode, u32 tmp, block; sysv_zone_t *p; struct buffer_head * result; - unsigned long limit; result = NULL; if (!bh) @@ -771,16 +756,6 @@ repeat: goto out; } } - *err = -EFBIG; - - limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit < RLIM_INFINITY) { - limit >>= sb->sv_block_size_bits; - if (new_block >= limit) { - send_sig(SIGXFSZ, current, 0); - goto out; - } - } block = sysv_new_block(sb); if (!block) diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 360c12ba0..bbc4e30a5 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -508,23 +508,6 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block, } udf_release_data(cbh); - *err = -EFBIG; - - /* Check file limits.. */ - { - unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit < RLIM_INFINITY) - { - limit >>= inode->i_sb->s_blocksize_bits; - if (block >= limit) - { - send_sig(SIGXFSZ, current, 0); - *err = -EFBIG; - return NULL; - } - } - } - /* if the current extent is not recorded but allocated, get the block in the extent corresponding to the requested block */ if ((laarr[c].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index fffaa7d3e..771069834 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -186,7 +186,6 @@ static struct buffer_head * ufs_inode_getfrag (struct inode *inode, struct super_block * sb; struct ufs_sb_private_info * uspi; struct buffer_head * result; - unsigned long limit; unsigned block, blockoff, lastfrag, lastblock, lastblockoff; unsigned tmp, goal; u32 * p, * p2; @@ -221,16 +220,6 @@ repeat: return NULL; } } - *err = -EFBIG; - - limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit < RLIM_INFINITY) { - limit >>= sb->s_blocksize_bits; - if (new_fragment >= limit) { - send_sig(SIGXFSZ, current, 0); - return NULL; - } - } lastblock = ufs_fragstoblks (lastfrag); lastblockoff = ufs_fragnum (lastfrag); @@ -348,19 +337,7 @@ repeat: goto out; } } - *err = -EFBIG; - - { - unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit < RLIM_INFINITY) { - limit >>= sb->s_blocksize_bits; - if (new_fragment >= limit) { - brelse (bh); - send_sig(SIGXFSZ, current, 0); - return NULL; - } - } - } + if (block && (tmp = SWAB32(((u32*)bh->b_data)[block-1]) + uspi->s_fpb)) goal = tmp + uspi->s_fpb; else |