lsm/stable-6.19 PR 20251201

-----BEGIN PGP SIGNATURE-----
 
 iQJIBAABCgAyFiEES0KozwfymdVUl37v6iDy2pc3iXMFAmkuALUUHHBhdWxAcGF1
 bC1tb29yZS5jb20ACgkQ6iDy2pc3iXOtDg/8DMxvN2XKZrryP31zdknUEHLJOTfz
 eFCaNKQJK9GpJ1Q/Z4P/q/dH4QUKZHEM7E18N/hjA4Nx6Z7I1eVPK6hvvySkRa9l
 b5j+GTLteMcANV04i04B8VTn2mtEW5SZp0Y280EFOMoVGvav72zAt4HHWVytDzyy
 tVzvuC6iPNbe7rw+eUzTjHAq3WWWYe42QmiDfnAttdjWloSnfMx6AIvEoeo6jryc
 aLGeZQsrgk2wL/ovXXD5kvDo1EQnETGuxQRh8P3W2DzLwEtt6d+BpfAm9PE0FE4k
 oE5YrqOhvIpmcBm/8DdkvZ0o0gdfe0IrACvoEqJVpWs6w6T6zusiTzwWp7tBzET/
 ygqYabUpz+BrAsGNVtXlDD4va37e5OI500PjDntuT4GMwKBGe5JKXLeki0sQeu6d
 AcZd8hu6sVpYDLWJoWDXplxq1ndJTfafVtONQ5Cw8BHM5j6CIAaZM13KG9rJSOYa
 uyNOfHxndsjV7dzuQ9S763l4djixiw0oU/PF+XQP4dC/Dyf60yb47mCOlZndRaJj
 /FqR0Rbp2KonOSrkmzPTteGJOLMgM5bquZsSHNClxC/qeHTv8xKWf0HRWN61ZUe2
 /NLcSjL+CIcN6q0c8jx/k7I9N/yQcmQLQIVTnUY6YOi0TkhUUdqSaq0rp8rSDW9z
 AUvHpfPpC92klcM=
 =u7yQ
 -----END PGP SIGNATURE-----

Merge tag 'lsm-pr-20251201' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm

Pull LSM updates from Paul Moore:

 - Rework the LSM initialization code

   What started as a "quick" patch to enable a notification event once
   all of the individual LSMs were initialized, snowballed a bit into a
   30+ patch patchset when everything was done. Most of the patches, and
   diffstat, is due to splitting out the initialization code into
   security/lsm_init.c and cleaning up some of the mess that was there.
   While not strictly necessary, it does cleanup the code signficantly,
   and hopefully makes the upkeep a bit easier in the future.

   Aside from the new LSM_STARTED_ALL notification, these changes also
   ensure that individual LSM initcalls are only called when the LSM is
   enabled at boot time. There should be a minor reduction in boot times
   for those who build multiple LSMs into their kernels, but only enable
   a subset at boot.

   It is worth mentioning that nothing at present makes use of the
   LSM_STARTED_ALL notification, but there is work in progress which is
   dependent upon LSM_STARTED_ALL.

 - Make better use of the seq_put*() helpers in device_cgroup

* tag 'lsm-pr-20251201' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm: (36 commits)
  lsm: use unrcu_pointer() for current->cred in security_init()
  device_cgroup: Refactor devcgroup_seq_show to use seq_put* helpers
  lsm: add a LSM_STARTED_ALL notification event
  lsm: consolidate all of the LSM framework initcalls
  selinux: move initcalls to the LSM framework
  ima,evm: move initcalls to the LSM framework
  lockdown: move initcalls to the LSM framework
  apparmor: move initcalls to the LSM framework
  safesetid: move initcalls to the LSM framework
  tomoyo: move initcalls to the LSM framework
  smack: move initcalls to the LSM framework
  ipe: move initcalls to the LSM framework
  loadpin: move initcalls to the LSM framework
  lsm: introduce an initcall mechanism into the LSM framework
  lsm: group lsm_order_parse() with the other lsm_order_*() functions
  lsm: output available LSMs when debugging
  lsm: cleanup the debug and console output in lsm_init.c
  lsm: add/tweak function header comment blocks in lsm_init.c
  lsm: fold lsm_init_ordered() into security_init()
  lsm: cleanup initialize_lsm() and rename to lsm_init_single()
  ...
This commit is contained in:
Linus Torvalds 2025-12-03 09:53:48 -08:00
commit 121cc35cfb
53 changed files with 1026 additions and 743 deletions

View File

@ -102,23 +102,23 @@ struct security_hook_list {
* Security blob size or offset data.
*/
struct lsm_blob_sizes {
int lbs_cred;
int lbs_file;
int lbs_ib;
int lbs_inode;
int lbs_sock;
int lbs_superblock;
int lbs_ipc;
int lbs_key;
int lbs_msg_msg;
int lbs_perf_event;
int lbs_task;
int lbs_xattr_count; /* number of xattr slots in new_xattrs array */
int lbs_tun_dev;
int lbs_bdev;
int lbs_bpf_map;
int lbs_bpf_prog;
int lbs_bpf_token;
unsigned int lbs_cred;
unsigned int lbs_file;
unsigned int lbs_ib;
unsigned int lbs_inode;
unsigned int lbs_sock;
unsigned int lbs_superblock;
unsigned int lbs_ipc;
unsigned int lbs_key;
unsigned int lbs_msg_msg;
unsigned int lbs_perf_event;
unsigned int lbs_task;
unsigned int lbs_xattr_count; /* num xattr slots in new_xattrs array */
unsigned int lbs_tun_dev;
unsigned int lbs_bdev;
unsigned int lbs_bpf_map;
unsigned int lbs_bpf_prog;
unsigned int lbs_bpf_token;
};
/*
@ -151,13 +151,36 @@ enum lsm_order {
LSM_ORDER_LAST = 1, /* This is only for integrity. */
};
/**
* struct lsm_info - Define an individual LSM for the LSM framework.
* @id: LSM name/ID info
* @order: ordering with respect to other LSMs, optional
* @flags: descriptive flags, optional
* @blobs: LSM blob sharing, optional
* @enabled: controlled by CONFIG_LSM, optional
* @init: LSM specific initialization routine
* @initcall_pure: LSM callback for initcall_pure() setup, optional
* @initcall_early: LSM callback for early_initcall setup, optional
* @initcall_core: LSM callback for core_initcall() setup, optional
* @initcall_subsys: LSM callback for subsys_initcall() setup, optional
* @initcall_fs: LSM callback for fs_initcall setup, optional
* @nitcall_device: LSM callback for device_initcall() setup, optional
* @initcall_late: LSM callback for late_initcall() setup, optional
*/
struct lsm_info {
const char *name; /* Required. */
enum lsm_order order; /* Optional: default is LSM_ORDER_MUTABLE */
unsigned long flags; /* Optional: flags describing LSM */
int *enabled; /* Optional: controlled by CONFIG_LSM */
int (*init)(void); /* Required. */
struct lsm_blob_sizes *blobs; /* Optional: for blob sharing. */
const struct lsm_id *id;
enum lsm_order order;
unsigned long flags;
struct lsm_blob_sizes *blobs;
int *enabled;
int (*init)(void);
int (*initcall_pure)(void);
int (*initcall_early)(void);
int (*initcall_core)(void);
int (*initcall_subsys)(void);
int (*initcall_fs)(void);
int (*initcall_device)(void);
int (*initcall_late)(void);
};
#define DEFINE_LSM(lsm) \
@ -170,11 +193,9 @@ struct lsm_info {
__used __section(".early_lsm_info.init") \
__aligned(sizeof(unsigned long))
/* DO NOT tamper with these variables outside of the LSM framework */
extern char *lsm_names;
extern struct lsm_static_calls_table static_calls_table __ro_after_init;
extern struct lsm_info __start_lsm_info[], __end_lsm_info[];
extern struct lsm_info __start_early_lsm_info[], __end_early_lsm_info[];
/**
* lsm_get_xattr_slot - Return the next available slot and increment the index

View File

@ -85,6 +85,7 @@ struct timezone;
enum lsm_event {
LSM_POLICY_CHANGE,
LSM_STARTED_ALL,
};
struct dm_verity_digest {
@ -167,8 +168,6 @@ struct lsm_prop {
};
extern const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1];
extern u32 lsm_active_cnt;
extern const struct lsm_id *lsm_idlist[];
/* These functions are in security/commoncap.c */
extern int cap_capable(const struct cred *cred, struct user_namespace *ns,

View File

@ -11,7 +11,7 @@ obj-$(CONFIG_SECURITY) += lsm_syscalls.o
obj-$(CONFIG_MMU) += min_addr.o
# Object file lists
obj-$(CONFIG_SECURITY) += security.o
obj-$(CONFIG_SECURITY) += security.o lsm_notifier.o lsm_init.o
obj-$(CONFIG_SECURITYFS) += inode.o
obj-$(CONFIG_SECURITY_SELINUX) += selinux/
obj-$(CONFIG_SECURITY_SMACK) += smack/

View File

@ -2649,7 +2649,7 @@ static const struct inode_operations policy_link_iops = {
*
* Returns: error on failure
*/
static int __init aa_create_aafs(void)
int __init aa_create_aafs(void)
{
struct dentry *dent;
int error;
@ -2728,5 +2728,3 @@ static int __init aa_create_aafs(void)
AA_ERROR("Error creating AppArmor securityfs\n");
return error;
}
fs_initcall(aa_create_aafs);

View File

@ -53,10 +53,9 @@ int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,
return 0;
}
static int __init init_profile_hash(void)
int __init init_profile_hash(void)
{
if (apparmor_initialized)
aa_info_message("AppArmor sha256 policy hashing enabled");
return 0;
}
late_initcall(init_profile_hash);

View File

@ -104,6 +104,8 @@ enum aafs_prof_type {
#define prof_dir(X) ((X)->dents[AAFS_PROF_DIR])
#define prof_child_dir(X) ((X)->dents[AAFS_PROF_PROFS])
int aa_create_aafs(void);
void __aa_bump_ns_revision(struct aa_ns *ns);
void __aafs_profile_rmdir(struct aa_profile *profile);
void __aafs_profile_migrate_dents(struct aa_profile *old,

View File

@ -13,6 +13,7 @@
#include "policy.h"
#ifdef CONFIG_SECURITY_APPARMOR_HASH
int init_profile_hash(void);
unsigned int aa_hash_size(void);
char *aa_calc_hash(void *data, size_t len);
int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,

View File

@ -32,6 +32,7 @@
#include "include/audit.h"
#include "include/capability.h"
#include "include/cred.h"
#include "include/crypto.h"
#include "include/file.h"
#include "include/ipc.h"
#include "include/net.h"
@ -2426,7 +2427,6 @@ static int __init apparmor_nf_ip_init(void)
return 0;
}
__initcall(apparmor_nf_ip_init);
#endif
static char nulldfa_src[] __aligned(8) = {
@ -2555,9 +2555,16 @@ static int __init apparmor_init(void)
}
DEFINE_LSM(apparmor) = {
.name = "apparmor",
.id = &apparmor_lsmid,
.flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
.enabled = &apparmor_enabled,
.blobs = &apparmor_blob_sizes,
.init = apparmor_init,
.initcall_fs = aa_create_aafs,
#if defined(CONFIG_NETFILTER) && defined(CONFIG_NETWORK_SECMARK)
.initcall_device = apparmor_nf_ip_init,
#endif
#ifdef CONFIG_SECURITY_APPARMOR_HASH
.initcall_late = init_profile_hash,
#endif
};

View File

@ -33,7 +33,7 @@ struct lsm_blob_sizes bpf_lsm_blob_sizes __ro_after_init = {
};
DEFINE_LSM(bpf) = {
.name = "bpf",
.id = &bpf_lsmid,
.init = bpf_lsm_init,
.blobs = &bpf_lsm_blob_sizes
};

View File

@ -1505,7 +1505,7 @@ static int __init capability_init(void)
}
DEFINE_LSM(capability) = {
.name = "capability",
.id = &capability_lsmid,
.order = LSM_ORDER_FIRST,
.init = capability_init,
};

View File

@ -244,45 +244,40 @@ static void devcgroup_css_free(struct cgroup_subsys_state *css)
#define DEVCG_DENY 2
#define DEVCG_LIST 3
#define MAJMINLEN 13
#define ACCLEN 4
static void set_access(char *acc, short access)
static void seq_putaccess(struct seq_file *m, short access)
{
int idx = 0;
memset(acc, 0, ACCLEN);
if (access & DEVCG_ACC_READ)
acc[idx++] = 'r';
seq_putc(m, 'r');
if (access & DEVCG_ACC_WRITE)
acc[idx++] = 'w';
seq_putc(m, 'w');
if (access & DEVCG_ACC_MKNOD)
acc[idx++] = 'm';
seq_putc(m, 'm');
}
static char type_to_char(short type)
static void seq_puttype(struct seq_file *m, short type)
{
if (type == DEVCG_DEV_ALL)
return 'a';
if (type == DEVCG_DEV_CHAR)
return 'c';
if (type == DEVCG_DEV_BLOCK)
return 'b';
return 'X';
seq_putc(m, 'a');
else if (type == DEVCG_DEV_CHAR)
seq_putc(m, 'c');
else if (type == DEVCG_DEV_BLOCK)
seq_putc(m, 'b');
else
seq_putc(m, 'X');
}
static void set_majmin(char *str, unsigned m)
static void seq_putversion(struct seq_file *m, unsigned int version)
{
if (m == ~0)
strcpy(str, "*");
if (version == ~0)
seq_putc(m, '*');
else
sprintf(str, "%u", m);
seq_printf(m, "%u", version);
}
static int devcgroup_seq_show(struct seq_file *m, void *v)
{
struct dev_cgroup *devcgroup = css_to_devcgroup(seq_css(m));
struct dev_exception_item *ex;
char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN];
rcu_read_lock();
/*
@ -292,18 +287,17 @@ static int devcgroup_seq_show(struct seq_file *m, void *v)
* This way, the file remains as a "whitelist of devices"
*/
if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) {
set_access(acc, DEVCG_ACC_MASK);
set_majmin(maj, ~0);
set_majmin(min, ~0);
seq_printf(m, "%c %s:%s %s\n", type_to_char(DEVCG_DEV_ALL),
maj, min, acc);
seq_puts(m, "a *:* rwm\n");
} else {
list_for_each_entry_rcu(ex, &devcgroup->exceptions, list) {
set_access(acc, ex->access);
set_majmin(maj, ex->major);
set_majmin(min, ex->minor);
seq_printf(m, "%c %s:%s %s\n", type_to_char(ex->type),
maj, min, acc);
seq_puttype(m, ex->type);
seq_putc(m, ' ');
seq_putversion(m, ex->major);
seq_putc(m, ':');
seq_putversion(m, ex->minor);
seq_putc(m, ' ');
seq_putaccess(m, ex->access);
seq_putc(m, '\n');
}
}
rcu_read_unlock();

View File

@ -22,6 +22,8 @@
#include <linux/lsm_hooks.h>
#include <linux/magic.h>
#include "lsm.h"
static struct vfsmount *mount;
static int mount_count;
@ -315,12 +317,49 @@ void securityfs_remove(struct dentry *dentry)
EXPORT_SYMBOL_GPL(securityfs_remove);
#ifdef CONFIG_SECURITY
#include <linux/spinlock.h>
static struct dentry *lsm_dentry;
static ssize_t lsm_read(struct file *filp, char __user *buf, size_t count,
loff_t *ppos)
{
return simple_read_from_buffer(buf, count, ppos, lsm_names,
strlen(lsm_names));
int i;
static char *str;
static size_t len;
static DEFINE_SPINLOCK(lock);
/* NOTE: we never free or modify the string once it is set */
if (unlikely(!str || !len)) {
char *str_tmp;
size_t len_tmp = 0;
for (i = 0; i < lsm_active_cnt; i++)
/* the '+ 1' accounts for either a comma or a NUL */
len_tmp += strlen(lsm_idlist[i]->name) + 1;
str_tmp = kmalloc(len_tmp, GFP_KERNEL);
if (!str_tmp)
return -ENOMEM;
str_tmp[0] = '\0';
for (i = 0; i < lsm_active_cnt; i++) {
if (i > 0)
strcat(str_tmp, ",");
strcat(str_tmp, lsm_idlist[i]->name);
}
spin_lock(&lock);
if (!str) {
str = str_tmp;
len = len_tmp - 1;
} else
kfree(str_tmp);
spin_unlock(&lock);
}
return simple_read_from_buffer(buf, count, ppos, str, len);
}
static const struct file_operations lsm_ops = {
@ -329,7 +368,7 @@ static const struct file_operations lsm_ops = {
};
#endif
static int __init securityfs_init(void)
int __init securityfs_init(void)
{
int retval;
@ -348,4 +387,3 @@ static int __init securityfs_init(void)
#endif
return 0;
}
core_initcall(securityfs_init);

View File

@ -1175,10 +1175,9 @@ struct lsm_blob_sizes evm_blob_sizes __ro_after_init = {
};
DEFINE_LSM(evm) = {
.name = "evm",
.id = &evm_lsmid,
.init = init_evm_lsm,
.order = LSM_ORDER_LAST,
.blobs = &evm_blob_sizes,
.initcall_late = init_evm,
};
late_initcall(init_evm);

View File

@ -302,10 +302,16 @@ int __init evm_init_secfs(void)
int error = 0;
struct dentry *dentry;
evm_dir = securityfs_create_dir("evm", integrity_dir);
if (IS_ERR(evm_dir))
error = integrity_fs_init();
if (error < 0)
return -EFAULT;
evm_dir = securityfs_create_dir("evm", integrity_dir);
if (IS_ERR(evm_dir)) {
error = -EFAULT;
goto out;
}
dentry = securityfs_create_file("evm", 0660,
evm_dir, NULL, &evm_key_ops);
if (IS_ERR(dentry)) {
@ -329,5 +335,6 @@ int __init evm_init_secfs(void)
out:
securityfs_remove(evm_symlink);
securityfs_remove(evm_dir);
integrity_fs_fini();
return error;
}

View File

@ -42,8 +42,11 @@ void __init integrity_load_keys(void)
evm_load_x509();
}
static int __init integrity_fs_init(void)
int __init integrity_fs_init(void)
{
if (integrity_dir)
return 0;
integrity_dir = securityfs_create_dir("integrity", NULL);
if (IS_ERR(integrity_dir)) {
int ret = PTR_ERR(integrity_dir);
@ -58,4 +61,11 @@ static int __init integrity_fs_init(void)
return 0;
}
late_initcall(integrity_fs_init)
void __init integrity_fs_fini(void)
{
if (!integrity_dir || !simple_empty(integrity_dir))
return;
securityfs_remove(integrity_dir);
integrity_dir = NULL;
}

View File

@ -499,9 +499,15 @@ int __init ima_fs_init(void)
struct dentry *dentry;
int ret;
ret = integrity_fs_init();
if (ret < 0)
return ret;
ima_dir = securityfs_create_dir("ima", integrity_dir);
if (IS_ERR(ima_dir))
return PTR_ERR(ima_dir);
if (IS_ERR(ima_dir)) {
ret = PTR_ERR(ima_dir);
goto out;
}
ima_symlink = securityfs_create_symlink("ima", NULL, "integrity/ima",
NULL);
@ -555,6 +561,7 @@ int __init ima_fs_init(void)
out:
securityfs_remove(ima_symlink);
securityfs_remove(ima_dir);
integrity_fs_fini();
return ret;
}

View File

@ -1279,10 +1279,10 @@ struct lsm_blob_sizes ima_blob_sizes __ro_after_init = {
};
DEFINE_LSM(ima) = {
.name = "ima",
.id = &ima_lsmid,
.init = init_ima_lsm,
.order = LSM_ORDER_LAST,
.blobs = &ima_blob_sizes,
/* Start IMA after the TPM is available */
.initcall_late = init_ima,
};
late_initcall(init_ima); /* Start IMA after the TPM is available */

View File

@ -114,6 +114,8 @@ struct ima_file_id {
int integrity_kernel_read(struct file *file, loff_t offset,
void *addr, unsigned long count);
int __init integrity_fs_init(void);
void __init integrity_fs_fini(void);
#define INTEGRITY_KEYRING_EVM 0
#define INTEGRITY_KEYRING_IMA 1

View File

@ -193,7 +193,7 @@ static const struct file_operations enforce_fops = {
* Return: %0 on success. If an error occurs, the function will return
* the -errno.
*/
static int __init ipe_init_securityfs(void)
int __init ipe_init_securityfs(void)
{
int rc = 0;
struct ipe_policy *ap;
@ -244,5 +244,3 @@ static int __init ipe_init_securityfs(void)
securityfs_remove(root);
return rc;
}
fs_initcall(ipe_init_securityfs);

View File

@ -92,7 +92,8 @@ static int __init ipe_init(void)
}
DEFINE_LSM(ipe) = {
.name = "ipe",
.id = &ipe_lsmid,
.init = ipe_init,
.blobs = &ipe_blobs,
.initcall_fs = ipe_init_securityfs,
};

View File

@ -23,4 +23,6 @@ struct ipe_bdev *ipe_bdev(struct block_device *b);
struct ipe_inode *ipe_inode(const struct inode *inode);
#endif /* CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */
int ipe_init_securityfs(void);
#endif /* _IPE_H */

View File

@ -75,7 +75,7 @@ static int __init landlock_init(void)
}
DEFINE_LSM(LANDLOCK_NAME) = {
.name = LANDLOCK_NAME,
.id = &landlock_lsmid,
.init = landlock_init,
.blobs = &landlock_blob_sizes,
};

View File

@ -270,11 +270,6 @@ static int __init loadpin_init(void)
return 0;
}
DEFINE_LSM(loadpin) = {
.name = "loadpin",
.init = loadpin_init,
};
#ifdef CONFIG_SECURITY_LOADPIN_VERITY
enum loadpin_securityfs_interface_index {
@ -434,10 +429,16 @@ static int __init init_loadpin_securityfs(void)
return 0;
}
fs_initcall(init_loadpin_securityfs);
#endif /* CONFIG_SECURITY_LOADPIN_VERITY */
DEFINE_LSM(loadpin) = {
.id = &loadpin_lsmid,
.init = loadpin_init,
#ifdef CONFIG_SECURITY_LOADPIN_VERITY
.initcall_fs = init_loadpin_securityfs,
#endif /* CONFIG_SECURITY_LOADPIN_VERITY */
};
/* Should not be mutable after boot, so not listed in sysfs (perm == 0). */
module_param(enforce, int, 0);
MODULE_PARM_DESC(enforce, "Enforce module/firmware pinning");

