root/security/selinux/ss/status.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. selinux_kernel_status_page
  2. selinux_status_update_setenforce
  3. selinux_status_update_policyload

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

/* [<][>][^][v][top][bottom][index][help] */