Commit 396fc59e authored by David S. Miller's avatar David S. Miller

Merge branch 'netlink-allow-NLA_BINARY-length-range-validation'

Johannes Berg says:

====================
netlink: allow NLA_BINARY length range validation

In quite a few places (perhaps particularly in wireless) we need to
validation an NLA_BINARY attribute with both a minimum and a maximum
length. Currently, we can do either of the two, but not both, given
that we have NLA_MIN_LEN (minimum length) and NLA_BINARY (maximum).

Extend the range mechanisms that we use for integer validation to
apply to NLA_BINARY as well.

After converting everything to use NLA_POLICY_MIN_LEN() we can thus
get rid of the NLA_MIN_LEN type since that's now a special case of
NLA_BINARY with a minimum length validation. Similarly, NLA_EXACT_LEN
can be specified using NLA_POLICY_EXACT_LEN() and also maps to the
new NLA_BINARY validation (min == max == desired length).

Finally, NLA_POLICY_EXACT_LEN_WARN() also gets to be a somewhat
special case of this.

I haven't included the patch here now that converts nl82011 to use
this because it doesn't apply without another cleanup patch, but
we can remove a number of hand-coded min/max length checks and get
better error messages from the general validation code while doing
that.

As I had originally built the netlink policy export to userspace in
a way that has min/max length for NLA_BINARY (for the types that we
used to call NLA_MIN_LEN, NLA_BINARY and NLA_EXACT_LEN) anyway, it
doesn't really change anything there except that now there's a chance
that userspace sees min length < max length, which previously wasn't
possible.

v2:
 * fix the min<max comment to correctly say min<=max
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 06a4ec1d 8aa26c57
...@@ -1611,7 +1611,7 @@ static const struct nla_policy macsec_genl_rxsc_policy[NUM_MACSEC_RXSC_ATTR] = { ...@@ -1611,7 +1611,7 @@ static const struct nla_policy macsec_genl_rxsc_policy[NUM_MACSEC_RXSC_ATTR] = {
static const struct nla_policy macsec_genl_sa_policy[NUM_MACSEC_SA_ATTR] = { static const struct nla_policy macsec_genl_sa_policy[NUM_MACSEC_SA_ATTR] = {
[MACSEC_SA_ATTR_AN] = { .type = NLA_U8 }, [MACSEC_SA_ATTR_AN] = { .type = NLA_U8 },
[MACSEC_SA_ATTR_ACTIVE] = { .type = NLA_U8 }, [MACSEC_SA_ATTR_ACTIVE] = { .type = NLA_U8 },
[MACSEC_SA_ATTR_PN] = { .type = NLA_MIN_LEN, .len = 4 }, [MACSEC_SA_ATTR_PN] = NLA_POLICY_MIN_LEN(4),
[MACSEC_SA_ATTR_KEYID] = { .type = NLA_BINARY, [MACSEC_SA_ATTR_KEYID] = { .type = NLA_BINARY,
.len = MACSEC_KEYID_LEN, }, .len = MACSEC_KEYID_LEN, },
[MACSEC_SA_ATTR_KEY] = { .type = NLA_BINARY, [MACSEC_SA_ATTR_KEY] = { .type = NLA_BINARY,
......
...@@ -22,8 +22,8 @@ static struct genl_family genl_family; ...@@ -22,8 +22,8 @@ static struct genl_family genl_family;
static const struct nla_policy device_policy[WGDEVICE_A_MAX + 1] = { static const struct nla_policy device_policy[WGDEVICE_A_MAX + 1] = {
[WGDEVICE_A_IFINDEX] = { .type = NLA_U32 }, [WGDEVICE_A_IFINDEX] = { .type = NLA_U32 },
[WGDEVICE_A_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 }, [WGDEVICE_A_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
[WGDEVICE_A_PRIVATE_KEY] = { .type = NLA_EXACT_LEN, .len = NOISE_PUBLIC_KEY_LEN }, [WGDEVICE_A_PRIVATE_KEY] = NLA_POLICY_EXACT_LEN(NOISE_PUBLIC_KEY_LEN),
[WGDEVICE_A_PUBLIC_KEY] = { .type = NLA_EXACT_LEN, .len = NOISE_PUBLIC_KEY_LEN }, [WGDEVICE_A_PUBLIC_KEY] = NLA_POLICY_EXACT_LEN(NOISE_PUBLIC_KEY_LEN),
[WGDEVICE_A_FLAGS] = { .type = NLA_U32 }, [WGDEVICE_A_FLAGS] = { .type = NLA_U32 },
[WGDEVICE_A_LISTEN_PORT] = { .type = NLA_U16 }, [WGDEVICE_A_LISTEN_PORT] = { .type = NLA_U16 },
[WGDEVICE_A_FWMARK] = { .type = NLA_U32 }, [WGDEVICE_A_FWMARK] = { .type = NLA_U32 },
...@@ -31,12 +31,12 @@ static const struct nla_policy device_policy[WGDEVICE_A_MAX + 1] = { ...@@ -31,12 +31,12 @@ static const struct nla_policy device_policy[WGDEVICE_A_MAX + 1] = {
}; };
static const struct nla_policy peer_policy[WGPEER_A_MAX + 1] = { static const struct nla_policy peer_policy[WGPEER_A_MAX + 1] = {
[WGPEER_A_PUBLIC_KEY] = { .type = NLA_EXACT_LEN, .len = NOISE_PUBLIC_KEY_LEN }, [WGPEER_A_PUBLIC_KEY] = NLA_POLICY_EXACT_LEN(NOISE_PUBLIC_KEY_LEN),
[WGPEER_A_PRESHARED_KEY] = { .type = NLA_EXACT_LEN, .len = NOISE_SYMMETRIC_KEY_LEN }, [WGPEER_A_PRESHARED_KEY] = NLA_POLICY_EXACT_LEN(NOISE_SYMMETRIC_KEY_LEN),
[WGPEER_A_FLAGS] = { .type = NLA_U32 }, [WGPEER_A_FLAGS] = { .type = NLA_U32 },
[WGPEER_A_ENDPOINT] = { .type = NLA_MIN_LEN, .len = sizeof(struct sockaddr) }, [WGPEER_A_ENDPOINT] = NLA_POLICY_MIN_LEN(sizeof(struct sockaddr)),
[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NLA_U16 }, [WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NLA_U16 },
[WGPEER_A_LAST_HANDSHAKE_TIME] = { .type = NLA_EXACT_LEN, .len = sizeof(struct __kernel_timespec) }, [WGPEER_A_LAST_HANDSHAKE_TIME] = NLA_POLICY_EXACT_LEN(sizeof(struct __kernel_timespec)),
[WGPEER_A_RX_BYTES] = { .type = NLA_U64 }, [WGPEER_A_RX_BYTES] = { .type = NLA_U64 },
[WGPEER_A_TX_BYTES] = { .type = NLA_U64 }, [WGPEER_A_TX_BYTES] = { .type = NLA_U64 },
[WGPEER_A_ALLOWEDIPS] = { .type = NLA_NESTED }, [WGPEER_A_ALLOWEDIPS] = { .type = NLA_NESTED },
...@@ -45,7 +45,7 @@ static const struct nla_policy peer_policy[WGPEER_A_MAX + 1] = { ...@@ -45,7 +45,7 @@ static const struct nla_policy peer_policy[WGPEER_A_MAX + 1] = {
static const struct nla_policy allowedip_policy[WGALLOWEDIP_A_MAX + 1] = { static const struct nla_policy allowedip_policy[WGALLOWEDIP_A_MAX + 1] = {
[WGALLOWEDIP_A_FAMILY] = { .type = NLA_U16 }, [WGALLOWEDIP_A_FAMILY] = { .type = NLA_U16 },
[WGALLOWEDIP_A_IPADDR] = { .type = NLA_MIN_LEN, .len = sizeof(struct in_addr) }, [WGALLOWEDIP_A_IPADDR] = NLA_POLICY_MIN_LEN(sizeof(struct in_addr)),
[WGALLOWEDIP_A_CIDR_MASK] = { .type = NLA_U8 } [WGALLOWEDIP_A_CIDR_MASK] = { .type = NLA_U8 }
}; };
......
...@@ -181,8 +181,6 @@ enum { ...@@ -181,8 +181,6 @@ enum {
NLA_S64, NLA_S64,
NLA_BITFIELD32, NLA_BITFIELD32,
NLA_REJECT, NLA_REJECT,
NLA_EXACT_LEN,
NLA_MIN_LEN,
__NLA_TYPE_MAX, __NLA_TYPE_MAX,
}; };
...@@ -199,11 +197,11 @@ struct netlink_range_validation_signed { ...@@ -199,11 +197,11 @@ struct netlink_range_validation_signed {
enum nla_policy_validation { enum nla_policy_validation {
NLA_VALIDATE_NONE, NLA_VALIDATE_NONE,
NLA_VALIDATE_RANGE, NLA_VALIDATE_RANGE,
NLA_VALIDATE_RANGE_WARN_TOO_LONG,
NLA_VALIDATE_MIN, NLA_VALIDATE_MIN,
NLA_VALIDATE_MAX, NLA_VALIDATE_MAX,
NLA_VALIDATE_RANGE_PTR, NLA_VALIDATE_RANGE_PTR,
NLA_VALIDATE_FUNCTION, NLA_VALIDATE_FUNCTION,
NLA_VALIDATE_WARN_TOO_LONG,
}; };
/** /**
...@@ -222,7 +220,7 @@ enum nla_policy_validation { ...@@ -222,7 +220,7 @@ enum nla_policy_validation {
* NLA_NUL_STRING Maximum length of string (excluding NUL) * NLA_NUL_STRING Maximum length of string (excluding NUL)
* NLA_FLAG Unused * NLA_FLAG Unused
* NLA_BINARY Maximum length of attribute payload * NLA_BINARY Maximum length of attribute payload
* NLA_MIN_LEN Minimum length of attribute payload * (but see also below with the validation type)
* NLA_NESTED, * NLA_NESTED,
* NLA_NESTED_ARRAY Length verification is done by checking len of * NLA_NESTED_ARRAY Length verification is done by checking len of
* nested header (or empty); len field is used if * nested header (or empty); len field is used if
...@@ -237,11 +235,6 @@ enum nla_policy_validation { ...@@ -237,11 +235,6 @@ enum nla_policy_validation {
* just like "All other" * just like "All other"
* NLA_BITFIELD32 Unused * NLA_BITFIELD32 Unused
* NLA_REJECT Unused * NLA_REJECT Unused
* NLA_EXACT_LEN Attribute should have exactly this length, otherwise
* it is rejected or warned about, the latter happening
* if and only if the `validation_type' is set to
* NLA_VALIDATE_WARN_TOO_LONG.
* NLA_MIN_LEN Minimum length of attribute payload
* All other Minimum length of attribute payload * All other Minimum length of attribute payload
* *
* Meaning of validation union: * Meaning of validation union:
...@@ -296,6 +289,11 @@ enum nla_policy_validation { ...@@ -296,6 +289,11 @@ enum nla_policy_validation {
* pointer to a struct netlink_range_validation_signed * pointer to a struct netlink_range_validation_signed
* that indicates the min/max values. * that indicates the min/max values.
* Use NLA_POLICY_FULL_RANGE_SIGNED(). * Use NLA_POLICY_FULL_RANGE_SIGNED().
*
* NLA_BINARY If the validation type is like the ones for integers
* above, then the min/max length (not value like for
* integers) of the attribute is enforced.
*
* All other Unused - but note that it's a union * All other Unused - but note that it's a union
* *
* Meaning of `validate' field, use via NLA_POLICY_VALIDATE_FN: * Meaning of `validate' field, use via NLA_POLICY_VALIDATE_FN:
...@@ -309,7 +307,7 @@ enum nla_policy_validation { ...@@ -309,7 +307,7 @@ enum nla_policy_validation {
* static const struct nla_policy my_policy[ATTR_MAX+1] = { * static const struct nla_policy my_policy[ATTR_MAX+1] = {
* [ATTR_FOO] = { .type = NLA_U16 }, * [ATTR_FOO] = { .type = NLA_U16 },
* [ATTR_BAR] = { .type = NLA_STRING, .len = BARSIZ }, * [ATTR_BAR] = { .type = NLA_STRING, .len = BARSIZ },
* [ATTR_BAZ] = { .type = NLA_EXACT_LEN, .len = sizeof(struct mystruct) }, * [ATTR_BAZ] = NLA_POLICY_EXACT_LEN(sizeof(struct mystruct)),
* [ATTR_GOO] = NLA_POLICY_BITFIELD32(myvalidflags), * [ATTR_GOO] = NLA_POLICY_BITFIELD32(myvalidflags),
* }; * };
*/ */
...@@ -335,9 +333,10 @@ struct nla_policy { ...@@ -335,9 +333,10 @@ struct nla_policy {
* nesting validation starts here. * nesting validation starts here.
* *
* Additionally, it means that NLA_UNSPEC is actually NLA_REJECT * Additionally, it means that NLA_UNSPEC is actually NLA_REJECT
* for any types >= this, so need to use NLA_MIN_LEN to get the * for any types >= this, so need to use NLA_POLICY_MIN_LEN() to
* previous pure { .len = xyz } behaviour. The advantage of this * get the previous pure { .len = xyz } behaviour. The advantage
* is that types not specified in the policy will be rejected. * of this is that types not specified in the policy will be
* rejected.
* *
* For completely new families it should be set to 1 so that the * For completely new families it should be set to 1 so that the
* validation is enforced for all attributes. For existing ones * validation is enforced for all attributes. For existing ones
...@@ -349,12 +348,6 @@ struct nla_policy { ...@@ -349,12 +348,6 @@ struct nla_policy {
}; };
}; };
#define NLA_POLICY_EXACT_LEN(_len) { .type = NLA_EXACT_LEN, .len = _len }
#define NLA_POLICY_EXACT_LEN_WARN(_len) \
{ .type = NLA_EXACT_LEN, .len = _len, \
.validation_type = NLA_VALIDATE_WARN_TOO_LONG, }
#define NLA_POLICY_MIN_LEN(_len) { .type = NLA_MIN_LEN, .len = _len }
#define NLA_POLICY_ETH_ADDR NLA_POLICY_EXACT_LEN(ETH_ALEN) #define NLA_POLICY_ETH_ADDR NLA_POLICY_EXACT_LEN(ETH_ALEN)
#define NLA_POLICY_ETH_ADDR_COMPAT NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN) #define NLA_POLICY_ETH_ADDR_COMPAT NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN)
...@@ -370,19 +363,21 @@ struct nla_policy { ...@@ -370,19 +363,21 @@ struct nla_policy {
{ .type = NLA_BITFIELD32, .bitfield32_valid = valid } { .type = NLA_BITFIELD32, .bitfield32_valid = valid }
#define __NLA_ENSURE(condition) BUILD_BUG_ON_ZERO(!(condition)) #define __NLA_ENSURE(condition) BUILD_BUG_ON_ZERO(!(condition))
#define NLA_ENSURE_UINT_TYPE(tp) \ #define NLA_ENSURE_UINT_OR_BINARY_TYPE(tp) \
(__NLA_ENSURE(tp == NLA_U8 || tp == NLA_U16 || \ (__NLA_ENSURE(tp == NLA_U8 || tp == NLA_U16 || \
tp == NLA_U32 || tp == NLA_U64 || \ tp == NLA_U32 || tp == NLA_U64 || \
tp == NLA_MSECS) + tp) tp == NLA_MSECS || \
tp == NLA_BINARY) + tp)
#define NLA_ENSURE_SINT_TYPE(tp) \ #define NLA_ENSURE_SINT_TYPE(tp) \
(__NLA_ENSURE(tp == NLA_S8 || tp == NLA_S16 || \ (__NLA_ENSURE(tp == NLA_S8 || tp == NLA_S16 || \
tp == NLA_S32 || tp == NLA_S64) + tp) tp == NLA_S32 || tp == NLA_S64) + tp)
#define NLA_ENSURE_INT_TYPE(tp) \ #define NLA_ENSURE_INT_OR_BINARY_TYPE(tp) \
(__NLA_ENSURE(tp == NLA_S8 || tp == NLA_U8 || \ (__NLA_ENSURE(tp == NLA_S8 || tp == NLA_U8 || \
tp == NLA_S16 || tp == NLA_U16 || \ tp == NLA_S16 || tp == NLA_U16 || \
tp == NLA_S32 || tp == NLA_U32 || \ tp == NLA_S32 || tp == NLA_U32 || \
tp == NLA_S64 || tp == NLA_U64 || \ tp == NLA_S64 || tp == NLA_U64 || \
tp == NLA_MSECS) + tp) tp == NLA_MSECS || \
tp == NLA_BINARY) + tp)
#define NLA_ENSURE_NO_VALIDATION_PTR(tp) \ #define NLA_ENSURE_NO_VALIDATION_PTR(tp) \
(__NLA_ENSURE(tp != NLA_BITFIELD32 && \ (__NLA_ENSURE(tp != NLA_BITFIELD32 && \
tp != NLA_REJECT && \ tp != NLA_REJECT && \
...@@ -390,14 +385,14 @@ struct nla_policy { ...@@ -390,14 +385,14 @@ struct nla_policy {
tp != NLA_NESTED_ARRAY) + tp) tp != NLA_NESTED_ARRAY) + tp)
#define NLA_POLICY_RANGE(tp, _min, _max) { \ #define NLA_POLICY_RANGE(tp, _min, _max) { \
.type = NLA_ENSURE_INT_TYPE(tp), \ .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \
.validation_type = NLA_VALIDATE_RANGE, \ .validation_type = NLA_VALIDATE_RANGE, \
.min = _min, \ .min = _min, \
.max = _max \ .max = _max \
} }
#define NLA_POLICY_FULL_RANGE(tp, _range) { \ #define NLA_POLICY_FULL_RANGE(tp, _range) { \
.type = NLA_ENSURE_UINT_TYPE(tp), \ .type = NLA_ENSURE_UINT_OR_BINARY_TYPE(tp), \
.validation_type = NLA_VALIDATE_RANGE_PTR, \ .validation_type = NLA_VALIDATE_RANGE_PTR, \
.range = _range, \ .range = _range, \
} }
...@@ -409,13 +404,13 @@ struct nla_policy { ...@@ -409,13 +404,13 @@ struct nla_policy {
} }
#define NLA_POLICY_MIN(tp, _min) { \ #define NLA_POLICY_MIN(tp, _min) { \
.type = NLA_ENSURE_INT_TYPE(tp), \ .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \
.validation_type = NLA_VALIDATE_MIN, \ .validation_type = NLA_VALIDATE_MIN, \
.min = _min, \ .min = _min, \
} }
#define NLA_POLICY_MAX(tp, _max) { \ #define NLA_POLICY_MAX(tp, _max) { \
.type = NLA_ENSURE_INT_TYPE(tp), \ .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \
.validation_type = NLA_VALIDATE_MAX, \ .validation_type = NLA_VALIDATE_MAX, \
.max = _max, \ .max = _max, \
} }
...@@ -427,6 +422,15 @@ struct nla_policy { ...@@ -427,6 +422,15 @@ struct nla_policy {
.len = __VA_ARGS__ + 0, \ .len = __VA_ARGS__ + 0, \
} }
#define NLA_POLICY_EXACT_LEN(_len) NLA_POLICY_RANGE(NLA_BINARY, _len, _len)
#define NLA_POLICY_EXACT_LEN_WARN(_len) { \
.type = NLA_BINARY, \
.validation_type = NLA_VALIDATE_RANGE_WARN_TOO_LONG, \
.min = _len, \
.max = _len \
}
#define NLA_POLICY_MIN_LEN(_len) NLA_POLICY_MIN(NLA_BINARY, _len)
/** /**
* struct nl_info - netlink source information * struct nl_info - netlink source information
* @nlh: Netlink message header of original request * @nlh: Netlink message header of original request
......
...@@ -124,6 +124,7 @@ void nla_get_range_unsigned(const struct nla_policy *pt, ...@@ -124,6 +124,7 @@ void nla_get_range_unsigned(const struct nla_policy *pt,
range->max = U8_MAX; range->max = U8_MAX;
break; break;
case NLA_U16: case NLA_U16:
case NLA_BINARY:
range->max = U16_MAX; range->max = U16_MAX;
break; break;
case NLA_U32: case NLA_U32:
...@@ -140,6 +141,7 @@ void nla_get_range_unsigned(const struct nla_policy *pt, ...@@ -140,6 +141,7 @@ void nla_get_range_unsigned(const struct nla_policy *pt,
switch (pt->validation_type) { switch (pt->validation_type) {
case NLA_VALIDATE_RANGE: case NLA_VALIDATE_RANGE:
case NLA_VALIDATE_RANGE_WARN_TOO_LONG:
range->min = pt->min; range->min = pt->min;
range->max = pt->max; range->max = pt->max;
break; break;
...@@ -157,9 +159,10 @@ void nla_get_range_unsigned(const struct nla_policy *pt, ...@@ -157,9 +159,10 @@ void nla_get_range_unsigned(const struct nla_policy *pt,
} }
} }
static int nla_validate_int_range_unsigned(const struct nla_policy *pt, static int nla_validate_range_unsigned(const struct nla_policy *pt,
const struct nlattr *nla, const struct nlattr *nla,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack,
unsigned int validate)
{ {
struct netlink_range_validation range; struct netlink_range_validation range;
u64 value; u64 value;
...@@ -178,15 +181,39 @@ static int nla_validate_int_range_unsigned(const struct nla_policy *pt, ...@@ -178,15 +181,39 @@ static int nla_validate_int_range_unsigned(const struct nla_policy *pt,
case NLA_MSECS: case NLA_MSECS:
value = nla_get_u64(nla); value = nla_get_u64(nla);
break; break;
case NLA_BINARY:
value = nla_len(nla);
break;
default: default:
return -EINVAL; return -EINVAL;
} }
nla_get_range_unsigned(pt, &range); nla_get_range_unsigned(pt, &range);
if (pt->validation_type == NLA_VALIDATE_RANGE_WARN_TOO_LONG &&
pt->type == NLA_BINARY && value > range.max) {
pr_warn_ratelimited("netlink: '%s': attribute type %d has an invalid length.\n",
current->comm, pt->type);
if (validate & NL_VALIDATE_STRICT_ATTRS) {
NL_SET_ERR_MSG_ATTR(extack, nla,
"invalid attribute length");
return -EINVAL;
}
/* this assumes min <= max (don't validate against min) */
return 0;
}
if (value < range.min || value > range.max) { if (value < range.min || value > range.max) {
NL_SET_ERR_MSG_ATTR(extack, nla, bool binary = pt->type == NLA_BINARY;
"integer out of range");
if (binary)
NL_SET_ERR_MSG_ATTR(extack, nla,
"binary attribute size out of range");
else
NL_SET_ERR_MSG_ATTR(extack, nla,
"integer out of range");
return -ERANGE; return -ERANGE;
} }
...@@ -274,7 +301,8 @@ static int nla_validate_int_range_signed(const struct nla_policy *pt, ...@@ -274,7 +301,8 @@ static int nla_validate_int_range_signed(const struct nla_policy *pt,
static int nla_validate_int_range(const struct nla_policy *pt, static int nla_validate_int_range(const struct nla_policy *pt,
const struct nlattr *nla, const struct nlattr *nla,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack,
unsigned int validate)
{ {
switch (pt->type) { switch (pt->type) {
case NLA_U8: case NLA_U8:
...@@ -282,7 +310,8 @@ static int nla_validate_int_range(const struct nla_policy *pt, ...@@ -282,7 +310,8 @@ static int nla_validate_int_range(const struct nla_policy *pt,
case NLA_U32: case NLA_U32:
case NLA_U64: case NLA_U64:
case NLA_MSECS: case NLA_MSECS:
return nla_validate_int_range_unsigned(pt, nla, extack); case NLA_BINARY:
return nla_validate_range_unsigned(pt, nla, extack, validate);
case NLA_S8: case NLA_S8:
case NLA_S16: case NLA_S16:
case NLA_S32: case NLA_S32:
...@@ -313,10 +342,7 @@ static int validate_nla(const struct nlattr *nla, int maxtype, ...@@ -313,10 +342,7 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
BUG_ON(pt->type > NLA_TYPE_MAX); BUG_ON(pt->type > NLA_TYPE_MAX);
if ((nla_attr_len[pt->type] && attrlen != nla_attr_len[pt->type]) || if (nla_attr_len[pt->type] && attrlen != nla_attr_len[pt->type]) {
(pt->type == NLA_EXACT_LEN &&
pt->validation_type == NLA_VALIDATE_WARN_TOO_LONG &&
attrlen != pt->len)) {
pr_warn_ratelimited("netlink: '%s': attribute type %d has an invalid length.\n", pr_warn_ratelimited("netlink: '%s': attribute type %d has an invalid length.\n",
current->comm, type); current->comm, type);
if (validate & NL_VALIDATE_STRICT_ATTRS) { if (validate & NL_VALIDATE_STRICT_ATTRS) {
...@@ -449,19 +475,10 @@ static int validate_nla(const struct nlattr *nla, int maxtype, ...@@ -449,19 +475,10 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
"Unsupported attribute"); "Unsupported attribute");
return -EINVAL; return -EINVAL;
} }
/* fall through */
case NLA_MIN_LEN:
if (attrlen < pt->len) if (attrlen < pt->len)
goto out_err; goto out_err;
break; break;
case NLA_EXACT_LEN:
if (pt->validation_type != NLA_VALIDATE_WARN_TOO_LONG) {
if (attrlen != pt->len)
goto out_err;
break;
}
/* fall through */
default: default:
if (pt->len) if (pt->len)
minlen = pt->len; minlen = pt->len;
...@@ -479,9 +496,10 @@ static int validate_nla(const struct nlattr *nla, int maxtype, ...@@ -479,9 +496,10 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
break; break;
case NLA_VALIDATE_RANGE_PTR: case NLA_VALIDATE_RANGE_PTR:
case NLA_VALIDATE_RANGE: case NLA_VALIDATE_RANGE:
case NLA_VALIDATE_RANGE_WARN_TOO_LONG:
case NLA_VALIDATE_MIN: case NLA_VALIDATE_MIN:
case NLA_VALIDATE_MAX: case NLA_VALIDATE_MAX:
err = nla_validate_int_range(pt, nla, extack); err = nla_validate_int_range(pt, nla, extack, validate);
if (err) if (err)
return err; return err;
break; break;
......
...@@ -1095,8 +1095,8 @@ static const struct nla_policy br_policy[IFLA_BR_MAX + 1] = { ...@@ -1095,8 +1095,8 @@ static const struct nla_policy br_policy[IFLA_BR_MAX + 1] = {
[IFLA_BR_MCAST_IGMP_VERSION] = { .type = NLA_U8 }, [IFLA_BR_MCAST_IGMP_VERSION] = { .type = NLA_U8 },
[IFLA_BR_MCAST_MLD_VERSION] = { .type = NLA_U8 }, [IFLA_BR_MCAST_MLD_VERSION] = { .type = NLA_U8 },
[IFLA_BR_VLAN_STATS_PER_PORT] = { .type = NLA_U8 }, [IFLA_BR_VLAN_STATS_PER_PORT] = { .type = NLA_U8 },
[IFLA_BR_MULTI_BOOLOPT] = { .type = NLA_EXACT_LEN, [IFLA_BR_MULTI_BOOLOPT] =
.len = sizeof(struct br_boolopt_multi) }, NLA_POLICY_EXACT_LEN(sizeof(struct br_boolopt_multi)),
}; };
static int br_changelink(struct net_device *brdev, struct nlattr *tb[], static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
......
...@@ -1884,8 +1884,8 @@ static int br_vlan_rtm_dump(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1884,8 +1884,8 @@ static int br_vlan_rtm_dump(struct sk_buff *skb, struct netlink_callback *cb)
} }
static const struct nla_policy br_vlan_db_policy[BRIDGE_VLANDB_ENTRY_MAX + 1] = { static const struct nla_policy br_vlan_db_policy[BRIDGE_VLANDB_ENTRY_MAX + 1] = {
[BRIDGE_VLANDB_ENTRY_INFO] = { .type = NLA_EXACT_LEN, [BRIDGE_VLANDB_ENTRY_INFO] =
.len = sizeof(struct bridge_vlan_info) }, NLA_POLICY_EXACT_LEN(sizeof(struct bridge_vlan_info)),
[BRIDGE_VLANDB_ENTRY_RANGE] = { .type = NLA_U16 }, [BRIDGE_VLANDB_ENTRY_RANGE] = { .type = NLA_U16 },
[BRIDGE_VLANDB_ENTRY_STATE] = { .type = NLA_U8 }, [BRIDGE_VLANDB_ENTRY_STATE] = { .type = NLA_U8 },
[BRIDGE_VLANDB_ENTRY_TUNNEL_INFO] = { .type = NLA_NESTED }, [BRIDGE_VLANDB_ENTRY_TUNNEL_INFO] = { .type = NLA_NESTED },
......
...@@ -384,8 +384,8 @@ mptcp_pm_addr_policy[MPTCP_PM_ADDR_ATTR_MAX + 1] = { ...@@ -384,8 +384,8 @@ mptcp_pm_addr_policy[MPTCP_PM_ADDR_ATTR_MAX + 1] = {
[MPTCP_PM_ADDR_ATTR_FAMILY] = { .type = NLA_U16, }, [MPTCP_PM_ADDR_ATTR_FAMILY] = { .type = NLA_U16, },
[MPTCP_PM_ADDR_ATTR_ID] = { .type = NLA_U8, }, [MPTCP_PM_ADDR_ATTR_ID] = { .type = NLA_U8, },
[MPTCP_PM_ADDR_ATTR_ADDR4] = { .type = NLA_U32, }, [MPTCP_PM_ADDR_ATTR_ADDR4] = { .type = NLA_U32, },
[MPTCP_PM_ADDR_ATTR_ADDR6] = { .type = NLA_EXACT_LEN, [MPTCP_PM_ADDR_ATTR_ADDR6] =
.len = sizeof(struct in6_addr), }, NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)),
[MPTCP_PM_ADDR_ATTR_PORT] = { .type = NLA_U16 }, [MPTCP_PM_ADDR_ATTR_PORT] = { .type = NLA_U16 },
[MPTCP_PM_ADDR_ATTR_FLAGS] = { .type = NLA_U32 }, [MPTCP_PM_ADDR_ATTR_FLAGS] = { .type = NLA_U32 },
[MPTCP_PM_ADDR_ATTR_IF_IDX] = { .type = NLA_S32 }, [MPTCP_PM_ADDR_ATTR_IF_IDX] = { .type = NLA_S32 },
......
...@@ -251,12 +251,6 @@ int netlink_policy_dump_write(struct sk_buff *skb, unsigned long _state) ...@@ -251,12 +251,6 @@ int netlink_policy_dump_write(struct sk_buff *skb, unsigned long _state)
pt->bitfield32_valid)) pt->bitfield32_valid))
goto nla_put_failure; goto nla_put_failure;
break; break;
case NLA_EXACT_LEN:
type = NL_ATTR_TYPE_BINARY;
if (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MIN_LENGTH, pt->len) ||
nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MAX_LENGTH, pt->len))
goto nla_put_failure;
break;
case NLA_STRING: case NLA_STRING:
case NLA_NUL_STRING: case NLA_NUL_STRING:
case NLA_BINARY: case NLA_BINARY:
...@@ -266,14 +260,26 @@ int netlink_policy_dump_write(struct sk_buff *skb, unsigned long _state) ...@@ -266,14 +260,26 @@ int netlink_policy_dump_write(struct sk_buff *skb, unsigned long _state)
type = NL_ATTR_TYPE_NUL_STRING; type = NL_ATTR_TYPE_NUL_STRING;
else else
type = NL_ATTR_TYPE_BINARY; type = NL_ATTR_TYPE_BINARY;
if (pt->len && nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MAX_LENGTH,
pt->len)) if (pt->validation_type != NLA_VALIDATE_NONE) {
goto nla_put_failure; struct netlink_range_validation range;
break;
case NLA_MIN_LEN: nla_get_range_unsigned(pt, &range);
type = NL_ATTR_TYPE_BINARY;
if (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MIN_LENGTH, pt->len)) if (range.min &&
nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MIN_LENGTH,
range.min))
goto nla_put_failure;
if (range.max < U16_MAX &&
nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MAX_LENGTH,
range.max))
goto nla_put_failure;
} else if (pt->len &&
nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MAX_LENGTH,
pt->len)) {
goto nla_put_failure; goto nla_put_failure;
}
break; break;
case NLA_FLAG: case NLA_FLAG:
type = NL_ATTR_TYPE_FLAG; type = NL_ATTR_TYPE_FLAG;
......
...@@ -1039,7 +1039,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a, ...@@ -1039,7 +1039,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
static const struct nla_policy ct_policy[TCA_CT_MAX + 1] = { static const struct nla_policy ct_policy[TCA_CT_MAX + 1] = {
[TCA_CT_ACTION] = { .type = NLA_U16 }, [TCA_CT_ACTION] = { .type = NLA_U16 },
[TCA_CT_PARMS] = { .type = NLA_EXACT_LEN, .len = sizeof(struct tc_ct) }, [TCA_CT_PARMS] = NLA_POLICY_EXACT_LEN(sizeof(struct tc_ct)),
[TCA_CT_ZONE] = { .type = NLA_U16 }, [TCA_CT_ZONE] = { .type = NLA_U16 },
[TCA_CT_MARK] = { .type = NLA_U32 }, [TCA_CT_MARK] = { .type = NLA_U32 },
[TCA_CT_MARK_MASK] = { .type = NLA_U32 }, [TCA_CT_MARK_MASK] = { .type = NLA_U32 },
...@@ -1049,10 +1049,8 @@ static const struct nla_policy ct_policy[TCA_CT_MAX + 1] = { ...@@ -1049,10 +1049,8 @@ static const struct nla_policy ct_policy[TCA_CT_MAX + 1] = {
.len = 128 / BITS_PER_BYTE }, .len = 128 / BITS_PER_BYTE },
[TCA_CT_NAT_IPV4_MIN] = { .type = NLA_U32 }, [TCA_CT_NAT_IPV4_MIN] = { .type = NLA_U32 },
[TCA_CT_NAT_IPV4_MAX] = { .type = NLA_U32 }, [TCA_CT_NAT_IPV4_MAX] = { .type = NLA_U32 },
[TCA_CT_NAT_IPV6_MIN] = { .type = NLA_EXACT_LEN, [TCA_CT_NAT_IPV6_MIN] = NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)),
.len = sizeof(struct in6_addr) }, [TCA_CT_NAT_IPV6_MAX] = NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)),
[TCA_CT_NAT_IPV6_MAX] = { .type = NLA_EXACT_LEN,
.len = sizeof(struct in6_addr) },
[TCA_CT_NAT_PORT_MIN] = { .type = NLA_U16 }, [TCA_CT_NAT_PORT_MIN] = { .type = NLA_U16 },
[TCA_CT_NAT_PORT_MAX] = { .type = NLA_U16 }, [TCA_CT_NAT_PORT_MAX] = { .type = NLA_U16 },
}; };
......
...@@ -144,9 +144,8 @@ static int tcf_ctinfo_act(struct sk_buff *skb, const struct tc_action *a, ...@@ -144,9 +144,8 @@ static int tcf_ctinfo_act(struct sk_buff *skb, const struct tc_action *a,
} }
static const struct nla_policy ctinfo_policy[TCA_CTINFO_MAX + 1] = { static const struct nla_policy ctinfo_policy[TCA_CTINFO_MAX + 1] = {
[TCA_CTINFO_ACT] = { .type = NLA_EXACT_LEN, [TCA_CTINFO_ACT] =
.len = sizeof(struct NLA_POLICY_EXACT_LEN(sizeof(struct tc_ctinfo)),
tc_ctinfo) },
[TCA_CTINFO_ZONE] = { .type = NLA_U16 }, [TCA_CTINFO_ZONE] = { .type = NLA_U16 },
[TCA_CTINFO_PARMS_DSCP_MASK] = { .type = NLA_U32 }, [TCA_CTINFO_PARMS_DSCP_MASK] = { .type = NLA_U32 },
[TCA_CTINFO_PARMS_DSCP_STATEMASK] = { .type = NLA_U32 }, [TCA_CTINFO_PARMS_DSCP_STATEMASK] = { .type = NLA_U32 },
......
...@@ -159,8 +159,8 @@ static const struct nla_policy entry_policy[TCA_GATE_ENTRY_MAX + 1] = { ...@@ -159,8 +159,8 @@ static const struct nla_policy entry_policy[TCA_GATE_ENTRY_MAX + 1] = {
}; };
static const struct nla_policy gate_policy[TCA_GATE_MAX + 1] = { static const struct nla_policy gate_policy[TCA_GATE_MAX + 1] = {
[TCA_GATE_PARMS] = { .len = sizeof(struct tc_gate), [TCA_GATE_PARMS] =
.type = NLA_EXACT_LEN }, NLA_POLICY_EXACT_LEN(sizeof(struct tc_gate)),
[TCA_GATE_PRIORITY] = { .type = NLA_S32 }, [TCA_GATE_PRIORITY] = { .type = NLA_S32 },
[TCA_GATE_ENTRY_LIST] = { .type = NLA_NESTED }, [TCA_GATE_ENTRY_LIST] = { .type = NLA_NESTED },
[TCA_GATE_BASE_TIME] = { .type = NLA_U64 }, [TCA_GATE_BASE_TIME] = { .type = NLA_U64 },
......
...@@ -654,10 +654,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { ...@@ -654,10 +654,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_RECEIVE_MULTICAST] = { .type = NLA_FLAG }, [NL80211_ATTR_RECEIVE_MULTICAST] = { .type = NLA_FLAG },
[NL80211_ATTR_WIPHY_FREQ_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999), [NL80211_ATTR_WIPHY_FREQ_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
[NL80211_ATTR_SCAN_FREQ_KHZ] = { .type = NLA_NESTED }, [NL80211_ATTR_SCAN_FREQ_KHZ] = { .type = NLA_NESTED },
[NL80211_ATTR_HE_6GHZ_CAPABILITY] = { [NL80211_ATTR_HE_6GHZ_CAPABILITY] =
.type = NLA_EXACT_LEN, NLA_POLICY_EXACT_LEN(sizeof(struct ieee80211_he_6ghz_capa)),
.len = sizeof(struct ieee80211_he_6ghz_capa),
},
}; };
/* policy for the key attributes */ /* policy for the key attributes */
...@@ -703,7 +701,7 @@ nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = { ...@@ -703,7 +701,7 @@ nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
[NL80211_WOWLAN_TCP_DST_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN), [NL80211_WOWLAN_TCP_DST_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
[NL80211_WOWLAN_TCP_SRC_PORT] = { .type = NLA_U16 }, [NL80211_WOWLAN_TCP_SRC_PORT] = { .type = NLA_U16 },
[NL80211_WOWLAN_TCP_DST_PORT] = { .type = NLA_U16 }, [NL80211_WOWLAN_TCP_DST_PORT] = { .type = NLA_U16 },
[NL80211_WOWLAN_TCP_DATA_PAYLOAD] = { .type = NLA_MIN_LEN, .len = 1 }, [NL80211_WOWLAN_TCP_DATA_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ] = { [NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ] = {
.len = sizeof(struct nl80211_wowlan_tcp_data_seq) .len = sizeof(struct nl80211_wowlan_tcp_data_seq)
}, },
...@@ -711,8 +709,8 @@ nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = { ...@@ -711,8 +709,8 @@ nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
.len = sizeof(struct nl80211_wowlan_tcp_data_token) .len = sizeof(struct nl80211_wowlan_tcp_data_token)
}, },
[NL80211_WOWLAN_TCP_DATA_INTERVAL] = { .type = NLA_U32 }, [NL80211_WOWLAN_TCP_DATA_INTERVAL] = { .type = NLA_U32 },
[NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = { .type = NLA_MIN_LEN, .len = 1 }, [NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
[NL80211_WOWLAN_TCP_WAKE_MASK] = { .type = NLA_MIN_LEN, .len = 1 }, [NL80211_WOWLAN_TCP_WAKE_MASK] = NLA_POLICY_MIN_LEN(1),
}; };
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
......
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