diff mbox series

[v15,01/11] LSM: Identify modules by more than name

Message ID 20230912205658.3432-2-casey@schaufler-ca.com (mailing list archive)
State Accepted
Delegated to: Paul Moore
Headers show
Series LSM: Three basic syscalls | expand

Commit Message

Casey Schaufler Sept. 12, 2023, 8:56 p.m. UTC
Create a struct lsm_id to contain identifying information about Linux
Security Modules (LSMs). At inception this contains the name of the
module and an identifier associated with the security module.  Change
the security_add_hooks() interface to use this structure.  Change the
individual modules to maintain their own struct lsm_id and pass it to
security_add_hooks().

The values are for LSM identifiers are defined in a new UAPI
header file linux/lsm.h. Each existing LSM has been updated to
include it's LSMID in the lsm_id.

The LSM ID values are sequential, with the oldest module
LSM_ID_CAPABILITY being the lowest value and the existing modules
numbered in the order they were included in the main line kernel.
This is an arbitrary convention for assigning the values, but
none better presents itself. The value 0 is defined as being invalid.
The values 1-99 are reserved for any special case uses which may
arise in the future. This may include attributes of the LSM
infrastructure itself, possibly related to namespacing or network
attribute management. A special range is identified for such attributes
to help reduce confusion for developers unfamiliar with LSMs.

LSM attribute values are defined for the attributes presented by
modules that are available today. As with the LSM IDs, The value 0
is defined as being invalid. The values 1-99 are reserved for any
special case uses which may arise in the future.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Cc: linux-security-module <linux-security-module@vger.kernel.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Reviewed-by: Mickael Salaun <mic@digikod.net>
Reviewed-by: John Johansen <john.johansen@canonical.com>
---
 Documentation/userspace-api/index.rst |  1 +
 MAINTAINERS                           |  1 +
 include/linux/lsm_hooks.h             | 16 +++++++-
 include/uapi/linux/lsm.h              | 54 +++++++++++++++++++++++++++
 security/apparmor/lsm.c               |  8 +++-
 security/bpf/hooks.c                  |  9 ++++-
 security/commoncap.c                  |  8 +++-
 security/landlock/cred.c              |  2 +-
 security/landlock/fs.c                |  2 +-
 security/landlock/ptrace.c            |  2 +-
 security/landlock/setup.c             |  6 +++
 security/landlock/setup.h             |  1 +
 security/loadpin/loadpin.c            |  9 ++++-
 security/lockdown/lockdown.c          |  8 +++-
 security/safesetid/lsm.c              |  9 ++++-
 security/security.c                   | 12 +++---
 security/selinux/hooks.c              |  9 ++++-
 security/smack/smack_lsm.c            |  8 +++-
 security/tomoyo/tomoyo.c              |  9 ++++-
 security/yama/yama_lsm.c              |  8 +++-
 20 files changed, 161 insertions(+), 21 deletions(-)
 create mode 100644 include/uapi/linux/lsm.h

Comments

Tetsuo Handa Sept. 15, 2023, 11:32 a.m. UTC | #1
On 2023/09/13 5:56, Casey Schaufler wrote:
> Create a struct lsm_id to contain identifying information about Linux
> Security Modules (LSMs). At inception this contains the name of the
> module and an identifier associated with the security module.  Change
> the security_add_hooks() interface to use this structure.  Change the
> individual modules to maintain their own struct lsm_id and pass it to
> security_add_hooks().
> 
> The values are for LSM identifiers are defined in a new UAPI
> header file linux/lsm.h. Each existing LSM has been updated to
> include it's LSMID in the lsm_id.
> 
> The LSM ID values are sequential, with the oldest module
> LSM_ID_CAPABILITY being the lowest value and the existing modules
> numbered in the order they were included in the main line kernel.
> This is an arbitrary convention for assigning the values, but
> none better presents itself. The value 0 is defined as being invalid.
> The values 1-99 are reserved for any special case uses which may
> arise in the future. This may include attributes of the LSM
> infrastructure itself, possibly related to namespacing or network
> attribute management. A special range is identified for such attributes
> to help reduce confusion for developers unfamiliar with LSMs.
> 
> LSM attribute values are defined for the attributes presented by
> modules that are available today. As with the LSM IDs, The value 0
> is defined as being invalid. The values 1-99 are reserved for any
> special case uses which may arise in the future.
> 
> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> Cc: linux-security-module <linux-security-module@vger.kernel.org>
> Reviewed-by: Kees Cook <keescook@chromium.org>
> Reviewed-by: Serge Hallyn <serge@hallyn.com>
> Reviewed-by: Mickael Salaun <mic@digikod.net>
> Reviewed-by: John Johansen <john.johansen@canonical.com>

Nacked-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>

https://lkml.kernel.org/r/4a6b6e2c-9872-4d4c-e42e-4ff0fb79f3ae@I-love.SAKURA.ne.jp
Casey Schaufler Sept. 15, 2023, 5:53 p.m. UTC | #2
On 9/15/2023 4:32 AM, Tetsuo Handa wrote:
> On 2023/09/13 5:56, Casey Schaufler wrote:
>> Create a struct lsm_id to contain identifying information about Linux
>> Security Modules (LSMs). At inception this contains the name of the
>> module and an identifier associated with the security module.  Change
>> the security_add_hooks() interface to use this structure.  Change the
>> individual modules to maintain their own struct lsm_id and pass it to
>> security_add_hooks().
>>
>> The values are for LSM identifiers are defined in a new UAPI
>> header file linux/lsm.h. Each existing LSM has been updated to
>> include it's LSMID in the lsm_id.
>>
>> The LSM ID values are sequential, with the oldest module
>> LSM_ID_CAPABILITY being the lowest value and the existing modules
>> numbered in the order they were included in the main line kernel.
>> This is an arbitrary convention for assigning the values, but
>> none better presents itself. The value 0 is defined as being invalid.
>> The values 1-99 are reserved for any special case uses which may
>> arise in the future. This may include attributes of the LSM
>> infrastructure itself, possibly related to namespacing or network
>> attribute management. A special range is identified for such attributes
>> to help reduce confusion for developers unfamiliar with LSMs.
>>
>> LSM attribute values are defined for the attributes presented by
>> modules that are available today. As with the LSM IDs, The value 0
>> is defined as being invalid. The values 1-99 are reserved for any
>> special case uses which may arise in the future.
>>
>> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
>> Cc: linux-security-module <linux-security-module@vger.kernel.org>
>> Reviewed-by: Kees Cook <keescook@chromium.org>
>> Reviewed-by: Serge Hallyn <serge@hallyn.com>
>> Reviewed-by: Mickael Salaun <mic@digikod.net>
>> Reviewed-by: John Johansen <john.johansen@canonical.com>
> Nacked-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>

I *could* respond with:

-#define LSM_ID_TOMOYO	103

but I won't. I won't make a difference because TOMOYO doesn't present
any attributes. I understand your objections, but don't believe that
they can't be worked around. The argument that a LSM ID will prevent
new LSM development is rebuffed by the exact same situation with system
calls, PRCTL and IOCTL values. The argument that it somehow prevents
out-of-tree modules falls on deaf ears. The argument that it prevents
dynamic security modules is subsumed by the other issues surrounding
dynamic security modules, and does nothing to decrease the likelihood
of that facility going upstream. Especially since, to the best of my
knowledge, no one is working on it.


> https://lkml.kernel.org/r/4a6b6e2c-9872-4d4c-e42e-4ff0fb79f3ae@I-love.SAKURA.ne.jp
>
Tetsuo Handa Sept. 16, 2023, 6:32 a.m. UTC | #3
On 2023/09/16 2:53, Casey Schaufler wrote:
> I *could* respond with:
> 
> -#define LSM_ID_TOMOYO	103
> 
> but I won't. I won't make a difference because TOMOYO doesn't present
> any attributes. I understand your objections, but don't believe that
> they can't be worked around. The argument that a LSM ID will prevent
> new LSM development is rebuffed by the exact same situation with system
> calls, PRCTL and IOCTL values. The argument that it somehow prevents
> out-of-tree modules falls on deaf ears. The argument that it prevents
> dynamic security modules is subsumed by the other issues surrounding
> dynamic security modules, and does nothing to decrease the likelihood
> of that facility going upstream. Especially since, to the best of my
> knowledge, no one is working on it.

+/**
+ * struct lsm_id - Identify a Linux Security Module.
+ * @lsm: name of the LSM, must be approved by the LSM maintainers

Why can't you understand that "approved by the LSM maintainers" is a horrible
requirement for LSM modules which cannot become one of in-tree LSMs?

One of reasons for not every proposed LSM module can become in-tree is out of
the LSM community's resources for reviewing/maintaining (or failure to acquire
attention from the LSM community enough to get reviewed).

+ * @id: LSM ID number from uapi/linux/lsm.h

Since the LSM community cannot accept all of proposed LSMs due to limited resources,
the LSM community is responsible for allowing whatever proposed LSMs (effectively any
publicly available LSMs) to live as out-of-tree LSMs, by approving the LSM name and
assigning a permanent LSM ID number.

The only exception the LSM community can refuse to approve/assign would be that the name
is not appropriate (e.g. a LSM module named "FuckYou") or the name is misleading (e.g.
"selinux+", "smock", "tomato", "apparmour"). Otherwise, no matter how many times you repeat
"we don't care out-of-tree LSMs" or "I do not intentionally plan to make life difficult for
the out-of-tree LSMs", this patch is intended to lock out out-of-tree LSMs.

+ *
+ * Contains the information that identifies the LSM.
+ */
+struct lsm_id {
+	const char	*name;
+	u64		id;
+};

Therefore, unless you change the policy for assigning LSM ID, I keep NACK on this change.
Casey Schaufler Sept. 17, 2023, 4:38 p.m. UTC | #4
On 9/15/2023 11:32 PM, Tetsuo Handa wrote:
> On 2023/09/16 2:53, Casey Schaufler wrote:
>> I *could* respond with:
>>
>> -#define LSM_ID_TOMOYO	103
>>
>> but I won't. I won't make a difference because TOMOYO doesn't present
>> any attributes. I understand your objections, but don't believe that
>> they can't be worked around. The argument that a LSM ID will prevent
>> new LSM development is rebuffed by the exact same situation with system
>> calls, PRCTL and IOCTL values. The argument that it somehow prevents
>> out-of-tree modules falls on deaf ears. The argument that it prevents
>> dynamic security modules is subsumed by the other issues surrounding
>> dynamic security modules, and does nothing to decrease the likelihood
>> of that facility going upstream. Especially since, to the best of my
>> knowledge, no one is working on it.
> +/**
> + * struct lsm_id - Identify a Linux Security Module.
> + * @lsm: name of the LSM, must be approved by the LSM maintainers
>
> Why can't you understand that "approved by the LSM maintainers" is a horrible
> requirement for LSM modules which cannot become one of in-tree LSMs?
>
> One of reasons for not every proposed LSM module can become in-tree is out of
> the LSM community's resources for reviewing/maintaining (or failure to acquire
> attention from the LSM community enough to get reviewed).
>
> + * @id: LSM ID number from uapi/linux/lsm.h
>
> Since the LSM community cannot accept all of proposed LSMs due to limited resources,
> the LSM community is responsible for allowing whatever proposed LSMs (effectively any
> publicly available LSMs) to live as out-of-tree LSMs, by approving the LSM name and
> assigning a permanent LSM ID number.
>
> The only exception the LSM community can refuse to approve/assign would be that the name
> is not appropriate (e.g. a LSM module named "FuckYou") or the name is misleading (e.g.
> "selinux+", "smock", "tomato", "apparmour"). Otherwise, no matter how many times you repeat
> "we don't care out-of-tree LSMs" or "I do not intentionally plan to make life difficult for
> the out-of-tree LSMs", this patch is intended to lock out out-of-tree LSMs.

That is a false statement. There is a huge difference between apathy and malice. 

>
> + *
> + * Contains the information that identifies the LSM.
> + */
> +struct lsm_id {
> +	const char	*name;
> +	u64		id;
> +};
>
> Therefore, unless you change the policy for assigning LSM ID, I keep NACK on this change.
>
Tetsuo Handa Sept. 20, 2023, 10:20 a.m. UTC | #5
On 2023/09/18 1:38, Casey Schaufler wrote:
> On 9/15/2023 11:32 PM, Tetsuo Handa wrote:
>> +/**
>> + * struct lsm_id - Identify a Linux Security Module.
>> + * @lsm: name of the LSM, must be approved by the LSM maintainers
>>
>> Why can't you understand that "approved by the LSM maintainers" is a horrible
>> requirement for LSM modules which cannot become one of in-tree LSMs?
>>
>> One of reasons for not every proposed LSM module can become in-tree is out of
>> the LSM community's resources for reviewing/maintaining (or failure to acquire
>> attention from the LSM community enough to get reviewed).
>>
>> + * @id: LSM ID number from uapi/linux/lsm.h
>>
>> Since the LSM community cannot accept all of proposed LSMs due to limited resources,
>> the LSM community is responsible for allowing whatever proposed LSMs (effectively any
>> publicly available LSMs) to live as out-of-tree LSMs, by approving the LSM name and
>> assigning a permanent LSM ID number.
>>
>> The only exception the LSM community can refuse to approve/assign would be that the name
>> is not appropriate (e.g. a LSM module named "FuckYou") or the name is misleading (e.g.
>> "selinux+", "smock", "tomato", "apparmour"). Otherwise, no matter how many times you repeat
>> "we don't care out-of-tree LSMs" or "I do not intentionally plan to make life difficult for
>> the out-of-tree LSMs", this patch is intended to lock out out-of-tree LSMs.
> 
> That is a false statement. There is a huge difference between apathy and malice. 

Dave Chinner wrote at https://lkml.kernel.org/r/ZQo94mCzV7hOrVkh@dread.disaster.area
as a response to "We don't care about out of tree filesystems.":

  In this case, we most certainly do care. Downstream distros support
  all sorts of out of tree filesystems loaded via kernel modules, so a
  syscall that is used to uniquely identify a filesystem type to
  userspace *must* have a mechanism for the filesystem to provide that
  unique identifier to userspace.

  Fundamentally, the kernel does not and should not dictate what
  filesystem types it supports; the user decides what filesystem they
  need to use, and it is the kernel's job to provide infrastructure
  that works with that user's choice.

Can you see? What you are trying to is NACKed by simple s/filesystem/LSM/g .

The kernel is ultimately there for users. The kernel is never there for doing patent
acquisition competition. If the LSM community accepts only LSMs which won the patent
acquisition competition as in-tree (as described in "ANN: new LSM guidelines"),
the LSM community is responsible for allowing any publicly available LSMs to live as
out of tree modules.

Unless the policy is updated to approve any publicly available LSMs and assign a unique
identifier (which can be passed to the syscalls introduced by this series) to each
publicly available LSM, this series is a regression.

The "[PATCH v15 01/11] LSM: Identify modules by more than name" is exactly doing
"LSM: allow only in-tree LSM modules, lock out out-of-tree LSM modules".
Nack, Nack, Nack, Nack, Nack!!!!!

> 
>>
>> + *
>> + * Contains the information that identifies the LSM.
>> + */
>> +struct lsm_id {
>> +	const char	*name;
>> +	u64		id;
>> +};
>>
>> Therefore, unless you change the policy for assigning LSM ID, I keep NACK on this change.
>>
Kees Cook Sept. 20, 2023, 3:08 p.m. UTC | #6
On Wed, Sep 20, 2023 at 07:20:35PM +0900, Tetsuo Handa wrote:
> On 2023/09/18 1:38, Casey Schaufler wrote:
> > On 9/15/2023 11:32 PM, Tetsuo Handa wrote:
> >> +/**
> >> + * struct lsm_id - Identify a Linux Security Module.
> >> + * @lsm: name of the LSM, must be approved by the LSM maintainers
> >>
> >> Why can't you understand that "approved by the LSM maintainers" is a horrible
> >> requirement for LSM modules which cannot become one of in-tree LSMs?
> >>
> >> One of reasons for not every proposed LSM module can become in-tree is out of
> >> the LSM community's resources for reviewing/maintaining (or failure to acquire
> >> attention from the LSM community enough to get reviewed).
> >>
> >> + * @id: LSM ID number from uapi/linux/lsm.h
> >>
> >> Since the LSM community cannot accept all of proposed LSMs due to limited resources,
> >> the LSM community is responsible for allowing whatever proposed LSMs (effectively any
> >> publicly available LSMs) to live as out-of-tree LSMs, by approving the LSM name and
> >> assigning a permanent LSM ID number.
> >>
> >> The only exception the LSM community can refuse to approve/assign would be that the name
> >> is not appropriate (e.g. a LSM module named "FuckYou") or the name is misleading (e.g.
> >> "selinux+", "smock", "tomato", "apparmour"). Otherwise, no matter how many times you repeat
> >> "we don't care out-of-tree LSMs" or "I do not intentionally plan to make life difficult for
> >> the out-of-tree LSMs", this patch is intended to lock out out-of-tree LSMs.
> > 
> > That is a false statement. There is a huge difference between apathy and malice. 
> 
> Dave Chinner wrote at https://lkml.kernel.org/r/ZQo94mCzV7hOrVkh@dread.disaster.area
> as a response to "We don't care about out of tree filesystems.":
> 
>   In this case, we most certainly do care. Downstream distros support
>   all sorts of out of tree filesystems loaded via kernel modules, so a
>   syscall that is used to uniquely identify a filesystem type to
>   userspace *must* have a mechanism for the filesystem to provide that
>   unique identifier to userspace.
> 
>   Fundamentally, the kernel does not and should not dictate what
>   filesystem types it supports; the user decides what filesystem they
>   need to use, and it is the kernel's job to provide infrastructure
>   that works with that user's choice.
> 
> Can you see? What you are trying to is NACKed by simple s/filesystem/LSM/g .
> 
> The kernel is ultimately there for users. The kernel is never there for doing patent
> acquisition competition. If the LSM community accepts only LSMs which won the patent
> acquisition competition as in-tree (as described in "ANN: new LSM guidelines"),
> the LSM community is responsible for allowing any publicly available LSMs to live as
> out of tree modules.
> 
> Unless the policy is updated to approve any publicly available LSMs and assign a unique
> identifier (which can be passed to the syscalls introduced by this series) to each
> publicly available LSM, this series is a regression.
> 
> The "[PATCH v15 01/11] LSM: Identify modules by more than name" is exactly doing
> "LSM: allow only in-tree LSM modules, lock out out-of-tree LSM modules".
> Nack, Nack, Nack, Nack, Nack!!!!!

I feel like you are willfully not listening to us when we say that this
doesn't block out of tree LSMs. Again, there is nothing here that stops
it. To prove this point, here is an out of tree LSM that works with this
series. So let's move from theoretical to practical: given this example,
why do you think out of tree LSMs are blocked?


From a6f50cb719aac2452506babda07657f9f6961a95 Mon Sep 17 00:00:00 2001
From: Kees Cook <keescook@chromium.org>
Date: Wed, 20 Sep 2023 08:00:31 -0700
Subject: [PATCH] security: Add GOAT LSM

This will never go upstream, but it still works with the new LSM
syscalls.

Cc: Paul Moore <paul@paul-moore.com>
Cc: James Morris <jmorris@namei.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: linux-security-module@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/uapi/linux/lsm.h |  2 ++
 security/Kconfig         |  1 +
 security/Makefile        |  1 +
 security/goat/Kconfig    |  9 +++++++
 security/goat/Makefile   |  2 ++
 security/goat/goat.c     | 51 ++++++++++++++++++++++++++++++++++++++++
 6 files changed, 66 insertions(+)
 create mode 100644 security/goat/Kconfig
 create mode 100644 security/goat/Makefile
 create mode 100644 security/goat/goat.c

diff --git a/include/uapi/linux/lsm.h b/include/uapi/linux/lsm.h
index eeda59a77c02..23b7a8f79cef 100644
--- a/include/uapi/linux/lsm.h
+++ b/include/uapi/linux/lsm.h
@@ -63,6 +63,8 @@ struct lsm_ctx {
 #define LSM_ID_BPF		110
 #define LSM_ID_LANDLOCK		111
 
+#define LSM_ID_GOAT		1138
+
 /*
  * LSM_ATTR_XXX definitions identify different LSM attributes
  * which are used in the kernel's LSM userspace API. Support
diff --git a/security/Kconfig b/security/Kconfig
index 52c9af08ad35..0c692913a1a6 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -194,6 +194,7 @@ source "security/yama/Kconfig"
 source "security/safesetid/Kconfig"
 source "security/lockdown/Kconfig"
 source "security/landlock/Kconfig"
+source "security/goat/Kconfig"
 
 source "security/integrity/Kconfig"
 
diff --git a/security/Makefile b/security/Makefile
index 59f238490665..1d260f994fac 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_SECURITY_LOCKDOWN_LSM)	+= lockdown/
 obj-$(CONFIG_CGROUPS)			+= device_cgroup.o
 obj-$(CONFIG_BPF_LSM)			+= bpf/
 obj-$(CONFIG_SECURITY_LANDLOCK)		+= landlock/
+obj-$(CONFIG_SECURITY_GOAT)		+= goat/
 
 # Object integrity file lists
 obj-$(CONFIG_INTEGRITY)			+= integrity/
diff --git a/security/goat/Kconfig b/security/goat/Kconfig
new file mode 100644
index 000000000000..dd25848e3204
--- /dev/null
+++ b/security/goat/Kconfig
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config SECURITY_GOAT
+	bool "Greatest Of All Time security features"
+	depends on SECURITY
+	help
+	  This LSM provides the greatest security features of all
+	  time.
+
+	  If in doubt, choose "Heck yeah".
diff --git a/security/goat/Makefile b/security/goat/Makefile
new file mode 100644
index 000000000000..e673c913f66f
--- /dev/null
+++ b/security/goat/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_SECURITY_GOAT) += goat.o
diff --git a/security/goat/goat.c b/security/goat/goat.c
new file mode 100644
index 000000000000..f1eee60c9217
--- /dev/null
+++ b/security/goat/goat.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Greatest Linux Security Module Of All Time
+ *
+ * Author: Kees Cook <keescook@chromium.org>
+ */
+
+#define pr_fmt(fmt) "GOAT: " fmt
+
+#include <linux/module.h>
+#include <linux/lsm_hooks.h>
+#include <uapi/linux/lsm.h>
+
+const struct lsm_id goat_lsmid = {
+	.name = "goat",
+	.id = LSM_ID_GOAT,
+};
+
+static int goat_read_file(struct file *file, enum kernel_read_file_id id,
+			  bool contents)
+{
+	pr_info("universally allowing file read\n");
+	return 0;
+}
+
+static int goat_load_data(enum kernel_load_data_id id, bool contents)
+{
+	pr_info("No blobs allowed!\n");
+	return -EUCLEAN;
+}
+
+static struct security_hook_list goat_hooks[] __ro_after_init = {
+	LSM_HOOK_INIT(kernel_read_file, goat_read_file),
+	LSM_HOOK_INIT(kernel_load_data, goat_load_data),
+};
+
+static int __init goat_init(void)
+{
+	pr_info("GOAT loading: Bleeeaaaeeeeggh\n");
+
+	security_add_hooks(goat_hooks, ARRAY_SIZE(goat_hooks), &goat_lsmid);
+
+	return 0;
+}
+
+DEFINE_LSM(goat) = {
+	.name = "goat",
+	.init = goat_init,
+};
Tetsuo Handa Sept. 23, 2023, 4:46 a.m. UTC | #7
On 2023/09/21 0:08, Kees Cook wrote:
> I feel like you are willfully not listening to us when we say that this
> doesn't block out of tree LSMs. Again, there is nothing here that stops
> it. To prove this point, here is an out of tree LSM that works with this
> series. So let's move from theoretical to practical: given this example,
> why do you think out of tree LSMs are blocked?

