* Re: [RFC PATCH 0/1] lsm: Add hook unix_path_connect
From: Kuniyuki Iwashima @ 2026-01-05 7:46 UTC (permalink / raw)
To: Justin Suess
Cc: Paul Moore, James Morris, Serge E . Hallyn, Simon Horman,
Mickaël Salaün, Günther Noack,
linux-security-module, Tingmao Wang, netdev
In-Reply-To: <20251231213314.2979118-1-utilityemal77@gmail.com>
On Wed, Dec 31, 2025 at 1:33 PM Justin Suess <utilityemal77@gmail.com> wrote:
>
> Hi,
>
> This patch introduces a new LSM hook unix_path_connect.
>
> The idea for this patch and the hook came from Günther Noack, who
> is cc'd. Much credit to him for the idea and discussion.
>
> This patch is based on the lsm next branch.
>
> Motivation
> ---
>
> For AF_UNIX sockets bound to a filesystem path (aka named sockets), one
> identifying object from a policy perspective is the path passed to
> connect(2). However, this operation currently restricts LSMs that rely
> on VFS-based mediation, because the pathname resolved during connect()
> is not preserved in a form visible to existing hooks before connection
> establishment.
Why can't LSM use unix_sk(other)->path in security_unix_stream_connect()
and security_unix_may_send() ?
> As a result, LSMs such as Landlock cannot currently
> restrict connections to named UNIX domain sockets by their VFS path.
>
> This gap has been discussed previously (e.g. in the context of Landlock's
> path-based access controls). [1] [2]
>
> I've cc'd the netdev folks as well on this, as the placement of this hook is
> important and in a core unix socket function.
>
> Design Choices
> ---
>
> The hook is called in net/unix/af_unix.c in the function unix_find_bsd().
>
> The hook takes a single parameter, a const struct path* to the named unix
> socket to which the connection is being established.
>
> The hook takes place after normal permissions checks, and after the
> inode is determined to be a socket. It however, takes place before
> the socket is actually connected to.
>
> If the hook returns non-zero it will do a put on the path, and return.
>
> References
> ---
>
> [1]: https://github.com/landlock-lsm/linux/issues/36#issue-2354007438
> [2]: https://lore.kernel.org/linux-security-module/cover.1767115163.git.m@maowtm.org/
>
> Kind Regards,
> Justin Suess
>
> Justin Suess (1):
> lsm: Add hook unix_path_connect
>
> include/linux/lsm_hook_defs.h | 1 +
> include/linux/security.h | 6 ++++++
> net/unix/af_unix.c | 8 ++++++++
> security/security.c | 16 ++++++++++++++++
> 4 files changed, 31 insertions(+)
>
>
> base-commit: 1c0860d4415d52f3ad1c8e0a15c1272869278a06
> --
> 2.51.0
>
^ permalink raw reply
* [PATCH v2 3/3] landlock: Document audit blocker field format
From: Samasth Norway Ananda @ 2026-01-03 0:27 UTC (permalink / raw)
To: mic, gnoack; +Cc: linux-security-module, linux-kernel
In-Reply-To: <20260103002722.1465371-1-samasth.norway.ananda@oracle.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 3176 bytes --]
Add comprehensive documentation for the ``blockers`` field format
in AUDIT_LANDLOCK_ACCESS records, including all possible prefixes
(fs., net., scope.) and their meanings.
Also fix a typo and update the documentation date to reflect these
changes.
Signed-off-by: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
---
Documentation/admin-guide/LSM/landlock.rst | 35 ++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/Documentation/admin-guide/LSM/landlock.rst b/Documentation/admin-guide/LSM/landlock.rst
index 9e61607def08..9923874e2156 100644
--- a/Documentation/admin-guide/LSM/landlock.rst
+++ b/Documentation/admin-guide/LSM/landlock.rst
@@ -6,7 +6,7 @@ Landlock: system-wide management
================================
:Author: Mickaël Salaün
-:Date: March 2025
+:Date: January 2026
Landlock can leverage the audit framework to log events.
@@ -38,6 +38,37 @@ AUDIT_LANDLOCK_ACCESS
domain=195ba459b blockers=fs.refer path="/usr/bin" dev="vda2" ino=351
domain=195ba459b blockers=fs.make_reg,fs.refer path="/usr/local" dev="vda2" ino=365
+
+ The ``blockers`` field uses dot-separated prefixes to indicate the type of
+ restriction that caused the denial:
+
+ **fs.*** - Filesystem access rights (ABI 1+):
+ - fs.execute, fs.write_file, fs.read_file, fs.read_dir
+ - fs.remove_dir, fs.remove_file
+ - fs.make_char, fs.make_dir, fs.make_reg, fs.make_sock
+ - fs.make_fifo, fs.make_block, fs.make_sym
+ - fs.refer (ABI 2+)
+ - fs.truncate (ABI 3+)
+ - fs.ioctl_dev (ABI 5+)
+
+ **net.*** - Network access rights (ABI 4+):
+ - net.bind_tcp - TCP port binding was denied
+ - net.connect_tcp - TCP connection was denied
+
+ **scope.*** - IPC scoping restrictions (ABI 6+):
+ - scope.abstract_unix_socket - Abstract UNIX socket connection denied
+ - scope.signal - Signal sending denied
+
+ Multiple blockers can appear in a single event (comma-separated) when
+ multiple access rights are missing. For example, creating a regular file
+ in a directory that lacks both ``make_reg`` and ``refer`` rights would show
+ ``blockers=fs.make_reg,fs.refer``.
+
+ The object identification fields (path, dev, ino for filesystem; opid,
+ ocomm for signals) depend on the type of access being blocked and provide
+ context about what resource was involved in the denial.
+
+
AUDIT_LANDLOCK_DOMAIN
This record type describes the status of a Landlock domain. The ``status``
field can be either ``allocated`` or ``deallocated``.
@@ -86,7 +117,7 @@ This command generates two events, each identified with a unique serial
number following a timestamp (``msg=audit(1729738800.268:30)``). The first
event (serial ``30``) contains 4 records. The first record
(``type=LANDLOCK_ACCESS``) shows an access denied by the domain `1a6fdc66f`.
-The cause of this denial is signal scopping restriction
+The cause of this denial is signal scoping restriction
(``blockers=scope.signal``). The process that would have receive this signal
is the init process (``opid=1 ocomm="systemd"``).
--
2.50.1
^ permalink raw reply related
* [PATCH v2 0/3] landlock: Documentation improvements
From: Samasth Norway Ananda @ 2026-01-03 0:27 UTC (permalink / raw)
To: mic, gnoack; +Cc: linux-security-module, linux-kernel
This series improves Landlock documentation to address gaps in ABI
compatibility handling, errata documentation, and audit field formats.
Changes since v1:
Patch 1: Add backwards compatibility section for restrict flags, fix
/usr rule description.
Patch 2: Enhance existing DOC sections with Impact descriptions, add
errata usage documentation.
Patch 3: Document audit blocker field format.
Samasth Norway Ananda (3):
landlock: Add missing ABI 7 case in documentation example
landlock: Add comprehensive errata documentation
landlock: Document audit blocker field format
Documentation/admin-guide/LSM/landlock.rst | 35 +++++++-
Documentation/userspace-api/landlock.rst | 95 ++++++++++++++++++++--
security/landlock/errata/abi-1.h | 8 ++
security/landlock/errata/abi-4.h | 7 ++
security/landlock/errata/abi-6.h | 10 +++
security/landlock/syscalls.c | 4 +-
6 files changed, 151 insertions(+), 8 deletions(-)
--
2.50.1
^ permalink raw reply
* [PATCH v2 1/3] landlock: Add missing ABI 7 case in documentation example
From: Samasth Norway Ananda @ 2026-01-03 0:27 UTC (permalink / raw)
To: mic, gnoack; +Cc: linux-security-module, linux-kernel
In-Reply-To: <20260103002722.1465371-1-samasth.norway.ananda@oracle.com>
Add the missing case 6 and case 7 handling in the ABI version
compatibility example to properly handle ABI < 7 kernels.
Add an optional backwards compatibility section for restrict flags
between the case analysis and landlock_restrict_self() call. The main
tutorial example remains unchanged with
landlock_restrict_self(ruleset_fd, 0) to keep it simple for users who
don't need logging flags.
Also fix misleading description of the /usr rule which incorrectly
stated it "only allow[s] reading" when the code actually allows both
reading and executing (LANDLOCK_ACCESS_FS_EXECUTE is included in
allowed_access).
Signed-off-by: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
---
Documentation/userspace-api/landlock.rst | 35 +++++++++++++++++++++---
1 file changed, 31 insertions(+), 4 deletions(-)
diff --git a/Documentation/userspace-api/landlock.rst b/Documentation/userspace-api/landlock.rst
index 1d0c2c15c22e..650c7b368561 100644
--- a/Documentation/userspace-api/landlock.rst
+++ b/Documentation/userspace-api/landlock.rst
@@ -127,6 +127,12 @@ version, and only use the available subset of access rights:
/* Removes LANDLOCK_SCOPE_* for ABI < 6 */
ruleset_attr.scoped &= ~(LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET |
LANDLOCK_SCOPE_SIGNAL);
+ __attribute__((fallthrough));
+ case 6:
+ /* Removes logging flags for ABI < 7 */
+ __attribute__((fallthrough));
+ case 7:
+ break;
}
This enables the creation of an inclusive ruleset that will contain our rules.
@@ -142,8 +148,9 @@ This enables the creation of an inclusive ruleset that will contain our rules.
}
We can now add a new rule to this ruleset thanks to the returned file
-descriptor referring to this ruleset. The rule will only allow reading the
-file hierarchy ``/usr``. Without another rule, write actions would then be
+descriptor referring to this ruleset. The rule will allow reading and
+executing files in the ``/usr`` hierarchy. Without another rule, write actions
+and other operations (make_dir, remove_file, etc.) would then be
denied by the ruleset. To add ``/usr`` to the ruleset, we open it with the
``O_PATH`` flag and fill the &struct landlock_path_beneath_attr with this file
descriptor.
@@ -191,10 +198,30 @@ number for a specific action: HTTPS connections.
err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
&net_port, 0);
+Backwards compatibility for restrict flags
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When passing a non-zero ``flags`` argument to ``landlock_restrict_self()``, the
+following backwards compatibility check needs to be taken into account:
+
+.. code-block:: c
+
+ /*
+ * Desired restriction flags, see ABI version section above.
+ * This value is only an example and differs by use case.
+ */
+ int restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON;
+ if (abi < 7) {
+ /* Clear logging flags unsupported in ABI < 7 */
+ restrict_flags &= ~(LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF |
+ LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON |
+ LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF);
+ }
+
The next step is to restrict the current thread from gaining more privileges
(e.g. through a SUID binary). We now have a ruleset with the first rule
-allowing read access to ``/usr`` while denying all other handled accesses for
-the filesystem, and a second rule allowing HTTPS connections.
+allowing read and execute access to ``/usr`` while denying all other handled
+accesses for the filesystem, and a second rule allowing HTTPS connections.
.. code-block:: c
--
2.50.1
^ permalink raw reply related
* [PATCH v2 2/3] landlock: Add comprehensive errata documentation
From: Samasth Norway Ananda @ 2026-01-03 0:27 UTC (permalink / raw)
To: mic, gnoack; +Cc: linux-security-module, linux-kernel
In-Reply-To: <20260103002722.1465371-1-samasth.norway.ananda@oracle.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 7554 bytes --]
Add comprehensive documentation for the Landlock errata mechanism,
including how to query errata using LANDLOCK_CREATE_RULESET_ERRATA
and links to enhanced detailed descriptions in the kernel source.
Also enhance existing DOC sections in security/landlock/errata/abi-*.h
files with Impact sections, and update the code comment in syscalls.c
to remind developers to update errata documentation when applicable.
This addresses the gap where the kernel implements errata tracking
but provides no user-facing documentation on how to use it, while
improving the existing technical documentation in-place rather than
duplicating it.
Signed-off-by: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
---
Documentation/userspace-api/landlock.rst | 60 +++++++++++++++++++++++-
security/landlock/errata/abi-1.h | 8 ++++
security/landlock/errata/abi-4.h | 7 +++
security/landlock/errata/abi-6.h | 10 ++++
security/landlock/syscalls.c | 4 +-
5 files changed, 87 insertions(+), 2 deletions(-)
diff --git a/Documentation/userspace-api/landlock.rst b/Documentation/userspace-api/landlock.rst
index 650c7b368561..930723fd7c1a 100644
--- a/Documentation/userspace-api/landlock.rst
+++ b/Documentation/userspace-api/landlock.rst
@@ -8,7 +8,7 @@ Landlock: unprivileged access control
=====================================
:Author: Mickaël Salaün
-:Date: March 2025
+:Date: January 2026
The goal of Landlock is to enable restriction of ambient rights (e.g. global
filesystem or network access) for a set of processes. Because Landlock
@@ -458,6 +458,64 @@ system call:
printf("Landlock supports LANDLOCK_ACCESS_FS_REFER.\n");
}
+Landlock Errata
+---------------
+
+In addition to ABI versions, Landlock provides an errata mechanism to track
+fixes for issues that may affect backwards compatibility or require userspace
+awareness. The errata bitmask can be queried using:
+
+.. code-block:: c
+
+ int errata;
+
+ errata = landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_ERRATA);
+ if (errata < 0) {
+ /* Landlock not available or disabled */
+ return 0;
+ }
+
+The returned value is a bitmask where each bit represents a specific erratum.
+If bit N is set (``errata & (1 << (N - 1))``), then erratum N has been fixed
+in the running kernel.
+
+.. warning::
+
+ **Most applications should NOT check errata.** In 99.9% of cases, checking
+ errata is unnecessary, increases code complexity, and can potentially
+ decrease protection if misused. For example, disabling the sandbox when an
+ erratum is not fixed could leave the system less secure than using
+ Landlock's best-effort protection. When in doubt, ignore errata.
+
+For detailed technical descriptions of each erratum, including their impact
+and when they affect applications, see the DOC sections in the kernel source:
+
+- **Erratum 1: TCP socket identification (ABI 4)** - See ``erratum_1`` in ``security/landlock/errata/abi-4.h``
+- **Erratum 2: Scoped signal handling (ABI 6)** - See ``erratum_2`` in ``security/landlock/errata/abi-6.h``
+- **Erratum 3: Disconnected directory handling (ABI 1)** - See ``erratum_3`` in ``security/landlock/errata/abi-1.h``
+
+How to Check for Errata
+~~~~~~~~~~~~~~~~~~~~~~~
+
+If you determine that your application needs to check for specific errata,
+use this pattern:
+
+.. code-block:: c
+
+ int errata = landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_ERRATA);
+ if (errata >= 0) {
+ /* Check for specific erratum (1-indexed) */
+ if (errata & (1 << (erratum_number - 1))) {
+ /* Erratum N is fixed in this kernel */
+ } else {
+ /* Erratum N is NOT fixed - consider implications for your use case */
+ }
+ }
+
+**Important:** Only check errata if your application specifically relies on
+behavior that changed due to the fix. The fixes generally make Landlock less
+restrictive or more correct, not more restrictive.
+
The following kernel interfaces are implicitly supported by the first ABI
version. Features only supported from a specific version are explicitly marked
as such.
diff --git a/security/landlock/errata/abi-1.h b/security/landlock/errata/abi-1.h
index e8a2bff2e5b6..ba9895bf8ce1 100644
--- a/security/landlock/errata/abi-1.h
+++ b/security/landlock/errata/abi-1.h
@@ -12,5 +12,13 @@
* hierarchy down to its filesystem root and those from the related mount point
* hierarchy. This prevents access right widening through rename or link
* actions.
+ *
+ * Impact:
+ *
+ * Without this fix, it was possible to widen access rights through rename or
+ * link actions involving disconnected directories, potentially bypassing
+ * ``LANDLOCK_ACCESS_FS_REFER`` restrictions. This could allow privilege
+ * escalation in complex mount scenarios where directories become disconnected
+ * from their original mount points.
*/
LANDLOCK_ERRATUM(3)
diff --git a/security/landlock/errata/abi-4.h b/security/landlock/errata/abi-4.h
index c052ee54f89f..59574759dc1e 100644
--- a/security/landlock/errata/abi-4.h
+++ b/security/landlock/errata/abi-4.h
@@ -11,5 +11,12 @@
* :manpage:`bind(2)` and :manpage:`connect(2)` operations. This change ensures
* that only TCP sockets are subject to TCP access rights, allowing other
* protocols to operate without unnecessary restrictions.
+ *
+ * Impact:
+ *
+ * In kernels without this fix, using ``LANDLOCK_ACCESS_NET_BIND_TCP`` or
+ * ``LANDLOCK_ACCESS_NET_CONNECT_TCP`` would incorrectly restrict non-TCP
+ * stream protocols (SMC, MPTCP, SCTP), potentially breaking applications
+ * that rely on these protocols while using Landlock network restrictions.
*/
LANDLOCK_ERRATUM(1)
diff --git a/security/landlock/errata/abi-6.h b/security/landlock/errata/abi-6.h
index df7bc0e1fdf4..a3a48b2bf2db 100644
--- a/security/landlock/errata/abi-6.h
+++ b/security/landlock/errata/abi-6.h
@@ -15,5 +15,15 @@
* interaction between threads of the same process should always be allowed.
* This change ensures that any thread is allowed to send signals to any other
* thread within the same process, regardless of their domain.
+ *
+ * Impact:
+ *
+ * This problem only manifests when the userspace process is itself using
+ * :manpage:`libpsx(3)` or an equivalent mechanism to enforce a Landlock policy
+ * on multiple already-running threads at once. Programs which enforce a
+ * Landlock policy at startup time and only then become multithreaded are not
+ * affected. Without this fix, signal scoping could break multi-threaded
+ * applications that expect threads within the same process to freely signal
+ * each other.
*/
LANDLOCK_ERRATUM(2)
diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c
index 0116e9f93ffe..cf5ba7715916 100644
--- a/security/landlock/syscalls.c
+++ b/security/landlock/syscalls.c
@@ -157,9 +157,11 @@ static const struct file_operations ruleset_fops = {
/*
* The Landlock ABI version should be incremented for each new Landlock-related
* user space visible change (e.g. Landlock syscalls). This version should
- * only be incremented once per Linux release, and the date in
+ * only be incremented once per Linux release. When incrementing, the date in
* Documentation/userspace-api/landlock.rst should be updated to reflect the
* UAPI change.
+ * If the change involves a fix that requires userspace awareness, also update
+ * the errata documentation in Documentation/userspace-api/landlock.rst.
*/
const int landlock_abi_version = 7;
--
2.50.1
^ permalink raw reply related
* Re: [RFC PATCH 0/5] landlock: Pathname-based UNIX connect() control
From: Demi Marie Obenour @ 2026-01-02 18:37 UTC (permalink / raw)
To: Günther Noack
Cc: Tingmao Wang, Mickaël Salaün, Paul Moore,
linux-security-module, Justin Suess, Samasth Norway Ananda,
Matthieu Buffet, Mikhail Ivanov, konstantin.meskhidze,
Alyssa Ross, Jann Horn, Tahera Fahimi
In-Reply-To: <20260102.17e1c2b9faa4@gnoack.org>
[-- Attachment #1.1.1: Type: text/plain, Size: 2393 bytes --]
On 1/2/26 05:50, Günther Noack wrote:
> On Fri, Jan 02, 2026 at 05:27:40AM -0500, Demi Marie Obenour wrote:
>> On 1/2/26 05:16, Günther Noack wrote:
>>> On Thu, Jan 01, 2026 at 05:44:51PM -0500, Demi Marie Obenour wrote:
>>>> On 1/1/26 17:34, Tingmao Wang wrote:
>>>>> On 1/1/26 22:14, Demi Marie Obenour wrote:
>>>>>> [...]
>>>>>> Does this leave directory traversal as the only missing Landlock
>>>>>> filesystem access control? Ideally Landlock could provide the same
>>>>>> isolation from the filesystem that mount namespaces do.
>>>>>
>>>>> I think that level of isolation would require path walk control - see:
>>>>> https://github.com/landlock-lsm/linux/issues/9
>>>>>
>>>>> (Landlock also doesn't currently control some metadata operations - see
>>>>> the warning at the end of the "Filesystem flags" section in [1])
>>>>>
>>>>> [1]: https://docs.kernel.org/6.18/userspace-api/landlock.html#filesystem-flags
>>>>
>>>> Could this replace all of the existing hooks?
>>>
>>> If you do not need to distinguish between the different operations
>>> which Landlock offers access rights for, but you only want to limit
>>> the visibility of directory hierarchies in the file system, then yes,
>>> the path walk control described in issue 9 would be sufficient and a
>>> more complete control.
>>>
>>> The path walk control is probably among the more difficult Landlock
>>> feature requests. A simple implementation would be easy to implement
>>> technically, but it also requires a new LSM hook which will have to
>>> get called *during* path lookup, and we'd have to make sure that the
>>> performance impact stays in check. Path lookup is after all a very
>>> central facility in a OS kernel.
>>
>> What about instead using the inode-based hooks for directory searching?
>> SELinux can already restrict that.
>
> Oh, thanks, good pointer! I was under the impression that this didn't
> exist yet -- I assume you are referring to the
> security_inode_follow_link() hook, which is already happening during
> path resolution?
I'm not familiar with existing LSM hooks, but I do know that SELinux
enforces checks on searching and reading directories and symlinks.
> I take it back then. :) If there is prior art, implementing this might
> be more feasible than I thought.
I think so too!
--
Sincerely,
Demi Marie Obenour (she/her/hers)
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 7253 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH v2 6/6] docs: trusted-encryped: add PKWM as a new trust source
From: Mimi Zohar @ 2026-01-02 17:48 UTC (permalink / raw)
To: Srish Srinivasan, linux-integrity, keyrings, linuxppc-dev
Cc: maddy, mpe, npiggin, christophe.leroy, James.Bottomley, jarkko,
nayna, rnsastry, linux-kernel, linux-security-module
In-Reply-To: <20251217172505.112398-7-ssrish@linux.ibm.com>
On Wed, 2025-12-17 at 22:55 +0530, Srish Srinivasan wrote:
> From: Nayna Jain <nayna@linux.ibm.com>
>
> Update Documentation/security/keys/trusted-encrypted.rst and Documentation/
> admin-guide/kernel-parameters.txt with PowerVM Key Wrapping Module (PKWM)
> as a new trust source
>
> Signed-off-by: Nayna Jain <nayna@linux.ibm.com>
> Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>
Thanks, Nayna, Srish.
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
^ permalink raw reply
* Re: [PATCH v2 5/6] keys/trusted_keys: establish PKWM as a trusted source
From: Mimi Zohar @ 2026-01-02 17:44 UTC (permalink / raw)
To: Srish Srinivasan, linux-integrity, keyrings, linuxppc-dev
Cc: maddy, mpe, npiggin, christophe.leroy, James.Bottomley, jarkko,
nayna, rnsastry, linux-kernel, linux-security-module
In-Reply-To: <20251217172505.112398-6-ssrish@linux.ibm.com>
On Wed, 2025-12-17 at 22:55 +0530, Srish Srinivasan wrote:
> The wrapping key does not exist by default and is generated by the
> hypervisor as a part of PKWM initialization. This key is then persisted by
> the hypervisor and is used to wrap trusted keys. These are variable length
> symmetric keys, which in the case of PowerVM Key Wrapping Module (PKWM) are
> generated using the kernel RNG. PKWM can be used as a trust source through
> the following example keyctl command
-> commands:
>
> keyctl add trusted my_trusted_key "new 32" @u
>
> Use the wrap_flags command option to set the secure boot requirement for
> the wrapping request through the following keyctl commands
>
> case1: no secure boot requirement. (default)
> keyctl usage: keyctl add trusted my_trusted_key "new 32" @u
> OR
> keyctl add trusted my_trusted_key "new 32 wrap_flags=0x00" @u
>
> case2: secure boot required to in either audit or enforce mode. set bit 0
> keyctl usage: keyctl add trusted my_trusted_key "new 32 wrap_flags=0x01" @u
>
> case3: secure boot required to be in enforce mode. set bit 1
> keyctl usage: keyctl add trusted my_trusted_key "new 32 wrap_flags=0x02" @u
>
> NOTE:
> -> Setting the secure boot requirement is NOT a must.
> -> Only either of the secure boot requirement options should be set. Not
> both.
> -> All the other bits are requied to be not set.
-> required
> -> Set the kernel parameter trusted.source=pkwm to choose PKWM as the
> backend for trusted keys implementation.
> -> CONFIG_PSERIES_PLPKS must be enabled to build PKWM.
>
> Add PKWM, which is a combination of IBM PowerVM and Power LPAR Platform
> KeyStore, as a new trust source for trusted keys.
>
> Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>
Thanks, Srish. Other than fixing the typo and other suggestion above,
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
^ permalink raw reply
* Re: [PATCH v2 2/6] powerpc/pseries: move the PLPKS config inside its own sysfs directory
From: Mimi Zohar @ 2026-01-02 17:28 UTC (permalink / raw)
To: Srish Srinivasan, linux-integrity, keyrings, linuxppc-dev
Cc: maddy, mpe, npiggin, christophe.leroy, James.Bottomley, jarkko,
nayna, rnsastry, linux-kernel, linux-security-module
In-Reply-To: <20251217172505.112398-3-ssrish@linux.ibm.com>
On Wed, 2025-12-17 at 22:55 +0530, Srish Srinivasan wrote:
> The /sys/firmware/secvar/config directory represents Power LPAR Platform
> KeyStore (PLPKS) configuration properties such as max_object_size, signed_
> update_algorithms, supported_policies, total_size, used_space, and version.
> These attributes describe the PLPKS, and not the secure boot variables
> (secvars).
>
> Create /sys/firmware/plpks directory and move the PLPKS config inside this
> directory. For backwards compatibility, create a soft link from the secvar
> sysfs directory to this config and emit a warning stating that the older
> sysfs path has been deprecated. Separate out the plpks specific
> documentation from secvar.
>
> Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>
LGTM.
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
^ permalink raw reply
* Re: [PATCH v2 4/6] pseries/plpks: add HCALLs for PowerVM Key Wrapping Module
From: Mimi Zohar @ 2026-01-02 17:25 UTC (permalink / raw)
To: Srish Srinivasan, linux-integrity, keyrings, linuxppc-dev
Cc: maddy, mpe, npiggin, christophe.leroy, James.Bottomley, jarkko,
nayna, rnsastry, linux-kernel, linux-security-module
In-Reply-To: <20251217172505.112398-5-ssrish@linux.ibm.com>
Hi Srish,
On Wed, 2025-12-17 at 22:55 +0530, Srish Srinivasan wrote:
> The hypervisor generated wrapping key is an AES-GCM-256 symmetric key which
> is stored in a non-volatile, secure, and encrypted storage called the Power
> LPAR Platform KeyStore. It has policy based protections that prevent it
> from being read out or exposed to the user.
>
> Implement H_PKS_GEN_KEY, H_PKS_WRAP_OBJECT, and H_PKS_UNWRAP_OBJECT HCALLs
> to enable using the PowerVM Key Wrapping Module (PKWM) as a new trust
> source for trusted keys. Disallow H_PKS_READ_OBJECT, H_PKS_SIGNED_UPDATE,
> and H_PKS_WRITE_OBJECT for objects with the 'wrapping key' policy set.
> Capture the availability status for the H_PKS_WRAP_OBJECT interface.
>
> Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>
scripts/checkpatch.pl --codespell caught a couple of typos. Please fix the
typos here in in this patch and the one in v2 5/6.
> ---
> Documentation/arch/powerpc/papr_hcalls.rst | 43 +++
> arch/powerpc/include/asm/plpks.h | 10 +
> arch/powerpc/platforms/pseries/plpks.c | 345 ++++++++++++++++++++-
> 3 files changed, 396 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/arch/powerpc/papr_hcalls.rst b/Documentation/arch/powerpc/papr_hcalls.rst
> index 805e1cb9bab9..14e39f095a1c 100644
> --- a/Documentation/arch/powerpc/papr_hcalls.rst
> +++ b/Documentation/arch/powerpc/papr_hcalls.rst
> @@ -300,6 +300,49 @@ H_HTM supports setup, configuration, control and dumping of Hardware Trace
> Macro (HTM) function and its data. HTM buffer stores tracing data for functions
> like core instruction, core LLAT and nest.
>
> +**H_PKS_GEN_KEY**
> +
> +| Input: authorization, objectlabel, objectlabellen, policy, out, outlen
> +| Out: *Hypervisor Generated Key, or None when the wrapping key policy is set*
> +| Return Value: *H_SUCCESS, H_Function, H_State, H_R_State, H_Parameter, H_P2,
> + H_P3, H_P4, H_P5, H_P6, H_Authority, H_Nomem, H_Busy, H_Resource,
> + H_Aborted*
> +
> +H_PKS_GEN_KEY is used to have the hypervisor generate a new random key.
> +This key is stored as an object in the Power LPAR Platform KeyStore with
> +the provided object label. With the wrapping key policy set the key is only
> +visible to the hypervisor, while the key's label would still be visible to
> +the user. Generation of wrapping keys is supported only for a key size of
> +32 bytes.
> +
> +**H_PKS_WRAP_OBJECT**
> +
> +| Input: authorization, wrapkeylabel, wrapkeylabellen, objectwrapflags, in,
> +| inlen, out, outlen, continue-token
> +| Out: *continue-token, byte size of wrapped object, wrapped object*
> +| Return Value: *H_SUCCESS, H_Function, H_State, H_R_State, H_Parameter, H_P2,
> + H_P3, H_P4, H_P5, H_P6, H_P7, H_P8, H_P9, H_Authority, H_Invalid_Key,
> + H_NOT_FOUND, H_Busy, H_LongBusy, H_Aborted*
> +
> +H_PKS_WRAP_OBJECT is used to wrap an object using a wrapping key stored in the
> +Power LPAR Platform KeyStore and return the wrapped object to the caller. The
> +caller provides a label to a wrapping key with the 'wrapping key' policy set,
> +which must have been previously created with H_PKS_GEN_KEY. The provided object
> +is then encrypted with the wrapping key and additional metadata and the result
> +is returned to the caller.
> +
> +
> +**H_PKS_UNWRAP_OBJECT**
> +
> +| Input: authorization, objectwrapflags, in, inlen, out, outlen, continue-token
> +| Out: *continue-token, byte size of unwrapped object, unwrapped object*
> +| Return Value: *H_SUCCESS, H_Function, H_State, H_R_State, H_Parameter, H_P2,
> + H_P3, H_P4, H_P5, H_P6, H_P7, H_Authority, H_Unsupported, H_Bad_Data,
> + H_NOT_FOUND, H_Invalid_Key, H_Busy, H_LongBusy, H_Aborted*
> +
> +H_PKS_UNWRAP_OBJECT is used to unwrap an object that was previously warapped with
> +H_PKS_WRAP_OBJECT.
> +
> References
> ==========
> .. [1] "Power Architecture Platform Reference"
> diff --git a/arch/powerpc/include/asm/plpks.h b/arch/powerpc/include/asm/plpks.h
> index 8f034588fdf7..e87f90e40d4e 100644
> --- a/arch/powerpc/include/asm/plpks.h
> +++ b/arch/powerpc/include/asm/plpks.h
> @@ -113,6 +113,16 @@ void plpks_early_init_devtree(void);
> int plpks_populate_fdt(void *fdt);
>
> int plpks_config_create_softlink(struct kobject *from);
> +
> +bool plpks_wrapping_is_supported(void);
> +
> +int plpks_gen_wrapping_key(void);
> +
> +int plpks_wrap_object(u8 **input_buf, u32 input_len, u16 wrap_flags,
> + u8 **output_buf, u32 *output_len);
> +
> +int plpks_unwrap_object(u8 **input_buf, u32 input_len,
> + u8 **output_buf, u32 *output_len);
> #else // CONFIG_PSERIES_PLPKS
> static inline bool plpks_is_available(void) { return false; }
> static inline u16 plpks_get_passwordlen(void) { BUILD_BUG(); }
> diff --git a/arch/powerpc/platforms/pseries/plpks.c b/arch/powerpc/platforms/pseries/plpks.c
> index 4a08f51537c8..2ec04908b057 100644
> --- a/arch/powerpc/platforms/pseries/plpks.c
> +++ b/arch/powerpc/platforms/pseries/plpks.c
> @@ -9,6 +9,32 @@
>
> #define pr_fmt(fmt) "plpks: " fmt
>
> +#define PLPKS_WRAPKEY_COMPONENT "PLPKSWR"
> +#define PLPKS_WRAPKEY_NAME "default-wrapping-key"
> +
> +/*
> + * To 4K align the {input, output} buffers to the {UN}WRAP H_CALLs
> + */
> +#define PLPKS_WRAPPING_BUF_ALIGN 4096
> +
> +/*
> + * To ensure the output buffer's length is at least 1024 bytes greater
> + * than the input buffer's length during the WRAP H_CALL
> + */
> +#define PLPKS_WRAPPING_BUF_DIFF 1024
> +
> +#define PLPKS_WRAP_INTERFACE_BIT 3
> +#define PLPKS_WRAPPING_KEY_LENGTH 32
> +
> +#define WRAPFLAG_BE_BIT_SET(be_bit) \
> + BIT_ULL(63 - (be_bit))
> +
> +#define WRAPFLAG_BE_GENMASK(be_bit_hi, be_bit_lo) \
> + GENMASK_ULL(63 - (be_bit_hi), 63 - (be_bit_lo))
> +
> +#define WRAPFLAG_BE_FIELD_PREP(be_bit_hi, be_bit_lo, val) \
> + FIELD_PREP(WRAPFLAG_BE_GENMASK(be_bit_hi, be_bit_lo), (val))
> +
> #include <linux/delay.h>
> #include <linux/errno.h>
> #include <linux/io.h>
> @@ -39,6 +65,7 @@ static u32 supportedpolicies;
> static u32 maxlargeobjectsize;
> static u64 signedupdatealgorithms;
> static u64 wrappingfeatures;
> +static bool wrapsupport;
>
> struct plpks_auth {
> u8 version;
> @@ -283,6 +310,7 @@ static int _plpks_get_config(void)
> maxlargeobjectsize = be32_to_cpu(config->maxlargeobjectsize);
> signedupdatealgorithms = be64_to_cpu(config->signedupdatealgorithms);
> wrappingfeatures = be64_to_cpu(config->wrappingfeatures);
> + wrapsupport = config->flags & PPC_BIT8(PLPKS_WRAP_INTERFACE_BIT);
>
> // Validate that the numbers we get back match the requirements of the spec
> if (maxpwsize < 32) {
> @@ -614,6 +642,9 @@ int plpks_signed_update_var(struct plpks_var *var, u64 flags)
> if (!(var->policy & PLPKS_SIGNEDUPDATE))
> return -EINVAL;
>
> + if (var->policy & PLPKS_WRAPPINGKEY)
> + return -EINVAL;
> +
> // Signed updates need the component to be NULL.
> if (var->component)
> return -EINVAL;
> @@ -696,6 +727,9 @@ int plpks_write_var(struct plpks_var var)
> if (var.policy & PLPKS_SIGNEDUPDATE)
> return -EINVAL;
>
> + if (var.policy & PLPKS_WRAPPINGKEY)
> + return -EINVAL;
> +
> auth = construct_auth(PLPKS_OS_OWNER);
> if (IS_ERR(auth))
> return PTR_ERR(auth);
> @@ -790,6 +824,9 @@ static int plpks_read_var(u8 consumer, struct plpks_var *var)
> if (var->namelen > PLPKS_MAX_NAME_SIZE)
> return -EINVAL;
>
> + if (var->policy & PLPKS_WRAPPINGKEY)
> + return -EINVAL;
> +
> auth = construct_auth(consumer);
> if (IS_ERR(auth))
> return PTR_ERR(auth);
> @@ -845,8 +882,312 @@ static int plpks_read_var(u8 consumer, struct plpks_var *var)
> }
>
> /**
> - * plpks_read_os_var() - Fetch the data for the specified variable that is
> - * owned by the OS consumer.
> + * plpks_wrapping_is_supported() - Get the H_PKS_WRAP_OBJECT interface
> + * availability status for the LPAR.
> + *
> + * Successful execution of the H_PKS_GET_CONFIG HCALL during initialization
> + * sets bit 3 of the flags variable in the PLPKS config structure if the
> + * H_PKS_WRAP_OBJECT interface is supported.
> + *
> + * Returns: true if the H_PKS_WRAP_OBJECT interface is supported, false if not.
> + */
> +bool plpks_wrapping_is_supported(void)
> +{
> + return wrapsupport;
> +}
> +
> +/**
> + * plpks_gen_wrapping_key() - Generate a new random key with the 'wrapping key'
> + * policy set.
> + *
> + * The H_PKS_GEN_KEY HCALL makes the hypervisor generate a new random key and
> + * store the key in a PLPKS object with the provided object label. With the
> + * 'wrapping key' policy set, only the label to the newly generated random key
> + * would be visible to the user.
> + *
> + * Possible reasons for the returned errno values:
> + *
> + * -ENXIO if PLPKS is not supported
> + * -EIO if PLPKS access is blocked due to the LPAR's state
> + * if PLPKS modification is blocked due to the LPAR's state
> + * if an error occurred while processing the request
> + * -EINVAL if invalid authorization parameter
> + * if invalid object label parameter
> + * if invalid object label len parameter
> + * if invalid or unsupported policy declaration
> + * if invalid output buffer parameter
> + * if invalid output buffer length parameter
> + * -EPERM if access is denied
> + * -ENOMEM if there is inadequate memory to perform this operation
> + * -EBUSY if unable to handle the request
> + * -EEXIST if the object label already exists
> + *
> + * Returns: On success 0 is returned, a negative errno if not.
> + */
> +int plpks_gen_wrapping_key(void)
> +{
> + unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
> + struct plpks_auth *auth;
> + struct label *label;
> + int rc = 0, pseries_status = 0;
> + struct plpks_var var = {
> + .name = PLPKS_WRAPKEY_NAME,
> + .namelen = strlen(var.name),
> + .policy = PLPKS_WRAPPINGKEY,
> + .os = PLPKS_VAR_LINUX,
> + .component = PLPKS_WRAPKEY_COMPONENT
> + };
> +
> + auth = construct_auth(PLPKS_OS_OWNER);
> + if (IS_ERR(auth))
> + return PTR_ERR(auth);
> +
> + label = construct_label(var.component, var.os, var.name, var.namelen);
> + if (IS_ERR(label)) {
> + rc = PTR_ERR(label);
> + goto out;
> + }
> +
> + rc = plpar_hcall(H_PKS_GEN_KEY, retbuf,
> + virt_to_phys(auth), virt_to_phys(label),
> + label->size, var.policy,
> + NULL, PLPKS_WRAPPING_KEY_LENGTH);
> +
> + if (!rc)
> + rc = plpks_confirm_object_flushed(label, auth);
> +
> + pseries_status = rc;
> + rc = pseries_status_to_err(rc);
> +
> + if (rc && rc != -EEXIST) {
> + pr_err("H_PKS_GEN_KEY failed.");
> + pr_err("pseries_status = %d, error code = %d", pseries_status,
> + rc);
> + } else {
> + rc = 0;
> + }
> +
> + kfree(label);
> +out:
> + kfree(auth);
> + return rc;
> +}
> +EXPORT_SYMBOL_GPL(plpks_gen_wrapping_key);
> +
> +/**
> + * plpks_wrap_object() - Wrap an object using the default wrapping key stored in
> + * the PLPKS.
> + * @input_buf: buffer containing the data to be wrapped
> + * @input_len: length of the input buffer
> + * @wrap_flags: object wrapping flags
> + * @output_buf: buffer to store the wrapped data
> + * @output_len: length of the output buffer
> + *
> + * The H_PKS_WRAP_OBJECT HCALL wraps an object using a wrapping key stored in
> + * the PLPKS and returns the wrapped object to the caller. The caller provides a
> + * label to the wrapping key with the 'wrapping key' policy set that must have
> + * been previously created with the H_PKS_GEN_KEY HCALL. The provided object is
> + * then encrypted with the wrapping key and additional metadata and the result
> + * is returned to the user. The metadata includes the wrapping algorithm and the
> + * wrapping key name so those parameters are not required during unwrap.
> + *
> + * Possible reasons for the returned errno values:
> + *
> + * -ENXIO if PLPKS is not supported
> + * -EIO if PLPKS access is blocked due to the LPAR's state
> + * if PLPKS modification is blocked due to the LPAR's state
> + * if an error occurred while processing the request
> + * -EINVAL if invalid authorization parameter
> + * if invalid wraping key label parameter
-> wrapping
> + * if invalid wrapping key label length parameter
> + * if invalid or unsupported object wrapping flags
> + * if invalid inut buffer parameter
-> input
> + * if invalid input buffer length parameter
> + * if invalid output buffer parameter
> + * if invalid output buffer length parameter
> + * if invalid continue token parameter
> + * if the wrapping key is not compatible with the wrapping
> + * algorithm
> + * -EPERM if access is denied
> + * -ENOENT if the requested wrapping key was not found
> + * -EBUSY if unable to handle the request or long running operation
> + * initiated, retry later.
> + *
> + * Returns: On success 0 is returned, a negative errno if not.
> + */
> +int plpks_wrap_object(u8 **input_buf, u32 input_len, u16 wrap_flags,
> + u8 **output_buf, u32 *output_len)
> +{
> + unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = { 0 };
> + struct plpks_auth *auth;
> + struct label *label;
> + u64 continuetoken = 0;
> + u64 objwrapflags = 0;
> + int rc = 0, pseries_status = 0;
> + bool sb_audit_or_enforce_bit = wrap_flags & BIT(0);
> + bool sb_enforce_bit = wrap_flags & BIT(1);
> + struct plpks_var var = {
> + .name = PLPKS_WRAPKEY_NAME,
> + .namelen = strlen(var.name),
> + .os = PLPKS_VAR_LINUX,
> + .component = PLPKS_WRAPKEY_COMPONENT
> + };
> +
> + auth = construct_auth(PLPKS_OS_OWNER);
> + if (IS_ERR(auth))
> + return PTR_ERR(auth);
> +
> + label = construct_label(var.component, var.os, var.name, var.namelen);
> + if (IS_ERR(label)) {
> + rc = PTR_ERR(label);
> + goto out;
> + }
> +
> + /* Set the consumer password requirement bit. A must have. */
> + objwrapflags |= WRAPFLAG_BE_BIT_SET(3);
> +
> + /* Set the wrapping algorithm bit. Just one algorithm option for now */
> + objwrapflags |= WRAPFLAG_BE_FIELD_PREP(60, 63, 0x1);
> +
> + if (sb_audit_or_enforce_bit & sb_enforce_bit) {
> + pr_err("Cannot set both audit/enforce and enforce bits.");
> + rc = -EINVAL;
> + goto out_free_label;
> + } else if (sb_audit_or_enforce_bit) {
> + objwrapflags |= WRAPFLAG_BE_BIT_SET(1);
> + } else if (sb_enforce_bit) {
> + objwrapflags |= WRAPFLAG_BE_BIT_SET(2);
> + }
> +
> + *output_len = input_len + PLPKS_WRAPPING_BUF_DIFF;
> +
> + *output_buf = kzalloc(ALIGN(*output_len, PLPKS_WRAPPING_BUF_ALIGN),
> + GFP_KERNEL);
> + if (!(*output_buf)) {
> + pr_err("Output buffer allocation failed. Returning -ENOMEM.");
> + rc = -ENOMEM;
> + goto out_free_label;
> + }
> +
> + do {
> + rc = plpar_hcall9(H_PKS_WRAP_OBJECT, retbuf,
> + virt_to_phys(auth), virt_to_phys(label),
> + label->size, objwrapflags,
> + virt_to_phys(*input_buf), input_len,
> + virt_to_phys(*output_buf), *output_len,
> + continuetoken);
> +
> + continuetoken = retbuf[0];
> + pseries_status = rc;
> + rc = pseries_status_to_err(rc);
> + } while (rc == -EBUSY);
> +
> + if (rc) {
> + pr_err("H_PKS_WRAP_OBJECT failed.");
> + pr_err("pseries_status = %d, return code = %d", pseries_status,
> + rc);
> + kfree(*output_buf);
> + *output_buf = NULL;
> + } else {
> + *output_len = retbuf[1];
> + }
> +
> +out_free_label:
> + kfree(label);
> +out:
> + kfree(auth);
> + return rc;
> +}
> +EXPORT_SYMBOL_GPL(plpks_wrap_object);
> +
> +/**
> + * plpks_unwrap_object() - Unwrap an object using the default wrapping key
> + * stored in the PLPKS.
> + * @input_buf: buffer containing the data to be unwrapped
> + * @input_len: length of the input buffer
> + * @output_buf: buffer to store the unwrapped data
> + * @output_len: length of the output buffer
> + *
> + * The H_PKS_UNWRAP_OBJECT HCALL unwraps an object that was previously wrapped
> + * using the H_PKS_WRAP_OBJECT HCALL.
> + *
> + * Possible reasons for the returned errno values:
> + *
> + * -ENXIO if PLPKS is not supported
> + * -EIO if PLPKS access is blocked due to the LPAR's state
> + * if PLPKS modification is blocked due to the LPAR's state
> + * if an error occurred while processing the request
> + * -EINVAL if invalid authorization parameter
> + * if invalid or unsupported object unwrapping flags
> + * if invalid inut buffer parameter
-> input
> + * if invalid input buffer length parameter
> + * if invalid output buffer parameter
> + * if invalid output buffer length parameter
> + * if invalid continue token parameter
> + * if the wrapping key is not compatible with the wrapping
> + * algorithm
> + * if the wrapped object's format is not supported
> + * if the wrapped object is invalid
> + * -EPERM if access is denied
> + * -ENOENT if the wrapping key for the provided object was not found
> + * -EBUSY if unable to handle the request or long running operation
> + * initiated, retry later.
> + *
> + * Returns: On success 0 is returned, a negative errno if not.
> + */
> +int plpks_unwrap_object(u8 **input_buf, u32 input_len, u8 **output_buf,
> + u32 *output_len)
> +{
> + unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = { 0 };
> + struct plpks_auth *auth;
> + u64 continuetoken = 0;
> + u64 objwrapflags = 0;
> + int rc = 0, pseries_status = 0;
> +
> + auth = construct_auth(PLPKS_OS_OWNER);
> + if (IS_ERR(auth))
> + return PTR_ERR(auth);
> +
> + *output_len = input_len - PLPKS_WRAPPING_BUF_DIFF;
> + *output_buf = kzalloc(ALIGN(*output_len, PLPKS_WRAPPING_BUF_ALIGN),
> + GFP_KERNEL);
> + if (!(*output_buf)) {
> + pr_err("Output buffer allocation failed. Returning -ENOMEM.");
> + rc = -ENOMEM;
> + goto out;
> + }
> +
> + do {
> + rc = plpar_hcall9(H_PKS_UNWRAP_OBJECT, retbuf,
> + virt_to_phys(auth), objwrapflags,
> + virt_to_phys(*input_buf), input_len,
> + virt_to_phys(*output_buf), *output_len,
> + continuetoken);
> +
> + continuetoken = retbuf[0];
> + pseries_status = rc;
> + rc = pseries_status_to_err(rc);
> + } while (rc == -EBUSY);
> +
> + if (rc) {
> + pr_err("H_PKS_UNWRAP_OBJECT failed.");
> + pr_err("pseries_status = %d, return code = %d", pseries_status,
> + rc);
> + kfree(*output_buf);
> + *output_buf = NULL;
> + } else {
> + *output_len = retbuf[1];
> + }
> +
> +out:
> + kfree(auth);
> + return rc;
> +}
> +EXPORT_SYMBOL_GPL(plpks_unwrap_object);
> +
> +/**
> + * plpks_read_os_var() - Fetch the data for the specified variable that is owned
> + * by the OS consumer.
> * @var: variable to be read from the PLPKS
> *
> * The consumer or the owner of the object is the os kernel. The
^ permalink raw reply
* Re: [PATCH v2 1/6] pseries/plpks: fix kernel-doc comment inconsistencies
From: Mimi Zohar @ 2026-01-02 17:23 UTC (permalink / raw)
To: Srish Srinivasan, linux-integrity, keyrings, linuxppc-dev
Cc: maddy, mpe, npiggin, christophe.leroy, James.Bottomley, jarkko,
nayna, rnsastry, linux-kernel, linux-security-module
In-Reply-To: <20251217172505.112398-2-ssrish@linux.ibm.com>
On Wed, 2025-12-17 at 22:55 +0530, Srish Srinivasan wrote:
> Fix issues with comments for all the applicable functions to be
> consistent with kernel-doc format. Move them before the function
> definition as opposed to the function prototype.
>
> Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>
Thanks Srish for moving and fixing the kernel documentation.
--
Mimi
^ permalink raw reply
* Re: [PATCH v8 03/12] tpm: Orchestrate TPM commands in tpm_get_random()
From: Jarkko Sakkinen @ 2026-01-02 16:40 UTC (permalink / raw)
To: Jonathan McDowell
Cc: linux-integrity, Eric Biggers, Peter Huewe, Jason Gunthorpe,
David Howells, Paul Moore, James Morris, Serge E. Hallyn,
open list, open list:KEYS/KEYRINGS, open list:SECURITY SUBSYSTEM
In-Reply-To: <aUUeP5qhEISjythp@earth.li>
On Fri, Dec 19, 2025 at 09:43:27AM +0000, Jonathan McDowell wrote:
> On Tue, Dec 16, 2025 at 11:21:37AM +0200, Jarkko Sakkinen wrote:
> > tpm1_get_random() and tpm2_get_random() contain duplicate orchestration
> > code. Consolidate orchestration to tpm_get_random().
>
> Does keeping the respective tpm1/tpm2 bits in their -cmd.c files not make
> more sense, still allowing for the consolidation of orchestration in
> tpm_get_random?
Yeah, especially after not paying attention to this for couple of weeks
this really feels like unnecessary. It would also reduce the overall
delta caused by these patches. I will take here step back and retain
the helpers in tpm1/tpm2-cmd.c files.
BR, Jarkko
^ permalink raw reply
* Re: [PATCH v8 04/12] tpm: Change tpm_get_random() opportunistic
From: Jarkko Sakkinen @ 2026-01-02 16:37 UTC (permalink / raw)
To: Jonathan McDowell
Cc: linux-integrity, David S . Miller, Herbert Xu, Eric Biggers,
Peter Huewe, Jason Gunthorpe, David Howells, Paul Moore,
James Morris, Serge E. Hallyn, open list, open list:KEYS/KEYRINGS,
open list:SECURITY SUBSYSTEM
In-Reply-To: <aUUd760l89lrNOs-@earth.li>
On Fri, Dec 19, 2025 at 09:42:07AM +0000, Jonathan McDowell wrote:
> On Tue, Dec 16, 2025 at 11:21:38AM +0200, Jarkko Sakkinen wrote:
> > hwrng framework does not have a requirement that the all bytes requested
> > need to be provided. By enforcing such a requirement internally, TPM driver
> > can cause unpredictability in latency, as a single tpm_get_random() call
> > can result multiple TPM commands.
> >
> > Especially, when TCG_TPM2_HMAC is enabled, extra roundtrips could have
> > significant effect to the system latency.
> >
> > Thus, send TPM command only once and return bytes received instead of
> > committing to the number of requested bytes.
>
> Function comment for tpm_get_random needs updated as well, as it currently
> says "until all of the @max bytes have been received", which is no longer
> true with this patch. With that:
>
> Reviewed-by: Jonathan McDowell <noodles@meta.com>
Thank you and definitely can refine that comment. After holidays it is
probably to go through this patch set with time and send +1 iteration
:-)
BR, Jarkko
^ permalink raw reply
* Re: [PATCH v8 05/12] tpm2-sessions: Define TPM2_NAME_MAX_SIZE
From: Jarkko Sakkinen @ 2026-01-02 16:35 UTC (permalink / raw)
To: Jonathan McDowell
Cc: linux-integrity, Peter Huewe, Jason Gunthorpe, David Howells,
Paul Moore, James Morris, Serge E. Hallyn, open list,
open list:KEYS/KEYRINGS, open list:SECURITY SUBSYSTEM
In-Reply-To: <aUUbkosWlOjZ48YP@earth.li>
On Fri, Dec 19, 2025 at 09:32:02AM +0000, Jonathan McDowell wrote:
> On Tue, Dec 16, 2025 at 11:21:39AM +0200, Jarkko Sakkinen wrote:
> > Define TPM2_NAME_MAX_SIZE, which describes the maximum size for hashes
> > encoded as TPMT_HA, which the prime identifier used for persistent and
> > transient keys in TPM2 protocol.
> >
> > Set its value to 'SHA512_DIGEST_SIZE + 2', as SHA512 has the largest
> > digest size of the algorithms in TCG algorithm repository.
> >
> > In additionl, rename TPM2_NAME_SIZE as TPM2_NULL_NAME_SIZE in order to
> > avoid any possible confusion.
>
> One minor capitalisation nit, otherwise:
>
> Reviewed-by: Jonathan McDowell <noodles@meta.com>
>
> > Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
> > ---
> > v6:
> > - Rewrote the commit message.
> > v2:
> > - Rename TPM2_NAME_SIZE as TPM2_NULL_NAME_SIZE.
> > ---
> > drivers/char/tpm/tpm-sysfs.c | 2 +-
> > drivers/char/tpm/tpm2-sessions.c | 2 +-
> > include/linux/tpm.h | 37 +++++++++++++++++++++-----------
> > 3 files changed, 27 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
> > index 94231f052ea7..4a6a27ee295d 100644
> > --- a/drivers/char/tpm/tpm-sysfs.c
> > +++ b/drivers/char/tpm/tpm-sysfs.c
> > @@ -314,7 +314,7 @@ static ssize_t null_name_show(struct device *dev, struct device_attribute *attr,
> > char *buf)
> > {
> > struct tpm_chip *chip = to_tpm_chip(dev);
> > - int size = TPM2_NAME_SIZE;
> > + int size = TPM2_NULL_NAME_SIZE;
> >
> > bin2hex(buf, chip->null_key_name, size);
> > size *= 2;
> > diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c
> > index 4149379665c4..525b8622d1c3 100644
> > --- a/drivers/char/tpm/tpm2-sessions.c
> > +++ b/drivers/char/tpm/tpm2-sessions.c
> > @@ -137,7 +137,7 @@ struct tpm2_auth {
> > * we must compute and remember
> > */
> > u32 name_h[AUTH_MAX_NAMES];
> > - u8 name[AUTH_MAX_NAMES][2 + SHA512_DIGEST_SIZE];
> > + u8 name[AUTH_MAX_NAMES][TPM2_MAX_NAME_SIZE];
> > };
> >
> > #ifdef CONFIG_TCG_TPM2_HMAC
> > diff --git a/include/linux/tpm.h b/include/linux/tpm.h
> > index 202da079d500..e10f2096eae7 100644
> > --- a/include/linux/tpm.h
> > +++ b/include/linux/tpm.h
> > @@ -27,9 +27,33 @@
> >
> > #define TPM_DIGEST_SIZE 20 /* Max TPM v1.2 PCR size */
> >
> > +/*
> > + * SHA-512 is, as of today, the largest digest in the TCG algorithm repository.
> > + */
> > #define TPM2_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
> > +
> > +/*
> > + * A TPM name digest i.e., TPMT_HA, is a concatenation of TPM_ALG_ID of the
> > + * name algorithm and hash of TPMT_PUBLIC.
> > + */
> > +#define TPM2_MAX_NAME_SIZE (TPM2_MAX_DIGEST_SIZE + 2)
> > +
> > +/*
> > + * The maximum number of PCR banks.
> > + */
> > #define TPM2_MAX_PCR_BANKS 8
> >
> > +/*
> > + * fixed define for the size of a name. This is actually HASHALG size
>
> "Fixed define".
Thanks, yeah, I can fix this up :-)
>
> > + * plus 2, so 32 for SHA256
> > + */
> > +#define TPM2_NULL_NAME_SIZE 34
> > +
> > +/*
> > + * The maximum size for an object context
> > + */
> > +#define TPM2_MAX_CONTEXT_SIZE 4096
> > +
> > struct tpm_chip;
> > struct trusted_key_payload;
> > struct trusted_key_options;
> > @@ -139,17 +163,6 @@ struct tpm_chip_seqops {
> > /* fixed define for the curve we use which is NIST_P256 */
> > #define EC_PT_SZ 32
> >
> > -/*
> > - * fixed define for the size of a name. This is actually HASHALG size
> > - * plus 2, so 32 for SHA256
> > - */
> > -#define TPM2_NAME_SIZE 34
> > -
> > -/*
> > - * The maximum size for an object context
> > - */
> > -#define TPM2_MAX_CONTEXT_SIZE 4096
> > -
> > struct tpm_chip {
> > struct device dev;
> > struct device devs;
> > @@ -211,7 +224,7 @@ struct tpm_chip {
> > /* saved context for NULL seed */
> > u8 null_key_context[TPM2_MAX_CONTEXT_SIZE];
> > /* name of NULL seed */
> > - u8 null_key_name[TPM2_NAME_SIZE];
> > + u8 null_key_name[TPM2_NULL_NAME_SIZE];
> > u8 null_ec_key_x[EC_PT_SZ];
> > u8 null_ec_key_y[EC_PT_SZ];
> > struct tpm2_auth *auth;
> > --
> > 2.39.5
> >
> >
>
> J.
>
> --
> Why do I get the feeling I'm going to regret this?
> This .sig brought to you by the letter S and the number 50
> Product of the Republic of HuggieTag
BR, Jarkko
^ permalink raw reply
* Re: [PATCH v8 02/12] KEYS: trusted: Use get_random_bytes_wait() instead of tpm_get_random()
From: Jarkko Sakkinen @ 2026-01-02 16:34 UTC (permalink / raw)
To: Jonathan McDowell
Cc: linux-integrity, Eric Biggers, David Howells, Paul Moore,
James Morris, Serge E. Hallyn, James Bottomley, Mimi Zohar,
open list:KEYS/KEYRINGS, open list:SECURITY SUBSYSTEM, open list
In-Reply-To: <aUUZKu2xaZvEdq-2@earth.li>
On Fri, Dec 19, 2025 at 09:21:46AM +0000, Jonathan McDowell wrote:
> On Tue, Dec 16, 2025 at 11:21:36AM +0200, Jarkko Sakkinen wrote:
> > Substitute remaining tpm_get_random() calls in trusted_tpm1.c with
> > get_random_bytes_wait() thus aligning random number generation for TPM 1.2
> > with the removal of '.get_random' callback.
>
> Had to double check we wouldn't end up not getting all the randomness we ask
> for, but get_random_bytes_wait does indeed DTRT.
>
> Reviewed-by: Jonathan McDowell <noodles@meta.com>
Thank you.
BR, Jarkko
^ permalink raw reply
* Re: [PATCH v8 07/12] KEYS: trusted: Remove dead branch from tpm2_unseal_cmd
From: Jarkko Sakkinen @ 2026-01-02 16:31 UTC (permalink / raw)
To: James Bottomley
Cc: linux-integrity, David Howells, Paul Moore, James Morris,
Serge E. Hallyn, Mimi Zohar, open list:KEYS/KEYRINGS,
open list:SECURITY SUBSYSTEM, open list
In-Reply-To: <57e69d4fd5a40899cd779ee04f29f33009c97431.camel@HansenPartnership.com>
On Fri, Dec 19, 2025 at 03:54:47PM -0500, James Bottomley wrote:
> On Tue, 2025-12-16 at 11:21 +0200, Jarkko Sakkinen wrote:
> > TPM2_Unseal requires TPM2_ST_SESSIONS, and tpm2_unseal_cmd() always
> > does set up either password or HMAC session.
> >
> > Remove the branch in tpm2_unseal_cmd() conditionally setting
> > TPM2_ST_NO_SESSIONS. It is faulty but luckily it is never exercised
> > at run-time, and thus does not cause regressions.
>
> Shouldn't that also be
>
> Fixes: b7960b904861 ("tpm2-sessions: Open code tpm_buf_append_hmac_session()")
The implementation has pre-existed before that commit so it did
not really cause it. The call path was just more masked before
open coding it.
The code is of course exercised in !TCG_TPM2_HMAC case but it
by definition does nothing.
>
> > Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
> > ---
> > security/keys/trusted-keys/trusted_tpm2.c | 10 +---------
> > 1 file changed, 1 insertion(+), 9 deletions(-)
> >
> > diff --git a/security/keys/trusted-keys/trusted_tpm2.c
> > b/security/keys/trusted-keys/trusted_tpm2.c
> > index d3a5c5f2b926..3666e3e48eab 100644
> > --- a/security/keys/trusted-keys/trusted_tpm2.c
> > +++ b/security/keys/trusted-keys/trusted_tpm2.c
> > @@ -451,10 +451,8 @@ static int tpm2_unseal_cmd(struct tpm_chip
> > *chip,
> > struct trusted_key_options *options,
> > u32 blob_handle)
> > {
> > - struct tpm_header *head;
> > struct tpm_buf buf;
> > u16 data_len;
> > - int offset;
> > u8 *data;
> > int rc;
> >
> > @@ -495,14 +493,8 @@ static int tpm2_unseal_cmd(struct tpm_chip
> > *chip,
> > tpm_buf_append_u16(&buf, options->blobauth_len);
> > tpm_buf_append(&buf, options->blobauth, options-
> > >blobauth_len);
> >
> > - if (tpm2_chip_auth(chip)) {
> > + if (tpm2_chip_auth(chip))
>
> Since the statement above is that the if is always true, why do you
> still have it here?
This is still necessary for !TCG_TPM2_HMAC case. The commit is pretty
much exactly in its described scope.
>
> Regards,
>
> James
>
BR, Jarkko
^ permalink raw reply
* Re: [PATCH V2 1/1] IMA event log trimming
From: steven chen @ 2026-01-02 14:33 UTC (permalink / raw)
To: Mimi Zohar, linux-integrity
Cc: roberto.sassu, dmitry.kasatkin, eric.snowberg, corbet, serge,
paul, jmorris, linux-security-module, anirudhve, gregorylumen,
nramas, sushring, linux-doc, steven chen
In-Reply-To: <9a26898f46406314be1308e5416c0d51cedf44a4.camel@linux.ibm.com>
On 12/23/2025 2:32 PM, Mimi Zohar wrote:
> On Tue, 2025-12-16 at 11:59 -0800, steven chen wrote:
>>>>> +{
>>>>> + struct ima_queue_entry *qe, *qe_tmp;
>>>>> + LIST_HEAD(ima_measurements_staged);
>>>>> + unsigned int i;
>>>>> + long cur = number_logs;
>>> The variable name "number_logs" is confusing. As I mentioned in the patch
>>> description, there is one measurement list with multiple records. There aren't
>>> multiple logs in the kernel (other than the staged list).
>> Will update it to "req_value". Thanks!
> Please refer to the section titled "Naming" in Documentation/process/coding-
> style.rst. Since this is the number of records being deleted, perhaps a better
> variable name would be "num_records".
>
Will update. Thanks
Steven
^ permalink raw reply
* Re: [RFC PATCH 0/5] landlock: Pathname-based UNIX connect() control
From: Günther Noack @ 2026-01-02 10:50 UTC (permalink / raw)
To: Demi Marie Obenour
Cc: Tingmao Wang, Mickaël Salaün, Paul Moore,
linux-security-module, Justin Suess, Samasth Norway Ananda,
Matthieu Buffet, Mikhail Ivanov, konstantin.meskhidze,
Alyssa Ross, Jann Horn, Tahera Fahimi
In-Reply-To: <81f908e3-8a98-46e7-b20c-fe647784ceb4@gmail.com>
On Fri, Jan 02, 2026 at 05:27:40AM -0500, Demi Marie Obenour wrote:
> On 1/2/26 05:16, Günther Noack wrote:
> > On Thu, Jan 01, 2026 at 05:44:51PM -0500, Demi Marie Obenour wrote:
> >> On 1/1/26 17:34, Tingmao Wang wrote:
> >>> On 1/1/26 22:14, Demi Marie Obenour wrote:
> >>>> [...]
> >>>> Does this leave directory traversal as the only missing Landlock
> >>>> filesystem access control? Ideally Landlock could provide the same
> >>>> isolation from the filesystem that mount namespaces do.
> >>>
> >>> I think that level of isolation would require path walk control - see:
> >>> https://github.com/landlock-lsm/linux/issues/9
> >>>
> >>> (Landlock also doesn't currently control some metadata operations - see
> >>> the warning at the end of the "Filesystem flags" section in [1])
> >>>
> >>> [1]: https://docs.kernel.org/6.18/userspace-api/landlock.html#filesystem-flags
> >>
> >> Could this replace all of the existing hooks?
> >
> > If you do not need to distinguish between the different operations
> > which Landlock offers access rights for, but you only want to limit
> > the visibility of directory hierarchies in the file system, then yes,
> > the path walk control described in issue 9 would be sufficient and a
> > more complete control.
> >
> > The path walk control is probably among the more difficult Landlock
> > feature requests. A simple implementation would be easy to implement
> > technically, but it also requires a new LSM hook which will have to
> > get called *during* path lookup, and we'd have to make sure that the
> > performance impact stays in check. Path lookup is after all a very
> > central facility in a OS kernel.
>
> What about instead using the inode-based hooks for directory searching?
> SELinux can already restrict that.
Oh, thanks, good pointer! I was under the impression that this didn't
exist yet -- I assume you are referring to the
security_inode_follow_link() hook, which is already happening during
path resolution?
I take it back then. :) If there is prior art, implementing this might
be more feasible than I thought.
–Günther
^ permalink raw reply
* Re: [RFC PATCH 0/5] landlock: Pathname-based UNIX connect() control
From: Demi Marie Obenour @ 2026-01-02 10:27 UTC (permalink / raw)
To: Günther Noack
Cc: Tingmao Wang, Mickaël Salaün, Paul Moore,
linux-security-module, Justin Suess, Samasth Norway Ananda,
Matthieu Buffet, Mikhail Ivanov, konstantin.meskhidze,
Alyssa Ross, Jann Horn, Tahera Fahimi
In-Reply-To: <20260102.93e0d7b9c9b5@gnoack.org>
[-- Attachment #1.1.1: Type: text/plain, Size: 1722 bytes --]
On 1/2/26 05:16, Günther Noack wrote:
> On Thu, Jan 01, 2026 at 05:44:51PM -0500, Demi Marie Obenour wrote:
>> On 1/1/26 17:34, Tingmao Wang wrote:
>>> On 1/1/26 22:14, Demi Marie Obenour wrote:
>>>> [...]
>>>> Does this leave directory traversal as the only missing Landlock
>>>> filesystem access control? Ideally Landlock could provide the same
>>>> isolation from the filesystem that mount namespaces do.
>>>
>>> I think that level of isolation would require path walk control - see:
>>> https://github.com/landlock-lsm/linux/issues/9
>>>
>>> (Landlock also doesn't currently control some metadata operations - see
>>> the warning at the end of the "Filesystem flags" section in [1])
>>>
>>> [1]: https://docs.kernel.org/6.18/userspace-api/landlock.html#filesystem-flags
>>
>> Could this replace all of the existing hooks?
>
> If you do not need to distinguish between the different operations
> which Landlock offers access rights for, but you only want to limit
> the visibility of directory hierarchies in the file system, then yes,
> the path walk control described in issue 9 would be sufficient and a
> more complete control.
>
> The path walk control is probably among the more difficult Landlock
> feature requests. A simple implementation would be easy to implement
> technically, but it also requires a new LSM hook which will have to
> get called *during* path lookup, and we'd have to make sure that the
> performance impact stays in check. Path lookup is after all a very
> central facility in a OS kernel.
What about instead using the inode-based hooks for directory searching?
SELinux can already restrict that.
--
Sincerely,
Demi Marie Obenour (she/her/hers)
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 7253 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [RFC PATCH 0/5] landlock: Pathname-based UNIX connect() control
From: Günther Noack @ 2026-01-02 10:25 UTC (permalink / raw)
To: Demi Marie Obenour
Cc: Tingmao Wang, Mickaël Salaün, Paul Moore,
linux-security-module, Justin Suess, Samasth Norway Ananda,
Matthieu Buffet, Mikhail Ivanov, konstantin.meskhidze,
Alyssa Ross, Jann Horn, Tahera Fahimi
In-Reply-To: <20260102.93e0d7b9c9b5@gnoack.org>
On Fri, Jan 02, 2026 at 11:16:33AM +0100, Günther Noack wrote:
> Regarding the un-restrictable operations, Tingmao's pointers are
> correct. In the warning box in the documentation, the missing
> operations that I am aware of are (a) the Unix socket connect()
> operation, and (b) the symlink lookup which happens implicitly during
> path traversal and which Landlock and other LSMs can not control
> through LSM hooks at the moment. (A symlink always gets implicitly
> resolved during path lookup even when you do not have directory read
> permissions on the directory where the symlink is.)
I forgot to mention - the error codes returned by Landlock make it
possible to probe for the presence of files, even when all available
FS access rights are denied on a directory. Attempting to open a file
for reading will return EEXIST if it is missing, but will return
EACCES if it is denied by Landlock.
gnoack:/tmp/xxx$ ls
foobar.txt
gnoack:/tmp/xxx$ landlock-restrict -rofiles /proc /usr /bin /etc/ -- /bin/cat foobar.txt
cat: foobar.txt: Permission denied
gnoack:/tmp/xxx$ landlock-restrict -rofiles /proc /usr /bin /etc/ -- /bin/cat nonexistent.txt
cat: nonexistent.txt: No such file or directory
gnoack:/tmp/xxx$ landlock-restrict -rofiles /proc /usr /bin /etc/ -- /bin/ls
ls: cannot open directory '.': Permission denied
–Günther
^ permalink raw reply
* Re: [RFC PATCH 0/5] landlock: Pathname-based UNIX connect() control
From: Günther Noack @ 2026-01-02 10:16 UTC (permalink / raw)
To: Demi Marie Obenour
Cc: Tingmao Wang, Mickaël Salaün, Paul Moore,
linux-security-module, Justin Suess, Samasth Norway Ananda,
Matthieu Buffet, Mikhail Ivanov, konstantin.meskhidze,
Alyssa Ross, Jann Horn, Tahera Fahimi
In-Reply-To: <1d36b2ee-b967-42d7-a6c2-e5b1602a512f@gmail.com>
On Thu, Jan 01, 2026 at 05:44:51PM -0500, Demi Marie Obenour wrote:
> On 1/1/26 17:34, Tingmao Wang wrote:
> > On 1/1/26 22:14, Demi Marie Obenour wrote:
> >> [...]
> >> Does this leave directory traversal as the only missing Landlock
> >> filesystem access control? Ideally Landlock could provide the same
> >> isolation from the filesystem that mount namespaces do.
> >
> > I think that level of isolation would require path walk control - see:
> > https://github.com/landlock-lsm/linux/issues/9
> >
> > (Landlock also doesn't currently control some metadata operations - see
> > the warning at the end of the "Filesystem flags" section in [1])
> >
> > [1]: https://docs.kernel.org/6.18/userspace-api/landlock.html#filesystem-flags
>
> Could this replace all of the existing hooks?
If you do not need to distinguish between the different operations
which Landlock offers access rights for, but you only want to limit
the visibility of directory hierarchies in the file system, then yes,
the path walk control described in issue 9 would be sufficient and a
more complete control.
The path walk control is probably among the more difficult Landlock
feature requests. A simple implementation would be easy to implement
technically, but it also requires a new LSM hook which will have to
get called *during* path lookup, and we'd have to make sure that the
performance impact stays in check. Path lookup is after all a very
central facility in a OS kernel.
Regarding the un-restrictable operations, Tingmao's pointers are
correct. In the warning box in the documentation, the missing
operations that I am aware of are (a) the Unix socket connect()
operation, and (b) the symlink lookup which happens implicitly during
path traversal and which Landlock and other LSMs can not control
through LSM hooks at the moment. (A symlink always gets implicitly
resolved during path lookup even when you do not have directory read
permissions on the directory where the symlink is.)
–Günther
^ permalink raw reply
* Re: [RFC PATCH 3/5] samples/landlock: Add support for LANDLOCK_ACCESS_FS_CONNECT_UNIX
From: Günther Noack @ 2026-01-02 9:53 UTC (permalink / raw)
To: Demi Marie Obenour
Cc: Justin Suess, Tingmao Wang, fahimitahera, hi, ivanov.mikhail1,
jannh, konstantin.meskhidze, linux-security-module, matthieu, mic,
paul, samasth.norway.ananda
In-Reply-To: <884e44c6-7695-49a2-8d60-c7e76d260bea@gmail.com>
On Thu, Jan 01, 2026 at 05:39:26PM -0500, Demi Marie Obenour wrote:
> On 1/1/26 17:38, Justin Suess wrote:
> > On 1/1/26 17:19, Tingmao Wang wrote:
> >> On 1/1/26 22:11, Demi Marie Obenour wrote:
> >>> On 1/1/26 17:07, Tingmao Wang wrote:
> >>>
> >>> (snip)
> >>>
> >>>> Looking at this I guess it might also make sense for the kernel side to
> >>>> enforce only being able to add LANDLOCK_ACCESS_FS_CONNECT_UNIX on socket
> >>>> files (S_ISSOCK(d_backing_inode)) too in landlock_append_fs_rule?
> >>>>
> >>>> Also, for the sandboxer logic, maybe a better way would be having
> >>>> LANDLOCK_ACCESS_FS_CONNECT_UNIX in ACCESS_FILE (matching the kernel code),
> >>>> then another if(!S_ISSOCK) below this that will clear out
> >>>> LANDLOCK_ACCESS_FS_CONNECT_UNIX if not socket.
> >>> A process might legitimately need to connect to a socket that doesn't
> >>> exist at the time it sandboxes itself. Therefore, I think it makes
> >>> sense to for LANDLOCK_ACCESS_FS_CONNECT_UNIX access to a directory
> >>> to allow LANDLOCK_ACCESS_FS_CONNECT_UNIX to any socket under that
> >>> directory. This matches the flexibility mount namespaces can achieve.
> >> Right, I forgot about the fact that we also need it on dirs, apologies.
> >>
> >> (But maybe it might still make sense to not allow this on files which are
> >> neither a socket or a dir? (If the file later gets removed and recreated
> >> as a socket, the rule would not apply retroactively anyway due to being
> >> tied to the inode.))
> > How do we handle IOCTL access on regular files? I think that landlock will let you put IOCTL rights on regular files even they are not valid for that operation.
>
> Regular files definitely support ioctls.
The LANDLOCK_ACCESS_FS_IOCTL_DEV right only applies to ioctl(2)
invocations on device files.
> > Sockets seem like a similar case where the operation is only valid for a subset of file types.
> >
> > I think we should mirror the existing behavior is for consistency.
> >
> > Besides, restricting which file types can have that right also makes it harder for applications that may not care about the specific file type, but now would have to check the filetype before making a policy on them (also opening them to TOCTOU).
>
> I agree.
I also agree with your interpretation, Justin.
For the record, Landlock's kernel implementation currently groups FS
access rights into two groups:
- file access rights
- directory-only rights
When adding a rule, the directory access rights can only be granted on
a directory inode. The file access rights can be granted on both a
directory inode and a regular file inode.
It is pointless to grant the CONNECT_UNIX (or IOCTL_DEV) right on a
file which is not a Unix socket (or device file). But it complicates
the userspace API if we introduce more special rules there. - Users of
Landlock would have to keep track of all these special cases and
mirror the logic, which is error prone. IMHO is is granular enough if
we differentiate between files and directories as we currently do.
For reference, this is documented at
https://docs.kernel.org/userspace-api/landlock.html#filesystem-flags
and the logic is implemented in landlock_append_fs_rule() in fs.c.
(Actually, in the implementation, the IOCTL_DEV right is treated the
same as one of the ACCESS_FILE rights - I should probably revise that
documentation: That right does not *directly* apply to a directory
inode, as directories are not device files. It only inherits down in
the file system hierarchy. Looking back at earlier versions of the
IOCTL_DEV patch set, it was different there. I think I missed to keep
the documentation in-line.)
–Günther
^ permalink raw reply
* Re: [RFC PATCH 0/1] lsm: Add hook unix_path_connect
From: Justin Suess @ 2026-01-01 23:40 UTC (permalink / raw)
To: Tingmao Wang
Cc: gnoack3000, gnoack, horms, jmorris, kuniyu, linux-security-module,
mic, netdev, paul, serge
In-Reply-To: <b992df90-92da-48bd-91d1-051af9670d07@maowtm.org>
On 1/1/26 18:11, Tingmao Wang wrote:
> On 1/1/26 19:45, Justin Suess wrote:
>> [...]
>> diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
>> index 55cdebfa0da0..397687e2d87f 100644
>> --- a/net/unix/af_unix.c
>> +++ b/net/unix/af_unix.c
>> @@ -1226,6 +1226,18 @@ static struct sock *unix_find_bsd(struct
>> sockaddr_un *sunaddr, int addr_len,
>> if (!S_ISSOCK(inode->i_mode))
>> goto path_put;
>>
>> + /*
>> + * We call the hook because we know that the inode is a socket
>> + * and we hold a valid reference to it via the path.
>> + * We intentionally forgo the ability to restrict SOCK_COREDUMP.
>> + */
>> + if (!(flags & SOCK_COREDUMP)) {
>> + err = security_unix_path_connect(&path);
>> + if (err)
>> + goto path_put;
>> + err = -ECONNREFUSED;
> I'm not sure if this is a good suggestion, but I think it might be cleaner
> to move this `err = -ECONNREFUSED;` out of the if, and do it
> unconditionally above the `sk = unix_find_socket_byinode(inode);` below?
> To me that makes the intention for resetting err clear (it is to ensure
> that a NULL return from unix_find_socket_byinode causes us to return
> -ECONNREFUSED).
>
I'll do that. That does make it more clear.
I suspect resetting the error accidentally was what caused the syzbot to rightfully complain.
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 55cdebfa0da0..2e0300121ab5 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1226,6 +1226,18 @@ static struct sock *unix_find_bsd(struct sockaddr_un *sunaddr, int addr_len,
if (!S_ISSOCK(inode->i_mode))
goto path_put;
+ /*
+ * We call the hook because we know that the inode is a socket
+ * and we hold a valid reference to it via the path.
+ * We intentionally forgo the ability to restrict SOCK_COREDUMP.
+ */
+ if (!(flags & SOCK_COREDUMP)) {
+ err = security_unix_path_connect(&path);
+ if (err)
+ goto path_put;
+ }
+ err = -ECONNREFUSED;
+
sk = unix_find_socket_byinode(inode);
if (!sk)
goto path_put;
^ permalink raw reply related
* Re: [RFC PATCH 0/1] lsm: Add hook unix_path_connect
From: Tingmao Wang @ 2026-01-01 23:11 UTC (permalink / raw)
To: Justin Suess
Cc: gnoack3000, gnoack, horms, jmorris, kuniyu, linux-security-module,
mic, netdev, paul, serge
In-Reply-To: <20260101194551.4017198-1-utilityemal77@gmail.com>
On 1/1/26 19:45, Justin Suess wrote:
> [...]
> diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
> index 55cdebfa0da0..397687e2d87f 100644
> --- a/net/unix/af_unix.c
> +++ b/net/unix/af_unix.c
> @@ -1226,6 +1226,18 @@ static struct sock *unix_find_bsd(struct
> sockaddr_un *sunaddr, int addr_len,
> if (!S_ISSOCK(inode->i_mode))
> goto path_put;
>
> + /*
> + * We call the hook because we know that the inode is a socket
> + * and we hold a valid reference to it via the path.
> + * We intentionally forgo the ability to restrict SOCK_COREDUMP.
> + */
> + if (!(flags & SOCK_COREDUMP)) {
> + err = security_unix_path_connect(&path);
> + if (err)
> + goto path_put;
> + err = -ECONNREFUSED;
I'm not sure if this is a good suggestion, but I think it might be cleaner
to move this `err = -ECONNREFUSED;` out of the if, and do it
unconditionally above the `sk = unix_find_socket_byinode(inode);` below?
To me that makes the intention for resetting err clear (it is to ensure
that a NULL return from unix_find_socket_byinode causes us to return
-ECONNREFUSED).
^ permalink raw reply
* Re: [RFC PATCH 0/5] landlock: Pathname-based UNIX connect() control
From: Demi Marie Obenour @ 2026-01-01 22:44 UTC (permalink / raw)
To: Tingmao Wang
Cc: Günther Noack, Mickaël Salaün, Paul Moore,
linux-security-module, Justin Suess, Samasth Norway Ananda,
Matthieu Buffet, Mikhail Ivanov, konstantin.meskhidze,
Alyssa Ross, Jann Horn, Tahera Fahimi
In-Reply-To: <73c5509a-5daa-4ea5-ab9f-e24a59786f6d@maowtm.org>
[-- Attachment #1.1.1: Type: text/plain, Size: 755 bytes --]
On 1/1/26 17:34, Tingmao Wang wrote:
> On 1/1/26 22:14, Demi Marie Obenour wrote:
>> [...]
>> Does this leave directory traversal as the only missing Landlock
>> filesystem access control? Ideally Landlock could provide the same
>> isolation from the filesystem that mount namespaces do.
>
> I think that level of isolation would require path walk control - see:
> https://github.com/landlock-lsm/linux/issues/9
>
> (Landlock also doesn't currently control some metadata operations - see
> the warning at the end of the "Filesystem flags" section in [1])
>
> [1]: https://docs.kernel.org/6.18/userspace-api/landlock.html#filesystem-flags
Could this replace all of the existing hooks?
--
Sincerely,
Demi Marie Obenour (she/her/hers)
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 7253 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox