Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 /*
0004  * Copyright (C) 2020 Google LLC.
0005  */
0006 
0007 #include <test_progs.h>
0008 #include <linux/limits.h>
0009 
0010 #include "bprm_opts.skel.h"
0011 #include "network_helpers.h"
0012 
0013 #ifndef __NR_pidfd_open
0014 #define __NR_pidfd_open 434
0015 #endif
0016 
0017 static const char * const bash_envp[] = { "TMPDIR=shouldnotbeset", NULL };
0018 
0019 static inline int sys_pidfd_open(pid_t pid, unsigned int flags)
0020 {
0021     return syscall(__NR_pidfd_open, pid, flags);
0022 }
0023 
0024 static int update_storage(int map_fd, int secureexec)
0025 {
0026     int task_fd, ret = 0;
0027 
0028     task_fd = sys_pidfd_open(getpid(), 0);
0029     if (task_fd < 0)
0030         return errno;
0031 
0032     ret = bpf_map_update_elem(map_fd, &task_fd, &secureexec, BPF_NOEXIST);
0033     if (ret)
0034         ret = errno;
0035 
0036     close(task_fd);
0037     return ret;
0038 }
0039 
0040 static int run_set_secureexec(int map_fd, int secureexec)
0041 {
0042     int child_pid, child_status, ret, null_fd;
0043 
0044     child_pid = fork();
0045     if (child_pid == 0) {
0046         null_fd = open("/dev/null", O_WRONLY);
0047         if (null_fd == -1)
0048             exit(errno);
0049         dup2(null_fd, STDOUT_FILENO);
0050         dup2(null_fd, STDERR_FILENO);
0051         close(null_fd);
0052 
0053         /* Ensure that all executions from hereon are
0054          * secure by setting a local storage which is read by
0055          * the bprm_creds_for_exec hook and sets bprm->secureexec.
0056          */
0057         ret = update_storage(map_fd, secureexec);
0058         if (ret)
0059             exit(ret);
0060 
0061         /* If the binary is executed with securexec=1, the dynamic
0062          * loader ingores and unsets certain variables like LD_PRELOAD,
0063          * TMPDIR etc. TMPDIR is used here to simplify the example, as
0064          * LD_PRELOAD requires a real .so file.
0065          *
0066          * If the value of TMPDIR is set, the bash command returns 10
0067          * and if the value is unset, it returns 20.
0068          */
0069         execle("/bin/bash", "bash", "-c",
0070                "[[ -z \"${TMPDIR}\" ]] || exit 10 && exit 20", NULL,
0071                bash_envp);
0072         exit(errno);
0073     } else if (child_pid > 0) {
0074         waitpid(child_pid, &child_status, 0);
0075         ret = WEXITSTATUS(child_status);
0076 
0077         /* If a secureexec occurred, the exit status should be 20 */
0078         if (secureexec && ret == 20)
0079             return 0;
0080 
0081         /* If normal execution happened, the exit code should be 10 */
0082         if (!secureexec && ret == 10)
0083             return 0;
0084     }
0085 
0086     return -EINVAL;
0087 }
0088 
0089 void test_test_bprm_opts(void)
0090 {
0091     int err, duration = 0;
0092     struct bprm_opts *skel = NULL;
0093 
0094     skel = bprm_opts__open_and_load();
0095     if (CHECK(!skel, "skel_load", "skeleton failed\n"))
0096         goto close_prog;
0097 
0098     err = bprm_opts__attach(skel);
0099     if (CHECK(err, "attach", "attach failed: %d\n", err))
0100         goto close_prog;
0101 
0102     /* Run the test with the secureexec bit unset */
0103     err = run_set_secureexec(bpf_map__fd(skel->maps.secure_exec_task_map),
0104                  0 /* secureexec */);
0105     if (CHECK(err, "run_set_secureexec:0", "err = %d\n", err))
0106         goto close_prog;
0107 
0108     /* Run the test with the secureexec bit set */
0109     err = run_set_secureexec(bpf_map__fd(skel->maps.secure_exec_task_map),
0110                  1 /* secureexec */);
0111     if (CHECK(err, "run_set_secureexec:1", "err = %d\n", err))
0112         goto close_prog;
0113 
0114 close_prog:
0115     bprm_opts__destroy(skel);
0116 }