summaryrefslogtreecommitdiff
path: root/src/lib/sandbox/sandbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/sandbox/sandbox.c')
-rw-r--r--src/lib/sandbox/sandbox.c136
1 files changed, 120 insertions, 16 deletions
diff --git a/src/lib/sandbox/sandbox.c b/src/lib/sandbox/sandbox.c
index cc00d2048f..a476e57fbc 100644
--- a/src/lib/sandbox/sandbox.c
+++ b/src/lib/sandbox/sandbox.c
@@ -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.
@@ -516,14 +518,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
@@ -531,7 +525,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),
@@ -612,6 +606,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)
@@ -664,6 +684,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.
@@ -696,6 +742,39 @@ sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
}
/**
+ * 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.
*/
@@ -712,7 +791,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));
@@ -954,6 +1033,14 @@ sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return rc;
#endif /* defined(IPV6_V6ONLY) */
+#ifdef IP_BIND_ADDRESS_NO_PORT
+ rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
+ SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
+ SCMP_CMP(2, SCMP_CMP_EQ, IP_BIND_ADDRESS_NO_PORT));
+ if (rc)
+ return rc;
+#endif
+
return 0;
}
@@ -1315,7 +1402,9 @@ static sandbox_filter_func_t filter_func[] = {
#else
sb_chown,
#endif
+ sb_fchownat,
sb_chmod,
+ sb_fchmodat,
sb_open,
sb_openat,
sb_opendir,
@@ -1323,6 +1412,7 @@ static sandbox_filter_func_t filter_func[] = {
sb_ptrace,
#endif
sb_rename,
+ sb_renameat,
#ifdef __NR_fcntl64
sb_fcntl64,
#endif
@@ -1590,10 +1680,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
@@ -1631,7 +1735,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;
@@ -1657,7 +1761,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;