]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Revert skb_copy_datagram_iovec recursion patch, from DaveM
authorChris Wright <chrisw@sous-sol.org>
Tue, 14 Feb 2006 01:10:35 +0000 (17:10 -0800)
committerChris Wright <chrisw@sous-sol.org>
Tue, 14 Feb 2006 01:10:35 +0000 (17:10 -0800)
queue/revert-skb_copy_datagram_iovec-recursion-elimination.patch [new file with mode: 0644]
queue/series

diff --git a/queue/revert-skb_copy_datagram_iovec-recursion-elimination.patch b/queue/revert-skb_copy_datagram_iovec-recursion-elimination.patch
new file mode 100644 (file)
index 0000000..7745582
--- /dev/null
@@ -0,0 +1,128 @@
+From stable-bounces@linux.kernel.org  Mon Feb 13 16:49:33 2006
+Date: Mon, 13 Feb 2006 16:46:25 -0800 (PST)
+From: "David S. Miller" <davem@davemloft.net>
+To: stable@kernel.org
+Cc: 
+Subject: [NET]: Revert skb_copy_datagram_iovec() recursion elimination.
+
+Revert the following changeset:
+
+bc8dfcb93970ad7139c976356bfc99d7e251deaf
+
+Recursive SKB frag lists are really possible and disallowing
+them breaks things.
+
+Noticed by: Jesse Brandeburg <jesse.brandeburg@intel.com>
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+
+ net/core/datagram.c |   81 ++++++++++++++++++++++++++++++++++------------------
+ 1 files changed, 53 insertions(+), 28 deletions(-)
+
+--- linux-2.6.15.4.orig/net/core/datagram.c
++++ linux-2.6.15.4/net/core/datagram.c
+@@ -211,49 +211,74 @@ void skb_free_datagram(struct sock *sk, 
+ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
+                           struct iovec *to, int len)
+ {
+-      int i, err, fraglen, end = 0;
+-      struct sk_buff *next = skb_shinfo(skb)->frag_list;
++      int start = skb_headlen(skb);
++      int i, copy = start - offset;
+-      if (!len)
+-              return 0;
++      /* Copy header. */
++      if (copy > 0) {
++              if (copy > len)
++                      copy = len;
++              if (memcpy_toiovec(to, skb->data + offset, copy))
++                      goto fault;
++              if ((len -= copy) == 0)
++                      return 0;
++              offset += copy;
++      }
+-next_skb:
+-      fraglen = skb_headlen(skb);
+-      i = -1;
++      /* Copy paged appendix. Hmm... why does this look so complicated? */
++      for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
++              int end;
+-      while (1) {
+-              int start = end;
++              BUG_TRAP(start <= offset + len);
+-              if ((end += fraglen) > offset) {
+-                      int copy = end - offset, o = offset - start;
++              end = start + skb_shinfo(skb)->frags[i].size;
++              if ((copy = end - offset) > 0) {
++                      int err;
++                      u8  *vaddr;
++                      skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
++                      struct page *page = frag->page;
+                       if (copy > len)
+                               copy = len;
+-                      if (i == -1)
+-                              err = memcpy_toiovec(to, skb->data + o, copy);
+-                      else {
+-                              skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+-                              struct page *page = frag->page;
+-                              void *p = kmap(page) + frag->page_offset + o;
+-                              err = memcpy_toiovec(to, p, copy);
+-                              kunmap(page);
+-                      }
++                      vaddr = kmap(page);
++                      err = memcpy_toiovec(to, vaddr + frag->page_offset +
++                                           offset - start, copy);
++                      kunmap(page);
+                       if (err)
+                               goto fault;
+                       if (!(len -= copy))
+                               return 0;
+                       offset += copy;
+               }
+-              if (++i >= skb_shinfo(skb)->nr_frags)
+-                      break;
+-              fraglen = skb_shinfo(skb)->frags[i].size;
++              start = end;
+       }
+-      if (next) {
+-              skb = next;
+-              BUG_ON(skb_shinfo(skb)->frag_list);
+-              next = skb->next;
+-              goto next_skb;
++
++      if (skb_shinfo(skb)->frag_list) {
++              struct sk_buff *list = skb_shinfo(skb)->frag_list;
++
++              for (; list; list = list->next) {
++                      int end;
++
++                      BUG_TRAP(start <= offset + len);
++
++                      end = start + list->len;
++                      if ((copy = end - offset) > 0) {
++                              if (copy > len)
++                                      copy = len;
++                              if (skb_copy_datagram_iovec(list,
++                                                          offset - start,
++                                                          to, copy))
++                                      goto fault;
++                              if ((len -= copy) == 0)
++                                      return 0;
++                              offset += copy;
++                      }
++                      start = end;
++              }
+       }
++      if (!len)
++              return 0;
++
+ fault:
+       return -EFAULT;
+ }
index d550294aacefe05d9a9ccb82bb5fc3501a67533e..9f4e8a59c2d63c223d45f06f84acb611e172e023 100644 (file)
@@ -5,3 +5,4 @@ netfilter-missing-symbol.patch
 i386-move-phys_proc_id-early-intel-workaround-to-correct-function.patch
 hugetlbfs-mmap-enomem-failure.patch
 reiserfs-disable-automatic-enabling-of-reiserfs-inode-attributes.patch
+revert-skb_copy_datagram_iovec-recursion-elimination.patch