All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Günther Noack" <gnoack3000@gmail.com>
To: "Mickaël Salaün" <mic@digikod.net>
Cc: linux-security-module@vger.kernel.org,
	James Morris <jmorris@namei.org>,
	Paul Moore <paul@paul-moore.com>,
	"Serge E . Hallyn" <serge@hallyn.com>,
	linux-fsdevel@vger.kernel.org,
	Konstantin Meskhidze <konstantin.meskhidze@huawei.com>
Subject: Re: [PATCH v8 7/9] selftests/landlock: Test FD passing from a Landlock-restricted to an unrestricted process
Date: Sat, 8 Oct 2022 10:25:38 +0200	[thread overview]
Message-ID: <Y0E0AuxsnwOYV8TL@nuc> (raw)
In-Reply-To: <ffacf78b-991f-3476-b3b8-9d8b847141fb@digikod.net>

On Wed, Oct 05, 2022 at 08:57:12PM +0200, Mickaël Salaün wrote:
> Thanks for this refactoring.
> 
> We need a shorter subject though. ;)

Done, changed to:
"selftests/landlock: Test FD passing from restricted to unrestricted processes"

> On 01/10/2022 17:49, Günther Noack wrote:
> > A file descriptor created in a restricted process carries Landlock
> > restrictions with it which will apply even if the same opened file is
> > used from an unrestricted process.
> > 
> > This change extracts suitable FD-passing helpers from base_test.c and
> > moves them to common.h. We use the fixture variants from the ftruncate
> > fixture to exercise the same scenarios as in the open_and_ftruncate
> > test, but doing the Landlock restriction and open() in a different
> > process than the ftruncate() call.
> > 
> > Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> > ---
> >   tools/testing/selftests/landlock/base_test.c | 36 +----------
> >   tools/testing/selftests/landlock/common.h    | 67 ++++++++++++++++++++
> >   tools/testing/selftests/landlock/fs_test.c   | 62 ++++++++++++++++++
> >   3 files changed, 132 insertions(+), 33 deletions(-)
> > 
> > diff --git a/tools/testing/selftests/landlock/base_test.c b/tools/testing/selftests/landlock/base_test.c
> > index 72cdae277b02..6d1b6eedb432 100644
> > --- a/tools/testing/selftests/landlock/base_test.c
> > +++ b/tools/testing/selftests/landlock/base_test.c
> > @@ -263,23 +263,6 @@ TEST(ruleset_fd_transfer)
> >   		.allowed_access = LANDLOCK_ACCESS_FS_READ_DIR,
> >   	};
> >   	int ruleset_fd_tx, dir_fd;
> > -	union {
> > -		/* Aligned ancillary data buffer. */
> > -		char buf[CMSG_SPACE(sizeof(ruleset_fd_tx))];
> > -		struct cmsghdr _align;
> > -	} cmsg_tx = {};
> > -	char data_tx = '.';
> > -	struct iovec io = {
> > -		.iov_base = &data_tx,
> > -		.iov_len = sizeof(data_tx),
> > -	};
> > -	struct msghdr msg = {
> > -		.msg_iov = &io,
> > -		.msg_iovlen = 1,
> > -		.msg_control = &cmsg_tx.buf,
> > -		.msg_controllen = sizeof(cmsg_tx.buf),
> > -	};
> > -	struct cmsghdr *cmsg;
> >   	int socket_fds[2];
> >   	pid_t child;
> >   	int status;
> > @@ -298,33 +281,20 @@ TEST(ruleset_fd_transfer)
> >   				    &path_beneath_attr, 0));
> >   	ASSERT_EQ(0, close(path_beneath_attr.parent_fd));
> > -	cmsg = CMSG_FIRSTHDR(&msg);
> > -	ASSERT_NE(NULL, cmsg);
> > -	cmsg->cmsg_len = CMSG_LEN(sizeof(ruleset_fd_tx));
> > -	cmsg->cmsg_level = SOL_SOCKET;
> > -	cmsg->cmsg_type = SCM_RIGHTS;
> > -	memcpy(CMSG_DATA(cmsg), &ruleset_fd_tx, sizeof(ruleset_fd_tx));
> > -
> >   	/* Sends the ruleset FD over a socketpair and then close it. */
> >   	ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0,
> >   				socket_fds));
> > -	ASSERT_EQ(sizeof(data_tx), sendmsg(socket_fds[0], &msg, 0));
> > +	ASSERT_EQ(0, send_fd(socket_fds[0], ruleset_fd_tx));
> >   	ASSERT_EQ(0, close(socket_fds[0]));
> >   	ASSERT_EQ(0, close(ruleset_fd_tx));
> >   	child = fork();
> >   	ASSERT_LE(0, child);
> >   	if (child == 0) {
> > -		int ruleset_fd_rx;
> > +		int ruleset_fd_rx = recv_fd(socket_fds[1]);
> 
> We can now make it const.

Done.

> > -		*(char *)msg.msg_iov->iov_base = '\0';
> > -		ASSERT_EQ(sizeof(data_tx),
> > -			  recvmsg(socket_fds[1], &msg, MSG_CMSG_CLOEXEC));
> > -		ASSERT_EQ('.', *(char *)msg.msg_iov->iov_base);
> > +		ASSERT_LE(0, ruleset_fd_rx);
> >   		ASSERT_EQ(0, close(socket_fds[1]));
> > -		cmsg = CMSG_FIRSTHDR(&msg);
> > -		ASSERT_EQ(cmsg->cmsg_len, CMSG_LEN(sizeof(ruleset_fd_tx)));
> > -		memcpy(&ruleset_fd_rx, CMSG_DATA(cmsg), sizeof(ruleset_fd_tx));
> >   		/* Enforces the received ruleset on the child. */
> >   		ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
> > diff --git a/tools/testing/selftests/landlock/common.h b/tools/testing/selftests/landlock/common.h
> > index 7d34592471db..15149d34e43b 100644
> > --- a/tools/testing/selftests/landlock/common.h
> > +++ b/tools/testing/selftests/landlock/common.h
> > @@ -10,6 +10,7 @@
> >   #include <errno.h>
> >   #include <linux/landlock.h>
> >   #include <sys/capability.h>
> > +#include <sys/socket.h>
> >   #include <sys/syscall.h>
> >   #include <sys/types.h>
> >   #include <sys/wait.h>
> > @@ -189,3 +190,69 @@ static void __maybe_unused clear_cap(struct __test_metadata *const _metadata,
> >   {
> >   	_effective_cap(_metadata, caps, CAP_CLEAR);
> >   }
> > +
> > +/* Receives an FD from a UNIX socket. Returns the received FD, -1 on error. */
> > +static int __maybe_unused recv_fd(int usock)
> > +{
> > +	int fd_rx;
> > +	union {
> > +		/* Aligned ancillary data buffer. */
> > +		char buf[CMSG_SPACE(sizeof(fd_rx))];
> > +		struct cmsghdr _align;
> > +	} cmsg_rx = {};
> > +	char data = '\0';
> > +	struct iovec io = {
> > +		.iov_base = &data,
> > +		.iov_len = sizeof(data),
> > +	};
> > +	struct msghdr msg = {
> > +		.msg_iov = &io,
> > +		.msg_iovlen = 1,
> > +		.msg_control = &cmsg_rx.buf,
> > +		.msg_controllen = sizeof(cmsg_rx.buf),
> > +	};
> > +	struct cmsghdr *cmsg;
> > +	int res;
> > +
> > +	res = recvmsg(usock, &msg, MSG_CMSG_CLOEXEC);
> > +	if (res < 0)
> > +		return -1;
> 
> It could be useful to return -errno for recv_fd() and send_fd(), and update
> the description accordingly. That would enable to quickly know the error
> with the ASSERT_*() calls.

Done, good idea.


> > +	cmsg = CMSG_FIRSTHDR(&msg);
> > +	if (cmsg->cmsg_len != CMSG_LEN(sizeof(fd_rx)))
> > +		return -1;

I made it return -EIO in the case where the other side sends invalid data.


> > +	memcpy(&fd_rx, CMSG_DATA(cmsg), sizeof(fd_rx));
> > +	return fd_rx;
> > +}
> > +
> > +/* Sends an FD on a UNIX socket. Returns 0 on success or -1 on error. */
> > +static int __maybe_unused send_fd(int usock, int fd_tx)
> > +{
> > +	union {
> > +		/* Aligned ancillary data buffer. */
> > +		char buf[CMSG_SPACE(sizeof(fd_tx))];
> > +		struct cmsghdr _align;
> > +	} cmsg_tx = {};
> > +	char data_tx = '.';
> > +	struct iovec io = {
> > +		.iov_base = &data_tx,
> > +		.iov_len = sizeof(data_tx),
> > +	};
> > +	struct msghdr msg = {
> > +		.msg_iov = &io,
> > +		.msg_iovlen = 1,
> > +		.msg_control = &cmsg_tx.buf,
> > +		.msg_controllen = sizeof(cmsg_tx.buf),
> > +	};
> > +	struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
> > +
> > +	cmsg->cmsg_len = CMSG_LEN(sizeof(fd_tx));
> > +	cmsg->cmsg_level = SOL_SOCKET;
> > +	cmsg->cmsg_type = SCM_RIGHTS;
> > +	memcpy(CMSG_DATA(cmsg), &fd_tx, sizeof(fd_tx));
> > +
> > +	if (sendmsg(usock, &msg, 0) < 0)
> > +		return -1;
> > +	return 0;
> > +}
> > diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c
> > index 308f6f36e8c0..93ed80a25a74 100644
> > --- a/tools/testing/selftests/landlock/fs_test.c
> > +++ b/tools/testing/selftests/landlock/fs_test.c
> > @@ -3541,6 +3541,68 @@ TEST_F_FORK(ftruncate, open_and_ftruncate)
> >   	}
> >   }
> > +TEST_F_FORK(ftruncate, open_and_ftruncate_in_different_processes)
> > +{
> > +	int child, fd, status;
> > +	int socket_fds[2];
> > +
> > +	ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0,
> > +				socket_fds));
> > +
> > +	child = fork();
> > +	ASSERT_LE(0, child);
> > +	if (child == 0) {
> > +		/*
> > +		 * Enable Landlock in the child process, open a file descriptor
> 
> "Enables"…

Done.

> > +		 * where truncation is forbidden and send it to the
> > +		 * non-landlocked parent process.
> > +		 */
> > +		const char *const path = file1_s1d1;
> > +		const struct rule rules[] = {
> > +			{
> > +				.path = path,
> > +				.access = variant->permitted,
> > +			},
> > +			{},
> > +		};
> > +		int fd, ruleset_fd;
> > +
> > +		/* Enable Landlock. */
> 
> This comment is not necessary.

Done.

> > +		ruleset_fd = create_ruleset(_metadata, variant->handled, rules);
> > +		ASSERT_LE(0, ruleset_fd);
> > +		enforce_ruleset(_metadata, ruleset_fd);
> > +		ASSERT_EQ(0, close(ruleset_fd));
> > +
> > +		fd = open(path, O_WRONLY);
> > +		ASSERT_EQ(variant->expected_open_result, (fd < 0 ? errno : 0));
> > +
> > +		if (fd >= 0) {
> > +			ASSERT_EQ(0, send_fd(socket_fds[0], fd));
> > +			ASSERT_EQ(0, close(fd));
> > +		}
> > +
> > +		ASSERT_EQ(0, close(socket_fds[0]));
> > +
> > +		_exit(_metadata->passed ? EXIT_SUCCESS : EXIT_FAILURE);
> 
> You might want to add a "return" here to help the compiler (and the reader).

Done.

> > +	}
> > +
> > +	if (variant->expected_open_result == 0) {
> > +		fd = recv_fd(socket_fds[1]);
> > +		ASSERT_LE(0, fd);
> > +
> > +		EXPECT_EQ(variant->expected_ftruncate_result,
> > +			  test_ftruncate(fd));
> > +		ASSERT_EQ(0, close(fd));
> > +	}
> > +
> > +	ASSERT_EQ(child, waitpid(child, &status, 0));
> > +	ASSERT_EQ(1, WIFEXITED(status));
> > +	ASSERT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
> > +
> > +	ASSERT_EQ(0, close(socket_fds[0]));
> > +	ASSERT_EQ(0, close(socket_fds[1]));
> > +}
> > +
> >   /* clang-format off */
> >   FIXTURE(layout1_bind) {};
> >   /* clang-format on */

-- 

  reply	other threads:[~2022-10-08  8:25 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-01 15:48 [PATCH v8 0/9] landlock: truncate support Günther Noack
2022-10-01 15:49 ` [PATCH v8 1/9] security: Create file_truncate hook from path_truncate hook Günther Noack
2022-10-05 18:53   ` Mickaël Salaün
2022-10-08  7:45     ` Günther Noack
2022-10-06  1:10   ` Paul Moore
2022-10-01 15:49 ` [PATCH v8 2/9] selftests/landlock: Locally define __maybe_unused Günther Noack
2022-10-05 18:53   ` Mickaël Salaün
2022-10-08  7:47     ` Günther Noack
2022-10-01 15:49 ` [PATCH v8 3/9] landlock: Refactor check_access_path_dual() into is_access_to_paths_allowed() Günther Noack
2022-10-05 18:54   ` Mickaël Salaün
2022-10-08  7:54     ` Günther Noack
2022-10-01 15:49 ` [PATCH v8 4/9] landlock: Support file truncation Günther Noack
2022-10-04 19:56   ` Nathan Chancellor
2022-10-05 18:52     ` Mickaël Salaün
2022-10-06 20:19       ` Günther Noack
2022-10-05 18:55   ` Mickaël Salaün
2022-10-08  8:08     ` Günther Noack
2022-10-01 15:49 ` [PATCH v8 5/9] selftests/landlock: Selftests for file truncation support Günther Noack
2022-10-01 15:49 ` [PATCH v8 6/9] selftests/landlock: Test open() and ftruncate() in multiple scenarios Günther Noack
2022-10-05 18:56   ` Mickaël Salaün
2022-10-01 15:49 ` [PATCH v8 7/9] selftests/landlock: Test FD passing from a Landlock-restricted to an unrestricted process Günther Noack
2022-10-05 18:57   ` Mickaël Salaün
2022-10-08  8:25     ` Günther Noack [this message]
2022-10-01 15:49 ` [PATCH v8 8/9] samples/landlock: Extend sample tool to support LANDLOCK_ACCESS_FS_TRUNCATE Günther Noack
2022-10-05 18:57   ` Mickaël Salaün
2022-10-08  8:47     ` Günther Noack
2022-10-01 15:49 ` [PATCH v8 9/9] landlock: Document Landlock's file truncation support Günther Noack
2022-10-05 18:57   ` Mickaël Salaün
2022-10-08  8:49     ` Günther Noack
2022-10-05 19:18 ` [PATCH v8 0/9] landlock: truncate support Mickaël Salaün
2022-10-08 10:20   ` Günther Noack

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=Y0E0AuxsnwOYV8TL@nuc \
    --to=gnoack3000@gmail.com \
    --cc=jmorris@namei.org \
    --cc=konstantin.meskhidze@huawei.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=mic@digikod.net \
    --cc=paul@paul-moore.com \
    --cc=serge@hallyn.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.