^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * mmap based event notifications for SELinux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author: KaiGai Kohei <kaigai@ak.jp.nec.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2010 NEC corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "avc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "security.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * The selinux_status_page shall be exposed to userspace applications
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * using mmap interface on /selinux/status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * It enables to notify applications a few events that will cause reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * of userspace access vector without context switching.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * The selinux_kernel_status structure on the head of status page is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * protected from concurrent accesses using seqlock logic, so userspace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * application should reference the status page according to the seqlock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * logic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * Typically, application checks status->sequence at the head of access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * control routine. If it is odd-number, kernel is updating the status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * so please wait for a moment. If it is changed from the last sequence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * number, it means something happen, so application will reset userspace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * avc, if needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * In most cases, application shall confirm the kernel status is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * changed without any system call invocations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * selinux_kernel_status_page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * It returns a reference to selinux_status_page. If the status page is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * not allocated yet, it also tries to allocate it at the first time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct page *selinux_kernel_status_page(struct selinux_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct selinux_kernel_status *status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct page *result = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) mutex_lock(&state->status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (!state->status_page) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) state->status_page = alloc_page(GFP_KERNEL|__GFP_ZERO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (state->status_page) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) status = page_address(state->status_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) status->version = SELINUX_KERNEL_STATUS_VERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) status->sequence = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) status->enforcing = enforcing_enabled(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * NOTE: the next policyload event shall set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * a positive value on the status->policyload,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * although it may not be 1, but never zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * So, application can know it was updated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) status->policyload = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) status->deny_unknown =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) !security_get_allow_unknown(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) result = state->status_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) mutex_unlock(&state->status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * selinux_status_update_setenforce
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * It updates status of the current enforcing/permissive mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) void selinux_status_update_setenforce(struct selinux_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int enforcing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct selinux_kernel_status *status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) mutex_lock(&state->status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (state->status_page) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) status = page_address(state->status_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) status->sequence++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) smp_wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) status->enforcing = enforcing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) smp_wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) status->sequence++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) mutex_unlock(&state->status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * selinux_status_update_policyload
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * It updates status of the times of policy reloaded, and current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * setting of deny_unknown.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) void selinux_status_update_policyload(struct selinux_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) int seqno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct selinux_kernel_status *status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) mutex_lock(&state->status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (state->status_page) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) status = page_address(state->status_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) status->sequence++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) smp_wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) status->policyload = seqno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) status->deny_unknown = !security_get_allow_unknown(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) smp_wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) status->sequence++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) mutex_unlock(&state->status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }