Received: by 2002:a05:6a10:16a7:0:0:0:0 with SMTP id gp39csp4241719pxb; Tue, 17 Nov 2020 15:34:20 -0800 (PST) X-Google-Smtp-Source: ABdhPJxIaH1VvgOyh6kODTm+b1moYAZzcu8Vv4DOcYKQhM0CiHTCprfkjI1Q8TMVuTr78H9Y/aaq X-Received: by 2002:a17:906:3daa:: with SMTP id y10mr21150465ejh.23.1605656060302; Tue, 17 Nov 2020 15:34:20 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605656060; cv=none; d=google.com; s=arc-20160816; b=YYhMK8zPVYjOcW3zQ1WD05XksLr9vZWgnkyOCDnxuKBepxnAMT2LpZbdI9Yf/1o2TK 04T0EEFh6822XIdbj9f8eHxCOBQMViYVfgnjgEYMTRXpj7m9IKb8tHHhHST8tl9LMM7E pAtuWjXoeSuNrG9AwgDf/zHJlTiMbCtLU1CXYosKiWGw0wFGD2sbr53Atn3PqdfF/ydb N4oGuaOnWRBCB8bUUqDac4Bh7lhhfx4t+4PTIHOG/kZV+TIvDLD8ZprEH/U1SzshdwsB TuK/3AhN8ToYuOb37WJ6XkZ0+2Tf5WwdEisY/8OCbx1aoDm43A9P3qBZacLitsOglWH0 rh6Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=pj9GAd6lPX1luvhTRtjAwGqzDzBvcBv8m7DVR+Is5uw=; b=z0GZlJswFjAdUJV5f0IS8Qgh30yVgx0RUAbn9XX2M0if4e9DvLLZxSn8slQTdjlyac /LDhDsMz5sORQ9Eynt2LDtKwZxhNrqFpLhhY5IGFQvFcot9IZj/DOvOVdUhbNXI9BtPj RaoT8Vy4Hf5wsYsqzCpyLHGG70bqORfxf8tiDobNknwUNADuBuZ0PaIb4qnNv8CATPyv 9DtySzx0k5InYsf5reC87vEcfQiY2IkVz7lK5wUa28NeyDHdcOcQqfeWMyXk2j5RkXpl mn4iWvzapdkZbW+T7aXSbs2PmgoY0+3SKYu8cGC1Jwt4Ymd6i/ZfbiqSm5U8hFhXHHgy aMWA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=UAKmz27B; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id k26si14032557ejz.41.2020.11.17.15.33.56; Tue, 17 Nov 2020 15:34:20 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=UAKmz27B; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726636AbgKQX3f (ORCPT + 99 others); Tue, 17 Nov 2020 18:29:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41354 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726558AbgKQX3f (ORCPT ); Tue, 17 Nov 2020 18:29:35 -0500 Received: from mail-wm1-x344.google.com (mail-wm1-x344.google.com [IPv6:2a00:1450:4864:20::344]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 78F02C0617A6 for ; Tue, 17 Nov 2020 15:29:33 -0800 (PST) Received: by mail-wm1-x344.google.com with SMTP id 23so3008683wmg.1 for ; Tue, 17 Nov 2020 15:29:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=pj9GAd6lPX1luvhTRtjAwGqzDzBvcBv8m7DVR+Is5uw=; b=UAKmz27BMPIPbI0bWQo8kRhYVHct0edQpiEo4rQhkH4BwgyomWNfUA1Y7wFQ1iPgx9 Q7sEV+P93u7JGo1xzJrbcrqTPztosr7+bK26ORfOamwjtMZRBIx8bCmLv8B9xlhXEr2S uS7ByHTyfDA8JDJEP2J6XkXGMYvEjc2WO0Sm4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=pj9GAd6lPX1luvhTRtjAwGqzDzBvcBv8m7DVR+Is5uw=; b=La+gZrXMfVDkokVpJx4FNbLZwGFnsQJFmYiY+qN90tNuNeZY5IfSZhRryr6HLZ0KQe jTlKBqv8u65TF+k22cvPKk2zRE7b58F5dONe/jLhKI8N7s3SkTKuqxuplEzuJJ0d8Vyz QJ8aHWks+ZNRxxpUN4Hz+jZSgnLdTO9u+/rGV+4J6YTnK8FwJgqhTLB1G0LI8hsqsxub LD3p2q4Nz2iORRphgkqy6z1AQAvc/n1Y8PjrZnUZVkFGJTaaEyW5ktpWJDLJrpj+rV86 +hRFu5idVgS64ZX6DL7fEvXCvYqDJWWSrD+TfYJ7JXJHTKlcn6bdMDnhcxCNK97AVh2v fg1A== X-Gm-Message-State: AOAM532kw6JWklS88Qn+nIe1zfrjG5VN0KXm+rbTSjlk5P3qhKSGw2zv Fk3KRuUYqBqSIwm7vl7GCitZLjQT9kBpjVkI X-Received: by 2002:a1c:a344:: with SMTP id m65mr1396001wme.77.1605655771928; Tue, 17 Nov 2020 15:29:31 -0800 (PST) Received: from kpsingh.c.googlers.com.com (203.75.199.104.bc.googleusercontent.com. [104.199.75.203]) by smtp.gmail.com with ESMTPSA id k3sm10212083wrn.81.2020.11.17.15.29.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Nov 2020 15:29:31 -0800 (PST) From: KP Singh To: linux-kernel@vger.kernel.org, bpf@vger.kernel.org Cc: Martin KaFai Lau , Alexei Starovoitov , Daniel Borkmann , Florent Revest , Brendan Jackman , Pauline Middelink Subject: [PATCH bpf-next v4 2/2] bpf: Add tests for bpf_bprm_opts_set helper Date: Tue, 17 Nov 2020 23:29:29 +0000 Message-Id: <20201117232929.2156341-2-kpsingh@chromium.org> X-Mailer: git-send-email 2.29.2.299.gdc1121823c-goog In-Reply-To: <20201117232929.2156341-1-kpsingh@chromium.org> References: <20201117232929.2156341-1-kpsingh@chromium.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: KP Singh The test forks a child process, updates the local storage to set/unset the securexec bit. The BPF program in the test attaches to bprm_creds_for_exec which checks the local storage of the current task to set the secureexec bit on the binary parameters (bprm). The child then execs a bash command with the environment variable TMPDIR set in the envp. The bash command returns a different exit code based on its observed value of the TMPDIR variable. Since TMPDIR is one of the variables that is ignored by the dynamic loader when the secureexec bit is set, one should expect the child execution to not see this value when the secureexec bit is set. Acked-by: Martin KaFai Lau Signed-off-by: KP Singh --- .../selftests/bpf/prog_tests/test_bprm_opts.c | 116 ++++++++++++++++++ tools/testing/selftests/bpf/progs/bprm_opts.c | 34 +++++ 2 files changed, 150 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/test_bprm_opts.c create mode 100644 tools/testing/selftests/bpf/progs/bprm_opts.c diff --git a/tools/testing/selftests/bpf/prog_tests/test_bprm_opts.c b/tools/testing/selftests/bpf/prog_tests/test_bprm_opts.c new file mode 100644 index 000000000000..2559bb775762 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/test_bprm_opts.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Copyright (C) 2020 Google LLC. + */ + +#include +#include + +#include "bprm_opts.skel.h" +#include "network_helpers.h" + +#ifndef __NR_pidfd_open +#define __NR_pidfd_open 434 +#endif + +static const char * const bash_envp[] = { "TMPDIR=shouldnotbeset", NULL }; + +static inline int sys_pidfd_open(pid_t pid, unsigned int flags) +{ + return syscall(__NR_pidfd_open, pid, flags); +} + +static int update_storage(int map_fd, int secureexec) +{ + int task_fd, ret = 0; + + task_fd = sys_pidfd_open(getpid(), 0); + if (task_fd < 0) + return errno; + + ret = bpf_map_update_elem(map_fd, &task_fd, &secureexec, BPF_NOEXIST); + if (ret) + ret = errno; + + close(task_fd); + return ret; +} + +static int run_set_secureexec(int map_fd, int secureexec) +{ + int child_pid, child_status, ret, null_fd; + + child_pid = fork(); + if (child_pid == 0) { + null_fd = open("/dev/null", O_WRONLY); + if (null_fd == -1) + exit(errno); + dup2(null_fd, STDOUT_FILENO); + dup2(null_fd, STDERR_FILENO); + close(null_fd); + + /* Ensure that all executions from hereon are + * secure by setting a local storage which is read by + * the bprm_creds_for_exec hook and sets bprm->secureexec. + */ + ret = update_storage(map_fd, secureexec); + if (ret) + exit(ret); + + /* If the binary is executed with securexec=1, the dynamic + * loader ingores and unsets certain variables like LD_PRELOAD, + * TMPDIR etc. TMPDIR is used here to simplify the example, as + * LD_PRELOAD requires a real .so file. + * + * If the value of TMPDIR is set, the bash command returns 10 + * and if the value is unset, it returns 20. + */ + execle("/bin/bash", "bash", "-c", + "[[ -z \"${TMPDIR}\" ]] || exit 10 && exit 20", NULL, + bash_envp); + exit(errno); + } else if (child_pid > 0) { + waitpid(child_pid, &child_status, 0); + ret = WEXITSTATUS(child_status); + + /* If a secureexec occurred, the exit status should be 20 */ + if (secureexec && ret == 20) + return 0; + + /* If normal execution happened, the exit code should be 10 */ + if (!secureexec && ret == 10) + return 0; + } + + return -EINVAL; +} + +void test_test_bprm_opts(void) +{ + int err, duration = 0; + struct bprm_opts *skel = NULL; + + skel = bprm_opts__open_and_load(); + if (CHECK(!skel, "skel_load", "skeleton failed\n")) + goto close_prog; + + err = bprm_opts__attach(skel); + if (CHECK(err, "attach", "attach failed: %d\n", err)) + goto close_prog; + + /* Run the test with the secureexec bit unset */ + err = run_set_secureexec(bpf_map__fd(skel->maps.secure_exec_task_map), + 0 /* secureexec */); + if (CHECK(err, "run_set_secureexec:0", "err = %d\n", err)) + goto close_prog; + + /* Run the test with the secureexec bit set */ + err = run_set_secureexec(bpf_map__fd(skel->maps.secure_exec_task_map), + 1 /* secureexec */); + if (CHECK(err, "run_set_secureexec:1", "err = %d\n", err)) + goto close_prog; + +close_prog: + bprm_opts__destroy(skel); +} diff --git a/tools/testing/selftests/bpf/progs/bprm_opts.c b/tools/testing/selftests/bpf/progs/bprm_opts.c new file mode 100644 index 000000000000..5bfef2887e70 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/bprm_opts.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Copyright 2020 Google LLC. + */ + +#include "vmlinux.h" +#include +#include +#include + +char _license[] SEC("license") = "GPL"; + +struct { + __uint(type, BPF_MAP_TYPE_TASK_STORAGE); + __uint(map_flags, BPF_F_NO_PREALLOC); + __type(key, int); + __type(value, int); +} secure_exec_task_map SEC(".maps"); + +SEC("lsm/bprm_creds_for_exec") +int BPF_PROG(secure_exec, struct linux_binprm *bprm) +{ + int *secureexec; + + secureexec = bpf_task_storage_get(&secure_exec_task_map, + bpf_get_current_task_btf(), 0, + BPF_LOCAL_STORAGE_GET_F_CREATE); + + if (secureexec && *secureexec) + bpf_bprm_opts_set(bprm, BPF_F_BPRM_SECUREEXEC); + + return 0; +} -- 2.29.2.299.gdc1121823c-goog