diff options
author | Etienne Basset <etienne.basset@numericable.fr> | 2009-04-08 14:40:06 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2009-04-13 19:00:23 -0400 |
commit | ecfcc53fef3c357574bb6143dce6631e6d56295c (patch) | |
tree | d7bee04b64c5ad2ba0ed273bff2c8c7c98b3eee5 /security/smack/smack_access.c | |
parent | 6e837fb152410e571a81aaadbd9884f0bc46a55e (diff) |
smack: implement logging V3
the following patch, add logging of Smack security decisions.
This is of course very useful to understand what your current smack policy does.
As suggested by Casey, it also now forbids labels with ', " or \
It introduces a '/smack/logging' switch :
0: no logging
1: log denied (default)
2: log accepted
3: log denied&accepted
Signed-off-by: Etienne Basset <etienne.basset@numericable.fr>
Acked-by: Casey Schaufler <casey@schaufler-ca.com>
Acked-by: Eric Paris <eparis@redhat.com>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/smack/smack_access.c')
-rw-r--r-- | security/smack/smack_access.c | 143 |
1 files changed, 127 insertions, 16 deletions
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index ac0a2707f6d4..513dc1aa16dd 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
@@ -59,11 +59,18 @@ LIST_HEAD(smack_known_list); | |||
59 | */ | 59 | */ |
60 | static u32 smack_next_secid = 10; | 60 | static u32 smack_next_secid = 10; |
61 | 61 | ||
62 | /* | ||
63 | * what events do we log | ||
64 | * can be overwritten at run-time by /smack/logging | ||
65 | */ | ||
66 | int log_policy = SMACK_AUDIT_DENIED; | ||
67 | |||
62 | /** | 68 | /** |
63 | * smk_access - determine if a subject has a specific access to an object | 69 | * smk_access - determine if a subject has a specific access to an object |
64 | * @subject_label: a pointer to the subject's Smack label | 70 | * @subject_label: a pointer to the subject's Smack label |
65 | * @object_label: a pointer to the object's Smack label | 71 | * @object_label: a pointer to the object's Smack label |
66 | * @request: the access requested, in "MAY" format | 72 | * @request: the access requested, in "MAY" format |
73 | * @a : a pointer to the audit data | ||
67 | * | 74 | * |
68 | * This function looks up the subject/object pair in the | 75 | * This function looks up the subject/object pair in the |
69 | * access rule list and returns 0 if the access is permitted, | 76 | * access rule list and returns 0 if the access is permitted, |
@@ -78,10 +85,12 @@ static u32 smack_next_secid = 10; | |||
78 | * will be on the list, so checking the pointers may be a worthwhile | 85 | * will be on the list, so checking the pointers may be a worthwhile |
79 | * optimization. | 86 | * optimization. |
80 | */ | 87 | */ |
81 | int smk_access(char *subject_label, char *object_label, int request) | 88 | int smk_access(char *subject_label, char *object_label, int request, |
89 | struct smk_audit_info *a) | ||
82 | { | 90 | { |
83 | u32 may = MAY_NOT; | 91 | u32 may = MAY_NOT; |
84 | struct smack_rule *srp; | 92 | struct smack_rule *srp; |
93 | int rc = 0; | ||
85 | 94 | ||
86 | /* | 95 | /* |
87 | * Hardcoded comparisons. | 96 | * Hardcoded comparisons. |
@@ -89,8 +98,10 @@ int smk_access(char *subject_label, char *object_label, int request) | |||
89 | * A star subject can't access any object. | 98 | * A star subject can't access any object. |
90 | */ | 99 | */ |
91 | if (subject_label == smack_known_star.smk_known || | 100 | if (subject_label == smack_known_star.smk_known || |
92 | strcmp(subject_label, smack_known_star.smk_known) == 0) | 101 | strcmp(subject_label, smack_known_star.smk_known) == 0) { |
93 | return -EACCES; | 102 | rc = -EACCES; |
103 | goto out_audit; | ||
104 | } | ||
94 | /* | 105 | /* |
95 | * An internet object can be accessed by any subject. | 106 | * An internet object can be accessed by any subject. |
96 | * Tasks cannot be assigned the internet label. | 107 | * Tasks cannot be assigned the internet label. |
@@ -100,20 +111,20 @@ int smk_access(char *subject_label, char *object_label, int request) | |||
100 | subject_label == smack_known_web.smk_known || | 111 | subject_label == smack_known_web.smk_known || |
101 | strcmp(object_label, smack_known_web.smk_known) == 0 || | 112 | strcmp(object_label, smack_known_web.smk_known) == 0 || |
102 | strcmp(subject_label, smack_known_web.smk_known) == 0) | 113 | strcmp(subject_label, smack_known_web.smk_known) == 0) |
103 | return 0; | 114 | goto out_audit; |
104 | /* | 115 | /* |
105 | * A star object can be accessed by any subject. | 116 | * A star object can be accessed by any subject. |
106 | */ | 117 | */ |
107 | if (object_label == smack_known_star.smk_known || | 118 | if (object_label == smack_known_star.smk_known || |
108 | strcmp(object_label, smack_known_star.smk_known) == 0) | 119 | strcmp(object_label, smack_known_star.smk_known) == 0) |
109 | return 0; | 120 | goto out_audit; |
110 | /* | 121 | /* |
111 | * An object can be accessed in any way by a subject | 122 | * An object can be accessed in any way by a subject |
112 | * with the same label. | 123 | * with the same label. |
113 | */ | 124 | */ |
114 | if (subject_label == object_label || | 125 | if (subject_label == object_label || |
115 | strcmp(subject_label, object_label) == 0) | 126 | strcmp(subject_label, object_label) == 0) |
116 | return 0; | 127 | goto out_audit; |
117 | /* | 128 | /* |
118 | * A hat subject can read any object. | 129 | * A hat subject can read any object. |
119 | * A floor object can be read by any subject. | 130 | * A floor object can be read by any subject. |
@@ -121,10 +132,10 @@ int smk_access(char *subject_label, char *object_label, int request) | |||
121 | if ((request & MAY_ANYREAD) == request) { | 132 | if ((request & MAY_ANYREAD) == request) { |
122 | if (object_label == smack_known_floor.smk_known || | 133 | if (object_label == smack_known_floor.smk_known || |
123 | strcmp(object_label, smack_known_floor.smk_known) == 0) | 134 | strcmp(object_label, smack_known_floor.smk_known) == 0) |
124 | return 0; | 135 | goto out_audit; |
125 | if (subject_label == smack_known_hat.smk_known || | 136 | if (subject_label == smack_known_hat.smk_known || |
126 | strcmp(subject_label, smack_known_hat.smk_known) == 0) | 137 | strcmp(subject_label, smack_known_hat.smk_known) == 0) |
127 | return 0; | 138 | goto out_audit; |
128 | } | 139 | } |
129 | /* | 140 | /* |
130 | * Beyond here an explicit relationship is required. | 141 | * Beyond here an explicit relationship is required. |
@@ -148,28 +159,36 @@ int smk_access(char *subject_label, char *object_label, int request) | |||
148 | * This is a bit map operation. | 159 | * This is a bit map operation. |
149 | */ | 160 | */ |
150 | if ((request & may) == request) | 161 | if ((request & may) == request) |
151 | return 0; | 162 | goto out_audit; |
152 | 163 | ||
153 | return -EACCES; | 164 | rc = -EACCES; |
165 | out_audit: | ||
166 | #ifdef CONFIG_AUDIT | ||
167 | if (a) | ||
168 | smack_log(subject_label, object_label, request, rc, a); | ||
169 | #endif | ||
170 | return rc; | ||
154 | } | 171 | } |
155 | 172 | ||
156 | /** | 173 | /** |
157 | * smk_curacc - determine if current has a specific access to an object | 174 | * smk_curacc - determine if current has a specific access to an object |
158 | * @obj_label: a pointer to the object's Smack label | 175 | * @obj_label: a pointer to the object's Smack label |
159 | * @mode: the access requested, in "MAY" format | 176 | * @mode: the access requested, in "MAY" format |
177 | * @a : common audit data | ||
160 | * | 178 | * |
161 | * This function checks the current subject label/object label pair | 179 | * This function checks the current subject label/object label pair |
162 | * in the access rule list and returns 0 if the access is permitted, | 180 | * in the access rule list and returns 0 if the access is permitted, |
163 | * non zero otherwise. It allows that current may have the capability | 181 | * non zero otherwise. It allows that current may have the capability |
164 | * to override the rules. | 182 | * to override the rules. |
165 | */ | 183 | */ |
166 | int smk_curacc(char *obj_label, u32 mode) | 184 | int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) |
167 | { | 185 | { |
168 | int rc; | 186 | int rc; |
187 | char *sp = current_security(); | ||
169 | 188 | ||
170 | rc = smk_access(current_security(), obj_label, mode); | 189 | rc = smk_access(sp, obj_label, mode, NULL); |
171 | if (rc == 0) | 190 | if (rc == 0) |
172 | return 0; | 191 | goto out_audit; |
173 | 192 | ||
174 | /* | 193 | /* |
175 | * Return if a specific label has been designated as the | 194 | * Return if a specific label has been designated as the |
@@ -177,14 +196,105 @@ int smk_curacc(char *obj_label, u32 mode) | |||
177 | * have that label. | 196 | * have that label. |
178 | */ | 197 | */ |
179 | if (smack_onlycap != NULL && smack_onlycap != current->cred->security) | 198 | if (smack_onlycap != NULL && smack_onlycap != current->cred->security) |
180 | return rc; | 199 | goto out_audit; |
181 | 200 | ||
182 | if (capable(CAP_MAC_OVERRIDE)) | 201 | if (capable(CAP_MAC_OVERRIDE)) |
183 | return 0; | 202 | return 0; |
184 | 203 | ||
204 | out_audit: | ||
205 | #ifdef CONFIG_AUDIT | ||
206 | if (a) | ||
207 | smack_log(sp, obj_label, mode, rc, a); | ||
208 | #endif | ||
185 | return rc; | 209 | return rc; |
186 | } | 210 | } |
187 | 211 | ||
212 | #ifdef CONFIG_AUDIT | ||
213 | /** | ||
214 | * smack_str_from_perm : helper to transalate an int to a | ||
215 | * readable string | ||
216 | * @string : the string to fill | ||
217 | * @access : the int | ||
218 | * | ||
219 | */ | ||
220 | static inline void smack_str_from_perm(char *string, int access) | ||
221 | { | ||
222 | int i = 0; | ||
223 | if (access & MAY_READ) | ||
224 | string[i++] = 'r'; | ||
225 | if (access & MAY_WRITE) | ||
226 | string[i++] = 'w'; | ||
227 | if (access & MAY_EXEC) | ||
228 | string[i++] = 'x'; | ||
229 | if (access & MAY_APPEND) | ||
230 | string[i++] = 'a'; | ||
231 | string[i] = '\0'; | ||
232 | } | ||
233 | /** | ||
234 | * smack_log_callback - SMACK specific information | ||
235 | * will be called by generic audit code | ||
236 | * @ab : the audit_buffer | ||
237 | * @a : audit_data | ||
238 | * | ||
239 | */ | ||
240 | static void smack_log_callback(struct audit_buffer *ab, void *a) | ||
241 | { | ||
242 | struct common_audit_data *ad = a; | ||
243 | struct smack_audit_data *sad = &ad->lsm_priv.smack_audit_data; | ||
244 | audit_log_format(ab, "lsm=SMACK fn=%s action=%s", ad->function, | ||
245 | sad->result ? "denied" : "granted"); | ||
246 | audit_log_format(ab, " subject="); | ||
247 | audit_log_untrustedstring(ab, sad->subject); | ||
248 | audit_log_format(ab, " object="); | ||
249 | audit_log_untrustedstring(ab, sad->object); | ||
250 | audit_log_format(ab, " requested=%s", sad->request); | ||
251 | } | ||
252 | |||
253 | /** | ||
254 | * smack_log - Audit the granting or denial of permissions. | ||
255 | * @subject_label : smack label of the requester | ||
256 | * @object_label : smack label of the object being accessed | ||
257 | * @request: requested permissions | ||
258 | * @result: result from smk_access | ||
259 | * @a: auxiliary audit data | ||
260 | * | ||
261 | * Audit the granting or denial of permissions in accordance | ||
262 | * with the policy. | ||
263 | */ | ||
264 | void smack_log(char *subject_label, char *object_label, int request, | ||
265 | int result, struct smk_audit_info *ad) | ||
266 | { | ||
267 | char request_buffer[SMK_NUM_ACCESS_TYPE + 1]; | ||
268 | struct smack_audit_data *sad; | ||
269 | struct common_audit_data *a = &ad->a; | ||
270 | |||
271 | /* check if we have to log the current event */ | ||
272 | if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0) | ||
273 | return; | ||
274 | if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0) | ||
275 | return; | ||
276 | |||
277 | if (a->function == NULL) | ||
278 | a->function = "unknown"; | ||
279 | |||
280 | /* end preparing the audit data */ | ||
281 | sad = &a->lsm_priv.smack_audit_data; | ||
282 | smack_str_from_perm(request_buffer, request); | ||
283 | sad->subject = subject_label; | ||
284 | sad->object = object_label; | ||
285 | sad->request = request_buffer; | ||
286 | sad->result = result; | ||
287 | a->lsm_pre_audit = smack_log_callback; | ||
288 | |||
289 | common_lsm_audit(a); | ||
290 | } | ||
291 | #else /* #ifdef CONFIG_AUDIT */ | ||
292 | void smack_log(char *subject_label, char *object_label, int request, | ||
293 | int result, struct smk_audit_info *ad) | ||
294 | { | ||
295 | } | ||
296 | #endif | ||
297 | |||
188 | static DEFINE_MUTEX(smack_known_lock); | 298 | static DEFINE_MUTEX(smack_known_lock); |
189 | 299 | ||
190 | /** | 300 | /** |
@@ -209,7 +319,8 @@ struct smack_known *smk_import_entry(const char *string, int len) | |||
209 | if (found) | 319 | if (found) |
210 | smack[i] = '\0'; | 320 | smack[i] = '\0'; |
211 | else if (i >= len || string[i] > '~' || string[i] <= ' ' || | 321 | else if (i >= len || string[i] > '~' || string[i] <= ' ' || |
212 | string[i] == '/') { | 322 | string[i] == '/' || string[i] == '"' || |
323 | string[i] == '\\' || string[i] == '\'') { | ||
213 | smack[i] = '\0'; | 324 | smack[i] = '\0'; |
214 | found = 1; | 325 | found = 1; |
215 | } else | 326 | } else |