View File

@ -161,13 +161,12 @@ static int __init lockdown_secfs_init(void)
return PTR_ERR_OR_ZERO(dentry);
}
core_initcall(lockdown_secfs_init);
#ifdef CONFIG_SECURITY_LOCKDOWN_LSM_EARLY
DEFINE_EARLY_LSM(lockdown) = {
#else
DEFINE_LSM(lockdown) = {
#endif
.name = "lockdown",
.id = &lockdown_lsmid,
.init = lockdown_lsm_init,
.initcall_core = lockdown_secfs_init,
};

58
security/lsm.h Normal file
View File

@ -0,0 +1,58 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* LSM functions
*/
#ifndef _LSM_H_
#define _LSM_H_
#include <linux/printk.h>
#include <linux/lsm_hooks.h>
#include <linux/lsm_count.h>
/* LSM debugging */
extern bool lsm_debug;
#define lsm_pr(...) pr_info(__VA_ARGS__)
#define lsm_pr_cont(...) pr_cont(__VA_ARGS__)
#define lsm_pr_dbg(...) \
do { \
if (lsm_debug) \
pr_info(__VA_ARGS__); \
} while (0)
/* List of configured LSMs */
extern unsigned int lsm_active_cnt;
extern const struct lsm_id *lsm_idlist[];
/* LSM blob configuration */
extern struct lsm_blob_sizes blob_sizes;
/* LSM blob caches */
extern struct kmem_cache *lsm_file_cache;
extern struct kmem_cache *lsm_inode_cache;
/* LSM blob allocators */
int lsm_cred_alloc(struct cred *cred, gfp_t gfp);
int lsm_task_alloc(struct task_struct *task);
/* LSM framework initializers */
#ifdef CONFIG_MMU
int min_addr_init(void);
#else
static inline int min_addr_init(void)
{
return 0;
}
#endif /* CONFIG_MMU */
#ifdef CONFIG_SECURITYFS
int securityfs_init(void);
#else
static inline int securityfs_init(void)
{
return 0;
}
#endif /* CONFIG_SECURITYFS */
#endif /* _LSM_H_ */

564
security/lsm_init.c Normal file
View File

@ -0,0 +1,564 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* LSM initialization functions
*/
#define pr_fmt(fmt) "LSM: " fmt
#include <linux/init.h>
#include <linux/lsm_hooks.h>
#include "lsm.h"
/* LSM enabled constants. */
static __initdata int lsm_enabled_true = 1;
static __initdata int lsm_enabled_false = 0;
/* Pointers to LSM sections defined in include/asm-generic/vmlinux.lds.h */
extern struct lsm_info __start_lsm_info[], __end_lsm_info[];
extern struct lsm_info __start_early_lsm_info[], __end_early_lsm_info[];
/* Number of "early" LSMs */
static __initdata unsigned int lsm_count_early;
/* Build and boot-time LSM ordering. */
static __initconst const char *const lsm_order_builtin = CONFIG_LSM;
static __initdata const char *lsm_order_cmdline;
static __initdata const char *lsm_order_legacy;
/* Ordered list of LSMs to initialize. */
static __initdata struct lsm_info *lsm_order[MAX_LSM_COUNT + 1];
static __initdata struct lsm_info *lsm_exclusive;
#define lsm_order_for_each(iter) \
for ((iter) = lsm_order; *(iter); (iter)++)
#define lsm_for_each_raw(iter) \
for ((iter) = __start_lsm_info; \
(iter) < __end_lsm_info; (iter)++)
#define lsm_early_for_each_raw(iter) \
for ((iter) = __start_early_lsm_info; \
(iter) < __end_early_lsm_info; (iter)++)
#define lsm_initcall(level) \
({ \
int _r, _rc = 0; \
struct lsm_info **_lp, *_l; \
lsm_order_for_each(_lp) { \
_l = *_lp; \
if (!_l->initcall_##level) \
continue; \
lsm_pr_dbg("running %s %s initcall", \
_l->id->name, #level); \
_r = _l->initcall_##level(); \
if (_r) { \
pr_warn("failed LSM %s %s initcall with errno %d\n", \
_l->id->name, #level, _r); \
if (!_rc) \
_rc = _r; \
} \
} \
_rc; \
})
/**
* lsm_choose_security - Legacy "major" LSM selection
* @str: kernel command line parameter
*/
static int __init lsm_choose_security(char *str)
{
lsm_order_legacy = str;
return 1;
}
__setup("security=", lsm_choose_security);
/**
* lsm_choose_lsm - Modern LSM selection
* @str: kernel command line parameter
*/
static int __init lsm_choose_lsm(char *str)
{
lsm_order_cmdline = str;
return 1;
}
__setup("lsm=", lsm_choose_lsm);
/**
* lsm_debug_enable - Enable LSM framework debugging
* @str: kernel command line parameter
*
* Currently we only provide debug info during LSM initialization, but we may
* want to expand this in the future.
*/
static int __init lsm_debug_enable(char *str)
{
lsm_debug = true;
return 1;
}
__setup("lsm.debug", lsm_debug_enable);
/**
* lsm_enabled_set - Mark a LSM as enabled
* @lsm: LSM definition
* @enabled: enabled flag
*/
static void __init lsm_enabled_set(struct lsm_info *lsm, bool enabled)
{
/*
* When an LSM hasn't configured an enable variable, we can use
* a hard-coded location for storing the default enabled state.
*/
if (!lsm->enabled ||
lsm->enabled == &lsm_enabled_true ||
lsm->enabled == &lsm_enabled_false) {
lsm->enabled = enabled ? &lsm_enabled_true : &lsm_enabled_false;
} else {
*lsm->enabled = enabled;
}
}
/**
* lsm_is_enabled - Determine if a LSM is enabled
* @lsm: LSM definition
*/
static inline bool lsm_is_enabled(struct lsm_info *lsm)
{
return (lsm->enabled ? *lsm->enabled : false);
}
/**
* lsm_order_exists - Determine if a LSM exists in the ordered list
* @lsm: LSM definition
*/
static bool __init lsm_order_exists(struct lsm_info *lsm)
{
struct lsm_info **check;
lsm_order_for_each(check) {
if (*check == lsm)
return true;
}
return false;
}
/**
* lsm_order_append - Append a LSM to the ordered list
* @lsm: LSM definition
* @src: source of the addition
*
* Append @lsm to the enabled LSM array after ensuring that it hasn't been
* explicitly disabled, is a duplicate entry, or would run afoul of the
* LSM_FLAG_EXCLUSIVE logic.
*/
static void __init lsm_order_append(struct lsm_info *lsm, const char *src)
{
/* Ignore duplicate selections. */
if (lsm_order_exists(lsm))
return;
/* Skip explicitly disabled LSMs. */
if (lsm->enabled && !lsm_is_enabled(lsm)) {
lsm_pr_dbg("skip previously disabled LSM %s:%s\n",
src, lsm->id->name);
return;
}
if (lsm_active_cnt == MAX_LSM_COUNT) {
pr_warn("exceeded maximum LSM count on %s:%s\n",
src, lsm->id->name);
lsm_enabled_set(lsm, false);
return;
}
if (lsm->flags & LSM_FLAG_EXCLUSIVE) {
if (lsm_exclusive) {
lsm_pr_dbg("skip exclusive LSM conflict %s:%s\n",
src, lsm->id->name);
lsm_enabled_set(lsm, false);
return;
} else {
lsm_pr_dbg("select exclusive LSM %s:%s\n",
src, lsm->id->name);
lsm_exclusive = lsm;
}
}
lsm_enabled_set(lsm, true);
lsm_order[lsm_active_cnt] = lsm;
lsm_idlist[lsm_active_cnt++] = lsm->id;
lsm_pr_dbg("enabling LSM %s:%s\n", src, lsm->id->name);
}
/**
* lsm_order_parse - Parse the comma delimited LSM list
* @list: LSM list
* @src: source of the list
*/
static void __init lsm_order_parse(const char *list, const char *src)
{
struct lsm_info *lsm;
char *sep, *name, *next;
/* Handle any Legacy LSM exclusions if one was specified. */
if (lsm_order_legacy) {
/*
* To match the original "security=" behavior, this explicitly
* does NOT fallback to another Legacy Major if the selected
* one was separately disabled: disable all non-matching
* Legacy Major LSMs.
*/
lsm_for_each_raw(lsm) {
if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) &&
strcmp(lsm->id->name, lsm_order_legacy)) {
lsm_enabled_set(lsm, false);
lsm_pr_dbg("skip legacy LSM conflict %s:%s\n",
src, lsm->id->name);
}
}
}
/* LSM_ORDER_FIRST */
lsm_for_each_raw(lsm) {
if (lsm->order == LSM_ORDER_FIRST)
lsm_order_append(lsm, "first");
}
/* Normal or "mutable" LSMs */
sep = kstrdup(list, GFP_KERNEL);
next = sep;
/* Walk the list, looking for matching LSMs. */
while ((name = strsep(&next, ",")) != NULL) {
lsm_for_each_raw(lsm) {
if (!strcmp(lsm->id->name, name) &&
lsm->order == LSM_ORDER_MUTABLE)
lsm_order_append(lsm, src);
}
}
kfree(sep);
/* Legacy LSM if specified. */
if (lsm_order_legacy) {
lsm_for_each_raw(lsm) {
if (!strcmp(lsm->id->name, lsm_order_legacy))
lsm_order_append(lsm, src);
}
}
/* LSM_ORDER_LAST */
lsm_for_each_raw(lsm) {
if (lsm->order == LSM_ORDER_LAST)
lsm_order_append(lsm, "last");
}
/* Disable all LSMs not previously enabled. */
lsm_for_each_raw(lsm) {
if (lsm_order_exists(lsm))
continue;
lsm_enabled_set(lsm, false);
lsm_pr_dbg("skip disabled LSM %s:%s\n", src, lsm->id->name);
}
}
/**
* lsm_blob_size_update - Update the LSM blob size and offset information
* @sz_req: the requested additional blob size
* @sz_cur: the existing blob size
*/
static void __init lsm_blob_size_update(unsigned int *sz_req,
unsigned int *sz_cur)
{
unsigned int offset;
if (*sz_req == 0)
return;
offset = ALIGN(*sz_cur, sizeof(void *));
*sz_cur = offset + *sz_req;
*sz_req = offset;
}
/**
* lsm_prepare - Prepare the LSM framework for a new LSM
* @lsm: LSM definition
*/
static void __init lsm_prepare(struct lsm_info *lsm)
{
struct lsm_blob_sizes *blobs = lsm->blobs;
if (!blobs)
return;
/* Register the LSM blob sizes. */
blobs = lsm->blobs;
lsm_blob_size_update(&blobs->lbs_cred, &blob_sizes.lbs_cred);
lsm_blob_size_update(&blobs->lbs_file, &blob_sizes.lbs_file);
lsm_blob_size_update(&blobs->lbs_ib, &blob_sizes.lbs_ib);
/* inode blob gets an rcu_head in addition to LSM blobs. */
if (blobs->lbs_inode && blob_sizes.lbs_inode == 0)
blob_sizes.lbs_inode = sizeof(struct rcu_head);
lsm_blob_size_update(&blobs->lbs_inode, &blob_sizes.lbs_inode);
lsm_blob_size_update(&blobs->lbs_ipc, &blob_sizes.lbs_ipc);
lsm_blob_size_update(&blobs->lbs_key, &blob_sizes.lbs_key);
lsm_blob_size_update(&blobs->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
lsm_blob_size_update(&blobs->lbs_perf_event,
&blob_sizes.lbs_perf_event);
lsm_blob_size_update(&blobs->lbs_sock, &blob_sizes.lbs_sock);
lsm_blob_size_update(&blobs->lbs_superblock,
&blob_sizes.lbs_superblock);
lsm_blob_size_update(&blobs->lbs_task, &blob_sizes.lbs_task);
lsm_blob_size_update(&blobs->lbs_tun_dev, &blob_sizes.lbs_tun_dev);
lsm_blob_size_update(&blobs->lbs_xattr_count,
&blob_sizes.lbs_xattr_count);
lsm_blob_size_update(&blobs->lbs_bdev, &blob_sizes.lbs_bdev);
lsm_blob_size_update(&blobs->lbs_bpf_map, &blob_sizes.lbs_bpf_map);
lsm_blob_size_update(&blobs->lbs_bpf_prog, &blob_sizes.lbs_bpf_prog);
lsm_blob_size_update(&blobs->lbs_bpf_token, &blob_sizes.lbs_bpf_token);
}
/**
* lsm_init_single - Initialize a given LSM
* @lsm: LSM definition
*/
static void __init lsm_init_single(struct lsm_info *lsm)
{
int ret;
if (!lsm_is_enabled(lsm))
return;
lsm_pr_dbg("initializing %s\n", lsm->id->name);
ret = lsm->init();
WARN(ret, "%s failed to initialize: %d\n", lsm->id->name, ret);
}
/**
* lsm_static_call_init - Initialize a LSM's static calls
* @hl: LSM hook list
*/
static int __init lsm_static_call_init(struct security_hook_list *hl)
{
struct lsm_static_call *scall = hl->scalls;
int i;
for (i = 0; i < MAX_LSM_COUNT; i++) {
/* Update the first static call that is not used yet */
if (!scall->hl) {
__static_call_update(scall->key, scall->trampoline,
hl->hook.lsm_func_addr);
scall->hl = hl;
static_branch_enable(scall->active);
return 0;
}
scall++;
}
return -ENOSPC;
}
/**
* security_add_hooks - Add a LSM's hooks to the LSM framework's hook lists
* @hooks: LSM hooks to add
* @count: number of hooks to add
* @lsmid: identification information for the LSM
*
* Each LSM has to register its hooks with the LSM framework.
*/
void __init security_add_hooks(struct security_hook_list *hooks, int count,
const struct lsm_id *lsmid)
{
int i;
for (i = 0; i < count; i++) {
hooks[i].lsmid = lsmid;
if (lsm_static_call_init(&hooks[i]))
panic("exhausted LSM callback slots with LSM %s\n",
lsmid->name);
}
}
/**
* early_security_init - Initialize the early LSMs
*/
int __init early_security_init(void)
{
struct lsm_info *lsm;
/* NOTE: lsm_pr_dbg() doesn't work here as lsm_debug is not yet set */
lsm_early_for_each_raw(lsm) {
lsm_enabled_set(lsm, true);
lsm_order_append(lsm, "early");
lsm_prepare(lsm);
lsm_init_single(lsm);
lsm_count_early++;
}
return 0;
}
/**
* security_init - Initializes the LSM framework
*
* This should be called early in the kernel initialization sequence.
*/
int __init security_init(void)
{
unsigned int cnt;
struct lsm_info **lsm;
if (lsm_debug) {
struct lsm_info *i;
cnt = 0;
lsm_pr("available LSMs: ");
lsm_early_for_each_raw(i)
lsm_pr_cont("%s%s(E)", (cnt++ ? "," : ""), i->id->name);
lsm_for_each_raw(i)
lsm_pr_cont("%s%s", (cnt++ ? "," : ""), i->id->name);
lsm_pr_cont("\n");
lsm_pr("built-in LSM config: %s\n", lsm_order_builtin);
lsm_pr("legacy LSM parameter: %s\n", lsm_order_legacy);
lsm_pr("boot LSM parameter: %s\n", lsm_order_cmdline);
/* see the note about lsm_pr_dbg() in early_security_init() */
lsm_early_for_each_raw(i)
lsm_pr("enabled LSM early:%s\n", i->id->name);
}
if (lsm_order_cmdline) {
if (lsm_order_legacy)
lsm_order_legacy = NULL;
lsm_order_parse(lsm_order_cmdline, "cmdline");
} else
lsm_order_parse(lsm_order_builtin, "builtin");
lsm_order_for_each(lsm)
lsm_prepare(*lsm);
if (lsm_debug) {
lsm_pr("blob(cred) size %d\n", blob_sizes.lbs_cred);
lsm_pr("blob(file) size %d\n", blob_sizes.lbs_file);
lsm_pr("blob(ib) size %d\n", blob_sizes.lbs_ib);
lsm_pr("blob(inode) size %d\n", blob_sizes.lbs_inode);
lsm_pr("blob(ipc) size %d\n", blob_sizes.lbs_ipc);
lsm_pr("blob(key) size %d\n", blob_sizes.lbs_key);
lsm_pr("blob(msg_msg)_size %d\n", blob_sizes.lbs_msg_msg);
lsm_pr("blob(sock) size %d\n", blob_sizes.lbs_sock);
lsm_pr("blob(superblock) size %d\n", blob_sizes.lbs_superblock);
lsm_pr("blob(perf_event) size %d\n", blob_sizes.lbs_perf_event);
lsm_pr("blob(task) size %d\n", blob_sizes.lbs_task);
lsm_pr("blob(tun_dev) size %d\n", blob_sizes.lbs_tun_dev);
lsm_pr("blob(xattr) count %d\n", blob_sizes.lbs_xattr_count);
lsm_pr("blob(bdev) size %d\n", blob_sizes.lbs_bdev);
lsm_pr("blob(bpf_map) size %d\n", blob_sizes.lbs_bpf_map);
lsm_pr("blob(bpf_prog) size %d\n", blob_sizes.lbs_bpf_prog);
lsm_pr("blob(bpf_token) size %d\n", blob_sizes.lbs_bpf_token);
}
if (blob_sizes.lbs_file)
lsm_file_cache = kmem_cache_create("lsm_file_cache",
blob_sizes.lbs_file, 0,
SLAB_PANIC, NULL);
if (blob_sizes.lbs_inode)
lsm_inode_cache = kmem_cache_create("lsm_inode_cache",
blob_sizes.lbs_inode, 0,
SLAB_PANIC, NULL);
if (lsm_cred_alloc((struct cred *)unrcu_pointer(current->cred),
GFP_KERNEL))
panic("early LSM cred alloc failed\n");
if (lsm_task_alloc(current))
panic("early LSM task alloc failed\n");
cnt = 0;
lsm_order_for_each(lsm) {
/* skip the "early" LSMs as they have already been setup */
if (cnt++ < lsm_count_early)
continue;
lsm_init_single(*lsm);
}
return 0;
}
/**
* security_initcall_pure - Run the LSM pure initcalls
*/
static int __init security_initcall_pure(void)
{
int rc_adr, rc_lsm;
rc_adr = min_addr_init();
rc_lsm = lsm_initcall(pure);
return (rc_adr ? rc_adr : rc_lsm);
}
pure_initcall(security_initcall_pure);
/**
* security_initcall_early - Run the LSM early initcalls
*/
static int __init security_initcall_early(void)
{
return lsm_initcall(early);
}
early_initcall(security_initcall_early);
/**
* security_initcall_core - Run the LSM core initcalls
*/
static int __init security_initcall_core(void)
{
int rc_sfs, rc_lsm;
rc_sfs = securityfs_init();
rc_lsm = lsm_initcall(core);
return (rc_sfs ? rc_sfs : rc_lsm);
}
core_initcall(security_initcall_core);
/**
* security_initcall_subsys - Run the LSM subsys initcalls
*/
static int __init security_initcall_subsys(void)
{
return lsm_initcall(subsys);
}
subsys_initcall(security_initcall_subsys);
/**
* security_initcall_fs - Run the LSM fs initcalls
*/
static int __init security_initcall_fs(void)
{
return lsm_initcall(fs);
}
fs_initcall(security_initcall_fs);
/**
* security_initcall_device - Run the LSM device initcalls
*/
static int __init security_initcall_device(void)
{
return lsm_initcall(device);
}
device_initcall(security_initcall_device);
/**
* security_initcall_late - Run the LSM late initcalls
*/
static int __init security_initcall_late(void)
{
int rc;
rc = lsm_initcall(late);
lsm_pr_dbg("all enabled LSMs fully activated\n");
call_blocking_lsm_notifier(LSM_STARTED_ALL, NULL);
return rc;
}
late_initcall(security_initcall_late);

31
security/lsm_notifier.c Normal file
View File

@ -0,0 +1,31 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* LSM notifier functions
*
*/
#include <linux/notifier.h>
#include <linux/security.h>
static BLOCKING_NOTIFIER_HEAD(blocking_lsm_notifier_chain);
int call_blocking_lsm_notifier(enum lsm_event event, void *data)
{
return blocking_notifier_call_chain(&blocking_lsm_notifier_chain,
event, data);
}
EXPORT_SYMBOL(call_blocking_lsm_notifier);
int register_blocking_lsm_notifier(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&blocking_lsm_notifier_chain,
nb);
}
EXPORT_SYMBOL(register_blocking_lsm_notifier);
int unregister_blocking_lsm_notifier(struct notifier_block *nb)
{
return blocking_notifier_chain_unregister(&blocking_lsm_notifier_chain,
nb);
}
EXPORT_SYMBOL(unregister_blocking_lsm_notifier);

View File

@ -17,6 +17,8 @@
#include <linux/lsm_hooks.h>
#include <uapi/linux/lsm.h>
#include "lsm.h"
/**
* lsm_name_to_attr - map an LSM attribute name to its ID
* @name: name of the attribute

View File

@ -5,6 +5,8 @@
#include <linux/sysctl.h>
#include <linux/minmax.h>
#include "lsm.h"
/* amount of vm to protect from userspace access by both DAC and the LSM*/
unsigned long mmap_min_addr;
/* amount of vm to protect from userspace using CAP_SYS_RAWIO (DAC) */
@ -52,11 +54,10 @@ static const struct ctl_table min_addr_sysctl_table[] = {
},
};
static int __init init_mmap_min_addr(void)
int __init min_addr_init(void)
{
register_sysctl_init("vm", min_addr_sysctl_table);
update_mmap_min_addr();
return 0;
}
pure_initcall(init_mmap_min_addr);

View File

@ -287,6 +287,7 @@ static int __init safesetid_security_init(void)
}
DEFINE_LSM(safesetid_security_init) = {
.id = &safesetid_lsmid,
.init = safesetid_security_init,
.name = "safesetid",
.initcall_fs = safesetid_init_securityfs,
};

