Home > Mobile >  C/C recvmsg() causes error 'unaligned tcache chunk detected' but recv() is successful
C/C recvmsg() causes error 'unaligned tcache chunk detected' but recv() is successful

Time:09-25

I observe the below error when receiving UDP packets via Epoll:

'unaligned tcache chunk detected'

I've managed to locate which part of the code but it doesn't make much sense.

This is the original code:

while (_listen)
{
    const int count = epoll_wait(_epollFd, &events[0], MAX_SOCKETS, -1);
    assert(count != -1);

    for (int j = 0; j < count;   j)
    {
        iovec iov;
        char control[1024];

        msghdr msg;

        iov.iov_base = _buffer;
        iov.iov_len = sizeof(_buffer);
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
        msg.msg_namelen = sizeof(sockaddr_in);
        msg.msg_control = &control[0];
        msg.msg_controllen = 1024;

        const int sock = events[j].data.fd;
        const int64_t n = recvmsg(sock, &msg, 0);   // This line seems to cause the problem
        // More code
    }
}

_buffer is a class member declared as: char _buffer[65'536];

By trial and error I narrowed the problem to this line:

const int64_t n = recvmsg(sock, &msg, 0);

So I replaced ::recvmsg() with a call to ::recv() and it runs successfully:

while (_listen)
{
    const int count = epoll_wait(_epollFd, &events[0], MAX_SOCKETS, -1);
    assert(count != -1);

    for (int j = 0; j < count;   j)
    {
        const int sock = events[j].data.fd;
        const int64_t n = recv(sock, _buffer, sizeof(_buffer), 0);
        // More code
    }
}

Now the problem doesn't occur. What is causing this?

I'd like to understand why the first code doesn't work. The only memory is _buffer and that's not manually allocated.

(Unfortunately I cannot use a sanitize build due to the environment/build system).

CodePudding user response:

In your code you forgot to set member msg_name of the struct msg:

iovec iov;
char control[1024];
msghdr msg;

// add the following line:
sockaddr_in addr;

iov.iov_base = _buffer;
iov.iov_len = sizeof(_buffer);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = &control[0];
msg.msg_controllen = 1024;

// set the following members:
msg.msg_name = &addr;
msg.msg_namelen = sizeof(addr);

const int sock = events[j].data.fd;
const int64_t n = recvmsg(sock, &msg, 0);

// More code

The reason you had memory corruption is because you had undefined behavior: recvmsg() tried to write to pointer msg.msg_name, but the latter contained an uninitialized memory address, so recvmsg() was actually writing to an invalid location.

recvmsg() writes information about the host that sent the message inside msg.msg_name.

  • Related