Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Seccomp BPF example using a macro-based generator.
0004  *
0005  * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
0006  * Author: Will Drewry <wad@chromium.org>
0007  *
0008  * The code may be used by anyone for any purpose,
0009  * and can serve as a starting point for developing
0010  * applications using prctl(PR_ATTACH_SECCOMP_FILTER).
0011  */
0012 
0013 #include <linux/filter.h>
0014 #include <linux/seccomp.h>
0015 #include <linux/unistd.h>
0016 #include <stdio.h>
0017 #include <string.h>
0018 #include <sys/prctl.h>
0019 #include <unistd.h>
0020 
0021 #include "bpf-helper.h"
0022 
0023 #ifndef PR_SET_NO_NEW_PRIVS
0024 #define PR_SET_NO_NEW_PRIVS 38
0025 #endif
0026 
0027 int main(int argc, char **argv)
0028 {
0029     struct bpf_labels l = {
0030         .count = 0,
0031     };
0032     static const char msg1[] = "Please type something: ";
0033     static const char msg2[] = "You typed: ";
0034     char buf[256];
0035     struct sock_filter filter[] = {
0036         /* TODO: LOAD_SYSCALL_NR(arch) and enforce an arch */
0037         LOAD_SYSCALL_NR,
0038         SYSCALL(__NR_exit, ALLOW),
0039         SYSCALL(__NR_exit_group, ALLOW),
0040         SYSCALL(__NR_write, JUMP(&l, write_fd)),
0041         SYSCALL(__NR_read, JUMP(&l, read)),
0042         DENY,  /* Don't passthrough into a label */
0043 
0044         LABEL(&l, read),
0045         ARG(0),
0046         JNE(STDIN_FILENO, DENY),
0047         ARG(1),
0048         JNE((unsigned long)buf, DENY),
0049         ARG(2),
0050         JGE(sizeof(buf), DENY),
0051         ALLOW,
0052 
0053         LABEL(&l, write_fd),
0054         ARG(0),
0055         JEQ(STDOUT_FILENO, JUMP(&l, write_buf)),
0056         JEQ(STDERR_FILENO, JUMP(&l, write_buf)),
0057         DENY,
0058 
0059         LABEL(&l, write_buf),
0060         ARG(1),
0061         JEQ((unsigned long)msg1, JUMP(&l, msg1_len)),
0062         JEQ((unsigned long)msg2, JUMP(&l, msg2_len)),
0063         JEQ((unsigned long)buf, JUMP(&l, buf_len)),
0064         DENY,
0065 
0066         LABEL(&l, msg1_len),
0067         ARG(2),
0068         JLT(sizeof(msg1), ALLOW),
0069         DENY,
0070 
0071         LABEL(&l, msg2_len),
0072         ARG(2),
0073         JLT(sizeof(msg2), ALLOW),
0074         DENY,
0075 
0076         LABEL(&l, buf_len),
0077         ARG(2),
0078         JLT(sizeof(buf), ALLOW),
0079         DENY,
0080     };
0081     struct sock_fprog prog = {
0082         .filter = filter,
0083         .len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
0084     };
0085     ssize_t bytes;
0086     bpf_resolve_jumps(&l, filter, sizeof(filter)/sizeof(*filter));
0087 
0088     if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
0089         perror("prctl(NO_NEW_PRIVS)");
0090         return 1;
0091     }
0092 
0093     if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
0094         perror("prctl(SECCOMP)");
0095         return 1;
0096     }
0097     syscall(__NR_write, STDOUT_FILENO, msg1, strlen(msg1));
0098     bytes = syscall(__NR_read, STDIN_FILENO, buf, sizeof(buf)-1);
0099     bytes = (bytes > 0 ? bytes : 0);
0100     syscall(__NR_write, STDERR_FILENO, msg2, strlen(msg2));
0101     syscall(__NR_write, STDERR_FILENO, buf, bytes);
0102     /* Now get killed */
0103     syscall(__NR_write, STDERR_FILENO, msg2, strlen(msg2)+2);
0104     return 0;
0105 }