From: Johannes Berg <johannes-cdvu00un1VgdHxzADdlk8Q@public.gmane.org>
To: Michal Kubecek <mkubecek-AlSwsSmVLrQ@public.gmane.org>
Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH] netlink: add policy attribute range validation
Date: Thu, 27 Sep 2018 10:12:09 +0200 [thread overview]
Message-ID: <1538035929.14416.21.camel@sipsolutions.net> (raw)
In-Reply-To: <20180927071621.GF30601-OEaqT8BN2ewCVLCxKZUutA@public.gmane.org>
On Thu, 2018-09-27 at 09:16 +0200, Michal Kubecek wrote:
> The overloading still feels a bit complicated. Perhaps we could rather
> use validation_data in the natural way, i.e. as a pointer to validation
> data. That would be a struct (maybe array) of two values of the
> corresponding type. It would mean a bit more data and a bit more writing
> but it would be IMHO more straightforward.
I considered that, but I didn't really like it either. The memory
wasting isn't *that* bad (even if we go to s64 that'd only be ~20x16
bytes for nl80211, eating up 320 out of the 550 saved, but still); I'm
more worried about making this really hard to actually *do*.
Consider
policy[] = {
...
[NL80211_ATTR_WIPHY_RETRY_SHORT] =
NLA_POLICY_RANGE(NLA_U8, 1, 255),
...
};
vs.
static const struct netlink_policy_range retry_range = {
.min = 1,
.max = 255,
};
policy[] = {
...
[NL80211_ATTR_WIPHY_RETRY_SHORT] = {
.type = NLA_U8,
.validation_data = &retry_range,
},
...
};
That's significantly more to type, to the point where I'd seriously
consider doing this only for attributes that are used and checked in
many places - it doesn't feel like a big win over manual range-checking.
But I want it to be a win over manual range-checking so it gets used
more because it's more efficient, less prone to getting messed up if
multiple places use the same attribute and validates attributes even if
they're ignored by an operation.
I'd also say that we're certainly no strangers to union/overloading, so
I don't feel like this is a big argument. One doesn't even really have
to be *aware* of it for the most part: if it were a struct instead of a
union, it'd actually have the same effect since the .type field
indicates which part gets used. That it's overloaded in a union is
basically just a space saving measure, I don't think it makes the
reasoning much more complex?
That said, given that I also later sent that RFC patch for a further
validation function pointer (which is useful e.g. for ensuring certain
binary attributes are well-formed), I think it might in fact be better
to split .type field (it really only needs to be u8, we have ~20) and
adding a "validation" enum to the policy:
enum netlink_policy_validation {
/* default */
NLA_VALIDATE_NONE,
/* valid for NLA_{U,S}{8,16,32,64} */
NLA_VALIDATE_MIN,
NLA_VALIDATE_MAX,
NLA_VALIDATE_RANGE,
/* valid for any type other than NLA_BITFIELD32/NLA_REJECT */
NLA_VALIDATE_FUNCTION,
};
Combining that with macros like the ones I wrote in my previous message
in this thread:
#define __NLA_ENSURE(condition) (sizeof(char[1 - 2*!(condition)]) - 1)
#define NLA_ENSURE_INT_TYPE(tp) \
(__NLA_ENSURE(tp == NLA_S8 || tp == NLA_U8 || \
tp == NLA_S16 || tp == NLA_U16 || \
tp == NLA_S32 || tp == NLA_U32 || \
tp == NLA_S64 || tp == NLA_U64) + tp)
#define NLA_ENSURE_NO_VALIDATION_PTR(tp) \
(__NLA_ENSURE(tp != NLA_BITFIELD32 && \
tp != NLA_REJECT && \
tp != NLA_NESTED && \
tp != NLA_NESTED_ARRAY) + tp)
#define NLA_POLICY_RANGE(tp, _min, _max) {
.type = NLA_ENSURE_INT_TYPE(tp),
.validate_type = NLA_VALIDATE_RANGE,
.min = _min,
.max = _max,
}
#define NLA_POLICY_MIN(tp, _min) {
.type = NLA_ENSURE_INT_TYPE(tp),
.validate_type = NLA_VALIDATE_MIN,
.min = _min,
}
#define NLA_POLICY_MAX(tp, _max) {
.type = NLA_ENSURE_INT_TYPE(tp),
.validate_type = NLA_VALIDATE_MAX,
.max = _max,
}
#define NLA_POLICY_FN(tp, fn) {
.type = NLA_ENSURE_NO_VALIDATION_PTR(tp),
.validate_type = NLA_VALIDATE_FUNCTION,
.validate = fn,
}
This would even give us the flexibility to extend the validation type
further in the future, to actually have what you suggested where the
validation_data is a pointer and the valid range is given in a struct
pointed to, to allow larger ranges than s16.
johannes
next prev parent reply other threads:[~2018-09-27 8:12 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-09-26 20:06 [PATCH] netlink: add policy attribute range validation Johannes Berg
2018-09-26 20:07 ` [RFC] nl80211: use policy range validation where applicable Johannes Berg
2018-09-26 20:09 ` Johannes Berg
2018-09-26 20:17 ` [PATCH] netlink: add policy attribute range validation Johannes Berg
[not found] ` <1537993066.28767.29.camel-cdvu00un1VgdHxzADdlk8Q@public.gmane.org>
2018-09-26 20:35 ` Johannes Berg
2018-09-27 7:16 ` Michal Kubecek
[not found] ` <20180927071621.GF30601-OEaqT8BN2ewCVLCxKZUutA@public.gmane.org>
2018-09-27 8:12 ` Johannes Berg [this message]
[not found] ` <1538035929.14416.21.camel-cdvu00un1VgdHxzADdlk8Q@public.gmane.org>
2018-09-27 8:48 ` Michal Kubecek
2018-09-27 8:51 ` Johannes Berg
2018-09-26 20:24 ` Johannes Berg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1538035929.14416.21.camel@sipsolutions.net \
--to=johannes-cdvu00un1vgdhxzaddlk8q@public.gmane.org \
--cc=linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=mkubecek-AlSwsSmVLrQ@public.gmane.org \
--cc=netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).