Merge "Merge 72eaa0967b ("Merge tag 'selinux-pr-20230420' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux") into android-mainline" into android-mainline
This commit is contained in:
+3
@@ -4,6 +4,9 @@ KernelVersion: 2.6.12-rc2 (predates git)
|
||||
Contact: selinux@vger.kernel.org
|
||||
Description:
|
||||
|
||||
REMOVAL UPDATE: The SELinux checkreqprot functionality was removed in
|
||||
March 2023, the original deprecation notice is shown below.
|
||||
|
||||
The selinuxfs "checkreqprot" node allows SELinux to be configured
|
||||
to check the protection requested by userspace for mmap/mprotect
|
||||
calls instead of the actual protection applied by the kernel.
|
||||
+3
@@ -4,6 +4,9 @@ KernelVersion: 2.6.12-rc2 (predates git)
|
||||
Contact: selinux@vger.kernel.org
|
||||
Description:
|
||||
|
||||
REMOVAL UPDATE: The SELinux runtime disable functionality was removed
|
||||
in March 2023, the original deprecation notice is shown below.
|
||||
|
||||
The selinuxfs "disable" node allows SELinux to be disabled at runtime
|
||||
prior to a policy being loaded into the kernel. If disabled via this
|
||||
mechanism, SELinux will remain disabled until the system is rebooted.
|
||||
+2
-2
@@ -18829,8 +18829,8 @@ S: Supported
|
||||
W: https://selinuxproject.org
|
||||
W: https://github.com/SELinuxProject
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
|
||||
F: Documentation/ABI/obsolete/sysfs-selinux-checkreqprot
|
||||
F: Documentation/ABI/obsolete/sysfs-selinux-disable
|
||||
F: Documentation/ABI/removed/sysfs-selinux-checkreqprot
|
||||
F: Documentation/ABI/removed/sysfs-selinux-disable
|
||||
F: Documentation/admin-guide/LSM/SELinux.rst
|
||||
F: include/trace/events/avc.h
|
||||
F: include/uapi/linux/selinux_netlink.h
|
||||
|
||||
@@ -1740,36 +1740,6 @@ extern struct lsm_info __start_early_lsm_info[], __end_early_lsm_info[];
|
||||
__used __section(".early_lsm_info.init") \
|
||||
__aligned(sizeof(unsigned long))
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
|
||||
/*
|
||||
* Assuring the safety of deleting a security module is up to
|
||||
* the security module involved. This may entail ordering the
|
||||
* module's hook list in a particular way, refusing to disable
|
||||
* the module once a policy is loaded or any number of other
|
||||
* actions better imagined than described.
|
||||
*
|
||||
* The name of the configuration option reflects the only module
|
||||
* that currently uses the mechanism. Any developer who thinks
|
||||
* disabling their module is a good idea needs to be at least as
|
||||
* careful as the SELinux team.
|
||||
*/
|
||||
static inline void security_delete_hooks(struct security_hook_list *hooks,
|
||||
int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
hlist_del_rcu(&hooks[i].list);
|
||||
}
|
||||
#endif /* CONFIG_SECURITY_SELINUX_DISABLE */
|
||||
|
||||
/* Currently required to handle SELinux runtime hook disable. */
|
||||
#ifdef CONFIG_SECURITY_WRITABLE_HOOKS
|
||||
#define __lsm_ro_after_init
|
||||
#else
|
||||
#define __lsm_ro_after_init __ro_after_init
|
||||
#endif /* CONFIG_SECURITY_WRITABLE_HOOKS */
|
||||
|
||||
extern int lsm_inode_alloc(struct inode *inode);
|
||||
|
||||
#endif /* ! __LINUX_LSM_HOOKS_H */
|
||||
|
||||
@@ -32,11 +32,6 @@ config SECURITY
|
||||
|
||||
If you are unsure how to answer this question, answer N.
|
||||
|
||||
config SECURITY_WRITABLE_HOOKS
|
||||
depends on SECURITY
|
||||
bool
|
||||
default n
|
||||
|
||||
config SECURITYFS
|
||||
bool "Enable the securityfs filesystem"
|
||||
help
|
||||
|
||||
@@ -1209,13 +1209,13 @@ static int apparmor_inet_conn_request(const struct sock *sk, struct sk_buff *skb
|
||||
/*
|
||||
* The cred blob is a pointer to, not an instance of, an aa_label.
|
||||
*/
|
||||
struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = {
|
||||
struct lsm_blob_sizes apparmor_blob_sizes __ro_after_init = {
|
||||
.lbs_cred = sizeof(struct aa_label *),
|
||||
.lbs_file = sizeof(struct aa_file_ctx),
|
||||
.lbs_task = sizeof(struct aa_task_ctx),
|
||||
};
|
||||
|
||||
static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
|
||||
static struct security_hook_list apparmor_hooks[] __ro_after_init = {
|
||||
LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
|
||||
LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
|
||||
LSM_HOOK_INIT(capget, apparmor_capget),
|
||||
@@ -1427,7 +1427,7 @@ static const struct kernel_param_ops param_ops_aaintbool = {
|
||||
.get = param_get_aaintbool
|
||||
};
|
||||
/* Boot time disable flag */
|
||||
static int apparmor_enabled __lsm_ro_after_init = 1;
|
||||
static int apparmor_enabled __ro_after_init = 1;
|
||||
module_param_named(enabled, apparmor_enabled, aaintbool, 0444);
|
||||
|
||||
static int __init apparmor_enabled_setup(char *str)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <linux/lsm_hooks.h>
|
||||
#include <linux/bpf_lsm.h>
|
||||
|
||||
static struct security_hook_list bpf_lsm_hooks[] __lsm_ro_after_init = {
|
||||
static struct security_hook_list bpf_lsm_hooks[] __ro_after_init = {
|
||||
#define LSM_HOOK(RET, DEFAULT, NAME, ...) \
|
||||
LSM_HOOK_INIT(NAME, bpf_lsm_##NAME),
|
||||
#include <linux/lsm_hook_defs.h>
|
||||
@@ -22,7 +22,7 @@ static int __init bpf_lsm_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct lsm_blob_sizes bpf_lsm_blob_sizes __lsm_ro_after_init = {
|
||||
struct lsm_blob_sizes bpf_lsm_blob_sizes __ro_after_init = {
|
||||
.lbs_inode = sizeof(struct bpf_storage_blob),
|
||||
.lbs_task = sizeof(struct bpf_storage_blob),
|
||||
};
|
||||
|
||||
@@ -1440,7 +1440,7 @@ int cap_mmap_file(struct file *file, unsigned long reqprot,
|
||||
|
||||
#ifdef CONFIG_SECURITY
|
||||
|
||||
static struct security_hook_list capability_hooks[] __lsm_ro_after_init = {
|
||||
static struct security_hook_list capability_hooks[] __ro_after_init = {
|
||||
LSM_HOOK_INIT(capable, cap_capable),
|
||||
LSM_HOOK_INIT(settime, cap_settime),
|
||||
LSM_HOOK_INIT(ptrace_access_check, cap_ptrace_access_check),
|
||||
|
||||
@@ -34,7 +34,7 @@ static void hook_cred_free(struct cred *const cred)
|
||||
landlock_put_ruleset_deferred(dom);
|
||||
}
|
||||
|
||||
static struct security_hook_list landlock_hooks[] __lsm_ro_after_init = {
|
||||
static struct security_hook_list landlock_hooks[] __ro_after_init = {
|
||||
LSM_HOOK_INIT(cred_prepare, hook_cred_prepare),
|
||||
LSM_HOOK_INIT(cred_free, hook_cred_free),
|
||||
};
|
||||
|
||||
@@ -1280,7 +1280,7 @@ static int hook_file_truncate(struct file *const file)
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
static struct security_hook_list landlock_hooks[] __lsm_ro_after_init = {
|
||||
static struct security_hook_list landlock_hooks[] __ro_after_init = {
|
||||
LSM_HOOK_INIT(inode_free_security, hook_inode_free_security),
|
||||
|
||||
LSM_HOOK_INIT(sb_delete, hook_sb_delete),
|
||||
|
||||
@@ -108,7 +108,7 @@ static int hook_ptrace_traceme(struct task_struct *const parent)
|
||||
return task_ptrace(parent, current);
|
||||
}
|
||||
|
||||
static struct security_hook_list landlock_hooks[] __lsm_ro_after_init = {
|
||||
static struct security_hook_list landlock_hooks[] __ro_after_init = {
|
||||
LSM_HOOK_INIT(ptrace_access_check, hook_ptrace_access_check),
|
||||
LSM_HOOK_INIT(ptrace_traceme, hook_ptrace_traceme),
|
||||
};
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
#include "ptrace.h"
|
||||
#include "setup.h"
|
||||
|
||||
bool landlock_initialized __lsm_ro_after_init = false;
|
||||
bool landlock_initialized __ro_after_init = false;
|
||||
|
||||
struct lsm_blob_sizes landlock_blob_sizes __lsm_ro_after_init = {
|
||||
struct lsm_blob_sizes landlock_blob_sizes __ro_after_init = {
|
||||
.lbs_cred = sizeof(struct landlock_cred_security),
|
||||
.lbs_file = sizeof(struct landlock_file_security),
|
||||
.lbs_inode = sizeof(struct landlock_inode_security),
|
||||
|
||||
@@ -214,7 +214,7 @@ static int loadpin_load_data(enum kernel_load_data_id id, bool contents)
|
||||
return loadpin_check(NULL, (enum kernel_read_file_id) id);
|
||||
}
|
||||
|
||||
static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
|
||||
static struct security_hook_list loadpin_hooks[] __ro_after_init = {
|
||||
LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
|
||||
LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
|
||||
LSM_HOOK_INIT(kernel_load_data, loadpin_load_data),
|
||||
|
||||
@@ -71,7 +71,7 @@ static int lockdown_is_locked_down(enum lockdown_reason what)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct security_hook_list lockdown_hooks[] __lsm_ro_after_init = {
|
||||
static struct security_hook_list lockdown_hooks[] __ro_after_init = {
|
||||
LSM_HOOK_INIT(locked_down, lockdown_is_locked_down),
|
||||
};
|
||||
|
||||
|
||||
+2
-2
@@ -74,14 +74,14 @@ const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
|
||||
[LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
|
||||
};
|
||||
|
||||
struct security_hook_heads security_hook_heads __lsm_ro_after_init;
|
||||
struct security_hook_heads security_hook_heads __ro_after_init;
|
||||
static BLOCKING_NOTIFIER_HEAD(blocking_lsm_notifier_chain);
|
||||
|
||||
static struct kmem_cache *lsm_file_cache;
|
||||
static struct kmem_cache *lsm_inode_cache;
|
||||
|
||||
char *lsm_names;
|
||||
static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init;
|
||||
static struct lsm_blob_sizes blob_sizes __ro_after_init;
|
||||
|
||||
/* Boot-time LSM user choice */
|
||||
static __initdata const char *chosen_lsm_order;
|
||||
|
||||
@@ -23,30 +23,6 @@ config SECURITY_SELINUX_BOOTPARAM
|
||||
|
||||
If you are unsure how to answer this question, answer N.
|
||||
|
||||
config SECURITY_SELINUX_DISABLE
|
||||
bool "NSA SELinux runtime disable"
|
||||
depends on SECURITY_SELINUX
|
||||
select SECURITY_WRITABLE_HOOKS
|
||||
default n
|
||||
help
|
||||
This option enables writing to a selinuxfs node 'disable', which
|
||||
allows SELinux to be disabled at runtime prior to the policy load.
|
||||
SELinux will then remain disabled until the next boot.
|
||||
This option is similar to the selinux=0 boot parameter, but is to
|
||||
support runtime disabling of SELinux, e.g. from /sbin/init, for
|
||||
portability across platforms where boot parameters are difficult
|
||||
to employ.
|
||||
|
||||
NOTE: selecting this option will disable the '__ro_after_init'
|
||||
kernel hardening feature for security hooks. Please consider
|
||||
using the selinux=0 boot parameter instead of enabling this
|
||||
option.
|
||||
|
||||
WARNING: this option is deprecated and will be removed in a future
|
||||
kernel release.
|
||||
|
||||
If you are unsure how to answer this question, answer N.
|
||||
|
||||
config SECURITY_SELINUX_DEVELOP
|
||||
bool "NSA SELinux Development Support"
|
||||
depends on SECURITY_SELINUX
|
||||
@@ -70,29 +46,6 @@ config SECURITY_SELINUX_AVC_STATS
|
||||
/sys/fs/selinux/avc/cache_stats, which may be monitored via
|
||||
tools such as avcstat.
|
||||
|
||||
config SECURITY_SELINUX_CHECKREQPROT_VALUE
|
||||
int "NSA SELinux checkreqprot default value"
|
||||
depends on SECURITY_SELINUX
|
||||
range 0 1
|
||||
default 0
|
||||
help
|
||||
This option sets the default value for the 'checkreqprot' flag
|
||||
that determines whether SELinux checks the protection requested
|
||||
by the application or the protection that will be applied by the
|
||||
kernel (including any implied execute for read-implies-exec) for
|
||||
mmap and mprotect calls. If this option is set to 0 (zero),
|
||||
SELinux will default to checking the protection that will be applied
|
||||
by the kernel. If this option is set to 1 (one), SELinux will
|
||||
default to checking the protection requested by the application.
|
||||
The checkreqprot flag may be changed from the default via the
|
||||
'checkreqprot=' boot parameter. It may also be changed at runtime
|
||||
via /sys/fs/selinux/checkreqprot if authorized by policy.
|
||||
|
||||
WARNING: this option is deprecated and will be removed in a future
|
||||
kernel release.
|
||||
|
||||
If you are unsure how to answer this question, answer 0.
|
||||
|
||||
config SECURITY_SELINUX_SIDTAB_HASH_BITS
|
||||
int "NSA SELinux sidtab hashtable size"
|
||||
depends on SECURITY_SELINUX
|
||||
|
||||
@@ -23,8 +23,8 @@ ccflags-y := -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include
|
||||
$(addprefix $(obj)/,$(selinux-y)): $(obj)/flask.h
|
||||
|
||||
quiet_cmd_flask = GEN $(obj)/flask.h $(obj)/av_permissions.h
|
||||
cmd_flask = scripts/selinux/genheaders/genheaders $(obj)/flask.h $(obj)/av_permissions.h
|
||||
cmd_flask = $< $(obj)/flask.h $(obj)/av_permissions.h
|
||||
|
||||
targets += flask.h av_permissions.h
|
||||
$(obj)/flask.h: $(src)/include/classmap.h FORCE
|
||||
$(obj)/flask.h $(obj)/av_permissions.h &: scripts/selinux/genheaders/genheaders FORCE
|
||||
$(call if_changed,flask)
|
||||
|
||||
+140
-138
@@ -96,7 +96,7 @@ struct selinux_avc {
|
||||
|
||||
static struct selinux_avc selinux_avc;
|
||||
|
||||
void selinux_avc_init(struct selinux_avc **avc)
|
||||
void selinux_avc_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -107,18 +107,16 @@ void selinux_avc_init(struct selinux_avc **avc)
|
||||
}
|
||||
atomic_set(&selinux_avc.avc_cache.active_nodes, 0);
|
||||
atomic_set(&selinux_avc.avc_cache.lru_hint, 0);
|
||||
*avc = &selinux_avc;
|
||||
}
|
||||
|
||||
unsigned int avc_get_cache_threshold(struct selinux_avc *avc)
|
||||
unsigned int avc_get_cache_threshold(void)
|
||||
{
|
||||
return avc->avc_cache_threshold;
|
||||
return selinux_avc.avc_cache_threshold;
|
||||
}
|
||||
|
||||
void avc_set_cache_threshold(struct selinux_avc *avc,
|
||||
unsigned int cache_threshold)
|
||||
void avc_set_cache_threshold(unsigned int cache_threshold)
|
||||
{
|
||||
avc->avc_cache_threshold = cache_threshold;
|
||||
selinux_avc.avc_cache_threshold = cache_threshold;
|
||||
}
|
||||
|
||||
static struct avc_callback_node *avc_callbacks __ro_after_init;
|
||||
@@ -153,7 +151,7 @@ void __init avc_init(void)
|
||||
0, SLAB_PANIC, NULL);
|
||||
}
|
||||
|
||||
int avc_get_hash_stats(struct selinux_avc *avc, char *page)
|
||||
int avc_get_hash_stats(char *page)
|
||||
{
|
||||
int i, chain_len, max_chain_len, slots_used;
|
||||
struct avc_node *node;
|
||||
@@ -164,7 +162,7 @@ int avc_get_hash_stats(struct selinux_avc *avc, char *page)
|
||||
slots_used = 0;
|
||||
max_chain_len = 0;
|
||||
for (i = 0; i < AVC_CACHE_SLOTS; i++) {
|
||||
head = &avc->avc_cache.slots[i];
|
||||
head = &selinux_avc.avc_cache.slots[i];
|
||||
if (!hlist_empty(head)) {
|
||||
slots_used++;
|
||||
chain_len = 0;
|
||||
@@ -179,7 +177,7 @@ int avc_get_hash_stats(struct selinux_avc *avc, char *page)
|
||||
|
||||
return scnprintf(page, PAGE_SIZE, "entries: %d\nbuckets used: %d/%d\n"
|
||||
"longest chain: %d\n",
|
||||
atomic_read(&avc->avc_cache.active_nodes),
|
||||
atomic_read(&selinux_avc.avc_cache.active_nodes),
|
||||
slots_used, AVC_CACHE_SLOTS, max_chain_len);
|
||||
}
|
||||
|
||||
@@ -417,8 +415,7 @@ static inline u32 avc_xperms_audit_required(u32 requested,
|
||||
return audited;
|
||||
}
|
||||
|
||||
static inline int avc_xperms_audit(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid, u16 tclass,
|
||||
static inline int avc_xperms_audit(u32 ssid, u32 tsid, u16 tclass,
|
||||
u32 requested, struct av_decision *avd,
|
||||
struct extended_perms_decision *xpd,
|
||||
u8 perm, int result,
|
||||
@@ -430,7 +427,7 @@ static inline int avc_xperms_audit(struct selinux_state *state,
|
||||
requested, avd, xpd, perm, result, &denied);
|
||||
if (likely(!audited))
|
||||
return 0;
|
||||
return slow_avc_audit(state, ssid, tsid, tclass, requested,
|
||||
return slow_avc_audit(ssid, tsid, tclass, requested,
|
||||
audited, denied, result, ad);
|
||||
}
|
||||
|
||||
@@ -442,32 +439,31 @@ static void avc_node_free(struct rcu_head *rhead)
|
||||
avc_cache_stats_incr(frees);
|
||||
}
|
||||
|
||||
static void avc_node_delete(struct selinux_avc *avc, struct avc_node *node)
|
||||
static void avc_node_delete(struct avc_node *node)
|
||||
{
|
||||
trace_android_rvh_selinux_avc_node_delete(node);
|
||||
hlist_del_rcu(&node->list);
|
||||
call_rcu(&node->rhead, avc_node_free);
|
||||
atomic_dec(&avc->avc_cache.active_nodes);
|
||||
atomic_dec(&selinux_avc.avc_cache.active_nodes);
|
||||
}
|
||||
|
||||
static void avc_node_kill(struct selinux_avc *avc, struct avc_node *node)
|
||||
static void avc_node_kill(struct avc_node *node)
|
||||
{
|
||||
avc_xperms_free(node->ae.xp_node);
|
||||
kmem_cache_free(avc_node_cachep, node);
|
||||
avc_cache_stats_incr(frees);
|
||||
atomic_dec(&avc->avc_cache.active_nodes);
|
||||
atomic_dec(&selinux_avc.avc_cache.active_nodes);
|
||||
}
|
||||
|
||||
static void avc_node_replace(struct selinux_avc *avc,
|
||||
struct avc_node *new, struct avc_node *old)
|
||||
static void avc_node_replace(struct avc_node *new, struct avc_node *old)
|
||||
{
|
||||
trace_android_rvh_selinux_avc_node_replace(old, new);
|
||||
hlist_replace_rcu(&old->list, &new->list);
|
||||
call_rcu(&old->rhead, avc_node_free);
|
||||
atomic_dec(&avc->avc_cache.active_nodes);
|
||||
atomic_dec(&selinux_avc.avc_cache.active_nodes);
|
||||
}
|
||||
|
||||
static inline int avc_reclaim_node(struct selinux_avc *avc)
|
||||
static inline int avc_reclaim_node(void)
|
||||
{
|
||||
struct avc_node *node;
|
||||
int hvalue, try, ecx;
|
||||
@@ -476,17 +472,17 @@ static inline int avc_reclaim_node(struct selinux_avc *avc)
|
||||
spinlock_t *lock;
|
||||
|
||||
for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++) {
|
||||
hvalue = atomic_inc_return(&avc->avc_cache.lru_hint) &
|
||||
hvalue = atomic_inc_return(&selinux_avc.avc_cache.lru_hint) &
|
||||
(AVC_CACHE_SLOTS - 1);
|
||||
head = &avc->avc_cache.slots[hvalue];
|
||||
lock = &avc->avc_cache.slots_lock[hvalue];
|
||||
head = &selinux_avc.avc_cache.slots[hvalue];
|
||||
lock = &selinux_avc.avc_cache.slots_lock[hvalue];
|
||||
|
||||
if (!spin_trylock_irqsave(lock, flags))
|
||||
continue;
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry(node, head, list) {
|
||||
avc_node_delete(avc, node);
|
||||
avc_node_delete(node);
|
||||
avc_cache_stats_incr(reclaims);
|
||||
ecx++;
|
||||
if (ecx >= AVC_CACHE_RECLAIM) {
|
||||
@@ -502,7 +498,7 @@ out:
|
||||
return ecx;
|
||||
}
|
||||
|
||||
static struct avc_node *avc_alloc_node(struct selinux_avc *avc)
|
||||
static struct avc_node *avc_alloc_node(void)
|
||||
{
|
||||
struct avc_node *node;
|
||||
|
||||
@@ -513,9 +509,9 @@ static struct avc_node *avc_alloc_node(struct selinux_avc *avc)
|
||||
INIT_HLIST_NODE(&node->list);
|
||||
avc_cache_stats_incr(allocations);
|
||||
|
||||
if (atomic_inc_return(&avc->avc_cache.active_nodes) >
|
||||
avc->avc_cache_threshold)
|
||||
avc_reclaim_node(avc);
|
||||
if (atomic_inc_return(&selinux_avc.avc_cache.active_nodes) >
|
||||
selinux_avc.avc_cache_threshold)
|
||||
avc_reclaim_node();
|
||||
|
||||
out:
|
||||
return node;
|
||||
@@ -529,15 +525,14 @@ static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid, u16 tcl
|
||||
memcpy(&node->ae.avd, avd, sizeof(node->ae.avd));
|
||||
}
|
||||
|
||||
static inline struct avc_node *avc_search_node(struct selinux_avc *avc,
|
||||
u32 ssid, u32 tsid, u16 tclass)
|
||||
static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass)
|
||||
{
|
||||
struct avc_node *node, *ret = NULL;
|
||||
int hvalue;
|
||||
struct hlist_head *head;
|
||||
|
||||
hvalue = avc_hash(ssid, tsid, tclass);
|
||||
head = &avc->avc_cache.slots[hvalue];
|
||||
head = &selinux_avc.avc_cache.slots[hvalue];
|
||||
hlist_for_each_entry_rcu(node, head, list) {
|
||||
if (ssid == node->ae.ssid &&
|
||||
tclass == node->ae.tclass &&
|
||||
@@ -552,7 +547,6 @@ static inline struct avc_node *avc_search_node(struct selinux_avc *avc,
|
||||
|
||||
/**
|
||||
* avc_lookup - Look up an AVC entry.
|
||||
* @avc: the access vector cache
|
||||
* @ssid: source security identifier
|
||||
* @tsid: target security identifier
|
||||
* @tclass: target security class
|
||||
@@ -563,13 +557,12 @@ static inline struct avc_node *avc_search_node(struct selinux_avc *avc,
|
||||
* then this function returns the avc_node.
|
||||
* Otherwise, this function returns NULL.
|
||||
*/
|
||||
static struct avc_node *avc_lookup(struct selinux_avc *avc,
|
||||
u32 ssid, u32 tsid, u16 tclass)
|
||||
static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass)
|
||||
{
|
||||
struct avc_node *node;
|
||||
|
||||
avc_cache_stats_incr(lookups);
|
||||
node = avc_search_node(avc, ssid, tsid, tclass);
|
||||
node = avc_search_node(ssid, tsid, tclass);
|
||||
|
||||
if (node) {
|
||||
trace_android_rvh_selinux_avc_lookup(node, ssid, tsid, tclass);
|
||||
@@ -580,8 +573,7 @@ static struct avc_node *avc_lookup(struct selinux_avc *avc,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int avc_latest_notif_update(struct selinux_avc *avc,
|
||||
int seqno, int is_insert)
|
||||
static int avc_latest_notif_update(int seqno, int is_insert)
|
||||
{
|
||||
int ret = 0;
|
||||
static DEFINE_SPINLOCK(notif_lock);
|
||||
@@ -589,14 +581,14 @@ static int avc_latest_notif_update(struct selinux_avc *avc,
|
||||
|
||||
spin_lock_irqsave(¬if_lock, flag);
|
||||
if (is_insert) {
|
||||
if (seqno < avc->avc_cache.latest_notif) {
|
||||
if (seqno < selinux_avc.avc_cache.latest_notif) {
|
||||
pr_warn("SELinux: avc: seqno %d < latest_notif %d\n",
|
||||
seqno, avc->avc_cache.latest_notif);
|
||||
seqno, selinux_avc.avc_cache.latest_notif);
|
||||
ret = -EAGAIN;
|
||||
}
|
||||
} else {
|
||||
if (seqno > avc->avc_cache.latest_notif)
|
||||
avc->avc_cache.latest_notif = seqno;
|
||||
if (seqno > selinux_avc.avc_cache.latest_notif)
|
||||
selinux_avc.avc_cache.latest_notif = seqno;
|
||||
}
|
||||
spin_unlock_irqrestore(¬if_lock, flag);
|
||||
|
||||
@@ -605,7 +597,6 @@ static int avc_latest_notif_update(struct selinux_avc *avc,
|
||||
|
||||
/**
|
||||
* avc_insert - Insert an AVC entry.
|
||||
* @avc: the access vector cache
|
||||
* @ssid: source security identifier
|
||||
* @tsid: target security identifier
|
||||
* @tclass: target security class
|
||||
@@ -619,13 +610,10 @@ static int avc_latest_notif_update(struct selinux_avc *avc,
|
||||
* response to a security_compute_av() call. If the
|
||||
* sequence number @avd->seqno is not less than the latest
|
||||
* revocation notification, then the function copies
|
||||
* the access vectors into a cache entry, returns
|
||||
* avc_node inserted. Otherwise, this function returns NULL.
|
||||
* the access vectors into a cache entry.
|
||||
*/
|
||||
static struct avc_node *avc_insert(struct selinux_avc *avc,
|
||||
u32 ssid, u32 tsid, u16 tclass,
|
||||
struct av_decision *avd,
|
||||
struct avc_xperms_node *xp_node)
|
||||
static void avc_insert(u32 ssid, u32 tsid, u16 tclass,
|
||||
struct av_decision *avd, struct avc_xperms_node *xp_node)
|
||||
{
|
||||
struct avc_node *pos, *node = NULL;
|
||||
int hvalue;
|
||||
@@ -633,28 +621,28 @@ static struct avc_node *avc_insert(struct selinux_avc *avc,
|
||||
spinlock_t *lock;
|
||||
struct hlist_head *head;
|
||||
|
||||
if (avc_latest_notif_update(avc, avd->seqno, 1))
|
||||
return NULL;
|
||||
if (avc_latest_notif_update(avd->seqno, 1))
|
||||
return;
|
||||
|
||||
node = avc_alloc_node(avc);
|
||||
node = avc_alloc_node();
|
||||
if (!node)
|
||||
return NULL;
|
||||
return;
|
||||
|
||||
avc_node_populate(node, ssid, tsid, tclass, avd);
|
||||
if (avc_xperms_populate(node, xp_node)) {
|
||||
avc_node_kill(avc, node);
|
||||
return NULL;
|
||||
avc_node_kill(node);
|
||||
return;
|
||||
}
|
||||
|
||||
hvalue = avc_hash(ssid, tsid, tclass);
|
||||
head = &avc->avc_cache.slots[hvalue];
|
||||
lock = &avc->avc_cache.slots_lock[hvalue];
|
||||
head = &selinux_avc.avc_cache.slots[hvalue];
|
||||
lock = &selinux_avc.avc_cache.slots_lock[hvalue];
|
||||
spin_lock_irqsave(lock, flag);
|
||||
hlist_for_each_entry(pos, head, list) {
|
||||
if (pos->ae.ssid == ssid &&
|
||||
pos->ae.tsid == tsid &&
|
||||
pos->ae.tclass == tclass) {
|
||||
avc_node_replace(avc, node, pos);
|
||||
avc_node_replace(node, pos);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
@@ -662,7 +650,7 @@ static struct avc_node *avc_insert(struct selinux_avc *avc,
|
||||
trace_android_rvh_selinux_avc_insert(node);
|
||||
found:
|
||||
spin_unlock_irqrestore(lock, flag);
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -723,14 +711,14 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
|
||||
u32 tcontext_len;
|
||||
int rc;
|
||||
|
||||
rc = security_sid_to_context(sad->state, sad->ssid, &scontext,
|
||||
rc = security_sid_to_context(sad->ssid, &scontext,
|
||||
&scontext_len);
|
||||
if (rc)
|
||||
audit_log_format(ab, " ssid=%d", sad->ssid);
|
||||
else
|
||||
audit_log_format(ab, " scontext=%s", scontext);
|
||||
|
||||
rc = security_sid_to_context(sad->state, sad->tsid, &tcontext,
|
||||
rc = security_sid_to_context(sad->tsid, &tcontext,
|
||||
&tcontext_len);
|
||||
if (rc)
|
||||
audit_log_format(ab, " tsid=%d", sad->tsid);
|
||||
@@ -748,7 +736,7 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
|
||||
kfree(scontext);
|
||||
|
||||
/* in case of invalid context report also the actual context string */
|
||||
rc = security_sid_to_context_inval(sad->state, sad->ssid, &scontext,
|
||||
rc = security_sid_to_context_inval(sad->ssid, &scontext,
|
||||
&scontext_len);
|
||||
if (!rc && scontext) {
|
||||
if (scontext_len && scontext[scontext_len - 1] == '\0')
|
||||
@@ -758,7 +746,7 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
|
||||
kfree(scontext);
|
||||
}
|
||||
|
||||
rc = security_sid_to_context_inval(sad->state, sad->tsid, &scontext,
|
||||
rc = security_sid_to_context_inval(sad->tsid, &scontext,
|
||||
&scontext_len);
|
||||
if (!rc && scontext) {
|
||||
if (scontext_len && scontext[scontext_len - 1] == '\0')
|
||||
@@ -774,8 +762,7 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
|
||||
* Note that it is non-blocking and can be called from under
|
||||
* rcu_read_lock().
|
||||
*/
|
||||
noinline int slow_avc_audit(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid, u16 tclass,
|
||||
noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
|
||||
u32 requested, u32 audited, u32 denied, int result,
|
||||
struct common_audit_data *a)
|
||||
{
|
||||
@@ -797,7 +784,6 @@ noinline int slow_avc_audit(struct selinux_state *state,
|
||||
sad.audited = audited;
|
||||
sad.denied = denied;
|
||||
sad.result = result;
|
||||
sad.state = state;
|
||||
|
||||
a->selinux_audit_data = &sad;
|
||||
|
||||
@@ -835,7 +821,6 @@ out:
|
||||
|
||||
/**
|
||||
* avc_update_node - Update an AVC entry
|
||||
* @avc: the access vector cache
|
||||
* @event : Updating event
|
||||
* @perms : Permission mask bits
|
||||
* @driver: xperm driver information
|
||||
@@ -852,8 +837,7 @@ out:
|
||||
* otherwise, this function updates the AVC entry. The original AVC-entry object
|
||||
* will release later by RCU.
|
||||
*/
|
||||
static int avc_update_node(struct selinux_avc *avc,
|
||||
u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid,
|
||||
static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid,
|
||||
u32 tsid, u16 tclass, u32 seqno,
|
||||
struct extended_perms_decision *xpd,
|
||||
u32 flags)
|
||||
@@ -864,7 +848,7 @@ static int avc_update_node(struct selinux_avc *avc,
|
||||
struct hlist_head *head;
|
||||
spinlock_t *lock;
|
||||
|
||||
node = avc_alloc_node(avc);
|
||||
node = avc_alloc_node();
|
||||
if (!node) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
@@ -873,8 +857,8 @@ static int avc_update_node(struct selinux_avc *avc,
|
||||
/* Lock the target slot */
|
||||
hvalue = avc_hash(ssid, tsid, tclass);
|
||||
|
||||
head = &avc->avc_cache.slots[hvalue];
|
||||
lock = &avc->avc_cache.slots_lock[hvalue];
|
||||
head = &selinux_avc.avc_cache.slots[hvalue];
|
||||
lock = &selinux_avc.avc_cache.slots_lock[hvalue];
|
||||
|
||||
spin_lock_irqsave(lock, flag);
|
||||
|
||||
@@ -890,7 +874,7 @@ static int avc_update_node(struct selinux_avc *avc,
|
||||
|
||||
if (!orig) {
|
||||
rc = -ENOENT;
|
||||
avc_node_kill(avc, node);
|
||||
avc_node_kill(node);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
@@ -903,7 +887,7 @@ static int avc_update_node(struct selinux_avc *avc,
|
||||
if (orig->ae.xp_node) {
|
||||
rc = avc_xperms_populate(node, orig->ae.xp_node);
|
||||
if (rc) {
|
||||
avc_node_kill(avc, node);
|
||||
avc_node_kill(node);
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
@@ -934,7 +918,7 @@ static int avc_update_node(struct selinux_avc *avc,
|
||||
avc_add_xperms_decision(node, xpd);
|
||||
break;
|
||||
}
|
||||
avc_node_replace(avc, node, orig);
|
||||
avc_node_replace(node, orig);
|
||||
out_unlock:
|
||||
spin_unlock_irqrestore(lock, flag);
|
||||
out:
|
||||
@@ -943,9 +927,8 @@ out:
|
||||
|
||||
/**
|
||||
* avc_flush - Flush the cache
|
||||
* @avc: the access vector cache
|
||||
*/
|
||||
static void avc_flush(struct selinux_avc *avc)
|
||||
static void avc_flush(void)
|
||||
{
|
||||
struct hlist_head *head;
|
||||
struct avc_node *node;
|
||||
@@ -954,8 +937,8 @@ static void avc_flush(struct selinux_avc *avc)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AVC_CACHE_SLOTS; i++) {
|
||||
head = &avc->avc_cache.slots[i];
|
||||
lock = &avc->avc_cache.slots_lock[i];
|
||||
head = &selinux_avc.avc_cache.slots[i];
|
||||
lock = &selinux_avc.avc_cache.slots_lock[i];
|
||||
|
||||
spin_lock_irqsave(lock, flag);
|
||||
/*
|
||||
@@ -964,7 +947,7 @@ static void avc_flush(struct selinux_avc *avc)
|
||||
*/
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry(node, head, list)
|
||||
avc_node_delete(avc, node);
|
||||
avc_node_delete(node);
|
||||
rcu_read_unlock();
|
||||
spin_unlock_irqrestore(lock, flag);
|
||||
}
|
||||
@@ -972,15 +955,14 @@ static void avc_flush(struct selinux_avc *avc)
|
||||
|
||||
/**
|
||||
* avc_ss_reset - Flush the cache and revalidate migrated permissions.
|
||||
* @avc: the access vector cache
|
||||
* @seqno: policy sequence number
|
||||
*/
|
||||
int avc_ss_reset(struct selinux_avc *avc, u32 seqno)
|
||||
int avc_ss_reset(u32 seqno)
|
||||
{
|
||||
struct avc_callback_node *c;
|
||||
int rc = 0, tmprc;
|
||||
|
||||
avc_flush(avc);
|
||||
avc_flush();
|
||||
|
||||
for (c = avc_callbacks; c; c = c->next) {
|
||||
if (c->events & AVC_CALLBACK_RESET) {
|
||||
@@ -992,34 +974,32 @@ int avc_ss_reset(struct selinux_avc *avc, u32 seqno)
|
||||
}
|
||||
}
|
||||
|
||||
avc_latest_notif_update(avc, seqno, 0);
|
||||
avc_latest_notif_update(seqno, 0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Slow-path helper function for avc_has_perm_noaudit,
|
||||
* when the avc_node lookup fails. We get called with
|
||||
* the RCU read lock held, and need to return with it
|
||||
* still held, but drop if for the security compute.
|
||||
/**
|
||||
* avc_compute_av - Add an entry to the AVC based on the security policy
|
||||
* @ssid: subject
|
||||
* @tsid: object/target
|
||||
* @tclass: object class
|
||||
* @avd: access vector decision
|
||||
* @xp_node: AVC extended permissions node
|
||||
*
|
||||
* Don't inline this, since it's the slow-path and just
|
||||
* results in a bigger stack frame.
|
||||
* Slow-path helper function for avc_has_perm_noaudit, when the avc_node lookup
|
||||
* fails. Don't inline this, since it's the slow-path and just results in a
|
||||
* bigger stack frame.
|
||||
*/
|
||||
static noinline
|
||||
struct avc_node *avc_compute_av(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid,
|
||||
u16 tclass, struct av_decision *avd,
|
||||
struct avc_xperms_node *xp_node)
|
||||
static noinline void avc_compute_av(u32 ssid, u32 tsid, u16 tclass,
|
||||
struct av_decision *avd,
|
||||
struct avc_xperms_node *xp_node)
|
||||
{
|
||||
rcu_read_unlock();
|
||||
INIT_LIST_HEAD(&xp_node->xpd_head);
|
||||
security_compute_av(state, ssid, tsid, tclass, avd, &xp_node->xp);
|
||||
rcu_read_lock();
|
||||
return avc_insert(state->avc, ssid, tsid, tclass, avd, xp_node);
|
||||
security_compute_av(ssid, tsid, tclass, avd, &xp_node->xp);
|
||||
avc_insert(ssid, tsid, tclass, avd, xp_node);
|
||||
}
|
||||
|
||||
static noinline int avc_denied(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid,
|
||||
static noinline int avc_denied(u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 requested,
|
||||
u8 driver, u8 xperm, unsigned int flags,
|
||||
struct av_decision *avd)
|
||||
@@ -1027,11 +1007,11 @@ static noinline int avc_denied(struct selinux_state *state,
|
||||
if (flags & AVC_STRICT)
|
||||
return -EACCES;
|
||||
|
||||
if (enforcing_enabled(state) &&
|
||||
if (enforcing_enabled() &&
|
||||
!(avd->flags & AVD_FLAGS_PERMISSIVE))
|
||||
return -EACCES;
|
||||
|
||||
avc_update_node(state->avc, AVC_CALLBACK_GRANT, requested, driver,
|
||||
avc_update_node(AVC_CALLBACK_GRANT, requested, driver,
|
||||
xperm, ssid, tsid, tclass, avd->seqno, NULL, flags);
|
||||
return 0;
|
||||
}
|
||||
@@ -1043,8 +1023,7 @@ static noinline int avc_denied(struct selinux_state *state,
|
||||
* as-is the case with ioctls, then multiple may be chained together and the
|
||||
* driver field is used to specify which set contains the permission.
|
||||
*/
|
||||
int avc_has_extended_perms(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid, u16 tclass, u32 requested,
|
||||
int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested,
|
||||
u8 driver, u8 xperm, struct common_audit_data *ad)
|
||||
{
|
||||
struct avc_node *node;
|
||||
@@ -1065,9 +1044,9 @@ int avc_has_extended_perms(struct selinux_state *state,
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
node = avc_lookup(state->avc, ssid, tsid, tclass);
|
||||
node = avc_lookup(ssid, tsid, tclass);
|
||||
if (unlikely(!node)) {
|
||||
avc_compute_av(state, ssid, tsid, tclass, &avd, xp_node);
|
||||
avc_compute_av(ssid, tsid, tclass, &avd, xp_node);
|
||||
} else {
|
||||
memcpy(&avd, &node->ae.avd, sizeof(avd));
|
||||
xp_node = node->ae.xp_node;
|
||||
@@ -1091,10 +1070,10 @@ int avc_has_extended_perms(struct selinux_state *state,
|
||||
goto decision;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
security_compute_xperms_decision(state, ssid, tsid, tclass,
|
||||
security_compute_xperms_decision(ssid, tsid, tclass,
|
||||
driver, &local_xpd);
|
||||
rcu_read_lock();
|
||||
avc_update_node(state->avc, AVC_CALLBACK_ADD_XPERMS, requested,
|
||||
avc_update_node(AVC_CALLBACK_ADD_XPERMS, requested,
|
||||
driver, xperm, ssid, tsid, tclass, avd.seqno,
|
||||
&local_xpd, 0);
|
||||
} else {
|
||||
@@ -1108,21 +1087,48 @@ int avc_has_extended_perms(struct selinux_state *state,
|
||||
decision:
|
||||
denied = requested & ~(avd.allowed);
|
||||
if (unlikely(denied))
|
||||
rc = avc_denied(state, ssid, tsid, tclass, requested,
|
||||
rc = avc_denied(ssid, tsid, tclass, requested,
|
||||
driver, xperm, AVC_EXTENDED_PERMS, &avd);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
rc2 = avc_xperms_audit(state, ssid, tsid, tclass, requested,
|
||||
rc2 = avc_xperms_audit(ssid, tsid, tclass, requested,
|
||||
&avd, xpd, xperm, rc, ad);
|
||||
if (rc2)
|
||||
return rc2;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* avc_perm_nonode - Add an entry to the AVC
|
||||
* @ssid: subject
|
||||
* @tsid: object/target
|
||||
* @tclass: object class
|
||||
* @requested: requested permissions
|
||||
* @flags: AVC flags
|
||||
* @avd: access vector decision
|
||||
*
|
||||
* This is the "we have no node" part of avc_has_perm_noaudit(), which is
|
||||
* unlikely and needs extra stack space for the new node that we generate, so
|
||||
* don't inline it.
|
||||
*/
|
||||
static noinline int avc_perm_nonode(u32 ssid, u32 tsid, u16 tclass,
|
||||
u32 requested, unsigned int flags,
|
||||
struct av_decision *avd)
|
||||
{
|
||||
u32 denied;
|
||||
struct avc_xperms_node xp_node;
|
||||
|
||||
avc_compute_av(ssid, tsid, tclass, avd, &xp_node);
|
||||
denied = requested & ~(avd->allowed);
|
||||
if (unlikely(denied))
|
||||
return avc_denied(ssid, tsid, tclass, requested, 0, 0,
|
||||
flags, avd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* avc_has_perm_noaudit - Check permissions but perform no auditing.
|
||||
* @state: SELinux state
|
||||
* @ssid: source security identifier
|
||||
* @tsid: target security identifier
|
||||
* @tclass: target security class
|
||||
@@ -1141,40 +1147,36 @@ decision:
|
||||
* auditing, e.g. in cases where a lock must be held for the check but
|
||||
* should be released for the auditing.
|
||||
*/
|
||||
inline int avc_has_perm_noaudit(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid,
|
||||
inline int avc_has_perm_noaudit(u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 requested,
|
||||
unsigned int flags,
|
||||
struct av_decision *avd)
|
||||
{
|
||||
struct avc_node *node;
|
||||
struct avc_xperms_node xp_node;
|
||||
int rc = 0;
|
||||
u32 denied;
|
||||
struct avc_node *node;
|
||||
|
||||
if (WARN_ON(!requested))
|
||||
return -EACCES;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
node = avc_lookup(state->avc, ssid, tsid, tclass);
|
||||
if (unlikely(!node))
|
||||
avc_compute_av(state, ssid, tsid, tclass, avd, &xp_node);
|
||||
else
|
||||
memcpy(avd, &node->ae.avd, sizeof(*avd));
|
||||
|
||||
denied = requested & ~(avd->allowed);
|
||||
if (unlikely(denied))
|
||||
rc = avc_denied(state, ssid, tsid, tclass, requested, 0, 0,
|
||||
flags, avd);
|
||||
|
||||
node = avc_lookup(ssid, tsid, tclass);
|
||||
if (unlikely(!node)) {
|
||||
rcu_read_unlock();
|
||||
return avc_perm_nonode(ssid, tsid, tclass, requested,
|
||||
flags, avd);
|
||||
}
|
||||
denied = requested & ~node->ae.avd.allowed;
|
||||
memcpy(avd, &node->ae.avd, sizeof(*avd));
|
||||
rcu_read_unlock();
|
||||
return rc;
|
||||
|
||||
if (unlikely(denied))
|
||||
return avc_denied(ssid, tsid, tclass, requested, 0, 0,
|
||||
flags, avd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* avc_has_perm - Check permissions and perform any appropriate auditing.
|
||||
* @state: SELinux state
|
||||
* @ssid: source security identifier
|
||||
* @tsid: target security identifier
|
||||
* @tclass: target security class
|
||||
@@ -1189,25 +1191,25 @@ inline int avc_has_perm_noaudit(struct selinux_state *state,
|
||||
* permissions are granted, -%EACCES if any permissions are denied, or
|
||||
* another -errno upon other errors.
|
||||
*/
|
||||
int avc_has_perm(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass,
|
||||
int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
|
||||
u32 requested, struct common_audit_data *auditdata)
|
||||
{
|
||||
struct av_decision avd;
|
||||
int rc, rc2;
|
||||
|
||||
rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested, 0,
|
||||
rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0,
|
||||
&avd);
|
||||
|
||||
rc2 = avc_audit(state, ssid, tsid, tclass, requested, &avd, rc,
|
||||
rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc,
|
||||
auditdata);
|
||||
if (rc2)
|
||||
return rc2;
|
||||
return rc;
|
||||
}
|
||||
|
||||
u32 avc_policy_seqno(struct selinux_state *state)
|
||||
u32 avc_policy_seqno(void)
|
||||
{
|
||||
return state->avc->avc_cache.latest_notif;
|
||||
return selinux_avc.avc_cache.latest_notif;
|
||||
}
|
||||
|
||||
void avc_disable(void)
|
||||
@@ -1224,7 +1226,7 @@ void avc_disable(void)
|
||||
* the cache and get that memory back.
|
||||
*/
|
||||
if (avc_node_cachep) {
|
||||
avc_flush(selinux_state.avc);
|
||||
avc_flush();
|
||||
/* kmem_cache_destroy(avc_node_cachep); */
|
||||
}
|
||||
}
|
||||
|
||||
+207
-405
File diff suppressed because it is too large
Load Diff
@@ -141,7 +141,7 @@ static int sel_ib_pkey_sid_slow(u64 subnet_prefix, u16 pkey_num, u32 *sid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = security_ib_pkey_sid(&selinux_state, subnet_prefix, pkey_num,
|
||||
ret = security_ib_pkey_sid(subnet_prefix, pkey_num,
|
||||
sid);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
+16
-21
@@ -15,12 +15,10 @@
|
||||
/*
|
||||
* selinux_ima_collect_state - Read selinux configuration settings
|
||||
*
|
||||
* @state: selinux_state
|
||||
*
|
||||
* On success returns the configuration settings string.
|
||||
* On error, returns NULL.
|
||||
*/
|
||||
static char *selinux_ima_collect_state(struct selinux_state *state)
|
||||
static char *selinux_ima_collect_state(void)
|
||||
{
|
||||
const char *on = "=1;", *off = "=0;";
|
||||
char *buf;
|
||||
@@ -39,26 +37,27 @@ static char *selinux_ima_collect_state(struct selinux_state *state)
|
||||
rc = strscpy(buf, "initialized", buf_len);
|
||||
WARN_ON(rc < 0);
|
||||
|
||||
rc = strlcat(buf, selinux_initialized(state) ? on : off, buf_len);
|
||||
rc = strlcat(buf, selinux_initialized() ? on : off, buf_len);
|
||||
WARN_ON(rc >= buf_len);
|
||||
|
||||
rc = strlcat(buf, "enforcing", buf_len);
|
||||
WARN_ON(rc >= buf_len);
|
||||
|
||||
rc = strlcat(buf, enforcing_enabled(state) ? on : off, buf_len);
|
||||
rc = strlcat(buf, enforcing_enabled() ? on : off, buf_len);
|
||||
WARN_ON(rc >= buf_len);
|
||||
|
||||
rc = strlcat(buf, "checkreqprot", buf_len);
|
||||
WARN_ON(rc >= buf_len);
|
||||
|
||||
rc = strlcat(buf, checkreqprot_get(state) ? on : off, buf_len);
|
||||
rc = strlcat(buf, checkreqprot_get() ? on : off, buf_len);
|
||||
WARN_ON(rc >= buf_len);
|
||||
|
||||
for (i = 0; i < __POLICYDB_CAP_MAX; i++) {
|
||||
rc = strlcat(buf, selinux_policycap_names[i], buf_len);
|
||||
WARN_ON(rc >= buf_len);
|
||||
|
||||
rc = strlcat(buf, state->policycap[i] ? on : off, buf_len);
|
||||
rc = strlcat(buf, selinux_state.policycap[i] ? on : off,
|
||||
buf_len);
|
||||
WARN_ON(rc >= buf_len);
|
||||
}
|
||||
|
||||
@@ -67,19 +66,17 @@ static char *selinux_ima_collect_state(struct selinux_state *state)
|
||||
|
||||
/*
|
||||
* selinux_ima_measure_state_locked - Measure SELinux state and hash of policy
|
||||
*
|
||||
* @state: selinux state struct
|
||||
*/
|
||||
void selinux_ima_measure_state_locked(struct selinux_state *state)
|
||||
void selinux_ima_measure_state_locked(void)
|
||||
{
|
||||
char *state_str = NULL;
|
||||
void *policy = NULL;
|
||||
size_t policy_len;
|
||||
int rc = 0;
|
||||
|
||||
lockdep_assert_held(&state->policy_mutex);
|
||||
lockdep_assert_held(&selinux_state.policy_mutex);
|
||||
|
||||
state_str = selinux_ima_collect_state(state);
|
||||
state_str = selinux_ima_collect_state();
|
||||
if (!state_str) {
|
||||
pr_err("SELinux: %s: failed to read state.\n", __func__);
|
||||
return;
|
||||
@@ -94,10 +91,10 @@ void selinux_ima_measure_state_locked(struct selinux_state *state)
|
||||
/*
|
||||
* Measure SELinux policy only after initialization is completed.
|
||||
*/
|
||||
if (!selinux_initialized(state))
|
||||
if (!selinux_initialized())
|
||||
return;
|
||||
|
||||
rc = security_read_state_kernel(state, &policy, &policy_len);
|
||||
rc = security_read_state_kernel(&policy, &policy_len);
|
||||
if (rc) {
|
||||
pr_err("SELinux: %s: failed to read policy %d.\n", __func__, rc);
|
||||
return;
|
||||
@@ -112,14 +109,12 @@ void selinux_ima_measure_state_locked(struct selinux_state *state)
|
||||
|
||||
/*
|
||||
* selinux_ima_measure_state - Measure SELinux state and hash of policy
|
||||
*
|
||||
* @state: selinux state struct
|
||||
*/
|
||||
void selinux_ima_measure_state(struct selinux_state *state)
|
||||
void selinux_ima_measure_state(void)
|
||||
{
|
||||
lockdep_assert_not_held(&state->policy_mutex);
|
||||
lockdep_assert_not_held(&selinux_state.policy_mutex);
|
||||
|
||||
mutex_lock(&state->policy_mutex);
|
||||
selinux_ima_measure_state_locked(state);
|
||||
mutex_unlock(&state->policy_mutex);
|
||||
mutex_lock(&selinux_state.policy_mutex);
|
||||
selinux_ima_measure_state_locked();
|
||||
mutex_unlock(&selinux_state.policy_mutex);
|
||||
}
|
||||
|
||||
@@ -52,7 +52,6 @@ struct selinux_audit_data {
|
||||
u32 audited;
|
||||
u32 denied;
|
||||
int result;
|
||||
struct selinux_state *state;
|
||||
} __randomize_layout;
|
||||
|
||||
/*
|
||||
@@ -97,14 +96,12 @@ static inline u32 avc_audit_required(u32 requested,
|
||||
return audited;
|
||||
}
|
||||
|
||||
int slow_avc_audit(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid, u16 tclass,
|
||||
int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
|
||||
u32 requested, u32 audited, u32 denied, int result,
|
||||
struct common_audit_data *a);
|
||||
|
||||
/**
|
||||
* avc_audit - Audit the granting or denial of permissions.
|
||||
* @state: SELinux state
|
||||
* @ssid: source security identifier
|
||||
* @tsid: target security identifier
|
||||
* @tclass: target security class
|
||||
@@ -122,8 +119,7 @@ int slow_avc_audit(struct selinux_state *state,
|
||||
* be performed under a lock, to allow the lock to be released
|
||||
* before calling the auditing code.
|
||||
*/
|
||||
static inline int avc_audit(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid,
|
||||
static inline int avc_audit(u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 requested,
|
||||
struct av_decision *avd,
|
||||
int result,
|
||||
@@ -133,30 +129,27 @@ static inline int avc_audit(struct selinux_state *state,
|
||||
audited = avc_audit_required(requested, avd, result, 0, &denied);
|
||||
if (likely(!audited))
|
||||
return 0;
|
||||
return slow_avc_audit(state, ssid, tsid, tclass,
|
||||
return slow_avc_audit(ssid, tsid, tclass,
|
||||
requested, audited, denied, result,
|
||||
a);
|
||||
}
|
||||
|
||||
#define AVC_STRICT 1 /* Ignore permissive mode. */
|
||||
#define AVC_EXTENDED_PERMS 2 /* update extended permissions */
|
||||
int avc_has_perm_noaudit(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid,
|
||||
int avc_has_perm_noaudit(u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 requested,
|
||||
unsigned flags,
|
||||
struct av_decision *avd);
|
||||
|
||||
int avc_has_perm(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid,
|
||||
int avc_has_perm(u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 requested,
|
||||
struct common_audit_data *auditdata);
|
||||
|
||||
int avc_has_extended_perms(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid, u16 tclass, u32 requested,
|
||||
int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested,
|
||||
u8 driver, u8 perm, struct common_audit_data *ad);
|
||||
|
||||
|
||||
u32 avc_policy_seqno(struct selinux_state *state);
|
||||
u32 avc_policy_seqno(void);
|
||||
|
||||
#define AVC_CALLBACK_GRANT 1
|
||||
#define AVC_CALLBACK_TRY_REVOKE 2
|
||||
@@ -171,11 +164,9 @@ u32 avc_policy_seqno(struct selinux_state *state);
|
||||
int avc_add_callback(int (*callback)(u32 event), u32 events);
|
||||
|
||||
/* Exported to selinuxfs */
|
||||
struct selinux_avc;
|
||||
int avc_get_hash_stats(struct selinux_avc *avc, char *page);
|
||||
unsigned int avc_get_cache_threshold(struct selinux_avc *avc);
|
||||
void avc_set_cache_threshold(struct selinux_avc *avc,
|
||||
unsigned int cache_threshold);
|
||||
int avc_get_hash_stats(char *page);
|
||||
unsigned int avc_get_cache_threshold(void);
|
||||
void avc_set_cache_threshold(unsigned int cache_threshold);
|
||||
|
||||
/* Attempt to free avc node cache */
|
||||
void avc_disable(void);
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct selinux_avc;
|
||||
int avc_ss_reset(struct selinux_avc *avc, u32 seqno);
|
||||
int avc_ss_reset(u32 seqno);
|
||||
|
||||
/* Class/perm mapping support */
|
||||
struct security_class_mapping {
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
int security_get_bools(struct selinux_policy *policy,
|
||||
u32 *len, char ***names, int **values);
|
||||
|
||||
int security_set_bools(struct selinux_state *state, u32 len, int *values);
|
||||
int security_set_bools(u32 len, int *values);
|
||||
|
||||
int security_get_bool_value(struct selinux_state *state, u32 index);
|
||||
int security_get_bool_value(u32 index);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,15 +14,13 @@
|
||||
#include "security.h"
|
||||
|
||||
#ifdef CONFIG_IMA
|
||||
extern void selinux_ima_measure_state(struct selinux_state *selinux_state);
|
||||
extern void selinux_ima_measure_state_locked(
|
||||
struct selinux_state *selinux_state);
|
||||
extern void selinux_ima_measure_state(void);
|
||||
extern void selinux_ima_measure_state_locked(void);
|
||||
#else
|
||||
static inline void selinux_ima_measure_state(struct selinux_state *selinux_state)
|
||||
static inline void selinux_ima_measure_state(void)
|
||||
{
|
||||
}
|
||||
static inline void selinux_ima_measure_state_locked(
|
||||
struct selinux_state *selinux_state)
|
||||
static inline void selinux_ima_measure_state_locked(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -86,17 +86,12 @@ extern int selinux_enabled_boot;
|
||||
/* limitation of boundary depth */
|
||||
#define POLICYDB_BOUNDS_MAXDEPTH 4
|
||||
|
||||
struct selinux_avc;
|
||||
struct selinux_policy;
|
||||
|
||||
struct selinux_state {
|
||||
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
|
||||
bool disabled;
|
||||
#endif
|
||||
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
|
||||
bool enforcing;
|
||||
#endif
|
||||
bool checkreqprot;
|
||||
bool initialized;
|
||||
bool policycap[__POLICYDB_CAP_MAX];
|
||||
bool android_netlink_route;
|
||||
@@ -105,77 +100,53 @@ struct selinux_state {
|
||||
struct page *status_page;
|
||||
struct mutex status_lock;
|
||||
|
||||
struct selinux_avc *avc;
|
||||
struct selinux_policy __rcu *policy;
|
||||
struct mutex policy_mutex;
|
||||
} __randomize_layout;
|
||||
|
||||
void selinux_avc_init(struct selinux_avc **avc);
|
||||
void selinux_avc_init(void);
|
||||
|
||||
extern struct selinux_state selinux_state;
|
||||
|
||||
static inline bool selinux_initialized(const struct selinux_state *state)
|
||||
static inline bool selinux_initialized(void)
|
||||
{
|
||||
/* do a synchronized load to avoid race conditions */
|
||||
return smp_load_acquire(&state->initialized);
|
||||
return smp_load_acquire(&selinux_state.initialized);
|
||||
}
|
||||
|
||||
static inline void selinux_mark_initialized(struct selinux_state *state)
|
||||
static inline void selinux_mark_initialized(void)
|
||||
{
|
||||
/* do a synchronized write to avoid race conditions */
|
||||
smp_store_release(&state->initialized, true);
|
||||
smp_store_release(&selinux_state.initialized, true);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
|
||||
static inline bool enforcing_enabled(struct selinux_state *state)
|
||||
static inline bool enforcing_enabled(void)
|
||||
{
|
||||
return READ_ONCE(state->enforcing);
|
||||
return READ_ONCE(selinux_state.enforcing);
|
||||
}
|
||||
|
||||
static inline void enforcing_set(struct selinux_state *state, bool value)
|
||||
static inline void enforcing_set(bool value)
|
||||
{
|
||||
WRITE_ONCE(state->enforcing, value);
|
||||
WRITE_ONCE(selinux_state.enforcing, value);
|
||||
}
|
||||
#else
|
||||
static inline bool enforcing_enabled(struct selinux_state *state)
|
||||
static inline bool enforcing_enabled(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void enforcing_set(struct selinux_state *state, bool value)
|
||||
static inline void enforcing_set(bool value)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline bool checkreqprot_get(const struct selinux_state *state)
|
||||
static inline bool checkreqprot_get(void)
|
||||
{
|
||||
return READ_ONCE(state->checkreqprot);
|
||||
/* non-zero/true checkreqprot values are no longer supported */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void checkreqprot_set(struct selinux_state *state, bool value)
|
||||
{
|
||||
if (value)
|
||||
pr_err("SELinux: https://github.com/SELinuxProject/selinux-kernel/wiki/DEPRECATE-checkreqprot\n");
|
||||
WRITE_ONCE(state->checkreqprot, value);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
|
||||
static inline bool selinux_disabled(struct selinux_state *state)
|
||||
{
|
||||
return READ_ONCE(state->disabled);
|
||||
}
|
||||
|
||||
static inline void selinux_mark_disabled(struct selinux_state *state)
|
||||
{
|
||||
WRITE_ONCE(state->disabled, true);
|
||||
}
|
||||
#else
|
||||
static inline bool selinux_disabled(struct selinux_state *state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline bool selinux_policycap_netpeer(void)
|
||||
{
|
||||
struct selinux_state *state = &selinux_state;
|
||||
@@ -253,20 +224,14 @@ struct selinux_load_state {
|
||||
struct selinux_policy_convert_data *convert_data;
|
||||
};
|
||||
|
||||
int security_mls_enabled(struct selinux_state *state);
|
||||
int security_load_policy(struct selinux_state *state,
|
||||
void *data, size_t len,
|
||||
int security_mls_enabled(void);
|
||||
int security_load_policy(void *data, size_t len,
|
||||
struct selinux_load_state *load_state);
|
||||
void selinux_policy_commit(struct selinux_state *state,
|
||||
struct selinux_load_state *load_state);
|
||||
void selinux_policy_cancel(struct selinux_state *state,
|
||||
struct selinux_load_state *load_state);
|
||||
int security_read_policy(struct selinux_state *state,
|
||||
void **data, size_t *len);
|
||||
int security_read_state_kernel(struct selinux_state *state,
|
||||
void **data, size_t *len);
|
||||
int security_policycap_supported(struct selinux_state *state,
|
||||
unsigned int req_cap);
|
||||
void selinux_policy_commit(struct selinux_load_state *load_state);
|
||||
void selinux_policy_cancel(struct selinux_load_state *load_state);
|
||||
int security_read_policy(void **data, size_t *len);
|
||||
int security_read_state_kernel(void **data, size_t *len);
|
||||
int security_policycap_supported(unsigned int req_cap);
|
||||
|
||||
#define SEL_VEC_MAX 32
|
||||
struct av_decision {
|
||||
@@ -303,94 +268,68 @@ struct extended_perms {
|
||||
/* definitions of av_decision.flags */
|
||||
#define AVD_FLAGS_PERMISSIVE 0x0001
|
||||
|
||||
void security_compute_av(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid,
|
||||
void security_compute_av(u32 ssid, u32 tsid,
|
||||
u16 tclass, struct av_decision *avd,
|
||||
struct extended_perms *xperms);
|
||||
|
||||
void security_compute_xperms_decision(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid, u16 tclass,
|
||||
void security_compute_xperms_decision(u32 ssid, u32 tsid, u16 tclass,
|
||||
u8 driver,
|
||||
struct extended_perms_decision *xpermd);
|
||||
|
||||
void security_compute_av_user(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid,
|
||||
void security_compute_av_user(u32 ssid, u32 tsid,
|
||||
u16 tclass, struct av_decision *avd);
|
||||
|
||||
int security_transition_sid(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid, u16 tclass,
|
||||
int security_transition_sid(u32 ssid, u32 tsid, u16 tclass,
|
||||
const struct qstr *qstr, u32 *out_sid);
|
||||
|
||||
int security_transition_sid_user(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid, u16 tclass,
|
||||
int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass,
|
||||
const char *objname, u32 *out_sid);
|
||||
|
||||
int security_member_sid(struct selinux_state *state, u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 *out_sid);
|
||||
int security_member_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid);
|
||||
|
||||
int security_change_sid(struct selinux_state *state, u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 *out_sid);
|
||||
int security_change_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid);
|
||||
|
||||
int security_sid_to_context(struct selinux_state *state, u32 sid,
|
||||
char **scontext, u32 *scontext_len);
|
||||
int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len);
|
||||
|
||||
int security_sid_to_context_force(struct selinux_state *state,
|
||||
u32 sid, char **scontext, u32 *scontext_len);
|
||||
int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len);
|
||||
|
||||
int security_sid_to_context_inval(struct selinux_state *state,
|
||||
u32 sid, char **scontext, u32 *scontext_len);
|
||||
int security_sid_to_context_inval(u32 sid, char **scontext, u32 *scontext_len);
|
||||
|
||||
int security_context_to_sid(struct selinux_state *state,
|
||||
const char *scontext, u32 scontext_len,
|
||||
int security_context_to_sid(const char *scontext, u32 scontext_len,
|
||||
u32 *out_sid, gfp_t gfp);
|
||||
|
||||
int security_context_str_to_sid(struct selinux_state *state,
|
||||
const char *scontext, u32 *out_sid, gfp_t gfp);
|
||||
int security_context_str_to_sid(const char *scontext, u32 *out_sid, gfp_t gfp);
|
||||
|
||||
int security_context_to_sid_default(struct selinux_state *state,
|
||||
const char *scontext, u32 scontext_len,
|
||||
int security_context_to_sid_default(const char *scontext, u32 scontext_len,
|
||||
u32 *out_sid, u32 def_sid, gfp_t gfp_flags);
|
||||
|
||||
int security_context_to_sid_force(struct selinux_state *state,
|
||||
const char *scontext, u32 scontext_len,
|
||||
int security_context_to_sid_force(const char *scontext, u32 scontext_len,
|
||||
u32 *sid);
|
||||
|
||||
int security_get_user_sids(struct selinux_state *state,
|
||||
u32 callsid, char *username,
|
||||
u32 **sids, u32 *nel);
|
||||
int security_get_user_sids(u32 callsid, char *username, u32 **sids, u32 *nel);
|
||||
|
||||
int security_port_sid(struct selinux_state *state,
|
||||
u8 protocol, u16 port, u32 *out_sid);
|
||||
int security_port_sid(u8 protocol, u16 port, u32 *out_sid);
|
||||
|
||||
int security_ib_pkey_sid(struct selinux_state *state,
|
||||
u64 subnet_prefix, u16 pkey_num, u32 *out_sid);
|
||||
int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid);
|
||||
|
||||
int security_ib_endport_sid(struct selinux_state *state,
|
||||
const char *dev_name, u8 port_num, u32 *out_sid);
|
||||
int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid);
|
||||
|
||||
int security_netif_sid(struct selinux_state *state,
|
||||
char *name, u32 *if_sid);
|
||||
int security_netif_sid(char *name, u32 *if_sid);
|
||||
|
||||
int security_node_sid(struct selinux_state *state,
|
||||
u16 domain, void *addr, u32 addrlen,
|
||||
int security_node_sid(u16 domain, void *addr, u32 addrlen,
|
||||
u32 *out_sid);
|
||||
|
||||
int security_validate_transition(struct selinux_state *state,
|
||||
u32 oldsid, u32 newsid, u32 tasksid,
|
||||
int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
|
||||
u16 tclass);
|
||||
|
||||
int security_validate_transition_user(struct selinux_state *state,
|
||||
u32 oldsid, u32 newsid, u32 tasksid,
|
||||
int security_validate_transition_user(u32 oldsid, u32 newsid, u32 tasksid,
|
||||
u16 tclass);
|
||||
|
||||
int security_bounded_transition(struct selinux_state *state,
|
||||
u32 oldsid, u32 newsid);
|
||||
int security_bounded_transition(u32 oldsid, u32 newsid);
|
||||
|
||||
int security_sid_mls_copy(struct selinux_state *state,
|
||||
u32 sid, u32 mls_sid, u32 *new_sid);
|
||||
int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
|
||||
|
||||
int security_net_peersid_resolve(struct selinux_state *state,
|
||||
u32 nlbl_sid, u32 nlbl_type,
|
||||
int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
|
||||
u32 xfrm_sid,
|
||||
u32 *peer_sid);
|
||||
|
||||
@@ -398,8 +337,8 @@ int security_get_classes(struct selinux_policy *policy,
|
||||
char ***classes, int *nclasses);
|
||||
int security_get_permissions(struct selinux_policy *policy,
|
||||
char *class, char ***perms, int *nperms);
|
||||
int security_get_reject_unknown(struct selinux_state *state);
|
||||
int security_get_allow_unknown(struct selinux_state *state);
|
||||
int security_get_reject_unknown(void);
|
||||
int security_get_allow_unknown(void);
|
||||
|
||||
#define SECURITY_FS_USE_XATTR 1 /* use xattr */
|
||||
#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */
|
||||
@@ -410,10 +349,9 @@ int security_get_allow_unknown(struct selinux_state *state);
|
||||
#define SECURITY_FS_USE_NATIVE 7 /* use native label support */
|
||||
#define SECURITY_FS_USE_MAX 7 /* Highest SECURITY_FS_USE_XXX */
|
||||
|
||||
int security_fs_use(struct selinux_state *state, struct super_block *sb);
|
||||
int security_fs_use(struct super_block *sb);
|
||||
|
||||
int security_genfs_sid(struct selinux_state *state,
|
||||
const char *fstype, const char *path, u16 sclass,
|
||||
int security_genfs_sid(const char *fstype, const char *path, u16 sclass,
|
||||
u32 *sid);
|
||||
|
||||
int selinux_policy_genfs_sid(struct selinux_policy *policy,
|
||||
@@ -421,23 +359,19 @@ int selinux_policy_genfs_sid(struct selinux_policy *policy,
|
||||
u32 *sid);
|
||||
|
||||
#ifdef CONFIG_NETLABEL
|
||||
int security_netlbl_secattr_to_sid(struct selinux_state *state,
|
||||
struct netlbl_lsm_secattr *secattr,
|
||||
int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
|
||||
u32 *sid);
|
||||
|
||||
int security_netlbl_sid_to_secattr(struct selinux_state *state,
|
||||
u32 sid,
|
||||
int security_netlbl_sid_to_secattr(u32 sid,
|
||||
struct netlbl_lsm_secattr *secattr);
|
||||
#else
|
||||
static inline int security_netlbl_secattr_to_sid(struct selinux_state *state,
|
||||
struct netlbl_lsm_secattr *secattr,
|
||||
static inline int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
|
||||
u32 *sid)
|
||||
{
|
||||
return -EIDRM;
|
||||
}
|
||||
|
||||
static inline int security_netlbl_sid_to_secattr(struct selinux_state *state,
|
||||
u32 sid,
|
||||
static inline int security_netlbl_sid_to_secattr(u32 sid,
|
||||
struct netlbl_lsm_secattr *secattr)
|
||||
{
|
||||
return -ENOENT;
|
||||
@@ -449,7 +383,7 @@ const char *security_get_initial_sid_context(u32 sid);
|
||||
/*
|
||||
* status notifier using mmap interface
|
||||
*/
|
||||
extern struct page *selinux_kernel_status_page(struct selinux_state *state);
|
||||
extern struct page *selinux_kernel_status_page(void);
|
||||
|
||||
#define SELINUX_KERNEL_STATUS_VERSION 1
|
||||
struct selinux_kernel_status {
|
||||
@@ -463,12 +397,9 @@ struct selinux_kernel_status {
|
||||
*/
|
||||
} __packed;
|
||||
|
||||
extern void selinux_status_update_setenforce(struct selinux_state *state,
|
||||
int enforcing);
|
||||
extern void selinux_status_update_policyload(struct selinux_state *state,
|
||||
int seqno);
|
||||
extern void selinux_status_update_setenforce(int enforcing);
|
||||
extern void selinux_status_update_policyload(int seqno);
|
||||
extern void selinux_complete_init(void);
|
||||
extern int selinux_disable(struct selinux_state *state);
|
||||
extern void exit_sel_fs(void);
|
||||
extern struct path selinux_null;
|
||||
extern void selnl_notify_setenforce(int val);
|
||||
@@ -478,7 +409,7 @@ extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
|
||||
extern void avtab_cache_init(void);
|
||||
extern void ebitmap_cache_init(void);
|
||||
extern void hashtab_cache_init(void);
|
||||
extern int security_sidtab_hash_stats(struct selinux_state *state, char *page);
|
||||
extern int security_sidtab_hash_stats(char *page);
|
||||
extern void selinux_nlmsg_init(void);
|
||||
|
||||
#endif /* _SELINUX_SECURITY_H_ */
|
||||
|
||||
@@ -153,7 +153,7 @@ static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = security_netif_sid(&selinux_state, dev->name, sid);
|
||||
ret = security_netif_sid(dev->name, sid);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
new = kzalloc(sizeof(*new), GFP_ATOMIC);
|
||||
|
||||
@@ -46,7 +46,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = security_netlbl_secattr_to_sid(&selinux_state, secattr, sid);
|
||||
rc = security_netlbl_secattr_to_sid(secattr, sid);
|
||||
if (rc == 0 &&
|
||||
(secattr->flags & NETLBL_SECATTR_CACHEABLE) &&
|
||||
(secattr->flags & NETLBL_SECATTR_CACHE))
|
||||
@@ -77,8 +77,7 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
|
||||
secattr = netlbl_secattr_alloc(GFP_ATOMIC);
|
||||
if (secattr == NULL)
|
||||
return NULL;
|
||||
rc = security_netlbl_sid_to_secattr(&selinux_state, sksec->sid,
|
||||
secattr);
|
||||
rc = security_netlbl_sid_to_secattr(sksec->sid, secattr);
|
||||
if (rc != 0) {
|
||||
netlbl_secattr_free(secattr);
|
||||
return NULL;
|
||||
@@ -245,8 +244,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
|
||||
if (secattr == NULL) {
|
||||
secattr = &secattr_storage;
|
||||
netlbl_secattr_init(secattr);
|
||||
rc = security_netlbl_sid_to_secattr(&selinux_state, sid,
|
||||
secattr);
|
||||
rc = security_netlbl_sid_to_secattr(sid, secattr);
|
||||
if (rc != 0)
|
||||
goto skbuff_setsid_return;
|
||||
}
|
||||
@@ -283,8 +281,7 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_association *asoc,
|
||||
return 0;
|
||||
|
||||
netlbl_secattr_init(&secattr);
|
||||
rc = security_netlbl_sid_to_secattr(&selinux_state,
|
||||
asoc->secid, &secattr);
|
||||
rc = security_netlbl_sid_to_secattr(asoc->secid, &secattr);
|
||||
if (rc != 0)
|
||||
goto assoc_request_return;
|
||||
|
||||
@@ -332,8 +329,7 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
|
||||
return 0;
|
||||
|
||||
netlbl_secattr_init(&secattr);
|
||||
rc = security_netlbl_sid_to_secattr(&selinux_state, req->secid,
|
||||
&secattr);
|
||||
rc = security_netlbl_sid_to_secattr(req->secid, &secattr);
|
||||
if (rc != 0)
|
||||
goto inet_conn_request_return;
|
||||
rc = netlbl_req_setattr(req, &secattr);
|
||||
@@ -463,8 +459,7 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
|
||||
perm = RAWIP_SOCKET__RECVFROM;
|
||||
}
|
||||
|
||||
rc = avc_has_perm(&selinux_state,
|
||||
sksec->sid, nlbl_sid, sksec->sclass, perm, ad);
|
||||
rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad);
|
||||
if (rc == 0)
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -204,13 +204,13 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
|
||||
new = kzalloc(sizeof(*new), GFP_ATOMIC);
|
||||
switch (family) {
|
||||
case PF_INET:
|
||||
ret = security_node_sid(&selinux_state, PF_INET,
|
||||
ret = security_node_sid(PF_INET,
|
||||
addr, sizeof(struct in_addr), sid);
|
||||
if (new)
|
||||
new->nsec.addr.ipv4 = *(__be32 *)addr;
|
||||
break;
|
||||
case PF_INET6:
|
||||
ret = security_node_sid(&selinux_state, PF_INET6,
|
||||
ret = security_node_sid(PF_INET6,
|
||||
addr, sizeof(struct in6_addr), sid);
|
||||
if (new)
|
||||
new->nsec.addr.ipv6 = *(struct in6_addr *)addr;
|
||||
|
||||
@@ -148,7 +148,7 @@ static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = security_port_sid(&selinux_state, protocol, pnum, sid);
|
||||
ret = security_port_sid(protocol, pnum, sid);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
new = kzalloc(sizeof(*new), GFP_ATOMIC);
|
||||
|
||||
+86
-172
@@ -77,7 +77,6 @@ struct selinux_fs_info {
|
||||
bool policy_opened;
|
||||
struct dentry *policycap_dir;
|
||||
unsigned long last_ino;
|
||||
struct selinux_state *state;
|
||||
struct super_block *sb;
|
||||
};
|
||||
|
||||
@@ -90,7 +89,6 @@ static int selinux_fs_info_create(struct super_block *sb)
|
||||
return -ENOMEM;
|
||||
|
||||
fsi->last_ino = SEL_INO_NEXT - 1;
|
||||
fsi->state = &selinux_state;
|
||||
fsi->sb = sb;
|
||||
sb->s_fs_info = fsi;
|
||||
return 0;
|
||||
@@ -125,12 +123,11 @@ static void selinux_fs_info_free(struct super_block *sb)
|
||||
static ssize_t sel_read_enforce(struct file *filp, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
|
||||
char tmpbuf[TMPBUFLEN];
|
||||
ssize_t length;
|
||||
|
||||
length = scnprintf(tmpbuf, TMPBUFLEN, "%d",
|
||||
enforcing_enabled(fsi->state));
|
||||
enforcing_enabled());
|
||||
return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
|
||||
}
|
||||
|
||||
@@ -139,8 +136,6 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
|
||||
struct selinux_state *state = fsi->state;
|
||||
char *page = NULL;
|
||||
ssize_t length;
|
||||
int old_value, new_value;
|
||||
@@ -162,10 +157,9 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
|
||||
|
||||
new_value = !!new_value;
|
||||
|
||||
old_value = enforcing_enabled(state);
|
||||
old_value = enforcing_enabled();
|
||||
if (new_value != old_value) {
|
||||
length = avc_has_perm(&selinux_state,
|
||||
current_sid(), SECINITSID_SECURITY,
|
||||
length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
|
||||
SECCLASS_SECURITY, SECURITY__SETENFORCE,
|
||||
NULL);
|
||||
if (length)
|
||||
@@ -176,15 +170,15 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
|
||||
new_value, old_value,
|
||||
from_kuid(&init_user_ns, audit_get_loginuid(current)),
|
||||
audit_get_sessionid(current));
|
||||
enforcing_set(state, new_value);
|
||||
enforcing_set(new_value);
|
||||
if (new_value)
|
||||
avc_ss_reset(state->avc, 0);
|
||||
avc_ss_reset(0);
|
||||
selnl_notify_setenforce(new_value);
|
||||
selinux_status_update_setenforce(state, new_value);
|
||||
selinux_status_update_setenforce(new_value);
|
||||
if (!new_value)
|
||||
call_blocking_lsm_notifier(LSM_POLICY_CHANGE, NULL);
|
||||
|
||||
selinux_ima_measure_state(state);
|
||||
selinux_ima_measure_state();
|
||||
}
|
||||
length = count;
|
||||
out:
|
||||
@@ -204,14 +198,12 @@ static const struct file_operations sel_enforce_ops = {
|
||||
static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
|
||||
struct selinux_state *state = fsi->state;
|
||||
char tmpbuf[TMPBUFLEN];
|
||||
ssize_t length;
|
||||
ino_t ino = file_inode(filp)->i_ino;
|
||||
int handle_unknown = (ino == SEL_REJECT_UNKNOWN) ?
|
||||
security_get_reject_unknown(state) :
|
||||
!security_get_allow_unknown(state);
|
||||
security_get_reject_unknown() :
|
||||
!security_get_allow_unknown();
|
||||
|
||||
length = scnprintf(tmpbuf, TMPBUFLEN, "%d", handle_unknown);
|
||||
return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
|
||||
@@ -224,8 +216,7 @@ static const struct file_operations sel_handle_unknown_ops = {
|
||||
|
||||
static int sel_open_handle_status(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
|
||||
struct page *status = selinux_kernel_status_page(fsi->state);
|
||||
struct page *status = selinux_kernel_status_page();
|
||||
|
||||
if (!status)
|
||||
return -ENOMEM;
|
||||
@@ -276,25 +267,13 @@ static const struct file_operations sel_handle_status_ops = {
|
||||
.llseek = generic_file_llseek,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
|
||||
static ssize_t sel_write_disable(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
|
||||
char *page;
|
||||
ssize_t length;
|
||||
int new_value;
|
||||
int enforcing;
|
||||
|
||||
/* NOTE: we are now officially considering runtime disable as
|
||||
* deprecated, and using it will become increasingly painful
|
||||
* (e.g. sleeping/blocking) as we progress through future
|
||||
* kernel releases until eventually it is removed
|
||||
*/
|
||||
pr_err("SELinux: Runtime disable is deprecated, use selinux=0 on the kernel cmdline.\n");
|
||||
pr_err("SELinux: https://github.com/SELinuxProject/selinux-kernel/wiki/DEPRECATE-runtime-disable\n");
|
||||
ssleep(15);
|
||||
|
||||
if (count >= PAGE_SIZE)
|
||||
return -ENOMEM;
|
||||
@@ -307,31 +286,21 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf,
|
||||
if (IS_ERR(page))
|
||||
return PTR_ERR(page);
|
||||
|
||||
length = -EINVAL;
|
||||
if (sscanf(page, "%d", &new_value) != 1)
|
||||
if (sscanf(page, "%d", &new_value) != 1) {
|
||||
length = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
length = count;
|
||||
|
||||
if (new_value) {
|
||||
enforcing = enforcing_enabled(fsi->state);
|
||||
length = selinux_disable(fsi->state);
|
||||
if (length)
|
||||
goto out;
|
||||
audit_log(audit_context(), GFP_KERNEL, AUDIT_MAC_STATUS,
|
||||
"enforcing=%d old_enforcing=%d auid=%u ses=%u"
|
||||
" enabled=0 old-enabled=1 lsm=selinux res=1",
|
||||
enforcing, enforcing,
|
||||
from_kuid(&init_user_ns, audit_get_loginuid(current)),
|
||||
audit_get_sessionid(current));
|
||||
pr_err("SELinux: https://github.com/SELinuxProject/selinux-kernel/wiki/DEPRECATE-runtime-disable\n");
|
||||
pr_err("SELinux: Runtime disable is not supported, use selinux=0 on the kernel cmdline.\n");
|
||||
}
|
||||
|
||||
length = count;
|
||||
out:
|
||||
kfree(page);
|
||||
return length;
|
||||
}
|
||||
#else
|
||||
#define sel_write_disable NULL
|
||||
#endif
|
||||
|
||||
static const struct file_operations sel_disable_ops = {
|
||||
.write = sel_write_disable,
|
||||
@@ -375,12 +344,11 @@ static void sel_remove_entries(struct dentry *de);
|
||||
static ssize_t sel_read_mls(struct file *filp, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
|
||||
char tmpbuf[TMPBUFLEN];
|
||||
ssize_t length;
|
||||
|
||||
length = scnprintf(tmpbuf, TMPBUFLEN, "%d",
|
||||
security_mls_enabled(fsi->state));
|
||||
security_mls_enabled());
|
||||
return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
|
||||
}
|
||||
|
||||
@@ -397,16 +365,14 @@ struct policy_load_memory {
|
||||
static int sel_open_policy(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct selinux_fs_info *fsi = inode->i_sb->s_fs_info;
|
||||
struct selinux_state *state = fsi->state;
|
||||
struct policy_load_memory *plm = NULL;
|
||||
int rc;
|
||||
|
||||
BUG_ON(filp->private_data);
|
||||
|
||||
mutex_lock(&fsi->state->policy_mutex);
|
||||
mutex_lock(&selinux_state.policy_mutex);
|
||||
|
||||
rc = avc_has_perm(&selinux_state,
|
||||
current_sid(), SECINITSID_SECURITY,
|
||||
rc = avc_has_perm(current_sid(), SECINITSID_SECURITY,
|
||||
SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL);
|
||||
if (rc)
|
||||
goto err;
|
||||
@@ -420,7 +386,7 @@ static int sel_open_policy(struct inode *inode, struct file *filp)
|
||||
if (!plm)
|
||||
goto err;
|
||||
|
||||
rc = security_read_policy(state, &plm->data, &plm->len);
|
||||
rc = security_read_policy(&plm->data, &plm->len);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
@@ -434,11 +400,11 @@ static int sel_open_policy(struct inode *inode, struct file *filp)
|
||||
|
||||
filp->private_data = plm;
|
||||
|
||||
mutex_unlock(&fsi->state->policy_mutex);
|
||||
mutex_unlock(&selinux_state.policy_mutex);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
mutex_unlock(&fsi->state->policy_mutex);
|
||||
mutex_unlock(&selinux_state.policy_mutex);
|
||||
|
||||
if (plm)
|
||||
vfree(plm->data);
|
||||
@@ -467,8 +433,7 @@ static ssize_t sel_read_policy(struct file *filp, char __user *buf,
|
||||
struct policy_load_memory *plm = filp->private_data;
|
||||
int ret;
|
||||
|
||||
ret = avc_has_perm(&selinux_state,
|
||||
current_sid(), SECINITSID_SECURITY,
|
||||
ret = avc_has_perm(current_sid(), SECINITSID_SECURITY,
|
||||
SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -621,10 +586,9 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
|
||||
ssize_t length;
|
||||
void *data = NULL;
|
||||
|
||||
mutex_lock(&fsi->state->policy_mutex);
|
||||
mutex_lock(&selinux_state.policy_mutex);
|
||||
|
||||
length = avc_has_perm(&selinux_state,
|
||||
current_sid(), SECINITSID_SECURITY,
|
||||
length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
|
||||
SECCLASS_SECURITY, SECURITY__LOAD_POLICY, NULL);
|
||||
if (length)
|
||||
goto out;
|
||||
@@ -643,7 +607,7 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
|
||||
if (copy_from_user(data, buf, count) != 0)
|
||||
goto out;
|
||||
|
||||
length = security_load_policy(fsi->state, data, count, &load_state);
|
||||
length = security_load_policy(data, count, &load_state);
|
||||
if (length) {
|
||||
pr_warn_ratelimited("SELinux: failed to load policy\n");
|
||||
goto out;
|
||||
@@ -652,11 +616,11 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
|
||||
length = sel_make_policy_nodes(fsi, load_state.policy);
|
||||
if (length) {
|
||||
pr_warn_ratelimited("SELinux: failed to initialize selinuxfs\n");
|
||||
selinux_policy_cancel(fsi->state, &load_state);
|
||||
selinux_policy_cancel(&load_state);
|
||||
goto out;
|
||||
}
|
||||
|
||||
selinux_policy_commit(fsi->state, &load_state);
|
||||
selinux_policy_commit(&load_state);
|
||||
|
||||
length = count;
|
||||
|
||||
@@ -665,7 +629,7 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
|
||||
from_kuid(&init_user_ns, audit_get_loginuid(current)),
|
||||
audit_get_sessionid(current));
|
||||
out:
|
||||
mutex_unlock(&fsi->state->policy_mutex);
|
||||
mutex_unlock(&selinux_state.policy_mutex);
|
||||
vfree(data);
|
||||
return length;
|
||||
}
|
||||
@@ -677,23 +641,20 @@ static const struct file_operations sel_load_ops = {
|
||||
|
||||
static ssize_t sel_write_context(struct file *file, char *buf, size_t size)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
|
||||
struct selinux_state *state = fsi->state;
|
||||
char *canon = NULL;
|
||||
u32 sid, len;
|
||||
ssize_t length;
|
||||
|
||||
length = avc_has_perm(&selinux_state,
|
||||
current_sid(), SECINITSID_SECURITY,
|
||||
length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
|
||||
SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, NULL);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
length = security_context_to_sid(state, buf, size, &sid, GFP_KERNEL);
|
||||
length = security_context_to_sid(buf, size, &sid, GFP_KERNEL);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
length = security_sid_to_context(state, sid, &canon, &len);
|
||||
length = security_sid_to_context(sid, &canon, &len);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
@@ -714,25 +675,22 @@ out:
|
||||
static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
|
||||
char tmpbuf[TMPBUFLEN];
|
||||
ssize_t length;
|
||||
|
||||
length = scnprintf(tmpbuf, TMPBUFLEN, "%u",
|
||||
checkreqprot_get(fsi->state));
|
||||
checkreqprot_get());
|
||||
return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
|
||||
}
|
||||
|
||||
static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
|
||||
char *page;
|
||||
ssize_t length;
|
||||
unsigned int new_value;
|
||||
|
||||
length = avc_has_perm(&selinux_state,
|
||||
current_sid(), SECINITSID_SECURITY,
|
||||
length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
|
||||
SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT,
|
||||
NULL);
|
||||
if (length)
|
||||
@@ -749,24 +707,21 @@ static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
|
||||
if (IS_ERR(page))
|
||||
return PTR_ERR(page);
|
||||
|
||||
length = -EINVAL;
|
||||
if (sscanf(page, "%u", &new_value) != 1)
|
||||
if (sscanf(page, "%u", &new_value) != 1) {
|
||||
length = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
length = count;
|
||||
|
||||
if (new_value) {
|
||||
char comm[sizeof(current->comm)];
|
||||
|
||||
memcpy(comm, current->comm, sizeof(comm));
|
||||
pr_err("SELinux: %s (%d) set checkreqprot to 1. This is deprecated and will be rejected in a future kernel release.\n",
|
||||
pr_err("SELinux: %s (%d) set checkreqprot to 1. This is no longer supported.\n",
|
||||
comm, current->pid);
|
||||
}
|
||||
|
||||
checkreqprot_set(fsi->state, (new_value ? 1 : 0));
|
||||
if (new_value)
|
||||
ssleep(15);
|
||||
length = count;
|
||||
|
||||
selinux_ima_measure_state(fsi->state);
|
||||
selinux_ima_measure_state();
|
||||
|
||||
out:
|
||||
kfree(page);
|
||||
@@ -782,16 +737,13 @@ static ssize_t sel_write_validatetrans(struct file *file,
|
||||
const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
|
||||
struct selinux_state *state = fsi->state;
|
||||
char *oldcon = NULL, *newcon = NULL, *taskcon = NULL;
|
||||
char *req = NULL;
|
||||
u32 osid, nsid, tsid;
|
||||
u16 tclass;
|
||||
int rc;
|
||||
|
||||
rc = avc_has_perm(&selinux_state,
|
||||
current_sid(), SECINITSID_SECURITY,
|
||||
rc = avc_has_perm(current_sid(), SECINITSID_SECURITY,
|
||||
SECCLASS_SECURITY, SECURITY__VALIDATE_TRANS, NULL);
|
||||
if (rc)
|
||||
goto out;
|
||||
@@ -829,19 +781,19 @@ static ssize_t sel_write_validatetrans(struct file *file,
|
||||
if (sscanf(req, "%s %s %hu %s", oldcon, newcon, &tclass, taskcon) != 4)
|
||||
goto out;
|
||||
|
||||
rc = security_context_str_to_sid(state, oldcon, &osid, GFP_KERNEL);
|
||||
rc = security_context_str_to_sid(oldcon, &osid, GFP_KERNEL);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
rc = security_context_str_to_sid(state, newcon, &nsid, GFP_KERNEL);
|
||||
rc = security_context_str_to_sid(newcon, &nsid, GFP_KERNEL);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
rc = security_context_str_to_sid(state, taskcon, &tsid, GFP_KERNEL);
|
||||
rc = security_context_str_to_sid(taskcon, &tsid, GFP_KERNEL);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
rc = security_validate_transition_user(state, osid, nsid, tsid, tclass);
|
||||
rc = security_validate_transition_user(osid, nsid, tsid, tclass);
|
||||
if (!rc)
|
||||
rc = count;
|
||||
out:
|
||||
@@ -911,16 +863,13 @@ static const struct file_operations transaction_ops = {
|
||||
|
||||
static ssize_t sel_write_access(struct file *file, char *buf, size_t size)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
|
||||
struct selinux_state *state = fsi->state;
|
||||
char *scon = NULL, *tcon = NULL;
|
||||
u32 ssid, tsid;
|
||||
u16 tclass;
|
||||
struct av_decision avd;
|
||||
ssize_t length;
|
||||
|
||||
length = avc_has_perm(&selinux_state,
|
||||
current_sid(), SECINITSID_SECURITY,
|
||||
length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
|
||||
SECCLASS_SECURITY, SECURITY__COMPUTE_AV, NULL);
|
||||
if (length)
|
||||
goto out;
|
||||
@@ -939,15 +888,15 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size)
|
||||
if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
|
||||
goto out;
|
||||
|
||||
length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL);
|
||||
length = security_context_str_to_sid(scon, &ssid, GFP_KERNEL);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL);
|
||||
length = security_context_str_to_sid(tcon, &tsid, GFP_KERNEL);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
security_compute_av_user(state, ssid, tsid, tclass, &avd);
|
||||
security_compute_av_user(ssid, tsid, tclass, &avd);
|
||||
|
||||
length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT,
|
||||
"%x %x %x %x %u %x",
|
||||
@@ -962,8 +911,6 @@ out:
|
||||
|
||||
static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
|
||||
struct selinux_state *state = fsi->state;
|
||||
char *scon = NULL, *tcon = NULL;
|
||||
char *namebuf = NULL, *objname = NULL;
|
||||
u32 ssid, tsid, newsid;
|
||||
@@ -973,8 +920,7 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
|
||||
u32 len;
|
||||
int nargs;
|
||||
|
||||
length = avc_has_perm(&selinux_state,
|
||||
current_sid(), SECINITSID_SECURITY,
|
||||
length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
|
||||
SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE,
|
||||
NULL);
|
||||
if (length)
|
||||
@@ -1030,20 +976,20 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
|
||||
objname = namebuf;
|
||||
}
|
||||
|
||||
length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL);
|
||||
length = security_context_str_to_sid(scon, &ssid, GFP_KERNEL);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL);
|
||||
length = security_context_str_to_sid(tcon, &tsid, GFP_KERNEL);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
length = security_transition_sid_user(state, ssid, tsid, tclass,
|
||||
length = security_transition_sid_user(ssid, tsid, tclass,
|
||||
objname, &newsid);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
length = security_sid_to_context(state, newsid, &newcon, &len);
|
||||
length = security_sid_to_context(newsid, &newcon, &len);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
@@ -1066,8 +1012,6 @@ out:
|
||||
|
||||
static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
|
||||
struct selinux_state *state = fsi->state;
|
||||
char *scon = NULL, *tcon = NULL;
|
||||
u32 ssid, tsid, newsid;
|
||||
u16 tclass;
|
||||
@@ -1075,8 +1019,7 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size)
|
||||
char *newcon = NULL;
|
||||
u32 len;
|
||||
|
||||
length = avc_has_perm(&selinux_state,
|
||||
current_sid(), SECINITSID_SECURITY,
|
||||
length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
|
||||
SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL,
|
||||
NULL);
|
||||
if (length)
|
||||
@@ -1096,19 +1039,19 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size)
|
||||
if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
|
||||
goto out;
|
||||
|
||||
length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL);
|
||||
length = security_context_str_to_sid(scon, &ssid, GFP_KERNEL);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL);
|
||||
length = security_context_str_to_sid(tcon, &tsid, GFP_KERNEL);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
length = security_change_sid(state, ssid, tsid, tclass, &newsid);
|
||||
length = security_change_sid(ssid, tsid, tclass, &newsid);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
length = security_sid_to_context(state, newsid, &newcon, &len);
|
||||
length = security_sid_to_context(newsid, &newcon, &len);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
@@ -1127,8 +1070,6 @@ out:
|
||||
|
||||
static ssize_t sel_write_user(struct file *file, char *buf, size_t size)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
|
||||
struct selinux_state *state = fsi->state;
|
||||
char *con = NULL, *user = NULL, *ptr;
|
||||
u32 sid, *sids = NULL;
|
||||
ssize_t length;
|
||||
@@ -1136,8 +1077,7 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size)
|
||||
int i, rc;
|
||||
u32 len, nsids;
|
||||
|
||||
length = avc_has_perm(&selinux_state,
|
||||
current_sid(), SECINITSID_SECURITY,
|
||||
length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
|
||||
SECCLASS_SECURITY, SECURITY__COMPUTE_USER,
|
||||
NULL);
|
||||
if (length)
|
||||
@@ -1157,18 +1097,18 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size)
|
||||
if (sscanf(buf, "%s %s", con, user) != 2)
|
||||
goto out;
|
||||
|
||||
length = security_context_str_to_sid(state, con, &sid, GFP_KERNEL);
|
||||
length = security_context_str_to_sid(con, &sid, GFP_KERNEL);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
length = security_get_user_sids(state, sid, user, &sids, &nsids);
|
||||
length = security_get_user_sids(sid, user, &sids, &nsids);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
length = sprintf(buf, "%u", nsids) + 1;
|
||||
ptr = buf + length;
|
||||
for (i = 0; i < nsids; i++) {
|
||||
rc = security_sid_to_context(state, sids[i], &newcon, &len);
|
||||
rc = security_sid_to_context(sids[i], &newcon, &len);
|
||||
if (rc) {
|
||||
length = rc;
|
||||
goto out;
|
||||
@@ -1192,8 +1132,6 @@ out:
|
||||
|
||||
static ssize_t sel_write_member(struct file *file, char *buf, size_t size)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
|
||||
struct selinux_state *state = fsi->state;
|
||||
char *scon = NULL, *tcon = NULL;
|
||||
u32 ssid, tsid, newsid;
|
||||
u16 tclass;
|
||||
@@ -1201,8 +1139,7 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size)
|
||||
char *newcon = NULL;
|
||||
u32 len;
|
||||
|
||||
length = avc_has_perm(&selinux_state,
|
||||
current_sid(), SECINITSID_SECURITY,
|
||||
length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
|
||||
SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER,
|
||||
NULL);
|
||||
if (length)
|
||||
@@ -1222,19 +1159,19 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size)
|
||||
if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
|
||||
goto out;
|
||||
|
||||
length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL);
|
||||
length = security_context_str_to_sid(scon, &ssid, GFP_KERNEL);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL);
|
||||
length = security_context_str_to_sid(tcon, &tsid, GFP_KERNEL);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
length = security_member_sid(state, ssid, tsid, tclass, &newsid);
|
||||
length = security_member_sid(ssid, tsid, tclass, &newsid);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
length = security_sid_to_context(state, newsid, &newcon, &len);
|
||||
length = security_sid_to_context(newsid, &newcon, &len);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
@@ -1276,7 +1213,7 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
|
||||
unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK;
|
||||
const char *name = filep->f_path.dentry->d_name.name;
|
||||
|
||||
mutex_lock(&fsi->state->policy_mutex);
|
||||
mutex_lock(&selinux_state.policy_mutex);
|
||||
|
||||
ret = -EINVAL;
|
||||
if (index >= fsi->bool_num || strcmp(name,
|
||||
@@ -1288,21 +1225,21 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
|
||||
if (!page)
|
||||
goto out_unlock;
|
||||
|
||||
cur_enforcing = security_get_bool_value(fsi->state, index);
|
||||
cur_enforcing = security_get_bool_value(index);
|
||||
if (cur_enforcing < 0) {
|
||||
ret = cur_enforcing;
|
||||
goto out_unlock;
|
||||
}
|
||||
length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
|
||||
fsi->bool_pending_values[index]);
|
||||
mutex_unlock(&fsi->state->policy_mutex);
|
||||
mutex_unlock(&selinux_state.policy_mutex);
|
||||
ret = simple_read_from_buffer(buf, count, ppos, page, length);
|
||||
out_free:
|
||||
free_page((unsigned long)page);
|
||||
return ret;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&fsi->state->policy_mutex);
|
||||
mutex_unlock(&selinux_state.policy_mutex);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
@@ -1327,10 +1264,9 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
|
||||
if (IS_ERR(page))
|
||||
return PTR_ERR(page);
|
||||
|
||||
mutex_lock(&fsi->state->policy_mutex);
|
||||
mutex_lock(&selinux_state.policy_mutex);
|
||||
|
||||
length = avc_has_perm(&selinux_state,
|
||||
current_sid(), SECINITSID_SECURITY,
|
||||
length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
|
||||
SECCLASS_SECURITY, SECURITY__SETBOOL,
|
||||
NULL);
|
||||
if (length)
|
||||
@@ -1352,7 +1288,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
|
||||
length = count;
|
||||
|
||||
out:
|
||||
mutex_unlock(&fsi->state->policy_mutex);
|
||||
mutex_unlock(&selinux_state.policy_mutex);
|
||||
kfree(page);
|
||||
return length;
|
||||
}
|
||||
@@ -1383,10 +1319,9 @@ static ssize_t sel_commit_bools_write(struct file *filep,
|
||||
if (IS_ERR(page))
|
||||
return PTR_ERR(page);
|
||||
|
||||
mutex_lock(&fsi->state->policy_mutex);
|
||||
mutex_lock(&selinux_state.policy_mutex);
|
||||
|
||||
length = avc_has_perm(&selinux_state,
|
||||
current_sid(), SECINITSID_SECURITY,
|
||||
length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
|
||||
SECCLASS_SECURITY, SECURITY__SETBOOL,
|
||||
NULL);
|
||||
if (length)
|
||||
@@ -1398,14 +1333,14 @@ static ssize_t sel_commit_bools_write(struct file *filep,
|
||||
|
||||
length = 0;
|
||||
if (new_value && fsi->bool_pending_values)
|
||||
length = security_set_bools(fsi->state, fsi->bool_num,
|
||||
length = security_set_bools(fsi->bool_num,
|
||||
fsi->bool_pending_values);
|
||||
|
||||
if (!length)
|
||||
length = count;
|
||||
|
||||
out:
|
||||
mutex_unlock(&fsi->state->policy_mutex);
|
||||
mutex_unlock(&selinux_state.policy_mutex);
|
||||
kfree(page);
|
||||
return length;
|
||||
}
|
||||
@@ -1503,13 +1438,11 @@ out:
|
||||
static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
|
||||
struct selinux_state *state = fsi->state;
|
||||
char tmpbuf[TMPBUFLEN];
|
||||
ssize_t length;
|
||||
|
||||
length = scnprintf(tmpbuf, TMPBUFLEN, "%u",
|
||||
avc_get_cache_threshold(state->avc));
|
||||
avc_get_cache_threshold());
|
||||
return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
|
||||
}
|
||||
|
||||
@@ -1518,14 +1451,11 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file,
|
||||
size_t count, loff_t *ppos)
|
||||
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
|
||||
struct selinux_state *state = fsi->state;
|
||||
char *page;
|
||||
ssize_t ret;
|
||||
unsigned int new_value;
|
||||
|
||||
ret = avc_has_perm(&selinux_state,
|
||||
current_sid(), SECINITSID_SECURITY,
|
||||
ret = avc_has_perm(current_sid(), SECINITSID_SECURITY,
|
||||
SECCLASS_SECURITY, SECURITY__SETSECPARAM,
|
||||
NULL);
|
||||
if (ret)
|
||||
@@ -1546,7 +1476,7 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file,
|
||||
if (sscanf(page, "%u", &new_value) != 1)
|
||||
goto out;
|
||||
|
||||
avc_set_cache_threshold(state->avc, new_value);
|
||||
avc_set_cache_threshold(new_value);
|
||||
|
||||
ret = count;
|
||||
out:
|
||||
@@ -1557,8 +1487,6 @@ out:
|
||||
static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
|
||||
struct selinux_state *state = fsi->state;
|
||||
char *page;
|
||||
ssize_t length;
|
||||
|
||||
@@ -1566,7 +1494,7 @@ static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf,
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
|
||||
length = avc_get_hash_stats(state->avc, page);
|
||||
length = avc_get_hash_stats(page);
|
||||
if (length >= 0)
|
||||
length = simple_read_from_buffer(buf, count, ppos, page, length);
|
||||
free_page((unsigned long)page);
|
||||
@@ -1577,8 +1505,6 @@ static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf,
|
||||
static ssize_t sel_read_sidtab_hash_stats(struct file *filp, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
|
||||
struct selinux_state *state = fsi->state;
|
||||
char *page;
|
||||
ssize_t length;
|
||||
|
||||
@@ -1586,7 +1512,7 @@ static ssize_t sel_read_sidtab_hash_stats(struct file *filp, char __user *buf,
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
|
||||
length = security_sidtab_hash_stats(state, page);
|
||||
length = security_sidtab_hash_stats(page);
|
||||
if (length >= 0)
|
||||
length = simple_read_from_buffer(buf, count, ppos, page,
|
||||
length);
|
||||
@@ -1752,13 +1678,12 @@ static int sel_make_ss_files(struct dentry *dir)
|
||||
static ssize_t sel_read_initcon(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
|
||||
char *con;
|
||||
u32 sid, len;
|
||||
ssize_t ret;
|
||||
|
||||
sid = file_inode(file)->i_ino&SEL_INO_MASK;
|
||||
ret = security_sid_to_context(fsi->state, sid, &con, &len);
|
||||
ret = security_sid_to_context(sid, &con, &len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1852,13 +1777,12 @@ static const struct file_operations sel_perm_ops = {
|
||||
static ssize_t sel_read_policycap(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
|
||||
int value;
|
||||
char tmpbuf[TMPBUFLEN];
|
||||
ssize_t length;
|
||||
unsigned long i_ino = file_inode(file)->i_ino;
|
||||
|
||||
value = security_policycap_supported(fsi->state, i_ino & SEL_INO_MASK);
|
||||
value = security_policycap_supported(i_ino & SEL_INO_MASK);
|
||||
length = scnprintf(tmpbuf, TMPBUFLEN, "%d", value);
|
||||
|
||||
return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
|
||||
@@ -2249,13 +2173,3 @@ static int __init init_sel_fs(void)
|
||||
}
|
||||
|
||||
__initcall(init_sel_fs);
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
|
||||
void exit_sel_fs(void)
|
||||
{
|
||||
sysfs_remove_mount_point(fs_kobj, "selinux");
|
||||
dput(selinux_null.dentry);
|
||||
kern_unmount(selinuxfs_mount);
|
||||
unregister_filesystem(&sel_fs_type);
|
||||
}
|
||||
#endif
|
||||
|
||||
+141
-205
File diff suppressed because it is too large
Load Diff
@@ -30,7 +30,6 @@ struct selinux_policy {
|
||||
} __randomize_layout;
|
||||
|
||||
struct convert_context_args {
|
||||
struct selinux_state *state;
|
||||
struct policydb *oldp;
|
||||
struct policydb *newp;
|
||||
};
|
||||
|
||||
+21
-23
@@ -39,21 +39,21 @@
|
||||
* It returns a reference to selinux_status_page. If the status page is
|
||||
* not allocated yet, it also tries to allocate it at the first time.
|
||||
*/
|
||||
struct page *selinux_kernel_status_page(struct selinux_state *state)
|
||||
struct page *selinux_kernel_status_page(void)
|
||||
{
|
||||
struct selinux_kernel_status *status;
|
||||
struct page *result = NULL;
|
||||
|
||||
mutex_lock(&state->status_lock);
|
||||
if (!state->status_page) {
|
||||
state->status_page = alloc_page(GFP_KERNEL|__GFP_ZERO);
|
||||
mutex_lock(&selinux_state.status_lock);
|
||||
if (!selinux_state.status_page) {
|
||||
selinux_state.status_page = alloc_page(GFP_KERNEL|__GFP_ZERO);
|
||||
|
||||
if (state->status_page) {
|
||||
status = page_address(state->status_page);
|
||||
if (selinux_state.status_page) {
|
||||
status = page_address(selinux_state.status_page);
|
||||
|
||||
status->version = SELINUX_KERNEL_STATUS_VERSION;
|
||||
status->sequence = 0;
|
||||
status->enforcing = enforcing_enabled(state);
|
||||
status->enforcing = enforcing_enabled();
|
||||
/*
|
||||
* NOTE: the next policyload event shall set
|
||||
* a positive value on the status->policyload,
|
||||
@@ -62,11 +62,11 @@ struct page *selinux_kernel_status_page(struct selinux_state *state)
|
||||
*/
|
||||
status->policyload = 0;
|
||||
status->deny_unknown =
|
||||
!security_get_allow_unknown(state);
|
||||
!security_get_allow_unknown();
|
||||
}
|
||||
}
|
||||
result = state->status_page;
|
||||
mutex_unlock(&state->status_lock);
|
||||
result = selinux_state.status_page;
|
||||
mutex_unlock(&selinux_state.status_lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -76,14 +76,13 @@ struct page *selinux_kernel_status_page(struct selinux_state *state)
|
||||
*
|
||||
* It updates status of the current enforcing/permissive mode.
|
||||
*/
|
||||
void selinux_status_update_setenforce(struct selinux_state *state,
|
||||
int enforcing)
|
||||
void selinux_status_update_setenforce(int enforcing)
|
||||
{
|
||||
struct selinux_kernel_status *status;
|
||||
|
||||
mutex_lock(&state->status_lock);
|
||||
if (state->status_page) {
|
||||
status = page_address(state->status_page);
|
||||
mutex_lock(&selinux_state.status_lock);
|
||||
if (selinux_state.status_page) {
|
||||
status = page_address(selinux_state.status_page);
|
||||
|
||||
status->sequence++;
|
||||
smp_wmb();
|
||||
@@ -93,7 +92,7 @@ void selinux_status_update_setenforce(struct selinux_state *state,
|
||||
smp_wmb();
|
||||
status->sequence++;
|
||||
}
|
||||
mutex_unlock(&state->status_lock);
|
||||
mutex_unlock(&selinux_state.status_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -102,23 +101,22 @@ void selinux_status_update_setenforce(struct selinux_state *state,
|
||||
* It updates status of the times of policy reloaded, and current
|
||||
* setting of deny_unknown.
|
||||
*/
|
||||
void selinux_status_update_policyload(struct selinux_state *state,
|
||||
int seqno)
|
||||
void selinux_status_update_policyload(int seqno)
|
||||
{
|
||||
struct selinux_kernel_status *status;
|
||||
|
||||
mutex_lock(&state->status_lock);
|
||||
if (state->status_page) {
|
||||
status = page_address(state->status_page);
|
||||
mutex_lock(&selinux_state.status_lock);
|
||||
if (selinux_state.status_page) {
|
||||
status = page_address(selinux_state.status_page);
|
||||
|
||||
status->sequence++;
|
||||
smp_wmb();
|
||||
|
||||
status->policyload = seqno;
|
||||
status->deny_unknown = !security_get_allow_unknown(state);
|
||||
status->deny_unknown = !security_get_allow_unknown();
|
||||
|
||||
smp_wmb();
|
||||
status->sequence++;
|
||||
}
|
||||
mutex_unlock(&state->status_lock);
|
||||
mutex_unlock(&selinux_state.status_lock);
|
||||
}
|
||||
|
||||
+8
-12
@@ -98,13 +98,12 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,
|
||||
ctx->ctx_len = str_len;
|
||||
memcpy(ctx->ctx_str, &uctx[1], str_len);
|
||||
ctx->ctx_str[str_len] = '\0';
|
||||
rc = security_context_to_sid(&selinux_state, ctx->ctx_str, str_len,
|
||||
rc = security_context_to_sid(ctx->ctx_str, str_len,
|
||||
&ctx->ctx_sid, gfp);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
rc = avc_has_perm(&selinux_state,
|
||||
tsec->sid, ctx->ctx_sid,
|
||||
rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
|
||||
SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL);
|
||||
if (rc)
|
||||
goto err;
|
||||
@@ -140,8 +139,7 @@ static int selinux_xfrm_delete(struct xfrm_sec_ctx *ctx)
|
||||
if (!ctx)
|
||||
return 0;
|
||||
|
||||
return avc_has_perm(&selinux_state,
|
||||
tsec->sid, ctx->ctx_sid,
|
||||
return avc_has_perm(tsec->sid, ctx->ctx_sid,
|
||||
SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
|
||||
NULL);
|
||||
}
|
||||
@@ -163,8 +161,7 @@ int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid)
|
||||
if (!selinux_authorizable_ctx(ctx))
|
||||
return -EINVAL;
|
||||
|
||||
rc = avc_has_perm(&selinux_state,
|
||||
fl_secid, ctx->ctx_sid,
|
||||
rc = avc_has_perm(fl_secid, ctx->ctx_sid,
|
||||
SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, NULL);
|
||||
return (rc == -EACCES ? -ESRCH : rc);
|
||||
}
|
||||
@@ -205,7 +202,7 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
|
||||
/* We don't need a separate SA Vs. policy polmatch check since the SA
|
||||
* is now of the same label as the flow and a flow Vs. policy polmatch
|
||||
* check had already happened in selinux_xfrm_policy_lookup() above. */
|
||||
return (avc_has_perm(&selinux_state, flic_sid, state_sid,
|
||||
return (avc_has_perm(flic_sid, state_sid,
|
||||
SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO,
|
||||
NULL) ? 0 : 1);
|
||||
}
|
||||
@@ -355,7 +352,7 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
|
||||
if (secid == 0)
|
||||
return -EINVAL;
|
||||
|
||||
rc = security_sid_to_context(&selinux_state, secid, &ctx_str,
|
||||
rc = security_sid_to_context(secid, &ctx_str,
|
||||
&str_len);
|
||||
if (rc)
|
||||
return rc;
|
||||
@@ -424,8 +421,7 @@ int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
|
||||
/* This check even when there's no association involved is intended,
|
||||
* according to Trent Jaeger, to make sure a process can't engage in
|
||||
* non-IPsec communication unless explicitly allowed by policy. */
|
||||
return avc_has_perm(&selinux_state,
|
||||
sk_sid, peer_sid,
|
||||
return avc_has_perm(sk_sid, peer_sid,
|
||||
SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, ad);
|
||||
}
|
||||
|
||||
@@ -468,6 +464,6 @@ int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
|
||||
/* This check even when there's no association involved is intended,
|
||||
* according to Trent Jaeger, to make sure a process can't engage in
|
||||
* non-IPsec communication unless explicitly allowed by policy. */
|
||||
return avc_has_perm(&selinux_state, sk_sid, SECINITSID_UNLABELED,
|
||||
return avc_has_perm(sk_sid, SECINITSID_UNLABELED,
|
||||
SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, ad);
|
||||
}
|
||||
|
||||
@@ -4847,7 +4847,7 @@ static int smack_uring_cmd(struct io_uring_cmd *ioucmd)
|
||||
|
||||
#endif /* CONFIG_IO_URING */
|
||||
|
||||
struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
|
||||
struct lsm_blob_sizes smack_blob_sizes __ro_after_init = {
|
||||
.lbs_cred = sizeof(struct task_smack),
|
||||
.lbs_file = sizeof(struct smack_known *),
|
||||
.lbs_inode = sizeof(struct inode_smack),
|
||||
@@ -4856,7 +4856,7 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
|
||||
.lbs_superblock = sizeof(struct superblock_smack),
|
||||
};
|
||||
|
||||
static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
|
||||
static struct security_hook_list smack_hooks[] __ro_after_init = {
|
||||
LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
|
||||
LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
|
||||
LSM_HOOK_INIT(syslog, smack_syslog),
|
||||
|
||||
@@ -499,7 +499,7 @@ static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg,
|
||||
return tomoyo_socket_sendmsg_permission(sock, msg, size);
|
||||
}
|
||||
|
||||
struct lsm_blob_sizes tomoyo_blob_sizes __lsm_ro_after_init = {
|
||||
struct lsm_blob_sizes tomoyo_blob_sizes __ro_after_init = {
|
||||
.lbs_task = sizeof(struct tomoyo_task),
|
||||
};
|
||||
|
||||
@@ -546,7 +546,7 @@ static void tomoyo_task_free(struct task_struct *task)
|
||||
* tomoyo_security_ops is a "struct security_operations" which is used for
|
||||
* registering TOMOYO.
|
||||
*/
|
||||
static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = {
|
||||
static struct security_hook_list tomoyo_hooks[] __ro_after_init = {
|
||||
LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare),
|
||||
LSM_HOOK_INIT(bprm_committed_creds, tomoyo_bprm_committed_creds),
|
||||
LSM_HOOK_INIT(task_alloc, tomoyo_task_alloc),
|
||||
@@ -583,7 +583,7 @@ static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = {
|
||||
/* Lock for GC. */
|
||||
DEFINE_SRCU(tomoyo_ss);
|
||||
|
||||
int tomoyo_enabled __lsm_ro_after_init = 1;
|
||||
int tomoyo_enabled __ro_after_init = 1;
|
||||
|
||||
/**
|
||||
* tomoyo_init - Register TOMOYO Linux as a LSM module.
|
||||
|
||||
@@ -421,7 +421,7 @@ static int yama_ptrace_traceme(struct task_struct *parent)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct security_hook_list yama_hooks[] __lsm_ro_after_init = {
|
||||
static struct security_hook_list yama_hooks[] __ro_after_init = {
|
||||
LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check),
|
||||
LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme),
|
||||
LSM_HOOK_INIT(task_prctl, yama_task_prctl),
|
||||
|
||||
Reference in New Issue
Block a user