View File

@ -70,4 +70,6 @@ enum sid_policy_type _setid_policy_lookup(struct setid_ruleset *policy,
extern struct setid_ruleset __rcu *safesetid_setuid_rules;
extern struct setid_ruleset __rcu *safesetid_setgid_rules;
int safesetid_init_securityfs(void);
#endif /* _SAFESETID_H */

View File

@ -308,7 +308,7 @@ static const struct file_operations safesetid_gid_file_fops = {
.write = safesetid_gid_file_write,
};
static int __init safesetid_init_securityfs(void)
int __init safesetid_init_securityfs(void)
{
int ret;
struct dentry *policy_dir;
@ -345,4 +345,3 @@ static int __init safesetid_init_securityfs(void)
securityfs_remove(policy_dir);
return ret;
}
fs_initcall(safesetid_init_securityfs);

View File

@ -32,24 +32,7 @@
#include <net/flow.h>
#include <net/sock.h>
#define SECURITY_HOOK_ACTIVE_KEY(HOOK, IDX) security_hook_active_##HOOK##_##IDX
/*
* Identifier for the LSM static calls.
* HOOK is an LSM hook as defined in linux/lsm_hookdefs.h
* IDX is the index of the static call. 0 <= NUM < MAX_LSM_COUNT
*/
#define LSM_STATIC_CALL(HOOK, IDX) lsm_static_call_##HOOK##_##IDX
/*
* Call the macro M for each LSM hook MAX_LSM_COUNT times.
*/
#define LSM_LOOP_UNROLL(M, ...) \
do { \
UNROLL(MAX_LSM_COUNT, M, __VA_ARGS__) \
} while (0)
#define LSM_DEFINE_UNROLL(M, ...) UNROLL(MAX_LSM_COUNT, M, __VA_ARGS__)
#include "lsm.h"
/*
* These are descriptions of the reasons that can be passed to the
@ -90,23 +73,34 @@ const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX + 1] = {
[LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
};
static BLOCKING_NOTIFIER_HEAD(blocking_lsm_notifier_chain);
bool lsm_debug __ro_after_init;
static struct kmem_cache *lsm_file_cache;
static struct kmem_cache *lsm_inode_cache;
unsigned int lsm_active_cnt __ro_after_init;
const struct lsm_id *lsm_idlist[MAX_LSM_COUNT];
char *lsm_names;
static struct lsm_blob_sizes blob_sizes __ro_after_init;
struct lsm_blob_sizes blob_sizes;
/* Boot-time LSM user choice */
static __initdata const char *chosen_lsm_order;
static __initdata const char *chosen_major_lsm;
struct kmem_cache *lsm_file_cache;
struct kmem_cache *lsm_inode_cache;
static __initconst const char *const builtin_lsm_order = CONFIG_LSM;
#define SECURITY_HOOK_ACTIVE_KEY(HOOK, IDX) security_hook_active_##HOOK##_##IDX
/* Ordered list of LSMs to initialize. */
static __initdata struct lsm_info *ordered_lsms[MAX_LSM_COUNT + 1];
static __initdata struct lsm_info *exclusive;
/*
* Identifier for the LSM static calls.
* HOOK is an LSM hook as defined in linux/lsm_hookdefs.h
* IDX is the index of the static call. 0 <= NUM < MAX_LSM_COUNT
*/
#define LSM_STATIC_CALL(HOOK, IDX) lsm_static_call_##HOOK##_##IDX
/*
* Call the macro M for each LSM hook MAX_LSM_COUNT times.
*/
#define LSM_LOOP_UNROLL(M, ...) \
do { \
UNROLL(MAX_LSM_COUNT, M, __VA_ARGS__) \
} while (0)
#define LSM_DEFINE_UNROLL(M, ...) UNROLL(MAX_LSM_COUNT, M, __VA_ARGS__)
#ifdef CONFIG_HAVE_STATIC_CALL
#define LSM_HOOK_TRAMP(NAME, NUM) \
@ -157,519 +151,27 @@ struct lsm_static_calls_table
#undef INIT_LSM_STATIC_CALL
};
static __initdata bool debug;
#define init_debug(...) \
do { \
if (debug) \
pr_info(__VA_ARGS__); \
} while (0)
static bool __init is_enabled(struct lsm_info *lsm)
{
if (!lsm->enabled)
return false;
return *lsm->enabled;
}
/* Mark an LSM's enabled flag. */
static int lsm_enabled_true __initdata = 1;
static int lsm_enabled_false __initdata = 0;
static void __init set_enabled(struct lsm_info *lsm, bool enabled)
{
/*
* When an LSM hasn't configured an enable variable, we can use
* a hard-coded location for storing the default enabled state.
*/
if (!lsm->enabled) {
if (enabled)
lsm->enabled = &lsm_enabled_true;
else
lsm->enabled = &lsm_enabled_false;
} else if (lsm->enabled == &lsm_enabled_true) {
if (!enabled)
lsm->enabled = &lsm_enabled_false;
} else if (lsm->enabled == &lsm_enabled_false) {
if (enabled)
lsm->enabled = &lsm_enabled_true;
} else {
*lsm->enabled = enabled;
}
}
/* Is an LSM already listed in the ordered LSMs list? */
static bool __init exists_ordered_lsm(struct lsm_info *lsm)
{
struct lsm_info **check;
for (check = ordered_lsms; *check; check++)
if (*check == lsm)
return true;
return false;
}
/* Append an LSM to the list of ordered LSMs to initialize. */
static int last_lsm __initdata;
static void __init append_ordered_lsm(struct lsm_info *lsm, const char *from)
{
/* Ignore duplicate selections. */
if (exists_ordered_lsm(lsm))
return;
if (WARN(last_lsm == MAX_LSM_COUNT, "%s: out of LSM static calls!?\n", from))
return;
/* Enable this LSM, if it is not already set. */
if (!lsm->enabled)
lsm->enabled = &lsm_enabled_true;
ordered_lsms[last_lsm++] = lsm;
init_debug("%s ordered: %s (%s)\n", from, lsm->name,
is_enabled(lsm) ? "enabled" : "disabled");
}
/* Is an LSM allowed to be initialized? */
static bool __init lsm_allowed(struct lsm_info *lsm)
{
/* Skip if the LSM is disabled. */
if (!is_enabled(lsm))
return false;
/* Not allowed if another exclusive LSM already initialized. */
if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && exclusive) {
init_debug("exclusive disabled: %s\n", lsm->name);
return false;
}
return true;
}
static void __init lsm_set_blob_size(int *need, int *lbs)
{
int offset;
if (*need <= 0)
return;
offset = ALIGN(*lbs, sizeof(void *));
*lbs = offset + *need;
*need = offset;
}
static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
{
if (!needed)
return;
lsm_set_blob_size(&needed->lbs_cred, &blob_sizes.lbs_cred);
lsm_set_blob_size(&needed->lbs_file, &blob_sizes.lbs_file);
lsm_set_blob_size(&needed->lbs_ib, &blob_sizes.lbs_ib);
/*
* The inode blob gets an rcu_head in addition to
* what the modules might need.
*/
if (needed->lbs_inode && blob_sizes.lbs_inode == 0)
blob_sizes.lbs_inode = sizeof(struct rcu_head);
lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode);
lsm_set_blob_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc);
lsm_set_blob_size(&needed->lbs_key, &blob_sizes.lbs_key);
lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
lsm_set_blob_size(&needed->lbs_perf_event, &blob_sizes.lbs_perf_event);
lsm_set_blob_size(&needed->lbs_sock, &blob_sizes.lbs_sock);
lsm_set_blob_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock);
lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task);
lsm_set_blob_size(&needed->lbs_tun_dev, &blob_sizes.lbs_tun_dev);
lsm_set_blob_size(&needed->lbs_xattr_count,
&blob_sizes.lbs_xattr_count);
lsm_set_blob_size(&needed->lbs_bdev, &blob_sizes.lbs_bdev);
lsm_set_blob_size(&needed->lbs_bpf_map, &blob_sizes.lbs_bpf_map);
lsm_set_blob_size(&needed->lbs_bpf_prog, &blob_sizes.lbs_bpf_prog);
lsm_set_blob_size(&needed->lbs_bpf_token, &blob_sizes.lbs_bpf_token);
}
/* Prepare LSM for initialization. */
static void __init prepare_lsm(struct lsm_info *lsm)
{
int enabled = lsm_allowed(lsm);
/* Record enablement (to handle any following exclusive LSMs). */
set_enabled(lsm, enabled);
/* If enabled, do pre-initialization work. */
if (enabled) {
if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && !exclusive) {
exclusive = lsm;
init_debug("exclusive chosen: %s\n", lsm->name);
}
lsm_set_blob_sizes(lsm->blobs);
}
}
/* Initialize a given LSM, if it is enabled. */
static void __init initialize_lsm(struct lsm_info *lsm)
{
if (is_enabled(lsm)) {
int ret;
init_debug("initializing %s\n", lsm->name);
ret = lsm->init();
WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret);
}
}
/*
* Current index to use while initializing the lsm id list.
*/
u32 lsm_active_cnt __ro_after_init;
const struct lsm_id *lsm_idlist[MAX_LSM_COUNT];
/* Populate ordered LSMs list from comma-separated LSM name list. */
static void __init ordered_lsm_parse(const char *order, const char *origin)
{
struct lsm_info *lsm;
char *sep, *name, *next;
/* LSM_ORDER_FIRST is always first. */
for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
if (lsm->order == LSM_ORDER_FIRST)
append_ordered_lsm(lsm, " first");
}
/* Process "security=", if given. */
if (chosen_major_lsm) {
struct lsm_info *major;
/*
* To match the original "security=" behavior, this
* explicitly does NOT fallback to another Legacy Major
* if the selected one was separately disabled: disable
* all non-matching Legacy Major LSMs.
*/
for (major = __start_lsm_info; major < __end_lsm_info;
major++) {
if ((major->flags & LSM_FLAG_LEGACY_MAJOR) &&
strcmp(major->name, chosen_major_lsm) != 0) {
set_enabled(major, false);
init_debug("security=%s disabled: %s (only one legacy major LSM)\n",
chosen_major_lsm, major->name);
}
}
}
sep = kstrdup(order, GFP_KERNEL);
next = sep;
/* Walk the list, looking for matching LSMs. */
while ((name = strsep(&next, ",")) != NULL) {
bool found = false;
for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
if (strcmp(lsm->name, name) == 0) {
if (lsm->order == LSM_ORDER_MUTABLE)
append_ordered_lsm(lsm, origin);
found = true;
}
}
if (!found)
init_debug("%s ignored: %s (not built into kernel)\n",
origin, name);
}
/* Process "security=", if given. */
if (chosen_major_lsm) {
for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
if (exists_ordered_lsm(lsm))
continue;
if (strcmp(lsm->name, chosen_major_lsm) == 0)
append_ordered_lsm(lsm, "security=");
}
}
/* LSM_ORDER_LAST is always last. */
for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
if (lsm->order == LSM_ORDER_LAST)
append_ordered_lsm(lsm, " last");
}
/* Disable all LSMs not in the ordered list. */
for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
if (exists_ordered_lsm(lsm))
continue;
set_enabled(lsm, false);
init_debug("%s skipped: %s (not in requested order)\n",
origin, lsm->name);
}
kfree(sep);
}
static void __init lsm_static_call_init(struct security_hook_list *hl)
{
struct lsm_static_call *scall = hl->scalls;
int i;
for (i = 0; i < MAX_LSM_COUNT; i++) {
/* Update the first static call that is not used yet */
if (!scall->hl) {
__static_call_update(scall->key, scall->trampoline,
hl->hook.lsm_func_addr);
scall->hl = hl;
static_branch_enable(scall->active);
return;
}
scall++;
}
panic("%s - Ran out of static slots.\n", __func__);
}
static void __init lsm_early_cred(struct cred *cred);
static void __init lsm_early_task(struct task_struct *task);
static int lsm_append(const char *new, char **result);
static void __init report_lsm_order(void)
{
struct lsm_info **lsm, *early;
int first = 0;
pr_info("initializing lsm=");
/* Report each enabled LSM name, comma separated. */
for (early = __start_early_lsm_info;
early < __end_early_lsm_info; early++)
if (is_enabled(early))
pr_cont("%s%s", first++ == 0 ? "" : ",", early->name);
for (lsm = ordered_lsms; *lsm; lsm++)
if (is_enabled(*lsm))
pr_cont("%s%s", first++ == 0 ? "" : ",", (*lsm)->name);
pr_cont("\n");
}
static void __init ordered_lsm_init(void)
{
struct lsm_info **lsm;
if (chosen_lsm_order) {
if (chosen_major_lsm) {
pr_warn("security=%s is ignored because it is superseded by lsm=%s\n",
chosen_major_lsm, chosen_lsm_order);
chosen_major_lsm = NULL;
}
ordered_lsm_parse(chosen_lsm_order, "cmdline");
} else
ordered_lsm_parse(builtin_lsm_order, "builtin");
for (lsm = ordered_lsms; *lsm; lsm++)
prepare_lsm(*lsm);
report_lsm_order();
init_debug("cred blob size = %d\n", blob_sizes.lbs_cred);
init_debug("file blob size = %d\n", blob_sizes.lbs_file);
init_debug("ib blob size = %d\n", blob_sizes.lbs_ib);
init_debug("inode blob size = %d\n", blob_sizes.lbs_inode);
init_debug("ipc blob size = %d\n", blob_sizes.lbs_ipc);
#ifdef CONFIG_KEYS
init_debug("key blob size = %d\n", blob_sizes.lbs_key);
#endif /* CONFIG_KEYS */
init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg);
init_debug("sock blob size = %d\n", blob_sizes.lbs_sock);
init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock);
init_debug("perf event blob size = %d\n", blob_sizes.lbs_perf_event);
init_debug("task blob size = %d\n", blob_sizes.lbs_task);
init_debug("tun device blob size = %d\n", blob_sizes.lbs_tun_dev);
init_debug("xattr slots = %d\n", blob_sizes.lbs_xattr_count);
init_debug("bdev blob size = %d\n", blob_sizes.lbs_bdev);
init_debug("bpf map blob size = %d\n", blob_sizes.lbs_bpf_map);
init_debug("bpf prog blob size = %d\n", blob_sizes.lbs_bpf_prog);
init_debug("bpf token blob size = %d\n", blob_sizes.lbs_bpf_token);
/*
* Create any kmem_caches needed for blobs
*/
if (blob_sizes.lbs_file)
lsm_file_cache = kmem_cache_create("lsm_file_cache",
blob_sizes.lbs_file, 0,
SLAB_PANIC, NULL);
if (blob_sizes.lbs_inode)
lsm_inode_cache = kmem_cache_create("lsm_inode_cache",
blob_sizes.lbs_inode, 0,
SLAB_PANIC, NULL);
lsm_early_cred((struct cred *) current->cred);
lsm_early_task(current);
for (lsm = ordered_lsms; *lsm; lsm++)
initialize_lsm(*lsm);
}
int __init early_security_init(void)
{
struct lsm_info *lsm;
for (lsm = __start_early_lsm_info; lsm < __end_early_lsm_info; lsm++) {
if (!lsm->enabled)
lsm->enabled = &lsm_enabled_true;
prepare_lsm(lsm);
initialize_lsm(lsm);
}
return 0;
}
/**
* security_init - initializes the security framework
* lsm_file_alloc - allocate a composite file blob
* @file: the file that needs a blob
*
* This should be called early in the kernel initialization sequence.
* Allocate the file blob for all the modules
*
* Returns 0, or -ENOMEM if memory can't be allocated.
*/
int __init security_init(void)
static int lsm_file_alloc(struct file *file)
{
struct lsm_info *lsm;
init_debug("legacy security=%s\n", chosen_major_lsm ? : " *unspecified*");
init_debug(" CONFIG_LSM=%s\n", builtin_lsm_order);
init_debug("boot arg lsm=%s\n", chosen_lsm_order ? : " *unspecified*");
/*
* Append the names of the early LSM modules now that kmalloc() is
* available
*/
for (lsm = __start_early_lsm_info; lsm < __end_early_lsm_info; lsm++) {
init_debug(" early started: %s (%s)\n", lsm->name,
is_enabled(lsm) ? "enabled" : "disabled");
if (lsm->enabled)
lsm_append(lsm->name, &lsm_names);
if (!lsm_file_cache) {
file->f_security = NULL;
return 0;
}
/* Load LSMs in specified order. */
ordered_lsm_init();
file->f_security = kmem_cache_zalloc(lsm_file_cache, GFP_KERNEL);
if (file->f_security == NULL)
return -ENOMEM;
return 0;
}
/* Save user chosen LSM */
static int __init choose_major_lsm(char *str)
{
chosen_major_lsm = str;
return 1;
}
__setup("security=", choose_major_lsm);
/* Explicitly choose LSM initialization order. */
static int __init choose_lsm_order(char *str)
{
chosen_lsm_order = str;
return 1;
}
__setup("lsm=", choose_lsm_order);
/* Enable LSM order debugging. */
static int __init enable_debug(char *str)
{
debug = true;
return 1;
}
__setup("lsm.debug", enable_debug);
static bool match_last_lsm(const char *list, const char *lsm)
{
const char *last;
if (WARN_ON(!list || !lsm))
return false;
last = strrchr(list, ',');
if (last)
/* Pass the comma, strcmp() will check for '\0' */
last++;
else
last = list;
return !strcmp(last, lsm);
}
static int lsm_append(const char *new, char **result)
{
char *cp;
if (*result == NULL) {
*result = kstrdup(new, GFP_KERNEL);
if (*result == NULL)
return -ENOMEM;
} else {
/* Check if it is the last registered name */
if (match_last_lsm(*result, new))
return 0;
cp = kasprintf(GFP_KERNEL, "%s,%s", *result, new);
if (cp == NULL)
return -ENOMEM;
kfree(*result);
*result = cp;
}
return 0;
}
/**
* security_add_hooks - Add a modules hooks to the hook lists.
* @hooks: the hooks to add
* @count: the number of hooks to add
* @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 struct lsm_id *lsmid)
{
int i;
/*
* A security module may call security_add_hooks() more
* than once during initialization, and LSM initialization
* is serialized. Landlock is one such case.
* Look at the previous entry, if there is one, for duplication.
*/
if (lsm_active_cnt == 0 || lsm_idlist[lsm_active_cnt - 1] != lsmid) {
if (lsm_active_cnt >= MAX_LSM_COUNT)
panic("%s Too many LSMs registered.\n", __func__);
lsm_idlist[lsm_active_cnt++] = lsmid;
}
for (i = 0; i < count; i++) {
hooks[i].lsmid = lsmid;
lsm_static_call_init(&hooks[i]);
}
/*
* Don't try to append during early_security_init(), we'll come back
* and fix this up afterwards.
*/
if (slab_is_available()) {
if (lsm_append(lsmid->name, &lsm_names) < 0)
panic("%s - Cannot get early memory.\n", __func__);
}
}
int call_blocking_lsm_notifier(enum lsm_event event, void *data)
{
return blocking_notifier_call_chain(&blocking_lsm_notifier_chain,
event, data);
}
EXPORT_SYMBOL(call_blocking_lsm_notifier);
int register_blocking_lsm_notifier(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&blocking_lsm_notifier_chain,
nb);
}
EXPORT_SYMBOL(register_blocking_lsm_notifier);
int unregister_blocking_lsm_notifier(struct notifier_block *nb)
{
return blocking_notifier_chain_unregister(&blocking_lsm_notifier_chain,
nb);
}
EXPORT_SYMBOL(unregister_blocking_lsm_notifier);
/**
* lsm_blob_alloc - allocate a composite blob
* @dest: the destination for the blob
@ -702,46 +204,11 @@ static int lsm_blob_alloc(void **dest, size_t size, gfp_t gfp)
*
* Returns 0, or -ENOMEM if memory can't be allocated.
*/
static int lsm_cred_alloc(struct cred *cred, gfp_t gfp)
int lsm_cred_alloc(struct cred *cred, gfp_t gfp)
{
return lsm_blob_alloc(&cred->security, blob_sizes.lbs_cred, gfp);
}
/**
* lsm_early_cred - during initialization allocate a composite cred blob
* @cred: the cred that needs a blob
*
* Allocate the cred blob for all the modules
*/
static void __init lsm_early_cred(struct cred *cred)
{
int rc = lsm_cred_alloc(cred, GFP_KERNEL);
if (rc)
panic("%s: Early cred alloc failed.\n", __func__);
}
/**
* lsm_file_alloc - allocate a composite file blob
* @file: the file that needs a blob
*
* Allocate the file blob for all the modules
*
* Returns 0, or -ENOMEM if memory can't be allocated.
*/
static int lsm_file_alloc(struct file *file)
{
if (!lsm_file_cache) {
file->f_security = NULL;
return 0;
}
file->f_security = kmem_cache_zalloc(lsm_file_cache, GFP_KERNEL);
if (file->f_security == NULL)
return -ENOMEM;
return 0;
}
/**
* lsm_inode_alloc - allocate a composite inode blob
* @inode: the inode that needs a blob
@ -772,7 +239,7 @@ static int lsm_inode_alloc(struct inode *inode, gfp_t gfp)
*
* Returns 0, or -ENOMEM if memory can't be allocated.
*/
static int lsm_task_alloc(struct task_struct *task)
int lsm_task_alloc(struct task_struct *task)
{
return lsm_blob_alloc(&task->security, blob_sizes.lbs_task, GFP_KERNEL);
}
@ -874,20 +341,6 @@ static int lsm_bpf_token_alloc(struct bpf_token *token)
}
#endif /* CONFIG_BPF_SYSCALL */
/**
* lsm_early_task - during initialization allocate a composite task blob
* @task: the task that needs a blob
*
* Allocate the task blob for all the modules
*/
static void __init lsm_early_task(struct task_struct *task)
{
int rc = lsm_task_alloc(task);
if (rc)
panic("%s: Early task alloc failed.\n", __func__);
}
/**
* lsm_superblock_alloc - allocate a composite superblock blob
* @sb: the superblock that needs a blob

View File

@ -15,7 +15,7 @@ ccflags-y := -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include
ccflags-$(CONFIG_SECURITY_SELINUX_DEBUG) += -DDEBUG
selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o \
netnode.o netport.o status.o \
netnode.o netport.o status.o initcalls.o \
ss/ebitmap.o ss/hashtab.o ss/symtab.o ss/sidtab.o ss/avtab.o \
ss/policydb.o ss/services.o ss/conditional.o ss/mls.o ss/context.o

View File

@ -94,6 +94,7 @@
#include <linux/io_uring/cmd.h>
#include <uapi/linux/lsm.h>
#include "initcalls.h"
#include "avc.h"
#include "objsec.h"
#include "netif.h"
@ -7617,6 +7618,10 @@ static __init int selinux_init(void)
if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET))
panic("SELinux: Unable to register AVC LSM notifier callback\n");
if (avc_add_callback(selinux_audit_rule_avc_callback,
AVC_CALLBACK_RESET))
panic("SELinux: Unable to register AVC audit callback\n");
if (selinux_enforcing_boot)
pr_debug("SELinux: Starting in enforcing mode\n");
else
@ -7644,11 +7649,12 @@ void selinux_complete_init(void)
/* SELinux requires early initialization in order to label
all processes and objects when they are created. */
DEFINE_LSM(selinux) = {
.name = "selinux",
.id = &selinux_lsmid,
.flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
.enabled = &selinux_enabled_boot,
.blobs = &selinux_blob_sizes,
.init = selinux_init,
.initcall_device = selinux_initcall,
};
#if defined(CONFIG_NETFILTER)
@ -7710,7 +7716,7 @@ static struct pernet_operations selinux_net_ops = {
.exit = selinux_nf_unregister,
};
static int __init selinux_nf_ip_init(void)
int __init selinux_nf_ip_init(void)
{
int err;
@ -7725,5 +7731,4 @@ static int __init selinux_nf_ip_init(void)
return 0;
}
__initcall(selinux_nf_ip_init);
#endif /* CONFIG_NETFILTER */

