diff mbox series

[v5,17/24] landlock: Add LANDLOCK_RESTRICT_SELF_QUIET_SUBDOMAINS

Message ID 20250131163059.1139617-18-mic@digikod.net (mailing list archive)
State New
Headers show
Series Landlock audit support | expand

Commit Message

Mickaël Salaün Jan. 31, 2025, 4:30 p.m. UTC
Add LANDLOCK_RESTRICT_SELF_QUIET_SUBDOMAINS for the case of sandboxer
tools, init systems, or runtime containers launching programs sandboxing
themselves in an inconsistent way.  Setting this flag should only
depends on runtime configuration (i.e. not hardcoded).

We don't create a new ruleset's option because this should not be part
of the security policy: only the task that enforces the policy (not the
one that create it) knows if itself or its children may request denied
actions.

Cc: Günther Noack <gnoack@google.com>
Cc: Paul Moore <paul@paul-moore.com>
Signed-off-by: Mickaël Salaün <mic@digikod.net>
Link: https://lore.kernel.org/r/20250131163059.1139617-18-mic@digikod.net
---

Using "mute" instead of "quiet" might be more appropriate.

Changes since v4:
- New patch.
---
 include/uapi/linux/landlock.h | 11 +++++++++++
 security/landlock/domain.c    |  1 +
 security/landlock/domain.h    |  5 +++++
 security/landlock/limits.h    |  2 +-
 security/landlock/syscalls.c  | 14 +++++++++++---
 5 files changed, 29 insertions(+), 4 deletions(-)

Comments

kernel test robot Jan. 31, 2025, 8:28 p.m. UTC | #1
Hi Mickaël,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 69e858e0b8b2ea07759e995aa383e8780d9d140c]

url:    https://github.com/intel-lab-lkp/linux/commits/Micka-l-Sala-n/lsm-Add-audit_log_lsm_data-helper/20250201-004434
base:   69e858e0b8b2ea07759e995aa383e8780d9d140c
patch link:    https://lore.kernel.org/r/20250131163059.1139617-18-mic%40digikod.net
patch subject: [PATCH v5 17/24] landlock: Add LANDLOCK_RESTRICT_SELF_QUIET_SUBDOMAINS
config: x86_64-buildonly-randconfig-002-20250201 (https://download.01.org/0day-ci/archive/20250201/202502010411.lOcXpnOG-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250201/202502010411.lOcXpnOG-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202502010411.lOcXpnOG-lkp@intel.com/

All warnings (new ones prefixed by >>):

   security/landlock/syscalls.c: In function '__do_sys_landlock_restrict_self':
>> security/landlock/syscalls.c:469:24: warning: variable 'is_quiet_subdomains' set but not used [-Wunused-but-set-variable]
     469 |         bool is_quiet, is_quiet_subdomains,
         |                        ^~~~~~~~~~~~~~~~~~~
   security/landlock/syscalls.c:469:14: warning: variable 'is_quiet' set but not used [-Wunused-but-set-variable]
     469 |         bool is_quiet, is_quiet_subdomains,
         |              ^~~~~~~~


vim +/is_quiet_subdomains +469 security/landlock/syscalls.c

   435	
   436	/**
   437	 * sys_landlock_restrict_self - Enforce a ruleset on the calling thread
   438	 *
   439	 * @ruleset_fd: File descriptor tied to the ruleset to merge with the target.
   440	 * @flags: Supported values:
   441	 *
   442	 * - %LANDLOCK_RESTRICT_SELF_QUIET
   443	 * - %LANDLOCK_RESTRICT_SELF_QUIET_SUBDOMAINS
   444	 *
   445	 * This system call enables to enforce a Landlock ruleset on the current
   446	 * thread.  Enforcing a ruleset requires that the task has %CAP_SYS_ADMIN in its
   447	 * namespace or is running with no_new_privs.  This avoids scenarios where
   448	 * unprivileged tasks can affect the behavior of privileged children.
   449	 *
   450	 * Possible returned errors are:
   451	 *
   452	 * - %EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;
   453	 * - %EINVAL: @flags contains an unknown bit.
   454	 * - %EBADF: @ruleset_fd is not a file descriptor for the current thread;
   455	 * - %EBADFD: @ruleset_fd is not a ruleset file descriptor;
   456	 * - %EPERM: @ruleset_fd has no read access to the underlying ruleset, or the
   457	 *   current thread is not running with no_new_privs, or it doesn't have
   458	 *   %CAP_SYS_ADMIN in its namespace.
   459	 * - %E2BIG: The maximum number of stacked rulesets is reached for the current
   460	 *   thread.
   461	 */
   462	SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
   463			flags)
   464	{
   465		struct landlock_ruleset *new_dom,
   466			*ruleset __free(landlock_put_ruleset) = NULL;
   467		struct cred *new_cred;
   468		struct landlock_cred_security *new_llcred;
 > 469		bool is_quiet, is_quiet_subdomains,
   470			__maybe_unused inherits_quiet_subdomains;
   471	
   472		if (!is_initialized())
   473			return -EOPNOTSUPP;
   474	
   475		/*
   476		 * Similar checks as for seccomp(2), except that an -EPERM may be
   477		 * returned.
   478		 */
   479		if (!task_no_new_privs(current) &&
   480		    !ns_capable_noaudit(current_user_ns(), CAP_SYS_ADMIN))
   481			return -EPERM;
   482	
   483		if ((flags | LANDLOCK_MASK_RESTRICT_SELF) !=
   484		    LANDLOCK_MASK_RESTRICT_SELF)
   485			return -EINVAL;
   486	
   487		is_quiet = !!(flags & LANDLOCK_RESTRICT_SELF_QUIET);
   488		is_quiet_subdomains =
   489			!!(flags & LANDLOCK_RESTRICT_SELF_QUIET_SUBDOMAINS);
   490	
   491		/* Gets and checks the ruleset. */
   492		ruleset = get_ruleset_from_fd(ruleset_fd, FMODE_CAN_READ);
   493		if (IS_ERR(ruleset))
   494			return PTR_ERR(ruleset);
   495	
   496		/* Prepares new credentials. */
   497		new_cred = prepare_creds();
   498		if (!new_cred)
   499			return -ENOMEM;
   500	
   501		new_llcred = landlock_cred(new_cred);
   502	
   503		/*
   504		 * There is no possible race condition while copying and manipulating
   505		 * the current credentials because they are dedicated per thread.
   506		 */
   507		new_dom = landlock_merge_ruleset(new_llcred->domain, ruleset);
   508		if (IS_ERR(new_dom)) {
   509			abort_creds(new_cred);
   510			return PTR_ERR(new_dom);
   511		}
   512
diff mbox series

Patch

diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h
index b7f78abd6ddd..d810fd9e17c6 100644
--- a/include/uapi/linux/landlock.h
+++ b/include/uapi/linux/landlock.h
@@ -71,9 +71,20 @@  struct landlock_ruleset_attr {
  *   service manager).  Because programs sandboxing themselves should fix any
  *   denied access, they should not set this flag to be aware of potential
  *   issues reported by system's logs (i.e. audit).
+ * - %LANDLOCK_RESTRICT_SELF_QUIET_SUBDOMAINS: Do not create any log related
+ *   to the enforced restrictions coming from descendant domains.  This should
+ *   only be set according to a runtime configuration (i.e. not hardcoded) by
+ *   programs launching other unknown or untrusted programs that may create
+ *   their own Landlock domains and spam logs.  The main use case is for
+ *   container runtimes to enable users to mute buggy sandboxed programs for a
+ *   specific container image.  Other use cases include sandboxer tools and
+ *   init systems.  Unlike %LANDLOCK_RESTRICT_SELF_QUIET,
+ *   %LANDLOCK_RESTRICT_SELF_QUIET_SUBDOMAINS does not impact the requested
+ *   restriction but only the potential descendant domains.
  */
 /* clang-format off */
 #define LANDLOCK_RESTRICT_SELF_QUIET			(1U << 0)
+#define LANDLOCK_RESTRICT_SELF_QUIET_SUBDOMAINS		(1U << 1)
 /* clang-format on */
 
 /**
diff --git a/security/landlock/domain.c b/security/landlock/domain.c
index 6704e9283206..eff7c774bf06 100644
--- a/security/landlock/domain.c
+++ b/security/landlock/domain.c
@@ -127,6 +127,7 @@  int landlock_init_hierarchy_log(struct landlock_hierarchy *const hierarchy)
 	hierarchy->details = details;
 	hierarchy->id = landlock_get_id_range(1);
 	hierarchy->log_status = LANDLOCK_LOG_PENDING;
+	hierarchy->quiet_subdomains = false;
 	atomic64_set(&hierarchy->num_denials, 0);
 	return 0;
 }
diff --git a/security/landlock/domain.h b/security/landlock/domain.h
index 25be0a18da1f..8979cf00f8be 100644
--- a/security/landlock/domain.h
+++ b/security/landlock/domain.h
@@ -104,6 +104,11 @@  struct landlock_hierarchy {
 	 * @details: Information about the related domain.
 	 */
 	const struct landlock_details *details;
+	/**
+	 * @quiet_subdomains: Set if the domain descendants's log_status
+	 * should be set to %LANDLOCK_LOG_DISABLED.
+	 */
+	u32 quiet_subdomains : 1;
 #endif /* CONFIG_AUDIT */
 };
 
