diff options
author | Thomas Graf <tgr@deb.localdomain> | 2008-01-14 15:17:56 (GMT) |
---|---|---|
committer | Thomas Graf <tgr@deb.localdomain> | 2008-01-14 15:17:56 (GMT) |
commit | 6de17f3308cfd53ad922d144a1b28ddd962d6678 (patch) | |
tree | f589f1328bae4d165a4e0842a21322645134890c /lib | |
parent | 13c85b663390547d8787aa8f45fbd009f4f8a332 (diff) | |
download | libnl-6de17f3308cfd53ad922d144a1b28ddd962d6678.zip libnl-6de17f3308cfd53ad922d144a1b28ddd962d6678.tar.gz libnl-6de17f3308cfd53ad922d144a1b28ddd962d6678.tar.bz2 |
Fix stale data pointers when constructing messages
Patrick McHardy reported a problem where pointers to the
payload of a netlink message as returned by f.e. the
nesting helpers become stale when the payload data
chunk is reallocated.
In order to avoid further problems, the payload chunk is
no longer extended on the fly. Instead the allocation is
made during netlink message object allocation time with
a default size of a page which should be fine for the
majority of all users. Additionally the functions
nlmsg_alloc_size() and nlmsg_set_default_size() have been
added to allocate messages of a particular length and to
modify the default message size.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/attr.c | 5 | ||||
-rw-r--r-- | lib/msg.c | 68 | ||||
-rw-r--r-- | lib/nl.c | 9 |
3 files changed, 54 insertions, 28 deletions
@@ -481,9 +481,8 @@ struct nlattr *nla_reserve(struct nl_msg *n, int attrtype, int attrlen) tlen = NLMSG_ALIGN(n->nm_nlh->nlmsg_len) + nla_total_size(attrlen); - n->nm_nlh = realloc(n->nm_nlh, tlen); - if (!n->nm_nlh) { - nl_errno(ENOMEM); + if ((tlen + n->nm_nlh->nlmsg_len) > n->nm_size) { + nl_errno(ENOBUFS); return NULL; } @@ -164,6 +164,13 @@ #include <netlink/attr.h> #include <linux/socket.h> +static size_t default_msg_size; + +static void __init init_msg_size(void) +{ + default_msg_size = getpagesize(); +} + /** * @name Size Calculations * @{ @@ -369,9 +376,10 @@ static struct nl_msg *__nlmsg_alloc(size_t len) goto errout; nm->nm_protocol = -1; - nm->nm_nlh->nlmsg_len = len; + nm->nm_size = len; + nm->nm_nlh->nlmsg_len = nlmsg_total_size(0); - NL_DBG(2, "msg %p: Allocated new message, nlmsg_len=%zu\n", nm, len); + NL_DBG(2, "msg %p: Allocated new message, maxlen=%zu\n", nm, len); return nm; errout: @@ -381,25 +389,34 @@ errout: } /** - * Allocate a new netlink message + * Allocate a new netlink message with the default maximum payload size. * - * Allocates a new netlink message without any further payload. + * Allocates a new netlink message without any further payload. The + * maximum payload size defaults to PAGESIZE or as otherwise specified + * with nlmsg_set_default_size(). * * @return Newly allocated netlink message or NULL. */ struct nl_msg *nlmsg_alloc(void) { - return __nlmsg_alloc(nlmsg_total_size(0)); + return __nlmsg_alloc(default_msg_size); +} + +/** + * Allocate a new netlink message with maximum payload size specified. + */ +struct nl_msg *nlmsg_alloc_size(size_t max) +{ + return __nlmsg_alloc(max); } /** * Allocate a new netlink message and inherit netlink message header * @arg hdr Netlink message header template * - * Allocates a new netlink message with a tailroom for the netlink - * message header. If \a hdr is not NULL it will be used as a - * template for the netlink message header, otherwise the header - * is left blank. + * Allocates a new netlink message and inherits the original message + * header. If \a hdr is not NULL it will be used as a template for + * the netlink message header, otherwise the header is left blank. * * @return Newly allocated netlink message or NULL */ @@ -443,6 +460,18 @@ struct nl_msg *nlmsg_alloc_simple(int nlmsgtype, int flags) } /** + * Set the default maximum message payload size for allocated messages + * @arg max Size of payload in bytes. + */ +void nlmsg_set_default_size(size_t max) +{ + if (max < nlmsg_total_size(0)) + max = nlmsg_total_size(0); + + default_msg_size = max; +} + +/** * Convert a netlink message received from a netlink socket to a nl_msg * @arg hdr Netlink message received from netlink socket. * @@ -477,35 +506,31 @@ errout: * existing netlink message. Eventual padding required will * be zeroed out. * - * @note All existing pointers into the old data section may have - * become obsolete and illegal to reference after this call. - * * @return Pointer to start of additional data tailroom or NULL. */ void *nlmsg_reserve(struct nl_msg *n, size_t len, int pad) { - void *tmp; + void *buf = n->nm_nlh; + size_t nlmsg_len = n->nm_nlh->nlmsg_len; size_t tlen; tlen = pad ? ((len + (pad - 1)) & ~(pad - 1)) : len; - tmp = realloc(n->nm_nlh, n->nm_nlh->nlmsg_len + tlen); - if (!tmp) { - nl_errno(ENOMEM); + if ((tlen + nlmsg_len) > n->nm_size) { + nl_errno(ENOBUFS); return NULL; } - n->nm_nlh = tmp; - tmp += n->nm_nlh->nlmsg_len; + buf += nlmsg_len; n->nm_nlh->nlmsg_len += tlen; if (tlen > len) - memset(tmp + len, 0, tlen - len); + memset(buf + len, 0, tlen - len); NL_DBG(2, "msg %p: Reserved %zu bytes, pad=%d, nlmsg_len=%d\n", n, len, pad, n->nm_nlh->nlmsg_len); - return tmp; + return buf; } /** @@ -518,9 +543,6 @@ void *nlmsg_reserve(struct nl_msg *n, size_t len, int pad) * Extends the netlink message as needed and appends the data of given * length to the message. * - * @note All existing pointers into the old data section may have - * become obsolete and illegal to reference after this call. - * * @return 0 on success or a negative error code */ int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad) @@ -417,10 +417,15 @@ int nl_send_simple(struct nl_handle *handle, int type, int flags, void *buf, if (!msg) return nl_errno(ENOMEM); - if (buf && size) - nlmsg_append(msg, buf, size, NLMSG_ALIGNTO); + if (buf && size) { + err = nlmsg_append(msg, buf, size, NLMSG_ALIGNTO); + if (err < 0) + goto errout; + } + err = nl_send_auto_complete(handle, msg); +errout: nlmsg_free(msg); return err; |