Commit 82182ed2 authored by Al Viro's avatar Al Viro Committed by Adrian Bunk

add forgotten ->b_data in memcpy() call in ext3/resize.c (oopsable)

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarAdrian Bunk <bunk@stusta.de>
parent cf76a4a8
...@@ -213,7 +213,7 @@ static int setup_new_group_blocks(struct super_block *sb, ...@@ -213,7 +213,7 @@ static int setup_new_group_blocks(struct super_block *sb,
goto exit_bh; goto exit_bh;
} }
lock_buffer(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); set_buffer_uptodate(gdb);
unlock_buffer(bh); unlock_buffer(bh);
ext3_journal_dirty_metadata(handle, gdb); ext3_journal_dirty_metadata(handle, gdb);
......
...@@ -997,6 +997,21 @@ static inline int pskb_trim(struct sk_buff *skb, unsigned int len) ...@@ -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; 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_orphan - orphan a buffer
* @skb: buffer to orphan * @skb: buffer to orphan
......
...@@ -946,7 +946,7 @@ int ip_append_data(struct sock *sk, ...@@ -946,7 +946,7 @@ int ip_append_data(struct sock *sk,
skb_prev->csum = csum_sub(skb_prev->csum, skb_prev->csum = csum_sub(skb_prev->csum,
skb->csum); skb->csum);
data += fraggap; data += fraggap;
skb_trim(skb_prev, maxfraglen); pskb_trim_unique(skb_prev, maxfraglen);
} }
copy = datalen - transhdrlen - fraggap; copy = datalen - transhdrlen - fraggap;
...@@ -1139,7 +1139,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, ...@@ -1139,7 +1139,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page,
data, fraggap, 0); data, fraggap, 0);
skb_prev->csum = csum_sub(skb_prev->csum, skb_prev->csum = csum_sub(skb_prev->csum,
skb->csum); skb->csum);
skb_trim(skb_prev, maxfraglen); pskb_trim_unique(skb_prev, maxfraglen);
} }
/* /*
......
...@@ -1046,7 +1046,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, ...@@ -1046,7 +1046,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
skb_prev->csum = csum_sub(skb_prev->csum, skb_prev->csum = csum_sub(skb_prev->csum,
skb->csum); skb->csum);
data += fraggap; data += fraggap;
skb_trim(skb_prev, maxfraglen); pskb_trim_unique(skb_prev, maxfraglen);
} }
copy = datalen - transhdrlen - fraggap; copy = datalen - transhdrlen - fraggap;
if (copy < 0) { if (copy < 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment