Commit 943a0d4a authored by David S. Miller's avatar David S. Miller

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf

Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains large batch with Netfilter fixes for
your net tree, mostly due to syzbot report fixups and pr_err()
ratelimiting, more specifically, they are:

1) Get rid of superfluous unnecessary check in x_tables before vmalloc(),
   we don't hit BUG there anymore, patch from Michal Hock, suggested by
   Andrew Morton.

2) Race condition in proc file creation in ipt_CLUSTERIP, from Cong Wang.

3) Drop socket lock that results in circular locking dependency, patch
   from Paolo Abeni.

4) Drop packet if case of malformed blob that makes backpointer jump
   in x_tables, from Florian Westphal.

5) Fix refcount leak due to race in ipt_CLUSTERIP in
   clusterip_config_find_get(), from Cong Wang.

6) Several patches to ratelimit pr_err() for x_tables since this can be
   a problem where CAP_NET_ADMIN semantics can protect us in untrusted
   namespace, from Florian Westphal.

7) Missing .gitignore update for new autogenerated asn1 state machine
   for the SNMP NAT helper, from Zhu Lingshan.

8) Missing timer initialization in xt_LED, from Paolo Abeni.

9) Do not allow negative port range in NAT, also from Paolo.

10) Lock imbalance in the xt_hashlimit rate match mode, patch from
    Eric Dumazet.

11) Initialize workqueue before timer in the idletimer match,
    from Eric Dumazet.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5ae437ad cfc2c740
