Linux Test Project
 help / color / mirror / Atom feed
From: Andrea Cervesato <andrea.cervesato@suse.de>
To: Linux Test Project <ltp@lists.linux.it>
Subject: [LTP] [PATCH STAGING v2 06/16] fchroot03: test fchroot() permission checks
Date: Thu, 20 Aug 2026 09:44:46 +0200	[thread overview]
Message-ID: <20260820-fchroot-v2-6-062ed20957a0@suse.com> (raw)
In-Reply-To: <20260820-fchroot-v2-0-062ed20957a0@suse.com>

From: Andrea Cervesato <andrea.cervesato@suse.com>

Verify that with a regular directory fd the kernel first checks the
execute permission on the directory and then CAP_SYS_CHROOT: an
unprivileged process with an accessible directory fails with EPERM and
a process without execute permission fails with EACCES.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 runtest/staging                               |  1 +
 testcases/kernel/syscalls/fchroot/.gitignore  |  1 +
 testcases/kernel/syscalls/fchroot/fchroot03.c | 78 +++++++++++++++++++++++++++
 3 files changed, 80 insertions(+)

diff --git a/runtest/staging b/runtest/staging
index e12230218..13635037b 100644
--- a/runtest/staging
+++ b/runtest/staging
@@ -2,3 +2,4 @@
 
 fchroot01 fchroot01
 fchroot02 fchroot02
+fchroot03 fchroot03
diff --git a/testcases/kernel/syscalls/fchroot/.gitignore b/testcases/kernel/syscalls/fchroot/.gitignore
index fb3287612..235befd99 100644
--- a/testcases/kernel/syscalls/fchroot/.gitignore
+++ b/testcases/kernel/syscalls/fchroot/.gitignore
@@ -1,2 +1,3 @@
 fchroot01
 fchroot02
+fchroot03
diff --git a/testcases/kernel/syscalls/fchroot/fchroot03.c b/testcases/kernel/syscalls/fchroot/fchroot03.c
new file mode 100644
index 000000000..79d3daf7d
--- /dev/null
+++ b/testcases/kernel/syscalls/fchroot/fchroot03.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test the :manpage:`fchroot(2)` permission checks with a regular directory
+ * fd.
+ *
+ * :manpage:`fchroot(2) `was introduced in Linux v7.3. With a regular directory
+ * fd the kernel first checks that the caller has execute permission on the
+ * directory, then that it holds ``CAP_SYS_CHROOT``:
+ *
+ * - an unprivileged process with an accessible directory fails with ``EPERM``
+ * - a process without execute permission on the directory fails with
+ *   ``EACCES``, proving the permission check comes before the capability
+ *   check
+ *
+ * Root is required to open the directory file descriptors before dropping
+ * to an unprivileged user in forked children.
+ */
+
+#include <fcntl.h>
+#include <pwd.h>
+#include "tst_test.h"
+#include "lapi/fcntl.h"
+#include "lapi/syscalls.h"
+
+static struct tcase {
+	const char *dir;
+	mode_t mode;
+	int exp_errno;
+	const char *desc;
+} tcases[] = {
+	{"pubdir", 0755, EPERM, "no CAP_SYS_CHROOT"},
+	{"privdir", 0600, EACCES, "no execute permission"},
+};
+
+static struct passwd *ltpuser;
+
+static void run(unsigned int i)
+{
+	struct tcase *tc = &tcases[i];
+
+	if (SAFE_FORK())
+		return;
+
+	int dfd = SAFE_OPEN(tc->dir, O_PATH | O_DIRECTORY);
+
+	SAFE_SETRESUID(ltpuser->pw_uid, ltpuser->pw_uid,
+		ltpuser->pw_uid);
+
+	TST_EXP_FAIL(tst_syscall(__NR_fchroot, dfd, 0),
+		tc->exp_errno, "fchroot() with %s", tc->desc);
+
+	exit(0);
+}
+
+static void setup(void)
+{
+	unsigned int i;
+
+	ltpuser = SAFE_GETPWNAM("nobody");
+
+	for (i = 0; i < ARRAY_SIZE(tcases); i++) {
+		SAFE_MKDIR(tcases[i].dir, tcases[i].mode);
+		SAFE_CHMOD(tcases[i].dir, tcases[i].mode);
+	}
+}
+
+static struct tst_test test = {
+	.test = run,
+	.tcnt = ARRAY_SIZE(tcases),
+	.setup = setup,
+	.needs_root = 1,
+	.needs_tmpdir = 1,
+	.forks_child = 1,
+};

