forked from lix-project/lix
It is possible to exfiltrate a file descriptor out of the build sandbox
of FODs, and use it to modify the store path after it has been
registered. To avoid that issue, don't register the output of the build,
but a copy of it (that will be free of any leaked file descriptor).
Test that we can't leverage abstract unix domain sockets to leak file
descriptors out of the sandbox and modify the path after it has been
registered.
(cherry picked from commit 2dadfeb690e7f4b8f97298e29791d202fdba5ca6)
(tests cherry picked from commit c854ae5b3078ac5d99fa75fe148005044809e18c)
Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io>
Co-authored-by: Theophane Hufschmitt <theophane.hufschmitt@tweag.io>
Co-authored-by: Tom Bereknyei <tomberek@gmail.com>
Change-Id: I87cd58f1c0a4f7b7a610d354206b33301e47b1a4
66 lines
1.9 KiB
C
66 lines
1.9 KiB
C
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
assert(argc == 2);
|
|
|
|
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
|
|
// Set up a abstract domain socket path to connect to.
|
|
struct sockaddr_un data;
|
|
data.sun_family = AF_UNIX;
|
|
data.sun_path[0] = 0;
|
|
strcpy(data.sun_path + 1, argv[1]);
|
|
|
|
// Now try to connect, To ensure we work no matter what order we are
|
|
// executed in, just busyloop here.
|
|
int res = -1;
|
|
while (res < 0) {
|
|
res = connect(sock, (const struct sockaddr *)&data,
|
|
offsetof(struct sockaddr_un, sun_path)
|
|
+ strlen(argv[1])
|
|
+ 1);
|
|
if (res < 0 && errno != ECONNREFUSED) perror("connect");
|
|
if (errno != ECONNREFUSED) break;
|
|
}
|
|
|
|
// Write our message header.
|
|
struct msghdr msg = {0};
|
|
msg.msg_control = malloc(128);
|
|
msg.msg_controllen = 128;
|
|
|
|
// Write an SCM_RIGHTS message containing the output path.
|
|
struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg);
|
|
hdr->cmsg_len = CMSG_LEN(sizeof(int));
|
|
hdr->cmsg_level = SOL_SOCKET;
|
|
hdr->cmsg_type = SCM_RIGHTS;
|
|
int fd = open(getenv("out"), O_RDWR | O_CREAT, 0640);
|
|
memcpy(CMSG_DATA(hdr), (void *)&fd, sizeof(int));
|
|
|
|
msg.msg_controllen = CMSG_SPACE(sizeof(int));
|
|
|
|
// Write a single null byte too.
|
|
msg.msg_iov = malloc(sizeof(struct iovec));
|
|
msg.msg_iov[0].iov_base = "";
|
|
msg.msg_iov[0].iov_len = 1;
|
|
msg.msg_iovlen = 1;
|
|
|
|
// Send it to the othher side of this connection.
|
|
res = sendmsg(sock, &msg, 0);
|
|
if (res < 0) perror("sendmsg");
|
|
int buf;
|
|
|
|
// Wait for the server to close the socket, implying that it has
|
|
// received the commmand.
|
|
recv(sock, (void *)&buf, sizeof(int), 0);
|
|
}
|