Because an LSM ID value

> diff --git a/include/uapi/linux/lsm.h b/include/uapi/linux/lsm.h
> index eeda59a77c02..23b7a8f79cef 100644
> --- a/include/uapi/linux/lsm.h
> +++ b/include/uapi/linux/lsm.h
> @@ -63,6 +63,8 @@ struct lsm_ctx {
>  #define LSM_ID_BPF		110
>  #define LSM_ID_LANDLOCK		111
>  
> +#define LSM_ID_GOAT		1138
> +
>  /*
>   * LSM_ATTR_XXX definitions identify different LSM attributes
>   * which are used in the kernel's LSM userspace API. Support

is assigned to LSM only when that LSM became no longer out of tree.

I'm against the policy that only LSM modules that succeeded to become
in-tree are assigned LSM ID. That's not a good usage of identifier.

Quoting from https://lkml.kernel.org/r/4a6b6e2c-9872-4d4c-e42e-4ff0fb79f3ae@I-love.SAKURA.ne.jp :

  The sane and the better usage of LSM ID is to register any publicly available
  LSMs. If LSM ID serves as an index for what LSMs are available in the world,
  by maintaining "the LSM module name, the LSM ID value, short description about
  that LSM module, the public git repository or web site for more information
  about that LSM module" pairs, people can easily find what LSMs could be used
  for their purpose, and developers can avoid re-inventing similar LSM modules
  which are already available somewhere in the world (and optionally helps
  avoiding module name collisions with any publicly available LSMs).

You must not say "We don't care about out of tree LSMs." when talking about this patch.
Kees Cook Sept. 24, 2023, 1:58 a.m. UTC | #8
On Sat, Sep 23, 2023 at 01:46:35PM +0900, Tetsuo Handa wrote:
> On 2023/09/21 0:08, Kees Cook wrote:
> > I feel like you are willfully not listening to us when we say that this
> > doesn't block out of tree LSMs. Again, there is nothing here that stops
> > it. To prove this point, here is an out of tree LSM that works with this
> > series. So let's move from theoretical to practical: given this example,
> > why do you think out of tree LSMs are blocked?
> 
> Because an LSM ID value

But my example includes one.

> > diff --git a/include/uapi/linux/lsm.h b/include/uapi/linux/lsm.h
> > index eeda59a77c02..23b7a8f79cef 100644
> > --- a/include/uapi/linux/lsm.h
> > +++ b/include/uapi/linux/lsm.h
> > @@ -63,6 +63,8 @@ struct lsm_ctx {
> >  #define LSM_ID_BPF		110
> >  #define LSM_ID_LANDLOCK		111
> >  
> > +#define LSM_ID_GOAT		1138
> > +
> >  /*
> >   * LSM_ATTR_XXX definitions identify different LSM attributes
> >   * which are used in the kernel's LSM userspace API. Support
> 
> is assigned to LSM only when that LSM became no longer out of tree.

Why? My example code will work just fine. The only possible reason
it could be awkward would be if an out of tree LSM became so useful
that the author decided to upstream it, and risked colliding with an
existing LSM id. But lsm_id::id is a u64 (not an enum!), so there is
a HUGE space available. If out of tree LSMs used the epoch time they
were first authored as their id, the chances of a collision would be
approaching zero. There isn't an out of tree LSM written every second,
but if there were, it would take 584 billion years to run out of LSM ids.

And, as mentioned several times before, this is _not a new problem_, and
exists for out of tree syscalls, out of tree prctls, etc. I even DID
this for the Yama LSM when it looked like it wasn't going to get
upstream in the early days. Its prctl number _is not sequential_:

include/uapi/linux/prctl.h:#define PR_SET_PTRACER 0x59616d61

(And you'll see 0x59616d61 in ASCII is "Yama"; my effort to avoid
collision.)

So, there is both ability (u64) and precedent (Yama) for this. Having an
LSM id is _not_ a blocker for out of tree LSMs, and I've given the proof.

-Kees
Tetsuo Handa Sept. 24, 2023, 11:06 a.m. UTC | #9
Patch description says

  The LSM ID values are sequential, with the oldest module
  LSM_ID_CAPABILITY being the lowest value and the existing modules
  numbered in the order they were included in the main line kernel.
  This is an arbitrary convention for assigning the values, but
  none better presents itself. The value 0 is defined as being invalid.

and your non-sequential assignment

> But lsm_id::id is a u64 (not an enum!), so there is a HUGE space available.

violated it. include/uapi/linux/lsm.h is a userspace API file, where
we can't change this value after once defined.

You withdraw your "Reviewed-by" response unless "The LSM ID values are sequential"
and "must be approved by the LSM maintainers" are removed and "the LSM maintainers/community
shall never complain about what names and/or values are assigned" is added, don't you?

Quoting from https://lkml.kernel.org/r/4a6b6e2c-9872-4d4c-e42e-4ff0fb79f3ae@I-love.SAKURA.ne.jp :

  You are intentionally making life difficult for the out-of-tree LSMs, by
  requiring an LSM ID (and facilitating LSM ID collisions). No matter how
  priority of out-of-tree LSMs is low for you, what you are about to merge
  goes against the "developers try to avoid identifier collisions" effort.

  Introducing a numeric identifier is a good opportunity for permanently
  eliminating possibility of identifier collisions. But current usage of this
  numeric identifier is designed for facilitating possibility of identifier
  collisions.

Keeping how the HUGE space is used under control of the LSM community will be
better for both in-tree and out-of-tree LSM modules. I really can't understand
why you don't want to utilize this opportunity.
Kees Cook Sept. 24, 2023, 7:48 p.m. UTC | #10
On September 24, 2023 4:06:07 AM PDT, Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> wrote:
>Patch description says
>
>  The LSM ID values are sequential, with the oldest module
>  LSM_ID_CAPABILITY being the lowest value and the existing modules
>  numbered in the order they were included in the main line kernel.
>  This is an arbitrary convention for assigning the values, but
>  none better presents itself. The value 0 is defined as being invalid.

"in the order they were included in the main line kernel" Out of trees aren't in main line.

And "This is an arbitrary convention" specifically says it's arbitrary.

There is literally nothing here stopping out of tree modules. I have proven this, and so have you with these quotes. What is left to object to?

>You withdraw your "Reviewed-by" response unless "The LSM ID values are sequential"
>and "must be approved by the LSM maintainers" are removed and "the LSM maintainers/community
>shall never complain about what names and/or values are assigned" is added, don't you?

*For main line kernels*

Please, understand both the *intent* and *reality*: this does not block out of tree LSMs, full stop.

>Keeping how the HUGE space is used under control of the LSM community will be
>better for both in-tree and out-of-tree LSM modules. I really can't understand
>why you don't want to utilize this opportunity.

I cannot understand what else you need to hear.

-Kees
Tetsuo Handa Oct. 5, 2023, 12:58 p.m. UTC | #11
On 2023/09/13 5:56, Casey Schaufler wrote:
> Create a struct lsm_id to contain identifying information about Linux
> Security Modules (LSMs). At inception this contains the name of the
> module and an identifier associated with the security module.  Change
> the security_add_hooks() interface to use this structure.  Change the
> individual modules to maintain their own struct lsm_id and pass it to
> security_add_hooks().

I came to worry about what purpose does the LSM ID value (or more precisely,
"struct lsm_id") is used for. If the LSM ID value is used for only switch
{reading,writing} /proc/self/attr/ of specific LSM module's information, only
LSM modules that use /proc/self/attr/ will need the LSM ID value.

But this series uses "struct lsm_id" as one of arguments for security_add_hooks(),
and might be reused for different purposes.

Then, BPF-based LSMs (which are not considered as in-tree LSM modules, for
only BPF hook is considered as in-tree LSM module) might receive unfavorable
treatment than non BPF-based LSMs? 

[PATCH v15 05/11] says

  Create a system call to report the list of Linux Security Modules
  that are active on the system. The list is provided as an array
  of LSM ID numbers.
  
  The calling application can use this list determine what LSM
  specific actions it might take. That might include choosing an
  output format, determining required privilege or bypassing
  security module specific behavior.

but, at least, name of BPF-based LSMs won't be shown up in lsm_list_modules()
compared to non BPF-based LSMs? Then, the calling application can't use this
list determine what BPF-based LSM specific actions it might take?
Casey Schaufler Oct. 20, 2023, 7:52 p.m. UTC | #12
On 10/5/2023 5:58 AM, Tetsuo Handa wrote:
> On 2023/09/13 5:56, Casey Schaufler wrote:
>> Create a struct lsm_id to contain identifying information about Linux
>> Security Modules (LSMs). At inception this contains the name of the
>> module and an identifier associated with the security module.  Change
>> the security_add_hooks() interface to use this structure.  Change the
>> individual modules to maintain their own struct lsm_id and pass it to
>> security_add_hooks().
> I came to worry about what purpose does the LSM ID value (or more precisely,
> "struct lsm_id") is used for. If the LSM ID value is used for only switch
> {reading,writing} /proc/self/attr/ of specific LSM module's information, only
> LSM modules that use /proc/self/attr/ will need the LSM ID value.
>
> But this series uses "struct lsm_id" as one of arguments for security_add_hooks(),
> and might be reused for different purposes.
>
> Then, BPF-based LSMs (which are not considered as in-tree LSM modules, for
> only BPF hook is considered as in-tree LSM module) might receive unfavorable
> treatment than non BPF-based LSMs? 
>
> [PATCH v15 05/11] says
>
>   Create a system call to report the list of Linux Security Modules
>   that are active on the system. The list is provided as an array
>   of LSM ID numbers.
>   
>   The calling application can use this list determine what LSM
>   specific actions it might take. That might include choosing an
>   output format, determining required privilege or bypassing
>   security module specific behavior.
>
> but, at least, name of BPF-based LSMs won't be shown up in lsm_list_modules()
> compared to non BPF-based LSMs? Then, the calling application can't use this
> list determine what BPF-based LSM specific actions it might take?

That is correct. Just as knowing that your system is using SELinux won't
tell you whether a specific action might be permitted because that's driven
by the loaded policy, so too knowing that your system is using BPF won't
tell you whether a specific action might be permitted because that's driven
by the eBPF programs in place.

I wish we could stop people from saying "BPF-based LSM". BPF is the LSM. The
eBPF programs that implement a "policy" are NOT a LSM. There needs to be a
name for that, but LSM  is  not  it.
Tetsuo Handa Oct. 21, 2023, 12:20 p.m. UTC | #13
On 2023/10/21 4:52, Casey Schaufler wrote:
> On 10/5/2023 5:58 AM, Tetsuo Handa wrote:
>> On 2023/09/13 5:56, Casey Schaufler wrote:
>>> Create a struct lsm_id to contain identifying information about Linux
>>> Security Modules (LSMs). At inception this contains the name of the
>>> module and an identifier associated with the security module.  Change
>>> the security_add_hooks() interface to use this structure.  Change the
>>> individual modules to maintain their own struct lsm_id and pass it to
>>> security_add_hooks().
>> I came to worry about what purpose does the LSM ID value (or more precisely,
>> "struct lsm_id") is used for. If the LSM ID value is used for only switch
>> {reading,writing} /proc/self/attr/ of specific LSM module's information, only
>> LSM modules that use /proc/self/attr/ will need the LSM ID value.
>>
>> But this series uses "struct lsm_id" as one of arguments for security_add_hooks(),
>> and might be reused for different purposes.
>>
>> Then, BPF-based LSMs (which are not considered as in-tree LSM modules, for
>> only BPF hook is considered as in-tree LSM module) might receive unfavorable
>> treatment than non BPF-based LSMs? 
>>
>> [PATCH v15 05/11] says
>>
>>   Create a system call to report the list of Linux Security Modules
>>   that are active on the system. The list is provided as an array
>>   of LSM ID numbers.
>>   
>>   The calling application can use this list determine what LSM
>>   specific actions it might take. That might include choosing an
>>   output format, determining required privilege or bypassing
>>   security module specific behavior.
>>
>> but, at least, name of BPF-based LSMs won't be shown up in lsm_list_modules()
>> compared to non BPF-based LSMs? Then, the calling application can't use this
>> list determine what BPF-based LSM specific actions it might take?
> 
> That is correct. Just as knowing that your system is using SELinux won't
> tell you whether a specific action might be permitted because that's driven
> by the loaded policy, so too knowing that your system is using BPF won't
> tell you whether a specific action might be permitted because that's driven
> by the eBPF programs in place.

If the system call returning LSM ID value for SELinux but does not tell
the caller of that system call whether a specific action might be permitted,
what information does LSM ID value tell?

The patch description lacks relationship between LSM ID value and data.
In other words, why LSM ID values are needed (and are useful for doing what).
If the only information the caller can know from the LSM ID value were
what LSMs are enabled (i.e. the content of /sys/kernel/security/lsm ), why
bother to use LSM ID values? (Yes, integer comparison is faster than string
comparison. But that is not enough justification for not allowing out-of-tree
LSMs and eBPF-based access control mechanisms to have stable LSM ID values.)

What does "choosing an output format", "determining required privilege",
"bypassing security module specific behavior" mean? How can they choose
meaningful output format, determine appropriate privilege, bypass security
module specific behavior (if the only information the caller can know from
the LSM ID value were what LSMs are enabled) ?



> I wish we could stop people from saying "BPF-based LSM". BPF is the LSM. The
> eBPF programs that implement a "policy" are NOT a LSM. There needs to be a
> name for that, but LSM  is  not  it.

My understanding is that "BPF is not an LSM module but infrastructure for using
LSM hooks".

Say, an access control implementation consists of two parts; "code" and "data".
The "code" is written by developers and is determined at compile time and is
interpreted by CPU, and the "data" is written by administrators and is interpreted
by "code". The "data" part can be either built-in (determined at compile time) or
loadable (configurable at run-time).

eBPF-based access control implementations (which can be loaded via bpf() system
call after boot) consists of "code" and "data". BPF will remain no-op unless
eBPF-based access control implementations are loaded via bpf() system call.
Thus, I believe that an eBPF-based access control implementation should be
considered as an LSM module (like SELinux etc.)
Casey Schaufler Oct. 21, 2023, 2:11 p.m. UTC | #14
On 10/21/2023 5:20 AM, Tetsuo Handa wrote:
> On 2023/10/21 4:52, Casey Schaufler wrote:
>> On 10/5/2023 5:58 AM, Tetsuo Handa wrote:
>>> On 2023/09/13 5:56, Casey Schaufler wrote:
>>>> Create a struct lsm_id to contain identifying information about Linux
>>>> Security Modules (LSMs). At inception this contains the name of the
>>>> module and an identifier associated with the security module.  Change
>>>> the security_add_hooks() interface to use this structure.  Change the
>>>> individual modules to maintain their own struct lsm_id and pass it to
>>>> security_add_hooks().
>>> I came to worry about what purpose does the LSM ID value (or more precisely,
>>> "struct lsm_id") is used for. If the LSM ID value is used for only switch
>>> {reading,writing} /proc/self/attr/ of specific LSM module's information, only
>>> LSM modules that use /proc/self/attr/ will need the LSM ID value.
>>>
>>> But this series uses "struct lsm_id" as one of arguments for security_add_hooks(),
>>> and might be reused for different purposes.
>>>
>>> Then, BPF-based LSMs (which are not considered as in-tree LSM modules, for
>>> only BPF hook is considered as in-tree LSM module) might receive unfavorable
>>> treatment than non BPF-based LSMs? 
>>>
>>> [PATCH v15 05/11] says
>>>
>>>   Create a system call to report the list of Linux Security Modules
>>>   that are active on the system. The list is provided as an array
>>>   of LSM ID numbers.
>>>   
>>>   The calling application can use this list determine what LSM
>>>   specific actions it might take. That might include choosing an
>>>   output format, determining required privilege or bypassing
>>>   security module specific behavior.
>>>
>>> but, at least, name of BPF-based LSMs won't be shown up in lsm_list_modules()
>>> compared to non BPF-based LSMs? Then, the calling application can't use this
>>> list determine what BPF-based LSM specific actions it might take?
>> That is correct. Just as knowing that your system is using SELinux won't
>> tell you whether a specific action might be permitted because that's driven
>> by the loaded policy, so too knowing that your system is using BPF won't
>> tell you whether a specific action might be permitted because that's driven
>> by the eBPF programs in place.
> If the system call returning LSM ID value for SELinux but does not tell
> the caller of that system call whether a specific action might be permitted,
> what information does LSM ID value tell?

It tells the caller that the LSM is active on the system. That's it.
Just like reading /sys/kernel/security/lsm.

>
> The patch description lacks relationship between LSM ID value and data.
> In other words, why LSM ID values are needed (and are useful for doing what).
> If the only information the caller can know from the LSM ID value were
> what LSMs are enabled (i.e. the content of /sys/kernel/security/lsm ), why
> bother to use LSM ID values? (Yes, integer comparison is faster than string
> comparison. But that is not enough justification for not allowing out-of-tree
> LSMs and eBPF-based access control mechanisms to have stable LSM ID values.)
>
> What does "choosing an output format", "determining required privilege",
> "bypassing security module specific behavior" mean? How can they choose
> meaningful output format, determine appropriate privilege, bypass security
> module specific behavior (if the only information the caller can know from
> the LSM ID value were what LSMs are enabled) ?

If Smack and SELinux not enabled on the system there is no point in
setting up a netlabel configuration, for example.

>> I wish we could stop people from saying "BPF-based LSM". BPF is the LSM. The
>> eBPF programs that implement a "policy" are NOT a LSM. There needs to be a
>> name for that, but LSM  is  not  it.
> My understanding is that "BPF is not an LSM module but infrastructure for using
> LSM hooks".

As BPF is implemented as a LSM I suggest your statement is incorrect.

> Say, an access control implementation consists of two parts; "code" and "data".
> The "code" is written by developers and is determined at compile time and is
> interpreted by CPU, and the "data" is written by administrators and is interpreted
> by "code". The "data" part can be either built-in (determined at compile time) or
> loadable (configurable at run-time).
>
> eBPF-based access control implementations (which can be loaded via bpf() system
> call after boot) consists of "code" and "data". BPF will remain no-op unless
> eBPF-based access control implementations are loaded via bpf() system call.
> Thus, I believe that an eBPF-based access control implementation should be
> considered as an LSM module (like SELinux etc.)

And I say you're wrong. Your arguments are gibberish.

https://www.youtube.com/watch?v=-7cUnID7vFs
Tetsuo Handa Oct. 29, 2023, 10:57 a.m. UTC | #15
On 2023/10/21 23:11, Casey Schaufler wrote:
>> If the system call returning LSM ID value for SELinux but does not tell
>> the caller of that system call whether a specific action might be permitted,
>> what information does LSM ID value tell?
> 
> It tells the caller that the LSM is active on the system. That's it.
> Just like reading /sys/kernel/security/lsm.

Then, the

  The calling application can use this list determine what LSM
  specific actions it might take. That might include choosing an
  output format, determining required privilege or bypassing
  security module specific behavior.

part should be removed from the description. Instead, the description should
emphasis that the numeric LSM ID values are there in order to allow
identifying what LSM modules are active without interpreting string LSM names
in /sys/kernel/security/lsm .



>> What does "choosing an output format", "determining required privilege",
>> "bypassing security module specific behavior" mean? How can they choose
>> meaningful output format, determine appropriate privilege, bypass security
>> module specific behavior (if the only information the caller can know from
>> the LSM ID value were what LSMs are enabled) ?
> 
> If Smack and SELinux not enabled on the system there is no point in
> setting up a netlabel configuration, for example.

I know nothing about netlabel. But can userspace make such assumption from
this granularity? For example, if TOMOYO and AppArmor start supporting
netlabel configuration, your assumption

  If Smack and SELinux not enabled on the system there is no point in
  setting up a netlabel configuration

becomes no longer true. It is also possible that a new LSM implementation
obtains an LSM ID for that LSM, and starts supporting netlabel configuration
some timer later. I don't know if we come to the point where we can enable
SELinux and Smack at the same time. But when it becomes possible to enable
SELinux and Smack at the same time, the userspace might have already written
code based on current situation that netlabel configuration are exclusive. Then,
someday starting to return both LSM ID for SELinux and LSM ID for Smack might
confuse userspace.

Thus, it might be safe to determine what LSMs are active from the LSM ID values
returned from the system call. But it is not safe to assume what functionality
is active (e.g. netlabel configuration is interpreted) from the LSM ID values
returned from the system call.

If you want to allow userspace to make such assumption using the system call,
the granularity the system call returns needs to be what access control mechanism
(not only LSM modules but also eBPF-based access control mechanisms) hooks which
LSM hooks. More information than interpreting string LSM names in 
/sys/kernel/security/lsm will be needed.

> 
>>> I wish we could stop people from saying "BPF-based LSM". BPF is the LSM. The
>>> eBPF programs that implement a "policy" are NOT a LSM. There needs to be a
>>> name for that, but LSM  is  not  it.
>> My understanding is that "BPF is not an LSM module but infrastructure for using
>> LSM hooks".
> 
> As BPF is implemented as a LSM I suggest your statement is incorrect.

Enumerating only LSM modules are not useful. "ID for access control mechanisms
that can be controlled via LSM hooks" will be needed.

> 
>>
>> The patch description lacks relationship between LSM ID value and data.
>> In other words, why LSM ID values are needed (and are useful for doing what).
>> If the only information the caller can know from the LSM ID value were
>> what LSMs are enabled (i.e. the content of /sys/kernel/security/lsm ), why
>> bother to use LSM ID values? (Yes, integer comparison is faster than string
>> comparison. But that is not enough justification for not allowing out-of-tree
>> LSMs and eBPF-based access control mechanisms to have stable LSM ID values.)
>>

I conclude that LSM ID values are pointless and are NOT needed.
Casey Schaufler Oct. 29, 2023, 6 p.m. UTC | #16
On 10/29/2023 3:57 AM, Tetsuo Handa wrote:
> On 2023/10/21 23:11, Casey Schaufler wrote:
>>> If the system call returning LSM ID value for SELinux but does not tell
>>> the caller of that system call whether a specific action might be permitted,
>>> what information does LSM ID value tell?
>> It tells the caller that the LSM is active on the system. That's it.
>> Just like reading /sys/kernel/security/lsm.
> Then, the
>
>   The calling application can use this list determine what LSM
>   specific actions it might take. That might include choosing an
>   output format, determining required privilege or bypassing
>   security module specific behavior.
>
> part should be removed from the description. Instead, the description should
> emphasis that the numeric LSM ID values are there in order to allow
> identifying what LSM modules are active without interpreting string LSM names
> in /sys/kernel/security/lsm .

No, I stand by the description as written.

>>> What does "choosing an output format", "determining required privilege",
>>> "bypassing security module specific behavior" mean? How can they choose
>>> meaningful output format, determine appropriate privilege, bypass security
>>> module specific behavior (if the only information the caller can know from
>>> the LSM ID value were what LSMs are enabled) ?
>> If Smack and SELinux not enabled on the system there is no point in
>> setting up a netlabel configuration, for example.
> I know nothing about netlabel. But can userspace make such assumption from
> this granularity? For example, if TOMOYO and AppArmor start supporting
> netlabel configuration, your assumption
>
>   If Smack and SELinux not enabled on the system there is no point in
>   setting up a netlabel configuration
>
> becomes no longer true.

You are correct. If I thought there was the remotest possibility
of that, I wouldn't have used it as an example.

If Smack isn't enabled there's no point in running the Smack testsuite.
If SELinux isn't enabled there's no point in running the SELinux testsuite.
If SELinux isn't enabled there's no reason to invoke SELinux userspace features.

>  It is also possible that a new LSM implementation
> obtains an LSM ID for that LSM, and starts supporting netlabel configuration
> some timer later. I don't know if we come to the point where we can enable
> SELinux and Smack at the same time. But when it becomes possible to enable
> SELinux and Smack at the same time, the userspace might have already written
> code based on current situation that netlabel configuration are exclusive. Then,
> someday starting to return both LSM ID for SELinux and LSM ID for Smack might
> confuse userspace.

Believe me, that's way down on the list of userspace issues with using Smack and
SELinux together in a meaningful way.

>
> Thus, it might be safe to determine what LSMs are active from the LSM ID values
> returned from the system call. But it is not safe to assume what functionality
> is active (e.g. netlabel configuration is interpreted) from the LSM ID values
> returned from the system call.

That is correct.

> If you want to allow userspace to make such assumption using the system call,
> the granularity the system call returns needs to be what access control mechanism
> (not only LSM modules but also eBPF-based access control mechanisms) hooks which
> LSM hooks. More information than interpreting string LSM names in 
> /sys/kernel/security/lsm will be needed.

That's already true. You have to understand all sorts of factors, like SELinux policy,
Smack rule sets and AppArmor policy definitions. Then there's netfilter configuration.


>>>> I wish we could stop people from saying "BPF-based LSM". BPF is the LSM. The
>>>> eBPF programs that implement a "policy" are NOT a LSM. There needs to be a
>>>> name for that, but LSM  is  not  it.
>>> My understanding is that "BPF is not an LSM module but infrastructure for using
>>> LSM hooks".
>> As BPF is implemented as a LSM I suggest your statement is incorrect.
> Enumerating only LSM modules are not useful. "ID for access control mechanisms
> that can be controlled via LSM hooks" will be needed.

The BPF program set is no different from the SELinux policy in this regard.
It's completely user defined, and out of the kernel's control. I seriously
doubt that you want an ID for "SELinux reference policy 4.3.2 with Infiniband"



>>> The patch description lacks relationship between LSM ID value and data.
>>> In other words, why LSM ID values are needed (and are useful for doing what).
>>> If the only information the caller can know from the LSM ID value were
>>> what LSMs are enabled (i.e. the content of /sys/kernel/security/lsm ), why
>>> bother to use LSM ID values? (Yes, integer comparison is faster than string
>>> comparison. But that is not enough justification for not allowing out-of-tree
>>> LSMs and eBPF-based access control mechanisms to have stable LSM ID values.)
>>>
> I conclude that LSM ID values are pointless and are NOT needed.

OK.
diff mbox series

Patch

diff --git a/Documentation/userspace-api/index.rst b/Documentation/userspace-api/index.rst
index 72a65db0c498..b5fa29c077eb 100644
--- a/Documentation/userspace-api/index.rst
+++ b/Documentation/userspace-api/index.rst
@@ -32,6 +32,7 @@  place where this information is gathered.
    sysfs-platform_profile
    vduse
    futex2
+   lsm
 
 .. only::  subproject and html
 
diff --git a/MAINTAINERS b/MAINTAINERS
index 90f13281d297..935334123b04 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19307,6 +19307,7 @@  L:	linux-security-module@vger.kernel.org (suggested Cc:)
 S:	Supported
 W:	http://kernsec.org/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm.git
+F:	include/uapi/linux/lsm.h
 F:	security/
 X:	security/selinux/
 
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index dcb5e5b5eb13..7f0adb33caaa 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -42,6 +42,18 @@  struct security_hook_heads {
 	#undef LSM_HOOK
 } __randomize_layout;
 
+/**
+ * struct lsm_id - Identify a Linux Security Module.
+ * @lsm: name of the LSM, must be approved by the LSM maintainers
+ * @id: LSM ID number from uapi/linux/lsm.h
+ *
+ * Contains the information that identifies the LSM.
+ */
+struct lsm_id {
+	const char	*name;
+	u64		id;
+};
+
 /*
  * Security module hook list structure.
  * For use with generic list macros for common operations.
@@ -50,7 +62,7 @@  struct security_hook_list {
 	struct hlist_node		list;
 	struct hlist_head		*head;
 	union security_list_options	hook;
-	const char			*lsm;
+	const struct lsm_id		*lsmid;
 } __randomize_layout;
 
 /*
@@ -104,7 +116,7 @@  extern struct security_hook_heads security_hook_heads;
 extern char *lsm_names;
 
 extern void security_add_hooks(struct security_hook_list *hooks, int count,
-				const char *lsm);
+			       const struct lsm_id *lsmid);
 
 #define LSM_FLAG_LEGACY_MAJOR	BIT(0)
 #define LSM_FLAG_EXCLUSIVE	BIT(1)
diff --git a/include/uapi/linux/lsm.h b/include/uapi/linux/lsm.h
new file mode 100644
index 000000000000..f27c9a9cc376
--- /dev/null
+++ b/include/uapi/linux/lsm.h
@@ -0,0 +1,54 @@ 
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Linux Security Modules (LSM) - User space API
+ *
+ * Copyright (C) 2022 Casey Schaufler <casey@schaufler-ca.com>
+ * Copyright (C) 2022 Intel Corporation
+ */
+
+#ifndef _UAPI_LINUX_LSM_H
+#define _UAPI_LINUX_LSM_H
+
+/*
+ * ID tokens to identify Linux Security Modules (LSMs)
+ *
+ * These token values are used to uniquely identify specific LSMs
+ * in the kernel as well as in the kernel's LSM userspace API.
+ *
+ * A value of zero/0 is considered undefined and should not be used
+ * outside the kernel. Values 1-99 are reserved for potential
+ * future use.
+ */
+#define LSM_ID_UNDEF		0
+#define LSM_ID_CAPABILITY	100
+#define LSM_ID_SELINUX		101
+#define LSM_ID_SMACK		102
+#define LSM_ID_TOMOYO		103
+#define LSM_ID_IMA		104
+#define LSM_ID_APPARMOR		105
+#define LSM_ID_YAMA		106
+#define LSM_ID_LOADPIN		107
+#define LSM_ID_SAFESETID	108
+#define LSM_ID_LOCKDOWN		109
+#define LSM_ID_BPF		110
+#define LSM_ID_LANDLOCK		111
+
+/*
+ * LSM_ATTR_XXX definitions identify different LSM attributes
+ * which are used in the kernel's LSM userspace API. Support
+ * for these attributes vary across the different LSMs. None
+ * are required.
+ *
+ * A value of zero/0 is considered undefined and should not be used
+ * outside the kernel. Values 1-99 are reserved for potential
+ * future use.
+ */
+#define LSM_ATTR_UNDEF		0
+#define LSM_ATTR_CURRENT	100
+#define LSM_ATTR_EXEC		101
+#define LSM_ATTR_FSCREATE	102
+#define LSM_ATTR_KEYCREATE	103
+#define LSM_ATTR_PREV		104
+#define LSM_ATTR_SOCKCREATE	105
+
+#endif /* _UAPI_LINUX_LSM_H */
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 108eccc5ada5..20b93501fbd1 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -24,6 +24,7 @@ 
 #include <linux/zstd.h>
 #include <net/sock.h>
 #include <uapi/linux/mount.h>
+#include <uapi/linux/lsm.h>
 
 #include "include/apparmor.h"
 #include "include/apparmorfs.h"
@@ -1215,6 +1216,11 @@  struct lsm_blob_sizes apparmor_blob_sizes __ro_after_init = {
 	.lbs_task = sizeof(struct aa_task_ctx),
 };
 
+const struct lsm_id apparmor_lsmid = {
+	.name = "apparmor",
+	.id = LSM_ID_APPARMOR,
+};
+
 static struct security_hook_list apparmor_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
 	LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
@@ -1904,7 +1910,7 @@  static int __init apparmor_init(void)
 		goto buffers_out;
 	}
 	security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks),
