[SRU][F:linux-bluefield][PATCH 1/4] netlink: add mask validation
Bodong Wang
bodong at nvidia.com
Thu Sep 30 20:51:17 UTC 2021
From: Jakub Kicinski <kuba at kernel.org>
BugLink: https://bugs.launchpad.net/bugs/1944390
We don't have good validation policy for existing unsigned int attrs
which serve as flags (for new ones we could use NLA_BITFIELD32).
With increased use of policy dumping having the validation be
expressed as part of the policy is important. Add validation
policy in form of a mask of supported/valid bits.
Support u64 in the uAPI to be future-proof, but really for now
the embedded mask member can only hold 32 bits, so anything with
bit 32+ set will always fail validation.
Signed-off-by: Jakub Kicinski <kuba at kernel.org>
Signed-off-by: David S. Miller <davem at davemloft.net>
(Backported from upstream commit bdbb4e29df8b790db50cb73ce25d23543329f05f)
Signed-off-by: Paul Blakey <paulb at nvidia.com>
[Paul: Changes for patch to apply:
added missing RANGE_PTR to enum nla_policy_validation
added missing helpers __NLA_IS_.*INT_TYPE()
removed unneeded uapi netlink changes as enum netlink_policy_type_attr
doesn't exist]
Signed-off-by: Bodong Wang <bodong at nvidia.com>
---
include/net/netlink.h | 16 ++++++++++++++++
lib/nlattr.c | 36 ++++++++++++++++++++++++++++++++++++
2 files changed, 52 insertions(+)
diff --git a/include/net/netlink.h b/include/net/netlink.h
index b140c8f..22dd99b 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -194,6 +194,8 @@ enum nla_policy_validation {
NLA_VALIDATE_RANGE,
NLA_VALIDATE_MIN,
NLA_VALIDATE_MAX,
+ NLA_VALIDATE_MASK,
+ NLA_VALIDATE_RANGE_PTR,
NLA_VALIDATE_FUNCTION,
};
@@ -294,6 +296,7 @@ struct nla_policy {
u16 len;
union {
const void *validation_data;
+ const u32 mask;
struct {
s16 min, max;
};
@@ -337,12 +340,19 @@ struct nla_policy {
#define NLA_POLICY_NESTED_ARRAY(policy) \
_NLA_POLICY_NESTED_ARRAY(ARRAY_SIZE(policy) - 1, policy)
+#define __NLA_IS_UINT_TYPE(tp) \
+ (tp == NLA_U8 || tp == NLA_U16 || tp == NLA_U32 || tp == NLA_U64)
+#define __NLA_IS_SINT_TYPE(tp) \
+ (tp == NLA_S8 || tp == NLA_S16 || tp == NLA_S32 || tp == NLA_S64)
+
#define __NLA_ENSURE(condition) BUILD_BUG_ON_ZERO(!(condition))
#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_UINT_TYPE(tp) \
+ (__NLA_ENSURE(__NLA_IS_UINT_TYPE(tp)) + tp)
#define NLA_ENSURE_NO_VALIDATION_PTR(tp) \
(__NLA_ENSURE(tp != NLA_BITFIELD32 && \
tp != NLA_REJECT && \
@@ -368,6 +378,12 @@ struct nla_policy {
.max = _max, \
}
+#define NLA_POLICY_MASK(tp, _mask) { \
+ .type = NLA_ENSURE_UINT_TYPE(tp), \
+ .validation_type = NLA_VALIDATE_MASK, \
+ .mask = _mask, \
+}
+
#define NLA_POLICY_VALIDATE_FN(tp, fn, ...) { \
.type = NLA_ENSURE_NO_VALIDATION_PTR(tp), \
.validation_type = NLA_VALIDATE_FUNCTION, \
diff --git a/lib/nlattr.c b/lib/nlattr.c
index 0d84f79..c94b014 100644
--- a/lib/nlattr.c
+++ b/lib/nlattr.c
@@ -154,6 +154,37 @@ static int nla_validate_int_range(const struct nla_policy *pt,
return 0;
}
+static int nla_validate_mask(const struct nla_policy *pt,
+ const struct nlattr *nla,
+ struct netlink_ext_ack *extack)
+{
+ u64 value;
+
+ switch (pt->type) {
+ case NLA_U8:
+ value = nla_get_u8(nla);
+ break;
+ case NLA_U16:
+ value = nla_get_u16(nla);
+ break;
+ case NLA_U32:
+ value = nla_get_u32(nla);
+ break;
+ case NLA_U64:
+ value = nla_get_u64(nla);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (value & ~(u64)pt->mask) {
+ NL_SET_ERR_MSG_ATTR(extack, nla, "reserved bit set");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int validate_nla(const struct nlattr *nla, int maxtype,
const struct nla_policy *policy, unsigned int validate,
struct netlink_ext_ack *extack)
@@ -339,6 +370,11 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
if (err)
return err;
break;
+ case NLA_VALIDATE_MASK:
+ err = nla_validate_mask(pt, nla, extack);
+ if (err)
+ return err;
+ break;
case NLA_VALIDATE_FUNCTION:
if (pt->validate) {
err = pt->validate(nla, extack);
--
1.8.3.1
More information about the kernel-team
mailing list