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