diff --git a/security/landlock/limits.h b/security/landlock/limits.h
index 2a5e9f3ee750..48aa75c98665 100644
--- a/security/landlock/limits.h
+++ b/security/landlock/limits.h
@@ -30,7 +30,7 @@ 
 #define LANDLOCK_MASK_SCOPE		((LANDLOCK_LAST_SCOPE << 1) - 1)
 #define LANDLOCK_NUM_SCOPE		__const_hweight64(LANDLOCK_MASK_SCOPE)
 
-#define LANDLOCK_LAST_RESTRICT_SELF	LANDLOCK_RESTRICT_SELF_QUIET
+#define LANDLOCK_LAST_RESTRICT_SELF	LANDLOCK_RESTRICT_SELF_QUIET_SUBDOMAINS
 #define LANDLOCK_MASK_RESTRICT_SELF	((LANDLOCK_LAST_RESTRICT_SELF << 1) - 1)
 
 /* clang-format on */
diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c
index 5c6abcd6d604..f44f4f884499 100644
--- a/security/landlock/syscalls.c
+++ b/security/landlock/syscalls.c
@@ -440,6 +440,7 @@  SYSCALL_DEFINE4(landlock_add_rule, const int, ruleset_fd,
  * @flags: Supported values:
  *
  * - %LANDLOCK_RESTRICT_SELF_QUIET
+ * - %LANDLOCK_RESTRICT_SELF_QUIET_SUBDOMAINS
  *
  * This system call enables to enforce a Landlock ruleset on the current
  * thread.  Enforcing a ruleset requires that the task has %CAP_SYS_ADMIN in its
@@ -465,7 +466,8 @@  SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
 		*ruleset __free(landlock_put_ruleset) = NULL;
 	struct cred *new_cred;
 	struct landlock_cred_security *new_llcred;
-	bool is_quiet;
+	bool is_quiet, is_quiet_subdomains,
+		__maybe_unused inherits_quiet_subdomains;
 
 	if (!is_initialized())
 		return -EOPNOTSUPP;
@@ -483,6 +485,8 @@  SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
 		return -EINVAL;
 
 	is_quiet = !!(flags & LANDLOCK_RESTRICT_SELF_QUIET);
+	is_quiet_subdomains =
+		!!(flags & LANDLOCK_RESTRICT_SELF_QUIET_SUBDOMAINS);
 
 	/* Gets and checks the ruleset. */
 	ruleset = get_ruleset_from_fd(ruleset_fd, FMODE_CAN_READ);
@@ -506,11 +510,15 @@  SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
 		return PTR_ERR(new_dom);
 	}
 
-	if (is_quiet) {
 #ifdef CONFIG_AUDIT
+	inherits_quiet_subdomains =
+		new_llcred->domain &&
+		new_llcred->domain->hierarchy->quiet_subdomains;
+	new_dom->hierarchy->quiet_subdomains = is_quiet_subdomains ||
+					       inherits_quiet_subdomains;
+	if (is_quiet || inherits_quiet_subdomains)
 		new_dom->hierarchy->log_status = LANDLOCK_LOG_DISABLED;
 #endif /* CONFIG_AUDIT */
-	}
 
 	/* Replaces the old (prepared) domain. */
 	landlock_put_ruleset(new_llcred->domain);