From ba0c53547c4f2f0ffadd7c339cf7cfdf0da19785 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 6 Oct 2003 12:58:15 -0700 Subject: [LAPB]: Fix packet handlers to be PKT_CAN_SHARE_SKB. --- drivers/net/wan/comx-proto-lapb.c | 4 ++++ drivers/net/wan/hdlc_x25.c | 7 ++++++- drivers/net/wan/lapbether.c | 22 ++++++++++++++++------ include/net/lapb.h | 2 +- net/lapb/lapb_in.c | 5 ++++- net/lapb/lapb_subr.c | 16 ++++++++++++++-- 6 files changed, 45 insertions(+), 11 deletions(-) diff --git a/drivers/net/wan/comx-proto-lapb.c b/drivers/net/wan/comx-proto-lapb.c index 30c818601ecf..f3d0fb325c53 100644 --- a/drivers/net/wan/comx-proto-lapb.c +++ b/drivers/net/wan/comx-proto-lapb.c @@ -372,6 +372,10 @@ static int comxlapb_data_indication(void *token, struct sk_buff *skb) if (ch->dev->type == ARPHRD_X25) { skb_push(skb, 1); + + if (skb_cow(skb, 1)) + return NET_RX_DROP; + skb->data[0] = 0; // indicate data for X25 skb->protocol = htons(ETH_P_X25); } else { diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c index 3f0612c4c4be..76e7daf5c3e1 100644 --- a/drivers/net/wan/hdlc_x25.c +++ b/drivers/net/wan/hdlc_x25.c @@ -68,7 +68,12 @@ static int x25_data_indication(void *token, struct sk_buff *skb) hdlc_device *hdlc = token; unsigned char *ptr; - ptr = skb_push(skb, 1); + skb_push(skb, 1); + + if (skb_cow(skb, 1)) + return NET_RX_DROP; + + ptr = skb->data; *ptr = 0; skb->dev = hdlc_to_dev(hdlc); diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index 293ce6cf9aca..271b7c64ebca 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -89,14 +89,15 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe int len, err; struct lapbethdev *lapbeth; - skb->sk = NULL; /* Initially we don't know who it's for */ + if (!pskb_may_pull(skb, 2)) + goto drop; rcu_read_lock(); lapbeth = lapbeth_get_x25_dev(dev); if (!lapbeth) - goto drop; + goto drop_unlock; if (!netif_running(lapbeth->axdev)) - goto drop; + goto drop_unlock; lapbeth->stats.rx_packets++; @@ -108,14 +109,17 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe if ((err = lapb_data_received(lapbeth, skb)) != LAPB_OK) { printk(KERN_DEBUG "lapbether: lapb_data_received err - %d\n", err); - goto drop; + goto drop_unlock; } out: rcu_read_unlock(); return 0; -drop: +drop_unlock: kfree_skb(skb); goto out; +drop: + kfree_skb(skb); + return 0; } static int lapbeth_data_indication(void *token, struct sk_buff *skb) @@ -123,7 +127,12 @@ static int lapbeth_data_indication(void *token, struct sk_buff *skb) struct lapbethdev *lapbeth = (struct lapbethdev *)token; unsigned char *ptr; - ptr = skb_push(skb, 1); + skb_push(skb, 1); + + if (skb_cow(skb, 1)) + return NET_RX_DROP; + + ptr = skb->data; *ptr = 0x00; skb->dev = lapbeth->axdev; @@ -426,6 +435,7 @@ static int lapbeth_device_event(struct notifier_block *this, static struct packet_type lapbeth_packet_type = { .type = __constant_htons(ETH_P_DEC), .func = lapbeth_rcv, + .data = PKT_CAN_SHARE_SKB, }; static struct notifier_block lapbeth_dev_notifier = { diff --git a/include/net/lapb.h b/include/net/lapb.h index 50292be77a71..83a241043842 100644 --- a/include/net/lapb.h +++ b/include/net/lapb.h @@ -129,7 +129,7 @@ extern void lapb_clear_queues(struct lapb_cb *lapb); extern void lapb_frames_acked(struct lapb_cb *lapb, unsigned short); extern void lapb_requeue_frames(struct lapb_cb *lapb); extern int lapb_validate_nr(struct lapb_cb *lapb, unsigned short); -extern void lapb_decode(struct lapb_cb *lapb, struct sk_buff *, struct lapb_frame *); +extern int lapb_decode(struct lapb_cb *lapb, struct sk_buff *, struct lapb_frame *); extern void lapb_send_control(struct lapb_cb *lapb, int, int, int); extern void lapb_transmit_frmr(struct lapb_cb *lapb); diff --git a/net/lapb/lapb_in.c b/net/lapb/lapb_in.c index 431c6918aaf0..2275e15a9719 100644 --- a/net/lapb/lapb_in.c +++ b/net/lapb/lapb_in.c @@ -702,7 +702,10 @@ void lapb_data_input(struct lapb_cb *lapb, struct sk_buff *skb) { struct lapb_frame frame; - lapb_decode(lapb, skb, &frame); + if (lapb_decode(lapb, skb, &frame) < 0) { + kfree_skb(skb); + return; + } switch (lapb->state) { case LAPB_STATE_0: diff --git a/net/lapb/lapb_subr.c b/net/lapb/lapb_subr.c index 36e1769330e4..e1ae5fd7302d 100644 --- a/net/lapb/lapb_subr.c +++ b/net/lapb/lapb_subr.c @@ -107,8 +107,8 @@ int lapb_validate_nr(struct lapb_cb *lapb, unsigned short nr) * This routine is the centralised routine for parsing the control * information for the different frame formats. */ -void lapb_decode(struct lapb_cb *lapb, struct sk_buff *skb, - struct lapb_frame *frame) +int lapb_decode(struct lapb_cb *lapb, struct sk_buff *skb, + struct lapb_frame *frame) { frame->type = LAPB_ILLEGAL; @@ -118,6 +118,12 @@ void lapb_decode(struct lapb_cb *lapb, struct sk_buff *skb, skb->data[0], skb->data[1], skb->data[2]); #endif + /* We always need to look at 2 bytes, sometimes we need + * to look at 3 and those cases are handled below. + */ + if (!pskb_may_pull(skb, 2)) + return -1; + if (lapb->mode & LAPB_MLP) { if (lapb->mode & LAPB_DCE) { if (skb->data[0] == LAPB_ADDR_D) @@ -148,6 +154,8 @@ void lapb_decode(struct lapb_cb *lapb, struct sk_buff *skb, if (lapb->mode & LAPB_EXTENDED) { if (!(skb->data[0] & LAPB_S)) { + if (!pskb_may_pull(skb, 2)) + return -1; /* * I frame - carries NR/NS/PF */ @@ -159,6 +167,8 @@ void lapb_decode(struct lapb_cb *lapb, struct sk_buff *skb, frame->control[1] = skb->data[1]; skb_pull(skb, 2); } else if ((skb->data[0] & LAPB_U) == 1) { + if (!pskb_may_pull(skb, 2)) + return -1; /* * S frame - take out PF/NR */ @@ -206,6 +216,8 @@ void lapb_decode(struct lapb_cb *lapb, struct sk_buff *skb, skb_pull(skb, 1); } + + return 0; } /* -- cgit v1.2.3