mirror of
https://github.com/torvalds/linux.git
synced 2024-12-01 00:21:32 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following patchset contains Netfilter fixes for your net tree, they are: 1) Allow to recycle a TCP port in conntrack when the change role from server to client, from Marcelo Leitner. 2) Fix possible off by one access in ip_set_nfnl_get_byindex(), patch from Dan Carpenter. 3) alloc_percpu returns NULL on error, no need for IS_ERR() in nf_tables chain statistic updates. From Sabrina Dubroca. 4) Don't compile ip options in bridge netfilter, this mangles the packet and bridge should not alter layer >= 3 headers when forwarding packets. Patch from Herbert Xu and tested by Florian Westphal. 5) Account the final NLMSG_DONE message when calculating the size of the nflog netlink batches. Patch from Florian Westphal. 6) Fix a possible netlink attribute length overflow with large packets. Again from Florian Westphal. 7) Release the skbuff if nfnetlink_log fails to put the final NLMSG_DONE message. This fixes a leak on error. This shouldn't ever happen though, otherwise this means we miscalculate the netlink batch size, so spot a warning if this ever happens so we can track down the problem. This patch from Houcheng Lin. 8) Look at the right list when recycling targets in the nft_compat, patch from Arturo Borrero. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
5d26b1f50a
@ -192,7 +192,6 @@ static inline void nf_bridge_save_header(struct sk_buff *skb)
|
||||
|
||||
static int br_parse_ip_options(struct sk_buff *skb)
|
||||
{
|
||||
struct ip_options *opt;
|
||||
const struct iphdr *iph;
|
||||
struct net_device *dev = skb->dev;
|
||||
u32 len;
|
||||
@ -201,7 +200,6 @@ static int br_parse_ip_options(struct sk_buff *skb)
|
||||
goto inhdr_error;
|
||||
|
||||
iph = ip_hdr(skb);
|
||||
opt = &(IPCB(skb)->opt);
|
||||
|
||||
/* Basic sanity checks */
|
||||
if (iph->ihl < 5 || iph->version != 4)
|
||||
@ -227,23 +225,11 @@ static int br_parse_ip_options(struct sk_buff *skb)
|
||||
}
|
||||
|
||||
memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
|
||||
if (iph->ihl == 5)
|
||||
return 0;
|
||||
|
||||
opt->optlen = iph->ihl*4 - sizeof(struct iphdr);
|
||||
if (ip_options_compile(dev_net(dev), opt, skb))
|
||||
goto inhdr_error;
|
||||
|
||||
/* Check correct handling of SRR option */
|
||||
if (unlikely(opt->srr)) {
|
||||
struct in_device *in_dev = __in_dev_get_rcu(dev);
|
||||
if (in_dev && !IN_DEV_SOURCE_ROUTE(in_dev))
|
||||
goto drop;
|
||||
|
||||
if (ip_options_rcv_srr(skb))
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* We should really parse IP options here but until
|
||||
* somebody who actually uses IP options complains to
|
||||
* us we'll just silently ignore the options because
|
||||
* we're lazy!
|
||||
*/
|
||||
return 0;
|
||||
|
||||
inhdr_error:
|
||||
|
@ -659,7 +659,7 @@ ip_set_nfnl_get_byindex(struct net *net, ip_set_id_t index)
|
||||
struct ip_set *set;
|
||||
struct ip_set_net *inst = ip_set_pernet(net);
|
||||
|
||||
if (index > inst->ip_set_max)
|
||||
if (index >= inst->ip_set_max)
|
||||
return IPSET_INVALID_ID;
|
||||
|
||||
nfnl_lock(NFNL_SUBSYS_IPSET);
|
||||
|
@ -213,7 +213,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
|
||||
{
|
||||
/* REPLY */
|
||||
/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */
|
||||
/*syn*/ { sIV, sS2, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sS2 },
|
||||
/*syn*/ { sIV, sS2, sIV, sIV, sIV, sIV, sIV, sSS, sIV, sS2 },
|
||||
/*
|
||||
* sNO -> sIV Never reached.
|
||||
* sSS -> sS2 Simultaneous open
|
||||
@ -223,7 +223,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
|
||||
* sFW -> sIV
|
||||
* sCW -> sIV
|
||||
* sLA -> sIV
|
||||
* sTW -> sIV Reopened connection, but server may not do it.
|
||||
* sTW -> sSS Reopened connection, but server may have switched role
|
||||
* sCL -> sIV
|
||||
*/
|
||||
/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */
|
||||
|
@ -1328,10 +1328,10 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
|
||||
basechain->stats = stats;
|
||||
} else {
|
||||
stats = netdev_alloc_pcpu_stats(struct nft_stats);
|
||||
if (IS_ERR(stats)) {
|
||||
if (stats == NULL) {
|
||||
module_put(type->owner);
|
||||
kfree(basechain);
|
||||
return PTR_ERR(stats);
|
||||
return -ENOMEM;
|
||||
}
|
||||
rcu_assign_pointer(basechain->stats, stats);
|
||||
}
|
||||
|
@ -43,7 +43,8 @@
|
||||
#define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE
|
||||
#define NFULNL_TIMEOUT_DEFAULT 100 /* every second */
|
||||
#define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */
|
||||
#define NFULNL_COPY_RANGE_MAX 0xFFFF /* max packet size is limited by 16-bit struct nfattr nfa_len field */
|
||||
/* max packet size is limited by 16-bit struct nfattr nfa_len field */
|
||||
#define NFULNL_COPY_RANGE_MAX (0xFFFF - NLA_HDRLEN)
|
||||
|
||||
#define PRINTR(x, args...) do { if (net_ratelimit()) \
|
||||
printk(x, ## args); } while (0);
|
||||
@ -252,6 +253,8 @@ nfulnl_set_mode(struct nfulnl_instance *inst, u_int8_t mode,
|
||||
|
||||
case NFULNL_COPY_PACKET:
|
||||
inst->copy_mode = mode;
|
||||
if (range == 0)
|
||||
range = NFULNL_COPY_RANGE_MAX;
|
||||
inst->copy_range = min_t(unsigned int,
|
||||
range, NFULNL_COPY_RANGE_MAX);
|
||||
break;
|
||||
@ -343,26 +346,25 @@ nfulnl_alloc_skb(struct net *net, u32 peer_portid, unsigned int inst_size,
|
||||
return skb;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
__nfulnl_send(struct nfulnl_instance *inst)
|
||||
{
|
||||
int status = -1;
|
||||
|
||||
if (inst->qlen > 1) {
|
||||
struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0,
|
||||
NLMSG_DONE,
|
||||
sizeof(struct nfgenmsg),
|
||||
0);
|
||||
if (!nlh)
|
||||
if (WARN_ONCE(!nlh, "bad nlskb size: %u, tailroom %d\n",
|
||||
inst->skb->len, skb_tailroom(inst->skb))) {
|
||||
kfree_skb(inst->skb);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
status = nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid,
|
||||
MSG_DONTWAIT);
|
||||
|
||||
nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid,
|
||||
MSG_DONTWAIT);
|
||||
out:
|
||||
inst->qlen = 0;
|
||||
inst->skb = NULL;
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -649,7 +651,8 @@ nfulnl_log_packet(struct net *net,
|
||||
+ nla_total_size(sizeof(u_int32_t)) /* gid */
|
||||
+ nla_total_size(plen) /* prefix */
|
||||
+ nla_total_size(sizeof(struct nfulnl_msg_packet_hw))
|
||||
+ nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp));
|
||||
+ nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp))
|
||||
+ nla_total_size(sizeof(struct nfgenmsg)); /* NLMSG_DONE */
|
||||
|
||||
if (in && skb_mac_header_was_set(skb)) {
|
||||
size += nla_total_size(skb->dev->hard_header_len)
|
||||
@ -678,8 +681,7 @@ nfulnl_log_packet(struct net *net,
|
||||
break;
|
||||
|
||||
case NFULNL_COPY_PACKET:
|
||||
if (inst->copy_range == 0
|
||||
|| inst->copy_range > skb->len)
|
||||
if (inst->copy_range > skb->len)
|
||||
data_len = skb->len;
|
||||
else
|
||||
data_len = inst->copy_range;
|
||||
@ -692,8 +694,7 @@ nfulnl_log_packet(struct net *net,
|
||||
goto unlock_and_release;
|
||||
}
|
||||
|
||||
if (inst->skb &&
|
||||
size > skb_tailroom(inst->skb) - sizeof(struct nfgenmsg)) {
|
||||
if (inst->skb && size > skb_tailroom(inst->skb)) {
|
||||
/* either the queue len is too high or we don't have
|
||||
* enough room in the skb left. flush to userspace. */
|
||||
__nfulnl_flush(inst);
|
||||
|
@ -672,7 +672,7 @@ nft_target_select_ops(const struct nft_ctx *ctx,
|
||||
family = ctx->afi->family;
|
||||
|
||||
/* Re-use the existing target if it's already loaded. */
|
||||
list_for_each_entry(nft_target, &nft_match_list, head) {
|
||||
list_for_each_entry(nft_target, &nft_target_list, head) {
|
||||
struct xt_target *target = nft_target->ops.data;
|
||||
|
||||
if (strcmp(target->name, tg_name) == 0 &&
|
||||
|
Loading…
Reference in New Issue
Block a user