-				"apparmor");
+				&apparmor_lsmid);
 
 	/* Report that AppArmor successfully initialized */
 	apparmor_initialized = 1;
diff --git a/security/bpf/hooks.c b/security/bpf/hooks.c
index cfaf1d0e6a5f..91011e0c361a 100644
--- a/security/bpf/hooks.c
+++ b/security/bpf/hooks.c
@@ -5,6 +5,7 @@ 
  */
 #include <linux/lsm_hooks.h>
 #include <linux/bpf_lsm.h>
+#include <uapi/linux/lsm.h>
 
 static struct security_hook_list bpf_lsm_hooks[] __ro_after_init = {
 	#define LSM_HOOK(RET, DEFAULT, NAME, ...) \
@@ -15,9 +16,15 @@  static struct security_hook_list bpf_lsm_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(task_free, bpf_task_storage_free),
 };
 
+const struct lsm_id bpf_lsmid = {
+	.name = "bpf",
+	.id = LSM_ID_BPF,
+};
+
 static int __init bpf_lsm_init(void)
 {
-	security_add_hooks(bpf_lsm_hooks, ARRAY_SIZE(bpf_lsm_hooks), "bpf");
+	security_add_hooks(bpf_lsm_hooks, ARRAY_SIZE(bpf_lsm_hooks),
+			   &bpf_lsmid);
 	pr_info("LSM support for eBPF active\n");
 	return 0;
 }
