(root)/
glibc-2.38/
socket/
tst-cmsg_cloexec.c
       1  /* Smoke test for MSG_CMSG_CLOEXEC.
       2     Copyright (C) 2021-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <support/xunistd.h>
      20  #include <support/check.h>
      21  #include <sys/socket.h>
      22  #include <sys/un.h>
      23  #include <string.h>
      24  #include <fcntl.h>
      25  
      26  static void
      27  send_fd (int sockfd, int fd)
      28  {
      29    char data[] = "hello";
      30    struct iovec iov = { .iov_base = data, .iov_len = sizeof (data) };
      31  
      32    union
      33    {
      34      struct cmsghdr header;
      35      char bytes[CMSG_SPACE (sizeof (fd))];
      36    } cmsg_storage;
      37  
      38    struct msghdr msg =
      39      {
      40        .msg_iov = &iov,
      41        .msg_iovlen = 1,
      42        .msg_control = cmsg_storage.bytes,
      43        .msg_controllen = sizeof (cmsg_storage)
      44      };
      45  
      46    memset (&cmsg_storage, 0, sizeof (cmsg_storage));
      47  
      48    struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
      49    cmsg->cmsg_level = SOL_SOCKET;
      50    cmsg->cmsg_type = SCM_RIGHTS;
      51    cmsg->cmsg_len = CMSG_LEN (sizeof (fd));
      52    memcpy (CMSG_DATA (cmsg), &fd, sizeof (fd));
      53  
      54    ssize_t nsent = sendmsg (sockfd, &msg, 0);
      55    if (nsent < 0)
      56      FAIL_EXIT1 ("sendmsg (%d): %m", sockfd);
      57    TEST_COMPARE (nsent, sizeof (data));
      58  }
      59  
      60  static int
      61  recv_fd (int sockfd, int flags)
      62  {
      63    char buffer[100];
      64    struct iovec iov = { .iov_base = buffer, .iov_len = sizeof (buffer) };
      65  
      66    union
      67    {
      68      struct cmsghdr header;
      69      char bytes[100];
      70    } cmsg_storage;
      71  
      72    struct msghdr msg =
      73      {
      74        .msg_iov = &iov,
      75        .msg_iovlen = 1,
      76        .msg_control = cmsg_storage.bytes,
      77        .msg_controllen = sizeof (cmsg_storage)
      78      };
      79  
      80    ssize_t nrecv = recvmsg (sockfd, &msg, flags);
      81    if (nrecv < 0)
      82      FAIL_EXIT1 ("recvmsg (%d): %m", sockfd);
      83  
      84    TEST_COMPARE (msg.msg_controllen, CMSG_SPACE (sizeof (int)));
      85    struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
      86    TEST_COMPARE (cmsg->cmsg_level, SOL_SOCKET);
      87    TEST_COMPARE (cmsg->cmsg_type, SCM_RIGHTS);
      88    TEST_COMPARE (cmsg->cmsg_len, CMSG_LEN (sizeof (int)));
      89  
      90    int fd;
      91    memcpy (&fd, CMSG_DATA (cmsg), sizeof (fd));
      92    return fd;
      93  }
      94  
      95  static int
      96  do_test (void)
      97  {
      98    int sockfd[2];
      99    int newfd;
     100    int flags;
     101    int rc = socketpair (AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0, sockfd);
     102    if (rc < 0)
     103      FAIL_EXIT1 ("socketpair: %m");
     104  
     105    send_fd (sockfd[1], STDIN_FILENO);
     106    newfd = recv_fd (sockfd[0], 0);
     107    TEST_VERIFY_EXIT (newfd > 0);
     108    flags = fcntl (newfd, F_GETFD, 0);
     109    TEST_VERIFY_EXIT (flags != -1);
     110    TEST_VERIFY (!(flags & FD_CLOEXEC));
     111    xclose (newfd);
     112  
     113    send_fd (sockfd[1], STDIN_FILENO);
     114    newfd = recv_fd (sockfd[0], MSG_CMSG_CLOEXEC);
     115    TEST_VERIFY_EXIT (newfd > 0);
     116    flags = fcntl (newfd, F_GETFD, 0);
     117    TEST_VERIFY_EXIT (flags != -1);
     118    TEST_VERIFY (flags & FD_CLOEXEC);
     119    xclose (newfd);
     120  
     121    xclose (sockfd[0]);
     122    xclose (sockfd[1]);
     123    return 0;
     124  }
     125  
     126  #include <support/test-driver.c>