Commit 550cbea0 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'netlink-validation-improvements-refactoring'



Johannes Berg says:

====================
netlink validation improvements/refactoring

Alright, this is the resend now, really just changing

 - the WARN_ON_ONCE() as spotted by Jakub;
 - mark the export patch no longer RFC.
   I wasn't actually sure if you meant this one too, and I really
   should dig out and polish the code that showed it in userspace.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4d73ce19 d07dcf9a
Loading
Loading
Loading
Loading
+99 −36
Original line number Diff line number Diff line
@@ -182,19 +182,28 @@ enum {
	NLA_BITFIELD32,
	NLA_REJECT,
	NLA_EXACT_LEN,
	NLA_EXACT_LEN_WARN,
	NLA_MIN_LEN,
	__NLA_TYPE_MAX,
};

#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)

struct netlink_range_validation {
	u64 min, max;
};

struct netlink_range_validation_signed {
	s64 min, max;
};

enum nla_policy_validation {
	NLA_VALIDATE_NONE,
	NLA_VALIDATE_RANGE,
	NLA_VALIDATE_MIN,
	NLA_VALIDATE_MAX,
	NLA_VALIDATE_RANGE_PTR,
	NLA_VALIDATE_FUNCTION,
	NLA_VALIDATE_WARN_TOO_LONG,
};

/**
@@ -217,7 +226,7 @@ enum nla_policy_validation {
 *    NLA_NESTED,
 *    NLA_NESTED_ARRAY     Length verification is done by checking len of
 *                         nested header (or empty); len field is used if
 *                         validation_data is also used, for the max attr
 *                         nested_policy is also used, for the max attr
 *                         number in the nested policy.
 *    NLA_U8, NLA_U16,
 *    NLA_U32, NLA_U64,
@@ -228,34 +237,32 @@ enum nla_policy_validation {
 *                         just like "All other"
 *    NLA_BITFIELD32       Unused
 *    NLA_REJECT           Unused
 *    NLA_EXACT_LEN        Attribute must have exactly this length, otherwise
 *                         it is rejected.
 *    NLA_EXACT_LEN_WARN   Attribute should have exactly this length, a warning
 *                         is logged if it is longer, shorter is rejected.
 *    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
 *
 * Meaning of `validation_data' field:
 * Meaning of validation union:
 *    NLA_BITFIELD32       This is a 32-bit bitmap/bitselector attribute and
 *                         validation data must point to a u32 value of valid
 *                         flags
 *    NLA_REJECT           This attribute is always rejected and validation data
 *                         `bitfield32_valid' is the u32 value of valid flags
 *    NLA_REJECT           This attribute is always rejected and `reject_message'
 *                         may point to a string to report as the error instead
 *                         of the generic one in extended ACK.
 *    NLA_NESTED           Points to a nested policy to validate, must also set
 *                         `len' to the max attribute number.
 *    NLA_NESTED           `nested_policy' to a nested policy to validate, must
 *                         also set `len' to the max attribute number. Use the
 *                         provided NLA_POLICY_NESTED() macro.
 *                         Note that nla_parse() will validate, but of course not
 *                         parse, the nested sub-policies.
 *    NLA_NESTED_ARRAY     Points to a nested policy to validate, must also set
 *                         `len' to the max attribute number. The difference to
 *                         NLA_NESTED is the structure - NLA_NESTED has the
 *                         nested attributes directly inside, while an array has
 *                         the nested attributes at another level down and the
 *                         attributes directly in the nesting don't matter.
 *    All other            Unused - but note that it's a union
 *
 * Meaning of `min' and `max' fields, use via NLA_POLICY_MIN, NLA_POLICY_MAX
 * and NLA_POLICY_RANGE:
 *    NLA_NESTED_ARRAY     `nested_policy' points to a nested policy to validate,
 *                         must also set `len' to the max attribute number. Use
 *                         the provided NLA_POLICY_NESTED_ARRAY() macro.
 *                         The difference to NLA_NESTED is the structure:
 *                         NLA_NESTED has the nested attributes directly inside
 *                         while an array has the nested attributes at another
 *                         level down and the attribute types directly in the
 *                         nesting don't matter.
 *    NLA_U8,
 *    NLA_U16,
 *    NLA_U32,
@@ -263,29 +270,47 @@ enum nla_policy_validation {
 *    NLA_S8,
 *    NLA_S16,
 *    NLA_S32,
 *    NLA_S64              These are used depending on the validation_type
 *                         field, if that is min/max/range then the minimum,
 *                         maximum and both are used (respectively) to check
 *    NLA_S64              The `min' and `max' fields are used depending on the
 *                         validation_type field, if that is min/max/range then
 *                         the min, max or both are used (respectively) to check
 *                         the value of the integer attribute.
 *                         Note that in the interest of code simplicity and
 *                         struct size both limits are s16, so you cannot
 *                         enforce a range that doesn't fall within the range
 *                         of s16 - do that as usual in the code instead.
 *                         Use the NLA_POLICY_MIN(), NLA_POLICY_MAX() and
 *                         NLA_POLICY_RANGE() macros.
 *    NLA_U8,
 *    NLA_U16,
 *    NLA_U32,
 *    NLA_U64              If the validation_type field instead is set to
 *                         NLA_VALIDATE_RANGE_PTR, `range' must be a pointer
 *                         to a struct netlink_range_validation that indicates
 *                         the min/max values.
 *                         Use NLA_POLICY_FULL_RANGE().
 *    NLA_S8,
 *    NLA_S16,
 *    NLA_S32,
 *    NLA_S64              If the validation_type field instead is set to
 *                         NLA_VALIDATE_RANGE_PTR, `range_signed' must be a
 *                         pointer to a struct netlink_range_validation_signed
 *                         that indicates the min/max values.
 *                         Use NLA_POLICY_FULL_RANGE_SIGNED().
 *    All other            Unused - but note that it's a union
 *
 * Meaning of `validate' field, use via NLA_POLICY_VALIDATE_FN:
 *    NLA_BINARY           Validation function called for the attribute,
 *                         not compatible with use of the validation_data
 *                         as in NLA_BITFIELD32, NLA_REJECT, NLA_NESTED and
 *                         NLA_NESTED_ARRAY.
 *    NLA_BINARY           Validation function called for the attribute.
 *    All other            Unused - but note that it's a union
 *
 * Example:
 *
 * static const u32 myvalidflags = 0xff231023;
 *
 * static const struct nla_policy my_policy[ATTR_MAX+1] = {
 * 	[ATTR_FOO] = { .type = NLA_U16 },
 *	[ATTR_BAR] = { .type = NLA_STRING, .len = BARSIZ },
 *	[ATTR_BAZ] = { .type = NLA_EXACT_LEN, .len = sizeof(struct mystruct) },
 *	[ATTR_GOO] = { .type = NLA_BITFIELD32, .validation_data = &myvalidflags },
 *	[ATTR_GOO] = NLA_POLICY_BITFIELD32(myvalidflags),
 * };
 */
struct nla_policy {
@@ -293,7 +318,11 @@ struct nla_policy {
	u8		validation_type;
	u16		len;
	union {
		const void *validation_data;
		const u32 bitfield32_valid;
		const char *reject_message;
		const struct nla_policy *nested_policy;
		struct netlink_range_validation *range;
		struct netlink_range_validation_signed *range_signed;
		struct {
			s16 min, max;
		};
@@ -321,28 +350,39 @@ 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_WARN, \
					  .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_COMPAT	NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN)

#define _NLA_POLICY_NESTED(maxattr, policy) \
	{ .type = NLA_NESTED, .validation_data = policy, .len = maxattr }
	{ .type = NLA_NESTED, .nested_policy = policy, .len = maxattr }
#define _NLA_POLICY_NESTED_ARRAY(maxattr, policy) \
	{ .type = NLA_NESTED_ARRAY, .validation_data = policy, .len = maxattr }
	{ .type = NLA_NESTED_ARRAY, .nested_policy = policy, .len = maxattr }
#define NLA_POLICY_NESTED(policy) \
	_NLA_POLICY_NESTED(ARRAY_SIZE(policy) - 1, policy)
#define NLA_POLICY_NESTED_ARRAY(policy) \
	_NLA_POLICY_NESTED_ARRAY(ARRAY_SIZE(policy) - 1, policy)
#define NLA_POLICY_BITFIELD32(valid) \
	{ .type = NLA_BITFIELD32, .bitfield32_valid = valid }

#define __NLA_ENSURE(condition) BUILD_BUG_ON_ZERO(!(condition))
#define NLA_ENSURE_UINT_TYPE(tp)			\
	(__NLA_ENSURE(tp == NLA_U8 || tp == NLA_U16 ||	\
		      tp == NLA_U32 || tp == NLA_U64 ||	\
		      tp == NLA_MSECS) + tp)
#define NLA_ENSURE_SINT_TYPE(tp)			\
	(__NLA_ENSURE(tp == NLA_S8 || tp == NLA_S16  ||	\
		      tp == NLA_S32 || tp == NLA_S64) + tp)
#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)
		      tp == NLA_S64 || tp == NLA_U64 ||	\
		      tp == NLA_MSECS) + tp)