......@@ -127,3 +127,7 @@ all.config
# Kdevelop4
*.kdev4
#Automatically generated by ASN.1 compiler
net/ipv4/netfilter/nf_nat_snmp_basic-asn1.c
net/ipv4/netfilter/nf_nat_snmp_basic-asn1.h
......@@ -187,17 +187,17 @@ static int ebt_among_mt_check(const struct xt_mtchk_param *par)
expected_length += ebt_mac_wormhash_size(wh_src);
if (em->match_size != EBT_ALIGN(expected_length)) {
pr_info("wrong size: %d against expected %d, rounded to %zd\n",
em->match_size, expected_length,
EBT_ALIGN(expected_length));
pr_err_ratelimited("wrong size: %d against expected %d, rounded to %zd\n",
em->match_size, expected_length,
EBT_ALIGN(expected_length));
return -EINVAL;
}
if (wh_dst && (err = ebt_mac_wormhash_check_integrity(wh_dst))) {
pr_info("dst integrity fail: %x\n", -err);
pr_err_ratelimited("dst integrity fail: %x\n", -err);
return -EINVAL;
}
if (wh_src && (err = ebt_mac_wormhash_check_integrity(wh_src))) {
pr_info("src integrity fail: %x\n", -err);
pr_err_ratelimited("src integrity fail: %x\n", -err);
return -EINVAL;
}
return 0;
......
......@@ -72,8 +72,8 @@ static int ebt_limit_mt_check(const struct xt_mtchk_param *par)
/* Check for overflow. */
if (info->burst == 0 ||
user2credits(info->avg * info->burst) < user2credits(info->avg)) {
pr_info("overflow, try lower: %u/%u\n",
info->avg, info->burst);
pr_info_ratelimited("overflow, try lower: %u/%u\n",
info->avg, info->burst);
return -EINVAL;
}
......
......@@ -1567,10 +1567,7 @@ int ip_getsockopt(struct sock *sk, int level,
if (get_user(len, optlen))
return -EFAULT;
lock_sock(sk);
err = nf_getsockopt(sk, PF_INET, optname, optval,
&len);
release_sock(sk);
err = nf_getsockopt(sk, PF_INET, optname, optval, &len);
if (err >= 0)
err = put_user(len, optlen);
return err;
......@@ -1602,9 +1599,7 @@ int compat_ip_getsockopt(struct sock *sk, int level, int optname,
if (get_user(len, optlen))
return -EFAULT;
lock_sock(sk);
err = compat_nf_getsockopt(sk, PF_INET, optname, optval, &len);
release_sock(sk);
if (err >= 0)
err = put_user(len, optlen);
return err;
......
......@@ -252,6 +252,10 @@ unsigned int arpt_do_table(struct sk_buff *skb,
}
if (table_base + v
!= arpt_next_entry(e)) {
if (unlikely(stackidx >= private->stacksize)) {
verdict = NF_DROP;
break;
}
jumpstack[stackidx++] = e;
}
......
......@@ -330,8 +330,13 @@ ipt_do_table(struct sk_buff *skb,
continue;
}
if (table_base + v != ipt_next_entry(e) &&
!(e->ip.flags & IPT_F_GOTO))
!(e->ip.flags & IPT_F_GOTO)) {
if (unlikely(stackidx >= private->stacksize)) {
verdict = NF_DROP;
break;
}
jumpstack[stackidx++] = e;
}
e = get_entry(table_base, v);
continue;
......
......@@ -107,12 +107,6 @@ clusterip_config_entry_put(struct net *net, struct clusterip_config *c)
local_bh_disable();
if (refcount_dec_and_lock(&c->entries, &cn->lock)) {
list_del_rcu(&c->list);
spin_unlock(&cn->lock);
local_bh_enable();
unregister_netdevice_notifier(&c->notifier);
/* In case anyone still accesses the file, the open/close
* functions are also incrementing the refcount on their own,
* so it's safe to remove the entry even if it's in use. */
......@@ -120,6 +114,12 @@ clusterip_config_entry_put(struct net *net, struct clusterip_config *c)
if (cn->procdir)
proc_remove(c->pde);
#endif
list_del_rcu(&c->list);
spin_unlock(&cn->lock);
local_bh_enable();
unregister_netdevice_notifier(&c->notifier);
return;
}
local_bh_enable();
......@@ -154,8 +154,12 @@ clusterip_config_find_get(struct net *net, __be32 clusterip, int entry)
#endif
if (unlikely(!refcount_inc_not_zero(&c->refcount)))
c = NULL;
else if (entry)
refcount_inc(&c->entries);
else if (entry) {
if (unlikely(!refcount_inc_not_zero(&c->entries))) {
clusterip_config_put(c);
c = NULL;
}
}
}
rcu_read_unlock_bh();
......
......@@ -98,17 +98,15 @@ static int ecn_tg_check(const struct xt_tgchk_param *par)
const struct ipt_ECN_info *einfo = par->targinfo;
const struct ipt_entry *e = par->entryinfo;
if (einfo->operation & IPT_ECN_OP_MASK) {
pr_info("unsupported ECN operation %x\n", einfo->operation);
if (einfo->operation & IPT_ECN_OP_MASK)
return -EINVAL;
}
if (einfo->ip_ect & ~IPT_ECN_IP_MASK) {
pr_info("new ECT codepoint %x out of mask\n", einfo->ip_ect);
if (einfo->ip_ect & ~IPT_ECN_IP_MASK)
return -EINVAL;
}
if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)) &&
(e->ip.proto != IPPROTO_TCP || (e->ip.invflags & XT_INV_PROTO))) {
pr_info("cannot use TCP operations on a non-tcp rule\n");
pr_info_ratelimited("cannot use operation on non-tcp rule\n");
return -EINVAL;
}
return 0;
......
......@@ -74,13 +74,13 @@ static int reject_tg_check(const struct xt_tgchk_param *par)
const struct ipt_entry *e = par->entryinfo;
if (rejinfo->with == IPT_ICMP_ECHOREPLY) {
pr_info("ECHOREPLY no longer supported.\n");
pr_info_ratelimited("ECHOREPLY no longer supported.\n");
return -EINVAL;
} else if (rejinfo->with == IPT_TCP_RESET) {
/* Must specify that it's a TCP packet */
if (e->ip.proto != IPPROTO_TCP ||
(e->ip.invflags & XT_INV_PROTO)) {
pr_info("TCP_RESET invalid for non-tcp\n");
pr_info_ratelimited("TCP_RESET invalid for non-tcp\n");
return -EINVAL;
}
}
......
......@@ -105,14 +105,14 @@ static int rpfilter_check(const struct xt_mtchk_param *par)
const struct xt_rpfilter_info *info = par->matchinfo;
unsigned int options = ~XT_RPFILTER_OPTION_MASK;
if (info->flags & options) {
pr_info("unknown options encountered");
pr_info_ratelimited("unknown options\n");
return -EINVAL;
}
if (strcmp(par->table, "mangle") != 0 &&
strcmp(par->table, "raw") != 0) {
pr_info("match only valid in the \'raw\' "
"or \'mangle\' tables, not \'%s\'.\n", par->table);
pr_info_ratelimited("only valid in \'raw\' or \'mangle\' table, not \'%s\'\n",
par->table);
return -EINVAL;
}
......
......@@ -1367,10 +1367,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
if (get_user(len, optlen))
return -EFAULT;
lock_sock(sk);
err = nf_getsockopt(sk, PF_INET6, optname, optval,
&len);
release_sock(sk);
err = nf_getsockopt(sk, PF_INET6, optname, optval, &len);
if (err >= 0)
err = put_user(len, optlen);
}
......@@ -1409,10 +1406,7 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
if (get_user(len, optlen))
return -EFAULT;
lock_sock(sk);
err = compat_nf_getsockopt(sk, PF_INET6,
optname, optval, &len);
release_sock(sk);
err = compat_nf_getsockopt(sk, PF_INET6, optname, optval, &len);
if (err >= 0)
err = put_user(len, optlen);
}
......
......@@ -352,6 +352,10 @@ ip6t_do_table(struct sk_buff *skb,
}
if (table_base + v != ip6t_next_entry(e) &&
!(e->ipv6.flags & IP6T_F_GOTO)) {
if (unlikely(stackidx >= private->stacksize)) {
verdict = NF_DROP;
break;
}
jumpstack[stackidx++] = e;
}
......
......@@ -85,14 +85,14 @@ static int reject_tg6_check(const struct xt_tgchk_param *par)
const struct ip6t_entry *e = par->entryinfo;
if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
pr_info("ECHOREPLY is not supported.\n");
pr_info_ratelimited("ECHOREPLY is not supported\n");
return -EINVAL;
} else if (rejinfo->with == IP6T_TCP_RESET) {
/* Must specify that it's a TCP packet */
if (!(e->ipv6.flags & IP6T_F_PROTO) ||
e->ipv6.proto != IPPROTO_TCP ||
(e->ipv6.invflags & XT_INV_PROTO)) {
pr_info("TCP_RESET illegal for non-tcp\n");
pr_info_ratelimited("TCP_RESET illegal for non-tcp\n");
return -EINVAL;
}
}
......
......@@ -103,14 +103,14 @@ static int rpfilter_check(const struct xt_mtchk_param *par)
unsigned int options = ~XT_RPFILTER_OPTION_MASK;
if (info->flags & options) {
pr_info("unknown options encountered");
pr_info_ratelimited("unknown options\n");
return -EINVAL;
}
if (strcmp(par->table, "mangle") != 0 &&
strcmp(par->table, "raw") != 0) {
pr_info("match only valid in the \'raw\' "
"or \'mangle\' tables, not \'%s\'.\n", par->table);
pr_info_ratelimited("only valid in \'raw\' or \'mangle\' table, not \'%s\'\n",
par->table);
return -EINVAL;
}
......
......@@ -122,12 +122,14 @@ static int srh_mt6_check(const struct xt_mtchk_param *par)
const struct ip6t_srh *srhinfo = par->matchinfo;
if (srhinfo->mt_flags & ~IP6T_SRH_MASK) {
pr_err("unknown srh match flags %X\n", srhinfo->mt_flags);
pr_info_ratelimited("unknown srh match flags %X\n",
srhinfo->mt_flags);
return -EINVAL;
}
if (srhinfo->mt_invflags & ~IP6T_SRH_INV_MASK) {
pr_err("unknown srh invflags %X\n", srhinfo->mt_invflags);
pr_info_ratelimited("unknown srh invflags %X\n",
srhinfo->mt_invflags);
return -EINVAL;
}
......
......@@ -41,7 +41,7 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto,
const struct nf_conn *ct,
u16 *rover)
{
unsigned int range_size, min, i;
unsigned int range_size, min, max, i;
__be16 *portptr;
u_int16_t off;
......@@ -71,7 +71,10 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto,
}
} else {
min = ntohs(range->min_proto.all);
range_size = ntohs(range->max_proto.all) - min + 1;
max = ntohs(range->max_proto.all);
if (unlikely(max < min))
swap(max, min);
range_size = max - min + 1;
}
if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) {
......
......@@ -434,36 +434,35 @@ int xt_check_match(struct xt_mtchk_param *par,
* ebt_among is exempt from centralized matchsize checking
* because it uses a dynamic-size data set.
*/
pr_err("%s_tables: %s.%u match: invalid size "
"%u (kernel) != (user) %u\n",
xt_prefix[par->family], par->match->name,
par->match->revision,
XT_ALIGN(par->match->matchsize), size);
pr_err_ratelimited("%s_tables: %s.%u match: invalid size %u (kernel) != (user) %u\n",
xt_prefix[par->family], par->match->name,
par->match->revision,
XT_ALIGN(par->match->matchsize), size);
return -EINVAL;
}
if (par->match->table != NULL &&
strcmp(par->match->table, par->table) != 0) {
pr_err("%s_tables: %s match: only valid in %s table, not %s\n",
xt_prefix[par->family], par->match->name,
par->match->table, par->table);
pr_info_ratelimited("%s_tables: %s match: only valid in %s table, not %s\n",
xt_prefix[par->family], par->match->name,
par->match->table, par->table);
return -EINVAL;
}
if (par->match->hooks && (par->hook_mask & ~par->match->hooks) != 0) {
char used[64], allow[64];
pr_err("%s_tables: %s match: used from hooks %s, but only "
"valid from %s\n",
xt_prefix[par->family], par->match->name,
textify_hooks(used, sizeof(used), par->hook_mask,
par->family),
textify_hooks(allow, sizeof(allow), par->match->hooks,
par->family));
pr_info_ratelimited("%s_tables: %s match: used from hooks %s, but only valid from %s\n",
xt_prefix[par->family], par->match->name,
textify_hooks(used, sizeof(used),
par->hook_mask, par->family),
textify_hooks(allow, sizeof(allow),
par->match->hooks,
par->family));
return -EINVAL;
}
if (par->match->proto && (par->match->proto != proto || inv_proto)) {
pr_err("%s_tables: %s match: only valid for protocol %u\n",
xt_prefix[par->family], par->match->name,
par->match->proto);
pr_info_ratelimited("%s_tables: %s match: only valid for protocol %u\n",
xt_prefix[par->family], par->match->name,
par->match->proto);
return -EINVAL;
}
if (par->match->checkentry != NULL) {
......@@ -814,36 +813,35 @@ int xt_check_target(struct xt_tgchk_param *par,
int ret;
if (XT_ALIGN(par->target->targetsize) != size) {
pr_err("%s_tables: %s.%u target: invalid size "
"%u (kernel) != (user) %u\n",
xt_prefix[par->family], par->target->name,
par->target->revision,
XT_ALIGN(par->target->targetsize), size);
pr_err_ratelimited("%s_tables: %s.%u target: invalid size %u (kernel) != (user) %u\n",
xt_prefix[par->family], par->target->name,
par->target->revision,
XT_ALIGN(par->target->targetsize), size);
return -EINVAL;
}
if (par->target->table != NULL &&
strcmp(par->target->table, par->table) != 0) {
pr_err("%s_tables: %s target: only valid in %s table, not %s\n",
xt_prefix[par->family], par->target->name,
par->target->table, par->table);
pr_info_ratelimited("%s_tables: %s target: only valid in %s table, not %s\n",
xt_prefix[par->family], par->target->name,
par->target->table, par->table);
return -EINVAL;
}
if (par->target->hooks && (par->hook_mask & ~par->target->hooks) != 0) {
char used[64], allow[64];
pr_err("%s_tables: %s target: used from hooks %s, but only "
"usable from %s\n",
xt_prefix[par->family], par->target->name,
textify_hooks(used, sizeof(used), par->hook_mask,
par->family),
textify_hooks(allow, sizeof(allow), par->target->hooks,
par->family));
pr_info_ratelimited("%s_tables: %s target: used from hooks %s, but only usable from %s\n",
xt_prefix[par->family], par->target->name,
textify_hooks(used, sizeof(used),
par->hook_mask, par->family),
textify_hooks(allow, sizeof(allow),
par->target->hooks,
par->family));
return -EINVAL;
}
if (par->target->proto && (par->target->proto != proto || inv_proto)) {
pr_err("%s_tables: %s target: only valid for protocol %u\n",
xt_prefix[par->family], par->target->name,
par->target->proto);
pr_info_ratelimited("%s_tables: %s target: only valid for protocol %u\n",
xt_prefix[par->family], par->target->name,
par->target->proto);
return -EINVAL;
}
if (par->target->checkentry != NULL) {
......@@ -1004,10 +1002,6 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
if (sz < sizeof(*info))
return NULL;
/* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
if ((size >> PAGE_SHIFT) + 2 > totalram_pages)
return NULL;
/* __GFP_NORETRY is not fully supported by kvmalloc but it should
* work reasonably well if sz is too large and bail out rather
* than shoot all processes down before realizing there is nothing
......
......@@ -120,8 +120,8 @@ static int audit_tg_check(const struct xt_tgchk_param *par)
const struct xt_audit_info *info = par->targinfo;
if (info->type > XT_AUDIT_TYPE_MAX) {
pr_info("Audit type out of range (valid range: 0..%hhu)\n",
XT_AUDIT_TYPE_MAX);
pr_info_ratelimited("Audit type out of range (valid range: 0..%hhu)\n",
XT_AUDIT_TYPE_MAX);
return -ERANGE;
}
......
......@@ -36,13 +36,13 @@ static int checksum_tg_check(const struct xt_tgchk_param *par)
const struct xt_CHECKSUM_info *einfo = par->targinfo;
if (einfo->operation & ~XT_CHECKSUM_OP_FILL) {
pr_info("unsupported CHECKSUM operation %x\n", einfo->operation);
pr_info_ratelimited("unsupported CHECKSUM operation %x\n",
einfo->operation);
return -EINVAL;
}
if (!einfo->operation) {
pr_info("no CHECKSUM operation enabled\n");
if (!einfo->operation)
return -EINVAL;
}
return 0;
}
......
......@@ -91,8 +91,8 @@ static int connsecmark_tg_check(const struct xt_tgchk_param *par)
if (strcmp(par->table, "mangle") != 0 &&
strcmp(par->table, "security") != 0) {
pr_info("target only valid in the \'mangle\' "
"or \'security\' tables, not \'%s\'.\n", par->table);
pr_info_ratelimited("only valid in \'mangle\' or \'security\' table, not \'%s\'\n",
par->table);
return -EINVAL;
}
......@@ -102,14 +102,14 @@ static int connsecmark_tg_check(const struct xt_tgchk_param *par)
break;
default:
pr_info("invalid mode: %hu\n", info->mode);
pr_info_ratelimited("invalid mode: %hu\n", info->mode);
return -EINVAL;
}
ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0)
pr_info("cannot load conntrack support for proto=%u\n",
par->family);
pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
par->family);
return ret;
}
......
......@@ -82,15 +82,14 @@ xt_ct_set_helper(struct nf_conn *ct, const char *helper_name,
proto = xt_ct_find_proto(par);
if (!proto) {
pr_info("You must specify a L4 protocol, and not use "
"inversions on it.\n");
pr_info_ratelimited("You must specify a L4 protocol and not use inversions on it\n");
return -ENOENT;
}
helper = nf_conntrack_helper_try_module_get(helper_name, par->family,
proto);
if (helper == NULL) {
pr_info("No such helper \"%s\"\n", helper_name);
pr_info_ratelimited("No such helper \"%s\"\n", helper_name);
return -ENOENT;
}
......@@ -124,6 +123,7 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
const struct nf_conntrack_l4proto *l4proto;
struct ctnl_timeout *timeout;
struct nf_conn_timeout *timeout_ext;
const char *errmsg = NULL;
int ret = 0;
u8 proto;
......@@ -131,29 +131,29 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook);
if (timeout_find_get == NULL) {
ret = -ENOENT;
pr_info("Timeout policy base is empty\n");
errmsg = "Timeout policy base is empty";
goto out;
}
proto = xt_ct_find_proto(par);
if (!proto) {
ret = -EINVAL;
pr_info("You must specify a L4 protocol, and not use "
"inversions on it.\n");
errmsg = "You must specify a L4 protocol and not use inversions on it";
goto out;
}
timeout = timeout_find_get(par->net, timeout_name);
if (timeout == NULL) {
ret = -ENOENT;
pr_info("No such timeout policy \"%s\"\n", timeout_name);
pr_info_ratelimited("No such timeout policy \"%s\"\n",
timeout_name);
goto out;
}
if (timeout->l3num != par->family) {
ret = -EINVAL;
pr_info("Timeout policy `%s' can only be used by L3 protocol "
"number %d\n", timeout_name, timeout->l3num);
pr_info_ratelimited("Timeout policy `%s' can only be used by L%d protocol number %d\n",
timeout_name, 3, timeout->l3num);
goto err_put_timeout;
}
/* Make sure the timeout policy matches any existing protocol tracker,
......@@ -162,9 +162,8 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
l4proto = __nf_ct_l4proto_find(par->family, proto);
if (timeout->l4proto->l4proto != l4proto->l4proto) {
ret = -EINVAL;
pr_info("Timeout policy `%s' can only be used by L4 protocol "
"number %d\n",
timeout_name, timeout->l4proto->l4proto);
pr_info_ratelimited("Timeout policy `%s' can only be used by L%d protocol number %d\n",
timeout_name, 4, timeout->l4proto->l4proto);
goto err_put_timeout;
}
timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC);
......@@ -180,6 +179,8 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
__xt_ct_tg_timeout_put(timeout);
out:
rcu_read_unlock();
if (errmsg)
pr_info_ratelimited("%s\n", errmsg);
return ret;
#else
return -EOPNOTSUPP;
......
......@@ -66,10 +66,8 @@ static int dscp_tg_check(const struct xt_tgchk_param *par)
{
const struct xt_DSCP_info *info = par->targinfo;
if (info->dscp > XT_DSCP_MAX) {
pr_info("dscp %x out of range\n", info->dscp);
if (info->dscp > XT_DSCP_MAX)
return -EDOM;
}
return 0;
}
......
......@@ -105,10 +105,8 @@ static int ttl_tg_check(const struct xt_tgchk_param *par)
{
const struct ipt_TTL_info *info = par->targinfo;
if (info->mode > IPT_TTL_MAXMODE) {
pr_info("TTL: invalid or unknown mode %u\n", info->mode);
if (info->mode > IPT_TTL_MAXMODE)
return -EINVAL;
}
if (info->mode != IPT_TTL_SET && info->ttl == 0)
return -EINVAL;
return 0;
......@@ -118,15 +116,10 @@ static int hl_tg6_check(const struct xt_tgchk_param *par)
{
const struct ip6t_HL_info *info = par->targinfo;
if (info->mode > IP6T_HL_MAXMODE) {
pr_info("invalid or unknown mode %u\n", info->mode);
if (info->mode > IP6T_HL_MAXMODE)
return -EINVAL;
}
if (info->mode != IP6T_HL_SET && info->hop_limit == 0) {
pr_info("increment/decrement does not "
"make sense with value 0\n");
if (info->mode != IP6T_HL_SET && info->hop_limit == 0)
return -EINVAL;
}
return 0;
}
......
......@@ -9,6 +9,8 @@
* the Free Software Foundation.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/icmp.h>
......@@ -312,29 +314,30 @@ hmark_tg_v4(struct sk_buff *skb, const struct xt_action_param *par)
static int hmark_tg_check(const struct xt_tgchk_param *par)
{
const struct xt_hmark_info *info = par->targinfo;
const char *errmsg = "proto mask must be zero with L3 mode";
if (!info->hmodulus) {
pr_info("xt_HMARK: hash modulus can't be zero\n");
if (!info->hmodulus)
return -EINVAL;
}
if (info->proto_mask &&
(info->flags & XT_HMARK_FLAG(XT_HMARK_METHOD_L3))) {
pr_info("xt_HMARK: proto mask must be zero with L3 mode\n");
return -EINVAL;
}
(info->flags & XT_HMARK_FLAG(XT_HMARK_METHOD_L3)))
goto err;
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK) &&
(info->flags & (XT_HMARK_FLAG(XT_HMARK_SPORT_MASK) |
XT_HMARK_FLAG(XT_HMARK_DPORT_MASK)))) {
pr_info("xt_HMARK: spi-mask and port-mask can't be combined\n");
XT_HMARK_FLAG(XT_HMARK_DPORT_MASK))))
return -EINVAL;
}
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI) &&
(info->flags & (XT_HMARK_FLAG(XT_HMARK_SPORT) |
XT_HMARK_FLAG(XT_HMARK_DPORT)))) {
pr_info("xt_HMARK: spi-set and port-set can't be combined\n");
return -EINVAL;
errmsg = "spi-set and port-set can't be combined";
goto err;
}
return 0;
err:
pr_info_ratelimited("%s\n", errmsg);
return -EINVAL;
}
static struct xt_target hmark_tg_reg[] __read_mostly = {
......
......@@ -146,11 +146,11 @@ static int idletimer_tg_create(struct idletimer_tg_info *info)
timer_setup(&info->timer->timer, idletimer_tg_expired, 0);
info->timer->refcnt = 1;
INIT_WORK(&info->timer->work, idletimer_tg_work);
mod_timer(&info->timer->timer,
msecs_to_jiffies(info->timeout * 1000) + jiffies);
INIT_WORK(&info->timer->work, idletimer_tg_work);
return 0;
out_free_attr:
......@@ -191,7 +191,10 @@ static int idletimer_tg_checkentry(const struct xt_tgchk_param *par)
pr_debug("timeout value is zero\n");
return -EINVAL;
}
if (info->timeout >= INT_MAX / 1000) {
pr_debug("timeout value is too big\n");
return -EINVAL;
}
if (info->label[0] == '\0' ||
strnlen(info->label,
MAX_IDLETIMER_LABEL_SIZE) == MAX_IDLETIMER_LABEL_SIZE) {
......
......@@ -111,10 +111,8 @@ static int led_tg_check(const struct xt_tgchk_param *par)
struct xt_led_info_internal *ledinternal;
int err;
if (ledinfo->id[0] == '\0') {
pr_info("No 'id' parameter given.\n");
if (ledinfo->id[0] == '\0')
return -EINVAL;
}
mutex_lock(&xt_led_mutex);
......@@ -138,13 +136,14 @@ static int led_tg_check(const struct xt_tgchk_param *par)
err = led_trigger_register(&ledinternal->netfilter_led_trigger);
if (err) {
pr_err("Trigger name is already in use.\n");
pr_info_ratelimited("Trigger name is already in use.\n");
goto exit_alloc;
}
/* See if we need to set up a timer */
if (ledinfo->delay > 0)
timer_setup(&ledinternal->timer, led_timeout_callback, 0);
/* Since the letinternal timer can be shared between multiple targets,
* always set it up, even if the current target does not need it
*/
timer_setup(&ledinternal->timer, led_timeout_callback, 0);
list_add_tail(&ledinternal->list, &xt_led_triggers);
......@@ -181,8 +180,7 @@ static void led_tg_destroy(const struct xt_tgdtor_param *par)
list_del(&ledinternal->list);
if (ledinfo->delay > 0)
del_timer_sync(&ledinternal->timer);
del_timer_sync(&ledinternal->timer);
led_trigger_unregister(&ledinternal->netfilter_led_trigger);
......
......@@ -8,6 +8,8 @@
*
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/skbuff.h>
......@@ -67,13 +69,13 @@ static int nfqueue_tg_check(const struct xt_tgchk_param *par)
init_hashrandom(&jhash_initval);
if (info->queues_total == 0) {
pr_err("NFQUEUE: number of total queues is 0\n");
pr_info_ratelimited("number of total queues is 0\n");
return -EINVAL;
}
maxid = info->queues_total - 1 + info->queuenum;
if (maxid > 0xffff) {
pr_err("NFQUEUE: number of queues (%u) out of range (got %u)\n",
info->queues_total, maxid);
pr_info_ratelimited("number of queues (%u) out of range (got %u)\n",
info->queues_total, maxid);
return -ERANGE;
}
if (par->target->revision == 2 && info->flags > 1)
......
......@@ -60,18 +60,20 @@ static int checkentry_lsm(struct xt_secmark_target_info *info)
&info->secid);
if (err) {
if (err == -EINVAL)
pr_info("invalid security context \'%s\'\n", info->secctx);
pr_info_ratelimited("invalid security context \'%s\'\n",
info->secctx);
return err;
}
if (!info->secid) {
pr_info("unable to map security context \'%s\'\n", info->secctx);
pr_info_ratelimited("unable to map security context \'%s\'\n",
info->secctx);
return -ENOENT;
}
err = security_secmark_relabel_packet(info->secid);
if (err) {
pr_info("unable to obtain relabeling permission\n");
pr_info_ratelimited("unable to obtain relabeling permission\n");
return err;
}
......@@ -86,14 +88,14 @@ static int secmark_tg_check(const struct xt_tgchk_param *par)
if (strcmp(par->table, "mangle") != 0 &&
strcmp(par->table, "security") != 0) {
pr_info("target only valid in the \'mangle\' "
"or \'security\' tables, not \'%s\'.\n", par->table);
pr_info_ratelimited("only valid in \'mangle\' or \'security\' table, not \'%s\'\n",
par->table);
return -EINVAL;
}
if (mode && mode != info->mode) {
pr_info("mode already set to %hu cannot mix with "
"rules for mode %hu\n", mode, info->mode);
pr_info_ratelimited("mode already set to %hu cannot mix with rules for mode %hu\n",
mode, info->mode);
return -EINVAL;
}
......@@ -101,7 +103,7 @@ static int secmark_tg_check(const struct xt_tgchk_param *par)
case SECMARK_MODE_SEL:
break;
default:
pr_info("invalid mode: %hu\n", info->mode);
pr_info_ratelimited("invalid mode: %hu\n", info->mode);
return -EINVAL;
}
......
......@@ -273,8 +273,7 @@ static int tcpmss_tg4_check(const struct xt_tgchk_param *par)
(par->hook_mask & ~((1 << NF_INET_FORWARD) |
(1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_POST_ROUTING))) != 0) {
pr_info("path-MTU clamping only supported in "
"FORWARD, OUTPUT and POSTROUTING hooks\n");
pr_info_ratelimited("path-MTU clamping only supported in FORWARD, OUTPUT and POSTROUTING hooks\n");
return -EINVAL;
}
if (par->nft_compat)
......@@ -283,7 +282,7 @@ static int tcpmss_tg4_check(const struct xt_tgchk_param *par)
xt_ematch_foreach(ematch, e)
if (find_syn_match(ematch))
return 0;
pr_info("Only works on TCP SYN packets\n");
pr_info_ratelimited("Only works on TCP SYN packets\n");
return -EINVAL;
}
......@@ -298,8 +297,7 @@ static int tcpmss_tg6_check(const struct xt_tgchk_param *par)
(par->hook_mask & ~((1 << NF_INET_FORWARD) |
(1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_POST_ROUTING))) != 0) {
pr_info("path-MTU clamping only supported in "
"FORWARD, OUTPUT and POSTROUTING hooks\n");
pr_info_ratelimited("path-MTU clamping only supported in FORWARD, OUTPUT and POSTROUTING hooks\n");
return -EINVAL;
}
if (par->nft_compat)
......@@ -308,7 +306,7 @@ static int tcpmss_tg6_check(const struct xt_tgchk_param *par)
xt_ematch_foreach(ematch, e)
if (find_syn_match(ematch))
return 0;
pr_info("Only works on TCP SYN packets\n");
pr_info_ratelimited("Only works on TCP SYN packets\n");
return -EINVAL;
}
#endif
......
......@@ -540,8 +540,7 @@ static int tproxy_tg6_check(const struct xt_tgchk_param *par)
!(i->invflags & IP6T_INV_PROTO))
return 0;
pr_info("Can be used only in combination with "
"either -p tcp or -p udp\n");
pr_info_ratelimited("Can be used only with -p tcp or -p udp\n");
return -EINVAL;
}
#endif
......@@ -559,8 +558,7 @@ static int tproxy_tg4_check(const struct xt_tgchk_param *par)
&& !(i->invflags & IPT_INV_PROTO))
return 0;
pr_info("Can be used only in combination with "
"either -p tcp or -p udp\n");
pr_info_ratelimited("Can be used only with -p tcp or -p udp\n");
return -EINVAL;
}
......
......@@ -164,48 +164,47 @@ addrtype_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
static int addrtype_mt_checkentry_v1(const struct xt_mtchk_param *par)
{
const char *errmsg = "both incoming and outgoing interface limitation cannot be selected";
struct xt_addrtype_info_v1 *info = par->matchinfo;
if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN &&
info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT) {
pr_info("both incoming and outgoing "
"interface limitation cannot be selected\n");
return -EINVAL;
}
info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT)
goto err;
if (par->hook_mask & ((1 << NF_INET_PRE_ROUTING) |
(1 << NF_INET_LOCAL_IN)) &&
info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT) {
pr_info("output interface limitation "
"not valid in PREROUTING and INPUT\n");
return -EINVAL;
errmsg = "output interface limitation not valid in PREROUTING and INPUT";
goto err;
}
if (par->hook_mask & ((1 << NF_INET_POST_ROUTING) |
(1 << NF_INET_LOCAL_OUT)) &&
info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN) {
pr_info("input interface limitation "
"not valid in POSTROUTING and OUTPUT\n");
return -EINVAL;
errmsg = "input interface limitation not valid in POSTROUTING and OUTPUT";
goto err;
}
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
if (par->family == NFPROTO_IPV6) {
if ((info->source | info->dest) & XT_ADDRTYPE_BLACKHOLE) {
pr_err("ipv6 BLACKHOLE matching not supported\n");
return -EINVAL;
errmsg = "ipv6 BLACKHOLE matching not supported";
goto err;
}
if ((info->source | info->dest) >= XT_ADDRTYPE_PROHIBIT) {
pr_err("ipv6 PROHIBIT (THROW, NAT ..) matching not supported\n");
return -EINVAL;
errmsg = "ipv6 PROHIBIT (THROW, NAT ..) matching not supported";
goto err;
}
if ((info->source | info->dest) & XT_ADDRTYPE_BROADCAST) {
pr_err("ipv6 does not support BROADCAST matching\n");
return -EINVAL;
errmsg = "ipv6 does not support BROADCAST matching";
goto err;
}
}
#endif
return 0;
err:
pr_info_ratelimited("%s\n", errmsg);
return -EINVAL;
}
static struct xt_match addrtype_mt_reg[] __read_mostly = {
......
......@@ -7,6 +7,8 @@
* published by the Free Software Foundation.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/syscalls.h>
#include <linux/skbuff.h>
......@@ -34,7 +36,7 @@ static int __bpf_mt_check_bytecode(struct sock_filter *insns, __u16 len,
program.filter = insns;
if (bpf_prog_create(ret, &program)) {
pr_info("bpf: check failed: parse error\n");
pr_info_ratelimited("check failed: parse error\n");
return -EINVAL;
}
......
......@@ -12,6 +12,8 @@
* published by the Free Software Foundation.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/skbuff.h>
#include <linux/module.h>
#include <linux/netfilter/x_tables.h>
......@@ -48,7 +50,7 @@ static int cgroup_mt_check_v1(const struct xt_mtchk_param *par)
}
if (info->has_path && info->has_classid) {
pr_info("xt_cgroup: both path and classid specified\n");
pr_info_ratelimited("path and classid specified\n");
return -EINVAL;
}
......@@ -56,8 +58,8 @@ static int cgroup_mt_check_v1(const struct xt_mtchk_param *par)
if (info->has_path) {
cgrp = cgroup_get_from_path(info->path);
if (IS_ERR(cgrp)) {
pr_info("xt_cgroup: invalid path, errno=%ld\n",
PTR_ERR(cgrp));
pr_info_ratelimited("invalid path, errno=%ld\n",
PTR_ERR(cgrp));
return -EINVAL;
}
info->priv = cgrp;
......
......@@ -135,14 +135,12 @@ static int xt_cluster_mt_checkentry(const struct xt_mtchk_param *par)
struct xt_cluster_match_info *info = par->matchinfo;
if (info->total_nodes > XT_CLUSTER_NODES_MAX) {
pr_info("you have exceeded the maximum "
"number of cluster nodes (%u > %u)\n",
info->total_nodes, XT_CLUSTER_NODES_MAX);
pr_info_ratelimited("you have exceeded the maximum number of cluster nodes (%u > %u)\n",
info->total_nodes, XT_CLUSTER_NODES_MAX);
return -EINVAL;
}
if (info->node_mask >= (1ULL << info->total_nodes)) {
pr_info("this node mask cannot be "
"higher than the total number of nodes\n");
pr_info_ratelimited("node mask cannot exceed total number of nodes\n");
return -EDOM;
}
return 0;
......
......@@ -112,8 +112,8 @@ static int connbytes_mt_check(const struct xt_mtchk_param *par)
ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0)
pr_info("cannot load conntrack support for proto=%u\n",
par->family);
pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
par->family);
/*
* This filter cannot function correctly unless connection tracking
......
......@@ -57,14 +57,15 @@ static int connlabel_mt_check(const struct xt_mtchk_param *par)
int ret;
if (info->options & ~options) {
pr_err("Unknown options in mask %x\n", info->options);
pr_info_ratelimited("Unknown options in mask %x\n",
info->options);
return -EINVAL;
}
ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0) {
pr_info("cannot load conntrack support for proto=%u\n",
par->family);
pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
par->family);
return ret;
}
......
......@@ -79,8 +79,8 @@ static int connmark_tg_check(const struct xt_tgchk_param *par)
ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0)
pr_info("cannot load conntrack support for proto=%u\n",
par->family);
pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
par->family);
return ret;
}
......@@ -109,8 +109,8 @@ static int connmark_mt_check(const struct xt_mtchk_param *par)
ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0)
pr_info("cannot load conntrack support for proto=%u\n",
par->family);
pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
par->family);
return ret;
}
......
......@@ -272,8 +272,8 @@ static int conntrack_mt_check(const struct xt_mtchk_param *par)
ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0)
pr_info("cannot load conntrack support for proto=%u\n",
par->family);
pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
par->family);
return ret;
}
......
......@@ -46,10 +46,8 @@ static int dscp_mt_check(const struct xt_mtchk_param *par)
{
const struct xt_dscp_info *info = par->matchinfo;
if (info->dscp > XT_DSCP_MAX) {
pr_info("dscp %x out of range\n", info->dscp);
if (info->dscp > XT_DSCP_MAX)
return -EDOM;
}
return 0;
}
......
......@@ -97,7 +97,7 @@ static int ecn_mt_check4(const struct xt_mtchk_param *par)
if (info->operation & (XT_ECN_OP_MATCH_ECE | XT_ECN_OP_MATCH_CWR) &&
(ip->proto != IPPROTO_TCP || ip->invflags & IPT_INV_PROTO)) {
pr_info("cannot match TCP bits in rule for non-tcp packets\n");
pr_info_ratelimited("cannot match TCP bits for non-tcp packets\n");
return -EINVAL;
}
......@@ -139,7 +139,7 @@ static int ecn_mt_check6(const struct xt_mtchk_param *par)
if (info->operation & (XT_ECN_OP_MATCH_ECE | XT_ECN_OP_MATCH_CWR) &&
(ip->proto != IPPROTO_TCP || ip->invflags & IP6T_INV_PROTO)) {
pr_info("cannot match TCP bits in rule for non-tcp packets\n");
pr_info_ratelimited("cannot match TCP bits for non-tcp packets\n");
return -EINVAL;
}
......
......@@ -523,7 +523,8 @@ static u64 user2rate(u64 user)
if (user != 0) {
return div64_u64(XT_HASHLIMIT_SCALE_v2, user);
} else {
pr_warn("invalid rate from userspace: %llu\n", user);
pr_info_ratelimited("invalid rate from userspace: %llu\n",
user);
return 0;
}
}
......@@ -774,7 +775,7 @@ hashlimit_mt_common(const struct sk_buff *skb, struct xt_action_param *par,
if (!dh->rateinfo.prev_window &&
(dh->rateinfo.current_rate <= dh->rateinfo.burst)) {
spin_unlock(&dh->lock);
rcu_read_unlock_bh();
local_bh_enable();
return !(cfg->mode & XT_HASHLIMIT_INVERT);
} else {
goto overlimit;
......@@ -865,33 +866,34 @@ static int hashlimit_mt_check_common(const struct xt_mtchk_param *par,
}
if (cfg->mode & ~XT_HASHLIMIT_ALL) {
pr_info("Unknown mode mask %X, kernel too old?\n",
cfg->mode);
pr_info_ratelimited("Unknown mode mask %X, kernel too old?\n",
cfg->mode);
return -EINVAL;
}
/* Check for overflow. */
if (revision >= 3 && cfg->mode & XT_HASHLIMIT_RATE_MATCH) {
if (cfg->avg == 0 || cfg->avg > U32_MAX) {
pr_info("hashlimit invalid rate\n");
pr_info_ratelimited("invalid rate\n");
return -ERANGE;
}
if (cfg->interval == 0) {
pr_info("hashlimit invalid interval\n");
pr_info_ratelimited("invalid interval\n");
return -EINVAL;
}
} else if (cfg->mode & XT_HASHLIMIT_BYTES) {
if (user2credits_byte(cfg->avg) == 0) {
pr_info("overflow, rate too high: %llu\n", cfg->avg);
pr_info_ratelimited("overflow, rate too high: %llu\n",
cfg->avg);
return -EINVAL;
}
} else if (cfg->burst == 0 ||
user2credits(cfg->avg * cfg->burst, revision) <
user2credits(cfg->avg, revision)) {
pr_info("overflow, try lower: %llu/%llu\n",
cfg->avg, cfg->burst);
return -ERANGE;
user2credits(cfg->avg * cfg->burst, revision) <
user2credits(cfg->avg, revision)) {
pr_info_ratelimited("overflow, try lower: %llu/%llu\n",
cfg->avg, cfg->burst);
return -ERANGE;
}
mutex_lock(&hashlimit_mutex);
......
......@@ -61,8 +61,8 @@ static int helper_mt_check(const struct xt_mtchk_param *par)
ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0) {
pr_info("cannot load conntrack support for proto=%u\n",
par->family);
pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
par->family);
return ret;
}
info->name[sizeof(info->name) - 1] = '\0';
......
......@@ -72,7 +72,7 @@ static int comp_mt_check(const struct xt_mtchk_param *par)
/* Must specify no unknown invflags */
if (compinfo->invflags & ~XT_IPCOMP_INV_MASK) {
pr_err("unknown flags %X\n", compinfo->invflags);
pr_info_ratelimited("unknown flags %X\n", compinfo->invflags);
return -EINVAL;
}
return 0;
......
......@@ -158,7 +158,8 @@ static int ipvs_mt_check(const struct xt_mtchk_param *par)
&& par->family != NFPROTO_IPV6
#endif
) {
pr_info("protocol family %u not supported\n", par->family);
pr_info_ratelimited("protocol family %u not supported\n",
par->family);
return -EINVAL;
}
......
......@@ -216,7 +216,7 @@ static int l2tp_mt_check(const struct xt_mtchk_param *par)
/* Check for invalid flags */
if (info->flags & ~(XT_L2TP_TID | XT_L2TP_SID | XT_L2TP_VERSION |
XT_L2TP_TYPE)) {
pr_info("unknown flags: %x\n", info->flags);
pr_info_ratelimited("unknown flags: %x\n", info->flags);
return -EINVAL;
}
......@@ -225,7 +225,8 @@ static int l2tp_mt_check(const struct xt_mtchk_param *par)
(!(info->flags & XT_L2TP_SID)) &&
((!(info->flags & XT_L2TP_TYPE)) ||
(info->type != XT_L2TP_TYPE_CONTROL))) {
pr_info("invalid flags combination: %x\n", info->flags);
pr_info_ratelimited("invalid flags combination: %x\n",
info->flags);
return -EINVAL;
}
......@@ -234,19 +235,22 @@ static int l2tp_mt_check(const struct xt_mtchk_param *par)
*/
if (info->flags & XT_L2TP_VERSION) {
if ((info->version < 2) || (info->version > 3)) {
pr_info("wrong L2TP version: %u\n", info->version);
pr_info_ratelimited("wrong L2TP version: %u\n",
info->version);
return -EINVAL;
}
if (info->version == 2) {
if ((info->flags & XT_L2TP_TID) &&
(info->tid > 0xffff)) {
pr_info("v2 tid > 0xffff: %u\n", info->tid);
pr_info_ratelimited("v2 tid > 0xffff: %u\n",
info->tid);
return -EINVAL;
}
if ((info->flags & XT_L2TP_SID) &&
(info->sid > 0xffff)) {
pr_info("v2 sid > 0xffff: %u\n", info->sid);
pr_info_ratelimited("v2 sid > 0xffff: %u\n",
info->sid);
return -EINVAL;
}
}
......@@ -268,13 +272,13 @@ static int l2tp_mt_check4(const struct xt_mtchk_param *par)
if ((ip->proto != IPPROTO_UDP) &&
(ip->proto != IPPROTO_L2TP)) {
pr_info("missing protocol rule (udp|l2tpip)\n");
pr_info_ratelimited("missing protocol rule (udp|l2tpip)\n");
return -EINVAL;
}
if ((ip->proto == IPPROTO_L2TP) &&
(info->version == 2)) {
pr_info("v2 doesn't support IP mode\n");
pr_info_ratelimited("v2 doesn't support IP mode\n");
return -EINVAL;
}
......@@ -295,13 +299,13 @@ static int l2tp_mt_check6(const struct xt_mtchk_param *par)
if ((ip->proto != IPPROTO_UDP) &&
(ip->proto != IPPROTO_L2TP)) {
pr_info("missing protocol rule (udp|l2tpip)\n");
pr_info_ratelimited("missing protocol rule (udp|l2tpip)\n");
return -EINVAL;
}
if ((ip->proto == IPPROTO_L2TP) &&
(info->version == 2)) {
pr_info("v2 doesn't support IP mode\n");
pr_info_ratelimited("v2 doesn't support IP mode\n");
return -EINVAL;
}
......
......@@ -106,8 +106,8 @@ static int limit_mt_check(const struct xt_mtchk_param *par)
/* Check for overflow. */
if (r->burst == 0
|| user2credits(r->avg * r->burst) < user2credits(r->avg)) {
pr_info("Overflow, try lower: %u/%u\n",
r->avg, r->burst);
pr_info_ratelimited("Overflow, try lower: %u/%u\n",
r->avg, r->burst);
return -ERANGE;
}
......
......@@ -8,6 +8,8 @@
* published by the Free Software Foundation.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netfilter.h>
......@@ -19,8 +21,7 @@ static int xt_nat_checkentry_v0(const struct xt_tgchk_param *par)
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
if (mr->rangesize != 1) {
pr_info("%s: multiple ranges no longer supported\n",
par->target->name);
pr_info_ratelimited("multiple ranges no longer supported\n");
return -EINVAL;
}
return nf_ct_netns_get(par->net, par->family);
......
......@@ -6,6 +6,8 @@
* it under the terms of the GNU General Public License version 2 (or any
* later at your option) as published by the Free Software Foundation.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/skbuff.h>
......@@ -39,8 +41,8 @@ nfacct_mt_checkentry(const struct xt_mtchk_param *par)
nfacct = nfnl_acct_find_get(par->net, info->name);
if (nfacct == NULL) {
pr_info("xt_nfacct: accounting object with name `%s' "
"does not exists\n", info->name);
pr_info_ratelimited("accounting object `%s' does not exists\n",
info->name);
return -ENOENT;
}
info->nfacct = nfacct;
......
......@@ -107,9 +107,7 @@ static int physdev_mt_check(const struct xt_mtchk_param *par)
info->invert & XT_PHYSDEV_OP_BRIDGED) &&
par->hook_mask & ((1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_FORWARD) | (1 << NF_INET_POST_ROUTING))) {
pr_info("using --physdev-out and --physdev-is-out are only "
"supported in the FORWARD and POSTROUTING chains with "
"bridged traffic.\n");
pr_info_ratelimited("--physdev-out and --physdev-is-out only supported in the FORWARD and POSTROUTING chains with bridged traffic\n");
if (par->hook_mask & (1 << NF_INET_LOCAL_OUT))
return -EINVAL;
}
......
......@@ -132,26 +132,29 @@ policy_mt(const struct sk_buff *skb, struct xt_action_param *par)
static int policy_mt_check(const struct xt_mtchk_param *par)
{
const struct xt_policy_info *info = par->matchinfo;
const char *errmsg = "neither incoming nor outgoing policy selected";
if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT)))
goto err;
if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) {
pr_info("neither incoming nor outgoing policy selected\n");
return -EINVAL;
}
if (par->hook_mask & ((1 << NF_INET_PRE_ROUTING) |
(1 << NF_INET_LOCAL_IN)) && info->flags & XT_POLICY_MATCH_OUT) {
pr_info("output policy not valid in PREROUTING and INPUT\n");
return -EINVAL;
errmsg = "output policy not valid in PREROUTING and INPUT";
goto err;
}
if (par->hook_mask & ((1 << NF_INET_POST_ROUTING) |
(1 << NF_INET_LOCAL_OUT)) && info->flags & XT_POLICY_MATCH_IN) {
pr_info("input policy not valid in POSTROUTING and OUTPUT\n");
return -EINVAL;
errmsg = "input policy not valid in POSTROUTING and OUTPUT";
goto err;
}
if (info->len > XT_POLICY_MAX_ELEM) {
pr_info("too many policy elements\n");
return -EINVAL;
errmsg = "too many policy elements";
goto err;
}
return 0;
err:
pr_info_ratelimited("%s\n", errmsg);
return -EINVAL;
}
static struct xt_match policy_mt_reg[] __read_mostly = {
......
......@@ -342,8 +342,8 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
net_get_random_once(&hash_rnd, sizeof(hash_rnd));
if (info->check_set & ~XT_RECENT_VALID_FLAGS) {
pr_info("Unsupported user space flags (%08x)\n",
info->check_set);
pr_info_ratelimited("Unsupported userspace flags (%08x)\n",
info->check_set);
return -EINVAL;
}
if (hweight8(info->check_set &
......@@ -357,8 +357,8 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
if ((info->check_set & XT_RECENT_REAP) && !info->seconds)
return -EINVAL;
if (info->hit_count >= XT_RECENT_MAX_NSTAMPS) {
pr_info("hitcount (%u) is larger than allowed maximum (%u)\n",
info->hit_count, XT_RECENT_MAX_NSTAMPS - 1);
pr_info_ratelimited("hitcount (%u) is larger than allowed maximum (%u)\n",
info->hit_count, XT_RECENT_MAX_NSTAMPS - 1);
return -EINVAL;
}
if (info->name[0] == '\0' ||
......@@ -587,7 +587,7 @@ recent_mt_proc_write(struct file *file, const char __user *input,
add = true;
break;
default:
pr_info("Need \"+ip\", \"-ip\" or \"/\"\n");
pr_info_ratelimited("Need \"+ip\", \"-ip\" or \"/\"\n");
return -EINVAL;
}
......@@ -601,10 +601,8 @@ recent_mt_proc_write(struct file *file, const char __user *input,
succ = in4_pton(c, size, (void *)&addr, '\n', NULL);
}
if (!succ) {
pr_info("illegal address written to procfs\n");
if (!succ)
return -EINVAL;
}
spin_lock_bh(&recent_lock);
e = recent_entry_lookup(t, &addr, family, 0);
......
......@@ -92,12 +92,12 @@ set_match_v0_checkentry(const struct xt_mtchk_param *par)
index = ip_set_nfnl_get_byindex(par->net, info->match_set.index);
if (index == IPSET_INVALID_ID) {
pr_warn("Cannot find set identified by id %u to match\n",
info->match_set.index);
pr_info_ratelimited("Cannot find set identified by id %u to match\n",
info->match_set.index);
return -ENOENT;
}
if (info->match_set.u.flags[IPSET_DIM_MAX - 1] != 0) {
pr_warn("Protocol error: set match dimension is over the limit!\n");
pr_info_ratelimited("set match dimension is over the limit!\n");
ip_set_nfnl_put(par->net, info->match_set.index);
return -ERANGE;
}
......@@ -143,12 +143,12 @@ set_match_v1_checkentry(const struct xt_mtchk_param *par)
index = ip_set_nfnl_get_byindex(par->net, info->match_set.index);
if (index == IPSET_INVALID_ID) {
pr_warn("Cannot find set identified by id %u to match\n",
info->match_set.index);
pr_info_ratelimited("Cannot find set identified by id %u to match\n",
info->match_set.index);
return -ENOENT;
}
if (info->match_set.dim > IPSET_DIM_MAX) {
pr_warn("Protocol error: set match dimension is over the limit!\n");
pr_info_ratelimited("set match dimension is over the limit!\n");
ip_set_nfnl_put(par->net, info->match_set.index);
return -ERANGE;
}
......@@ -241,8 +241,8 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par)
if (info->add_set.index != IPSET_INVALID_ID) {
index = ip_set_nfnl_get_byindex(par->net, info->add_set.index);
if (index == IPSET_INVALID_ID) {
pr_warn("Cannot find add_set index %u as target\n",
info->add_set.index);
pr_info_ratelimited("Cannot find add_set index %u as target\n",
info->add_set.index);
return -ENOENT;
}
}
......@@ -250,8 +250,8 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par)
if (info->del_set.index != IPSET_INVALID_ID) {
index = ip_set_nfnl_get_byindex(par->net, info->del_set.index);
if (index == IPSET_INVALID_ID) {
pr_warn("Cannot find del_set index %u as target\n",
info->del_set.index);
pr_info_ratelimited("Cannot find del_set index %u as target\n",
info->del_set.index);
if (info->add_set.index != IPSET_INVALID_ID)
ip_set_nfnl_put(par->net, info->add_set.index);
return -ENOENT;
......@@ -259,7 +259,7 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par)
}
if (info->add_set.u.flags[IPSET_DIM_MAX - 1] != 0 ||
info->del_set.u.flags[IPSET_DIM_MAX - 1] != 0) {
pr_warn("Protocol error: SET target dimension is over the limit!\n");
pr_info_ratelimited("SET target dimension over the limit!\n");
if (info->add_set.index != IPSET_INVALID_ID)
ip_set_nfnl_put(par->net, info->add_set.index);
if (info->del_set.index != IPSET_INVALID_ID)
......@@ -316,8 +316,8 @@ set_target_v1_checkentry(const struct xt_tgchk_param *par)
if (info->add_set.index != IPSET_INVALID_ID) {
index = ip_set_nfnl_get_byindex(par->net, info->add_set.index);
if (index == IPSET_INVALID_ID) {
pr_warn("Cannot find add_set index %u as target\n",
info->add_set.index);
pr_info_ratelimited("Cannot find add_set index %u as target\n",
info->add_set.index);
return -ENOENT;
}
}
......@@ -325,8 +325,8 @@ set_target_v1_checkentry(const struct xt_tgchk_param *par)
if (info->del_set.index != IPSET_INVALID_ID) {
index = ip_set_nfnl_get_byindex(par->net, info->del_set.index);
if (index == IPSET_INVALID_ID) {
pr_warn("Cannot find del_set index %u as target\n",
info->del_set.index);
pr_info_ratelimited("Cannot find del_set index %u as target\n",
info->del_set.index);
if (info->add_set.index != IPSET_INVALID_ID)
ip_set_nfnl_put(par->net, info->add_set.index);
return -ENOENT;
......@@ -334,7 +334,7 @@ set_target_v1_checkentry(const struct xt_tgchk_param *par)
}
if (info->add_set.dim > IPSET_DIM_MAX ||
info->del_set.dim > IPSET_DIM_MAX) {
pr_warn("Protocol error: SET target dimension is over the limit!\n");
pr_info_ratelimited("SET target dimension over the limit!\n");
if (info->add_set.index != IPSET_INVALID_ID)
ip_set_nfnl_put(par->net, info->add_set.index);
if (info->del_set.index != IPSET_INVALID_ID)
......@@ -444,8 +444,8 @@ set_target_v3_checkentry(const struct xt_tgchk_param *par)
index = ip_set_nfnl_get_byindex(par->net,
info->add_set.index);
if (index == IPSET_INVALID_ID) {
pr_warn("Cannot find add_set index %u as target\n",
info->add_set.index);
pr_info_ratelimited("Cannot find add_set index %u as target\n",
info->add_set.index);
return -ENOENT;
}
}
......@@ -454,8 +454,8 @@ set_target_v3_checkentry(const struct xt_tgchk_param *par)
index = ip_set_nfnl_get_byindex(par->net,
info->del_set.index);
if (index == IPSET_INVALID_ID) {
pr_warn("Cannot find del_set index %u as target\n",
info->del_set.index);
pr_info_ratelimited("Cannot find del_set index %u as target\n",
info->del_set.index);
if (info->add_set.index != IPSET_INVALID_ID)
ip_set_nfnl_put(par->net,
info->add_set.index);
......@@ -465,7 +465,7 @@ set_target_v3_checkentry(const struct xt_tgchk_param *par)
if (info->map_set.index != IPSET_INVALID_ID) {
if (strncmp(par->table, "mangle", 7)) {
pr_warn("--map-set only usable from mangle table\n");
pr_info_ratelimited("--map-set only usable from mangle table\n");
return -EINVAL;
}
if (((info->flags & IPSET_FLAG_MAP_SKBPRIO) |
......@@ -473,14 +473,14 @@ set_target_v3_checkentry(const struct xt_tgchk_param *par)
!(par->hook_mask & (1 << NF_INET_FORWARD |
1 << NF_INET_LOCAL_OUT |
1 << NF_INET_POST_ROUTING))) {
pr_warn("mapping of prio or/and queue is allowed only from OUTPUT/FORWARD/POSTROUTING chains\n");
pr_info_ratelimited("mapping of prio or/and queue is allowed only from OUTPUT/FORWARD/POSTROUTING chains\n");
return -EINVAL;
}
index = ip_set_nfnl_get_byindex(par->net,
info->map_set.index);
if (index == IPSET_INVALID_ID) {
pr_warn("Cannot find map_set index %u as target\n",
info->map_set.index);
pr_info_ratelimited("Cannot find map_set index %u as target\n",
info->map_set.index);
if (info->add_set.index != IPSET_INVALID_ID)
ip_set_nfnl_put(par->net,
info->add_set.index);
......@@ -494,7 +494,7 @@ set_target_v3_checkentry(const struct xt_tgchk_param *par)
if (info->add_set.dim > IPSET_DIM_MAX ||
info->del_set.dim > IPSET_DIM_MAX ||
info->map_set.dim > IPSET_DIM_MAX) {
pr_warn("Protocol error: SET target dimension is over the limit!\n");
pr_info_ratelimited("SET target dimension over the limit!\n");
if (info->add_set.index != IPSET_INVALID_ID)
ip_set_nfnl_put(par->net, info->add_set.index);
if (info->del_set.index != IPSET_INVALID_ID)
......
......@@ -171,7 +171,8 @@ static int socket_mt_v1_check(const struct xt_mtchk_param *par)
return err;
if (info->flags & ~XT_SOCKET_FLAGS_V1) {
pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V1);
pr_info_ratelimited("unknown flags 0x%x\n",
info->flags & ~XT_SOCKET_FLAGS_V1);
return -EINVAL;
}
return 0;
......@@ -187,7 +188,8 @@ static int socket_mt_v2_check(const struct xt_mtchk_param *par)
return err;
if (info->flags & ~XT_SOCKET_FLAGS_V2) {
pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V2);
pr_info_ratelimited("unknown flags 0x%x\n",
info->flags & ~XT_SOCKET_FLAGS_V2);
return -EINVAL;
}
return 0;
......@@ -203,8 +205,8 @@ static int socket_mt_v3_check(const struct xt_mtchk_param *par)
if (err)
return err;
if (info->flags & ~XT_SOCKET_FLAGS_V3) {
pr_info("unknown flags 0x%x\n",
info->flags & ~XT_SOCKET_FLAGS_V3);
pr_info_ratelimited("unknown flags 0x%x\n",
info->flags & ~XT_SOCKET_FLAGS_V3);
return -EINVAL;
}
return 0;
......
......@@ -44,8 +44,8 @@ static int state_mt_check(const struct xt_mtchk_param *par)
ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0)
pr_info("cannot load conntrack support for proto=%u\n",
par->family);
pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
par->family);
return ret;
}
......
......@@ -235,13 +235,13 @@ static int time_mt_check(const struct xt_mtchk_param *par)
if (info->daytime_start > XT_TIME_MAX_DAYTIME ||
info->daytime_stop > XT_TIME_MAX_DAYTIME) {
pr_info("invalid argument - start or "
"stop time greater than 23:59:59\n");
pr_info_ratelimited("invalid argument - start or stop time greater than 23:59:59\n");
return -EDOM;
}
if (info->flags & ~XT_TIME_ALL_FLAGS) {
pr_info("unknown flags 0x%x\n", info->flags & ~XT_TIME_ALL_FLAGS);
pr_info_ratelimited("unknown flags 0x%x\n",
info->flags & ~XT_TIME_ALL_FLAGS);
return -EINVAL;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment