lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250131163447.1140564-3-mic@digikod.net>
Date: Fri, 31 Jan 2025 17:34:46 +0100
From: Mickaël Salaün <mic@...ikod.net>
To: Christian Brauner <brauner@...nel.org>,
	Günther Noack <gnoack@...gle.com>
Cc: Mickaël Salaün <mic@...ikod.net>,
	Charles Zaffery <czaffery@...lox.com>,
	Daniel Burgener <dburgener@...ux.microsoft.com>,
	Francis Laniel <flaniel@...ux.microsoft.com>,
	James Morris <jmorris@...ei.org>,
	Jann Horn <jannh@...gle.com>,
	Jeff Xu <jeffxu@...gle.com>,
	Kees Cook <kees@...nel.org>,
	Luca Boccassi <luca.boccassi@...il.com>,
	Mikhail Ivanov <ivanov.mikhail1@...wei-partners.com>,
	Praveen K Paladugu <prapal@...ux.microsoft.com>,
	Robert Salvet <robert.salvet@...lox.com>,
	Shervin Oloumi <enlightened@...gle.com>,
	Tyler Hicks <code@...icks.com>,
	linux-kernel@...r.kernel.org,
	linux-security-module@...r.kernel.org
Subject: [RFC PATCH v1 2/3] pidfd: Extend PIDFD_GET_INFO with PIDFD_INFO_LANDLOCK_*_DOMAIN

Because Landlock enables users to create nested sandboxes (i.e.
domains), we might need to identify the domain with all restrictions
(latest), or the domain we created (i.e. closest domain).  Indeed,
because any process can create its own domain, the latest domain may not
be known by the requester.

The PIDFD_INFO_LANDLOCK_LAST_DOMAIN flag enables user space to get the
latest (i.e. most nested) Landlock domain ID related to a sandboxed
task, if any.  The domain ID is set in the pidfd_info's
landlock_last_domain field according to the related mask.

The PIDFD_INFO_LANDLOCK_FIRST_DOMAIN flag enables user space to get the
closest (i.e. first hierarchy relative to the pidfd's credentials)
Landlock domain ID related to a sandboxed task, if any.  The domain ID
is set in the pidfd_info's landlock_first_domain field according to the
related mask.

It is only allowed to get information about a Landlock domain if the
task's domain that created the pidfd is a parent of the PID's domain.
Following the object-capability model, the pidfd's credentials are used
instead of the caller's credentials.  This makes this command
idenmpotent wrt the referenced process's state.

If Landlock is not supported or if access to this information is denied,
then the IOCTL does not set the PIDFD_INFO_LANDLOCK_*_DOMAIN flag in the
returned mask.

If PIDFD_INFO_LANDLOCK_LAST_DOMAIN or PIDFD_INFO_LANDLOCK_FIRST_DOMAIN
is specified but the provided struct pidfd_info is not large enough to
contain the related field, then -EINVAL is returned.

Cc: Christian Brauner <brauner@...nel.org>
Cc: Günther Noack <gnoack@...gle.com>
Cc: Luca Boccassi <luca.boccassi@...il.com>
Cc: Praveen K Paladugu <prapal@...ux.microsoft.com>
Closes: https://github.com/landlock-lsm/linux/issues/26
Signed-off-by: Mickaël Salaün <mic@...ikod.net>
Link: https://lore.kernel.org/r/20250131163447.1140564-3-mic@digikod.net
---
 fs/pidfs.c                 | 24 ++++++++++++++++++++++--
 include/uapi/linux/pidfd.h |  4 ++++
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/fs/pidfs.c b/fs/pidfs.c
index 049352f973de..4ff5b6c776ce 100644
--- a/fs/pidfs.c
+++ b/fs/pidfs.c
@@ -20,6 +20,7 @@
 #include <linux/time_namespace.h>
 #include <linux/utsname.h>
 #include <net/net_namespace.h>
+#include <linux/landlock.h>
 
 #include "internal.h"
 #include "mount.h"
@@ -207,7 +208,8 @@ static __poll_t pidfd_poll(struct file *file, struct poll_table_struct *pts)
 	return poll_flags;
 }
 
-static long pidfd_info(struct task_struct *task, unsigned int cmd, unsigned long arg)
+static long pidfd_info(const struct cred *cred, struct task_struct *task,
+		       unsigned int cmd, unsigned long arg)
 {
 	struct pidfd_info __user *uinfo = (struct pidfd_info __user *)arg;
 	size_t usize = _IOC_SIZE(cmd);
@@ -227,6 +229,14 @@ static long pidfd_info(struct task_struct *task, unsigned int cmd, unsigned long
 	if (copy_from_user(&mask, &uinfo->mask, sizeof(mask)))
 		return -EFAULT;
 
+	if ((mask & PIDFD_INFO_LANDLOCK_LAST_DOMAIN) &&
+	    usize < offsetofend(typeof(*uinfo), landlock_last_domain))
+		return -EINVAL;
+
+	if ((mask & PIDFD_INFO_LANDLOCK_FIRST_DOMAIN) &&
+	    usize < offsetofend(typeof(*uinfo), landlock_first_domain))
+		return -EINVAL;
+
 	c = get_task_cred(task);
 	if (!c)
 		return -ESRCH;
@@ -253,6 +263,16 @@ static long pidfd_info(struct task_struct *task, unsigned int cmd, unsigned long
 	rcu_read_unlock();
 #endif
 
+	if ((mask & PIDFD_INFO_LANDLOCK_LAST_DOMAIN) &&
+	    !landlock_read_domain_id(cred, task, true,
+				     &kinfo.landlock_last_domain))
+		kinfo.mask |= PIDFD_INFO_LANDLOCK_LAST_DOMAIN;
+
+	if ((mask & PIDFD_INFO_LANDLOCK_FIRST_DOMAIN) &&
+	    !landlock_read_domain_id(cred, task, false,
+				     &kinfo.landlock_first_domain))
+		kinfo.mask |= PIDFD_INFO_LANDLOCK_FIRST_DOMAIN;
+
 	/*
 	 * Copy pid/tgid last, to reduce the chances the information might be
 	 * stale. Note that it is not possible to ensure it will be valid as the
@@ -328,7 +348,7 @@ static long pidfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 	/* Extensible IOCTL that does not open namespace FDs, take a shortcut */
 	if (_IOC_NR(cmd) == _IOC_NR(PIDFD_GET_INFO))
-		return pidfd_info(task, cmd, arg);
+		return pidfd_info(file->f_cred, task, cmd, arg);
 
 	if (arg)
 		return -EINVAL;
diff --git a/include/uapi/linux/pidfd.h b/include/uapi/linux/pidfd.h
index 4540f6301b8c..267991bd266c 100644
--- a/include/uapi/linux/pidfd.h
+++ b/include/uapi/linux/pidfd.h
@@ -20,6 +20,8 @@
 #define PIDFD_INFO_PID			(1UL << 0) /* Always returned, even if not requested */
 #define PIDFD_INFO_CREDS		(1UL << 1) /* Always returned, even if not requested */
 #define PIDFD_INFO_CGROUPID		(1UL << 2) /* Always returned if available, even if not requested */
+#define PIDFD_INFO_LANDLOCK_LAST_DOMAIN	(1UL << 3) /* Only returned if requested */
+#define PIDFD_INFO_LANDLOCK_FIRST_DOMAIN	(1UL << 4) /* Only returned if requested */
 
 #define PIDFD_INFO_SIZE_VER0		64 /* sizeof first published struct */
 
@@ -63,6 +65,8 @@ struct pidfd_info {
 	__u32 fsuid;
 	__u32 fsgid;
 	__u32 spare0[1];
+	__u64 landlock_last_domain;
+	__u64 landlock_first_domain;
 };
 
 #define PIDFS_IOCTL_MAGIC 0xFF
-- 
2.48.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