Skip to content

Commit b98af83

Browse files
Nazarov Sergeygregkh
authored andcommitted
net: avoid use IPCB in cipso_v4_error
[ Upstream commit 3da1ed7 ] 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 826987f commit b98af83

3 files changed

Lines changed: 34 additions & 7 deletions

File tree

include/net/ip.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,8 @@ static inline int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb)
546546
}
547547

548548
void ip_options_fragment(struct sk_buff *skb);
549+
int __ip_options_compile(struct net *net, struct ip_options *opt,
550+
struct sk_buff *skb, __be32 *info);
549551
int ip_options_compile(struct net *net, struct ip_options *opt,
550552
struct sk_buff *skb);
551553
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
@@ -1805,13 +1805,26 @@ int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option)
18051805
*/
18061806
void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
18071807
{
1808+
unsigned char optbuf[sizeof(struct ip_options) + 40];
1809+
struct ip_options *opt = (struct ip_options *)optbuf;
1810+
18081811
if (ip_hdr(skb)->protocol == IPPROTO_ICMP || error != -EACCES)
18091812
return;
18101813

1814+
/*
1815+
* We might be called above the IP layer,
1816+
* so we can not use icmp_send and IPCB here.
1817+
*/
1818+
1819+
memset(opt, 0, sizeof(struct ip_options));
1820+
opt->optlen = ip_hdr(skb)->ihl*4 - sizeof(struct iphdr);
1821+
if (__ip_options_compile(dev_net(skb->dev), opt, skb, NULL))
1822+
return;
1823+
18111824
if (gateway)
1812-
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0);
1825+
__icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0, opt);
18131826
else
1814-
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0);
1827+
__icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0, opt);
18151828
}
18161829

18171830
/**

net/ipv4/ip_options.c

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

257-
int ip_options_compile(struct net *net,
258-
struct ip_options *opt, struct sk_buff *skb)
257+
int __ip_options_compile(struct net *net,
258+
struct ip_options *opt, struct sk_buff *skb,
259+
__be32 *info)
259260
{
260261
__be32 spec_dst = htonl(INADDR_ANY);
261262
unsigned char *pp_ptr = NULL;
@@ -472,11 +473,22 @@ int ip_options_compile(struct net *net,
472473
return 0;
473474

474475
error:
475-
if (skb) {
476-
icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((pp_ptr-iph)<<24));
477-
}
476+
if (info)
477+
*info = htonl((pp_ptr-iph)<<24);
478478
return -EINVAL;
479479
}
480+
481+
int ip_options_compile(struct net *net,
482+
struct ip_options *opt, struct sk_buff *skb)
483+
{
484+
int ret;
485+
__be32 info;
486+
487+
ret = __ip_options_compile(net, opt, skb, &info);
488+
if (ret != 0 && skb)
489+
icmp_send(skb, ICMP_PARAMETERPROB, 0, info);
490+
return ret;
491+
}
480492
EXPORT_SYMBOL(ip_options_compile);
481493

482494
/*

0 commit comments

Comments
 (0)