From 4b36cb773a8153417a080f8025d522322f915aea Mon Sep 17 00:00:00 2001 From: Ondrej Mosnacek Date: Fri, 17 Jan 2020 14:15:14 +0100 Subject: selinux: move status variables out of selinux_ss It fits more naturally in selinux_state, since it reflects also global state (the enforcing and policyload fields). Signed-off-by: Ondrej Mosnacek Reviewed-by: Stephen Smalley Signed-off-by: Paul Moore --- security/selinux/Makefile | 4 +- security/selinux/hooks.c | 1 + security/selinux/include/security.h | 4 ++ security/selinux/ss/services.c | 2 - security/selinux/ss/services.h | 2 - security/selinux/ss/status.c | 124 ------------------------------------ security/selinux/status.c | 124 ++++++++++++++++++++++++++++++++++++ 7 files changed, 131 insertions(+), 130 deletions(-) delete mode 100644 security/selinux/ss/status.c create mode 100644 security/selinux/status.c (limited to 'security/selinux') diff --git a/security/selinux/Makefile b/security/selinux/Makefile index 2000f95fb197..0c77ede1cc11 100644 --- a/security/selinux/Makefile +++ b/security/selinux/Makefile @@ -6,9 +6,9 @@ obj-$(CONFIG_SECURITY_SELINUX) := selinux.o selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o \ - netnode.o netport.o \ + netnode.o netport.o status.o \ ss/ebitmap.o ss/hashtab.o ss/symtab.o ss/sidtab.o ss/avtab.o \ - ss/policydb.o ss/services.o ss/conditional.o ss/mls.o ss/status.o + ss/policydb.o ss/services.o ss/conditional.o ss/mls.o selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 4b6991e178d3..b33cf155cc48 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -7161,6 +7161,7 @@ static __init int selinux_init(void) selinux_state.checkreqprot = selinux_checkreqprot_boot; selinux_ss_init(&selinux_state.ss); selinux_avc_init(&selinux_state.avc); + mutex_init(&selinux_state.status_lock); /* Set the security state for the initial task. */ cred_init_security(); diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index a39f9565d80b..f3a621058aba 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -108,6 +108,10 @@ struct selinux_state { bool checkreqprot; bool initialized; bool policycap[__POLICYDB_CAPABILITY_MAX]; + + struct page *status_page; + struct mutex status_lock; + struct selinux_avc *avc; struct selinux_ss *ss; } __randomize_layout; diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 216ce602a2b5..5cf491768142 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include @@ -81,7 +80,6 @@ static struct selinux_ss selinux_ss; void selinux_ss_init(struct selinux_ss **ss) { rwlock_init(&selinux_ss.policy_rwlock); - mutex_init(&selinux_ss.status_lock); *ss = &selinux_ss; } diff --git a/security/selinux/ss/services.h b/security/selinux/ss/services.h index c5896f39e8f6..e9bddf33e53d 100644 --- a/security/selinux/ss/services.h +++ b/security/selinux/ss/services.h @@ -29,8 +29,6 @@ struct selinux_ss { rwlock_t policy_rwlock; u32 latest_granting; struct selinux_map map; - struct page *status_page; - struct mutex status_lock; } __randomize_layout; void services_compute_xperms_drivers(struct extended_perms *xperms, diff --git a/security/selinux/ss/status.c b/security/selinux/ss/status.c deleted file mode 100644 index 3c554a442467..000000000000 --- a/security/selinux/ss/status.c +++ /dev/null @@ -1,124 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * mmap based event notifications for SELinux - * - * Author: KaiGai Kohei - * - * Copyright (C) 2010 NEC corporation - */ -#include -#include -#include -#include -#include "avc.h" -#include "services.h" - -/* - * The selinux_status_page shall be exposed to userspace applications - * using mmap interface on /selinux/status. - * It enables to notify applications a few events that will cause reset - * of userspace access vector without context switching. - * - * The selinux_kernel_status structure on the head of status page is - * protected from concurrent accesses using seqlock logic, so userspace - * application should reference the status page according to the seqlock - * logic. - * - * Typically, application checks status->sequence at the head of access - * control routine. If it is odd-number, kernel is updating the status, - * so please wait for a moment. If it is changed from the last sequence - * number, it means something happen, so application will reset userspace - * avc, if needed. - * In most cases, application shall confirm the kernel status is not - * changed without any system call invocations. - */ - -/* - * selinux_kernel_status_page - * - * 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 selinux_kernel_status *status; - struct page *result = NULL; - - mutex_lock(&state->ss->status_lock); - if (!state->ss->status_page) { - state->ss->status_page = alloc_page(GFP_KERNEL|__GFP_ZERO); - - if (state->ss->status_page) { - status = page_address(state->ss->status_page); - - status->version = SELINUX_KERNEL_STATUS_VERSION; - status->sequence = 0; - status->enforcing = enforcing_enabled(state); - /* - * NOTE: the next policyload event shall set - * a positive value on the status->policyload, - * although it may not be 1, but never zero. - * So, application can know it was updated. - */ - status->policyload = 0; - status->deny_unknown = - !security_get_allow_unknown(state); - } - } - result = state->ss->status_page; - mutex_unlock(&state->ss->status_lock); - - return result; -} - -/* - * selinux_status_update_setenforce - * - * It updates status of the current enforcing/permissive mode. - */ -void selinux_status_update_setenforce(struct selinux_state *state, - int enforcing) -{ - struct selinux_kernel_status *status; - - mutex_lock(&state->ss->status_lock); - if (state->ss->status_page) { - status = page_address(state->ss->status_page); - - status->sequence++; - smp_wmb(); - - status->enforcing = enforcing; - - smp_wmb(); - status->sequence++; - } - mutex_unlock(&state->ss->status_lock); -} - -/* - * selinux_status_update_policyload - * - * 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) -{ - struct selinux_kernel_status *status; - - mutex_lock(&state->ss->status_lock); - if (state->ss->status_page) { - status = page_address(state->ss->status_page); - - status->sequence++; - smp_wmb(); - - status->policyload = seqno; - status->deny_unknown = !security_get_allow_unknown(state); - - smp_wmb(); - status->sequence++; - } - mutex_unlock(&state->ss->status_lock); -} diff --git a/security/selinux/status.c b/security/selinux/status.c new file mode 100644 index 000000000000..4bc8f809934c --- /dev/null +++ b/security/selinux/status.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * mmap based event notifications for SELinux + * + * Author: KaiGai Kohei + * + * Copyright (C) 2010 NEC corporation + */ +#include +#include +#include +#include +#include "avc.h" +#include "security.h" + +/* + * The selinux_status_page shall be exposed to userspace applications + * using mmap interface on /selinux/status. + * It enables to notify applications a few events that will cause reset + * of userspace access vector without context switching. + * + * The selinux_kernel_status structure on the head of status page is + * protected from concurrent accesses using seqlock logic, so userspace + * application should reference the status page according to the seqlock + * logic. + * + * Typically, application checks status->sequence at the head of access + * control routine. If it is odd-number, kernel is updating the status, + * so please wait for a moment. If it is changed from the last sequence + * number, it means something happen, so application will reset userspace + * avc, if needed. + * In most cases, application shall confirm the kernel status is not + * changed without any system call invocations. + */ + +/* + * selinux_kernel_status_page + * + * 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 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); + + if (state->status_page) { + status = page_address(state->status_page); + + status->version = SELINUX_KERNEL_STATUS_VERSION; + status->sequence = 0; + status->enforcing = enforcing_enabled(state); + /* + * NOTE: the next policyload event shall set + * a positive value on the status->policyload, + * although it may not be 1, but never zero. + * So, application can know it was updated. + */ + status->policyload = 0; + status->deny_unknown = + !security_get_allow_unknown(state); + } + } + result = state->status_page; + mutex_unlock(&state->status_lock); + + return result; +} + +/* + * selinux_status_update_setenforce + * + * It updates status of the current enforcing/permissive mode. + */ +void selinux_status_update_setenforce(struct selinux_state *state, + int enforcing) +{ + struct selinux_kernel_status *status; + + mutex_lock(&state->status_lock); + if (state->status_page) { + status = page_address(state->status_page); + + status->sequence++; + smp_wmb(); + + status->enforcing = enforcing; + + smp_wmb(); + status->sequence++; + } + mutex_unlock(&state->status_lock); +} + +/* + * selinux_status_update_policyload + * + * 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) +{ + struct selinux_kernel_status *status; + + mutex_lock(&state->status_lock); + if (state->status_page) { + status = page_address(state->status_page); + + status->sequence++; + smp_wmb(); + + status->policyload = seqno; + status->deny_unknown = !security_get_allow_unknown(state); + + smp_wmb(); + status->sequence++; + } + mutex_unlock(&state->status_lock); +} -- cgit v1.2.3