From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp.gentoo.org (woodpecker.gentoo.org [140.211.166.183]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 2EE3B1582EF for ; Sat, 22 Feb 2025 19:49:26 +0000 (UTC) Received: from lists.gentoo.org (bobolink.gentoo.org [140.211.166.189]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) (Authenticated sender: relay-lists.gentoo.org@gentoo.org) by smtp.gentoo.org (Postfix) with ESMTPSA id 180DE34324D for ; Sat, 22 Feb 2025 19:49:26 +0000 (UTC) Received: from bobolink.gentoo.org (localhost [127.0.0.1]) by bobolink.gentoo.org (Postfix) with ESMTP id CAF44110477; Sat, 22 Feb 2025 19:49:10 +0000 (UTC) Received: from smtp.gentoo.org (mail.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bobolink.gentoo.org (Postfix) with ESMTPS id B9C80110477 for ; Sat, 22 Feb 2025 19:49:10 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 6580334321E for ; Sat, 22 Feb 2025 19:49:10 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 0504B273E for ; Sat, 22 Feb 2025 19:49:08 +0000 (UTC) From: "Mike Gilbert" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Mike Gilbert" Message-ID: <1739583800.766ac14e269fda699f11549bedb14c77c2c8c623.floppym@gentoo> Subject: [gentoo-commits] proj/sandbox:master commit in: libsandbox/ X-VCS-Repository: proj/sandbox X-VCS-Files: libsandbox/libsandbox.c libsandbox/libsandbox.h libsandbox/memory.c X-VCS-Directories: libsandbox/ X-VCS-Committer: floppym X-VCS-Committer-Name: Mike Gilbert X-VCS-Revision: 766ac14e269fda699f11549bedb14c77c2c8c623 X-VCS-Branch: master Date: Sat, 22 Feb 2025 19:49:08 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: 6ae9c2dc-f754-4b6e-816c-8c15537fc4ca X-Archives-Hash: 05550708d3e0022ab97760307c42a851 commit: 766ac14e269fda699f11549bedb14c77c2c8c623 Author: Mike Gilbert gentoo org> AuthorDate: Fri Feb 14 21:50:16 2025 +0000 Commit: Mike Gilbert gentoo org> CommitDate: Sat Feb 15 01:43:20 2025 +0000 URL: https://gitweb.gentoo.org/proj/sandbox.git/commit/?id=766ac14e Optimize prefix loading Reduce the number of malloc/mmap calls needed by storing each set of prefixes in a single chunk of memory. Signed-off-by: Mike Gilbert gentoo.org> libsandbox/libsandbox.c | 132 ++++++++++++++---------------------------------- libsandbox/libsandbox.h | 2 + libsandbox/memory.c | 11 ++++ 3 files changed, 52 insertions(+), 93 deletions(-) diff --git a/libsandbox/libsandbox.c b/libsandbox/libsandbox.c index f5b3e62..5764cf6 100644 --- a/libsandbox/libsandbox.c +++ b/libsandbox/libsandbox.c @@ -31,18 +31,12 @@ typedef struct { bool show_access_violation, on, active, testing, verbose, debug; sandbox_method_t method; char *ld_library_path; - char **prefixes[5]; - int num_prefixes[5]; + char *prefixes[5]; #define deny_prefixes prefixes[0] -#define num_deny_prefixes num_prefixes[0] #define read_prefixes prefixes[1] -#define num_read_prefixes num_prefixes[1] #define write_prefixes prefixes[2] -#define num_write_prefixes num_prefixes[2] #define predict_prefixes prefixes[3] -#define num_predict_prefixes num_prefixes[3] #define write_denied_prefixes prefixes[4] -#define num_write_denied_prefixes num_prefixes[4] #define MAX_DYN_PREFIXES 4 /* the first 4 are dynamic */ } sbcontext_t; static sbcontext_t sbcontext; @@ -58,8 +52,6 @@ int (*sbio_faccessat)(int, const char *, int, int) = sb_unwrapped_faccessat; int (*sbio_open)(const char *, int, mode_t) = sb_unwrapped_open; FILE *(*sbio_popen)(const char *, const char *) = sb_unwrapped_popen; -static int check_prefixes(char **, int, const char *); -static void clean_env_entries(char ***, int *); static void sb_process_env_settings(void); const char *sbio_message_path; @@ -190,41 +182,27 @@ static bool write_logfile(const char *logfile, const char *func, const char *pat return ret; } -static void clean_env_entries(char ***prefixes_array, int *prefixes_num) +static size_t strv_append(char **basep, size_t offset, const char *value) { - if (*prefixes_array == NULL) - return; + char *base = *basep; + size_t bsize = malloc_size(base); + size_t vsize = strlen(value) + 1; - size_t i; - save_errno(); + if (offset + vsize >= bsize) + *basep = base = xrealloc(base, offset + vsize + 1); - for (i = 0; i < *prefixes_num; ++i) { - if (NULL != (*prefixes_array)[i]) { - free((*prefixes_array)[i]); - (*prefixes_array)[i] = NULL; - } - } - if (NULL != *prefixes_array) - free(*prefixes_array); - *prefixes_array = NULL; - *prefixes_num = 0; + memcpy(base + offset, value, vsize); + offset += vsize; + base[offset] = '\0'; - restore_errno(); + return offset; } -#define pfx_num (*prefixes_num) -#define pfx_array (*prefixes_array) -#define pfx_item ((*prefixes_array)[(*prefixes_num)]) -#define pfx_prev ((*prefixes_array)[(*prefixes_num) - 1]) - -static void init_env_entries(char ***prefixes_array, int *prefixes_num, const char *env, const char *prefixes_env, int warn) +static void init_env_entries(char **prefixes, const char *env, const char *prefixes_env) { char *token = NULL; char *buffer = NULL; char *buffer_ptr = NULL; - int prefixes_env_length = strlen(prefixes_env); - int num_delimiters = 0; - int i = 0; int old_errno = errno; if (NULL == prefixes_env) { @@ -234,23 +212,10 @@ static void init_env_entries(char ***prefixes_array, int *prefixes_num, const ch fprintf(stderr, "libsandbox: The '%s' env variable is not defined!\n", env); - if (pfx_array) { - for (i = 0; i < pfx_num; i++) - free(pfx_item); - free(pfx_array); - } - pfx_num = 0; goto done; } - for (i = 0; i < prefixes_env_length; i++) { - if (':' == prefixes_env[i]) - num_delimiters++; - } - - /* num_delimiters might be 0, and we need 2 entries at least */ - pfx_array = xmalloc(((num_delimiters * 2) + 2) * sizeof(char *)); buffer = xstrdup(prefixes_env); buffer_ptr = buffer; @@ -260,19 +225,18 @@ static void init_env_entries(char ***prefixes_array, int *prefixes_num, const ch token = strtok(buffer_ptr, ":"); #endif + size_t offset = 0; + while (token && strlen(token) > 0) { char buf[SB_PATH_MAX]; if (sb_abspathat(AT_FDCWD, token, buf, sizeof(buf))) { - pfx_item = xstrdup(buf); - ++pfx_num; + size_t prev_offset = offset; + offset = strv_append(prefixes, offset, buf); /* Now add the realpath if it exists and * are not a duplicate */ - if (sb_realpathat(AT_FDCWD, token, buf, sizeof(buf), 0, false)) { - if (strcmp(buf, pfx_prev)) { - pfx_item = xstrdup(buf); - ++pfx_num; - } - } + if (sb_realpathat(AT_FDCWD, token, buf, sizeof(buf), 0, false)) + if (strcmp(buf, *prefixes + prev_offset)) + offset = strv_append(prefixes, offset, buf); } #ifdef HAVE_STRTOK_R @@ -311,14 +275,12 @@ static void sb_process_env_settings(void) !cached_env_vars[i] || strcmp(cached_env_vars[i], sb_env) != 0) { - clean_env_entries(&sbcontext.prefixes[i], &sbcontext.num_prefixes[i]); - - if (cached_env_vars[i]) - free(cached_env_vars[i]); + free(sbcontext.prefixes[i]); + sbcontext.prefixes[i] = NULL; + free(cached_env_vars[i]); if (sb_env) { - init_env_entries(&sbcontext.prefixes[i], &sbcontext.num_prefixes[i], - sb_env_names[i], sb_env, 1); + init_env_entries(sbcontext.prefixes + i, sb_env_names[i], sb_env); cached_env_vars[i] = xstrdup(sb_env); } else cached_env_vars[i] = NULL; @@ -326,33 +288,31 @@ static void sb_process_env_settings(void) } } -static int check_prefixes(char **prefixes, int num_prefixes, const char *path) +static bool check_prefixes(char *prefixes, const char *path) { if (!prefixes) - return 0; + return false; - size_t i; - for (i = 0; i < num_prefixes; ++i) { - if (unlikely(!prefixes[i])) - continue; + size_t prefix_len; + + for (const char *prefix = prefixes; *prefix; prefix += prefix_len + 1) { + prefix_len = strlen(prefix); - size_t prefix_len = strlen(prefixes[i]); /* Start with a regular prefix match for speed */ - if (strncmp(path, prefixes[i], prefix_len)) + if (strncmp(path, prefix, prefix_len)) continue; /* Now, if prefix did not end with a slash, we need to make sure * we are not matching in the middle of a filename. So check * whether the match is followed by a slash, or NUL. */ - if (prefixes[i][prefix_len-1] != '/' - && path[prefix_len] != '/' && path[prefix_len] != '\0') + if (prefix[prefix_len - 1] != '/' && path[prefix_len] != '/' && path[prefix_len] != '\0') continue; - return 1; + return true; } - return 0; + return false; } static int check_access(sbcontext_t *sbcontext, int sb_nr, const char *func, @@ -360,7 +320,6 @@ static int check_access(sbcontext_t *sbcontext, int sb_nr, const char *func, { int old_errno = errno; int result = 0; - int retval; /* Do not check non-filesystem objects like pipes and sockets */ /* Allow operations on memfd objects #910561 */ @@ -369,15 +328,11 @@ static int check_access(sbcontext_t *sbcontext, int sb_nr, const char *func, goto out; } - retval = check_prefixes(sbcontext->deny_prefixes, - sbcontext->num_deny_prefixes, abs_path); - if (1 == retval) + if (check_prefixes(sbcontext->deny_prefixes, abs_path)) /* Fall in a read/write denied path, Deny Access */ goto out; - retval = check_prefixes(sbcontext->deny_prefixes, - sbcontext->num_deny_prefixes, resolv_path); - if (1 == retval) + if (check_prefixes(sbcontext->deny_prefixes, resolv_path)) /* Fall in a read/write denied path, Deny Access */ goto out; @@ -397,9 +352,7 @@ static int check_access(sbcontext_t *sbcontext, int sb_nr, const char *func, sb_nr == SB_NR_EXECVPE || sb_nr == SB_NR_FEXECVE)) { - retval = check_prefixes(sbcontext->read_prefixes, - sbcontext->num_read_prefixes, resolv_path); - if (1 == retval) { + if (check_prefixes(sbcontext->read_prefixes, resolv_path)) { /* Fall in a readable path, Grant Access */ result = 1; goto out; @@ -478,16 +431,11 @@ static int check_access(sbcontext_t *sbcontext, int sb_nr, const char *func, sb_nr == SB_NR___XMKNODAT) { - retval = check_prefixes(sbcontext->write_denied_prefixes, - sbcontext->num_write_denied_prefixes, - resolv_path); - if (1 == retval) + if (check_prefixes(sbcontext->write_denied_prefixes, resolv_path)) /* Falls in a write denied path, Deny Access */ goto out; - retval = check_prefixes(sbcontext->write_prefixes, - sbcontext->num_write_prefixes, resolv_path); - if (1 == retval) { + if (check_prefixes(sbcontext->write_prefixes, resolv_path)) { /* Falls in a writable path, Grant Access */ result = 1; goto out; @@ -519,9 +467,7 @@ static int check_access(sbcontext_t *sbcontext, int sb_nr, const char *func, goto out; } - retval = check_prefixes(sbcontext->predict_prefixes, - sbcontext->num_predict_prefixes, resolv_path); - if (1 == retval) { + if (check_prefixes(sbcontext->predict_prefixes, resolv_path)) { /* Is a known access violation, so deny access, * and do not log it */ sbcontext->show_access_violation = false; diff --git a/libsandbox/libsandbox.h b/libsandbox/libsandbox.h index d1a8e7e..22c5535 100644 --- a/libsandbox/libsandbox.h +++ b/libsandbox/libsandbox.h @@ -97,6 +97,8 @@ bool sb_realpathat(int dirfd, const char *restrict path, char *buf, size_t bufsi /* most linux systems use ENAMETOOLONG, but some (ia64) use ERANGE, as do some BSDs */ #define errno_is_too_long() (errno == ENAMETOOLONG || errno == ERANGE) +size_t malloc_size(void *ptr); + #include "sbutil.h" /* glibc sometimes redefines this crap on us */ diff --git a/libsandbox/memory.c b/libsandbox/memory.c index b6f7f80..1446116 100644 --- a/libsandbox/memory.c +++ b/libsandbox/memory.c @@ -127,6 +127,17 @@ void *realloc(void *ptr, size_t size) return sp + ALIGN_FACTOR; } +size_t malloc_size(void *ptr) +{ + if (!ptr) + return 0; + + size_t *sp = ptr; + sp -= 2; + + return *sp - ALIGN_SIZE; +} + char *strdup(const char *s) { size_t len;