Skip to content

Commit

Permalink
netfilter: xtables: slightly better error reporting
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jan Engelhardt committed Mar 25, 2010
1 parent d6b00a5 commit 4a5a5c7
Show file tree
Hide file tree
Showing 25 changed files with 107 additions and 61 deletions.
11 changes: 6 additions & 5 deletions net/ipv4/netfilter/ipt_CLUSTERIP.c
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,8 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)
{
struct ipt_clusterip_tgt_info *cipinfo = par->targinfo;
const struct ipt_entry *e = par->entryinfo;

struct clusterip_config *config;
int ret;

if (cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP &&
cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT &&
Expand Down Expand Up @@ -387,25 +387,26 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)
if (!dev) {
pr_info("no such interface %s\n",
e->ip.iniface);
return -EINVAL;
return -ENOENT;
}

config = clusterip_config_init(cipinfo,
e->ip.dst.s_addr, dev);
if (!config) {
pr_info("cannot allocate config\n");
dev_put(dev);
return -EINVAL;
return -ENOMEM;
}
dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0);
}
}
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",
par->family);
return -EINVAL;
return ret;
}

return 0;
Expand Down
8 changes: 5 additions & 3 deletions net/netfilter/xt_CONNSECMARK.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
const struct xt_connsecmark_target_info *info = par->targinfo;
int ret;

if (strcmp(par->table, "mangle") != 0 &&
strcmp(par->table, "security") != 0) {
Expand All @@ -102,13 +103,14 @@ static int connsecmark_tg_check(const struct xt_tgchk_param *par)

default:
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",
par->family);
return -EINVAL;
return ret;
}
return 0;
}
Expand Down
11 changes: 9 additions & 2 deletions net/netfilter/xt_CT.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par)
struct nf_conntrack_tuple t;
struct nf_conn_help *help;
struct nf_conn *ct;
int ret = 0;
u8 proto;

if (info->flags & ~XT_CT_NOTRACK)
Expand All @@ -75,28 +76,34 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par)
goto err1;
#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;

memset(&t, 0, sizeof(t));
ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL);
ret = PTR_ERR(ct);
if (IS_ERR(ct))
goto err2;

ret = 0;
if ((info->ct_events || info->exp_events) &&
!nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
GFP_KERNEL))
goto err3;

if (info->helper[0]) {
ret = -ENOENT;
proto = xt_ct_find_proto(par);
if (!proto)
goto err3;

ret = -ENOMEM;
help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
if (help == NULL)
goto err3;

ret = -ENOENT;
help->helper = nf_conntrack_helper_try_module_get(info->helper,
par->family,
proto);
Expand All @@ -115,7 +122,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par)
err2:
nf_ct_l3proto_module_put(par->family);
err1:
return -EINVAL;
return ret;
}

static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par)
Expand Down
2 changes: 1 addition & 1 deletion net/netfilter/xt_DSCP.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ static int dscp_tg_check(const struct xt_tgchk_param *par)

if (info->dscp > XT_DSCP_MAX) {
pr_info("dscp %x out of range\n", info->dscp);
return -EINVAL;
return -EDOM;
}
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion net/netfilter/xt_HL.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ static int ttl_tg_check(const struct xt_tgchk_param *par)

if (info->mode > IPT_TTL_MAXMODE) {
pr_info("TTL: invalid or unknown mode %u\n", info->mode);
return false;
return -EINVAL;
}
if (info->mode != IPT_TTL_SET && info->ttl == 0)
return -EINVAL;
Expand Down
4 changes: 2 additions & 2 deletions net/netfilter/xt_LED.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
if (!ledinternal)
return -EINVAL;
return -ENOMEM;

ledinternal->netfilter_led_trigger.name = ledinfo->id;

Expand All @@ -115,7 +115,7 @@ static int led_tg_check(const struct xt_tgchk_param *par)

exit_alloc:
kfree(ledinternal);
return -EINVAL;
return err;
}

static void led_tg_destroy(const struct xt_tgdtor_param *par)
Expand Down
2 changes: 1 addition & 1 deletion net/netfilter/xt_NFQUEUE.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ static int nfqueue_tg_v1_check(const struct xt_tgchk_param *par)
if (maxid > 0xffff) {
pr_err("NFQUEUE: number of queues (%u) out of range (got %u)\n",
info->queues_total, maxid);
return -EINVAL;
return -ERANGE;
}
return 0;
}
Expand Down
9 changes: 6 additions & 3 deletions net/netfilter/xt_RATEEST.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
struct nlattr opt;
struct gnet_estimator est;
} cfg;
int ret;

if (unlikely(!rnd_inited)) {
get_random_bytes(&jhash_rnd, sizeof(jhash_rnd));
Expand All @@ -115,6 +116,7 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
return 0;
}

