aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink/attr.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-09-23 16:49:31 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-23 16:49:31 -0700
commita4c12d6c5dde48c69464baf7c703e425ee511433 (patch)
tree73c375e41a353e2da0461ff30d744bff73958b08 /net/netlink/attr.c
parent73af07de3e32b9ac328c3d1417258bb98a9b0a9b (diff)
parent3b9f9a1c3903b64c38505f9fed3bb11e48dbc931 (diff)
downloadkernel_samsung_smdk4412-a4c12d6c5dde48c69464baf7c703e425ee511433.zip
kernel_samsung_smdk4412-a4c12d6c5dde48c69464baf7c703e425ee511433.tar.gz
kernel_samsung_smdk4412-a4c12d6c5dde48c69464baf7c703e425ee511433.tar.bz2
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (353 commits) [IPV6] ADDRCONF: Mobile IPv6 Home Address support. [IPV6] ADDRCONF: Allow non-DAD'able addresses. [IPV6] NDISC: Fix is_router flag setting. [IPV6] ADDRCONF: Convert addrconf_lock to RCU. [IPV6] NDISC: Add proxy_ndp sysctl. [IPV6] NDISC: Set per-entry is_router flag in Proxy NA. [IPV6] NDISC: Avoid updating neighbor cache for proxied address in receiving NA. [IPV6]: Don't forward packets to proxied link-local address. [IPV6] NDISC: Handle NDP messages to proxied addresses. [NETFILTER]: PPTP conntrack: fix another GRE keymap leak [NETFILTER]: PPTP conntrack: fix GRE keymap leak [NETFILTER]: PPTP conntrack: fix PPTP_IN_CALL message types [NETFILTER]: PPTP conntrack: check call ID before changing state [NETFILTER]: PPTP conntrack: clean up debugging cruft [NETFILTER]: PPTP conntrack: consolidate header parsing [NETFILTER]: PPTP conntrack: consolidate header size checks [NETFILTER]: PPTP conntrack: simplify expectation handling [NETFILTER]: PPTP conntrack: remove unnecessary cid/pcid header pointers [NETFILTER]: PPTP conntrack: fix header definitions [NETFILTER]: PPTP conntrack: remove more dead code ...
Diffstat (limited to 'net/netlink/attr.c')
-rw-r--r--net/netlink/attr.c124
1 files changed, 114 insertions, 10 deletions
diff --git a/net/netlink/attr.c b/net/netlink/attr.c
index dddbd15..0041395 100644
--- a/net/netlink/attr.c
+++ b/net/netlink/attr.c
@@ -20,7 +20,6 @@ static u16 nla_attr_minlen[NLA_TYPE_MAX+1] __read_mostly = {
[NLA_U16] = sizeof(u16),
[NLA_U32] = sizeof(u32),
[NLA_U64] = sizeof(u64),
- [NLA_STRING] = 1,
[NLA_NESTED] = NLA_HDRLEN,
};
@@ -28,7 +27,7 @@ static int validate_nla(struct nlattr *nla, int maxtype,
struct nla_policy *policy)
{
struct nla_policy *pt;
- int minlen = 0;
+ int minlen = 0, attrlen = nla_len(nla);
if (nla->nla_type <= 0 || nla->nla_type > maxtype)
return 0;
@@ -37,16 +36,46 @@ static int validate_nla(struct nlattr *nla, int maxtype,
BUG_ON(pt->type > NLA_TYPE_MAX);
- if (pt->minlen)
- minlen = pt->minlen;
- else if (pt->type != NLA_UNSPEC)
- minlen = nla_attr_minlen[pt->type];
+ switch (pt->type) {
+ case NLA_FLAG:
+ if (attrlen > 0)
+ return -ERANGE;
+ break;
- if (pt->type == NLA_FLAG && nla_len(nla) > 0)
- return -ERANGE;
+ case NLA_NUL_STRING:
+ if (pt->len)
+ minlen = min_t(int, attrlen, pt->len + 1);
+ else
+ minlen = attrlen;
- if (nla_len(nla) < minlen)
- return -ERANGE;
+ if (!minlen || memchr(nla_data(nla), '\0', minlen) == NULL)
+ return -EINVAL;
+ /* fall through */
+
+ case NLA_STRING:
+ if (attrlen < 1)
+ return -ERANGE;
+
+ if (pt->len) {
+ char *buf = nla_data(nla);
+
+ if (buf[attrlen - 1] == '\0')
+ attrlen--;
+
+ if (attrlen > pt->len)
+ return -ERANGE;
+ }
+ break;
+
+ default:
+ if (pt->len)
+ minlen = pt->len;
+ else if (pt->type != NLA_UNSPEC)
+ minlen = nla_attr_minlen[pt->type];
+
+ if (attrlen < minlen)
+ return -ERANGE;
+ }
return 0;
}
@@ -255,6 +284,26 @@ struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
}
/**
+ * __nla_reserve_nohdr - reserve room for attribute without header
+ * @skb: socket buffer to reserve room on
+ * @attrlen: length of attribute payload
+ *
+ * Reserves room for attribute payload without a header.
+ *
+ * The caller is responsible to ensure that the skb provides enough
+ * tailroom for the payload.
+ */
+void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen)
+{
+ void *start;
+
+ start = skb_put(skb, NLA_ALIGN(attrlen));
+ memset(start, 0, NLA_ALIGN(attrlen));
+
+ return start;
+}
+
+/**
* nla_reserve - reserve room for attribute on the skb
* @skb: socket buffer to reserve room on
* @attrtype: attribute type
@@ -275,6 +324,24 @@ struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
}
/**
+ * nla_reserve - reserve room for attribute without header
+ * @skb: socket buffer to reserve room on
+ * @len: length of attribute payload
+ *
+ * Reserves room for attribute payload without a header.
+ *
+ * Returns NULL if the tailroom of the skb is insufficient to store
+ * the attribute payload.
+ */
+void *nla_reserve_nohdr(struct sk_buff *skb, int attrlen)
+{
+ if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
+ return NULL;
+
+ return __nla_reserve_nohdr(skb, attrlen);
+}
+
+/**
* __nla_put - Add a netlink attribute to a socket buffer
* @skb: socket buffer to add attribute to
* @attrtype: attribute type
@@ -293,6 +360,22 @@ void __nla_put(struct sk_buff *skb, int attrtype, int attrlen,
memcpy(nla_data(nla), data, attrlen);
}
+/**
+ * __nla_put_nohdr - Add a netlink attribute without header
+ * @skb: socket buffer to add attribute to
+ * @attrlen: length of attribute payload
+ * @data: head of attribute payload
+ *
+ * The caller is responsible to ensure that the skb provides enough
+ * tailroom for the attribute payload.
+ */
+void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data)
+{
+ void *start;
+
+ start = __nla_reserve_nohdr(skb, attrlen);
+ memcpy(start, data, attrlen);
+}
/**
* nla_put - Add a netlink attribute to a socket buffer
@@ -313,15 +396,36 @@ int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
return 0;
}
+/**
+ * nla_put_nohdr - Add a netlink attribute without header
+ * @skb: socket buffer to add attribute to
+ * @attrlen: length of attribute payload
+ * @data: head of attribute payload
+ *
+ * Returns -1 if the tailroom of the skb is insufficient to store
+ * the attribute payload.
+ */
+int nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data)
+{
+ if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
+ return -1;
+
+ __nla_put_nohdr(skb, attrlen, data);
+ return 0;
+}
EXPORT_SYMBOL(nla_validate);
EXPORT_SYMBOL(nla_parse);
EXPORT_SYMBOL(nla_find);
EXPORT_SYMBOL(nla_strlcpy);
EXPORT_SYMBOL(__nla_reserve);
+EXPORT_SYMBOL(__nla_reserve_nohdr);
EXPORT_SYMBOL(nla_reserve);
+EXPORT_SYMBOL(nla_reserve_nohdr);
EXPORT_SYMBOL(__nla_put);
+EXPORT_SYMBOL(__nla_put_nohdr);
EXPORT_SYMBOL(nla_put);
+EXPORT_SYMBOL(nla_put_nohdr);
EXPORT_SYMBOL(nla_memcpy);
EXPORT_SYMBOL(nla_memcmp);
EXPORT_SYMBOL(nla_strcmp);