Reputation: 118
I am working on a Linux kernel module which has a bi-directional communication link with a userspace module provided by netlink.
I have an issue with an incorrect message length calculation on messages sent from userspace to kernel space. The message is sent from userspace like this:
this->sendLock.lock();
this->netlinkTxHeader->nlmsg_len = NLMSG_SPACE(len);
this->netlinkTxIov.iov_len = this->netlinkTxHeader->nlmsg_len;
memcpy(NLMSG_DATA(this->netlinkTxHeader), buf, len);
int32_t status = sendmsg(this->netlinkSock, &this->netlinkTxMsg, 0);
And is received in kernel space like this:
unsigned char* buf = (unsigned char*)NLMSG_DATA(nlh);
int len = NLMSG_PAYLOAD(nlh, 0);
However the calculated value of len
always seems to be the aligned size, which I don't want. For example, I can see from debug information that the userspace process sends a message with a payload of 14 bytes (excluding netlink headers). When this is received in the kernel module, however, NLMSG_PAYLOAD
returns a length of 16 bytes.
Is there any way to get the unaligned payload length (i.e. the actual payload length) back in the kernel module? I looked through the macros in netlink.h
but I don't see anything which would help.
Note that the nlmsghdr
object is derived using the netlink_rcv_skb()
function in the kernel module.
The only other way I can see to fix this is to prefix the actual length in the payload information which I think would work, but doesn't really feel "correct".
Upvotes: 0
Views: 494
Reputation: 39406
See man 3 netlink: you need to use NLMSG_LENGTH(len)
(and not NLMSG_SPACE(len)
) to calculate the nlmsg_len
field of the nlmsghdr
.
Upvotes: 1