-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

  parent reply	other threads:[~2026-08-20  7:47 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-20  7:44 [LTP] [PATCH v2 00/16] fchroot: add fchroot() testing suite Andrea Cervesato
2026-08-20  7:44 ` [LTP] [PATCH v2 01/16] syscalls: add v7.3 syscall numbers Andrea Cervesato
2026-08-20  8:34   ` [LTP] " linuxtestproject.agent
2026-08-20  8:37     ` Andrea Cervesato via ltp
2026-08-20  7:44 ` [LTP] [PATCH v2 02/16] syscalls: update outdated syscall entries Andrea Cervesato
2026-08-20  7:44 ` [LTP] [PATCH STAGING v2 03/16] lapi: fallback fchroot() parameters Andrea Cervesato
2026-08-20  7:44 ` [LTP] [PATCH STAGING v2 04/16] fchroot01: test fchroot() with a directory fd Andrea Cervesato
2026-08-20 14:13   ` Cyril Hrubis
2026-08-20 14:23     ` Andrea Cervesato via ltp
2026-08-20 14:58       ` Cyril Hrubis
2026-08-20  7:44 ` [LTP] [PATCH STAGING v2 05/16] fchroot02: test fchroot() invalid arguments Andrea Cervesato
2026-08-20 14:10   ` Cyril Hrubis
2026-08-20  7:44 ` Andrea Cervesato [this message]
2026-08-20 14:19   ` [LTP] [PATCH STAGING v2 06/16] fchroot03: test fchroot() permission checks Cyril Hrubis
2026-08-20  7:44 ` [LTP] [PATCH STAGING v2 07/16] fchroot04: test fchroot() into failfs as root Andrea Cervesato
2026-08-20 14:24   ` Cyril Hrubis
2026-08-20  7:44 ` [LTP] [PATCH STAGING v2 08/16] fchroot05: test failfs root can not be referenced Andrea Cervesato
2026-08-20 14:37   ` Cyril Hrubis
2026-08-20  7:44 ` [LTP] [PATCH STAGING v2 09/16] fchroot06: test path walks under failfs root Andrea Cervesato
2026-08-20 15:54   ` Cyril Hrubis
2026-08-20  7:44 ` [LTP] [PATCH STAGING v2 10/16] fchroot07: test execve blocked by " Andrea Cervesato
2026-08-20 16:17   ` Cyril Hrubis
2026-08-20  7:44 ` [LTP] [PATCH STAGING v2 11/16] fchroot08: test failfs root fork inheritance Andrea Cervesato
2026-08-20  7:44 ` [LTP] [PATCH STAGING v2 12/16] fchroot09: test setns escape from failfs root Andrea Cervesato
2026-08-20  7:44 ` [LTP] [PATCH STAGING v2 13/16] fchroot10: test failfs entry without no_new_privs Andrea Cervesato
2026-08-20  7:44 ` [LTP] [PATCH STAGING v2 14/16] fchroot11: test failfs entry with no_new_privs Andrea Cervesato
2026-08-20  7:44 ` [LTP] [PATCH STAGING v2 15/16] fchroot12: test failfs entry with shared fs_struct Andrea Cervesato
2026-08-20  7:44 ` [LTP] [PATCH STAGING v2 16/16] fchroot13: test failfs entry when chrooted Andrea Cervesato

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=20260820-fchroot-v2-6-062ed20957a0@suse.com \
    --to=andrea.cervesato@suse.de \
    --cc=ltp@lists.linux.it \
    /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