230-tun_get_user_backport.patch 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. Index: linux-2.4.35.4/include/linux/skbuff.h
  2. ===================================================================
  3. --- linux-2.4.35.4.orig/include/linux/skbuff.h
  4. +++ linux-2.4.35.4/include/linux/skbuff.h
  5. @@ -912,6 +912,49 @@ static inline void skb_reserve(struct sk
  6. skb->tail+=len;
  7. }
  8. +/*
  9. + * CPUs often take a performance hit when accessing unaligned memory
  10. + * locations. The actual performance hit varies, it can be small if the
  11. + * hardware handles it or large if we have to take an exception and fix it
  12. + * in software.
  13. + *
  14. + * Since an ethernet header is 14 bytes network drivers often end up with
  15. + * the IP header at an unaligned offset. The IP header can be aligned by
  16. + * shifting the start of the packet by 2 bytes. Drivers should do this
  17. + * with:
  18. + *
  19. + * skb_reserve(NET_IP_ALIGN);
  20. + *
  21. + * The downside to this alignment of the IP header is that the DMA is now
  22. + * unaligned. On some architectures the cost of an unaligned DMA is high
  23. + * and this cost outweighs the gains made by aligning the IP header.
  24. + *
  25. + * Since this trade off varies between architectures, we allow NET_IP_ALIGN
  26. + * to be overridden.
  27. + */
  28. +#ifndef NET_IP_ALIGN
  29. +#define NET_IP_ALIGN 2
  30. +#endif
  31. +
  32. +/*
  33. + * The networking layer reserves some headroom in skb data (via
  34. + * dev_alloc_skb). This is used to avoid having to reallocate skb data when
  35. + * the header has to grow. In the default case, if the header has to grow
  36. + * 16 bytes or less we avoid the reallocation.
  37. + *
  38. + * Unfortunately this headroom changes the DMA alignment of the resulting
  39. + * network packet. As for NET_IP_ALIGN, this unaligned DMA is expensive
  40. + * on some architectures. An architecture can override this value,
  41. + * perhaps setting it to a cacheline in size (since that will maintain
  42. + * cacheline alignment of the DMA). It must be a power of 2.
  43. + *
  44. + * Various parts of the networking layer expect at least 16 bytes of
  45. + * headroom, you should not reduce this.
  46. + */
  47. +#ifndef NET_SKB_PAD
  48. +#define NET_SKB_PAD 16
  49. +#endif
  50. +
  51. extern int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc);
  52. static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
  53. Index: linux-2.4.35.4/drivers/net/tun.c
  54. ===================================================================
  55. --- linux-2.4.35.4.orig/drivers/net/tun.c
  56. +++ linux-2.4.35.4/drivers/net/tun.c
  57. @@ -185,22 +185,31 @@ static __inline__ ssize_t tun_get_user(s
  58. {
  59. struct tun_pi pi = { 0, __constant_htons(ETH_P_IP) };
  60. struct sk_buff *skb;
  61. - size_t len = count;
  62. + size_t len = count, align = 0;
  63. if (!(tun->flags & TUN_NO_PI)) {
  64. if ((len -= sizeof(pi)) > count)
  65. return -EINVAL;
  66. - memcpy_fromiovec((void *)&pi, iv, sizeof(pi));
  67. + if(memcpy_fromiovec((void *)&pi, iv, sizeof(pi)))
  68. + return -EFAULT;
  69. }
  70. -
  71. - if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) {
  72. +
  73. + if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV)
  74. + align = NET_IP_ALIGN;
  75. +
  76. + if (!(skb = alloc_skb(len + align, GFP_KERNEL))) {
  77. tun->stats.rx_dropped++;
  78. return -ENOMEM;
  79. }
  80. - skb_reserve(skb, 2);
  81. - memcpy_fromiovec(skb_put(skb, len), iv, len);
  82. + if (align)
  83. + skb_reserve(skb, align);
  84. + if (memcpy_fromiovec(skb_put(skb, len), iv, len)) {
  85. + tun->stats.rx_dropped++;
  86. + kfree_skb(skb);
  87. + return -EFAULT;
  88. + }
  89. skb->dev = &tun->dev;
  90. switch (tun->flags & TUN_TYPE_MASK) {
  91. @@ -271,7 +280,8 @@ static __inline__ ssize_t tun_put_user(s
  92. pi.flags |= TUN_PKT_STRIP;
  93. }
  94. - memcpy_toiovec(iv, (void *) &pi, sizeof(pi));
  95. + if(memcpy_toiovec(iv, (void *) &pi, sizeof(pi)))
  96. + return -EFAULT;
  97. total += sizeof(pi);
  98. }