diff options
author | Shyam Iyer <shyam_iyer@dell.com> | 2009-01-29 19:12:42 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-01-29 19:12:42 -0500 |
commit | 71b3346d182355f19509fadb8fe45114a35cc499 (patch) | |
tree | 4f22b15445a0b722dc124ca66f23fddc689f0bf9 | |
parent | 95e3b24cfb4ec0479d2c42f7a1780d68063a542a (diff) |
net: Fix OOPS in skb_seq_read().
It oopsd for me in skb_seq_read. addr2line said it was
linux-2.6/net/core/skbuff.c:2228, which is this line:
while (st->frag_idx < skb_shinfo(st->cur_skb)->nr_frags) {
I added some printks in there and it looks like we hit this:
} else if (st->root_skb == st->cur_skb &&
skb_shinfo(st->root_skb)->frag_list) {
st->cur_skb = skb_shinfo(st->root_skb)->frag_list;
st->frag_idx = 0;
goto next_skb;
}
Actually I did some testing and added a few printks and found that the
st->cur_skb->data was 0 and hence the ptr used by iscsi_tcp was null.
This caused the kernel panic.
if (abs_offset < block_limit) {
- *data = st->cur_skb->data + abs_offset;
+ *data = st->cur_skb->data + (abs_offset - st->stepped_offset);
I enabled the debug_tcp and with a few printks found that the code did
not go to the next_skb label and could find that the sequence being
followed was this -
It hit this if condition -
if (st->cur_skb->next) {
st->cur_skb = st->cur_skb->next;
st->frag_idx = 0;
goto next_skb;
And so, now the st pointer is shifted to the next skb whereas actually
it should have hit the second else if first since the data is in the
frag_list.
else if (st->root_skb == st->cur_skb &&
skb_shinfo(st->root_skb)->frag_list) {
st->cur_skb = skb_shinfo(st->root_skb)->frag_list;
goto next_skb;
}
Reversing the two conditions the attached patch fixes the issue for me
on top of Herbert's patches.
Signed-off-by: Shyam Iyer <shyam_iyer@dell.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/core/skbuff.c | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index f23fd43539ed..da74b844f4ea 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -2250,13 +2250,13 @@ next_skb: | |||
2250 | st->frag_data = NULL; | 2250 | st->frag_data = NULL; |
2251 | } | 2251 | } |
2252 | 2252 | ||
2253 | if (st->cur_skb->next) { | 2253 | if (st->root_skb == st->cur_skb && |
2254 | st->cur_skb = st->cur_skb->next; | 2254 | skb_shinfo(st->root_skb)->frag_list) { |
2255 | st->cur_skb = skb_shinfo(st->root_skb)->frag_list; | ||
2255 | st->frag_idx = 0; | 2256 | st->frag_idx = 0; |
2256 | goto next_skb; | 2257 | goto next_skb; |
2257 | } else if (st->root_skb == st->cur_skb && | 2258 | } else if (st->cur_skb->next) { |
2258 | skb_shinfo(st->root_skb)->frag_list) { | 2259 | st->cur_skb = st->cur_skb->next; |
2259 | st->cur_skb = skb_shinfo(st->root_skb)->frag_list; | ||
2260 | st->frag_idx = 0; | 2260 | st->frag_idx = 0; |
2261 | goto next_skb; | 2261 | goto next_skb; |
2262 | } | 2262 | } |