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