Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define _GNU_SOURCE
- #include <errno.h>
- #include <fcntl.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdnoreturn.h>
- #include <sys/socket.h>
- #include <sys/socket.h>
- #include <sys/stat.h>
- #include <sys/syscall.h>
- #include <unistd.h>
- #define BPF_LD 0x00
- #define BPF_ALU 0x04
- #define BPF_RET 0x06
- #define BPF_B 0x10
- #define BPF_ABS 0x20
- #define BPF_ADD 0x00
- #define BPF_K 0x00
- #define BPF_A 0x10
- struct sock_filter {
- uint16_t code;
- uint8_t jt;
- uint8_t jf;
- uint32_t k;
- };
- struct sock_fprog {
- unsigned short len;
- struct sock_filter *filter;
- };
- #define ERR ((uint64_t)-4096)
- static uint64_t syscall0(uint64_t no) {
- uint64_t result;
- __asm__ volatile(
- "syscall"
- : "=a" (result)
- : "a" (no)
- : "rcx", "r11"
- );
- return result;
- }
- static uint64_t syscall1(uint64_t no, uint64_t arg0) {
- uint64_t result;
- __asm__ volatile(
- "syscall"
- : "=a" (result)
- : "a" (no), "D" (arg0)
- : "rcx", "r11"
- );
- return result;
- }
- static uint64_t syscall2(uint64_t no, uint64_t arg0, uint64_t arg1) {
- uint64_t result;
- __asm__ volatile(
- "syscall"
- : "=a" (result)
- : "a" (no), "D" (arg0), "S" (arg1)
- : "rcx", "r11"
- );
- return result;
- }
- static uint64_t syscall3(uint64_t no, uint64_t arg0, uint64_t arg1, uint64_t arg2) {
- uint64_t result;
- __asm__ volatile(
- "syscall"
- : "=a" (result)
- : "a" (no), "D" (arg0), "S" (arg1), "d" (arg2)
- : "rcx", "r11"
- );
- return result;
- }
- static uint64_t syscall5(uint64_t no, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4) {
- uint64_t result;
- register uint64_t r10 __asm__("r10") = arg3;
- register uint64_t r8 __asm__("r8") = arg4;
- __asm__ volatile(
- "syscall"
- : "=a" (result)
- : "a" (no), "D" (arg0), "S" (arg1), "d" (arg2), "r" (r10), "r" (r8)
- : "rcx", "r11"
- );
- return result;
- }
- static uint64_t syscall6(uint64_t no, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5) {
- uint64_t result;
- register uint64_t r10 __asm__("r10") = arg3;
- register uint64_t r8 __asm__("r8") = arg4;
- register uint64_t r9 __asm__("r9") = arg5;
- __asm__ volatile(
- "syscall"
- : "=a" (result)
- : "a" (no), "D" (arg0), "S" (arg1), "d" (arg2), "r" (r10), "r" (r8), "r" (r9)
- : "rcx", "r11"
- );
- return result;
- }
- static noreturn void do_exit(int status) {
- syscall1(SYS_exit_group, status);
- __builtin_unreachable();
- }
- static noreturn void do_err(uint64_t result) {
- #ifdef DEBUG
- errno = -result;
- perror(NULL);
- #else
- (void)result;
- #endif
- do_exit(-1);
- }
- static int create_pipe(void) {
- static const char PATHNAME[] = "/tmp/.anon-fifo";
- uint64_t result;
- while ((result = syscall2(SYS_mknod, (uintptr_t)PATHNAME, S_IFIFO|S_IRUSR|S_IWUSR)) != 0) {
- if (result != (uint64_t)-EEXIST) {
- do_err(result);
- }
- syscall0(SYS_sched_yield);
- }
- if ((result = syscall2(SYS_open, (uintptr_t)PATHNAME, O_RDWR|O_CLOEXEC)) > ERR) {
- syscall1(SYS_unlink, (uintptr_t)PATHNAME);
- do_err(result);
- }
- int pipefd = result;
- if ((result = syscall1(SYS_unlink, (uintptr_t)PATHNAME)) != 0) {
- syscall1(SYS_close, pipefd);
- do_err(result);
- }
- return pipefd;
- }
- static void stdin_to_pipe(int pipefd) {
- uint64_t result;
- if ((result = syscall6(SYS_splice, STDIN_FILENO, 0, pipefd, 0, 1, 0)) == 0) {
- if ((result = syscall1(SYS_close, pipefd)) != 0) {
- do_err(result);
- }
- do_exit(-1);
- } else if (result != 1) {
- syscall1(SYS_close, pipefd);
- do_err(result);
- }
- }
- static int create_socket(int pipefd) {
- static const struct sock_filter FILTER[] = {
- {BPF_LD|BPF_B|BPF_ABS, 0, 0, 0},
- {BPF_ALU|BPF_ADD|BPF_K, 0, 0, 1},
- {BPF_RET|BPF_A, 0, 0, 0}
- };
- static const struct sock_fprog FPROG = {3, (struct sock_filter *)FILTER};
- static const struct {
- sa_family_t sa_family;
- char sa_data[16];
- } ADDR = {AF_UNIX, "/tmp/.anon-sock"};
- uint64_t result;
- if ((result = syscall3(SYS_socket, AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) > ERR) {
- syscall1(SYS_close, pipefd);
- do_err(result);
- }
- int sockfd = result;
- if ((result = syscall5(SYS_setsockopt, sockfd, SOL_SOCKET, SO_ATTACH_FILTER, (uintptr_t)&FPROG, sizeof(struct sock_fprog))) != 0) {
- syscall1(SYS_close, sockfd);
- syscall1(SYS_close, pipefd);
- do_err(result);
- }
- while ((result = syscall3(SYS_bind, sockfd, (uintptr_t)&ADDR, sizeof ADDR)) != 0) {
- if (result != (uint64_t)-EADDRINUSE) {
- syscall1(SYS_close, sockfd);
- syscall1(SYS_close, pipefd);
- do_err(result);
- }
- syscall0(SYS_sched_yield);
- }
- if ((result = syscall3(SYS_connect, sockfd, (uintptr_t)&ADDR, sizeof ADDR)) != 0) {
- syscall1(SYS_unlink, (uintptr_t)&ADDR.sa_data);
- syscall1(SYS_close, sockfd);
- syscall1(SYS_close, pipefd);
- do_err(result);
- }
- if ((result = syscall1(SYS_unlink, (uintptr_t)&ADDR.sa_data)) != 0) {
- syscall1(SYS_close, sockfd);
- syscall1(SYS_close, pipefd);
- do_err(result);
- }
- return sockfd;
- }
- static void pipe_to_socket(int pipefd, int sockfd) {
- static const char PADDING[255] = {0};
- uint64_t result;
- if ((result = syscall3(SYS_write, pipefd, (uintptr_t)PADDING, 255)) != 255) {
- syscall1(SYS_close, sockfd);
- syscall1(SYS_close, pipefd);
- do_err(result > ERR ? result : (uint64_t)-EIO);
- }
- if ((result = syscall6(SYS_splice, pipefd, 0, sockfd, 0, 256, 0)) != 256) {
- syscall1(SYS_close, sockfd);
- syscall1(SYS_close, pipefd);
- do_err(result > ERR ? result : (uint64_t)-EIO);
- }
- }
- static unsigned char read_from_socket(int pipefd, int sockfd) {
- uint64_t result;
- if ((result = syscall6(SYS_splice, sockfd, 0, pipefd, 0, 256, 0)) == 0 || result > ERR) {
- syscall1(SYS_close, sockfd);
- syscall1(SYS_close, pipefd);
- do_err(result != 0 ? result : (uint64_t)-EIO);
- }
- return result - 1;
- }
- static void close_fds(int pipefd, int sockfd) {
- uint64_t result;
- if ((result = syscall1(SYS_close, sockfd)) != 0) {
- syscall1(SYS_close, pipefd);
- do_err(result);
- }
- if ((result = syscall1(SYS_close, pipefd)) != 0) {
- do_err(result);
- }
- }
- int main(void) {
- int pipefd = create_pipe();
- stdin_to_pipe(pipefd);
- int sockfd = create_socket(pipefd);
- pipe_to_socket(pipefd, sockfd);
- unsigned char c = read_from_socket(pipefd, sockfd);
- close_fds(pipefd, sockfd);
- do_exit(c);
- }
Advertisement
Add Comment
Please, Sign In to add comment