Loading changes/aarch64_sandbox 0 → 100644 +5 −0 Original line number Diff line number Diff line o Minor bugfixes (sandbox): - Fix sandbox support on AArch64 systems. More "*at" variants of syscalls are now supported. Signed 32 bit syscall parameters are checked more precisely, which should lead to lower likelihood of breakages with future compiler and libc releases. Fixes bug 40599; bugfix on 0.4.4.3-alpha. src/lib/sandbox/sandbox.c +112 −16 Original line number Diff line number Diff line Loading @@ -141,10 +141,12 @@ static sandbox_cfg_t *filter_dynamic = NULL; * the high bits of the value might get masked out improperly. */ #define SCMP_CMP_MASKED(a,b,c) \ SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, ~(scmp_datum_t)(b), (c)) /* For negative constants, the rule to add depends on the glibc version. */ #define SCMP_CMP_NEG(a,op,b) (libc_negative_constant_needs_cast() ? \ (SCMP_CMP((a), (op), (unsigned int)(b))) : \ (SCMP_CMP_STR((a), (op), (b)))) /* Negative constants aren't consistently sign extended or zero extended. * Different compilers, libc, and architectures behave differently. For cases * where the kernel ABI uses a 32 bit integer, this macro can be used to * mask-compare only the lower 32 bits of the value. */ #define SCMP_CMP_LOWER32_EQ(a,b) \ SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, 0xFFFFFFFF, (unsigned int)(b)) /** Variable used for storing all syscall numbers that will be allowed with the * stage 1 general Tor sandbox. Loading Loading @@ -513,14 +515,6 @@ libc_uses_openat_for_opendir(void) (is_libc_at_least(2, 15) && !is_libc_at_least(2, 22)); } /* Return true if we think we're running with a libc that needs to cast * negative arguments like AT_FDCWD for seccomp rules. */ static int libc_negative_constant_needs_cast(void) { return is_libc_at_least(2, 27); } /** Allow a single file to be opened. If <b>use_openat</b> is true, * we're using a libc that remaps all the opens into openats. */ static int Loading @@ -528,7 +522,7 @@ allow_file_open(scmp_filter_ctx ctx, int use_openat, const char *file) { if (use_openat) { return seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), SCMP_CMP_NEG(0, SCMP_CMP_EQ, AT_FDCWD), SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), SCMP_CMP_STR(1, SCMP_CMP_EQ, file)); } else { return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), Loading Loading @@ -609,6 +603,32 @@ sb_chmod(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } static int sb_fchmodat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc; sandbox_cfg_t *elem = NULL; // for each dynamic parameter filters for (elem = filter; elem != NULL; elem = elem->next) { smp_param_t *param = elem->param; if (param != NULL && param->prot == 1 && param->syscall == SCMP_SYS(fchmodat)) { rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchmodat), SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add fchmodat syscall, received " "libseccomp error %d", rc); return rc; } } } return 0; } #ifdef __i386__ static int sb_chown32(scmp_filter_ctx ctx, sandbox_cfg_t *filter) Loading Loading @@ -661,6 +681,32 @@ sb_chown(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } #endif /* defined(__i386__) */ static int sb_fchownat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc; sandbox_cfg_t *elem = NULL; // for each dynamic parameter filters for (elem = filter; elem != NULL; elem = elem->next) { smp_param_t *param = elem->param; if (param != NULL && param->prot == 1 && param->syscall == SCMP_SYS(fchownat)) { rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchownat), SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add fchownat syscall, received " "libseccomp error %d", rc); return rc; } } } return 0; } /** * Function responsible for setting up the rename syscall for * the seccomp filter sandbox. Loading Loading @@ -692,6 +738,39 @@ sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } /** * Function responsible for setting up the renameat syscall for * the seccomp filter sandbox. */ static int sb_renameat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc; sandbox_cfg_t *elem = NULL; // for each dynamic parameter filters for (elem = filter; elem != NULL; elem = elem->next) { smp_param_t *param = elem->param; if (param != NULL && param->prot == 1 && param->syscall == SCMP_SYS(renameat)) { rc = seccomp_rule_add_4(ctx, SCMP_ACT_ALLOW, SCMP_SYS(renameat), SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value), SCMP_CMP_LOWER32_EQ(2, AT_FDCWD), SCMP_CMP_STR(3, SCMP_CMP_EQ, param->value2)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add renameat syscall, received " "libseccomp error %d", rc); return rc; } } } return 0; } /** * Function responsible for setting up the openat syscall for * the seccomp filter sandbox. Loading @@ -709,7 +788,7 @@ sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (param != NULL && param->prot == 1 && param->syscall == SCMP_SYS(openat)) { rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), SCMP_CMP_NEG(0, SCMP_CMP_EQ, AT_FDCWD), SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value), SCMP_CMP(2, SCMP_CMP_EQ, O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY| O_CLOEXEC)); Loading Loading @@ -1312,7 +1391,9 @@ static sandbox_filter_func_t filter_func[] = { #else sb_chown, #endif sb_fchownat, sb_chmod, sb_fchmodat, sb_open, sb_openat, sb_opendir, Loading @@ -1320,6 +1401,7 @@ static sandbox_filter_func_t filter_func[] = { sb_ptrace, #endif sb_rename, sb_renameat, #ifdef __NR_fcntl64 sb_fcntl64, #endif Loading Loading @@ -1587,10 +1669,24 @@ new_element(int syscall, char *value) #ifdef __i386__ #define SCMP_chown SCMP_SYS(chown32) #elif defined(__aarch64__) && defined(__LP64__) #define SCMP_chown SCMP_SYS(fchownat) #else #define SCMP_chown SCMP_SYS(chown) #endif #if defined(__aarch64__) && defined(__LP64__) #define SCMP_chmod SCMP_SYS(fchmodat) #else #define SCMP_chmod SCMP_SYS(chmod) #endif #if defined(__aarch64__) && defined(__LP64__) #define SCMP_rename SCMP_SYS(renameat) #else #define SCMP_rename SCMP_SYS(rename) #endif #ifdef __NR_stat64 #define SCMP_stat SCMP_SYS(stat64) #else Loading Loading @@ -1628,7 +1724,7 @@ sandbox_cfg_allow_chmod_filename(sandbox_cfg_t **cfg, char *file) { sandbox_cfg_t *elem = NULL; elem = new_element(SCMP_SYS(chmod), file); elem = new_element(SCMP_chmod, file); elem->next = *cfg; *cfg = elem; Loading @@ -1654,7 +1750,7 @@ sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2) { sandbox_cfg_t *elem = NULL; elem = new_element2(SCMP_SYS(rename), file1, file2); elem = new_element2(SCMP_rename, file1, file2); elem->next = *cfg; *cfg = elem; Loading Loading
changes/aarch64_sandbox 0 → 100644 +5 −0 Original line number Diff line number Diff line o Minor bugfixes (sandbox): - Fix sandbox support on AArch64 systems. More "*at" variants of syscalls are now supported. Signed 32 bit syscall parameters are checked more precisely, which should lead to lower likelihood of breakages with future compiler and libc releases. Fixes bug 40599; bugfix on 0.4.4.3-alpha.
src/lib/sandbox/sandbox.c +112 −16 Original line number Diff line number Diff line Loading @@ -141,10 +141,12 @@ static sandbox_cfg_t *filter_dynamic = NULL; * the high bits of the value might get masked out improperly. */ #define SCMP_CMP_MASKED(a,b,c) \ SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, ~(scmp_datum_t)(b), (c)) /* For negative constants, the rule to add depends on the glibc version. */ #define SCMP_CMP_NEG(a,op,b) (libc_negative_constant_needs_cast() ? \ (SCMP_CMP((a), (op), (unsigned int)(b))) : \ (SCMP_CMP_STR((a), (op), (b)))) /* Negative constants aren't consistently sign extended or zero extended. * Different compilers, libc, and architectures behave differently. For cases * where the kernel ABI uses a 32 bit integer, this macro can be used to * mask-compare only the lower 32 bits of the value. */ #define SCMP_CMP_LOWER32_EQ(a,b) \ SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, 0xFFFFFFFF, (unsigned int)(b)) /** Variable used for storing all syscall numbers that will be allowed with the * stage 1 general Tor sandbox. Loading Loading @@ -513,14 +515,6 @@ libc_uses_openat_for_opendir(void) (is_libc_at_least(2, 15) && !is_libc_at_least(2, 22)); } /* Return true if we think we're running with a libc that needs to cast * negative arguments like AT_FDCWD for seccomp rules. */ static int libc_negative_constant_needs_cast(void) { return is_libc_at_least(2, 27); } /** Allow a single file to be opened. If <b>use_openat</b> is true, * we're using a libc that remaps all the opens into openats. */ static int Loading @@ -528,7 +522,7 @@ allow_file_open(scmp_filter_ctx ctx, int use_openat, const char *file) { if (use_openat) { return seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), SCMP_CMP_NEG(0, SCMP_CMP_EQ, AT_FDCWD), SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), SCMP_CMP_STR(1, SCMP_CMP_EQ, file)); } else { return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), Loading Loading @@ -609,6 +603,32 @@ sb_chmod(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } static int sb_fchmodat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc; sandbox_cfg_t *elem = NULL; // for each dynamic parameter filters for (elem = filter; elem != NULL; elem = elem->next) { smp_param_t *param = elem->param; if (param != NULL && param->prot == 1 && param->syscall == SCMP_SYS(fchmodat)) { rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchmodat), SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add fchmodat syscall, received " "libseccomp error %d", rc); return rc; } } } return 0; } #ifdef __i386__ static int sb_chown32(scmp_filter_ctx ctx, sandbox_cfg_t *filter) Loading Loading @@ -661,6 +681,32 @@ sb_chown(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } #endif /* defined(__i386__) */ static int sb_fchownat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc; sandbox_cfg_t *elem = NULL; // for each dynamic parameter filters for (elem = filter; elem != NULL; elem = elem->next) { smp_param_t *param = elem->param; if (param != NULL && param->prot == 1 && param->syscall == SCMP_SYS(fchownat)) { rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchownat), SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add fchownat syscall, received " "libseccomp error %d", rc); return rc; } } } return 0; } /** * Function responsible for setting up the rename syscall for * the seccomp filter sandbox. Loading Loading @@ -692,6 +738,39 @@ sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } /** * Function responsible for setting up the renameat syscall for * the seccomp filter sandbox. */ static int sb_renameat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc; sandbox_cfg_t *elem = NULL; // for each dynamic parameter filters for (elem = filter; elem != NULL; elem = elem->next) { smp_param_t *param = elem->param; if (param != NULL && param->prot == 1 && param->syscall == SCMP_SYS(renameat)) { rc = seccomp_rule_add_4(ctx, SCMP_ACT_ALLOW, SCMP_SYS(renameat), SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value), SCMP_CMP_LOWER32_EQ(2, AT_FDCWD), SCMP_CMP_STR(3, SCMP_CMP_EQ, param->value2)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add renameat syscall, received " "libseccomp error %d", rc); return rc; } } } return 0; } /** * Function responsible for setting up the openat syscall for * the seccomp filter sandbox. Loading @@ -709,7 +788,7 @@ sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (param != NULL && param->prot == 1 && param->syscall == SCMP_SYS(openat)) { rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), SCMP_CMP_NEG(0, SCMP_CMP_EQ, AT_FDCWD), SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value), SCMP_CMP(2, SCMP_CMP_EQ, O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY| O_CLOEXEC)); Loading Loading @@ -1312,7 +1391,9 @@ static sandbox_filter_func_t filter_func[] = { #else sb_chown, #endif sb_fchownat, sb_chmod, sb_fchmodat, sb_open, sb_openat, sb_opendir, Loading @@ -1320,6 +1401,7 @@ static sandbox_filter_func_t filter_func[] = { sb_ptrace, #endif sb_rename, sb_renameat, #ifdef __NR_fcntl64 sb_fcntl64, #endif Loading Loading @@ -1587,10 +1669,24 @@ new_element(int syscall, char *value) #ifdef __i386__ #define SCMP_chown SCMP_SYS(chown32) #elif defined(__aarch64__) && defined(__LP64__) #define SCMP_chown SCMP_SYS(fchownat) #else #define SCMP_chown SCMP_SYS(chown) #endif #if defined(__aarch64__) && defined(__LP64__) #define SCMP_chmod SCMP_SYS(fchmodat) #else #define SCMP_chmod SCMP_SYS(chmod) #endif #if defined(__aarch64__) && defined(__LP64__) #define SCMP_rename SCMP_SYS(renameat) #else #define SCMP_rename SCMP_SYS(rename) #endif #ifdef __NR_stat64 #define SCMP_stat SCMP_SYS(stat64) #else Loading Loading @@ -1628,7 +1724,7 @@ sandbox_cfg_allow_chmod_filename(sandbox_cfg_t **cfg, char *file) { sandbox_cfg_t *elem = NULL; elem = new_element(SCMP_SYS(chmod), file); elem = new_element(SCMP_chmod, file); elem->next = *cfg; *cfg = elem; Loading @@ -1654,7 +1750,7 @@ sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2) { sandbox_cfg_t *elem = NULL; elem = new_element2(SCMP_SYS(rename), file1, file2); elem = new_element2(SCMP_rename, file1, file2); elem->next = *cfg; *cfg = elem; Loading