Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP3:GA
grub2.6869
0007-arp-icmp-Fix-handling-in-case-of-oversized...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0007-arp-icmp-Fix-handling-in-case-of-oversized-or-invali.patch of Package grub2.6869
From 63034d32612dd34f577605dfa8b417ee9144d8cb Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko <phcoder@gmail.com> Date: Fri, 20 Mar 2015 21:14:23 +0100 Subject: [PATCH] arp, icmp: Fix handling in case of oversized or invalid packets. This restrict ARP handling to MAC and IP addresses but in practice we need only this case anyway and other cases are very rar if exist at all. It makes code much simpler and less error-prone. --- grub-core/net/arp.c | 145 +++++++++++++++++++++------------------------ grub-core/net/icmp.c | 14 +---- grub-core/net/netbuff.c | 20 +++++++ include/grub/net/netbuff.h | 1 + 4 files changed, 92 insertions(+), 88 deletions(-) Index: grub-2.02~beta2/grub-core/net/arp.c =================================================================== --- grub-2.02~beta2.orig/grub-core/net/arp.c +++ grub-2.02~beta2/grub-core/net/arp.c @@ -37,12 +37,16 @@ enum GRUB_NET_ARPHRD_ETHERNET = 1 }; -struct arphdr { +struct arppkt { grub_uint16_t hrd; grub_uint16_t pro; grub_uint8_t hln; grub_uint8_t pln; grub_uint16_t op; + grub_uint8_t sender_mac[6]; + grub_uint32_t sender_ip; + grub_uint8_t recv_mac[6]; + grub_uint32_t recv_ip; } GRUB_PACKED; static int have_pending; @@ -53,21 +57,14 @@ grub_net_arp_send_request (struct grub_n const grub_net_network_level_address_t *proto_addr) { struct grub_net_buff nb; - struct arphdr *arp_header; - grub_net_link_level_address_t target_hw_addr; - grub_uint8_t *aux, arp_data[128]; + struct arppkt *arp_packet; + grub_net_link_level_address_t target_mac_addr; grub_err_t err; int i; - grub_size_t addrlen; - grub_uint16_t etherpro; grub_uint8_t *nbd; + grub_uint8_t arp_data[128]; - if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) - { - addrlen = 4; - etherpro = GRUB_NET_ETHERTYPE_IP; - } - else + if (proto_addr->type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) return grub_error (GRUB_ERR_BUG, "unsupported address family"); /* Build a request packet. */ @@ -76,34 +73,26 @@ grub_net_arp_send_request (struct grub_n grub_netbuff_clear (&nb); grub_netbuff_reserve (&nb, 128); - err = grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + addrlen)); + err = grub_netbuff_push (&nb, sizeof (*arp_packet)); if (err) return err; - arp_header = (struct arphdr *) nb.data; - arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET); - arp_header->hln = 6; - arp_header->pro = grub_cpu_to_be16 (etherpro); - arp_header->pln = addrlen; - arp_header->op = grub_cpu_to_be16 (ARP_REQUEST); - aux = (grub_uint8_t *) arp_header + sizeof (*arp_header); + arp_packet = (struct arppkt *) nb.data; + arp_packet->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET); + arp_packet->hln = 6; + arp_packet->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP); + arp_packet->pln = 4; + arp_packet->op = grub_cpu_to_be16_compile_time (ARP_REQUEST); /* Sender hardware address. */ - grub_memcpy (aux, &inf->hwaddress.mac, 6); - - aux += 6; - /* Sender protocol address */ - grub_memcpy (aux, &inf->address.ipv4, 4); - aux += addrlen; - /* Target hardware address */ - for (i = 0; i < 6; i++) - aux[i] = 0x00; - aux += 6; + grub_memcpy (arp_packet->sender_mac, &inf->hwaddress.mac, 6); + arp_packet->sender_ip = inf->address.ipv4; + grub_memset (arp_packet->recv_mac, 0, 6); + arp_packet->recv_ip = proto_addr->ipv4; /* Target protocol address */ - grub_memcpy (aux, &proto_addr->ipv4, 4); - grub_memset (&target_hw_addr.mac, 0xff, 6); + grub_memset (&target_mac_addr.mac, 0xff, 6); nbd = nb.data; - send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); + send_ethernet_packet (inf, &nb, target_mac_addr, GRUB_NET_ETHERTYPE_ARP); for (i = 0; i < GRUB_NET_TRIES; i++) { if (grub_net_link_layer_resolve_check (inf, proto_addr)) @@ -115,7 +104,7 @@ grub_net_arp_send_request (struct grub_n if (grub_net_link_layer_resolve_check (inf, proto_addr)) return GRUB_ERR_NONE; nb.data = nbd; - send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); + send_ethernet_packet (inf, &nb, target_mac_addr, GRUB_NET_ETHERTYPE_ARP); } return GRUB_ERR_NONE; @@ -125,36 +114,27 @@ grub_err_t grub_net_arp_receive (struct grub_net_buff *nb, struct grub_net_card *card, grub_uint16_t vlantag_vid) { - struct arphdr *arp_header = (struct arphdr *) nb->data; - grub_uint8_t *sender_hardware_address; - grub_uint8_t *target_hardware_address; + struct arppkt *arp_packet = (struct arppkt *) nb->data; grub_net_network_level_address_t sender_addr, target_addr; - grub_net_link_level_address_t sender_hw_addr; + grub_net_link_level_address_t sender_mac_addr; struct grub_net_network_level_interface *inf; - grub_uint8_t *sender_protocol_address, *target_protocol_address; - sender_hardware_address = - (grub_uint8_t *) arp_header + sizeof (*arp_header); - sender_protocol_address = sender_hardware_address + arp_header->hln; - target_hardware_address = sender_protocol_address + arp_header->pln; - target_protocol_address = target_hardware_address + arp_header->hln; - if (grub_be_to_cpu16 (arp_header->pro) == GRUB_NET_ETHERTYPE_IP - && arp_header->pln == 4) - { - sender_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - grub_memcpy (&sender_addr.ipv4, sender_protocol_address, 4); - grub_memcpy (&target_addr.ipv4, target_protocol_address, 4); - if (grub_memcmp (sender_protocol_address, &pending_req, 4) == 0) - have_pending = 1; - } - else + if (arp_packet->pro != grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP) + || arp_packet->pln != 4 || arp_packet->hln != 6 + || nb->tail - nb->data < (int) sizeof (*arp_packet)) return GRUB_ERR_NONE; - sender_hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - grub_memcpy (sender_hw_addr.mac, sender_hardware_address, - sizeof (sender_hw_addr.mac)); - grub_net_link_layer_add_address (card, &sender_addr, &sender_hw_addr, 1); + sender_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + sender_addr.ipv4 = arp_packet->sender_ip; + target_addr.ipv4 = arp_packet->recv_ip; + if (arp_packet->sender_ip == pending_req) + have_pending = 1; + + sender_mac_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memcpy (sender_mac_addr.mac, arp_packet->sender_mac, + sizeof (sender_mac_addr.mac)); + grub_net_link_layer_add_address (card, &sender_addr, &sender_mac_addr, 1); FOR_NET_NETWORK_LEVEL_INTERFACES (inf) { @@ -166,28 +146,41 @@ grub_net_arp_receive (struct grub_net_bu /* Am I the protocol address target? */ if (grub_net_addr_cmp (&inf->address, &target_addr) == 0 - && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) + && arp_packet->op == grub_cpu_to_be16_compile_time (ARP_REQUEST)) { grub_net_link_level_address_t target; - /* We've already checked that pln is either 4 or 16. */ - char tmp[16]; - grub_size_t pln = arp_header->pln; - - if (pln > 16) - pln = 16; + struct grub_net_buff nb_reply; + struct arppkt *arp_reply; + grub_uint8_t arp_data[128]; + grub_err_t err; + + nb_reply.head = arp_data; + nb_reply.end = arp_data + sizeof (arp_data); + grub_netbuff_clear (&nb_reply); + grub_netbuff_reserve (&nb_reply, 128); + + err = grub_netbuff_push (&nb_reply, sizeof (*arp_packet)); + if (err) + return err; + + arp_reply = (struct arppkt *) nb_reply.data; + + arp_reply->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET); + arp_reply->pro = grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP); + arp_reply->pln = 4; + arp_reply->hln = 6; + arp_reply->op = grub_cpu_to_be16_compile_time (ARP_REPLY); + arp_reply->sender_ip = arp_packet->recv_ip; + arp_reply->recv_ip = arp_packet->sender_ip; + arp_reply->hln = 6; target.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - grub_memcpy (target.mac, sender_hardware_address, 6); - grub_memcpy (target_hardware_address, target.mac, 6); - grub_memcpy (sender_hardware_address, inf->hwaddress.mac, 6); - - grub_memcpy (tmp, sender_protocol_address, pln); - grub_memcpy (sender_protocol_address, target_protocol_address, pln); - grub_memcpy (target_protocol_address, tmp, pln); + grub_memcpy (target.mac, arp_packet->sender_mac, 6); + grub_memcpy (arp_reply->sender_mac, inf->hwaddress.mac, 6); + grub_memcpy (arp_reply->recv_mac, arp_packet->sender_mac, 6); /* Change operation to REPLY and send packet */ - arp_header->op = grub_be_to_cpu16 (ARP_REPLY); - send_ethernet_packet (inf, nb, target, GRUB_NET_ETHERTYPE_ARP); + send_ethernet_packet (inf, &nb_reply, target, GRUB_NET_ETHERTYPE_ARP); } } return GRUB_ERR_NONE; Index: grub-2.02~beta2/grub-core/net/icmp.c =================================================================== --- grub-2.02~beta2.orig/grub-core/net/icmp.c +++ grub-2.02~beta2/grub-core/net/icmp.c @@ -85,22 +85,13 @@ grub_net_recv_icmp_packet (struct grub_n struct icmp_header *icmphr; if (icmph->code) break; - nb_reply = grub_netbuff_alloc (nb->tail - nb->data + 512); + nb_reply = grub_netbuff_make_pkt (nb->tail - nb->data + sizeof (*icmphr)); if (!nb_reply) { grub_netbuff_free (nb); return grub_errno; } - err = grub_netbuff_reserve (nb_reply, nb->tail - nb->data + 512); - if (err) - goto ping_fail; - err = grub_netbuff_push (nb_reply, nb->tail - nb->data); - if (err) - goto ping_fail; - grub_memcpy (nb_reply->data, nb->data, nb->tail - nb->data); - err = grub_netbuff_push (nb_reply, sizeof (*icmphr)); - if (err) - goto ping_fail; + grub_memcpy (nb_reply->data + sizeof (*icmphr), nb->data, nb->tail - nb->data); icmphr = (struct icmp_header *) nb_reply->data; icmphr->type = ICMP_ECHO_REPLY; icmphr->code = 0; @@ -110,7 +101,6 @@ grub_net_recv_icmp_packet (struct grub_n err = grub_net_send_ip_packet (inf, src, ll_src, nb_reply, GRUB_NET_IP_ICMP); - ping_fail: grub_netbuff_free (nb); grub_netbuff_free (nb_reply); return err; Index: grub-2.02~beta2/grub-core/net/netbuff.c =================================================================== --- grub-2.02~beta2.orig/grub-core/net/netbuff.c +++ grub-2.02~beta2/grub-core/net/netbuff.c @@ -97,6 +97,26 @@ grub_netbuff_alloc (grub_size_t len) return nb; } +struct grub_net_buff * +grub_netbuff_make_pkt (grub_size_t len) +{ + struct grub_net_buff *nb; + grub_err_t err; + nb = grub_netbuff_alloc (len + 512); + if (!nb) + return NULL; + err = grub_netbuff_reserve (nb, len + 512); + if (err) + goto fail; + err = grub_netbuff_push (nb, len); + if (err) + goto fail; + return nb; + fail: + grub_netbuff_free (nb); + return NULL; +} + void grub_netbuff_free (struct grub_net_buff *nb) { Index: grub-2.02~beta2/include/grub/net/netbuff.h =================================================================== --- grub-2.02~beta2.orig/include/grub/net/netbuff.h +++ grub-2.02~beta2/include/grub/net/netbuff.h @@ -25,6 +25,7 @@ grub_err_t grub_netbuff_pull (struct gru grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff, grub_size_t len); grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff); struct grub_net_buff * grub_netbuff_alloc (grub_size_t len); +struct grub_net_buff * grub_netbuff_make_pkt (grub_size_t len); void grub_netbuff_free (struct grub_net_buff *net_buff); #endif
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor