2023-02-22 20:09:08

by Casey Schaufler

[permalink] [raw]
Subject: [PATCH v6 00/11] LSM: Three basic syscalls

Add three system calls for the Linux Security Module ABI.

lsm_get_self_attr() provides the security module specific attributes
that have previously been visible in the /proc/self/attr directory.
For each security module that uses the specified attribute on the
current process the system call will return an LSM identifier and
the value of the attribute. The LSM and attribute identifier values
are defined in include/uapi/linux/lsm.h

LSM identifiers are simple integers and reflect the order in which
the LSM was added to the mainline kernel. This is a convention, not
a promise of the API. LSM identifiers below the value of 100 are
reserved for unspecified future uses. That could include information
about the security infrastructure itself, or about how multiple LSMs
might interact with each other.

A new LSM hook security_getselfattr() is introduced to get the
required information from the security modules. This is similar
to the existing security_getprocattr() hook, but specifies the
format in which string data is returned and requires the module
to put the information into a userspace destination.

lsm_set_self_attr() changes the specified LSM attribute. Only one
attribute can be changed at a time, and then only if the specified
security module allows the change.

A new LSM hook security_setselfattr() is introduced to set the
required information in the security modules. This is similar
to the existing security_setprocattr() hook, but specifies the
format in which string data is presented and requires the module
to get the information from a userspace destination.

lsm_module_list() provides the LSM identifiers, in order, of the
security modules that are active on the system. This has been
available in the securityfs file /sys/kernel/security/lsm.

Patch 0001 changes the LSM registration from passing the name
of the module to passing a lsm_id structure that contains the
name of the module, an LSM identifier number and an attribute
identifier.
Patch 0002 adds the registered lsm_ids to a table.
Patch 0003 changes security_[gs]etprocattr() to use LSM IDs instead
of LSM names.
Patch 0004 implements lsm_get_self_attr() and lsm_set_self_attr().
New LSM hooks security_getselfattr() and security_setselfattr() are
defined.
Patch 0005 implements lsm_module_list().
Patch 0006 wires up the syscalls.
Patch 0007 implements helper functions to make it easier for
security modules to use lsm_ctx structures.
Patch 0008 provides the Smack implementation for [gs]etselfattr().
Patch 0009 provides the AppArmor implementation for [gs]etselfattr().
Patch 0010 provides the SELinux implementation for [gs]etselfattr().
Patch 0011 implements selftests for the three new syscalls.

https://github.com/cschaufler/lsm-stacking.git#lsm-syscalls-6.2-rc8-v6

v6: Switch from reusing security_[gs]procattr() to using new
security_[gs]selfattr() hooks. Use explicit sized data types
in the lsm_ctx structure.

v5: Correct syscall parameter data types.

v4: Restore "reserved" LSM ID values. Add explaination.
Squash patches that introduce fields in lsm_id.
Correct a wireup error.

v3: Add lsm_set_self_attr().
Rename lsm_self_attr() to lsm_get_self_attr().
Provide the values only for a specifed attribute in
lsm_get_self_attr().
Add selftests for the three new syscalls.
Correct some parameter checking.

v2: Use user-interface safe data types.
Remove "reserved" LSM ID values.
Improve kerneldoc comments
Include copyright dates
Use more descriptive name for LSM counter
Add documentation
Correct wireup errors

Casey Schaufler (11):
LSM: Identify modules by more than name
LSM: Maintain a table of LSM attribute data
proc: Use lsmids instead of lsm names for attrs
LSM: syscalls for current process attributes
LSM: Create lsm_module_list system call
LSM: wireup Linux Security Module syscalls
LSM: Helpers for attribute names and filling an lsm_ctx
Smack: implement setselfattr and getselfattr hooks
AppArmor: Add selfattr hooks
SELinux: Add selfattr hooks
LSM: selftests for Linux Security Module syscalls

Documentation/userspace-api/index.rst | 1 +
Documentation/userspace-api/lsm.rst | 73 +++++
MAINTAINERS | 1 +
arch/alpha/kernel/syscalls/syscall.tbl | 3 +
arch/arm/tools/syscall.tbl | 3 +
arch/arm64/include/asm/unistd.h | 2 +-
arch/arm64/include/asm/unistd32.h | 6 +
arch/ia64/kernel/syscalls/syscall.tbl | 3 +
arch/m68k/kernel/syscalls/syscall.tbl | 3 +
arch/microblaze/kernel/syscalls/syscall.tbl | 3 +
arch/mips/kernel/syscalls/syscall_n32.tbl | 3 +
arch/mips/kernel/syscalls/syscall_n64.tbl | 3 +
arch/mips/kernel/syscalls/syscall_o32.tbl | 3 +
arch/parisc/kernel/syscalls/syscall.tbl | 3 +
arch/powerpc/kernel/syscalls/syscall.tbl | 3 +
arch/s390/kernel/syscalls/syscall.tbl | 3 +
arch/sh/kernel/syscalls/syscall.tbl | 3 +
arch/sparc/kernel/syscalls/syscall.tbl | 3 +
arch/x86/entry/syscalls/syscall_32.tbl | 3 +
arch/x86/entry/syscalls/syscall_64.tbl | 3 +
arch/xtensa/kernel/syscalls/syscall.tbl | 3 +
fs/proc/base.c | 29 +-
fs/proc/internal.h | 2 +-
include/linux/lsm_hook_defs.h | 4 +
include/linux/lsm_hooks.h | 27 +-
include/linux/security.h | 45 ++-
include/linux/syscalls.h | 5 +
include/uapi/asm-generic/unistd.h | 11 +-
include/uapi/linux/lsm.h | 82 ++++++
kernel/sys_ni.c | 5 +
security/Makefile | 1 +
security/apparmor/include/procattr.h | 2 +-
security/apparmor/lsm.c | 100 ++++++-
security/apparmor/procattr.c | 11 +-
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/lsm_syscalls.c | 145 ++++++++++
security/safesetid/lsm.c | 9 +-
security/security.c | 176 ++++++++++--
security/selinux/hooks.c | 154 ++++++++--
security/smack/smack_lsm.c | 96 ++++++-
security/tomoyo/tomoyo.c | 9 +-
security/yama/yama_lsm.c | 8 +-
.../arch/mips/entry/syscalls/syscall_n64.tbl | 3 +
.../arch/powerpc/entry/syscalls/syscall.tbl | 3 +
.../perf/arch/s390/entry/syscalls/syscall.tbl | 3 +
.../arch/x86/entry/syscalls/syscall_64.tbl | 3 +
tools/testing/selftests/Makefile | 1 +
tools/testing/selftests/lsm/Makefile | 12 +
tools/testing/selftests/lsm/config | 2 +
.../selftests/lsm/lsm_get_self_attr_test.c | 267 ++++++++++++++++++
.../selftests/lsm/lsm_module_list_test.c | 149 ++++++++++
.../selftests/lsm/lsm_set_self_attr_test.c | 69 +++++
60 files changed, 1512 insertions(+), 99 deletions(-)
create mode 100644 Documentation/userspace-api/lsm.rst
create mode 100644 include/uapi/linux/lsm.h
create mode 100644 security/lsm_syscalls.c
create mode 100644 tools/testing/selftests/lsm/Makefile
create mode 100644 tools/testing/selftests/lsm/config
create mode 100644 tools/testing/selftests/lsm/lsm_get_self_attr_test.c
create mode 100644 tools/testing/selftests/lsm/lsm_module_list_test.c
create mode 100644 tools/testing/selftests/lsm/lsm_set_self_attr_test.c

--
2.39.0



2023-02-22 20:09:11

by Casey Schaufler

[permalink] [raw]
Subject: [PATCH v6 02/11] LSM: Maintain a table of LSM attribute data

As LSMs are registered add their lsm_id pointers to a table.
This will be used later for attribute reporting.

Determine the number of possible security modules based on
their respective CONFIG options. This allows the number to be
known at build time. This allows data structures and tables
to use the constant.

Signed-off-by: Casey Schaufler <[email protected]>
---
include/linux/security.h | 2 ++
security/security.c | 44 ++++++++++++++++++++++++++++++++--------
2 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index 5b67f208f7de..33ed1860b96f 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -138,6 +138,8 @@ enum lockdown_reason {
};

extern const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1];
+extern u32 lsm_active_cnt;
+extern struct lsm_id *lsm_idlist[];

/* These functions are in security/commoncap.c */
extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
diff --git a/security/security.c b/security/security.c
index 07a8fe7f92bf..4b81734ae9bd 100644
--- a/security/security.c
+++ b/security/security.c
@@ -28,12 +28,29 @@
#include <linux/backing-dev.h>
#include <linux/string.h>
#include <linux/msg.h>
+#include <uapi/linux/lsm.h>
#include <net/flow.h>

#define MAX_LSM_EVM_XATTR 2

-/* How many LSMs were built into the kernel? */
-#define LSM_COUNT (__end_lsm_info - __start_lsm_info)
+/*
+ * How many LSMs are built into the kernel as determined at
+ * build time. Used to determine fixed array sizes.
+ * The capability module is accounted for by CONFIG_SECURITY
+ */
+#define LSM_COUNT ( \
+ (IS_ENABLED(CONFIG_SECURITY) ? 1 : 0) + \
+ (IS_ENABLED(CONFIG_SECURITY_SELINUX) ? 1 : 0) + \
+ (IS_ENABLED(CONFIG_SECURITY_SMACK) ? 1 : 0) + \
+ (IS_ENABLED(CONFIG_SECURITY_TOMOYO) ? 1 : 0) + \
+ (IS_ENABLED(CONFIG_SECURITY_IMA) ? 1 : 0) + \
+ (IS_ENABLED(CONFIG_SECURITY_APPARMOR) ? 1 : 0) + \
+ (IS_ENABLED(CONFIG_SECURITY_YAMA) ? 1 : 0) + \
+ (IS_ENABLED(CONFIG_SECURITY_LOADPIN) ? 1 : 0) + \
+ (IS_ENABLED(CONFIG_SECURITY_SAFESETID) ? 1 : 0) + \
+ (IS_ENABLED(CONFIG_SECURITY_LOCKDOWN_LSM) ? 1 : 0) + \
+ (IS_ENABLED(CONFIG_BPF_LSM) ? 1 : 0) + \
+ (IS_ENABLED(CONFIG_SECURITY_LANDLOCK) ? 1 : 0))

/*
* These are descriptions of the reasons that can be passed to the
@@ -90,7 +107,7 @@ static __initdata const char *chosen_major_lsm;
static __initconst const char * const builtin_lsm_order = CONFIG_LSM;

/* Ordered list of LSMs to initialize. */
-static __initdata struct lsm_info **ordered_lsms;
+static __initdata struct lsm_info *ordered_lsms[LSM_COUNT];
static __initdata struct lsm_info *exclusive;

static __initdata bool debug;
@@ -341,13 +358,16 @@ static void __init report_lsm_order(void)
pr_cont("\n");
}

+/*
+ * Current index to use while initializing the lsm id list.
+ */
+u32 lsm_active_cnt __lsm_ro_after_init;
+struct lsm_id *lsm_idlist[LSM_COUNT] __lsm_ro_after_init;
+
static void __init ordered_lsm_init(void)
{
struct lsm_info **lsm;

- ordered_lsms = kcalloc(LSM_COUNT + 1, sizeof(*ordered_lsms),
- GFP_KERNEL);
-
if (chosen_lsm_order) {
if (chosen_major_lsm) {
pr_warn("security=%s is ignored because it is superseded by lsm=%s\n",
@@ -387,8 +407,6 @@ static void __init ordered_lsm_init(void)
lsm_early_task(current);
for (lsm = ordered_lsms; *lsm; lsm++)
initialize_lsm(*lsm);
-
- kfree(ordered_lsms);
}

int __init early_security_init(void)
@@ -513,6 +531,16 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
{
int i;

+ /*
+ * A security module may call security_add_hooks() more
+ * than once. Landlock is one such case.
+ */
+ if (lsm_active_cnt == 0 || lsm_idlist[lsm_active_cnt - 1] != lsmid)
+ lsm_idlist[lsm_active_cnt++] = lsmid;
+
+ if (lsm_active_cnt > LSM_COUNT)
+ panic("%s Too many LSMs registered.\n", __func__);
+
for (i = 0; i < count; i++) {
hooks[i].lsmid = lsmid;
hlist_add_tail_rcu(&hooks[i].list, hooks[i].head);
--
2.39.0


2023-02-22 20:09:20

by Casey Schaufler

[permalink] [raw]
Subject: [PATCH v6 01/11] LSM: Identify modules by more than name

Create a struct lsm_id to contain identifying information
about Linux Security Modules (LSMs). At inception this contains
the name of the module, an identifier associated with the security
module and an integer member "attrs" which identifies the API
related data associated with each security module. The initial set
of features maps to information that has traditionaly been available
in /proc/self/attr. They are documented in a new userspace-api file.
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.

Signed-off-by: Casey Schaufler <[email protected]>
---
Documentation/userspace-api/index.rst | 1 +
Documentation/userspace-api/lsm.rst | 55 +++++++++++++++++++++++++++
MAINTAINERS | 1 +
include/linux/lsm_hooks.h | 18 ++++++++-
include/uapi/linux/lsm.h | 49 ++++++++++++++++++++++++
security/apparmor/lsm.c | 9 ++++-
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 | 11 +++++-
security/smack/smack_lsm.c | 9 ++++-
security/tomoyo/tomoyo.c | 9 ++++-
security/yama/yama_lsm.c | 8 +++-
21 files changed, 217 insertions(+), 21 deletions(-)
create mode 100644 Documentation/userspace-api/lsm.rst
create mode 100644 include/uapi/linux/lsm.h

diff --git a/Documentation/userspace-api/index.rst b/Documentation/userspace-api/index.rst
index f16337bdb852..54c0f54cde89 100644
--- a/Documentation/userspace-api/index.rst
+++ b/Documentation/userspace-api/index.rst
@@ -31,6 +31,7 @@ place where this information is gathered.
sysfs-platform_profile
vduse
futex2
+ lsm

.. only:: subproject and html

diff --git a/Documentation/userspace-api/lsm.rst b/Documentation/userspace-api/lsm.rst
new file mode 100644
index 000000000000..6ddf5506110b
--- /dev/null
+++ b/Documentation/userspace-api/lsm.rst
@@ -0,0 +1,55 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. Copyright (C) 2022 Casey Schaufler <[email protected]>
+.. Copyright (C) 2022 Intel Corporation
+
+=====================================
+Linux Security Modules
+=====================================
+
+:Author: Casey Schaufler
+:Date: November 2022
+
+Linux security modules (LSM) provide a mechanism to implement
+additional access controls to the Linux security policies.
+
+The various security modules may support any of these attributes:
+
+``LSM_ATTR_CURRENT`` is the current, active security context of the
+process.
+The proc filesystem provides this value in ``/proc/self/attr/current``.
+This is supported by the SELinux, Smack and AppArmor security modules.
+Smack also provides this value in ``/proc/self/attr/smack/current``.
+AppArmor also provides this value in ``/proc/self/attr/apparmor/current``.
+
+``LSM_ATTR_EXEC`` is the security context of the process at the time the
+current image was executed.
+The proc filesystem provides this value in ``/proc/self/attr/exec``.
+This is supported by the SELinux and AppArmor security modules.
+AppArmor also provides this value in ``/proc/self/attr/apparmor/exec``.
+
+``LSM_ATTR_FSCREATE`` is the security context of the process used when
+creating file system objects.
+The proc filesystem provides this value in ``/proc/self/attr/fscreate``.
+This is supported by the SELinux security module.
+
+``LSM_ATTR_KEYCREATE`` is the security context of the process used when
+creating key objects.
+The proc filesystem provides this value in ``/proc/self/attr/keycreate``.
+This is supported by the SELinux security module.
+
+``LSM_ATTR_PREV`` is the security context of the process at the time the
+current security context was set.
+The proc filesystem provides this value in ``/proc/self/attr/prev``.
+This is supported by the SELinux and AppArmor security modules.
+AppArmor also provides this value in ``/proc/self/attr/apparmor/prev``.
+
+``LSM_ATTR_SOCKCREATE`` is the security context of the process used when
+creating socket objects.
+The proc filesystem provides this value in ``/proc/self/attr/sockcreate``.
+This is supported by the SELinux security module.
+
+Additional documentation
+========================
+
+* Documentation/security/lsm.rst
+* Documentation/security/lsm-development.rst
diff --git a/MAINTAINERS b/MAINTAINERS
index 39ff1a717625..3fe73ddc32c5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18820,6 +18820,7 @@ S: Supported
W: http://kernsec.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm.git
F: security/
+F: include/uapi/linux/lsm.h
X: security/selinux/

SELINUX SECURITY MODULE
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 0a5ba81f7367..98acafc60f47 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1665,6 +1665,20 @@ 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
+ * @attrs: which attributes this LSM supports
+ *
+ * Contains the information that identifies the LSM.
+ */
+struct lsm_id {
+ const u8 *lsm;
+ u64 id;
+ u64 attrs;
+};
+
/*
* Security module hook list structure.
* For use with generic list macros for common operations.
@@ -1673,7 +1687,7 @@ struct security_hook_list {
struct hlist_node list;
struct hlist_head *head;
union security_list_options hook;
- const char *lsm;
+ struct lsm_id *lsmid;
} __randomize_layout;

/*
@@ -1708,7 +1722,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);
+ 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..523748cae615
--- /dev/null
+++ b/include/uapi/linux/lsm.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Linux Security Modules (LSM) - User space API
+ *
+ * Copyright (C) 2022 Casey Schaufler <[email protected]>
+ * 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.
+ */
+#define LSM_ATTR_CURRENT 0x0001
+#define LSM_ATTR_EXEC 0x0002
+#define LSM_ATTR_FSCREATE 0x0004
+#define LSM_ATTR_KEYCREATE 0x0008
+#define LSM_ATTR_PREV 0x0010
+#define LSM_ATTR_SOCKCREATE 0x0020
+
+#endif /* _UAPI_LINUX_LSM_H */
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index c6728a629437..0c2f4d47af42 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"
@@ -1217,6 +1218,12 @@ struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = {
.lbs_task = sizeof(struct aa_task_ctx),
};

+static struct lsm_id apparmor_lsmid __lsm_ro_after_init = {
+ .lsm = "apparmor",
+ .id = LSM_ID_APPARMOR,
+ .attrs = LSM_ATTR_CURRENT | LSM_ATTR_PREV | LSM_ATTR_EXEC,
+};
+
static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
@@ -1912,7 +1919,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 e5971fa74fd7..5f3c6dcb6850 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[] __lsm_ro_after_init = {
#define LSM_HOOK(RET, DEFAULT, NAME, ...) \
@@ -15,9 +16,15 @@ static struct security_hook_list bpf_lsm_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(task_free, bpf_task_storage_free),
};

+struct lsm_id bpf_lsmid __lsm_ro_after_init = {
+ .lsm = "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 1164278b97fd..76c5a0af95d6 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
@@ -1445,6 +1446,11 @@ int cap_mmap_file(struct file *file, unsigned long reqprot,

#ifdef CONFIG_SECURITY

+static struct lsm_id capability_lsmid __lsm_ro_after_init = {
+ .lsm = "capability",
+ .id = LSM_ID_CAPABILITY,
+};
+
static struct security_hook_list capability_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(capable, cap_capable),
LSM_HOOK_INIT(settime, cap_settime),
@@ -1469,7 +1475,7 @@ static struct security_hook_list capability_hooks[] __lsm_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 ec6c37f04a19..2eb1d65f10d6 100644
--- a/security/landlock/cred.c
+++ b/security/landlock/cred.c
@@ -42,5 +42,5 @@ static struct security_hook_list landlock_hooks[] __lsm_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 adcea0fe7e68..fa0e6e76991c 100644
--- a/security/landlock/fs.c
+++ b/security/landlock/fs.c
@@ -1307,5 +1307,5 @@ static struct security_hook_list landlock_hooks[] __lsm_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 4c5b9cd71286..eab35808f395 100644
--- a/security/landlock/ptrace.c
+++ b/security/landlock/ptrace.c
@@ -116,5 +116,5 @@ static struct security_hook_list landlock_hooks[] __lsm_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 3f196d2ce4f9..9104133d04ca 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 __lsm_ro_after_init = {
.lbs_superblock = sizeof(struct landlock_superblock_security),
};

+struct lsm_id landlock_lsmid __lsm_ro_after_init = {
+ .lsm = 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..38bce5b172dc 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 struct lsm_id landlock_lsmid;

#endif /* _SECURITY_LANDLOCK_SETUP_H */
diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
index 110a5ab2b46b..d5c1373a096d 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"

@@ -203,6 +204,11 @@ static int loadpin_load_data(enum kernel_load_data_id id, bool contents)
return loadpin_check(NULL, (enum kernel_read_file_id) id);
}

+static struct lsm_id loadpin_lsmid __lsm_ro_after_init = {
+ .lsm = "loadpin",
+ .id = LSM_ID_LOADPIN,
+};
+
static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
@@ -250,7 +256,8 @@ static int __init loadpin_init(void)
pr_info("ready to pin (currently %senforcing)\n",
enforce ? "" : "not ");
parse_exclude();
- 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 a79b985e917e..e8c41a0caf7d 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[] __lsm_ro_after_init = {
LSM_HOOK_INIT(locked_down, lockdown_is_locked_down),
};

+static struct lsm_id lockdown_lsmid __lsm_ro_after_init = {
+ .lsm = "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 e806739f7868..8d0742ba045d 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;
}

+static struct lsm_id safesetid_lsmid __lsm_ro_after_init = {
+ .lsm = "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 d1571900a8c7..07a8fe7f92bf 100644
--- a/security/security.c
+++ b/security/security.c
@@ -504,17 +504,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)
+ 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);
}

@@ -523,7 +523,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->lsm, &lsm_names) < 0)
panic("%s - Cannot get early memory.\n", __func__);
}
}
@@ -2145,7 +2145,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->lsm))
continue;
return hp->hook.getprocattr(p, name, value);
}
@@ -2158,7 +2158,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->lsm))
continue;
return hp->hook.setprocattr(name, value, size);
}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 3c5be76a9199..5cb09986a2dc 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"
@@ -7032,6 +7033,13 @@ static int selinux_uring_cmd(struct io_uring_cmd *ioucmd)
}
#endif /* CONFIG_IO_URING */

