From: Pascal H. <pa...@pl...> - 2011-08-03 20:22:50
|
- Check that the LLC header matches the expected payload type. - Remove the FCS bytes only if the PID is ethernet with FCS. - Check the data length before removing the FCS or padding bytes. Signed-off-by: Pascal Hambourg <pa...@pl...> --- net/atm/br2684.c | 70 ++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff -uprN a/net/atm/br2684.c b/net/atm/br2684.c --- a/net/atm/br2684.c 2011-08-01 23:54:44.000000000 +0200 +++ b/net/atm/br2684.c 2011-08-02 20:21:22.000000000 +0200 @@ -404,37 +404,44 @@ static void br2684_push(struct atm_vcc * atm_return(atmvcc, skb->truesize); pr_debug("skb from brdev %p\n", brdev); if (brvcc->encaps == e_llc) { - - if (skb->len > 7 && skb->data[7] == 0x01) - __skb_trim(skb, skb->len - 4); - - /* accept packets that have "ipv[46]" in the snap header */ - if ((skb->len >= (sizeof(llc_oui_ipv4))) && - (memcmp(skb->data, llc_oui_ipv4, - sizeof(llc_oui_ipv4) - BR2684_ETHERTYPE_LEN) == 0)) { - if (memcmp(skb->data + 6, ethertype_ipv6, - sizeof(ethertype_ipv6)) == 0) - skb->protocol = htons(ETH_P_IPV6); - else if (memcmp(skb->data + 6, ethertype_ipv4, - sizeof(ethertype_ipv4)) == 0) - skb->protocol = htons(ETH_P_IP); - else + if (brdev->payload == p_routed) { + /* accept packets that have "ipv[46]" in the snap header */ + if ((skb->len >= (sizeof(llc_oui_ipv4))) && + (memcmp(skb->data, llc_oui_ipv4, + sizeof(llc_oui_ipv4) - BR2684_ETHERTYPE_LEN) == 0)) { + if (memcmp(skb->data + 6, ethertype_ipv6, + sizeof(ethertype_ipv6)) == 0) + skb->protocol = htons(ETH_P_IPV6); + else if (memcmp(skb->data + 6, ethertype_ipv4, + sizeof(ethertype_ipv4)) == 0) + skb->protocol = htons(ETH_P_IP); + else + goto error; + skb_pull(skb, sizeof(llc_oui_ipv4)); + skb_reset_network_header(skb); + skb->pkt_type = PACKET_HOST; + } else { goto error; - skb_pull(skb, sizeof(llc_oui_ipv4)); - skb_reset_network_header(skb); - skb->pkt_type = PACKET_HOST; - /* - * Let us waste some time for checking the encapsulation. - * Note, that only 7 char is checked so frames with a valid FCS - * are also accepted (but FCS is not checked of course). - */ - } else if ((skb->len >= sizeof(llc_oui_pid_pad)) && - (memcmp(skb->data, llc_oui_pid_pad, 7) == 0)) { - skb_pull(skb, sizeof(llc_oui_pid_pad)); - skb->protocol = eth_type_trans(skb, net_dev); - } else - goto error; - + } + } else { /* p_bridged */ + /* + * Let us waste some time for checking the encapsulation. + * Note, that only 7 char is checked so frames with a valid FCS + * are also accepted (but FCS is not checked of course). + */ + if ((skb->len >= sizeof(llc_oui_pid_pad)) && + (memcmp(skb->data, llc_oui_pid_pad, 7) == 0)) { + if (skb->data[7] == 0x01 && + skb->len >= sizeof(llc_oui_pid_pad) + 4) + __skb_trim(skb, skb->len - 4); /* trim FCS */ + else if (skb->data[7] != 0x07) + goto error; + skb_pull(skb, sizeof(llc_oui_pid_pad)); + skb->protocol = eth_type_trans(skb, net_dev); + } else { + goto error; + } + } } else { /* e_vc */ if (brdev->payload == p_routed) { struct iphdr *iph; @@ -450,7 +457,8 @@ static void br2684_push(struct atm_vcc * skb->pkt_type = PACKET_HOST; } else { /* p_bridged */ /* first 2 chars should be 0 */ - if (*((u16 *) (skb->data)) != 0) + if (skb->len < BR2684_PAD_LEN || + *((u16 *) (skb->data)) != 0) /* needed ? */ goto error; skb_pull(skb, BR2684_PAD_LEN); skb->protocol = eth_type_trans(skb, net_dev); |