From patchwork Tue Apr 30 19:25:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 1929818 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=qBG4xJZK; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=libc-alpha-bounces+incoming=patchwork.ozlabs.org@sourceware.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4VTVl06Y3Bz23jG for ; Wed, 1 May 2024 05:34:36 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 240543858CDB for ; Tue, 30 Apr 2024 19:34:35 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pf1-x42c.google.com (mail-pf1-x42c.google.com [IPv6:2607:f8b0:4864:20::42c]) by sourceware.org (Postfix) with ESMTPS id AFD4A3858D34 for ; Tue, 30 Apr 2024 19:32:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org AFD4A3858D34 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org AFD4A3858D34 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::42c ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1714505587; cv=none; b=oNJ11GQL+9TJpP1975pr8q4ISMM8p0B660FjWL9JydfV5nzzLbF/nTKXBzdCG67Lkx0n4Hc0uWi+YUJHO83cy18Ll9I3om+T5waO5nl9kDj9UOeCtM7JODVvBxHjbGlFEvlZU8AZ0JkzOqH5qziFoskiOIctdLBXP3zgoepsLvM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1714505587; c=relaxed/simple; bh=SMUji7r5JpEZDeAgvdai+FwmMwfxYqIQmTGvTl61zq4=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=OmQ4j2/s3PsVc4da9xsjxabqDZgr1WZtpAavcDsc1yxMWQtU4qGelWhCOX2I9Y0oqaOdB8en2ylnum2z0MkHQbjdQ3v9hTDnWuy8DSUO/nivcMx8PN/9TZVmvl0IU895xyNAZO5aMjRBnOBVTnAdRIdfcVRuSqZyVuQtQrfF4BU= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pf1-x42c.google.com with SMTP id d2e1a72fcca58-6effe9c852eso5474453b3a.3 for ; Tue, 30 Apr 2024 12:32:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1714505578; x=1715110378; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ozo/WGZB4PzfVOQdQVAfUM2SMZqnNC5zs1unz/mic2c=; b=qBG4xJZKOXaXCJ1d7qGARnmvKmHjK56SkTqR1nmYVSWi7mxzMwy9kcUFTTbWnbYuv/ ddtrmAxM/rZB61TVFVJG8cX3PUPVQ5MF4C4oG8zTFiBvdj8okMsB9qCKIwvYl6cHYgJ4 dH5RTuNYdTRH6mH/jFlhtEXFaxCzHMLvfzf2uER10q1tRJZuZxgQi8DzYhHGJLE99g6c Qze+F2vLzP0JURahhFEMTNva8BwK9fVsDwe01ln8bvt4T2MV8eemZ1/nxazzP/LkSwFe k2fzA+LNuR9CNyjhXOte6+tIqmP2+D1inclIkE3f4zhFjCfN0DsUi/ReSEChGxifkkhD mHtw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714505578; x=1715110378; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ozo/WGZB4PzfVOQdQVAfUM2SMZqnNC5zs1unz/mic2c=; b=l0ZO+jaEmq7IQgLp205BRRYQDOsBPfx6sfT3fEvKZNZShWSGz1Q6DVis9Z9kr29v1+ SCHrY3kOa7/ZJKABhDee7xTwflwYhJWVe0Ayu4kx1sp/VUieYYMv6WyGO6CL9KO8iPkq FfwKc5guKsP1gGmXsnS5xH842O5+Ch+PRTp2b/JngrOY9g08vLycrPA1Hg5iJTGKmI0i IlMvgDiBJixcleEiNqHvp1eHQvvoecPDhN8bnR5ma59KZ5wulBrGwOwRbfZc8qHGzeVa Ywrp5dWamC3X7QHrtlpI9M2mN8pDLiL40gVw3C1fcLS/IM+xUUtn+PrHC3qk/lruLzuF y32A== X-Gm-Message-State: AOJu0YyCrP1scBmlFN71xALBThZ6zqZzfh7Ust81jeJ26llyyxcYVHos UdIqkhrmcVQScFmZSFLcOkhogp+RtcvIRnCpBVdrPy3xFt56ewGYMrDdrSiL//kpzAyitHFaraD w X-Google-Smtp-Source: AGHT+IHscK3B3Jd2B1P2JXbHA67J7q6V9lwkeOrhGgVNuUeXO39gZ/25KBcDgRlseb8mGRIQi9CJnA== X-Received: by 2002:a05:6a21:819a:b0:1a9:8836:ae37 with SMTP id pd26-20020a056a21819a00b001a98836ae37mr927547pzb.12.1714505578050; Tue, 30 Apr 2024 12:32:58 -0700 (PDT) Received: from mandiga.. ([2804:1b3:a7c1:e3c5:c9b5:f382:64ea:c32b]) by smtp.gmail.com with ESMTPSA id gr6-20020a056a004d0600b006ed1ea5219csm21449143pfb.130.2024.04.30.12.32.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Apr 2024 12:32:57 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Cc: Joe Simmons-Talbott , Siddhesh Poyarekar Subject: [PATCH 4/4] elf: Make glibc.rtld.enable_secure ignore alias environment variables Date: Tue, 30 Apr 2024 16:25:05 -0300 Message-ID: <20240430192739.1032549-5-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240430192739.1032549-1-adhemerval.zanella@linaro.org> References: <20240430192739.1032549-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces+incoming=patchwork.ozlabs.org@sourceware.org So tunable with environment variables aliases are also ignored if glibc.rtld.enable_secure is enabled. The tunable parsing is also optimized a bit, where the loop that checks each environment variable only checks for the tunables with aliases instead of all tables. Checked on aarch64-linux-gnu and x86_64-linux-gnu. --- elf/dl-tunables.c | 34 ++++++-- elf/tst-tunables-enable_secure.c | 131 +++++++++++++++++++++++++++---- scripts/gen-tunables.awk | 64 ++++++++++----- 3 files changed, 189 insertions(+), 40 deletions(-) diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c index 63cf8c7ab5..c1a1d1a2e3 100644 --- a/elf/dl-tunables.c +++ b/elf/dl-tunables.c @@ -300,6 +300,10 @@ __tunables_init (char **envp) if (__libc_enable_secure) return; + /* The tunable with environment variable alias are placed at the start of + tunable array. */ + struct tunable_toset_t tunables_env_alias[TUNABLE_NUM_ENV_ALIAS] = { 0 }; + while ((envp = get_next_env (envp, &envname, &envval, &prev_envp)) != NULL) { /* The environment variable is allocated on the stack by the kernel, so @@ -311,29 +315,43 @@ __tunables_init (char **envp) continue; } - for (int i = 0; i < tunables_list_size; i++) + for (int i = 0; i < TUNABLE_NUM_ENV_ALIAS; i++) { tunable_t *cur = &tunable_list[i]; + const char *name = cur->env_alias; - /* Skip over tunables that have either been set already or should be - skipped. */ - if (cur->initialized || cur->env_alias[0] == '\0') + if (name[0] == '\0') continue; - const char *name = cur->env_alias; - - /* We have a match. Initialize and move on to the next line. */ if (tunable_is_name (name, envname)) { size_t envvallen = 0; /* The environment variable is always null-terminated. */ for (const char *p = envval; *p != '\0'; p++, envvallen++); - tunable_initialize (cur, envval, envvallen); + tunables_env_alias[i] = + (struct tunable_toset_t) { cur, envval, envvallen }; break; } } } + + /* Check if glibc.rtld.enable_secure was set and skip over the environment + variables aliases. */ + if (__libc_enable_secure) + return; + + for (int i = 0; i < TUNABLE_NUM_ENV_ALIAS; i++) + { + if (tunables_env_alias[i].t == NULL + || tunables_env_alias[i].t->initialized) + continue; + + if (!tunable_initialize (tunables_env_alias[i].t, + tunables_env_alias[i].value, + tunables_env_alias[i].len)) + parse_tunable_print_error (&tunables_env_alias[i]); + } } void diff --git a/elf/tst-tunables-enable_secure.c b/elf/tst-tunables-enable_secure.c index f5db1c84e9..d4938a2e5c 100644 --- a/elf/tst-tunables-enable_secure.c +++ b/elf/tst-tunables-enable_secure.c @@ -17,6 +17,7 @@ . */ #include +#define TUNABLES_INTERNAL 1 #include #include #include @@ -34,6 +35,8 @@ static int restart; static const struct test_t { const char *env; + const char *extraenv; + bool check_multiple; int32_t expected_malloc_check; int32_t expected_enable_secure; } tests[] = @@ -41,39 +44,124 @@ static const struct test_t /* Expected tunable format. */ /* Tunables should be ignored if enable_secure is set. */ { - "glibc.malloc.check=2:glibc.rtld.enable_secure=1", + "GLIBC_TUNABLES=glibc.malloc.check=2:glibc.rtld.enable_secure=1", + NULL, + false, 0, 1, }, /* Tunables should be ignored if enable_secure is set. */ { - "glibc.rtld.enable_secure=1:glibc.malloc.check=2", + "GLIBC_TUNABLES=glibc.rtld.enable_secure=1:glibc.malloc.check=2", + NULL, + false, 0, 1, }, /* Tunables should be set if enable_secure is unset. */ { - "glibc.rtld.enable_secure=0:glibc.malloc.check=2", + "GLIBC_TUNABLES=glibc.rtld.enable_secure=0:glibc.malloc.check=2", + NULL, + false, 2, 0, }, + /* Tunables should be ignored if enable_secure is set. */ + { + "GLIBC_TUNABLES=glibc.malloc.check=2:glibc.rtld.enable_secure=1", + "MALLOC_CHECK_=2", + false, + 0, + 1, + }, + /* Same as before, but with enviroment alias prior GLIBC_TUNABLES. */ + { + "MALLOC_CHECK_=2", + "GLIBC_TUNABLES=glibc.malloc.check=2:glibc.rtld.enable_secure=1", + false, + 0, + 1, + }, + /* Tunables should be ignored if enable_secure is set. */ + { + "GLIBC_TUNABLES=glibc.rtld.enable_secure=1:glibc.malloc.check=2", + "MALLOC_CHECK_=2", + false, + 0, + 1, + }, + { + "MALLOC_CHECK_=2", + "GLIBC_TUNABLES=glibc.rtld.enable_secure=1:glibc.malloc.check=2", + false, + 0, + 1, + }, + /* Tunables should be set if enable_secure is unset. */ + { + "GLIBC_TUNABLES=glibc.rtld.enable_secure=0:glibc.malloc.check=2", + /* Tunable have precedence over the environment variable. */ + "MALLOC_CHECK_=1", + false, + 2, + 0, + }, + { + "MALLOC_CHECK_=1", + "GLIBC_TUNABLES=glibc.rtld.enable_secure=0:glibc.malloc.check=2", + /* Tunable have precedence over the environment variable. */ + false, + 2, + 0, + }, + /* Tunables should be set if enable_secure is unset. */ + { + "GLIBC_TUNABLES=glibc.rtld.enable_secure=0", + /* Tunable have precedence over the environment variable. */ + "MALLOC_CHECK_=1", + false, + 1, + 0, + }, + /* Tunables should be set if enable_secure is unset. */ + { + "GLIBC_TUNABLES=glibc.rtld.enable_secure=0", + /* Tunable have precedence over the environment variable. */ + "MALLOC_CHECK_=1", + false, + 1, + 0, + }, + /* Check with tunables environment variable alias set multiple times. */ + { + "GLIBC_TUNABLES=glibc.rtld.enable_secure=1:glibc.malloc.check=2", + "MALLOC_CHECK_=2", + true, + 0, + 1, + }, + /* Tunables should be set if enable_secure is unset. */ + { + "GLIBC_TUNABLES=glibc.rtld.enable_secure=0", + /* Tunable have precedence over the environment variable. */ + "MALLOC_CHECK_=1", + true, + 1, + 0, + }, }; static int handle_restart (int i) { if (tests[i].expected_enable_secure == 1) - { - TEST_COMPARE (1, __libc_enable_secure); - } + TEST_COMPARE (1, __libc_enable_secure); else - { - TEST_COMPARE (tests[i].expected_malloc_check, - TUNABLE_GET_FULL (glibc, malloc, check, int32_t, NULL)); - TEST_COMPARE (tests[i].expected_enable_secure, - TUNABLE_GET_FULL (glibc, rtld, enable_secure, int32_t, - NULL)); - } + TEST_COMPARE (tests[i].expected_enable_secure, + TUNABLE_GET_FULL (glibc, rtld, enable_secure, int32_t, + NULL)); + TEST_COMPARE (tests[i].expected_malloc_check, + TUNABLE_GET_FULL (glibc, malloc, check, int32_t, NULL)); return 0; } @@ -112,8 +200,23 @@ do_test (int argc, char *argv[]) printf ("[%d] Spawned test for %s\n", i, tests[i].env); setenv ("GLIBC_TUNABLES", tests[i].env, 1); + + char *envp[2 + TUNABLE_NUM_ENV_ALIAS + 1] = + { + (char *) tests[i].env, + (char *) tests[i].extraenv, + NULL, + }; + if (tests[i].check_multiple) + { + int j; + for (j=0; j < TUNABLE_NUM_ENV_ALIAS; j++) + envp[j + 2] = (char *) tests[i].extraenv; + envp[j + 2] = NULL; + } + struct support_capture_subprocess result - = support_capture_subprogram (spargv[0], spargv, NULL); + = support_capture_subprogram (spargv[0], spargv, envp); support_capture_subprocess_check (&result, "tst-tunables-enable_secure", 0, sc_allow_stderr); support_capture_subprocess_free (&result); diff --git a/scripts/gen-tunables.awk b/scripts/gen-tunables.awk index 9f5336381e..9a18aa6861 100644 --- a/scripts/gen-tunables.awk +++ b/scripts/gen-tunables.awk @@ -14,6 +14,7 @@ BEGIN { top_ns="" max_name_len=0 max_alias_len=0 + num_env_alias=0 } # Skip over blank lines and comments. @@ -60,6 +61,8 @@ $1 == "}" { } if (!env_alias[top_ns,ns,tunable]) { env_alias[top_ns,ns,tunable] = "{0}" + } else { + num_env_alias = num_env_alias + 1 } len = length(top_ns"."ns"."tunable) if (len > max_name_len) @@ -125,6 +128,39 @@ $1 == "}" { } } +function print_tunable_id_t (envfirst) +{ + for (tnm in types) { + split (tnm, indices, SUBSEP); + t = indices[1]; + n = indices[2]; + m = indices[3]; + if ((envfirst && env_alias[t,n,m] == "{0}") \ + || (!envfirst && env_alias[t,n,m] != "{0}")) { + continue; + } + printf (" TUNABLE_ENUM_NAME(%s, %s, %s),\n", t, n, m); + } +} + +function print_tunable_entry (envfirst) +{ + for (tnm in types) { + split (tnm, indices, SUBSEP); + t = indices[1]; + n = indices[2]; + m = indices[3]; + if ((envfirst && env_alias[t,n,m] == "{0}") \ + || (!envfirst && env_alias[t,n,m] != "{0}")) { + continue; + } + printf (" {TUNABLE_NAME_S(%s, %s, %s)", t, n, m) + printf (", {TUNABLE_TYPE_%s, %s, %s}, {%s}, {%s}, false, %s},\n", + types[t,n,m], minvals[t,n,m], maxvals[t,n,m], default_val[t,n,m], + default_val[t,n,m], env_alias[t,n,m]); + } +} + END { if (ns != "") { print "Unterminated namespace. Is a closing brace missing?" @@ -138,35 +174,27 @@ END { print "#endif" print "#include \n" + # asort (types) + # Now, the enum names print "\ntypedef enum" print "{" - for (tnm in types) { - split (tnm, indices, SUBSEP); - t = indices[1]; - n = indices[2]; - m = indices[3]; - printf (" TUNABLE_ENUM_NAME(%s, %s, %s),\n", t, n, m); - } + # Make the tunable with environment variables aliases first, their index + # will be used in the tunable parsing. + print_tunable_id_t(1) + print_tunable_id_t(0) print "} tunable_id_t;\n" print "\n#ifdef TUNABLES_INTERNAL" # Internal definitions. print "# define TUNABLE_NAME_MAX " (max_name_len + 1) print "# define TUNABLE_ALIAS_MAX " (max_alias_len + 1) + print "# define TUNABLE_NUM_ENV_ALIAS " (num_env_alias) print "# include \"dl-tunable-types.h\"" # Finally, the tunable list. - print "static tunable_t tunable_list[] attribute_relro = {" - for (tnm in types) { - split (tnm, indices, SUBSEP); - t = indices[1]; - n = indices[2]; - m = indices[3]; - printf (" {TUNABLE_NAME_S(%s, %s, %s)", t, n, m) - printf (", {TUNABLE_TYPE_%s, %s, %s}, {%s}, {%s}, false, %s},\n", - types[t,n,m], minvals[t,n,m], maxvals[t,n,m], default_val[t,n,m], - default_val[t,n,m], env_alias[t,n,m]); - } + print "static tunable_t tunable_list[] attribute_relro __attribute_used__ = {" + print_tunable_entry(1) + print_tunable_entry(0) print "};" print "#endif" }