+static struct lsm_id selinux_lsmid __lsm_ro_after_init = {
+ .lsm = "selinux",
+ .id = LSM_ID_SELINUX,
+ .attrs = LSM_ATTR_CURRENT | LSM_ATTR_EXEC | LSM_ATTR_FSCREATE |
+ LSM_ATTR_KEYCREATE | LSM_ATTR_PREV | LSM_ATTR_SOCKCREATE,
+};
+
/*
* 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,
@@ -7355,7 +7363,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 9a82a15685d1..a27157910fe7 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"
@@ -4856,6 +4857,12 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
.lbs_superblock = sizeof(struct superblock_smack),
};

+static struct lsm_id smack_lsmid __lsm_ro_after_init = {
+ .lsm = "smack",
+ .id = LSM_ID_SMACK,
+ .attrs = LSM_ATTR_CURRENT,
+};
+
static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
@@ -5062,7 +5069,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 af04a7b7eb28..a4658fb5ef0e 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)
}
}

+static struct lsm_id tomoyo_lsmid __lsm_ro_after_init = {
+ .lsm = "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 06e226166aab..2487b8f847f3 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;
}

+static struct lsm_id yama_lsmid __lsm_ro_after_init = {
+ .lsm = "yama",
+ .id = LSM_ID_YAMA,
+};
+
static struct security_hook_list yama_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check),
LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme),
@@ -477,7 +483,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;
}
--
2.39.0


2023-02-22 20:10:35

by Casey Schaufler

[permalink] [raw]
Subject: [PATCH v6 03/11] proc: Use lsmids instead of lsm names for attrs

Use the LSM ID number instead of the LSM name to identify which
security module's attibute data should be shown in /proc/self/attr.
The security_[gs]etprocattr() functions have been changed to expect
the LSM ID. The change from a string comparison to an integer comparison
in these functions will provide a minor performance improvement.

Signed-off-by: Casey Schaufler <[email protected]>
Cc: [email protected]
---
fs/proc/base.c | 29 +++++++++++++++--------------
fs/proc/internal.h | 2 +-
include/linux/security.h | 11 +++++------
security/security.c | 11 +++++------
4 files changed, 26 insertions(+), 27 deletions(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index 9e479d7d202b..4c8c886d214f 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -96,6 +96,7 @@
#include <linux/time_namespace.h>
#include <linux/resctrl.h>
#include <linux/cn_proc.h>
+#include <uapi/linux/lsm.h>
#include <trace/events/oom.h>
#include "internal.h"
#include "fd.h"
@@ -145,10 +146,10 @@ struct pid_entry {
NOD(NAME, (S_IFREG|(MODE)), \
NULL, &proc_single_file_operations, \
{ .proc_show = show } )
-#define ATTR(LSM, NAME, MODE) \
+#define ATTR(LSMID, NAME, MODE) \
NOD(NAME, (S_IFREG|(MODE)), \
NULL, &proc_pid_attr_operations, \
- { .lsm = LSM })
+ { .lsmid = LSMID })

/*
* Count the number of hardlinks for the pid_entry table, excluding the .
@@ -2730,7 +2731,7 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
if (!task)
return -ESRCH;

- length = security_getprocattr(task, PROC_I(inode)->op.lsm,
+ length = security_getprocattr(task, PROC_I(inode)->op.lsmid,
file->f_path.dentry->d_name.name,
&p);
put_task_struct(task);
@@ -2788,7 +2789,7 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
if (rv < 0)
goto out_free;

- rv = security_setprocattr(PROC_I(inode)->op.lsm,
+ rv = security_setprocattr(PROC_I(inode)->op.lsmid,
file->f_path.dentry->d_name.name, page,
count);
mutex_unlock(&current->signal->cred_guard_mutex);
@@ -2837,27 +2838,27 @@ static const struct inode_operations proc_##LSM##_attr_dir_inode_ops = { \

#ifdef CONFIG_SECURITY_SMACK
static const struct pid_entry smack_attr_dir_stuff[] = {
- ATTR("smack", "current", 0666),
+ ATTR(LSM_ID_SMACK, "current", 0666),
};
LSM_DIR_OPS(smack);
#endif

#ifdef CONFIG_SECURITY_APPARMOR
static const struct pid_entry apparmor_attr_dir_stuff[] = {
- ATTR("apparmor", "current", 0666),
- ATTR("apparmor", "prev", 0444),
- ATTR("apparmor", "exec", 0666),
+ ATTR(LSM_ID_APPARMOR, "current", 0666),
+ ATTR(LSM_ID_APPARMOR, "prev", 0444),
+ ATTR(LSM_ID_APPARMOR, "exec", 0666),
};
LSM_DIR_OPS(apparmor);
#endif

static const struct pid_entry attr_dir_stuff[] = {
- ATTR(NULL, "current", 0666),
- ATTR(NULL, "prev", 0444),
- ATTR(NULL, "exec", 0666),
- ATTR(NULL, "fscreate", 0666),
- ATTR(NULL, "keycreate", 0666),
- ATTR(NULL, "sockcreate", 0666),
+ ATTR(LSM_ID_UNDEF, "current", 0666),
+ ATTR(LSM_ID_UNDEF, "prev", 0444),
+ ATTR(LSM_ID_UNDEF, "exec", 0666),
+ ATTR(LSM_ID_UNDEF, "fscreate", 0666),
+ ATTR(LSM_ID_UNDEF, "keycreate", 0666),
+ ATTR(LSM_ID_UNDEF, "sockcreate", 0666),
#ifdef CONFIG_SECURITY_SMACK
DIR("smack", 0555,
proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index b701d0207edf..18db9722c81b 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -92,7 +92,7 @@ union proc_op {
int (*proc_show)(struct seq_file *m,
struct pid_namespace *ns, struct pid *pid,
struct task_struct *task);
- const char *lsm;
+ int lsmid;
};

struct proc_inode {
diff --git a/include/linux/security.h b/include/linux/security.h
index 33ed1860b96f..2d09e818a7d1 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -475,10 +475,9 @@ int security_sem_semctl(struct kern_ipc_perm *sma, int cmd);
int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops,
unsigned nsops, int alter);
void security_d_instantiate(struct dentry *dentry, struct inode *inode);
-int security_getprocattr(struct task_struct *p, const char *lsm, const char *name,
+int security_getprocattr(struct task_struct *p, int lsmid, const char *name,
char **value);
-int security_setprocattr(const char *lsm, const char *name, void *value,
- size_t size);
+int security_setprocattr(int lsmid, const char *name, void *value, size_t size);
int security_netlink_send(struct sock *sk, struct sk_buff *skb);
int security_ismaclabel(const char *name);
int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
@@ -1346,14 +1345,14 @@ static inline void security_d_instantiate(struct dentry *dentry,
struct inode *inode)
{ }

-static inline int security_getprocattr(struct task_struct *p, const char *lsm,
+static inline int security_getprocattr(struct task_struct *p, int lsmid,
const char *name, char **value)
{
return -EINVAL;
}

-static inline int security_setprocattr(const char *lsm, char *name,
- void *value, size_t size)
+static inline int security_setprocattr(int lsmid, char *name, void *value,
+ size_t size)
{
return -EINVAL;
}
diff --git a/security/security.c b/security/security.c
index 4b81734ae9bd..3308d7c8a20b 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2167,26 +2167,25 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode)
}
EXPORT_SYMBOL(security_d_instantiate);

-int security_getprocattr(struct task_struct *p, const char *lsm,
- const char *name, char **value)
+int security_getprocattr(struct task_struct *p, int lsmid, const char *name,
+ char **value)
{
struct security_hook_list *hp;

hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) {
- if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm))
+ if (lsmid != 0 && lsmid != hp->lsmid->id)
continue;
return hp->hook.getprocattr(p, name, value);
}
return LSM_RET_DEFAULT(getprocattr);
}

-int security_setprocattr(const char *lsm, const char *name, void *value,
- size_t size)
+int security_setprocattr(int lsmid, const char *name, void *value, size_t size)
{
struct security_hook_list *hp;

hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) {
- if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm))
+ if (lsmid != 0 && lsmid != hp->lsmid->id)
continue;
return hp->hook.setprocattr(name, value, size);
}
--
2.39.0


2023-02-22 20:10:38

by Casey Schaufler

[permalink] [raw]
Subject: [PATCH v6 04/11] LSM: syscalls for current process attributes

Create a system call lsm_get_self_attr() to provide the security
module maintained attributes of the current process.
Create a system call lsm_set_self_attr() to set a security
module maintained attribute of the current process.
Historically these attributes have been exposed to user space via
entries in procfs under /proc/self/attr.

The attribute value is provided in a lsm_ctx structure. The structure
identifys the size of the attribute, and the attribute value. The format
of the attribute value is defined by the security module. A flags field
is included for LSM specific information. It is currently unused and must
be 0. The total size of the data, including the lsm_ctx structure and any
padding, is maintained as well.

struct lsm_ctx {
__u64 id;
__u64 flags;
__u64 len;
__u64 ctx_len;
__u8 ctx[];
};

Two new LSM hooks are used to interface with the LSMs.
security_getselfattr() collects the lsm_ctx values from the
LSMs that support the hook, accounting for space requirements.
security_setselfattr() identifies which LSM the attribute is
intended for and passes it along.

Signed-off-by: Casey Schaufler <[email protected]>
---
Documentation/userspace-api/lsm.rst | 15 ++++
include/linux/lsm_hook_defs.h | 4 ++
include/linux/lsm_hooks.h | 9 +++
include/linux/security.h | 19 +++++
include/linux/syscalls.h | 4 ++
include/uapi/linux/lsm.h | 33 +++++++++
kernel/sys_ni.c | 4 ++
security/Makefile | 1 +
security/lsm_syscalls.c | 104 ++++++++++++++++++++++++++++
security/security.c | 82 ++++++++++++++++++++++
10 files changed, 275 insertions(+)
create mode 100644 security/lsm_syscalls.c

diff --git a/Documentation/userspace-api/lsm.rst b/Documentation/userspace-api/lsm.rst
index 6ddf5506110b..b45e402302b3 100644
--- a/Documentation/userspace-api/lsm.rst
+++ b/Documentation/userspace-api/lsm.rst
@@ -48,6 +48,21 @@ creating socket objects.
The proc filesystem provides this value in ``/proc/self/attr/sockcreate``.
This is supported by the SELinux security module.

+Kernel interface
+================
+
+Set a security attribute of the current process
+--------------------------------------------------
+
+.. kernel-doc:: security/lsm_syscalls.c
+ :identifiers: sys_lsm_set_self_attr
+
+Get the specified security attributes of the current process
+--------------------------------------------------
+
+.. kernel-doc:: security/lsm_syscalls.c
+ :identifiers: sys_lsm_get_self_attr
+
Additional documentation
========================

diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index ed6cb2ac55fa..a834bc2311bf 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -261,6 +261,10 @@ LSM_HOOK(int, 0, sem_semop, struct kern_ipc_perm *perm, struct sembuf *sops,
LSM_HOOK(int, 0, netlink_send, struct sock *sk, struct sk_buff *skb)
LSM_HOOK(void, LSM_RET_VOID, d_instantiate, struct dentry *dentry,
struct inode *inode)
+LSM_HOOK(int, -EOPNOTSUPP, getselfattr, u64 __user attr,
+ struct lsm_ctx __user *ctx, size_t *size)
+LSM_HOOK(int, -EOPNOTSUPP, setselfattr, u64 __user attr,
+ struct lsm_ctx __user *ctx, size_t size)
LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name,
char **value)
LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 98acafc60f47..36cd1692b82b 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -25,6 +25,7 @@
#ifndef __LINUX_LSM_HOOKS_H
#define __LINUX_LSM_HOOKS_H

+#include <uapi/linux/lsm.h>
#include <linux/security.h>
#include <linux/init.h>
#include <linux/rculist.h>
@@ -503,6 +504,14 @@
* and writing the xattrs as this hook is merely a filter.
* @d_instantiate:
* Fill in @inode security information for a @dentry if allowed.
+ * @getselfattr:
+ * Read attribute @attr for the current process and store it into @ctx.
+ * Return 0 on success, -EOPNOTSUPP if the attribute is not supported,
+ * or another negative value otherwise.
+ * @setselfattr:
+ * Set attribute @attr for the current process.
+ * Return 0 on success, -EOPNOTSUPP if the attribute is not supported,
+ * or another negative value otherwise.
* @getprocattr:
* Read attribute @name for process @p and store it into @value if allowed.
* Return the length of @value on success, a negative value otherwise.
diff --git a/include/linux/security.h b/include/linux/security.h
index 2d09e818a7d1..21971a635b6a 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -60,6 +60,7 @@ struct fs_parameter;
enum fs_value_type;
struct watch;
struct watch_notification;
+struct lsm_ctx;

/* Default (no) options for the capable function */
#define CAP_OPT_NONE 0x0
@@ -475,6 +476,10 @@ int security_sem_semctl(struct kern_ipc_perm *sma, int cmd);
int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops,
unsigned nsops, int alter);
void security_d_instantiate(struct dentry *dentry, struct inode *inode);
+int security_getselfattr(u64 __user attr, struct lsm_ctx __user *ctx,
+ size_t __user *size);
+int security_setselfattr(u64 __user attr, struct lsm_ctx __user *ctx,
+ size_t __user size);
int security_getprocattr(struct task_struct *p, int lsmid, const char *name,
char **value);
int security_setprocattr(int lsmid, const char *name, void *value, size_t size);
@@ -1345,6 +1350,20 @@ static inline void security_d_instantiate(struct dentry *dentry,
struct inode *inode)
{ }

+static inline int security_getselfattr(u64 __user attr,
+ struct lsm_ctx __user *ctx,
+ size_t __user *size);
+{
+ return -EINVAL;
+}
+
+static inline int security_setselfattr(u64 __user attr,
+ struct lsm_ctx __user *ctx,
+ size_t __user size);
+{
+ return -EINVAL;
+}
+
static inline int security_getprocattr(struct task_struct *p, int lsmid,
const char *name, char **value)
{
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 33a0ee3bcb2e..1ef2a3de8ae0 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -71,6 +71,7 @@ struct clone_args;
struct open_how;
struct mount_attr;
struct landlock_ruleset_attr;
+struct lsm_ctx;
enum landlock_rule_type;

#include <linux/types.h>
@@ -1058,6 +1059,9 @@ asmlinkage long sys_memfd_secret(unsigned int flags);
asmlinkage long sys_set_mempolicy_home_node(unsigned long start, unsigned long len,
unsigned long home_node,
unsigned long flags);
+asmlinkage long sys_lsm_get_self_attr(struct lsm_ctx *ctx, size_t *size,
+ __u64 flags);
+asmlinkage long sys_lsm_set_self_attr(struct lsm_ctx *ctx, __u64 flags);

/*
* Architecture-specific system calls
diff --git a/include/uapi/linux/lsm.h b/include/uapi/linux/lsm.h
index 523748cae615..7850fed28998 100644
--- a/include/uapi/linux/lsm.h
+++ b/include/uapi/linux/lsm.h
@@ -9,6 +9,39 @@
#ifndef _UAPI_LINUX_LSM_H
#define _UAPI_LINUX_LSM_H

+#include <linux/types.h>
+#include <linux/unistd.h>
+
+/**
+ * struct lsm_ctx - LSM context information
+ * @id: the LSM id number, see LSM_ID_XXX
+ * @flags: LSM specific flags
+ * @len: length of the lsm_ctx struct, @ctx and any other data or padding
+ * @ctx_len: the size of @ctx
+ * @ctx: the LSM context value
+ *
+ * The @len field MUST be equal to the size of the lsm_ctx struct
+ * plus any additional padding and/or data placed after @ctx.
+ *
+ * In all cases @ctx_len MUST be equal to the length of @ctx.
+ * If @ctx is a string value it should be nul terminated with
+ * @ctx_len equal to `strlen(@ctx) + 1`. Binary values are
+ * supported.
+ *
+ * The @flags and @ctx fields SHOULD only be interpreted by the
+ * LSM specified by @id; they MUST be set to zero/0 when not used.
+ */
+struct lsm_ctx {
+ __u64 id;
+ __u64 flags;
+ __u64 len;
+ __u64 ctx_len;
+ __u8 ctx[];
+};
+
+#include <linux/types.h>
+#include <linux/unistd.h>
+
/*
* ID tokens to identify Linux Security Modules (LSMs)
*
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 860b2dcf3ac4..d03c78ef1562 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -262,6 +262,10 @@ COND_SYSCALL_COMPAT(recvmsg);
/* mm/nommu.c, also with MMU */
COND_SYSCALL(mremap);

+/* security/lsm_syscalls.c */
+COND_SYSCALL(lsm_get_self_attr);
+COND_SYSCALL(lsm_set_self_attr);
+
/* security/keys/keyctl.c */
COND_SYSCALL(add_key);
COND_SYSCALL(request_key);
diff --git a/security/Makefile b/security/Makefile
index 18121f8f85cd..59f238490665 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_KEYS) += keys/

# always enable default capabilities
obj-y += commoncap.o
+obj-$(CONFIG_SECURITY) += lsm_syscalls.o
obj-$(CONFIG_MMU) += min_addr.o

# Object file lists
diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c
new file mode 100644
index 000000000000..b89c4e7d009e
--- /dev/null
+++ b/security/lsm_syscalls.c
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * System calls implementing the Linux Security Module API.
+ *
+ * Copyright (C) 2022 Casey Schaufler <[email protected]>
+ * Copyright (C) 2022 Intel Corporation
+ */
+
+#include <asm/current.h>
+#include <linux/compiler_types.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/security.h>
+#include <linux/stddef.h>
+#include <linux/syscalls.h>
+#include <linux/types.h>
+#include <linux/lsm_hooks.h>
+#include <uapi/linux/lsm.h>
+
+struct attrs_map {
+ char *name;
+ int attrs;
+};
+
+static const struct attrs_map lsm_attr_names[] = {
+ {
+ .name = "current",
+ .attrs = LSM_ATTR_CURRENT,
+ },
+ {
+ .name = "exec",
+ .attrs = LSM_ATTR_EXEC,
+ },
+ {
+ .name = "fscreate",
+ .attrs = LSM_ATTR_FSCREATE,
+ },
+ {
+ .name = "keycreate",
+ .attrs = LSM_ATTR_KEYCREATE,
+ },
+ {
+ .name = "prev",
+ .attrs = LSM_ATTR_PREV,
+ },
+ {
+ .name = "sockcreate",
+ .attrs = LSM_ATTR_SOCKCREATE,
+ },
+};
+
+/**
+ * lsm_name_to_attr - map an LSM attribute name to its ID
+ * @name: name of the attribute
+ *
+ * Look the given @name up in the table of know attribute names.
+ *
+ * Returns the LSM attribute value associated with @name, or 0 if
+ * there is no mapping.
+ */
+u64 lsm_name_to_attr(const char *name)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(lsm_attr_names); i++)
+ if (!strcmp(name, lsm_attr_names[i].name))
+ return lsm_attr_names[i].attrs;
+ return 0;
+}
+
+/**
+ * sys_lsm_set_self_attr - Set current task's security module attribute
+ * @ctx: the LSM contexts
+ * @size: size of @ctx
+ * @flags: which attribute to set
+ *
+ * Sets the calling task's LSM context. On success this function
+ * returns 0. If the attribute specified cannot be set a negative
+ * value indicating the reason for the error is returned.
+ */
+SYSCALL_DEFINE3(lsm_set_self_attr, struct lsm_ctx __user *, ctx, size_t __user,
+ size, u64, flags)
+{
+ return security_setselfattr(flags, ctx, size);
+}
+
+/**
+ * sys_lsm_get_self_attr - Return current task's security module attributes
+ * @ctx: the LSM contexts
+ * @size: size of @ctx, updated on return
+ * @flags: which attribute to return
+ *
+ * Returns the calling task's LSM contexts. On success this
+ * function returns the number of @ctx array elements. This value
+ * may be zero if there are no LSM contexts assigned. If @size is
+ * insufficient to contain the return data -E2BIG is returned and
+ * @size is set to the minimum required size. In all other cases
+ * a negative value indicating the error is returned.
+ */
+SYSCALL_DEFINE3(lsm_get_self_attr, struct lsm_ctx __user *, ctx,
+ size_t __user *, size, u64, flags)
+{
+ return security_getselfattr(flags, ctx, size);
+}
diff --git a/security/security.c b/security/security.c
index 3308d7c8a20b..6823a6cb32a9 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2167,6 +2167,88 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode)
}
EXPORT_SYMBOL(security_d_instantiate);

