netfilter: xtables: slightly better error reporting
When extended status codes are available, such as ENOMEM on failed allocations, or subsequent functions (e.g. nf_ct_get_l3proto), passing them up to userspace seems like a good idea compared to just always EINVAL. Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
This commit is contained in:
parent
d6b00a5345
commit
4a5a5c73b7
|
@ -351,8 +351,8 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)
|
||||||
{
|
{
|
||||||
struct ipt_clusterip_tgt_info *cipinfo = par->targinfo;
|
struct ipt_clusterip_tgt_info *cipinfo = par->targinfo;
|
||||||
const struct ipt_entry *e = par->entryinfo;
|
const struct ipt_entry *e = par->entryinfo;
|
||||||
|
|
||||||
struct clusterip_config *config;
|
struct clusterip_config *config;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP &&
|
if (cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP &&
|
||||||
cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT &&
|
cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT &&
|
||||||
|
@ -387,7 +387,7 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)
|
||||||
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 -EINVAL;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
config = clusterip_config_init(cipinfo,
|
config = clusterip_config_init(cipinfo,
|
||||||
|
@ -395,17 +395,18 @@ 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 -EINVAL;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0);
|
dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cipinfo->config = config;
|
cipinfo->config = config;
|
||||||
|
|
||||||
if (nf_ct_l3proto_try_module_get(par->family) < 0) {
|
ret = nf_ct_l3proto_try_module_get(par->family);
|
||||||
|
if (ret < 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 -EINVAL;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -87,6 +87,7 @@ connsecmark_tg(struct sk_buff *skb, const struct xt_target_param *par)
|
||||||
static int connsecmark_tg_check(const struct xt_tgchk_param *par)
|
static int connsecmark_tg_check(const struct xt_tgchk_param *par)
|
||||||
{
|
{
|
||||||
const struct xt_connsecmark_target_info *info = par->targinfo;
|
const struct xt_connsecmark_target_info *info = par->targinfo;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (strcmp(par->table, "mangle") != 0 &&
|
if (strcmp(par->table, "mangle") != 0 &&
|
||||||
strcmp(par->table, "security") != 0) {
|
strcmp(par->table, "security") != 0) {
|
||||||
|
@ -102,13 +103,14 @@ static int connsecmark_tg_check(const struct xt_tgchk_param *par)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
pr_info("invalid mode: %hu\n", info->mode);
|
pr_info("invalid mode: %hu\n", info->mode);
|
||||||
return false;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nf_ct_l3proto_try_module_get(par->family) < 0) {
|
ret = nf_ct_l3proto_try_module_get(par->family);
|
||||||
|
if (ret < 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 -EINVAL;
|
return ret;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par)
|
||||||
struct nf_conntrack_tuple t;
|
struct nf_conntrack_tuple t;
|
||||||
struct nf_conn_help *help;
|
struct nf_conn_help *help;
|
||||||
struct nf_conn *ct;
|
struct nf_conn *ct;
|
||||||
|
int ret = 0;
|
||||||
u8 proto;
|
u8 proto;
|
||||||
|
|
||||||
if (info->flags & ~XT_CT_NOTRACK)
|
if (info->flags & ~XT_CT_NOTRACK)
|
||||||
|
@ -75,28 +76,34 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par)
|
||||||
goto err1;
|
goto err1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (nf_ct_l3proto_try_module_get(par->family) < 0)
|
ret = nf_ct_l3proto_try_module_get(par->family);
|
||||||
|
if (ret < 0)
|
||||||
goto err1;
|
goto err1;
|
||||||
|
|
||||||
memset(&t, 0, sizeof(t));
|
memset(&t, 0, sizeof(t));
|
||||||
ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL);
|
ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL);
|
||||||
|
ret = PTR_ERR(ct);
|
||||||
if (IS_ERR(ct))
|
if (IS_ERR(ct))
|
||||||
goto err2;
|
goto err2;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
if ((info->ct_events || info->exp_events) &&
|
if ((info->ct_events || info->exp_events) &&
|
||||||
!nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
|
!nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
|
||||||
GFP_KERNEL))
|
GFP_KERNEL))
|
||||||
goto err3;
|
goto err3;
|
||||||
|
|
||||||
if (info->helper[0]) {
|
if (info->helper[0]) {
|
||||||
|
ret = -ENOENT;
|
||||||
proto = xt_ct_find_proto(par);
|
proto = xt_ct_find_proto(par);
|
||||||
if (!proto)
|
if (!proto)
|
||||||
goto err3;
|
goto err3;
|
||||||
|
|
||||||
|
ret = -ENOMEM;
|
||||||
help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
|
help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
|
||||||
if (help == NULL)
|
if (help == NULL)
|
||||||
goto err3;
|
goto err3;
|
||||||
|
|
||||||
|
ret = -ENOENT;
|
||||||
help->helper = nf_conntrack_helper_try_module_get(info->helper,
|
help->helper = nf_conntrack_helper_try_module_get(info->helper,
|
||||||
par->family,
|
par->family,
|
||||||
proto);
|
proto);
|
||||||
|
@ -115,7 +122,7 @@ err3:
|
||||||
err2:
|
err2:
|
||||||
nf_ct_l3proto_module_put(par->family);
|
nf_ct_l3proto_module_put(par->family);
|
||||||
err1:
|
err1:
|
||||||
return -EINVAL;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
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,7 +66,7 @@ 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 -EINVAL;
|
return -EDOM;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@ static int ttl_tg_check(const struct xt_tgchk_param *par)
|
||||||
|
|
||||||
if (info->mode > IPT_TTL_MAXMODE) {
|
if (info->mode > IPT_TTL_MAXMODE) {
|
||||||
pr_info("TTL: invalid or unknown mode %u\n", info->mode);
|
pr_info("TTL: invalid or unknown mode %u\n", info->mode);
|
||||||
return false;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (info->mode != IPT_TTL_SET && info->ttl == 0)
|
if (info->mode != IPT_TTL_SET && info->ttl == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -93,7 +93,7 @@ static int led_tg_check(const struct xt_tgchk_param *par)
|
||||||
|
|
||||||
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 -EINVAL;
|
return -ENOMEM;
|
||||||
|
|
||||||
ledinternal->netfilter_led_trigger.name = ledinfo->id;
|
ledinternal->netfilter_led_trigger.name = ledinfo->id;
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ static int led_tg_check(const struct xt_tgchk_param *par)
|
||||||
|
|
||||||
exit_alloc:
|
exit_alloc:
|
||||||
kfree(ledinternal);
|
kfree(ledinternal);
|
||||||
return -EINVAL;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void led_tg_destroy(const struct xt_tgdtor_param *par)
|
static void led_tg_destroy(const struct xt_tgdtor_param *par)
|
||||||
|
|
|
@ -98,7 +98,7 @@ static int nfqueue_tg_v1_check(const struct xt_tgchk_param *par)
|
||||||
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 -EINVAL;
|
return -ERANGE;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,6 +93,7 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
|
||||||
struct nlattr opt;
|
struct nlattr opt;
|
||||||
struct gnet_estimator est;
|
struct gnet_estimator est;
|
||||||
} cfg;
|
} cfg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (unlikely(!rnd_inited)) {
|
if (unlikely(!rnd_inited)) {
|
||||||
get_random_bytes(&jhash_rnd, sizeof(jhash_rnd));
|
get_random_bytes(&jhash_rnd, sizeof(jhash_rnd));
|
||||||
|
@ -115,6 +116,7 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = -ENOMEM;
|
||||||
est = kzalloc(sizeof(*est), GFP_KERNEL);
|
est = kzalloc(sizeof(*est), GFP_KERNEL);
|
||||||
if (!est)
|
if (!est)
|
||||||
goto err1;
|
goto err1;
|
||||||
|
@ -130,8 +132,9 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
|
||||||
cfg.est.interval = info->interval;
|
cfg.est.interval = info->interval;
|
||||||
cfg.est.ewma_log = info->ewma_log;
|
cfg.est.ewma_log = info->ewma_log;
|
||||||
|
|
||||||
if (gen_new_estimator(&est->bstats, &est->rstats, &est->lock,
|
ret = gen_new_estimator(&est->bstats, &est->rstats,
|
||||||
&cfg.opt) < 0)
|
&est->lock, &cfg.opt);
|
||||||
|
if (ret < 0)
|
||||||
goto err2;
|
goto err2;
|
||||||
|
|
||||||
info->est = est;
|
info->est = est;
|
||||||
|
@ -141,7 +144,7 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
|
||||||
err2:
|
err2:
|
||||||
kfree(est);
|
kfree(est);
|
||||||
err1:
|
err1:
|
||||||
return -EINVAL;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par)
|
static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par)
|
||||||
|
|
|
@ -50,7 +50,7 @@ secmark_tg(struct sk_buff *skb, const struct xt_target_param *par)
|
||||||
return XT_CONTINUE;
|
return XT_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool checkentry_selinux(struct xt_secmark_target_info *info)
|
static int checkentry_selinux(struct xt_secmark_target_info *info)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
struct xt_secmark_target_selinux_info *sel = &info->u.sel;
|
struct xt_secmark_target_selinux_info *sel = &info->u.sel;
|
||||||
|
@ -62,27 +62,28 @@ static bool checkentry_selinux(struct xt_secmark_target_info *info)
|
||||||
if (err == -EINVAL)
|
if (err == -EINVAL)
|
||||||
pr_info("invalid SELinux context \'%s\'\n",
|
pr_info("invalid SELinux context \'%s\'\n",
|
||||||
sel->selctx);
|
sel->selctx);
|
||||||
return false;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sel->selsid) {
|
if (!sel->selsid) {
|
||||||
pr_info("unable to map SELinux context \'%s\'\n", sel->selctx);
|
pr_info("unable to map SELinux context \'%s\'\n", sel->selctx);
|
||||||
return false;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = selinux_secmark_relabel_packet_permission(sel->selsid);
|
err = selinux_secmark_relabel_packet_permission(sel->selsid);
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_info("unable to obtain relabeling permission\n");
|
pr_info("unable to obtain relabeling permission\n");
|
||||||
return false;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
selinux_secmark_refcount_inc();
|
selinux_secmark_refcount_inc();
|
||||||
return true;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secmark_tg_check(const struct xt_tgchk_param *par)
|
static int secmark_tg_check(const struct xt_tgchk_param *par)
|
||||||
{
|
{
|
||||||
struct xt_secmark_target_info *info = par->targinfo;
|
struct xt_secmark_target_info *info = par->targinfo;
|
||||||
|
int err;
|
||||||
|
|
||||||
if (strcmp(par->table, "mangle") != 0 &&
|
if (strcmp(par->table, "mangle") != 0 &&
|
||||||
strcmp(par->table, "security") != 0) {
|
strcmp(par->table, "security") != 0) {
|
||||||
|
@ -99,8 +100,9 @@ static int secmark_tg_check(const struct xt_tgchk_param *par)
|
||||||
|
|
||||||
switch (info->mode) {
|
switch (info->mode) {
|
||||||
case SECMARK_MODE_SEL:
|
case SECMARK_MODE_SEL:
|
||||||
if (!checkentry_selinux(info))
|
err = checkentry_selinux(info);
|
||||||
return -EINVAL;
|
if (err <= 0)
|
||||||
|
return err;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -145,7 +145,7 @@ static int xt_cluster_mt_checkentry(const struct xt_mtchk_param *par)
|
||||||
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("this node mask cannot be "
|
||||||
"higher than the total number of nodes\n");
|
"higher than the total number of nodes\n");
|
||||||
return -EINVAL;
|
return -EDOM;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,7 @@ connbytes_mt(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||||
static int connbytes_mt_check(const struct xt_mtchk_param *par)
|
static int connbytes_mt_check(const struct xt_mtchk_param *par)
|
||||||
{
|
{
|
||||||
const struct xt_connbytes_info *sinfo = par->matchinfo;
|
const struct xt_connbytes_info *sinfo = par->matchinfo;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (sinfo->what != XT_CONNBYTES_PKTS &&
|
if (sinfo->what != XT_CONNBYTES_PKTS &&
|
||||||
sinfo->what != XT_CONNBYTES_BYTES &&
|
sinfo->what != XT_CONNBYTES_BYTES &&
|
||||||
|
@ -107,10 +108,11 @@ static int connbytes_mt_check(const struct xt_mtchk_param *par)
|
||||||
sinfo->direction != XT_CONNBYTES_DIR_BOTH)
|
sinfo->direction != XT_CONNBYTES_DIR_BOTH)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (nf_ct_l3proto_try_module_get(par->family) < 0) {
|
ret = nf_ct_l3proto_try_module_get(par->family);
|
||||||
|
if (ret < 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 -EINVAL;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -220,22 +220,24 @@ static int connlimit_mt_check(const struct xt_mtchk_param *par)
|
||||||
{
|
{
|
||||||
struct xt_connlimit_info *info = par->matchinfo;
|
struct xt_connlimit_info *info = par->matchinfo;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (unlikely(!connlimit_rnd_inited)) {
|
if (unlikely(!connlimit_rnd_inited)) {
|
||||||
get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd));
|
get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd));
|
||||||
connlimit_rnd_inited = true;
|
connlimit_rnd_inited = true;
|
||||||
}
|
}
|
||||||
if (nf_ct_l3proto_try_module_get(par->family) < 0) {
|
ret = nf_ct_l3proto_try_module_get(par->family);
|
||||||
|
if (ret < 0) {
|
||||||
pr_info("cannot load conntrack support for "
|
pr_info("cannot load conntrack support for "
|
||||||
"address family %u\n", par->family);
|
"address family %u\n", par->family);
|
||||||
return -EINVAL;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* init private data */
|
/* init private data */
|
||||||
info->data = kmalloc(sizeof(struct xt_connlimit_data), GFP_KERNEL);
|
info->data = kmalloc(sizeof(struct xt_connlimit_data), GFP_KERNEL);
|
||||||
if (info->data == NULL) {
|
if (info->data == NULL) {
|
||||||
nf_ct_l3proto_module_put(par->family);
|
nf_ct_l3proto_module_put(par->family);
|
||||||
return -EINVAL;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_init(&info->data->lock);
|
spin_lock_init(&info->data->lock);
|
||||||
|
|
|
@ -76,10 +76,13 @@ connmark_tg(struct sk_buff *skb, const struct xt_target_param *par)
|
||||||
|
|
||||||
static int connmark_tg_check(const struct xt_tgchk_param *par)
|
static int connmark_tg_check(const struct xt_tgchk_param *par)
|
||||||
{
|
{
|
||||||
if (nf_ct_l3proto_try_module_get(par->family) < 0) {
|
int ret;
|
||||||
|
|
||||||
|
ret = nf_ct_l3proto_try_module_get(par->family);
|
||||||
|
if (ret < 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 -EINVAL;
|
return ret;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -105,10 +108,13 @@ connmark_mt(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||||
|
|
||||||
static int connmark_mt_check(const struct xt_mtchk_param *par)
|
static int connmark_mt_check(const struct xt_mtchk_param *par)
|
||||||
{
|
{
|
||||||
if (nf_ct_l3proto_try_module_get(par->family) < 0) {
|
int ret;
|
||||||
|
|
||||||
|
ret = nf_ct_l3proto_try_module_get(par->family);
|
||||||
|
if (ret < 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 -EINVAL;
|
return ret;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,10 +208,13 @@ conntrack_mt_v2(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||||
|
|
||||||
static int conntrack_mt_check(const struct xt_mtchk_param *par)
|
static int conntrack_mt_check(const struct xt_mtchk_param *par)
|
||||||
{
|
{
|
||||||
if (nf_ct_l3proto_try_module_get(par->family) < 0) {
|
int ret;
|
||||||
|
|
||||||
|
ret = nf_ct_l3proto_try_module_get(par->family);
|
||||||
|
if (ret < 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 -EINVAL;
|
return ret;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ static int dscp_mt_check(const struct xt_mtchk_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 -EINVAL;
|
return -EDOM;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -214,7 +214,7 @@ static int htable_create_v0(struct net *net, struct xt_hashlimit_info *minfo, u_
|
||||||
hinfo = vmalloc(sizeof(struct xt_hashlimit_htable) +
|
hinfo = vmalloc(sizeof(struct xt_hashlimit_htable) +
|
||||||
sizeof(struct list_head) * size);
|
sizeof(struct list_head) * size);
|
||||||
if (!hinfo)
|
if (!hinfo)
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
minfo->hinfo = hinfo;
|
minfo->hinfo = hinfo;
|
||||||
|
|
||||||
/* copy match config into hashtable config */
|
/* copy match config into hashtable config */
|
||||||
|
@ -250,7 +250,7 @@ static int htable_create_v0(struct net *net, struct xt_hashlimit_info *minfo, u_
|
||||||
&dl_file_ops, hinfo);
|
&dl_file_ops, hinfo);
|
||||||
if (!hinfo->pde) {
|
if (!hinfo->pde) {
|
||||||
vfree(hinfo);
|
vfree(hinfo);
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
hinfo->net = net;
|
hinfo->net = net;
|
||||||
|
|
||||||
|
@ -285,7 +285,7 @@ static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo,
|
||||||
hinfo = vmalloc(sizeof(struct xt_hashlimit_htable) +
|
hinfo = vmalloc(sizeof(struct xt_hashlimit_htable) +
|
||||||
sizeof(struct list_head) * size);
|
sizeof(struct list_head) * size);
|
||||||
if (hinfo == NULL)
|
if (hinfo == NULL)
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
minfo->hinfo = hinfo;
|
minfo->hinfo = hinfo;
|
||||||
|
|
||||||
/* copy match config into hashtable config */
|
/* copy match config into hashtable config */
|
||||||
|
@ -311,7 +311,7 @@ static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo,
|
||||||
&dl_file_ops, hinfo);
|
&dl_file_ops, hinfo);
|
||||||
if (hinfo->pde == NULL) {
|
if (hinfo->pde == NULL) {
|
||||||
vfree(hinfo);
|
vfree(hinfo);
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
hinfo->net = net;
|
hinfo->net = net;
|
||||||
|
|
||||||
|
@ -675,13 +675,14 @@ static int hashlimit_mt_check_v0(const struct xt_mtchk_param *par)
|
||||||
{
|
{
|
||||||
struct net *net = par->net;
|
struct net *net = par->net;
|
||||||
struct xt_hashlimit_info *r = par->matchinfo;
|
struct xt_hashlimit_info *r = par->matchinfo;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* Check for overflow. */
|
/* Check for overflow. */
|
||||||
if (r->cfg.burst == 0 ||
|
if (r->cfg.burst == 0 ||
|
||||||
user2credits(r->cfg.avg * r->cfg.burst) < user2credits(r->cfg.avg)) {
|
user2credits(r->cfg.avg * r->cfg.burst) < user2credits(r->cfg.avg)) {
|
||||||
pr_info("overflow, try lower: %u/%u\n",
|
pr_info("overflow, try lower: %u/%u\n",
|
||||||
r->cfg.avg, r->cfg.burst);
|
r->cfg.avg, r->cfg.burst);
|
||||||
return -EINVAL;
|
return -ERANGE;
|
||||||
}
|
}
|
||||||
if (r->cfg.mode == 0 ||
|
if (r->cfg.mode == 0 ||
|
||||||
r->cfg.mode > (XT_HASHLIMIT_HASH_DPT |
|
r->cfg.mode > (XT_HASHLIMIT_HASH_DPT |
|
||||||
|
@ -698,9 +699,12 @@ static int hashlimit_mt_check_v0(const struct xt_mtchk_param *par)
|
||||||
|
|
||||||
mutex_lock(&hashlimit_mutex);
|
mutex_lock(&hashlimit_mutex);
|
||||||
r->hinfo = htable_find_get(net, r->name, par->family);
|
r->hinfo = htable_find_get(net, r->name, par->family);
|
||||||
if (!r->hinfo && htable_create_v0(net, r, par->family) != 0) {
|
if (r->hinfo == NULL) {
|
||||||
|
ret = htable_create_v0(net, r, par->family);
|
||||||
|
if (ret < 0) {
|
||||||
mutex_unlock(&hashlimit_mutex);
|
mutex_unlock(&hashlimit_mutex);
|
||||||
return -EINVAL;
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&hashlimit_mutex);
|
mutex_unlock(&hashlimit_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -710,6 +714,7 @@ static int hashlimit_mt_check(const struct xt_mtchk_param *par)
|
||||||
{
|
{
|
||||||
struct net *net = par->net;
|
struct net *net = par->net;
|
||||||
struct xt_hashlimit_mtinfo1 *info = par->matchinfo;
|
struct xt_hashlimit_mtinfo1 *info = par->matchinfo;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* Check for overflow. */
|
/* Check for overflow. */
|
||||||
if (info->cfg.burst == 0 ||
|
if (info->cfg.burst == 0 ||
|
||||||
|
@ -717,7 +722,7 @@ static int hashlimit_mt_check(const struct xt_mtchk_param *par)
|
||||||
user2credits(info->cfg.avg)) {
|
user2credits(info->cfg.avg)) {
|
||||||
pr_info("overflow, try lower: %u/%u\n",
|
pr_info("overflow, try lower: %u/%u\n",
|
||||||
info->cfg.avg, info->cfg.burst);
|
info->cfg.avg, info->cfg.burst);
|
||||||
return -EINVAL;
|
return -ERANGE;
|
||||||
}
|
}
|
||||||
if (info->cfg.gc_interval == 0 || info->cfg.expire == 0)
|
if (info->cfg.gc_interval == 0 || info->cfg.expire == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -733,9 +738,12 @@ static int hashlimit_mt_check(const struct xt_mtchk_param *par)
|
||||||
|
|
||||||
mutex_lock(&hashlimit_mutex);
|
mutex_lock(&hashlimit_mutex);
|
||||||
info->hinfo = htable_find_get(net, info->name, par->family);
|
info->hinfo = htable_find_get(net, info->name, par->family);
|
||||||
if (!info->hinfo && htable_create(net, info, par->family) != 0) {
|
if (info->hinfo == NULL) {
|
||||||
|
ret = htable_create(net, info, par->family);
|
||||||
|
if (ret < 0) {
|
||||||
mutex_unlock(&hashlimit_mutex);
|
mutex_unlock(&hashlimit_mutex);
|
||||||
return -EINVAL;
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&hashlimit_mutex);
|
mutex_unlock(&hashlimit_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -57,11 +57,13 @@ helper_mt(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||||
static int helper_mt_check(const struct xt_mtchk_param *par)
|
static int helper_mt_check(const struct xt_mtchk_param *par)
|
||||||
{
|
{
|
||||||
struct xt_helper_info *info = par->matchinfo;
|
struct xt_helper_info *info = par->matchinfo;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (nf_ct_l3proto_try_module_get(par->family) < 0) {
|
ret = nf_ct_l3proto_try_module_get(par->family);
|
||||||
|
if (ret < 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 -EINVAL;
|
return ret;
|
||||||
}
|
}
|
||||||
info->name[29] = '\0';
|
info->name[29] = '\0';
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -107,12 +107,12 @@ static int limit_mt_check(const struct xt_mtchk_param *par)
|
||||||
|| 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("Overflow, try lower: %u/%u\n",
|
||||||
r->avg, r->burst);
|
r->avg, r->burst);
|
||||||
return -EINVAL;
|
return -ERANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv = kmalloc(sizeof(*priv), GFP_KERNEL);
|
priv = kmalloc(sizeof(*priv), GFP_KERNEL);
|
||||||
if (priv == NULL)
|
if (priv == NULL)
|
||||||
return -EINVAL;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* For SMP, we only want to use one set of state. */
|
/* For SMP, we only want to use one set of state. */
|
||||||
r->master = priv;
|
r->master = priv;
|
||||||
|
|
|
@ -52,7 +52,7 @@ static int quota_mt_check(const struct xt_mtchk_param *par)
|
||||||
|
|
||||||
q->master = kmalloc(sizeof(*q->master), GFP_KERNEL);
|
q->master = kmalloc(sizeof(*q->master), GFP_KERNEL);
|
||||||
if (q->master == NULL)
|
if (q->master == NULL)
|
||||||
return -EINVAL;
|
return -ENOMEM;
|
||||||
|
|
||||||
q->master->quota = q->quota;
|
q->master->quota = q->quota;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -78,6 +78,7 @@ static int xt_rateest_mt_checkentry(const struct xt_mtchk_param *par)
|
||||||
{
|
{
|
||||||
struct xt_rateest_match_info *info = par->matchinfo;
|
struct xt_rateest_match_info *info = par->matchinfo;
|
||||||
struct xt_rateest *est1, *est2;
|
struct xt_rateest *est1, *est2;
|
||||||
|
int ret = false;
|
||||||
|
|
||||||
if (hweight32(info->flags & (XT_RATEEST_MATCH_ABS |
|
if (hweight32(info->flags & (XT_RATEEST_MATCH_ABS |
|
||||||
XT_RATEEST_MATCH_REL)) != 1)
|
XT_RATEEST_MATCH_REL)) != 1)
|
||||||
|
@ -95,6 +96,7 @@ static int xt_rateest_mt_checkentry(const struct xt_mtchk_param *par)
|
||||||
goto err1;
|
goto err1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = -ENOENT;
|
||||||
est1 = xt_rateest_lookup(info->name1);
|
est1 = xt_rateest_lookup(info->name1);
|
||||||
if (!est1)
|
if (!est1)
|
||||||
goto err1;
|
goto err1;
|
||||||
|
|
|
@ -355,8 +355,10 @@ static int recent_mt_check(const struct xt_mtchk_param *par)
|
||||||
|
|
||||||
t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size,
|
t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (t == NULL)
|
if (t == NULL) {
|
||||||
|
ret = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
t->refcnt = 1;
|
t->refcnt = 1;
|
||||||
strcpy(t->name, info->name);
|
strcpy(t->name, info->name);
|
||||||
INIT_LIST_HEAD(&t->lru_list);
|
INIT_LIST_HEAD(&t->lru_list);
|
||||||
|
@ -367,6 +369,7 @@ static int recent_mt_check(const struct xt_mtchk_param *par)
|
||||||
&recent_mt_fops, t);
|
&recent_mt_fops, t);
|
||||||
if (pde == NULL) {
|
if (pde == NULL) {
|
||||||
kfree(t);
|
kfree(t);
|
||||||
|
ret = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
pde->uid = ip_list_uid;
|
pde->uid = ip_list_uid;
|
||||||
|
|
|
@ -39,10 +39,13 @@ state_mt(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||||
|
|
||||||
static int state_mt_check(const struct xt_mtchk_param *par)
|
static int state_mt_check(const struct xt_mtchk_param *par)
|
||||||
{
|
{
|
||||||
if (nf_ct_l3proto_try_module_get(par->family) < 0) {
|
int ret;
|
||||||
|
|
||||||
|
ret = nf_ct_l3proto_try_module_get(par->family);
|
||||||
|
if (ret < 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 -EINVAL;
|
return ret;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ static int statistic_mt_check(const struct xt_mtchk_param *par)
|
||||||
|
|
||||||
info->master = kzalloc(sizeof(*info->master), GFP_KERNEL);
|
info->master = kzalloc(sizeof(*info->master), GFP_KERNEL);
|
||||||
if (info->master == NULL)
|
if (info->master == NULL)
|
||||||
return -EINVAL;
|
return -ENOMEM;
|
||||||
info->master->count = info->u.nth.count;
|
info->master->count = info->u.nth.count;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -63,7 +63,7 @@ static int string_mt_check(const struct xt_mtchk_param *par)
|
||||||
ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen,
|
ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen,
|
||||||
GFP_KERNEL, flags);
|
GFP_KERNEL, flags);
|
||||||
if (IS_ERR(ts_conf))
|
if (IS_ERR(ts_conf))
|
||||||
return -EINVAL;
|
return PTR_ERR(ts_conf);
|
||||||
|
|
||||||
conf->config = ts_conf;
|
conf->config = ts_conf;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -225,7 +225,7 @@ static int time_mt_check(const struct xt_mtchk_param *par)
|
||||||
info->daytime_stop > XT_TIME_MAX_DAYTIME) {
|
info->daytime_stop > XT_TIME_MAX_DAYTIME) {
|
||||||
pr_info("invalid argument - start or "
|
pr_info("invalid argument - start or "
|
||||||
"stop time greater than 23:59:59\n");
|
"stop time greater than 23:59:59\n");
|
||||||
return -EINVAL;
|
return -EDOM;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue