Re: [PATCH 1/6] Core changes for better error reporting to userspace.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Saturday 2009-06-20 23:56, Jozsef Kadlecsik wrote:
>@@ -210,6 +219,9 @@ struct xt_match_param {
>  * @match:	struct xt_match through which this function was invoked
>  * @matchinfo:	per-match data
>  * @hook_mask:	via which hooks the new rule is reachable
>+ * @family:	protocol family
>+ * @proto:	transport protocol
>+ * @inverted:	transport protocol check is inverted

Should preferably be named nfproto and l4proto/thproto to avoid confusion.
Similarly I would sugegst thinv... something as 'inverted' alone seems
generic.

>  */
> struct xt_mtchk_param {
> 	const char *table;

You are adding a number of fields here and there, but they are not
used until later patches. I think that is a bit obscure, and would
have splitted things differently[1], for I now have to go back and
forth and figure out just what extensions actually make use of
the new fields.

[1] (E.g. "make function unsigned", "add proto/inverted and do proto checks
inside matches", and so on) Due to the mass of files it touches,
splitting it between matches/targets or even per-struct instead
of arp/v4/v6 seems like a good idea.

>@@ -217,7 +229,10 @@ struct xt_mtchk_param {
> 	const struct xt_match *match;
> 	void *matchinfo;
> 	unsigned int hook_mask;
>+	u_int16_t proto;
> 	u_int8_t family;
>+	bool inverted;
>+	bool compat_log;

nfproto is a uint8 too.

> };
> 
> /* Match destructor parameters */
>@@ -259,7 +274,10 @@ struct xt_tgchk_param {
> 	const struct xt_target *target;
> 	void *targinfo;
> 	unsigned int hook_mask;
>+	u_int16_t proto;
> 	u_int8_t family;
>+	bool inverted;
>+	bool compat_log;

Same here

>@@ -284,8 +302,9 @@ struct xt_match
> 	bool (*match)(const struct sk_buff *skb,
> 		      const struct xt_match_param *);
> 
>-	/* Called when user tries to insert an entry of this type. */
>-	bool (*checkentry)(const struct xt_mtchk_param *);
>+	/* Called when user tries to insert an entry of this type.
>+	 * Returns zero or a positive errno. */
>+	unsigned int (*checkentry)(const struct xt_mtchk_param *);
> 
> 	/* Called when entry of this type deleted. */
> 	void (*destroy)(const struct xt_mtdtor_param *);

This change will flag up tons of compiler warnings (because only
later patches fix it up), but see note above[1].

>-	ret = xt_check_match(par, m->match_size,
>-	      e->ethproto, e->invflags & EBT_IPROTO);
>-	if (ret < 0) {
>+	par->proto     = e->ethproto;
>+	par->inverted  = e->invflags & EBT_IPROTO;
>+	ret = xt_check_match(par, m->match_size);

This is where things can go wrong, in theory. Above, proto was
said to be the 'transport protocol', but ethproto is actually
the network protocol. Ick :/
Suggestion to use

	/* When nfproto is NFPROTO_BRIDGE, use l3proto, otherwise l4proto. */
	union {
		uint8_t l3proto;
		uint8_t l4proto;
	};

to be a bit futureproof.

>+
>+static int get_replace(struct net *net, void __user *user, int *len)
>+{
	[...]
>+#ifndef ARPT_ENTRY_MATCH_INTRODUCED
>+			ret = -EFAULT;
>+#else

Where was this macro defined?

>index fdefae6..954e90e 100644
>--- a/net/ipv4/netfilter/ip_tables.c
>+++ b/net/ipv4/netfilter/ip_tables.c
>@@ -600,28 +600,30 @@ check_entry(struct ipt_entry *e, const char *name)
> 
> static int
> check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
>-	    unsigned int *i)
>+	    unsigned int *i, unsigned int *error_offset)
> {
> 	const struct ipt_ip *ip = par->entryinfo;
> 	int ret;
> 
> 	par->match     = m->u.kernel.match;
> 	par->matchinfo = m->data;
>+	par->proto     = ip->proto;
>+	par->inverted  = ip->invflags & IPT_INV_PROTO;

I like this one, because it makes it possible to possibly ditch
par->entryinfo from the extensions.

What I don't like with the approach...

>+static unsigned int icmp_checkentry(const struct xt_mtchk_param *par)
> {
>-	const struct ipt_icmp *icmpinfo = par->matchinfo;
>+	struct ipt_icmp *icmpinfo = par->matchinfo;
> 
>+	if (par->proto != IPPROTO_ICMP || par->inverted) {
>+		xt_compat_log(par, "icmp match: only valid for protocol ICMP");
>+		return IPT_ICMP_ERR_PROTO;
>+	}

We had that before, and replace it on
5d04bff096180f032de8b9b12153a8a1b4009b8d by centralized error checking.
Adding the replicated logic into extensions again looks like a step
backwards to me. At least for single-protocol extensions.
My word here: keep the centralized proto, hooks and table
checking and return a generic code if it does not match up.

>--- a/net/netfilter/x_tables.c
>+++ b/net/netfilter/x_tables.c
>@@ -329,34 +329,7 @@ int xt_find_revision(u8 af, const char *name, u8 revision, int target,
> }
> EXPORT_SYMBOL_GPL(xt_find_revision);
> 
>-static char *textify_hooks(char *buf, size_t size, unsigned int mask)
>-{
>-	static const char *const names[] = {
>-		"PREROUTING", "INPUT", "FORWARD",
>-		"OUTPUT", "POSTROUTING", "BROUTING",
>-	};
>-	unsigned int i;
>-	char *p = buf;
>-	bool np = false;
>-	int res;

You cannot remove textif_hooks, because I do not believe that userspace
knows which hooks an extension is usable from to report meaningful
error.

>-	if (par->match->table != NULL &&
>-	    strcmp(par->match->table, par->table) != 0) {
>-		pr_err("%s_tables: %s match: only valid in %s table, not %s\n",
>-		       xt_prefix[par->family], par->match->name,
>-		       par->match->table, par->table);
>-		return -EINVAL;
>-	}
>-	if (par->match->hooks && (par->hook_mask & ~par->match->hooks) != 0) {
>-		char used[64], allow[64];
>-
>-		pr_err("%s_tables: %s match: used from hooks %s, but only "
>-		       "valid from %s\n",
>-		       xt_prefix[par->family], par->match->name,
>-		       textify_hooks(used, sizeof(used), par->hook_mask),
>-		       textify_hooks(allow, sizeof(allow), par->match->hooks));
>-		return -EINVAL;
>-	}
>-	if (par->match->proto && (par->match->proto != proto || inv_proto)) {
>-		pr_err("%s_tables: %s match: only valid for protocol %u\n",
>-		       xt_prefix[par->family], par->match->name,
>-		       par->match->proto);
>-		return -EINVAL;
>-	}
>-	if (par->match->checkentry != NULL && !par->match->checkentry(par))
>-		return -EINVAL;
>+	if (par->match->checkentry != NULL)
>+		return par->match->checkentry(par);
> 	return 0;
> }
> EXPORT_SYMBOL_GPL(xt_check_match);
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux