summaryrefslogtreecommitdiff
path: root/backport/compat/backport-4.20.c
diff options
context:
space:
mode:
Diffstat (limited to 'backport/compat/backport-4.20.c')
-rw-r--r--backport/compat/backport-4.20.c379
1 files changed, 0 insertions, 379 deletions
diff --git a/backport/compat/backport-4.20.c b/backport/compat/backport-4.20.c
deleted file mode 100644
index e26f3b52..00000000
--- a/backport/compat/backport-4.20.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Copyright (C) 2018 Intel Corporation
- *
- * Backport functionality introduced in Linux 4.20.
- * This is basically upstream lib/nlattr.c.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <net/netlink.h>
-
-static const u8 nla_attr_len[NLA_TYPE_MAX+1] = {
- [NLA_U8] = sizeof(u8),
- [NLA_U16] = sizeof(u16),
- [NLA_U32] = sizeof(u32),
- [NLA_U64] = sizeof(u64),
- [NLA_S8] = sizeof(s8),
- [NLA_S16] = sizeof(s16),
- [NLA_S32] = sizeof(s32),
- [NLA_S64] = sizeof(s64),
-};
-
-static const u8 nla_attr_minlen[NLA_TYPE_MAX+1] = {
- [NLA_U8] = sizeof(u8),
- [NLA_U16] = sizeof(u16),
- [NLA_U32] = sizeof(u32),
- [NLA_U64] = sizeof(u64),
- [NLA_MSECS] = sizeof(u64),
- [NLA_NESTED] = NLA_HDRLEN,
- [NLA_S8] = sizeof(s8),
- [NLA_S16] = sizeof(s16),
- [NLA_S32] = sizeof(s32),
- [NLA_S64] = sizeof(s64),
-};
-
-static int validate_nla_bitfield32(const struct nlattr *nla,
- const u32 *valid_flags_mask)
-{
- const struct nla_bitfield32 *bf = nla_data(nla);
-
- if (!valid_flags_mask)
- return -EINVAL;
-
- /*disallow invalid bit selector */
- if (bf->selector & ~*valid_flags_mask)
- return -EINVAL;
-
- /*disallow invalid bit values */
- if (bf->value & ~*valid_flags_mask)
- return -EINVAL;
-
- /*disallow valid bit values that are not selected*/
- if (bf->value & ~bf->selector)
- return -EINVAL;
-
- return 0;
-}
-
-static int nla_validate_array(const struct nlattr *head, int len, int maxtype,
- const struct nla_policy *policy,
- struct netlink_ext_ack *extack)
-{
- const struct nlattr *entry;
- int rem;
-
- nla_for_each_attr(entry, head, len, rem) {
- int ret;
-
- if (nla_len(entry) == 0)
- continue;
-
- if (nla_len(entry) < NLA_HDRLEN) {
- NL_SET_ERR_MSG_ATTR(extack, entry,
- "Array element too short");
- return -ERANGE;
- }
-
- ret = nla_validate(nla_data(entry), nla_len(entry),
- maxtype, policy, extack);
- if (ret < 0)
- return ret;
- }
-
- return 0;
-}
-
-static int nla_validate_int_range(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;
-
- 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_S8:
- value = nla_get_s8(nla);
- break;
- case NLA_S16:
- value = nla_get_s16(nla);
- break;
- case NLA_S32:
- value = nla_get_s32(nla);
- break;
- 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)) {
- NL_SET_ERR_MSG_ATTR(extack, nla,
- "integer out of range");
- return -ERANGE;
- }
-
- return 0;
-}
-
-static int validate_nla(const struct nlattr *nla, int maxtype,
- const struct nla_policy *policy,
- struct netlink_ext_ack *extack)
-{
- const struct nla_policy *pt;
- int minlen = 0, attrlen = nla_len(nla), type = nla_type(nla);
- int err = -ERANGE;
-
- if (type <= 0 || type > maxtype)
- return 0;
-
- pt = &policy[type];
-
- 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)) {
- pr_warn_ratelimited("netlink: '%s': attribute type %d has an invalid length.\n",
- current->comm, type);
- }
-
- switch (pt->type) {
- case NLA_EXACT_LEN:
- if (attrlen != pt->len)
- goto out_err;
- break;
-
- case NLA_REJECT:
- if (extack && pt->validation_data) {
- NL_SET_BAD_ATTR(extack, nla);
- extack->_msg = pt->validation_data;
- return -EINVAL;
- }
- err = -EINVAL;
- goto out_err;
-
- case NLA_FLAG:
- if (attrlen > 0)
- goto out_err;
- break;
-
- case NLA_BITFIELD32:
- if (attrlen != sizeof(struct nla_bitfield32))
- goto out_err;
-
- err = validate_nla_bitfield32(nla, pt->validation_data);
- if (err)
- goto out_err;
- break;
-
- case NLA_NUL_STRING:
- if (pt->len)
- minlen = min_t(int, attrlen, pt->len + 1);
- else
- minlen = attrlen;
-
- if (!minlen || memchr(nla_data(nla), '\0', minlen) == NULL) {
- err = -EINVAL;
- goto out_err;
- }
- /* fall through */
-
- case NLA_STRING:
- if (attrlen < 1)
- goto out_err;
-
- if (pt->len) {
- char *buf = nla_data(nla);
-
- if (buf[attrlen - 1] == '\0')
- attrlen--;
-
- if (attrlen > pt->len)
- goto out_err;
- }
- break;
-
- case NLA_BINARY:
- if (pt->len && attrlen > pt->len)
- goto out_err;
- break;
-
- case NLA_NESTED:
- /* a nested attributes is allowed to be empty; if its not,
- * it must have a size of at least NLA_HDRLEN.
- */
- if (attrlen == 0)
- 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, extack);
- if (err < 0) {
- /*
- * return directly to preserve the inner
- * error message/attribute pointer
- */
- return err;
- }
- }
- break;
- case NLA_NESTED_ARRAY:
- /* a nested array attribute is allowed to be empty; if its not,
- * it must have a size of at least NLA_HDRLEN.
- */
- if (attrlen == 0)
- break;
- if (attrlen < NLA_HDRLEN)
- goto out_err;
- if (pt->validation_data) {
- int err;
-
- err = nla_validate_array(nla_data(nla), nla_len(nla),
- pt->len, pt->validation_data,
- extack);
- if (err < 0) {
- /*
- * return directly to preserve the inner
- * error message/attribute pointer
- */
- return err;
- }
- }
- break;
- default:
- if (pt->len)
- minlen = pt->len;
- else if (pt->type != NLA_UNSPEC)
- minlen = nla_attr_minlen[pt->type];
-
- if (attrlen < minlen)
- goto out_err;
- }
-
- /* further validation */
- switch (pt->validation_type) {
- case NLA_VALIDATE_NONE:
- /* nothing to do */
- break;
- case NLA_VALIDATE_RANGE:
- case NLA_VALIDATE_MIN:
- case NLA_VALIDATE_MAX:
- err = nla_validate_int_range(pt, nla, extack);
- if (err)
- return err;
- break;
- case NLA_VALIDATE_FUNCTION:
- if (pt->validate) {
- err = pt->validate(nla, extack);
- if (err)
- return err;
- }
- break;
- }
-
- return 0;
-out_err:
- NL_SET_ERR_MSG_ATTR(extack, nla, "Attribute failed policy validation");
- return err;
-}
-
-int backport_nla_validate(const struct nlattr *head, int len, int maxtype,
- const struct nla_policy *policy,
- struct netlink_ext_ack *extack)
-{
- const struct nlattr *nla;
- int rem;
-
- nla_for_each_attr(nla, head, len, rem) {
- int err = validate_nla(nla, maxtype, policy, extack);
-
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(backport_nla_validate);
-
-int backport_nla_policy_len(const struct nla_policy *p, int n)
-{
- int i, len = 0;
-
- for (i = 0; i < n; i++, p++) {
- if (p->len)
- len += nla_total_size(p->len);
- else if (nla_attr_len[p->type])
- len += nla_total_size(nla_attr_len[p->type]);
- else if (nla_attr_minlen[p->type])
- len += nla_total_size(nla_attr_minlen[p->type]);
- }
-
- return len;
-}
-EXPORT_SYMBOL_GPL(backport_nla_policy_len);
-
-int backport_nla_parse(struct nlattr **tb, int maxtype,
- const struct nlattr *head,
- int len, const struct nla_policy *policy,
- struct netlink_ext_ack *extack)
-{
- const struct nlattr *nla;
- int rem;
-
- memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
-
- nla_for_each_attr(nla, head, len, rem) {
- u16 type = nla_type(nla);
-
- if (type > 0 && type <= maxtype) {
- if (policy) {
- int err = validate_nla(nla, maxtype, policy,
- extack);
-
- if (err < 0)
- return err;
- }
-
- tb[type] = (struct nlattr *)nla;
- }
- }
-
- if (unlikely(rem > 0))
- pr_warn_ratelimited("netlink: %d bytes leftover after parsing attributes in process `%s'.\n",
- rem, current->comm);
-
- return 0;
-}
-EXPORT_SYMBOL(backport_nla_parse);