Verified Commit 4f459618 authored by Alberto Miranda's avatar Alberto Miranda ♨️
Browse files

Handle extra internal fds passed ini recvmsg()

Fixes #64.
parent e65f4053
Loading
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@
#include <syscall.h>
#include <errno.h>
#include <boost/optional.hpp>
#include <sys/types.h>
#include <sys/socket.h>

#include <printf.h>

@@ -303,6 +305,43 @@ hook_internal(long syscall_number,
            }
            break;

        case SYS_recvmsg:
        {
            *result = syscall_no_intercept(syscall_number,
                                        static_cast<int>(arg0),
                                        reinterpret_cast<struct msghdr*>(arg1),
                                        static_cast<int>(arg2));

            // The recvmsg() syscall can receive file descriptors from another
            // process that the kernel automatically adds to the client's fds
            // as if dup2 had been called. Whenever that happens, we need to
            // make sure that we register these additional fds as internal, or
            // we could inadvertently overwrite them
            if(*result >= 0) {
                auto* hdr = reinterpret_cast<struct msghdr*>(arg1);
                struct cmsghdr* cmsg = CMSG_FIRSTHDR(hdr);

                for(; cmsg != NULL; cmsg = CMSG_NXTHDR(hdr, cmsg)) {
                    if(cmsg->cmsg_type == SCM_RIGHTS) {

                        size_t nfd = cmsg->cmsg_len > CMSG_LEN(0) ? 
                            (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int) : 
                            0;

                        const int* fds = 
                            reinterpret_cast<int*>(CMSG_DATA(cmsg));

                        for(size_t i = 0; i < nfd; ++i) {
                            LOG(DEBUG, "recvmsg() provided extra fd {}", fds[i]);
                            CTX->register_internal_fd(fds[i]);
                        }
                    }
                }
            }

            break;
        }

        case SYS_accept:
            *result = syscall_no_intercept(syscall_number,
                                           static_cast<int>(arg0),