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