]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
add forgotten ->b_data in memcpy() call in ext3/resize.c (oopsable)
authorAl Viro <viro@zeniv.linux.org.uk>
Wed, 29 Nov 2006 10:40:22 +0000 (11:40 +0100)
committerAdrian Bunk <bunk@stusta.de>
Wed, 29 Nov 2006 10:40:22 +0000 (11:40 +0100)
sbi->s_group_desc is an array of pointers to buffer_head.  memcpy() of
buffer size from address of buffer_head is a bad idea - it will generate
junk in any case, may oops if buffer_head is close to the end of slab
page and next page is not mapped and isn't what was intended there.
IOW, ->b_data is missing in that call.  Fortunately, result doesn't go
into the primary on-disk data structures, so only backup ones get crap
written to them; that had allowed this bug to remain unnoticed until
now.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
fs/ext3/resize.c
include/linux/skbuff.h
net/ipv4/ip_output.c
net/ipv6/ip6_output.c

index 14f5f6ea3e7230fb2621a620a3639ff136f1996d..34b39e9a1e5a01588db869c02c85f2407d12221a 100644 (file)
@@ -213,7 +213,7 @@ static int setup_new_group_blocks(struct super_block *sb,
                        goto exit_bh;
                }
                lock_buffer(bh);
-               memcpy(gdb->b_data, sbi->s_group_desc[i], bh->b_size);
+               memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, bh->b_size);
                set_buffer_uptodate(gdb);
                unlock_buffer(bh);
                ext3_journal_dirty_metadata(handle, gdb);
index 7e631a542577deac5830f72f223ff45825b08931..9a0e9e789339f6e1cd58d99d857844898e0aab85 100644 (file)
@@ -997,6 +997,21 @@ static inline int pskb_trim(struct sk_buff *skb, unsigned int len)
        return (len < skb->len) ? __pskb_trim(skb, len) : 0;
 }
 
+/**
+ *     pskb_trim_unique - remove end from a paged unique (not cloned) buffer
+ *     @skb: buffer to alter
+ *     @len: new length
+ *
+ *     This is identical to pskb_trim except that the caller knows that
+ *     the skb is not cloned so we should never get an error due to out-
+ *     of-memory.
+ */
+static inline void pskb_trim_unique(struct sk_buff *skb, unsigned int len)
+{
+       int err = pskb_trim(skb, len);
+       BUG_ON(err);
+}
+
 /**
  *     skb_orphan - orphan a buffer
  *     @skb: buffer to orphan
index 8dcba3887f04eb647df01ae404b3b9bda955408d..b24c6a0c5574c7c229975251367121c60f17a446 100644 (file)
@@ -946,7 +946,7 @@ alloc_new_skb:
                                skb_prev->csum = csum_sub(skb_prev->csum,
                                                          skb->csum);
                                data += fraggap;
-                               skb_trim(skb_prev, maxfraglen);
+                               pskb_trim_unique(skb_prev, maxfraglen);
                        }
 
                        copy = datalen - transhdrlen - fraggap;
@@ -1139,7 +1139,7 @@ ssize_t   ip_append_page(struct sock *sk, struct page *page,
                                        data, fraggap, 0);
                                skb_prev->csum = csum_sub(skb_prev->csum,
                                                          skb->csum);
-                               skb_trim(skb_prev, maxfraglen);
+                               pskb_trim_unique(skb_prev, maxfraglen);
                        }
 
                        /*
index 5bf70b1442eae1f0be6497774be8ea7ceac9cbf1..1b528aa132007dc1b16e475dfe7eb4311ae76599 100644 (file)
@@ -1046,7 +1046,7 @@ alloc_new_skb:
                                skb_prev->csum = csum_sub(skb_prev->csum,
                                                          skb->csum);
                                data += fraggap;
-                               skb_trim(skb_prev, maxfraglen);
+                               pskb_trim_unique(skb_prev, maxfraglen);
                        }
                        copy = datalen - transhdrlen - fraggap;
                        if (copy < 0) {