aboutsummaryrefslogtreecommitdiffstats
path: root/security/smack/smackfs.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-03-16 12:15:43 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-16 12:15:43 -0400
commit0f6e0e8448a16d8d22119ce91d8dd24b44865b51 (patch)
tree7c295c02db035fc6a0b867465911a2bc9dc6b1ef /security/smack/smackfs.c
parent0d2ecee2bdb2a19d04bc5cefac0f86e790f1aad4 (diff)
parenta002951c97ff8da49938c982a4c236bf2fafdc9f (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (33 commits) AppArmor: kill unused macros in lsm.c AppArmor: cleanup generated files correctly KEYS: Add an iovec version of KEYCTL_INSTANTIATE KEYS: Add a new keyctl op to reject a key with a specified error code KEYS: Add a key type op to permit the key description to be vetted KEYS: Add an RCU payload dereference macro AppArmor: Cleanup make file to remove cruft and make it easier to read SELinux: implement the new sb_remount LSM hook LSM: Pass -o remount options to the LSM SELinux: Compute SID for the newly created socket SELinux: Socket retains creator role and MLS attribute SELinux: Auto-generate security_is_socket_class TOMOYO: Fix memory leak upon file open. Revert "selinux: simplify ioctl checking" selinux: drop unused packet flow permissions selinux: Fix packet forwarding checks on postrouting selinux: Fix wrong checks for selinux_policycap_netpeer selinux: Fix check for xfrm selinux context algorithm ima: remove unnecessary call to ima_must_measure IMA: remove IMA imbalance checking ...
Diffstat (limited to 'security/smack/smackfs.c')
-rw-r--r--security/smack/smackfs.c370
1 files changed, 255 insertions, 115 deletions
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);