View File

@ -23,6 +23,7 @@
#include <linux/list.h>
#include <linux/spinlock.h>
#include "initcalls.h"
#include "ibpkey.h"
#include "objsec.h"
@ -218,7 +219,7 @@ void sel_ib_pkey_flush(void)
spin_unlock_irqrestore(&sel_ib_pkey_lock, flags);
}
static __init int sel_ib_pkey_init(void)
int __init sel_ib_pkey_init(void)
{
int iter;
@ -232,5 +233,3 @@ static __init int sel_ib_pkey_init(void)
return 0;
}
subsys_initcall(sel_ib_pkey_init);

View File

@ -15,6 +15,15 @@
#include <linux/audit.h>
#include <linux/types.h>
/**
* selinux_audit_rule_avc_callback - update the audit LSM rules on AVC events.
* @event: the AVC event
*
* Update any audit LSM rules based on the AVC event specified in @event.
* Returns 0 on success, negative values otherwise.
*/
int selinux_audit_rule_avc_callback(u32 event);
/**
* selinux_audit_rule_init - alloc/init an selinux audit rule structure.
* @field: the field this rule refers to

View File

@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* SELinux initcalls
*/
#ifndef _SELINUX_INITCALLS_H
#define _SELINUX_INITCALLS_H
int init_sel_fs(void);
int sel_netport_init(void);
int sel_netnode_init(void);
int sel_netif_init(void);
int sel_netlink_init(void);
int sel_ib_pkey_init(void);
int selinux_nf_ip_init(void);
int selinux_initcall(void);
#endif

