/*
 * pi3's Linux kernel Runtime Guard
 *
 * Component:
 *  - Intercept 'sel_write_enforce' function
 *
 * Notes:
 *  - Intercept SELinux state modifications
 *
 * Caveats:
 *  - None
 *
 * Timeline:
 *  - Created: 13.XI.2017
 *
 * Author:
 *  - Adam 'pi3' Zabrocki (http://pi3.com.pl)
 *
 */


#ifdef CONFIG_SECURITY_SELINUX_DEVELOP

#include "../../../../p_lkrg_main.h"

static int p_sel_write_enforce_entry(struct kretprobe_instance *p_ri, struct pt_regs *p_regs) {

   struct p_ed_process *p_tmp;
   if ((p_tmp = ed_task_lock_current())) {
      // This process is on the ED list - validate 'off' flag
      p_ed_is_off_off_wrap(p_tmp);
      ed_task_unlock(p_tmp);
   }

   p_ed_enforce_validation();

   // lock shadow SELinux updates
   p_lkrg_counter_lock_lock(&p_ed_guard_globals.p_selinux_lock);
   p_lkrg_counter_lock_val_inc(&p_ed_guard_globals.p_selinux_lock);
   p_lkrg_counter_lock_unlock(&p_ed_guard_globals.p_selinux_lock);

   return 0;
}

static int p_sel_write_enforce_ret(struct kretprobe_instance *p_ri, struct pt_regs *p_regs) {

   // Success ?
   if (!IS_ERR((void *)p_regs_get_ret(p_regs))) {
      // track down new SELinux information
#ifdef P_SELINUX_VERIFY
      p_selinux_state_update();
#endif
#if (!defined(RHEL_RELEASE_CODE) && LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0)) || \
     (defined(RHEL_RELEASE_CODE) && RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8, 3))
      p_ed_guard_globals.p_selinux.p_selinux_enabled = *P_SYM(p_selinux_enabled);
#endif
   }

   // unlock shadow SELinux updates
   p_lkrg_counter_lock_val_dec(&p_ed_guard_globals.p_selinux_lock);

   p_ed_enforce_validation();

   return 0;
}

static struct lkrg_probe p_sel_write_enforce_probe = {
  .type = LKRG_KRETPROBE,
  .krp = {
    .kp.symbol_name = "sel_write_enforce",
    .handler = p_sel_write_enforce_ret,
    .entry_handler = p_sel_write_enforce_entry,
  }
};

GENERATE_INSTALL_FUNC(sel_write_enforce)

#endif