diff --git a/security/commoncap.c b/security/commoncap.c
index bc0521104197..9aaad2c3e54a 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -25,6 +25,7 @@ 
 #include <linux/binfmts.h>
 #include <linux/personality.h>
 #include <linux/mnt_idmapping.h>
+#include <uapi/linux/lsm.h>
 
 /*
  * If a non-root user executes a setuid-root binary in
@@ -1440,6 +1441,11 @@  int cap_mmap_file(struct file *file, unsigned long reqprot,
 
 #ifdef CONFIG_SECURITY
 
+const struct lsm_id capability_lsmid = {
+	.name = "capability",
+	.id = LSM_ID_CAPABILITY,
+};
+
 static struct security_hook_list capability_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(capable, cap_capable),
 	LSM_HOOK_INIT(settime, cap_settime),
@@ -1464,7 +1470,7 @@  static struct security_hook_list capability_hooks[] __ro_after_init = {
 static int __init capability_init(void)
 {
 	security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks),
-				"capability");
+			   &capability_lsmid);
 	return 0;
 }
 
diff --git a/security/landlock/cred.c b/security/landlock/cred.c
index 13dff2a31545..786af18c4a1c 100644
--- a/security/landlock/cred.c
+++ b/security/landlock/cred.c
@@ -42,5 +42,5 @@  static struct security_hook_list landlock_hooks[] __ro_after_init = {
 __init void landlock_add_cred_hooks(void)
 {
 	security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
-			   LANDLOCK_NAME);
+			   &landlock_lsmid);
 }
diff --git a/security/landlock/fs.c b/security/landlock/fs.c
index 1c0c198f6fdb..db5ebecfbf02 100644
--- a/security/landlock/fs.c
+++ b/security/landlock/fs.c
@@ -1307,5 +1307,5 @@  static struct security_hook_list landlock_hooks[] __ro_after_init = {
 __init void landlock_add_fs_hooks(void)
 {
 	security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
-			   LANDLOCK_NAME);
+			   &landlock_lsmid);
 }
diff --git a/security/landlock/ptrace.c b/security/landlock/ptrace.c
index 8a06d6c492bf..2bfc533d36e4 100644
--- a/security/landlock/ptrace.c
+++ b/security/landlock/ptrace.c
@@ -116,5 +116,5 @@  static struct security_hook_list landlock_hooks[] __ro_after_init = {
 __init void landlock_add_ptrace_hooks(void)
 {
 	security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
-			   LANDLOCK_NAME);
+			   &landlock_lsmid);
 }
diff --git a/security/landlock/setup.c b/security/landlock/setup.c
index 0f6113528fa4..aab13750edde 100644
--- a/security/landlock/setup.c
+++ b/security/landlock/setup.c
@@ -8,6 +8,7 @@ 
 
 #include <linux/init.h>
 #include <linux/lsm_hooks.h>
+#include <uapi/linux/lsm.h>
 
 #include "common.h"
 #include "cred.h"
@@ -24,6 +25,11 @@  struct lsm_blob_sizes landlock_blob_sizes __ro_after_init = {
 	.lbs_superblock = sizeof(struct landlock_superblock_security),
 };
 
+const struct lsm_id landlock_lsmid = {
+	.name = LANDLOCK_NAME,
+	.id = LSM_ID_LANDLOCK,
+};
+
 static int __init landlock_init(void)
 {
 	landlock_add_cred_hooks();
diff --git a/security/landlock/setup.h b/security/landlock/setup.h
index 1daffab1ab4b..c4252d46d49d 100644
--- a/security/landlock/setup.h
+++ b/security/landlock/setup.h
@@ -14,5 +14,6 @@ 
 extern bool landlock_initialized;
 
 extern struct lsm_blob_sizes landlock_blob_sizes;
+extern const struct lsm_id landlock_lsmid;
 
 #endif /* _SECURITY_LANDLOCK_SETUP_H */
diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
index a9d40456a064..d682a851de58 100644
--- a/security/loadpin/loadpin.c
+++ b/security/loadpin/loadpin.c
@@ -20,6 +20,7 @@ 
 #include <linux/string_helpers.h>
 #include <linux/dm-verity-loadpin.h>
 #include <uapi/linux/loadpin.h>
+#include <uapi/linux/lsm.h>
 
 #define VERITY_DIGEST_FILE_HEADER "# LOADPIN_TRUSTED_VERITY_ROOT_DIGESTS"
 
@@ -208,6 +209,11 @@  static int loadpin_load_data(enum kernel_load_data_id id, bool contents)
 	return loadpin_check(NULL, (enum kernel_read_file_id) id);
 }
 
+const struct lsm_id loadpin_lsmid = {
+	.name = "loadpin",
+	.id = LSM_ID_LOADPIN,
+};
+
 static struct security_hook_list loadpin_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
 	LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
@@ -259,7 +265,8 @@  static int __init loadpin_init(void)
 	if (!register_sysctl("kernel/loadpin", loadpin_sysctl_table))
 		pr_notice("sysctl registration failed!\n");
 #endif
-	security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin");
+	security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks),
+			   &loadpin_lsmid);
 
 	return 0;
 }
diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
index 68d19632aeb7..cd84d8ea1dfb 100644
--- a/security/lockdown/lockdown.c
+++ b/security/lockdown/lockdown.c
@@ -13,6 +13,7 @@ 
 #include <linux/security.h>
 #include <linux/export.h>
 #include <linux/lsm_hooks.h>
