linux-api.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Aleksa Sarai <cyphar@cyphar.com>
To: Ingo Molnar <mingo@redhat.com>,
	Peter Zijlstra <peterz@infradead.org>,
	 Juri Lelli <juri.lelli@redhat.com>,
	 Vincent Guittot <vincent.guittot@linaro.org>,
	 Dietmar Eggemann <dietmar.eggemann@arm.com>,
	 Steven Rostedt <rostedt@goodmis.org>,
	Ben Segall <bsegall@google.com>,  Mel Gorman <mgorman@suse.de>,
	Valentin Schneider <vschneid@redhat.com>,
	 Alexander Viro <viro@zeniv.linux.org.uk>,
	 Christian Brauner <brauner@kernel.org>, Jan Kara <jack@suse.cz>,
	 Arnd Bergmann <arnd@arndb.de>, Shuah Khan <shuah@kernel.org>
Cc: Kees Cook <kees@kernel.org>, Florian Weimer <fweimer@redhat.com>,
	 Arnd Bergmann <arnd@arndb.de>,
	Mark Rutland <mark.rutland@arm.com>,
	 linux-kernel@vger.kernel.org, linux-api@vger.kernel.org,
	 linux-fsdevel@vger.kernel.org, linux-arch@vger.kernel.org,
	 linux-kselftest@vger.kernel.org,
	Aleksa Sarai <cyphar@cyphar.com>
Subject: [PATCH RFC 5/8] clone3: add CHECK_FIELDS flag to usize argument
Date: Mon, 02 Sep 2024 17:06:27 +1000	[thread overview]
Message-ID: <20240902-extensible-structs-check_fields-v1-5-545e93ede2f2@cyphar.com> (raw)
In-Reply-To: <20240902-extensible-structs-check_fields-v1-0-545e93ede2f2@cyphar.com>

As with openat2(2), this allows userspace to easily figure out what
flags and fields are supported by clone3(2). For fields which are not
flag-based, we simply set every bit in the field so that a naive
bitwise-and would show that any value of the field is valid.

For args->exit_signal, since we have an explicit bitmask for the field
defined already (CSIGNAL) we can indicate that only those bits are
supported by current kernels. If we add some extra bits to exit_signal
in the future, being able to detect them as new features would be quite
useful.

The intended way of using this interface to get feature information
looks something like the following:

  static bool clone3_clear_sighand_supported;
  static bool clone3_cgroup_supported;

  int check_clone3_support(void)
  {
      int err;
      struct clone_args args = {};

      err = clone3(&args, CHECK_FIELDS | sizeof(args));
      assert(err < 0);
      switch (errno) {
      case EFAULT: case E2BIG:
          /* Old kernel... */
          check_support_the_old_way();
          break;
      case EEXTSYS_NOOP:
          clone3_clear_sighand_supported = (how.flags & CLONE_CLEAR_SIGHAND);
          clone3_cgroup_supported = (how.flags & CLONE_INTO_CGROUP) &&
                                    (how.cgroup != 0);
          break;
      }
  }

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
---
 kernel/fork.c | 33 +++++++++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/kernel/fork.c b/kernel/fork.c
index cc760491f201..1a170098a1c5 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -2925,6 +2925,9 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
 }
 #endif
 
+
+#define CLONE3_VALID_FLAGS (CLONE_LEGACY_FLAGS | CLONE_CLEAR_SIGHAND | CLONE_INTO_CGROUP)
+
 noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
 					      struct clone_args __user *uargs,
 					      size_t usize)
@@ -2941,11 +2944,34 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
 		     CLONE_ARGS_SIZE_VER2);
 	BUILD_BUG_ON(sizeof(struct clone_args) != CLONE_ARGS_SIZE_VER2);
 
-	if (unlikely(usize > PAGE_SIZE))
-		return -E2BIG;
 	if (unlikely(usize < CLONE_ARGS_SIZE_VER0))
 		return -EINVAL;
 
