提交 bd26b906 编写于 作者: Y Yang Yingliang

netfilter: nat: check the bounds of nf_nat_l3protos and nf_nat_l4protos

hulk inclusion
category: bugfix
bugzilla: NA
CVE: NA

-------------------------------------------------

famliy can be passed from user space and will be out of range of
nf_nat_l3protos or nf_nat_l4protos, so we need check the family
when call __nf_nat_l3proto_find() or __nf_nat_l4proto_find().

nfnetlink_parse_nat_setup() need return EAGAIN, if __nf_nat_l3proto_find()
returns null, so we return a error number to distinguish this case.
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
Reviewed-by: NWei Yongjun <weiyongjun1@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 6ff93aef
......@@ -218,6 +218,8 @@ int nf_nat_icmp_reply_translation(struct sk_buff *skb,
return 1;
l4proto = __nf_nat_l4proto_find(NFPROTO_IPV4, inside->ip.protocol);
if (!l4proto)
return 1;
if (!nf_nat_ipv4_manip_pkt(skb, hdrlen + sizeof(inside->icmp),
l4proto, &ct->tuplehash[!dir].tuple, !manip))
return 0;
......@@ -234,7 +236,7 @@ int nf_nat_icmp_reply_translation(struct sk_buff *skb,
/* Change outer to look like the reply to an incoming packet */
nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
l4proto = __nf_nat_l4proto_find(NFPROTO_IPV4, 0);
if (!nf_nat_ipv4_manip_pkt(skb, 0, l4proto, &target, manip))
if (l4proto && !nf_nat_ipv4_manip_pkt(skb, 0, l4proto, &target, manip))
return 0;
return 1;
......
......@@ -228,6 +228,8 @@ int nf_nat_icmpv6_reply_translation(struct sk_buff *skb,
return 1;
l4proto = __nf_nat_l4proto_find(NFPROTO_IPV6, inside->ip6.nexthdr);
if (!l4proto)
return 1;
if (!nf_nat_ipv6_manip_pkt(skb, hdrlen + sizeof(inside->icmp6),
l4proto, &ct->tuplehash[!dir].tuple, !manip))
return 0;
......@@ -245,7 +247,7 @@ int nf_nat_icmpv6_reply_translation(struct sk_buff *skb,
nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
l4proto = __nf_nat_l4proto_find(NFPROTO_IPV6, IPPROTO_ICMPV6);
if (!nf_nat_ipv6_manip_pkt(skb, 0, l4proto, &target, manip))
if (l4proto && !nf_nat_ipv6_manip_pkt(skb, 0, l4proto, &target, manip))
return 0;
return 1;
......
......@@ -64,12 +64,18 @@ struct nat_net {
inline const struct nf_nat_l3proto *
__nf_nat_l3proto_find(u8 family)
{
if (unlikely(family >= NFPROTO_NUMPROTO))
return ERR_PTR(-EPROTONOSUPPORT);
return rcu_dereference(nf_nat_l3protos[family]);
}
inline const struct nf_nat_l4proto *
__nf_nat_l4proto_find(u8 family, u8 protonum)
{
if (unlikely(family >= NFPROTO_NUMPROTO || nf_nat_l4protos[family] == NULL))
return NULL;
return rcu_dereference(nf_nat_l4protos[family][protonum]);
}
EXPORT_SYMBOL_GPL(__nf_nat_l4proto_find);
......@@ -90,7 +96,7 @@ static void __nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl)
family = nf_ct_l3num(ct);
l3proto = __nf_nat_l3proto_find(family);
if (l3proto == NULL)
if (IS_ERR_OR_NULL(l3proto))
return;
dir = CTINFO2DIR(ctinfo);
......@@ -333,8 +339,12 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
rcu_read_lock();
l3proto = __nf_nat_l3proto_find(orig_tuple->src.l3num);
if (IS_ERR_OR_NULL(l3proto))
goto out;
l4proto = __nf_nat_l4proto_find(orig_tuple->src.l3num,
orig_tuple->dst.protonum);
if (!l4proto)
goto out;
/* 1) If this srcip/proto/src-proto-part is currently mapped,
* and that same mapping gives a unique tuple within the given
......@@ -509,8 +519,12 @@ static unsigned int nf_nat_manip_pkt(struct sk_buff *skb, struct nf_conn *ct,
nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
l3proto = __nf_nat_l3proto_find(target.src.l3num);
if (IS_ERR_OR_NULL(l3proto))
return NF_DROP;
l4proto = __nf_nat_l4proto_find(target.src.l3num,
target.dst.protonum);
if (!l4proto)
return NF_DROP;
if (!l3proto->manip_pkt(skb, 0, l4proto, &target, mtype))
return NF_DROP;
......@@ -816,6 +830,9 @@ static int nfnetlink_parse_nat_proto(struct nlattr *attr,
return err;
l4proto = __nf_nat_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
if (!l4proto)
return -EPROTONOSUPPORT;
if (l4proto->nlattr_to_range)
err = l4proto->nlattr_to_range(tb, range);
......@@ -876,6 +893,8 @@ nfnetlink_parse_nat_setup(struct nf_conn *ct,
l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct));
if (l3proto == NULL)
return -EAGAIN;
if (IS_ERR(l3proto))
return PTR_ERR(l3proto);
/* No NAT information has been passed, allocate the null-binding */
if (attr == NULL)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册