#define NLA_ENSURE_NO_VALIDATION_PTR(tp)		\
	(__NLA_ENSURE(tp != NLA_BITFIELD32 &&		\
		      tp != NLA_REJECT &&		\
@@ -356,6 +396,18 @@ struct nla_policy {
	.max = _max					\
}

#define NLA_POLICY_FULL_RANGE(tp, _range) {		\
	.type = NLA_ENSURE_UINT_TYPE(tp),		\
	.validation_type = NLA_VALIDATE_RANGE_PTR,	\
	.range = _range,				\
}

#define NLA_POLICY_FULL_RANGE_SIGNED(tp, _range) {	\
	.type = NLA_ENSURE_SINT_TYPE(tp),		\
	.validation_type = NLA_VALIDATE_RANGE_PTR,	\
	.range_signed = _range,				\
}

#define NLA_POLICY_MIN(tp, _min) {			\
	.type = NLA_ENSURE_INT_TYPE(tp),		\
	.validation_type = NLA_VALIDATE_MIN,		\
@@ -1876,4 +1928,15 @@ static inline bool nla_is_last(const struct nlattr *nla, int rem)
	return nla->nla_len == rem;
}

void nla_get_range_unsigned(const struct nla_policy *pt,
			    struct netlink_range_validation *range);
void nla_get_range_signed(const struct nla_policy *pt,
			  struct netlink_range_validation_signed *range);

int netlink_policy_dump_start(const struct nla_policy *policy,
			      unsigned int maxtype,
			      unsigned long *state);
bool netlink_policy_dump_loop(unsigned long *state);
int netlink_policy_dump_write(struct sk_buff *skb, unsigned long state);

#endif
+2 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ enum {
	CTRL_CMD_NEWMCAST_GRP,
	CTRL_CMD_DELMCAST_GRP,
	CTRL_CMD_GETMCAST_GRP, /* unused */
	CTRL_CMD_GETPOLICY,
	__CTRL_CMD_MAX,
};

@@ -62,6 +63,7 @@ enum {
	CTRL_ATTR_MAXATTR,
	CTRL_ATTR_OPS,
	CTRL_ATTR_MCAST_GROUPS,
	CTRL_ATTR_POLICY,
	__CTRL_ATTR_MAX,
};

+103 −0
Original line number Diff line number Diff line
@@ -249,4 +249,107 @@ struct nla_bitfield32 {
	__u32 selector;
};

/*
 * policy descriptions - it's specific to each family how this is used
 * Normally, it should be retrieved via a dump inside another attribute
 * specifying where it applies.
 */

/**
 * enum netlink_attribute_type - type of an attribute
 * @NL_ATTR_TYPE_INVALID: unused
 * @NL_ATTR_TYPE_FLAG: flag attribute (present/not present)
 * @NL_ATTR_TYPE_U8: 8-bit unsigned attribute
 * @NL_ATTR_TYPE_U16: 16-bit unsigned attribute
 * @NL_ATTR_TYPE_U32: 32-bit unsigned attribute
 * @NL_ATTR_TYPE_U64: 64-bit unsigned attribute
 * @NL_ATTR_TYPE_S8: 8-bit signed attribute
 * @NL_ATTR_TYPE_S16: 16-bit signed attribute
 * @NL_ATTR_TYPE_S32: 32-bit signed attribute
 * @NL_ATTR_TYPE_S64: 64-bit signed attribute
 * @NL_ATTR_TYPE_BINARY: binary data, min/max length may be specified
 * @NL_ATTR_TYPE_STRING: string, min/max length may be specified
 * @NL_ATTR_TYPE_NUL_STRING: NUL-terminated string,
 *	min/max length may be specified
 * @NL_ATTR_TYPE_NESTED: nested, i.e. the content of this attribute
 *	consists of sub-attributes. The nested policy and maxtype
 *	inside may be specified.
 * @NL_ATTR_TYPE_NESTED_ARRAY: nested array, i.e. the content of this
 *	attribute contains sub-attributes whose type is irrelevant
 *	(just used to separate the array entries) and each such array
 *	entry has attributes again, the policy for those inner ones
 *	and the corresponding maxtype may be specified.
 * @NL_ATTR_TYPE_BITFIELD32: &struct nla_bitfield32 attribute
 */
