Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net: socket: Incorrect msg_iovlen value with TCP Sockets in zsock_recvmsg() #84475

Open
skryjapetr opened this issue Jan 24, 2025 · 4 comments
Open
Assignees
Labels
area: Networking bug The issue is a bug, or the PR is fixing a bug

Comments

@skryjapetr
Copy link

Describe the bug
The function ssize_t zsock_recvmsg(int sock, struct msghdr *msg, int flags) is expected to receive data and store it into buffers specified by the msg->msg_iov array. The msg->msg_iovlen field indicates the number of buffers in the array. However, when using a TCP socket, the msg->msg_iovlen value is incorrectly updated after a successful receive operation, reducing its value unexpectedly. This issue does not occur with UDP sockets.

To Reproduce

  1. Set up a UDP socket.
  2. Prepare a struct msghdr with two buffers specified in msg_iov:
    • Buffer 1: 5 bytes
    • Buffer 2: 5 bytes
    • Set msg->msg_iovlen = 2.
  3. Send a 10-byte message from peer socket.
  4. Call zsock_recvmsg() on the client to receive the message.
  5. Check msg->msg_iovlen value
  6. Set up a TCP socket and connect to a server
  7. Repeat steps 1-5 with the TCP socket

Expected behavior

  • msg->msg_iovlen remains unchanged at 2 as two buffers were used for storing the data

Impact
This bug causes confusion and potential misinterpretation of the msg->msg_iovlen value, particularly in cases where applications rely on it to verify the number of buffers used for data storage.

Environment (please complete the following information):

  • OS: Linux
  • Toolchain Zephyr SDK 4.0

Additional context
The msg_iovlen is modified in function zsock_recv_stream_timed() in module subsys/net/lib/sockets/sockets_inet.c.

The code:

if (iovec == max_iovlen) {
	break;
}

should be probably moved after msg->msg_iovlen = iovec; in order to fix this issue.

@skryjapetr skryjapetr added the bug The issue is a bug, or the PR is fixing a bug label Jan 24, 2025
Copy link

Hi @skryjapetr! We appreciate you submitting your first issue for our open-source project. 🌟

Even though I'm a bot, I can assure you that the whole community is genuinely grateful for your time and effort. 🤖💙

@rlubos
Copy link
Contributor

rlubos commented Jan 24, 2025

Actually, I wonder if zsock_recvmsg() should modify msg->msg_iovlen or msg_iov[n].iov_len at all? I could not find a mention of such behavior in https://linux.die.net/man/3/recvmsg.

Also, I've tested how recvmsg() for TCP socket behaves in Linux with a simple app, and it does seem to leave those fields intact, regardless of the amount of bytes received. The number of bytes received is placed in the return value. That should be enough for the application to determine which buffers got filled, given this takes place in a continuous manner.

@jukkar
Copy link
Member

jukkar commented Jan 24, 2025

Actually, I wonder if zsock_recvmsg() should modify msg->msg_iovlen or msg_iov[n].iov_len at all?

That is a good point. It is better not to modify the msg fields so that user can call the recvmsg() again with same msg without needing to "reset" the lengths.

@skryjapetr
Copy link
Author

@rlubos @jukkar that makes sense to me. If so decided, the function zsock_recv_dgram(), which is called when doing recvmsg with a UDP socket, should also be fixed, because this function also modifies msg->msg_iovlen and msg_iov[n].iov_len.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Networking bug The issue is a bug, or the PR is fixing a bug
Projects
None yet
Development

No branches or pull requests

4 participants