diff options
author | Eric Paris <eparis@redhat.com> | 2010-11-23 11:40:08 -0500 |
---|---|---|
committer | Eric Paris <eparis@redhat.com> | 2010-11-30 17:28:57 -0500 |
commit | b77a493b1dc8010245feeac001e5c7ed0988678f (patch) | |
tree | f0d2364ce8ed46ab569f3a41cbebb9a51bffb0f0 /security/selinux/selinuxfs.c | |
parent | 9398c7f794078dc1768cc061b3da8cdd59f179a5 (diff) |
SELinux: standardize return code handling in selinuxfs.c
selinuxfs.c has lots of different standards on how to handle return paths on
error. For the most part transition to
rc=errno
if (failure)
goto out;
[...]
out:
cleanup()
return rc;
Instead of doing cleanup mid function, or having multiple returns or other
options. This doesn't do that for every function, but most of the complex
functions which have cleanup routines on error.
Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'security/selinux/selinuxfs.c')
-rw-r--r-- | security/selinux/selinuxfs.c | 648 |
1 files changed, 311 insertions, 337 deletions
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 073fd5b0a53a..8bae68e21af9 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
@@ -141,19 +141,24 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, | |||
141 | size_t count, loff_t *ppos) | 141 | size_t count, loff_t *ppos) |
142 | 142 | ||
143 | { | 143 | { |
144 | char *page; | 144 | char *page = NULL; |
145 | ssize_t length; | 145 | ssize_t length; |
146 | int new_value; | 146 | int new_value; |
147 | 147 | ||
148 | length = -ENOMEM; | ||
148 | if (count >= PAGE_SIZE) | 149 | if (count >= PAGE_SIZE) |
149 | return -ENOMEM; | 150 | goto out; |
150 | if (*ppos != 0) { | 151 | |
151 | /* No partial writes. */ | 152 | /* No partial writes. */ |
152 | return -EINVAL; | 153 | length = EINVAL; |
153 | } | 154 | if (*ppos != 0) |
155 | goto out; | ||
156 | |||
157 | length = -ENOMEM; | ||
154 | page = (char *)get_zeroed_page(GFP_KERNEL); | 158 | page = (char *)get_zeroed_page(GFP_KERNEL); |
155 | if (!page) | 159 | if (!page) |
156 | return -ENOMEM; | 160 | goto out; |
161 | |||
157 | length = -EFAULT; | 162 | length = -EFAULT; |
158 | if (copy_from_user(page, buf, count)) | 163 | if (copy_from_user(page, buf, count)) |
159 | goto out; | 164 | goto out; |
@@ -268,20 +273,25 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf, | |||
268 | size_t count, loff_t *ppos) | 273 | size_t count, loff_t *ppos) |
269 | 274 | ||
270 | { | 275 | { |
271 | char *page; | 276 | char *page = NULL; |
272 | ssize_t length; | 277 | ssize_t length; |
273 | int new_value; | 278 | int new_value; |
274 | extern int selinux_disable(void); | 279 | extern int selinux_disable(void); |
275 | 280 | ||
281 | length = -ENOMEM; | ||
276 | if (count >= PAGE_SIZE) | 282 | if (count >= PAGE_SIZE) |
277 | return -ENOMEM; | 283 | goto out;; |
278 | if (*ppos != 0) { | 284 | |
279 | /* No partial writes. */ | 285 | /* No partial writes. */ |
280 | return -EINVAL; | 286 | length = -EINVAL; |
281 | } | 287 | if (*ppos != 0) |
288 | goto out; | ||
289 | |||
290 | length = -ENOMEM; | ||
282 | page = (char *)get_zeroed_page(GFP_KERNEL); | 291 | page = (char *)get_zeroed_page(GFP_KERNEL); |
283 | if (!page) | 292 | if (!page) |
284 | return -ENOMEM; | 293 | goto out; |
294 | |||
285 | length = -EFAULT; | 295 | length = -EFAULT; |
286 | if (copy_from_user(page, buf, count)) | 296 | if (copy_from_user(page, buf, count)) |
287 | goto out; | 297 | goto out; |
@@ -292,7 +302,7 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf, | |||
292 | 302 | ||
293 | if (new_value) { | 303 | if (new_value) { |
294 | length = selinux_disable(); | 304 | length = selinux_disable(); |
295 | if (length < 0) | 305 | if (length) |
296 | goto out; | 306 | goto out; |
297 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, | 307 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, |
298 | "selinux=0 auid=%u ses=%u", | 308 | "selinux=0 auid=%u ses=%u", |
@@ -493,7 +503,6 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, | |||
493 | size_t count, loff_t *ppos) | 503 | size_t count, loff_t *ppos) |
494 | 504 | ||
495 | { | 505 | { |
496 | int ret; | ||
497 | ssize_t length; | 506 | ssize_t length; |
498 | void *data = NULL; | 507 | void *data = NULL; |
499 | 508 | ||
@@ -503,17 +512,19 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, | |||
503 | if (length) | 512 | if (length) |
504 | goto out; | 513 | goto out; |
505 | 514 | ||
506 | if (*ppos != 0) { | 515 | /* No partial writes. */ |
507 | /* No partial writes. */ | 516 | length = -EINVAL; |
508 | length = -EINVAL; | 517 | if (*ppos != 0) |
509 | goto out; | 518 | goto out; |
510 | } | ||
511 | 519 | ||
512 | if ((count > 64 * 1024 * 1024) | 520 | length = -EFBIG; |
513 | || (data = vmalloc(count)) == NULL) { | 521 | if (count > 64 * 1024 * 1024) |
514 | length = -ENOMEM; | 522 | goto out; |
523 | |||
524 | length = -ENOMEM; | ||
525 | data = vmalloc(count); | ||
526 | if (!data) | ||
515 | goto out; | 527 | goto out; |
516 | } | ||
517 | 528 | ||
518 | length = -EFAULT; | 529 | length = -EFAULT; |
519 | if (copy_from_user(data, buf, count) != 0) | 530 | if (copy_from_user(data, buf, count) != 0) |
@@ -523,23 +534,19 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, | |||
523 | if (length) | 534 | if (length) |
524 | goto out; | 535 | goto out; |
525 | 536 | ||
526 | ret = sel_make_bools(); | 537 | length = sel_make_bools(); |
527 | if (ret) { | 538 | if (length) |
528 | length = ret; | ||
529 | goto out1; | 539 | goto out1; |
530 | } | ||
531 | 540 | ||
532 | ret = sel_make_classes(); | 541 | length = sel_make_classes(); |
533 | if (ret) { | 542 | if (length) |
534 | length = ret; | ||
535 | goto out1; | 543 | goto out1; |
536 | } | ||
537 | 544 | ||
538 | ret = sel_make_policycap(); | 545 | length = sel_make_policycap(); |
539 | if (ret) | 546 | if (length) |
540 | length = ret; | 547 | goto out1; |
541 | else | 548 | |
542 | length = count; | 549 | length = count; |
543 | 550 | ||
544 | out1: | 551 | out1: |
545 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD, | 552 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD, |
@@ -559,26 +566,26 @@ static const struct file_operations sel_load_ops = { | |||
559 | 566 | ||
560 | static ssize_t sel_write_context(struct file *file, char *buf, size_t size) | 567 | static ssize_t sel_write_context(struct file *file, char *buf, size_t size) |
561 | { | 568 | { |
562 | char *canon; | 569 | char *canon = NULL; |
563 | u32 sid, len; | 570 | u32 sid, len; |
564 | ssize_t length; | 571 | ssize_t length; |
565 | 572 | ||
566 | length = task_has_security(current, SECURITY__CHECK_CONTEXT); | 573 | length = task_has_security(current, SECURITY__CHECK_CONTEXT); |
567 | if (length) | 574 | if (length) |
568 | return length; | 575 | goto out; |
569 | 576 | ||
570 | length = security_context_to_sid(buf, size, &sid); | 577 | length = security_context_to_sid(buf, size, &sid); |
571 | if (length < 0) | 578 | if (length) |
572 | return length; | 579 | goto out; |
573 | 580 | ||
574 | length = security_sid_to_context(sid, &canon, &len); | 581 | length = security_sid_to_context(sid, &canon, &len); |
575 | if (length < 0) | 582 | if (length) |
576 | return length; | 583 | goto out; |
577 | 584 | ||
585 | length = -ERANGE; | ||
578 | if (len > SIMPLE_TRANSACTION_LIMIT) { | 586 | if (len > SIMPLE_TRANSACTION_LIMIT) { |
579 | printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " | 587 | printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " |
580 | "payload max\n", __func__, len); | 588 | "payload max\n", __func__, len); |
581 | length = -ERANGE; | ||
582 | goto out; | 589 | goto out; |
583 | } | 590 | } |
584 | 591 | ||
@@ -602,23 +609,28 @@ static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf, | |||
602 | static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, | 609 | static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, |
603 | size_t count, loff_t *ppos) | 610 | size_t count, loff_t *ppos) |
604 | { | 611 | { |
605 | char *page; | 612 | char *page = NULL; |
606 | ssize_t length; | 613 | ssize_t length; |
607 | unsigned int new_value; | 614 | unsigned int new_value; |
608 | 615 | ||
609 | length = task_has_security(current, SECURITY__SETCHECKREQPROT); | 616 | length = task_has_security(current, SECURITY__SETCHECKREQPROT); |
610 | if (length) | 617 | if (length) |
611 | return length; | 618 | goto out; |
612 | 619 | ||
620 | length = -ENOMEM; | ||
613 | if (count >= PAGE_SIZE) | 621 | if (count >= PAGE_SIZE) |
614 | return -ENOMEM; | 622 | goto out; |
615 | if (*ppos != 0) { | 623 | |
616 | /* No partial writes. */ | 624 | /* No partial writes. */ |
617 | return -EINVAL; | 625 | length = -EINVAL; |
618 | } | 626 | if (*ppos != 0) |
627 | goto out; | ||
628 | |||
629 | length = -ENOMEM; | ||
619 | page = (char *)get_zeroed_page(GFP_KERNEL); | 630 | page = (char *)get_zeroed_page(GFP_KERNEL); |
620 | if (!page) | 631 | if (!page) |
621 | return -ENOMEM; | 632 | goto out; |
633 | |||
622 | length = -EFAULT; | 634 | length = -EFAULT; |
623 | if (copy_from_user(page, buf, count)) | 635 | if (copy_from_user(page, buf, count)) |
624 | goto out; | 636 | goto out; |
@@ -693,7 +705,7 @@ static const struct file_operations transaction_ops = { | |||
693 | 705 | ||
694 | static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | 706 | static ssize_t sel_write_access(struct file *file, char *buf, size_t size) |
695 | { | 707 | { |
696 | char *scon, *tcon; | 708 | char *scon = NULL, *tcon = NULL; |
697 | u32 ssid, tsid; | 709 | u32 ssid, tsid; |
698 | u16 tclass; | 710 | u16 tclass; |
699 | struct av_decision avd; | 711 | struct av_decision avd; |
@@ -701,27 +713,29 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
701 | 713 | ||
702 | length = task_has_security(current, SECURITY__COMPUTE_AV); | 714 | length = task_has_security(current, SECURITY__COMPUTE_AV); |
703 | if (length) | 715 | if (length) |
704 | return length; | 716 | goto out; |
705 | 717 | ||
706 | length = -ENOMEM; | 718 | length = -ENOMEM; |
707 | scon = kzalloc(size + 1, GFP_KERNEL); | 719 | scon = kzalloc(size + 1, GFP_KERNEL); |
708 | if (!scon) | 720 | if (!scon) |
709 | return length; | 721 | goto out; |
710 | 722 | ||
723 | length = -ENOMEM; | ||
711 | tcon = kzalloc(size + 1, GFP_KERNEL); | 724 | tcon = kzalloc(size + 1, GFP_KERNEL); |
712 | if (!tcon) | 725 | if (!tcon) |
713 | goto out; | 726 | goto out; |
714 | 727 | ||
715 | length = -EINVAL; | 728 | length = -EINVAL; |
716 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 729 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
717 | goto out2; | 730 | goto out; |
718 | 731 | ||
719 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); | 732 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
720 | if (length < 0) | 733 | if (length) |
721 | goto out2; | 734 | goto out; |
735 | |||
722 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); | 736 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
723 | if (length < 0) | 737 | if (length) |
724 | goto out2; | 738 | goto out; |
725 | 739 | ||
726 | security_compute_av_user(ssid, tsid, tclass, &avd); | 740 | security_compute_av_user(ssid, tsid, tclass, &avd); |
727 | 741 | ||
@@ -730,133 +744,131 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
730 | avd.allowed, 0xffffffff, | 744 | avd.allowed, 0xffffffff, |
731 | avd.auditallow, avd.auditdeny, | 745 | avd.auditallow, avd.auditdeny, |
732 | avd.seqno, avd.flags); | 746 | avd.seqno, avd.flags); |
733 | out2: | ||
734 | kfree(tcon); | ||
735 | out: | 747 | out: |
748 | kfree(tcon); | ||
736 | kfree(scon); | 749 | kfree(scon); |
737 | return length; | 750 | return length; |
738 | } | 751 | } |
739 | 752 | ||
740 | static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | 753 | static ssize_t sel_write_create(struct file *file, char *buf, size_t size) |
741 | { | 754 | { |
742 | char *scon, *tcon; | 755 | char *scon = NULL, *tcon = NULL; |
743 | u32 ssid, tsid, newsid; | 756 | u32 ssid, tsid, newsid; |
744 | u16 tclass; | 757 | u16 tclass; |
745 | ssize_t length; | 758 | ssize_t length; |
746 | char *newcon; | 759 | char *newcon = NULL; |
747 | u32 len; | 760 | u32 len; |
748 | 761 | ||
749 | length = task_has_security(current, SECURITY__COMPUTE_CREATE); | 762 | length = task_has_security(current, SECURITY__COMPUTE_CREATE); |
750 | if (length) | 763 | if (length) |
751 | return length; | 764 | goto out; |
752 | 765 | ||
753 | length = -ENOMEM; | 766 | length = -ENOMEM; |
754 | scon = kzalloc(size + 1, GFP_KERNEL); | 767 | scon = kzalloc(size + 1, GFP_KERNEL); |
755 | if (!scon) | 768 | if (!scon) |
756 | return length; | 769 | goto out; |
757 | 770 | ||
771 | length = -ENOMEM; | ||
758 | tcon = kzalloc(size + 1, GFP_KERNEL); | 772 | tcon = kzalloc(size + 1, GFP_KERNEL); |
759 | if (!tcon) | 773 | if (!tcon) |
760 | goto out; | 774 | goto out; |
761 | 775 | ||
762 | length = -EINVAL; | 776 | length = -EINVAL; |
763 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 777 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
764 | goto out2; | 778 | goto out; |
765 | 779 | ||
766 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); | 780 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
767 | if (length < 0) | 781 | if (length) |
768 | goto out2; | 782 | goto out; |
783 | |||
769 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); | 784 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
770 | if (length < 0) | 785 | if (length) |
771 | goto out2; | 786 | goto out; |
772 | 787 | ||
773 | length = security_transition_sid_user(ssid, tsid, tclass, &newsid); | 788 | length = security_transition_sid_user(ssid, tsid, tclass, &newsid); |
774 | if (length < 0) | 789 | if (length) |
775 | goto out2; | 790 | goto out; |
776 | 791 | ||
777 | length = security_sid_to_context(newsid, &newcon, &len); | 792 | length = security_sid_to_context(newsid, &newcon, &len); |
778 | if (length < 0) | 793 | if (length) |
779 | goto out2; | 794 | goto out; |
780 | 795 | ||
796 | length = -ERANGE; | ||
781 | if (len > SIMPLE_TRANSACTION_LIMIT) { | 797 | if (len > SIMPLE_TRANSACTION_LIMIT) { |
782 | printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " | 798 | printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " |
783 | "payload max\n", __func__, len); | 799 | "payload max\n", __func__, len); |
784 | length = -ERANGE; | 800 | goto out; |
785 | goto out3; | ||
786 | } | 801 | } |
787 | 802 | ||
788 | memcpy(buf, newcon, len); | 803 | memcpy(buf, newcon, len); |
789 | length = len; | 804 | length = len; |
790 | out3: | 805 | out: |
791 | kfree(newcon); | 806 | kfree(newcon); |
792 | out2: | ||
793 | kfree(tcon); | 807 | kfree(tcon); |
794 | out: | ||
795 | kfree(scon); | 808 | kfree(scon); |
796 | return length; | 809 | return length; |
797 | } | 810 | } |
798 | 811 | ||
799 | static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) | 812 | static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) |
800 | { | 813 | { |
801 | char *scon, *tcon; | 814 | char *scon = NULL, *tcon = NULL; |
802 | u32 ssid, tsid, newsid; | 815 | u32 ssid, tsid, newsid; |
803 | u16 tclass; | 816 | u16 tclass; |
804 | ssize_t length; | 817 | ssize_t length; |
805 | char *newcon; | 818 | char *newcon = NULL; |
806 | u32 len; | 819 | u32 len; |
807 | 820 | ||
808 | length = task_has_security(current, SECURITY__COMPUTE_RELABEL); | 821 | length = task_has_security(current, SECURITY__COMPUTE_RELABEL); |
809 | if (length) | 822 | if (length) |
810 | return length; | 823 | goto out; |
811 | 824 | ||
812 | length = -ENOMEM; | 825 | length = -ENOMEM; |
813 | scon = kzalloc(size + 1, GFP_KERNEL); | 826 | scon = kzalloc(size + 1, GFP_KERNEL); |
814 | if (!scon) | 827 | if (!scon) |
815 | return length; | 828 | goto out; |
816 | 829 | ||
830 | length = -ENOMEM; | ||
817 | tcon = kzalloc(size + 1, GFP_KERNEL); | 831 | tcon = kzalloc(size + 1, GFP_KERNEL); |
818 | if (!tcon) | 832 | if (!tcon) |
819 | goto out; | 833 | goto out; |
820 | 834 | ||
821 | length = -EINVAL; | 835 | length = -EINVAL; |
822 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 836 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
823 | goto out2; | 837 | goto out; |
824 | 838 | ||
825 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); | 839 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
826 | if (length < 0) | 840 | if (length) |
827 | goto out2; | 841 | goto out; |
842 | |||
828 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); | 843 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
829 | if (length < 0) | 844 | if (length) |
830 | goto out2; | 845 | goto out; |
831 | 846 | ||
832 | length = security_change_sid(ssid, tsid, tclass, &newsid); | 847 | length = security_change_sid(ssid, tsid, tclass, &newsid); |
833 | if (length < 0) | 848 | if (length) |
834 | goto out2; | 849 | goto out; |
835 | 850 | ||
836 | length = security_sid_to_context(newsid, &newcon, &len); | 851 | length = security_sid_to_context(newsid, &newcon, &len); |
837 | if (length < 0) | 852 | if (length) |
838 | goto out2; | 853 | goto out; |
839 | 854 | ||
840 | if (len > SIMPLE_TRANSACTION_LIMIT) { | 855 | length = -ERANGE; |
841 | length = -ERANGE; | 856 | if (len > SIMPLE_TRANSACTION_LIMIT) |
842 | goto out3; | 857 | goto out; |
843 | } | ||
844 | 858 | ||
845 | memcpy(buf, newcon, len); | 859 | memcpy(buf, newcon, len); |
846 | length = len; | 860 | length = len; |
847 | out3: | 861 | out: |
848 | kfree(newcon); | 862 | kfree(newcon); |
849 | out2: | ||
850 | kfree(tcon); | 863 | kfree(tcon); |
851 | out: | ||
852 | kfree(scon); | 864 | kfree(scon); |
853 | return length; | 865 | return length; |
854 | } | 866 | } |
855 | 867 | ||
856 | static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | 868 | static ssize_t sel_write_user(struct file *file, char *buf, size_t size) |
857 | { | 869 | { |
858 | char *con, *user, *ptr; | 870 | char *con = NULL, *user = NULL, *ptr; |
859 | u32 sid, *sids; | 871 | u32 sid, *sids = NULL; |
860 | ssize_t length; | 872 | ssize_t length; |
861 | char *newcon; | 873 | char *newcon; |
862 | int i, rc; | 874 | int i, rc; |
@@ -864,28 +876,29 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | |||
864 | 876 | ||
865 | length = task_has_security(current, SECURITY__COMPUTE_USER); | 877 | length = task_has_security(current, SECURITY__COMPUTE_USER); |
866 | if (length) | 878 | if (length) |
867 | return length; | 879 | goto out;; |
868 | 880 | ||
869 | length = -ENOMEM; | 881 | length = -ENOMEM; |
870 | con = kzalloc(size + 1, GFP_KERNEL); | 882 | con = kzalloc(size + 1, GFP_KERNEL); |
871 | if (!con) | 883 | if (!con) |
872 | return length; | 884 | goto out;; |
873 | 885 | ||
886 | length = -ENOMEM; | ||
874 | user = kzalloc(size + 1, GFP_KERNEL); | 887 | user = kzalloc(size + 1, GFP_KERNEL); |
875 | if (!user) | 888 | if (!user) |
876 | goto out; | 889 | goto out; |
877 | 890 | ||
878 | length = -EINVAL; | 891 | length = -EINVAL; |
879 | if (sscanf(buf, "%s %s", con, user) != 2) | 892 | if (sscanf(buf, "%s %s", con, user) != 2) |
880 | goto out2; | 893 | goto out; |
881 | 894 | ||
882 | length = security_context_to_sid(con, strlen(con) + 1, &sid); | 895 | length = security_context_to_sid(con, strlen(con) + 1, &sid); |
883 | if (length < 0) | 896 | if (length) |
884 | goto out2; | 897 | goto out; |
885 | 898 | ||
886 | length = security_get_user_sids(sid, user, &sids, &nsids); | 899 | length = security_get_user_sids(sid, user, &sids, &nsids); |
887 | if (length < 0) | 900 | if (length) |
888 | goto out2; | 901 | goto out; |
889 | 902 | ||
890 | length = sprintf(buf, "%u", nsids) + 1; | 903 | length = sprintf(buf, "%u", nsids) + 1; |
891 | ptr = buf + length; | 904 | ptr = buf + length; |
@@ -893,82 +906,80 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | |||
893 | rc = security_sid_to_context(sids[i], &newcon, &len); | 906 | rc = security_sid_to_context(sids[i], &newcon, &len); |
894 | if (rc) { | 907 | if (rc) { |
895 | length = rc; | 908 | length = rc; |
896 | goto out3; | 909 | goto out; |
897 | } | 910 | } |
898 | if ((length + len) >= SIMPLE_TRANSACTION_LIMIT) { | 911 | if ((length + len) >= SIMPLE_TRANSACTION_LIMIT) { |
899 | kfree(newcon); | 912 | kfree(newcon); |
900 | length = -ERANGE; | 913 | length = -ERANGE; |
901 | goto out3; | 914 | goto out; |
902 | } | 915 | } |
903 | memcpy(ptr, newcon, len); | 916 | memcpy(ptr, newcon, len); |
904 | kfree(newcon); | 917 | kfree(newcon); |
905 | ptr += len; | 918 | ptr += len; |
906 | length += len; | 919 | length += len; |
907 | } | 920 | } |
908 | out3: | 921 | out: |
909 | kfree(sids); | 922 | kfree(sids); |
910 | out2: | ||
911 | kfree(user); | 923 | kfree(user); |
912 | out: | ||
913 | kfree(con); | 924 | kfree(con); |
914 | return length; | 925 | return length; |
915 | } | 926 | } |
916 | 927 | ||
917 | static ssize_t sel_write_member(struct file *file, char *buf, size_t size) | 928 | static ssize_t sel_write_member(struct file *file, char *buf, size_t size) |
918 | { | 929 | { |
919 | char *scon, *tcon; | 930 | char *scon = NULL, *tcon = NULL; |
920 | u32 ssid, tsid, newsid; | 931 | u32 ssid, tsid, newsid; |
921 | u16 tclass; | 932 | u16 tclass; |
922 | ssize_t length; | 933 | ssize_t length; |
923 | char *newcon; | 934 | char *newcon = NULL; |
924 | u32 len; | 935 | u32 len; |
925 | 936 | ||
926 | length = task_has_security(current, SECURITY__COMPUTE_MEMBER); | 937 | length = task_has_security(current, SECURITY__COMPUTE_MEMBER); |
927 | if (length) | 938 | if (length) |
928 | return length; | 939 | goto out; |
929 | 940 | ||
930 | length = -ENOMEM; | 941 | length = -ENOMEM; |
931 | scon = kzalloc(size + 1, GFP_KERNEL); | 942 | scon = kzalloc(size + 1, GFP_KERNEL); |
932 | if (!scon) | 943 | if (!scon) |
933 | return length; | 944 | goto out;; |
934 | 945 | ||
946 | length = -ENOMEM; | ||
935 | tcon = kzalloc(size + 1, GFP_KERNEL); | 947 | tcon = kzalloc(size + 1, GFP_KERNEL); |
936 | if (!tcon) | 948 | if (!tcon) |
937 | goto out; | 949 | goto out; |
938 | 950 | ||
939 | length = -EINVAL; | 951 | length = -EINVAL; |
940 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 952 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
941 | goto out2; | 953 | goto out; |
942 | 954 | ||
943 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); | 955 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
944 | if (length < 0) | 956 | if (length) |
945 | goto out2; | 957 | goto out; |
958 | |||
946 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); | 959 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
947 | if (length < 0) | 960 | if (length) |
948 | goto out2; | 961 | goto out; |
949 | 962 | ||
950 | length = security_member_sid(ssid, tsid, tclass, &newsid); | 963 | length = security_member_sid(ssid, tsid, tclass, &newsid); |
951 | if (length < 0) | 964 | if (length) |
952 | goto out2; | 965 | goto out; |
953 | 966 | ||
954 | length = security_sid_to_context(newsid, &newcon, &len); | 967 | length = security_sid_to_context(newsid, &newcon, &len); |
955 | if (length < 0) | 968 | if (length) |
956 | goto out2; | 969 | goto out; |
957 | 970 | ||
971 | length = -ERANGE; | ||
958 | if (len > SIMPLE_TRANSACTION_LIMIT) { | 972 | if (len > SIMPLE_TRANSACTION_LIMIT) { |
959 | printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " | 973 | printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " |
960 | "payload max\n", __func__, len); | 974 | "payload max\n", __func__, len); |
961 | length = -ERANGE; | 975 | goto out; |
962 | goto out3; | ||
963 | } | 976 | } |
964 | 977 | ||
965 | memcpy(buf, newcon, len); | 978 | memcpy(buf, newcon, len); |
966 | length = len; | 979 | length = len; |
967 | out3: | 980 | out: |
968 | kfree(newcon); | 981 | kfree(newcon); |
969 | out2: | ||
970 | kfree(tcon); | 982 | kfree(tcon); |
971 | out: | ||
972 | kfree(scon); | 983 | kfree(scon); |
973 | return length; | 984 | return length; |
974 | } | 985 | } |
@@ -998,16 +1009,14 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, | |||
998 | 1009 | ||
999 | mutex_lock(&sel_mutex); | 1010 | mutex_lock(&sel_mutex); |
1000 | 1011 | ||
1001 | if (index >= bool_num || strcmp(name, bool_pending_names[index])) { | 1012 | ret = -EINVAL; |
1002 | ret = -EINVAL; | 1013 | if (index >= bool_num || strcmp(name, bool_pending_names[index])) |
1003 | goto out; | 1014 | goto out; |
1004 | } | ||
1005 | 1015 | ||
1016 | ret = -ENOMEM; | ||
1006 | page = (char *)get_zeroed_page(GFP_KERNEL); | 1017 | page = (char *)get_zeroed_page(GFP_KERNEL); |
1007 | if (!page) { | 1018 | if (!page) |
1008 | ret = -ENOMEM; | ||
1009 | goto out; | 1019 | goto out; |
1010 | } | ||
1011 | 1020 | ||
1012 | cur_enforcing = security_get_bool_value(index); | 1021 | cur_enforcing = security_get_bool_value(index); |
1013 | if (cur_enforcing < 0) { | 1022 | if (cur_enforcing < 0) { |
@@ -1019,8 +1028,7 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, | |||
1019 | ret = simple_read_from_buffer(buf, count, ppos, page, length); | 1028 | ret = simple_read_from_buffer(buf, count, ppos, page, length); |
1020 | out: | 1029 | out: |
1021 | mutex_unlock(&sel_mutex); | 1030 | mutex_unlock(&sel_mutex); |
1022 | if (page) | 1031 | free_page((unsigned long)page); |
1023 | free_page((unsigned long)page); | ||
1024 | return ret; | 1032 | return ret; |
1025 | } | 1033 | } |
1026 | 1034 | ||
@@ -1040,26 +1048,23 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, | |||
1040 | if (length) | 1048 | if (length) |
1041 | goto out; | 1049 | goto out; |
1042 | 1050 | ||
1043 | if (index >= bool_num || strcmp(name, bool_pending_names[index])) { | 1051 | length = -EINVAL; |
1044 | length = -EINVAL; | 1052 | if (index >= bool_num || strcmp(name, bool_pending_names[index])) |
1045 | goto out; | 1053 | goto out; |
1046 | } | ||
1047 | 1054 | ||
1048 | if (count >= PAGE_SIZE) { | 1055 | length = -ENOMEM; |
1049 | length = -ENOMEM; | 1056 | if (count >= PAGE_SIZE) |
1050 | goto out; | 1057 | goto out; |
1051 | } | ||
1052 | 1058 | ||
1053 | if (*ppos != 0) { | 1059 | /* No partial writes. */ |
1054 | /* No partial writes. */ | 1060 | length = -EINVAL; |
1055 | length = -EINVAL; | 1061 | if (*ppos != 0) |
1056 | goto out; | 1062 | goto out; |
1057 | } | 1063 | |
1064 | length = -ENOMEM; | ||
1058 | page = (char *)get_zeroed_page(GFP_KERNEL); | 1065 | page = (char *)get_zeroed_page(GFP_KERNEL); |
1059 | if (!page) { | 1066 | if (!page) |
1060 | length = -ENOMEM; | ||
1061 | goto out; | 1067 | goto out; |
1062 | } | ||
1063 | 1068 | ||
1064 | length = -EFAULT; | 1069 | length = -EFAULT; |
1065 | if (copy_from_user(page, buf, count)) | 1070 | if (copy_from_user(page, buf, count)) |
@@ -1077,8 +1082,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, | |||
1077 | 1082 | ||
1078 | out: | 1083 | out: |
1079 | mutex_unlock(&sel_mutex); | 1084 | mutex_unlock(&sel_mutex); |
1080 | if (page) | 1085 | free_page((unsigned long) page); |
1081 | free_page((unsigned long) page); | ||
1082 | return length; | 1086 | return length; |
1083 | } | 1087 | } |
1084 | 1088 | ||
@@ -1102,19 +1106,19 @@ static ssize_t sel_commit_bools_write(struct file *filep, | |||
1102 | if (length) | 1106 | if (length) |
1103 | goto out; | 1107 | goto out; |
1104 | 1108 | ||
1105 | if (count >= PAGE_SIZE) { | 1109 | length = -ENOMEM; |
1106 | length = -ENOMEM; | 1110 | if (count >= PAGE_SIZE) |
1107 | goto out; | 1111 | goto out; |
1108 | } | 1112 | |
1109 | if (*ppos != 0) { | 1113 | /* No partial writes. */ |
1110 | /* No partial writes. */ | 1114 | length = -EINVAL; |
1115 | if (*ppos != 0) | ||
1111 | goto out; | 1116 | goto out; |
1112 | } | 1117 | |
1118 | length = -ENOMEM; | ||
1113 | page = (char *)get_zeroed_page(GFP_KERNEL); | 1119 | page = (char *)get_zeroed_page(GFP_KERNEL); |
1114 | if (!page) { | 1120 | if (!page) |
1115 | length = -ENOMEM; | ||
1116 | goto out; | 1121 | goto out; |
1117 | } | ||
1118 | 1122 | ||
1119 | length = -EFAULT; | 1123 | length = -EFAULT; |
1120 | if (copy_from_user(page, buf, count)) | 1124 | if (copy_from_user(page, buf, count)) |
@@ -1124,15 +1128,16 @@ static ssize_t sel_commit_bools_write(struct file *filep, | |||
1124 | if (sscanf(page, "%d", &new_value) != 1) | 1128 | if (sscanf(page, "%d", &new_value) != 1) |
1125 | goto out; | 1129 | goto out; |
1126 | 1130 | ||
1131 | length = 0; | ||
1127 | if (new_value && bool_pending_values) | 1132 | if (new_value && bool_pending_values) |
1128 | security_set_bools(bool_num, bool_pending_values); | 1133 | length = security_set_bools(bool_num, bool_pending_values); |
1129 | 1134 | ||
1130 | length = count; | 1135 | if (!length) |
1136 | length = count; | ||
1131 | 1137 | ||
1132 | out: | 1138 | out: |
1133 | mutex_unlock(&sel_mutex); | 1139 | mutex_unlock(&sel_mutex); |
1134 | if (page) | 1140 | free_page((unsigned long) page); |
1135 | free_page((unsigned long) page); | ||
1136 | return length; | 1141 | return length; |
1137 | } | 1142 | } |
1138 | 1143 | ||
@@ -1169,7 +1174,7 @@ static void sel_remove_entries(struct dentry *de) | |||
1169 | 1174 | ||
1170 | static int sel_make_bools(void) | 1175 | static int sel_make_bools(void) |
1171 | { | 1176 | { |
1172 | int i, ret = 0; | 1177 | int i, ret; |
1173 | ssize_t len; | 1178 | ssize_t len; |
1174 | struct dentry *dentry = NULL; | 1179 | struct dentry *dentry = NULL; |
1175 | struct dentry *dir = bool_dir; | 1180 | struct dentry *dir = bool_dir; |
@@ -1190,38 +1195,40 @@ static int sel_make_bools(void) | |||
1190 | 1195 | ||
1191 | sel_remove_entries(dir); | 1196 | sel_remove_entries(dir); |
1192 | 1197 | ||
1198 | ret = -ENOMEM; | ||
1193 | page = (char *)get_zeroed_page(GFP_KERNEL); | 1199 | page = (char *)get_zeroed_page(GFP_KERNEL); |
1194 | if (!page) | 1200 | if (!page) |
1195 | return -ENOMEM; | 1201 | goto out; |
1196 | 1202 | ||
1197 | ret = security_get_bools(&num, &names, &values); | 1203 | ret = security_get_bools(&num, &names, &values); |
1198 | if (ret != 0) | 1204 | if (ret) |
1199 | goto out; | 1205 | goto out; |
1200 | 1206 | ||
1201 | for (i = 0; i < num; i++) { | 1207 | for (i = 0; i < num; i++) { |
1208 | ret = -ENOMEM; | ||
1202 | dentry = d_alloc_name(dir, names[i]); | 1209 | dentry = d_alloc_name(dir, names[i]); |
1203 | if (!dentry) { | 1210 | if (!dentry) |
1204 | ret = -ENOMEM; | 1211 | goto out; |
1205 | goto err; | 1212 | |
1206 | } | 1213 | ret = -ENOMEM; |
1207 | inode = sel_make_inode(dir->d_sb, S_IFREG | S_IRUGO | S_IWUSR); | 1214 | inode = sel_make_inode(dir->d_sb, S_IFREG | S_IRUGO | S_IWUSR); |
1208 | if (!inode) { | 1215 | if (!inode) |
1209 | ret = -ENOMEM; | 1216 | goto out; |
1210 | goto err; | ||
1211 | } | ||
1212 | 1217 | ||
1218 | ret = -EINVAL; | ||
1213 | len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]); | 1219 | len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]); |
1214 | if (len < 0) { | 1220 | if (len < 0) |
1215 | ret = -EINVAL; | 1221 | goto out; |
1216 | goto err; | 1222 | |
1217 | } else if (len >= PAGE_SIZE) { | 1223 | ret = -ENAMETOOLONG; |
1218 | ret = -ENAMETOOLONG; | 1224 | if (len >= PAGE_SIZE) |
1219 | goto err; | 1225 | goto out; |
1220 | } | 1226 | |
1221 | isec = (struct inode_security_struct *)inode->i_security; | 1227 | isec = (struct inode_security_struct *)inode->i_security; |
1222 | ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid); | 1228 | ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid); |
1223 | if (ret) | 1229 | if (ret) |
1224 | goto err; | 1230 | goto out; |
1231 | |||
1225 | isec->sid = sid; | 1232 | isec->sid = sid; |
1226 | isec->initialized = 1; | 1233 | isec->initialized = 1; |
1227 | inode->i_fop = &sel_bool_ops; | 1234 | inode->i_fop = &sel_bool_ops; |
@@ -1231,10 +1238,12 @@ static int sel_make_bools(void) | |||
1231 | bool_num = num; | 1238 | bool_num = num; |
1232 | bool_pending_names = names; | 1239 | bool_pending_names = names; |
1233 | bool_pending_values = values; | 1240 | bool_pending_values = values; |
1241 | |||
1242 | free_page((unsigned long)page); | ||
1243 | return 0; | ||
1234 | out: | 1244 | out: |
1235 | free_page((unsigned long)page); | 1245 | free_page((unsigned long)page); |
1236 | return ret; | 1246 | |
1237 | err: | ||
1238 | if (names) { | 1247 | if (names) { |
1239 | for (i = 0; i < num; i++) | 1248 | for (i = 0; i < num; i++) |
1240 | kfree(names[i]); | 1249 | kfree(names[i]); |
@@ -1242,8 +1251,8 @@ err: | |||
1242 | } | 1251 | } |
1243 | kfree(values); | 1252 | kfree(values); |
1244 | sel_remove_entries(dir); | 1253 | sel_remove_entries(dir); |
1245 | ret = -ENOMEM; | 1254 | |
1246 | goto out; | 1255 | return ret; |
1247 | } | 1256 | } |
1248 | 1257 | ||
1249 | #define NULL_FILE_NAME "null" | 1258 | #define NULL_FILE_NAME "null" |
@@ -1265,47 +1274,41 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file, | |||
1265 | size_t count, loff_t *ppos) | 1274 | size_t count, loff_t *ppos) |
1266 | 1275 | ||
1267 | { | 1276 | { |
1268 | char *page; | 1277 | char *page = NULL; |
1269 | ssize_t ret; | 1278 | ssize_t ret; |
1270 | int new_value; | 1279 | int new_value; |
1271 | 1280 | ||
1272 | if (count >= PAGE_SIZE) { | 1281 | ret = task_has_security(current, SECURITY__SETSECPARAM); |
1273 | ret = -ENOMEM; | 1282 | if (ret) |
1274 | goto out; | 1283 | goto out; |
1275 | } | ||
1276 | 1284 | ||
1277 | if (*ppos != 0) { | 1285 | ret = -ENOMEM; |
1278 | /* No partial writes. */ | 1286 | if (count >= PAGE_SIZE) |
1279 | ret = -EINVAL; | ||
1280 | goto out; | 1287 | goto out; |
1281 | } | ||
1282 | 1288 | ||
1289 | /* No partial writes. */ | ||
1290 | ret = -EINVAL; | ||
1291 | if (*ppos != 0) | ||
1292 | goto out; | ||
1293 | |||
1294 | ret = -ENOMEM; | ||
1283 | page = (char *)get_zeroed_page(GFP_KERNEL); | 1295 | page = (char *)get_zeroed_page(GFP_KERNEL); |
1284 | if (!page) { | 1296 | if (!page) |
1285 | ret = -ENOMEM; | ||
1286 | goto out; | 1297 | goto out; |
1287 | } | ||
1288 | 1298 | ||
1289 | if (copy_from_user(page, buf, count)) { | 1299 | ret = -EFAULT; |
1290 | ret = -EFAULT; | 1300 | if (copy_from_user(page, buf, count)) |
1291 | goto out_free; | 1301 | goto out; |
1292 | } | ||
1293 | 1302 | ||
1294 | if (sscanf(page, "%u", &new_value) != 1) { | 1303 | ret = -EINVAL; |
1295 | ret = -EINVAL; | 1304 | if (sscanf(page, "%u", &new_value) != 1) |
1296 | goto out; | 1305 | goto out; |
1297 | } | ||
1298 | 1306 | ||
1299 | if (new_value != avc_cache_threshold) { | 1307 | avc_cache_threshold = new_value; |
1300 | ret = task_has_security(current, SECURITY__SETSECPARAM); | 1308 | |
1301 | if (ret) | ||
1302 | goto out_free; | ||
1303 | avc_cache_threshold = new_value; | ||
1304 | } | ||
1305 | ret = count; | 1309 | ret = count; |
1306 | out_free: | ||
1307 | free_page((unsigned long)page); | ||
1308 | out: | 1310 | out: |
1311 | free_page((unsigned long)page); | ||
1309 | return ret; | 1312 | return ret; |
1310 | } | 1313 | } |
1311 | 1314 | ||
@@ -1313,19 +1316,18 @@ static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf, | |||
1313 | size_t count, loff_t *ppos) | 1316 | size_t count, loff_t *ppos) |
1314 | { | 1317 | { |
1315 | char *page; | 1318 | char *page; |
1316 | ssize_t ret = 0; | 1319 | ssize_t length; |
1317 | 1320 | ||
1318 | page = (char *)__get_free_page(GFP_KERNEL); | 1321 | page = (char *)__get_free_page(GFP_KERNEL); |
1319 | if (!page) { | 1322 | if (!page) |
1320 | ret = -ENOMEM; | 1323 | return -ENOMEM; |
1321 | goto out; | 1324 | |
1322 | } | 1325 | length = avc_get_hash_stats(page); |
1323 | ret = avc_get_hash_stats(page); | 1326 | if (length >= 0) |
1324 | if (ret >= 0) | 1327 | length = simple_read_from_buffer(buf, count, ppos, page, length); |
1325 | ret = simple_read_from_buffer(buf, count, ppos, page, ret); | ||
1326 | free_page((unsigned long)page); | 1328 | free_page((unsigned long)page); |
1327 | out: | 1329 | |
1328 | return ret; | 1330 | return length; |
1329 | } | 1331 | } |
1330 | 1332 | ||
1331 | static const struct file_operations sel_avc_cache_threshold_ops = { | 1333 | static const struct file_operations sel_avc_cache_threshold_ops = { |
@@ -1407,7 +1409,7 @@ static const struct file_operations sel_avc_cache_stats_ops = { | |||
1407 | 1409 | ||
1408 | static int sel_make_avc_files(struct dentry *dir) | 1410 | static int sel_make_avc_files(struct dentry *dir) |
1409 | { | 1411 | { |
1410 | int i, ret = 0; | 1412 | int i; |
1411 | static struct tree_descr files[] = { | 1413 | static struct tree_descr files[] = { |
1412 | { "cache_threshold", | 1414 | { "cache_threshold", |
1413 | &sel_avc_cache_threshold_ops, S_IRUGO|S_IWUSR }, | 1415 | &sel_avc_cache_threshold_ops, S_IRUGO|S_IWUSR }, |
@@ -1422,22 +1424,19 @@ static int sel_make_avc_files(struct dentry *dir) | |||
1422 | struct dentry *dentry; | 1424 | struct dentry *dentry; |
1423 | 1425 | ||
1424 | dentry = d_alloc_name(dir, files[i].name); | 1426 | dentry = d_alloc_name(dir, files[i].name); |
1425 | if (!dentry) { | 1427 | if (!dentry) |
1426 | ret = -ENOMEM; | 1428 | return -ENOMEM; |
1427 | goto out; | ||
1428 | } | ||
1429 | 1429 | ||
1430 | inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode); | 1430 | inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode); |
1431 | if (!inode) { | 1431 | if (!inode) |
1432 | ret = -ENOMEM; | 1432 | return -ENOMEM; |
1433 | goto out; | 1433 | |
1434 | } | ||
1435 | inode->i_fop = files[i].ops; | 1434 | inode->i_fop = files[i].ops; |
1436 | inode->i_ino = ++sel_last_ino; | 1435 | inode->i_ino = ++sel_last_ino; |
1437 | d_add(dentry, inode); | 1436 | d_add(dentry, inode); |
1438 | } | 1437 | } |
1439 | out: | 1438 | |
1440 | return ret; | 1439 | return 0; |
1441 | } | 1440 | } |
1442 | 1441 | ||
1443 | static ssize_t sel_read_initcon(struct file *file, char __user *buf, | 1442 | static ssize_t sel_read_initcon(struct file *file, char __user *buf, |
@@ -1451,7 +1450,7 @@ static ssize_t sel_read_initcon(struct file *file, char __user *buf, | |||
1451 | inode = file->f_path.dentry->d_inode; | 1450 | inode = file->f_path.dentry->d_inode; |
1452 | sid = inode->i_ino&SEL_INO_MASK; | 1451 | sid = inode->i_ino&SEL_INO_MASK; |
1453 | ret = security_sid_to_context(sid, &con, &len); | 1452 | ret = security_sid_to_context(sid, &con, &len); |
1454 | if (ret < 0) | 1453 | if (ret) |
1455 | return ret; | 1454 | return ret; |
1456 | 1455 | ||
1457 | ret = simple_read_from_buffer(buf, count, ppos, con, len); | 1456 | ret = simple_read_from_buffer(buf, count, ppos, con, len); |
@@ -1466,28 +1465,25 @@ static const struct file_operations sel_initcon_ops = { | |||
1466 | 1465 | ||
1467 | static int sel_make_initcon_files(struct dentry *dir) | 1466 | static int sel_make_initcon_files(struct dentry *dir) |
1468 | { | 1467 | { |
1469 | int i, ret = 0; | 1468 | int i; |
1470 | 1469 | ||
1471 | for (i = 1; i <= SECINITSID_NUM; i++) { | 1470 | for (i = 1; i <= SECINITSID_NUM; i++) { |
1472 | struct inode *inode; | 1471 | struct inode *inode; |
1473 | struct dentry *dentry; | 1472 | struct dentry *dentry; |
1474 | dentry = d_alloc_name(dir, security_get_initial_sid_context(i)); | 1473 | dentry = d_alloc_name(dir, security_get_initial_sid_context(i)); |
1475 | if (!dentry) { | 1474 | if (!dentry) |
1476 | ret = -ENOMEM; | 1475 | return -ENOMEM; |
1477 | goto out; | ||
1478 | } | ||
1479 | 1476 | ||
1480 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); | 1477 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); |
1481 | if (!inode) { | 1478 | if (!inode) |
1482 | ret = -ENOMEM; | 1479 | return -ENOMEM; |
1483 | goto out; | 1480 | |
1484 | } | ||
1485 | inode->i_fop = &sel_initcon_ops; | 1481 | inode->i_fop = &sel_initcon_ops; |
1486 | inode->i_ino = i|SEL_INITCON_INO_OFFSET; | 1482 | inode->i_ino = i|SEL_INITCON_INO_OFFSET; |
1487 | d_add(dentry, inode); | 1483 | d_add(dentry, inode); |
1488 | } | 1484 | } |
1489 | out: | 1485 | |
1490 | return ret; | 1486 | return 0; |
1491 | } | 1487 | } |
1492 | 1488 | ||
1493 | static inline unsigned int sel_div(unsigned long a, unsigned long b) | 1489 | static inline unsigned int sel_div(unsigned long a, unsigned long b) |
@@ -1523,15 +1519,13 @@ static ssize_t sel_read_class(struct file *file, char __user *buf, | |||
1523 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; | 1519 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; |
1524 | 1520 | ||
1525 | page = (char *)__get_free_page(GFP_KERNEL); | 1521 | page = (char *)__get_free_page(GFP_KERNEL); |
1526 | if (!page) { | 1522 | if (!page) |
1527 | rc = -ENOMEM; | 1523 | return -ENOMEM; |
1528 | goto out; | ||
1529 | } | ||
1530 | 1524 | ||
1531 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino)); | 1525 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino)); |
1532 | rc = simple_read_from_buffer(buf, count, ppos, page, len); | 1526 | rc = simple_read_from_buffer(buf, count, ppos, page, len); |
1533 | free_page((unsigned long)page); | 1527 | free_page((unsigned long)page); |
1534 | out: | 1528 | |
1535 | return rc; | 1529 | return rc; |
1536 | } | 1530 | } |
1537 | 1531 | ||
@@ -1548,15 +1542,13 @@ static ssize_t sel_read_perm(struct file *file, char __user *buf, | |||
1548 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; | 1542 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; |
1549 | 1543 | ||
1550 | page = (char *)__get_free_page(GFP_KERNEL); | 1544 | page = (char *)__get_free_page(GFP_KERNEL); |
1551 | if (!page) { | 1545 | if (!page) |
1552 | rc = -ENOMEM; | 1546 | return -ENOMEM; |
1553 | goto out; | ||
1554 | } | ||
1555 | 1547 | ||
1556 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_perm(ino)); | 1548 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_perm(ino)); |
1557 | rc = simple_read_from_buffer(buf, count, ppos, page, len); | 1549 | rc = simple_read_from_buffer(buf, count, ppos, page, len); |
1558 | free_page((unsigned long)page); | 1550 | free_page((unsigned long)page); |
1559 | out: | 1551 | |
1560 | return rc; | 1552 | return rc; |
1561 | } | 1553 | } |
1562 | 1554 | ||
@@ -1587,39 +1579,37 @@ static const struct file_operations sel_policycap_ops = { | |||
1587 | static int sel_make_perm_files(char *objclass, int classvalue, | 1579 | static int sel_make_perm_files(char *objclass, int classvalue, |
1588 | struct dentry *dir) | 1580 | struct dentry *dir) |
1589 | { | 1581 | { |
1590 | int i, rc = 0, nperms; | 1582 | int i, rc, nperms; |
1591 | char **perms; | 1583 | char **perms; |
1592 | 1584 | ||
1593 | rc = security_get_permissions(objclass, &perms, &nperms); | 1585 | rc = security_get_permissions(objclass, &perms, &nperms); |
1594 | if (rc) | 1586 | if (rc) |
1595 | goto out; | 1587 | return rc; |
1596 | 1588 | ||
1597 | for (i = 0; i < nperms; i++) { | 1589 | for (i = 0; i < nperms; i++) { |
1598 | struct inode *inode; | 1590 | struct inode *inode; |
1599 | struct dentry *dentry; | 1591 | struct dentry *dentry; |
1600 | 1592 | ||
1593 | rc = -ENOMEM; | ||
1601 | dentry = d_alloc_name(dir, perms[i]); | 1594 | dentry = d_alloc_name(dir, perms[i]); |
1602 | if (!dentry) { | 1595 | if (!dentry) |
1603 | rc = -ENOMEM; | 1596 | goto out; |
1604 | goto out1; | ||
1605 | } | ||
1606 | 1597 | ||
1598 | rc = -ENOMEM; | ||
1607 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); | 1599 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); |
1608 | if (!inode) { | 1600 | if (!inode) |
1609 | rc = -ENOMEM; | 1601 | goto out; |
1610 | goto out1; | 1602 | |
1611 | } | ||
1612 | inode->i_fop = &sel_perm_ops; | 1603 | inode->i_fop = &sel_perm_ops; |
1613 | /* i+1 since perm values are 1-indexed */ | 1604 | /* i+1 since perm values are 1-indexed */ |
1614 | inode->i_ino = sel_perm_to_ino(classvalue, i + 1); | 1605 | inode->i_ino = sel_perm_to_ino(classvalue, i + 1); |
1615 | d_add(dentry, inode); | 1606 | d_add(dentry, inode); |
1616 | } | 1607 | } |
1617 | 1608 | rc = 0; | |
1618 | out1: | 1609 | out: |
1619 | for (i = 0; i < nperms; i++) | 1610 | for (i = 0; i < nperms; i++) |
1620 | kfree(perms[i]); | 1611 | kfree(perms[i]); |
1621 | kfree(perms); | 1612 | kfree(perms); |
1622 | out: | ||
1623 | return rc; | 1613 | return rc; |
1624 | } | 1614 | } |
1625 | 1615 | ||
@@ -1631,34 +1621,27 @@ static int sel_make_class_dir_entries(char *classname, int index, | |||
1631 | int rc; | 1621 | int rc; |
1632 | 1622 | ||
1633 | dentry = d_alloc_name(dir, "index"); | 1623 | dentry = d_alloc_name(dir, "index"); |
1634 | if (!dentry) { | 1624 | if (!dentry) |
1635 | rc = -ENOMEM; | 1625 | return -ENOMEM; |
1636 | goto out; | ||
1637 | } | ||
1638 | 1626 | ||
1639 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); | 1627 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); |
1640 | if (!inode) { | 1628 | if (!inode) |
1641 | rc = -ENOMEM; | 1629 | return -ENOMEM; |
1642 | goto out; | ||
1643 | } | ||
1644 | 1630 | ||
1645 | inode->i_fop = &sel_class_ops; | 1631 | inode->i_fop = &sel_class_ops; |
1646 | inode->i_ino = sel_class_to_ino(index); | 1632 | inode->i_ino = sel_class_to_ino(index); |
1647 | d_add(dentry, inode); | 1633 | d_add(dentry, inode); |
1648 | 1634 | ||
1649 | dentry = d_alloc_name(dir, "perms"); | 1635 | dentry = d_alloc_name(dir, "perms"); |
1650 | if (!dentry) { | 1636 | if (!dentry) |
1651 | rc = -ENOMEM; | 1637 | return -ENOMEM; |
1652 | goto out; | ||
1653 | } | ||
1654 | 1638 | ||
1655 | rc = sel_make_dir(dir->d_inode, dentry, &last_class_ino); | 1639 | rc = sel_make_dir(dir->d_inode, dentry, &last_class_ino); |
1656 | if (rc) | 1640 | if (rc) |
1657 | goto out; | 1641 | return rc; |
1658 | 1642 | ||
1659 | rc = sel_make_perm_files(classname, index, dentry); | 1643 | rc = sel_make_perm_files(classname, index, dentry); |
1660 | 1644 | ||
1661 | out: | ||
1662 | return rc; | 1645 | return rc; |
1663 | } | 1646 | } |
1664 | 1647 | ||
@@ -1688,15 +1671,15 @@ static void sel_remove_classes(void) | |||
1688 | 1671 | ||
1689 | static int sel_make_classes(void) | 1672 | static int sel_make_classes(void) |
1690 | { | 1673 | { |
1691 | int rc = 0, nclasses, i; | 1674 | int rc, nclasses, i; |
1692 | char **classes; | 1675 | char **classes; |
1693 | 1676 | ||
1694 | /* delete any existing entries */ | 1677 | /* delete any existing entries */ |
1695 | sel_remove_classes(); | 1678 | sel_remove_classes(); |
1696 | 1679 | ||
1697 | rc = security_get_classes(&classes, &nclasses); | 1680 | rc = security_get_classes(&classes, &nclasses); |
1698 | if (rc < 0) | 1681 | if (rc) |
1699 | goto out; | 1682 | return rc; |
1700 | 1683 | ||
1701 | /* +2 since classes are 1-indexed */ | 1684 | /* +2 since classes are 1-indexed */ |
1702 | last_class_ino = sel_class_to_ino(nclasses + 2); | 1685 | last_class_ino = sel_class_to_ino(nclasses + 2); |
@@ -1704,29 +1687,27 @@ static int sel_make_classes(void) | |||
1704 | for (i = 0; i < nclasses; i++) { | 1687 | for (i = 0; i < nclasses; i++) { |
1705 | struct dentry *class_name_dir; | 1688 | struct dentry *class_name_dir; |
1706 | 1689 | ||
1690 | rc = -ENOMEM; | ||
1707 | class_name_dir = d_alloc_name(class_dir, classes[i]); | 1691 | class_name_dir = d_alloc_name(class_dir, classes[i]); |
1708 | if (!class_name_dir) { | 1692 | if (!class_name_dir) |
1709 | rc = -ENOMEM; | 1693 | goto out; |
1710 | goto out1; | ||
1711 | } | ||
1712 | 1694 | ||
1713 | rc = sel_make_dir(class_dir->d_inode, class_name_dir, | 1695 | rc = sel_make_dir(class_dir->d_inode, class_name_dir, |
1714 | &last_class_ino); | 1696 | &last_class_ino); |
1715 | if (rc) | 1697 | if (rc) |
1716 | goto out1; | 1698 | goto out; |
1717 | 1699 | ||
1718 | /* i+1 since class values are 1-indexed */ | 1700 | /* i+1 since class values are 1-indexed */ |
1719 | rc = sel_make_class_dir_entries(classes[i], i + 1, | 1701 | rc = sel_make_class_dir_entries(classes[i], i + 1, |
1720 | class_name_dir); | 1702 | class_name_dir); |
1721 | if (rc) | 1703 | if (rc) |
1722 | goto out1; | 1704 | goto out; |
1723 | } | 1705 | } |
1724 | 1706 | rc = 0; | |
1725 | out1: | 1707 | out: |
1726 | for (i = 0; i < nclasses; i++) | 1708 | for (i = 0; i < nclasses; i++) |
1727 | kfree(classes[i]); | 1709 | kfree(classes[i]); |
1728 | kfree(classes); | 1710 | kfree(classes); |
1729 | out: | ||
1730 | return rc; | 1711 | return rc; |
1731 | } | 1712 | } |
1732 | 1713 | ||
@@ -1763,14 +1744,12 @@ static int sel_make_policycap(void) | |||
1763 | static int sel_make_dir(struct inode *dir, struct dentry *dentry, | 1744 | static int sel_make_dir(struct inode *dir, struct dentry *dentry, |
1764 | unsigned long *ino) | 1745 | unsigned long *ino) |
1765 | { | 1746 | { |
1766 | int ret = 0; | ||
1767 | struct inode *inode; | 1747 | struct inode *inode; |
1768 | 1748 | ||
1769 | inode = sel_make_inode(dir->i_sb, S_IFDIR | S_IRUGO | S_IXUGO); | 1749 | inode = sel_make_inode(dir->i_sb, S_IFDIR | S_IRUGO | S_IXUGO); |
1770 | if (!inode) { | 1750 | if (!inode) |
1771 | ret = -ENOMEM; | 1751 | return -ENOMEM; |
1772 | goto out; | 1752 | |
1773 | } | ||
1774 | inode->i_op = &simple_dir_inode_operations; | 1753 | inode->i_op = &simple_dir_inode_operations; |
1775 | inode->i_fop = &simple_dir_operations; | 1754 | inode->i_fop = &simple_dir_operations; |
1776 | inode->i_ino = ++(*ino); | 1755 | inode->i_ino = ++(*ino); |
@@ -1779,8 +1758,8 @@ static int sel_make_dir(struct inode *dir, struct dentry *dentry, | |||
1779 | d_add(dentry, inode); | 1758 | d_add(dentry, inode); |
1780 | /* bump link count on parent directory, too */ | 1759 | /* bump link count on parent directory, too */ |
1781 | inc_nlink(dir); | 1760 | inc_nlink(dir); |
1782 | out: | 1761 | |
1783 | return ret; | 1762 | return 0; |
1784 | } | 1763 | } |
1785 | 1764 | ||
1786 | static int sel_fill_super(struct super_block *sb, void *data, int silent) | 1765 | static int sel_fill_super(struct super_block *sb, void *data, int silent) |
@@ -1816,11 +1795,10 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1816 | 1795 | ||
1817 | root_inode = sb->s_root->d_inode; | 1796 | root_inode = sb->s_root->d_inode; |
1818 | 1797 | ||
1798 | ret = -ENOMEM; | ||
1819 | dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME); | 1799 | dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME); |
1820 | if (!dentry) { | 1800 | if (!dentry) |
1821 | ret = -ENOMEM; | ||
1822 | goto err; | 1801 | goto err; |
1823 | } | ||
1824 | 1802 | ||
1825 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); | 1803 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); |
1826 | if (ret) | 1804 | if (ret) |
@@ -1828,17 +1806,16 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1828 | 1806 | ||
1829 | bool_dir = dentry; | 1807 | bool_dir = dentry; |
1830 | 1808 | ||
1809 | ret = -ENOMEM; | ||
1831 | dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME); | 1810 | dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME); |
1832 | if (!dentry) { | 1811 | if (!dentry) |
1833 | ret = -ENOMEM; | ||
1834 | goto err; | 1812 | goto err; |
1835 | } | ||
1836 | 1813 | ||
1814 | ret = -ENOMEM; | ||
1837 | inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO); | 1815 | inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO); |
1838 | if (!inode) { | 1816 | if (!inode) |
1839 | ret = -ENOMEM; | ||
1840 | goto err; | 1817 | goto err; |
1841 | } | 1818 | |
1842 | inode->i_ino = ++sel_last_ino; | 1819 | inode->i_ino = ++sel_last_ino; |
1843 | isec = (struct inode_security_struct *)inode->i_security; | 1820 | isec = (struct inode_security_struct *)inode->i_security; |
1844 | isec->sid = SECINITSID_DEVNULL; | 1821 | isec->sid = SECINITSID_DEVNULL; |
@@ -1849,11 +1826,10 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1849 | d_add(dentry, inode); | 1826 | d_add(dentry, inode); |
1850 | selinux_null = dentry; | 1827 | selinux_null = dentry; |
1851 | 1828 | ||
1829 | ret = -ENOMEM; | ||
1852 | dentry = d_alloc_name(sb->s_root, "avc"); | 1830 | dentry = d_alloc_name(sb->s_root, "avc"); |
1853 | if (!dentry) { | 1831 | if (!dentry) |
1854 | ret = -ENOMEM; | ||
1855 | goto err; | 1832 | goto err; |
1856 | } | ||
1857 | 1833 | ||
1858 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); | 1834 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); |
1859 | if (ret) | 1835 | if (ret) |
@@ -1863,11 +1839,10 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1863 | if (ret) | 1839 | if (ret) |
1864 | goto err; | 1840 | goto err; |
1865 | 1841 | ||
1842 | ret = -ENOMEM; | ||
1866 | dentry = d_alloc_name(sb->s_root, "initial_contexts"); | 1843 | dentry = d_alloc_name(sb->s_root, "initial_contexts"); |
1867 | if (!dentry) { | 1844 | if (!dentry) |
1868 | ret = -ENOMEM; | ||
1869 | goto err; | 1845 | goto err; |
1870 | } | ||
1871 | 1846 | ||
1872 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); | 1847 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); |
1873 | if (ret) | 1848 | if (ret) |
@@ -1877,11 +1852,10 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1877 | if (ret) | 1852 | if (ret) |
1878 | goto err; | 1853 | goto err; |
1879 | 1854 | ||
1855 | ret = -ENOMEM; | ||
1880 | dentry = d_alloc_name(sb->s_root, "class"); | 1856 | dentry = d_alloc_name(sb->s_root, "class"); |
1881 | if (!dentry) { | 1857 | if (!dentry) |
1882 | ret = -ENOMEM; | ||
1883 | goto err; | 1858 | goto err; |
1884 | } | ||
1885 | 1859 | ||
1886 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); | 1860 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); |
1887 | if (ret) | 1861 | if (ret) |
@@ -1889,11 +1863,10 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1889 | 1863 | ||
1890 | class_dir = dentry; | 1864 | class_dir = dentry; |
1891 | 1865 | ||
1866 | ret = -ENOMEM; | ||
1892 | dentry = d_alloc_name(sb->s_root, "policy_capabilities"); | 1867 | dentry = d_alloc_name(sb->s_root, "policy_capabilities"); |
1893 | if (!dentry) { | 1868 | if (!dentry) |
1894 | ret = -ENOMEM; | ||
1895 | goto err; | 1869 | goto err; |
1896 | } | ||
1897 | 1870 | ||
1898 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); | 1871 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); |
1899 | if (ret) | 1872 | if (ret) |
@@ -1901,12 +1874,11 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1901 | 1874 | ||
1902 | policycap_dir = dentry; | 1875 | policycap_dir = dentry; |
1903 | 1876 | ||
1904 | out: | 1877 | return 0; |
1905 | return ret; | ||
1906 | err: | 1878 | err: |
1907 | printk(KERN_ERR "SELinux: %s: failed while creating inodes\n", | 1879 | printk(KERN_ERR "SELinux: %s: failed while creating inodes\n", |
1908 | __func__); | 1880 | __func__); |
1909 | goto out; | 1881 | return ret; |
1910 | } | 1882 | } |
1911 | 1883 | ||
1912 | static struct dentry *sel_mount(struct file_system_type *fs_type, | 1884 | static struct dentry *sel_mount(struct file_system_type *fs_type, |
@@ -1930,14 +1902,16 @@ static int __init init_sel_fs(void) | |||
1930 | if (!selinux_enabled) | 1902 | if (!selinux_enabled) |
1931 | return 0; | 1903 | return 0; |
1932 | err = register_filesystem(&sel_fs_type); | 1904 | err = register_filesystem(&sel_fs_type); |
1933 | if (!err) { | 1905 | if (err) |
1934 | selinuxfs_mount = kern_mount(&sel_fs_type); | 1906 | return err; |
1935 | if (IS_ERR(selinuxfs_mount)) { | 1907 | |
1936 | printk(KERN_ERR "selinuxfs: could not mount!\n"); | 1908 | selinuxfs_mount = kern_mount(&sel_fs_type); |
1937 | err = PTR_ERR(selinuxfs_mount); | 1909 | if (IS_ERR(selinuxfs_mount)) { |
1938 | selinuxfs_mount = NULL; | 1910 | printk(KERN_ERR "selinuxfs: could not mount!\n"); |
1939 | } | 1911 | err = PTR_ERR(selinuxfs_mount); |
1912 | selinuxfs_mount = NULL; | ||
1940 | } | 1913 | } |
1914 | |||
1941 | return err; | 1915 | return err; |
1942 | } | 1916 | } |
1943 | 1917 | ||