aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/smack/smack.h9
-rw-r--r--security/smack/smack_access.c52
-rw-r--r--security/smack/smack_lsm.c269
-rw-r--r--security/smack/smackfs.c370
4 files changed, 522 insertions, 178 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 129c4eb8ffb1..e365d455ceb6 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -52,13 +52,16 @@ struct socket_smack {
52struct inode_smack { 52struct 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 char *smk_task; /* label of the task */
55 char *smk_mmap; /* label of the mmap domain */
55 struct mutex smk_lock; /* initialization lock */ 56 struct mutex smk_lock; /* initialization lock */
56 int smk_flags; /* smack inode flags */ 57 int smk_flags; /* smack inode flags */
57}; 58};
58 59
59struct task_smack { 60struct task_smack {
60 char *smk_task; /* label used for access control */ 61 char *smk_task; /* label for access control */
61 char *smk_forked; /* label when forked */ 62 char *smk_forked; /* label when forked */
63 struct list_head smk_rules; /* per task access rules */
64 struct mutex smk_rules_lock; /* lock for the rules */
62}; 65};
63 66
64#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ 67#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */
@@ -202,7 +205,7 @@ struct inode_smack *new_inode_smack(char *);
202/* 205/*
203 * These functions are in smack_access.c 206 * These functions are in smack_access.c
204 */ 207 */
205int smk_access_entry(char *, char *); 208int smk_access_entry(char *, char *, struct list_head *);
206int smk_access(char *, char *, int, struct smk_audit_info *); 209int smk_access(char *, char *, int, struct smk_audit_info *);
207int smk_curacc(char *, u32, struct smk_audit_info *); 210int smk_curacc(char *, u32, struct smk_audit_info *);
208int smack_to_cipso(const char *, struct smack_cipso *); 211int smack_to_cipso(const char *, struct smack_cipso *);
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 7ba8478f599e..86453db4333d 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -70,10 +70,11 @@ int log_policy = SMACK_AUDIT_DENIED;
70 * smk_access_entry - look up matching access rule 70 * smk_access_entry - look up matching access rule
71 * @subject_label: a pointer to the subject's Smack label 71 * @subject_label: a pointer to the subject's Smack label
72 * @object_label: a pointer to the object's Smack label 72 * @object_label: a pointer to the object's Smack label
73 * @rule_list: the list of rules to search
73 * 74 *
74 * This function looks up the subject/object pair in the 75 * This function looks up the subject/object pair in the
75 * access rule list and returns pointer to the matching rule if found, 76 * access rule list and returns the access mode. If no
76 * NULL otherwise. 77 * entry is found returns -ENOENT.
77 * 78 *
78 * NOTE: 79 * NOTE:
79 * Even though Smack labels are usually shared on smack_list 80 * Even though Smack labels are usually shared on smack_list
@@ -85,13 +86,13 @@ int log_policy = SMACK_AUDIT_DENIED;
85 * will be on the list, so checking the pointers may be a worthwhile 86 * will be on the list, so checking the pointers may be a worthwhile
86 * optimization. 87 * optimization.
87 */ 88 */
88int smk_access_entry(char *subject_label, char *object_label) 89int smk_access_entry(char *subject_label, char *object_label,
90 struct list_head *rule_list)
89{ 91{
90 u32 may = MAY_NOT; 92 int may = -ENOENT;
91 struct smack_rule *srp; 93 struct smack_rule *srp;
92 94
93 rcu_read_lock(); 95 list_for_each_entry_rcu(srp, rule_list, list) {
94 list_for_each_entry_rcu(srp, &smack_rule_list, list) {
95 if (srp->smk_subject == subject_label || 96 if (srp->smk_subject == subject_label ||
96 strcmp(srp->smk_subject, subject_label) == 0) { 97 strcmp(srp->smk_subject, subject_label) == 0) {
97 if (srp->smk_object == object_label || 98 if (srp->smk_object == object_label ||
@@ -101,7 +102,6 @@ int smk_access_entry(char *subject_label, char *object_label)
101 } 102 }
102 } 103 }
103 } 104 }
104 rcu_read_unlock();
105 105
106 return may; 106 return may;
107} 107}
@@ -129,7 +129,7 @@ int smk_access_entry(char *subject_label, char *object_label)
129int smk_access(char *subject_label, char *object_label, int request, 129int smk_access(char *subject_label, char *object_label, int request,
130 struct smk_audit_info *a) 130 struct smk_audit_info *a)
131{ 131{
132 u32 may = MAY_NOT; 132 int may = MAY_NOT;
133 int rc = 0; 133 int rc = 0;
134 134
135 /* 135 /*
@@ -181,13 +181,14 @@ int smk_access(char *subject_label, char *object_label, int request,
181 * Beyond here an explicit relationship is required. 181 * Beyond here an explicit relationship is required.
182 * If the requested access is contained in the available 182 * If the requested access is contained in the available
183 * access (e.g. read is included in readwrite) it's 183 * access (e.g. read is included in readwrite) it's
184 * good. 184 * good. A negative response from smk_access_entry()
185 */ 185 * indicates there is no entry for this pair.
186 may = smk_access_entry(subject_label, object_label);
187 /*
188 * This is a bit map operation.
189 */ 186 */
190 if ((request & may) == request) 187 rcu_read_lock();
188 may = smk_access_entry(subject_label, object_label, &smack_rule_list);
189 rcu_read_unlock();
190
191 if (may > 0 && (request & may) == request)
191 goto out_audit; 192 goto out_audit;
192 193
193 rc = -EACCES; 194 rc = -EACCES;
@@ -212,12 +213,27 @@ out_audit:
212 */ 213 */
213int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) 214int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
214{ 215{
216 struct task_smack *tsp = current_security();
217 char *sp = smk_of_task(tsp);
218 int may;
215 int rc; 219 int rc;
216 char *sp = smk_of_current();
217 220
221 /*
222 * Check the global rule list
223 */
218 rc = smk_access(sp, obj_label, mode, NULL); 224 rc = smk_access(sp, obj_label, mode, NULL);
219 if (rc == 0) 225 if (rc == 0) {
220 goto out_audit; 226 /*
227 * If there is an entry in the task's rule list
228 * it can further restrict access.
229 */
230 may = smk_access_entry(sp, obj_label, &tsp->smk_rules);
231 if (may < 0)
232 goto out_audit;
233 if ((mode & may) == mode)
234 goto out_audit;
235 rc = -EACCES;
236 }
221 237
222 /* 238 /*
223 * Return if a specific label has been designated as the 239 * Return if a specific label has been designated as the
@@ -228,7 +244,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
228 goto out_audit; 244 goto out_audit;
229 245
230 if (capable(CAP_MAC_OVERRIDE)) 246 if (capable(CAP_MAC_OVERRIDE))
231 return 0; 247 rc = 0;
232 248
233out_audit: 249out_audit:
234#ifdef CONFIG_AUDIT 250#ifdef CONFIG_AUDIT
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 533bf3255d7f..123a499ded37 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -84,6 +84,56 @@ struct inode_smack *new_inode_smack(char *smack)
84 return isp; 84 return isp;
85} 85}
86 86
87/**
88 * new_task_smack - allocate a task security blob
89 * @smack: a pointer to the Smack label to use in the blob
90 *
91 * Returns the new blob or NULL if there's no memory available
92 */
93static struct task_smack *new_task_smack(char *task, char *forked, gfp_t gfp)
94{
95 struct task_smack *tsp;
96
97 tsp = kzalloc(sizeof(struct task_smack), gfp);
98 if (tsp == NULL)
99 return NULL;
100
101 tsp->smk_task = task;
102 tsp->smk_forked = forked;
103 INIT_LIST_HEAD(&tsp->smk_rules);
104 mutex_init(&tsp->smk_rules_lock);
105
106 return tsp;
107}
108
109/**
110 * smk_copy_rules - copy a rule set
111 * @nhead - new rules header pointer
112 * @ohead - old rules header pointer
113 *
114 * Returns 0 on success, -ENOMEM on error
115 */
116static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead,
117 gfp_t gfp)
118{
119 struct smack_rule *nrp;
120 struct smack_rule *orp;
121 int rc = 0;
122
123 INIT_LIST_HEAD(nhead);
124
125 list_for_each_entry_rcu(orp, ohead, list) {
126 nrp = kzalloc(sizeof(struct smack_rule), gfp);
127 if (nrp == NULL) {
128 rc = -ENOMEM;
129 break;
130 }
131 *nrp = *orp;
132 list_add_rcu(&nrp->list, nhead);
133 }
134 return rc;
135}
136
87/* 137/*
88 * LSM hooks. 138 * LSM hooks.
89 * We he, that is fun! 139 * We he, that is fun!
@@ -102,23 +152,17 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
102{ 152{
103 int rc; 153 int rc;
104 struct smk_audit_info ad; 154 struct smk_audit_info ad;
105 char *sp, *tsp; 155 char *tsp;
106 156
107 rc = cap_ptrace_access_check(ctp, mode); 157 rc = cap_ptrace_access_check(ctp, mode);
108 if (rc != 0) 158 if (rc != 0)
109 return rc; 159 return rc;
110 160
111 sp = smk_of_current();
112 tsp = smk_of_task(task_security(ctp)); 161 tsp = smk_of_task(task_security(ctp));
113 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); 162 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
114 smk_ad_setfield_u_tsk(&ad, ctp); 163 smk_ad_setfield_u_tsk(&ad, ctp);
115 164
116 /* we won't log here, because rc can be overriden */ 165 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; 166 return rc;
123} 167}
124 168
@@ -134,23 +178,17 @@ static int smack_ptrace_traceme(struct task_struct *ptp)
134{ 178{
135 int rc; 179 int rc;
136 struct smk_audit_info ad; 180 struct smk_audit_info ad;
137 char *sp, *tsp; 181 char *tsp;
138 182
139 rc = cap_ptrace_traceme(ptp); 183 rc = cap_ptrace_traceme(ptp);
140 if (rc != 0) 184 if (rc != 0)
141 return rc; 185 return rc;
142 186
187 tsp = smk_of_task(task_security(ptp));
143 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); 188 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
144 smk_ad_setfield_u_tsk(&ad, ptp); 189 smk_ad_setfield_u_tsk(&ad, ptp);
145 190
146 sp = smk_of_current(); 191 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; 192 return rc;
155} 193}
156 194
@@ -474,7 +512,7 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
474{ 512{
475 char *isp = smk_of_inode(inode); 513 char *isp = smk_of_inode(inode);
476 char *dsp = smk_of_inode(dir); 514 char *dsp = smk_of_inode(dir);
477 u32 may; 515 int may;
478 516
479 if (name) { 517 if (name) {
480 *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); 518 *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL);
@@ -483,14 +521,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
483 } 521 }
484 522
485 if (value) { 523 if (value) {
486 may = smk_access_entry(smk_of_current(), dsp); 524 rcu_read_lock();
525 may = smk_access_entry(smk_of_current(), dsp, &smack_rule_list);
526 rcu_read_unlock();
487 527
488 /* 528 /*
489 * If the access rule allows transmutation and 529 * If the access rule allows transmutation and
490 * the directory requests transmutation then 530 * the directory requests transmutation then
491 * by all means transmute. 531 * by all means transmute.
492 */ 532 */
493 if (((may & MAY_TRANSMUTE) != 0) && smk_inode_transmutable(dir)) 533 if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
534 smk_inode_transmutable(dir))
494 isp = dsp; 535 isp = dsp;
495 536
496 *value = kstrdup(isp, GFP_KERNEL); 537 *value = kstrdup(isp, GFP_KERNEL);
@@ -716,7 +757,8 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
716 if (strcmp(name, XATTR_NAME_SMACK) == 0 || 757 if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
717 strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || 758 strcmp(name, XATTR_NAME_SMACKIPIN) == 0 ||
718 strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || 759 strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
719 strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { 760 strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
761 strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
720 if (!capable(CAP_MAC_ADMIN)) 762 if (!capable(CAP_MAC_ADMIN))
721 rc = -EPERM; 763 rc = -EPERM;
722 /* 764 /*
@@ -773,6 +815,12 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
773 isp->smk_task = nsp; 815 isp->smk_task = nsp;
774 else 816 else
775 isp->smk_task = smack_known_invalid.smk_known; 817 isp->smk_task = smack_known_invalid.smk_known;
818 } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
819 nsp = smk_import(value, size);
820 if (nsp != NULL)
821 isp->smk_mmap = nsp;
822 else
823 isp->smk_mmap = smack_known_invalid.smk_known;
776 } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) 824 } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0)
777 isp->smk_flags |= SMK_INODE_TRANSMUTE; 825 isp->smk_flags |= SMK_INODE_TRANSMUTE;
778 826
@@ -815,7 +863,8 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
815 strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || 863 strcmp(name, XATTR_NAME_SMACKIPIN) == 0 ||
816 strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || 864 strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
817 strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || 865 strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
818 strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { 866 strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 ||
867 strcmp(name, XATTR_NAME_SMACKMMAP)) {
819 if (!capable(CAP_MAC_ADMIN)) 868 if (!capable(CAP_MAC_ADMIN))
820 rc = -EPERM; 869 rc = -EPERM;
821 } else 870 } else
@@ -829,6 +878,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
829 if (rc == 0) { 878 if (rc == 0) {
830 isp = dentry->d_inode->i_security; 879 isp = dentry->d_inode->i_security;
831 isp->smk_task = NULL; 880 isp->smk_task = NULL;
881 isp->smk_mmap = NULL;
832 } 882 }
833 883
834 return rc; 884 return rc;
@@ -1060,6 +1110,113 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
1060} 1110}
1061 1111
1062/** 1112/**
1113 * smk_mmap_list_check - the mmap check
1114 * @sub: subject label
1115 * @obj: object label
1116 * @access: access mode
1117 * @local: the task specific rule list
1118 *
1119 * Returns 0 if acces is permitted, -EACCES otherwise
1120 */
1121static int smk_mmap_list_check(char *sub, char *obj, int access,
1122 struct list_head *local)
1123{
1124 int may;
1125
1126 /*
1127 * If there is not a global rule that
1128 * allows access say no.
1129 */
1130 may = smk_access_entry(sub, obj, &smack_rule_list);
1131 if (may == -ENOENT || (may & access) != access)
1132 return -EACCES;
1133 /*
1134 * If there is a task local rule that
1135 * denies access say no.
1136 */
1137 may = smk_access_entry(sub, obj, local);
1138 if (may != -ENOENT && (may & access) != access)
1139 return -EACCES;
1140
1141 return 0;
1142}
1143
1144/**
1145 * smack_file_mmap :
1146 * Check permissions for a mmap operation. The @file may be NULL, e.g.
1147 * if mapping anonymous memory.
1148 * @file contains the file structure for file to map (may be NULL).
1149 * @reqprot contains the protection requested by the application.
1150 * @prot contains the protection that will be applied by the kernel.
1151 * @flags contains the operational flags.
1152 * Return 0 if permission is granted.
1153 */
1154static int smack_file_mmap(struct file *file,
1155 unsigned long reqprot, unsigned long prot,
1156 unsigned long flags, unsigned long addr,
1157 unsigned long addr_only)
1158{
1159 struct smack_rule *srp;
1160 struct task_smack *tsp;
1161 char *sp;
1162 char *msmack;
1163 struct inode_smack *isp;
1164 struct dentry *dp;
1165 int rc;
1166
1167 /* do DAC check on address space usage */
1168 rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
1169 if (rc || addr_only)
1170 return rc;
1171
1172 if (file == NULL || file->f_dentry == NULL)
1173 return 0;
1174
1175 dp = file->f_dentry;
1176
1177 if (dp->d_inode == NULL)
1178 return 0;
1179
1180 isp = dp->d_inode->i_security;
1181 if (isp->smk_mmap == NULL)
1182 return 0;
1183 msmack = isp->smk_mmap;
1184
1185 tsp = current_security();
1186 sp = smk_of_current();
1187 rc = 0;
1188
1189 rcu_read_lock();
1190 /*
1191 * For each Smack rule associated with the subject
1192 * label verify that the SMACK64MMAP also has access
1193 * to that rule's object label.
1194 *
1195 * Because neither of the labels comes
1196 * from the networking code it is sufficient
1197 * to compare pointers.
1198 */
1199 list_for_each_entry_rcu(srp, &smack_rule_list, list) {
1200 if (srp->smk_subject != sp)
1201 continue;
1202 /*
1203 * Matching labels always allows access.
1204 */
1205 if (msmack == srp->smk_object)
1206 continue;
1207
1208 rc = smk_mmap_list_check(msmack, srp->smk_object,
1209 srp->smk_access, &tsp->smk_rules);
1210 if (rc != 0)
1211 break;
1212 }
1213
1214 rcu_read_unlock();
1215
1216 return rc;
1217}
1218
1219/**
1063 * smack_file_set_fowner - set the file security blob value 1220 * smack_file_set_fowner - set the file security blob value
1064 * @file: object in question 1221 * @file: object in question
1065 * 1222 *
@@ -1095,6 +1252,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
1095 * struct fown_struct is never outside the context of a struct file 1252 * struct fown_struct is never outside the context of a struct file
1096 */ 1253 */
1097 file = container_of(fown, struct file, f_owner); 1254 file = container_of(fown, struct file, f_owner);
1255
1098 /* we don't log here as rc can be overriden */ 1256 /* we don't log here as rc can be overriden */
1099 rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL); 1257 rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL);
1100 if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) 1258 if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE))
@@ -1145,9 +1303,14 @@ static int smack_file_receive(struct file *file)
1145 */ 1303 */
1146static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) 1304static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp)
1147{ 1305{
1148 cred->security = kzalloc(sizeof(struct task_smack), gfp); 1306 struct task_smack *tsp;
1149 if (cred->security == NULL) 1307
1308 tsp = new_task_smack(NULL, NULL, gfp);
1309 if (tsp == NULL)
1150 return -ENOMEM; 1310 return -ENOMEM;
1311
1312 cred->security = tsp;
1313
1151 return 0; 1314 return 0;
1152} 1315}
1153 1316
@@ -1156,13 +1319,24 @@ static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp)
1156 * smack_cred_free - "free" task-level security credentials 1319 * smack_cred_free - "free" task-level security credentials
1157 * @cred: the credentials in question 1320 * @cred: the credentials in question
1158 * 1321 *
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 */ 1322 */
1163static void smack_cred_free(struct cred *cred) 1323static void smack_cred_free(struct cred *cred)
1164{ 1324{
1165 kfree(cred->security); 1325 struct task_smack *tsp = cred->security;
1326 struct smack_rule *rp;
1327 struct list_head *l;
1328 struct list_head *n;
1329
1330 if (tsp == NULL)
1331 return;
1332 cred->security = NULL;
1333
1334 list_for_each_safe(l, n, &tsp->smk_rules) {
1335 rp = list_entry(l, struct smack_rule, list);
1336 list_del(&rp->list);
1337 kfree(rp);
1338 }
1339 kfree(tsp);
1166} 1340}
1167 1341
1168/** 1342/**
@@ -1178,13 +1352,16 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old,
1178{ 1352{
1179 struct task_smack *old_tsp = old->security; 1353 struct task_smack *old_tsp = old->security;
1180 struct task_smack *new_tsp; 1354 struct task_smack *new_tsp;
1355 int rc;
1181 1356
1182 new_tsp = kzalloc(sizeof(struct task_smack), gfp); 1357 new_tsp = new_task_smack(old_tsp->smk_task, old_tsp->smk_task, gfp);
1183 if (new_tsp == NULL) 1358 if (new_tsp == NULL)
1184 return -ENOMEM; 1359 return -ENOMEM;
1185 1360
1186 new_tsp->smk_task = old_tsp->smk_task; 1361 rc = smk_copy_rules(&new_tsp->smk_rules, &old_tsp->smk_rules, gfp);
1187 new_tsp->smk_forked = old_tsp->smk_task; 1362 if (rc != 0)
1363 return rc;
1364
1188 new->security = new_tsp; 1365 new->security = new_tsp;
1189 return 0; 1366 return 0;
1190} 1367}
@@ -1203,6 +1380,11 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old)
1203 1380
1204 new_tsp->smk_task = old_tsp->smk_task; 1381 new_tsp->smk_task = old_tsp->smk_task;
1205 new_tsp->smk_forked = old_tsp->smk_task; 1382 new_tsp->smk_forked = old_tsp->smk_task;
1383 mutex_init(&new_tsp->smk_rules_lock);
1384 INIT_LIST_HEAD(&new_tsp->smk_rules);
1385
1386
1387 /* cbs copy rule list */
1206} 1388}
1207 1389
1208/** 1390/**
@@ -2419,6 +2601,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
2419 } 2601 }
2420 } 2602 }
2421 isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); 2603 isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp);
2604 isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp);
2422 2605
2423 dput(dp); 2606 dput(dp);
2424 break; 2607 break;
@@ -2478,6 +2661,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value)
2478static int smack_setprocattr(struct task_struct *p, char *name, 2661static int smack_setprocattr(struct task_struct *p, char *name,
2479 void *value, size_t size) 2662 void *value, size_t size)
2480{ 2663{
2664 int rc;
2481 struct task_smack *tsp; 2665 struct task_smack *tsp;
2482 struct task_smack *oldtsp; 2666 struct task_smack *oldtsp;
2483 struct cred *new; 2667 struct cred *new;
@@ -2513,13 +2697,16 @@ static int smack_setprocattr(struct task_struct *p, char *name,
2513 new = prepare_creds(); 2697 new = prepare_creds();
2514 if (new == NULL) 2698 if (new == NULL)
2515 return -ENOMEM; 2699 return -ENOMEM;
2516 tsp = kzalloc(sizeof(struct task_smack), GFP_KERNEL); 2700
2701 tsp = new_task_smack(newsmack, oldtsp->smk_forked, GFP_KERNEL);
2517 if (tsp == NULL) { 2702 if (tsp == NULL) {
2518 kfree(new); 2703 kfree(new);
2519 return -ENOMEM; 2704 return -ENOMEM;
2520 } 2705 }
2521 tsp->smk_task = newsmack; 2706 rc = smk_copy_rules(&tsp->smk_rules, &oldtsp->smk_rules, GFP_KERNEL);
2522 tsp->smk_forked = oldtsp->smk_forked; 2707 if (rc != 0)
2708 return rc;
2709
2523 new->security = tsp; 2710 new->security = tsp;
2524 commit_creds(new); 2711 commit_creds(new);
2525 return size; 2712 return size;
@@ -3221,6 +3408,7 @@ struct security_operations smack_ops = {
3221 .file_ioctl = smack_file_ioctl, 3408 .file_ioctl = smack_file_ioctl,
3222 .file_lock = smack_file_lock, 3409 .file_lock = smack_file_lock,
3223 .file_fcntl = smack_file_fcntl, 3410 .file_fcntl = smack_file_fcntl,
3411 .file_mmap = smack_file_mmap,
3224 .file_set_fowner = smack_file_set_fowner, 3412 .file_set_fowner = smack_file_set_fowner,
3225 .file_send_sigiotask = smack_file_send_sigiotask, 3413 .file_send_sigiotask = smack_file_send_sigiotask,
3226 .file_receive = smack_file_receive, 3414 .file_receive = smack_file_receive,
@@ -3334,23 +3522,20 @@ static __init int smack_init(void)
3334 struct cred *cred; 3522 struct cred *cred;
3335 struct task_smack *tsp; 3523 struct task_smack *tsp;
3336 3524
3337 tsp = kzalloc(sizeof(struct task_smack), GFP_KERNEL); 3525 if (!security_module_enable(&smack_ops))
3526 return 0;
3527
3528 tsp = new_task_smack(smack_known_floor.smk_known,
3529 smack_known_floor.smk_known, GFP_KERNEL);
3338 if (tsp == NULL) 3530 if (tsp == NULL)
3339 return -ENOMEM; 3531 return -ENOMEM;
3340 3532
3341 if (!security_module_enable(&smack_ops)) {
3342 kfree(tsp);
3343 return 0;
3344 }
3345
3346 printk(KERN_INFO "Smack: Initializing.\n"); 3533 printk(KERN_INFO "Smack: Initializing.\n");
3347 3534
3348 /* 3535 /*
3349 * Set the security state for the initial task. 3536 * Set the security state for the initial task.
3350 */ 3537 */
3351 cred = (struct cred *) current->cred; 3538 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; 3539 cred->security = tsp;
3355 3540
3356 /* initialize the smack_know_list */ 3541 /* initialize the smack_know_list */
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 362d5eda948b..90d1bbaaa6f3 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -43,6 +43,7 @@ enum smk_inos {
43 SMK_NETLBLADDR = 8, /* single label hosts */ 43 SMK_NETLBLADDR = 8, /* single label hosts */
44 SMK_ONLYCAP = 9, /* the only "capable" label */ 44 SMK_ONLYCAP = 9, /* the only "capable" label */
45 SMK_LOGGING = 10, /* logging */ 45 SMK_LOGGING = 10, /* logging */
46 SMK_LOAD_SELF = 11, /* task specific rules */
46}; 47};
47 48
48/* 49/*
@@ -135,104 +136,30 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap)
135#define SMK_NETLBLADDRMIN 9 136#define SMK_NETLBLADDRMIN 9
136#define SMK_NETLBLADDRMAX 42 137#define SMK_NETLBLADDRMAX 42
137 138
138/*
139 * Seq_file read operations for /smack/load
140 */
141
142static void *load_seq_start(struct seq_file *s, loff_t *pos)
143{
144 if (*pos == SEQ_READ_FINISHED)
145 return NULL;
146 if (list_empty(&smack_rule_list))
147 return NULL;
148 return smack_rule_list.next;
149}
150
151static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
152{
153 struct list_head *list = v;
154
155 if (list_is_last(list, &smack_rule_list)) {
156 *pos = SEQ_READ_FINISHED;
157 return NULL;
158 }
159 return list->next;
160}
161
162static int load_seq_show(struct seq_file *s, void *v)
163{
164 struct list_head *list = v;
165 struct smack_rule *srp =
166 list_entry(list, struct smack_rule, list);
167
168 seq_printf(s, "%s %s", (char *)srp->smk_subject,
169 (char *)srp->smk_object);
170
171 seq_putc(s, ' ');
172
173 if (srp->smk_access & MAY_READ)
174 seq_putc(s, 'r');
175 if (srp->smk_access & MAY_WRITE)
176 seq_putc(s, 'w');
177 if (srp->smk_access & MAY_EXEC)
178 seq_putc(s, 'x');
179 if (srp->smk_access & MAY_APPEND)
180 seq_putc(s, 'a');
181 if (srp->smk_access & MAY_TRANSMUTE)
182 seq_putc(s, 't');
183 if (srp->smk_access == 0)
184 seq_putc(s, '-');
185
186 seq_putc(s, '\n');
187
188 return 0;
189}
190
191static void load_seq_stop(struct seq_file *s, void *v)
192{
193 /* No-op */
194}
195
196static const struct seq_operations load_seq_ops = {
197 .start = load_seq_start,
198 .next = load_seq_next,
199 .show = load_seq_show,
200 .stop = load_seq_stop,
201};
202
203/**
204 * smk_open_load - open() for /smack/load
205 * @inode: inode structure representing file
206 * @file: "load" file pointer
207 *
208 * For reading, use load_seq_* seq_file reading operations.
209 */
210static int smk_open_load(struct inode *inode, struct file *file)
211{
212 return seq_open(file, &load_seq_ops);
213}
214
215/** 139/**
216 * smk_set_access - add a rule to the rule list 140 * smk_set_access - add a rule to the rule list
217 * @srp: the new rule to add 141 * @srp: the new rule to add
142 * @rule_list: the list of rules
143 * @rule_lock: the rule list lock
218 * 144 *
219 * Looks through the current subject/object/access list for 145 * Looks through the current subject/object/access list for
220 * the subject/object pair and replaces the access that was 146 * the subject/object pair and replaces the access that was
221 * there. If the pair isn't found add it with the specified 147 * there. If the pair isn't found add it with the specified
222 * access. 148 * access.
223 * 149 *
150 * Returns 1 if a rule was found to exist already, 0 if it is new
224 * Returns 0 if nothing goes wrong or -ENOMEM if it fails 151 * Returns 0 if nothing goes wrong or -ENOMEM if it fails
225 * during the allocation of the new pair to add. 152 * during the allocation of the new pair to add.
226 */ 153 */
227static int smk_set_access(struct smack_rule *srp) 154static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
155 struct mutex *rule_lock)
228{ 156{
229 struct smack_rule *sp; 157 struct smack_rule *sp;
230 int ret = 0; 158 int found = 0;
231 int found;
232 mutex_lock(&smack_list_lock);
233 159
234 found = 0; 160 mutex_lock(rule_lock);
235 list_for_each_entry_rcu(sp, &smack_rule_list, list) { 161
162 list_for_each_entry_rcu(sp, rule_list, list) {
236 if (sp->smk_subject == srp->smk_subject && 163 if (sp->smk_subject == srp->smk_subject &&
237 sp->smk_object == srp->smk_object) { 164 sp->smk_object == srp->smk_object) {
238 found = 1; 165 found = 1;
@@ -241,19 +168,21 @@ static int smk_set_access(struct smack_rule *srp)
241 } 168 }
242 } 169 }
243 if (found == 0) 170 if (found == 0)
244 list_add_rcu(&srp->list, &smack_rule_list); 171 list_add_rcu(&srp->list, rule_list);
245 172
246 mutex_unlock(&smack_list_lock); 173 mutex_unlock(rule_lock);
247 174
248 return ret; 175 return found;
249} 176}
250 177
251/** 178/**
252 * smk_write_load - write() for /smack/load 179 * smk_write_load_list - write() for any /smack/load
253 * @file: file pointer, not actually used 180 * @file: file pointer, not actually used
254 * @buf: where to get the data from 181 * @buf: where to get the data from
255 * @count: bytes sent 182 * @count: bytes sent
256 * @ppos: where to start - must be 0 183 * @ppos: where to start - must be 0
184 * @rule_list: the list of rules to write to
185 * @rule_lock: lock for the rule list
257 * 186 *
258 * Get one smack access rule from above. 187 * Get one smack access rule from above.
259 * The format is exactly: 188 * The format is exactly:
@@ -263,21 +192,19 @@ static int smk_set_access(struct smack_rule *srp)
263 * 192 *
264 * writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes. 193 * writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes.
265 */ 194 */
266static ssize_t smk_write_load(struct file *file, const char __user *buf, 195static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
267 size_t count, loff_t *ppos) 196 size_t count, loff_t *ppos,
197 struct list_head *rule_list,
198 struct mutex *rule_lock)
268{ 199{
269 struct smack_rule *rule; 200 struct smack_rule *rule;
270 char *data; 201 char *data;
271 int rc = -EINVAL; 202 int rc = -EINVAL;
272 203
273 /* 204 /*
274 * Must have privilege.
275 * No partial writes. 205 * No partial writes.
276 * Enough data must be present. 206 * Enough data must be present.
277 */ 207 */
278 if (!capable(CAP_MAC_ADMIN))
279 return -EPERM;
280
281 if (*ppos != 0) 208 if (*ppos != 0)
282 return -EINVAL; 209 return -EINVAL;
283 /* 210 /*
@@ -372,11 +299,13 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
372 goto out_free_rule; 299 goto out_free_rule;
373 } 300 }
374 301
375 rc = smk_set_access(rule); 302 rc = count;
376 303 /*
377 if (!rc) 304 * smk_set_access returns true if there was already a rule
378 rc = count; 305 * for the subject/object pair, and false if it was new.
379 goto out; 306 */
307 if (!smk_set_access(rule, rule_list, rule_lock))
308 goto out;
380 309
381out_free_rule: 310out_free_rule:
382 kfree(rule); 311 kfree(rule);
@@ -385,6 +314,108 @@ out:
385 return rc; 314 return rc;
386} 315}
387 316
317
318/*
319 * Seq_file read operations for /smack/load
320 */
321
322static void *load_seq_start(struct seq_file *s, loff_t *pos)
323{
324 if (*pos == SEQ_READ_FINISHED)
325 return NULL;
326 if (list_empty(&smack_rule_list))
327 return NULL;
328 return smack_rule_list.next;
329}
330
331static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
332{
333 struct list_head *list = v;
334
335 if (list_is_last(list, &smack_rule_list)) {
336 *pos = SEQ_READ_FINISHED;
337 return NULL;
338 }
339 return list->next;
340}
341
342static int load_seq_show(struct seq_file *s, void *v)
343{
344 struct list_head *list = v;
345 struct smack_rule *srp =
346 list_entry(list, struct smack_rule, list);
347
348 seq_printf(s, "%s %s", (char *)srp->smk_subject,
349 (char *)srp->smk_object);
350
351 seq_putc(s, ' ');
352
353 if (srp->smk_access & MAY_READ)
354 seq_putc(s, 'r');
355 if (srp->smk_access & MAY_WRITE)
356 seq_putc(s, 'w');
357 if (srp->smk_access & MAY_EXEC)
358 seq_putc(s, 'x');
359 if (srp->smk_access & MAY_APPEND)
360 seq_putc(s, 'a');
361 if (srp->smk_access & MAY_TRANSMUTE)
362 seq_putc(s, 't');
363 if (srp->smk_access == 0)
364 seq_putc(s, '-');
365
366 seq_putc(s, '\n');
367
368 return 0;
369}
370
371static void load_seq_stop(struct seq_file *s, void *v)
372{
373 /* No-op */
374}
375
376static const struct seq_operations load_seq_ops = {
377 .start = load_seq_start,
378 .next = load_seq_next,
379 .show = load_seq_show,
380 .stop = load_seq_stop,
381};
382
383/**
384 * smk_open_load - open() for /smack/load
385 * @inode: inode structure representing file
386 * @file: "load" file pointer
387 *
388 * For reading, use load_seq_* seq_file reading operations.
389 */
390static int smk_open_load(struct inode *inode, struct file *file)
391{
392 return seq_open(file, &load_seq_ops);
393}
394
395/**
396 * smk_write_load - write() for /smack/load
397 * @file: file pointer, not actually used
398 * @buf: where to get the data from
399 * @count: bytes sent
400 * @ppos: where to start - must be 0
401 *
402 */
403static ssize_t smk_write_load(struct file *file, const char __user *buf,
404 size_t count, loff_t *ppos)
405{
406
407 /*
408 * Must have privilege.
409 * No partial writes.
410 * Enough data must be present.
411 */
412 if (!capable(CAP_MAC_ADMIN))
413 return -EPERM;
414
415 return smk_write_load_list(file, buf, count, ppos, &smack_rule_list,
416 &smack_list_lock);
417}
418
388static const struct file_operations smk_load_ops = { 419static const struct file_operations smk_load_ops = {
389 .open = smk_open_load, 420 .open = smk_open_load,
390 .read = seq_read, 421 .read = seq_read,
@@ -1288,6 +1319,112 @@ static const struct file_operations smk_logging_ops = {
1288 .write = smk_write_logging, 1319 .write = smk_write_logging,
1289 .llseek = default_llseek, 1320 .llseek = default_llseek,
1290}; 1321};
1322
1323/*
1324 * Seq_file read operations for /smack/load-self
1325 */
1326
1327static void *load_self_seq_start(struct seq_file *s, loff_t *pos)
1328{
1329 struct task_smack *tsp = current_security();
1330
1331 if (*pos == SEQ_READ_FINISHED)
1332 return NULL;
1333 if (list_empty(&tsp->smk_rules))
1334 return NULL;
1335 return tsp->smk_rules.next;
1336}
1337
1338static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos)
1339{
1340 struct task_smack *tsp = current_security();
1341 struct list_head *list = v;
1342
1343 if (list_is_last(list, &tsp->smk_rules)) {
1344 *pos = SEQ_READ_FINISHED;
1345 return NULL;
1346 }
1347 return list->next;
1348}
1349
1350static int load_self_seq_show(struct seq_file *s, void *v)
1351{
1352 struct list_head *list = v;
1353 struct smack_rule *srp =
1354 list_entry(list, struct smack_rule, list);
1355
1356 seq_printf(s, "%s %s", (char *)srp->smk_subject,
1357 (char *)srp->smk_object);
1358
1359 seq_putc(s, ' ');
1360
1361 if (srp->smk_access & MAY_READ)
1362 seq_putc(s, 'r');
1363 if (srp->smk_access & MAY_WRITE)
1364 seq_putc(s, 'w');
1365 if (srp->smk_access & MAY_EXEC)
1366 seq_putc(s, 'x');
1367 if (srp->smk_access & MAY_APPEND)
1368 seq_putc(s, 'a');
1369 if (srp->smk_access & MAY_TRANSMUTE)
1370 seq_putc(s, 't');
1371 if (srp->smk_access == 0)
1372 seq_putc(s, '-');
1373
1374 seq_putc(s, '\n');
1375
1376 return 0;
1377}
1378
1379static void load_self_seq_stop(struct seq_file *s, void *v)
1380{
1381 /* No-op */
1382}
1383
1384static const struct seq_operations load_self_seq_ops = {
1385 .start = load_self_seq_start,
1386 .next = load_self_seq_next,
1387 .show = load_self_seq_show,
1388 .stop = load_self_seq_stop,
1389};
1390
1391
1392/**
1393 * smk_open_load_self - open() for /smack/load-self
1394 * @inode: inode structure representing file
1395 * @file: "load" file pointer
1396 *
1397 * For reading, use load_seq_* seq_file reading operations.
1398 */
1399static int smk_open_load_self(struct inode *inode, struct file *file)
1400{
1401 return seq_open(file, &load_self_seq_ops);
1402}
1403
1404/**
1405 * smk_write_load_self - write() for /smack/load-self
1406 * @file: file pointer, not actually used
1407 * @buf: where to get the data from
1408 * @count: bytes sent
1409 * @ppos: where to start - must be 0
1410 *
1411 */
1412static ssize_t smk_write_load_self(struct file *file, const char __user *buf,
1413 size_t count, loff_t *ppos)
1414{
1415 struct task_smack *tsp = current_security();
1416
1417 return smk_write_load_list(file, buf, count, ppos, &tsp->smk_rules,
1418 &tsp->smk_rules_lock);
1419}
1420
1421static const struct file_operations smk_load_self_ops = {
1422 .open = smk_open_load_self,
1423 .read = seq_read,
1424 .llseek = seq_lseek,
1425 .write = smk_write_load_self,
1426 .release = seq_release,
1427};
1291/** 1428/**
1292 * smk_fill_super - fill the /smackfs superblock 1429 * smk_fill_super - fill the /smackfs superblock
1293 * @sb: the empty superblock 1430 * @sb: the empty superblock
@@ -1304,23 +1441,26 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
1304 struct inode *root_inode; 1441 struct inode *root_inode;
1305 1442
1306 static struct tree_descr smack_files[] = { 1443 static struct tree_descr smack_files[] = {
1307 [SMK_LOAD] = 1444 [SMK_LOAD] = {
1308 {"load", &smk_load_ops, S_IRUGO|S_IWUSR}, 1445 "load", &smk_load_ops, S_IRUGO|S_IWUSR},
1309 [SMK_CIPSO] = 1446 [SMK_CIPSO] = {
1310 {"cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR}, 1447 "cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR},
1311 [SMK_DOI] = 1448 [SMK_DOI] = {
1312 {"doi", &smk_doi_ops, S_IRUGO|S_IWUSR}, 1449 "doi", &smk_doi_ops, S_IRUGO|S_IWUSR},
1313 [SMK_DIRECT] = 1450 [SMK_DIRECT] = {
1314 {"direct", &smk_direct_ops, S_IRUGO|S_IWUSR}, 1451 "direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
1315 [SMK_AMBIENT] = 1452 [SMK_AMBIENT] = {
1316 {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, 1453 "ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
1317 [SMK_NETLBLADDR] = 1454 [SMK_NETLBLADDR] = {
1318 {"netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR}, 1455 "netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR},
1319 [SMK_ONLYCAP] = 1456 [SMK_ONLYCAP] = {
1320 {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR}, 1457 "onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
1321 [SMK_LOGGING] = 1458 [SMK_LOGGING] = {
1322 {"logging", &smk_logging_ops, S_IRUGO|S_IWUSR}, 1459 "logging", &smk_logging_ops, S_IRUGO|S_IWUSR},
1323 /* last one */ {""} 1460 [SMK_LOAD_SELF] = {
1461 "load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO},
1462 /* last one */
1463 {""}
1324 }; 1464 };
1325 1465
1326 rc = simple_fill_super(sb, SMACK_MAGIC, smack_files); 1466 rc = simple_fill_super(sb, SMACK_MAGIC, smack_files);