diff options
Diffstat (limited to 'security/smack/smack_lsm.c')
-rw-r--r-- | security/smack/smack_lsm.c | 673 |
1 files changed, 509 insertions, 164 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index c448d57ae2b7..9831a39c11f6 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -3,12 +3,14 @@ | |||
3 | * | 3 | * |
4 | * This file contains the smack hook function implementations. | 4 | * This file contains the smack hook function implementations. |
5 | * | 5 | * |
6 | * Author: | 6 | * Authors: |
7 | * Casey Schaufler <casey@schaufler-ca.com> | 7 | * Casey Schaufler <casey@schaufler-ca.com> |
8 | * Jarkko Sakkinen <ext-jarkko.2.sakkinen@nokia.com> | ||
8 | * | 9 | * |
9 | * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> | 10 | * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> |
10 | * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. | 11 | * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. |
11 | * Paul Moore <paul.moore@hp.com> | 12 | * Paul Moore <paul.moore@hp.com> |
13 | * Copyright (C) 2010 Nokia Corporation | ||
12 | * | 14 | * |
13 | * This program is free software; you can redistribute it and/or modify | 15 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License version 2, | 16 | * it under the terms of the GNU General Public License version 2, |
@@ -31,10 +33,14 @@ | |||
31 | #include <net/cipso_ipv4.h> | 33 | #include <net/cipso_ipv4.h> |
32 | #include <linux/audit.h> | 34 | #include <linux/audit.h> |
33 | #include <linux/magic.h> | 35 | #include <linux/magic.h> |
36 | #include <linux/dcache.h> | ||
34 | #include "smack.h" | 37 | #include "smack.h" |
35 | 38 | ||
36 | #define task_security(task) (task_cred_xxx((task), security)) | 39 | #define task_security(task) (task_cred_xxx((task), security)) |
37 | 40 | ||
41 | #define TRANS_TRUE "TRUE" | ||
42 | #define TRANS_TRUE_SIZE 4 | ||
43 | |||
38 | /** | 44 | /** |
39 | * smk_fetch - Fetch the smack label from a file. | 45 | * smk_fetch - Fetch the smack label from a file. |
40 | * @ip: a pointer to the inode | 46 | * @ip: a pointer to the inode |
@@ -43,7 +49,7 @@ | |||
43 | * Returns a pointer to the master list entry for the Smack label | 49 | * Returns a pointer to the master list entry for the Smack label |
44 | * or NULL if there was no label to fetch. | 50 | * or NULL if there was no label to fetch. |
45 | */ | 51 | */ |
46 | static char *smk_fetch(struct inode *ip, struct dentry *dp) | 52 | static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp) |
47 | { | 53 | { |
48 | int rc; | 54 | int rc; |
49 | char in[SMK_LABELLEN]; | 55 | char in[SMK_LABELLEN]; |
@@ -51,7 +57,7 @@ static char *smk_fetch(struct inode *ip, struct dentry *dp) | |||
51 | if (ip->i_op->getxattr == NULL) | 57 | if (ip->i_op->getxattr == NULL) |
52 | return NULL; | 58 | return NULL; |
53 | 59 | ||
54 | rc = ip->i_op->getxattr(dp, XATTR_NAME_SMACK, in, SMK_LABELLEN); | 60 | rc = ip->i_op->getxattr(dp, name, in, SMK_LABELLEN); |
55 | if (rc < 0) | 61 | if (rc < 0) |
56 | return NULL; | 62 | return NULL; |
57 | 63 | ||
@@ -79,6 +85,56 @@ struct inode_smack *new_inode_smack(char *smack) | |||
79 | return isp; | 85 | return isp; |
80 | } | 86 | } |
81 | 87 | ||
88 | /** | ||
89 | * new_task_smack - allocate a task security blob | ||
90 | * @smack: a pointer to the Smack label to use in the blob | ||
91 | * | ||
92 | * Returns the new blob or NULL if there's no memory available | ||
93 | */ | ||
94 | static struct task_smack *new_task_smack(char *task, char *forked, gfp_t gfp) | ||
95 | { | ||
96 | struct task_smack *tsp; | ||
97 | |||
98 | tsp = kzalloc(sizeof(struct task_smack), gfp); | ||
99 | if (tsp == NULL) | ||
100 | return NULL; | ||
101 | |||
102 | tsp->smk_task = task; | ||
103 | tsp->smk_forked = forked; | ||
104 | INIT_LIST_HEAD(&tsp->smk_rules); | ||
105 | mutex_init(&tsp->smk_rules_lock); | ||
106 | |||
107 | return tsp; | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * smk_copy_rules - copy a rule set | ||
112 | * @nhead - new rules header pointer | ||
113 | * @ohead - old rules header pointer | ||
114 | * | ||
115 | * Returns 0 on success, -ENOMEM on error | ||
116 | */ | ||
117 | static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead, | ||
118 | gfp_t gfp) | ||
119 | { | ||
120 | struct smack_rule *nrp; | ||
121 | struct smack_rule *orp; | ||
122 | int rc = 0; | ||
123 | |||
124 | INIT_LIST_HEAD(nhead); | ||
125 | |||
126 | list_for_each_entry_rcu(orp, ohead, list) { | ||
127 | nrp = kzalloc(sizeof(struct smack_rule), gfp); | ||
128 | if (nrp == NULL) { | ||
129 | rc = -ENOMEM; | ||
130 | break; | ||
131 | } | ||
132 | *nrp = *orp; | ||
133 | list_add_rcu(&nrp->list, nhead); | ||
134 | } | ||
135 | return rc; | ||
136 | } | ||
137 | |||
82 | /* | 138 | /* |
83 | * LSM hooks. | 139 | * LSM hooks. |
84 | * We he, that is fun! | 140 | * We he, that is fun! |
@@ -97,23 +153,17 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) | |||
97 | { | 153 | { |
98 | int rc; | 154 | int rc; |
99 | struct smk_audit_info ad; | 155 | struct smk_audit_info ad; |
100 | char *sp, *tsp; | 156 | char *tsp; |
101 | 157 | ||
102 | rc = cap_ptrace_access_check(ctp, mode); | 158 | rc = cap_ptrace_access_check(ctp, mode); |
103 | if (rc != 0) | 159 | if (rc != 0) |
104 | return rc; | 160 | return rc; |
105 | 161 | ||
106 | sp = current_security(); | 162 | tsp = smk_of_task(task_security(ctp)); |
107 | tsp = task_security(ctp); | ||
108 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 163 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
109 | smk_ad_setfield_u_tsk(&ad, ctp); | 164 | smk_ad_setfield_u_tsk(&ad, ctp); |
110 | 165 | ||
111 | /* we won't log here, because rc can be overriden */ | 166 | rc = smk_curacc(tsp, MAY_READWRITE, &ad); |
112 | rc = smk_access(sp, tsp, MAY_READWRITE, NULL); | ||
113 | if (rc != 0 && capable(CAP_MAC_OVERRIDE)) | ||
114 | rc = 0; | ||
115 | |||
116 | smack_log(sp, tsp, MAY_READWRITE, rc, &ad); | ||
117 | return rc; | 167 | return rc; |
118 | } | 168 | } |
119 | 169 | ||
@@ -129,23 +179,17 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
129 | { | 179 | { |
130 | int rc; | 180 | int rc; |
131 | struct smk_audit_info ad; | 181 | struct smk_audit_info ad; |
132 | char *sp, *tsp; | 182 | char *tsp; |
133 | 183 | ||
134 | rc = cap_ptrace_traceme(ptp); | 184 | rc = cap_ptrace_traceme(ptp); |
135 | if (rc != 0) | 185 | if (rc != 0) |
136 | return rc; | 186 | return rc; |
137 | 187 | ||
188 | tsp = smk_of_task(task_security(ptp)); | ||
138 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 189 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
139 | smk_ad_setfield_u_tsk(&ad, ptp); | 190 | smk_ad_setfield_u_tsk(&ad, ptp); |
140 | 191 | ||
141 | sp = current_security(); | 192 | rc = smk_curacc(tsp, MAY_READWRITE, &ad); |
142 | tsp = task_security(ptp); | ||
143 | /* we won't log here, because rc can be overriden */ | ||
144 | rc = smk_access(tsp, sp, MAY_READWRITE, NULL); | ||
145 | if (rc != 0 && has_capability(ptp, CAP_MAC_OVERRIDE)) | ||
146 | rc = 0; | ||
147 | |||
148 | smack_log(tsp, sp, MAY_READWRITE, rc, &ad); | ||
149 | return rc; | 193 | return rc; |
150 | } | 194 | } |
151 | 195 | ||
@@ -157,14 +201,10 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
157 | * | 201 | * |
158 | * Returns 0 on success, error code otherwise. | 202 | * Returns 0 on success, error code otherwise. |
159 | */ | 203 | */ |
160 | static int smack_syslog(int type, bool from_file) | 204 | static int smack_syslog(int typefrom_file) |
161 | { | 205 | { |
162 | int rc; | 206 | int rc = 0; |
163 | char *sp = current_security(); | 207 | char *sp = smk_of_current(); |
164 | |||
165 | rc = cap_syslog(type, from_file); | ||
166 | if (rc != 0) | ||
167 | return rc; | ||
168 | 208 | ||
169 | if (capable(CAP_MAC_OVERRIDE)) | 209 | if (capable(CAP_MAC_OVERRIDE)) |
170 | return 0; | 210 | return 0; |
@@ -343,7 +383,7 @@ static int smack_sb_statfs(struct dentry *dentry) | |||
343 | int rc; | 383 | int rc; |
344 | struct smk_audit_info ad; | 384 | struct smk_audit_info ad; |
345 | 385 | ||
346 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 386 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
347 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 387 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
348 | 388 | ||
349 | rc = smk_curacc(sbp->smk_floor, MAY_READ, &ad); | 389 | rc = smk_curacc(sbp->smk_floor, MAY_READ, &ad); |
@@ -367,7 +407,7 @@ static int smack_sb_mount(char *dev_name, struct path *path, | |||
367 | struct superblock_smack *sbp = path->mnt->mnt_sb->s_security; | 407 | struct superblock_smack *sbp = path->mnt->mnt_sb->s_security; |
368 | struct smk_audit_info ad; | 408 | struct smk_audit_info ad; |
369 | 409 | ||
370 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 410 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
371 | smk_ad_setfield_u_fs_path(&ad, *path); | 411 | smk_ad_setfield_u_fs_path(&ad, *path); |
372 | 412 | ||
373 | return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad); | 413 | return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad); |
@@ -385,16 +425,53 @@ static int smack_sb_umount(struct vfsmount *mnt, int flags) | |||
385 | { | 425 | { |
386 | struct superblock_smack *sbp; | 426 | struct superblock_smack *sbp; |
387 | struct smk_audit_info ad; | 427 | struct smk_audit_info ad; |
428 | struct path path; | ||
388 | 429 | ||
389 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 430 | path.dentry = mnt->mnt_root; |
390 | smk_ad_setfield_u_fs_path_dentry(&ad, mnt->mnt_root); | 431 | path.mnt = mnt; |
391 | smk_ad_setfield_u_fs_path_mnt(&ad, mnt); | 432 | |
433 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | ||
434 | smk_ad_setfield_u_fs_path(&ad, path); | ||
392 | 435 | ||
393 | sbp = mnt->mnt_sb->s_security; | 436 | sbp = mnt->mnt_sb->s_security; |
394 | return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad); | 437 | return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad); |
395 | } | 438 | } |
396 | 439 | ||
397 | /* | 440 | /* |
441 | * BPRM hooks | ||
442 | */ | ||
443 | |||
444 | static int smack_bprm_set_creds(struct linux_binprm *bprm) | ||
445 | { | ||
446 | struct task_smack *tsp = bprm->cred->security; | ||
447 | struct inode_smack *isp; | ||
448 | struct dentry *dp; | ||
449 | int rc; | ||
450 | |||
451 | rc = cap_bprm_set_creds(bprm); | ||
452 | if (rc != 0) | ||
453 | return rc; | ||
454 | |||
455 | if (bprm->cred_prepared) | ||
456 | return 0; | ||
457 | |||
458 | if (bprm->file == NULL || bprm->file->f_dentry == NULL) | ||
459 | return 0; | ||
460 | |||
461 | dp = bprm->file->f_dentry; | ||
462 | |||
463 | if (dp->d_inode == NULL) | ||
464 | return 0; | ||
465 | |||
466 | isp = dp->d_inode->i_security; | ||
467 | |||
468 | if (isp->smk_task != NULL) | ||
469 | tsp->smk_task = isp->smk_task; | ||
470 | |||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | /* | ||
398 | * Inode hooks | 475 | * Inode hooks |
399 | */ | 476 | */ |
400 | 477 | ||
@@ -406,7 +483,7 @@ static int smack_sb_umount(struct vfsmount *mnt, int flags) | |||
406 | */ | 483 | */ |
407 | static int smack_inode_alloc_security(struct inode *inode) | 484 | static int smack_inode_alloc_security(struct inode *inode) |
408 | { | 485 | { |
409 | inode->i_security = new_inode_smack(current_security()); | 486 | inode->i_security = new_inode_smack(smk_of_current()); |
410 | if (inode->i_security == NULL) | 487 | if (inode->i_security == NULL) |
411 | return -ENOMEM; | 488 | return -ENOMEM; |
412 | return 0; | 489 | return 0; |
@@ -428,6 +505,7 @@ static void smack_inode_free_security(struct inode *inode) | |||
428 | * smack_inode_init_security - copy out the smack from an inode | 505 | * smack_inode_init_security - copy out the smack from an inode |
429 | * @inode: the inode | 506 | * @inode: the inode |
430 | * @dir: unused | 507 | * @dir: unused |
508 | * @qstr: unused | ||
431 | * @name: where to put the attribute name | 509 | * @name: where to put the attribute name |
432 | * @value: where to put the attribute value | 510 | * @value: where to put the attribute value |
433 | * @len: where to put the length of the attribute | 511 | * @len: where to put the length of the attribute |
@@ -435,9 +513,12 @@ static void smack_inode_free_security(struct inode *inode) | |||
435 | * Returns 0 if it all works out, -ENOMEM if there's no memory | 513 | * Returns 0 if it all works out, -ENOMEM if there's no memory |
436 | */ | 514 | */ |
437 | static int smack_inode_init_security(struct inode *inode, struct inode *dir, | 515 | static int smack_inode_init_security(struct inode *inode, struct inode *dir, |
438 | char **name, void **value, size_t *len) | 516 | const struct qstr *qstr, char **name, |
517 | void **value, size_t *len) | ||
439 | { | 518 | { |
440 | char *isp = smk_of_inode(inode); | 519 | char *isp = smk_of_inode(inode); |
520 | char *dsp = smk_of_inode(dir); | ||
521 | int may; | ||
441 | 522 | ||
442 | if (name) { | 523 | if (name) { |
443 | *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); | 524 | *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); |
@@ -446,6 +527,19 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
446 | } | 527 | } |
447 | 528 | ||
448 | if (value) { | 529 | if (value) { |
530 | rcu_read_lock(); | ||
531 | may = smk_access_entry(smk_of_current(), dsp, &smack_rule_list); | ||
532 | rcu_read_unlock(); | ||
533 | |||
534 | /* | ||
535 | * If the access rule allows transmutation and | ||
536 | * the directory requests transmutation then | ||
537 | * by all means transmute. | ||
538 | */ | ||
539 | if (may > 0 && ((may & MAY_TRANSMUTE) != 0) && | ||
540 | smk_inode_transmutable(dir)) | ||
541 | isp = dsp; | ||
542 | |||
449 | *value = kstrdup(isp, GFP_KERNEL); | 543 | *value = kstrdup(isp, GFP_KERNEL); |
450 | if (*value == NULL) | 544 | if (*value == NULL) |
451 | return -ENOMEM; | 545 | return -ENOMEM; |
@@ -472,7 +566,7 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, | |||
472 | struct smk_audit_info ad; | 566 | struct smk_audit_info ad; |
473 | int rc; | 567 | int rc; |
474 | 568 | ||
475 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 569 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
476 | smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry); | 570 | smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry); |
477 | 571 | ||
478 | isp = smk_of_inode(old_dentry->d_inode); | 572 | isp = smk_of_inode(old_dentry->d_inode); |
@@ -501,7 +595,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry) | |||
501 | struct smk_audit_info ad; | 595 | struct smk_audit_info ad; |
502 | int rc; | 596 | int rc; |
503 | 597 | ||
504 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 598 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
505 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 599 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
506 | 600 | ||
507 | /* | 601 | /* |
@@ -532,7 +626,7 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) | |||
532 | struct smk_audit_info ad; | 626 | struct smk_audit_info ad; |
533 | int rc; | 627 | int rc; |
534 | 628 | ||
535 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 629 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
536 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 630 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
537 | 631 | ||
538 | /* | 632 | /* |
@@ -572,7 +666,7 @@ static int smack_inode_rename(struct inode *old_inode, | |||
572 | char *isp; | 666 | char *isp; |
573 | struct smk_audit_info ad; | 667 | struct smk_audit_info ad; |
574 | 668 | ||
575 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 669 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
576 | smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry); | 670 | smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry); |
577 | 671 | ||
578 | isp = smk_of_inode(old_dentry->d_inode); | 672 | isp = smk_of_inode(old_dentry->d_inode); |
@@ -595,7 +689,7 @@ static int smack_inode_rename(struct inode *old_inode, | |||
595 | * | 689 | * |
596 | * Returns 0 if access is permitted, -EACCES otherwise | 690 | * Returns 0 if access is permitted, -EACCES otherwise |
597 | */ | 691 | */ |
598 | static int smack_inode_permission(struct inode *inode, int mask) | 692 | static int smack_inode_permission(struct inode *inode, int mask, unsigned flags) |
599 | { | 693 | { |
600 | struct smk_audit_info ad; | 694 | struct smk_audit_info ad; |
601 | 695 | ||
@@ -605,7 +699,11 @@ static int smack_inode_permission(struct inode *inode, int mask) | |||
605 | */ | 699 | */ |
606 | if (mask == 0) | 700 | if (mask == 0) |
607 | return 0; | 701 | return 0; |
608 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 702 | |
703 | /* May be droppable after audit */ | ||
704 | if (flags & IPERM_FLAG_RCU) | ||
705 | return -ECHILD; | ||
706 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); | ||
609 | smk_ad_setfield_u_fs_inode(&ad, inode); | 707 | smk_ad_setfield_u_fs_inode(&ad, inode); |
610 | return smk_curacc(smk_of_inode(inode), mask, &ad); | 708 | return smk_curacc(smk_of_inode(inode), mask, &ad); |
611 | } | 709 | } |
@@ -625,7 +723,7 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) | |||
625 | */ | 723 | */ |
626 | if (iattr->ia_valid & ATTR_FORCE) | 724 | if (iattr->ia_valid & ATTR_FORCE) |
627 | return 0; | 725 | return 0; |
628 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 726 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
629 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 727 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
630 | 728 | ||
631 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); | 729 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); |
@@ -641,10 +739,13 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) | |||
641 | static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | 739 | static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) |
642 | { | 740 | { |
643 | struct smk_audit_info ad; | 741 | struct smk_audit_info ad; |
742 | struct path path; | ||
644 | 743 | ||
645 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 744 | path.dentry = dentry; |
646 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 745 | path.mnt = mnt; |
647 | smk_ad_setfield_u_fs_path_mnt(&ad, mnt); | 746 | |
747 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | ||
748 | smk_ad_setfield_u_fs_path(&ad, path); | ||
648 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); | 749 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); |
649 | } | 750 | } |
650 | 751 | ||
@@ -668,7 +769,9 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
668 | 769 | ||
669 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || | 770 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || |
670 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || | 771 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || |
671 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) { | 772 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || |
773 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || | ||
774 | strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { | ||
672 | if (!capable(CAP_MAC_ADMIN)) | 775 | if (!capable(CAP_MAC_ADMIN)) |
673 | rc = -EPERM; | 776 | rc = -EPERM; |
674 | /* | 777 | /* |
@@ -678,10 +781,16 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
678 | if (size == 0 || size >= SMK_LABELLEN || | 781 | if (size == 0 || size >= SMK_LABELLEN || |
679 | smk_import(value, size) == NULL) | 782 | smk_import(value, size) == NULL) |
680 | rc = -EINVAL; | 783 | rc = -EINVAL; |
784 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { | ||
785 | if (!capable(CAP_MAC_ADMIN)) | ||
786 | rc = -EPERM; | ||
787 | if (size != TRANS_TRUE_SIZE || | ||
788 | strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0) | ||
789 | rc = -EINVAL; | ||
681 | } else | 790 | } else |
682 | rc = cap_inode_setxattr(dentry, name, value, size, flags); | 791 | rc = cap_inode_setxattr(dentry, name, value, size, flags); |
683 | 792 | ||
684 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 793 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
685 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 794 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
686 | 795 | ||
687 | if (rc == 0) | 796 | if (rc == 0) |
@@ -704,26 +813,29 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
704 | static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, | 813 | static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, |
705 | const void *value, size_t size, int flags) | 814 | const void *value, size_t size, int flags) |
706 | { | 815 | { |
707 | struct inode_smack *isp; | ||
708 | char *nsp; | 816 | char *nsp; |
817 | struct inode_smack *isp = dentry->d_inode->i_security; | ||
709 | 818 | ||
710 | /* | 819 | if (strcmp(name, XATTR_NAME_SMACK) == 0) { |
711 | * Not SMACK | 820 | nsp = smk_import(value, size); |
712 | */ | 821 | if (nsp != NULL) |
713 | if (strcmp(name, XATTR_NAME_SMACK)) | 822 | isp->smk_inode = nsp; |
714 | return; | 823 | else |
715 | 824 | isp->smk_inode = smack_known_invalid.smk_known; | |
716 | isp = dentry->d_inode->i_security; | 825 | } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { |
717 | 826 | nsp = smk_import(value, size); | |
718 | /* | 827 | if (nsp != NULL) |
719 | * No locking is done here. This is a pointer | 828 | isp->smk_task = nsp; |
720 | * assignment. | 829 | else |
721 | */ | 830 | isp->smk_task = smack_known_invalid.smk_known; |
722 | nsp = smk_import(value, size); | 831 | } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { |
723 | if (nsp != NULL) | 832 | nsp = smk_import(value, size); |
724 | isp->smk_inode = nsp; | 833 | if (nsp != NULL) |
725 | else | 834 | isp->smk_mmap = nsp; |
726 | isp->smk_inode = smack_known_invalid.smk_known; | 835 | else |
836 | isp->smk_mmap = smack_known_invalid.smk_known; | ||
837 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) | ||
838 | isp->smk_flags |= SMK_INODE_TRANSMUTE; | ||
727 | 839 | ||
728 | return; | 840 | return; |
729 | } | 841 | } |
@@ -739,7 +851,7 @@ static int smack_inode_getxattr(struct dentry *dentry, const char *name) | |||
739 | { | 851 | { |
740 | struct smk_audit_info ad; | 852 | struct smk_audit_info ad; |
741 | 853 | ||
742 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 854 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
743 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 855 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
744 | 856 | ||
745 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); | 857 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); |
@@ -756,22 +868,32 @@ static int smack_inode_getxattr(struct dentry *dentry, const char *name) | |||
756 | */ | 868 | */ |
757 | static int smack_inode_removexattr(struct dentry *dentry, const char *name) | 869 | static int smack_inode_removexattr(struct dentry *dentry, const char *name) |
758 | { | 870 | { |
871 | struct inode_smack *isp; | ||
759 | struct smk_audit_info ad; | 872 | struct smk_audit_info ad; |
760 | int rc = 0; | 873 | int rc = 0; |
761 | 874 | ||
762 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || | 875 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || |
763 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || | 876 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || |
764 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) { | 877 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || |
878 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || | ||
879 | strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 || | ||
880 | strcmp(name, XATTR_NAME_SMACKMMAP)) { | ||
765 | if (!capable(CAP_MAC_ADMIN)) | 881 | if (!capable(CAP_MAC_ADMIN)) |
766 | rc = -EPERM; | 882 | rc = -EPERM; |
767 | } else | 883 | } else |
768 | rc = cap_inode_removexattr(dentry, name); | 884 | rc = cap_inode_removexattr(dentry, name); |
769 | 885 | ||
770 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 886 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
771 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 887 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
772 | if (rc == 0) | 888 | if (rc == 0) |
773 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); | 889 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); |
774 | 890 | ||
891 | if (rc == 0) { | ||
892 | isp = dentry->d_inode->i_security; | ||
893 | isp->smk_task = NULL; | ||
894 | isp->smk_mmap = NULL; | ||
895 | } | ||
896 | |||
775 | return rc; | 897 | return rc; |
776 | } | 898 | } |
777 | 899 | ||
@@ -899,7 +1021,7 @@ static int smack_file_permission(struct file *file, int mask) | |||
899 | */ | 1021 | */ |
900 | static int smack_file_alloc_security(struct file *file) | 1022 | static int smack_file_alloc_security(struct file *file) |
901 | { | 1023 | { |
902 | file->f_security = current_security(); | 1024 | file->f_security = smk_of_current(); |
903 | return 0; | 1025 | return 0; |
904 | } | 1026 | } |
905 | 1027 | ||
@@ -931,7 +1053,7 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd, | |||
931 | int rc = 0; | 1053 | int rc = 0; |
932 | struct smk_audit_info ad; | 1054 | struct smk_audit_info ad; |
933 | 1055 | ||
934 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 1056 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
935 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1057 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
936 | 1058 | ||
937 | if (_IOC_DIR(cmd) & _IOC_WRITE) | 1059 | if (_IOC_DIR(cmd) & _IOC_WRITE) |
@@ -954,8 +1076,8 @@ static int smack_file_lock(struct file *file, unsigned int cmd) | |||
954 | { | 1076 | { |
955 | struct smk_audit_info ad; | 1077 | struct smk_audit_info ad; |
956 | 1078 | ||
957 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 1079 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
958 | smk_ad_setfield_u_fs_path_dentry(&ad, file->f_path.dentry); | 1080 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
959 | return smk_curacc(file->f_security, MAY_WRITE, &ad); | 1081 | return smk_curacc(file->f_security, MAY_WRITE, &ad); |
960 | } | 1082 | } |
961 | 1083 | ||
@@ -973,7 +1095,7 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
973 | struct smk_audit_info ad; | 1095 | struct smk_audit_info ad; |
974 | int rc; | 1096 | int rc; |
975 | 1097 | ||
976 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 1098 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
977 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1099 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
978 | 1100 | ||
979 | switch (cmd) { | 1101 | switch (cmd) { |
@@ -1001,6 +1123,126 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
1001 | } | 1123 | } |
1002 | 1124 | ||
1003 | /** | 1125 | /** |
1126 | * smack_file_mmap : | ||
1127 | * Check permissions for a mmap operation. The @file may be NULL, e.g. | ||
1128 | * if mapping anonymous memory. | ||
1129 | * @file contains the file structure for file to map (may be NULL). | ||
1130 | * @reqprot contains the protection requested by the application. | ||
1131 | * @prot contains the protection that will be applied by the kernel. | ||
1132 | * @flags contains the operational flags. | ||
1133 | * Return 0 if permission is granted. | ||
1134 | */ | ||
1135 | static int smack_file_mmap(struct file *file, | ||
1136 | unsigned long reqprot, unsigned long prot, | ||
1137 | unsigned long flags, unsigned long addr, | ||
1138 | unsigned long addr_only) | ||
1139 | { | ||
1140 | struct smack_rule *srp; | ||
1141 | struct task_smack *tsp; | ||
1142 | char *sp; | ||
1143 | char *msmack; | ||
1144 | char *osmack; | ||
1145 | struct inode_smack *isp; | ||
1146 | struct dentry *dp; | ||
1147 | int may; | ||
1148 | int mmay; | ||
1149 | int tmay; | ||
1150 | int rc; | ||
1151 | |||
1152 | /* do DAC check on address space usage */ | ||
1153 | rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); | ||
1154 | if (rc || addr_only) | ||
1155 | return rc; | ||
1156 | |||
1157 | if (file == NULL || file->f_dentry == NULL) | ||
1158 | return 0; | ||
1159 | |||
1160 | dp = file->f_dentry; | ||
1161 | |||
1162 | if (dp->d_inode == NULL) | ||
1163 | return 0; | ||
1164 | |||
1165 | isp = dp->d_inode->i_security; | ||
1166 | if (isp->smk_mmap == NULL) | ||
1167 | return 0; | ||
1168 | msmack = isp->smk_mmap; | ||
1169 | |||
1170 | tsp = current_security(); | ||
1171 | sp = smk_of_current(); | ||
1172 | rc = 0; | ||
1173 | |||
1174 | rcu_read_lock(); | ||
1175 | /* | ||
1176 | * For each Smack rule associated with the subject | ||
1177 | * label verify that the SMACK64MMAP also has access | ||
1178 | * to that rule's object label. | ||
1179 | * | ||
1180 | * Because neither of the labels comes | ||
1181 | * from the networking code it is sufficient | ||
1182 | * to compare pointers. | ||
1183 | */ | ||
1184 | list_for_each_entry_rcu(srp, &smack_rule_list, list) { | ||
1185 | if (srp->smk_subject != sp) | ||
1186 | continue; | ||
1187 | |||
1188 | osmack = srp->smk_object; | ||
1189 | /* | ||
1190 | * Matching labels always allows access. | ||
1191 | */ | ||
1192 | if (msmack == osmack) | ||
1193 | continue; | ||
1194 | /* | ||
1195 | * If there is a matching local rule take | ||
1196 | * that into account as well. | ||
1197 | */ | ||
1198 | may = smk_access_entry(srp->smk_subject, osmack, | ||
1199 | &tsp->smk_rules); | ||
1200 | if (may == -ENOENT) | ||
1201 | may = srp->smk_access; | ||
1202 | else | ||
1203 | may &= srp->smk_access; | ||
1204 | /* | ||
1205 | * If may is zero the SMACK64MMAP subject can't | ||
1206 | * possibly have less access. | ||
1207 | */ | ||
1208 | if (may == 0) | ||
1209 | continue; | ||
1210 | |||
1211 | /* | ||
1212 | * Fetch the global list entry. | ||
1213 | * If there isn't one a SMACK64MMAP subject | ||
1214 | * can't have as much access as current. | ||
1215 | */ | ||
1216 | mmay = smk_access_entry(msmack, osmack, &smack_rule_list); | ||
1217 | if (mmay == -ENOENT) { | ||
1218 | rc = -EACCES; | ||
1219 | break; | ||
1220 | } | ||
1221 | /* | ||
1222 | * If there is a local entry it modifies the | ||
1223 | * potential access, too. | ||
1224 | */ | ||
1225 | tmay = smk_access_entry(msmack, osmack, &tsp->smk_rules); | ||
1226 | if (tmay != -ENOENT) | ||
1227 | mmay &= tmay; | ||
1228 | |||
1229 | /* | ||
1230 | * If there is any access available to current that is | ||
1231 | * not available to a SMACK64MMAP subject | ||
1232 | * deny access. | ||
1233 | */ | ||
1234 | if ((may | mmay) != mmay) { | ||
1235 | rc = -EACCES; | ||
1236 | break; | ||
1237 | } | ||
1238 | } | ||
1239 | |||
1240 | rcu_read_unlock(); | ||
1241 | |||
1242 | return rc; | ||
1243 | } | ||
1244 | |||
1245 | /** | ||
1004 | * smack_file_set_fowner - set the file security blob value | 1246 | * smack_file_set_fowner - set the file security blob value |
1005 | * @file: object in question | 1247 | * @file: object in question |
1006 | * | 1248 | * |
@@ -1009,7 +1251,7 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
1009 | */ | 1251 | */ |
1010 | static int smack_file_set_fowner(struct file *file) | 1252 | static int smack_file_set_fowner(struct file *file) |
1011 | { | 1253 | { |
1012 | file->f_security = current_security(); | 1254 | file->f_security = smk_of_current(); |
1013 | return 0; | 1255 | return 0; |
1014 | } | 1256 | } |
1015 | 1257 | ||
@@ -1029,13 +1271,14 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, | |||
1029 | { | 1271 | { |
1030 | struct file *file; | 1272 | struct file *file; |
1031 | int rc; | 1273 | int rc; |
1032 | char *tsp = tsk->cred->security; | 1274 | char *tsp = smk_of_task(tsk->cred->security); |
1033 | struct smk_audit_info ad; | 1275 | struct smk_audit_info ad; |
1034 | 1276 | ||
1035 | /* | 1277 | /* |
1036 | * struct fown_struct is never outside the context of a struct file | 1278 | * struct fown_struct is never outside the context of a struct file |
1037 | */ | 1279 | */ |
1038 | file = container_of(fown, struct file, f_owner); | 1280 | file = container_of(fown, struct file, f_owner); |
1281 | |||
1039 | /* we don't log here as rc can be overriden */ | 1282 | /* we don't log here as rc can be overriden */ |
1040 | rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL); | 1283 | rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL); |
1041 | if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) | 1284 | if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) |
@@ -1086,7 +1329,14 @@ static int smack_file_receive(struct file *file) | |||
1086 | */ | 1329 | */ |
1087 | static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) | 1330 | static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) |
1088 | { | 1331 | { |
1089 | cred->security = NULL; | 1332 | struct task_smack *tsp; |
1333 | |||
1334 | tsp = new_task_smack(NULL, NULL, gfp); | ||
1335 | if (tsp == NULL) | ||
1336 | return -ENOMEM; | ||
1337 | |||
1338 | cred->security = tsp; | ||
1339 | |||
1090 | return 0; | 1340 | return 0; |
1091 | } | 1341 | } |
1092 | 1342 | ||
@@ -1095,13 +1345,24 @@ static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) | |||
1095 | * smack_cred_free - "free" task-level security credentials | 1345 | * smack_cred_free - "free" task-level security credentials |
1096 | * @cred: the credentials in question | 1346 | * @cred: the credentials in question |
1097 | * | 1347 | * |
1098 | * Smack isn't using copies of blobs. Everyone | ||
1099 | * points to an immutable list. The blobs never go away. | ||
1100 | * There is no leak here. | ||
1101 | */ | 1348 | */ |
1102 | static void smack_cred_free(struct cred *cred) | 1349 | static void smack_cred_free(struct cred *cred) |
1103 | { | 1350 | { |
1351 | struct task_smack *tsp = cred->security; | ||
1352 | struct smack_rule *rp; | ||
1353 | struct list_head *l; | ||
1354 | struct list_head *n; | ||
1355 | |||
1356 | if (tsp == NULL) | ||
1357 | return; | ||
1104 | cred->security = NULL; | 1358 | cred->security = NULL; |
1359 | |||
1360 | list_for_each_safe(l, n, &tsp->smk_rules) { | ||
1361 | rp = list_entry(l, struct smack_rule, list); | ||
1362 | list_del(&rp->list); | ||
1363 | kfree(rp); | ||
1364 | } | ||
1365 | kfree(tsp); | ||
1105 | } | 1366 | } |
1106 | 1367 | ||
1107 | /** | 1368 | /** |
@@ -1115,7 +1376,19 @@ static void smack_cred_free(struct cred *cred) | |||
1115 | static int smack_cred_prepare(struct cred *new, const struct cred *old, | 1376 | static int smack_cred_prepare(struct cred *new, const struct cred *old, |
1116 | gfp_t gfp) | 1377 | gfp_t gfp) |
1117 | { | 1378 | { |
1118 | new->security = old->security; | 1379 | struct task_smack *old_tsp = old->security; |
1380 | struct task_smack *new_tsp; | ||
1381 | int rc; | ||
1382 | |||
1383 | new_tsp = new_task_smack(old_tsp->smk_task, old_tsp->smk_task, gfp); | ||
1384 | if (new_tsp == NULL) | ||
1385 | return -ENOMEM; | ||
1386 | |||
1387 | rc = smk_copy_rules(&new_tsp->smk_rules, &old_tsp->smk_rules, gfp); | ||
1388 | if (rc != 0) | ||
1389 | return rc; | ||
1390 | |||
1391 | new->security = new_tsp; | ||
1119 | return 0; | 1392 | return 0; |
1120 | } | 1393 | } |
1121 | 1394 | ||
@@ -1128,7 +1401,16 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old, | |||
1128 | */ | 1401 | */ |
1129 | static void smack_cred_transfer(struct cred *new, const struct cred *old) | 1402 | static void smack_cred_transfer(struct cred *new, const struct cred *old) |
1130 | { | 1403 | { |
1131 | new->security = old->security; | 1404 | struct task_smack *old_tsp = old->security; |
1405 | struct task_smack *new_tsp = new->security; | ||
1406 | |||
1407 | new_tsp->smk_task = old_tsp->smk_task; | ||
1408 | new_tsp->smk_forked = old_tsp->smk_task; | ||
1409 | mutex_init(&new_tsp->smk_rules_lock); | ||
1410 | INIT_LIST_HEAD(&new_tsp->smk_rules); | ||
1411 | |||
1412 | |||
1413 | /* cbs copy rule list */ | ||
1132 | } | 1414 | } |
1133 | 1415 | ||
1134 | /** | 1416 | /** |
@@ -1140,12 +1422,13 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old) | |||
1140 | */ | 1422 | */ |
1141 | static int smack_kernel_act_as(struct cred *new, u32 secid) | 1423 | static int smack_kernel_act_as(struct cred *new, u32 secid) |
1142 | { | 1424 | { |
1425 | struct task_smack *new_tsp = new->security; | ||
1143 | char *smack = smack_from_secid(secid); | 1426 | char *smack = smack_from_secid(secid); |
1144 | 1427 | ||
1145 | if (smack == NULL) | 1428 | if (smack == NULL) |
1146 | return -EINVAL; | 1429 | return -EINVAL; |
1147 | 1430 | ||
1148 | new->security = smack; | 1431 | new_tsp->smk_task = smack; |
1149 | return 0; | 1432 | return 0; |
1150 | } | 1433 | } |
1151 | 1434 | ||
@@ -1161,8 +1444,10 @@ static int smack_kernel_create_files_as(struct cred *new, | |||
1161 | struct inode *inode) | 1444 | struct inode *inode) |
1162 | { | 1445 | { |
1163 | struct inode_smack *isp = inode->i_security; | 1446 | struct inode_smack *isp = inode->i_security; |
1447 | struct task_smack *tsp = new->security; | ||
1164 | 1448 | ||
1165 | new->security = isp->smk_inode; | 1449 | tsp->smk_forked = isp->smk_inode; |
1450 | tsp->smk_task = isp->smk_inode; | ||
1166 | return 0; | 1451 | return 0; |
1167 | } | 1452 | } |
1168 | 1453 | ||
@@ -1179,7 +1464,7 @@ static int smk_curacc_on_task(struct task_struct *p, int access) | |||
1179 | 1464 | ||
1180 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 1465 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
1181 | smk_ad_setfield_u_tsk(&ad, p); | 1466 | smk_ad_setfield_u_tsk(&ad, p); |
1182 | return smk_curacc(task_security(p), access, &ad); | 1467 | return smk_curacc(smk_of_task(task_security(p)), access, &ad); |
1183 | } | 1468 | } |
1184 | 1469 | ||
1185 | /** | 1470 | /** |
@@ -1225,7 +1510,7 @@ static int smack_task_getsid(struct task_struct *p) | |||
1225 | */ | 1510 | */ |
1226 | static void smack_task_getsecid(struct task_struct *p, u32 *secid) | 1511 | static void smack_task_getsecid(struct task_struct *p, u32 *secid) |
1227 | { | 1512 | { |
1228 | *secid = smack_to_secid(task_security(p)); | 1513 | *secid = smack_to_secid(smk_of_task(task_security(p))); |
1229 | } | 1514 | } |
1230 | 1515 | ||
1231 | /** | 1516 | /** |
@@ -1281,12 +1566,11 @@ static int smack_task_getioprio(struct task_struct *p) | |||
1281 | * | 1566 | * |
1282 | * Return 0 if read access is permitted | 1567 | * Return 0 if read access is permitted |
1283 | */ | 1568 | */ |
1284 | static int smack_task_setscheduler(struct task_struct *p, int policy, | 1569 | static int smack_task_setscheduler(struct task_struct *p) |
1285 | struct sched_param *lp) | ||
1286 | { | 1570 | { |
1287 | int rc; | 1571 | int rc; |
1288 | 1572 | ||
1289 | rc = cap_task_setscheduler(p, policy, lp); | 1573 | rc = cap_task_setscheduler(p); |
1290 | if (rc == 0) | 1574 | if (rc == 0) |
1291 | rc = smk_curacc_on_task(p, MAY_WRITE); | 1575 | rc = smk_curacc_on_task(p, MAY_WRITE); |
1292 | return rc; | 1576 | return rc; |
@@ -1338,14 +1622,15 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, | |||
1338 | * can write the receiver. | 1622 | * can write the receiver. |
1339 | */ | 1623 | */ |
1340 | if (secid == 0) | 1624 | if (secid == 0) |
1341 | return smk_curacc(task_security(p), MAY_WRITE, &ad); | 1625 | return smk_curacc(smk_of_task(task_security(p)), MAY_WRITE, |
1626 | &ad); | ||
1342 | /* | 1627 | /* |
1343 | * If the secid isn't 0 we're dealing with some USB IO | 1628 | * If the secid isn't 0 we're dealing with some USB IO |
1344 | * specific behavior. This is not clean. For one thing | 1629 | * specific behavior. This is not clean. For one thing |
1345 | * we can't take privilege into account. | 1630 | * we can't take privilege into account. |
1346 | */ | 1631 | */ |
1347 | return smk_access(smack_from_secid(secid), task_security(p), | 1632 | return smk_access(smack_from_secid(secid), |
1348 | MAY_WRITE, &ad); | 1633 | smk_of_task(task_security(p)), MAY_WRITE, &ad); |
1349 | } | 1634 | } |
1350 | 1635 | ||
1351 | /** | 1636 | /** |
@@ -1357,12 +1642,12 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, | |||
1357 | static int smack_task_wait(struct task_struct *p) | 1642 | static int smack_task_wait(struct task_struct *p) |
1358 | { | 1643 | { |
1359 | struct smk_audit_info ad; | 1644 | struct smk_audit_info ad; |
1360 | char *sp = current_security(); | 1645 | char *sp = smk_of_current(); |
1361 | char *tsp = task_security(p); | 1646 | char *tsp = smk_of_forked(task_security(p)); |
1362 | int rc; | 1647 | int rc; |
1363 | 1648 | ||
1364 | /* we don't log here, we can be overriden */ | 1649 | /* we don't log here, we can be overriden */ |
1365 | rc = smk_access(sp, tsp, MAY_WRITE, NULL); | 1650 | rc = smk_access(tsp, sp, MAY_WRITE, NULL); |
1366 | if (rc == 0) | 1651 | if (rc == 0) |
1367 | goto out_log; | 1652 | goto out_log; |
1368 | 1653 | ||
@@ -1383,7 +1668,7 @@ static int smack_task_wait(struct task_struct *p) | |||
1383 | out_log: | 1668 | out_log: |
1384 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 1669 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
1385 | smk_ad_setfield_u_tsk(&ad, p); | 1670 | smk_ad_setfield_u_tsk(&ad, p); |
1386 | smack_log(sp, tsp, MAY_WRITE, rc, &ad); | 1671 | smack_log(tsp, sp, MAY_WRITE, rc, &ad); |
1387 | return rc; | 1672 | return rc; |
1388 | } | 1673 | } |
1389 | 1674 | ||
@@ -1397,7 +1682,7 @@ static int smack_task_wait(struct task_struct *p) | |||
1397 | static void smack_task_to_inode(struct task_struct *p, struct inode *inode) | 1682 | static void smack_task_to_inode(struct task_struct *p, struct inode *inode) |
1398 | { | 1683 | { |
1399 | struct inode_smack *isp = inode->i_security; | 1684 | struct inode_smack *isp = inode->i_security; |
1400 | isp->smk_inode = task_security(p); | 1685 | isp->smk_inode = smk_of_task(task_security(p)); |
1401 | } | 1686 | } |
1402 | 1687 | ||
1403 | /* | 1688 | /* |
@@ -1416,7 +1701,7 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode) | |||
1416 | */ | 1701 | */ |
1417 | static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) | 1702 | static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) |
1418 | { | 1703 | { |
1419 | char *csp = current_security(); | 1704 | char *csp = smk_of_current(); |
1420 | struct socket_smack *ssp; | 1705 | struct socket_smack *ssp; |
1421 | 1706 | ||
1422 | ssp = kzalloc(sizeof(struct socket_smack), gfp_flags); | 1707 | ssp = kzalloc(sizeof(struct socket_smack), gfp_flags); |
@@ -1519,7 +1804,7 @@ static void smack_set_catset(char *catset, struct netlbl_lsm_secattr *sap) | |||
1519 | * Casey says that CIPSO is good enough for now. | 1804 | * Casey says that CIPSO is good enough for now. |
1520 | * It can be used to effect. | 1805 | * It can be used to effect. |
1521 | * It can also be abused to effect when necessary. | 1806 | * It can also be abused to effect when necessary. |
1522 | * Appologies to the TSIG group in general and GW in particular. | 1807 | * Apologies to the TSIG group in general and GW in particular. |
1523 | */ | 1808 | */ |
1524 | static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp) | 1809 | static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp) |
1525 | { | 1810 | { |
@@ -1672,10 +1957,13 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, | |||
1672 | ssp->smk_in = sp; | 1957 | ssp->smk_in = sp; |
1673 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { | 1958 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { |
1674 | ssp->smk_out = sp; | 1959 | ssp->smk_out = sp; |
1675 | rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); | 1960 | if (sock->sk->sk_family != PF_UNIX) { |
1676 | if (rc != 0) | 1961 | rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); |
1677 | printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n", | 1962 | if (rc != 0) |
1678 | __func__, -rc); | 1963 | printk(KERN_WARNING |
1964 | "Smack: \"%s\" netlbl error %d.\n", | ||
1965 | __func__, -rc); | ||
1966 | } | ||
1679 | } else | 1967 | } else |
1680 | return -EOPNOTSUPP; | 1968 | return -EOPNOTSUPP; |
1681 | 1969 | ||
@@ -1754,7 +2042,7 @@ static int smack_flags_to_may(int flags) | |||
1754 | */ | 2042 | */ |
1755 | static int smack_msg_msg_alloc_security(struct msg_msg *msg) | 2043 | static int smack_msg_msg_alloc_security(struct msg_msg *msg) |
1756 | { | 2044 | { |
1757 | msg->security = current_security(); | 2045 | msg->security = smk_of_current(); |
1758 | return 0; | 2046 | return 0; |
1759 | } | 2047 | } |
1760 | 2048 | ||
@@ -1790,7 +2078,7 @@ static int smack_shm_alloc_security(struct shmid_kernel *shp) | |||
1790 | { | 2078 | { |
1791 | struct kern_ipc_perm *isp = &shp->shm_perm; | 2079 | struct kern_ipc_perm *isp = &shp->shm_perm; |
1792 | 2080 | ||
1793 | isp->security = current_security(); | 2081 | isp->security = smk_of_current(); |
1794 | return 0; | 2082 | return 0; |
1795 | } | 2083 | } |
1796 | 2084 | ||
@@ -1913,7 +2201,7 @@ static int smack_sem_alloc_security(struct sem_array *sma) | |||
1913 | { | 2201 | { |
1914 | struct kern_ipc_perm *isp = &sma->sem_perm; | 2202 | struct kern_ipc_perm *isp = &sma->sem_perm; |
1915 | 2203 | ||
1916 | isp->security = current_security(); | 2204 | isp->security = smk_of_current(); |
1917 | return 0; | 2205 | return 0; |
1918 | } | 2206 | } |
1919 | 2207 | ||
@@ -2031,7 +2319,7 @@ static int smack_msg_queue_alloc_security(struct msg_queue *msq) | |||
2031 | { | 2319 | { |
2032 | struct kern_ipc_perm *kisp = &msq->q_perm; | 2320 | struct kern_ipc_perm *kisp = &msq->q_perm; |
2033 | 2321 | ||
2034 | kisp->security = current_security(); | 2322 | kisp->security = smk_of_current(); |
2035 | return 0; | 2323 | return 0; |
2036 | } | 2324 | } |
2037 | 2325 | ||
@@ -2203,9 +2491,11 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2203 | struct super_block *sbp; | 2491 | struct super_block *sbp; |
2204 | struct superblock_smack *sbsp; | 2492 | struct superblock_smack *sbsp; |
2205 | struct inode_smack *isp; | 2493 | struct inode_smack *isp; |
2206 | char *csp = current_security(); | 2494 | char *csp = smk_of_current(); |
2207 | char *fetched; | 2495 | char *fetched; |
2208 | char *final; | 2496 | char *final; |
2497 | char trattr[TRANS_TRUE_SIZE]; | ||
2498 | int transflag = 0; | ||
2209 | struct dentry *dp; | 2499 | struct dentry *dp; |
2210 | 2500 | ||
2211 | if (inode == NULL) | 2501 | if (inode == NULL) |
@@ -2250,7 +2540,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2250 | switch (sbp->s_magic) { | 2540 | switch (sbp->s_magic) { |
2251 | case SMACK_MAGIC: | 2541 | case SMACK_MAGIC: |
2252 | /* | 2542 | /* |
2253 | * Casey says that it's a little embarassing | 2543 | * Casey says that it's a little embarrassing |
2254 | * that the smack file system doesn't do | 2544 | * that the smack file system doesn't do |
2255 | * extended attributes. | 2545 | * extended attributes. |
2256 | */ | 2546 | */ |
@@ -2272,9 +2562,10 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2272 | break; | 2562 | break; |
2273 | case SOCKFS_MAGIC: | 2563 | case SOCKFS_MAGIC: |
2274 | /* | 2564 | /* |
2275 | * Casey says sockets get the smack of the task. | 2565 | * Socket access is controlled by the socket |
2566 | * structures associated with the task involved. | ||
2276 | */ | 2567 | */ |
2277 | final = csp; | 2568 | final = smack_known_star.smk_known; |
2278 | break; | 2569 | break; |
2279 | case PROC_SUPER_MAGIC: | 2570 | case PROC_SUPER_MAGIC: |
2280 | /* | 2571 | /* |
@@ -2301,7 +2592,16 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2301 | /* | 2592 | /* |
2302 | * This isn't an understood special case. | 2593 | * This isn't an understood special case. |
2303 | * Get the value from the xattr. | 2594 | * Get the value from the xattr. |
2304 | * | 2595 | */ |
2596 | |||
2597 | /* | ||
2598 | * UNIX domain sockets use lower level socket data. | ||
2599 | */ | ||
2600 | if (S_ISSOCK(inode->i_mode)) { | ||
2601 | final = smack_known_star.smk_known; | ||
2602 | break; | ||
2603 | } | ||
2604 | /* | ||
2305 | * No xattr support means, alas, no SMACK label. | 2605 | * No xattr support means, alas, no SMACK label. |
2306 | * Use the aforeapplied default. | 2606 | * Use the aforeapplied default. |
2307 | * It would be curious if the label of the task | 2607 | * It would be curious if the label of the task |
@@ -2313,9 +2613,22 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2313 | * Get the dentry for xattr. | 2613 | * Get the dentry for xattr. |
2314 | */ | 2614 | */ |
2315 | dp = dget(opt_dentry); | 2615 | dp = dget(opt_dentry); |
2316 | fetched = smk_fetch(inode, dp); | 2616 | fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp); |
2317 | if (fetched != NULL) | 2617 | if (fetched != NULL) { |
2318 | final = fetched; | 2618 | final = fetched; |
2619 | if (S_ISDIR(inode->i_mode)) { | ||
2620 | trattr[0] = '\0'; | ||
2621 | inode->i_op->getxattr(dp, | ||
2622 | XATTR_NAME_SMACKTRANSMUTE, | ||
2623 | trattr, TRANS_TRUE_SIZE); | ||
2624 | if (strncmp(trattr, TRANS_TRUE, | ||
2625 | TRANS_TRUE_SIZE) == 0) | ||
2626 | transflag = SMK_INODE_TRANSMUTE; | ||
2627 | } | ||
2628 | } | ||
2629 | isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); | ||
2630 | isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp); | ||
2631 | |||
2319 | dput(dp); | 2632 | dput(dp); |
2320 | break; | 2633 | break; |
2321 | } | 2634 | } |
@@ -2325,7 +2638,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2325 | else | 2638 | else |
2326 | isp->smk_inode = final; | 2639 | isp->smk_inode = final; |
2327 | 2640 | ||
2328 | isp->smk_flags |= SMK_INODE_INSTANT; | 2641 | isp->smk_flags |= (SMK_INODE_INSTANT | transflag); |
2329 | 2642 | ||
2330 | unlockandout: | 2643 | unlockandout: |
2331 | mutex_unlock(&isp->smk_lock); | 2644 | mutex_unlock(&isp->smk_lock); |
@@ -2350,7 +2663,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value) | |||
2350 | if (strcmp(name, "current") != 0) | 2663 | if (strcmp(name, "current") != 0) |
2351 | return -EINVAL; | 2664 | return -EINVAL; |
2352 | 2665 | ||
2353 | cp = kstrdup(task_security(p), GFP_KERNEL); | 2666 | cp = kstrdup(smk_of_task(task_security(p)), GFP_KERNEL); |
2354 | if (cp == NULL) | 2667 | if (cp == NULL) |
2355 | return -ENOMEM; | 2668 | return -ENOMEM; |
2356 | 2669 | ||
@@ -2374,6 +2687,9 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value) | |||
2374 | static int smack_setprocattr(struct task_struct *p, char *name, | 2687 | static int smack_setprocattr(struct task_struct *p, char *name, |
2375 | void *value, size_t size) | 2688 | void *value, size_t size) |
2376 | { | 2689 | { |
2690 | int rc; | ||
2691 | struct task_smack *tsp; | ||
2692 | struct task_smack *oldtsp; | ||
2377 | struct cred *new; | 2693 | struct cred *new; |
2378 | char *newsmack; | 2694 | char *newsmack; |
2379 | 2695 | ||
@@ -2403,34 +2719,49 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
2403 | if (newsmack == smack_known_web.smk_known) | 2719 | if (newsmack == smack_known_web.smk_known) |
2404 | return -EPERM; | 2720 | return -EPERM; |
2405 | 2721 | ||
2722 | oldtsp = p->cred->security; | ||
2406 | new = prepare_creds(); | 2723 | new = prepare_creds(); |
2407 | if (new == NULL) | 2724 | if (new == NULL) |
2408 | return -ENOMEM; | 2725 | return -ENOMEM; |
2409 | new->security = newsmack; | 2726 | |
2727 | tsp = new_task_smack(newsmack, oldtsp->smk_forked, GFP_KERNEL); | ||
2728 | if (tsp == NULL) { | ||
2729 | kfree(new); | ||
2730 | return -ENOMEM; | ||
2731 | } | ||
2732 | rc = smk_copy_rules(&tsp->smk_rules, &oldtsp->smk_rules, GFP_KERNEL); | ||
2733 | if (rc != 0) | ||
2734 | return rc; | ||
2735 | |||
2736 | new->security = tsp; | ||
2410 | commit_creds(new); | 2737 | commit_creds(new); |
2411 | return size; | 2738 | return size; |
2412 | } | 2739 | } |
2413 | 2740 | ||
2414 | /** | 2741 | /** |
2415 | * smack_unix_stream_connect - Smack access on UDS | 2742 | * smack_unix_stream_connect - Smack access on UDS |
2416 | * @sock: one socket | 2743 | * @sock: one sock |
2417 | * @other: the other socket | 2744 | * @other: the other sock |
2418 | * @newsk: unused | 2745 | * @newsk: unused |
2419 | * | 2746 | * |
2420 | * Return 0 if a subject with the smack of sock could access | 2747 | * Return 0 if a subject with the smack of sock could access |
2421 | * an object with the smack of other, otherwise an error code | 2748 | * an object with the smack of other, otherwise an error code |
2422 | */ | 2749 | */ |
2423 | static int smack_unix_stream_connect(struct socket *sock, | 2750 | static int smack_unix_stream_connect(struct sock *sock, |
2424 | struct socket *other, struct sock *newsk) | 2751 | struct sock *other, struct sock *newsk) |
2425 | { | 2752 | { |
2426 | struct inode *sp = SOCK_INODE(sock); | 2753 | struct socket_smack *ssp = sock->sk_security; |
2427 | struct inode *op = SOCK_INODE(other); | 2754 | struct socket_smack *osp = other->sk_security; |
2428 | struct smk_audit_info ad; | 2755 | struct smk_audit_info ad; |
2756 | int rc = 0; | ||
2429 | 2757 | ||
2430 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); | 2758 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); |
2431 | smk_ad_setfield_u_net_sk(&ad, other->sk); | 2759 | smk_ad_setfield_u_net_sk(&ad, other); |
2432 | return smk_access(smk_of_inode(sp), smk_of_inode(op), | 2760 | |
2433 | MAY_READWRITE, &ad); | 2761 | if (!capable(CAP_MAC_OVERRIDE)) |
2762 | rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); | ||
2763 | |||
2764 | return rc; | ||
2434 | } | 2765 | } |
2435 | 2766 | ||
2436 | /** | 2767 | /** |
@@ -2443,13 +2774,18 @@ static int smack_unix_stream_connect(struct socket *sock, | |||
2443 | */ | 2774 | */ |
2444 | static int smack_unix_may_send(struct socket *sock, struct socket *other) | 2775 | static int smack_unix_may_send(struct socket *sock, struct socket *other) |
2445 | { | 2776 | { |
2446 | struct inode *sp = SOCK_INODE(sock); | 2777 | struct socket_smack *ssp = sock->sk->sk_security; |
2447 | struct inode *op = SOCK_INODE(other); | 2778 | struct socket_smack *osp = other->sk->sk_security; |
2448 | struct smk_audit_info ad; | 2779 | struct smk_audit_info ad; |
2780 | int rc = 0; | ||
2449 | 2781 | ||
2450 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); | 2782 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); |
2451 | smk_ad_setfield_u_net_sk(&ad, other->sk); | 2783 | smk_ad_setfield_u_net_sk(&ad, other->sk); |
2452 | return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_WRITE, &ad); | 2784 | |
2785 | if (!capable(CAP_MAC_OVERRIDE)) | ||
2786 | rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); | ||
2787 | |||
2788 | return rc; | ||
2453 | } | 2789 | } |
2454 | 2790 | ||
2455 | /** | 2791 | /** |
@@ -2634,7 +2970,7 @@ static int smack_socket_getpeersec_stream(struct socket *sock, | |||
2634 | 2970 | ||
2635 | /** | 2971 | /** |
2636 | * smack_socket_getpeersec_dgram - pull in packet label | 2972 | * smack_socket_getpeersec_dgram - pull in packet label |
2637 | * @sock: the socket | 2973 | * @sock: the peer socket |
2638 | * @skb: packet data | 2974 | * @skb: packet data |
2639 | * @secid: pointer to where to put the secid of the packet | 2975 | * @secid: pointer to where to put the secid of the packet |
2640 | * | 2976 | * |
@@ -2645,41 +2981,39 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, | |||
2645 | 2981 | ||
2646 | { | 2982 | { |
2647 | struct netlbl_lsm_secattr secattr; | 2983 | struct netlbl_lsm_secattr secattr; |
2648 | struct sock *sk; | 2984 | struct socket_smack *sp; |
2649 | char smack[SMK_LABELLEN]; | 2985 | char smack[SMK_LABELLEN]; |
2650 | int family = PF_INET; | 2986 | int family = PF_UNSPEC; |
2651 | u32 s; | 2987 | u32 s = 0; /* 0 is the invalid secid */ |
2652 | int rc; | 2988 | int rc; |
2653 | 2989 | ||
2654 | /* | 2990 | if (skb != NULL) { |
2655 | * Only works for families with packets. | 2991 | if (skb->protocol == htons(ETH_P_IP)) |
2656 | */ | 2992 | family = PF_INET; |
2657 | if (sock != NULL) { | 2993 | else if (skb->protocol == htons(ETH_P_IPV6)) |
2658 | sk = sock->sk; | 2994 | family = PF_INET6; |
2659 | if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) | ||
2660 | return 0; | ||
2661 | family = sk->sk_family; | ||
2662 | } | 2995 | } |
2663 | /* | 2996 | if (family == PF_UNSPEC && sock != NULL) |
2664 | * Translate what netlabel gave us. | 2997 | family = sock->sk->sk_family; |
2665 | */ | ||
2666 | netlbl_secattr_init(&secattr); | ||
2667 | rc = netlbl_skbuff_getattr(skb, family, &secattr); | ||
2668 | if (rc == 0) | ||
2669 | smack_from_secattr(&secattr, smack); | ||
2670 | netlbl_secattr_destroy(&secattr); | ||
2671 | 2998 | ||
2672 | /* | 2999 | if (family == PF_UNIX) { |
2673 | * Give up if we couldn't get anything | 3000 | sp = sock->sk->sk_security; |
2674 | */ | 3001 | s = smack_to_secid(sp->smk_out); |
2675 | if (rc != 0) | 3002 | } else if (family == PF_INET || family == PF_INET6) { |
2676 | return rc; | 3003 | /* |
2677 | 3004 | * Translate what netlabel gave us. | |
2678 | s = smack_to_secid(smack); | 3005 | */ |
3006 | netlbl_secattr_init(&secattr); | ||
3007 | rc = netlbl_skbuff_getattr(skb, family, &secattr); | ||
3008 | if (rc == 0) { | ||
3009 | smack_from_secattr(&secattr, smack); | ||
3010 | s = smack_to_secid(smack); | ||
3011 | } | ||
3012 | netlbl_secattr_destroy(&secattr); | ||
3013 | } | ||
3014 | *secid = s; | ||
2679 | if (s == 0) | 3015 | if (s == 0) |
2680 | return -EINVAL; | 3016 | return -EINVAL; |
2681 | |||
2682 | *secid = s; | ||
2683 | return 0; | 3017 | return 0; |
2684 | } | 3018 | } |
2685 | 3019 | ||
@@ -2700,7 +3034,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent) | |||
2700 | return; | 3034 | return; |
2701 | 3035 | ||
2702 | ssp = sk->sk_security; | 3036 | ssp = sk->sk_security; |
2703 | ssp->smk_in = ssp->smk_out = current_security(); | 3037 | ssp->smk_in = ssp->smk_out = smk_of_current(); |
2704 | /* cssp->smk_packet is already set in smack_inet_csk_clone() */ | 3038 | /* cssp->smk_packet is already set in smack_inet_csk_clone() */ |
2705 | } | 3039 | } |
2706 | 3040 | ||
@@ -2760,7 +3094,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
2760 | /* | 3094 | /* |
2761 | * We need to decide if we want to label the incoming connection here | 3095 | * We need to decide if we want to label the incoming connection here |
2762 | * if we do we only need to label the request_sock and the stack will | 3096 | * if we do we only need to label the request_sock and the stack will |
2763 | * propogate the wire-label to the sock when it is created. | 3097 | * propagate the wire-label to the sock when it is created. |
2764 | */ | 3098 | */ |
2765 | hdr = ip_hdr(skb); | 3099 | hdr = ip_hdr(skb); |
2766 | addr.sin_addr.s_addr = hdr->saddr; | 3100 | addr.sin_addr.s_addr = hdr->saddr; |
@@ -2821,7 +3155,7 @@ static void smack_inet_csk_clone(struct sock *sk, | |||
2821 | static int smack_key_alloc(struct key *key, const struct cred *cred, | 3155 | static int smack_key_alloc(struct key *key, const struct cred *cred, |
2822 | unsigned long flags) | 3156 | unsigned long flags) |
2823 | { | 3157 | { |
2824 | key->security = cred->security; | 3158 | key->security = smk_of_task(cred->security); |
2825 | return 0; | 3159 | return 0; |
2826 | } | 3160 | } |
2827 | 3161 | ||
@@ -2850,6 +3184,7 @@ static int smack_key_permission(key_ref_t key_ref, | |||
2850 | { | 3184 | { |
2851 | struct key *keyp; | 3185 | struct key *keyp; |
2852 | struct smk_audit_info ad; | 3186 | struct smk_audit_info ad; |
3187 | char *tsp = smk_of_task(cred->security); | ||
2853 | 3188 | ||
2854 | keyp = key_ref_to_ptr(key_ref); | 3189 | keyp = key_ref_to_ptr(key_ref); |
2855 | if (keyp == NULL) | 3190 | if (keyp == NULL) |
@@ -2863,14 +3198,14 @@ static int smack_key_permission(key_ref_t key_ref, | |||
2863 | /* | 3198 | /* |
2864 | * This should not occur | 3199 | * This should not occur |
2865 | */ | 3200 | */ |
2866 | if (cred->security == NULL) | 3201 | if (tsp == NULL) |
2867 | return -EACCES; | 3202 | return -EACCES; |
2868 | #ifdef CONFIG_AUDIT | 3203 | #ifdef CONFIG_AUDIT |
2869 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_KEY); | 3204 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_KEY); |
2870 | ad.a.u.key_struct.key = keyp->serial; | 3205 | ad.a.u.key_struct.key = keyp->serial; |
2871 | ad.a.u.key_struct.key_desc = keyp->description; | 3206 | ad.a.u.key_struct.key_desc = keyp->description; |
2872 | #endif | 3207 | #endif |
2873 | return smk_access(cred->security, keyp->security, | 3208 | return smk_access(tsp, keyp->security, |
2874 | MAY_READWRITE, &ad); | 3209 | MAY_READWRITE, &ad); |
2875 | } | 3210 | } |
2876 | #endif /* CONFIG_KEYS */ | 3211 | #endif /* CONFIG_KEYS */ |
@@ -3005,7 +3340,8 @@ static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | |||
3005 | { | 3340 | { |
3006 | char *sp = smack_from_secid(secid); | 3341 | char *sp = smack_from_secid(secid); |
3007 | 3342 | ||
3008 | *secdata = sp; | 3343 | if (secdata) |
3344 | *secdata = sp; | ||
3009 | *seclen = strlen(sp); | 3345 | *seclen = strlen(sp); |
3010 | return 0; | 3346 | return 0; |
3011 | } | 3347 | } |
@@ -3071,6 +3407,8 @@ struct security_operations smack_ops = { | |||
3071 | .sb_mount = smack_sb_mount, | 3407 | .sb_mount = smack_sb_mount, |
3072 | .sb_umount = smack_sb_umount, | 3408 | .sb_umount = smack_sb_umount, |
3073 | 3409 | ||
3410 | .bprm_set_creds = smack_bprm_set_creds, | ||
3411 | |||
3074 | .inode_alloc_security = smack_inode_alloc_security, | 3412 | .inode_alloc_security = smack_inode_alloc_security, |
3075 | .inode_free_security = smack_inode_free_security, | 3413 | .inode_free_security = smack_inode_free_security, |
3076 | .inode_init_security = smack_inode_init_security, | 3414 | .inode_init_security = smack_inode_init_security, |
@@ -3096,6 +3434,7 @@ struct security_operations smack_ops = { | |||
3096 | .file_ioctl = smack_file_ioctl, | 3434 | .file_ioctl = smack_file_ioctl, |
3097 | .file_lock = smack_file_lock, | 3435 | .file_lock = smack_file_lock, |
3098 | .file_fcntl = smack_file_fcntl, | 3436 | .file_fcntl = smack_file_fcntl, |
3437 | .file_mmap = smack_file_mmap, | ||
3099 | .file_set_fowner = smack_file_set_fowner, | 3438 | .file_set_fowner = smack_file_set_fowner, |
3100 | .file_send_sigiotask = smack_file_send_sigiotask, | 3439 | .file_send_sigiotask = smack_file_send_sigiotask, |
3101 | .file_receive = smack_file_receive, | 3440 | .file_receive = smack_file_receive, |
@@ -3207,17 +3546,23 @@ static __init void init_smack_know_list(void) | |||
3207 | static __init int smack_init(void) | 3546 | static __init int smack_init(void) |
3208 | { | 3547 | { |
3209 | struct cred *cred; | 3548 | struct cred *cred; |
3549 | struct task_smack *tsp; | ||
3210 | 3550 | ||
3211 | if (!security_module_enable(&smack_ops)) | 3551 | if (!security_module_enable(&smack_ops)) |
3212 | return 0; | 3552 | return 0; |
3213 | 3553 | ||
3554 | tsp = new_task_smack(smack_known_floor.smk_known, | ||
3555 | smack_known_floor.smk_known, GFP_KERNEL); | ||
3556 | if (tsp == NULL) | ||
3557 | return -ENOMEM; | ||
3558 | |||
3214 | printk(KERN_INFO "Smack: Initializing.\n"); | 3559 | printk(KERN_INFO "Smack: Initializing.\n"); |
3215 | 3560 | ||
3216 | /* | 3561 | /* |
3217 | * Set the security state for the initial task. | 3562 | * Set the security state for the initial task. |
3218 | */ | 3563 | */ |
3219 | cred = (struct cred *) current->cred; | 3564 | cred = (struct cred *) current->cred; |
3220 | cred->security = &smack_known_floor.smk_known; | 3565 | cred->security = tsp; |
3221 | 3566 | ||
3222 | /* initialize the smack_know_list */ | 3567 | /* initialize the smack_know_list */ |
3223 | init_smack_know_list(); | 3568 | init_smack_know_list(); |