+/**
+ * security_getselfattr - Read an LSM attribute of the current process.
+ * @attr: which attribute to return
+ * @ctx: the user-space destination for the information, or NULL
+ * @size: the size of space available to receive the data
+ *
+ * Returns the number of attributes found on success, negative value
+ * on error. @size is reset to the total size of the data.
+ * If @size is insufficient to contain the data -E2BIG is returned.
+ */
+int security_getselfattr(u64 __user attr, struct lsm_ctx __user *ctx,
+ size_t __user *size)
+{
+ struct security_hook_list *hp;
+ void __user *base = (void *)ctx;
+ size_t total = 0;
+ size_t this;
+ size_t left;
+ int count = 0;
+ int rc;
+
+ if (attr == 0)
+ return -EINVAL;
+ if (size == NULL)
+ return -EINVAL;
+ if (get_user(left, size))
+ return -EFAULT;
+
+ hlist_for_each_entry(hp, &security_hook_heads.getselfattr, list) {
+ if ((hp->lsmid->attrs & attr) != attr)
+ continue;
+ this = left;
+ if (base)
+ ctx = (struct lsm_ctx __user *)(base + total);
+ rc = hp->hook.getselfattr(attr, ctx, &this);
+ if (rc == -E2BIG)
+ left = 0;
+ else if (rc == 0)
+ left -= this;
+ else
+ return rc;
+ total += this;
+ count++;
+ }
+ if (count == 0)
+ return LSM_RET_DEFAULT(getselfattr);
+ if (put_user(total, size))
+ return -EFAULT;
+ if (rc)
+ return rc;
+ return count;
+}
+
+/**
+ * security_setselfattr - Set an LSM attribute on the current process.
+ * @attr: which attribute to return
+ * @ctx: the user-space source for the information
+ * @size: the size of the data
+ *
+ * Set an LSM attribute for the current process. The LSM, attribute
+ * and new value are included in @ctx.
+ *
+ * Returns 0 on seccess, an LSM specific value on failure.
+ */
+int security_setselfattr(u64 __user attr, struct lsm_ctx __user *ctx,
+ size_t __user size)
+{
+ struct security_hook_list *hp;
+ struct lsm_ctx lctx;
+
+ if (size < sizeof(*ctx))
+ return -EINVAL;
+ if (copy_from_user(&lctx, ctx, sizeof(*ctx)))
+ return -EFAULT;
+
+ hlist_for_each_entry(hp, &security_hook_heads.setselfattr, list)
+ if ((hp->lsmid->id) == lctx.id)
+ return hp->hook.setselfattr(attr, ctx, size);
+
+ return LSM_RET_DEFAULT(setselfattr);
+}
+
int security_getprocattr(struct task_struct *p, int lsmid, const char *name,
char **value)
{
--
2.39.0


2023-02-22 20:10:47

by Casey Schaufler

[permalink] [raw]
Subject: [PATCH v6 05/11] LSM: Create lsm_module_list system call

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 chosing an
output format, determining required privilege or bypassing
security module specific behavior.

Signed-off-by: Casey Schaufler <[email protected]>
---
Documentation/userspace-api/lsm.rst | 3 ++
include/linux/syscalls.h | 1 +
kernel/sys_ni.c | 1 +
security/lsm_syscalls.c | 43 ++++++++++++++++++++++++++++-
4 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/Documentation/userspace-api/lsm.rst b/Documentation/userspace-api/lsm.rst
index b45e402302b3..ecdf1acd15b1 100644
--- a/Documentation/userspace-api/lsm.rst
+++ b/Documentation/userspace-api/lsm.rst
@@ -63,6 +63,9 @@ Get the specified security attributes of the current process
.. kernel-doc:: security/lsm_syscalls.c
:identifiers: sys_lsm_get_self_attr

+.. kernel-doc:: security/lsm_syscalls.c
+ :identifiers: sys_lsm_module_list
+
Additional documentation
========================

diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 1ef2a3de8ae0..9c947022a411 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1062,6 +1062,7 @@ asmlinkage long sys_set_mempolicy_home_node(unsigned long start, unsigned long l
asmlinkage long sys_lsm_get_self_attr(struct lsm_ctx *ctx, size_t *size,
__u64 flags);
asmlinkage long sys_lsm_set_self_attr(struct lsm_ctx *ctx, __u64 flags);
+asmlinkage long sys_lsm_module_list(u64 *ids, size_t *size, int flags);

/*
* Architecture-specific system calls
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index d03c78ef1562..32784e271fa5 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -265,6 +265,7 @@ COND_SYSCALL(mremap);
/* security/lsm_syscalls.c */
COND_SYSCALL(lsm_get_self_attr);
COND_SYSCALL(lsm_set_self_attr);
+COND_SYSCALL(lsm_module_list);

/* security/keys/keyctl.c */
COND_SYSCALL(add_key);
diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c
index b89c4e7d009e..ccd3b236670b 100644
--- a/security/lsm_syscalls.c
+++ b/security/lsm_syscalls.c
@@ -19,7 +19,7 @@

struct attrs_map {
char *name;
- int attrs;
+ u64 attrs;
};

static const struct attrs_map lsm_attr_names[] = {
@@ -102,3 +102,44 @@ SYSCALL_DEFINE3(lsm_get_self_attr, struct lsm_ctx __user *, ctx,
{
return security_getselfattr(flags, ctx, size);
}
+
+/**
+ * sys_lsm_module_list - Return a list of the active security modules
+ * @ids: the LSM module ids
+ * @size: size of @ids, updated on return
+ * @flags: reserved for future use, must be zero
+ *
+ * Returns a list of the active LSM ids. On success this function
+ * returns the number of @ids array elements. This value may be zero
+ * if there are no LSMs active. If @size is insufficient to contain
+ * the return data -E2BIG is returned and @size is set to the minimum
+ * required size. In all other cases a negative value indicating the
+ * error is returned.
+ */
+SYSCALL_DEFINE3(lsm_module_list,
+ u64 __user *, ids,
+ size_t __user *, size,
+ u64, flags)
+{
+ size_t total_size = lsm_active_cnt * sizeof(*ids);
+ size_t usize;
+ int i;
+
+ if (flags)
+ return -EINVAL;
+
+ if (get_user(usize, size))
+ return -EFAULT;
+
+ if (put_user(total_size, size) != 0)
+ return -EFAULT;
+
+ if (usize < total_size)
+ return -E2BIG;
+
+ for (i = 0; i < lsm_active_cnt; i++)
+ if (put_user(lsm_idlist[i]->id, ids++))
+ return -EFAULT;
+
+ return lsm_active_cnt;
+}
--
2.39.0


2023-02-22 20:12:29

by Casey Schaufler

[permalink] [raw]
Subject: [PATCH v6 06/11] LSM: wireup Linux Security Module syscalls

Wireup lsm_get_self_attr, lsm_set_self_attr and lsm_module_list
system calls.

Signed-off-by: Casey Schaufler <[email protected]>
Cc: [email protected]
---
arch/alpha/kernel/syscalls/syscall.tbl | 3 +++
arch/arm/tools/syscall.tbl | 3 +++
arch/arm64/include/asm/unistd.h | 2 +-
arch/arm64/include/asm/unistd32.h | 6 ++++++
arch/ia64/kernel/syscalls/syscall.tbl | 3 +++
arch/m68k/kernel/syscalls/syscall.tbl | 3 +++
arch/microblaze/kernel/syscalls/syscall.tbl | 3 +++
arch/mips/kernel/syscalls/syscall_n32.tbl | 3 +++
arch/mips/kernel/syscalls/syscall_n64.tbl | 3 +++
arch/mips/kernel/syscalls/syscall_o32.tbl | 3 +++
arch/parisc/kernel/syscalls/syscall.tbl | 3 +++
arch/powerpc/kernel/syscalls/syscall.tbl | 3 +++
arch/s390/kernel/syscalls/syscall.tbl | 3 +++
arch/sh/kernel/syscalls/syscall.tbl | 3 +++
arch/sparc/kernel/syscalls/syscall.tbl | 3 +++
arch/x86/entry/syscalls/syscall_32.tbl | 3 +++
arch/x86/entry/syscalls/syscall_64.tbl | 3 +++
arch/xtensa/kernel/syscalls/syscall.tbl | 3 +++
include/uapi/asm-generic/unistd.h | 11 ++++++++++-
tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl | 3 +++
tools/perf/arch/powerpc/entry/syscalls/syscall.tbl | 3 +++
tools/perf/arch/s390/entry/syscalls/syscall.tbl | 3 +++
tools/perf/arch/x86/entry/syscalls/syscall_64.tbl | 3 +++
23 files changed, 77 insertions(+), 2 deletions(-)

diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl
index 8ebacf37a8cf..002e6a39fcb1 100644
--- a/arch/alpha/kernel/syscalls/syscall.tbl
+++ b/arch/alpha/kernel/syscalls/syscall.tbl
@@ -490,3 +490,6 @@
558 common process_mrelease sys_process_mrelease
559 common futex_waitv sys_futex_waitv
560 common set_mempolicy_home_node sys_ni_syscall
+561 common lsm_get_self_attr sys_lsm_get_self_attr
+562 common lsm_module_list sys_lsm_module_list
+563 common lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl
index ac964612d8b0..dca80a2d3927 100644
--- a/arch/arm/tools/syscall.tbl
+++ b/arch/arm/tools/syscall.tbl
@@ -464,3 +464,6 @@
448 common process_mrelease sys_process_mrelease
449 common futex_waitv sys_futex_waitv
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+451 common lsm_get_self_attr sys_lsm_get_self_attr
+452 common lsm_module_list sys_lsm_module_list
+453 common lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 037feba03a51..6a28fb91b85d 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -39,7 +39,7 @@
#define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5)
#define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800)

-#define __NR_compat_syscalls 451
+#define __NR_compat_syscalls 454
#endif

#define __ARCH_WANT_SYS_CLONE
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index 604a2053d006..cb4b3149024d 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -907,6 +907,12 @@ __SYSCALL(__NR_process_mrelease, sys_process_mrelease)
__SYSCALL(__NR_futex_waitv, sys_futex_waitv)
#define __NR_set_mempolicy_home_node 450
__SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node)
+#define __NR_lsm_get_self_attr 451
+__SYSCALL(__NR_lsm_get_self_attr, sys_lsm_get_self_attr)
+#define __NR_lsm_module_list 452
+__SYSCALL(__NR_lsm_module_list, sys_module_list)
+#define __NR_lsm_set_self_attr 453
+__SYSCALL(__NR_lsm_set_self_attr, sys_lsm_set_self_attr)

/*
* Please add new compat syscalls above this comment and update
diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl
index 72c929d9902b..1a5d560a1317 100644
--- a/arch/ia64/kernel/syscalls/syscall.tbl
+++ b/arch/ia64/kernel/syscalls/syscall.tbl
@@ -371,3 +371,6 @@
448 common process_mrelease sys_process_mrelease
449 common futex_waitv sys_futex_waitv
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+451 common lsm_get_self_attr sys_lsm_get_self_attr
+452 common lsm_module_list sys_lsm_module_list
+453 common lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl
index b1f3940bc298..0b7b01c90315 100644
--- a/arch/m68k/kernel/syscalls/syscall.tbl
+++ b/arch/m68k/kernel/syscalls/syscall.tbl
@@ -450,3 +450,6 @@
448 common process_mrelease sys_process_mrelease
449 common futex_waitv sys_futex_waitv
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+451 common lsm_get_self_attr sys_lsm_get_self_attr
+452 common lsm_module_list sys_lsm_module_list
+453 common lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl
index 820145e47350..b69d57014c7b 100644
--- a/arch/microblaze/kernel/syscalls/syscall.tbl
+++ b/arch/microblaze/kernel/syscalls/syscall.tbl
@@ -456,3 +456,6 @@
448 common process_mrelease sys_process_mrelease
449 common futex_waitv sys_futex_waitv
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+451 common lsm_get_self_attr sys_lsm_get_self_attr
+452 common lsm_module_list sys_lsm_module_list
+453 common lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl
index 253ff994ed2e..7c1ca6241b90 100644
--- a/arch/mips/kernel/syscalls/syscall_n32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n32.tbl
@@ -389,3 +389,6 @@
448 n32 process_mrelease sys_process_mrelease
449 n32 futex_waitv sys_futex_waitv
450 n32 set_mempolicy_home_node sys_set_mempolicy_home_node
+451 n32 lsm_get_self_attr sys_lsm_get_self_attr
+452 n32 lsm_module_list sys_lsm_module_list
+453 n32 lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl
index 3f1886ad9d80..99453966d179 100644
--- a/arch/mips/kernel/syscalls/syscall_n64.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n64.tbl
@@ -365,3 +365,6 @@
448 n64 process_mrelease sys_process_mrelease
449 n64 futex_waitv sys_futex_waitv
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+451 n64 lsm_get_self_attr sys_lsm_get_self_attr
+452 n64 lsm_module_list sys_lsm_module_list
+453 n64 lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl
index 8f243e35a7b2..4ddb0ff66793 100644
--- a/arch/mips/kernel/syscalls/syscall_o32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_o32.tbl
@@ -438,3 +438,6 @@
448 o32 process_mrelease sys_process_mrelease
449 o32 futex_waitv sys_futex_waitv
450 o32 set_mempolicy_home_node sys_set_mempolicy_home_node
+451 o32 lsm_get_self_attr sys_lsm_get_self_attr
+452 o32 lsm_module_list sys_lsm_module_list
+453 032 lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl
index 0e42fceb2d5e..5ab1a5b22d8e 100644
--- a/arch/parisc/kernel/syscalls/syscall.tbl
+++ b/arch/parisc/kernel/syscalls/syscall.tbl
@@ -448,3 +448,6 @@
448 common process_mrelease sys_process_mrelease
449 common futex_waitv sys_futex_waitv
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+451 common lsm_get_self_attr sys_lsm_get_self_attr
+452 common lsm_module_list sys_lsm_module_list
+453 common lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl
index a0be127475b1..8d31bb83d6a2 100644
--- a/arch/powerpc/kernel/syscalls/syscall.tbl
+++ b/arch/powerpc/kernel/syscalls/syscall.tbl
@@ -537,3 +537,6 @@
448 common process_mrelease sys_process_mrelease
449 common futex_waitv sys_futex_waitv
450 nospu set_mempolicy_home_node sys_set_mempolicy_home_node
+451 common lsm_get_self_attr sys_lsm_get_self_attr
+452 common lsm_module_list sys_lsm_module_list
+453 common lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl
index 799147658dee..bb7597be2e4f 100644
--- a/arch/s390/kernel/syscalls/syscall.tbl
+++ b/arch/s390/kernel/syscalls/syscall.tbl
@@ -453,3 +453,6 @@
448 common process_mrelease sys_process_mrelease sys_process_mrelease
449 common futex_waitv sys_futex_waitv sys_futex_waitv
450 common set_mempolicy_home_node sys_set_mempolicy_home_node sys_set_mempolicy_home_node
+451 common lsm_get_self_attr sys_lsm_get_self_attr sys_lsm_get_self_attr
+452 common lsm_module_list sys_lsm_module_list sys_lsm_module_list
+453 common lsm_set_self_attr sys_lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl
index 2de85c977f54..43d468742916 100644
--- a/arch/sh/kernel/syscalls/syscall.tbl
+++ b/arch/sh/kernel/syscalls/syscall.tbl
@@ -453,3 +453,6 @@
448 common process_mrelease sys_process_mrelease
449 common futex_waitv sys_futex_waitv
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+451 common lsm_get_self_attr sys_lsm_get_self_attr
+452 common lsm_module_list sys_lsm_module_list
+453 common lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl
index 4398cc6fb68d..c7791c7bdde4 100644
--- a/arch/sparc/kernel/syscalls/syscall.tbl
+++ b/arch/sparc/kernel/syscalls/syscall.tbl
@@ -496,3 +496,6 @@
448 common process_mrelease sys_process_mrelease
449 common futex_waitv sys_futex_waitv
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+451 common lsm_get_self_attr sys_lsm_get_self_attr
+452 common lsm_module_list sys_lsm_module_list
+453 common lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
index 320480a8db4f..4f2e6577466e 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -455,3 +455,6 @@
448 i386 process_mrelease sys_process_mrelease
449 i386 futex_waitv sys_futex_waitv
450 i386 set_mempolicy_home_node sys_set_mempolicy_home_node
+451 i386 lsm_get_self_attr sys_lsm_get_self_attr
+452 i386 lsm_module_list sys_lsm_module_list
+453 i386 lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
index c84d12608cd2..3a7866f72042 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
@@ -372,6 +372,9 @@
448 common process_mrelease sys_process_mrelease
449 common futex_waitv sys_futex_waitv
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+451 common lsm_get_self_attr sys_lsm_get_self_attr
+452 common lsm_module_list sys_lsm_module_list
+453 common lsm_set_self_attr sys_lsm_set_self_attr

#
# Due to a historical design error, certain syscalls are numbered differently
diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl
index 52c94ab5c205..e0a5b61c1f1a 100644
--- a/arch/xtensa/kernel/syscalls/syscall.tbl
+++ b/arch/xtensa/kernel/syscalls/syscall.tbl
@@ -421,3 +421,6 @@
448 common process_mrelease sys_process_mrelease
449 common futex_waitv sys_futex_waitv
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+451 common lsm_get_self_attr sys_lsm_get_self_attr
+452 common lsm_module_list sys_lsm_module_list
+453 common lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index 45fa180cc56a..3659b2b02f5a 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -886,8 +886,17 @@ __SYSCALL(__NR_futex_waitv, sys_futex_waitv)
#define __NR_set_mempolicy_home_node 450
__SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node)

+#define __NR_lsm_get_self_attr 451
+__SYSCALL(__NR_lsm_get_self_attr, sys_lsm_get_self_attr)
+
+#define __NR_lsm_module_list 452
+__SYSCALL(__NR_lsm_module_list, sys_lsm_module_list)
+
+#define __NR_lsm_set_self_attr 453
+__SYSCALL(__NR_lsm_set_self_attr, sys_lsm_set_self_attr)
+
#undef __NR_syscalls
-#define __NR_syscalls 451
+#define __NR_syscalls 454

/*
* 32 bit systems traditionally used different
diff --git a/tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl b/tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
index 3f1886ad9d80..99453966d179 100644
--- a/tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
+++ b/tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
@@ -365,3 +365,6 @@
448 n64 process_mrelease sys_process_mrelease
449 n64 futex_waitv sys_futex_waitv
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+451 n64 lsm_get_self_attr sys_lsm_get_self_attr
+452 n64 lsm_module_list sys_lsm_module_list
+453 n64 lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
index a0be127475b1..8d31bb83d6a2 100644
--- a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
+++ b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
@@ -537,3 +537,6 @@
448 common process_mrelease sys_process_mrelease
449 common futex_waitv sys_futex_waitv
450 nospu set_mempolicy_home_node sys_set_mempolicy_home_node
+451 common lsm_get_self_attr sys_lsm_get_self_attr
+452 common lsm_module_list sys_lsm_module_list
+453 common lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/tools/perf/arch/s390/entry/syscalls/syscall.tbl b/tools/perf/arch/s390/entry/syscalls/syscall.tbl
index 799147658dee..d69bd5550b46 100644
--- a/tools/perf/arch/s390/entry/syscalls/syscall.tbl
+++ b/tools/perf/arch/s390/entry/syscalls/syscall.tbl
@@ -453,3 +453,6 @@
448 common process_mrelease sys_process_mrelease sys_process_mrelease
449 common futex_waitv sys_futex_waitv sys_futex_waitv
450 common set_mempolicy_home_node sys_set_mempolicy_home_node sys_set_mempolicy_home_node
+451 common lsm_get_self_attr sys_lsm_get_self_attr sys_lsm_get_self_attr
+452 common lsm_module_list sys_lsm_module_list sys_lsm_module_list
+453 common lsm_set_self_attr sys_lsm_set_self_attr sys_lsm_set_self_attr
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
index c84d12608cd2..3a7866f72042 100644
--- a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
@@ -372,6 +372,9 @@
448 common process_mrelease sys_process_mrelease
449 common futex_waitv sys_futex_waitv
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+451 common lsm_get_self_attr sys_lsm_get_self_attr
+452 common lsm_module_list sys_lsm_module_list
+453 common lsm_set_self_attr sys_lsm_set_self_attr

#
# Due to a historical design error, certain syscalls are numbered differently
--
2.39.0


2023-02-22 20:12:30

by Casey Schaufler

[permalink] [raw]
Subject: [PATCH v6 07/11] LSM: Helpers for attribute names and filling an lsm_ctx

Add lsm_name_to_attr(), which translates a text string to a
LSM_ATTR value if one is available.

Add lsm_fill_user_ctx(), which fills a struct lsm_ctx, including
the trailing attribute value.

Both are used in module specific components of LSM system calls.

Signed-off-by: Casey Schaufler <[email protected]>
---
include/linux/security.h | 13 +++++++++++++
security/security.c | 31 +++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+)

diff --git a/include/linux/security.h b/include/linux/security.h
index 21971a635b6a..bf615981b147 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -264,6 +264,7 @@ int unregister_blocking_lsm_notifier(struct notifier_block *nb);
/* prototypes */
extern int security_init(void);
extern int early_security_init(void);
+extern u64 lsm_name_to_attr(const char *name);

/* Security operations */
int security_binder_set_context_mgr(const struct cred *mgr);
@@ -493,6 +494,8 @@ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
int security_locked_down(enum lockdown_reason what);
+int lsm_fill_user_ctx(struct lsm_ctx __user *ctx, void *context,
+ size_t context_size, u64 id, u64 flags);
#else /* CONFIG_SECURITY */

static inline int call_blocking_lsm_notifier(enum lsm_event event, void *data)
@@ -510,6 +513,11 @@ static inline int unregister_blocking_lsm_notifier(struct notifier_block *nb)
return 0;
}

+static inline u64 lsm_name_to_attr(const char *name)
+{
+ return 0;
+}
+
static inline void security_free_mnt_opts(void **mnt_opts)
{
}
@@ -1422,6 +1430,11 @@ static inline int security_locked_down(enum lockdown_reason what)
{
return 0;
}
+static inline int lsm_fill_user_ctx(struct lsm_ctx __user *ctx, void *context,
+ size_t context_size, u64 id, u64 flags)
+{
+ return 0;
+}
#endif /* CONFIG_SECURITY */

#if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE)
diff --git a/security/security.c b/security/security.c
index 6823a6cb32a9..48c883c8d340 100644
--- a/security/security.c
+++ b/security/security.c
@@ -753,6 +753,37 @@ static int lsm_superblock_alloc(struct super_block *sb)
return 0;
}

+/**
+ * lsm_fill_user_ctx - Fill a user space lsm_ctx structure
+ * @ctx: an LSM context to be filled
+ * @context: the new context value
+ * @context_size: the size of the new context value
+ * @id: LSM id
+ * @flags: LSM defined flags
+ *
+ * Fill all of the fields in a user space lsm_ctx structure.
+ * Caller is assumed to have verified that @ctx has enough space
+ * for @context.
+ * Returns 0 on success, -EFAULT on a copyout error.
+ */
+int lsm_fill_user_ctx(struct lsm_ctx __user *ctx, void *context,
+ size_t context_size, u64 id, u64 flags)
+{
+ struct lsm_ctx local;
+ void __user *vc = ctx;
+
+ local.id = id;
+ local.flags = flags;
+ local.ctx_len = context_size;
+ local.len = context_size + sizeof(local);
+ vc += sizeof(local);
+ if (copy_to_user(ctx, &local, sizeof(local)))
+ return -EFAULT;
+ if (context_size > 0 && copy_to_user(vc, context, context_size))
+ return -EFAULT;
+ return 0;
+}
+
/*
* The default value of the LSM hook is defined in linux/lsm_hook_defs.h and
* can be accessed with:
--
2.39.0


2023-02-22 20:12:39

by Casey Schaufler

[permalink] [raw]
Subject: [PATCH v6 08/11] Smack: implement setselfattr and getselfattr hooks

Implement Smack support for security_[gs]etselfattr.
Refactor the setprocattr hook to avoid code duplication.

Signed-off-by: Casey Schaufler <[email protected]>
---
security/smack/smack_lsm.c | 87 ++++++++++++++++++++++++++++++++++++--
1 file changed, 83 insertions(+), 4 deletions(-)

diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index a27157910fe7..b4cadc7244ab 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3552,6 +3552,38 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
return;
}

+/**
+ * smack_getselfattr - Smack current process attribute
+ * @p: the object task
+ * @name: the name of the attribute in /proc/.../attr
+ * @value: where to put the result
+ *
+ * Places a copy of the task Smack into value
+ *
+ * Returns the length of the smack label or an error code
+ */
+static int smack_getselfattr(u64 __user attr, struct lsm_ctx __user *ctx,
+ size_t *size)
+{
+ struct smack_known *skp = smk_of_current();
+ int total;
+ int slen;
+ int rc = 0;
+
+ if (attr != LSM_ATTR_CURRENT)
+ return -EINVAL;
+
+ slen = strlen(skp->smk_known) + 1;
+ total = slen + sizeof(*ctx);
+ if (total > *size)
+ rc = -E2BIG;
+ else
+ lsm_fill_user_ctx(ctx, skp->smk_known, slen, LSM_ID_SMACK, 0);
+
+ *size = total;
+ return rc;
+}
+
/**
* smack_getprocattr - Smack process attribute access
* @p: the object task
@@ -3581,8 +3613,8 @@ static int smack_getprocattr(struct task_struct *p, const char *name, char **val
}

/**
- * smack_setprocattr - Smack process attribute setting
- * @name: the name of the attribute in /proc/.../attr
+ * do_setattr - Smack process attribute setting
+ * @attr: the ID of the attribute
* @value: the value to set
* @size: the size of the value
*
@@ -3591,7 +3623,7 @@ static int smack_getprocattr(struct task_struct *p, const char *name, char **val
*
* Returns the length of the smack label or an error code
*/
-static int smack_setprocattr(const char *name, void *value, size_t size)
+static int do_setattr(u64 attr, void *value, size_t size)
{
struct task_smack *tsp = smack_cred(current_cred());
struct cred *new;
@@ -3605,7 +3637,7 @@ static int smack_setprocattr(const char *name, void *value, size_t size)
if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
return -EINVAL;

- if (strcmp(name, "current") != 0)
+ if (attr != LSM_ATTR_CURRENT)
return -EINVAL;

skp = smk_import_entry(value, size);
@@ -3645,6 +3677,51 @@ static int smack_setprocattr(const char *name, void *value, size_t size)
return size;
}

+static int smack_setselfattr(u64 __user attr, struct lsm_ctx __user *ctx,
+ size_t __user size)
+{
+ struct lsm_ctx *lctx;
+ void *context;
+ int rc;
+
+ context = kmalloc(size, GFP_KERNEL);
+ if (context == NULL)
+ return -ENOMEM;
+
+ lctx = (struct lsm_ctx *)context;
+ if (copy_from_user(context, ctx, size))
+ rc = -EFAULT;
+ else if (lctx->ctx_len > size)
+ rc = -EINVAL;
+ else
+ rc = do_setattr(attr, lctx + 1, lctx->ctx_len);
+
+ kfree(context);
+ if (rc > 0)
+ return 0;
+ return rc;
+}
+
+/**
+ * smack_setprocattr - Smack process attribute setting
+ * @name: the name of the attribute in /proc/.../attr
+ * @value: the value to set
+ * @size: the size of the value
+ *
+ * Sets the Smack value of the task. Only setting self
+ * is permitted and only with privilege
+ *
+ * Returns the length of the smack label or an error code
+ */
+static int smack_setprocattr(const char *name, void *value, size_t size)
+{
+ int attr = lsm_name_to_attr(name);
+
+ if (attr)
+ return do_setattr(attr, value, size);
+ return -EINVAL;
+}
+
/**
* smack_unix_stream_connect - Smack access on UDS
* @sock: one sock
@@ -4956,6 +5033,8 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {

LSM_HOOK_INIT(d_instantiate, smack_d_instantiate),

+ LSM_HOOK_INIT(getselfattr, smack_getselfattr),
+ LSM_HOOK_INIT(setselfattr, smack_setselfattr),
LSM_HOOK_INIT(getprocattr, smack_getprocattr),
LSM_HOOK_INIT(setprocattr, smack_setprocattr),

--
2.39.0


2023-02-22 20:14:00

by Casey Schaufler

[permalink] [raw]
Subject: [PATCH v6 09/11] AppArmor: Add selfattr hooks

Add hooks for setselfattr and getselfattr. These hooks are not very
different from their setprocattr and getprocattr equivalents, and
much of the code is shared.

Signed-off-by: Casey Schaufler <[email protected]>
---
security/apparmor/include/procattr.h | 2 +-
security/apparmor/lsm.c | 91 ++++++++++++++++++++++++++--
security/apparmor/procattr.c | 11 +++-
3 files changed, 94 insertions(+), 10 deletions(-)

diff --git a/security/apparmor/include/procattr.h b/security/apparmor/include/procattr.h
index 31689437e0e1..03dbfdb2f2c0 100644
--- a/security/apparmor/include/procattr.h
+++ b/security/apparmor/include/procattr.h
@@ -11,7 +11,7 @@
#ifndef __AA_PROCATTR_H
#define __AA_PROCATTR_H

-int aa_getprocattr(struct aa_label *label, char **string);
+int aa_getprocattr(struct aa_label *label, char **string, bool newline);
int aa_setprocattr_changehat(char *args, size_t size, int flags);

#endif /* __AA_PROCATTR_H */
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 0c2f4d47af42..165fffff095a 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -632,6 +632,44 @@ static int apparmor_sb_pivotroot(const struct path *old_path,
return error;
}

+static int apparmor_getselfattr(u64 __user attr, struct lsm_ctx __user *lx,
+ size_t *size)
+{
+ int error = -ENOENT;
+ struct aa_task_ctx *ctx = task_ctx(current);
+ struct aa_label *label = NULL;
+ size_t total_len;
+ char *value;
+
+ if (attr == LSM_ATTR_CURRENT)
+ label = aa_get_newest_label(cred_label(current_cred()));
+ else if (attr == LSM_ATTR_PREV && ctx->previous)
+ label = aa_get_newest_label(ctx->previous);
+ else if (attr == LSM_ATTR_EXEC && ctx->onexec)
+ label = aa_get_newest_label(ctx->onexec);
+ else
+ error = -EOPNOTSUPP;
+
+ if (label) {
+ error = aa_getprocattr(label, &value, false);
+ if (error > 0) {
+ total_len = error + sizeof(*ctx);
+ if (total_len > *size)
+ error = -E2BIG;
+ else
+ lsm_fill_user_ctx(lx, value, error,
+ LSM_ID_APPARMOR, 0);
+ }
+ }
+
+ aa_put_label(label);
+
+ *size = total_len;
+ if (error > 0)
+ return 0;
+ return error;
+}
+
static int apparmor_getprocattr(struct task_struct *task, const char *name,
char **value)
{
@@ -651,7 +689,7 @@ static int apparmor_getprocattr(struct task_struct *task, const char *name,
error = -EINVAL;

if (label)
- error = aa_getprocattr(label, value);
+ error = aa_getprocattr(label, value, true);

aa_put_label(label);
put_cred(cred);
@@ -659,8 +697,7 @@ static int apparmor_getprocattr(struct task_struct *task, const char *name,
return error;
}

-static int apparmor_setprocattr(const char *name, void *value,
- size_t size)
+static int do_setattr(u64 attr, void *value, size_t size)
{
char *command, *largs = NULL, *args = value;
size_t arg_size;
@@ -691,7 +728,7 @@ static int apparmor_setprocattr(const char *name, void *value,
goto out;

arg_size = size - (args - (largs ? largs : (char *) value));
- if (strcmp(name, "current") == 0) {
+ if (attr == LSM_ATTR_CURRENT) {
if (strcmp(command, "changehat") == 0) {
error = aa_setprocattr_changehat(args, arg_size,
AA_CHANGE_NOFLAGS);
@@ -706,7 +743,7 @@ static int apparmor_setprocattr(const char *name, void *value,
error = aa_change_profile(args, AA_CHANGE_STACK);
} else
goto fail;
- } else if (strcmp(name, "exec") == 0) {
+ } else if (attr == LSM_ATTR_EXEC) {
if (strcmp(command, "exec") == 0)
error = aa_change_profile(args, AA_CHANGE_ONEXEC);
else if (strcmp(command, "stack") == 0)
@@ -726,13 +763,53 @@ static int apparmor_setprocattr(const char *name, void *value,

fail:
aad(&sa)->label = begin_current_label_crit_section();
- aad(&sa)->info = name;
+ if (attr == LSM_ATTR_CURRENT)
+ aad(&sa)->info = "current";
+ else if (attr == LSM_ATTR_EXEC)
+ aad(&sa)->info = "exec";
+ else
+ aad(&sa)->info = "invalid";
aad(&sa)->error = error = -EINVAL;
aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL);
end_current_label_crit_section(aad(&sa)->label);
goto out;
}

+static int apparmor_setselfattr(u64 __user attr, struct lsm_ctx __user *ctx,
+ size_t __user size)
+{
+ struct lsm_ctx *lctx;
+ void *context;
+ int rc;
+
+ context = kmalloc(size, GFP_KERNEL);
+ if (context == NULL)
+ return -ENOMEM;
+
+ lctx = (struct lsm_ctx *)context;
+ if (copy_from_user(context, ctx, size))
+ rc = -EFAULT;
+ else if (lctx->ctx_len > size)
+ rc = -EINVAL;
+ else
+ rc = do_setattr(attr, lctx + 1, lctx->ctx_len);
+
+ kfree(context);
+ if (rc > 0)
+ return 0;
+ return rc;
+}
+
+static int apparmor_setprocattr(const char *name, void *value,
+ size_t size)
+{
+ int attr = lsm_name_to_attr(name);
+
+ if (attr)
+ return do_setattr(attr, value, size);
+ return -EINVAL;
+}
+
/**
* apparmor_bprm_committing_creds - do task cleanup on committing new creds
* @bprm: binprm for the exec (NOT NULL)
@@ -1256,6 +1333,8 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(file_lock, apparmor_file_lock),
LSM_HOOK_INIT(file_truncate, apparmor_file_truncate),

+ LSM_HOOK_INIT(getselfattr, apparmor_getselfattr),
+ LSM_HOOK_INIT(setselfattr, apparmor_setselfattr),
LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),

diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c
index 197d41f9c32b..196f319aa3b2 100644
--- a/security/apparmor/procattr.c
+++ b/security/apparmor/procattr.c
@@ -20,6 +20,7 @@
* aa_getprocattr - Return the label information for @label
* @label: the label to print label info about (NOT NULL)
* @string: Returns - string containing the label info (NOT NULL)
+ * @newline: indicates that a newline should be added
*
* Requires: label != NULL && string != NULL
*
@@ -27,7 +28,7 @@
*
* Returns: size of string placed in @string else error code on failure
*/
-int aa_getprocattr(struct aa_label *label, char **string)
+int aa_getprocattr(struct aa_label *label, char **string, bool newline)
{
struct aa_ns *ns = labels_ns(label);
struct aa_ns *current_ns = aa_get_current_ns();
@@ -57,10 +58,14 @@ int aa_getprocattr(struct aa_label *label, char **string)
return len;
}

- (*string)[len] = '\n';
- (*string)[len + 1] = 0;
+ if (newline)
+ (*string)[len++] = '\n';
+ (*string)[len] = 0;

aa_put_ns(current_ns);
+
+ if (newline)
+ return len;
return len + 1;
}

--
2.39.0


2023-02-22 20:14:04

by Casey Schaufler

[permalink] [raw]
Subject: [PATCH v6 10/11] SELinux: Add selfattr hooks

Add hooks for setselfattr and getselfattr. These hooks are not very
different from their setprocattr and getprocattr equivalents, and
much of the code is shared.

Signed-off-by: Casey Schaufler <[email protected]>
---
security/selinux/hooks.c | 143 +++++++++++++++++++++++++++++++--------
1 file changed, 114 insertions(+), 29 deletions(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 5cb09986a2dc..b95bbd7bb662 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6348,8 +6348,7 @@ static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
inode_doinit_with_dentry(inode, dentry);
}

-static int selinux_getprocattr(struct task_struct *p,
- const char *name, char **value)
+static int do_getattr(u64 attr, struct task_struct *p, char **value)
{
const struct task_security_struct *__tsec;
u32 sid;
@@ -6367,20 +6366,27 @@ static int selinux_getprocattr(struct task_struct *p,
goto bad;
}

- if (!strcmp(name, "current"))
+ switch (attr) {
+ case LSM_ATTR_CURRENT:
sid = __tsec->sid;
- else if (!strcmp(name, "prev"))
+ break;
+ case LSM_ATTR_PREV:
sid = __tsec->osid;
- else if (!strcmp(name, "exec"))
+ break;
+ case LSM_ATTR_EXEC:
sid = __tsec->exec_sid;
- else if (!strcmp(name, "fscreate"))
+ break;
+ case LSM_ATTR_FSCREATE:
sid = __tsec->create_sid;
- else if (!strcmp(name, "keycreate"))
+ break;
+ case LSM_ATTR_KEYCREATE:
sid = __tsec->keycreate_sid;
- else if (!strcmp(name, "sockcreate"))
+ break;
+ case LSM_ATTR_SOCKCREATE:
sid = __tsec->sockcreate_sid;
- else {
- error = -EINVAL;
+ break;
+ default:
+ error = -EOPNOTSUPP;
goto bad;
}
rcu_read_unlock();
@@ -6398,7 +6404,7 @@ static int selinux_getprocattr(struct task_struct *p,
return error;
}

-static int selinux_setprocattr(const char *name, void *value, size_t size)
+static int do_setattr(u64 attr, void *value, size_t size)
{
struct task_security_struct *tsec;
struct cred *new;
@@ -6409,28 +6415,36 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
/*
* Basic control over ability to set these attributes at all.
*/
- if (!strcmp(name, "exec"))
+ switch (attr) {
+ case LSM_ATTR_CURRENT:
+ error = avc_has_perm(&selinux_state,
+ mysid, mysid, SECCLASS_PROCESS,
+ PROCESS__SETCURRENT, NULL);
+ break;
+ case LSM_ATTR_EXEC:
error = avc_has_perm(&selinux_state,
mysid, mysid, SECCLASS_PROCESS,
PROCESS__SETEXEC, NULL);
- else if (!strcmp(name, "fscreate"))
+ break;
+ case LSM_ATTR_FSCREATE:
error = avc_has_perm(&selinux_state,
mysid, mysid, SECCLASS_PROCESS,
PROCESS__SETFSCREATE, NULL);
- else if (!strcmp(name, "keycreate"))
+ break;
+ case LSM_ATTR_KEYCREATE:
error = avc_has_perm(&selinux_state,
mysid, mysid, SECCLASS_PROCESS,
PROCESS__SETKEYCREATE, NULL);
- else if (!strcmp(name, "sockcreate"))
+ break;
+ case LSM_ATTR_SOCKCREATE:
error = avc_has_perm(&selinux_state,
mysid, mysid, SECCLASS_PROCESS,
PROCESS__SETSOCKCREATE, NULL);
- else if (!strcmp(name, "current"))
- error = avc_has_perm(&selinux_state,
- mysid, mysid, SECCLASS_PROCESS,
- PROCESS__SETCURRENT, NULL);
- else
+ break;
+ default:
error = -EINVAL;
+ break;
+ }
if (error)
return error;

@@ -6442,13 +6456,14 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
}
error = security_context_to_sid(&selinux_state, value, size,
&sid, GFP_KERNEL);
- if (error == -EINVAL && !strcmp(name, "fscreate")) {
+ if (error == -EINVAL && attr == LSM_ATTR_FSCREATE) {
if (!has_cap_mac_admin(true)) {
struct audit_buffer *ab;
size_t audit_size;

- /* We strip a nul only if it is at the end, otherwise the
- * context contains a nul and we should audit that */
+ /* We strip a nul only if it is at the end,
+ * otherwise the context contains a nul and
+ * we should audit that */
if (str[size - 1] == '\0')
audit_size = size - 1;
else
@@ -6459,7 +6474,8 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
if (!ab)
return error;
audit_log_format(ab, "op=fscreate invalid_context=");
- audit_log_n_untrustedstring(ab, value, audit_size);
+ audit_log_n_untrustedstring(ab, value,
+ audit_size);
audit_log_end(ab);

return error;
@@ -6483,11 +6499,11 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
checks and may_create for the file creation checks. The
operation will then fail if the context is not permitted. */
tsec = selinux_cred(new);
- if (!strcmp(name, "exec")) {
+ if (attr == LSM_ATTR_EXEC) {
tsec->exec_sid = sid;
- } else if (!strcmp(name, "fscreate")) {
+ } else if (attr == LSM_ATTR_FSCREATE) {
tsec->create_sid = sid;
- } else if (!strcmp(name, "keycreate")) {
+ } else if (attr == LSM_ATTR_KEYCREATE) {
if (sid) {
error = avc_has_perm(&selinux_state, mysid, sid,
SECCLASS_KEY, KEY__CREATE, NULL);
@@ -6495,9 +6511,9 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
goto abort_change;
}
tsec->keycreate_sid = sid;
- } else if (!strcmp(name, "sockcreate")) {
+ } else if (attr == LSM_ATTR_SOCKCREATE) {
tsec->sockcreate_sid = sid;
- } else if (!strcmp(name, "current")) {
+ } else if (attr == LSM_ATTR_CURRENT) {
error = -EINVAL;
if (sid == 0)
goto abort_change;
@@ -6542,6 +6558,73 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
return error;
}

+static int selinux_getselfattr(u64 __user attr, struct lsm_ctx __user *ctx,
+ size_t *size)
+{
+ char *value;
+ int total_len;
+ int len;
+ int rc = 0;
+
+ len = do_getattr(attr, current, &value);
+ if (len < 0)
+ return len;
+
+ total_len = len + sizeof(*ctx);
+
+ if (total_len > *size)
+ rc = -E2BIG;
+ else
+ lsm_fill_user_ctx(ctx, value, len, LSM_ID_SELINUX, 0);
+
+ *size = total_len;
+ return rc;
+}
+
+static int selinux_setselfattr(u64 __user attr, struct lsm_ctx __user *ctx,
+ size_t __user size)
+{
+ struct lsm_ctx *lctx;
+ void *context;
+ int rc;
+
+ context = kmalloc(size, GFP_KERNEL);
+ if (context == NULL)
+ return -ENOMEM;
+
+ lctx = (struct lsm_ctx *)context;
+ if (copy_from_user(context, ctx, size))
+ rc = -EFAULT;
+ else if (lctx->ctx_len > size)
+ rc = -EINVAL;
+ else
+ rc = do_setattr(attr, lctx + 1, lctx->ctx_len);
+
+ kfree(context);
+ if (rc > 0)
+ return 0;
+ return rc;
+}
+
+static int selinux_getprocattr(struct task_struct *p,
+ const char *name, char **value)
+{
+ u64 attr = lsm_name_to_attr(name);
+
+ if (attr)
+ return do_getattr(attr, p, value);
+ return -EINVAL;
+}
+
+static int selinux_setprocattr(const char *name, void *value, size_t size)
+{
+ int attr = lsm_name_to_attr(name);
+
+ if (attr)
+ return do_setattr(attr, value, size);
+ return -EINVAL;
+}
+
static int selinux_ismaclabel(const char *name)
{
return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
@@ -7185,6 +7268,8 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {

LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),

+ LSM_HOOK_INIT(getselfattr, selinux_getselfattr),
+ LSM_HOOK_INIT(setselfattr, selinux_setselfattr),
LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
LSM_HOOK_INIT(setprocattr, selinux_setprocattr),

--
2.39.0


2023-02-22 20:14:11

by Casey Schaufler

[permalink] [raw]
Subject: [PATCH v6 11/11] LSM: selftests for Linux Security Module syscalls

Add selftests for the three system calls supporting the LSM
infrastructure.

Signed-off-by: Casey Schaufler <[email protected]>
---
tools/testing/selftests/Makefile | 1 +
tools/testing/selftests/lsm/Makefile | 12 +
tools/testing/selftests/lsm/config | 2 +
.../selftests/lsm/lsm_get_self_attr_test.c | 267 ++++++++++++++++++
.../selftests/lsm/lsm_module_list_test.c | 149 ++++++++++
.../selftests/lsm/lsm_set_self_attr_test.c | 69 +++++
6 files changed, 500 insertions(+)
create mode 100644 tools/testing/selftests/lsm/Makefile
create mode 100644 tools/testing/selftests/lsm/config
create mode 100644 tools/testing/selftests/lsm/lsm_get_self_attr_test.c
create mode 100644 tools/testing/selftests/lsm/lsm_module_list_test.c
create mode 100644 tools/testing/selftests/lsm/lsm_set_self_attr_test.c

diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 41b649452560..ea58c5018529 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -37,6 +37,7 @@ TARGETS += landlock
TARGETS += lib
TARGETS += livepatch
TARGETS += lkdtm
+TARGETS += lsm
TARGETS += membarrier
TARGETS += memfd
TARGETS += memory-hotplug
diff --git a/tools/testing/selftests/lsm/Makefile b/tools/testing/selftests/lsm/Makefile
new file mode 100644
index 000000000000..d567ea9756ea
--- /dev/null
+++ b/tools/testing/selftests/lsm/Makefile
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# First run: make -C ../../../.. headers_install
+
+CFLAGS += -Wall -O2 $(KHDR_INCLUDES)
+
+TEST_GEN_PROGS := lsm_get_self_attr_test lsm_module_list_test \
+ lsm_set_self_attr_test
+
+include ../lib.mk
+
+$(TEST_GEN_PROGS):
diff --git a/tools/testing/selftests/lsm/config b/tools/testing/selftests/lsm/config
new file mode 100644
index 000000000000..afb887715f64
--- /dev/null
+++ b/tools/testing/selftests/lsm/config
@@ -0,0 +1,2 @@
+CONFIG_SYSFS=y
+CONFIG_SECURITY=y
diff --git a/tools/testing/selftests/lsm/lsm_get_self_attr_test.c b/tools/testing/selftests/lsm/lsm_get_self_attr_test.c
new file mode 100644
index 000000000000..72f02a210fa6
--- /dev/null
+++ b/tools/testing/selftests/lsm/lsm_get_self_attr_test.c
@@ -0,0 +1,267 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Linux Security Module infrastructure tests
+ * Tests for the lsm_get_self_attr system call
+ *
+ * Copyright © 2022 Casey Schaufler <[email protected]>
+ * Copyright © 2022 Intel Corporation
+ */
+
+#define _GNU_SOURCE
+#include <linux/lsm.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "../kselftest_harness.h"
+
+#define PROCATTR "/proc/self/attr/"
+
+static int read_proc_attr(const char *attr, char *value, __kernel_size_t size)
+{
+ int fd;
+ int len;
+ char *path;
+
+ len = strlen(PROCATTR) + strlen(attr) + 1;
+ path = calloc(len, 1);
+ if (path == NULL)
+ return -1;
+ sprintf(path, "%s%s", PROCATTR, attr);
+
+ fd = open(path, O_RDONLY);
+ free(path);
+
+ if (fd < 0)
+ return -1;
+ len = read(fd, value, size);
+ if (len <= 0)
+ return -1;
+fprintf(stderr, "len=%d\n", len);
+ close(fd);
+
+ path = strchr(value, '\n');
+ if (path)
+ *path = '\0';
+
+ return 0;
+}
+
+static struct lsm_ctx *next_ctx(struct lsm_ctx *ctxp)
+{
+ void *vp;
+
+ vp = (void *)ctxp + sizeof(*ctxp) + ctxp->ctx_len;
+ return (struct lsm_ctx *)vp;
+}
+
+TEST(size_null_lsm_get_self_attr)
+{
+ const long page_size = sysconf(_SC_PAGESIZE);
+ char *ctx = calloc(page_size, 1);
+
+ ASSERT_NE(NULL, ctx);
+ ASSERT_EQ(-1, syscall(__NR_lsm_get_self_attr, ctx, NULL,
+ LSM_ATTR_CURRENT));
+ ASSERT_EQ(EINVAL, errno);
+
+ free(ctx);
+}
+
+TEST(ctx_null_lsm_get_self_attr)
+{
+ const long page_size = sysconf(_SC_PAGESIZE);
+ __kernel_size_t size = page_size;
+
+ ASSERT_NE(-1, syscall(__NR_lsm_get_self_attr, NULL, &size,
+ LSM_ATTR_CURRENT));
+ ASSERT_NE(1, size);
+}
+
+TEST(size_too_small_lsm_get_self_attr)
+{
+ const long page_size = sysconf(_SC_PAGESIZE);
+ char *ctx = calloc(page_size, 1);
+ __kernel_size_t size = 1;
+
+ ASSERT_NE(NULL, ctx);
+ ASSERT_EQ(-1, syscall(__NR_lsm_get_self_attr, ctx, &size,
+ LSM_ATTR_CURRENT));
+ ASSERT_EQ(E2BIG, errno);
+ ASSERT_NE(1, size);
+
+ free(ctx);
+}
+
+TEST(flags_zero_lsm_get_self_attr)
+{
+ const long page_size = sysconf(_SC_PAGESIZE);
+ char *ctx = calloc(page_size, 1);
+ __kernel_size_t size = page_size;
+
+ ASSERT_NE(NULL, ctx);
+ ASSERT_EQ(-1, syscall(__NR_lsm_get_self_attr, ctx, &size, 0));
+ ASSERT_EQ(EINVAL, errno);
+ ASSERT_EQ(page_size, size);
+
+ free(ctx);
+}
+
+TEST(flags_overset_lsm_get_self_attr)
+{
+ const long page_size = sysconf(_SC_PAGESIZE);
+ char *ctx = calloc(page_size, 1);
+ __kernel_size_t size = page_size;
+
+ ASSERT_NE(NULL, ctx);
+ ASSERT_EQ(-1, syscall(__NR_lsm_get_self_attr, ctx, &size,
+ LSM_ATTR_CURRENT | LSM_ATTR_PREV));
+ ASSERT_EQ(EOPNOTSUPP, errno);
+ ASSERT_EQ(page_size, size);
+
+ free(ctx);
+}
+
+TEST(basic_lsm_get_self_attr)
+{
+ const long page_size = sysconf(_SC_PAGESIZE);
+ __kernel_size_t size = page_size;
+ struct lsm_ctx *ctx = calloc(page_size, 1);
+ struct lsm_ctx *tctx = NULL;
+ __u64 *syscall_lsms = calloc(page_size, 1);
+ char *attr = calloc(page_size, 1);
+ int cnt_current = 0;
+ int cnt_exec = 0;
+ int cnt_fscreate = 0;
+ int cnt_keycreate = 0;
+ int cnt_prev = 0;
+ int cnt_sockcreate = 0;
+ int lsmcount;
+ int count;
+ int i;
+
+ ASSERT_NE(NULL, ctx);
+ ASSERT_NE(NULL, syscall_lsms);
+
+ lsmcount = syscall(__NR_lsm_module_list, syscall_lsms, &size, 0);
+ ASSERT_LE(1, lsmcount);
+
+ for (i = 0; i < lsmcount; i++) {
+ switch (syscall_lsms[i]) {
+ case LSM_ID_SELINUX:
+ cnt_current++;
+ cnt_exec++;
+ cnt_fscreate++;
+ cnt_keycreate++;
+ cnt_prev++;
+ cnt_sockcreate++;
+ break;
+ case LSM_ID_SMACK:
+ cnt_current++;
+ break;
+ case LSM_ID_APPARMOR:
+ cnt_current++;
+ cnt_exec++;
+ cnt_prev++;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (cnt_current) {
+ size = page_size;
+ count = syscall(__NR_lsm_get_self_attr, ctx, &size,
+ LSM_ATTR_CURRENT);
+ ASSERT_EQ(cnt_current, count);
+ tctx = ctx;
+ ASSERT_EQ(0, read_proc_attr("current", attr, page_size));
+ ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr));
+ for (i = 1; i < count; i++) {
+ tctx = next_ctx(tctx);
+ ASSERT_NE(0, strcmp((char *)tctx->ctx, attr));
+ }
+ }
+ if (cnt_exec) {
+ size = page_size;
+ count = syscall(__NR_lsm_get_self_attr, ctx, &size,
+ LSM_ATTR_EXEC);
+ ASSERT_GE(cnt_exec, count);
+ if (count > 0) {
+ tctx = ctx;
+ if (read_proc_attr("exec", attr, page_size) == 0)
+ ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr));
+ }
+ for (i = 1; i < count; i++) {
+ tctx = next_ctx(tctx);
+ ASSERT_NE(0, strcmp((char *)tctx->ctx, attr));
+ }
+ }
+ if (cnt_fscreate) {
+ size = page_size;
+ count = syscall(__NR_lsm_get_self_attr, ctx, &size,
+ LSM_ATTR_FSCREATE);
+ ASSERT_GE(cnt_fscreate, count);
+ if (count > 0) {
+ tctx = ctx;
+ if (read_proc_attr("fscreate", attr, page_size) == 0)
+ ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr));
+ }
+ for (i = 1; i < count; i++) {
+ tctx = next_ctx(tctx);
+ ASSERT_NE(0, strcmp((char *)tctx->ctx, attr));
+ }
+ }
+ if (cnt_keycreate) {
+ size = page_size;
+ count = syscall(__NR_lsm_get_self_attr, ctx, &size,
+ LSM_ATTR_KEYCREATE);
+ ASSERT_GE(cnt_keycreate, count);
+ if (count > 0) {
+ tctx = ctx;
+ if (read_proc_attr("keycreate", attr, page_size) == 0)
+ ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr));
+ }
+ for (i = 1; i < count; i++) {
+ tctx = next_ctx(tctx);
+ ASSERT_NE(0, strcmp((char *)tctx->ctx, attr));
+ }
+ }
+ if (cnt_prev) {
+ size = page_size;
+ count = syscall(__NR_lsm_get_self_attr, ctx, &size,
+ LSM_ATTR_PREV);
+ ASSERT_GE(cnt_prev, count);
+ if (count > 0) {
+ tctx = ctx;
+ ASSERT_EQ(0, read_proc_attr("prev", attr, page_size));
+ ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr));
+ for (i = 1; i < count; i++) {
+ tctx = next_ctx(tctx);
+ ASSERT_NE(0, strcmp((char *)tctx->ctx, attr));
+ }
+ }
+ }
+ if (cnt_sockcreate) {
+ size = page_size;
+ count = syscall(__NR_lsm_get_self_attr, ctx, &size,
+ LSM_ATTR_SOCKCREATE);
+ ASSERT_GE(cnt_sockcreate, count);
+ if (count > 0) {
+ tctx = ctx;
+ if (read_proc_attr("sockcreate", attr, page_size) == 0)
+ ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr));
+ }
+ for (i = 1; i < count; i++) {
+ tctx = next_ctx(tctx);
+ ASSERT_NE(0, strcmp((char *)tctx->ctx, attr));
+ }
+ }
+
+ free(ctx);
+ free(attr);
+ free(syscall_lsms);
+}
+
+TEST_HARNESS_MAIN
diff --git a/tools/testing/selftests/lsm/lsm_module_list_test.c b/tools/testing/selftests/lsm/lsm_module_list_test.c
new file mode 100644
index 000000000000..96120b0aed18
--- /dev/null
+++ b/tools/testing/selftests/lsm/lsm_module_list_test.c
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Linux Security Module infrastructure tests
+ * Tests for the lsm_module_list system call
+ *
+ * Copyright © 2022 Casey Schaufler <[email protected]>
+ * Copyright © 2022 Intel Corporation
+ */
+
+#define _GNU_SOURCE
+#include <linux/lsm.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "../kselftest_harness.h"
+
+static int read_sysfs_lsms(char *lsms, __kernel_size_t size)
+{
+ FILE *fp;
+
+ fp = fopen("/sys/kernel/security/lsm", "r");
+ if (fp == NULL)
+ return -1;
+ if (fread(lsms, 1, size, fp) <= 0)
+ return -1;
+ fclose(fp);
+ return 0;
+}
+
+TEST(size_null_lsm_module_list)
+{
+ const long page_size = sysconf(_SC_PAGESIZE);
+ char *syscall_lsms = calloc(page_size, 1);
+
+ ASSERT_NE(NULL, syscall_lsms);
+ ASSERT_EQ(-1, syscall(__NR_lsm_module_list, syscall_lsms, NULL, 0));
+ ASSERT_EQ(EFAULT, errno);
+
+ free(syscall_lsms);
+}
+
+TEST(ids_null_lsm_module_list)
+{
+ const long page_size = sysconf(_SC_PAGESIZE);
+ __kernel_size_t size = page_size;
+
+ ASSERT_EQ(-1, syscall(__NR_lsm_module_list, NULL, &size, 0));
+ ASSERT_EQ(EFAULT, errno);
+ ASSERT_NE(1, size);
+}
+
+TEST(size_too_small_lsm_module_list)
+{
+ const long page_size = sysconf(_SC_PAGESIZE);
+ char *syscall_lsms = calloc(page_size, 1);
+ __kernel_size_t size = 1;
+
+ ASSERT_NE(NULL, syscall_lsms);
+ ASSERT_EQ(-1, syscall(__NR_lsm_module_list, syscall_lsms, &size, 0));
+ ASSERT_EQ(E2BIG, errno);
+ ASSERT_NE(1, size);
+
+ free(syscall_lsms);
+}
+
+TEST(flags_set_lsm_module_list)
+{
+ const long page_size = sysconf(_SC_PAGESIZE);
+ char *syscall_lsms = calloc(page_size, 1);
+ __kernel_size_t size = page_size;
+
+ ASSERT_NE(NULL, syscall_lsms);
+ ASSERT_EQ(-1, syscall(__NR_lsm_module_list, syscall_lsms, &size, 7));
+ ASSERT_EQ(EINVAL, errno);
+ ASSERT_EQ(page_size, size);
+
+ free(syscall_lsms);
+}
+
+TEST(correct_lsm_module_list)
+{
+ const long page_size = sysconf(_SC_PAGESIZE);
+ __kernel_size_t size = page_size;
+ __u64 *syscall_lsms = calloc(page_size, 1);
+ char *sysfs_lsms = calloc(page_size, 1);
+ char *name;
+ char *cp;
+ int count;
+ int i;
+
+ ASSERT_NE(NULL, sysfs_lsms);
+ ASSERT_NE(NULL, syscall_lsms);
+ ASSERT_EQ(0, read_sysfs_lsms(sysfs_lsms, page_size));
+
+ count = syscall(__NR_lsm_module_list, syscall_lsms, &size, 0);
+ ASSERT_LE(1, count);
+ cp = sysfs_lsms;
+ for (i = 0; i < count; i++) {
+ switch (syscall_lsms[i]) {
+ case LSM_ID_CAPABILITY:
+ name = "capability";
+ break;
+ case LSM_ID_SELINUX:
+ name = "selinux";
+ break;
+ case LSM_ID_SMACK:
+ name = "smack";
+ break;
+ case LSM_ID_TOMOYO:
+ name = "tomoyo";
+ break;
+ case LSM_ID_IMA:
+ name = "ima";
+ break;
+ case LSM_ID_APPARMOR:
+ name = "apparmor";
+ break;
+ case LSM_ID_YAMA:
+ name = "yama";
+ break;
+ case LSM_ID_LOADPIN:
+ name = "loadpin";
+ break;
+ case LSM_ID_SAFESETID:
+ name = "safesetid";
+ break;
+ case LSM_ID_LOCKDOWN:
+ name = "lockdown";
+ break;
+ case LSM_ID_BPF:
+ name = "bpf";
+ break;
+ case LSM_ID_LANDLOCK:
+ name = "landlock";
+ break;
+ default:
+ name = "INVALID";
+ break;
+ }
+ ASSERT_EQ(0, strncmp(cp, name, strlen(name)));
+ cp += strlen(name) + 1;
+ }
+
+ free(sysfs_lsms);
+ free(syscall_lsms);
+}
+
+TEST_HARNESS_MAIN
diff --git a/tools/testing/selftests/lsm/lsm_set_self_attr_test.c b/tools/testing/selftests/lsm/lsm_set_self_attr_test.c
new file mode 100644
index 000000000000..22f5c8664c5f
--- /dev/null
+++ b/tools/testing/selftests/lsm/lsm_set_self_attr_test.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Linux Security Module infrastructure tests
+ * Tests for the lsm_set_self_attr system call
+ *
+ * Copyright © 2022 Casey Schaufler <[email protected]>
+ * Copyright © 2022 Intel Corporation
+ */
+
+#define _GNU_SOURCE
+#include <linux/lsm.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "../kselftest_harness.h"
+
+TEST(ctx_null_lsm_set_self_attr)
+{
+ ASSERT_EQ(-1, syscall(__NR_lsm_set_self_attr, NULL,
+ sizeof(struct lsm_ctx), LSM_ATTR_CURRENT));
+}
+
+TEST(size_too_small_lsm_set_self_attr)
+{
+ const long page_size = sysconf(_SC_PAGESIZE);
+ struct lsm_ctx *ctx = calloc(page_size, 1);
+ __kernel_size_t size = page_size;
+
+ ASSERT_NE(NULL, ctx);
+ ASSERT_GE(1, syscall(__NR_lsm_get_self_attr, ctx, &size,
+ LSM_ATTR_CURRENT));
+ ASSERT_EQ(-1, syscall(__NR_lsm_set_self_attr, ctx, 1,
+ LSM_ATTR_CURRENT));
+
+ free(ctx);
+}
+
+TEST(flags_zero_lsm_set_self_attr)
+{
+ const long page_size = sysconf(_SC_PAGESIZE);
+ char *ctx = calloc(page_size, 1);
+ __kernel_size_t size = page_size;
+
+ ASSERT_NE(NULL, ctx);
+ ASSERT_GE(1, syscall(__NR_lsm_get_self_attr, ctx, &size,
+ LSM_ATTR_CURRENT));
+ ASSERT_EQ(-1, syscall(__NR_lsm_set_self_attr, ctx, size, 0));
+
+ free(ctx);
+}
+
+TEST(flags_overset_lsm_set_self_attr)
+{
+ const long page_size = sysconf(_SC_PAGESIZE);
+ char *ctx = calloc(page_size, 1);
+ __kernel_size_t size = page_size;
+ struct lsm_ctx *tctx = (struct lsm_ctx *)ctx;
+
+ ASSERT_NE(NULL, ctx);
+ ASSERT_GE(1, syscall(__NR_lsm_get_self_attr, tctx, &size,
+ LSM_ATTR_CURRENT));
+ ASSERT_EQ(-1, syscall(__NR_lsm_set_self_attr, tctx, size,
+ LSM_ATTR_CURRENT | LSM_ATTR_PREV));
+
+ free(ctx);
+}
+
+TEST_HARNESS_MAIN
--
2.39.0


2023-02-23 04:58:01

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v6 04/11] LSM: syscalls for current process attributes

Hi Casey,

I love your patch! Yet something to improve:

[auto build test ERROR on tip/perf/core]
[also build test ERROR on acme/perf/core shuah-kselftest/next shuah-kselftest/fixes v6.2]
[cannot apply to linus/master next-20230222]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Casey-Schaufler/LSM-Maintain-a-table-of-LSM-attribute-data/20230223-050902
patch link: https://lore.kernel.org/r/20230222200838.8149-5-casey%40schaufler-ca.com
patch subject: [PATCH v6 04/11] LSM: syscalls for current process attributes
config: um-x86_64_defconfig (https://download.01.org/0day-ci/archive/20230223/[email protected]/config)
compiler: gcc-11 (Debian 11.3.0-8) 11.3.0
reproduce (this is a W=1 build):
# https://github.com/intel-lab-lkp/linux/commit/04ba82c1bd629c2114ad851b4723d6e8b0f9d08f
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Casey-Schaufler/LSM-Maintain-a-table-of-LSM-attribute-data/20230223-050902
git checkout 04ba82c1bd629c2114ad851b4723d6e8b0f9d08f
# save the config file
mkdir build_dir && cp config build_dir/.config
make W=1 O=build_dir ARCH=um SUBARCH=x86_64 olddefconfig
make W=1 O=build_dir ARCH=um SUBARCH=x86_64 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <[email protected]>
| Link: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All errors (new ones prefixed by >>):

In file included from include/linux/perf_event.h:62,
from include/linux/trace_events.h:10,
from include/trace/syscall.h:7,
from include/linux/syscalls.h:89,
from init/main.c:21:
>> include/linux/security.h:1356:1: error: expected identifier or '(' before '{' token
1356 | {
| ^
include/linux/security.h:1363:1: error: expected identifier or '(' before '{' token
1363 | {
| ^
init/main.c:775:20: warning: no previous prototype for 'arch_post_acpi_subsys_init' [-Wmissing-prototypes]
775 | void __init __weak arch_post_acpi_subsys_init(void) { }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
init/main.c:787:20: warning: no previous prototype for 'mem_encrypt_init' [-Wmissing-prototypes]
787 | void __init __weak mem_encrypt_init(void) { }
| ^~~~~~~~~~~~~~~~
init/main.c:789:20: warning: no previous prototype for 'poking_init' [-Wmissing-prototypes]
789 | void __init __weak poking_init(void) { }
| ^~~~~~~~~~~
In file included from include/linux/perf_event.h:62,
from include/linux/trace_events.h:10,
from include/trace/syscall.h:7,
from include/linux/syscalls.h:89,
from init/main.c:21:
include/linux/security.h:1353:19: warning: 'security_getselfattr' declared 'static' but never defined [-Wunused-function]
1353 | static inline int security_getselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
include/linux/security.h:1360:19: warning: 'security_setselfattr' declared 'static' but never defined [-Wunused-function]
1360 | static inline int security_setselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
--
In file included from init/do_mounts.c:9:
>> include/linux/security.h:1356:1: error: expected identifier or '(' before '{' token
1356 | {
| ^
include/linux/security.h:1363:1: error: expected identifier or '(' before '{' token
1363 | {
| ^
In file included from init/do_mounts.c:9:
include/linux/security.h:1353:19: warning: 'security_getselfattr' declared 'static' but never defined [-Wunused-function]
1353 | static inline int security_getselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
include/linux/security.h:1360:19: warning: 'security_setselfattr' declared 'static' but never defined [-Wunused-function]
1360 | static inline int security_setselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
--
In file included from include/net/scm.h:8,
from include/linux/netlink.h:9,
from include/uapi/linux/neighbour.h:6,
from include/linux/netdevice.h:46,
from include/uapi/linux/if_arp.h:27,
from include/linux/if_arp.h:23,
from arch/um/drivers/slirp_kern.c:6:
>> include/linux/security.h:1356:1: error: expected identifier or '(' before '{' token
1356 | {
| ^
include/linux/security.h:1363:1: error: expected identifier or '(' before '{' token
1363 | {
| ^
arch/um/drivers/slirp_kern.c:18:6: warning: no previous prototype for 'slirp_init' [-Wmissing-prototypes]
18 | void slirp_init(struct net_device *dev, void *data)
| ^~~~~~~~~~
In file included from include/net/scm.h:8,
from include/linux/netlink.h:9,
from include/uapi/linux/neighbour.h:6,
from include/linux/netdevice.h:46,
from include/uapi/linux/if_arp.h:27,
from include/linux/if_arp.h:23,
from arch/um/drivers/slirp_kern.c:6:
include/linux/security.h:1353:19: warning: 'security_getselfattr' declared 'static' but never defined [-Wunused-function]
1353 | static inline int security_getselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
include/linux/security.h:1360:19: warning: 'security_setselfattr' declared 'static' but never defined [-Wunused-function]
1360 | static inline int security_setselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
--
In file included from include/linux/perf_event.h:62,
from include/linux/trace_events.h:10,
from include/trace/syscall.h:7,
from include/linux/syscalls.h:89,
from arch/x86/um/syscalls_64.c:10:
>> include/linux/security.h:1356:1: error: expected identifier or '(' before '{' token
1356 | {
| ^
include/linux/security.h:1363:1: error: expected identifier or '(' before '{' token
1363 | {
| ^
arch/x86/um/syscalls_64.c:84:6: warning: no previous prototype for 'arch_switch_to' [-Wmissing-prototypes]
84 | void arch_switch_to(struct task_struct *to)
| ^~~~~~~~~~~~~~
In file included from include/linux/perf_event.h:62,
from include/linux/trace_events.h:10,
from include/trace/syscall.h:7,
from include/linux/syscalls.h:89,
from arch/x86/um/syscalls_64.c:10:
include/linux/security.h:1353:19: warning: 'security_getselfattr' declared 'static' but never defined [-Wunused-function]
1353 | static inline int security_getselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
include/linux/security.h:1360:19: warning: 'security_setselfattr' declared 'static' but never defined [-Wunused-function]
1360 | static inline int security_setselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
--
In file included from kernel/fork.c:51:
>> include/linux/security.h:1356:1: error: expected identifier or '(' before '{' token
1356 | {
| ^
include/linux/security.h:1363:1: error: expected identifier or '(' before '{' token
1363 | {
| ^
kernel/fork.c:162:13: warning: no previous prototype for 'arch_release_task_struct' [-Wmissing-prototypes]
162 | void __weak arch_release_task_struct(struct task_struct *tsk)
| ^~~~~~~~~~~~~~~~~~~~~~~~
kernel/fork.c:862:20: warning: no previous prototype for 'arch_task_cache_init' [-Wmissing-prototypes]
862 | void __init __weak arch_task_cache_init(void) { }
| ^~~~~~~~~~~~~~~~~~~~
kernel/fork.c:957:12: warning: no previous prototype for 'arch_dup_task_struct' [-Wmissing-prototypes]
957 | int __weak arch_dup_task_struct(struct task_struct *dst,
| ^~~~~~~~~~~~~~~~~~~~
In file included from kernel/fork.c:51:
include/linux/security.h:1353:19: warning: 'security_getselfattr' declared 'static' but never defined [-Wunused-function]
1353 | static inline int security_getselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
include/linux/security.h:1360:19: warning: 'security_setselfattr' declared 'static' but never defined [-Wunused-function]
1360 | static inline int security_setselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
--
In file included from include/linux/perf_event.h:62,
from include/linux/trace_events.h:10,
from include/trace/syscall.h:7,
from include/linux/syscalls.h:89,
from kernel/exit.c:42:
>> include/linux/security.h:1356:1: error: expected identifier or '(' before '{' token
1356 | {
| ^
include/linux/security.h:1363:1: error: expected identifier or '(' before '{' token
1363 | {
| ^
kernel/exit.c:1901:13: warning: no previous prototype for 'abort' [-Wmissing-prototypes]
1901 | __weak void abort(void)
| ^~~~~
In file included from include/linux/perf_event.h:62,
from include/linux/trace_events.h:10,
from include/trace/syscall.h:7,
from include/linux/syscalls.h:89,
from kernel/exit.c:42:
include/linux/security.h:1353:19: warning: 'security_getselfattr' declared 'static' but never defined [-Wunused-function]
1353 | static inline int security_getselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
include/linux/security.h:1360:19: warning: 'security_setselfattr' declared 'static' but never defined [-Wunused-function]
1360 | static inline int security_setselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
--
In file included from include/net/scm.h:8,
from include/linux/netlink.h:9,
from include/uapi/linux/neighbour.h:6,
from include/linux/netdevice.h:46,
from include/linux/if_vlan.h:10,
from include/linux/filter.h:20,
from kernel/kallsyms.c:25:
>> include/linux/security.h:1356:1: error: expected identifier or '(' before '{' token
1356 | {
| ^
include/linux/security.h:1363:1: error: expected identifier or '(' before '{' token
1363 | {
| ^
kernel/kallsyms.c:663:12: warning: no previous prototype for 'arch_get_kallsym' [-Wmissing-prototypes]
663 | int __weak arch_get_kallsym(unsigned int symnum, unsigned long *value,
| ^~~~~~~~~~~~~~~~
In file included from include/net/scm.h:8,
from include/linux/netlink.h:9,
from include/uapi/linux/neighbour.h:6,
from include/linux/netdevice.h:46,
from include/linux/if_vlan.h:10,
from include/linux/filter.h:20,
from kernel/kallsyms.c:25:
include/linux/security.h:1353:19: warning: 'security_getselfattr' declared 'static' but never defined [-Wunused-function]
1353 | static inline int security_getselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
include/linux/security.h:1360:19: warning: 'security_setselfattr' declared 'static' but never defined [-Wunused-function]
1360 | static inline int security_setselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
--
In file included from include/linux/fs_context.h:14,
from include/linux/pseudo_fs.h:4,
from fs/pipe.c:17:
>> include/linux/security.h:1356:1: error: expected identifier or '(' before '{' token
1356 | {
| ^
include/linux/security.h:1363:1: error: expected identifier or '(' before '{' token
1363 | {
| ^
fs/pipe.c:757:15: warning: no previous prototype for 'account_pipe_buffers' [-Wmissing-prototypes]
757 | unsigned long account_pipe_buffers(struct user_struct *user,
| ^~~~~~~~~~~~~~~~~~~~
fs/pipe.c:763:6: warning: no previous prototype for 'too_many_pipe_buffers_soft' [-Wmissing-prototypes]
763 | bool too_many_pipe_buffers_soft(unsigned long user_bufs)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
fs/pipe.c:770:6: warning: no previous prototype for 'too_many_pipe_buffers_hard' [-Wmissing-prototypes]
770 | bool too_many_pipe_buffers_hard(unsigned long user_bufs)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
fs/pipe.c:777:6: warning: no previous prototype for 'pipe_is_unprivileged_user' [-Wmissing-prototypes]
777 | bool pipe_is_unprivileged_user(void)
| ^~~~~~~~~~~~~~~~~~~~~~~~~
fs/pipe.c:1253:5: warning: no previous prototype for 'pipe_resize_ring' [-Wmissing-prototypes]
1253 | int pipe_resize_ring(struct pipe_inode_info *pipe, unsigned int nr_slots)
| ^~~~~~~~~~~~~~~~
In file included from include/linux/fs_context.h:14,
from include/linux/pseudo_fs.h:4,
from fs/pipe.c:17:
include/linux/security.h:1353:19: warning: 'security_getselfattr' declared 'static' but never defined [-Wunused-function]
1353 | static inline int security_getselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
include/linux/security.h:1360:19: warning: 'security_setselfattr' declared 'static' but never defined [-Wunused-function]
1360 | static inline int security_setselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
--
In file included from include/linux/perf_event.h:62,
from include/linux/trace_events.h:10,
from include/trace/syscall.h:7,
from include/linux/syscalls.h:89,
from fs/d_path.c:2:
>> include/linux/security.h:1356:1: error: expected identifier or '(' before '{' token
1356 | {
| ^
include/linux/security.h:1363:1: error: expected identifier or '(' before '{' token
1363 | {
| ^
fs/d_path.c:317:7: warning: no previous prototype for 'simple_dname' [-Wmissing-prototypes]
317 | char *simple_dname(struct dentry *dentry, char *buffer, int buflen)
| ^~~~~~~~~~~~
In file included from include/linux/perf_event.h:62,
from include/linux/trace_events.h:10,
from include/trace/syscall.h:7,
from include/linux/syscalls.h:89,
from fs/d_path.c:2:
include/linux/security.h:1353:19: warning: 'security_getselfattr' declared 'static' but never defined [-Wunused-function]
1353 | static inline int security_getselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
include/linux/security.h:1360:19: warning: 'security_setselfattr' declared 'static' but never defined [-Wunused-function]
1360 | static inline int security_setselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
--
In file included from include/linux/perf_event.h:62,
from include/linux/trace_events.h:10,
from include/trace/syscall.h:7,
from include/linux/syscalls.h:89,
from io_uring/io_uring.c:45:
>> include/linux/security.h:1356:1: error: expected identifier or '(' before '{' token
1356 | {
| ^
include/linux/security.h:1363:1: error: expected identifier or '(' before '{' token
1363 | {
| ^
io_uring/io_uring.c: In function '__io_submit_flush_completions':
io_uring/io_uring.c:1448:40: warning: variable 'prev' set but not used [-Wunused-but-set-variable]
1448 | struct io_wq_work_node *node, *prev;
| ^~~~
In file included from include/linux/perf_event.h:62,
from include/linux/trace_events.h:10,
from include/trace/syscall.h:7,
from include/linux/syscalls.h:89,
from io_uring/io_uring.c:45:
io_uring/io_uring.c: At top level:
include/linux/security.h:1353:19: warning: 'security_getselfattr' declared 'static' but never defined [-Wunused-function]
1353 | static inline int security_getselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
include/linux/security.h:1360:19: warning: 'security_setselfattr' declared 'static' but never defined [-Wunused-function]
1360 | static inline int security_setselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
--
In file included from include/net/scm.h:8,
from include/linux/netlink.h:9,
from include/uapi/linux/neighbour.h:6,
from include/linux/netdevice.h:46,
from include/net/sock.h:46,
from include/linux/tcp.h:19,
from include/linux/ipv6.h:93,
from include/net/addrconf.h:52,
from lib/vsprintf.c:40:
>> include/linux/security.h:1356:1: error: expected identifier or '(' before '{' token
1356 | {
| ^
include/linux/security.h:1363:1: error: expected identifier or '(' before '{' token
1363 | {
| ^
lib/vsprintf.c: In function 'va_format':
lib/vsprintf.c:1681:9: warning: function 'va_format' might be a candidate for 'gnu_printf' format attribute [-Wsuggest-attribute=format]
1681 | buf += vsnprintf(buf, end > buf ? end - buf : 0, va_fmt->fmt, va);
| ^~~
In file included from include/net/scm.h:8,
from include/linux/netlink.h:9,
from include/uapi/linux/neighbour.h:6,
from include/linux/netdevice.h:46,
from include/net/sock.h:46,
from include/linux/tcp.h:19,
from include/linux/ipv6.h:93,
from include/net/addrconf.h:52,
from lib/vsprintf.c:40:
lib/vsprintf.c: At top level:
include/linux/security.h:1353:19: warning: 'security_getselfattr' declared 'static' but never defined [-Wunused-function]
1353 | static inline int security_getselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
include/linux/security.h:1360:19: warning: 'security_setselfattr' declared 'static' but never defined [-Wunused-function]
1360 | static inline int security_setselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
..


vim +1356 include/linux/security.h

1352
1353 static inline int security_getselfattr(u64 __user attr,
1354 struct lsm_ctx __user *ctx,
1355 size_t __user *size);
> 1356 {
1357 return -EINVAL;
1358 }
1359

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

2023-02-23 08:35:23

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v6 04/11] LSM: syscalls for current process attributes

Hi Casey,

I love your patch! Yet something to improve:

[auto build test ERROR on tip/perf/core]
[also build test ERROR on acme/perf/core shuah-kselftest/next shuah-kselftest/fixes v6.2]
[cannot apply to linus/master next-20230223]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Casey-Schaufler/LSM-Maintain-a-table-of-LSM-attribute-data/20230223-050902
patch link: https://lore.kernel.org/r/20230222200838.8149-5-casey%40schaufler-ca.com
patch subject: [PATCH v6 04/11] LSM: syscalls for current process attributes
config: powerpc-allnoconfig (https://download.01.org/0day-ci/archive/20230223/[email protected]/config)
compiler: powerpc-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/04ba82c1bd629c2114ad851b4723d6e8b0f9d08f
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Casey-Schaufler/LSM-Maintain-a-table-of-LSM-attribute-data/20230223-050902
git checkout 04ba82c1bd629c2114ad851b4723d6e8b0f9d08f
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=powerpc olddefconfig
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=powerpc SHELL=/bin/bash arch/powerpc/kernel/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <[email protected]>
| Link: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All errors (new ones prefixed by >>):

In file included from include/linux/perf_event.h:62,
from include/linux/trace_events.h:10,
from include/trace/syscall.h:7,
from include/linux/syscalls.h:89,
from arch/powerpc/kernel/syscalls.c:19:
include/linux/security.h:1356:1: error: expected identifier or '(' before '{' token
1356 | {
| ^
include/linux/security.h:1363:1: error: expected identifier or '(' before '{' token
1363 | {
| ^
>> include/linux/security.h:1353:19: error: 'security_getselfattr' declared 'static' but never defined [-Werror=unused-function]
1353 | static inline int security_getselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
>> include/linux/security.h:1360:19: error: 'security_setselfattr' declared 'static' but never defined [-Werror=unused-function]
1360 | static inline int security_setselfattr(u64 __user attr,
| ^~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors


vim +1353 include/linux/security.h

1352
> 1353 static inline int security_getselfattr(u64 __user attr,
1354 struct lsm_ctx __user *ctx,
1355 size_t __user *size);
1356 {
1357 return -EINVAL;
1358 }
1359
> 1360 static inline int security_setselfattr(u64 __user attr,
1361 struct lsm_ctx __user *ctx,
1362 size_t __user size);
1363 {
1364 return -EINVAL;
1365 }
1366

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

2023-02-23 10:19:24

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH v6 06/11] LSM: wireup Linux Security Module syscalls

Hi Casey,

On Wed, Feb 22, 2023 at 9:18 PM Casey Schaufler <[email protected]> wrote:
> Wireup lsm_get_self_attr, lsm_set_self_attr and lsm_module_list
> system calls.
>
> Signed-off-by: Casey Schaufler <[email protected]>

Thanks for your patch!

> arch/m68k/kernel/syscalls/syscall.tbl | 3 +++

Please collect tags given, and add them when reposting.
I'm providing my
Acked-by: Geert Uytterhoeven <[email protected]> [m68k]
for the third time.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

2023-02-23 12:50:23

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v6 04/11] LSM: syscalls for current process attributes

Hi Casey,

I love your patch! Perhaps something to improve:

[auto build test WARNING on tip/perf/core]
[also build test WARNING on acme/perf/core shuah-kselftest/next shuah-kselftest/fixes v6.2]
[cannot apply to linus/master next-20230223]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Casey-Schaufler/LSM-Maintain-a-table-of-LSM-attribute-data/20230223-050902
patch link: https://lore.kernel.org/r/20230222200838.8149-5-casey%40schaufler-ca.com
patch subject: [PATCH v6 04/11] LSM: syscalls for current process attributes
config: x86_64-rhel-8.3 (https://download.01.org/0day-ci/archive/20230223/[email protected]/config)
compiler: gcc-11 (Debian 11.3.0-8) 11.3.0
reproduce (this is a W=1 build):
# https://github.com/intel-lab-lkp/linux/commit/04ba82c1bd629c2114ad851b4723d6e8b0f9d08f
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Casey-Schaufler/LSM-Maintain-a-table-of-LSM-attribute-data/20230223-050902
git checkout 04ba82c1bd629c2114ad851b4723d6e8b0f9d08f
# save the config file
mkdir build_dir && cp config build_dir/.config
make W=1 O=build_dir ARCH=x86_64 olddefconfig
make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <[email protected]>
| Link: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

>> security/lsm_syscalls.c:61:5: warning: no previous prototype for 'lsm_name_to_attr' [-Wmissing-prototypes]
61 | u64 lsm_name_to_attr(const char *name)
| ^~~~~~~~~~~~~~~~


vim +/lsm_name_to_attr +61 security/lsm_syscalls.c

51
52 /**
53 * lsm_name_to_attr - map an LSM attribute name to its ID
54 * @name: name of the attribute
55 *
56 * Look the given @name up in the table of know attribute names.
57 *
58 * Returns the LSM attribute value associated with @name, or 0 if
59 * there is no mapping.
60 */
> 61 u64 lsm_name_to_attr(const char *name)
62 {
63 int i;
64
65 for (i = 0; i < ARRAY_SIZE(lsm_attr_names); i++)
66 if (!strcmp(name, lsm_attr_names[i].name))
67 return lsm_attr_names[i].attrs;
68 return 0;
69 }
70

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

2023-02-25 13:38:25

by Oliver Sang

[permalink] [raw]
Subject: Re: [PATCH v6 02/11] LSM: Maintain a table of LSM attribute data


Greeting,

FYI, we noticed WARNING:at_security/security.c:#append_ordered_lsm due to commit (built with gcc-11):

commit: af5e9ce5abd1a5a2e91036acd8b340072ad840d6 ("[PATCH v6 02/11] LSM: Maintain a table of LSM attribute data")
url: https://github.com/intel-lab-lkp/linux/commits/Casey-Schaufler/LSM-Maintain-a-table-of-LSM-attribute-data/20230223-050902
base: https://git.kernel.org/cgit/linux/kernel/git/tip/tip.git c828441f21ddc819a28b5723a72e3c840e9de1c6
patch link: https://lore.kernel.org/all/[email protected]/
patch subject: [PATCH v6 02/11] LSM: Maintain a table of LSM attribute data

in testcase: boot

on test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G

caused below changes (please refer to attached dmesg/kmsg for entire log/backtrace):


If you fix the issue, kindly add following tag
| Reported-by: kernel test robot <[email protected]>
| Link: https://lore.kernel.org/oe-lkp/[email protected]


[ 0.397553][ T0] ------------[ cut here ]------------
[ 0.398454][ T0] builtin: out of LSM slots!?
[ 0.399456][ T0] WARNING: CPU: 0 PID: 0 at security/security.c:173 append_ordered_lsm (security/security.c:173 (discriminator 1))
[ 0.401167][ T0] Modules linked in:
[ 0.402167][ T0] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 6.2.0-rc4-00030-gaf5e9ce5abd1 #1
[ 0.403616][ T0] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-debian-1.16.0-5 04/01/2014
[ 0.404678][ T0] RIP: 0010:append_ordered_lsm (security/security.c:173 (discriminator 1))
[ 0.405466][ T0] Code: 89 f5 53 48 89 fb e8 de fe ff ff 84 c0 75 79 48 63 05 16 8f 13 00 83 f8 03 75 13 48 89 ee 48 c7 c7 34 aa 68 82 e8 1d c2 96 fe <0f> 0b eb 5a 48 83 7b 18 00 75 08 48 c7 43 18 18 3f 65 83 8d 50 01
All code
========
0: 89 f5 mov %esi,%ebp
2: 53 push %rbx
3: 48 89 fb mov %rdi,%rbx
6: e8 de fe ff ff callq 0xfffffffffffffee9
b: 84 c0 test %al,%al
d: 75 79 jne 0x88
f: 48 63 05 16 8f 13 00 movslq 0x138f16(%rip),%rax # 0x138f2c
16: 83 f8 03 cmp $0x3,%eax
19: 75 13 jne 0x2e
1b: 48 89 ee mov %rbp,%rsi
1e: 48 c7 c7 34 aa 68 82 mov $0xffffffff8268aa34,%rdi
25: e8 1d c2 96 fe callq 0xfffffffffe96c247
2a:* 0f 0b ud2 <-- trapping instruction
2c: eb 5a jmp 0x88
2e: 48 83 7b 18 00 cmpq $0x0,0x18(%rbx)
33: 75 08 jne 0x3d
35: 48 c7 43 18 18 3f 65 movq $0xffffffff83653f18,0x18(%rbx)
3c: 83
3d: 8d 50 01 lea 0x1(%rax),%edx

Code starting with the faulting instruction
===========================================
0: 0f 0b ud2
2: eb 5a jmp 0x5e
4: 48 83 7b 18 00 cmpq $0x0,0x18(%rbx)
9: 75 08 jne 0x13
b: 48 c7 43 18 18 3f 65 movq $0xffffffff83653f18,0x18(%rbx)
12: 83
13: 8d 50 01 lea 0x1(%rax),%edx
[ 0.406998][ T0] RSP: 0000:ffffffff82a03e90 EFLAGS: 00010286
[ 0.408167][ T0] RAX: 0000000000000000 RBX: ffffffff836fe878 RCX: c0000000ffff7fff
[ 0.409589][ T0] RDX: 0000000000000000 RSI: 0000000000027ffb RDI: 0000000000000001
[ 0.411167][ T0] RBP: ffffffff8266b47d R08: 0000000000000000 R09: 00000000ffff7fff
[ 0.412591][ T0] R10: ffffffff82a03d40 R11: ffffffff82dd70a8 R12: ffff88810018a573
[ 0.414167][ T0] R13: ffff88810018a540 R14: 0000000000000001 R15: 0000000000000000
[ 0.415626][ T0] FS: 0000000000000000(0000) GS:ffff88842fc00000(0000) knlGS:0000000000000000
[ 0.417170][ T0] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 0.418468][ T0] CR2: ffff88843ffff000 CR3: 0000000002a0a000 CR4: 00000000000406b0
[ 0.419598][ T0] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 0.421167][ T0] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 0.422618][ T0] Call Trace:
[ 0.423402][ T0] <TASK>
[ 0.424169][ T0] ordered_lsm_parse (security/security.c:307)
[ 0.425017][ T0] ordered_lsm_init (security/security.c:379)
[ 0.425457][ T0] security_init (security/security.c:459)
[ 0.426438][ T0] start_kernel (init/main.c:1129)
[ 0.427441][ T0] secondary_startup_64_no_verify (arch/x86/kernel/head_64.S:358)
[ 0.428466][ T0] </TASK>
[ 0.429401][ T0] ---[ end trace 0000000000000000 ]---
[ 0.430466][ T0] LSM: initializing lsm=capability,yama,integrity
[ 0.431488][ T0] Yama: becoming mindful.
[ 0.433189][ T0] Mount-cache hash table entries: 32768 (order: 6, 262144 bytes, linear)
[ 0.434656][ T0] Mountpoint-cache hash table entries: 32768 (order: 6, 262144 bytes, linear)
[ 0.436718][ T0] Last level iTLB entries: 4KB 0, 2MB 0, 4MB 0
[ 0.437498][ T0] Last level dTLB entries: 4KB 0, 2MB 0, 4MB 0, 1GB 0
[ 0.439173][ T0] Spectre V1 : Mitigation: usercopy/swapgs barriers and __user pointer sanitization
[ 0.440620][ T0] Spectre V2 : Mitigation: Retpolines
[ 0.441458][ T0] Spectre V2 : Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch
[ 0.443167][ T0] Spectre V2 : Spectre v2 / SpectreRSB : Filling RSB on VMEXIT
[ 0.444582][ T0] Speculative Store Bypass: Vulnerable
[ 0.445466][ T0] MDS: Vulnerable: Clear CPU buffers attempted, no microcode
[ 0.447166][ T0] MMIO Stale Data: Unknown: No mitigations
[ 0.475387][ T0] Freeing SMP alternatives memory: 44K
[ 0.476416][ T1] smpboot: CPU0: Intel Xeon E312xx (Sandy Bridge) (family: 0x6, model: 0x2a, stepping: 0x1)
[ 0.477947][ T1] cblist_init_generic: Setting adjustable number of callback queues.
[ 0.478169][ T1] cblist_init_generic: Setting shift to 1 and lim to 1.
[ 0.479233][ T1] cblist_init_generic: Setting shift to 1 and lim to 1.


To reproduce:

# build kernel
cd linux
cp config-6.2.0-rc4-00030-gaf5e9ce5abd1 .config
make HOSTCC=gcc-11 CC=gcc-11 ARCH=x86_64 olddefconfig prepare modules_prepare bzImage modules
make HOSTCC=gcc-11 CC=gcc-11 ARCH=x86_64 INSTALL_MOD_PATH=<mod-install-dir> modules_install
cd <mod-install-dir>
find lib/ | cpio -o -H newc --quiet | gzip > modules.cgz


git clone https://github.com/intel/lkp-tests.git
cd lkp-tests
bin/lkp qemu -k <bzImage> -m modules.cgz job-script # job-script is attached in this email

# if come across any failure that blocks the test,
# please remove ~/.lkp and /lkp dir to run from a clean state.



--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests



Attachments:
(No filename) (6.55 kB)
config-6.2.0-rc4-00030-gaf5e9ce5abd1 (163.56 kB)
job-script (4.83 kB)
dmesg.xz (28.77 kB)
Download all attachments

2023-03-03 18:32:59

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH v6 05/11] LSM: Create lsm_module_list system call

On Wed, Feb 22, 2023, at 21:08, Casey Schaufler wrote:
> @@ -1062,6 +1062,7 @@ asmlinkage long
> sys_set_mempolicy_home_node(unsigned long start, unsigned long l
> asmlinkage long sys_lsm_get_self_attr(struct lsm_ctx *ctx, size_t
> *size,
> __u64 flags);
> asmlinkage long sys_lsm_set_self_attr(struct lsm_ctx *ctx, __u64
> flags);
> +asmlinkage long sys_lsm_module_list(u64 *ids, size_t *size, int flags);
...
> + */
> +SYSCALL_DEFINE3(lsm_module_list,
> + u64 __user *, ids,
> + size_t __user *, size,
> + u64, flags)
> +{

I see that the prototype does not match the definition here,
which really should raise a compiler error, but I suspect that
broke at some point.

Since none of the flags bits are actually used here, can we
please make this a 32-bit field as in the prototype rather
than the 64-bit one in the argument list?

Passing 64-bit arguments through 32-bit registers would make
the calling conventions incompatible with compat mode tasks
on 64-bit kernels.

Arnd

2023-03-03 18:34:40

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH v6 06/11] LSM: wireup Linux Security Module syscalls

On Wed, Feb 22, 2023, at 21:08, Casey Schaufler wrote:
> Wireup lsm_get_self_attr, lsm_set_self_attr and lsm_module_list
> system calls.
>
> Signed-off-by: Casey Schaufler <[email protected]>
> Cc: [email protected]

This looks correct, you successfully avoided the various mistakes
that are frequently made when modifying these files.

Acked-by: Arnd Bergmann <[email protected]>

2023-03-03 18:43:09

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH v6 04/11] LSM: syscalls for current process attributes

On Wed, Feb 22, 2023, at 21:08, Casey Schaufler wrote:

> +/**
> + * sys_lsm_set_self_attr - Set current task's security module attribute
> + * @ctx: the LSM contexts
> + * @size: size of @ctx
> + * @flags: which attribute to set
> + *
> + * Sets the calling task's LSM context. On success this function
> + * returns 0. If the attribute specified cannot be set a negative
> + * value indicating the reason for the error is returned.
> + */
> +SYSCALL_DEFINE3(lsm_set_self_attr, struct lsm_ctx __user *, ctx,
> size_t __user,
> + size, u64, flags)
> +{
> + return security_setselfattr(flags, ctx, size);
> +}
> +
> +SYSCALL_DEFINE3(lsm_get_self_attr, struct lsm_ctx __user *, ctx,
> + size_t __user *, size, u64, flags)
> +{
> + return security_getselfattr(flags, ctx, size);
> +}

As with the other patch I commented on, I think it's better to use a
32-bit 'flags' argument here, to make this work for compat tasks.

Arnd

2023-03-07 11:35:03

by Mickaël Salaün

[permalink] [raw]
Subject: Re: [PATCH v6 05/11] LSM: Create lsm_module_list system call


On 22/02/2023 21:08, Casey Schaufler wrote:
> 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 chosing an

"choosing"

> output format, determining required privilege or bypassing
> security module specific behavior.
>
> Signed-off-by: Casey Schaufler <[email protected]>
> ---
> Documentation/userspace-api/lsm.rst | 3 ++
> include/linux/syscalls.h | 1 +
> kernel/sys_ni.c | 1 +
> security/lsm_syscalls.c | 43 ++++++++++++++++++++++++++++-
> 4 files changed, 47 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/userspace-api/lsm.rst b/Documentation/userspace-api/lsm.rst
> index b45e402302b3..ecdf1acd15b1 100644
> --- a/Documentation/userspace-api/lsm.rst
> +++ b/Documentation/userspace-api/lsm.rst
> @@ -63,6 +63,9 @@ Get the specified security attributes of the current process
> .. kernel-doc:: security/lsm_syscalls.c
> :identifiers: sys_lsm_get_self_attr
>
> +.. kernel-doc:: security/lsm_syscalls.c
> + :identifiers: sys_lsm_module_list
> +
> Additional documentation
> ========================
>
> diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
> index 1ef2a3de8ae0..9c947022a411 100644
> --- a/include/linux/syscalls.h
> +++ b/include/linux/syscalls.h
> @@ -1062,6 +1062,7 @@ asmlinkage long sys_set_mempolicy_home_node(unsigned long start, unsigned long l
> asmlinkage long sys_lsm_get_self_attr(struct lsm_ctx *ctx, size_t *size,
> __u64 flags);
> asmlinkage long sys_lsm_set_self_attr(struct lsm_ctx *ctx, __u64 flags);
> +asmlinkage long sys_lsm_module_list(u64 *ids, size_t *size, int flags);
>
> /*
> * Architecture-specific system calls
> diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
> index d03c78ef1562..32784e271fa5 100644
> --- a/kernel/sys_ni.c
> +++ b/kernel/sys_ni.c
> @@ -265,6 +265,7 @@ COND_SYSCALL(mremap);
> /* security/lsm_syscalls.c */
> COND_SYSCALL(lsm_get_self_attr);
> COND_SYSCALL(lsm_set_self_attr);
> +COND_SYSCALL(lsm_module_list);
>
> /* security/keys/keyctl.c */
> COND_SYSCALL(add_key);
> diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c
> index b89c4e7d009e..ccd3b236670b 100644
> --- a/security/lsm_syscalls.c
> +++ b/security/lsm_syscalls.c
> @@ -19,7 +19,7 @@
>
> struct attrs_map {
> char *name;
> - int attrs;
> + u64 attrs;

Why do we need this change in this patch?


> };
>
> static const struct attrs_map lsm_attr_names[] = {
> @@ -102,3 +102,44 @@ SYSCALL_DEFINE3(lsm_get_self_attr, struct lsm_ctx __user *, ctx,
> {
> return security_getselfattr(flags, ctx, size);
> }
> +
> +/**
> + * sys_lsm_module_list - Return a list of the active security modules
> + * @ids: the LSM module ids
> + * @size: size of @ids, updated on return
> + * @flags: reserved for future use, must be zero
> + *
> + * Returns a list of the active LSM ids. On success this function
> + * returns the number of @ids array elements. This value may be zero
> + * if there are no LSMs active. If @size is insufficient to contain
> + * the return data -E2BIG is returned and @size is set to the minimum
> + * required size. In all other cases a negative value indicating the
> + * error is returned.
> + */
> +SYSCALL_DEFINE3(lsm_module_list,

The name of this syscall differ from the two others: there is not "get"
verb. What about "lsm_get_modules" or "lsm_list_modules"?


> + u64 __user *, ids,
> + size_t __user *, size,
> + u64, flags)

As Arnd said, flags should be a u32.

> +{
> + size_t total_size = lsm_active_cnt * sizeof(*ids);
> + size_t usize;
> + int i;
> +
> + if (flags)
> + return -EINVAL;
> +
> + if (get_user(usize, size))
> + return -EFAULT;

I'm not a fan of using the same pointer to read and write. This avoid
using const pointers and differentiate between input and output values.
I suggest using a dedicated argument for each.


> +
> + if (put_user(total_size, size) != 0)
> + return -EFAULT;
> +
> + if (usize < total_size)
> + return -E2BIG;
> +
> + for (i = 0; i < lsm_active_cnt; i++)
> + if (put_user(lsm_idlist[i]->id, ids++))

I'm not sure about it, but it may be better to put the complete list of
IDs at once. Is it better to set the size before or after?


> + return -EFAULT;
> +
> + return lsm_active_cnt;
> +}

2023-03-07 11:53:31

by Mickaël Salaün

[permalink] [raw]
Subject: Re: [PATCH v6 04/11] LSM: syscalls for current process attributes


On 22/02/2023 21:08, Casey Schaufler wrote:
> Create a system call lsm_get_self_attr() to provide the security
> module maintained attributes of the current process.
> Create a system call lsm_set_self_attr() to set a security
> module maintained attribute of the current process.
> Historically these attributes have been exposed to user space via
> entries in procfs under /proc/self/attr.
>
> The attribute value is provided in a lsm_ctx structure. The structure
> identifys the size of the attribute, and the attribute value. The format
> of the attribute value is defined by the security module. A flags field
> is included for LSM specific information. It is currently unused and must
> be 0. The total size of the data, including the lsm_ctx structure and any
> padding, is maintained as well.
>
> struct lsm_ctx {
> __u64 id;
> __u64 flags;
> __u64 len;
> __u64 ctx_len;
> __u8 ctx[];
> };
>
> Two new LSM hooks are used to interface with the LSMs.
> security_getselfattr() collects the lsm_ctx values from the
> LSMs that support the hook, accounting for space requirements.
> security_setselfattr() identifies which LSM the attribute is
> intended for and passes it along.
>
> Signed-off-by: Casey Schaufler <[email protected]>
> ---
> Documentation/userspace-api/lsm.rst | 15 ++++
> include/linux/lsm_hook_defs.h | 4 ++
> include/linux/lsm_hooks.h | 9 +++
> include/linux/security.h | 19 +++++
> include/linux/syscalls.h | 4 ++
> include/uapi/linux/lsm.h | 33 +++++++++
> kernel/sys_ni.c | 4 ++
> security/Makefile | 1 +
> security/lsm_syscalls.c | 104 ++++++++++++++++++++++++++++
> security/security.c | 82 ++++++++++++++++++++++
> 10 files changed, 275 insertions(+)
> create mode 100644 security/lsm_syscalls.c
>

[...]

> +/**
> + * security_setselfattr - Set an LSM attribute on the current process.
> + * @attr: which attribute to return
> + * @ctx: the user-space source for the information
> + * @size: the size of the data
> + *
> + * Set an LSM attribute for the current process. The LSM, attribute
> + * and new value are included in @ctx.
> + *
> + * Returns 0 on seccess, an LSM specific value on failure.
> + */
> +int security_setselfattr(u64 __user attr, struct lsm_ctx __user *ctx,
> + size_t __user size)
> +{
> + struct security_hook_list *hp;
> + struct lsm_ctx lctx;
> +
> + if (size < sizeof(*ctx))

If the lsm_ctx struct could grow in the future, we should check the size
of the struct to the last field for compatibility reasons, see
Landlock's copy_min_struct_from_user().


> + return -EINVAL;
> + if (copy_from_user(&lctx, ctx, sizeof(*ctx)))
> + return -EFAULT;
> +
> + hlist_for_each_entry(hp, &security_hook_heads.setselfattr, list)
> + if ((hp->lsmid->id) == lctx.id)
> + return hp->hook.setselfattr(attr, ctx, size);
> +
> + return LSM_RET_DEFAULT(setselfattr);
> +}
> +
> int security_getprocattr(struct task_struct *p, int lsmid, const char *name,
> char **value)
> {

2023-03-07 11:56:25

by Mickaël Salaün

[permalink] [raw]
Subject: Re: [PATCH v6 04/11] LSM: syscalls for current process attributes

Let's say an LSM need to pass a file descriptor instead of a text value.
Would that be possible or would it need to use another interface?


On 22/02/2023 21:08, Casey Schaufler wrote:
> Create a system call lsm_get_self_attr() to provide the security
> module maintained attributes of the current process.
> Create a system call lsm_set_self_attr() to set a security
> module maintained attribute of the current process.
> Historically these attributes have been exposed to user space via
> entries in procfs under /proc/self/attr.
>
> The attribute value is provided in a lsm_ctx structure. The structure
> identifys the size of the attribute, and the attribute value. The format
> of the attribute value is defined by the security module. A flags field
> is included for LSM specific information. It is currently unused and must
> be 0. The total size of the data, including the lsm_ctx structure and any
> padding, is maintained as well.
>
> struct lsm_ctx {
> __u64 id;
> __u64 flags;
> __u64 len;
> __u64 ctx_len;
> __u8 ctx[];
> };
>
> Two new LSM hooks are used to interface with the LSMs.
> security_getselfattr() collects the lsm_ctx values from the
> LSMs that support the hook, accounting for space requirements.
> security_setselfattr() identifies which LSM the attribute is
> intended for and passes it along.

2023-03-07 15:06:39

by Florian Weimer

[permalink] [raw]
Subject: Re: [PATCH v6 04/11] LSM: syscalls for current process attributes

* Casey Schaufler:

> Create a system call lsm_get_self_attr() to provide the security
> module maintained attributes of the current process.

Is it really the current process, or the current thread?

> diff --git a/include/uapi/linux/lsm.h b/include/uapi/linux/lsm.h
> index 523748cae615..7850fed28998 100644
> --- a/include/uapi/linux/lsm.h
> +++ b/include/uapi/linux/lsm.h
> @@ -9,6 +9,39 @@
> #ifndef _UAPI_LINUX_LSM_H
> #define _UAPI_LINUX_LSM_H
>
> +#include <linux/types.h>
> +#include <linux/unistd.h>
> +
> +/**
> + * struct lsm_ctx - LSM context information
> + * @id: the LSM id number, see LSM_ID_XXX
> + * @flags: LSM specific flags
> + * @len: length of the lsm_ctx struct, @ctx and any other data or padding
> + * @ctx_len: the size of @ctx
> + * @ctx: the LSM context value
> + *
> + * The @len field MUST be equal to the size of the lsm_ctx struct
> + * plus any additional padding and/or data placed after @ctx.
> + *
> + * In all cases @ctx_len MUST be equal to the length of @ctx.
> + * If @ctx is a string value it should be nul terminated with
> + * @ctx_len equal to `strlen(@ctx) + 1`. Binary values are
> + * supported.
> + *
> + * The @flags and @ctx fields SHOULD only be interpreted by the
> + * LSM specified by @id; they MUST be set to zero/0 when not used.
> + */
> +struct lsm_ctx {
> + __u64 id;
> + __u64 flags;
> + __u64 len;
> + __u64 ctx_len;
> + __u8 ctx[];
> +};

The documentation seems to be written from the LSM point of view, not
the application point of view. As far as I understand it, the LSM
writes to the ctx member, not the application.

Thanks,
Florian


2023-03-07 17:11:35

by Casey Schaufler

[permalink] [raw]
Subject: Re: [PATCH v6 04/11] LSM: syscalls for current process attributes

On 3/7/2023 3:56 AM, Mickaël Salaün wrote:
> Let's say an LSM need to pass a file descriptor instead of a text
> value. Would that be possible or would it need to use another interface?

>
>
> On 22/02/2023 21:08, Casey Schaufler wrote:
>> Create a system call lsm_get_self_attr() to provide the security
>> module maintained attributes of the current process.
>> Create a system call lsm_set_self_attr() to set a security
>> module maintained attribute of the current process.
>> Historically these attributes have been exposed to user space via
>> entries in procfs under /proc/self/attr.
>>
>> The attribute value is provided in a lsm_ctx structure. The structure
>> identifys the size of the attribute, and the attribute value. The format
>> of the attribute value is defined by the security module. A flags field
>> is included for LSM specific information. It is currently unused and
>> must
>> be 0. The total size of the data, including the lsm_ctx structure and
>> any
>> padding, is maintained as well.
>>
>> struct lsm_ctx {
>>          __u64   id;
>>          __u64   flags;
>>          __u64   len;
>>          __u64   ctx_len;
>>          __u8    ctx[];
>> };
>>
>> Two new LSM hooks are used to interface with the LSMs.
>> security_getselfattr() collects the lsm_ctx values from the
>> LSMs that support the hook, accounting for space requirements.
>> security_setselfattr() identifies which LSM the attribute is
>> intended for and passes it along.

2023-03-07 17:18:44

by Casey Schaufler

[permalink] [raw]
Subject: Re: [PATCH v6 04/11] LSM: syscalls for current process attributes

On 3/7/2023 3:56 AM, Mickaël Salaün wrote:
> Let's say an LSM need to pass a file descriptor instead of a text
> value. Would that be possible or would it need to use another interface?

You could use this interface. LSM_ATTR_MAGICFD would have a
ctx_len = sizeof(fd) and the value in ctx. The underlying
plumbing is another matter entirely. It's likely you'd need
to provide more information in the ctx than the fd, but I
couldn't say what it would be, and I won't speculate.

I would not advocate such a use, as I am not now nor have
ever been a fan of passed file descriptors.

>
>
> On 22/02/2023 21:08, Casey Schaufler wrote:
>> Create a system call lsm_get_self_attr() to provide the security
>> module maintained attributes of the current process.
>> Create a system call lsm_set_self_attr() to set a security
>> module maintained attribute of the current process.
>> Historically these attributes have been exposed to user space via
>> entries in procfs under /proc/self/attr.
>>
>> The attribute value is provided in a lsm_ctx structure. The structure
>> identifys the size of the attribute, and the attribute value. The format
>> of the attribute value is defined by the security module. A flags field
>> is included for LSM specific information. It is currently unused and
>> must
>> be 0. The total size of the data, including the lsm_ctx structure and
>> any
>> padding, is maintained as well.
>>
>> struct lsm_ctx {
>>          __u64   id;
>>          __u64   flags;
>>          __u64   len;
>>          __u64   ctx_len;
>>          __u8    ctx[];
>> };
>>
>> Two new LSM hooks are used to interface with the LSMs.
>> security_getselfattr() collects the lsm_ctx values from the
>> LSMs that support the hook, accounting for space requirements.
>> security_setselfattr() identifies which LSM the attribute is
>> intended for and passes it along.

2023-03-09 02:30:55

by Casey Schaufler

[permalink] [raw]
Subject: Re: [PATCH v6 04/11] LSM: syscalls for current process attributes

On 3/7/2023 3:51 AM, Mickaël Salaün wrote:
>
> On 22/02/2023 21:08, Casey Schaufler wrote:
>> Create a system call lsm_get_self_attr() to provide the security
>> module maintained attributes of the current process.
>> Create a system call lsm_set_self_attr() to set a security
>> module maintained attribute of the current process.
>> Historically these attributes have been exposed to user space via
>> entries in procfs under /proc/self/attr.
>>
>> The attribute value is provided in a lsm_ctx structure. The structure
>> identifys the size of the attribute, and the attribute value. The format
>> of the attribute value is defined by the security module. A flags field
>> is included for LSM specific information. It is currently unused and
>> must
>> be 0. The total size of the data, including the lsm_ctx structure and
>> any
>> padding, is maintained as well.
>>
>> struct lsm_ctx {
>>          __u64   id;
>>          __u64   flags;
>>          __u64   len;
>>          __u64   ctx_len;
>>          __u8    ctx[];
>> };
>>
>> Two new LSM hooks are used to interface with the LSMs.
>> security_getselfattr() collects the lsm_ctx values from the
>> LSMs that support the hook, accounting for space requirements.
>> security_setselfattr() identifies which LSM the attribute is
>> intended for and passes it along.
>>
>> Signed-off-by: Casey Schaufler <[email protected]>
>> ---
>>   Documentation/userspace-api/lsm.rst |  15 ++++
>>   include/linux/lsm_hook_defs.h       |   4 ++
>>   include/linux/lsm_hooks.h           |   9 +++
>>   include/linux/security.h            |  19 +++++
>>   include/linux/syscalls.h            |   4 ++
>>   include/uapi/linux/lsm.h            |  33 +++++++++
>>   kernel/sys_ni.c                     |   4 ++
>>   security/Makefile                   |   1 +
>>   security/lsm_syscalls.c             | 104 ++++++++++++++++++++++++++++
>>   security/security.c                 |  82 ++++++++++++++++++++++
>>   10 files changed, 275 insertions(+)
>>   create mode 100644 security/lsm_syscalls.c
>>
>
> [...]
>
>> +/**
>> + * security_setselfattr - Set an LSM attribute on the current process.
>> + * @attr: which attribute to return
>> + * @ctx: the user-space source for the information
>> + * @size: the size of the data
>> + *
>> + * Set an LSM attribute for the current process. The LSM, attribute
>> + * and new value are included in @ctx.
>> + *
>> + * Returns 0 on seccess, an LSM specific value on failure.
>> + */
>> +int security_setselfattr(u64 __user attr, struct lsm_ctx __user *ctx,
>> +             size_t __user size)
>> +{
>> +    struct security_hook_list *hp;
>> +    struct lsm_ctx lctx;
>> +
>> +    if (size < sizeof(*ctx))
>
> If the lsm_ctx struct could grow in the future, we should check the
> size of the struct to the last field for compatibility reasons, see
> Landlock's copy_min_struct_from_user().

Because the lsm_ctx structure ends with the variable length context there's
no way to append new fields to it. The structure can't grow.

>
>
>> +        return -EINVAL;
>> +    if (copy_from_user(&lctx, ctx, sizeof(*ctx)))
>> +        return -EFAULT;
>> +
>> +    hlist_for_each_entry(hp, &security_hook_heads.setselfattr, list)
>> +        if ((hp->lsmid->id) == lctx.id)
>> +            return hp->hook.setselfattr(attr, ctx, size);
>> +
>> +    return LSM_RET_DEFAULT(setselfattr);
>> +}
>> +
>>   int security_getprocattr(struct task_struct *p, int lsmid, const
>> char *name,
>>                char **value)
>>   {

2023-03-14 22:00:46

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH v6 04/11] LSM: syscalls for current process attributes

On Wed, Mar 8, 2023 at 9:30 PM Casey Schaufler <[email protected]> wrote:
> On 3/7/2023 3:51 AM, Mickaël Salaün wrote:
> >
> > On 22/02/2023 21:08, Casey Schaufler wrote:
> >> Create a system call lsm_get_self_attr() to provide the security
> >> module maintained attributes of the current process.
> >> Create a system call lsm_set_self_attr() to set a security
> >> module maintained attribute of the current process.
> >> Historically these attributes have been exposed to user space via
> >> entries in procfs under /proc/self/attr.
> >>
> >> The attribute value is provided in a lsm_ctx structure. The structure
> >> identifys the size of the attribute, and the attribute value. The format
> >> of the attribute value is defined by the security module. A flags field
> >> is included for LSM specific information. It is currently unused and
> >> must
> >> be 0. The total size of the data, including the lsm_ctx structure and
> >> any
> >> padding, is maintained as well.
> >>
> >> struct lsm_ctx {
> >> __u64 id;
> >> __u64 flags;
> >> __u64 len;
> >> __u64 ctx_len;
> >> __u8 ctx[];
> >> };
> >>
> >> Two new LSM hooks are used to interface with the LSMs.
> >> security_getselfattr() collects the lsm_ctx values from the
> >> LSMs that support the hook, accounting for space requirements.
> >> security_setselfattr() identifies which LSM the attribute is
> >> intended for and passes it along.
> >>
> >> Signed-off-by: Casey Schaufler <[email protected]>
> >> ---
> >> Documentation/userspace-api/lsm.rst | 15 ++++
> >> include/linux/lsm_hook_defs.h | 4 ++
> >> include/linux/lsm_hooks.h | 9 +++
> >> include/linux/security.h | 19 +++++
> >> include/linux/syscalls.h | 4 ++
> >> include/uapi/linux/lsm.h | 33 +++++++++
> >> kernel/sys_ni.c | 4 ++
> >> security/Makefile | 1 +
> >> security/lsm_syscalls.c | 104 ++++++++++++++++++++++++++++
> >> security/security.c | 82 ++++++++++++++++++++++
> >> 10 files changed, 275 insertions(+)
> >> create mode 100644 security/lsm_syscalls.c
> >>
> >
> > [...]
> >
> >> +/**
> >> + * security_setselfattr - Set an LSM attribute on the current process.
> >> + * @attr: which attribute to return
> >> + * @ctx: the user-space source for the information
> >> + * @size: the size of the data
> >> + *
> >> + * Set an LSM attribute for the current process. The LSM, attribute
> >> + * and new value are included in @ctx.
> >> + *
> >> + * Returns 0 on seccess, an LSM specific value on failure.
> >> + */
> >> +int security_setselfattr(u64 __user attr, struct lsm_ctx __user *ctx,
> >> + size_t __user size)
> >> +{
> >> + struct security_hook_list *hp;
> >> + struct lsm_ctx lctx;
> >> +
> >> + if (size < sizeof(*ctx))
> >
> > If the lsm_ctx struct could grow in the future, we should check the
> > size of the struct to the last field for compatibility reasons, see
> > Landlock's copy_min_struct_from_user().
>
> Because the lsm_ctx structure ends with the variable length context there's
> no way to append new fields to it. The structure can't grow.

The lsm_ctx can grow; that was one of the reasons for having both a
@len and @ctx_len field in the struct, the other being padding. Of
course any LSM wanting to place information beyond the end of @ctx
will need to indicate that with a bit in the @flags field.

Having said that, there are probably other ways to pass other data via
a lsm_ctx struct, e.g. binary @ctx values, but I don't think we want
to rule anything out at this point.

Also, as a reminder, just because we *can* do something, doesn't mean
we will do something. Any LSM that wants to pass something other than
a string @ctx value will face a *lot* of scrutiny.

--
paul-moore.com

2023-04-06 16:47:42

by Casey Schaufler

[permalink] [raw]
Subject: Re: [PATCH v6 05/11] LSM: Create lsm_module_list system call

On 3/7/2023 3:33 AM, Mickaël Salaün wrote:
>
> On 22/02/2023 21:08, Casey Schaufler wrote:
>> 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 chosing an
>
> "choosing"

Oops. Thank you.

>
>> output format, determining required privilege or bypassing
>> security module specific behavior.
>>
>> Signed-off-by: Casey Schaufler <[email protected]>
>> ---
>>   Documentation/userspace-api/lsm.rst |  3 ++
>>   include/linux/syscalls.h            |  1 +
>>   kernel/sys_ni.c                     |  1 +
>>   security/lsm_syscalls.c             | 43 ++++++++++++++++++++++++++++-
>>   4 files changed, 47 insertions(+), 1 deletion(-)
>>
>> diff --git a/Documentation/userspace-api/lsm.rst
>> b/Documentation/userspace-api/lsm.rst
>> index b45e402302b3..ecdf1acd15b1 100644
>> --- a/Documentation/userspace-api/lsm.rst
>> +++ b/Documentation/userspace-api/lsm.rst
>> @@ -63,6 +63,9 @@ Get the specified security attributes of the
>> current process
>>   .. kernel-doc:: security/lsm_syscalls.c
>>       :identifiers: sys_lsm_get_self_attr
>>   +.. kernel-doc:: security/lsm_syscalls.c
>> +    :identifiers: sys_lsm_module_list
>> +
>>   Additional documentation
>>   ========================
>>   diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
>> index 1ef2a3de8ae0..9c947022a411 100644
>> --- a/include/linux/syscalls.h
>> +++ b/include/linux/syscalls.h
>> @@ -1062,6 +1062,7 @@ asmlinkage long
>> sys_set_mempolicy_home_node(unsigned long start, unsigned long l
>>   asmlinkage long sys_lsm_get_self_attr(struct lsm_ctx *ctx, size_t
>> *size,
>>                         __u64 flags);
>>   asmlinkage long sys_lsm_set_self_attr(struct lsm_ctx *ctx, __u64
>> flags);
>> +asmlinkage long sys_lsm_module_list(u64 *ids, size_t *size, int flags);
>>     /*
>>    * Architecture-specific system calls
>> diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
>> index d03c78ef1562..32784e271fa5 100644
>> --- a/kernel/sys_ni.c
>> +++ b/kernel/sys_ni.c
>> @@ -265,6 +265,7 @@ COND_SYSCALL(mremap);
>>   /* security/lsm_syscalls.c */
>>   COND_SYSCALL(lsm_get_self_attr);
>>   COND_SYSCALL(lsm_set_self_attr);
>> +COND_SYSCALL(lsm_module_list);
>>     /* security/keys/keyctl.c */
>>   COND_SYSCALL(add_key);
>> diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c
>> index b89c4e7d009e..ccd3b236670b 100644
>> --- a/security/lsm_syscalls.c
>> +++ b/security/lsm_syscalls.c
>> @@ -19,7 +19,7 @@
>>     struct attrs_map {
>>       char *name;
>> -    int attrs;
>> +    u64 attrs;
>
> Why do we need this change in this patch?

We don't. It's gone in subsequent versions.

>
>>   };
>>     static const struct attrs_map lsm_attr_names[] = {
>> @@ -102,3 +102,44 @@ SYSCALL_DEFINE3(lsm_get_self_attr, struct
>> lsm_ctx __user *, ctx,
>>   {
>>       return security_getselfattr(flags, ctx, size);
>>   }
>> +
>> +/**
>> + * sys_lsm_module_list - Return a list of the active security modules
>> + * @ids: the LSM module ids
>> + * @size: size of @ids, updated on return
>> + * @flags: reserved for future use, must be zero
>> + *
>> + * Returns a list of the active LSM ids. On success this function
>> + * returns the number of @ids array elements. This value may be zero
>> + * if there are no LSMs active. If @size is insufficient to contain
>> + * the return data -E2BIG is returned and @size is set to the minimum
>> + * required size. In all other cases a negative value indicating the
>> + * error is returned.
>> + */
>> +SYSCALL_DEFINE3(lsm_module_list,
>
> The name of this syscall differ from the two others: there is not
> "get" verb. What about "lsm_get_modules" or "lsm_list_modules"?

lsm_list_modules() it is henceforth.

>
>> +        u64 __user *, ids,
>> +        size_t __user *, size,
>> +        u64, flags)
>
> As Arnd said, flags should be a u32.

Agreed.

>
>> +{
>> +    size_t total_size = lsm_active_cnt * sizeof(*ids);
>> +    size_t usize;
>> +    int i;
>> +
>> +    if (flags)
>> +        return -EINVAL;
>> +
>> +    if (get_user(usize, size))
>> +        return -EFAULT;
>
> I'm not a fan of using the same pointer to read and write. This avoid
> using const pointers and differentiate between input and output
> values. I suggest using a dedicated argument for each.

This is pretty standard practice.

>
>> +
>> +    if (put_user(total_size, size) != 0)
>> +        return -EFAULT;
>> +
>> +    if (usize < total_size)
>> +        return -E2BIG;
>> +
>> +    for (i = 0; i < lsm_active_cnt; i++)
>> +        if (put_user(lsm_idlist[i]->id, ids++))
>
> I'm not sure about it, but it may be better to put the complete list
> of IDs at once. Is it better to set the size before or after?

You may be right. I'll consider it.

>
>
>> +            return -EFAULT;
>> +
>> +    return lsm_active_cnt;
>> +}