+#include <uapi/linux/lsm.h>
 
 static enum lockdown_reason kernel_locked_down;
 
@@ -75,6 +76,11 @@  static struct security_hook_list lockdown_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(locked_down, lockdown_is_locked_down),
 };
 
+const struct lsm_id lockdown_lsmid = {
+	.name = "lockdown",
+	.id = LSM_ID_LOCKDOWN,
+};
+
 static int __init lockdown_lsm_init(void)
 {
 #if defined(CONFIG_LOCK_DOWN_KERNEL_FORCE_INTEGRITY)
@@ -83,7 +89,7 @@  static int __init lockdown_lsm_init(void)
 	lock_kernel_down("Kernel configuration", LOCKDOWN_CONFIDENTIALITY_MAX);
 #endif
 	security_add_hooks(lockdown_hooks, ARRAY_SIZE(lockdown_hooks),
-			   "lockdown");
+			   &lockdown_lsmid);
 	return 0;
 }
 
diff --git a/security/safesetid/lsm.c b/security/safesetid/lsm.c
index 5be5894aa0ea..f42d5af5ffb0 100644
--- a/security/safesetid/lsm.c
+++ b/security/safesetid/lsm.c
@@ -19,6 +19,7 @@ 
 #include <linux/ptrace.h>
 #include <linux/sched/task_stack.h>
 #include <linux/security.h>
