diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2007-02-05 02:33:10 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-02-08 15:38:47 -0500 |
commit | ffbc61117d32dc4e768f999325ecfb2528d6b303 (patch) | |
tree | f59a235c4eb22ac5ad9ede80f814f5d6ab1e6641 /net/packet | |
parent | 8dc4194474159660d7f37c495e3fc3f10d0db8cc (diff) |
[PACKET]: Fix skb->cb clobbering between aux and sockaddr
Both aux data and sockaddr tries to use the same buffer which
obviously doesn't work. We just happen to have 4 bytes free in
the skb->cb if you take away the maximum length of sockaddr_ll.
That's just enough to store the one piece of info from aux data
that we can't generate at recvmsg(2) time.
This is what the following patch does.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/packet')
-rw-r--r-- | net/packet/af_packet.c | 46 |
1 files changed, 30 insertions, 16 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 8973ea78831e..a6fa48788e8f 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -60,6 +60,7 @@ | |||
60 | #include <linux/netdevice.h> | 60 | #include <linux/netdevice.h> |
61 | #include <linux/if_packet.h> | 61 | #include <linux/if_packet.h> |
62 | #include <linux/wireless.h> | 62 | #include <linux/wireless.h> |
63 | #include <linux/kernel.h> | ||
63 | #include <linux/kmod.h> | 64 | #include <linux/kmod.h> |
64 | #include <net/ip.h> | 65 | #include <net/ip.h> |
65 | #include <net/protocol.h> | 66 | #include <net/protocol.h> |
@@ -215,7 +216,15 @@ struct packet_sock { | |||
215 | #endif | 216 | #endif |
216 | }; | 217 | }; |
217 | 218 | ||
218 | #define PACKET_SKB_CB(__skb) ((struct tpacket_auxdata *)((__skb)->cb)) | 219 | struct packet_skb_cb { |
220 | unsigned int origlen; | ||
221 | union { | ||
222 | struct sockaddr_pkt pkt; | ||
223 | struct sockaddr_ll ll; | ||
224 | } sa; | ||
225 | }; | ||
226 | |||
227 | #define PACKET_SKB_CB(__skb) ((struct packet_skb_cb *)((__skb)->cb)) | ||
219 | 228 | ||
220 | #ifdef CONFIG_PACKET_MMAP | 229 | #ifdef CONFIG_PACKET_MMAP |
221 | 230 | ||
@@ -296,7 +305,7 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev, struct | |||
296 | /* drop conntrack reference */ | 305 | /* drop conntrack reference */ |
297 | nf_reset(skb); | 306 | nf_reset(skb); |
298 | 307 | ||
299 | spkt = (struct sockaddr_pkt*)skb->cb; | 308 | spkt = &PACKET_SKB_CB(skb)->sa.pkt; |
300 | 309 | ||
301 | skb_push(skb, skb->data-skb->mac.raw); | 310 | skb_push(skb, skb->data-skb->mac.raw); |
302 | 311 | ||
@@ -465,7 +474,6 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet | |||
465 | u8 * skb_head = skb->data; | 474 | u8 * skb_head = skb->data; |
466 | int skb_len = skb->len; | 475 | int skb_len = skb->len; |
467 | unsigned int snaplen, res; | 476 | unsigned int snaplen, res; |
468 | struct tpacket_auxdata *aux; | ||
469 | 477 | ||
470 | if (skb->pkt_type == PACKET_LOOPBACK) | 478 | if (skb->pkt_type == PACKET_LOOPBACK) |
471 | goto drop; | 479 | goto drop; |
@@ -516,7 +524,10 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet | |||
516 | skb = nskb; | 524 | skb = nskb; |
517 | } | 525 | } |
518 | 526 | ||
519 | sll = (struct sockaddr_ll*)skb->cb; | 527 | BUILD_BUG_ON(sizeof(*PACKET_SKB_CB(skb)) + MAX_ADDR_LEN - 8 > |
528 | sizeof(skb->cb)); | ||
529 | |||
530 | sll = &PACKET_SKB_CB(skb)->sa.ll; | ||
520 | sll->sll_family = AF_PACKET; | 531 | sll->sll_family = AF_PACKET; |
521 | sll->sll_hatype = dev->type; | 532 | sll->sll_hatype = dev->type; |
522 | sll->sll_protocol = skb->protocol; | 533 | sll->sll_protocol = skb->protocol; |
@@ -527,14 +538,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet | |||
527 | if (dev->hard_header_parse) | 538 | if (dev->hard_header_parse) |
528 | sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr); | 539 | sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr); |
529 | 540 | ||
530 | aux = PACKET_SKB_CB(skb); | 541 | PACKET_SKB_CB(skb)->origlen = skb->len; |
531 | aux->tp_status = TP_STATUS_USER; | ||
532 | if (skb->ip_summed == CHECKSUM_PARTIAL) | ||
533 | aux->tp_status |= TP_STATUS_CSUMNOTREADY; | ||
534 | aux->tp_len = skb->len; | ||
535 | aux->tp_snaplen = snaplen; | ||
536 | aux->tp_mac = 0; | ||
537 | aux->tp_net = skb->nh.raw - skb->data; | ||
538 | 542 | ||
539 | if (pskb_trim(skb, snaplen)) | 543 | if (pskb_trim(skb, snaplen)) |
540 | goto drop_n_acct; | 544 | goto drop_n_acct; |
@@ -1106,7 +1110,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1106 | * it in now. | 1110 | * it in now. |
1107 | */ | 1111 | */ |
1108 | 1112 | ||
1109 | sll = (struct sockaddr_ll*)skb->cb; | 1113 | sll = &PACKET_SKB_CB(skb)->sa.ll; |
1110 | if (sock->type == SOCK_PACKET) | 1114 | if (sock->type == SOCK_PACKET) |
1111 | msg->msg_namelen = sizeof(struct sockaddr_pkt); | 1115 | msg->msg_namelen = sizeof(struct sockaddr_pkt); |
1112 | else | 1116 | else |
@@ -1131,11 +1135,21 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1131 | sock_recv_timestamp(msg, sk, skb); | 1135 | sock_recv_timestamp(msg, sk, skb); |
1132 | 1136 | ||
1133 | if (msg->msg_name) | 1137 | if (msg->msg_name) |
1134 | memcpy(msg->msg_name, skb->cb, msg->msg_namelen); | 1138 | memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa, |
1139 | msg->msg_namelen); | ||
1135 | 1140 | ||
1136 | if (pkt_sk(sk)->auxdata) { | 1141 | if (pkt_sk(sk)->auxdata) { |
1137 | struct tpacket_auxdata *aux = PACKET_SKB_CB(skb); | 1142 | struct tpacket_auxdata aux; |
1138 | put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(*aux), aux); | 1143 | |
1144 | aux.tp_status = TP_STATUS_USER; | ||
1145 | if (skb->ip_summed == CHECKSUM_PARTIAL) | ||
1146 | aux.tp_status |= TP_STATUS_CSUMNOTREADY; | ||
1147 | aux.tp_len = PACKET_SKB_CB(skb)->origlen; | ||
1148 | aux.tp_snaplen = skb->len; | ||
1149 | aux.tp_mac = 0; | ||
1150 | aux.tp_net = skb->nh.raw - skb->data; | ||
1151 | |||
1152 | put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux); | ||
1139 | } | 1153 | } |
1140 | 1154 | ||
1141 | /* | 1155 | /* |