View File

@ -0,0 +1,52 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* SELinux initcalls
*/
#include <linux/init.h>
#include "initcalls.h"
/**
* selinux_initcall - Perform the SELinux initcalls
*
* Used as a device initcall in the SELinux LSM definition.
*/
int __init selinux_initcall(void)
{
int rc = 0, rc_tmp = 0;
rc_tmp = init_sel_fs();
if (!rc && rc_tmp)
rc = rc_tmp;
rc_tmp = sel_netport_init();
if (!rc && rc_tmp)
rc = rc_tmp;
rc_tmp = sel_netnode_init();
if (!rc && rc_tmp)
rc = rc_tmp;
rc_tmp = sel_netif_init();
if (!rc && rc_tmp)
rc = rc_tmp;
rc_tmp = sel_netlink_init();
if (!rc && rc_tmp)
rc = rc_tmp;
#if defined(CONFIG_SECURITY_INFINIBAND)
rc_tmp = sel_ib_pkey_init();
if (!rc && rc_tmp)
rc = rc_tmp;
#endif
#if defined(CONFIG_NETFILTER)
rc_tmp = selinux_nf_ip_init();
if (!rc && rc_tmp)
rc = rc_tmp;
#endif
return rc;
}

View File

@ -22,6 +22,7 @@
#include <linux/rcupdate.h>
#include <net/net_namespace.h>
#include "initcalls.h"
#include "security.h"
#include "objsec.h"
#include "netif.h"
@ -265,7 +266,7 @@ static struct notifier_block sel_netif_netdev_notifier = {
.notifier_call = sel_netif_netdev_notifier_handler,
};
static __init int sel_netif_init(void)
int __init sel_netif_init(void)
{
int i;
@ -280,5 +281,3 @@ static __init int sel_netif_init(void)
return 0;
}
__initcall(sel_netif_init);

