mirror of https://github.com/torvalds/linux.git
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:
commit
121cc35cfb
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
@ -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);
|
||||
|
|
@ -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);
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -476,6 +476,6 @@ static int __init yama_init(void)
|
|||
}
|
||||
|
||||
DEFINE_LSM(yama) = {
|
||||
.name = "yama",
|
||||
.id = &yama_lsmid,
|
||||
.init = yama_init,
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue