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 {
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);
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++;
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)
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;
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 = {
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);
{
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:
* 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;
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)
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
*/
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
*/
skb_pull(skb, 1);
}
+
+ return 0;
}
/*