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