teknoraver icon

scm_rights

teknoraver | PRO | 03/31/25 06:24:49 PM UTC (Edited) | 0 ⭐ | 14455 👁️ | Never ⏰ | []
C |

2.14 KB

|

None

|

0 👍

/

0 👎

#define _GNU_SOURCE
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/wait.h>
 
#define pexit(msg) do { perror(msg); exit(1); } while (0)
 
static int sendfd(int sockfd, int fd)
{
    struct msghdr msg = { 0 };
    struct cmsghdr *cmsg;
    int err;
    char iobuf;
    struct iovec io = {
        .iov_base = &iobuf,
        .iov_len = sizeof(iobuf),
    };
    union {
        char buf[CMSG_SPACE(sizeof(fd))];
        struct cmsghdr align;
    } u;
 
    msg.msg_iov = &io;
    msg.msg_iovlen = 1;
    msg.msg_control = u.buf;
    msg.msg_controllen = sizeof(u.buf);
    cmsg = CMSG_FIRSTHDR(&msg);
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;
    cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
 
    /* Send the file descriptor with an empty message
     * containing only the ancillary data. */
    msg.msg_iov = NULL;
    msg.msg_iovlen = 0;
 
    memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
 
    err = sendmsg(sockfd, &msg, 0);
    if (err < 0)
        pexit("sendmsg");
 
    if (err != msg.msg_iovlen)
        pexit("sendmsg");
 
    return 0;
}
 
static int recvfd(int sockfd)
{
    struct msghdr msg = { 0 };
    struct cmsghdr *cmsg;
    int err;
    int fd;
    union {
        char buf[CMSG_SPACE(sizeof(fd))];
        struct cmsghdr align;
    } u;
 
    msg.msg_control = u.buf;
    msg.msg_controllen = sizeof(u.buf);
 
    err = recvmsg(sockfd, &msg, 0);
    if (err < 0)
        pexit("recvmsg");
 
    cmsg = CMSG_FIRSTHDR(&msg);
    if (!cmsg ||
        cmsg->cmsg_len != CMSG_LEN(sizeof(fd)) ||
        cmsg->cmsg_level != SOL_SOCKET ||
        cmsg->cmsg_type != SCM_RIGHTS)
        pexit("Invalid cmsg");
 
    memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd));
 
    return fd;
}
 
int main(void)
{
    int scm_fds[2], r;
 
    r = socketpair(AF_UNIX, SOCK_STREAM, 0, scm_fds);
    if (r < 0)
        pexit("socketpair");
    
    if (fork()) {
        int fd = open("/", O_PATH | O_DIRECTORY);
 
        if (fd < 0)
            pexit("open");
 
        r = sendfd(scm_fds[0], fd);
        if (r < 0)
            pexit("sendfd");
 
        puts("sent fd");
 
    } else {
        int fd = recvfd(scm_fds[1]);
 
        if (fd < 0)
            pexit("recvfd");
 
        puts("received fd");
        
        exit(0);
    }
 
    wait(NULL);
    puts("done");
 
    return 0;
}
 

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