/[pkg-src]/trunk/kernel26-magellan/patches-2.6.16-r9/0130-2.6.16.15-SCTP-infinite-recursion-CVE-2006-2274.patch |
Contents of /trunk/kernel26-magellan/patches-2.6.16-r9/0130-2.6.16.15-SCTP-infinite-recursion-CVE-2006-2274.patch
Parent Directory | Revision Log
Revision 70 -
(show annotations)
(download)
Thu May 11 19:09:22 2006 UTC (18 years, 4 months ago) by niro
File size: 2773 byte(s)
Thu May 11 19:09:22 2006 UTC (18 years, 4 months ago) by niro
File size: 2773 byte(s)
import
1 | From: Vladislav Yasevich <vladsilav.yasevich@hp.com> |
2 | Date: Sat, 6 May 2006 00:03:49 +0000 (-0700) |
3 | Subject: [PATCH] SCTP: Prevent possible infinite recursion with multiple bundled DATA. (CVE ... |
4 | X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/stable/linux-2.6.16.y.git;a=commitdiff;h=25958c671804a3829d822fc3ccc3eff534b1aaa0 |
5 | |
6 | [PATCH] SCTP: Prevent possible infinite recursion with multiple bundled DATA. (CVE-2006-2274) |
7 | |
8 | There is a rare situation that causes lksctp to go into infinite recursion |
9 | and crash the system. The trigger is a packet that contains at least the |
10 | first two DATA fragments of a message bundled together. The recursion is |
11 | triggered when the user data buffer is smaller that the full data message. |
12 | The problem is that we clone the skb for every fragment in the message. |
13 | When reassembling the full message, we try to link skbs from the "first |
14 | fragment" clone using the frag_list. However, since the frag_list is shared |
15 | between two clones in this rare situation, we end up setting the frag_list |
16 | pointer of the second fragment to point to itself. This causes |
17 | sctp_skb_pull() to potentially recurse indefinitely. |
18 | |
19 | Proposed solution is to make a copy of the skb when attempting to link |
20 | things using frag_list. |
21 | |
22 | Signed-off-by: Vladislav Yasevich <vladsilav.yasevich@hp.com> |
23 | Signed-off-by: Sridhar Samudrala <sri@us.ibm.com> |
24 | Signed-off-by: David S. Miller <davem@davemloft.net> |
25 | Signed-off-by: Chris Wright <chrisw@sous-sol.org> |
26 | --- |
27 | |
28 | --- a/net/sctp/ulpqueue.c |
29 | +++ b/net/sctp/ulpqueue.c |
30 | @@ -279,6 +279,7 @@ static inline void sctp_ulpq_store_reasm |
31 | static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *queue, struct sk_buff *f_frag, struct sk_buff *l_frag) |
32 | { |
33 | struct sk_buff *pos; |
34 | + struct sk_buff *new = NULL; |
35 | struct sctp_ulpevent *event; |
36 | struct sk_buff *pnext, *last; |
37 | struct sk_buff *list = skb_shinfo(f_frag)->frag_list; |
38 | @@ -297,11 +298,33 @@ static struct sctp_ulpevent *sctp_make_r |
39 | */ |
40 | if (last) |
41 | last->next = pos; |
42 | - else |
43 | - skb_shinfo(f_frag)->frag_list = pos; |
44 | + else { |
45 | + if (skb_cloned(f_frag)) { |
46 | + /* This is a cloned skb, we can't just modify |
47 | + * the frag_list. We need a new skb to do that. |
48 | + * Instead of calling skb_unshare(), we'll do it |
49 | + * ourselves since we need to delay the free. |
50 | + */ |
51 | + new = skb_copy(f_frag, GFP_ATOMIC); |
52 | + if (!new) |
53 | + return NULL; /* try again later */ |
54 | + |
55 | + new->sk = f_frag->sk; |
56 | + |
57 | + skb_shinfo(new)->frag_list = pos; |
58 | + } else |
59 | + skb_shinfo(f_frag)->frag_list = pos; |
60 | + } |
61 | |
62 | /* Remove the first fragment from the reassembly queue. */ |
63 | __skb_unlink(f_frag, queue); |
64 | + |
65 | + /* if we did unshare, then free the old skb and re-assign */ |
66 | + if (new) { |
67 | + kfree_skb(f_frag); |
68 | + f_frag = new; |
69 | + } |
70 | + |
71 | while (pos) { |
72 | |
73 | pnext = pos->next; |