123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- /* vim: set expandtab ts=4 sw=4: */
- /*
- * You may redistribute this program and/or modify it under the terms of
- * the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include "util/Seccomp.h"
- // SIG_UNBLOCK
- #define _POSIX_SOURCE
- #include <signal.h>
- // getpriority()
- #include <sys/resource.h>
- #include <errno.h>
- #include <seccomp.h>
- #include <stddef.h>
- void Seccomp_dropPermissions(struct Except* eh)
- {
- scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_TRAP);
- if (!ctx) {
- seccomp_release(ctx);
- Except_throw(eh, "Failed to initialize SECCOMP");
- }
- int rc = 0;
- // Adding exceptions to the syscall filter:
- //
- // echo '#include <seccomp.h>' | gcc -E -dM - | grep 'define __NR_' | sort
- // for the full list of system calls with syscall numbers (different per ABI)
- //
- // If gdb traps out it will look like this:
- //
- // Program received signal SIGSYS, Bad system call.
- // [Switching to Thread 0x7ffff7fdd740 (LWP 14673)]
- // 0x00007ffff74d1caa in mmap64 () at ../sysdeps/unix/syscall-template.S:81
- // 81 ../sysdeps/unix/syscall-template.S: No such file or directory.
- //
- // %eax should contain the system call number (on different ABIs YMMV)
- //
- // (gdb) print $eax
- // $1 = 9
- // (gdb)
- //
- // Consult your syscall table from the above gcc command...
- //
- // #define __NR_mmap 9
- //
- // Then add:
- //
- // rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0);
- //
- // And add a comment documenting where you needed that syscall :)
- // see seccomp.h:307 and "man seccomp_rule_add" for docs on this function
- // libuv
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl), 0);
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_wait), 0);
- // logging to stdout/stderr, tun and eth0
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
- // tun device and eth0
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
- // malloc()
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);
- // udp
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sendmsg), 0);
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(recvmsg), 0);
- // ETHInterface
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sendto), 0);
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(recvfrom), 0);
- // abort()
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(gettid), 0);
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(tgkill), 0);
- rc |= seccomp_rule_add(ctx,
- SCMP_ACT_ALLOW,
- SCMP_SYS(rt_sigprocmask),
- 1,
- SCMP_CMP(0, SCMP_CMP_EQ, SIG_UNBLOCK, 0));
- // exit()
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
- // Seccomp_isWorking()
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ERRNO(9000), SCMP_SYS(getpriority), 0);
- // Securiy_checkPermissions() -> canOpenFiles()
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup), 0);
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
- // Security_checkPermissions() -> getMaxMem()
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getrlimit), 0);
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0);
- // printf
- rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0);
- /////
- char* err = NULL;
- if (rc) {
- err = "Failed to add SECCOMP filters";
- } else if (seccomp_load(ctx)) {
- err = "Failed to load SECCOMP";
- }
- seccomp_release(ctx);
- if (err) {
- Except_throw(eh, "%s", err);
- } else if (!Seccomp_isWorking()) {
- Except_throw(eh, "SECCOMP is not working correctly");
- }
- }
- int Seccomp_isWorking()
- {
- errno = 0;
- // If seccomp is not working, this will fail setting errno to EINVAL
- long ret = getpriority(1000, 1);
- // Inside of the kernel, it seems to check whether the errno return is sane
- // and if it is not, it treates it as a return value, 9000 is very unique so
- // we'll check for either case just in case this changes.
- return (ret == -1 && errno == 9000) || (ret == -9000 && errno == 0);
- }
|