Commit d6b00a53 authored by Jan Engelhardt's avatar Jan Engelhardt

netfilter: xtables: change targets to return error code

Part of the transition of done by this semantic patch:
// <smpl>
@ rule1 @
struct xt_target ops;
identifier check;
@@
 ops.checkentry = check;

@@
identifier rule1.check;
@@
 check(...) { <...
-return true;
+return 0;
 ...> }

@@
identifier rule1.check;
@@
 check(...) { <...
-return false;
+return -EINVAL;
 ...> }
// </smpl>
Signed-off-by: default avatarJan Engelhardt <jengelh@medozas.de>
parent bd414ee6
...@@ -63,11 +63,11 @@ static int ebt_arpreply_tg_check(const struct xt_tgchk_param *par) ...@@ -63,11 +63,11 @@ static int ebt_arpreply_tg_check(const struct xt_tgchk_param *par)
const struct ebt_entry *e = par->entryinfo; const struct ebt_entry *e = par->entryinfo;
if (BASE_CHAIN && info->target == EBT_RETURN) if (BASE_CHAIN && info->target == EBT_RETURN)
return false; return -EINVAL;
if (e->ethproto != htons(ETH_P_ARP) || if (e->ethproto != htons(ETH_P_ARP) ||
e->invflags & EBT_IPROTO) e->invflags & EBT_IPROTO)
return false; return -EINVAL;
return true; return 0;
} }
static struct xt_target ebt_arpreply_tg_reg __read_mostly = { static struct xt_target ebt_arpreply_tg_reg __read_mostly = {
......
...@@ -32,7 +32,7 @@ static int ebt_dnat_tg_check(const struct xt_tgchk_param *par) ...@@ -32,7 +32,7 @@ static int ebt_dnat_tg_check(const struct xt_tgchk_param *par)
unsigned int hook_mask; unsigned int hook_mask;
if (BASE_CHAIN && info->target == EBT_RETURN) if (BASE_CHAIN && info->target == EBT_RETURN)
return false; return -EINVAL;
hook_mask = par->hook_mask & ~(1 << NF_BR_NUMHOOKS); hook_mask = par->hook_mask & ~(1 << NF_BR_NUMHOOKS);
if ((strcmp(par->table, "nat") != 0 || if ((strcmp(par->table, "nat") != 0 ||
...@@ -40,10 +40,10 @@ static int ebt_dnat_tg_check(const struct xt_tgchk_param *par) ...@@ -40,10 +40,10 @@ static int ebt_dnat_tg_check(const struct xt_tgchk_param *par)
(1 << NF_BR_LOCAL_OUT)))) && (1 << NF_BR_LOCAL_OUT)))) &&
(strcmp(par->table, "broute") != 0 || (strcmp(par->table, "broute") != 0 ||
hook_mask & ~(1 << NF_BR_BROUTING))) hook_mask & ~(1 << NF_BR_BROUTING)))
return false; return -EINVAL;
if (INVALID_TARGET) if (INVALID_TARGET)
return false; return -EINVAL;
return true; return 0;
} }
static struct xt_target ebt_dnat_tg_reg __read_mostly = { static struct xt_target ebt_dnat_tg_reg __read_mostly = {
......
...@@ -29,11 +29,11 @@ static int ebt_log_tg_check(const struct xt_tgchk_param *par) ...@@ -29,11 +29,11 @@ static int ebt_log_tg_check(const struct xt_tgchk_param *par)
struct ebt_log_info *info = par->targinfo; struct ebt_log_info *info = par->targinfo;
if (info->bitmask & ~EBT_LOG_MASK) if (info->bitmask & ~EBT_LOG_MASK)
return false; return -EINVAL;
if (info->loglevel >= 8) if (info->loglevel >= 8)
return false; return -EINVAL;
info->prefix[EBT_LOG_PREFIX_SIZE - 1] = '\0'; info->prefix[EBT_LOG_PREFIX_SIZE - 1] = '\0';
return true; return 0;
} }
struct tcpudphdr struct tcpudphdr
......
...@@ -43,14 +43,14 @@ static int ebt_mark_tg_check(const struct xt_tgchk_param *par) ...@@ -43,14 +43,14 @@ static int ebt_mark_tg_check(const struct xt_tgchk_param *par)
tmp = info->target | ~EBT_VERDICT_BITS; tmp = info->target | ~EBT_VERDICT_BITS;
if (BASE_CHAIN && tmp == EBT_RETURN) if (BASE_CHAIN && tmp == EBT_RETURN)
return false; return -EINVAL;
if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
return false; return -EINVAL;
tmp = info->target & ~EBT_VERDICT_BITS; tmp = info->target & ~EBT_VERDICT_BITS;
if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE && if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE &&
tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE) tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE)
return false; return -EINVAL;
return true; return 0;
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
struct compat_ebt_mark_t_info { struct compat_ebt_mark_t_info {
......
...@@ -40,9 +40,9 @@ static int ebt_nflog_tg_check(const struct xt_tgchk_param *par) ...@@ -40,9 +40,9 @@ static int ebt_nflog_tg_check(const struct xt_tgchk_param *par)
struct ebt_nflog_info *info = par->targinfo; struct ebt_nflog_info *info = par->targinfo;
if (info->flags & ~EBT_NFLOG_MASK) if (info->flags & ~EBT_NFLOG_MASK)
return false; return -EINVAL;
info->prefix[EBT_NFLOG_PREFIX_SIZE - 1] = '\0'; info->prefix[EBT_NFLOG_PREFIX_SIZE - 1] = '\0';
return true; return 0;
} }
static struct xt_target ebt_nflog_tg_reg __read_mostly = { static struct xt_target ebt_nflog_tg_reg __read_mostly = {
......
...@@ -38,17 +38,17 @@ static int ebt_redirect_tg_check(const struct xt_tgchk_param *par) ...@@ -38,17 +38,17 @@ static int ebt_redirect_tg_check(const struct xt_tgchk_param *par)
unsigned int hook_mask; unsigned int hook_mask;
if (BASE_CHAIN && info->target == EBT_RETURN) if (BASE_CHAIN && info->target == EBT_RETURN)
return false; return -EINVAL;
hook_mask = par->hook_mask & ~(1 << NF_BR_NUMHOOKS); hook_mask = par->hook_mask & ~(1 << NF_BR_NUMHOOKS);
if ((strcmp(par->table, "nat") != 0 || if ((strcmp(par->table, "nat") != 0 ||
hook_mask & ~(1 << NF_BR_PRE_ROUTING)) && hook_mask & ~(1 << NF_BR_PRE_ROUTING)) &&
(strcmp(par->table, "broute") != 0 || (strcmp(par->table, "broute") != 0 ||
hook_mask & ~(1 << NF_BR_BROUTING))) hook_mask & ~(1 << NF_BR_BROUTING)))
return false; return -EINVAL;
if (INVALID_TARGET) if (INVALID_TARGET)
return false; return -EINVAL;
return true; return 0;
} }
static struct xt_target ebt_redirect_tg_reg __read_mostly = { static struct xt_target ebt_redirect_tg_reg __read_mostly = {
......
...@@ -49,14 +49,14 @@ static int ebt_snat_tg_check(const struct xt_tgchk_param *par) ...@@ -49,14 +49,14 @@ static int ebt_snat_tg_check(const struct xt_tgchk_param *par)
tmp = info->target | ~EBT_VERDICT_BITS; tmp = info->target | ~EBT_VERDICT_BITS;
if (BASE_CHAIN && tmp == EBT_RETURN) if (BASE_CHAIN && tmp == EBT_RETURN)
return false; return -EINVAL;
if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
return false; return -EINVAL;
tmp = info->target | EBT_VERDICT_BITS; tmp = info->target | EBT_VERDICT_BITS;
if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT) if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT)
return false; return -EINVAL;
return true; return 0;
} }
static struct xt_target ebt_snat_tg_reg __read_mostly = { static struct xt_target ebt_snat_tg_reg __read_mostly = {
......
...@@ -254,14 +254,14 @@ static int ebt_ulog_tg_check(const struct xt_tgchk_param *par) ...@@ -254,14 +254,14 @@ static int ebt_ulog_tg_check(const struct xt_tgchk_param *par)
struct ebt_ulog_info *uloginfo = par->targinfo; struct ebt_ulog_info *uloginfo = par->targinfo;
if (uloginfo->nlgroup > 31) if (uloginfo->nlgroup > 31)
return false; return -EINVAL;
uloginfo->prefix[EBT_ULOG_PREFIX_LEN - 1] = '\0'; uloginfo->prefix[EBT_ULOG_PREFIX_LEN - 1] = '\0';
if (uloginfo->qthreshold > EBT_ULOG_MAX_QLEN) if (uloginfo->qthreshold > EBT_ULOG_MAX_QLEN)
uloginfo->qthreshold = EBT_ULOG_MAX_QLEN; uloginfo->qthreshold = EBT_ULOG_MAX_QLEN;
return true; return 0;
} }
static struct xt_target ebt_ulog_tg_reg __read_mostly = { static struct xt_target ebt_ulog_tg_reg __read_mostly = {
......
...@@ -358,13 +358,13 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par) ...@@ -358,13 +358,13 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)
cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT && cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT &&
cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) { cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) {
pr_info("unknown mode %u\n", cipinfo->hash_mode); pr_info("unknown mode %u\n", cipinfo->hash_mode);
return false; return -EINVAL;
} }
if (e->ip.dmsk.s_addr != htonl(0xffffffff) || if (e->ip.dmsk.s_addr != htonl(0xffffffff) ||
e->ip.dst.s_addr == 0) { e->ip.dst.s_addr == 0) {
pr_info("Please specify destination IP\n"); pr_info("Please specify destination IP\n");
return false; return -EINVAL;
} }
/* FIXME: further sanity checks */ /* FIXME: further sanity checks */
...@@ -374,20 +374,20 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par) ...@@ -374,20 +374,20 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)
if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) { if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) {
pr_info("no config found for %pI4, need 'new'\n", pr_info("no config found for %pI4, need 'new'\n",
&e->ip.dst.s_addr); &e->ip.dst.s_addr);
return false; return -EINVAL;
} else { } else {
struct net_device *dev; struct net_device *dev;
if (e->ip.iniface[0] == '\0') { if (e->ip.iniface[0] == '\0') {
pr_info("Please specify an interface name\n"); pr_info("Please specify an interface name\n");
return false; return -EINVAL;
} }
dev = dev_get_by_name(&init_net, e->ip.iniface); dev = dev_get_by_name(&init_net, e->ip.iniface);
if (!dev) { if (!dev) {
pr_info("no such interface %s\n", pr_info("no such interface %s\n",
e->ip.iniface); e->ip.iniface);
return false; return -EINVAL;
} }
config = clusterip_config_init(cipinfo, config = clusterip_config_init(cipinfo,
...@@ -395,7 +395,7 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par) ...@@ -395,7 +395,7 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)
if (!config) { if (!config) {
pr_info("cannot allocate config\n"); pr_info("cannot allocate config\n");
dev_put(dev); dev_put(dev);
return false; return -EINVAL;
} }
dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0); dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0);
} }
...@@ -405,10 +405,10 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par) ...@@ -405,10 +405,10 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)
if (nf_ct_l3proto_try_module_get(par->family) < 0) { if (nf_ct_l3proto_try_module_get(par->family) < 0) {
pr_info("cannot load conntrack support for proto=%u\n", pr_info("cannot load conntrack support for proto=%u\n",
par->family); par->family);
return false; return -EINVAL;
} }
return true; return 0;
} }
/* drop reference count of cluster config when rule is deleted */ /* drop reference count of cluster config when rule is deleted */
......
...@@ -100,18 +100,18 @@ static int ecn_tg_check(const struct xt_tgchk_param *par) ...@@ -100,18 +100,18 @@ static int ecn_tg_check(const struct xt_tgchk_param *par)
if (einfo->operation & IPT_ECN_OP_MASK) { if (einfo->operation & IPT_ECN_OP_MASK) {
pr_info("unsupported ECN operation %x\n", einfo->operation); pr_info("unsupported ECN operation %x\n", einfo->operation);
return false; 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); pr_info("new ECT codepoint %x out of mask\n", einfo->ip_ect);
return false; 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("cannot use TCP operations on a non-tcp rule\n");
return false; return -EINVAL;
} }
return true; return 0;
} }
static struct xt_target ecn_tg_reg __read_mostly = { static struct xt_target ecn_tg_reg __read_mostly = {
......
...@@ -445,13 +445,13 @@ static int log_tg_check(const struct xt_tgchk_param *par) ...@@ -445,13 +445,13 @@ static int log_tg_check(const struct xt_tgchk_param *par)
if (loginfo->level >= 8) { if (loginfo->level >= 8) {
pr_debug("level %u >= 8\n", loginfo->level); pr_debug("level %u >= 8\n", loginfo->level);
return false; return -EINVAL;
} }
if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
pr_debug("prefix is not null-terminated\n"); pr_debug("prefix is not null-terminated\n");
return false; return -EINVAL;
} }
return true; return 0;
} }
static struct xt_target log_tg_reg __read_mostly = { static struct xt_target log_tg_reg __read_mostly = {
......
...@@ -34,13 +34,13 @@ static int masquerade_tg_check(const struct xt_tgchk_param *par) ...@@ -34,13 +34,13 @@ static int masquerade_tg_check(const struct xt_tgchk_param *par)
if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
pr_debug("bad MAP_IPS.\n"); pr_debug("bad MAP_IPS.\n");
return false; return -EINVAL;
} }
if (mr->rangesize != 1) { if (mr->rangesize != 1) {
pr_debug("bad rangesize %u\n", mr->rangesize); pr_debug("bad rangesize %u\n", mr->rangesize);
return false; return -EINVAL;
} }
return true; return 0;
} }
static unsigned int static unsigned int
......
...@@ -28,13 +28,13 @@ static int netmap_tg_check(const struct xt_tgchk_param *par) ...@@ -28,13 +28,13 @@ static int netmap_tg_check(const struct xt_tgchk_param *par)
if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) { if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) {
pr_debug("bad MAP_IPS.\n"); pr_debug("bad MAP_IPS.\n");
return false; return -EINVAL;
} }
if (mr->rangesize != 1) { if (mr->rangesize != 1) {
pr_debug("bad rangesize %u.\n", mr->rangesize); pr_debug("bad rangesize %u.\n", mr->rangesize);
return false; return -EINVAL;
} }
return true; return 0;
} }
static unsigned int static unsigned int
......
...@@ -32,13 +32,13 @@ static int redirect_tg_check(const struct xt_tgchk_param *par) ...@@ -32,13 +32,13 @@ static int redirect_tg_check(const struct xt_tgchk_param *par)
if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
pr_debug("bad MAP_IPS.\n"); pr_debug("bad MAP_IPS.\n");
return false; return -EINVAL;
} }
if (mr->rangesize != 1) { if (mr->rangesize != 1) {
pr_debug("bad rangesize %u.\n", mr->rangesize); pr_debug("bad rangesize %u.\n", mr->rangesize);
return false; return -EINVAL;
} }
return true; return 0;
} }
static unsigned int static unsigned int
......
...@@ -181,16 +181,16 @@ static int reject_tg_check(const struct xt_tgchk_param *par) ...@@ -181,16 +181,16 @@ static int reject_tg_check(const struct xt_tgchk_param *par)
if (rejinfo->with == IPT_ICMP_ECHOREPLY) { if (rejinfo->with == IPT_ICMP_ECHOREPLY) {
pr_info("ECHOREPLY no longer supported.\n"); pr_info("ECHOREPLY no longer supported.\n");
return false; 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("TCP_RESET invalid for non-tcp\n");
return false; return -EINVAL;
} }
} }
return true; return 0;
} }
static struct xt_target reject_tg_reg __read_mostly = { static struct xt_target reject_tg_reg __read_mostly = {
......
...@@ -313,14 +313,14 @@ static int ulog_tg_check(const struct xt_tgchk_param *par) ...@@ -313,14 +313,14 @@ static int ulog_tg_check(const struct xt_tgchk_param *par)
if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') { if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') {
pr_debug("prefix not null-terminated\n"); pr_debug("prefix not null-terminated\n");
return false; return -EINVAL;
} }
if (loginfo->qthreshold > ULOG_MAX_QLEN) { if (loginfo->qthreshold > ULOG_MAX_QLEN) {
pr_debug("queue threshold %Zu > MAX_QLEN\n", pr_debug("queue threshold %Zu > MAX_QLEN\n",
loginfo->qthreshold); loginfo->qthreshold);
return false; return -EINVAL;
} }
return true; return 0;
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
......
...@@ -81,9 +81,9 @@ static int ipt_snat_checkentry(const struct xt_tgchk_param *par) ...@@ -81,9 +81,9 @@ static int ipt_snat_checkentry(const struct xt_tgchk_param *par)
/* Must be a valid range */ /* Must be a valid range */
if (mr->rangesize != 1) { if (mr->rangesize != 1) {
pr_info("SNAT: multiple ranges no longer supported\n"); pr_info("SNAT: multiple ranges no longer supported\n");
return false; return -EINVAL;
} }
return true; return 0;
} }
static int ipt_dnat_checkentry(const struct xt_tgchk_param *par) static int ipt_dnat_checkentry(const struct xt_tgchk_param *par)
...@@ -93,9 +93,9 @@ static int ipt_dnat_checkentry(const struct xt_tgchk_param *par) ...@@ -93,9 +93,9 @@ static int ipt_dnat_checkentry(const struct xt_tgchk_param *par)
/* Must be a valid range */ /* Must be a valid range */
if (mr->rangesize != 1) { if (mr->rangesize != 1) {
pr_info("DNAT: multiple ranges no longer supported\n"); pr_info("DNAT: multiple ranges no longer supported\n");
return false; return -EINVAL;
} }
return true; return 0;
} }
unsigned int unsigned int
......
...@@ -457,13 +457,13 @@ static int log_tg6_check(const struct xt_tgchk_param *par) ...@@ -457,13 +457,13 @@ static int log_tg6_check(const struct xt_tgchk_param *par)
if (loginfo->level >= 8) { if (loginfo->level >= 8) {
pr_debug("level %u >= 8\n", loginfo->level); pr_debug("level %u >= 8\n", loginfo->level);
return false; return -EINVAL;
} }
if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
pr_debug("prefix not null-terminated\n"); pr_debug("prefix not null-terminated\n");
return false; return -EINVAL;
} }
return true; return 0;
} }
static struct xt_target log_tg6_reg __read_mostly = { static struct xt_target log_tg6_reg __read_mostly = {
......
...@@ -220,16 +220,16 @@ static int reject_tg6_check(const struct xt_tgchk_param *par) ...@@ -220,16 +220,16 @@ static int reject_tg6_check(const struct xt_tgchk_param *par)
if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) { if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
pr_info("ECHOREPLY is not supported.\n"); pr_info("ECHOREPLY is not supported.\n");
return false; 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.proto != IPPROTO_TCP || if (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("TCP_RESET illegal for non-tcp\n");
return false; return -EINVAL;
} }
} }
return true; return 0;
} }
static struct xt_target reject_tg6_reg __read_mostly = { static struct xt_target reject_tg6_reg __read_mostly = {
......
...@@ -528,6 +528,8 @@ EXPORT_SYMBOL_GPL(xt_compat_match_to_user); ...@@ -528,6 +528,8 @@ EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
int xt_check_target(struct xt_tgchk_param *par, int xt_check_target(struct xt_tgchk_param *par,
unsigned int size, u_int8_t proto, bool inv_proto) unsigned int size, u_int8_t proto, bool inv_proto)
{ {
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("%s_tables: %s.%u target: invalid size "
"%u (kernel) != (user) %u\n", "%u (kernel) != (user) %u\n",
...@@ -559,8 +561,14 @@ int xt_check_target(struct xt_tgchk_param *par, ...@@ -559,8 +561,14 @@ int xt_check_target(struct xt_tgchk_param *par,
par->target->proto); par->target->proto);
return -EINVAL; return -EINVAL;
} }
if (par->target->checkentry != NULL && !par->target->checkentry(par)) if (par->target->checkentry != NULL) {
return -EINVAL; ret = par->target->checkentry(par);
if (ret < 0)
return ret;
else if (ret > 0)
/* Flag up potential errors. */
return -EIO;
}
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(xt_check_target); EXPORT_SYMBOL_GPL(xt_check_target);
......
...@@ -92,7 +92,7 @@ static int connsecmark_tg_check(const struct xt_tgchk_param *par) ...@@ -92,7 +92,7 @@ static int connsecmark_tg_check(const struct xt_tgchk_param *par)
strcmp(par->table, "security") != 0) { strcmp(par->table, "security") != 0) {
pr_info("target only valid in the \'mangle\' " pr_info("target only valid in the \'mangle\' "
"or \'security\' tables, not \'%s\'.\n", par->table); "or \'security\' tables, not \'%s\'.\n", par->table);
return false; return -EINVAL;
} }
switch (info->mode) { switch (info->mode) {
...@@ -108,9 +108,9 @@ static int connsecmark_tg_check(const struct xt_tgchk_param *par) ...@@ -108,9 +108,9 @@ static int connsecmark_tg_check(const struct xt_tgchk_param *par)
if (nf_ct_l3proto_try_module_get(par->family) < 0) { if (nf_ct_l3proto_try_module_get(par->family) < 0) {
pr_info("cannot load conntrack support for proto=%u\n", pr_info("cannot load conntrack support for proto=%u\n",
par->family); par->family);
return false; return -EINVAL;
} }
return true; return 0;
} }
static void connsecmark_tg_destroy(const struct xt_tgdtor_param *par) static void connsecmark_tg_destroy(const struct xt_tgdtor_param *par)
......
...@@ -62,7 +62,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par) ...@@ -62,7 +62,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par)
u8 proto; u8 proto;
if (info->flags & ~XT_CT_NOTRACK) if (info->flags & ~XT_CT_NOTRACK)
return false; return -EINVAL;
if (info->flags & XT_CT_NOTRACK) { if (info->flags & XT_CT_NOTRACK) {
ct = &nf_conntrack_untracked; ct = &nf_conntrack_untracked;
...@@ -108,14 +108,14 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par) ...@@ -108,14 +108,14 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par)
__set_bit(IPS_CONFIRMED_BIT, &ct->status); __set_bit(IPS_CONFIRMED_BIT, &ct->status);
out: out:
info->ct = ct; info->ct = ct;
return true; return 0;
err3: err3:
nf_conntrack_free(ct); nf_conntrack_free(ct);
err2: err2:
nf_ct_l3proto_module_put(par->family); nf_ct_l3proto_module_put(par->family);
err1: err1:
return false; return -EINVAL;
} }
static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par) static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par)
......
...@@ -66,9 +66,9 @@ static int dscp_tg_check(const struct xt_tgchk_param *par) ...@@ -66,9 +66,9 @@ static int dscp_tg_check(const struct xt_tgchk_param *par)
if (info->dscp > XT_DSCP_MAX) { if (info->dscp > XT_DSCP_MAX) {
pr_info("dscp %x out of range\n", info->dscp); pr_info("dscp %x out of range\n", info->dscp);
return false; return -EINVAL;
} }
return true; return 0;
} }
static unsigned int static unsigned int
......
...@@ -110,8 +110,8 @@ static int ttl_tg_check(const struct xt_tgchk_param *par) ...@@ -110,8 +110,8 @@ static int ttl_tg_check(const struct xt_tgchk_param *par)
return false; return false;
} }
if (info->mode != IPT_TTL_SET && info->ttl == 0) if (info->mode != IPT_TTL_SET && info->ttl == 0)
return false; return -EINVAL;
return true; return 0;
} }
static int hl_tg6_check(const struct xt_tgchk_param *par) static int hl_tg6_check(const struct xt_tgchk_param *par)
...@@ -120,14 +120,14 @@ static int hl_tg6_check(const struct xt_tgchk_param *par) ...@@ -120,14 +120,14 @@ static int hl_tg6_check(const struct xt_tgchk_param *par)
if (info->mode > IP6T_HL_MAXMODE) { if (info->mode > IP6T_HL_MAXMODE) {
pr_info("invalid or unknown mode %u\n", info->mode); pr_info("invalid or unknown mode %u\n", info->mode);
return false; 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 " pr_info("increment/decrement does not "
"make sense with value 0\n"); "make sense with value 0\n");
return false; return -EINVAL;
} }
return true; return 0;
} }
static struct xt_target hl_tg_reg[] __read_mostly = { static struct xt_target hl_tg_reg[] __read_mostly = {
......
...@@ -88,12 +88,12 @@ static int led_tg_check(const struct xt_tgchk_param *par) ...@@ -88,12 +88,12 @@ static int led_tg_check(const struct xt_tgchk_param *par)
if (ledinfo->id[0] == '\0') { if (ledinfo->id[0] == '\0') {
pr_info("No 'id' parameter given.\n"); pr_info("No 'id' parameter given.\n");
return false; return -EINVAL;
} }
ledinternal = kzalloc(sizeof(struct xt_led_info_internal), GFP_KERNEL); ledinternal = kzalloc(sizeof(struct xt_led_info_internal), GFP_KERNEL);
if (!ledinternal) if (!ledinternal)
return false; return -EINVAL;
ledinternal->netfilter_led_trigger.name = ledinfo->id; ledinternal->netfilter_led_trigger.name = ledinfo->id;
...@@ -111,13 +111,11 @@ static int led_tg_check(const struct xt_tgchk_param *par) ...@@ -111,13 +111,11 @@ static int led_tg_check(const struct xt_tgchk_param *par)
(unsigned long)ledinfo); (unsigned long)ledinfo);
ledinfo->internal_data = ledinternal; ledinfo->internal_data = ledinternal;
return 0;
return true;
exit_alloc: exit_alloc:
kfree(ledinternal); kfree(ledinternal);
return -EINVAL;
return false;
} }
static void led_tg_destroy(const struct xt_tgdtor_param *par) static void led_tg_destroy(const struct xt_tgdtor_param *par)
......
...@@ -42,10 +42,10 @@ static int nflog_tg_check(const struct xt_tgchk_param *par) ...@@ -42,10 +42,10 @@ static int nflog_tg_check(const struct xt_tgchk_param *par)
const struct xt_nflog_info *info = par->targinfo; const struct xt_nflog_info *info = par->targinfo;
if (info->flags & ~XT_NFLOG_MASK) if (info->flags & ~XT_NFLOG_MASK)
return false; return -EINVAL;
if (info->prefix[sizeof(info->prefix) - 1] != '\0') if (info->prefix[sizeof(info->prefix) - 1] != '\0')
return false; return -EINVAL;
return true; return 0;
} }
static struct xt_target nflog_tg_reg __read_mostly = { static struct xt_target nflog_tg_reg __read_mostly = {
......
...@@ -92,15 +92,15 @@ static int nfqueue_tg_v1_check(const struct xt_tgchk_param *par) ...@@ -92,15 +92,15 @@ static int nfqueue_tg_v1_check(const struct xt_tgchk_param *par)
} }
if (info->queues_total == 0) { if (info->queues_total == 0) {
pr_err("NFQUEUE: number of total queues is 0\n"); pr_err("NFQUEUE: number of total queues is 0\n");
return false; 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_err("NFQUEUE: number of queues (%u) out of range (got %u)\n",
info->queues_total, maxid); info->queues_total, maxid);
return false; return -EINVAL;
} }
return true; return 0;
} }
static struct xt_target nfqueue_tg_reg[] __read_mostly = { static struct xt_target nfqueue_tg_reg[] __read_mostly = {
......
...@@ -109,10 +109,10 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) ...@@ -109,10 +109,10 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
(info->interval != est->params.interval || (info->interval != est->params.interval ||
info->ewma_log != est->params.ewma_log)) { info->ewma_log != est->params.ewma_log)) {
xt_rateest_put(est); xt_rateest_put(est);
return false; return -EINVAL;
} }
info->est = est; info->est = est;
return true; return 0;
} }
est = kzalloc(sizeof(*est), GFP_KERNEL); est = kzalloc(sizeof(*est), GFP_KERNEL);
...@@ -136,13 +136,12 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) ...@@ -136,13 +136,12 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
info->est = est; info->est = est;
xt_rateest_hash_insert(est); xt_rateest_hash_insert(est);
return 0;
return true;
err2: err2:
kfree(est); kfree(est);
err1: err1:
return false; return -EINVAL;
} }
static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par) static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par)
......
...@@ -88,29 +88,29 @@ static int secmark_tg_check(const struct xt_tgchk_param *par) ...@@ -88,29 +88,29 @@ static int secmark_tg_check(const struct xt_tgchk_param *par)
strcmp(par->table, "security") != 0) { strcmp(par->table, "security") != 0) {
pr_info("target only valid in the \'mangle\' " pr_info("target only valid in the \'mangle\' "
"or \'security\' tables, not \'%s\'.\n", par->table); "or \'security\' tables, not \'%s\'.\n", par->table);
return false; return -EINVAL;
} }
if (mode && mode != info->mode) { if (mode && mode != info->mode) {
pr_info("mode already set to %hu cannot mix with " pr_info("mode already set to %hu cannot mix with "
"rules for mode %hu\n", mode, info->mode); "rules for mode %hu\n", mode, info->mode);
return false; return -EINVAL;
} }
switch (info->mode) { switch (info->mode) {
case SECMARK_MODE_SEL: case SECMARK_MODE_SEL:
if (!checkentry_selinux(info)) if (!checkentry_selinux(info))
return false; return -EINVAL;
break; break;
default: default:
pr_info("invalid mode: %hu\n", info->mode); pr_info("invalid mode: %hu\n", info->mode);
return false; return -EINVAL;
} }
if (!mode) if (!mode)
mode = info->mode; mode = info->mode;
return true; return 0;
} }
static void secmark_tg_destroy(const struct xt_tgdtor_param *par) static void secmark_tg_destroy(const struct xt_tgdtor_param *par)
......
...@@ -246,13 +246,13 @@ static int tcpmss_tg4_check(const struct xt_tgchk_param *par) ...@@ -246,13 +246,13 @@ static int tcpmss_tg4_check(const struct xt_tgchk_param *par)
(1 << NF_INET_POST_ROUTING))) != 0) { (1 << NF_INET_POST_ROUTING))) != 0) {
pr_info("path-MTU clamping only supported in " pr_info("path-MTU clamping only supported in "
"FORWARD, OUTPUT and POSTROUTING hooks\n"); "FORWARD, OUTPUT and POSTROUTING hooks\n");
return false; return -EINVAL;
} }
xt_ematch_foreach(ematch, e) xt_ematch_foreach(ematch, e)
if (find_syn_match(ematch)) if (find_syn_match(ematch))
return true; return 0;
pr_info("Only works on TCP SYN packets\n"); pr_info("Only works on TCP SYN packets\n");
return false; return -EINVAL;
} }
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
...@@ -268,13 +268,13 @@ static int tcpmss_tg6_check(const struct xt_tgchk_param *par) ...@@ -268,13 +268,13 @@ static int tcpmss_tg6_check(const struct xt_tgchk_param *par)
(1 << NF_INET_POST_ROUTING))) != 0) { (1 << NF_INET_POST_ROUTING))) != 0) {
pr_info("path-MTU clamping only supported in " pr_info("path-MTU clamping only supported in "
"FORWARD, OUTPUT and POSTROUTING hooks\n"); "FORWARD, OUTPUT and POSTROUTING hooks\n");
return false; return -EINVAL;
} }
xt_ematch_foreach(ematch, e) xt_ematch_foreach(ematch, e)
if (find_syn_match(ematch)) if (find_syn_match(ematch))
return true; return 0;
pr_info("Only works on TCP SYN packets\n"); pr_info("Only works on TCP SYN packets\n");
return false; return -EINVAL;
} }
#endif #endif
......
...@@ -65,11 +65,11 @@ static int tproxy_tg_check(const struct xt_tgchk_param *par) ...@@ -65,11 +65,11 @@ static int tproxy_tg_check(const struct xt_tgchk_param *par)
if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP) if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)
&& !(i->invflags & IPT_INV_PROTO)) && !(i->invflags & IPT_INV_PROTO))
return true; return 0;
pr_info("Can be used only in combination with " pr_info("Can be used only in combination with "
"either -p tcp or -p udp\n"); "either -p tcp or -p udp\n");
return false; return -EINVAL;
} }
static struct xt_target tproxy_tg_reg __read_mostly = { static struct xt_target tproxy_tg_reg __read_mostly = {
......
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