[Bug 1691] New: mnl_nlmsg_ok returns true on malformed/incomplete messages leading to potential runtime issues
bugzilla-daemon at netfilter.org
bugzilla-daemon at netfilter.org
Mon Jul 3 09:31:37 CEST 2023
https://bugzilla.netfilter.org/show_bug.cgi?id=1691
Bug ID: 1691
Summary: mnl_nlmsg_ok returns true on malformed/incomplete
messages leading to potential runtime issues
Product: libmnl
Version: unspecified
Hardware: x86_64
OS: All
Status: NEW
Severity: normal
Priority: P5
Component: libmnl
Assignee: pablo at netfilter.org
Reporter: eliogovea1993 at gmail.com
Consider the following example:
source:
```
#include <linux/netfilter.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <libmnl/libmnl.h>
int main(int argc, char** argv) {
const struct nlmsghdr header = {
.nlmsg_len = 0xFFFFFFFF,
.nlmsg_type = 0x0000,
.nlmsg_flags = 0x0000,
.nlmsg_seq = 0x00000000,
.nlmsg_pid = 0x00000000
};
assert(!mnl_nlmsg_ok(&header, sizeof(struct nlmsghdr)));
return EXIT_SUCCESS;
}
```
output:
```
parse-header: parse-header.c:19: main: Assertion `!mnl_nlmsg_ok(&header,
sizeof(struct nlmsghdr))' failed.
Aborted (core dumped)
```
The previous example has a malformed message, the "buffer" used as argument for
"mnl_nlmsg_ok" doesn't hold a complete message (length "0xFFFFFFFF" is higher
than sizeof(header)), yet the function returns true. It seems unlikely that a
message will have that "nlmsg_len" in the header, but this report assumes that
such bytes are possible while parsing, and a parser using libmnl must correctly
identify any incomplete messages.
Looking at the source code
```
EXPORT_SYMBOL bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len)
{
return len >= (int)sizeof(struct nlmsghdr) &&
nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
(int)nlh->nlmsg_len <= len;
}
```
The last line casts "nlh->nlmsg_len" to "int", but that value can't be stored
in an "int" and casting it makes its value negative. To fix it, consider the
following patch:
```
diff --git a/src/nlmsg.c b/src/nlmsg.c
index c634501..8d0107f 100644
--- a/src/nlmsg.c
+++ b/src/nlmsg.c
@@ -154,7 +154,7 @@ EXPORT_SYMBOL bool mnl_nlmsg_ok(const struct nlmsghdr *nlh,
int len)
{
return len >= (int)sizeof(struct nlmsghdr) &&
nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
- (int)nlh->nlmsg_len <= len;
+ nlh->nlmsg_len <= (unsigned int)len;
}
/**
Casting "len" to "unsigned int" would be correct since the first line already
checks that it is positive.
Since "mnl_nlmsg_ok" is used in a while loop in "__mnl_cb_run", parsing
malformed messages like the previous one will try to dereference a "struct
nlmsghdr*" out of the limits of the message buffer.
```
--
You are receiving this mail because:
You are watching all bug changes.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.netfilter.org/pipermail/netfilter-buglog/attachments/20230703/aab736ac/attachment.html>
More information about the netfilter-buglog
mailing list