mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-04-13 09:59:31 +00:00
selftests/exec: add a test for execveat()'s comm
In the previous patch we've updated AT_EMPTY_PATH execs to use the dentry filename. Test for this and just to be sure keeps working with symlinks, which was a concern in [1], I've added a test for that as well. The test itself is a bit ugly, because the existing check_execveat_fail() helpers use a hardcoded envp and argv, and we want to "pass" things via the environment to test various argument values, but it seemed cleaner than passing one in everywhere in all the existing tests. Output looks like: ok 51 Check success of execveat(6, 'home/tycho/packages/...yyyyyyyyyyyyyyyyyyyy', 0)... # Check execveat(AT_EMPTY_PATH)'s comm is execveat ok 52 Check success of execveat(9, '', 4096)... # Check execveat(AT_EMPTY_PATH)'s comm is execveat ok 53 Check success of execveat(11, '', 4096)... # Check execveat(AT_EMPTY_PATH)'s comm is execveat [ 25.579272] process 'execveat' launched '/dev/fd/9' with NULL argv: empty string added ok 54 Check success of execveat(9, '', 4096)... Link: https://lore.kernel.org/all/20240925.152228-private.conflict.frozen.trios-TdUGhuI5Sb4v@cyphar.com/ [1] Signed-off-by: Tycho Andersen <tandersen@netflix.com> Link: https://lore.kernel.org/r/20241030203732.248767-2-tycho@tycho.pizza Signed-off-by: Kees Cook <kees@kernel.org>
This commit is contained in:
parent
543841d180
commit
184a9358e5
1 changed files with 72 additions and 3 deletions
|
@ -23,9 +23,11 @@
|
|||
|
||||
#include "../kselftest.h"
|
||||
|
||||
#define TESTS_EXPECTED 51
|
||||
#define TESTS_EXPECTED 54
|
||||
#define TEST_NAME_LEN (PATH_MAX * 4)
|
||||
|
||||
#define CHECK_COMM "CHECK_COMM"
|
||||
|
||||
static char longpath[2 * PATH_MAX] = "";
|
||||
static char *envp[] = { "IN_TEST=yes", NULL, NULL };
|
||||
static char *argv[] = { "execveat", "99", NULL };
|
||||
|
@ -237,6 +239,29 @@ static int check_execveat_pathmax(int root_dfd, const char *src, int is_script)
|
|||
return fail;
|
||||
}
|
||||
|
||||
static int check_execveat_comm(int fd, char *argv0, char *expected)
|
||||
{
|
||||
char buf[128], *old_env, *old_argv0;
|
||||
int ret;
|
||||
|
||||
snprintf(buf, sizeof(buf), CHECK_COMM "=%s", expected);
|
||||
|
||||
old_env = envp[1];
|
||||
envp[1] = buf;
|
||||
|
||||
old_argv0 = argv[0];
|
||||
argv[0] = argv0;
|
||||
|
||||
ksft_print_msg("Check execveat(AT_EMPTY_PATH)'s comm is %s\n",
|
||||
expected);
|
||||
ret = check_execveat_invoked_rc(fd, "", AT_EMPTY_PATH, 0, 0);
|
||||
|
||||
envp[1] = old_env;
|
||||
argv[0] = old_argv0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int run_tests(void)
|
||||
{
|
||||
int fail = 0;
|
||||
|
@ -389,6 +414,14 @@ static int run_tests(void)
|
|||
|
||||
fail += check_execveat_pathmax(root_dfd, "execveat", 0);
|
||||
fail += check_execveat_pathmax(root_dfd, "script", 1);
|
||||
|
||||
/* /proc/pid/comm gives filename by default */
|
||||
fail += check_execveat_comm(fd, "sentinel", "execveat");
|
||||
/* /proc/pid/comm gives argv[0] when invoked via link */
|
||||
fail += check_execveat_comm(fd_symlink, "sentinel", "execveat");
|
||||
/* /proc/pid/comm gives filename if NULL is passed */
|
||||
fail += check_execveat_comm(fd, NULL, "execveat");
|
||||
|
||||
return fail;
|
||||
}
|
||||
|
||||
|
@ -415,9 +448,13 @@ int main(int argc, char **argv)
|
|||
int ii;
|
||||
int rc;
|
||||
const char *verbose = getenv("VERBOSE");
|
||||
const char *check_comm = getenv(CHECK_COMM);
|
||||
|
||||
if (argc >= 2) {
|
||||
/* If we are invoked with an argument, don't run tests. */
|
||||
if (argc >= 2 || check_comm) {
|
||||
/*
|
||||
* If we are invoked with an argument, or no arguments but a
|
||||
* command to check, don't run tests.
|
||||
*/
|
||||
const char *in_test = getenv("IN_TEST");
|
||||
|
||||
if (verbose) {
|
||||
|
@ -426,6 +463,38 @@ int main(int argc, char **argv)
|
|||
ksft_print_msg("\t[%d]='%s\n'", ii, argv[ii]);
|
||||
}
|
||||
|
||||
/* If the tests wanted us to check the command, do so. */
|
||||
if (check_comm) {
|
||||
/* TASK_COMM_LEN == 16 */
|
||||
char buf[32];
|
||||
int fd, ret;
|
||||
|
||||
fd = open("/proc/self/comm", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
ksft_perror("open() comm failed");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = read(fd, buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
ksft_perror("read() comm failed");
|
||||
close(fd);
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
// trim off the \n
|
||||
buf[ret-1] = 0;
|
||||
|
||||
if (strcmp(buf, check_comm)) {
|
||||
ksft_print_msg("bad comm, got: %s expected: %s\n",
|
||||
buf, check_comm);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Check expected environment transferred. */
|
||||
if (!in_test || strcmp(in_test, "yes") != 0) {
|
||||
ksft_print_msg("no IN_TEST=yes in env\n");
|
||||
|
|
Loading…
Add table
Reference in a new issue