View File

@ -17,6 +17,7 @@
#include <net/net_namespace.h>
#include <net/netlink.h>
#include "initcalls.h"
#include "security.h"
static struct sock *selnl __ro_after_init;
@ -105,7 +106,7 @@ void selnl_notify_policyload(u32 seqno)
selnl_notify(SELNL_MSG_POLICYLOAD, &seqno);
}
static int __init selnl_init(void)
int __init sel_netlink_init(void)
{
struct netlink_kernel_cfg cfg = {
.groups = SELNLGRP_MAX,
@ -117,5 +118,3 @@ static int __init selnl_init(void)
panic("SELinux: Cannot create netlink socket.");
return 0;
}
__initcall(selnl_init);

View File

@ -30,6 +30,7 @@
#include <net/ip.h>
#include <net/ipv6.h>
#include "initcalls.h"
#include "netnode.h"
#include "objsec.h"
@ -290,7 +291,7 @@ void sel_netnode_flush(void)
spin_unlock_bh(&sel_netnode_lock);
}
static __init int sel_netnode_init(void)
int __init sel_netnode_init(void)
{
int iter;
@ -304,5 +305,3 @@ static __init int sel_netnode_init(void)
return 0;
}
__initcall(sel_netnode_init);

View File

@ -29,6 +29,7 @@
#include <net/ip.h>
#include <net/ipv6.h>
#include "initcalls.h"
#include "netport.h"
#include "objsec.h"
@ -218,7 +219,7 @@ void sel_netport_flush(void)
spin_unlock_bh(&sel_netport_lock);
}
static __init int sel_netport_init(void)
int __init sel_netport_init(void)
{
int iter;
@ -232,5 +233,3 @@ static __init int sel_netport_init(void)
return 0;
}
__initcall(sel_netport_init);

