diff options
author | Casey Schaufler <casey@schaufler-ca.com> | 2011-11-10 18:02:22 -0500 |
---|---|---|
committer | Casey Schaufler <cschaufler@cschaufler-intel.(none)> | 2011-11-11 14:07:21 -0500 |
commit | 40809565ca57a8e94bae20b22da014c44ec233f6 (patch) | |
tree | 6cad3fa8f6345934cf6c67552235869973524d21 /security/smack | |
parent | 0e94ae17c857b3835a2b8ea46ce44b5da4e2cc5d (diff) |
Smack: smackfs cipso seq read repair
Commit 272cd7a8c67dd40a31ecff76a503bbb84707f757 introduced
a change to the way rule lists are handled and reported in
the smackfs filesystem. One of the issues addressed had to
do with the termination of read requests on /smack/load.
This change introduced a error in /smack/cipso, which shares
some of the same list processing code.
This patch updates all the file access list handling in
smackfs to use the code introduced for /smack/load.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Diffstat (limited to 'security/smack')
-rw-r--r-- | security/smack/smackfs.c | 115 |
1 files changed, 39 insertions, 76 deletions
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 6aceef518a41..5c32f36ff706 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
@@ -102,9 +102,6 @@ static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; | |||
102 | 102 | ||
103 | const char *smack_cipso_option = SMACK_CIPSO_OPTION; | 103 | const char *smack_cipso_option = SMACK_CIPSO_OPTION; |
104 | 104 | ||
105 | |||
106 | #define SEQ_READ_FINISHED ((loff_t)-1) | ||
107 | |||
108 | /* | 105 | /* |
109 | * Values for parsing cipso rules | 106 | * Values for parsing cipso rules |
110 | * SMK_DIGITLEN: Length of a digit field in a rule. | 107 | * SMK_DIGITLEN: Length of a digit field in a rule. |
@@ -357,10 +354,12 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf, | |||
357 | 354 | ||
358 | rc = count; | 355 | rc = count; |
359 | /* | 356 | /* |
357 | * If this is "load" as opposed to "load-self" and a new rule | ||
358 | * it needs to get added for reporting. | ||
360 | * smk_set_access returns true if there was already a rule | 359 | * smk_set_access returns true if there was already a rule |
361 | * for the subject/object pair, and false if it was new. | 360 | * for the subject/object pair, and false if it was new. |
362 | */ | 361 | */ |
363 | if (!smk_set_access(rule, rule_list, rule_lock)) { | 362 | if (load && !smk_set_access(rule, rule_list, rule_lock)) { |
364 | smlp = kzalloc(sizeof(*smlp), GFP_KERNEL); | 363 | smlp = kzalloc(sizeof(*smlp), GFP_KERNEL); |
365 | if (smlp != NULL) { | 364 | if (smlp != NULL) { |
366 | smlp->smk_rule = rule; | 365 | smlp->smk_rule = rule; |
@@ -377,12 +376,12 @@ out: | |||
377 | return rc; | 376 | return rc; |
378 | } | 377 | } |
379 | 378 | ||
380 | |||
381 | /* | 379 | /* |
382 | * Seq_file read operations for /smack/load | 380 | * Core logic for smackfs seq list operations. |
383 | */ | 381 | */ |
384 | 382 | ||
385 | static void *load_seq_start(struct seq_file *s, loff_t *pos) | 383 | static void *smk_seq_start(struct seq_file *s, loff_t *pos, |
384 | struct list_head *head) | ||
386 | { | 385 | { |
387 | struct list_head *list; | 386 | struct list_head *list; |
388 | 387 | ||
@@ -390,7 +389,7 @@ static void *load_seq_start(struct seq_file *s, loff_t *pos) | |||
390 | * This is 0 the first time through. | 389 | * This is 0 the first time through. |
391 | */ | 390 | */ |
392 | if (s->index == 0) | 391 | if (s->index == 0) |
393 | s->private = &smack_rule_list; | 392 | s->private = head; |
394 | 393 | ||
395 | if (s->private == NULL) | 394 | if (s->private == NULL) |
396 | return NULL; | 395 | return NULL; |
@@ -404,11 +403,12 @@ static void *load_seq_start(struct seq_file *s, loff_t *pos) | |||
404 | return list; | 403 | return list; |
405 | } | 404 | } |
406 | 405 | ||
407 | static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos) | 406 | static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos, |
407 | struct list_head *head) | ||
408 | { | 408 | { |
409 | struct list_head *list = v; | 409 | struct list_head *list = v; |
410 | 410 | ||
411 | if (list_is_last(list, &smack_rule_list)) { | 411 | if (list_is_last(list, head)) { |
412 | s->private = NULL; | 412 | s->private = NULL; |
413 | return NULL; | 413 | return NULL; |
414 | } | 414 | } |
@@ -416,6 +416,25 @@ static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos) | |||
416 | return list->next; | 416 | return list->next; |
417 | } | 417 | } |
418 | 418 | ||
419 | static void smk_seq_stop(struct seq_file *s, void *v) | ||
420 | { | ||
421 | /* No-op */ | ||
422 | } | ||
423 | |||
424 | /* | ||
425 | * Seq_file read operations for /smack/load | ||
426 | */ | ||
427 | |||
428 | static void *load_seq_start(struct seq_file *s, loff_t *pos) | ||
429 | { | ||
430 | return smk_seq_start(s, pos, &smack_rule_list); | ||
431 | } | ||
432 | |||
433 | static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos) | ||
434 | { | ||
435 | return smk_seq_next(s, v, pos, &smack_rule_list); | ||
436 | } | ||
437 | |||
419 | static int load_seq_show(struct seq_file *s, void *v) | 438 | static int load_seq_show(struct seq_file *s, void *v) |
420 | { | 439 | { |
421 | struct list_head *list = v; | 440 | struct list_head *list = v; |
@@ -446,16 +465,11 @@ static int load_seq_show(struct seq_file *s, void *v) | |||
446 | return 0; | 465 | return 0; |
447 | } | 466 | } |
448 | 467 | ||
449 | static void load_seq_stop(struct seq_file *s, void *v) | ||
450 | { | ||
451 | /* No-op */ | ||
452 | } | ||
453 | |||
454 | static const struct seq_operations load_seq_ops = { | 468 | static const struct seq_operations load_seq_ops = { |
455 | .start = load_seq_start, | 469 | .start = load_seq_start, |
456 | .next = load_seq_next, | 470 | .next = load_seq_next, |
457 | .show = load_seq_show, | 471 | .show = load_seq_show, |
458 | .stop = load_seq_stop, | 472 | .stop = smk_seq_stop, |
459 | }; | 473 | }; |
460 | 474 | ||
461 | /** | 475 | /** |
@@ -574,28 +588,12 @@ static void smk_unlbl_ambient(char *oldambient) | |||
574 | 588 | ||
575 | static void *cipso_seq_start(struct seq_file *s, loff_t *pos) | 589 | static void *cipso_seq_start(struct seq_file *s, loff_t *pos) |
576 | { | 590 | { |
577 | if (*pos == SEQ_READ_FINISHED) | 591 | return smk_seq_start(s, pos, &smack_known_list); |
578 | return NULL; | ||
579 | if (list_empty(&smack_known_list)) | ||
580 | return NULL; | ||
581 | |||
582 | return smack_known_list.next; | ||
583 | } | 592 | } |
584 | 593 | ||
585 | static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos) | 594 | static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos) |
586 | { | 595 | { |
587 | struct list_head *list = v; | 596 | return smk_seq_next(s, v, pos, &smack_known_list); |
588 | |||
589 | /* | ||
590 | * labels with no associated cipso value wont be printed | ||
591 | * in cipso_seq_show | ||
592 | */ | ||
593 | if (list_is_last(list, &smack_known_list)) { | ||
594 | *pos = SEQ_READ_FINISHED; | ||
595 | return NULL; | ||
596 | } | ||
597 | |||
598 | return list->next; | ||
599 | } | 597 | } |
600 | 598 | ||
601 | /* | 599 | /* |
@@ -634,16 +632,11 @@ static int cipso_seq_show(struct seq_file *s, void *v) | |||
634 | return 0; | 632 | return 0; |
635 | } | 633 | } |
636 | 634 | ||
637 | static void cipso_seq_stop(struct seq_file *s, void *v) | ||
638 | { | ||
639 | /* No-op */ | ||
640 | } | ||
641 | |||
642 | static const struct seq_operations cipso_seq_ops = { | 635 | static const struct seq_operations cipso_seq_ops = { |
643 | .start = cipso_seq_start, | 636 | .start = cipso_seq_start, |
644 | .stop = cipso_seq_stop, | ||
645 | .next = cipso_seq_next, | 637 | .next = cipso_seq_next, |
646 | .show = cipso_seq_show, | 638 | .show = cipso_seq_show, |
639 | .stop = smk_seq_stop, | ||
647 | }; | 640 | }; |
648 | 641 | ||
649 | /** | 642 | /** |
@@ -788,23 +781,12 @@ static const struct file_operations smk_cipso_ops = { | |||
788 | 781 | ||
789 | static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos) | 782 | static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos) |
790 | { | 783 | { |
791 | if (*pos == SEQ_READ_FINISHED) | 784 | return smk_seq_start(s, pos, &smk_netlbladdr_list); |
792 | return NULL; | ||
793 | if (list_empty(&smk_netlbladdr_list)) | ||
794 | return NULL; | ||
795 | return smk_netlbladdr_list.next; | ||
796 | } | 785 | } |
797 | 786 | ||
798 | static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos) | 787 | static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos) |
799 | { | 788 | { |
800 | struct list_head *list = v; | 789 | return smk_seq_next(s, v, pos, &smk_netlbladdr_list); |
801 | |||
802 | if (list_is_last(list, &smk_netlbladdr_list)) { | ||
803 | *pos = SEQ_READ_FINISHED; | ||
804 | return NULL; | ||
805 | } | ||
806 | |||
807 | return list->next; | ||
808 | } | 790 | } |
809 | #define BEBITS (sizeof(__be32) * 8) | 791 | #define BEBITS (sizeof(__be32) * 8) |
810 | 792 | ||
@@ -828,16 +810,11 @@ static int netlbladdr_seq_show(struct seq_file *s, void *v) | |||
828 | return 0; | 810 | return 0; |
829 | } | 811 | } |
830 | 812 | ||
831 | static void netlbladdr_seq_stop(struct seq_file *s, void *v) | ||
832 | { | ||
833 | /* No-op */ | ||
834 | } | ||
835 | |||
836 | static const struct seq_operations netlbladdr_seq_ops = { | 813 | static const struct seq_operations netlbladdr_seq_ops = { |
837 | .start = netlbladdr_seq_start, | 814 | .start = netlbladdr_seq_start, |
838 | .stop = netlbladdr_seq_stop, | ||
839 | .next = netlbladdr_seq_next, | 815 | .next = netlbladdr_seq_next, |
840 | .show = netlbladdr_seq_show, | 816 | .show = netlbladdr_seq_show, |
817 | .stop = smk_seq_stop, | ||
841 | }; | 818 | }; |
842 | 819 | ||
843 | /** | 820 | /** |
@@ -1405,23 +1382,14 @@ static void *load_self_seq_start(struct seq_file *s, loff_t *pos) | |||
1405 | { | 1382 | { |
1406 | struct task_smack *tsp = current_security(); | 1383 | struct task_smack *tsp = current_security(); |
1407 | 1384 | ||
1408 | if (*pos == SEQ_READ_FINISHED) | 1385 | return smk_seq_start(s, pos, &tsp->smk_rules); |
1409 | return NULL; | ||
1410 | if (list_empty(&tsp->smk_rules)) | ||
1411 | return NULL; | ||
1412 | return tsp->smk_rules.next; | ||
1413 | } | 1386 | } |
1414 | 1387 | ||
1415 | static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos) | 1388 | static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos) |
1416 | { | 1389 | { |
1417 | struct task_smack *tsp = current_security(); | 1390 | struct task_smack *tsp = current_security(); |
1418 | struct list_head *list = v; | ||
1419 | 1391 | ||
1420 | if (list_is_last(list, &tsp->smk_rules)) { | 1392 | return smk_seq_next(s, v, pos, &tsp->smk_rules); |
1421 | *pos = SEQ_READ_FINISHED; | ||
1422 | return NULL; | ||
1423 | } | ||
1424 | return list->next; | ||
1425 | } | 1393 | } |
1426 | 1394 | ||
1427 | static int load_self_seq_show(struct seq_file *s, void *v) | 1395 | static int load_self_seq_show(struct seq_file *s, void *v) |
@@ -1453,16 +1421,11 @@ static int load_self_seq_show(struct seq_file *s, void *v) | |||
1453 | return 0; | 1421 | return 0; |
1454 | } | 1422 | } |
1455 | 1423 | ||
1456 | static void load_self_seq_stop(struct seq_file *s, void *v) | ||
1457 | { | ||
1458 | /* No-op */ | ||
1459 | } | ||
1460 | |||
1461 | static const struct seq_operations load_self_seq_ops = { | 1424 | static const struct seq_operations load_self_seq_ops = { |
1462 | .start = load_self_seq_start, | 1425 | .start = load_self_seq_start, |
1463 | .next = load_self_seq_next, | 1426 | .next = load_self_seq_next, |
1464 | .show = load_self_seq_show, | 1427 | .show = load_self_seq_show, |
1465 | .stop = load_self_seq_stop, | 1428 | .stop = smk_seq_stop, |
1466 | }; | 1429 | }; |
1467 | 1430 | ||
1468 | 1431 | ||