Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Joonwoo Park and committed by
David S. Miller
f83f1768 b50660f1

+74 -35
+2 -2
include/net/llc_pdu.h
··· 381 381 xid_info->fmt_id = LLC_XID_FMT_ID; /* 0x81 */ 382 382 xid_info->type = svcs_supported; 383 383 xid_info->rw = rx_window << 1; /* size of receive window */ 384 - skb_put(skb, 3); 384 + skb_put(skb, sizeof(struct llc_xid_info)); 385 385 } 386 386 387 387 /** ··· 406 406 xid_info->fmt_id = LLC_XID_FMT_ID; 407 407 xid_info->type = svcs_supported; 408 408 xid_info->rw = rx_window << 1; 409 - skb_put(skb, 3); 409 + skb_put(skb, sizeof(struct llc_xid_info)); 410 410 } 411 411 412 412 /* LLC Type 2 FRMR response information field format */
+5 -2
include/net/llc_sap.h
··· 1 1 #ifndef LLC_SAP_H 2 2 #define LLC_SAP_H 3 + 4 + #include <asm/types.h> 5 + 3 6 /* 4 7 * Copyright (c) 1997 by Procom Technology,Inc. 5 8 * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br> ··· 22 19 extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb); 23 20 extern void llc_save_primitive(struct sock *sk, struct sk_buff* skb, 24 21 unsigned char prim); 25 - extern struct sk_buff *llc_alloc_frame(struct sock *sk, 26 - struct net_device *dev); 22 + extern struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev, 23 + u8 type, u32 data_size); 27 24 28 25 extern void llc_build_and_send_test_pkt(struct llc_sap *sap, 29 26 struct sk_buff *skb,
+25 -22
net/llc/llc_c_ac.c
··· 198 198 { 199 199 int rc = -ENOBUFS; 200 200 struct llc_sock *llc = llc_sk(sk); 201 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 201 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); 202 202 203 203 if (nskb) { 204 204 struct llc_sap *sap = llc->sap; ··· 223 223 { 224 224 int rc = -ENOBUFS; 225 225 struct llc_sock *llc = llc_sk(sk); 226 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 226 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); 227 227 228 228 if (nskb) { 229 229 struct llc_sap *sap = llc->sap; ··· 249 249 { 250 250 int rc = -ENOBUFS; 251 251 struct llc_sock *llc = llc_sk(sk); 252 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 252 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); 253 253 254 254 if (nskb) { 255 255 struct llc_sap *sap = llc->sap; ··· 282 282 llc_pdu_decode_pf_bit(skb, &f_bit); 283 283 else 284 284 f_bit = 0; 285 - nskb = llc_alloc_frame(sk, llc->dev); 285 + nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 286 + sizeof(struct llc_frmr_info)); 286 287 if (nskb) { 287 288 struct llc_sap *sap = llc->sap; 288 289 ··· 307 306 { 308 307 int rc = -ENOBUFS; 309 308 struct llc_sock *llc = llc_sk(sk); 310 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 309 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 310 + sizeof(struct llc_frmr_info)); 311 311 312 312 if (nskb) { 313 313 struct llc_sap *sap = llc->sap; ··· 338 336 struct llc_sock *llc = llc_sk(sk); 339 337 340 338 llc_pdu_decode_pf_bit(skb, &f_bit); 341 - nskb = llc_alloc_frame(sk, llc->dev); 339 + nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 340 + sizeof(struct llc_frmr_info)); 342 341 if (nskb) { 343 342 struct llc_sap *sap = llc->sap; 344 343 struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); ··· 427 424 struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); 428 425 int rc = -ENOBUFS; 429 426 struct llc_sock *llc = llc_sk(sk); 430 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 427 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); 431 428 432 429 if (nskb) { 433 430 struct llc_sap *sap = llc->sap; ··· 462 459 { 463 460 int rc = -ENOBUFS; 464 461 struct llc_sock *llc = llc_sk(sk); 465 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 462 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); 466 463 467 464 if (nskb) { 468 465 struct llc_sap *sap = llc->sap; ··· 486 483 { 487 484 int rc = -ENOBUFS; 488 485 struct llc_sock *llc = llc_sk(sk); 489 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 486 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); 490 487 491 488 if (nskb) { 492 489 struct llc_sap *sap = llc->sap; ··· 510 507 { 511 508 int rc = -ENOBUFS; 512 509 struct llc_sock *llc = llc_sk(sk); 513 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 510 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); 514 511 515 512 if (nskb) { 516 513 struct llc_sap *sap = llc->sap; ··· 534 531 { 535 532 int rc = -ENOBUFS; 536 533 struct llc_sock *llc = llc_sk(sk); 537 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 534 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); 538 535 539 536 if (nskb) { 540 537 struct llc_sap *sap = llc->sap; ··· 558 555 { 559 556 int rc = -ENOBUFS; 560 557 struct llc_sock *llc = llc_sk(sk); 561 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 558 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); 562 559 563 560 if (nskb) { 564 561 struct llc_sap *sap = llc->sap; ··· 582 579 { 583 580 int rc = -ENOBUFS; 584 581 struct llc_sock *llc = llc_sk(sk); 585 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 582 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); 586 583 587 584 if (nskb) { 588 585 struct llc_sap *sap = llc->sap; ··· 618 615 { 619 616 int rc = -ENOBUFS; 620 617 struct llc_sock *llc = llc_sk(sk); 621 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 618 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); 622 619 623 620 if (nskb) { 624 621 struct llc_sap *sap = llc->sap; ··· 642 639 { 643 640 int rc = -ENOBUFS; 644 641 struct llc_sock *llc = llc_sk(sk); 645 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 642 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); 646 643 647 644 if (nskb) { 648 645 struct llc_sap *sap = llc->sap; ··· 666 663 { 667 664 int rc = -ENOBUFS; 668 665 struct llc_sock *llc = llc_sk(sk); 669 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 666 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); 670 667 671 668 if (nskb) { 672 669 struct llc_sap *sap = llc->sap; ··· 691 688 { 692 689 int rc = -ENOBUFS; 693 690 struct llc_sock *llc = llc_sk(sk); 694 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 691 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); 695 692 696 693 if (nskb) { 697 694 struct llc_sap *sap = llc->sap; ··· 715 712 { 716 713 int rc = -ENOBUFS; 717 714 struct llc_sock *llc = llc_sk(sk); 718 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 715 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); 719 716 720 717 if (nskb) { 721 718 struct llc_sap *sap = llc->sap; ··· 739 736 { 740 737 int rc = -ENOBUFS; 741 738 struct llc_sock *llc = llc_sk(sk); 742 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 739 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); 743 740 744 741 if (nskb) { 745 742 struct llc_sap *sap = llc->sap; ··· 773 770 { 774 771 int rc = -ENOBUFS; 775 772 struct llc_sock *llc = llc_sk(sk); 776 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 773 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); 777 774 778 775 if (nskb) { 779 776 struct llc_sap *sap = llc->sap; ··· 802 799 u8 f_bit; 803 800 int rc = -ENOBUFS; 804 801 struct llc_sock *llc = llc_sk(sk); 805 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 802 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); 806 803 807 804 llc_pdu_decode_pf_bit(skb, &f_bit); 808 805 if (nskb) { ··· 959 956 { 960 957 int rc = -ENOBUFS; 961 958 struct llc_sock *llc = llc_sk(sk); 962 - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 959 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); 963 960 964 961 if (nskb) { 965 962 struct llc_sap *sap = llc->sap;
+1 -1
net/llc/llc_pdu.c
··· 241 241 FRMR_INFO_SET_PDU_INFO_2LONG_IND(frmr_info, vzyxw); 242 242 FRMR_INFO_SET_PDU_INVALID_Nr_IND(frmr_info, vzyxw); 243 243 FRMR_INFO_SET_PDU_INVALID_Ns_IND(frmr_info, vzyxw); 244 - skb_put(skb, 5); 244 + skb_put(skb, sizeof(struct llc_frmr_info)); 245 245 } 246 246 247 247 /**
+7 -2
net/llc/llc_s_ac.c
··· 103 103 llc_pdu_decode_sa(skb, mac_da); 104 104 llc_pdu_decode_da(skb, mac_sa); 105 105 llc_pdu_decode_ssap(skb, &dsap); 106 - nskb = llc_alloc_frame(NULL, skb->dev); 106 + nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, 107 + sizeof(struct llc_xid_info)); 107 108 if (!nskb) 108 109 goto out; 109 110 llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, ··· 145 144 u8 mac_da[ETH_ALEN], mac_sa[ETH_ALEN], dsap; 146 145 struct sk_buff *nskb; 147 146 int rc = 1; 147 + u32 data_size; 148 148 149 149 llc_pdu_decode_sa(skb, mac_da); 150 150 llc_pdu_decode_da(skb, mac_sa); 151 151 llc_pdu_decode_ssap(skb, &dsap); 152 - nskb = llc_alloc_frame(NULL, skb->dev); 152 + 153 + /* The test request command is type U (llc_len = 3) */ 154 + data_size = ntohs(eth_hdr(skb)->h_proto) - 3; 155 + nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, data_size); 153 156 if (!nskb) 154 157 goto out; 155 158 llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
+24 -3
net/llc/llc_sap.c
··· 24 24 #include <net/tcp_states.h> 25 25 #include <linux/llc.h> 26 26 27 + static int llc_mac_header_len(unsigned short devtype) 28 + { 29 + switch (devtype) { 30 + case ARPHRD_ETHER: 31 + case ARPHRD_LOOPBACK: 32 + return sizeof(struct ethhdr); 33 + #ifdef CONFIG_TR 34 + case ARPHRD_IEEE802_TR: 35 + return sizeof(struct trh_hdr); 36 + #endif 37 + } 38 + return 0; 39 + } 40 + 27 41 /** 28 42 * llc_alloc_frame - allocates sk_buff for frame 29 43 * @dev: network device this skb will be sent over 44 + * @type: pdu type to allocate 45 + * @data_size: data size to allocate 30 46 * 31 47 * Allocates an sk_buff for frame and initializes sk_buff fields. 32 48 * Returns allocated skb or %NULL when out of memory. 33 49 */ 34 - struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev) 50 + struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev, 51 + u8 type, u32 data_size) 35 52 { 36 - struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC); 53 + int hlen = type == LLC_PDU_TYPE_U ? 3 : 4; 54 + struct sk_buff *skb; 55 + 56 + hlen += llc_mac_header_len(dev->type); 57 + skb = alloc_skb(hlen + data_size, GFP_ATOMIC); 37 58 38 59 if (skb) { 39 60 skb_reset_mac_header(skb); 40 - skb_reserve(skb, 50); 61 + skb_reserve(skb, hlen); 41 62 skb_reset_network_header(skb); 42 63 skb_reset_transport_header(skb); 43 64 skb->protocol = htons(ETH_P_802_2);
+10 -3
net/llc/llc_station.c
··· 253 253 static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb) 254 254 { 255 255 int rc = 1; 256 - struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev); 256 + struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, 257 + sizeof(struct llc_xid_info)); 257 258 258 259 if (!nskb) 259 260 goto out; ··· 275 274 { 276 275 u8 mac_da[ETH_ALEN], dsap; 277 276 int rc = 1; 278 - struct sk_buff* nskb = llc_alloc_frame(NULL, skb->dev); 277 + struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, 278 + sizeof(struct llc_xid_info)); 279 279 280 280 if (!nskb) 281 281 goto out; ··· 300 298 { 301 299 u8 mac_da[ETH_ALEN], dsap; 302 300 int rc = 1; 303 - struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev); 301 + u32 data_size; 302 + struct sk_buff *nskb; 303 + 304 + /* The test request command is type U (llc_len = 3) */ 305 + data_size = ntohs(eth_hdr(skb)->h_proto) - 3; 306 + nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, data_size); 304 307 305 308 if (!nskb) 306 309 goto out;