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) Revisit warning logic when not applying default helper assignment. Jiri Kosina considers we are breaking existing setups and not warning our users accordinly now that automatic helper assignment has been turned off by default. So let's make him happy by spotting the warning by when we find a helper but we cannot attach, instead of warning on the former deprecated behaviour. Patch from Jiri Kosina. 2) Two patches to fix regression in ctnetlink interfaces with nfnetlink_queue. Specifically, perform more relaxed in CTA_STATUS and do not bail out if CTA_HELP indicates the same helper that we already have. Patches from Kevin Cernekee. 3) A couple of bugfixes for ipset via Jozsef Kadlecsik. Due to wrong index logic in hash set types and null pointer exception in the list:set type. 4) hashlimit bails out with correct userspace parameters due to wrong arithmetics in the code that avoids "divide by zero" when transforming the userspace timing in milliseconds to token credits. Patch from Alban Browaeys. 5) Fix incorrect NFQA_VLAN_MAX definition, patch from Ken-ichirou MATSUZAWA. 6) Don't not declare nfnetlink batch error list as static, since this may be used by several subsystems at the same time. Patch from Liping Zhang. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ccaba0621a
|
@ -82,6 +82,10 @@ enum ip_conntrack_status {
|
|||
IPS_DYING_BIT = 9,
|
||||
IPS_DYING = (1 << IPS_DYING_BIT),
|
||||
|
||||
/* Bits that cannot be altered from userland. */
|
||||
IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK |
|
||||
IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING),
|
||||
|
||||
/* Connection has fixed timeout. */
|
||||
IPS_FIXED_TIMEOUT_BIT = 10,
|
||||
IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
|
||||
|
|
|
@ -36,7 +36,7 @@ enum nfqnl_vlan_attr {
|
|||
NFQA_VLAN_TCI, /* __be16 skb htons(vlan_tci) */
|
||||
__NFQA_VLAN_MAX,
|
||||
};
|
||||
#define NFQA_VLAN_MAX (__NFQA_VLAN_MAX + 1)
|
||||
#define NFQA_VLAN_MAX (__NFQA_VLAN_MAX - 1)
|
||||
|
||||
enum nfqnl_attr_type {
|
||||
NFQA_UNSPEC,
|
||||
|
|
|
@ -897,7 +897,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
|
|||
continue;
|
||||
data = ahash_data(n, j, dsize);
|
||||
memcpy(tmp->value + k * dsize, data, dsize);
|
||||
set_bit(j, tmp->used);
|
||||
set_bit(k, tmp->used);
|
||||
k++;
|
||||
}
|
||||
tmp->pos = k;
|
||||
|
|
|
@ -260,11 +260,14 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext,
|
|||
else
|
||||
prev = e;
|
||||
}
|
||||
|
||||
/* If before/after is used on an empty set */
|
||||
if ((d->before > 0 && !next) ||
|
||||
(d->before < 0 && !prev))
|
||||
return -IPSET_ERR_REF_EXIST;
|
||||
|
||||
/* Re-add already existing element */
|
||||
if (n) {
|
||||
if ((d->before > 0 && !next) ||
|
||||
(d->before < 0 && !prev))
|
||||
return -IPSET_ERR_REF_EXIST;
|
||||
if (!flag_exist)
|
||||
return -IPSET_ERR_EXIST;
|
||||
/* Update extensions */
|
||||
|
|
|
@ -188,6 +188,26 @@ nf_ct_helper_ext_add(struct nf_conn *ct,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add);
|
||||
|
||||
static struct nf_conntrack_helper *
|
||||
nf_ct_lookup_helper(struct nf_conn *ct, struct net *net)
|
||||
{
|
||||
if (!net->ct.sysctl_auto_assign_helper) {
|
||||
if (net->ct.auto_assign_helper_warned)
|
||||
return NULL;
|
||||
if (!__nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple))
|
||||
return NULL;
|
||||
pr_info("nf_conntrack: default automatic helper assignment "
|
||||
"has been turned off for security reasons and CT-based "
|
||||
" firewall rule not found. Use the iptables CT target "
|
||||
"to attach helpers instead.\n");
|
||||
net->ct.auto_assign_helper_warned = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
|
||||
}
|
||||
|
||||
|
||||
int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
|
||||
gfp_t flags)
|
||||
{
|
||||
|
@ -213,21 +233,14 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
|
|||
}
|
||||
|
||||
help = nfct_help(ct);
|
||||
if (net->ct.sysctl_auto_assign_helper && helper == NULL) {
|
||||
helper = __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
|
||||
if (unlikely(!net->ct.auto_assign_helper_warned && helper)) {
|
||||
pr_info("nf_conntrack: automatic helper "
|
||||
"assignment is deprecated and it will "
|
||||
"be removed soon. Use the iptables CT target "
|
||||
"to attach helpers instead.\n");
|
||||
net->ct.auto_assign_helper_warned = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (helper == NULL) {
|
||||
if (help)
|
||||
RCU_INIT_POINTER(help->helper, NULL);
|
||||
return 0;
|
||||
helper = nf_ct_lookup_helper(ct, net);
|
||||
if (helper == NULL) {
|
||||
if (help)
|
||||
RCU_INIT_POINTER(help->helper, NULL);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (help == NULL) {
|
||||
|
|
|
@ -1478,14 +1478,23 @@ static int ctnetlink_change_helper(struct nf_conn *ct,
|
|||
struct nlattr *helpinfo = NULL;
|
||||
int err;
|
||||
|
||||
/* don't change helper of sibling connections */
|
||||
if (ct->master)
|
||||
return -EBUSY;
|
||||
|
||||
err = ctnetlink_parse_help(cda[CTA_HELP], &helpname, &helpinfo);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* don't change helper of sibling connections */
|
||||
if (ct->master) {
|
||||
/* If we try to change the helper to the same thing twice,
|
||||
* treat the second attempt as a no-op instead of returning
|
||||
* an error.
|
||||
*/
|
||||
if (help && help->helper &&
|
||||
!strcmp(help->helper->name, helpname))
|
||||
return 0;
|
||||
else
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!strcmp(helpname, "")) {
|
||||
if (help && help->helper) {
|
||||
/* we had a helper before ... */
|
||||
|
@ -2269,6 +2278,30 @@ ctnetlink_glue_build(struct sk_buff *skb, struct nf_conn *ct,
|
|||
return -ENOSPC;
|
||||
}
|
||||
|
||||
static int
|
||||
ctnetlink_update_status(struct nf_conn *ct, const struct nlattr * const cda[])
|
||||
{
|
||||
unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS]));
|
||||
unsigned long d = ct->status ^ status;
|
||||
|
||||
if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
|
||||
/* SEEN_REPLY bit can only be set */
|
||||
return -EBUSY;
|
||||
|
||||
if (d & IPS_ASSURED && !(status & IPS_ASSURED))
|
||||
/* ASSURED bit can only be set */
|
||||
return -EBUSY;
|
||||
|
||||
/* This check is less strict than ctnetlink_change_status()
|
||||
* because callers often flip IPS_EXPECTED bits when sending
|
||||
* an NFQA_CT attribute to the kernel. So ignore the
|
||||
* unchangeable bits but do not error out.
|
||||
*/
|
||||
ct->status = (status & ~IPS_UNCHANGEABLE_MASK) |
|
||||
(ct->status & IPS_UNCHANGEABLE_MASK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ctnetlink_glue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct)
|
||||
{
|
||||
|
@ -2280,7 +2313,7 @@ ctnetlink_glue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct)
|
|||
return err;
|
||||
}
|
||||
if (cda[CTA_STATUS]) {
|
||||
err = ctnetlink_change_status(ct, cda);
|
||||
err = ctnetlink_update_status(ct, cda);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -279,7 +279,7 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
struct net *net = sock_net(skb->sk);
|
||||
const struct nfnetlink_subsystem *ss;
|
||||
const struct nfnl_callback *nc;
|
||||
static LIST_HEAD(err_list);
|
||||
LIST_HEAD(err_list);
|
||||
u32 status;
|
||||
int err;
|
||||
|
||||
|
|
|
@ -463,23 +463,16 @@ static u32 xt_hashlimit_len_to_chunks(u32 len)
|
|||
/* Precision saver. */
|
||||
static u64 user2credits(u64 user, int revision)
|
||||
{
|
||||
if (revision == 1) {
|
||||
/* If multiplying would overflow... */
|
||||
if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY_v1))
|
||||
/* Divide first. */
|
||||
return div64_u64(user, XT_HASHLIMIT_SCALE)
|
||||
* HZ * CREDITS_PER_JIFFY_v1;
|
||||
u64 scale = (revision == 1) ?
|
||||
XT_HASHLIMIT_SCALE : XT_HASHLIMIT_SCALE_v2;
|
||||
u64 cpj = (revision == 1) ?
|
||||
CREDITS_PER_JIFFY_v1 : CREDITS_PER_JIFFY;
|
||||
|
||||
return div64_u64(user * HZ * CREDITS_PER_JIFFY_v1,
|
||||
XT_HASHLIMIT_SCALE);
|
||||
} else {
|
||||
if (user > 0xFFFFFFFFFFFFFFFFULL / (HZ*CREDITS_PER_JIFFY))
|
||||
return div64_u64(user, XT_HASHLIMIT_SCALE_v2)
|
||||
* HZ * CREDITS_PER_JIFFY;
|
||||
/* Avoid overflow: divide the constant operands first */
|
||||
if (scale >= HZ * cpj)
|
||||
return div64_u64(user, div64_u64(scale, HZ * cpj));
|
||||
|
||||
return div64_u64(user * HZ * CREDITS_PER_JIFFY,
|
||||
XT_HASHLIMIT_SCALE_v2);
|
||||
}
|
||||
return user * div64_u64(HZ * cpj, scale);
|
||||
}
|
||||
|
||||
static u32 user2credits_byte(u32 user)
|
||||
|
|
Loading…
Reference in New Issue