enum netlink_attribute_type {
	NL_ATTR_TYPE_INVALID,

	NL_ATTR_TYPE_FLAG,

	NL_ATTR_TYPE_U8,
	NL_ATTR_TYPE_U16,
	NL_ATTR_TYPE_U32,
	NL_ATTR_TYPE_U64,

	NL_ATTR_TYPE_S8,
	NL_ATTR_TYPE_S16,
	NL_ATTR_TYPE_S32,
	NL_ATTR_TYPE_S64,

	NL_ATTR_TYPE_BINARY,
	NL_ATTR_TYPE_STRING,
	NL_ATTR_TYPE_NUL_STRING,

	NL_ATTR_TYPE_NESTED,
	NL_ATTR_TYPE_NESTED_ARRAY,

	NL_ATTR_TYPE_BITFIELD32,
};

/**
 * enum netlink_policy_type_attr - policy type attributes
 * @NL_POLICY_TYPE_ATTR_UNSPEC: unused
 * @NL_POLICY_TYPE_ATTR_TYPE: type of the attribute,
 *	&enum netlink_attribute_type (U32)
 * @NL_POLICY_TYPE_ATTR_MIN_VALUE_S: minimum value for signed
 *	integers (S64)
 * @NL_POLICY_TYPE_ATTR_MAX_VALUE_S: maximum value for signed
 *	integers (S64)
 * @NL_POLICY_TYPE_ATTR_MIN_VALUE_U: minimum value for unsigned
 *	integers (U64)
 * @NL_POLICY_TYPE_ATTR_MAX_VALUE_U: maximum value for unsigned
 *	integers (U64)
 * @NL_POLICY_TYPE_ATTR_MIN_LENGTH: minimum length for binary
 *	attributes, no minimum if not given (U32)
 * @NL_POLICY_TYPE_ATTR_MAX_LENGTH: maximum length for binary
 *	attributes, no maximum if not given (U32)
 * @NL_POLICY_TYPE_ATTR_POLICY_IDX: sub policy for nested and
 *	nested array types (U32)
 * @NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE: maximum sub policy
 *	attribute for nested and nested array types, this can
 *	in theory be < the size of the policy pointed to by
 *	the index, if limited inside the nesting (U32)
 * @NL_POLICY_TYPE_ATTR_BITFIELD32_MASK: valid mask for the
 *	bitfield32 type (U32)
 * @NL_POLICY_TYPE_ATTR_PAD: pad attribute for 64-bit alignment
 */
enum netlink_policy_type_attr {
	NL_POLICY_TYPE_ATTR_UNSPEC,
	NL_POLICY_TYPE_ATTR_TYPE,
	NL_POLICY_TYPE_ATTR_MIN_VALUE_S,
	NL_POLICY_TYPE_ATTR_MAX_VALUE_S,
	NL_POLICY_TYPE_ATTR_MIN_VALUE_U,
	NL_POLICY_TYPE_ATTR_MAX_VALUE_U,
	NL_POLICY_TYPE_ATTR_MIN_LENGTH,
	NL_POLICY_TYPE_ATTR_MAX_LENGTH,
	NL_POLICY_TYPE_ATTR_POLICY_IDX,
	NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE,
	NL_POLICY_TYPE_ATTR_BITFIELD32_MASK,
	NL_POLICY_TYPE_ATTR_PAD,

	/* keep last */
	__NL_POLICY_TYPE_ATTR_MAX,
	NL_POLICY_TYPE_ATTR_MAX = __NL_POLICY_TYPE_ATTR_MAX - 1
};

