diff options
Diffstat (limited to 'security/smack')
-rw-r--r-- | security/smack/smack.h | 45 | ||||
-rw-r--r-- | security/smack/smack_access.c | 58 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 354 | ||||
-rw-r--r-- | security/smack/smackfs.c | 41 |
4 files changed, 368 insertions, 130 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h index 43ae747a5aa4..129c4eb8ffb1 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
@@ -51,11 +51,18 @@ struct socket_smack { | |||
51 | */ | 51 | */ |
52 | struct inode_smack { | 52 | struct inode_smack { |
53 | char *smk_inode; /* label of the fso */ | 53 | char *smk_inode; /* label of the fso */ |
54 | char *smk_task; /* label of the task */ | ||
54 | struct mutex smk_lock; /* initialization lock */ | 55 | struct mutex smk_lock; /* initialization lock */ |
55 | int smk_flags; /* smack inode flags */ | 56 | int smk_flags; /* smack inode flags */ |
56 | }; | 57 | }; |
57 | 58 | ||
59 | struct task_smack { | ||
60 | char *smk_task; /* label used for access control */ | ||
61 | char *smk_forked; /* label when forked */ | ||
62 | }; | ||
63 | |||
58 | #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ | 64 | #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ |
65 | #define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */ | ||
59 | 66 | ||
60 | /* | 67 | /* |
61 | * A label access rule. | 68 | * A label access rule. |
@@ -161,6 +168,10 @@ struct smack_known { | |||
161 | #define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */ | 168 | #define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */ |
162 | 169 | ||
163 | /* | 170 | /* |
171 | * Flag for transmute access | ||
172 | */ | ||
173 | #define MAY_TRANSMUTE 64 | ||
174 | /* | ||
164 | * Just to make the common cases easier to deal with | 175 | * Just to make the common cases easier to deal with |
165 | */ | 176 | */ |
166 | #define MAY_ANY (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) | 177 | #define MAY_ANY (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) |
@@ -191,6 +202,7 @@ struct inode_smack *new_inode_smack(char *); | |||
191 | /* | 202 | /* |
192 | * These functions are in smack_access.c | 203 | * These functions are in smack_access.c |
193 | */ | 204 | */ |
205 | int smk_access_entry(char *, char *); | ||
194 | int smk_access(char *, char *, int, struct smk_audit_info *); | 206 | int smk_access(char *, char *, int, struct smk_audit_info *); |
195 | int smk_curacc(char *, u32, struct smk_audit_info *); | 207 | int smk_curacc(char *, u32, struct smk_audit_info *); |
196 | int smack_to_cipso(const char *, struct smack_cipso *); | 208 | int smack_to_cipso(const char *, struct smack_cipso *); |
@@ -234,6 +246,15 @@ static inline void smack_catset_bit(int cat, char *catsetp) | |||
234 | } | 246 | } |
235 | 247 | ||
236 | /* | 248 | /* |
249 | * Is the directory transmuting? | ||
250 | */ | ||
251 | static inline int smk_inode_transmutable(const struct inode *isp) | ||
252 | { | ||
253 | struct inode_smack *sip = isp->i_security; | ||
254 | return (sip->smk_flags & SMK_INODE_TRANSMUTE) != 0; | ||
255 | } | ||
256 | |||
257 | /* | ||
237 | * Present a pointer to the smack label in an inode blob. | 258 | * Present a pointer to the smack label in an inode blob. |
238 | */ | 259 | */ |
239 | static inline char *smk_of_inode(const struct inode *isp) | 260 | static inline char *smk_of_inode(const struct inode *isp) |
@@ -243,6 +264,30 @@ static inline char *smk_of_inode(const struct inode *isp) | |||
243 | } | 264 | } |
244 | 265 | ||
245 | /* | 266 | /* |
267 | * Present a pointer to the smack label in an task blob. | ||
268 | */ | ||
269 | static inline char *smk_of_task(const struct task_smack *tsp) | ||
270 | { | ||
271 | return tsp->smk_task; | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * Present a pointer to the forked smack label in an task blob. | ||
276 | */ | ||
277 | static inline char *smk_of_forked(const struct task_smack *tsp) | ||
278 | { | ||
279 | return tsp->smk_forked; | ||
280 | } | ||
281 | |||
282 | /* | ||
283 | * Present a pointer to the smack label in the current task blob. | ||
284 | */ | ||
285 | static inline char *smk_of_current(void) | ||
286 | { | ||
287 | return smk_of_task(current_security()); | ||
288 | } | ||
289 | |||
290 | /* | ||
246 | * logging functions | 291 | * logging functions |
247 | */ | 292 | */ |
248 | #define SMACK_AUDIT_DENIED 0x1 | 293 | #define SMACK_AUDIT_DENIED 0x1 |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index f4fac64c4da8..7ba8478f599e 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
@@ -67,6 +67,46 @@ static u32 smack_next_secid = 10; | |||
67 | int log_policy = SMACK_AUDIT_DENIED; | 67 | int log_policy = SMACK_AUDIT_DENIED; |
68 | 68 | ||
69 | /** | 69 | /** |
70 | * smk_access_entry - look up matching access rule | ||
71 | * @subject_label: a pointer to the subject's Smack label | ||
72 | * @object_label: a pointer to the object's Smack label | ||
73 | * | ||
74 | * This function looks up the subject/object pair in the | ||
75 | * access rule list and returns pointer to the matching rule if found, | ||
76 | * NULL otherwise. | ||
77 | * | ||
78 | * NOTE: | ||
79 | * Even though Smack labels are usually shared on smack_list | ||
80 | * labels that come in off the network can't be imported | ||
81 | * and added to the list for locking reasons. | ||
82 | * | ||
83 | * Therefore, it is necessary to check the contents of the labels, | ||
84 | * not just the pointer values. Of course, in most cases the labels | ||
85 | * will be on the list, so checking the pointers may be a worthwhile | ||
86 | * optimization. | ||
87 | */ | ||
88 | int smk_access_entry(char *subject_label, char *object_label) | ||
89 | { | ||
90 | u32 may = MAY_NOT; | ||
91 | struct smack_rule *srp; | ||
92 | |||
93 | rcu_read_lock(); | ||
94 | list_for_each_entry_rcu(srp, &smack_rule_list, list) { | ||
95 | if (srp->smk_subject == subject_label || | ||
96 | strcmp(srp->smk_subject, subject_label) == 0) { | ||
97 | if (srp->smk_object == object_label || | ||
98 | strcmp(srp->smk_object, object_label) == 0) { | ||
99 | may = srp->smk_access; | ||
100 | break; | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | rcu_read_unlock(); | ||
105 | |||
106 | return may; | ||
107 | } | ||
108 | |||
109 | /** | ||
70 | * smk_access - determine if a subject has a specific access to an object | 110 | * smk_access - determine if a subject has a specific access to an object |
71 | * @subject_label: a pointer to the subject's Smack label | 111 | * @subject_label: a pointer to the subject's Smack label |
72 | * @object_label: a pointer to the object's Smack label | 112 | * @object_label: a pointer to the object's Smack label |
@@ -90,7 +130,6 @@ int smk_access(char *subject_label, char *object_label, int request, | |||
90 | struct smk_audit_info *a) | 130 | struct smk_audit_info *a) |
91 | { | 131 | { |
92 | u32 may = MAY_NOT; | 132 | u32 may = MAY_NOT; |
93 | struct smack_rule *srp; | ||
94 | int rc = 0; | 133 | int rc = 0; |
95 | 134 | ||
96 | /* | 135 | /* |
@@ -144,18 +183,7 @@ int smk_access(char *subject_label, char *object_label, int request, | |||
144 | * access (e.g. read is included in readwrite) it's | 183 | * access (e.g. read is included in readwrite) it's |
145 | * good. | 184 | * good. |
146 | */ | 185 | */ |
147 | rcu_read_lock(); | 186 | may = smk_access_entry(subject_label, object_label); |
148 | list_for_each_entry_rcu(srp, &smack_rule_list, list) { | ||
149 | if (srp->smk_subject == subject_label || | ||
150 | strcmp(srp->smk_subject, subject_label) == 0) { | ||
151 | if (srp->smk_object == object_label || | ||
152 | strcmp(srp->smk_object, object_label) == 0) { | ||
153 | may = srp->smk_access; | ||
154 | break; | ||
155 | } | ||
156 | } | ||
157 | } | ||
158 | rcu_read_unlock(); | ||
159 | /* | 187 | /* |
160 | * This is a bit map operation. | 188 | * This is a bit map operation. |
161 | */ | 189 | */ |
@@ -185,7 +213,7 @@ out_audit: | |||
185 | int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) | 213 | int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) |
186 | { | 214 | { |
187 | int rc; | 215 | int rc; |
188 | char *sp = current_security(); | 216 | char *sp = smk_of_current(); |
189 | 217 | ||
190 | rc = smk_access(sp, obj_label, mode, NULL); | 218 | rc = smk_access(sp, obj_label, mode, NULL); |
191 | if (rc == 0) | 219 | if (rc == 0) |
@@ -196,7 +224,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) | |||
196 | * only one that gets privilege and current does not | 224 | * only one that gets privilege and current does not |
197 | * have that label. | 225 | * have that label. |
198 | */ | 226 | */ |
199 | if (smack_onlycap != NULL && smack_onlycap != current->cred->security) | 227 | if (smack_onlycap != NULL && smack_onlycap != sp) |
200 | goto out_audit; | 228 | goto out_audit; |
201 | 229 | ||
202 | if (capable(CAP_MAC_OVERRIDE)) | 230 | if (capable(CAP_MAC_OVERRIDE)) |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index ccb71a044a1a..533bf3255d7f 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, |
@@ -35,6 +37,9 @@ | |||
35 | 37 | ||
36 | #define task_security(task) (task_cred_xxx((task), security)) | 38 | #define task_security(task) (task_cred_xxx((task), security)) |
37 | 39 | ||
40 | #define TRANS_TRUE "TRUE" | ||
41 | #define TRANS_TRUE_SIZE 4 | ||
42 | |||
38 | /** | 43 | /** |
39 | * smk_fetch - Fetch the smack label from a file. | 44 | * smk_fetch - Fetch the smack label from a file. |
40 | * @ip: a pointer to the inode | 45 | * @ip: a pointer to the inode |
@@ -43,7 +48,7 @@ | |||
43 | * Returns a pointer to the master list entry for the Smack label | 48 | * Returns a pointer to the master list entry for the Smack label |
44 | * or NULL if there was no label to fetch. | 49 | * or NULL if there was no label to fetch. |
45 | */ | 50 | */ |
46 | static char *smk_fetch(struct inode *ip, struct dentry *dp) | 51 | static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp) |
47 | { | 52 | { |
48 | int rc; | 53 | int rc; |
49 | char in[SMK_LABELLEN]; | 54 | char in[SMK_LABELLEN]; |
@@ -51,7 +56,7 @@ static char *smk_fetch(struct inode *ip, struct dentry *dp) | |||
51 | if (ip->i_op->getxattr == NULL) | 56 | if (ip->i_op->getxattr == NULL) |
52 | return NULL; | 57 | return NULL; |
53 | 58 | ||
54 | rc = ip->i_op->getxattr(dp, XATTR_NAME_SMACK, in, SMK_LABELLEN); | 59 | rc = ip->i_op->getxattr(dp, name, in, SMK_LABELLEN); |
55 | if (rc < 0) | 60 | if (rc < 0) |
56 | return NULL; | 61 | return NULL; |
57 | 62 | ||
@@ -103,8 +108,8 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) | |||
103 | if (rc != 0) | 108 | if (rc != 0) |
104 | return rc; | 109 | return rc; |
105 | 110 | ||
106 | sp = current_security(); | 111 | sp = smk_of_current(); |
107 | tsp = task_security(ctp); | 112 | tsp = smk_of_task(task_security(ctp)); |
108 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 113 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
109 | smk_ad_setfield_u_tsk(&ad, ctp); | 114 | smk_ad_setfield_u_tsk(&ad, ctp); |
110 | 115 | ||
@@ -138,8 +143,8 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
138 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 143 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
139 | smk_ad_setfield_u_tsk(&ad, ptp); | 144 | smk_ad_setfield_u_tsk(&ad, ptp); |
140 | 145 | ||
141 | sp = current_security(); | 146 | sp = smk_of_current(); |
142 | tsp = task_security(ptp); | 147 | tsp = smk_of_task(task_security(ptp)); |
143 | /* we won't log here, because rc can be overriden */ | 148 | /* we won't log here, because rc can be overriden */ |
144 | rc = smk_access(tsp, sp, MAY_READWRITE, NULL); | 149 | rc = smk_access(tsp, sp, MAY_READWRITE, NULL); |
145 | if (rc != 0 && has_capability(ptp, CAP_MAC_OVERRIDE)) | 150 | if (rc != 0 && has_capability(ptp, CAP_MAC_OVERRIDE)) |
@@ -160,7 +165,7 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
160 | static int smack_syslog(int typefrom_file) | 165 | static int smack_syslog(int typefrom_file) |
161 | { | 166 | { |
162 | int rc = 0; | 167 | int rc = 0; |
163 | char *sp = current_security(); | 168 | char *sp = smk_of_current(); |
164 | 169 | ||
165 | if (capable(CAP_MAC_OVERRIDE)) | 170 | if (capable(CAP_MAC_OVERRIDE)) |
166 | return 0; | 171 | return 0; |
@@ -391,6 +396,40 @@ static int smack_sb_umount(struct vfsmount *mnt, int flags) | |||
391 | } | 396 | } |
392 | 397 | ||
393 | /* | 398 | /* |
399 | * BPRM hooks | ||
400 | */ | ||
401 | |||
402 | static int smack_bprm_set_creds(struct linux_binprm *bprm) | ||
403 | { | ||
404 | struct task_smack *tsp = bprm->cred->security; | ||
405 | struct inode_smack *isp; | ||
406 | struct dentry *dp; | ||
407 | int rc; | ||
408 | |||
409 | rc = cap_bprm_set_creds(bprm); | ||
410 | if (rc != 0) | ||
411 | return rc; | ||
412 | |||
413 | if (bprm->cred_prepared) | ||
414 | return 0; | ||
415 | |||
416 | if (bprm->file == NULL || bprm->file->f_dentry == NULL) | ||
417 | return 0; | ||
418 | |||
419 | dp = bprm->file->f_dentry; | ||
420 | |||
421 | if (dp->d_inode == NULL) | ||
422 | return 0; | ||
423 | |||
424 | isp = dp->d_inode->i_security; | ||
425 | |||
426 | if (isp->smk_task != NULL) | ||
427 | tsp->smk_task = isp->smk_task; | ||
428 | |||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | /* | ||
394 | * Inode hooks | 433 | * Inode hooks |
395 | */ | 434 | */ |
396 | 435 | ||
@@ -402,7 +441,7 @@ static int smack_sb_umount(struct vfsmount *mnt, int flags) | |||
402 | */ | 441 | */ |
403 | static int smack_inode_alloc_security(struct inode *inode) | 442 | static int smack_inode_alloc_security(struct inode *inode) |
404 | { | 443 | { |
405 | inode->i_security = new_inode_smack(current_security()); | 444 | inode->i_security = new_inode_smack(smk_of_current()); |
406 | if (inode->i_security == NULL) | 445 | if (inode->i_security == NULL) |
407 | return -ENOMEM; | 446 | return -ENOMEM; |
408 | return 0; | 447 | return 0; |
@@ -434,6 +473,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
434 | char **name, void **value, size_t *len) | 473 | char **name, void **value, size_t *len) |
435 | { | 474 | { |
436 | char *isp = smk_of_inode(inode); | 475 | char *isp = smk_of_inode(inode); |
476 | char *dsp = smk_of_inode(dir); | ||
477 | u32 may; | ||
437 | 478 | ||
438 | if (name) { | 479 | if (name) { |
439 | *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); | 480 | *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); |
@@ -442,6 +483,16 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
442 | } | 483 | } |
443 | 484 | ||
444 | if (value) { | 485 | if (value) { |
486 | may = smk_access_entry(smk_of_current(), dsp); | ||
487 | |||
488 | /* | ||
489 | * If the access rule allows transmutation and | ||
490 | * the directory requests transmutation then | ||
491 | * by all means transmute. | ||
492 | */ | ||
493 | if (((may & MAY_TRANSMUTE) != 0) && smk_inode_transmutable(dir)) | ||
494 | isp = dsp; | ||
495 | |||
445 | *value = kstrdup(isp, GFP_KERNEL); | 496 | *value = kstrdup(isp, GFP_KERNEL); |
446 | if (*value == NULL) | 497 | if (*value == NULL) |
447 | return -ENOMEM; | 498 | return -ENOMEM; |
@@ -664,7 +715,8 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
664 | 715 | ||
665 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || | 716 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || |
666 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || | 717 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || |
667 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) { | 718 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || |
719 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { | ||
668 | if (!capable(CAP_MAC_ADMIN)) | 720 | if (!capable(CAP_MAC_ADMIN)) |
669 | rc = -EPERM; | 721 | rc = -EPERM; |
670 | /* | 722 | /* |
@@ -674,6 +726,12 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
674 | if (size == 0 || size >= SMK_LABELLEN || | 726 | if (size == 0 || size >= SMK_LABELLEN || |
675 | smk_import(value, size) == NULL) | 727 | smk_import(value, size) == NULL) |
676 | rc = -EINVAL; | 728 | rc = -EINVAL; |
729 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { | ||
730 | if (!capable(CAP_MAC_ADMIN)) | ||
731 | rc = -EPERM; | ||
732 | if (size != TRANS_TRUE_SIZE || | ||
733 | strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0) | ||
734 | rc = -EINVAL; | ||
677 | } else | 735 | } else |
678 | rc = cap_inode_setxattr(dentry, name, value, size, flags); | 736 | rc = cap_inode_setxattr(dentry, name, value, size, flags); |
679 | 737 | ||
@@ -700,26 +758,23 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
700 | static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, | 758 | static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, |
701 | const void *value, size_t size, int flags) | 759 | const void *value, size_t size, int flags) |
702 | { | 760 | { |
703 | struct inode_smack *isp; | ||
704 | char *nsp; | 761 | char *nsp; |
762 | struct inode_smack *isp = dentry->d_inode->i_security; | ||
705 | 763 | ||
706 | /* | 764 | if (strcmp(name, XATTR_NAME_SMACK) == 0) { |
707 | * Not SMACK | 765 | nsp = smk_import(value, size); |
708 | */ | 766 | if (nsp != NULL) |
709 | if (strcmp(name, XATTR_NAME_SMACK)) | 767 | isp->smk_inode = nsp; |
710 | return; | 768 | else |
711 | 769 | isp->smk_inode = smack_known_invalid.smk_known; | |
712 | isp = dentry->d_inode->i_security; | 770 | } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { |
713 | 771 | nsp = smk_import(value, size); | |
714 | /* | 772 | if (nsp != NULL) |
715 | * No locking is done here. This is a pointer | 773 | isp->smk_task = nsp; |
716 | * assignment. | 774 | else |
717 | */ | 775 | isp->smk_task = smack_known_invalid.smk_known; |
718 | nsp = smk_import(value, size); | 776 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) |
719 | if (nsp != NULL) | 777 | isp->smk_flags |= SMK_INODE_TRANSMUTE; |
720 | isp->smk_inode = nsp; | ||
721 | else | ||
722 | isp->smk_inode = smack_known_invalid.smk_known; | ||
723 | 778 | ||
724 | return; | 779 | return; |
725 | } | 780 | } |
@@ -752,12 +807,15 @@ static int smack_inode_getxattr(struct dentry *dentry, const char *name) | |||
752 | */ | 807 | */ |
753 | static int smack_inode_removexattr(struct dentry *dentry, const char *name) | 808 | static int smack_inode_removexattr(struct dentry *dentry, const char *name) |
754 | { | 809 | { |
810 | struct inode_smack *isp; | ||
755 | struct smk_audit_info ad; | 811 | struct smk_audit_info ad; |
756 | int rc = 0; | 812 | int rc = 0; |
757 | 813 | ||
758 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || | 814 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || |
759 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || | 815 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || |
760 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) { | 816 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || |
817 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || | ||
818 | strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { | ||
761 | if (!capable(CAP_MAC_ADMIN)) | 819 | if (!capable(CAP_MAC_ADMIN)) |
762 | rc = -EPERM; | 820 | rc = -EPERM; |
763 | } else | 821 | } else |
@@ -768,6 +826,11 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) | |||
768 | if (rc == 0) | 826 | if (rc == 0) |
769 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); | 827 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); |
770 | 828 | ||
829 | if (rc == 0) { | ||
830 | isp = dentry->d_inode->i_security; | ||
831 | isp->smk_task = NULL; | ||
832 | } | ||
833 | |||
771 | return rc; | 834 | return rc; |
772 | } | 835 | } |
773 | 836 | ||
@@ -895,7 +958,7 @@ static int smack_file_permission(struct file *file, int mask) | |||
895 | */ | 958 | */ |
896 | static int smack_file_alloc_security(struct file *file) | 959 | static int smack_file_alloc_security(struct file *file) |
897 | { | 960 | { |
898 | file->f_security = current_security(); | 961 | file->f_security = smk_of_current(); |
899 | return 0; | 962 | return 0; |
900 | } | 963 | } |
901 | 964 | ||
@@ -1005,7 +1068,7 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
1005 | */ | 1068 | */ |
1006 | static int smack_file_set_fowner(struct file *file) | 1069 | static int smack_file_set_fowner(struct file *file) |
1007 | { | 1070 | { |
1008 | file->f_security = current_security(); | 1071 | file->f_security = smk_of_current(); |
1009 | return 0; | 1072 | return 0; |
1010 | } | 1073 | } |
1011 | 1074 | ||
@@ -1025,7 +1088,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, | |||
1025 | { | 1088 | { |
1026 | struct file *file; | 1089 | struct file *file; |
1027 | int rc; | 1090 | int rc; |
1028 | char *tsp = tsk->cred->security; | 1091 | char *tsp = smk_of_task(tsk->cred->security); |
1029 | struct smk_audit_info ad; | 1092 | struct smk_audit_info ad; |
1030 | 1093 | ||
1031 | /* | 1094 | /* |
@@ -1082,7 +1145,9 @@ static int smack_file_receive(struct file *file) | |||
1082 | */ | 1145 | */ |
1083 | static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) | 1146 | static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) |
1084 | { | 1147 | { |
1085 | cred->security = NULL; | 1148 | cred->security = kzalloc(sizeof(struct task_smack), gfp); |
1149 | if (cred->security == NULL) | ||
1150 | return -ENOMEM; | ||
1086 | return 0; | 1151 | return 0; |
1087 | } | 1152 | } |
1088 | 1153 | ||
@@ -1097,7 +1162,7 @@ static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) | |||
1097 | */ | 1162 | */ |
1098 | static void smack_cred_free(struct cred *cred) | 1163 | static void smack_cred_free(struct cred *cred) |
1099 | { | 1164 | { |
1100 | cred->security = NULL; | 1165 | kfree(cred->security); |
1101 | } | 1166 | } |
1102 | 1167 | ||
1103 | /** | 1168 | /** |
@@ -1111,7 +1176,16 @@ static void smack_cred_free(struct cred *cred) | |||
1111 | static int smack_cred_prepare(struct cred *new, const struct cred *old, | 1176 | static int smack_cred_prepare(struct cred *new, const struct cred *old, |
1112 | gfp_t gfp) | 1177 | gfp_t gfp) |
1113 | { | 1178 | { |
1114 | new->security = old->security; | 1179 | struct task_smack *old_tsp = old->security; |
1180 | struct task_smack *new_tsp; | ||
1181 | |||
1182 | new_tsp = kzalloc(sizeof(struct task_smack), gfp); | ||
1183 | if (new_tsp == NULL) | ||
1184 | return -ENOMEM; | ||
1185 | |||
1186 | new_tsp->smk_task = old_tsp->smk_task; | ||
1187 | new_tsp->smk_forked = old_tsp->smk_task; | ||
1188 | new->security = new_tsp; | ||
1115 | return 0; | 1189 | return 0; |
1116 | } | 1190 | } |
1117 | 1191 | ||
@@ -1124,7 +1198,11 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old, | |||
1124 | */ | 1198 | */ |
1125 | static void smack_cred_transfer(struct cred *new, const struct cred *old) | 1199 | static void smack_cred_transfer(struct cred *new, const struct cred *old) |
1126 | { | 1200 | { |
1127 | new->security = old->security; | 1201 | struct task_smack *old_tsp = old->security; |
1202 | struct task_smack *new_tsp = new->security; | ||
1203 | |||
1204 | new_tsp->smk_task = old_tsp->smk_task; | ||
1205 | new_tsp->smk_forked = old_tsp->smk_task; | ||
1128 | } | 1206 | } |
1129 | 1207 | ||
1130 | /** | 1208 | /** |
@@ -1136,12 +1214,13 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old) | |||
1136 | */ | 1214 | */ |
1137 | static int smack_kernel_act_as(struct cred *new, u32 secid) | 1215 | static int smack_kernel_act_as(struct cred *new, u32 secid) |
1138 | { | 1216 | { |
1217 | struct task_smack *new_tsp = new->security; | ||
1139 | char *smack = smack_from_secid(secid); | 1218 | char *smack = smack_from_secid(secid); |
1140 | 1219 | ||
1141 | if (smack == NULL) | 1220 | if (smack == NULL) |
1142 | return -EINVAL; | 1221 | return -EINVAL; |
1143 | 1222 | ||
1144 | new->security = smack; | 1223 | new_tsp->smk_task = smack; |
1145 | return 0; | 1224 | return 0; |
1146 | } | 1225 | } |
1147 | 1226 | ||
@@ -1157,8 +1236,10 @@ static int smack_kernel_create_files_as(struct cred *new, | |||
1157 | struct inode *inode) | 1236 | struct inode *inode) |
1158 | { | 1237 | { |
1159 | struct inode_smack *isp = inode->i_security; | 1238 | struct inode_smack *isp = inode->i_security; |
1239 | struct task_smack *tsp = new->security; | ||
1160 | 1240 | ||
1161 | new->security = isp->smk_inode; | 1241 | tsp->smk_forked = isp->smk_inode; |
1242 | tsp->smk_task = isp->smk_inode; | ||
1162 | return 0; | 1243 | return 0; |
1163 | } | 1244 | } |
1164 | 1245 | ||
@@ -1175,7 +1256,7 @@ static int smk_curacc_on_task(struct task_struct *p, int access) | |||
1175 | 1256 | ||
1176 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 1257 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
1177 | smk_ad_setfield_u_tsk(&ad, p); | 1258 | smk_ad_setfield_u_tsk(&ad, p); |
1178 | return smk_curacc(task_security(p), access, &ad); | 1259 | return smk_curacc(smk_of_task(task_security(p)), access, &ad); |
1179 | } | 1260 | } |
1180 | 1261 | ||
1181 | /** | 1262 | /** |
@@ -1221,7 +1302,7 @@ static int smack_task_getsid(struct task_struct *p) | |||
1221 | */ | 1302 | */ |
1222 | static void smack_task_getsecid(struct task_struct *p, u32 *secid) | 1303 | static void smack_task_getsecid(struct task_struct *p, u32 *secid) |
1223 | { | 1304 | { |
1224 | *secid = smack_to_secid(task_security(p)); | 1305 | *secid = smack_to_secid(smk_of_task(task_security(p))); |
1225 | } | 1306 | } |
1226 | 1307 | ||
1227 | /** | 1308 | /** |
@@ -1333,14 +1414,15 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, | |||
1333 | * can write the receiver. | 1414 | * can write the receiver. |
1334 | */ | 1415 | */ |
1335 | if (secid == 0) | 1416 | if (secid == 0) |
1336 | return smk_curacc(task_security(p), MAY_WRITE, &ad); | 1417 | return smk_curacc(smk_of_task(task_security(p)), MAY_WRITE, |
1418 | &ad); | ||
1337 | /* | 1419 | /* |
1338 | * If the secid isn't 0 we're dealing with some USB IO | 1420 | * If the secid isn't 0 we're dealing with some USB IO |
1339 | * specific behavior. This is not clean. For one thing | 1421 | * specific behavior. This is not clean. For one thing |
1340 | * we can't take privilege into account. | 1422 | * we can't take privilege into account. |
1341 | */ | 1423 | */ |
1342 | return smk_access(smack_from_secid(secid), task_security(p), | 1424 | return smk_access(smack_from_secid(secid), |
1343 | MAY_WRITE, &ad); | 1425 | smk_of_task(task_security(p)), MAY_WRITE, &ad); |
1344 | } | 1426 | } |
1345 | 1427 | ||
1346 | /** | 1428 | /** |
@@ -1352,12 +1434,12 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, | |||
1352 | static int smack_task_wait(struct task_struct *p) | 1434 | static int smack_task_wait(struct task_struct *p) |
1353 | { | 1435 | { |
1354 | struct smk_audit_info ad; | 1436 | struct smk_audit_info ad; |
1355 | char *sp = current_security(); | 1437 | char *sp = smk_of_current(); |
1356 | char *tsp = task_security(p); | 1438 | char *tsp = smk_of_forked(task_security(p)); |
1357 | int rc; | 1439 | int rc; |
1358 | 1440 | ||
1359 | /* we don't log here, we can be overriden */ | 1441 | /* we don't log here, we can be overriden */ |
1360 | rc = smk_access(sp, tsp, MAY_WRITE, NULL); | 1442 | rc = smk_access(tsp, sp, MAY_WRITE, NULL); |
1361 | if (rc == 0) | 1443 | if (rc == 0) |
1362 | goto out_log; | 1444 | goto out_log; |
1363 | 1445 | ||
@@ -1378,7 +1460,7 @@ static int smack_task_wait(struct task_struct *p) | |||
1378 | out_log: | 1460 | out_log: |
1379 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 1461 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
1380 | smk_ad_setfield_u_tsk(&ad, p); | 1462 | smk_ad_setfield_u_tsk(&ad, p); |
1381 | smack_log(sp, tsp, MAY_WRITE, rc, &ad); | 1463 | smack_log(tsp, sp, MAY_WRITE, rc, &ad); |
1382 | return rc; | 1464 | return rc; |
1383 | } | 1465 | } |
1384 | 1466 | ||
@@ -1392,7 +1474,7 @@ static int smack_task_wait(struct task_struct *p) | |||
1392 | static void smack_task_to_inode(struct task_struct *p, struct inode *inode) | 1474 | static void smack_task_to_inode(struct task_struct *p, struct inode *inode) |
1393 | { | 1475 | { |
1394 | struct inode_smack *isp = inode->i_security; | 1476 | struct inode_smack *isp = inode->i_security; |
1395 | isp->smk_inode = task_security(p); | 1477 | isp->smk_inode = smk_of_task(task_security(p)); |
1396 | } | 1478 | } |
1397 | 1479 | ||
1398 | /* | 1480 | /* |
@@ -1411,7 +1493,7 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode) | |||
1411 | */ | 1493 | */ |
1412 | static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) | 1494 | static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) |
1413 | { | 1495 | { |
1414 | char *csp = current_security(); | 1496 | char *csp = smk_of_current(); |
1415 | struct socket_smack *ssp; | 1497 | struct socket_smack *ssp; |
1416 | 1498 | ||
1417 | ssp = kzalloc(sizeof(struct socket_smack), gfp_flags); | 1499 | ssp = kzalloc(sizeof(struct socket_smack), gfp_flags); |
@@ -1667,10 +1749,13 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, | |||
1667 | ssp->smk_in = sp; | 1749 | ssp->smk_in = sp; |
1668 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { | 1750 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { |
1669 | ssp->smk_out = sp; | 1751 | ssp->smk_out = sp; |
1670 | rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); | 1752 | if (sock->sk->sk_family != PF_UNIX) { |
1671 | if (rc != 0) | 1753 | rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); |
1672 | printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n", | 1754 | if (rc != 0) |
1673 | __func__, -rc); | 1755 | printk(KERN_WARNING |
1756 | "Smack: \"%s\" netlbl error %d.\n", | ||
1757 | __func__, -rc); | ||
1758 | } | ||
1674 | } else | 1759 | } else |
1675 | return -EOPNOTSUPP; | 1760 | return -EOPNOTSUPP; |
1676 | 1761 | ||
@@ -1749,7 +1834,7 @@ static int smack_flags_to_may(int flags) | |||
1749 | */ | 1834 | */ |
1750 | static int smack_msg_msg_alloc_security(struct msg_msg *msg) | 1835 | static int smack_msg_msg_alloc_security(struct msg_msg *msg) |
1751 | { | 1836 | { |
1752 | msg->security = current_security(); | 1837 | msg->security = smk_of_current(); |
1753 | return 0; | 1838 | return 0; |
1754 | } | 1839 | } |
1755 | 1840 | ||
@@ -1785,7 +1870,7 @@ static int smack_shm_alloc_security(struct shmid_kernel *shp) | |||
1785 | { | 1870 | { |
1786 | struct kern_ipc_perm *isp = &shp->shm_perm; | 1871 | struct kern_ipc_perm *isp = &shp->shm_perm; |
1787 | 1872 | ||
1788 | isp->security = current_security(); | 1873 | isp->security = smk_of_current(); |
1789 | return 0; | 1874 | return 0; |
1790 | } | 1875 | } |
1791 | 1876 | ||
@@ -1908,7 +1993,7 @@ static int smack_sem_alloc_security(struct sem_array *sma) | |||
1908 | { | 1993 | { |
1909 | struct kern_ipc_perm *isp = &sma->sem_perm; | 1994 | struct kern_ipc_perm *isp = &sma->sem_perm; |
1910 | 1995 | ||
1911 | isp->security = current_security(); | 1996 | isp->security = smk_of_current(); |
1912 | return 0; | 1997 | return 0; |
1913 | } | 1998 | } |
1914 | 1999 | ||
@@ -2026,7 +2111,7 @@ static int smack_msg_queue_alloc_security(struct msg_queue *msq) | |||
2026 | { | 2111 | { |
2027 | struct kern_ipc_perm *kisp = &msq->q_perm; | 2112 | struct kern_ipc_perm *kisp = &msq->q_perm; |
2028 | 2113 | ||
2029 | kisp->security = current_security(); | 2114 | kisp->security = smk_of_current(); |
2030 | return 0; | 2115 | return 0; |
2031 | } | 2116 | } |
2032 | 2117 | ||
@@ -2198,9 +2283,11 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2198 | struct super_block *sbp; | 2283 | struct super_block *sbp; |
2199 | struct superblock_smack *sbsp; | 2284 | struct superblock_smack *sbsp; |
2200 | struct inode_smack *isp; | 2285 | struct inode_smack *isp; |
2201 | char *csp = current_security(); | 2286 | char *csp = smk_of_current(); |
2202 | char *fetched; | 2287 | char *fetched; |
2203 | char *final; | 2288 | char *final; |
2289 | char trattr[TRANS_TRUE_SIZE]; | ||
2290 | int transflag = 0; | ||
2204 | struct dentry *dp; | 2291 | struct dentry *dp; |
2205 | 2292 | ||
2206 | if (inode == NULL) | 2293 | if (inode == NULL) |
@@ -2267,9 +2354,10 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2267 | break; | 2354 | break; |
2268 | case SOCKFS_MAGIC: | 2355 | case SOCKFS_MAGIC: |
2269 | /* | 2356 | /* |
2270 | * Casey says sockets get the smack of the task. | 2357 | * Socket access is controlled by the socket |
2358 | * structures associated with the task involved. | ||
2271 | */ | 2359 | */ |
2272 | final = csp; | 2360 | final = smack_known_star.smk_known; |
2273 | break; | 2361 | break; |
2274 | case PROC_SUPER_MAGIC: | 2362 | case PROC_SUPER_MAGIC: |
2275 | /* | 2363 | /* |
@@ -2296,7 +2384,16 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2296 | /* | 2384 | /* |
2297 | * This isn't an understood special case. | 2385 | * This isn't an understood special case. |
2298 | * Get the value from the xattr. | 2386 | * Get the value from the xattr. |
2299 | * | 2387 | */ |
2388 | |||
2389 | /* | ||
2390 | * UNIX domain sockets use lower level socket data. | ||
2391 | */ | ||
2392 | if (S_ISSOCK(inode->i_mode)) { | ||
2393 | final = smack_known_star.smk_known; | ||
2394 | break; | ||
2395 | } | ||
2396 | /* | ||
2300 | * No xattr support means, alas, no SMACK label. | 2397 | * No xattr support means, alas, no SMACK label. |
2301 | * Use the aforeapplied default. | 2398 | * Use the aforeapplied default. |
2302 | * It would be curious if the label of the task | 2399 | * It would be curious if the label of the task |
@@ -2308,9 +2405,21 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2308 | * Get the dentry for xattr. | 2405 | * Get the dentry for xattr. |
2309 | */ | 2406 | */ |
2310 | dp = dget(opt_dentry); | 2407 | dp = dget(opt_dentry); |
2311 | fetched = smk_fetch(inode, dp); | 2408 | fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp); |
2312 | if (fetched != NULL) | 2409 | if (fetched != NULL) { |
2313 | final = fetched; | 2410 | final = fetched; |
2411 | if (S_ISDIR(inode->i_mode)) { | ||
2412 | trattr[0] = '\0'; | ||
2413 | inode->i_op->getxattr(dp, | ||
2414 | XATTR_NAME_SMACKTRANSMUTE, | ||
2415 | trattr, TRANS_TRUE_SIZE); | ||
2416 | if (strncmp(trattr, TRANS_TRUE, | ||
2417 | TRANS_TRUE_SIZE) == 0) | ||
2418 | transflag = SMK_INODE_TRANSMUTE; | ||
2419 | } | ||
2420 | } | ||
2421 | isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); | ||
2422 | |||
2314 | dput(dp); | 2423 | dput(dp); |
2315 | break; | 2424 | break; |
2316 | } | 2425 | } |
@@ -2320,7 +2429,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2320 | else | 2429 | else |
2321 | isp->smk_inode = final; | 2430 | isp->smk_inode = final; |
2322 | 2431 | ||
2323 | isp->smk_flags |= SMK_INODE_INSTANT; | 2432 | isp->smk_flags |= (SMK_INODE_INSTANT | transflag); |
2324 | 2433 | ||
2325 | unlockandout: | 2434 | unlockandout: |
2326 | mutex_unlock(&isp->smk_lock); | 2435 | mutex_unlock(&isp->smk_lock); |
@@ -2345,7 +2454,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value) | |||
2345 | if (strcmp(name, "current") != 0) | 2454 | if (strcmp(name, "current") != 0) |
2346 | return -EINVAL; | 2455 | return -EINVAL; |
2347 | 2456 | ||
2348 | cp = kstrdup(task_security(p), GFP_KERNEL); | 2457 | cp = kstrdup(smk_of_task(task_security(p)), GFP_KERNEL); |
2349 | if (cp == NULL) | 2458 | if (cp == NULL) |
2350 | return -ENOMEM; | 2459 | return -ENOMEM; |
2351 | 2460 | ||
@@ -2369,6 +2478,8 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value) | |||
2369 | static int smack_setprocattr(struct task_struct *p, char *name, | 2478 | static int smack_setprocattr(struct task_struct *p, char *name, |
2370 | void *value, size_t size) | 2479 | void *value, size_t size) |
2371 | { | 2480 | { |
2481 | struct task_smack *tsp; | ||
2482 | struct task_smack *oldtsp; | ||
2372 | struct cred *new; | 2483 | struct cred *new; |
2373 | char *newsmack; | 2484 | char *newsmack; |
2374 | 2485 | ||
@@ -2398,10 +2509,18 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
2398 | if (newsmack == smack_known_web.smk_known) | 2509 | if (newsmack == smack_known_web.smk_known) |
2399 | return -EPERM; | 2510 | return -EPERM; |
2400 | 2511 | ||
2512 | oldtsp = p->cred->security; | ||
2401 | new = prepare_creds(); | 2513 | new = prepare_creds(); |
2402 | if (new == NULL) | 2514 | if (new == NULL) |
2403 | return -ENOMEM; | 2515 | return -ENOMEM; |
2404 | new->security = newsmack; | 2516 | tsp = kzalloc(sizeof(struct task_smack), GFP_KERNEL); |
2517 | if (tsp == NULL) { | ||
2518 | kfree(new); | ||
2519 | return -ENOMEM; | ||
2520 | } | ||
2521 | tsp->smk_task = newsmack; | ||
2522 | tsp->smk_forked = oldtsp->smk_forked; | ||
2523 | new->security = tsp; | ||
2405 | commit_creds(new); | 2524 | commit_creds(new); |
2406 | return size; | 2525 | return size; |
2407 | } | 2526 | } |
@@ -2418,14 +2537,18 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
2418 | static int smack_unix_stream_connect(struct sock *sock, | 2537 | static int smack_unix_stream_connect(struct sock *sock, |
2419 | struct sock *other, struct sock *newsk) | 2538 | struct sock *other, struct sock *newsk) |
2420 | { | 2539 | { |
2421 | struct inode *sp = SOCK_INODE(sock->sk_socket); | 2540 | struct socket_smack *ssp = sock->sk_security; |
2422 | struct inode *op = SOCK_INODE(other->sk_socket); | 2541 | struct socket_smack *osp = other->sk_security; |
2423 | struct smk_audit_info ad; | 2542 | struct smk_audit_info ad; |
2543 | int rc = 0; | ||
2424 | 2544 | ||
2425 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); | 2545 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); |
2426 | smk_ad_setfield_u_net_sk(&ad, other); | 2546 | smk_ad_setfield_u_net_sk(&ad, other); |
2427 | return smk_access(smk_of_inode(sp), smk_of_inode(op), | 2547 | |
2428 | MAY_READWRITE, &ad); | 2548 | if (!capable(CAP_MAC_OVERRIDE)) |
2549 | rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); | ||
2550 | |||
2551 | return rc; | ||
2429 | } | 2552 | } |
2430 | 2553 | ||
2431 | /** | 2554 | /** |
@@ -2438,13 +2561,18 @@ static int smack_unix_stream_connect(struct sock *sock, | |||
2438 | */ | 2561 | */ |
2439 | static int smack_unix_may_send(struct socket *sock, struct socket *other) | 2562 | static int smack_unix_may_send(struct socket *sock, struct socket *other) |
2440 | { | 2563 | { |
2441 | struct inode *sp = SOCK_INODE(sock); | 2564 | struct socket_smack *ssp = sock->sk->sk_security; |
2442 | struct inode *op = SOCK_INODE(other); | 2565 | struct socket_smack *osp = other->sk->sk_security; |
2443 | struct smk_audit_info ad; | 2566 | struct smk_audit_info ad; |
2567 | int rc = 0; | ||
2444 | 2568 | ||
2445 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); | 2569 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); |
2446 | smk_ad_setfield_u_net_sk(&ad, other->sk); | 2570 | smk_ad_setfield_u_net_sk(&ad, other->sk); |
2447 | return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_WRITE, &ad); | 2571 | |
2572 | if (!capable(CAP_MAC_OVERRIDE)) | ||
2573 | rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); | ||
2574 | |||
2575 | return rc; | ||
2448 | } | 2576 | } |
2449 | 2577 | ||
2450 | /** | 2578 | /** |
@@ -2629,7 +2757,7 @@ static int smack_socket_getpeersec_stream(struct socket *sock, | |||
2629 | 2757 | ||
2630 | /** | 2758 | /** |
2631 | * smack_socket_getpeersec_dgram - pull in packet label | 2759 | * smack_socket_getpeersec_dgram - pull in packet label |
2632 | * @sock: the socket | 2760 | * @sock: the peer socket |
2633 | * @skb: packet data | 2761 | * @skb: packet data |
2634 | * @secid: pointer to where to put the secid of the packet | 2762 | * @secid: pointer to where to put the secid of the packet |
2635 | * | 2763 | * |
@@ -2640,41 +2768,39 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, | |||
2640 | 2768 | ||
2641 | { | 2769 | { |
2642 | struct netlbl_lsm_secattr secattr; | 2770 | struct netlbl_lsm_secattr secattr; |
2643 | struct sock *sk; | 2771 | struct socket_smack *sp; |
2644 | char smack[SMK_LABELLEN]; | 2772 | char smack[SMK_LABELLEN]; |
2645 | int family = PF_INET; | 2773 | int family = PF_UNSPEC; |
2646 | u32 s; | 2774 | u32 s = 0; /* 0 is the invalid secid */ |
2647 | int rc; | 2775 | int rc; |
2648 | 2776 | ||
2649 | /* | 2777 | if (skb != NULL) { |
2650 | * Only works for families with packets. | 2778 | if (skb->protocol == htons(ETH_P_IP)) |
2651 | */ | 2779 | family = PF_INET; |
2652 | if (sock != NULL) { | 2780 | else if (skb->protocol == htons(ETH_P_IPV6)) |
2653 | sk = sock->sk; | 2781 | family = PF_INET6; |
2654 | if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) | ||
2655 | return 0; | ||
2656 | family = sk->sk_family; | ||
2657 | } | 2782 | } |
2658 | /* | 2783 | if (family == PF_UNSPEC && sock != NULL) |
2659 | * Translate what netlabel gave us. | 2784 | family = sock->sk->sk_family; |
2660 | */ | ||
2661 | netlbl_secattr_init(&secattr); | ||
2662 | rc = netlbl_skbuff_getattr(skb, family, &secattr); | ||
2663 | if (rc == 0) | ||
2664 | smack_from_secattr(&secattr, smack); | ||
2665 | netlbl_secattr_destroy(&secattr); | ||
2666 | 2785 | ||
2667 | /* | 2786 | if (family == PF_UNIX) { |
2668 | * Give up if we couldn't get anything | 2787 | sp = sock->sk->sk_security; |
2669 | */ | 2788 | s = smack_to_secid(sp->smk_out); |
2670 | if (rc != 0) | 2789 | } else if (family == PF_INET || family == PF_INET6) { |
2671 | return rc; | 2790 | /* |
2672 | 2791 | * Translate what netlabel gave us. | |
2673 | s = smack_to_secid(smack); | 2792 | */ |
2793 | netlbl_secattr_init(&secattr); | ||
2794 | rc = netlbl_skbuff_getattr(skb, family, &secattr); | ||
2795 | if (rc == 0) { | ||
2796 | smack_from_secattr(&secattr, smack); | ||
2797 | s = smack_to_secid(smack); | ||
2798 | } | ||
2799 | netlbl_secattr_destroy(&secattr); | ||
2800 | } | ||
2801 | *secid = s; | ||
2674 | if (s == 0) | 2802 | if (s == 0) |
2675 | return -EINVAL; | 2803 | return -EINVAL; |
2676 | |||
2677 | *secid = s; | ||
2678 | return 0; | 2804 | return 0; |
2679 | } | 2805 | } |
2680 | 2806 | ||
@@ -2695,7 +2821,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent) | |||
2695 | return; | 2821 | return; |
2696 | 2822 | ||
2697 | ssp = sk->sk_security; | 2823 | ssp = sk->sk_security; |
2698 | ssp->smk_in = ssp->smk_out = current_security(); | 2824 | ssp->smk_in = ssp->smk_out = smk_of_current(); |
2699 | /* cssp->smk_packet is already set in smack_inet_csk_clone() */ | 2825 | /* cssp->smk_packet is already set in smack_inet_csk_clone() */ |
2700 | } | 2826 | } |
2701 | 2827 | ||
@@ -2816,7 +2942,7 @@ static void smack_inet_csk_clone(struct sock *sk, | |||
2816 | static int smack_key_alloc(struct key *key, const struct cred *cred, | 2942 | static int smack_key_alloc(struct key *key, const struct cred *cred, |
2817 | unsigned long flags) | 2943 | unsigned long flags) |
2818 | { | 2944 | { |
2819 | key->security = cred->security; | 2945 | key->security = smk_of_task(cred->security); |
2820 | return 0; | 2946 | return 0; |
2821 | } | 2947 | } |
2822 | 2948 | ||
@@ -2845,6 +2971,7 @@ static int smack_key_permission(key_ref_t key_ref, | |||
2845 | { | 2971 | { |
2846 | struct key *keyp; | 2972 | struct key *keyp; |
2847 | struct smk_audit_info ad; | 2973 | struct smk_audit_info ad; |
2974 | char *tsp = smk_of_task(cred->security); | ||
2848 | 2975 | ||
2849 | keyp = key_ref_to_ptr(key_ref); | 2976 | keyp = key_ref_to_ptr(key_ref); |
2850 | if (keyp == NULL) | 2977 | if (keyp == NULL) |
@@ -2858,14 +2985,14 @@ static int smack_key_permission(key_ref_t key_ref, | |||
2858 | /* | 2985 | /* |
2859 | * This should not occur | 2986 | * This should not occur |
2860 | */ | 2987 | */ |
2861 | if (cred->security == NULL) | 2988 | if (tsp == NULL) |
2862 | return -EACCES; | 2989 | return -EACCES; |
2863 | #ifdef CONFIG_AUDIT | 2990 | #ifdef CONFIG_AUDIT |
2864 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_KEY); | 2991 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_KEY); |
2865 | ad.a.u.key_struct.key = keyp->serial; | 2992 | ad.a.u.key_struct.key = keyp->serial; |
2866 | ad.a.u.key_struct.key_desc = keyp->description; | 2993 | ad.a.u.key_struct.key_desc = keyp->description; |
2867 | #endif | 2994 | #endif |
2868 | return smk_access(cred->security, keyp->security, | 2995 | return smk_access(tsp, keyp->security, |
2869 | MAY_READWRITE, &ad); | 2996 | MAY_READWRITE, &ad); |
2870 | } | 2997 | } |
2871 | #endif /* CONFIG_KEYS */ | 2998 | #endif /* CONFIG_KEYS */ |
@@ -3067,6 +3194,8 @@ struct security_operations smack_ops = { | |||
3067 | .sb_mount = smack_sb_mount, | 3194 | .sb_mount = smack_sb_mount, |
3068 | .sb_umount = smack_sb_umount, | 3195 | .sb_umount = smack_sb_umount, |
3069 | 3196 | ||
3197 | .bprm_set_creds = smack_bprm_set_creds, | ||
3198 | |||
3070 | .inode_alloc_security = smack_inode_alloc_security, | 3199 | .inode_alloc_security = smack_inode_alloc_security, |
3071 | .inode_free_security = smack_inode_free_security, | 3200 | .inode_free_security = smack_inode_free_security, |
3072 | .inode_init_security = smack_inode_init_security, | 3201 | .inode_init_security = smack_inode_init_security, |
@@ -3203,9 +3332,16 @@ static __init void init_smack_know_list(void) | |||
3203 | static __init int smack_init(void) | 3332 | static __init int smack_init(void) |
3204 | { | 3333 | { |
3205 | struct cred *cred; | 3334 | struct cred *cred; |
3335 | struct task_smack *tsp; | ||
3206 | 3336 | ||
3207 | if (!security_module_enable(&smack_ops)) | 3337 | tsp = kzalloc(sizeof(struct task_smack), GFP_KERNEL); |
3338 | if (tsp == NULL) | ||
3339 | return -ENOMEM; | ||
3340 | |||
3341 | if (!security_module_enable(&smack_ops)) { | ||
3342 | kfree(tsp); | ||
3208 | return 0; | 3343 | return 0; |
3344 | } | ||
3209 | 3345 | ||
3210 | printk(KERN_INFO "Smack: Initializing.\n"); | 3346 | printk(KERN_INFO "Smack: Initializing.\n"); |
3211 | 3347 | ||
@@ -3213,7 +3349,9 @@ static __init int smack_init(void) | |||
3213 | * Set the security state for the initial task. | 3349 | * Set the security state for the initial task. |
3214 | */ | 3350 | */ |
3215 | cred = (struct cred *) current->cred; | 3351 | cred = (struct cred *) current->cred; |
3216 | cred->security = &smack_known_floor.smk_known; | 3352 | tsp->smk_forked = smack_known_floor.smk_known; |
3353 | tsp->smk_task = smack_known_floor.smk_known; | ||
3354 | cred->security = tsp; | ||
3217 | 3355 | ||
3218 | /* initialize the smack_know_list */ | 3356 | /* initialize the smack_know_list */ |
3219 | init_smack_know_list(); | 3357 | init_smack_know_list(); |
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index dc1fd6239f24..362d5eda948b 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
@@ -109,9 +109,12 @@ const char *smack_cipso_option = SMACK_CIPSO_OPTION; | |||
109 | * SMK_ACCESSLEN: Maximum length for a rule access field | 109 | * SMK_ACCESSLEN: Maximum length for a rule access field |
110 | * SMK_LOADLEN: Smack rule length | 110 | * SMK_LOADLEN: Smack rule length |
111 | */ | 111 | */ |
112 | #define SMK_ACCESS "rwxa" | 112 | #define SMK_OACCESS "rwxa" |
113 | #define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1) | 113 | #define SMK_ACCESS "rwxat" |
114 | #define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN) | 114 | #define SMK_OACCESSLEN (sizeof(SMK_OACCESS) - 1) |
115 | #define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1) | ||
116 | #define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN) | ||
117 | #define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN) | ||
115 | 118 | ||
116 | /** | 119 | /** |
117 | * smk_netlabel_audit_set - fill a netlbl_audit struct | 120 | * smk_netlabel_audit_set - fill a netlbl_audit struct |
@@ -121,7 +124,7 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap) | |||
121 | { | 124 | { |
122 | nap->loginuid = audit_get_loginuid(current); | 125 | nap->loginuid = audit_get_loginuid(current); |
123 | nap->sessionid = audit_get_sessionid(current); | 126 | nap->sessionid = audit_get_sessionid(current); |
124 | nap->secid = smack_to_secid(current_security()); | 127 | nap->secid = smack_to_secid(smk_of_current()); |
125 | } | 128 | } |
126 | 129 | ||
127 | /* | 130 | /* |
@@ -175,6 +178,8 @@ static int load_seq_show(struct seq_file *s, void *v) | |||
175 | seq_putc(s, 'x'); | 178 | seq_putc(s, 'x'); |
176 | if (srp->smk_access & MAY_APPEND) | 179 | if (srp->smk_access & MAY_APPEND) |
177 | seq_putc(s, 'a'); | 180 | seq_putc(s, 'a'); |
181 | if (srp->smk_access & MAY_TRANSMUTE) | ||
182 | seq_putc(s, 't'); | ||
178 | if (srp->smk_access == 0) | 183 | if (srp->smk_access == 0) |
179 | seq_putc(s, '-'); | 184 | seq_putc(s, '-'); |
180 | 185 | ||
@@ -273,10 +278,15 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf, | |||
273 | if (!capable(CAP_MAC_ADMIN)) | 278 | if (!capable(CAP_MAC_ADMIN)) |
274 | return -EPERM; | 279 | return -EPERM; |
275 | 280 | ||
276 | if (*ppos != 0 || count != SMK_LOADLEN) | 281 | if (*ppos != 0) |
282 | return -EINVAL; | ||
283 | /* | ||
284 | * Minor hack for backward compatability | ||
285 | */ | ||
286 | if (count < (SMK_OLOADLEN) || count > SMK_LOADLEN) | ||
277 | return -EINVAL; | 287 | return -EINVAL; |
278 | 288 | ||
279 | data = kzalloc(count, GFP_KERNEL); | 289 | data = kzalloc(SMK_LOADLEN, GFP_KERNEL); |
280 | if (data == NULL) | 290 | if (data == NULL) |
281 | return -ENOMEM; | 291 | return -ENOMEM; |
282 | 292 | ||
@@ -285,6 +295,12 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf, | |||
285 | goto out; | 295 | goto out; |
286 | } | 296 | } |
287 | 297 | ||
298 | /* | ||
299 | * More on the minor hack for backward compatability | ||
300 | */ | ||
301 | if (count == (SMK_OLOADLEN)) | ||
302 | data[SMK_OLOADLEN] = '-'; | ||
303 | |||
288 | rule = kzalloc(sizeof(*rule), GFP_KERNEL); | 304 | rule = kzalloc(sizeof(*rule), GFP_KERNEL); |
289 | if (rule == NULL) { | 305 | if (rule == NULL) { |
290 | rc = -ENOMEM; | 306 | rc = -ENOMEM; |
@@ -345,6 +361,17 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf, | |||
345 | goto out_free_rule; | 361 | goto out_free_rule; |
346 | } | 362 | } |
347 | 363 | ||
364 | switch (data[SMK_LABELLEN + SMK_LABELLEN + 4]) { | ||
365 | case '-': | ||
366 | break; | ||
367 | case 't': | ||
368 | case 'T': | ||
369 | rule->smk_access |= MAY_TRANSMUTE; | ||
370 | break; | ||
371 | default: | ||
372 | goto out_free_rule; | ||
373 | } | ||
374 | |||
348 | rc = smk_set_access(rule); | 375 | rc = smk_set_access(rule); |
349 | 376 | ||
350 | if (!rc) | 377 | if (!rc) |
@@ -1160,7 +1187,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | |||
1160 | size_t count, loff_t *ppos) | 1187 | size_t count, loff_t *ppos) |
1161 | { | 1188 | { |
1162 | char in[SMK_LABELLEN]; | 1189 | char in[SMK_LABELLEN]; |
1163 | char *sp = current->cred->security; | 1190 | char *sp = smk_of_task(current->cred->security); |
1164 | 1191 | ||
1165 | if (!capable(CAP_MAC_ADMIN)) | 1192 | if (!capable(CAP_MAC_ADMIN)) |
1166 | return -EPERM; | 1193 | return -EPERM; |