From: Tycho Andersen <tycho@tycho.pizza>
To: Alexander Viro <viro@zeniv.linux.org.uk>,
Christian Brauner <brauner@kernel.org>, Jan Kara <jack@suse.cz>,
Eric Biederman <ebiederm@xmission.com>,
Kees Cook <kees@kernel.org>,
Shuah Khan <skhan@linuxfoundation.org>
Cc: "Zbigniew Jędrzejewski-Szmek" <zbyszek@in.waw.pl>,
"Aleksa Sarai" <cyphar@cyphar.com>,
linux-fsdevel@vger.kernel.org, linux-mm@kvack.org,
linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
"Tycho Andersen" <tycho@tycho.pizza>,
"Tycho Andersen" <tandersen@netflix.com>
Subject: [PATCH 2/2] selftests/exec: add a test for execveat()'s comm
Date: Wed, 30 Oct 2024 14:37:32 -0600 [thread overview]
Message-ID: <20241030203732.248767-2-tycho@tycho.pizza> (raw)
In-Reply-To: <20241030203732.248767-1-tycho@tycho.pizza>
From: Tycho Andersen <tandersen@netflix.com>
In the previous patch we've defined a couple behaviors:
1. execveat(fd, AT_EMPTY_PATH, {"foo"}, ...) should render argv[0] as
/proc/pid/comm
2. execveat(fd, AT_EMPTY_PATH, {NULL}, ...) should keep the old behavior of
rendering the fd as /proc/pid/comm
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 sentinel
ok 52 Check success of execveat(9, '', 4096)...
# Check execveat(AT_EMPTY_PATH)'s comm is sentinel
ok 53 Check success of execveat(11, '', 4096)...
# Check execveat(AT_EMPTY_PATH)'s comm is 9
[ 25.579272] process 'execveat' launched '/dev/fd/9' with NULL argv: empty string added
ok 54 Check success of execveat(9, '', 4096)...
[1]: https://lore.kernel.org/all/20240925.152228-private.conflict.frozen.trios-TdUGhuI5Sb4v@cyphar.com/
Signed-off-by: Tycho Andersen <tandersen@netflix.com>
---
v4: fix up commit message, use ksft_perror() vs perror(), Shuah
---
tools/testing/selftests/exec/execveat.c | 77 ++++++++++++++++++++++++-
1 file changed, 74 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/exec/execveat.c b/tools/testing/selftests/exec/execveat.c
index 071e03532cba..3a05f8cbd815 100644
--- a/tools/testing/selftests/exec/execveat.c
+++ b/tools/testing/selftests/exec/execveat.c
@@ -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,12 +239,36 @@ 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;
char *fullname = realpath("execveat", NULL);
char *fullname_script = realpath("script", NULL);
char *fullname_symlink = concat(fullname, ".symlink");
+ char fd_buf[10];
int subdir_dfd = open_or_die("subdir", O_DIRECTORY|O_RDONLY);
int subdir_dfd_ephemeral = open_or_die("subdir.ephemeral",
O_DIRECTORY|O_RDONLY);
@@ -389,6 +415,15 @@ 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 argv[0] by default */
+ fail += check_execveat_comm(fd, "sentinel", "sentinel");
+ /* /proc/pid/comm gives argv[0] when invoked via link */
+ fail += check_execveat_comm(fd_symlink, "sentinel", "sentinel");
+ /* /proc/pid/comm gives fdno if NULL is passed */
+ snprintf(fd_buf, sizeof(fd_buf), "%d", fd);
+ fail += check_execveat_comm(fd, NULL, fd_buf);
+
return fail;
}
@@ -415,9 +450,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 +465,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",
+ 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");
--
2.34.1
next prev parent reply other threads:[~2024-10-30 20:38 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-30 20:37 [PATCH 1/2] exec: fix up /proc/pid/comm in the execveat(AT_EMPTY_PATH) case Tycho Andersen
2024-10-30 20:37 ` Tycho Andersen [this message]
2024-11-27 14:25 ` [PATCH 2/2] selftests/exec: add a test for execveat()'s comm Mark Brown
2024-11-27 15:00 ` Tycho Andersen
2024-11-27 15:03 ` Mark Brown
2024-10-31 22:10 ` [PATCH 1/2] exec: fix up /proc/pid/comm in the execveat(AT_EMPTY_PATH) case Kees Cook
2024-11-02 11:29 ` Zbigniew Jędrzejewski-Szmek
2024-11-02 19:58 ` Kees Cook
2024-11-06 10:06 ` Christian Brauner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241030203732.248767-2-tycho@tycho.pizza \
--to=tycho@tycho.pizza \
--cc=brauner@kernel.org \
--cc=cyphar@cyphar.com \
--cc=ebiederm@xmission.com \
--cc=jack@suse.cz \
--cc=kees@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=skhan@linuxfoundation.org \
--cc=tandersen@netflix.com \
--cc=viro@zeniv.linux.org.uk \
--cc=zbyszek@in.waw.pl \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox