GNU Linux-libre 4.4.300-gnu1
[releases.git] / security / smack / smack_access.c
1 /*
2  * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com>
3  *
4  *      This program is free software; you can redistribute it and/or modify
5  *      it under the terms of the GNU General Public License as published by
6  *      the Free Software Foundation, version 2.
7  *
8  * Author:
9  *      Casey Schaufler <casey@schaufler-ca.com>
10  *
11  */
12
13 #include <linux/types.h>
14 #include <linux/slab.h>
15 #include <linux/fs.h>
16 #include <linux/sched.h>
17 #include "smack.h"
18
19 struct smack_known smack_known_huh = {
20         .smk_known      = "?",
21         .smk_secid      = 2,
22 };
23
24 struct smack_known smack_known_hat = {
25         .smk_known      = "^",
26         .smk_secid      = 3,
27 };
28
29 struct smack_known smack_known_star = {
30         .smk_known      = "*",
31         .smk_secid      = 4,
32 };
33
34 struct smack_known smack_known_floor = {
35         .smk_known      = "_",
36         .smk_secid      = 5,
37 };
38
39 struct smack_known smack_known_invalid = {
40         .smk_known      = "",
41         .smk_secid      = 6,
42 };
43
44 struct smack_known smack_known_web = {
45         .smk_known      = "@",
46         .smk_secid      = 7,
47 };
48
49 LIST_HEAD(smack_known_list);
50
51 /*
52  * The initial value needs to be bigger than any of the
53  * known values above.
54  */
55 static u32 smack_next_secid = 10;
56
57 /*
58  * what events do we log
59  * can be overwritten at run-time by /smack/logging
60  */
61 int log_policy = SMACK_AUDIT_DENIED;
62
63 /**
64  * smk_access_entry - look up matching access rule
65  * @subject_label: a pointer to the subject's Smack label
66  * @object_label: a pointer to the object's Smack label
67  * @rule_list: the list of rules to search
68  *
69  * This function looks up the subject/object pair in the
70  * access rule list and returns the access mode. If no
71  * entry is found returns -ENOENT.
72  *
73  * NOTE:
74  *
75  * Earlier versions of this function allowed for labels that
76  * were not on the label list. This was done to allow for
77  * labels to come over the network that had never been seen
78  * before on this host. Unless the receiving socket has the
79  * star label this will always result in a failure check. The
80  * star labeled socket case is now handled in the networking
81  * hooks so there is no case where the label is not on the
82  * label list. Checking to see if the address of two labels
83  * is the same is now a reliable test.
84  *
85  * Do the object check first because that is more
86  * likely to differ.
87  *
88  * Allowing write access implies allowing locking.
89  */
90 int smk_access_entry(char *subject_label, char *object_label,
91                         struct list_head *rule_list)
92 {
93         struct smack_rule *srp;
94
95         list_for_each_entry_rcu(srp, rule_list, list) {
96                 if (srp->smk_object->smk_known == object_label &&
97                     srp->smk_subject->smk_known == subject_label) {
98                         int may = srp->smk_access;
99                         /*
100                          * MAY_WRITE implies MAY_LOCK.
101                          */
102                         if ((may & MAY_WRITE) == MAY_WRITE)
103                                 may |= MAY_LOCK;
104                         return may;
105                 }
106         }
107
108         return -ENOENT;
109 }
110
111 /**
112  * smk_access - determine if a subject has a specific access to an object
113  * @subject: a pointer to the subject's Smack label entry
114  * @object: a pointer to the object's Smack label entry
115  * @request: the access requested, in "MAY" format
116  * @a : a pointer to the audit data
117  *
118  * This function looks up the subject/object pair in the
119  * access rule list and returns 0 if the access is permitted,
120  * non zero otherwise.
121  *
122  * Smack labels are shared on smack_list
123  */
124 int smk_access(struct smack_known *subject, struct smack_known *object,
125                int request, struct smk_audit_info *a)
126 {
127         int may = MAY_NOT;
128         int rc = 0;
129
130         /*
131          * Hardcoded comparisons.
132          */
133         /*
134          * A star subject can't access any object.
135          */
136         if (subject == &smack_known_star) {
137                 rc = -EACCES;
138                 goto out_audit;
139         }
140         /*
141          * An internet object can be accessed by any subject.
142          * Tasks cannot be assigned the internet label.
143          * An internet subject can access any object.
144          */
145         if (object == &smack_known_web || subject == &smack_known_web)
146                 goto out_audit;
147         /*
148          * A star object can be accessed by any subject.
149          */
150         if (object == &smack_known_star)
151                 goto out_audit;
152         /*
153          * An object can be accessed in any way by a subject
154          * with the same label.
155          */
156         if (subject->smk_known == object->smk_known)
157                 goto out_audit;
158         /*
159          * A hat subject can read or lock any object.
160          * A floor object can be read or locked by any subject.
161          */
162         if ((request & MAY_ANYREAD) == request ||
163             (request & MAY_LOCK) == request) {
164                 if (object == &smack_known_floor)
165                         goto out_audit;
166                 if (subject == &smack_known_hat)
167                         goto out_audit;
168         }
169         /*
170          * Beyond here an explicit relationship is required.
171          * If the requested access is contained in the available
172          * access (e.g. read is included in readwrite) it's
173          * good. A negative response from smk_access_entry()
174          * indicates there is no entry for this pair.
175          */
176         rcu_read_lock();
177         may = smk_access_entry(subject->smk_known, object->smk_known,
178                                &subject->smk_rules);
179         rcu_read_unlock();
180
181         if (may <= 0 || (request & may) != request) {
182                 rc = -EACCES;
183                 goto out_audit;
184         }
185 #ifdef CONFIG_SECURITY_SMACK_BRINGUP
186         /*
187          * Return a positive value if using bringup mode.
188          * This allows the hooks to identify checks that
189          * succeed because of "b" rules.
190          */
191         if (may & MAY_BRINGUP)
192                 rc = SMACK_BRINGUP_ALLOW;
193 #endif
194
195 out_audit:
196
197 #ifdef CONFIG_SECURITY_SMACK_BRINGUP
198         if (rc < 0) {
199                 if (object == smack_unconfined)
200                         rc = SMACK_UNCONFINED_OBJECT;
201                 if (subject == smack_unconfined)
202                         rc = SMACK_UNCONFINED_SUBJECT;
203         }
204 #endif
205
206 #ifdef CONFIG_AUDIT
207         if (a)
208                 smack_log(subject->smk_known, object->smk_known,
209                           request, rc, a);
210 #endif
211
212         return rc;
213 }
214
215 /**
216  * smk_tskacc - determine if a task has a specific access to an object
217  * @tsp: a pointer to the subject's task
218  * @obj_known: a pointer to the object's label entry
219  * @mode: the access requested, in "MAY" format
220  * @a : common audit data
221  *
222  * This function checks the subject task's label/object label pair
223  * in the access rule list and returns 0 if the access is permitted,
224  * non zero otherwise. It allows that the task may have the capability
225  * to override the rules.
226  */
227 int smk_tskacc(struct task_smack *tsp, struct smack_known *obj_known,
228                u32 mode, struct smk_audit_info *a)
229 {
230         struct smack_known *sbj_known = smk_of_task(tsp);
231         int may;
232         int rc;
233
234         /*
235          * Check the global rule list
236          */
237         rc = smk_access(sbj_known, obj_known, mode, NULL);
238         if (rc >= 0) {
239                 /*
240                  * If there is an entry in the task's rule list
241                  * it can further restrict access.
242                  */
243                 may = smk_access_entry(sbj_known->smk_known,
244                                        obj_known->smk_known,
245                                        &tsp->smk_rules);
246                 if (may < 0)
247                         goto out_audit;
248                 if ((mode & may) == mode)
249                         goto out_audit;
250                 rc = -EACCES;
251         }
252
253         /*
254          * Allow for priviliged to override policy.
255          */
256         if (rc != 0 && smack_privileged(CAP_MAC_OVERRIDE))
257                 rc = 0;
258
259 out_audit:
260 #ifdef CONFIG_AUDIT
261         if (a)
262                 smack_log(sbj_known->smk_known, obj_known->smk_known,
263                           mode, rc, a);
264 #endif
265         return rc;
266 }
267
268 /**
269  * smk_curacc - determine if current has a specific access to an object
270  * @obj_known: a pointer to the object's Smack label entry
271  * @mode: the access requested, in "MAY" format
272  * @a : common audit data
273  *
274  * This function checks the current subject label/object label pair
275  * in the access rule list and returns 0 if the access is permitted,
276  * non zero otherwise. It allows that current may have the capability
277  * to override the rules.
278  */
279 int smk_curacc(struct smack_known *obj_known,
280                u32 mode, struct smk_audit_info *a)
281 {
282         struct task_smack *tsp = current_security();
283
284         return smk_tskacc(tsp, obj_known, mode, a);
285 }
286
287 #ifdef CONFIG_AUDIT
288 /**
289  * smack_str_from_perm : helper to transalate an int to a
290  * readable string
291  * @string : the string to fill
292  * @access : the int
293  *
294  */
295 static inline void smack_str_from_perm(char *string, int access)
296 {
297         int i = 0;
298
299         if (access & MAY_READ)
300                 string[i++] = 'r';
301         if (access & MAY_WRITE)
302                 string[i++] = 'w';
303         if (access & MAY_EXEC)
304                 string[i++] = 'x';
305         if (access & MAY_APPEND)
306                 string[i++] = 'a';
307         if (access & MAY_TRANSMUTE)
308                 string[i++] = 't';
309         if (access & MAY_LOCK)
310                 string[i++] = 'l';
311         string[i] = '\0';
312 }
313 /**
314  * smack_log_callback - SMACK specific information
315  * will be called by generic audit code
316  * @ab : the audit_buffer
317  * @a  : audit_data
318  *
319  */
320 static void smack_log_callback(struct audit_buffer *ab, void *a)
321 {
322         struct common_audit_data *ad = a;
323         struct smack_audit_data *sad = ad->smack_audit_data;
324         audit_log_format(ab, "lsm=SMACK fn=%s action=%s",
325                          ad->smack_audit_data->function,
326                          sad->result ? "denied" : "granted");
327         audit_log_format(ab, " subject=");
328         audit_log_untrustedstring(ab, sad->subject);
329         audit_log_format(ab, " object=");
330         audit_log_untrustedstring(ab, sad->object);
331         if (sad->request[0] == '\0')
332                 audit_log_format(ab, " labels_differ");
333         else
334                 audit_log_format(ab, " requested=%s", sad->request);
335 }
336
337 /**
338  *  smack_log - Audit the granting or denial of permissions.
339  *  @subject_label : smack label of the requester
340  *  @object_label  : smack label of the object being accessed
341  *  @request: requested permissions
342  *  @result: result from smk_access
343  *  @a:  auxiliary audit data
344  *
345  * Audit the granting or denial of permissions in accordance
346  * with the policy.
347  */
348 void smack_log(char *subject_label, char *object_label, int request,
349                int result, struct smk_audit_info *ad)
350 {
351 #ifdef CONFIG_SECURITY_SMACK_BRINGUP
352         char request_buffer[SMK_NUM_ACCESS_TYPE + 5];
353 #else
354         char request_buffer[SMK_NUM_ACCESS_TYPE + 1];
355 #endif
356         struct smack_audit_data *sad;
357         struct common_audit_data *a = &ad->a;
358
359         /* check if we have to log the current event */
360         if (result < 0 && (log_policy & SMACK_AUDIT_DENIED) == 0)
361                 return;
362         if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
363                 return;
364
365         sad = a->smack_audit_data;
366
367         if (sad->function == NULL)
368                 sad->function = "unknown";
369
370         /* end preparing the audit data */
371         smack_str_from_perm(request_buffer, request);
372         sad->subject = subject_label;
373         sad->object  = object_label;
374 #ifdef CONFIG_SECURITY_SMACK_BRINGUP
375         /*
376          * The result may be positive in bringup mode.
377          * A positive result is an allow, but not for normal reasons.
378          * Mark it as successful, but don't filter it out even if
379          * the logging policy says to do so.
380          */
381         if (result == SMACK_UNCONFINED_SUBJECT)
382                 strcat(request_buffer, "(US)");
383         else if (result == SMACK_UNCONFINED_OBJECT)
384                 strcat(request_buffer, "(UO)");
385
386         if (result > 0)
387                 result = 0;
388 #endif
389         sad->request = request_buffer;
390         sad->result  = result;
391
392         common_lsm_audit(a, smack_log_callback, NULL);
393 }
394 #else /* #ifdef CONFIG_AUDIT */
395 void smack_log(char *subject_label, char *object_label, int request,
396                int result, struct smk_audit_info *ad)
397 {
398 }
399 #endif
400
401 DEFINE_MUTEX(smack_known_lock);
402
403 struct hlist_head smack_known_hash[SMACK_HASH_SLOTS];
404
405 /**
406  * smk_insert_entry - insert a smack label into a hash map,
407  *
408  * this function must be called under smack_known_lock
409  */
410 void smk_insert_entry(struct smack_known *skp)
411 {
412         unsigned int hash;
413         struct hlist_head *head;
414
415         hash = full_name_hash(skp->smk_known, strlen(skp->smk_known));
416         head = &smack_known_hash[hash & (SMACK_HASH_SLOTS - 1)];
417
418         hlist_add_head_rcu(&skp->smk_hashed, head);
419         list_add_rcu(&skp->list, &smack_known_list);
420 }
421
422 /**
423  * smk_find_entry - find a label on the list, return the list entry
424  * @string: a text string that might be a Smack label
425  *
426  * Returns a pointer to the entry in the label list that
427  * matches the passed string or NULL if not found.
428  */
429 struct smack_known *smk_find_entry(const char *string)
430 {
431         unsigned int hash;
432         struct hlist_head *head;
433         struct smack_known *skp;
434
435         hash = full_name_hash(string, strlen(string));
436         head = &smack_known_hash[hash & (SMACK_HASH_SLOTS - 1)];
437
438         hlist_for_each_entry_rcu(skp, head, smk_hashed)
439                 if (strcmp(skp->smk_known, string) == 0)
440                         return skp;
441
442         return NULL;
443 }
444
445 /**
446  * smk_parse_smack - parse smack label from a text string
447  * @string: a text string that might contain a Smack label
448  * @len: the maximum size, or zero if it is NULL terminated.
449  *
450  * Returns a pointer to the clean label or an error code.
451  */
452 char *smk_parse_smack(const char *string, int len)
453 {
454         char *smack;
455         int i;
456
457         if (len <= 0)
458                 len = strlen(string) + 1;
459
460         /*
461          * Reserve a leading '-' as an indicator that
462          * this isn't a label, but an option to interfaces
463          * including /smack/cipso and /smack/cipso2
464          */
465         if (string[0] == '-')
466                 return ERR_PTR(-EINVAL);
467
468         for (i = 0; i < len; i++)
469                 if (string[i] > '~' || string[i] <= ' ' || string[i] == '/' ||
470                     string[i] == '"' || string[i] == '\\' || string[i] == '\'')
471                         break;
472
473         if (i == 0 || i >= SMK_LONGLABEL)
474                 return ERR_PTR(-EINVAL);
475
476         smack = kzalloc(i + 1, GFP_NOFS);
477         if (smack == NULL)
478                 return ERR_PTR(-ENOMEM);
479
480         strncpy(smack, string, i);
481
482         return smack;
483 }
484
485 /**
486  * smk_netlbl_mls - convert a catset to netlabel mls categories
487  * @catset: the Smack categories
488  * @sap: where to put the netlabel categories
489  *
490  * Allocates and fills attr.mls
491  * Returns 0 on success, error code on failure.
492  */
493 int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
494                         int len)
495 {
496         unsigned char *cp;
497         unsigned char m;
498         int cat;
499         int rc;
500         int byte;
501
502         sap->flags |= NETLBL_SECATTR_MLS_CAT;
503         sap->attr.mls.lvl = level;
504         sap->attr.mls.cat = NULL;
505
506         for (cat = 1, cp = catset, byte = 0; byte < len; cp++, byte++)
507                 for (m = 0x80; m != 0; m >>= 1, cat++) {
508                         if ((m & *cp) == 0)
509                                 continue;
510                         rc = netlbl_catmap_setbit(&sap->attr.mls.cat,
511                                                   cat, GFP_ATOMIC);
512                         if (rc < 0) {
513                                 netlbl_catmap_free(sap->attr.mls.cat);
514                                 return rc;
515                         }
516                 }
517
518         return 0;
519 }
520
521 /**
522  * smk_import_entry - import a label, return the list entry
523  * @string: a text string that might be a Smack label
524  * @len: the maximum size, or zero if it is NULL terminated.
525  *
526  * Returns a pointer to the entry in the label list that
527  * matches the passed string, adding it if necessary,
528  * or an error code.
529  */
530 struct smack_known *smk_import_entry(const char *string, int len)
531 {
532         struct smack_known *skp;
533         char *smack;
534         int slen;
535         int rc;
536
537         smack = smk_parse_smack(string, len);
538         if (IS_ERR(smack))
539                 return ERR_CAST(smack);
540
541         mutex_lock(&smack_known_lock);
542
543         skp = smk_find_entry(smack);
544         if (skp != NULL)
545                 goto freeout;
546
547         skp = kzalloc(sizeof(*skp), GFP_NOFS);
548         if (skp == NULL) {
549                 skp = ERR_PTR(-ENOMEM);
550                 goto freeout;
551         }
552
553         skp->smk_known = smack;
554         skp->smk_secid = smack_next_secid++;
555         skp->smk_netlabel.domain = skp->smk_known;
556         skp->smk_netlabel.flags =
557                 NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
558         /*
559          * If direct labeling works use it.
560          * Otherwise use mapped labeling.
561          */
562         slen = strlen(smack);
563         if (slen < SMK_CIPSOLEN)
564                 rc = smk_netlbl_mls(smack_cipso_direct, skp->smk_known,
565                                &skp->smk_netlabel, slen);
566         else
567                 rc = smk_netlbl_mls(smack_cipso_mapped, (char *)&skp->smk_secid,
568                                &skp->smk_netlabel, sizeof(skp->smk_secid));
569
570         if (rc >= 0) {
571                 INIT_LIST_HEAD(&skp->smk_rules);
572                 mutex_init(&skp->smk_rules_lock);
573                 /*
574                  * Make sure that the entry is actually
575                  * filled before putting it on the list.
576                  */
577                 smk_insert_entry(skp);
578                 goto unlockout;
579         }
580         /*
581          * smk_netlbl_mls failed.
582          */
583         kfree(skp);
584         skp = ERR_PTR(rc);
585 freeout:
586         kfree(smack);
587 unlockout:
588         mutex_unlock(&smack_known_lock);
589
590         return skp;
591 }
592
593 /**
594  * smack_from_secid - find the Smack label associated with a secid
595  * @secid: an integer that might be associated with a Smack label
596  *
597  * Returns a pointer to the appropriate Smack label entry if there is one,
598  * otherwise a pointer to the invalid Smack label.
599  */
600 struct smack_known *smack_from_secid(const u32 secid)
601 {
602         struct smack_known *skp;
603
604         rcu_read_lock();
605         list_for_each_entry_rcu(skp, &smack_known_list, list) {
606                 if (skp->smk_secid == secid) {
607                         rcu_read_unlock();
608                         return skp;
609                 }
610         }
611
612         /*
613          * If we got this far someone asked for the translation
614          * of a secid that is not on the list.
615          */
616         rcu_read_unlock();
617         return &smack_known_invalid;
618 }
619
620 /*
621  * Unless a process is running with one of these labels
622  * even having CAP_MAC_OVERRIDE isn't enough to grant
623  * privilege to violate MAC policy. If no labels are
624  * designated (the empty list case) capabilities apply to
625  * everyone.
626  */
627 LIST_HEAD(smack_onlycap_list);
628 DEFINE_MUTEX(smack_onlycap_lock);
629
630 /*
631  * Is the task privileged and allowed to be privileged
632  * by the onlycap rule.
633  *
634  * Returns 1 if the task is allowed to be privileged, 0 if it's not.
635  */
636 int smack_privileged(int cap)
637 {
638         struct smack_known *skp = smk_of_current();
639         struct smack_known_list_elem *sklep;
640
641         /*
642          * All kernel tasks are privileged
643          */
644         if (unlikely(current->flags & PF_KTHREAD))
645                 return 1;
646
647         if (!capable(cap))
648                 return 0;
649
650         rcu_read_lock();
651         if (list_empty(&smack_onlycap_list)) {
652                 rcu_read_unlock();
653                 return 1;
654         }
655
656         list_for_each_entry_rcu(sklep, &smack_onlycap_list, list) {
657                 if (sklep->smk_label == skp) {
658                         rcu_read_unlock();
659                         return 1;
660                 }
661         }
662         rcu_read_unlock();
663
664         return 0;
665 }