18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Access vector cache interface for object managers. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author : Stephen Smalley, <sds@tycho.nsa.gov> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci#ifndef _SELINUX_AVC_H_ 88c2ecf20Sopenharmony_ci#define _SELINUX_AVC_H_ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/stddef.h> 118c2ecf20Sopenharmony_ci#include <linux/errno.h> 128c2ecf20Sopenharmony_ci#include <linux/kernel.h> 138c2ecf20Sopenharmony_ci#include <linux/kdev_t.h> 148c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 158c2ecf20Sopenharmony_ci#include <linux/init.h> 168c2ecf20Sopenharmony_ci#include <linux/audit.h> 178c2ecf20Sopenharmony_ci#include <linux/lsm_audit.h> 188c2ecf20Sopenharmony_ci#include <linux/in6.h> 198c2ecf20Sopenharmony_ci#include "flask.h" 208c2ecf20Sopenharmony_ci#include "av_permissions.h" 218c2ecf20Sopenharmony_ci#include "security.h" 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/* 248c2ecf20Sopenharmony_ci * An entry in the AVC. 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_cistruct avc_entry; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistruct task_struct; 298c2ecf20Sopenharmony_cistruct inode; 308c2ecf20Sopenharmony_cistruct sock; 318c2ecf20Sopenharmony_cistruct sk_buff; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/* 348c2ecf20Sopenharmony_ci * AVC statistics 358c2ecf20Sopenharmony_ci */ 368c2ecf20Sopenharmony_cistruct avc_cache_stats { 378c2ecf20Sopenharmony_ci unsigned int lookups; 388c2ecf20Sopenharmony_ci unsigned int misses; 398c2ecf20Sopenharmony_ci unsigned int allocations; 408c2ecf20Sopenharmony_ci unsigned int reclaims; 418c2ecf20Sopenharmony_ci unsigned int frees; 428c2ecf20Sopenharmony_ci}; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci/* 458c2ecf20Sopenharmony_ci * We only need this data after we have decided to send an audit message. 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_cistruct selinux_audit_data { 488c2ecf20Sopenharmony_ci u32 ssid; 498c2ecf20Sopenharmony_ci u32 tsid; 508c2ecf20Sopenharmony_ci u16 tclass; 518c2ecf20Sopenharmony_ci u32 requested; 528c2ecf20Sopenharmony_ci u32 audited; 538c2ecf20Sopenharmony_ci u32 denied; 548c2ecf20Sopenharmony_ci int result; 558c2ecf20Sopenharmony_ci struct selinux_state *state; 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/* 598c2ecf20Sopenharmony_ci * AVC operations 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_civoid __init avc_init(void); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic inline u32 avc_audit_required(u32 requested, 658c2ecf20Sopenharmony_ci struct av_decision *avd, 668c2ecf20Sopenharmony_ci int result, 678c2ecf20Sopenharmony_ci u32 auditdeny, 688c2ecf20Sopenharmony_ci u32 *deniedp) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci u32 denied, audited; 718c2ecf20Sopenharmony_ci denied = requested & ~avd->allowed; 728c2ecf20Sopenharmony_ci if (unlikely(denied)) { 738c2ecf20Sopenharmony_ci audited = denied & avd->auditdeny; 748c2ecf20Sopenharmony_ci /* 758c2ecf20Sopenharmony_ci * auditdeny is TRICKY! Setting a bit in 768c2ecf20Sopenharmony_ci * this field means that ANY denials should NOT be audited if 778c2ecf20Sopenharmony_ci * the policy contains an explicit dontaudit rule for that 788c2ecf20Sopenharmony_ci * permission. Take notice that this is unrelated to the 798c2ecf20Sopenharmony_ci * actual permissions that were denied. As an example lets 808c2ecf20Sopenharmony_ci * assume: 818c2ecf20Sopenharmony_ci * 828c2ecf20Sopenharmony_ci * denied == READ 838c2ecf20Sopenharmony_ci * avd.auditdeny & ACCESS == 0 (not set means explicit rule) 848c2ecf20Sopenharmony_ci * auditdeny & ACCESS == 1 858c2ecf20Sopenharmony_ci * 868c2ecf20Sopenharmony_ci * We will NOT audit the denial even though the denied 878c2ecf20Sopenharmony_ci * permission was READ and the auditdeny checks were for 888c2ecf20Sopenharmony_ci * ACCESS 898c2ecf20Sopenharmony_ci */ 908c2ecf20Sopenharmony_ci if (auditdeny && !(auditdeny & avd->auditdeny)) 918c2ecf20Sopenharmony_ci audited = 0; 928c2ecf20Sopenharmony_ci } else if (result) 938c2ecf20Sopenharmony_ci audited = denied = requested; 948c2ecf20Sopenharmony_ci else 958c2ecf20Sopenharmony_ci audited = requested & avd->auditallow; 968c2ecf20Sopenharmony_ci *deniedp = denied; 978c2ecf20Sopenharmony_ci return audited; 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ciint slow_avc_audit(struct selinux_state *state, 1018c2ecf20Sopenharmony_ci u32 ssid, u32 tsid, u16 tclass, 1028c2ecf20Sopenharmony_ci u32 requested, u32 audited, u32 denied, int result, 1038c2ecf20Sopenharmony_ci struct common_audit_data *a); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci/** 1068c2ecf20Sopenharmony_ci * avc_audit - Audit the granting or denial of permissions. 1078c2ecf20Sopenharmony_ci * @ssid: source security identifier 1088c2ecf20Sopenharmony_ci * @tsid: target security identifier 1098c2ecf20Sopenharmony_ci * @tclass: target security class 1108c2ecf20Sopenharmony_ci * @requested: requested permissions 1118c2ecf20Sopenharmony_ci * @avd: access vector decisions 1128c2ecf20Sopenharmony_ci * @result: result from avc_has_perm_noaudit 1138c2ecf20Sopenharmony_ci * @a: auxiliary audit data 1148c2ecf20Sopenharmony_ci * @flags: VFS walk flags 1158c2ecf20Sopenharmony_ci * 1168c2ecf20Sopenharmony_ci * Audit the granting or denial of permissions in accordance 1178c2ecf20Sopenharmony_ci * with the policy. This function is typically called by 1188c2ecf20Sopenharmony_ci * avc_has_perm() after a permission check, but can also be 1198c2ecf20Sopenharmony_ci * called directly by callers who use avc_has_perm_noaudit() 1208c2ecf20Sopenharmony_ci * in order to separate the permission check from the auditing. 1218c2ecf20Sopenharmony_ci * For example, this separation is useful when the permission check must 1228c2ecf20Sopenharmony_ci * be performed under a lock, to allow the lock to be released 1238c2ecf20Sopenharmony_ci * before calling the auditing code. 1248c2ecf20Sopenharmony_ci */ 1258c2ecf20Sopenharmony_cistatic inline int avc_audit(struct selinux_state *state, 1268c2ecf20Sopenharmony_ci u32 ssid, u32 tsid, 1278c2ecf20Sopenharmony_ci u16 tclass, u32 requested, 1288c2ecf20Sopenharmony_ci struct av_decision *avd, 1298c2ecf20Sopenharmony_ci int result, 1308c2ecf20Sopenharmony_ci struct common_audit_data *a, 1318c2ecf20Sopenharmony_ci int flags) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci u32 audited, denied; 1348c2ecf20Sopenharmony_ci audited = avc_audit_required(requested, avd, result, 0, &denied); 1358c2ecf20Sopenharmony_ci if (likely(!audited)) 1368c2ecf20Sopenharmony_ci return 0; 1378c2ecf20Sopenharmony_ci /* fall back to ref-walk if we have to generate audit */ 1388c2ecf20Sopenharmony_ci if (flags & MAY_NOT_BLOCK) 1398c2ecf20Sopenharmony_ci return -ECHILD; 1408c2ecf20Sopenharmony_ci return slow_avc_audit(state, ssid, tsid, tclass, 1418c2ecf20Sopenharmony_ci requested, audited, denied, result, 1428c2ecf20Sopenharmony_ci a); 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci#define AVC_STRICT 1 /* Ignore permissive mode. */ 1468c2ecf20Sopenharmony_ci#define AVC_EXTENDED_PERMS 2 /* update extended permissions */ 1478c2ecf20Sopenharmony_ci#define AVC_NONBLOCKING 4 /* non blocking */ 1488c2ecf20Sopenharmony_ciint avc_has_perm_noaudit(struct selinux_state *state, 1498c2ecf20Sopenharmony_ci u32 ssid, u32 tsid, 1508c2ecf20Sopenharmony_ci u16 tclass, u32 requested, 1518c2ecf20Sopenharmony_ci unsigned flags, 1528c2ecf20Sopenharmony_ci struct av_decision *avd); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ciint avc_has_perm(struct selinux_state *state, 1558c2ecf20Sopenharmony_ci u32 ssid, u32 tsid, 1568c2ecf20Sopenharmony_ci u16 tclass, u32 requested, 1578c2ecf20Sopenharmony_ci struct common_audit_data *auditdata); 1588c2ecf20Sopenharmony_ciint avc_has_perm_flags(struct selinux_state *state, 1598c2ecf20Sopenharmony_ci u32 ssid, u32 tsid, 1608c2ecf20Sopenharmony_ci u16 tclass, u32 requested, 1618c2ecf20Sopenharmony_ci struct common_audit_data *auditdata, 1628c2ecf20Sopenharmony_ci int flags); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ciint avc_has_extended_perms(struct selinux_state *state, 1658c2ecf20Sopenharmony_ci u32 ssid, u32 tsid, u16 tclass, u32 requested, 1668c2ecf20Sopenharmony_ci u8 driver, u8 perm, struct common_audit_data *ad); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ciu32 avc_policy_seqno(struct selinux_state *state); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci#define AVC_CALLBACK_GRANT 1 1728c2ecf20Sopenharmony_ci#define AVC_CALLBACK_TRY_REVOKE 2 1738c2ecf20Sopenharmony_ci#define AVC_CALLBACK_REVOKE 4 1748c2ecf20Sopenharmony_ci#define AVC_CALLBACK_RESET 8 1758c2ecf20Sopenharmony_ci#define AVC_CALLBACK_AUDITALLOW_ENABLE 16 1768c2ecf20Sopenharmony_ci#define AVC_CALLBACK_AUDITALLOW_DISABLE 32 1778c2ecf20Sopenharmony_ci#define AVC_CALLBACK_AUDITDENY_ENABLE 64 1788c2ecf20Sopenharmony_ci#define AVC_CALLBACK_AUDITDENY_DISABLE 128 1798c2ecf20Sopenharmony_ci#define AVC_CALLBACK_ADD_XPERMS 256 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ciint avc_add_callback(int (*callback)(u32 event), u32 events); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci/* Exported to selinuxfs */ 1848c2ecf20Sopenharmony_cistruct selinux_avc; 1858c2ecf20Sopenharmony_ciint avc_get_hash_stats(struct selinux_avc *avc, char *page); 1868c2ecf20Sopenharmony_ciunsigned int avc_get_cache_threshold(struct selinux_avc *avc); 1878c2ecf20Sopenharmony_civoid avc_set_cache_threshold(struct selinux_avc *avc, 1888c2ecf20Sopenharmony_ci unsigned int cache_threshold); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci/* Attempt to free avc node cache */ 1918c2ecf20Sopenharmony_civoid avc_disable(void); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci#ifdef CONFIG_SECURITY_SELINUX_AVC_STATS 1948c2ecf20Sopenharmony_ciDECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats); 1958c2ecf20Sopenharmony_ci#endif 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci#endif /* _SELINUX_AVC_H_ */ 1988c2ecf20Sopenharmony_ci 199