mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 04:34:08 +08:00
selinux/stable-6.4 PR 20230420
-----BEGIN PGP SIGNATURE----- iQJIBAABCAAyFiEES0KozwfymdVUl37v6iDy2pc3iXMFAmRBogMUHHBhdWxAcGF1 bC1tb29yZS5jb20ACgkQ6iDy2pc3iXPooxAA2DXBQaTiWA788Zo6gIzYrhGqnIFY NUCBmq8SEvzPmxc1yaxB8CgayAwN4Y8SeV/IZCyXvQL+0xIBKU+Bv65ZeNQ7Zk4s vcINH//hkev061ieP7R7t0WjJZiCpJpzJZWjwdbcPTPuTmEo4BTpi9AVQPWAIwse sIhudgNw+eP6BN5GCeM79WN9KZzW2nPIx6wuvA8U49O96jbD8TRAAycwf/iurErN LGvj42Wr/U6/xXZ/vakK5AA3Msb7ok/IzKcklyWckzyfsj+e504cxncatSsGBUdP NqCJ+FD4EB6OqTrB9kTOCRacKQdinb0IojwC6TchXWRZBcIgbvTqLZCCG6igZpA0 tBrdXHtXBVtDY7roZPoWeyCBG63DTNTfWa3KZCa9S7ww8HccQMvW3xU+UiGnNaM+ OWnGycIkQMKr7TXLZ+9rN28VSuI3For8R/yQb2gHNjdIR2C4Z4LcrgcKNI0Rjx4s 6KrSzczfF7Zmu/EdvtIO9CX/OCUnV0vuNiLxnK57m6HZgrCyDesVcjRysN1wlDnk BBn8RNCJq3UL1S9lJXvWG4ybYLsJ8uLnHC265QASUElov5ipvkBeptvp4C1CkFGR L43eACpgKmMyDxhfPBYlWdv8qHcC/sAz0kg+WFNZ5UKMSZS8L/LX0/Ru0ey/96Wk 56OrmGZTd3hv35w= =V4wc -----END PGP SIGNATURE----- Merge tag 'selinux-pr-20230420' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux Pull selinux updates from Paul Moore: - Stop passing the 'selinux_state' pointers as function arguments As discussed during the end of the last development cycle, passing a selinux_state pointer through the SELinux code has a noticeable impact on performance, and with the current code it is not strictly necessary. This simplifies things by referring directly to the single selinux_state global variable which should help improve SELinux performance. - Uninline the unlikely portions of avc_has_perm_noaudit() This change was also based on a discussion from the last development cycle, and is heavily based on an initial proof of concept patch from you. The core issue was that avc_has_perm_noaudit() was not able to be inlined, as intended, due to its size. We solved this issue by extracting the less frequently hit portions of avc_has_perm_noaudit() into a separate function, reducing the size of avc_has_perm_noaudit() to the point where the compiler began inlining the function. We also took the opportunity to clean up some ugly RCU locking in the code that became uglier with the change. - Remove the runtime disable functionality After several years of work by the userspace and distro folks, we are finally in a place where we feel comfortable removing the runtime disable functionality which we initially deprecated at the start of 2020. There is plenty of information in the kernel's deprecation (now removal) notice, but the main motivation was to be able to safely mark the LSM hook structures as '__ro_after_init'. LWN also wrote a good summary of the deprecation this morning which offers a more detailed history: https://lwn.net/SubscriberLink/927463/dcfa0d4ed2872f03 - Remove the checkreqprot functionality The original checkreqprot deprecation notice stated that the removal would happen no sooner than June 2021, which means this falls hard into the "better late than never" bucket. The Kconfig and deprecation notice has more detail on this setting, but the basic idea is that we want to ensure that the SELinux policy allows for the memory protections actually applied by the kernel, and not those requested by the process. While we haven't found anyone running a supported distro that is affected by this deprecation/removal, anyone who is affected would only need to update their policy to reflect the reality of their applications' mapping protections. - Minor Makefile improvements Some minor Makefile improvements to correct some dependency issues likely only ever seen by SELinux developers. I expect we will have at least one more tweak to the Makefile during the next merge window, but it didn't quite make the cutoff this time around. * tag 'selinux-pr-20230420' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: selinux: ensure av_permissions.h is built when needed selinux: fix Makefile dependencies of flask.h selinux: stop returning node from avc_insert() selinux: clean up dead code after removing runtime disable selinux: update the file list in MAINTAINERS selinux: remove the runtime disable functionality selinux: remove the 'checkreqprot' functionality selinux: stop passing selinux_state pointers and their offspring selinux: uninline unlikely parts of avc_has_perm_noaudit()
This commit is contained in:
commit
72eaa0967b
@ -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.
|
@ -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.
|
@ -18822,8 +18822,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),
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -93,7 +93,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;
|
||||
|
||||
@ -104,18 +104,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;
|
||||
@ -150,7 +148,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;
|
||||
@ -161,7 +159,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;
|
||||
@ -176,7 +174,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);
|
||||
}
|
||||
|
||||
@ -414,8 +412,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,
|
||||
@ -427,7 +424,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);
|
||||
}
|
||||
|
||||
@ -439,30 +436,29 @@ 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
@ -471,17 +467,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) {
|
||||
@ -497,7 +493,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;
|
||||
|
||||
@ -508,9 +504,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;
|
||||
@ -524,15 +520,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 &&
|
||||
@ -547,7 +542,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
|
||||
@ -558,13 +552,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)
|
||||
return node;
|
||||
@ -573,8 +566,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);
|
||||
@ -582,14 +574,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);
|
||||
|
||||
@ -598,7 +590,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
|
||||
@ -612,13 +603,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;
|
||||
@ -626,35 +614,35 @@ 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;
|
||||
}
|
||||
}
|
||||
hlist_add_head_rcu(&node->list, head);
|
||||
found:
|
||||
spin_unlock_irqrestore(lock, flag);
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -715,14 +703,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);
|
||||
@ -740,7 +728,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')
|
||||
@ -750,7 +738,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')
|
||||
@ -766,8 +754,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)
|
||||
{
|
||||
@ -789,7 +776,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;
|
||||
|
||||
@ -827,7 +813,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
|
||||
@ -844,8 +829,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)
|
||||
@ -856,7 +840,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;
|
||||
@ -865,8 +849,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);
|
||||
|
||||
@ -882,7 +866,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;
|
||||
}
|
||||
|
||||
@ -895,7 +879,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;
|
||||
}
|
||||
}
|
||||
@ -926,7 +910,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:
|
||||
@ -935,9 +919,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;
|
||||
@ -946,8 +929,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);
|
||||
/*
|
||||
@ -956,7 +939,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);
|
||||
}
|
||||
@ -964,15 +947,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) {
|
||||
@ -984,34 +966,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)
|
||||
@ -1019,11 +999,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;
|
||||
}
|
||||
@ -1035,8 +1015,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;
|
||||
@ -1057,9 +1036,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;
|
||||
@ -1083,10 +1062,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 {
|
||||
@ -1100,21 +1079,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
|
||||
@ -1133,40 +1139,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
|
||||
@ -1181,25 +1183,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)
|
||||
@ -1216,7 +1218,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); */
|
||||
}
|
||||
}
|
||||
|
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;
|
||||
|
@ -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,94 +86,65 @@ 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];
|
||||
|
||||
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;
|
||||
@ -237,20 +208,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 {
|
||||
@ -287,94 +252,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);
|
||||
|
||||
@ -382,8 +321,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 */
|
||||
@ -394,10 +333,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,
|
||||
@ -405,23 +343,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;
|
||||
@ -433,7 +367,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 {
|
||||
@ -447,12 +381,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);
|
||||
@ -462,6 +393,6 @@ 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);
|
||||
|
||||
#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);
|
||||
|
@ -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
|
||||
|
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;
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user