0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/types.h>
0010 #include <linux/slab.h>
0011 #include <linux/fs.h>
0012 #include <linux/sched.h>
0013 #include "smack.h"
0014
0015 struct smack_known smack_known_huh = {
0016 .smk_known = "?",
0017 .smk_secid = 2,
0018 };
0019
0020 struct smack_known smack_known_hat = {
0021 .smk_known = "^",
0022 .smk_secid = 3,
0023 };
0024
0025 struct smack_known smack_known_star = {
0026 .smk_known = "*",
0027 .smk_secid = 4,
0028 };
0029
0030 struct smack_known smack_known_floor = {
0031 .smk_known = "_",
0032 .smk_secid = 5,
0033 };
0034
0035 struct smack_known smack_known_web = {
0036 .smk_known = "@",
0037 .smk_secid = 7,
0038 };
0039
0040 LIST_HEAD(smack_known_list);
0041
0042
0043
0044
0045
0046 static u32 smack_next_secid = 10;
0047
0048
0049
0050
0051
0052 int log_policy = SMACK_AUDIT_DENIED;
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 int smk_access_entry(char *subject_label, char *object_label,
0082 struct list_head *rule_list)
0083 {
0084 struct smack_rule *srp;
0085
0086 list_for_each_entry_rcu(srp, rule_list, list) {
0087 if (srp->smk_object->smk_known == object_label &&
0088 srp->smk_subject->smk_known == subject_label) {
0089 int may = srp->smk_access;
0090
0091
0092
0093 if ((may & MAY_WRITE) == MAY_WRITE)
0094 may |= MAY_LOCK;
0095 return may;
0096 }
0097 }
0098
0099 return -ENOENT;
0100 }
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 int smk_access(struct smack_known *subject, struct smack_known *object,
0116 int request, struct smk_audit_info *a)
0117 {
0118 int may = MAY_NOT;
0119 int rc = 0;
0120
0121
0122
0123
0124
0125
0126
0127 if (subject == &smack_known_star) {
0128 rc = -EACCES;
0129 goto out_audit;
0130 }
0131
0132
0133
0134
0135
0136 if (object == &smack_known_web || subject == &smack_known_web)
0137 goto out_audit;
0138
0139
0140
0141 if (object == &smack_known_star)
0142 goto out_audit;
0143
0144
0145
0146
0147 if (subject->smk_known == object->smk_known)
0148 goto out_audit;
0149
0150
0151
0152
0153 if ((request & MAY_ANYREAD) == request ||
0154 (request & MAY_LOCK) == request) {
0155 if (object == &smack_known_floor)
0156 goto out_audit;
0157 if (subject == &smack_known_hat)
0158 goto out_audit;
0159 }
0160
0161
0162
0163
0164
0165
0166
0167 rcu_read_lock();
0168 may = smk_access_entry(subject->smk_known, object->smk_known,
0169 &subject->smk_rules);
0170 rcu_read_unlock();
0171
0172 if (may <= 0 || (request & may) != request) {
0173 rc = -EACCES;
0174 goto out_audit;
0175 }
0176 #ifdef CONFIG_SECURITY_SMACK_BRINGUP
0177
0178
0179
0180
0181
0182 if (may & MAY_BRINGUP)
0183 rc = SMACK_BRINGUP_ALLOW;
0184 #endif
0185
0186 out_audit:
0187
0188 #ifdef CONFIG_SECURITY_SMACK_BRINGUP
0189 if (rc < 0) {
0190 if (object == smack_unconfined)
0191 rc = SMACK_UNCONFINED_OBJECT;
0192 if (subject == smack_unconfined)
0193 rc = SMACK_UNCONFINED_SUBJECT;
0194 }
0195 #endif
0196
0197 #ifdef CONFIG_AUDIT
0198 if (a)
0199 smack_log(subject->smk_known, object->smk_known,
0200 request, rc, a);
0201 #endif
0202
0203 return rc;
0204 }
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218 int smk_tskacc(struct task_smack *tsp, struct smack_known *obj_known,
0219 u32 mode, struct smk_audit_info *a)
0220 {
0221 struct smack_known *sbj_known = smk_of_task(tsp);
0222 int may;
0223 int rc;
0224
0225
0226
0227
0228 rc = smk_access(sbj_known, obj_known, mode, NULL);
0229 if (rc >= 0) {
0230
0231
0232
0233
0234 may = smk_access_entry(sbj_known->smk_known,
0235 obj_known->smk_known,
0236 &tsp->smk_rules);
0237 if (may < 0)
0238 goto out_audit;
0239 if ((mode & may) == mode)
0240 goto out_audit;
0241 rc = -EACCES;
0242 }
0243
0244
0245
0246
0247 if (rc != 0 && smack_privileged(CAP_MAC_OVERRIDE))
0248 rc = 0;
0249
0250 out_audit:
0251 #ifdef CONFIG_AUDIT
0252 if (a)
0253 smack_log(sbj_known->smk_known, obj_known->smk_known,
0254 mode, rc, a);
0255 #endif
0256 return rc;
0257 }
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270 int smk_curacc(struct smack_known *obj_known,
0271 u32 mode, struct smk_audit_info *a)
0272 {
0273 struct task_smack *tsp = smack_cred(current_cred());
0274
0275 return smk_tskacc(tsp, obj_known, mode, a);
0276 }
0277
0278 #ifdef CONFIG_AUDIT
0279
0280
0281
0282
0283
0284
0285
0286 static inline void smack_str_from_perm(char *string, int access)
0287 {
0288 int i = 0;
0289
0290 if (access & MAY_READ)
0291 string[i++] = 'r';
0292 if (access & MAY_WRITE)
0293 string[i++] = 'w';
0294 if (access & MAY_EXEC)
0295 string[i++] = 'x';
0296 if (access & MAY_APPEND)
0297 string[i++] = 'a';
0298 if (access & MAY_TRANSMUTE)
0299 string[i++] = 't';
0300 if (access & MAY_LOCK)
0301 string[i++] = 'l';
0302 string[i] = '\0';
0303 }
0304
0305
0306
0307
0308
0309
0310
0311 static void smack_log_callback(struct audit_buffer *ab, void *a)
0312 {
0313 struct common_audit_data *ad = a;
0314 struct smack_audit_data *sad = ad->smack_audit_data;
0315 audit_log_format(ab, "lsm=SMACK fn=%s action=%s",
0316 ad->smack_audit_data->function,
0317 sad->result ? "denied" : "granted");
0318 audit_log_format(ab, " subject=");
0319 audit_log_untrustedstring(ab, sad->subject);
0320 audit_log_format(ab, " object=");
0321 audit_log_untrustedstring(ab, sad->object);
0322 if (sad->request[0] == '\0')
0323 audit_log_format(ab, " labels_differ");
0324 else
0325 audit_log_format(ab, " requested=%s", sad->request);
0326 }
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339 void smack_log(char *subject_label, char *object_label, int request,
0340 int result, struct smk_audit_info *ad)
0341 {
0342 #ifdef CONFIG_SECURITY_SMACK_BRINGUP
0343 char request_buffer[SMK_NUM_ACCESS_TYPE + 5];
0344 #else
0345 char request_buffer[SMK_NUM_ACCESS_TYPE + 1];
0346 #endif
0347 struct smack_audit_data *sad;
0348 struct common_audit_data *a = &ad->a;
0349
0350
0351 if (result < 0 && (log_policy & SMACK_AUDIT_DENIED) == 0)
0352 return;
0353 if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
0354 return;
0355
0356 sad = a->smack_audit_data;
0357
0358 if (sad->function == NULL)
0359 sad->function = "unknown";
0360
0361
0362 smack_str_from_perm(request_buffer, request);
0363 sad->subject = subject_label;
0364 sad->object = object_label;
0365 #ifdef CONFIG_SECURITY_SMACK_BRINGUP
0366
0367
0368
0369
0370
0371
0372 if (result == SMACK_UNCONFINED_SUBJECT)
0373 strcat(request_buffer, "(US)");
0374 else if (result == SMACK_UNCONFINED_OBJECT)
0375 strcat(request_buffer, "(UO)");
0376
0377 if (result > 0)
0378 result = 0;
0379 #endif
0380 sad->request = request_buffer;
0381 sad->result = result;
0382
0383 common_lsm_audit(a, smack_log_callback, NULL);
0384 }
0385 #else
0386 void smack_log(char *subject_label, char *object_label, int request,
0387 int result, struct smk_audit_info *ad)
0388 {
0389 }
0390 #endif
0391
0392 DEFINE_MUTEX(smack_known_lock);
0393
0394 struct hlist_head smack_known_hash[SMACK_HASH_SLOTS];
0395
0396
0397
0398
0399
0400
0401
0402 void smk_insert_entry(struct smack_known *skp)
0403 {
0404 unsigned int hash;
0405 struct hlist_head *head;
0406
0407 hash = full_name_hash(NULL, skp->smk_known, strlen(skp->smk_known));
0408 head = &smack_known_hash[hash & (SMACK_HASH_SLOTS - 1)];
0409
0410 hlist_add_head_rcu(&skp->smk_hashed, head);
0411 list_add_rcu(&skp->list, &smack_known_list);
0412 }
0413
0414
0415
0416
0417
0418
0419
0420
0421 struct smack_known *smk_find_entry(const char *string)
0422 {
0423 unsigned int hash;
0424 struct hlist_head *head;
0425 struct smack_known *skp;
0426
0427 hash = full_name_hash(NULL, string, strlen(string));
0428 head = &smack_known_hash[hash & (SMACK_HASH_SLOTS - 1)];
0429
0430 hlist_for_each_entry_rcu(skp, head, smk_hashed)
0431 if (strcmp(skp->smk_known, string) == 0)
0432 return skp;
0433
0434 return NULL;
0435 }
0436
0437
0438
0439
0440
0441
0442
0443
0444 char *smk_parse_smack(const char *string, int len)
0445 {
0446 char *smack;
0447 int i;
0448
0449 if (len <= 0)
0450 len = strlen(string) + 1;
0451
0452
0453
0454
0455
0456
0457 if (string[0] == '-')
0458 return ERR_PTR(-EINVAL);
0459
0460 for (i = 0; i < len; i++)
0461 if (string[i] > '~' || string[i] <= ' ' || string[i] == '/' ||
0462 string[i] == '"' || string[i] == '\\' || string[i] == '\'')
0463 break;
0464
0465 if (i == 0 || i >= SMK_LONGLABEL)
0466 return ERR_PTR(-EINVAL);
0467
0468 smack = kstrndup(string, i, GFP_NOFS);
0469 if (!smack)
0470 return ERR_PTR(-ENOMEM);
0471 return smack;
0472 }
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484 int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
0485 int len)
0486 {
0487 unsigned char *cp;
0488 unsigned char m;
0489 int cat;
0490 int rc;
0491 int byte;
0492
0493 sap->flags |= NETLBL_SECATTR_MLS_CAT;
0494 sap->attr.mls.lvl = level;
0495 sap->attr.mls.cat = NULL;
0496
0497 for (cat = 1, cp = catset, byte = 0; byte < len; cp++, byte++)
0498 for (m = 0x80; m != 0; m >>= 1, cat++) {
0499 if ((m & *cp) == 0)
0500 continue;
0501 rc = netlbl_catmap_setbit(&sap->attr.mls.cat,
0502 cat, GFP_NOFS);
0503 if (rc < 0) {
0504 netlbl_catmap_free(sap->attr.mls.cat);
0505 return rc;
0506 }
0507 }
0508
0509 return 0;
0510 }
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520 int smack_populate_secattr(struct smack_known *skp)
0521 {
0522 int slen;
0523
0524 skp->smk_netlabel.attr.secid = skp->smk_secid;
0525 skp->smk_netlabel.domain = skp->smk_known;
0526 skp->smk_netlabel.cache = netlbl_secattr_cache_alloc(GFP_ATOMIC);
0527 if (skp->smk_netlabel.cache != NULL) {
0528 skp->smk_netlabel.flags |= NETLBL_SECATTR_CACHE;
0529 skp->smk_netlabel.cache->free = NULL;
0530 skp->smk_netlabel.cache->data = skp;
0531 }
0532 skp->smk_netlabel.flags |= NETLBL_SECATTR_SECID |
0533 NETLBL_SECATTR_MLS_LVL |
0534 NETLBL_SECATTR_DOMAIN;
0535
0536
0537
0538
0539 slen = strlen(skp->smk_known);
0540 if (slen < SMK_CIPSOLEN)
0541 return smk_netlbl_mls(smack_cipso_direct, skp->smk_known,
0542 &skp->smk_netlabel, slen);
0543
0544 return smk_netlbl_mls(smack_cipso_mapped, (char *)&skp->smk_secid,
0545 &skp->smk_netlabel, sizeof(skp->smk_secid));
0546 }
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557 struct smack_known *smk_import_entry(const char *string, int len)
0558 {
0559 struct smack_known *skp;
0560 char *smack;
0561 int rc;
0562
0563 smack = smk_parse_smack(string, len);
0564 if (IS_ERR(smack))
0565 return ERR_CAST(smack);
0566
0567 mutex_lock(&smack_known_lock);
0568
0569 skp = smk_find_entry(smack);
0570 if (skp != NULL)
0571 goto freeout;
0572
0573 skp = kzalloc(sizeof(*skp), GFP_NOFS);
0574 if (skp == NULL) {
0575 skp = ERR_PTR(-ENOMEM);
0576 goto freeout;
0577 }
0578
0579 skp->smk_known = smack;
0580 skp->smk_secid = smack_next_secid++;
0581
0582 rc = smack_populate_secattr(skp);
0583 if (rc >= 0) {
0584 INIT_LIST_HEAD(&skp->smk_rules);
0585 mutex_init(&skp->smk_rules_lock);
0586
0587
0588
0589
0590 smk_insert_entry(skp);
0591 goto unlockout;
0592 }
0593 kfree(skp);
0594 skp = ERR_PTR(rc);
0595 freeout:
0596 kfree(smack);
0597 unlockout:
0598 mutex_unlock(&smack_known_lock);
0599
0600 return skp;
0601 }
0602
0603
0604
0605
0606
0607
0608
0609
0610 struct smack_known *smack_from_secid(const u32 secid)
0611 {
0612 struct smack_known *skp;
0613
0614 rcu_read_lock();
0615 list_for_each_entry_rcu(skp, &smack_known_list, list) {
0616 if (skp->smk_secid == secid) {
0617 rcu_read_unlock();
0618 return skp;
0619 }
0620 }
0621
0622
0623
0624
0625
0626 rcu_read_unlock();
0627 return &smack_known_huh;
0628 }
0629
0630
0631
0632
0633
0634
0635
0636
0637 LIST_HEAD(smack_onlycap_list);
0638 DEFINE_MUTEX(smack_onlycap_lock);
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650 bool smack_privileged_cred(int cap, const struct cred *cred)
0651 {
0652 struct task_smack *tsp = smack_cred(cred);
0653 struct smack_known *skp = tsp->smk_task;
0654 struct smack_known_list_elem *sklep;
0655 int rc;
0656
0657 rc = cap_capable(cred, &init_user_ns, cap, CAP_OPT_NONE);
0658 if (rc)
0659 return false;
0660
0661 rcu_read_lock();
0662 if (list_empty(&smack_onlycap_list)) {
0663 rcu_read_unlock();
0664 return true;
0665 }
0666
0667 list_for_each_entry_rcu(sklep, &smack_onlycap_list, list) {
0668 if (sklep->smk_label == skp) {
0669 rcu_read_unlock();
0670 return true;
0671 }
0672 }
0673 rcu_read_unlock();
0674
0675 return false;
0676 }
0677
0678
0679
0680
0681
0682
0683
0684
0685
0686
0687 bool smack_privileged(int cap)
0688 {
0689
0690
0691
0692 if (unlikely(current->flags & PF_KTHREAD))
0693 return true;
0694
0695 return smack_privileged_cred(cap, current_cred());
0696 }