[LLC]: skb allocation size for responses
Allocate the skb for llc responses with the received packet size by
using the size adjustable llc_frame_alloc.
Don't allocate useless extra payload.
Cleanup magic numbers.
So, this fixes oops.
Reported by Jim Westfall:
kernel: skb_over_panic: text:c0541fc7 len:1000 put:997 head:c166ac00 data:c166ac2f tail:0xc166b017 end:0xc166ac80 dev:eth0
kernel: ------------[ cut here ]------------
kernel: kernel BUG at net/core/skbuff.c:95!
Signed-off-by: Joonwoo Park <joonwpark81@gmail.com>
Acked-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c
index 2525165..e2ddde7 100644
--- a/net/llc/llc_sap.c
+++ b/net/llc/llc_sap.c
@@ -24,20 +24,41 @@
#include <net/tcp_states.h>
#include <linux/llc.h>
+static int llc_mac_header_len(unsigned short devtype)
+{
+ switch (devtype) {
+ case ARPHRD_ETHER:
+ case ARPHRD_LOOPBACK:
+ return sizeof(struct ethhdr);
+#ifdef CONFIG_TR
+ case ARPHRD_IEEE802_TR:
+ return sizeof(struct trh_hdr);
+#endif
+ }
+ return 0;
+}
+
/**
* llc_alloc_frame - allocates sk_buff for frame
* @dev: network device this skb will be sent over
+ * @type: pdu type to allocate
+ * @data_size: data size to allocate
*
* Allocates an sk_buff for frame and initializes sk_buff fields.
* Returns allocated skb or %NULL when out of memory.
*/
-struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev)
+struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev,
+ u8 type, u32 data_size)
{
- struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC);
+ int hlen = type == LLC_PDU_TYPE_U ? 3 : 4;
+ struct sk_buff *skb;
+
+ hlen += llc_mac_header_len(dev->type);
+ skb = alloc_skb(hlen + data_size, GFP_ATOMIC);
if (skb) {
skb_reset_mac_header(skb);
- skb_reserve(skb, 50);
+ skb_reserve(skb, hlen);
skb_reset_network_header(skb);
skb_reset_transport_header(skb);
skb->protocol = htons(ETH_P_802_2);