View File

@ -35,6 +35,7 @@
/* selinuxfs pseudo filesystem for exporting the security policy API.
Based on the proc code and the fs/nfsd/nfsctl.c code. */
#include "initcalls.h"
#include "flask.h"
#include "avc.h"
#include "avc_ss.h"
@ -2133,7 +2134,7 @@ static struct file_system_type sel_fs_type = {
struct path selinux_null __ro_after_init;
static int __init init_sel_fs(void)
int __init init_sel_fs(void)
{
struct qstr null_name = QSTR_INIT(NULL_FILE_NAME,
sizeof(NULL_FILE_NAME)-1);
@ -2177,5 +2178,3 @@ static int __init init_sel_fs(void)
return err;
}
__initcall(init_sel_fs);

View File

@ -3570,6 +3570,13 @@ struct selinux_audit_rule {
struct context au_ctxt;
};
int selinux_audit_rule_avc_callback(u32 event)
{
if (event == AVC_CALLBACK_RESET)
return audit_update_lsm_rules();
return 0;
}
void selinux_audit_rule_free(void *vrule)
{
struct selinux_audit_rule *rule = vrule;
@ -3820,25 +3827,6 @@ int selinux_audit_rule_match(struct lsm_prop *prop, u32 field, u32 op, void *vru
return match;
}
static int aurule_avc_callback(u32 event)
{
if (event == AVC_CALLBACK_RESET)
return audit_update_lsm_rules();
return 0;
}
static int __init aurule_init(void)
{
int err;
err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET);
if (err)
panic("avc_add_callback() failed, error %d\n", err);
return err;
}
__initcall(aurule_init);
#ifdef CONFIG_NETLABEL
/**
* security_netlbl_cache_add - Add an entry to the NetLabel cache

View File

@ -275,6 +275,20 @@ struct smk_audit_info {
#endif
};
/*
* Initialization
*/
#if defined(CONFIG_SECURITY_SMACK_NETFILTER)
int smack_nf_ip_init(void);
#else
static inline int smack_nf_ip_init(void)
{
return 0;
}
#endif
int init_smk_fs(void);
int smack_initcall(void);
/*
* These functions are in smack_access.c
*/

View File

@ -5275,13 +5275,22 @@ static __init int smack_init(void)
return 0;
}
int __init smack_initcall(void)
{
int rc_fs = init_smk_fs();
int rc_nf = smack_nf_ip_init();
return rc_fs ? rc_fs : rc_nf;
}
/*
* Smack requires early initialization in order to label
* all processes and objects when they are created.
*/
DEFINE_LSM(smack) = {
.name = "smack",
.id = &smack_lsmid,
.flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
.blobs = &smack_blob_sizes,
.init = smack_init,
.initcall_device = smack_initcall,
};

View File

@ -68,7 +68,7 @@ static struct pernet_operations smack_net_ops = {
.exit = smack_nf_unregister,
};
static int __init smack_nf_ip_init(void)
int __init smack_nf_ip_init(void)
{
if (smack_enabled == 0)
return 0;
@ -76,5 +76,3 @@ static int __init smack_nf_ip_init(void)
printk(KERN_DEBUG "Smack: Registering netfilter hooks\n");
return register_pernet_subsys(&smack_net_ops);
}
__initcall(smack_nf_ip_init);

View File

@ -2978,7 +2978,7 @@ static struct vfsmount *smackfs_mount;
* Returns true if we were not chosen on boot or if
* we were chosen and filesystem registration succeeded.
*/
static int __init init_smk_fs(void)
int __init init_smk_fs(void)
{
int err;
int rc;
@ -3021,5 +3021,3 @@ static int __init init_smk_fs(void)
return err;
}
__initcall(init_smk_fs);

View File

@ -924,6 +924,8 @@ struct tomoyo_task {
/********** Function prototypes. **********/
int tomoyo_interface_init(void);
bool tomoyo_address_matches_group(const bool is_ipv6, const __be32 *address,
const struct tomoyo_group *group);
bool tomoyo_compare_number_union(const unsigned long value,

View File

@ -233,7 +233,7 @@ static void __init tomoyo_create_entry(const char *name, const umode_t mode,
*
* Returns 0.
*/
static int __init tomoyo_interface_init(void)
int __init tomoyo_interface_init(void)
{
struct tomoyo_domain_info *domain;
struct dentry *tomoyo_dir;
@ -269,5 +269,3 @@ static int __init tomoyo_interface_init(void)
tomoyo_load_builtin_policy();
return 0;
}
fs_initcall(tomoyo_interface_init);

View File

@ -612,9 +612,10 @@ static int __init tomoyo_init(void)
}
DEFINE_LSM(tomoyo) = {
.name = "tomoyo",
.id = &tomoyo_lsmid,
.enabled = &tomoyo_enabled,
.flags = LSM_FLAG_LEGACY_MAJOR,
.blobs = &tomoyo_blob_sizes,
.init = tomoyo_init,
.initcall_fs = tomoyo_interface_init,
};

View File

@ -476,6 +476,6 @@ static int __init yama_init(void)
}
DEFINE_LSM(yama) = {
.name = "yama",
.id = &yama_lsmid,
.init = yama_init,
};