icmp: Fixed bug in raw sockets causing incorrect ICMP SNMP counter values
Subsystems (2)
PATCH 1/1 icmp: Fixed bug in raw sockets causing incorrect ICMP SNMP counter values
Sending ICMP packets with raw sockets ends up in the SNMP counters logging the type as the first byte of the IPv4 header rather than the ICMP header (in nearly all cases this is seen as "OutType69". This is fixed by adding the IP Header Length to the casting into a icmphdr struct.
--- net/ipv4/raw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/raw.c +1 -1
@@ -409,7 +409,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, }if (iph->protocol ==IPPROTO_ICMP )icmp_out_count (net, ((struct icmphdr *) -skb_transport_header (skb))->type); +skb_transport_header (skb) + iphlen)->type); err =NF_HOOK (NFPROTO_IPV4 ,NF_INET_LOCAL_OUT , sk, skb,NULL , rt->dst.dev, dst_output_sk);
Signature · 1 line
1.9.1
Quoted 16 lines · Ben Cartwright-Cox
Sending ICMP packets with raw sockets ends up in the SNMP counters logging the type as the first byte of the IPv4 header rather than the ICMP header (in nearly all cases this is seen as "OutType69". This is fixed by adding the IP Header Length to the casting into a icmphdr struct.
Signed-off-by Ben Cartwright-Cox <[email protected]>--- net/ipv4/raw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)net/ipv4/raw.c +0
-0
net/ipv4/raw.c static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, · line 415
Quoted 8 lines
net/ipv4/raw.c +1
-1@@ -409,7 +409,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, }if (iph->protocol ==IPPROTO_ICMP )icmp_out_count (net, ((struct icmphdr *) -skb_transport_header (skb))->type); +skb_transport_header (skb) + iphlen)->type); err =NF_HOOK (NFPROTO_IPV4 ,NF_INET_LOCAL_OUT , sk, skb,NULL , rt->dst.dev, dst_output_sk);
Hmm... This seems to lack checks against a malicious user ?
The only guarantee you have here is that iphlen < length.
It is not enough.
Make sure you do not access not initialized memory or even non existent one.
Forgive me for possibly being a little stupid here (This is my first patch to Linux so I am slightly over my head)
Is this issue not addressed above the file where the following check is done?
if (iphlen > length)
goto error_free;
Quoted 38 lines · Eric Dumazet
Quoted 16 lines · Ben Cartwright-Cox
Sending ICMP packets with raw sockets ends up in the SNMP counters logging the type as the first byte of the IPv4 header rather than the ICMP header (in nearly all cases this is seen as "OutType69". This is fixed by adding the IP Header Length to the casting into a icmphdr struct.
Signed-off-by Ben Cartwright-Cox <[email protected]>--- net/ipv4/raw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)net/ipv4/raw.c +0
-0net/ipv4/raw.c static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, · line 415
Quoted 8 lines
net/ipv4/raw.c +1
-1@@ -409,7 +409,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, }if (iph->protocol ==IPPROTO_ICMP )icmp_out_count (net, ((struct icmphdr *) -skb_transport_header (skb))->type); +skb_transport_header (skb) + iphlen)->type); err =NF_HOOK (NFPROTO_IPV4 ,NF_INET_LOCAL_OUT , sk, skb,NULL , rt->dst.dev, dst_output_sk);Hmm... This seems to lack checks against a malicious user ?
The only guarantee you have here is that iphlen < length.
It is not enough.
Make sure you do not access not initialized memory or even non existent one.
Quoted 8 lines · Ben Cox
Forgive me for possibly being a little stupid here (This is my first patch to Linux so I am slightly over my head)
Is this issue not addressed above the file where the following check is done?
if (iphlen > length)
goto error_free;
Imagine someone sends a frame, pretending it is ICMP, but containing only the IPv4 header. And not a _single_ byte more.
length = 20
iphlen = 20 (if say ihl == 5)
We copied 20 bytes from user land.
But your code reads 21th byte.
Quoted 1 line · Eric Dumazet
But your code reads 21th byte.
BTW, nice catch !
Your patch only need a small addition.
Thanks.
Quoted 5 lines · Eric Dumazet
Quoted 1 line · Eric Dumazet
But your code reads 21th byte.
BTW, nice catch !
Maybe the following one.
1) We properly set transport header
2) We use icmp_hdr() helper.
net/ipv4/raw.c +4 -4
@@ -406,11 +406,11 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,ip_select_ident (net, skb,NULL ); iph->check =ip_fast_csum ((unsigned char *)iph, iph->ihl); + skb->transport_header += iphlen; +if (iph->protocol ==IPPROTO_ICMP && + length >= iphlen +sizeof (struct icmphdr )) +icmp_out_count (net,icmp_hdr (skb)->type); } -if (iph->protocol ==IPPROTO_ICMP ) -icmp_out_count (net, ((struct icmphdr *) -skb_transport_header (skb))->type); - err =NF_HOOK (NFPROTO_IPV4 ,NF_INET_LOCAL_OUT , sk, skb,NULL , rt->dst.dev, dst_output_sk);if (err >0 )
Nice!
That works in my head at least, Sorry about not seeing that fairly glaring memory issue there.
Are you sure " skb->transport_header += iphlen; " won't have a knock on affect when it's given to NF_HOOK ( as in, would a potential userspace program get something it does not expect anymore ) ?
How does submission work at this point if the above is not a issue (apologies if this is already in a FAQ somewhere I missed)?
Quoted 34 lines · Eric Dumazet
Quoted 5 lines · Eric Dumazet
Quoted 1 line · Eric Dumazet
But your code reads 21th byte.
BTW, nice catch !
Maybe the following one.
1) We properly set transport header
2) We useicmp_hdr()helper.net/ipv4/raw.c +4
-4@@ -406,11 +406,11 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,ip_select_ident (net, skb,NULL ); iph->check =ip_fast_csum ((unsigned char *)iph, iph->ihl); + skb->transport_header += iphlen; +if (iph->protocol ==IPPROTO_ICMP && + length >= iphlen +sizeof (struct icmphdr )) +icmp_out_count (net,icmp_hdr (skb)->type); } -if (iph->protocol ==IPPROTO_ICMP ) -icmp_out_count (net, ((struct icmphdr *) -skb_transport_header (skb))->type); - err =NF_HOOK (NFPROTO_IPV4 ,NF_INET_LOCAL_OUT , sk, skb,NULL , rt->dst.dev, dst_output_sk);if (err >0 )
Please do not top-post on netdev and/or lkml
Quoted 4 lines · Ben Cox
Nice!
That works in my head at least, Sorry about not seeing that fairly glaring memory issue there.
No problem, this is why we review patches ;)
Quoted 4 lines
Are you sure "
skb->transport_header+= iphlen; " won't have a knock on affect when it's given toNF_HOOK( as in, would a potential userspace program get something it does not expect anymore ) ?
netfilter does not depend on transport_header being set (otherwise as you can see RAW packets would have problems with netfilter since the very beginning.
Quoted 3 lines
How does submission work at this point if the above is not a issue (apologies if this is already in a FAQ somewhere I missed)?
Just send a V2 of the patch, using following title :
[PATCH v2 net] raw: increment correct SNMP counters for ICMP messages
I'll add my 'Acked-by:' after your 'Signed-off-by:'
Thanks !