Skip to content

Commit 3da1ed7

Browse files
Nazarov Sergeydavem330
authored andcommitted
net: avoid use IPCB in cipso_v4_error
Extract IP options in cipso_v4_error and use __icmp_send. Signed-off-by: Sergey Nazarov <s-nazarov@yandex.ru> Acked-by: Paul Moore <paul@paul-moore.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 9ef6b42 commit 3da1ed7

File tree

3 files changed

+34
-7
lines changed

3 files changed

+34
-7
lines changed

include/net/ip.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,8 @@ static inline int ip_options_echo(struct net *net, struct ip_options *dopt,
667667
}
668668

669669
void ip_options_fragment(struct sk_buff *skb);
670+
int __ip_options_compile(struct net *net, struct ip_options *opt,
671+
struct sk_buff *skb, __be32 *info);
670672
int ip_options_compile(struct net *net, struct ip_options *opt,
671673
struct sk_buff *skb);
672674
int ip_options_get(struct net *net, struct ip_options_rcu **optp,

net/ipv4/cipso_ipv4.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1735,13 +1735,26 @@ int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option)
17351735
*/
17361736
void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
17371737
{
1738+
unsigned char optbuf[sizeof(struct ip_options) + 40];
1739+
struct ip_options *opt = (struct ip_options *)optbuf;
1740+
17381741
if (ip_hdr(skb)->protocol == IPPROTO_ICMP || error != -EACCES)
17391742
return;
17401743

1744+
/*
1745+
* We might be called above the IP layer,
1746+
* so we can not use icmp_send and IPCB here.
1747+
*/
1748+
1749+
memset(opt, 0, sizeof(struct ip_options));
1750+
opt->optlen = ip_hdr(skb)->ihl*4 - sizeof(struct iphdr);
1751+
if (__ip_options_compile(dev_net(skb->dev), opt, skb, NULL))
1752+
return;
1753+
17411754
if (gateway)
1742-
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0);
1755+
__icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0, opt);
17431756
else
1744-
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0);
1757+
__icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0, opt);
17451758
}
17461759

17471760
/**

net/ipv4/ip_options.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,9 @@ static void spec_dst_fill(__be32 *spec_dst, struct sk_buff *skb)
251251
* If opt == NULL, then skb->data should point to IP header.
252252
*/
253253

254-
int ip_options_compile(struct net *net,
255-
struct ip_options *opt, struct sk_buff *skb)
254+
int __ip_options_compile(struct net *net,
255+
struct ip_options *opt, struct sk_buff *skb,
256+
__be32 *info)
256257
{
257258
__be32 spec_dst = htonl(INADDR_ANY);
258259
unsigned char *pp_ptr = NULL;
@@ -468,11 +469,22 @@ int ip_options_compile(struct net *net,
468469
return 0;
469470

470471
error:
471-
if (skb) {
472-
icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((pp_ptr-iph)<<24));
473-
}
472+
if (info)
473+
*info = htonl((pp_ptr-iph)<<24);
474474
return -EINVAL;
475475
}
476+
477+
int ip_options_compile(struct net *net,
478+
struct ip_options *opt, struct sk_buff *skb)
479+
{
480+
int ret;
481+
__be32 info;
482+
483+
ret = __ip_options_compile(net, opt, skb, &info);
484+
if (ret != 0 && skb)
485+
icmp_send(skb, ICMP_PARAMETERPROB, 0, info);
486+
return ret;
487+
}
476488
EXPORT_SYMBOL(ip_options_compile);
477489

478490
/*

0 commit comments

Comments
 (0)