+	if (unlikely(usize & CHECK_FIELDS)) {
+		usize &= ~CHECK_FIELDS;
+
+		memset(&args, 0, sizeof(args));
+		args = (struct clone_args) {
+			.flags = CLONE3_VALID_FLAGS,
+			.pidfd = 0xFFFFFFFFFFFFFFFF,
+			.child_tid = 0xFFFFFFFFFFFFFFFF,
+			.parent_tid = 0xFFFFFFFFFFFFFFFF,
+			.exit_signal = (u64) CSIGNAL,
+			.stack = 0xFFFFFFFFFFFFFFFF,
+			.stack_size = 0xFFFFFFFFFFFFFFFF,
+			.tls = 0xFFFFFFFFFFFFFFFF,
+			.set_tid = 0xFFFFFFFFFFFFFFFF,
+			.set_tid_size = 0xFFFFFFFFFFFFFFFF,
+			.cgroup = 0xFFFFFFFFFFFFFFFF,
+		};
+
+		err = copy_struct_to_user(uargs, usize, &args, sizeof(args), NULL);
+		return err ?: -EEXTSYS_NOOP;
+	}
+
+	if (unlikely(usize > PAGE_SIZE))
+		return -E2BIG;
+
 	err = copy_struct_from_user(&args, sizeof(args), uargs, usize);
 	if (err)
 		return err;
@@ -3025,8 +3051,7 @@ static inline bool clone3_stack_valid(struct kernel_clone_args *kargs)
 static bool clone3_args_valid(struct kernel_clone_args *kargs)
 {
 	/* Verify that no unknown flags are passed along. */
-	if (kargs->flags &
-	    ~(CLONE_LEGACY_FLAGS | CLONE_CLEAR_SIGHAND | CLONE_INTO_CGROUP))
+	if (kargs->flags & ~CLONE3_VALID_FLAGS)
 		return false;
 
 	/*

-- 
2.46.0


  parent reply	other threads:[~2024-09-02  7:07 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-02  7:06 [PATCH RFC 0/8] extensible syscalls: CHECK_FIELDS to allow for easier feature detection Aleksa Sarai
2024-09-02  7:06 ` [PATCH RFC 1/8] uaccess: add copy_struct_to_user helper Aleksa Sarai
2024-09-02  8:55   ` Arnd Bergmann
2024-09-02 16:02     ` Aleksa Sarai
2024-09-02  7:06 ` [PATCH RFC 2/8] sched_getattr: port to copy_struct_to_user Aleksa Sarai
2024-09-02  7:06 ` [PATCH RFC 3/8] openat2: explicitly return -E2BIG for (usize > PAGE_SIZE) Aleksa Sarai
2024-09-02  9:09   ` Arnd Bergmann
2024-09-02 16:08     ` Aleksa Sarai
2024-09-02 19:23       ` Arnd Bergmann
2024-09-02  7:06 ` [PATCH RFC 4/8] openat2: add CHECK_FIELDS flag to usize argument Aleksa Sarai
2024-09-02  7:06 ` Aleksa Sarai [this message]
2024-09-02  7:06 ` [PATCH RFC 6/8] selftests: openat2: add 0xFF poisoned data after misaligned struct Aleksa Sarai
2024-09-02  7:06 ` [PATCH RFC 7/8] selftests: openat2: add CHECK_FIELDS selftests Aleksa Sarai
2024-09-02  7:06 ` [PATCH RFC 8/8] selftests: clone3: " Aleksa Sarai

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=20240902-extensible-structs-check_fields-v1-5-545e93ede2f2@cyphar.com \
    --to=cyphar@cyphar.com \
    --cc=arnd@arndb.de \
    --cc=brauner@kernel.org \
    --cc=bsegall@google.com \
    --cc=dietmar.eggemann@arm.com \
    --cc=fweimer@redhat.com \
    --cc=jack@suse.cz \
    --cc=juri.lelli@redhat.com \
    --cc=kees@kernel.org \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mgorman@suse.de \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=shuah@kernel.org \
    --cc=vincent.guittot@linaro.org \
    --cc=viro@zeniv.linux.org.uk \
    --cc=vschneid@redhat.com \
    /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;
as well as URLs for NNTP newsgroup(s).