#endif /* _UAPI__LINUX_NETLINK_H */
+200 −48
Original line number Diff line number Diff line
@@ -44,8 +44,22 @@ static const u8 nla_attr_minlen[NLA_TYPE_MAX+1] = {
	[NLA_S64]	= sizeof(s64),
};

/*
 * Nested policies might refer back to the original
 * policy in some cases, and userspace could try to
 * abuse that and recurse by nesting in the right
 * ways. Limit recursion to avoid this problem.
 */
#define MAX_POLICY_RECURSION_DEPTH	10

static int __nla_validate_parse(const struct nlattr *head, int len, int maxtype,
				const struct nla_policy *policy,
				unsigned int validate,
				struct netlink_ext_ack *extack,
				struct nlattr **tb, unsigned int depth);

static int validate_nla_bitfield32(const struct nlattr *nla,
				   const u32 *valid_flags_mask)
				   const u32 valid_flags_mask)
{
	const struct nla_bitfield32 *bf = nla_data(nla);

@@ -53,11 +67,11 @@ static int validate_nla_bitfield32(const struct nlattr *nla,
		return -EINVAL;

	/*disallow invalid bit selector */
	if (bf->selector & ~*valid_flags_mask)
	if (bf->selector & ~valid_flags_mask)
		return -EINVAL;

	/*disallow invalid bit values */
	if (bf->value & ~*valid_flags_mask)
	if (bf->value & ~valid_flags_mask)
		return -EINVAL;

	/*disallow valid bit values that are not selected*/
@@ -70,7 +84,7 @@ static int validate_nla_bitfield32(const struct nlattr *nla,
static int nla_validate_array(const struct nlattr *head, int len, int maxtype,
			      const struct nla_policy *policy,
			      struct netlink_ext_ack *extack,
			      unsigned int validate)
			      unsigned int validate, unsigned int depth)
{
	const struct nlattr *entry;
	int rem;
@@ -87,8 +101,9 @@ static int nla_validate_array(const struct nlattr *head, int len, int maxtype,
			return -ERANGE;
		}

		ret = __nla_validate(nla_data(entry), nla_len(entry),
				     maxtype, policy, validate, extack);
		ret = __nla_validate_parse(nla_data(entry), nla_len(entry),
					   maxtype, policy, validate, extack,
					   NULL, depth + 1);
		if (ret < 0)
			return ret;
	}
@@ -96,17 +111,58 @@ static int nla_validate_array(const struct nlattr *head, int len, int maxtype,
	return 0;
}

static int nla_validate_int_range(const struct nla_policy *pt,
void nla_get_range_unsigned(const struct nla_policy *pt,
			    struct netlink_range_validation *range)
{
	WARN_ON_ONCE(pt->validation_type != NLA_VALIDATE_RANGE_PTR &&
		     (pt->min < 0 || pt->max < 0));

	range->min = 0;

	switch (pt->type) {
	case NLA_U8:
		range->max = U8_MAX;
		break;
	case NLA_U16:
		range->max = U16_MAX;
		break;
	case NLA_U32:
		range->max = U32_MAX;
		break;
	case NLA_U64:
	case NLA_MSECS:
		range->max = U64_MAX;
		break;
	default:
		WARN_ON_ONCE(1);
		return;
	}

	switch (pt->validation_type) {
	case NLA_VALIDATE_RANGE:
		range->min = pt->min;
		range->max = pt->max;
		break;
	case NLA_VALIDATE_RANGE_PTR:
		*range = *pt->range;
		break;
	case NLA_VALIDATE_MIN:
		range->min = pt->min;
		break;
	case NLA_VALIDATE_MAX:
		range->max = pt->max;
		break;
	default:
		break;
	}
}

static int nla_validate_int_range_unsigned(const struct nla_policy *pt,
					   const struct nlattr *nla,
					   struct netlink_ext_ack *extack)
{
	bool validate_min, validate_max;
	s64 value;

	validate_min = pt->validation_type == NLA_VALIDATE_RANGE ||
		       pt->validation_type == NLA_VALIDATE_MIN;
	validate_max = pt->validation_type == NLA_VALIDATE_RANGE ||
		       pt->validation_type == NLA_VALIDATE_MAX;
	struct netlink_range_validation range;
	u64 value;

	switch (pt->type) {
	case NLA_U8:
@@ -118,6 +174,77 @@ static int nla_validate_int_range(const struct nla_policy *pt,
	case NLA_U32:
		value = nla_get_u32(nla);
		break;
	case NLA_U64:
	case NLA_MSECS:
		value = nla_get_u64(nla);
		break;
	default:
		return -EINVAL;
	}

	nla_get_range_unsigned(pt, &range);

	if (value < range.min || value > range.max) {
		NL_SET_ERR_MSG_ATTR(extack, nla,
				    "integer out of range");
		return -ERANGE;
	}

	return 0;
}

void nla_get_range_signed(const struct nla_policy *pt,
			  struct netlink_range_validation_signed *range)
{
	switch (pt->type) {
	case NLA_S8:
		range->min = S8_MIN;
		range->max = S8_MAX;
		break;
	case NLA_S16:
		range->min = S16_MIN;
		range->max = S16_MAX;
		break;
	case NLA_S32:
		range->min = S32_MIN;
		range->max = S32_MAX;
		break;
	case NLA_S64:
		range->min = S64_MIN;
		range->max = S64_MAX;
		break;
	default:
		WARN_ON_ONCE(1);
		return;
	}

	switch (pt->validation_type) {
	case NLA_VALIDATE_RANGE:
		range->min = pt->min;
		range->max = pt->max;
		break;
	case NLA_VALIDATE_RANGE_PTR:
		*range = *pt->range_signed;
		break;
	case NLA_VALIDATE_MIN:
		range->min = pt->min;
		break;
	case NLA_VALIDATE_MAX:
		range->max = pt->max;
		break;
	default:
		break;
	}
}

static int nla_validate_int_range_signed(const struct nla_policy *pt,
					 const struct nlattr *nla,
					 struct netlink_ext_ack *extack)
{
	struct netlink_range_validation_signed range;
	s64 value;

	switch (pt->type) {
	case NLA_S8:
		value = nla_get_s8(nla);
		break;
@@ -130,22 +257,13 @@ static int nla_validate_int_range(const struct nla_policy *pt,
	case NLA_S64:
		value = nla_get_s64(nla);
		break;
	case NLA_U64:
		/* treat this one specially, since it may not fit into s64 */
		if ((validate_min && nla_get_u64(nla) < pt->min) ||
		    (validate_max && nla_get_u64(nla) > pt->max)) {
			NL_SET_ERR_MSG_ATTR(extack, nla,
					    "integer out of range");
			return -ERANGE;
		}
		return 0;
	default:
		WARN_ON(1);
		return -EINVAL;
	}

	if ((validate_min && value < pt->min) ||
	    (validate_max && value > pt->max)) {
	nla_get_range_signed(pt, &range);

	if (value < range.min || value > range.max) {
		NL_SET_ERR_MSG_ATTR(extack, nla,
				    "integer out of range");
		return -ERANGE;
@@ -154,9 +272,31 @@ static int nla_validate_int_range(const struct nla_policy *pt,
	return 0;
}

static int nla_validate_int_range(const struct nla_policy *pt,
				  const struct nlattr *nla,
				  struct netlink_ext_ack *extack)
{
	switch (pt->type) {
	case NLA_U8:
	case NLA_U16:
	case NLA_U32:
	case NLA_U64:
	case NLA_MSECS:
		return nla_validate_int_range_unsigned(pt, nla, extack);
	case NLA_S8:
	case NLA_S16:
	case NLA_S32:
	case NLA_S64:
		return nla_validate_int_range_signed(pt, nla, extack);
	default:
		WARN_ON(1);
		return -EINVAL;
	}
}

static int validate_nla(const struct nlattr *nla, int maxtype,
			const struct nla_policy *policy, unsigned int validate,
			struct netlink_ext_ack *extack)
			struct netlink_ext_ack *extack, unsigned int depth)
{
	u16 strict_start_type = policy[0].strict_start_type;
	const struct nla_policy *pt;
@@ -174,7 +314,9 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
	BUG_ON(pt->type > NLA_TYPE_MAX);

	if ((nla_attr_len[pt->type] && attrlen != nla_attr_len[pt->type]) ||
	    (pt->type == NLA_EXACT_LEN_WARN && attrlen != pt->len)) {
	    (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",
				    current->comm, type);
		if (validate & NL_VALIDATE_STRICT_ATTRS) {
@@ -200,15 +342,10 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
	}

	switch (pt->type) {
	case NLA_EXACT_LEN:
		if (attrlen != pt->len)
			goto out_err;
		break;

	case NLA_REJECT:
		if (extack && pt->validation_data) {
		if (extack && pt->reject_message) {
			NL_SET_BAD_ATTR(extack, nla);
			extack->_msg = pt->validation_data;
			extack->_msg = pt->reject_message;
			return -EINVAL;
		}
		err = -EINVAL;
@@ -223,7 +360,7 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
		if (attrlen != sizeof(struct nla_bitfield32))
			goto out_err;

		err = validate_nla_bitfield32(nla, pt->validation_data);
		err = validate_nla_bitfield32(nla, pt->bitfield32_valid);
		if (err)
			goto out_err;
		break;
@@ -268,10 +405,11 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
			break;
		if (attrlen < NLA_HDRLEN)
			goto out_err;
		if (pt->validation_data) {
			err = __nla_validate(nla_data(nla), nla_len(nla), pt->len,
					     pt->validation_data, validate,
					     extack);
		if (pt->nested_policy) {
			err = __nla_validate_parse(nla_data(nla), nla_len(nla),
						   pt->len, pt->nested_policy,
						   validate, extack, NULL,
						   depth + 1);
			if (err < 0) {
				/*
				 * return directly to preserve the inner
@@ -289,12 +427,12 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
			break;
		if (attrlen < NLA_HDRLEN)
			goto out_err;
		if (pt->validation_data) {
		if (pt->nested_policy) {
			int err;

			err = nla_validate_array(nla_data(nla), nla_len(nla),
						 pt->len, pt->validation_data,
						 extack, validate);
						 pt->len, pt->nested_policy,
						 extack, validate, depth);
			if (err < 0) {
				/*
				 * return directly to preserve the inner
@@ -317,6 +455,13 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
			goto out_err;
		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:
		if (pt->len)
			minlen = pt->len;
@@ -332,6 +477,7 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
	case NLA_VALIDATE_NONE:
		/* nothing to do */
		break;
	case NLA_VALIDATE_RANGE_PTR:
	case NLA_VALIDATE_RANGE:
	case NLA_VALIDATE_MIN:
	case NLA_VALIDATE_MAX:
@@ -358,11 +504,17 @@ static int __nla_validate_parse(const struct nlattr *head, int len, int maxtype,
				const struct nla_policy *policy,
				unsigned int validate,
				struct netlink_ext_ack *extack,
				struct nlattr **tb)
				struct nlattr **tb, unsigned int depth)
{
	const struct nlattr *nla;
	int rem;

	if (depth >= MAX_POLICY_RECURSION_DEPTH) {
		NL_SET_ERR_MSG(extack,
			       "allowed policy recursion depth exceeded");
		return -EINVAL;
	}

	if (tb)
		memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));

@@ -379,7 +531,7 @@ static int __nla_validate_parse(const struct nlattr *head, int len, int maxtype,
		}
		if (policy) {
			int err = validate_nla(nla, maxtype, policy,
					       validate, extack);
					       validate, extack, depth);

			if (err < 0)
				return err;
@@ -421,7 +573,7 @@ int __nla_validate(const struct nlattr *head, int len, int maxtype,
		   struct netlink_ext_ack *extack)
{
	return __nla_validate_parse(head, len, maxtype, policy, validate,
				    extack, NULL);
				    extack, NULL, 0);
}
EXPORT_SYMBOL(__nla_validate);

@@ -476,7 +628,7 @@ int __nla_parse(struct nlattr **tb, int maxtype,
		struct netlink_ext_ack *extack)
{
	return __nla_validate_parse(head, len, maxtype, policy, validate,
				    extack, tb);
				    extack, tb, 0);
}
EXPORT_SYMBOL(__nla_parse);

+1 −1
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
# Makefile for the netlink driver.
#

obj-y  				:= af_netlink.o genetlink.o
obj-y  				:= af_netlink.o genetlink.o policy.o

obj-$(CONFIG_NETLINK_DIAG)	+= netlink_diag.o
netlink_diag-y			:= diag.o
Loading