Advertisement
teknoraver

scm_rights

Mar 31st, 2025 (edited)
584
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 2.14 KB | None | 0 0
  1. #define _GNU_SOURCE
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include <fcntl.h>
  8. #include <errno.h>
  9. #include <sys/socket.h>
  10. #include <sys/wait.h>
  11.  
  12. #define pexit(msg) do { perror(msg); exit(1); } while (0)
  13.  
  14. static int sendfd(int sockfd, int fd)
  15. {
  16.     struct msghdr msg = { 0 };
  17.     struct cmsghdr *cmsg;
  18.     int err;
  19.     char iobuf;
  20.     struct iovec io = {
  21.         .iov_base = &iobuf,
  22.         .iov_len = sizeof(iobuf),
  23.     };
  24.     union {
  25.         char buf[CMSG_SPACE(sizeof(fd))];
  26.         struct cmsghdr align;
  27.     } u;
  28.  
  29.     msg.msg_iov = &io;
  30.     msg.msg_iovlen = 1;
  31.     msg.msg_control = u.buf;
  32.     msg.msg_controllen = sizeof(u.buf);
  33.     cmsg = CMSG_FIRSTHDR(&msg);
  34.     cmsg->cmsg_level = SOL_SOCKET;
  35.     cmsg->cmsg_type = SCM_RIGHTS;
  36.     cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
  37.  
  38.     /* Send the file descriptor with an empty message
  39.      * containing only the ancillary data. */
  40.     msg.msg_iov = NULL;
  41.     msg.msg_iovlen = 0;
  42.  
  43.     memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
  44.  
  45.     err = sendmsg(sockfd, &msg, 0);
  46.     if (err < 0)
  47.         pexit("sendmsg");
  48.  
  49.     if (err != msg.msg_iovlen)
  50.         pexit("sendmsg");
  51.  
  52.     return 0;
  53. }
  54.  
  55. static int recvfd(int sockfd)
  56. {
  57.     struct msghdr msg = { 0 };
  58.     struct cmsghdr *cmsg;
  59.     int err;
  60.     int fd;
  61.     union {
  62.         char buf[CMSG_SPACE(sizeof(fd))];
  63.         struct cmsghdr align;
  64.     } u;
  65.  
  66.     msg.msg_control = u.buf;
  67.     msg.msg_controllen = sizeof(u.buf);
  68.  
  69.     err = recvmsg(sockfd, &msg, 0);
  70.     if (err < 0)
  71.         pexit("recvmsg");
  72.  
  73.     cmsg = CMSG_FIRSTHDR(&msg);
  74.     if (!cmsg ||
  75.         cmsg->cmsg_len != CMSG_LEN(sizeof(fd)) ||
  76.         cmsg->cmsg_level != SOL_SOCKET ||
  77.         cmsg->cmsg_type != SCM_RIGHTS)
  78.         pexit("Invalid cmsg");
  79.  
  80.     memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd));
  81.  
  82.     return fd;
  83. }
  84.  
  85. int main(void)
  86. {
  87.     int scm_fds[2], r;
  88.  
  89.     r = socketpair(AF_UNIX, SOCK_STREAM, 0, scm_fds);
  90.     if (r < 0)
  91.         pexit("socketpair");
  92.    
  93.     if (fork()) {
  94.         int fd = open("/", O_PATH | O_DIRECTORY);
  95.  
  96.         if (fd < 0)
  97.             pexit("open");
  98.  
  99.         r = sendfd(scm_fds[0], fd);
  100.         if (r < 0)
  101.             pexit("sendfd");
  102.  
  103.         puts("sent fd");
  104.  
  105.     } else {
  106.         int fd = recvfd(scm_fds[1]);
  107.  
  108.         if (fd < 0)
  109.             pexit("recvfd");
  110.  
  111.         puts("received fd");
  112.        
  113.         exit(0);
  114.     }
  115.  
  116.     wait(NULL);
  117.     puts("done");
  118.  
  119.     return 0;
  120. }
  121.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement