selinux: treat atomic flags more carefully

The disabled/enforcing/initialized flags are all accessed concurrently
by threads so use the appropriate accessors that ensure atomicity and
document that it is expected.

Use smp_load/acquire...() helpers (with memory barriers) for the
initialized flag, since it gates access to the rest of the state
structures.

Note that the disabled flag is currently not used for anything other
than avoiding double disable, but it will be used for bailing out of
hooks once security_delete_hooks() is removed.

Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: James Morris <jamorris@linux.microsoft.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
This commit is contained in:
Ondrej Mosnacek
2020-01-07 14:31:53 +01:00
committed by Paul Moore
parent b78b7d59bd
commit 65cddd5098
3 changed files with 61 additions and 31 deletions

View File

@@ -117,15 +117,27 @@ void selinux_avc_init(struct selinux_avc **avc);
extern struct selinux_state selinux_state;
static inline bool selinux_initialized(const struct selinux_state *state)
{
/* do a synchronized load to avoid race conditions */
return smp_load_acquire(&state->initialized);
}
static inline void selinux_mark_initialized(struct selinux_state *state)
{
/* do a synchronized write to avoid race conditions */
smp_store_release(&state->initialized, true);
}
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
static inline bool enforcing_enabled(struct selinux_state *state)
{
return state->enforcing;
return READ_ONCE(state->enforcing);
}
static inline void enforcing_set(struct selinux_state *state, bool value)
{
state->enforcing = value;
WRITE_ONCE(state->enforcing, value);
}
#else
static inline bool enforcing_enabled(struct selinux_state *state)
@@ -138,6 +150,23 @@ static inline void enforcing_set(struct selinux_state *state, bool value)
}
#endif
#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;