You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
338 lines
12 KiB
338 lines
12 KiB
From https://gitlab.torproject.org/tpo/core/tor/-/merge_requests/574
|
|
Gentoo Bug: https://bugs.gentoo.org/920063
|
|
From: Pierre Bourdon <delroth@gmail.com>
|
|
Date: Sat, 30 Apr 2022 11:52:59 +0200
|
|
Subject: [PATCH 1/4] sandbox: fix openat filtering on AArch64
|
|
|
|
New glibc versions not sign-extending 32 bit negative constants seems to
|
|
not be a thing on AArch64. I suspect that this might not be the only
|
|
architecture where the sign-extensions is happening, and the correct fix
|
|
might be instead to use a proper 32 bit comparison for the first openat
|
|
parameter. For now, band-aid fix this so the sandbox can work again on
|
|
AArch64.
|
|
--- a/src/lib/sandbox/sandbox.c
|
|
+++ b/src/lib/sandbox/sandbox.c
|
|
@@ -518,7 +518,12 @@ libc_uses_openat_for_opendir(void)
|
|
static int
|
|
libc_negative_constant_needs_cast(void)
|
|
{
|
|
+#if defined(__aarch64__) && defined(__LP64__)
|
|
+ /* Existing glibc versions always sign-extend to 64 bits on AArch64. */
|
|
+ return 0;
|
|
+#else
|
|
return is_libc_at_least(2, 27);
|
|
+#endif
|
|
}
|
|
|
|
/** Allow a single file to be opened. If <b>use_openat</b> is true,
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 8fd13f7a7bfd4efc02d888ce9d10bcb6a80a03c8 Mon Sep 17 00:00:00 2001
|
|
From: Pierre Bourdon <delroth@gmail.com>
|
|
Date: Sat, 30 Apr 2022 13:02:16 +0200
|
|
Subject: [PATCH 2/4] sandbox: filter {chown,chmod,rename} via their *at
|
|
variant on Aarch64
|
|
|
|
The chown/chmod/rename syscalls have never existed on AArch64, and libc
|
|
implements the POSIX functions via the fchownat/fchmodat/renameat
|
|
syscalls instead.
|
|
|
|
Add new filter functions for fchownat/fchmodat/renameat, not made
|
|
architecture specific since the syscalls exists everywhere else too.
|
|
However, in order to limit seccomp filter space usage, we only insert
|
|
rules for one of {chown, chown32, fchownat} depending on the
|
|
architecture (resp. {chmod, fchmodat}, {rename, renameat}).
|
|
--- a/src/lib/sandbox/sandbox.c
|
|
+++ b/src/lib/sandbox/sandbox.c
|
|
@@ -614,6 +614,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_NEG(0, SCMP_CMP_EQ, 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)
|
|
@@ -666,6 +692,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_NEG(0, SCMP_CMP_EQ, 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.
|
|
@@ -697,6 +749,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_NEG(0, SCMP_CMP_EQ, AT_FDCWD),
|
|
+ SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value),
|
|
+ SCMP_CMP_NEG(2, SCMP_CMP_EQ, 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.
|
|
@@ -1317,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,
|
|
@@ -1325,6 +1412,7 @@ static sandbox_filter_func_t filter_func[] = {
|
|
sb_ptrace,
|
|
#endif
|
|
sb_rename,
|
|
+ sb_renameat,
|
|
#ifdef __NR_fcntl64
|
|
sb_fcntl64,
|
|
#endif
|
|
@@ -1592,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
|
|
@@ -1633,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;
|
|
@@ -1659,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;
|
|
--
|
|
GitLab
|
|
|
|
|
|
From eb0749d64917fee6ff74c3810dbec8cd063f546c Mon Sep 17 00:00:00 2001
|
|
From: Pierre Bourdon <delroth@gmail.com>
|
|
Date: Wed, 4 May 2022 07:19:40 +0200
|
|
Subject: [PATCH 3/4] sandbox: replace SCMP_CMP_NEG with masked equality checks
|
|
|
|
For some syscalls the kernel ABI uses 32 bit signed integers. Whether
|
|
these 32 bit integer values are sign extended or zero extended to the
|
|
native 64 bit register sizes is undefined and dependent on the {arch,
|
|
compiler, libc} being used. Instead of trying to detect which cases
|
|
zero-extend and which cases sign-extend, this commit uses a masked
|
|
equality check on the lower 32 bits of the value.
|
|
--- 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.
|
|
@@ -513,19 +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)
|
|
-{
|
|
-#if defined(__aarch64__) && defined(__LP64__)
|
|
- /* Existing glibc versions always sign-extend to 64 bits on AArch64. */
|
|
- return 0;
|
|
-#else
|
|
- return is_libc_at_least(2, 27);
|
|
-#endif
|
|
-}
|
|
-
|
|
/** 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
|
|
@@ -533,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),
|
|
@@ -627,7 +616,7 @@ sb_fchmodat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
|
|
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_NEG(0, SCMP_CMP_EQ, AT_FDCWD),
|
|
+ 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 "
|
|
@@ -705,7 +694,7 @@ sb_fchownat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
|
|
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_NEG(0, SCMP_CMP_EQ, AT_FDCWD),
|
|
+ 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 "
|
|
@@ -767,9 +756,9 @@ sb_renameat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
|
|
param->syscall == SCMP_SYS(renameat)) {
|
|
|
|
rc = seccomp_rule_add_4(ctx, SCMP_ACT_ALLOW, SCMP_SYS(renameat),
|
|
- 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_NEG(2, SCMP_CMP_EQ, AT_FDCWD),
|
|
+ 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 "
|
|
@@ -799,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));
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 42034ae9da2866c67ce8cb8522d6a619d8b21170 Mon Sep 17 00:00:00 2001
|
|
From: Pierre Bourdon <delroth@gmail.com>
|
|
Date: Wed, 4 May 2022 07:31:06 +0200
|
|
Subject: [PATCH 4/4] changes: add entry for MR !574
|
|
|
|
--- /dev/null
|
|
+++ b/changes/aarch64_sandbox
|
|
@@ -0,0 +1,5 @@
|
|
+ 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.
|
|
--
|
|
GitLab
|
|
|