Skip to contentSkip to conversation

reiser4: fix null pointer dereference in reiser4_write_extent

PATCH New Edward Shishkin 1 participant 1 message Jan 25, 2008

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 reiser4: fix null pointer dereference in reiser4_write_extent

Andrew, please apply.

Thanks,
Edward.

Problem:
Oops when starting kde4:

BUG: unable to handle kernel NULL pointer dereference
at virtual address 0000000c
printing eip: c025eba5 *pde = 00000000
Oops: 0000 [#1] SMP
last sysfs file: /devices/pci0000:00/0000:00:1e.0/0000:04:04.0/resource
Modules linked in: thermal processor fan button

Pid: 3705, comm: kwrite Not tainted (2.6.23-mm1 #8)
EIP: 0060:[<c025eba5>] EFLAGS: 00010246 CPU: 0 EIP is at update_extents+0x44/0x2e7

Bug:
Trying to look at not persistent struct file in the case of expanded truncate via sys_truncate64(path, length).

The fixup:
. Don't look at struct file at truncate_file_body(); . Add an inode *inode argument to the following
functions to handle the case of not persistent struct file.
. reiser4_write_extent();
. reiser4_write_tail();
. reiser4_update_extents();
Other changes:
. Add missesd identifier in some asserts.
. Comments cleanups.

---
 linux-2.6.24-rc8-mm1/fs/reiser4/plugin/file/cryptcompress.c   |    8 
 linux-2.6.24-rc8-mm1/fs/reiser4/plugin/file/file.c            |  115 +++++-----
 linux-2.6.24-rc8-mm1/fs/reiser4/plugin/file/file.h            |    8 
 linux-2.6.24-rc8-mm1/fs/reiser4/plugin/file/tail_conversion.c |    2 
 linux-2.6.24-rc8-mm1/fs/reiser4/plugin/item/extent.h          |    4 
 linux-2.6.24-rc8-mm1/fs/reiser4/plugin/item/extent_file_ops.c |   15 -
 linux-2.6.24-rc8-mm1/fs/reiser4/plugin/item/item.h            |    3 
 linux-2.6.24-rc8-mm1/fs/reiser4/plugin/item/tail.c            |    9 
 linux-2.6.24-rc8-mm1/fs/reiser4/plugin/item/tail.h            |    4 
 9 files changed, 86 insertions(+), 82 deletions(-)
fs/reiser4/plugin/file/cryptcompress.c renamed from fs/reiser4/plugin/file/cryptcompress.c.orig +4 -4
@@ -3198,11 +3198,11 @@
 	return result;
 }
 
-static int
-update_cryptcompress_size(struct inode *inode, reiser4_key * key, int update_sd)
+static int update_cryptcompress_size(struct inode *inode, loff_t new_size,
+				     int update_sd)
 {
-	return (get_key_offset(key) & ((loff_t) (inode_cluster_size(inode)) - 1)
-		? 0 : reiser4_update_file_size(inode, key, update_sd));
+	return (new_size & ((loff_t) (inode_cluster_size(inode)) - 1)
+		? 0 : reiser4_update_file_size(inode, new_size, update_sd));
 }
 
 /* Prune cryptcompress file in two steps:
fs/reiser4/plugin/file/file.c renamed from fs/reiser4/plugin/file/file.c.orig +61 -54

239 lines not on this page · raw message

fs/reiser4/plugin/file/file.h renamed from fs/reiser4/plugin/file/file.h.orig +4 -4
@@ -280,10 +280,10 @@
 int hint_is_set(const hint_t *);
 void reiser4_unset_hint(hint_t *);
 
-int reiser4_update_file_size(struct inode *, reiser4_key *, int update_sd);
-int cut_file_items(struct inode *, loff_t new_size, int update_sd,
-		   loff_t cur_size, int (*update_actor) (struct inode *,
-							 reiser4_key *, int));
+int reiser4_update_file_size(struct inode *, loff_t, int update_sd);
+int cut_file_items(struct inode *, loff_t new_size,
+		   int update_sd, loff_t cur_size,
+		   int (*update_actor) (struct inode *, loff_t, int));
 #if REISER4_DEBUG
 
 /* return 1 is exclusive access is obtained, 0 - otherwise */
fs/reiser4/plugin/file/tail_conversion.c renamed from fs/reiser4/plugin/file/tail_conversion.c.orig +1 -1
@@ -651,7 +651,7 @@
 			assert("edward-1538",
 			       file->f_dentry->d_inode == inode);
 
-			result = reiser4_write_tail(file,
+			result = reiser4_write_tail(file, inode,
 						    (char __user *)kmap(page),
 						    count, &pos);
 			reiser4_free_file_fsdata(file);
fs/reiser4/plugin/item/extent.h renamed from fs/reiser4/plugin/item/extent.h.orig +2 -2
@@ -131,8 +131,8 @@
 int reiser4_check_extent(const coord_t * coord, const char **error);
 
 /* plugin->u.item.s.file.* */
-ssize_t reiser4_write_extent(struct file *, const char __user *,
-			     size_t, loff_t *);
+ssize_t reiser4_write_extent(struct file *, struct inode * inode,
+			     const char __user *, size_t, loff_t *);
 int reiser4_read_extent(struct file *, flow_t *, hint_t *);
 int reiser4_readpage_extent(void *, struct page *);
 int reiser4_do_readpage_extent(reiser4_extent*, reiser4_block_nr, struct page*);
fs/reiser4/plugin/item/extent_file_ops.c renamed from fs/reiser4/plugin/item/extent_file_ops.c.orig +6 -9
@@ -814,9 +814,9 @@
  * @off:
  *
  */
-static int update_extents(struct file *file, jnode **jnodes, int count, loff_t pos)
+static int update_extents(struct file *file, struct inode *inode,
+			  jnode **jnodes, int count, loff_t pos)
 {
-	struct inode *inode;
 	struct hint hint;
 	reiser4_key key;
 	int result;
@@ -825,7 +825,6 @@
 	result = load_file_hint(file, &hint);
 	BUG_ON(result != 0);
 
-	inode = file->f_dentry->d_inode;
 	if (count != 0)
 		/*
 		 * count == 0 is special case: expanding truncate
@@ -969,14 +968,13 @@
  * @pos: position in file to write to
  *
  */
-ssize_t reiser4_write_extent(struct file *file, const char __user *buf,
-			     size_t count, loff_t *pos)
+ssize_t reiser4_write_extent(struct file *file, struct inode * inode,
+			     const char __user *buf, size_t count, loff_t *pos)
 {
 	int have_to_update_extent;
 	int nr_pages, nr_dirty;
 	struct page *page;
 	jnode *jnodes[WRITE_GRANULARITY + 1];
-	struct inode *inode;
 	unsigned long index;
 	unsigned long end;
 	int i;
@@ -984,13 +982,12 @@
 	size_t left, written;
 	int result = 0;
 
-	inode = file->f_dentry->d_inode;
 	if (write_extent_reserve_space(inode))
 		return RETERR(-ENOSPC);
 
 	if (count == 0) {
 		/* truncate case */
-		update_extents(file, jnodes, 0, *pos);
+		update_extents(file, inode, jnodes, 0, *pos);
 		return 0;
 	}
 
@@ -1090,7 +1087,7 @@
 	}
 
 	if (have_to_update_extent) {
-		update_extents(file, jnodes, nr_dirty, *pos);
+		update_extents(file, inode, jnodes, nr_dirty, *pos);
 	} else {
 		for (i = 0; i < nr_dirty; i ++) {
 			int ret;
fs/reiser4/plugin/item/item.h renamed from fs/reiser4/plugin/item/item.h.orig +2 -1
@@ -233,7 +233,8 @@
 
 /* operations specific to items regular (unix) file metadata are built of */
 struct file_iops{
-	int (*write) (struct file *, const char __user *, size_t, loff_t *pos);
+	int (*write) (struct file *, struct inode *,
+		      const char __user *, size_t, loff_t *pos);
 	int (*read) (struct file *, flow_t *, hint_t *);
 	int (*readpage) (void *, struct page *);
 	int (*get_block) (const coord_t *, sector_t, sector_t *);
fs/reiser4/plugin/item/tail.c renamed from fs/reiser4/plugin/item/tail.c.orig +4 -5
@@ -626,7 +626,7 @@
 }
 
 /**
- * reiser4_write_extent - write method of tail item plugin
+ * reiser4_write_tail - write method of tail item plugin
  * @file: file to write to
  * @buf: address of user-space buffer
  * @count: number of bytes to write
@@ -634,10 +634,9 @@
  *
  * Returns number of written bytes or error code.
  */
-ssize_t reiser4_write_tail(struct file *file, const char __user *buf,
-			   size_t count, loff_t *pos)
+ssize_t reiser4_write_tail(struct file *file, struct inode * inode,
+			   const char __user *buf, size_t count, loff_t *pos)
 {
-	struct inode *inode;
 	struct hint hint;
 	int result;
 	flow_t flow;
@@ -645,7 +644,7 @@
 	lock_handle *lh;
 	znode *loaded;
 
-	inode = file->f_dentry->d_inode;
+	assert("edward-1548", inode != NULL);
 
 	if (write_extent_reserve_space(inode))
 		return RETERR(-ENOSPC);
fs/reiser4/plugin/item/tail.h renamed from fs/reiser4/plugin/item/tail.h.orig +2 -2
@@ -33,8 +33,8 @@
 reiser4_key *unit_key_tail(const coord_t *, reiser4_key *);
 
 /* plugin->u.item.s.* */
-ssize_t reiser4_write_tail(struct file *file, const char __user *buf,
-			   size_t count, loff_t *pos);
+ssize_t reiser4_write_tail(struct file *file, struct inode * inode,
+			   const char __user *buf, size_t count, loff_t *pos);
 int reiser4_read_tail(struct file *, flow_t *, hint_t *);
 int readpage_tail(void *vp, struct page *page);
 reiser4_key *append_key_tail(const coord_t *, reiser4_key *);