aboutsummaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig.hardening4
-rw-r--r--security/apparmor/domain.c1
-rw-r--r--security/apparmor/policy_unpack.c2
-rw-r--r--security/integrity/evm/evm_main.c3
-rw-r--r--security/integrity/ima/ima_main.c7
-rw-r--r--security/integrity/ima/ima_template_lib.c14
-rw-r--r--security/integrity/integrity.h4
-rw-r--r--security/ipe/Kconfig19
-rw-r--r--security/ipe/policy.c18
-rw-r--r--security/keys/keyring.c7
-rw-r--r--security/keys/trusted-keys/trusted_dcp.c9
-rw-r--r--security/keys/trusted-keys/trusted_tpm2.c2
-rw-r--r--security/landlock/fs.c31
-rw-r--r--security/landlock/net.c28
-rw-r--r--security/landlock/ruleset.h74
-rw-r--r--security/landlock/syscalls.c47
-rw-r--r--security/landlock/task.c18
-rw-r--r--security/loadpin/loadpin.c8
-rw-r--r--security/security.c10
-rw-r--r--security/tomoyo/Kconfig15
-rw-r--r--security/tomoyo/Makefile8
-rw-r--r--security/tomoyo/common.c14
-rw-r--r--security/tomoyo/common.h72
-rw-r--r--security/tomoyo/gc.c3
-rw-r--r--security/tomoyo/init.c366
-rw-r--r--security/tomoyo/load_policy.c12
-rw-r--r--security/tomoyo/proxy.c82
-rw-r--r--security/tomoyo/securityfs_if.c10
-rw-r--r--security/tomoyo/tomoyo.c (renamed from security/tomoyo/hooks.h)110
-rw-r--r--security/tomoyo/util.c3
30 files changed, 302 insertions, 699 deletions
diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening
index 2cff851ebfd7..c9d5ca3d8d08 100644
--- a/security/Kconfig.hardening
+++ b/security/Kconfig.hardening
@@ -340,7 +340,7 @@ choice
config RANDSTRUCT_FULL
bool "Fully randomize structure layout"
depends on CC_HAS_RANDSTRUCT || GCC_PLUGINS
- select MODVERSIONS if MODULES
+ select MODVERSIONS if MODULES && !COMPILE_TEST
help
Fully randomize the member layout of sensitive
structures as much as possible, which may have both a
@@ -356,7 +356,7 @@ choice
config RANDSTRUCT_PERFORMANCE
bool "Limit randomization of structure layout to cache-lines"
depends on GCC_PLUGINS
- select MODVERSIONS if MODULES
+ select MODVERSIONS if MODULES && !COMPILE_TEST
help
Randomization of sensitive kernel structures will make a
best effort at restricting randomization to cacheline-sized
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 571158ec6188..2bc34dce9a46 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -9,7 +9,6 @@
*/
#include <linux/errno.h>
-#include <linux/fdtable.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/mount.h>
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index 5a570235427d..3483c595f999 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -13,7 +13,7 @@
* All policy is validated before it is used.
*/
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include <kunit/visibility.h>
#include <linux/ctype.h>
#include <linux/errno.h>
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 6924ed508ebd..377e57e9084f 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -1084,7 +1084,8 @@ static void evm_file_release(struct file *file)
if (!S_ISREG(inode->i_mode) || !(mode & FMODE_WRITE))
return;
- if (iint && atomic_read(&inode->i_writecount) == 1)
+ if (iint && iint->flags & EVM_NEW_FILE &&
+ atomic_read(&inode->i_writecount) == 1)
iint->flags &= ~EVM_NEW_FILE;
}
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 06132cf47016..db5e2dd7cec9 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -1062,19 +1062,16 @@ out:
*/
void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
{
- struct fd f;
-
if (!buf || !size)
return;
- f = fdget(kernel_fd);
- if (!fd_file(f))
+ CLASS(fd, f)(kernel_fd);
+ if (fd_empty(f))
return;
process_buffer_measurement(file_mnt_idmap(fd_file(f)), file_inode(fd_file(f)),
buf, size, "kexec-cmdline", KEXEC_CMDLINE, 0,
NULL, false, NULL, 0);
- fdput(f);
}
/**
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
index 4183956c53af..0e627eac9c33 100644
--- a/security/integrity/ima/ima_template_lib.c
+++ b/security/integrity/ima/ima_template_lib.c
@@ -318,15 +318,21 @@ static int ima_eventdigest_init_common(const u8 *digest, u32 digestsize,
hash_algo_name[hash_algo]);
}
- if (digest)
+ if (digest) {
memcpy(buffer + offset, digest, digestsize);
- else
+ } else {
/*
* If digest is NULL, the event being recorded is a violation.
* Make room for the digest by increasing the offset by the
- * hash algorithm digest size.
+ * hash algorithm digest size. If the hash algorithm is not
+ * specified increase the offset by IMA_DIGEST_SIZE which
+ * fits SHA1 or MD5
*/
- offset += hash_digest_size[hash_algo];
+ if (hash_algo < HASH_ALGO__LAST)
+ offset += hash_digest_size[hash_algo];
+ else
+ offset += IMA_DIGEST_SIZE;
+ }
return ima_write_template_field_data(buffer, offset + digestsize,
fmt, field_data);
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 660f76cb69d3..c2c2da691123 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -37,6 +37,8 @@ struct evm_ima_xattr_data {
);
u8 data[];
} __packed;
+static_assert(offsetof(struct evm_ima_xattr_data, data) == sizeof(struct evm_ima_xattr_data_hdr),
+ "struct member likely outside of __struct_group()");
/* Only used in the EVM HMAC code. */
struct evm_xattr {
@@ -65,6 +67,8 @@ struct ima_digest_data {
);
u8 digest[];
} __packed;
+static_assert(offsetof(struct ima_digest_data, digest) == sizeof(struct ima_digest_data_hdr),
+ "struct member likely outside of __struct_group()");
/*
* Instead of wrapping the ima_digest_data struct inside a local structure
diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig
index 3ab582606ed2..3c75bf267da4 100644
--- a/security/ipe/Kconfig
+++ b/security/ipe/Kconfig
@@ -31,6 +31,25 @@ config IPE_BOOT_POLICY
If unsure, leave blank.
+config IPE_POLICY_SIG_SECONDARY_KEYRING
+ bool "IPE policy update verification with secondary keyring"
+ default y
+ depends on SECONDARY_TRUSTED_KEYRING
+ help
+ Also allow the secondary trusted keyring to verify IPE policy
+ updates.
+
+ If unsure, answer Y.
+
+config IPE_POLICY_SIG_PLATFORM_KEYRING
+ bool "IPE policy update verification with platform keyring"
+ default y
+ depends on INTEGRITY_PLATFORM_KEYRING
+ help
+ Also allow the platform keyring to verify IPE policy updates.
+
+ If unsure, answer Y.
+
menu "IPE Trust Providers"
config IPE_PROP_DM_VERITY
diff --git a/security/ipe/policy.c b/security/ipe/policy.c
index d8e7db857a2e..b628f696e32b 100644
--- a/security/ipe/policy.c
+++ b/security/ipe/policy.c
@@ -106,8 +106,8 @@ int ipe_update_policy(struct inode *root, const char *text, size_t textlen,
goto err;
}
- if (ver_to_u64(old) > ver_to_u64(new)) {
- rc = -EINVAL;
+ if (ver_to_u64(old) >= ver_to_u64(new)) {
+ rc = -ESTALE;
goto err;
}
@@ -169,9 +169,21 @@ struct ipe_policy *ipe_new_policy(const char *text, size_t textlen,
goto err;
}
- rc = verify_pkcs7_signature(NULL, 0, new->pkcs7, pkcs7len, NULL,
+ rc = verify_pkcs7_signature(NULL, 0, new->pkcs7, pkcs7len,
+#ifdef CONFIG_IPE_POLICY_SIG_SECONDARY_KEYRING
+ VERIFY_USE_SECONDARY_KEYRING,
+#else
+ NULL,
+#endif
VERIFYING_UNSPECIFIED_SIGNATURE,
set_pkcs7_data, new);
+#ifdef CONFIG_IPE_POLICY_SIG_PLATFORM_KEYRING
+ if (rc == -ENOKEY || rc == -EKEYREJECTED)
+ rc = verify_pkcs7_signature(NULL, 0, new->pkcs7, pkcs7len,
+ VERIFY_USE_PLATFORM_KEYRING,
+ VERIFYING_UNSPECIFIED_SIGNATURE,
+ set_pkcs7_data, new);
+#endif
if (rc)
goto err;
} else {
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 4448758f643a..f331725d5a37 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -772,8 +772,11 @@ ascend_to_node:
for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) {
ptr = READ_ONCE(node->slots[slot]);
- if (assoc_array_ptr_is_meta(ptr) && node->back_pointer)
- goto descend_to_node;
+ if (assoc_array_ptr_is_meta(ptr)) {
+ if (node->back_pointer ||
+ assoc_array_ptr_is_shortcut(ptr))
+ goto descend_to_node;
+ }
if (!keyring_ptr_is_keyring(ptr))
continue;
diff --git a/security/keys/trusted-keys/trusted_dcp.c b/security/keys/trusted-keys/trusted_dcp.c
index 4edc5bbbcda3..e908c53a803c 100644
--- a/security/keys/trusted-keys/trusted_dcp.c
+++ b/security/keys/trusted-keys/trusted_dcp.c
@@ -133,6 +133,7 @@ static int do_aead_crypto(u8 *in, u8 *out, size_t len, u8 *key, u8 *nonce,
struct scatterlist src_sg, dst_sg;
struct crypto_aead *aead;
int ret;
+ DECLARE_CRYPTO_WAIT(wait);
aead = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(aead)) {
@@ -163,8 +164,8 @@ static int do_aead_crypto(u8 *in, u8 *out, size_t len, u8 *key, u8 *nonce,
}
aead_request_set_crypt(aead_req, &src_sg, &dst_sg, len, nonce);
- aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL,
- NULL);
+ aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_SLEEP,
+ crypto_req_done, &wait);
aead_request_set_ad(aead_req, 0);
if (crypto_aead_setkey(aead, key, AES_KEYSIZE_128)) {
@@ -174,9 +175,9 @@ static int do_aead_crypto(u8 *in, u8 *out, size_t len, u8 *key, u8 *nonce,
}
if (do_encrypt)
- ret = crypto_aead_encrypt(aead_req);
+ ret = crypto_wait_req(crypto_aead_encrypt(aead_req), &wait);
else
- ret = crypto_aead_decrypt(aead_req);
+ ret = crypto_wait_req(crypto_aead_decrypt(aead_req), &wait);
free_req:
aead_request_free(aead_req);
diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c
index 8b7dd73d94c1..024be262702f 100644
--- a/security/keys/trusted-keys/trusted_tpm2.c
+++ b/security/keys/trusted-keys/trusted_tpm2.c
@@ -14,7 +14,7 @@
#include <keys/trusted-type.h>
#include <keys/trusted_tpm.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include "tpm2key.asn1.h"
diff --git a/security/landlock/fs.c b/security/landlock/fs.c
index 7d79fc8abe21..e31b97a9f175 100644
--- a/security/landlock/fs.c
+++ b/security/landlock/fs.c
@@ -389,37 +389,21 @@ static bool is_nouser_or_private(const struct dentry *dentry)
}
static access_mask_t
-get_raw_handled_fs_accesses(const struct landlock_ruleset *const domain)
-{
- access_mask_t access_dom = 0;
- size_t layer_level;
-
- for (layer_level = 0; layer_level < domain->num_layers; layer_level++)
- access_dom |=
- landlock_get_raw_fs_access_mask(domain, layer_level);
- return access_dom;
-}
-
-static access_mask_t
get_handled_fs_accesses(const struct landlock_ruleset *const domain)
{
/* Handles all initially denied by default access rights. */
- return get_raw_handled_fs_accesses(domain) |
+ return landlock_union_access_masks(domain).fs |
LANDLOCK_ACCESS_FS_INITIALLY_DENIED;
}
-static const struct landlock_ruleset *
-get_fs_domain(const struct landlock_ruleset *const domain)
-{
- if (!domain || !get_raw_handled_fs_accesses(domain))
- return NULL;
-
- return domain;
-}
+static const struct access_masks any_fs = {
+ .fs = ~0,
+};
static const struct landlock_ruleset *get_current_fs_domain(void)
{
- return get_fs_domain(landlock_get_current_domain());
+ return landlock_get_applicable_domain(landlock_get_current_domain(),
+ any_fs);
}
/*
@@ -1517,7 +1501,8 @@ static int hook_file_open(struct file *const file)
access_mask_t open_access_request, full_access_request, allowed_access,
optional_access;
const struct landlock_ruleset *const dom =
- get_fs_domain(landlock_cred(file->f_cred)->domain);
+ landlock_get_applicable_domain(
+ landlock_cred(file->f_cred)->domain, any_fs);
if (!dom)
return 0;
diff --git a/security/landlock/net.c b/security/landlock/net.c
index c8bcd29bde09..d5dcc4407a19 100644
--- a/security/landlock/net.c
+++ b/security/landlock/net.c
@@ -39,27 +39,9 @@ int landlock_append_net_rule(struct landlock_ruleset *const ruleset,
return err;
}
-static access_mask_t
-get_raw_handled_net_accesses(const struct landlock_ruleset *const domain)
-{
- access_mask_t access_dom = 0;
- size_t layer_level;
-
- for (layer_level = 0; layer_level < domain->num_layers; layer_level++)
- access_dom |= landlock_get_net_access_mask(domain, layer_level);
- return access_dom;
-}
-
-static const struct landlock_ruleset *get_current_net_domain(void)
-{
- const struct landlock_ruleset *const dom =
- landlock_get_current_domain();
-
- if (!dom || !get_raw_handled_net_accesses(dom))
- return NULL;
-
- return dom;
-}
+static const struct access_masks any_net = {
+ .net = ~0,
+};
static int current_check_access_socket(struct socket *const sock,
struct sockaddr *const address,
@@ -72,7 +54,9 @@ static int current_check_access_socket(struct socket *const sock,
struct landlock_id id = {
.type = LANDLOCK_KEY_NET_PORT,
};
- const struct landlock_ruleset *const dom = get_current_net_domain();
+ const struct landlock_ruleset *const dom =
+ landlock_get_applicable_domain(landlock_get_current_domain(),
+ any_net);
if (!dom)
return 0;
diff --git a/security/landlock/ruleset.h b/security/landlock/ruleset.h
index 61bdbc550172..631e24d4ffe9 100644
--- a/security/landlock/ruleset.h
+++ b/security/landlock/ruleset.h
@@ -11,6 +11,7 @@
#include <linux/bitops.h>
#include <linux/build_bug.h>
+#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/rbtree.h>
#include <linux/refcount.h>
@@ -47,6 +48,15 @@ struct access_masks {
access_mask_t scope : LANDLOCK_NUM_SCOPE;
};
+union access_masks_all {
+ struct access_masks masks;
+ u32 all;
+};
+
+/* Makes sure all fields are covered. */
+static_assert(sizeof(typeof_member(union access_masks_all, masks)) ==
+ sizeof(typeof_member(union access_masks_all, all)));
+
typedef u16 layer_mask_t;
/* Makes sure all layers can be checked. */
static_assert(BITS_PER_TYPE(layer_mask_t) >= LANDLOCK_MAX_NUM_LAYERS);
@@ -260,6 +270,61 @@ static inline void landlock_get_ruleset(struct landlock_ruleset *const ruleset)
refcount_inc(&ruleset->usage);
}
+/**
+ * landlock_union_access_masks - Return all access rights handled in the
+ * domain
+ *
+ * @domain: Landlock ruleset (used as a domain)
+ *
+ * Returns: an access_masks result of the OR of all the domain's access masks.
+ */
+static inline struct access_masks
+landlock_union_access_masks(const struct landlock_ruleset *const domain)
+{
+ union access_masks_all matches = {};
+ size_t layer_level;
+
+ for (layer_level = 0; layer_level < domain->num_layers; layer_level++) {
+ union access_masks_all layer = {
+ .masks = domain->access_masks[layer_level],
+ };
+
+ matches.all |= layer.all;
+ }
+
+ return matches.masks;
+}
+
+/**
+ * landlock_get_applicable_domain - Return @domain if it applies to (handles)
+ * at least one of the access rights specified
+ * in @masks
+ *
+ * @domain: Landlock ruleset (used as a domain)
+ * @masks: access masks
+ *
+ * Returns: @domain if any access rights specified in @masks is handled, or
+ * NULL otherwise.
+ */
+static inline const struct landlock_ruleset *
+landlock_get_applicable_domain(const struct landlock_ruleset *const domain,
+ const struct access_masks masks)
+{
+ const union access_masks_all masks_all = {
+ .masks = masks,
+ };
+ union access_masks_all merge = {};
+
+ if (!domain)
+ return NULL;
+
+ merge.masks = landlock_union_access_masks(domain);
+ if (merge.all & masks_all.all)
+ return domain;
+
+ return NULL;
+}
+
static inline void
landlock_add_fs_access_mask(struct landlock_ruleset *const ruleset,
const access_mask_t fs_access_mask,
@@ -296,18 +361,11 @@ landlock_add_scope_mask(struct landlock_ruleset *const ruleset,
}
static inline access_mask_t
-landlock_get_raw_fs_access_mask(const struct landlock_ruleset *const ruleset,
- const u16 layer_level)
-{
- return ruleset->access_masks[layer_level].fs;
-}
-
-static inline access_mask_t
landlock_get_fs_access_mask(const struct landlock_ruleset *const ruleset,
const u16 layer_level)
{
/* Handles all initially denied by default access rights. */
- return landlock_get_raw_fs_access_mask(ruleset, layer_level) |
+ return ruleset->access_masks[layer_level].fs |
LANDLOCK_ACCESS_FS_INITIALLY_DENIED;
}
diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c
index f5a0e7182ec0..4ed8e70c25ed 100644
--- a/security/landlock/syscalls.c
+++ b/security/landlock/syscalls.c
@@ -241,31 +241,21 @@ SYSCALL_DEFINE3(landlock_create_ruleset,
static struct landlock_ruleset *get_ruleset_from_fd(const int fd,
const fmode_t mode)
{
- struct fd ruleset_f;
+ CLASS(fd, ruleset_f)(fd);
struct landlock_ruleset *ruleset;
- ruleset_f = fdget(fd);
- if (!fd_file(ruleset_f))
+ if (fd_empty(ruleset_f))
return ERR_PTR(-EBADF);
/* Checks FD type and access right. */
- if (fd_file(ruleset_f)->f_op != &ruleset_fops) {
- ruleset = ERR_PTR(-EBADFD);
- goto out_fdput;
- }
- if (!(fd_file(ruleset_f)->f_mode & mode)) {
- ruleset = ERR_PTR(-EPERM);
- goto out_fdput;
- }
+ if (fd_file(ruleset_f)->f_op != &ruleset_fops)
+ return ERR_PTR(-EBADFD);
+ if (!(fd_file(ruleset_f)->f_mode & mode))
+ return ERR_PTR(-EPERM);
ruleset = fd_file(ruleset_f)->private_data;
- if (WARN_ON_ONCE(ruleset->num_layers != 1)) {
- ruleset = ERR_PTR(-EINVAL);
- goto out_fdput;
- }
+ if (WARN_ON_ONCE(ruleset->num_layers != 1))
+ return ERR_PTR(-EINVAL);
landlock_get_ruleset(ruleset);
-
-out_fdput:
- fdput(ruleset_f);
return ruleset;
}
@@ -276,15 +266,12 @@ out_fdput:
*/
static int get_path_from_fd(const s32 fd, struct path *const path)
{
- struct fd f;
- int err = 0;
+ CLASS(fd_raw, f)(fd);
BUILD_BUG_ON(!__same_type(
fd, ((struct landlock_path_beneath_attr *)NULL)->parent_fd));
- /* Handles O_PATH. */
- f = fdget_raw(fd);
- if (!fd_file(f))
+ if (fd_empty(f))
return -EBADF;
/*
* Forbids ruleset FDs, internal filesystems (e.g. nsfs), including
@@ -295,16 +282,12 @@ static int get_path_from_fd(const s32 fd, struct path *const path)
(fd_file(f)->f_path.mnt->mnt_flags & MNT_INTERNAL) ||
(fd_file(f)->f_path.dentry->d_sb->s_flags & SB_NOUSER) ||
d_is_negative(fd_file(f)->f_path.dentry) ||
- IS_PRIVATE(d_backing_inode(fd_file(f)->f_path.dentry))) {
- err = -EBADFD;
- goto out_fdput;
- }
+ IS_PRIVATE(d_backing_inode(fd_file(f)->f_path.dentry)))
+ return -EBADFD;
+
*path = fd_file(f)->f_path;
path_get(path);
-
-out_fdput:
- fdput(f);
- return err;
+ return 0;
}
static int add_rule_path_beneath(struct landlock_ruleset *const ruleset,
@@ -329,7 +312,7 @@ static int add_rule_path_beneath(struct landlock_ruleset *const ruleset,
return -ENOMSG;
/* Checks that allowed_access matches the @ruleset constraints. */
- mask = landlock_get_raw_fs_access_mask(ruleset, 0);
+ mask = ruleset->access_masks[0].fs;
if ((path_beneath_attr.allowed_access | mask) != mask)
return -EINVAL;
diff --git a/security/landlock/task.c b/security/landlock/task.c
index 4acbd7c40eee..dc7dab78392e 100644
--- a/security/landlock/task.c
+++ b/security/landlock/task.c
@@ -204,12 +204,17 @@ static bool is_abstract_socket(struct sock *const sock)
return false;
}
+static const struct access_masks unix_scope = {
+ .scope = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET,
+};
+
static int hook_unix_stream_connect(struct sock *const sock,
struct sock *const other,
struct sock *const newsk)
{
const struct landlock_ruleset *const dom =
- landlock_get_current_domain();
+ landlock_get_applicable_domain(landlock_get_current_domain(),
+ unix_scope);
/* Quick return for non-landlocked tasks. */
if (!dom)
@@ -225,7 +230,8 @@ static int hook_unix_may_send(struct socket *const sock,
struct socket *const other)
{
const struct landlock_ruleset *const dom =
- landlock_get_current_domain();
+ landlock_get_applicable_domain(landlock_get_current_domain(),
+ unix_scope);
if (!dom)
return 0;
@@ -243,6 +249,10 @@ static int hook_unix_may_send(struct socket *const sock,
return 0;
}
+static const struct access_masks signal_scope = {
+ .scope = LANDLOCK_SCOPE_SIGNAL,
+};
+
static int hook_task_kill(struct task_struct *const p,
struct kernel_siginfo *const info, const int sig,
const struct cred *const cred)
@@ -256,6 +266,7 @@ static int hook_task_kill(struct task_struct *const p,
} else {
dom = landlock_get_current_domain();
}
+ dom = landlock_get_applicable_domain(dom, signal_scope);
/* Quick return for non-landlocked tasks. */
if (!dom)
@@ -279,7 +290,8 @@ static int hook_file_send_sigiotask(struct task_struct *tsk,
/* Lock already held by send_sigio() and send_sigurg(). */
lockdep_assert_held(&fown->lock);
- dom = landlock_file(fown->file)->fown_domain;
+ dom = landlock_get_applicable_domain(
+ landlock_file(fown->file)->fown_domain, signal_scope);
/* Quick return for unowned socket. */
if (!dom)
diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
index 02144ec39f43..68252452b66c 100644
--- a/security/loadpin/loadpin.c
+++ b/security/loadpin/loadpin.c
@@ -283,7 +283,6 @@ enum loadpin_securityfs_interface_index {
static int read_trusted_verity_root_digests(unsigned int fd)
{
- struct fd f;
void *data;
int rc;
char *p, *d;
@@ -295,8 +294,8 @@ static int read_trusted_verity_root_digests(unsigned int fd)
if (!list_empty(&dm_verity_loadpin_trusted_root_digests))
return -EPERM;
- f = fdget(fd);
- if (!fd_file(f))
+ CLASS(fd, f)(fd);
+ if (fd_empty(f))
return -EINVAL;
data = kzalloc(SZ_4K, GFP_KERNEL);
@@ -359,7 +358,6 @@ static int read_trusted_verity_root_digests(unsigned int fd)
}
kfree(data);
- fdput(f);
return 0;
@@ -379,8 +377,6 @@ err:
/* disallow further attempts after reading a corrupt/invalid file */
deny_reading_verity_digests = true;
- fdput(f);
-
return rc;
}
diff --git a/security/security.c b/security/security.c
index 6875eb4a59fc..c5981e558bc2 100644
--- a/security/security.c
+++ b/security/security.c
@@ -740,19 +740,20 @@ static int lsm_file_alloc(struct file *file)
/**
* lsm_inode_alloc - allocate a composite inode blob
* @inode: the inode that needs a blob
+ * @gfp: allocation flags
*
* Allocate the inode blob for all the modules
*
* Returns 0, or -ENOMEM if memory can't be allocated.
*/
-static int lsm_inode_alloc(struct inode *inode)
+static int lsm_inode_alloc(struct inode *inode, gfp_t gfp)
{
if (!lsm_inode_cache) {
inode->i_security = NULL;
return 0;
}
- inode->i_security = kmem_cache_zalloc(lsm_inode_cache, GFP_NOFS);
+ inode->i_security = kmem_cache_zalloc(lsm_inode_cache, gfp);
if (inode->i_security == NULL)
return -ENOMEM;
return 0;
@@ -1678,6 +1679,7 @@ int security_path_notify(const struct path *path, u64 mask,
/**
* security_inode_alloc() - Allocate an inode LSM blob
* @inode: the inode
+ * @gfp: allocation flags
*
* Allocate and attach a security structure to @inode->i_security. The
* i_security field is initialized to NULL when the inode structure is
@@ -1685,9 +1687,9 @@ int security_path_notify(const struct path *path, u64 mask,
*
* Return: Return 0 if operation was successful.
*/
-int security_inode_alloc(struct inode *inode)
+int security_inode_alloc(struct inode *inode, gfp_t gfp)
{
- int rc = lsm_inode_alloc(inode);
+ int rc = lsm_inode_alloc(inode, gfp);
if (unlikely(rc))
return rc;
diff --git a/security/tomoyo/Kconfig b/security/tomoyo/Kconfig
index 90eccc6cd464..1e0dd1a6d0b0 100644
--- a/security/tomoyo/Kconfig
+++ b/security/tomoyo/Kconfig
@@ -13,21 +13,6 @@ config SECURITY_TOMOYO
found at <https://tomoyo.sourceforge.net/>.
If you are unsure how to answer this question, answer N.
-config SECURITY_TOMOYO_LKM
- bool "Cut out most of TOMOYO's code to a loadable kernel module"
- default n
- depends on SECURITY_TOMOYO
- depends on MODULES
- help
- Say Y here if you want to include TOMOYO without bloating
- vmlinux file. If you say Y, most of TOMOYO code is cut out to
- a loadable kernel module named tomoyo.ko . This option will be
- useful for kernels built by Linux distributors where TOMOYO is
- included but TOMOYO is not enabled by default. Please be sure
- to explicitly load tomoyo.ko if you want to activate TOMOYO
- without calling userspace policy loader, for tomoyo.ko is
- loaded immediately before calling userspace policy loader.
-
config SECURITY_TOMOYO_MAX_ACCEPT_ENTRY
int "Default maximal count for learning mode"
default 2048
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile
index 287a7d16fa15..55c67b9846a9 100644
--- a/security/tomoyo/Makefile
+++ b/security/tomoyo/Makefile
@@ -1,11 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-tomoyo-objs := audit.o common.o condition.o domain.o environ.o file.o gc.o group.o memory.o mount.o network.o proxy.o realpath.o securityfs_if.o util.o
-obj-y += init.o load_policy.o
-ifdef CONFIG_SECURITY_TOMOYO_LKM
-obj-m += tomoyo.o
-else
-obj-y += tomoyo.o
-endif
+obj-y = audit.o common.o condition.o domain.o environ.o file.o gc.o group.o load_policy.o memory.o mount.o network.o realpath.o securityfs_if.o tomoyo.o util.o
targets += builtin-policy.h
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index c0ef014f8009..5c7b059a332a 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -998,13 +998,8 @@ static bool tomoyo_select_domain(struct tomoyo_io_buffer *head,
p = find_task_by_pid_ns(pid, &init_pid_ns);
else
p = find_task_by_vpid(pid);
- if (p) {
+ if (p)
domain = tomoyo_task(p)->domain_info;
-#ifdef CONFIG_SECURITY_TOMOYO_LKM
- if (!domain)
- domain = &tomoyo_kernel_domain;
-#endif
- }
rcu_read_unlock();
} else if (!strncmp(data, "domain=", 7)) {
if (tomoyo_domain_def(data + 7))
@@ -1715,13 +1710,8 @@ static void tomoyo_read_pid(struct tomoyo_io_buffer *head)
p = find_task_by_pid_ns(pid, &init_pid_ns);
else
p = find_task_by_vpid(pid);
- if (p) {
+ if (p)
domain = tomoyo_task(p)->domain_info;
-#ifdef CONFIG_SECURITY_TOMOYO_LKM
- if (!domain)
- domain = &tomoyo_kernel_domain;
-#endif
- }
rcu_read_unlock();
if (!domain)
return;
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 4f6c52a9f478..0e8e2e959aef 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -978,7 +978,6 @@ int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile,
int tomoyo_init_request_info(struct tomoyo_request_info *r,
struct tomoyo_domain_info *domain,
const u8 index);
-int __init tomoyo_interface_init(void);
int tomoyo_mkdev_perm(const u8 operation, const struct path *path,
const unsigned int mode, unsigned int dev);
int tomoyo_mount_permission(const char *dev_name, const struct path *path,
@@ -1215,14 +1214,10 @@ static inline void tomoyo_put_group(struct tomoyo_group *group)
*
* Returns pointer to "struct tomoyo_task" for specified thread.
*/
-#ifdef CONFIG_SECURITY_TOMOYO_LKM
-extern struct tomoyo_task *tomoyo_task(struct task_struct *task);
-#else
static inline struct tomoyo_task *tomoyo_task(struct task_struct *task)
{
return task->security + tomoyo_blob_sizes.lbs_task;
}
-#endif
/**
* tomoyo_same_name_union - Check for duplicated "struct tomoyo_name_union" entry.
@@ -1289,71 +1284,4 @@ static inline struct tomoyo_policy_namespace *tomoyo_current_namespace(void)
pos = srcu_dereference((head)->next, &tomoyo_ss); \
for ( ; pos != (head); pos = srcu_dereference(pos->next, &tomoyo_ss))
-#ifdef CONFIG_SECURITY_TOMOYO_LKM
-
-#define LSM_HOOK(RET, DEFAULT, NAME, ...) typedef RET (NAME##_t)(__VA_ARGS__);
-#include <linux/lsm_hook_defs.h>
-#undef LSM_HOOK
-
-struct tomoyo_hooks {
- cred_prepare_t *cred_prepare;
- bprm_committed_creds_t *bprm_committed_creds;
- task_alloc_t *task_alloc;
- task_free_t *task_free;
- bprm_check_security_t *bprm_check_security;
- file_fcntl_t *file_fcntl;
- file_open_t *file_open;
- file_truncate_t *file_truncate;
- path_truncate_t *path_truncate;
- path_unlink_t *path_unlink;
- path_mkdir_t *path_mkdir;
- path_rmdir_t *path_rmdir;
- path_symlink_t *path_symlink;
- path_mknod_t *path_mknod;
- path_link_t *path_link;
- path_rename_t *path_rename;
- inode_getattr_t *inode_getattr;
- file_ioctl_t *file_ioctl;
- file_ioctl_compat_t *file_ioctl_compat;
- path_chmod_t *path_chmod;
- path_chown_t *path_chown;
- path_chroot_t *path_chroot;
- sb_mount_t *sb_mount;
- sb_umount_t *sb_umount;
- sb_pivotroot_t *sb_pivotroot;
- socket_bind_t *socket_bind;
- socket_connect_t *socket_connect;
- socket_listen_t *socket_listen;
- socket_sendmsg_t *socket_sendmsg;
-};
-
-extern void tomoyo_register_hooks(const struct tomoyo_hooks *tomoyo_hooks);
-
-struct tomoyo_operations {
- void (*check_profile)(void);
- int enabled;
-};
-
-extern struct tomoyo_operations tomoyo_ops;
-
-/*
- * Temporary hack: functions needed by tomoyo.ko . This will be removed
- * after all functions are marked as EXPORT_STMBOL_GPL().
- */
-struct tomoyo_tmp_exports {
- struct task_struct * (*find_task_by_vpid)(pid_t nr);
- struct task_struct * (*find_task_by_pid_ns)(pid_t nr, struct pid_namespace *ns);
- void (*put_filesystem)(struct file_system_type *fs);
- struct file * (*get_mm_exe_file)(struct mm_struct *mm);
- char * (*d_absolute_path)(const struct path *path, char *buf, int buflen);
-};
-extern const struct tomoyo_tmp_exports tomoyo_tmp_exports;
-#define find_task_by_vpid tomoyo_tmp_exports.find_task_by_vpid
-#define find_task_by_pid_ns tomoyo_tmp_exports.find_task_by_pid_ns
-#define put_filesystem tomoyo_tmp_exports.put_filesystem
-#define get_mm_exe_file tomoyo_tmp_exports.get_mm_exe_file
-#define d_absolute_path tomoyo_tmp_exports.d_absolute_path
-
-#endif /* defined(CONFIG_SECURITY_TOMOYO_LKM) */
-
#endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c
index 6eccca150839..026e29ea3796 100644
--- a/security/tomoyo/gc.c
+++ b/security/tomoyo/gc.c
@@ -9,9 +9,6 @@
#include <linux/kthread.h>
#include <linux/slab.h>
-/* Lock for GC. */
-DEFINE_SRCU(tomoyo_ss);
-
/**
* tomoyo_memory_free - Free memory for elements.
*
diff --git a/security/tomoyo/init.c b/security/tomoyo/init.c
deleted file mode 100644
index 034e7db22d4e..000000000000
--- a/security/tomoyo/init.c
+++ /dev/null
@@ -1,366 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * security/tomoyo/init.c
- *
- * Copyright (C) 2005-2011 NTT DATA CORPORATION
- */
-
-#include <linux/lsm_hooks.h>
-#include <uapi/linux/lsm.h>
-#include "common.h"
-
-#ifndef CONFIG_SECURITY_TOMOYO_LKM
-
-#include "hooks.h"
-
-#else
-
-#define DEFINE_STATIC_CALL_PROXY(NAME) \
- static NAME##_t tomoyo_##NAME; \
- DEFINE_STATIC_CALL_RET0(tomoyo_##NAME, tomoyo_##NAME);
-DEFINE_STATIC_CALL_PROXY(cred_prepare)
-DEFINE_STATIC_CALL_PROXY(bprm_committed_creds)
-DEFINE_STATIC_CALL_PROXY(bprm_check_security)
-DEFINE_STATIC_CALL_PROXY(inode_getattr)
-DEFINE_STATIC_CALL_PROXY(path_truncate)
-DEFINE_STATIC_CALL_PROXY(file_truncate)
-DEFINE_STATIC_CALL_PROXY(path_unlink)
-DEFINE_STATIC_CALL_PROXY(path_mkdir)
-DEFINE_STATIC_CALL_PROXY(path_rmdir)
-DEFINE_STATIC_CALL_PROXY(path_symlink)
-DEFINE_STATIC_CALL_PROXY(path_mknod)
-DEFINE_STATIC_CALL_PROXY(path_link)
-DEFINE_STATIC_CALL_PROXY(path_rename)
-DEFINE_STATIC_CALL_PROXY(file_fcntl)
-DEFINE_STATIC_CALL_PROXY(file_open)
-DEFINE_STATIC_CALL_PROXY(file_ioctl)
-DEFINE_STATIC_CALL_PROXY(path_chmod)
-DEFINE_STATIC_CALL_PROXY(path_chown)
-DEFINE_STATIC_CALL_PROXY(path_chroot)
-DEFINE_STATIC_CALL_PROXY(sb_mount)
-DEFINE_STATIC_CALL_PROXY(sb_umount)
-DEFINE_STATIC_CALL_PROXY(sb_pivotroot)
-DEFINE_STATIC_CALL_PROXY(socket_listen)
-DEFINE_STATIC_CALL_PROXY(socket_connect)
-DEFINE_STATIC_CALL_PROXY(socket_bind)
-DEFINE_STATIC_CALL_PROXY(socket_sendmsg)
-DEFINE_STATIC_CALL_PROXY(task_alloc)
-DEFINE_STATIC_CALL_PROXY(task_free)
-#undef DEFINE_STATIC_CALL_PROXY
-
-static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, gfp_t gfp)
-{
- return static_call(tomoyo_cred_prepare)(new, old, gfp);
-}
-
-static void tomoyo_bprm_committed_creds(const struct linux_binprm *bprm)
-{
- static_call(tomoyo_bprm_committed_creds)(bprm);
-}
-
-static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
-{
- return static_call(tomoyo_bprm_check_security)(bprm);
-}
-
-static int tomoyo_inode_getattr(const struct path *path)
-{
- return static_call(tomoyo_inode_getattr)(path);
-}
-
-static int tomoyo_path_truncate(const struct path *path)
-{
- return static_call(tomoyo_path_truncate)(path);
-}
-
-static int tomoyo_file_truncate(struct file *file)
-{
- return static_call(tomoyo_file_truncate)(file);
-}
-
-static int tomoyo_path_unlink(const struct path *parent, struct dentry *dentry)
-{
- return static_call(tomoyo_path_unlink)(parent, dentry);
-}
-
-static int tomoyo_path_mkdir(const struct path *parent, struct dentry *dentry, umode_t mode)
-{
- return static_call(tomoyo_path_mkdir)(parent, dentry, mode);
-}
-
-static int tomoyo_path_rmdir(const struct path *parent, struct dentry *dentry)
-{
- return static_call(tomoyo_path_rmdir)(parent, dentry);
-}
-
-static int tomoyo_path_symlink(const struct path *parent, struct dentry *dentry,
- const char *old_name)
-{
- return static_call(tomoyo_path_symlink)(parent, dentry, old_name);
-}
-
-static int tomoyo_path_mknod(const struct path *parent, struct dentry *dentry,
- umode_t mode, unsigned int dev)
-{
- return static_call(tomoyo_path_mknod)(parent, dentry, mode, dev);
-}
-
-static int tomoyo_path_link(struct dentry *old_dentry, const struct path *new_dir,
- struct dentry *new_dentry)
-{
- return static_call(tomoyo_path_link)(old_dentry, new_dir, new_dentry);
-}
-
-static int tomoyo_path_rename(const struct path *old_parent, struct dentry *old_dentry,
- const struct path *new_parent, struct dentry *new_dentry,
- const unsigned int flags)
-{
- return static_call(tomoyo_path_rename)(old_parent, old_dentry, new_parent, new_dentry, flags);
-}
-
-static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- return static_call(tomoyo_file_fcntl)(file, cmd, arg);
-}
-
-static int tomoyo_file_open(struct file *f)
-{
- return static_call(tomoyo_file_open)(f);
-}
-
-static int tomoyo_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- return static_call(tomoyo_file_ioctl)(file, cmd, arg);
-}
-
-static int tomoyo_path_chmod(const struct path *path, umode_t mode)
-{
- return static_call(tomoyo_path_chmod)(path, mode);
-}
-
-static int tomoyo_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
-{
- return static_call(tomoyo_path_chown)(path, uid, gid);
-}
-
-static int tomoyo_path_chroot(const struct path *path)
-{
- return static_call(tomoyo_path_chroot)(path);
-}
-
-static int tomoyo_sb_mount(const char *dev_name, const struct path *path,
- const char *type, unsigned long flags, void *data)
-{
- return static_call(tomoyo_sb_mount)(dev_name, path, type, flags, data);
-}
-
-static int tomoyo_sb_umount(struct vfsmount *mnt, int flags)
-{
- return static_call(tomoyo_sb_umount)(mnt, flags);
-}
-
-static int tomoyo_sb_pivotroot(const struct path *old_path, const struct path *new_path)
-{
- return static_call(tomoyo_sb_pivotroot)(old_path, new_path);
-}
-
-static int tomoyo_socket_listen(struct socket *sock, int backlog)
-{
- return static_call(tomoyo_socket_listen)(sock, backlog);
-}
-
-static int tomoyo_socket_connect(struct socket *sock, struct sockaddr *addr, int addr_len)
-{
- return static_call(tomoyo_socket_connect)(sock, addr, addr_len);
-}
-
-static int tomoyo_socket_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
-{
- return static_call(tomoyo_socket_bind)(sock, addr, addr_len);
-}
-
-static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
-{
- return static_call(tomoyo_socket_sendmsg)(sock, msg, size);
-}
-
-static int tomoyo_task_alloc(struct task_struct *task, unsigned long clone_flags)
-{
- return static_call(tomoyo_task_alloc)(task, clone_flags);
-}
-
-static void tomoyo_task_free(struct task_struct *task)
-{
- static_call(tomoyo_task_free)(task);
-}
-
-void tomoyo_register_hooks(const struct tomoyo_hooks *tomoyo_hooks)
-{
- static void *registered;
-
- if (cmpxchg(&registered, NULL, &registered))
- panic("%s was called twice!\n", __func__);
- static_call_update(tomoyo_task_free, tomoyo_hooks->task_free);
- static_call_update(tomoyo_task_alloc, tomoyo_hooks->task_alloc);
- static_call_update(tomoyo_cred_prepare, tomoyo_hooks->cred_prepare);
- static_call_update(tomoyo_bprm_committed_creds, tomoyo_hooks->bprm_committed_creds);
- static_call_update(tomoyo_bprm_check_security, tomoyo_hooks->bprm_check_security);
- static_call_update(tomoyo_inode_getattr, tomoyo_hooks->inode_getattr);
- static_call_update(tomoyo_path_truncate, tomoyo_hooks->path_truncate);
- static_call_update(tomoyo_file_truncate, tomoyo_hooks->file_truncate);
- static_call_update(tomoyo_path_unlink, tomoyo_hooks->path_unlink);
- static_call_update(tomoyo_path_mkdir, tomoyo_hooks->path_mkdir);
- static_call_update(tomoyo_path_rmdir, tomoyo_hooks->path_rmdir);
- static_call_update(tomoyo_path_symlink, tomoyo_hooks->path_symlink);
- static_call_update(tomoyo_path_mknod, tomoyo_hooks->path_mknod);
- static_call_update(tomoyo_path_link, tomoyo_hooks->path_link);
- static_call_update(tomoyo_path_rename, tomoyo_hooks->path_rename);
- static_call_update(tomoyo_file_fcntl, tomoyo_hooks->file_fcntl);
- static_call_update(tomoyo_file_open, tomoyo_hooks->file_open);
- static_call_update(tomoyo_file_ioctl, tomoyo_hooks->file_ioctl);
- static_call_update(tomoyo_path_chmod, tomoyo_hooks->path_chmod);
- static_call_update(tomoyo_path_chown, tomoyo_hooks->path_chown);
- static_call_update(tomoyo_path_chroot, tomoyo_hooks->path_chroot);
- static_call_update(tomoyo_sb_mount, tomoyo_hooks->sb_mount);
- static_call_update(tomoyo_sb_umount, tomoyo_hooks->sb_umount);
- static_call_update(tomoyo_sb_pivotroot, tomoyo_hooks->sb_pivotroot);
- static_call_update(tomoyo_socket_listen, tomoyo_hooks->socket_listen);
- static_call_update(tomoyo_socket_connect, tomoyo_hooks->socket_connect);
- static_call_update(tomoyo_socket_bind, tomoyo_hooks->socket_bind);
- static_call_update(tomoyo_socket_sendmsg, tomoyo_hooks->socket_sendmsg);
-}
-EXPORT_SYMBOL_GPL(tomoyo_register_hooks);
-
-/*
- * Temporary hack: functions needed by tomoyo.ko . This hack will be removed
- * after all functions are marked as EXPORT_STMBOL_GPL().
- */
-#undef find_task_by_vpid
-#undef find_task_by_pid_ns
-#undef put_filesystem
-#undef get_mm_exe_file
-#undef d_absolute_path
-const struct tomoyo_tmp_exports tomoyo_tmp_exports = {
- .find_task_by_vpid = find_task_by_vpid,
- .find_task_by_pid_ns = find_task_by_pid_ns,
- .put_filesystem = put_filesystem,
- .get_mm_exe_file = get_mm_exe_file,
- .d_absolute_path = d_absolute_path,
-};
-EXPORT_SYMBOL_GPL(tomoyo_tmp_exports);
-
-#endif
-
-#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER
-static int tomoyo_bprm_creds_for_exec(struct linux_binprm *bprm)
-{
- /*
- * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested
- * for the first time.
- */
- if (!tomoyo_policy_loaded)
- tomoyo_load_policy(bprm->filename);
- return 0;
-}
-#endif
-
-struct lsm_blob_sizes tomoyo_blob_sizes __ro_after_init = {
- .lbs_task = sizeof(struct tomoyo_task),
-};
-
-static const struct lsm_id tomoyo_lsmid = {
- .name = "tomoyo",
- .id = LSM_ID_TOMOYO,
-};
-
-/* tomoyo_hooks is used for registering TOMOYO. */
-static struct security_hook_list tomoyo_hooks[] __ro_after_init = {
- LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare),
- LSM_HOOK_INIT(bprm_committed_creds, tomoyo_bprm_committed_creds),
- LSM_HOOK_INIT(task_alloc, tomoyo_task_alloc),
- LSM_HOOK_INIT(task_free, tomoyo_task_free),
-#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER
- LSM_HOOK_INIT(bprm_creds_for_exec, tomoyo_bprm_creds_for_exec),
-#endif
- LSM_HOOK_INIT(bprm_check_security, tomoyo_bprm_check_security),
- LSM_HOOK_INIT(file_fcntl, tomoyo_file_fcntl),
- LSM_HOOK_INIT(file_open, tomoyo_file_open),
- LSM_HOOK_INIT(file_truncate, tomoyo_file_truncate),
- LSM_HOOK_INIT(path_truncate, tomoyo_path_truncate),
- LSM_HOOK_INIT(path_unlink, tomoyo_path_unlink),
- LSM_HOOK_INIT(path_mkdir, tomoyo_path_mkdir),
- LSM_HOOK_INIT(path_rmdir, tomoyo_path_rmdir),
- LSM_HOOK_INIT(path_symlink, tomoyo_path_symlink),
- LSM_HOOK_INIT(path_mknod, tomoyo_path_mknod),
- LSM_HOOK_INIT(path_link, tomoyo_path_link),
- LSM_HOOK_INIT(path_rename, tomoyo_path_rename),
- LSM_HOOK_INIT(inode_getattr, tomoyo_inode_getattr),
- LSM_HOOK_INIT(file_ioctl, tomoyo_file_ioctl),
- LSM_HOOK_INIT(file_ioctl_compat, tomoyo_file_ioctl),
- LSM_HOOK_INIT(path_chmod, tomoyo_path_chmod),
- LSM_HOOK_INIT(path_chown, tomoyo_path_chown),
- LSM_HOOK_INIT(path_chroot, tomoyo_path_chroot),
- LSM_HOOK_INIT(sb_mount, tomoyo_sb_mount),
- LSM_HOOK_INIT(sb_umount, tomoyo_sb_umount),
- LSM_HOOK_INIT(sb_pivotroot, tomoyo_sb_pivotroot),
- LSM_HOOK_INIT(socket_bind, tomoyo_socket_bind),
- LSM_HOOK_INIT(socket_connect, tomoyo_socket_connect),
- LSM_HOOK_INIT(socket_listen, tomoyo_socket_listen),
- LSM_HOOK_INIT(socket_sendmsg, tomoyo_socket_sendmsg),
-};
-
-int tomoyo_enabled __ro_after_init = 1;
-
-/* Has /sbin/init started? */
-bool tomoyo_policy_loaded;
-
-#ifdef CONFIG_SECURITY_TOMOYO_LKM
-EXPORT_SYMBOL_GPL(tomoyo_blob_sizes);
-EXPORT_SYMBOL_GPL(tomoyo_policy_loaded);
-
-struct tomoyo_operations tomoyo_ops;
-EXPORT_SYMBOL_GPL(tomoyo_ops);
-
-/**
- * tomoyo_init - Reserve hooks for TOMOYO Linux.
- *
- * Returns 0.
- */
-static int __init tomoyo_init(void)
-{
- /* register ourselves with the security framework */
- security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), &tomoyo_lsmid);
- tomoyo_ops.enabled = tomoyo_enabled;
- pr_info("Hooks for initializing TOMOYO Linux are ready\n");
- return 0;
-}
-#else
-/**
- * tomoyo_init - Register TOMOYO Linux as a LSM module.
- *
- * Returns 0.
- */
-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_lsmid);
- pr_info("TOMOYO Linux initialized\n");
- s->domain_info = &tomoyo_kernel_domain;
- atomic_inc(&tomoyo_kernel_domain.users);
- s->old_domain_info = NULL;
- tomoyo_mm_init();
-
- return 0;
-}
-#endif
-
-DEFINE_LSM(tomoyo) = {
- .name = "tomoyo",
- .enabled = &tomoyo_enabled,
- .flags = LSM_FLAG_LEGACY_MAJOR,
- .blobs = &tomoyo_blob_sizes,
- .init = tomoyo_init,
-};
diff --git a/security/tomoyo/load_policy.c b/security/tomoyo/load_policy.c
index 6a2a72354a64..363b65be87ab 100644
--- a/security/tomoyo/load_policy.c
+++ b/security/tomoyo/load_policy.c
@@ -97,14 +97,6 @@ void tomoyo_load_policy(const char *filename)
if (!tomoyo_policy_loader_exists())
return;
done = true;
-#ifdef CONFIG_SECURITY_TOMOYO_LKM
- /* Load tomoyo.ko if not yet loaded. */
- if (!tomoyo_ops.check_profile)
- request_module("tomoyo");
- /* Check if tomoyo.ko was successfully loaded. */
- if (!tomoyo_ops.check_profile)
- panic("Failed to load tomoyo module.");
-#endif
pr_info("Calling %s to load policy. Please wait.\n", tomoyo_loader);
argv[0] = (char *) tomoyo_loader;
argv[1] = NULL;
@@ -112,11 +104,7 @@ void tomoyo_load_policy(const char *filename)
envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
envp[2] = NULL;
call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
-#ifdef CONFIG_SECURITY_TOMOYO_LKM
- tomoyo_ops.check_profile();
-#else
tomoyo_check_profile();
-#endif
}
#endif
diff --git a/security/tomoyo/proxy.c b/security/tomoyo/proxy.c
deleted file mode 100644
index 1618cc0f2af8..000000000000
--- a/security/tomoyo/proxy.c
+++ /dev/null
@@ -1,82 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * security/tomoyo/proxy.c
- *
- * Copyright (C) 2005-2011 NTT DATA CORPORATION
- */
-
-#include <linux/security.h>
-#include "common.h"
-
-#ifdef CONFIG_SECURITY_TOMOYO_LKM
-
-struct tomoyo_task *tomoyo_task(struct task_struct *task)
-{
- struct tomoyo_task *s = task->security + tomoyo_blob_sizes.lbs_task;
-
- if (unlikely(!s->domain_info)) {
- if (likely(task == current)) {
- s->domain_info = &tomoyo_kernel_domain;
- atomic_inc(&tomoyo_kernel_domain.users);
- } else {
- /* Caller handles s->domain_info == NULL case. */
- }
- }
- return s;
-}
-
-#include "hooks.h"
-
-/**
- * tomoyo_runtime_init - Register TOMOYO Linux as a loadable LSM module.
- *
- * Returns 0 if TOMOYO is enabled, -EINVAL otherwise.
- */
-static int __init tomoyo_runtime_init(void)
-{
- const struct tomoyo_hooks tomoyo_hooks = {
- .cred_prepare = tomoyo_cred_prepare,
- .bprm_committed_creds = tomoyo_bprm_committed_creds,
- .task_alloc = tomoyo_task_alloc,
- .task_free = tomoyo_task_free,
- .bprm_check_security = tomoyo_bprm_check_security,
- .file_fcntl = tomoyo_file_fcntl,
- .file_open = tomoyo_file_open,
- .file_truncate = tomoyo_file_truncate,
- .path_truncate = tomoyo_path_truncate,
- .path_unlink = tomoyo_path_unlink,
- .path_mkdir = tomoyo_path_mkdir,
- .path_rmdir = tomoyo_path_rmdir,
- .path_symlink = tomoyo_path_symlink,
- .path_mknod = tomoyo_path_mknod,
- .path_link = tomoyo_path_link,
- .path_rename = tomoyo_path_rename,
- .inode_getattr = tomoyo_inode_getattr,
- .file_ioctl = tomoyo_file_ioctl,
- .file_ioctl_compat = tomoyo_file_ioctl,
- .path_chmod = tomoyo_path_chmod,
- .path_chown = tomoyo_path_chown,
- .path_chroot = tomoyo_path_chroot,
- .sb_mount = tomoyo_sb_mount,
- .sb_umount = tomoyo_sb_umount,
- .sb_pivotroot = tomoyo_sb_pivotroot,
- .socket_bind = tomoyo_socket_bind,
- .socket_connect = tomoyo_socket_connect,
- .socket_listen = tomoyo_socket_listen,
- .socket_sendmsg = tomoyo_socket_sendmsg,
- };
-
- if (!tomoyo_ops.enabled)
- return -EINVAL;
- tomoyo_ops.check_profile = tomoyo_check_profile;
- pr_info("TOMOYO Linux initialized\n");
- tomoyo_task(current);
- tomoyo_mm_init();
- tomoyo_interface_init();
- tomoyo_register_hooks(&tomoyo_hooks);
- return 0;
-}
-module_init(tomoyo_runtime_init);
-MODULE_LICENSE("GPL");
-
-#endif
diff --git a/security/tomoyo/securityfs_if.c b/security/tomoyo/securityfs_if.c
index a3b821b7f477..a2705798476f 100644
--- a/security/tomoyo/securityfs_if.c
+++ b/security/tomoyo/securityfs_if.c
@@ -229,19 +229,17 @@ static void __init tomoyo_create_entry(const char *name, const umode_t mode,
}
/**
- * tomoyo_interface_init - Initialize /sys/kernel/security/tomoyo/ interface.
+ * tomoyo_initerface_init - Initialize /sys/kernel/security/tomoyo/ interface.
*
* Returns 0.
*/
-int __init tomoyo_interface_init(void)
+static int __init tomoyo_initerface_init(void)
{
struct tomoyo_domain_info *domain;
struct dentry *tomoyo_dir;
-#ifndef CONFIG_SECURITY_TOMOYO_LKM
if (!tomoyo_enabled)
return 0;
-#endif
domain = tomoyo_domain();
/* Don't create securityfs entries unless registered. */
if (domain != &tomoyo_kernel_domain)
@@ -272,6 +270,4 @@ int __init tomoyo_interface_init(void)
return 0;
}
-#ifndef CONFIG_SECURITY_TOMOYO_LKM
-fs_initcall(tomoyo_interface_init);
-#endif
+fs_initcall(tomoyo_initerface_init);
diff --git a/security/tomoyo/hooks.h b/security/tomoyo/tomoyo.c
index 58929bb71477..04a92c3d65d4 100644
--- a/security/tomoyo/hooks.h
+++ b/security/tomoyo/tomoyo.c
@@ -1,10 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * security/tomoyo/hooks.h
+ * security/tomoyo/tomoyo.c
*
* Copyright (C) 2005-2011 NTT DATA CORPORATION
*/
+#include <linux/lsm_hooks.h>
+#include <uapi/linux/lsm.h>
#include "common.h"
/**
@@ -16,6 +18,10 @@ struct tomoyo_domain_info *tomoyo_domain(void)
{
struct tomoyo_task *s = tomoyo_task(current);
+ if (s->old_domain_info && !current->in_execve) {
+ atomic_dec(&s->old_domain_info->users);
+ s->old_domain_info = NULL;
+ }
return s->domain_info;
}
@@ -56,6 +62,26 @@ static void tomoyo_bprm_committed_creds(const struct linux_binprm *bprm)
s->old_domain_info = NULL;
}
+#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER
+/**
+ * tomoyo_bprm_creds_for_exec - Target for security_bprm_creds_for_exec().
+ *
+ * @bprm: Pointer to "struct linux_binprm".
+ *
+ * Returns 0.
+ */
+static int tomoyo_bprm_creds_for_exec(struct linux_binprm *bprm)
+{
+ /*
+ * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested
+ * for the first time.
+ */
+ if (!tomoyo_policy_loaded)
+ tomoyo_load_policy(bprm->filename);
+ return 0;
+}
+#endif
+
/**
* tomoyo_bprm_check_security - Target for security_bprm_check().
*
@@ -475,6 +501,10 @@ static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg,
return tomoyo_socket_sendmsg_permission(sock, msg, size);
}
+struct lsm_blob_sizes tomoyo_blob_sizes __ro_after_init = {
+ .lbs_task = sizeof(struct tomoyo_task),
+};
+
/**
* tomoyo_task_alloc - Target for security_task_alloc().
*
@@ -513,3 +543,81 @@ static void tomoyo_task_free(struct task_struct *task)
s->old_domain_info = NULL;
}
}
+
+static const struct lsm_id tomoyo_lsmid = {
+ .name = "tomoyo",
+ .id = LSM_ID_TOMOYO,
+};
+
+/*
+ * tomoyo_security_ops is a "struct security_operations" which is used for
+ * registering TOMOYO.
+ */
+static struct security_hook_list tomoyo_hooks[] __ro_after_init = {
+ LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare),
+ LSM_HOOK_INIT(bprm_committed_creds, tomoyo_bprm_committed_creds),
+ LSM_HOOK_INIT(task_alloc, tomoyo_task_alloc),
+ LSM_HOOK_INIT(task_free, tomoyo_task_free),
+#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER
+ LSM_HOOK_INIT(bprm_creds_for_exec, tomoyo_bprm_creds_for_exec),
+#endif
+ LSM_HOOK_INIT(bprm_check_security, tomoyo_bprm_check_security),
+ LSM_HOOK_INIT(file_fcntl, tomoyo_file_fcntl),
+ LSM_HOOK_INIT(file_open, tomoyo_file_open),
+ LSM_HOOK_INIT(file_truncate, tomoyo_file_truncate),
+ LSM_HOOK_INIT(path_truncate, tomoyo_path_truncate),
+ LSM_HOOK_INIT(path_unlink, tomoyo_path_unlink),
+ LSM_HOOK_INIT(path_mkdir, tomoyo_path_mkdir),
+ LSM_HOOK_INIT(path_rmdir, tomoyo_path_rmdir),
+ LSM_HOOK_INIT(path_symlink, tomoyo_path_symlink),
+ LSM_HOOK_INIT(path_mknod, tomoyo_path_mknod),
+ LSM_HOOK_INIT(path_link, tomoyo_path_link),
+ LSM_HOOK_INIT(path_rename, tomoyo_path_rename),
+ LSM_HOOK_INIT(inode_getattr, tomoyo_inode_getattr),
+ LSM_HOOK_INIT(file_ioctl, tomoyo_file_ioctl),
+ LSM_HOOK_INIT(file_ioctl_compat, tomoyo_file_ioctl),
+ LSM_HOOK_INIT(path_chmod, tomoyo_path_chmod),
+ LSM_HOOK_INIT(path_chown, tomoyo_path_chown),
+ LSM_HOOK_INIT(path_chroot, tomoyo_path_chroot),
+ LSM_HOOK_INIT(sb_mount, tomoyo_sb_mount),
+ LSM_HOOK_INIT(sb_umount, tomoyo_sb_umount),
+ LSM_HOOK_INIT(sb_pivotroot, tomoyo_sb_pivotroot),
+ LSM_HOOK_INIT(socket_bind, tomoyo_socket_bind),
+ LSM_HOOK_INIT(socket_connect, tomoyo_socket_connect),
+ LSM_HOOK_INIT(socket_listen, tomoyo_socket_listen),
+ LSM_HOOK_INIT(socket_sendmsg, tomoyo_socket_sendmsg),
+};
+
+/* Lock for GC. */
+DEFINE_SRCU(tomoyo_ss);
+
+int tomoyo_enabled __ro_after_init = 1;
+
+/**
+ * tomoyo_init - Register TOMOYO Linux as a LSM module.
+ *
+ * Returns 0.
+ */
+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_lsmid);
+ pr_info("TOMOYO Linux initialized\n");
+ s->domain_info = &tomoyo_kernel_domain;
+ atomic_inc(&tomoyo_kernel_domain.users);
+ s->old_domain_info = NULL;
+ tomoyo_mm_init();
+
+ return 0;
+}
+
+DEFINE_LSM(tomoyo) = {
+ .name = "tomoyo",
+ .enabled = &tomoyo_enabled,
+ .flags = LSM_FLAG_LEGACY_MAJOR,
+ .blobs = &tomoyo_blob_sizes,
+ .init = tomoyo_init,
+};
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c
index b851ff377382..6799b1122c9d 100644
--- a/security/tomoyo/util.c
+++ b/security/tomoyo/util.c
@@ -13,6 +13,9 @@
/* Lock for protecting policy. */
DEFINE_MUTEX(tomoyo_policy_lock);
+/* Has /sbin/init started? */
+bool tomoyo_policy_loaded;
+
/*
* Mapping table from "enum tomoyo_mac_index" to
* "enum tomoyo_mac_category_index".