ret = -ENOMEM;
est = kzalloc(sizeof(*est), GFP_KERNEL);
if (!est)
goto err1;
Expand All @@ -130,8 +132,9 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
cfg.est.interval = info->interval;
cfg.est.ewma_log = info->ewma_log;

if (gen_new_estimator(&est->bstats, &est->rstats, &est->lock,
&cfg.opt) < 0)
ret = gen_new_estimator(&est->bstats, &est->rstats,
&est->lock, &cfg.opt);
if (ret < 0)
goto err2;

info->est = est;
Expand All @@ -141,7 +144,7 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
err2:
kfree(est);
err1:
return -EINVAL;
return ret;
}

static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par)
Expand Down
16 changes: 9 additions & 7 deletions net/netfilter/xt_SECMARK.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ secmark_tg(struct sk_buff *skb, const struct xt_target_param *par)
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;
struct xt_secmark_target_selinux_info *sel = &info->u.sel;
Expand All @@ -62,27 +62,28 @@ static bool checkentry_selinux(struct xt_secmark_target_info *info)
if (err == -EINVAL)
pr_info("invalid SELinux context \'%s\'\n",
sel->selctx);
return false;
return err;
}

if (!sel->selsid) {
pr_info("unable to map SELinux context \'%s\'\n", sel->selctx);
return false;
return -ENOENT;
}

err = selinux_secmark_relabel_packet_permission(sel->selsid);
if (err) {
pr_info("unable to obtain relabeling permission\n");
return false;
return err;
}

selinux_secmark_refcount_inc();
return true;
return 0;
}

static int secmark_tg_check(const struct xt_tgchk_param *par)
{
struct xt_secmark_target_info *info = par->targinfo;
int err;

if (strcmp(par->table, "mangle") != 0 &&
strcmp(par->table, "security") != 0) {
Expand All @@ -99,8 +100,9 @@ static int secmark_tg_check(const struct xt_tgchk_param *par)

switch (info->mode) {
case SECMARK_MODE_SEL:
if (!checkentry_selinux(info))
return -EINVAL;
err = checkentry_selinux(info);
if (err <= 0)
return err;
break;

default:
Expand Down
2 changes: 1 addition & 1 deletion net/netfilter/xt_cluster.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ static int xt_cluster_mt_checkentry(const struct xt_mtchk_param *par)
if (info->node_mask >= (1ULL << info->total_nodes)) {
pr_info("this node mask cannot be "
"higher than the total number of nodes\n");
return -EINVAL;
return -EDOM;
}
return 0;
}
Expand Down
6 changes: 4 additions & 2 deletions net/netfilter/xt_connbytes.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
const struct xt_connbytes_info *sinfo = par->matchinfo;
int ret;

if (sinfo->what != XT_CONNBYTES_PKTS &&
sinfo->what != XT_CONNBYTES_BYTES &&
Expand All @@ -107,10 +108,11 @@ static int connbytes_mt_check(const struct xt_mtchk_param *par)
sinfo->direction != XT_CONNBYTES_DIR_BOTH)
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",
par->family);
return -EINVAL;
return ret;
}

return 0;
Expand Down
8 changes: 5 additions & 3 deletions net/netfilter/xt_connlimit.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,22 +220,24 @@ static int connlimit_mt_check(const struct xt_mtchk_param *par)
{
struct xt_connlimit_info *info = par->matchinfo;
unsigned int i;
int ret;

if (unlikely(!connlimit_rnd_inited)) {
get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd));
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 "
"address family %u\n", par->family);
return -EINVAL;
return ret;
}

/* init private data */
info->data = kmalloc(sizeof(struct xt_connlimit_data), GFP_KERNEL);
if (info->data == NULL) {
nf_ct_l3proto_module_put(par->family);
return -EINVAL;
return -ENOMEM;
}

spin_lock_init(&info->data->lock);
Expand Down
14 changes: 10 additions & 4 deletions net/netfilter/xt_connmark.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
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",
par->family);
return -EINVAL;
return ret;
}
return 0;
}
Expand All @@ -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)
{
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",
par->family);
return -EINVAL;
return ret;
}
return 0;
}
Expand Down
7 changes: 5 additions & 2 deletions net/netfilter/xt_conntrack.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
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",
par->family);
return -EINVAL;
return ret;
}
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion net/netfilter/xt_dscp.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ static int dscp_mt_check(const struct xt_mtchk_param *par)

if (info->dscp > XT_DSCP_MAX) {
pr_info("dscp %x out of range\n", info->dscp);
return -EINVAL;
return -EDOM;
}

return 0;
Expand Down
Loading

0 comments on commit 4a5a5c7

Please sign in to comment.