1ea87ae85SKP Singh // SPDX-License-Identifier: GPL-2.0
2ea87ae85SKP Singh
3ea87ae85SKP Singh /*
4ea87ae85SKP Singh * Copyright (C) 2020 Google LLC.
5ea87ae85SKP Singh */
6ea87ae85SKP Singh
7ea87ae85SKP Singh #include <test_progs.h>
8ea87ae85SKP Singh #include <linux/limits.h>
9ea87ae85SKP Singh
10ea87ae85SKP Singh #include "bprm_opts.skel.h"
11ea87ae85SKP Singh #include "network_helpers.h"
12*c710136eSHou Tao #include "task_local_storage_helpers.h"
13ea87ae85SKP Singh
14ea87ae85SKP Singh static const char * const bash_envp[] = { "TMPDIR=shouldnotbeset", NULL };
15ea87ae85SKP Singh
update_storage(int map_fd,int secureexec)16ea87ae85SKP Singh static int update_storage(int map_fd, int secureexec)
17ea87ae85SKP Singh {
18ea87ae85SKP Singh int task_fd, ret = 0;
19ea87ae85SKP Singh
20ea87ae85SKP Singh task_fd = sys_pidfd_open(getpid(), 0);
21ea87ae85SKP Singh if (task_fd < 0)
22ea87ae85SKP Singh return errno;
23ea87ae85SKP Singh
24ea87ae85SKP Singh ret = bpf_map_update_elem(map_fd, &task_fd, &secureexec, BPF_NOEXIST);
25ea87ae85SKP Singh if (ret)
26ea87ae85SKP Singh ret = errno;
27ea87ae85SKP Singh
28ea87ae85SKP Singh close(task_fd);
29ea87ae85SKP Singh return ret;
30ea87ae85SKP Singh }
31ea87ae85SKP Singh
run_set_secureexec(int map_fd,int secureexec)32ea87ae85SKP Singh static int run_set_secureexec(int map_fd, int secureexec)
33ea87ae85SKP Singh {
34ea87ae85SKP Singh int child_pid, child_status, ret, null_fd;
35ea87ae85SKP Singh
36ea87ae85SKP Singh child_pid = fork();
37ea87ae85SKP Singh if (child_pid == 0) {
38ea87ae85SKP Singh null_fd = open("/dev/null", O_WRONLY);
39ea87ae85SKP Singh if (null_fd == -1)
40ea87ae85SKP Singh exit(errno);
41ea87ae85SKP Singh dup2(null_fd, STDOUT_FILENO);
42ea87ae85SKP Singh dup2(null_fd, STDERR_FILENO);
43ea87ae85SKP Singh close(null_fd);
44ea87ae85SKP Singh
45ea87ae85SKP Singh /* Ensure that all executions from hereon are
46ea87ae85SKP Singh * secure by setting a local storage which is read by
47ea87ae85SKP Singh * the bprm_creds_for_exec hook and sets bprm->secureexec.
48ea87ae85SKP Singh */
49ea87ae85SKP Singh ret = update_storage(map_fd, secureexec);
50ea87ae85SKP Singh if (ret)
51ea87ae85SKP Singh exit(ret);
52ea87ae85SKP Singh
53ea87ae85SKP Singh /* If the binary is executed with securexec=1, the dynamic
54ea87ae85SKP Singh * loader ingores and unsets certain variables like LD_PRELOAD,
55ea87ae85SKP Singh * TMPDIR etc. TMPDIR is used here to simplify the example, as
56ea87ae85SKP Singh * LD_PRELOAD requires a real .so file.
57ea87ae85SKP Singh *
58ea87ae85SKP Singh * If the value of TMPDIR is set, the bash command returns 10
59ea87ae85SKP Singh * and if the value is unset, it returns 20.
60ea87ae85SKP Singh */
61ea87ae85SKP Singh execle("/bin/bash", "bash", "-c",
62ea87ae85SKP Singh "[[ -z \"${TMPDIR}\" ]] || exit 10 && exit 20", NULL,
63ea87ae85SKP Singh bash_envp);
64ea87ae85SKP Singh exit(errno);
65ea87ae85SKP Singh } else if (child_pid > 0) {
66ea87ae85SKP Singh waitpid(child_pid, &child_status, 0);
67ea87ae85SKP Singh ret = WEXITSTATUS(child_status);
68ea87ae85SKP Singh
69ea87ae85SKP Singh /* If a secureexec occurred, the exit status should be 20 */
70ea87ae85SKP Singh if (secureexec && ret == 20)
71ea87ae85SKP Singh return 0;
72ea87ae85SKP Singh
73ea87ae85SKP Singh /* If normal execution happened, the exit code should be 10 */
74ea87ae85SKP Singh if (!secureexec && ret == 10)
75ea87ae85SKP Singh return 0;
76ea87ae85SKP Singh }
77ea87ae85SKP Singh
78ea87ae85SKP Singh return -EINVAL;
79ea87ae85SKP Singh }
80ea87ae85SKP Singh
test_test_bprm_opts(void)81ea87ae85SKP Singh void test_test_bprm_opts(void)
82ea87ae85SKP Singh {
83ea87ae85SKP Singh int err, duration = 0;
84ea87ae85SKP Singh struct bprm_opts *skel = NULL;
85ea87ae85SKP Singh
86ea87ae85SKP Singh skel = bprm_opts__open_and_load();
87ea87ae85SKP Singh if (CHECK(!skel, "skel_load", "skeleton failed\n"))
88ea87ae85SKP Singh goto close_prog;
89ea87ae85SKP Singh
90ea87ae85SKP Singh err = bprm_opts__attach(skel);
91ea87ae85SKP Singh if (CHECK(err, "attach", "attach failed: %d\n", err))
92ea87ae85SKP Singh goto close_prog;
93ea87ae85SKP Singh
94ea87ae85SKP Singh /* Run the test with the secureexec bit unset */
95ea87ae85SKP Singh err = run_set_secureexec(bpf_map__fd(skel->maps.secure_exec_task_map),
96ea87ae85SKP Singh 0 /* secureexec */);
97ea87ae85SKP Singh if (CHECK(err, "run_set_secureexec:0", "err = %d\n", err))
98ea87ae85SKP Singh goto close_prog;
99ea87ae85SKP Singh
100ea87ae85SKP Singh /* Run the test with the secureexec bit set */
101ea87ae85SKP Singh err = run_set_secureexec(bpf_map__fd(skel->maps.secure_exec_task_map),
102ea87ae85SKP Singh 1 /* secureexec */);
103ea87ae85SKP Singh if (CHECK(err, "run_set_secureexec:1", "err = %d\n", err))
104ea87ae85SKP Singh goto close_prog;
105ea87ae85SKP Singh
106ea87ae85SKP Singh close_prog:
107ea87ae85SKP Singh bprm_opts__destroy(skel);
108ea87ae85SKP Singh }
109