diff options
author | Casey Schaufler <casey@schaufler-ca.com> | 2010-12-02 09:43:39 -0500 |
---|---|---|
committer | Casey Schaufler <casey@schaufler-ca.com> | 2010-12-02 09:43:39 -0500 |
commit | 676dac4b1bee0469d6932f698aeb77e8489f5861 (patch) | |
tree | 196b4cb35cf8dfdff0698dc4368cfd00acc7391a | |
parent | 93ae86e759299718c611bc543b9b1633bf32905a (diff) |
This patch adds a new security attribute to Smack called
SMACK64EXEC. It defines label that is used while task is
running.
Exception: in smack_task_wait() child task is checked
for write access to parent task using label inherited
from the task that forked it.
Fixed issues from previous submit:
- SMACK64EXEC was not read when SMACK64 was not set.
- inode security blob was not updated after setting
SMACK64EXEC
- inode security blob was not updated when removing
SMACK64EXEC
-rw-r--r-- | include/linux/xattr.h | 2 | ||||
-rw-r--r-- | security/smack/smack.h | 30 | ||||
-rw-r--r-- | security/smack/smack_access.c | 4 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 192 | ||||
-rw-r--r-- | security/smack/smackfs.c | 4 |
5 files changed, 178 insertions, 54 deletions
diff --git a/include/linux/xattr.h b/include/linux/xattr.h index f1e5bde4b35a..351c7901d74a 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h | |||
@@ -40,9 +40,11 @@ | |||
40 | #define XATTR_SMACK_SUFFIX "SMACK64" | 40 | #define XATTR_SMACK_SUFFIX "SMACK64" |
41 | #define XATTR_SMACK_IPIN "SMACK64IPIN" | 41 | #define XATTR_SMACK_IPIN "SMACK64IPIN" |
42 | #define XATTR_SMACK_IPOUT "SMACK64IPOUT" | 42 | #define XATTR_SMACK_IPOUT "SMACK64IPOUT" |
43 | #define XATTR_SMACK_EXEC "SMACK64EXEC" | ||
43 | #define XATTR_NAME_SMACK XATTR_SECURITY_PREFIX XATTR_SMACK_SUFFIX | 44 | #define XATTR_NAME_SMACK XATTR_SECURITY_PREFIX XATTR_SMACK_SUFFIX |
44 | #define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN | 45 | #define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN |
45 | #define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT | 46 | #define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT |
47 | #define XATTR_NAME_SMACKEXEC XATTR_SECURITY_PREFIX XATTR_SMACK_EXEC | ||
46 | 48 | ||
47 | #define XATTR_CAPS_SUFFIX "capability" | 49 | #define XATTR_CAPS_SUFFIX "capability" |
48 | #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX | 50 | #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX |
diff --git a/security/smack/smack.h b/security/smack/smack.h index 43ae747a5aa4..a2e2cdfab4ef 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
@@ -51,10 +51,16 @@ 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 */ |
59 | 65 | ||
60 | /* | 66 | /* |
@@ -243,6 +249,30 @@ static inline char *smk_of_inode(const struct inode *isp) | |||
243 | } | 249 | } |
244 | 250 | ||
245 | /* | 251 | /* |
252 | * Present a pointer to the smack label in an task blob. | ||
253 | */ | ||
254 | static inline char *smk_of_task(const struct task_smack *tsp) | ||
255 | { | ||
256 | return tsp->smk_task; | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * Present a pointer to the forked smack label in an task blob. | ||
261 | */ | ||
262 | static inline char *smk_of_forked(const struct task_smack *tsp) | ||
263 | { | ||
264 | return tsp->smk_forked; | ||
265 | } | ||
266 | |||
267 | /* | ||
268 | * Present a pointer to the smack label in the curren task blob. | ||
269 | */ | ||
270 | static inline char *smk_of_current(void) | ||
271 | { | ||
272 | return smk_of_task(current_security()); | ||
273 | } | ||
274 | |||
275 | /* | ||
246 | * logging functions | 276 | * logging functions |
247 | */ | 277 | */ |
248 | #define SMACK_AUDIT_DENIED 0x1 | 278 | #define SMACK_AUDIT_DENIED 0x1 |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index f4fac64c4da8..42becbc1ce33 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
@@ -185,7 +185,7 @@ out_audit: | |||
185 | int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) | 185 | int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) |
186 | { | 186 | { |
187 | int rc; | 187 | int rc; |
188 | char *sp = current_security(); | 188 | char *sp = smk_of_current(); |
189 | 189 | ||
190 | rc = smk_access(sp, obj_label, mode, NULL); | 190 | rc = smk_access(sp, obj_label, mode, NULL); |
191 | if (rc == 0) | 191 | if (rc == 0) |
@@ -196,7 +196,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) | |||
196 | * only one that gets privilege and current does not | 196 | * only one that gets privilege and current does not |
197 | * have that label. | 197 | * have that label. |
198 | */ | 198 | */ |
199 | if (smack_onlycap != NULL && smack_onlycap != current->cred->security) | 199 | if (smack_onlycap != NULL && smack_onlycap != sp) |
200 | goto out_audit; | 200 | goto out_audit; |
201 | 201 | ||
202 | if (capable(CAP_MAC_OVERRIDE)) | 202 | if (capable(CAP_MAC_OVERRIDE)) |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 04a98c361a65..7e19afe0e738 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -43,7 +43,7 @@ | |||
43 | * Returns a pointer to the master list entry for the Smack label | 43 | * Returns a pointer to the master list entry for the Smack label |
44 | * or NULL if there was no label to fetch. | 44 | * or NULL if there was no label to fetch. |
45 | */ | 45 | */ |
46 | static char *smk_fetch(struct inode *ip, struct dentry *dp) | 46 | static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp) |
47 | { | 47 | { |
48 | int rc; | 48 | int rc; |
49 | char in[SMK_LABELLEN]; | 49 | char in[SMK_LABELLEN]; |
@@ -51,7 +51,7 @@ static char *smk_fetch(struct inode *ip, struct dentry *dp) | |||
51 | if (ip->i_op->getxattr == NULL) | 51 | if (ip->i_op->getxattr == NULL) |
52 | return NULL; | 52 | return NULL; |
53 | 53 | ||
54 | rc = ip->i_op->getxattr(dp, XATTR_NAME_SMACK, in, SMK_LABELLEN); | 54 | rc = ip->i_op->getxattr(dp, name, in, SMK_LABELLEN); |
55 | if (rc < 0) | 55 | if (rc < 0) |
56 | return NULL; | 56 | return NULL; |
57 | 57 | ||
@@ -103,8 +103,8 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) | |||
103 | if (rc != 0) | 103 | if (rc != 0) |
104 | return rc; | 104 | return rc; |
105 | 105 | ||
106 | sp = current_security(); | 106 | sp = smk_of_current(); |
107 | tsp = task_security(ctp); | 107 | tsp = smk_of_task(task_security(ctp)); |
108 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 108 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
109 | smk_ad_setfield_u_tsk(&ad, ctp); | 109 | smk_ad_setfield_u_tsk(&ad, ctp); |
110 | 110 | ||
@@ -138,8 +138,8 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
138 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 138 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
139 | smk_ad_setfield_u_tsk(&ad, ptp); | 139 | smk_ad_setfield_u_tsk(&ad, ptp); |
140 | 140 | ||
141 | sp = current_security(); | 141 | sp = smk_of_current(); |
142 | tsp = task_security(ptp); | 142 | tsp = smk_of_task(task_security(ptp)); |
143 | /* we won't log here, because rc can be overriden */ | 143 | /* we won't log here, because rc can be overriden */ |
144 | rc = smk_access(tsp, sp, MAY_READWRITE, NULL); | 144 | rc = smk_access(tsp, sp, MAY_READWRITE, NULL); |
145 | if (rc != 0 && has_capability(ptp, CAP_MAC_OVERRIDE)) | 145 | if (rc != 0 && has_capability(ptp, CAP_MAC_OVERRIDE)) |
@@ -160,7 +160,7 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
160 | static int smack_syslog(int typefrom_file) | 160 | static int smack_syslog(int typefrom_file) |
161 | { | 161 | { |
162 | int rc = 0; | 162 | int rc = 0; |
163 | char *sp = current_security(); | 163 | char *sp = smk_of_current(); |
164 | 164 | ||
165 | if (capable(CAP_MAC_OVERRIDE)) | 165 | if (capable(CAP_MAC_OVERRIDE)) |
166 | return 0; | 166 | return 0; |
@@ -391,6 +391,40 @@ static int smack_sb_umount(struct vfsmount *mnt, int flags) | |||
391 | } | 391 | } |
392 | 392 | ||
393 | /* | 393 | /* |
394 | * BPRM hooks | ||
395 | */ | ||
396 | |||
397 | static int smack_bprm_set_creds(struct linux_binprm *bprm) | ||
398 | { | ||
399 | struct task_smack *tsp = bprm->cred->security; | ||
400 | struct inode_smack *isp; | ||
401 | struct dentry *dp; | ||
402 | int rc; | ||
403 | |||
404 | rc = cap_bprm_set_creds(bprm); | ||
405 | if (rc != 0) | ||
406 | return rc; | ||
407 | |||
408 | if (bprm->cred_prepared) | ||
409 | return 0; | ||
410 | |||
411 | if (bprm->file == NULL || bprm->file->f_dentry == NULL) | ||
412 | return 0; | ||
413 | |||
414 | dp = bprm->file->f_dentry; | ||
415 | |||
416 | if (dp->d_inode == NULL) | ||
417 | return 0; | ||
418 | |||
419 | isp = dp->d_inode->i_security; | ||
420 | |||
421 | if (isp->smk_task != NULL) | ||
422 | tsp->smk_task = isp->smk_task; | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | /* | ||
394 | * Inode hooks | 428 | * Inode hooks |
395 | */ | 429 | */ |
396 | 430 | ||
@@ -402,7 +436,7 @@ static int smack_sb_umount(struct vfsmount *mnt, int flags) | |||
402 | */ | 436 | */ |
403 | static int smack_inode_alloc_security(struct inode *inode) | 437 | static int smack_inode_alloc_security(struct inode *inode) |
404 | { | 438 | { |
405 | inode->i_security = new_inode_smack(current_security()); | 439 | inode->i_security = new_inode_smack(smk_of_current()); |
406 | if (inode->i_security == NULL) | 440 | if (inode->i_security == NULL) |
407 | return -ENOMEM; | 441 | return -ENOMEM; |
408 | return 0; | 442 | return 0; |
@@ -664,7 +698,8 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
664 | 698 | ||
665 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || | 699 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || |
666 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || | 700 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || |
667 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) { | 701 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || |
702 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { | ||
668 | if (!capable(CAP_MAC_ADMIN)) | 703 | if (!capable(CAP_MAC_ADMIN)) |
669 | rc = -EPERM; | 704 | rc = -EPERM; |
670 | /* | 705 | /* |
@@ -704,9 +739,10 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
704 | char *nsp; | 739 | char *nsp; |
705 | 740 | ||
706 | /* | 741 | /* |
707 | * Not SMACK | 742 | * Not SMACK or SMACKEXEC |
708 | */ | 743 | */ |
709 | if (strcmp(name, XATTR_NAME_SMACK)) | 744 | if (strcmp(name, XATTR_NAME_SMACK) && |
745 | strcmp(name, XATTR_NAME_SMACKEXEC)) | ||
710 | return; | 746 | return; |
711 | 747 | ||
712 | isp = dentry->d_inode->i_security; | 748 | isp = dentry->d_inode->i_security; |
@@ -716,10 +752,18 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
716 | * assignment. | 752 | * assignment. |
717 | */ | 753 | */ |
718 | nsp = smk_import(value, size); | 754 | nsp = smk_import(value, size); |
719 | if (nsp != NULL) | 755 | |
720 | isp->smk_inode = nsp; | 756 | if (strcmp(name, XATTR_NAME_SMACK) == 0) { |
721 | else | 757 | if (nsp != NULL) |
722 | isp->smk_inode = smack_known_invalid.smk_known; | 758 | isp->smk_inode = nsp; |
759 | else | ||
760 | isp->smk_inode = smack_known_invalid.smk_known; | ||
761 | } else { | ||
762 | if (nsp != NULL) | ||
763 | isp->smk_task = nsp; | ||
764 | else | ||
765 | isp->smk_task = smack_known_invalid.smk_known; | ||
766 | } | ||
723 | 767 | ||
724 | return; | 768 | return; |
725 | } | 769 | } |
@@ -752,12 +796,14 @@ static int smack_inode_getxattr(struct dentry *dentry, const char *name) | |||
752 | */ | 796 | */ |
753 | static int smack_inode_removexattr(struct dentry *dentry, const char *name) | 797 | static int smack_inode_removexattr(struct dentry *dentry, const char *name) |
754 | { | 798 | { |
799 | struct inode_smack *isp; | ||
755 | struct smk_audit_info ad; | 800 | struct smk_audit_info ad; |
756 | int rc = 0; | 801 | int rc = 0; |
757 | 802 | ||
758 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || | 803 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || |
759 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || | 804 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || |
760 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) { | 805 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || |
806 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { | ||
761 | if (!capable(CAP_MAC_ADMIN)) | 807 | if (!capable(CAP_MAC_ADMIN)) |
762 | rc = -EPERM; | 808 | rc = -EPERM; |
763 | } else | 809 | } else |
@@ -768,6 +814,11 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) | |||
768 | if (rc == 0) | 814 | if (rc == 0) |
769 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); | 815 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); |
770 | 816 | ||
817 | if (rc == 0) { | ||
818 | isp = dentry->d_inode->i_security; | ||
819 | isp->smk_task = NULL; | ||
820 | } | ||
821 | |||
771 | return rc; | 822 | return rc; |
772 | } | 823 | } |
773 | 824 | ||
@@ -895,7 +946,7 @@ static int smack_file_permission(struct file *file, int mask) | |||
895 | */ | 946 | */ |
896 | static int smack_file_alloc_security(struct file *file) | 947 | static int smack_file_alloc_security(struct file *file) |
897 | { | 948 | { |
898 | file->f_security = current_security(); | 949 | file->f_security = smk_of_current(); |
899 | return 0; | 950 | return 0; |
900 | } | 951 | } |
901 | 952 | ||
@@ -1005,7 +1056,7 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
1005 | */ | 1056 | */ |
1006 | static int smack_file_set_fowner(struct file *file) | 1057 | static int smack_file_set_fowner(struct file *file) |
1007 | { | 1058 | { |
1008 | file->f_security = current_security(); | 1059 | file->f_security = smk_of_current(); |
1009 | return 0; | 1060 | return 0; |
1010 | } | 1061 | } |
1011 | 1062 | ||
@@ -1025,7 +1076,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, | |||
1025 | { | 1076 | { |
1026 | struct file *file; | 1077 | struct file *file; |
1027 | int rc; | 1078 | int rc; |
1028 | char *tsp = tsk->cred->security; | 1079 | char *tsp = smk_of_task(tsk->cred->security); |
1029 | struct smk_audit_info ad; | 1080 | struct smk_audit_info ad; |
1030 | 1081 | ||
1031 | /* | 1082 | /* |
@@ -1082,7 +1133,9 @@ static int smack_file_receive(struct file *file) | |||
1082 | */ | 1133 | */ |
1083 | static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) | 1134 | static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) |
1084 | { | 1135 | { |
1085 | cred->security = NULL; | 1136 | cred->security = kzalloc(sizeof(struct task_smack), gfp); |
1137 | if (cred->security == NULL) | ||
1138 | return -ENOMEM; | ||
1086 | return 0; | 1139 | return 0; |
1087 | } | 1140 | } |
1088 | 1141 | ||
@@ -1097,7 +1150,7 @@ static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) | |||
1097 | */ | 1150 | */ |
1098 | static void smack_cred_free(struct cred *cred) | 1151 | static void smack_cred_free(struct cred *cred) |
1099 | { | 1152 | { |
1100 | cred->security = NULL; | 1153 | kfree(cred->security); |
1101 | } | 1154 | } |
1102 | 1155 | ||
1103 | /** | 1156 | /** |
@@ -1111,7 +1164,16 @@ static void smack_cred_free(struct cred *cred) | |||
1111 | static int smack_cred_prepare(struct cred *new, const struct cred *old, | 1164 | static int smack_cred_prepare(struct cred *new, const struct cred *old, |
1112 | gfp_t gfp) | 1165 | gfp_t gfp) |
1113 | { | 1166 | { |
1114 | new->security = old->security; | 1167 | struct task_smack *old_tsp = old->security; |
1168 | struct task_smack *new_tsp; | ||
1169 | |||
1170 | new_tsp = kzalloc(sizeof(struct task_smack), gfp); | ||
1171 | if (new_tsp == NULL) | ||
1172 | return -ENOMEM; | ||
1173 | |||
1174 | new_tsp->smk_task = old_tsp->smk_task; | ||
1175 | new_tsp->smk_forked = old_tsp->smk_task; | ||
1176 | new->security = new_tsp; | ||
1115 | return 0; | 1177 | return 0; |
1116 | } | 1178 | } |
1117 | 1179 | ||
@@ -1124,7 +1186,11 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old, | |||
1124 | */ | 1186 | */ |
1125 | static void smack_cred_transfer(struct cred *new, const struct cred *old) | 1187 | static void smack_cred_transfer(struct cred *new, const struct cred *old) |
1126 | { | 1188 | { |
1127 | new->security = old->security; | 1189 | struct task_smack *old_tsp = old->security; |
1190 | struct task_smack *new_tsp = new->security; | ||
1191 | |||
1192 | new_tsp->smk_task = old_tsp->smk_task; | ||
1193 | new_tsp->smk_forked = old_tsp->smk_task; | ||
1128 | } | 1194 | } |
1129 | 1195 | ||
1130 | /** | 1196 | /** |
@@ -1136,12 +1202,13 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old) | |||
1136 | */ | 1202 | */ |
1137 | static int smack_kernel_act_as(struct cred *new, u32 secid) | 1203 | static int smack_kernel_act_as(struct cred *new, u32 secid) |
1138 | { | 1204 | { |
1205 | struct task_smack *new_tsp = new->security; | ||
1139 | char *smack = smack_from_secid(secid); | 1206 | char *smack = smack_from_secid(secid); |
1140 | 1207 | ||
1141 | if (smack == NULL) | 1208 | if (smack == NULL) |
1142 | return -EINVAL; | 1209 | return -EINVAL; |
1143 | 1210 | ||
1144 | new->security = smack; | 1211 | new_tsp->smk_task = smack; |
1145 | return 0; | 1212 | return 0; |
1146 | } | 1213 | } |
1147 | 1214 | ||
@@ -1157,8 +1224,10 @@ static int smack_kernel_create_files_as(struct cred *new, | |||
1157 | struct inode *inode) | 1224 | struct inode *inode) |
1158 | { | 1225 | { |
1159 | struct inode_smack *isp = inode->i_security; | 1226 | struct inode_smack *isp = inode->i_security; |
1227 | struct task_smack *tsp = new->security; | ||
1160 | 1228 | ||
1161 | new->security = isp->smk_inode; | 1229 | tsp->smk_forked = isp->smk_inode; |
1230 | tsp->smk_task = isp->smk_inode; | ||
1162 | return 0; | 1231 | return 0; |
1163 | } | 1232 | } |
1164 | 1233 | ||
@@ -1175,7 +1244,7 @@ static int smk_curacc_on_task(struct task_struct *p, int access) | |||
1175 | 1244 | ||
1176 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 1245 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
1177 | smk_ad_setfield_u_tsk(&ad, p); | 1246 | smk_ad_setfield_u_tsk(&ad, p); |
1178 | return smk_curacc(task_security(p), access, &ad); | 1247 | return smk_curacc(smk_of_task(task_security(p)), access, &ad); |
1179 | } | 1248 | } |
1180 | 1249 | ||
1181 | /** | 1250 | /** |
@@ -1221,7 +1290,7 @@ static int smack_task_getsid(struct task_struct *p) | |||
1221 | */ | 1290 | */ |
1222 | static void smack_task_getsecid(struct task_struct *p, u32 *secid) | 1291 | static void smack_task_getsecid(struct task_struct *p, u32 *secid) |
1223 | { | 1292 | { |
1224 | *secid = smack_to_secid(task_security(p)); | 1293 | *secid = smack_to_secid(smk_of_task(task_security(p))); |
1225 | } | 1294 | } |
1226 | 1295 | ||
1227 | /** | 1296 | /** |
@@ -1333,14 +1402,15 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, | |||
1333 | * can write the receiver. | 1402 | * can write the receiver. |
1334 | */ | 1403 | */ |
1335 | if (secid == 0) | 1404 | if (secid == 0) |
1336 | return smk_curacc(task_security(p), MAY_WRITE, &ad); | 1405 | return smk_curacc(smk_of_task(task_security(p)), MAY_WRITE, |
1406 | &ad); | ||
1337 | /* | 1407 | /* |
1338 | * If the secid isn't 0 we're dealing with some USB IO | 1408 | * If the secid isn't 0 we're dealing with some USB IO |
1339 | * specific behavior. This is not clean. For one thing | 1409 | * specific behavior. This is not clean. For one thing |
1340 | * we can't take privilege into account. | 1410 | * we can't take privilege into account. |
1341 | */ | 1411 | */ |
1342 | return smk_access(smack_from_secid(secid), task_security(p), | 1412 | return smk_access(smack_from_secid(secid), |
1343 | MAY_WRITE, &ad); | 1413 | smk_of_task(task_security(p)), MAY_WRITE, &ad); |
1344 | } | 1414 | } |
1345 | 1415 | ||
1346 | /** | 1416 | /** |
@@ -1352,12 +1422,12 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, | |||
1352 | static int smack_task_wait(struct task_struct *p) | 1422 | static int smack_task_wait(struct task_struct *p) |
1353 | { | 1423 | { |
1354 | struct smk_audit_info ad; | 1424 | struct smk_audit_info ad; |
1355 | char *sp = current_security(); | 1425 | char *sp = smk_of_current(); |
1356 | char *tsp = task_security(p); | 1426 | char *tsp = smk_of_forked(task_security(p)); |
1357 | int rc; | 1427 | int rc; |
1358 | 1428 | ||
1359 | /* we don't log here, we can be overriden */ | 1429 | /* we don't log here, we can be overriden */ |
1360 | rc = smk_access(sp, tsp, MAY_WRITE, NULL); | 1430 | rc = smk_access(tsp, sp, MAY_WRITE, NULL); |
1361 | if (rc == 0) | 1431 | if (rc == 0) |
1362 | goto out_log; | 1432 | goto out_log; |
1363 | 1433 | ||
@@ -1378,7 +1448,7 @@ static int smack_task_wait(struct task_struct *p) | |||
1378 | out_log: | 1448 | out_log: |
1379 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 1449 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
1380 | smk_ad_setfield_u_tsk(&ad, p); | 1450 | smk_ad_setfield_u_tsk(&ad, p); |
1381 | smack_log(sp, tsp, MAY_WRITE, rc, &ad); | 1451 | smack_log(tsp, sp, MAY_WRITE, rc, &ad); |
1382 | return rc; | 1452 | return rc; |
1383 | } | 1453 | } |
1384 | 1454 | ||
@@ -1392,7 +1462,7 @@ static int smack_task_wait(struct task_struct *p) | |||
1392 | static void smack_task_to_inode(struct task_struct *p, struct inode *inode) | 1462 | static void smack_task_to_inode(struct task_struct *p, struct inode *inode) |
1393 | { | 1463 | { |
1394 | struct inode_smack *isp = inode->i_security; | 1464 | struct inode_smack *isp = inode->i_security; |
1395 | isp->smk_inode = task_security(p); | 1465 | isp->smk_inode = smk_of_task(task_security(p)); |
1396 | } | 1466 | } |
1397 | 1467 | ||
1398 | /* | 1468 | /* |
@@ -1411,7 +1481,7 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode) | |||
1411 | */ | 1481 | */ |
1412 | static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) | 1482 | static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) |
1413 | { | 1483 | { |
1414 | char *csp = current_security(); | 1484 | char *csp = smk_of_current(); |
1415 | struct socket_smack *ssp; | 1485 | struct socket_smack *ssp; |
1416 | 1486 | ||
1417 | ssp = kzalloc(sizeof(struct socket_smack), gfp_flags); | 1487 | ssp = kzalloc(sizeof(struct socket_smack), gfp_flags); |
@@ -1752,7 +1822,7 @@ static int smack_flags_to_may(int flags) | |||
1752 | */ | 1822 | */ |
1753 | static int smack_msg_msg_alloc_security(struct msg_msg *msg) | 1823 | static int smack_msg_msg_alloc_security(struct msg_msg *msg) |
1754 | { | 1824 | { |
1755 | msg->security = current_security(); | 1825 | msg->security = smk_of_current(); |
1756 | return 0; | 1826 | return 0; |
1757 | } | 1827 | } |
1758 | 1828 | ||
@@ -1788,7 +1858,7 @@ static int smack_shm_alloc_security(struct shmid_kernel *shp) | |||
1788 | { | 1858 | { |
1789 | struct kern_ipc_perm *isp = &shp->shm_perm; | 1859 | struct kern_ipc_perm *isp = &shp->shm_perm; |
1790 | 1860 | ||
1791 | isp->security = current_security(); | 1861 | isp->security = smk_of_current(); |
1792 | return 0; | 1862 | return 0; |
1793 | } | 1863 | } |
1794 | 1864 | ||
@@ -1911,7 +1981,7 @@ static int smack_sem_alloc_security(struct sem_array *sma) | |||
1911 | { | 1981 | { |
1912 | struct kern_ipc_perm *isp = &sma->sem_perm; | 1982 | struct kern_ipc_perm *isp = &sma->sem_perm; |
1913 | 1983 | ||
1914 | isp->security = current_security(); | 1984 | isp->security = smk_of_current(); |
1915 | return 0; | 1985 | return 0; |
1916 | } | 1986 | } |
1917 | 1987 | ||
@@ -2029,7 +2099,7 @@ static int smack_msg_queue_alloc_security(struct msg_queue *msq) | |||
2029 | { | 2099 | { |
2030 | struct kern_ipc_perm *kisp = &msq->q_perm; | 2100 | struct kern_ipc_perm *kisp = &msq->q_perm; |
2031 | 2101 | ||
2032 | kisp->security = current_security(); | 2102 | kisp->security = smk_of_current(); |
2033 | return 0; | 2103 | return 0; |
2034 | } | 2104 | } |
2035 | 2105 | ||
@@ -2201,7 +2271,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2201 | struct super_block *sbp; | 2271 | struct super_block *sbp; |
2202 | struct superblock_smack *sbsp; | 2272 | struct superblock_smack *sbsp; |
2203 | struct inode_smack *isp; | 2273 | struct inode_smack *isp; |
2204 | char *csp = current_security(); | 2274 | char *csp = smk_of_current(); |
2205 | char *fetched; | 2275 | char *fetched; |
2206 | char *final; | 2276 | char *final; |
2207 | struct dentry *dp; | 2277 | struct dentry *dp; |
@@ -2321,9 +2391,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2321 | * Get the dentry for xattr. | 2391 | * Get the dentry for xattr. |
2322 | */ | 2392 | */ |
2323 | dp = dget(opt_dentry); | 2393 | dp = dget(opt_dentry); |
2324 | fetched = smk_fetch(inode, dp); | 2394 | fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp); |
2325 | if (fetched != NULL) | 2395 | if (fetched != NULL) |
2326 | final = fetched; | 2396 | final = fetched; |
2397 | isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, | ||
2398 | dp); | ||
2399 | |||
2327 | dput(dp); | 2400 | dput(dp); |
2328 | break; | 2401 | break; |
2329 | } | 2402 | } |
@@ -2358,7 +2431,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value) | |||
2358 | if (strcmp(name, "current") != 0) | 2431 | if (strcmp(name, "current") != 0) |
2359 | return -EINVAL; | 2432 | return -EINVAL; |
2360 | 2433 | ||
2361 | cp = kstrdup(task_security(p), GFP_KERNEL); | 2434 | cp = kstrdup(smk_of_task(task_security(p)), GFP_KERNEL); |
2362 | if (cp == NULL) | 2435 | if (cp == NULL) |
2363 | return -ENOMEM; | 2436 | return -ENOMEM; |
2364 | 2437 | ||
@@ -2382,6 +2455,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value) | |||
2382 | static int smack_setprocattr(struct task_struct *p, char *name, | 2455 | static int smack_setprocattr(struct task_struct *p, char *name, |
2383 | void *value, size_t size) | 2456 | void *value, size_t size) |
2384 | { | 2457 | { |
2458 | struct task_smack *tsp; | ||
2385 | struct cred *new; | 2459 | struct cred *new; |
2386 | char *newsmack; | 2460 | char *newsmack; |
2387 | 2461 | ||
@@ -2414,7 +2488,13 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
2414 | new = prepare_creds(); | 2488 | new = prepare_creds(); |
2415 | if (new == NULL) | 2489 | if (new == NULL) |
2416 | return -ENOMEM; | 2490 | return -ENOMEM; |
2417 | new->security = newsmack; | 2491 | tsp = kzalloc(sizeof(struct task_smack), GFP_KERNEL); |
2492 | if (tsp == NULL) { | ||
2493 | kfree(new); | ||
2494 | return -ENOMEM; | ||
2495 | } | ||
2496 | tsp->smk_task = newsmack; | ||
2497 | new->security = tsp; | ||
2418 | commit_creds(new); | 2498 | commit_creds(new); |
2419 | return size; | 2499 | return size; |
2420 | } | 2500 | } |
@@ -2715,7 +2795,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent) | |||
2715 | return; | 2795 | return; |
2716 | 2796 | ||
2717 | ssp = sk->sk_security; | 2797 | ssp = sk->sk_security; |
2718 | ssp->smk_in = ssp->smk_out = current_security(); | 2798 | ssp->smk_in = ssp->smk_out = smk_of_current(); |
2719 | /* cssp->smk_packet is already set in smack_inet_csk_clone() */ | 2799 | /* cssp->smk_packet is already set in smack_inet_csk_clone() */ |
2720 | } | 2800 | } |
2721 | 2801 | ||
@@ -2836,7 +2916,7 @@ static void smack_inet_csk_clone(struct sock *sk, | |||
2836 | static int smack_key_alloc(struct key *key, const struct cred *cred, | 2916 | static int smack_key_alloc(struct key *key, const struct cred *cred, |
2837 | unsigned long flags) | 2917 | unsigned long flags) |
2838 | { | 2918 | { |
2839 | key->security = cred->security; | 2919 | key->security = smk_of_task(cred->security); |
2840 | return 0; | 2920 | return 0; |
2841 | } | 2921 | } |
2842 | 2922 | ||
@@ -2865,6 +2945,7 @@ static int smack_key_permission(key_ref_t key_ref, | |||
2865 | { | 2945 | { |
2866 | struct key *keyp; | 2946 | struct key *keyp; |
2867 | struct smk_audit_info ad; | 2947 | struct smk_audit_info ad; |
2948 | char *tsp = smk_of_task(cred->security); | ||
2868 | 2949 | ||
2869 | keyp = key_ref_to_ptr(key_ref); | 2950 | keyp = key_ref_to_ptr(key_ref); |
2870 | if (keyp == NULL) | 2951 | if (keyp == NULL) |
@@ -2878,14 +2959,14 @@ static int smack_key_permission(key_ref_t key_ref, | |||
2878 | /* | 2959 | /* |
2879 | * This should not occur | 2960 | * This should not occur |
2880 | */ | 2961 | */ |
2881 | if (cred->security == NULL) | 2962 | if (tsp == NULL) |
2882 | return -EACCES; | 2963 | return -EACCES; |
2883 | #ifdef CONFIG_AUDIT | 2964 | #ifdef CONFIG_AUDIT |
2884 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_KEY); | 2965 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_KEY); |
2885 | ad.a.u.key_struct.key = keyp->serial; | 2966 | ad.a.u.key_struct.key = keyp->serial; |
2886 | ad.a.u.key_struct.key_desc = keyp->description; | 2967 | ad.a.u.key_struct.key_desc = keyp->description; |
2887 | #endif | 2968 | #endif |
2888 | return smk_access(cred->security, keyp->security, | 2969 | return smk_access(tsp, keyp->security, |
2889 | MAY_READWRITE, &ad); | 2970 | MAY_READWRITE, &ad); |
2890 | } | 2971 | } |
2891 | #endif /* CONFIG_KEYS */ | 2972 | #endif /* CONFIG_KEYS */ |
@@ -3087,6 +3168,8 @@ struct security_operations smack_ops = { | |||
3087 | .sb_mount = smack_sb_mount, | 3168 | .sb_mount = smack_sb_mount, |
3088 | .sb_umount = smack_sb_umount, | 3169 | .sb_umount = smack_sb_umount, |
3089 | 3170 | ||
3171 | .bprm_set_creds = smack_bprm_set_creds, | ||
3172 | |||
3090 | .inode_alloc_security = smack_inode_alloc_security, | 3173 | .inode_alloc_security = smack_inode_alloc_security, |
3091 | .inode_free_security = smack_inode_free_security, | 3174 | .inode_free_security = smack_inode_free_security, |
3092 | .inode_init_security = smack_inode_init_security, | 3175 | .inode_init_security = smack_inode_init_security, |
@@ -3223,9 +3306,16 @@ static __init void init_smack_know_list(void) | |||
3223 | static __init int smack_init(void) | 3306 | static __init int smack_init(void) |
3224 | { | 3307 | { |
3225 | struct cred *cred; | 3308 | struct cred *cred; |
3309 | struct task_smack *tsp; | ||
3226 | 3310 | ||
3227 | if (!security_module_enable(&smack_ops)) | 3311 | tsp = kzalloc(sizeof(struct task_smack), GFP_KERNEL); |
3312 | if (tsp == NULL) | ||
3313 | return -ENOMEM; | ||
3314 | |||
3315 | if (!security_module_enable(&smack_ops)) { | ||
3316 | kfree(tsp); | ||
3228 | return 0; | 3317 | return 0; |
3318 | } | ||
3229 | 3319 | ||
3230 | printk(KERN_INFO "Smack: Initializing.\n"); | 3320 | printk(KERN_INFO "Smack: Initializing.\n"); |
3231 | 3321 | ||
@@ -3233,7 +3323,9 @@ static __init int smack_init(void) | |||
3233 | * Set the security state for the initial task. | 3323 | * Set the security state for the initial task. |
3234 | */ | 3324 | */ |
3235 | cred = (struct cred *) current->cred; | 3325 | cred = (struct cred *) current->cred; |
3236 | cred->security = &smack_known_floor.smk_known; | 3326 | tsp->smk_forked = smack_known_floor.smk_known; |
3327 | tsp->smk_task = smack_known_floor.smk_known; | ||
3328 | cred->security = tsp; | ||
3237 | 3329 | ||
3238 | /* initialize the smack_know_list */ | 3330 | /* initialize the smack_know_list */ |
3239 | init_smack_know_list(); | 3331 | init_smack_know_list(); |
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index dc1fd6239f24..01a0be93d8d0 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
@@ -121,7 +121,7 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap) | |||
121 | { | 121 | { |
122 | nap->loginuid = audit_get_loginuid(current); | 122 | nap->loginuid = audit_get_loginuid(current); |
123 | nap->sessionid = audit_get_sessionid(current); | 123 | nap->sessionid = audit_get_sessionid(current); |
124 | nap->secid = smack_to_secid(current_security()); | 124 | nap->secid = smack_to_secid(smk_of_current()); |
125 | } | 125 | } |
126 | 126 | ||
127 | /* | 127 | /* |
@@ -1160,7 +1160,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | |||
1160 | size_t count, loff_t *ppos) | 1160 | size_t count, loff_t *ppos) |
1161 | { | 1161 | { |
1162 | char in[SMK_LABELLEN]; | 1162 | char in[SMK_LABELLEN]; |
1163 | char *sp = current->cred->security; | 1163 | char *sp = smk_of_task(current->cred->security); |
1164 | 1164 | ||
1165 | if (!capable(CAP_MAC_ADMIN)) | 1165 | if (!capable(CAP_MAC_ADMIN)) |
1166 | return -EPERM; | 1166 | return -EPERM; |