summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-07-28 22:58:42 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-07-28 22:58:42 +0000
commiteed6b7c84cc33f229f6fecd884d9a22af5bec514 (patch)
tree422a7a49328c59053f4fb11805adb753523c2f2c /fs
parenta3b90e3c6976551acbac09f5aacd736a1658aaa8 (diff)
Merge with Linux 2.4.0-test5-pre6.
Diffstat (limited to 'fs')
-rw-r--r--fs/coda/pioctl.c2
-rw-r--r--fs/dquot.c2
-rw-r--r--fs/ext2/inode.c25
-rw-r--r--fs/fat/cache.c2
-rw-r--r--fs/jffs/inode-v23.c17
-rw-r--r--fs/minix/inode.c50
-rw-r--r--fs/namei.c12
-rw-r--r--fs/smbfs/ChangeLog4
-rw-r--r--fs/smbfs/proc.c87
-rw-r--r--fs/sysv/inode.c25
-rw-r--r--fs/udf/inode.c17
-rw-r--r--fs/ufs/inode.c25
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