diff options
Diffstat (limited to 'security/selinux/include/avc.h')
-rw-r--r-- | security/selinux/include/avc.h | 100 |
1 files changed, 77 insertions, 23 deletions
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 1931370233d7..92d0ab561db8 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h | |||
@@ -49,7 +49,7 @@ struct avc_cache_stats { | |||
49 | /* | 49 | /* |
50 | * We only need this data after we have decided to send an audit message. | 50 | * We only need this data after we have decided to send an audit message. |
51 | */ | 51 | */ |
52 | struct selinux_late_audit_data { | 52 | struct selinux_audit_data { |
53 | u32 ssid; | 53 | u32 ssid; |
54 | u32 tsid; | 54 | u32 tsid; |
55 | u16 tclass; | 55 | u16 tclass; |
@@ -60,28 +60,86 @@ struct selinux_late_audit_data { | |||
60 | }; | 60 | }; |
61 | 61 | ||
62 | /* | 62 | /* |
63 | * We collect this at the beginning or during an selinux security operation | ||
64 | */ | ||
65 | struct selinux_audit_data { | ||
66 | /* | ||
67 | * auditdeny is a bit tricky and unintuitive. See the | ||
68 | * comments in avc.c for it's meaning and usage. | ||
69 | */ | ||
70 | u32 auditdeny; | ||
71 | struct selinux_late_audit_data *slad; | ||
72 | }; | ||
73 | |||
74 | /* | ||
75 | * AVC operations | 63 | * AVC operations |
76 | */ | 64 | */ |
77 | 65 | ||
78 | void __init avc_init(void); | 66 | void __init avc_init(void); |
79 | 67 | ||
80 | int avc_audit(u32 ssid, u32 tsid, | 68 | static inline u32 avc_audit_required(u32 requested, |
81 | u16 tclass, u32 requested, | 69 | struct av_decision *avd, |
82 | struct av_decision *avd, | 70 | int result, |
83 | int result, | 71 | u32 auditdeny, |
84 | struct common_audit_data *a, unsigned flags); | 72 | u32 *deniedp) |
73 | { | ||
74 | u32 denied, audited; | ||
75 | denied = requested & ~avd->allowed; | ||
76 | if (unlikely(denied)) { | ||
77 | audited = denied & avd->auditdeny; | ||
78 | /* | ||
79 | * auditdeny is TRICKY! Setting a bit in | ||
80 | * this field means that ANY denials should NOT be audited if | ||
81 | * the policy contains an explicit dontaudit rule for that | ||
82 | * permission. Take notice that this is unrelated to the | ||
83 | * actual permissions that were denied. As an example lets | ||
84 | * assume: | ||
85 | * | ||
86 | * denied == READ | ||
87 | * avd.auditdeny & ACCESS == 0 (not set means explicit rule) | ||
88 | * auditdeny & ACCESS == 1 | ||
89 | * | ||
90 | * We will NOT audit the denial even though the denied | ||
91 | * permission was READ and the auditdeny checks were for | ||
92 | * ACCESS | ||
93 | */ | ||
94 | if (auditdeny && !(auditdeny & avd->auditdeny)) | ||
95 | audited = 0; | ||
96 | } else if (result) | ||
97 | audited = denied = requested; | ||
98 | else | ||
99 | audited = requested & avd->auditallow; | ||
100 | *deniedp = denied; | ||
101 | return audited; | ||
102 | } | ||
103 | |||
104 | int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, | ||
105 | u32 requested, u32 audited, u32 denied, | ||
106 | struct common_audit_data *a, | ||
107 | unsigned flags); | ||
108 | |||
109 | /** | ||
110 | * avc_audit - Audit the granting or denial of permissions. | ||
111 | * @ssid: source security identifier | ||
112 | * @tsid: target security identifier | ||
113 | * @tclass: target security class | ||
114 | * @requested: requested permissions | ||
115 | * @avd: access vector decisions | ||
116 | * @result: result from avc_has_perm_noaudit | ||
117 | * @a: auxiliary audit data | ||
118 | * @flags: VFS walk flags | ||
119 | * | ||
120 | * Audit the granting or denial of permissions in accordance | ||
121 | * with the policy. This function is typically called by | ||
122 | * avc_has_perm() after a permission check, but can also be | ||
123 | * called directly by callers who use avc_has_perm_noaudit() | ||
124 | * in order to separate the permission check from the auditing. | ||
125 | * For example, this separation is useful when the permission check must | ||
126 | * be performed under a lock, to allow the lock to be released | ||
127 | * before calling the auditing code. | ||
128 | */ | ||
129 | static inline int avc_audit(u32 ssid, u32 tsid, | ||
130 | u16 tclass, u32 requested, | ||
131 | struct av_decision *avd, | ||
132 | int result, | ||
133 | struct common_audit_data *a, unsigned flags) | ||
134 | { | ||
135 | u32 audited, denied; | ||
136 | audited = avc_audit_required(requested, avd, result, 0, &denied); | ||
137 | if (likely(!audited)) | ||
138 | return 0; | ||
139 | return slow_avc_audit(ssid, tsid, tclass, | ||
140 | requested, audited, denied, | ||
141 | a, flags); | ||
142 | } | ||
85 | 143 | ||
86 | #define AVC_STRICT 1 /* Ignore permissive mode. */ | 144 | #define AVC_STRICT 1 /* Ignore permissive mode. */ |
87 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, | 145 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, |
@@ -112,11 +170,7 @@ u32 avc_policy_seqno(void); | |||
112 | #define AVC_CALLBACK_AUDITDENY_ENABLE 64 | 170 | #define AVC_CALLBACK_AUDITDENY_ENABLE 64 |
113 | #define AVC_CALLBACK_AUDITDENY_DISABLE 128 | 171 | #define AVC_CALLBACK_AUDITDENY_DISABLE 128 |
114 | 172 | ||
115 | int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, | 173 | int avc_add_callback(int (*callback)(u32 event), u32 events); |
116 | u16 tclass, u32 perms, | ||
117 | u32 *out_retained), | ||
118 | u32 events, u32 ssid, u32 tsid, | ||
119 | u16 tclass, u32 perms); | ||
120 | 174 | ||
121 | /* Exported to selinuxfs */ | 175 | /* Exported to selinuxfs */ |
122 | int avc_get_hash_stats(char *page); | 176 | int avc_get_hash_stats(char *page); |