+#include <uapi/linux/lsm.h>
 #include "lsm.h"
 
 /* Flag indicating whether initialization completed */
@@ -261,6 +262,11 @@  static int safesetid_task_fix_setgroups(struct cred *new, const struct cred *old
 	return 0;
 }
 
+const struct lsm_id safesetid_lsmid = {
+	.name = "safesetid",
+	.id = LSM_ID_SAFESETID,
+};
+
 static struct security_hook_list safesetid_security_hooks[] = {
 	LSM_HOOK_INIT(task_fix_setuid, safesetid_task_fix_setuid),
 	LSM_HOOK_INIT(task_fix_setgid, safesetid_task_fix_setgid),
@@ -271,7 +277,8 @@  static struct security_hook_list safesetid_security_hooks[] = {
 static int __init safesetid_security_init(void)
 {
 	security_add_hooks(safesetid_security_hooks,
-			   ARRAY_SIZE(safesetid_security_hooks), "safesetid");
+			   ARRAY_SIZE(safesetid_security_hooks),
+			   &safesetid_lsmid);
 
 	/* Report that SafeSetID successfully initialized */
 	safesetid_initialized = 1;
diff --git a/security/security.c b/security/security.c
index 23b129d482a7..ea69e83936fc 100644
--- a/security/security.c
+++ b/security/security.c
@@ -513,17 +513,17 @@  static int lsm_append(const char *new, char **result)
  * security_add_hooks - Add a modules hooks to the hook lists.
  * @hooks: the hooks to add
  * @count: the number of hooks to add
- * @lsm: the name of the security module
+ * @lsmid: the identification information for the security module
  *
  * Each LSM has to register its hooks with the infrastructure.
  */
 void __init security_add_hooks(struct security_hook_list *hooks, int count,
-			       const char *lsm)
+			       const struct lsm_id *lsmid)
 {
 	int i;
 
 	for (i = 0; i < count; i++) {
-		hooks[i].lsm = lsm;
+		hooks[i].lsmid = lsmid;
 		hlist_add_tail_rcu(&hooks[i].list, hooks[i].head);
 	}
 
@@ -532,7 +532,7 @@  void __init security_add_hooks(struct security_hook_list *hooks, int count,
 	 * and fix this up afterwards.
 	 */
 	if (slab_is_available()) {
-		if (lsm_append(lsm, &lsm_names) < 0)
+		if (lsm_append(lsmid->name, &lsm_names) < 0)
 			panic("%s - Cannot get early memory.\n", __func__);
 	}
 }
@@ -3817,7 +3817,7 @@  int security_getprocattr(struct task_struct *p, const char *lsm,
 	struct security_hook_list *hp;
 
 	hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) {
-		if (lsm != NULL && strcmp(lsm, hp->lsm))
+		if (lsm != NULL && strcmp(lsm, hp->lsmid->name))
 			continue;
 		return hp->hook.getprocattr(p, name, value);
 	}
@@ -3842,7 +3842,7 @@  int security_setprocattr(const char *lsm, const char *name, void *value,
 	struct security_hook_list *hp;
 
 	hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) {
-		if (lsm != NULL && strcmp(lsm, hp->lsm))
+		if (lsm != NULL && strcmp(lsm, hp->lsmid->name))
 			continue;
 		return hp->hook.setprocattr(name, value, size);
 	}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 10350534de6d..3ad500dff390 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -92,6 +92,7 @@ 
 #include <linux/fsnotify.h>
 #include <linux/fanotify.h>
 #include <linux/io_uring.h>
+#include <uapi/linux/lsm.h>
 
 #include "avc.h"
 #include "objsec.h"
@@ -6944,6 +6945,11 @@  static int selinux_uring_cmd(struct io_uring_cmd *ioucmd)
 }
 #endif /* CONFIG_IO_URING */
 
+const struct lsm_id selinux_lsmid = {
+	.name = "selinux",
+	.id = LSM_ID_SELINUX,
+};
+
 /*
  * IMPORTANT NOTE: When adding new hooks, please be careful to keep this order:
  * 1. any hooks that don't belong to (2.) or (3.) below,
@@ -7264,7 +7270,8 @@  static __init int selinux_init(void)
 
 	hashtab_cache_init();
 
-	security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");
+	security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks),
+			   &selinux_lsmid);
 
 	if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
 		panic("SELinux: Unable to register AVC netcache callback\n");
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 65130a791f57..f73f9a2834eb 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -43,6 +43,7 @@ 
 #include <linux/fs_parser.h>
 #include <linux/watch_queue.h>
 #include <linux/io_uring.h>
+#include <uapi/linux/lsm.h>
 #include "smack.h"
 
 #define TRANS_TRUE	"TRUE"
@@ -4933,6 +4934,11 @@  struct lsm_blob_sizes smack_blob_sizes __ro_after_init = {
 	.lbs_xattr_count = SMACK_INODE_INIT_XATTRS,
 };
 
+const struct lsm_id smack_lsmid = {
+	.name = "smack",
+	.id = LSM_ID_SMACK,
+};
+
 static struct security_hook_list smack_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
 	LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
@@ -5140,7 +5146,7 @@  static __init int smack_init(void)
 	/*
 	 * Register with LSM
 	 */
-	security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), "smack");
+	security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), &smack_lsmid);
 	smack_enabled = 1;
 
 	pr_info("Smack:  Initializing.\n");
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 25006fddc964..556f8daecb07 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -6,6 +6,7 @@ 
  */
 
 #include <linux/lsm_hooks.h>
+#include <uapi/linux/lsm.h>
 #include "common.h"
 
 /**
@@ -542,6 +543,11 @@  static void tomoyo_task_free(struct task_struct *task)
 	}
 }
 
+const struct lsm_id tomoyo_lsmid = {
+	.name = "tomoyo",
+	.id = LSM_ID_TOMOYO,
+};
+
 /*
  * tomoyo_security_ops is a "struct security_operations" which is used for
  * registering TOMOYO.
@@ -595,7 +601,8 @@  static int __init tomoyo_init(void)
 	struct tomoyo_task *s = tomoyo_task(current);
 
 	/* register ourselves with the security framework */
-	security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo");
+	security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks),
+			   &tomoyo_lsmid);
 	pr_info("TOMOYO Linux initialized\n");
 	s->domain_info = &tomoyo_kernel_domain;
 	atomic_inc(&tomoyo_kernel_domain.users);
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
index 2503cf153d4a..5cdff292fcae 100644
--- a/security/yama/yama_lsm.c
+++ b/security/yama/yama_lsm.c
@@ -18,6 +18,7 @@ 
 #include <linux/task_work.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
+#include <uapi/linux/lsm.h>
 
 #define YAMA_SCOPE_DISABLED	0
 #define YAMA_SCOPE_RELATIONAL	1
@@ -421,6 +422,11 @@  static int yama_ptrace_traceme(struct task_struct *parent)
 	return rc;
 }
 
+const struct lsm_id yama_lsmid = {
+	.name = "yama",
+	.id = LSM_ID_YAMA,
+};
+
 static struct security_hook_list yama_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check),
 	LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme),
@@ -471,7 +477,7 @@  static inline void yama_init_sysctl(void) { }
 static int __init yama_init(void)
 {
 	pr_info("Yama: becoming mindful.\n");
-	security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), "yama");
+	security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), &yama_lsmid);
 	yama_init_sysctl();
 	return 0;
 }