diff options
Diffstat (limited to 'security/smack/smack_lsm.c')
-rw-r--r-- | security/smack/smack_lsm.c | 299 |
1 files changed, 252 insertions, 47 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 533bf3255d7f..400a5d5cde61 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <net/cipso_ipv4.h> | 33 | #include <net/cipso_ipv4.h> |
34 | #include <linux/audit.h> | 34 | #include <linux/audit.h> |
35 | #include <linux/magic.h> | 35 | #include <linux/magic.h> |
36 | #include <linux/dcache.h> | ||
36 | #include "smack.h" | 37 | #include "smack.h" |
37 | 38 | ||
38 | #define task_security(task) (task_cred_xxx((task), security)) | 39 | #define task_security(task) (task_cred_xxx((task), security)) |
@@ -84,6 +85,56 @@ struct inode_smack *new_inode_smack(char *smack) | |||
84 | return isp; | 85 | return isp; |
85 | } | 86 | } |
86 | 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 | |||
87 | /* | 138 | /* |
88 | * LSM hooks. | 139 | * LSM hooks. |
89 | * We he, that is fun! | 140 | * We he, that is fun! |
@@ -102,23 +153,17 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) | |||
102 | { | 153 | { |
103 | int rc; | 154 | int rc; |
104 | struct smk_audit_info ad; | 155 | struct smk_audit_info ad; |
105 | char *sp, *tsp; | 156 | char *tsp; |
106 | 157 | ||
107 | rc = cap_ptrace_access_check(ctp, mode); | 158 | rc = cap_ptrace_access_check(ctp, mode); |
108 | if (rc != 0) | 159 | if (rc != 0) |
109 | return rc; | 160 | return rc; |
110 | 161 | ||
111 | sp = smk_of_current(); | ||
112 | tsp = smk_of_task(task_security(ctp)); | 162 | tsp = smk_of_task(task_security(ctp)); |
113 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 163 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
114 | smk_ad_setfield_u_tsk(&ad, ctp); | 164 | smk_ad_setfield_u_tsk(&ad, ctp); |
115 | 165 | ||
116 | /* we won't log here, because rc can be overriden */ | 166 | rc = smk_curacc(tsp, MAY_READWRITE, &ad); |
117 | rc = smk_access(sp, tsp, MAY_READWRITE, NULL); | ||
118 | if (rc != 0 && capable(CAP_MAC_OVERRIDE)) | ||
119 | rc = 0; | ||
120 | |||
121 | smack_log(sp, tsp, MAY_READWRITE, rc, &ad); | ||
122 | return rc; | 167 | return rc; |
123 | } | 168 | } |
124 | 169 | ||
@@ -134,23 +179,17 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
134 | { | 179 | { |
135 | int rc; | 180 | int rc; |
136 | struct smk_audit_info ad; | 181 | struct smk_audit_info ad; |
137 | char *sp, *tsp; | 182 | char *tsp; |
138 | 183 | ||
139 | rc = cap_ptrace_traceme(ptp); | 184 | rc = cap_ptrace_traceme(ptp); |
140 | if (rc != 0) | 185 | if (rc != 0) |
141 | return rc; | 186 | return rc; |
142 | 187 | ||
188 | tsp = smk_of_task(task_security(ptp)); | ||
143 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 189 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
144 | smk_ad_setfield_u_tsk(&ad, ptp); | 190 | smk_ad_setfield_u_tsk(&ad, ptp); |
145 | 191 | ||
146 | sp = smk_of_current(); | 192 | rc = smk_curacc(tsp, MAY_READWRITE, &ad); |
147 | tsp = smk_of_task(task_security(ptp)); | ||
148 | /* we won't log here, because rc can be overriden */ | ||
149 | rc = smk_access(tsp, sp, MAY_READWRITE, NULL); | ||
150 | if (rc != 0 && has_capability(ptp, CAP_MAC_OVERRIDE)) | ||
151 | rc = 0; | ||
152 | |||
153 | smack_log(tsp, sp, MAY_READWRITE, rc, &ad); | ||
154 | return rc; | 193 | return rc; |
155 | } | 194 | } |
156 | 195 | ||
@@ -463,6 +502,7 @@ static void smack_inode_free_security(struct inode *inode) | |||
463 | * smack_inode_init_security - copy out the smack from an inode | 502 | * smack_inode_init_security - copy out the smack from an inode |
464 | * @inode: the inode | 503 | * @inode: the inode |
465 | * @dir: unused | 504 | * @dir: unused |
505 | * @qstr: unused | ||
466 | * @name: where to put the attribute name | 506 | * @name: where to put the attribute name |
467 | * @value: where to put the attribute value | 507 | * @value: where to put the attribute value |
468 | * @len: where to put the length of the attribute | 508 | * @len: where to put the length of the attribute |
@@ -470,11 +510,12 @@ static void smack_inode_free_security(struct inode *inode) | |||
470 | * Returns 0 if it all works out, -ENOMEM if there's no memory | 510 | * Returns 0 if it all works out, -ENOMEM if there's no memory |
471 | */ | 511 | */ |
472 | static int smack_inode_init_security(struct inode *inode, struct inode *dir, | 512 | static int smack_inode_init_security(struct inode *inode, struct inode *dir, |
473 | char **name, void **value, size_t *len) | 513 | const struct qstr *qstr, char **name, |
514 | void **value, size_t *len) | ||
474 | { | 515 | { |
475 | char *isp = smk_of_inode(inode); | 516 | char *isp = smk_of_inode(inode); |
476 | char *dsp = smk_of_inode(dir); | 517 | char *dsp = smk_of_inode(dir); |
477 | u32 may; | 518 | int may; |
478 | 519 | ||
479 | if (name) { | 520 | if (name) { |
480 | *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); | 521 | *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); |
@@ -483,14 +524,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
483 | } | 524 | } |
484 | 525 | ||
485 | if (value) { | 526 | if (value) { |
486 | may = smk_access_entry(smk_of_current(), dsp); | 527 | rcu_read_lock(); |
528 | may = smk_access_entry(smk_of_current(), dsp, &smack_rule_list); | ||
529 | rcu_read_unlock(); | ||
487 | 530 | ||
488 | /* | 531 | /* |
489 | * If the access rule allows transmutation and | 532 | * If the access rule allows transmutation and |
490 | * the directory requests transmutation then | 533 | * the directory requests transmutation then |
491 | * by all means transmute. | 534 | * by all means transmute. |
492 | */ | 535 | */ |
493 | if (((may & MAY_TRANSMUTE) != 0) && smk_inode_transmutable(dir)) | 536 | if (may > 0 && ((may & MAY_TRANSMUTE) != 0) && |
537 | smk_inode_transmutable(dir)) | ||
494 | isp = dsp; | 538 | isp = dsp; |
495 | 539 | ||
496 | *value = kstrdup(isp, GFP_KERNEL); | 540 | *value = kstrdup(isp, GFP_KERNEL); |
@@ -642,7 +686,7 @@ static int smack_inode_rename(struct inode *old_inode, | |||
642 | * | 686 | * |
643 | * Returns 0 if access is permitted, -EACCES otherwise | 687 | * Returns 0 if access is permitted, -EACCES otherwise |
644 | */ | 688 | */ |
645 | static int smack_inode_permission(struct inode *inode, int mask) | 689 | static int smack_inode_permission(struct inode *inode, int mask, unsigned flags) |
646 | { | 690 | { |
647 | struct smk_audit_info ad; | 691 | struct smk_audit_info ad; |
648 | 692 | ||
@@ -652,6 +696,10 @@ static int smack_inode_permission(struct inode *inode, int mask) | |||
652 | */ | 696 | */ |
653 | if (mask == 0) | 697 | if (mask == 0) |
654 | return 0; | 698 | return 0; |
699 | |||
700 | /* May be droppable after audit */ | ||
701 | if (flags & IPERM_FLAG_RCU) | ||
702 | return -ECHILD; | ||
655 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 703 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); |
656 | smk_ad_setfield_u_fs_inode(&ad, inode); | 704 | smk_ad_setfield_u_fs_inode(&ad, inode); |
657 | return smk_curacc(smk_of_inode(inode), mask, &ad); | 705 | return smk_curacc(smk_of_inode(inode), mask, &ad); |
@@ -716,7 +764,8 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
716 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || | 764 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || |
717 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || | 765 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || |
718 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || | 766 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || |
719 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { | 767 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || |
768 | strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { | ||
720 | if (!capable(CAP_MAC_ADMIN)) | 769 | if (!capable(CAP_MAC_ADMIN)) |
721 | rc = -EPERM; | 770 | rc = -EPERM; |
722 | /* | 771 | /* |
@@ -773,6 +822,12 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
773 | isp->smk_task = nsp; | 822 | isp->smk_task = nsp; |
774 | else | 823 | else |
775 | isp->smk_task = smack_known_invalid.smk_known; | 824 | isp->smk_task = smack_known_invalid.smk_known; |
825 | } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { | ||
826 | nsp = smk_import(value, size); | ||
827 | if (nsp != NULL) | ||
828 | isp->smk_mmap = nsp; | ||
829 | else | ||
830 | isp->smk_mmap = smack_known_invalid.smk_known; | ||
776 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) | 831 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) |
777 | isp->smk_flags |= SMK_INODE_TRANSMUTE; | 832 | isp->smk_flags |= SMK_INODE_TRANSMUTE; |
778 | 833 | ||
@@ -815,7 +870,8 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) | |||
815 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || | 870 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || |
816 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || | 871 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || |
817 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || | 872 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || |
818 | strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { | 873 | strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 || |
874 | strcmp(name, XATTR_NAME_SMACKMMAP)) { | ||
819 | if (!capable(CAP_MAC_ADMIN)) | 875 | if (!capable(CAP_MAC_ADMIN)) |
820 | rc = -EPERM; | 876 | rc = -EPERM; |
821 | } else | 877 | } else |
@@ -829,6 +885,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) | |||
829 | if (rc == 0) { | 885 | if (rc == 0) { |
830 | isp = dentry->d_inode->i_security; | 886 | isp = dentry->d_inode->i_security; |
831 | isp->smk_task = NULL; | 887 | isp->smk_task = NULL; |
888 | isp->smk_mmap = NULL; | ||
832 | } | 889 | } |
833 | 890 | ||
834 | return rc; | 891 | return rc; |
@@ -1060,6 +1117,126 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
1060 | } | 1117 | } |
1061 | 1118 | ||
1062 | /** | 1119 | /** |
1120 | * smack_file_mmap : | ||
1121 | * Check permissions for a mmap operation. The @file may be NULL, e.g. | ||
1122 | * if mapping anonymous memory. | ||
1123 | * @file contains the file structure for file to map (may be NULL). | ||
1124 | * @reqprot contains the protection requested by the application. | ||
1125 | * @prot contains the protection that will be applied by the kernel. | ||
1126 | * @flags contains the operational flags. | ||
1127 | * Return 0 if permission is granted. | ||
1128 | */ | ||
1129 | static int smack_file_mmap(struct file *file, | ||
1130 | unsigned long reqprot, unsigned long prot, | ||
1131 | unsigned long flags, unsigned long addr, | ||
1132 | unsigned long addr_only) | ||
1133 | { | ||
1134 | struct smack_rule *srp; | ||
1135 | struct task_smack *tsp; | ||
1136 | char *sp; | ||
1137 | char *msmack; | ||
1138 | char *osmack; | ||
1139 | struct inode_smack *isp; | ||
1140 | struct dentry *dp; | ||
1141 | int may; | ||
1142 | int mmay; | ||
1143 | int tmay; | ||
1144 | int rc; | ||
1145 | |||
1146 | /* do DAC check on address space usage */ | ||
1147 | rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); | ||
1148 | if (rc || addr_only) | ||
1149 | return rc; | ||
1150 | |||
1151 | if (file == NULL || file->f_dentry == NULL) | ||
1152 | return 0; | ||
1153 | |||
1154 | dp = file->f_dentry; | ||
1155 | |||
1156 | if (dp->d_inode == NULL) | ||
1157 | return 0; | ||
1158 | |||
1159 | isp = dp->d_inode->i_security; | ||
1160 | if (isp->smk_mmap == NULL) | ||
1161 | return 0; | ||
1162 | msmack = isp->smk_mmap; | ||
1163 | |||
1164 | tsp = current_security(); | ||
1165 | sp = smk_of_current(); | ||
1166 | rc = 0; | ||
1167 | |||
1168 | rcu_read_lock(); | ||
1169 | /* | ||
1170 | * For each Smack rule associated with the subject | ||
1171 | * label verify that the SMACK64MMAP also has access | ||
1172 | * to that rule's object label. | ||
1173 | * | ||
1174 | * Because neither of the labels comes | ||
1175 | * from the networking code it is sufficient | ||
1176 | * to compare pointers. | ||
1177 | */ | ||
1178 | list_for_each_entry_rcu(srp, &smack_rule_list, list) { | ||
1179 | if (srp->smk_subject != sp) | ||
1180 | continue; | ||
1181 | |||
1182 | osmack = srp->smk_object; | ||
1183 | /* | ||
1184 | * Matching labels always allows access. | ||
1185 | */ | ||
1186 | if (msmack == osmack) | ||
1187 | continue; | ||
1188 | /* | ||
1189 | * If there is a matching local rule take | ||
1190 | * that into account as well. | ||
1191 | */ | ||
1192 | may = smk_access_entry(srp->smk_subject, osmack, | ||
1193 | &tsp->smk_rules); | ||
1194 | if (may == -ENOENT) | ||
1195 | may = srp->smk_access; | ||
1196 | else | ||
1197 | may &= srp->smk_access; | ||
1198 | /* | ||
1199 | * If may is zero the SMACK64MMAP subject can't | ||
1200 | * possibly have less access. | ||
1201 | */ | ||
1202 | if (may == 0) | ||
1203 | continue; | ||
1204 | |||
1205 | /* | ||
1206 | * Fetch the global list entry. | ||
1207 | * If there isn't one a SMACK64MMAP subject | ||
1208 | * can't have as much access as current. | ||
1209 | */ | ||
1210 | mmay = smk_access_entry(msmack, osmack, &smack_rule_list); | ||
1211 | if (mmay == -ENOENT) { | ||
1212 | rc = -EACCES; | ||
1213 | break; | ||
1214 | } | ||
1215 | /* | ||
1216 | * If there is a local entry it modifies the | ||
1217 | * potential access, too. | ||
1218 | */ | ||
1219 | tmay = smk_access_entry(msmack, osmack, &tsp->smk_rules); | ||
1220 | if (tmay != -ENOENT) | ||
1221 | mmay &= tmay; | ||
1222 | |||
1223 | /* | ||
1224 | * If there is any access available to current that is | ||
1225 | * not available to a SMACK64MMAP subject | ||
1226 | * deny access. | ||
1227 | */ | ||
1228 | if ((may | mmay) != mmay) { | ||
1229 | rc = -EACCES; | ||
1230 | break; | ||
1231 | } | ||
1232 | } | ||
1233 | |||
1234 | rcu_read_unlock(); | ||
1235 | |||
1236 | return rc; | ||
1237 | } | ||
1238 | |||
1239 | /** | ||
1063 | * smack_file_set_fowner - set the file security blob value | 1240 | * smack_file_set_fowner - set the file security blob value |
1064 | * @file: object in question | 1241 | * @file: object in question |
1065 | * | 1242 | * |
@@ -1095,6 +1272,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, | |||
1095 | * struct fown_struct is never outside the context of a struct file | 1272 | * struct fown_struct is never outside the context of a struct file |
1096 | */ | 1273 | */ |
1097 | file = container_of(fown, struct file, f_owner); | 1274 | file = container_of(fown, struct file, f_owner); |
1275 | |||
1098 | /* we don't log here as rc can be overriden */ | 1276 | /* we don't log here as rc can be overriden */ |
1099 | rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL); | 1277 | rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL); |
1100 | if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) | 1278 | if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) |
@@ -1145,9 +1323,14 @@ static int smack_file_receive(struct file *file) | |||
1145 | */ | 1323 | */ |
1146 | static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) | 1324 | static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) |
1147 | { | 1325 | { |
1148 | cred->security = kzalloc(sizeof(struct task_smack), gfp); | 1326 | struct task_smack *tsp; |
1149 | if (cred->security == NULL) | 1327 | |
1328 | tsp = new_task_smack(NULL, NULL, gfp); | ||
1329 | if (tsp == NULL) | ||
1150 | return -ENOMEM; | 1330 | return -ENOMEM; |
1331 | |||
1332 | cred->security = tsp; | ||
1333 | |||
1151 | return 0; | 1334 | return 0; |
1152 | } | 1335 | } |
1153 | 1336 | ||
@@ -1156,13 +1339,24 @@ static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) | |||
1156 | * smack_cred_free - "free" task-level security credentials | 1339 | * smack_cred_free - "free" task-level security credentials |
1157 | * @cred: the credentials in question | 1340 | * @cred: the credentials in question |
1158 | * | 1341 | * |
1159 | * Smack isn't using copies of blobs. Everyone | ||
1160 | * points to an immutable list. The blobs never go away. | ||
1161 | * There is no leak here. | ||
1162 | */ | 1342 | */ |
1163 | static void smack_cred_free(struct cred *cred) | 1343 | static void smack_cred_free(struct cred *cred) |
1164 | { | 1344 | { |
1165 | kfree(cred->security); | 1345 | struct task_smack *tsp = cred->security; |
1346 | struct smack_rule *rp; | ||
1347 | struct list_head *l; | ||
1348 | struct list_head *n; | ||
1349 | |||
1350 | if (tsp == NULL) | ||
1351 | return; | ||
1352 | cred->security = NULL; | ||
1353 | |||
1354 | list_for_each_safe(l, n, &tsp->smk_rules) { | ||
1355 | rp = list_entry(l, struct smack_rule, list); | ||
1356 | list_del(&rp->list); | ||
1357 | kfree(rp); | ||
1358 | } | ||
1359 | kfree(tsp); | ||
1166 | } | 1360 | } |
1167 | 1361 | ||
1168 | /** | 1362 | /** |
@@ -1178,13 +1372,16 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old, | |||
1178 | { | 1372 | { |
1179 | struct task_smack *old_tsp = old->security; | 1373 | struct task_smack *old_tsp = old->security; |
1180 | struct task_smack *new_tsp; | 1374 | struct task_smack *new_tsp; |
1375 | int rc; | ||
1181 | 1376 | ||
1182 | new_tsp = kzalloc(sizeof(struct task_smack), gfp); | 1377 | new_tsp = new_task_smack(old_tsp->smk_task, old_tsp->smk_task, gfp); |
1183 | if (new_tsp == NULL) | 1378 | if (new_tsp == NULL) |
1184 | return -ENOMEM; | 1379 | return -ENOMEM; |
1185 | 1380 | ||
1186 | new_tsp->smk_task = old_tsp->smk_task; | 1381 | rc = smk_copy_rules(&new_tsp->smk_rules, &old_tsp->smk_rules, gfp); |
1187 | new_tsp->smk_forked = old_tsp->smk_task; | 1382 | if (rc != 0) |
1383 | return rc; | ||
1384 | |||
1188 | new->security = new_tsp; | 1385 | new->security = new_tsp; |
1189 | return 0; | 1386 | return 0; |
1190 | } | 1387 | } |
@@ -1203,6 +1400,11 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old) | |||
1203 | 1400 | ||
1204 | new_tsp->smk_task = old_tsp->smk_task; | 1401 | new_tsp->smk_task = old_tsp->smk_task; |
1205 | new_tsp->smk_forked = old_tsp->smk_task; | 1402 | new_tsp->smk_forked = old_tsp->smk_task; |
1403 | mutex_init(&new_tsp->smk_rules_lock); | ||
1404 | INIT_LIST_HEAD(&new_tsp->smk_rules); | ||
1405 | |||
1406 | |||
1407 | /* cbs copy rule list */ | ||
1206 | } | 1408 | } |
1207 | 1409 | ||
1208 | /** | 1410 | /** |
@@ -1596,7 +1798,7 @@ static void smack_set_catset(char *catset, struct netlbl_lsm_secattr *sap) | |||
1596 | * Casey says that CIPSO is good enough for now. | 1798 | * Casey says that CIPSO is good enough for now. |
1597 | * It can be used to effect. | 1799 | * It can be used to effect. |
1598 | * It can also be abused to effect when necessary. | 1800 | * It can also be abused to effect when necessary. |
1599 | * Appologies to the TSIG group in general and GW in particular. | 1801 | * Apologies to the TSIG group in general and GW in particular. |
1600 | */ | 1802 | */ |
1601 | static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp) | 1803 | static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp) |
1602 | { | 1804 | { |
@@ -2332,7 +2534,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2332 | switch (sbp->s_magic) { | 2534 | switch (sbp->s_magic) { |
2333 | case SMACK_MAGIC: | 2535 | case SMACK_MAGIC: |
2334 | /* | 2536 | /* |
2335 | * Casey says that it's a little embarassing | 2537 | * Casey says that it's a little embarrassing |
2336 | * that the smack file system doesn't do | 2538 | * that the smack file system doesn't do |
2337 | * extended attributes. | 2539 | * extended attributes. |
2338 | */ | 2540 | */ |
@@ -2419,6 +2621,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2419 | } | 2621 | } |
2420 | } | 2622 | } |
2421 | isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); | 2623 | isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); |
2624 | isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp); | ||
2422 | 2625 | ||
2423 | dput(dp); | 2626 | dput(dp); |
2424 | break; | 2627 | break; |
@@ -2478,6 +2681,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value) | |||
2478 | static int smack_setprocattr(struct task_struct *p, char *name, | 2681 | static int smack_setprocattr(struct task_struct *p, char *name, |
2479 | void *value, size_t size) | 2682 | void *value, size_t size) |
2480 | { | 2683 | { |
2684 | int rc; | ||
2481 | struct task_smack *tsp; | 2685 | struct task_smack *tsp; |
2482 | struct task_smack *oldtsp; | 2686 | struct task_smack *oldtsp; |
2483 | struct cred *new; | 2687 | struct cred *new; |
@@ -2513,13 +2717,16 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
2513 | new = prepare_creds(); | 2717 | new = prepare_creds(); |
2514 | if (new == NULL) | 2718 | if (new == NULL) |
2515 | return -ENOMEM; | 2719 | return -ENOMEM; |
2516 | tsp = kzalloc(sizeof(struct task_smack), GFP_KERNEL); | 2720 | |
2721 | tsp = new_task_smack(newsmack, oldtsp->smk_forked, GFP_KERNEL); | ||
2517 | if (tsp == NULL) { | 2722 | if (tsp == NULL) { |
2518 | kfree(new); | 2723 | kfree(new); |
2519 | return -ENOMEM; | 2724 | return -ENOMEM; |
2520 | } | 2725 | } |
2521 | tsp->smk_task = newsmack; | 2726 | rc = smk_copy_rules(&tsp->smk_rules, &oldtsp->smk_rules, GFP_KERNEL); |
2522 | tsp->smk_forked = oldtsp->smk_forked; | 2727 | if (rc != 0) |
2728 | return rc; | ||
2729 | |||
2523 | new->security = tsp; | 2730 | new->security = tsp; |
2524 | commit_creds(new); | 2731 | commit_creds(new); |
2525 | return size; | 2732 | return size; |
@@ -2881,7 +3088,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
2881 | /* | 3088 | /* |
2882 | * We need to decide if we want to label the incoming connection here | 3089 | * We need to decide if we want to label the incoming connection here |
2883 | * if we do we only need to label the request_sock and the stack will | 3090 | * if we do we only need to label the request_sock and the stack will |
2884 | * propogate the wire-label to the sock when it is created. | 3091 | * propagate the wire-label to the sock when it is created. |
2885 | */ | 3092 | */ |
2886 | hdr = ip_hdr(skb); | 3093 | hdr = ip_hdr(skb); |
2887 | addr.sin_addr.s_addr = hdr->saddr; | 3094 | addr.sin_addr.s_addr = hdr->saddr; |
@@ -3221,6 +3428,7 @@ struct security_operations smack_ops = { | |||
3221 | .file_ioctl = smack_file_ioctl, | 3428 | .file_ioctl = smack_file_ioctl, |
3222 | .file_lock = smack_file_lock, | 3429 | .file_lock = smack_file_lock, |
3223 | .file_fcntl = smack_file_fcntl, | 3430 | .file_fcntl = smack_file_fcntl, |
3431 | .file_mmap = smack_file_mmap, | ||
3224 | .file_set_fowner = smack_file_set_fowner, | 3432 | .file_set_fowner = smack_file_set_fowner, |
3225 | .file_send_sigiotask = smack_file_send_sigiotask, | 3433 | .file_send_sigiotask = smack_file_send_sigiotask, |
3226 | .file_receive = smack_file_receive, | 3434 | .file_receive = smack_file_receive, |
@@ -3334,23 +3542,20 @@ static __init int smack_init(void) | |||
3334 | struct cred *cred; | 3542 | struct cred *cred; |
3335 | struct task_smack *tsp; | 3543 | struct task_smack *tsp; |
3336 | 3544 | ||
3337 | tsp = kzalloc(sizeof(struct task_smack), GFP_KERNEL); | 3545 | if (!security_module_enable(&smack_ops)) |
3546 | return 0; | ||
3547 | |||
3548 | tsp = new_task_smack(smack_known_floor.smk_known, | ||
3549 | smack_known_floor.smk_known, GFP_KERNEL); | ||
3338 | if (tsp == NULL) | 3550 | if (tsp == NULL) |
3339 | return -ENOMEM; | 3551 | return -ENOMEM; |
3340 | 3552 | ||
3341 | if (!security_module_enable(&smack_ops)) { | ||
3342 | kfree(tsp); | ||
3343 | return 0; | ||
3344 | } | ||
3345 | |||
3346 | printk(KERN_INFO "Smack: Initializing.\n"); | 3553 | printk(KERN_INFO "Smack: Initializing.\n"); |
3347 | 3554 | ||
3348 | /* | 3555 | /* |
3349 | * Set the security state for the initial task. | 3556 | * Set the security state for the initial task. |
3350 | */ | 3557 | */ |
3351 | cred = (struct cred *) current->cred; | 3558 | cred = (struct cred *) current->cred; |
3352 | tsp->smk_forked = smack_known_floor.smk_known; | ||
3353 | tsp->smk_task = smack_known_floor.smk_known; | ||
3354 | cred->security = tsp; | 3559 | cred->security = tsp; |
3355 | 3560 | ||
3356 | /* initialize the smack_know_list */ | 3561 | /* initialize the smack_know_list */ |