diff options
Diffstat (limited to 'security/selinux/selinuxfs.c')
-rw-r--r-- | security/selinux/selinuxfs.c | 649 |
1 files changed, 311 insertions, 338 deletions
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 43deac219491..ea39cb742ae5 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 | } |
@@ -978,7 +989,6 @@ static struct inode *sel_make_inode(struct super_block *sb, int mode) | |||
978 | struct inode *ret = new_inode(sb); | 989 | struct inode *ret = new_inode(sb); |
979 | 990 | ||
980 | if (ret) { | 991 | if (ret) { |
981 | ret->i_ino = get_next_ino(); | ||
982 | ret->i_mode = mode; | 992 | ret->i_mode = mode; |
983 | ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME; | 993 | ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME; |
984 | } | 994 | } |
@@ -998,16 +1008,14 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, | |||
998 | 1008 | ||
999 | mutex_lock(&sel_mutex); | 1009 | mutex_lock(&sel_mutex); |
1000 | 1010 | ||
1001 | if (index >= bool_num || strcmp(name, bool_pending_names[index])) { | 1011 | ret = -EINVAL; |
1002 | ret = -EINVAL; | 1012 | if (index >= bool_num || strcmp(name, bool_pending_names[index])) |
1003 | goto out; | 1013 | goto out; |
1004 | } | ||
1005 | 1014 | ||
1015 | ret = -ENOMEM; | ||
1006 | page = (char *)get_zeroed_page(GFP_KERNEL); | 1016 | page = (char *)get_zeroed_page(GFP_KERNEL); |
1007 | if (!page) { | 1017 | if (!page) |
1008 | ret = -ENOMEM; | ||
1009 | goto out; | 1018 | goto out; |
1010 | } | ||
1011 | 1019 | ||
1012 | cur_enforcing = security_get_bool_value(index); | 1020 | cur_enforcing = security_get_bool_value(index); |
1013 | if (cur_enforcing < 0) { | 1021 | if (cur_enforcing < 0) { |
@@ -1019,8 +1027,7 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, | |||
1019 | ret = simple_read_from_buffer(buf, count, ppos, page, length); | 1027 | ret = simple_read_from_buffer(buf, count, ppos, page, length); |
1020 | out: | 1028 | out: |
1021 | mutex_unlock(&sel_mutex); | 1029 | mutex_unlock(&sel_mutex); |
1022 | if (page) | 1030 | free_page((unsigned long)page); |
1023 | free_page((unsigned long)page); | ||
1024 | return ret; | 1031 | return ret; |
1025 | } | 1032 | } |
1026 | 1033 | ||
@@ -1040,26 +1047,23 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, | |||
1040 | if (length) | 1047 | if (length) |
1041 | goto out; | 1048 | goto out; |
1042 | 1049 | ||
1043 | if (index >= bool_num || strcmp(name, bool_pending_names[index])) { | 1050 | length = -EINVAL; |
1044 | length = -EINVAL; | 1051 | if (index >= bool_num || strcmp(name, bool_pending_names[index])) |
1045 | goto out; | 1052 | goto out; |
1046 | } | ||
1047 | 1053 | ||
1048 | if (count >= PAGE_SIZE) { | 1054 | length = -ENOMEM; |
1049 | length = -ENOMEM; | 1055 | if (count >= PAGE_SIZE) |
1050 | goto out; | 1056 | goto out; |
1051 | } | ||
1052 | 1057 | ||
1053 | if (*ppos != 0) { | 1058 | /* No partial writes. */ |
1054 | /* No partial writes. */ | 1059 | length = -EINVAL; |
1055 | length = -EINVAL; | 1060 | if (*ppos != 0) |
1056 | goto out; | 1061 | goto out; |
1057 | } | 1062 | |
1063 | length = -ENOMEM; | ||
1058 | page = (char *)get_zeroed_page(GFP_KERNEL); | 1064 | page = (char *)get_zeroed_page(GFP_KERNEL); |
1059 | if (!page) { | 1065 | if (!page) |
1060 | length = -ENOMEM; | ||
1061 | goto out; | 1066 | goto out; |
1062 | } | ||
1063 | 1067 | ||
1064 | length = -EFAULT; | 1068 | length = -EFAULT; |
1065 | if (copy_from_user(page, buf, count)) | 1069 | if (copy_from_user(page, buf, count)) |
@@ -1077,8 +1081,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, | |||
1077 | 1081 | ||
1078 | out: | 1082 | out: |
1079 | mutex_unlock(&sel_mutex); | 1083 | mutex_unlock(&sel_mutex); |
1080 | if (page) | 1084 | free_page((unsigned long) page); |
1081 | free_page((unsigned long) page); | ||
1082 | return length; | 1085 | return length; |
1083 | } | 1086 | } |
1084 | 1087 | ||
@@ -1102,19 +1105,19 @@ static ssize_t sel_commit_bools_write(struct file *filep, | |||
1102 | if (length) | 1105 | if (length) |
1103 | goto out; | 1106 | goto out; |
1104 | 1107 | ||
1105 | if (count >= PAGE_SIZE) { | 1108 | length = -ENOMEM; |
1106 | length = -ENOMEM; | 1109 | if (count >= PAGE_SIZE) |
1107 | goto out; | 1110 | goto out; |
1108 | } | 1111 | |
1109 | if (*ppos != 0) { | 1112 | /* No partial writes. */ |
1110 | /* No partial writes. */ | 1113 | length = -EINVAL; |
1114 | if (*ppos != 0) | ||
1111 | goto out; | 1115 | goto out; |
1112 | } | 1116 | |
1117 | length = -ENOMEM; | ||
1113 | page = (char *)get_zeroed_page(GFP_KERNEL); | 1118 | page = (char *)get_zeroed_page(GFP_KERNEL); |
1114 | if (!page) { | 1119 | if (!page) |
1115 | length = -ENOMEM; | ||
1116 | goto out; | 1120 | goto out; |
1117 | } | ||
1118 | 1121 | ||
1119 | length = -EFAULT; | 1122 | length = -EFAULT; |
1120 | if (copy_from_user(page, buf, count)) | 1123 | if (copy_from_user(page, buf, count)) |
@@ -1124,15 +1127,16 @@ static ssize_t sel_commit_bools_write(struct file *filep, | |||
1124 | if (sscanf(page, "%d", &new_value) != 1) | 1127 | if (sscanf(page, "%d", &new_value) != 1) |
1125 | goto out; | 1128 | goto out; |
1126 | 1129 | ||
1130 | length = 0; | ||
1127 | if (new_value && bool_pending_values) | 1131 | if (new_value && bool_pending_values) |
1128 | security_set_bools(bool_num, bool_pending_values); | 1132 | length = security_set_bools(bool_num, bool_pending_values); |
1129 | 1133 | ||
1130 | length = count; | 1134 | if (!length) |
1135 | length = count; | ||
1131 | 1136 | ||
1132 | out: | 1137 | out: |
1133 | mutex_unlock(&sel_mutex); | 1138 | mutex_unlock(&sel_mutex); |
1134 | if (page) | 1139 | free_page((unsigned long) page); |
1135 | free_page((unsigned long) page); | ||
1136 | return length; | 1140 | return length; |
1137 | } | 1141 | } |
1138 | 1142 | ||
@@ -1173,7 +1177,7 @@ static void sel_remove_entries(struct dentry *de) | |||
1173 | 1177 | ||
1174 | static int sel_make_bools(void) | 1178 | static int sel_make_bools(void) |
1175 | { | 1179 | { |
1176 | int i, ret = 0; | 1180 | int i, ret; |
1177 | ssize_t len; | 1181 | ssize_t len; |
1178 | struct dentry *dentry = NULL; | 1182 | struct dentry *dentry = NULL; |
1179 | struct dentry *dir = bool_dir; | 1183 | struct dentry *dir = bool_dir; |
@@ -1194,38 +1198,40 @@ static int sel_make_bools(void) | |||
1194 | 1198 | ||
1195 | sel_remove_entries(dir); | 1199 | sel_remove_entries(dir); |
1196 | 1200 | ||
1201 | ret = -ENOMEM; | ||
1197 | page = (char *)get_zeroed_page(GFP_KERNEL); | 1202 | page = (char *)get_zeroed_page(GFP_KERNEL); |
1198 | if (!page) | 1203 | if (!page) |
1199 | return -ENOMEM; | 1204 | goto out; |
1200 | 1205 | ||
1201 | ret = security_get_bools(&num, &names, &values); | 1206 | ret = security_get_bools(&num, &names, &values); |
1202 | if (ret != 0) | 1207 | if (ret) |
1203 | goto out; | 1208 | goto out; |
1204 | 1209 | ||
1205 | for (i = 0; i < num; i++) { | 1210 | for (i = 0; i < num; i++) { |
1211 | ret = -ENOMEM; | ||
1206 | dentry = d_alloc_name(dir, names[i]); | 1212 | dentry = d_alloc_name(dir, names[i]); |
1207 | if (!dentry) { | 1213 | if (!dentry) |
1208 | ret = -ENOMEM; | 1214 | goto out; |
1209 | goto err; | 1215 | |
1210 | } | 1216 | ret = -ENOMEM; |
1211 | inode = sel_make_inode(dir->d_sb, S_IFREG | S_IRUGO | S_IWUSR); | 1217 | inode = sel_make_inode(dir->d_sb, S_IFREG | S_IRUGO | S_IWUSR); |
1212 | if (!inode) { | 1218 | if (!inode) |
1213 | ret = -ENOMEM; | 1219 | goto out; |
1214 | goto err; | ||
1215 | } | ||
1216 | 1220 | ||
1221 | ret = -EINVAL; | ||
1217 | len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]); | 1222 | len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]); |
1218 | if (len < 0) { | 1223 | if (len < 0) |
1219 | ret = -EINVAL; | 1224 | goto out; |
1220 | goto err; | 1225 | |
1221 | } else if (len >= PAGE_SIZE) { | 1226 | ret = -ENAMETOOLONG; |
1222 | ret = -ENAMETOOLONG; | 1227 | if (len >= PAGE_SIZE) |
1223 | goto err; | 1228 | goto out; |
1224 | } | 1229 | |
1225 | isec = (struct inode_security_struct *)inode->i_security; | 1230 | isec = (struct inode_security_struct *)inode->i_security; |
1226 | ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid); | 1231 | ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid); |
1227 | if (ret) | 1232 | if (ret) |
1228 | goto err; | 1233 | goto out; |
1234 | |||
1229 | isec->sid = sid; | 1235 | isec->sid = sid; |
1230 | isec->initialized = 1; | 1236 | isec->initialized = 1; |
1231 | inode->i_fop = &sel_bool_ops; | 1237 | inode->i_fop = &sel_bool_ops; |
@@ -1235,10 +1241,12 @@ static int sel_make_bools(void) | |||
1235 | bool_num = num; | 1241 | bool_num = num; |
1236 | bool_pending_names = names; | 1242 | bool_pending_names = names; |
1237 | bool_pending_values = values; | 1243 | bool_pending_values = values; |
1244 | |||
1245 | free_page((unsigned long)page); | ||
1246 | return 0; | ||
1238 | out: | 1247 | out: |
1239 | free_page((unsigned long)page); | 1248 | free_page((unsigned long)page); |
1240 | return ret; | 1249 | |
1241 | err: | ||
1242 | if (names) { | 1250 | if (names) { |
1243 | for (i = 0; i < num; i++) | 1251 | for (i = 0; i < num; i++) |
1244 | kfree(names[i]); | 1252 | kfree(names[i]); |
@@ -1246,8 +1254,8 @@ err: | |||
1246 | } | 1254 | } |
1247 | kfree(values); | 1255 | kfree(values); |
1248 | sel_remove_entries(dir); | 1256 | sel_remove_entries(dir); |
1249 | ret = -ENOMEM; | 1257 | |
1250 | goto out; | 1258 | return ret; |
1251 | } | 1259 | } |
1252 | 1260 | ||
1253 | #define NULL_FILE_NAME "null" | 1261 | #define NULL_FILE_NAME "null" |
@@ -1269,47 +1277,41 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file, | |||
1269 | size_t count, loff_t *ppos) | 1277 | size_t count, loff_t *ppos) |
1270 | 1278 | ||
1271 | { | 1279 | { |
1272 | char *page; | 1280 | char *page = NULL; |
1273 | ssize_t ret; | 1281 | ssize_t ret; |
1274 | int new_value; | 1282 | int new_value; |
1275 | 1283 | ||
1276 | if (count >= PAGE_SIZE) { | 1284 | ret = task_has_security(current, SECURITY__SETSECPARAM); |
1277 | ret = -ENOMEM; | 1285 | if (ret) |
1278 | goto out; | 1286 | goto out; |
1279 | } | ||
1280 | 1287 | ||
1281 | if (*ppos != 0) { | 1288 | ret = -ENOMEM; |
1282 | /* No partial writes. */ | 1289 | if (count >= PAGE_SIZE) |
1283 | ret = -EINVAL; | ||
1284 | goto out; | 1290 | goto out; |
1285 | } | ||
1286 | 1291 | ||
1292 | /* No partial writes. */ | ||
1293 | ret = -EINVAL; | ||
1294 | if (*ppos != 0) | ||
1295 | goto out; | ||
1296 | |||
1297 | ret = -ENOMEM; | ||
1287 | page = (char *)get_zeroed_page(GFP_KERNEL); | 1298 | page = (char *)get_zeroed_page(GFP_KERNEL); |
1288 | if (!page) { | 1299 | if (!page) |
1289 | ret = -ENOMEM; | ||
1290 | goto out; | 1300 | goto out; |
1291 | } | ||
1292 | 1301 | ||
1293 | if (copy_from_user(page, buf, count)) { | 1302 | ret = -EFAULT; |
1294 | ret = -EFAULT; | 1303 | if (copy_from_user(page, buf, count)) |
1295 | goto out_free; | 1304 | goto out; |
1296 | } | ||
1297 | 1305 | ||
1298 | if (sscanf(page, "%u", &new_value) != 1) { | 1306 | ret = -EINVAL; |
1299 | ret = -EINVAL; | 1307 | if (sscanf(page, "%u", &new_value) != 1) |
1300 | goto out; | 1308 | goto out; |
1301 | } | ||
1302 | 1309 | ||
1303 | if (new_value != avc_cache_threshold) { | 1310 | avc_cache_threshold = new_value; |
1304 | ret = task_has_security(current, SECURITY__SETSECPARAM); | 1311 | |
1305 | if (ret) | ||
1306 | goto out_free; | ||
1307 | avc_cache_threshold = new_value; | ||
1308 | } | ||
1309 | ret = count; | 1312 | ret = count; |
1310 | out_free: | ||
1311 | free_page((unsigned long)page); | ||
1312 | out: | 1313 | out: |
1314 | free_page((unsigned long)page); | ||
1313 | return ret; | 1315 | return ret; |
1314 | } | 1316 | } |
1315 | 1317 | ||
@@ -1317,19 +1319,18 @@ static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf, | |||
1317 | size_t count, loff_t *ppos) | 1319 | size_t count, loff_t *ppos) |
1318 | { | 1320 | { |
1319 | char *page; | 1321 | char *page; |
1320 | ssize_t ret = 0; | 1322 | ssize_t length; |
1321 | 1323 | ||
1322 | page = (char *)__get_free_page(GFP_KERNEL); | 1324 | page = (char *)__get_free_page(GFP_KERNEL); |
1323 | if (!page) { | 1325 | if (!page) |
1324 | ret = -ENOMEM; | 1326 | return -ENOMEM; |
1325 | goto out; | 1327 | |
1326 | } | 1328 | length = avc_get_hash_stats(page); |
1327 | ret = avc_get_hash_stats(page); | 1329 | if (length >= 0) |
1328 | if (ret >= 0) | 1330 | length = simple_read_from_buffer(buf, count, ppos, page, length); |
1329 | ret = simple_read_from_buffer(buf, count, ppos, page, ret); | ||
1330 | free_page((unsigned long)page); | 1331 | free_page((unsigned long)page); |
1331 | out: | 1332 | |
1332 | return ret; | 1333 | return length; |
1333 | } | 1334 | } |
1334 | 1335 | ||
1335 | static const struct file_operations sel_avc_cache_threshold_ops = { | 1336 | static const struct file_operations sel_avc_cache_threshold_ops = { |
@@ -1411,7 +1412,7 @@ static const struct file_operations sel_avc_cache_stats_ops = { | |||
1411 | 1412 | ||
1412 | static int sel_make_avc_files(struct dentry *dir) | 1413 | static int sel_make_avc_files(struct dentry *dir) |
1413 | { | 1414 | { |
1414 | int i, ret = 0; | 1415 | int i; |
1415 | static struct tree_descr files[] = { | 1416 | static struct tree_descr files[] = { |
1416 | { "cache_threshold", | 1417 | { "cache_threshold", |
1417 | &sel_avc_cache_threshold_ops, S_IRUGO|S_IWUSR }, | 1418 | &sel_avc_cache_threshold_ops, S_IRUGO|S_IWUSR }, |
@@ -1426,22 +1427,19 @@ static int sel_make_avc_files(struct dentry *dir) | |||
1426 | struct dentry *dentry; | 1427 | struct dentry *dentry; |
1427 | 1428 | ||
1428 | dentry = d_alloc_name(dir, files[i].name); | 1429 | dentry = d_alloc_name(dir, files[i].name); |
1429 | if (!dentry) { | 1430 | if (!dentry) |
1430 | ret = -ENOMEM; | 1431 | return -ENOMEM; |
1431 | goto out; | ||
1432 | } | ||
1433 | 1432 | ||
1434 | inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode); | 1433 | inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode); |
1435 | if (!inode) { | 1434 | if (!inode) |
1436 | ret = -ENOMEM; | 1435 | return -ENOMEM; |
1437 | goto out; | 1436 | |
1438 | } | ||
1439 | inode->i_fop = files[i].ops; | 1437 | inode->i_fop = files[i].ops; |
1440 | inode->i_ino = ++sel_last_ino; | 1438 | inode->i_ino = ++sel_last_ino; |
1441 | d_add(dentry, inode); | 1439 | d_add(dentry, inode); |
1442 | } | 1440 | } |
1443 | out: | 1441 | |
1444 | return ret; | 1442 | return 0; |
1445 | } | 1443 | } |
1446 | 1444 | ||
1447 | static ssize_t sel_read_initcon(struct file *file, char __user *buf, | 1445 | static ssize_t sel_read_initcon(struct file *file, char __user *buf, |
@@ -1455,7 +1453,7 @@ static ssize_t sel_read_initcon(struct file *file, char __user *buf, | |||
1455 | inode = file->f_path.dentry->d_inode; | 1453 | inode = file->f_path.dentry->d_inode; |
1456 | sid = inode->i_ino&SEL_INO_MASK; | 1454 | sid = inode->i_ino&SEL_INO_MASK; |
1457 | ret = security_sid_to_context(sid, &con, &len); | 1455 | ret = security_sid_to_context(sid, &con, &len); |
1458 | if (ret < 0) | 1456 | if (ret) |
1459 | return ret; | 1457 | return ret; |
1460 | 1458 | ||
1461 | ret = simple_read_from_buffer(buf, count, ppos, con, len); | 1459 | ret = simple_read_from_buffer(buf, count, ppos, con, len); |
@@ -1470,28 +1468,25 @@ static const struct file_operations sel_initcon_ops = { | |||
1470 | 1468 | ||
1471 | static int sel_make_initcon_files(struct dentry *dir) | 1469 | static int sel_make_initcon_files(struct dentry *dir) |
1472 | { | 1470 | { |
1473 | int i, ret = 0; | 1471 | int i; |
1474 | 1472 | ||
1475 | for (i = 1; i <= SECINITSID_NUM; i++) { | 1473 | for (i = 1; i <= SECINITSID_NUM; i++) { |
1476 | struct inode *inode; | 1474 | struct inode *inode; |
1477 | struct dentry *dentry; | 1475 | struct dentry *dentry; |
1478 | dentry = d_alloc_name(dir, security_get_initial_sid_context(i)); | 1476 | dentry = d_alloc_name(dir, security_get_initial_sid_context(i)); |
1479 | if (!dentry) { | 1477 | if (!dentry) |
1480 | ret = -ENOMEM; | 1478 | return -ENOMEM; |
1481 | goto out; | ||
1482 | } | ||
1483 | 1479 | ||
1484 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); | 1480 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); |
1485 | if (!inode) { | 1481 | if (!inode) |
1486 | ret = -ENOMEM; | 1482 | return -ENOMEM; |
1487 | goto out; | 1483 | |
1488 | } | ||
1489 | inode->i_fop = &sel_initcon_ops; | 1484 | inode->i_fop = &sel_initcon_ops; |
1490 | inode->i_ino = i|SEL_INITCON_INO_OFFSET; | 1485 | inode->i_ino = i|SEL_INITCON_INO_OFFSET; |
1491 | d_add(dentry, inode); | 1486 | d_add(dentry, inode); |
1492 | } | 1487 | } |
1493 | out: | 1488 | |
1494 | return ret; | 1489 | return 0; |
1495 | } | 1490 | } |
1496 | 1491 | ||
1497 | static inline unsigned int sel_div(unsigned long a, unsigned long b) | 1492 | static inline unsigned int sel_div(unsigned long a, unsigned long b) |
@@ -1527,15 +1522,13 @@ static ssize_t sel_read_class(struct file *file, char __user *buf, | |||
1527 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; | 1522 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; |
1528 | 1523 | ||
1529 | page = (char *)__get_free_page(GFP_KERNEL); | 1524 | page = (char *)__get_free_page(GFP_KERNEL); |
1530 | if (!page) { | 1525 | if (!page) |
1531 | rc = -ENOMEM; | 1526 | return -ENOMEM; |
1532 | goto out; | ||
1533 | } | ||
1534 | 1527 | ||
1535 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino)); | 1528 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino)); |
1536 | rc = simple_read_from_buffer(buf, count, ppos, page, len); | 1529 | rc = simple_read_from_buffer(buf, count, ppos, page, len); |
1537 | free_page((unsigned long)page); | 1530 | free_page((unsigned long)page); |
1538 | out: | 1531 | |
1539 | return rc; | 1532 | return rc; |
1540 | } | 1533 | } |
1541 | 1534 | ||
@@ -1552,15 +1545,13 @@ static ssize_t sel_read_perm(struct file *file, char __user *buf, | |||
1552 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; | 1545 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; |
1553 | 1546 | ||
1554 | page = (char *)__get_free_page(GFP_KERNEL); | 1547 | page = (char *)__get_free_page(GFP_KERNEL); |
1555 | if (!page) { | 1548 | if (!page) |
1556 | rc = -ENOMEM; | 1549 | return -ENOMEM; |
1557 | goto out; | ||
1558 | } | ||
1559 | 1550 | ||
1560 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_perm(ino)); | 1551 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_perm(ino)); |
1561 | rc = simple_read_from_buffer(buf, count, ppos, page, len); | 1552 | rc = simple_read_from_buffer(buf, count, ppos, page, len); |
1562 | free_page((unsigned long)page); | 1553 | free_page((unsigned long)page); |
1563 | out: | 1554 | |
1564 | return rc; | 1555 | return rc; |
1565 | } | 1556 | } |
1566 | 1557 | ||
@@ -1591,39 +1582,37 @@ static const struct file_operations sel_policycap_ops = { | |||
1591 | static int sel_make_perm_files(char *objclass, int classvalue, | 1582 | static int sel_make_perm_files(char *objclass, int classvalue, |
1592 | struct dentry *dir) | 1583 | struct dentry *dir) |
1593 | { | 1584 | { |
1594 | int i, rc = 0, nperms; | 1585 | int i, rc, nperms; |
1595 | char **perms; | 1586 | char **perms; |
1596 | 1587 | ||
1597 | rc = security_get_permissions(objclass, &perms, &nperms); | 1588 | rc = security_get_permissions(objclass, &perms, &nperms); |
1598 | if (rc) | 1589 | if (rc) |
1599 | goto out; | 1590 | return rc; |
1600 | 1591 | ||
1601 | for (i = 0; i < nperms; i++) { | 1592 | for (i = 0; i < nperms; i++) { |
1602 | struct inode *inode; | 1593 | struct inode *inode; |
1603 | struct dentry *dentry; | 1594 | struct dentry *dentry; |
1604 | 1595 | ||
1596 | rc = -ENOMEM; | ||
1605 | dentry = d_alloc_name(dir, perms[i]); | 1597 | dentry = d_alloc_name(dir, perms[i]); |
1606 | if (!dentry) { | 1598 | if (!dentry) |
1607 | rc = -ENOMEM; | 1599 | goto out; |
1608 | goto out1; | ||
1609 | } | ||
1610 | 1600 | ||
1601 | rc = -ENOMEM; | ||
1611 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); | 1602 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); |
1612 | if (!inode) { | 1603 | if (!inode) |
1613 | rc = -ENOMEM; | 1604 | goto out; |
1614 | goto out1; | 1605 | |
1615 | } | ||
1616 | inode->i_fop = &sel_perm_ops; | 1606 | inode->i_fop = &sel_perm_ops; |
1617 | /* i+1 since perm values are 1-indexed */ | 1607 | /* i+1 since perm values are 1-indexed */ |
1618 | inode->i_ino = sel_perm_to_ino(classvalue, i + 1); | 1608 | inode->i_ino = sel_perm_to_ino(classvalue, i + 1); |
1619 | d_add(dentry, inode); | 1609 | d_add(dentry, inode); |
1620 | } | 1610 | } |
1621 | 1611 | rc = 0; | |
1622 | out1: | 1612 | out: |
1623 | for (i = 0; i < nperms; i++) | 1613 | for (i = 0; i < nperms; i++) |
1624 | kfree(perms[i]); | 1614 | kfree(perms[i]); |
1625 | kfree(perms); | 1615 | kfree(perms); |
1626 | out: | ||
1627 | return rc; | 1616 | return rc; |
1628 | } | 1617 | } |
1629 | 1618 | ||
@@ -1635,34 +1624,27 @@ static int sel_make_class_dir_entries(char *classname, int index, | |||
1635 | int rc; | 1624 | int rc; |
1636 | 1625 | ||
1637 | dentry = d_alloc_name(dir, "index"); | 1626 | dentry = d_alloc_name(dir, "index"); |
1638 | if (!dentry) { | 1627 | if (!dentry) |
1639 | rc = -ENOMEM; | 1628 | return -ENOMEM; |
1640 | goto out; | ||
1641 | } | ||
1642 | 1629 | ||
1643 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); | 1630 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); |
1644 | if (!inode) { | 1631 | if (!inode) |
1645 | rc = -ENOMEM; | 1632 | return -ENOMEM; |
1646 | goto out; | ||
1647 | } | ||
1648 | 1633 | ||
1649 | inode->i_fop = &sel_class_ops; | 1634 | inode->i_fop = &sel_class_ops; |
1650 | inode->i_ino = sel_class_to_ino(index); | 1635 | inode->i_ino = sel_class_to_ino(index); |
1651 | d_add(dentry, inode); | 1636 | d_add(dentry, inode); |
1652 | 1637 | ||
1653 | dentry = d_alloc_name(dir, "perms"); | 1638 | dentry = d_alloc_name(dir, "perms"); |
1654 | if (!dentry) { | 1639 | if (!dentry) |
1655 | rc = -ENOMEM; | 1640 | return -ENOMEM; |
1656 | goto out; | ||
1657 | } | ||
1658 | 1641 | ||
1659 | rc = sel_make_dir(dir->d_inode, dentry, &last_class_ino); | 1642 | rc = sel_make_dir(dir->d_inode, dentry, &last_class_ino); |
1660 | if (rc) | 1643 | if (rc) |
1661 | goto out; | 1644 | return rc; |
1662 | 1645 | ||
1663 | rc = sel_make_perm_files(classname, index, dentry); | 1646 | rc = sel_make_perm_files(classname, index, dentry); |
1664 | 1647 | ||
1665 | out: | ||
1666 | return rc; | 1648 | return rc; |
1667 | } | 1649 | } |
1668 | 1650 | ||
@@ -1692,15 +1674,15 @@ static void sel_remove_classes(void) | |||
1692 | 1674 | ||
1693 | static int sel_make_classes(void) | 1675 | static int sel_make_classes(void) |
1694 | { | 1676 | { |
1695 | int rc = 0, nclasses, i; | 1677 | int rc, nclasses, i; |
1696 | char **classes; | 1678 | char **classes; |
1697 | 1679 | ||
1698 | /* delete any existing entries */ | 1680 | /* delete any existing entries */ |
1699 | sel_remove_classes(); | 1681 | sel_remove_classes(); |
1700 | 1682 | ||
1701 | rc = security_get_classes(&classes, &nclasses); | 1683 | rc = security_get_classes(&classes, &nclasses); |
1702 | if (rc < 0) | 1684 | if (rc) |
1703 | goto out; | 1685 | return rc; |
1704 | 1686 | ||
1705 | /* +2 since classes are 1-indexed */ | 1687 | /* +2 since classes are 1-indexed */ |
1706 | last_class_ino = sel_class_to_ino(nclasses + 2); | 1688 | last_class_ino = sel_class_to_ino(nclasses + 2); |
@@ -1708,29 +1690,27 @@ static int sel_make_classes(void) | |||
1708 | for (i = 0; i < nclasses; i++) { | 1690 | for (i = 0; i < nclasses; i++) { |
1709 | struct dentry *class_name_dir; | 1691 | struct dentry *class_name_dir; |
1710 | 1692 | ||
1693 | rc = -ENOMEM; | ||
1711 | class_name_dir = d_alloc_name(class_dir, classes[i]); | 1694 | class_name_dir = d_alloc_name(class_dir, classes[i]); |
1712 | if (!class_name_dir) { | 1695 | if (!class_name_dir) |
1713 | rc = -ENOMEM; | 1696 | goto out; |
1714 | goto out1; | ||
1715 | } | ||
1716 | 1697 | ||
1717 | rc = sel_make_dir(class_dir->d_inode, class_name_dir, | 1698 | rc = sel_make_dir(class_dir->d_inode, class_name_dir, |
1718 | &last_class_ino); | 1699 | &last_class_ino); |
1719 | if (rc) | 1700 | if (rc) |
1720 | goto out1; | 1701 | goto out; |
1721 | 1702 | ||
1722 | /* i+1 since class values are 1-indexed */ | 1703 | /* i+1 since class values are 1-indexed */ |
1723 | rc = sel_make_class_dir_entries(classes[i], i + 1, | 1704 | rc = sel_make_class_dir_entries(classes[i], i + 1, |
1724 | class_name_dir); | 1705 | class_name_dir); |
1725 | if (rc) | 1706 | if (rc) |
1726 | goto out1; | 1707 | goto out; |
1727 | } | 1708 | } |
1728 | 1709 | rc = 0; | |
1729 | out1: | 1710 | out: |
1730 | for (i = 0; i < nclasses; i++) | 1711 | for (i = 0; i < nclasses; i++) |
1731 | kfree(classes[i]); | 1712 | kfree(classes[i]); |
1732 | kfree(classes); | 1713 | kfree(classes); |
1733 | out: | ||
1734 | return rc; | 1714 | return rc; |
1735 | } | 1715 | } |
1736 | 1716 | ||
@@ -1767,14 +1747,12 @@ static int sel_make_policycap(void) | |||
1767 | static int sel_make_dir(struct inode *dir, struct dentry *dentry, | 1747 | static int sel_make_dir(struct inode *dir, struct dentry *dentry, |
1768 | unsigned long *ino) | 1748 | unsigned long *ino) |
1769 | { | 1749 | { |
1770 | int ret = 0; | ||
1771 | struct inode *inode; | 1750 | struct inode *inode; |
1772 | 1751 | ||
1773 | inode = sel_make_inode(dir->i_sb, S_IFDIR | S_IRUGO | S_IXUGO); | 1752 | inode = sel_make_inode(dir->i_sb, S_IFDIR | S_IRUGO | S_IXUGO); |
1774 | if (!inode) { | 1753 | if (!inode) |
1775 | ret = -ENOMEM; | 1754 | return -ENOMEM; |
1776 | goto out; | 1755 | |
1777 | } | ||
1778 | inode->i_op = &simple_dir_inode_operations; | 1756 | inode->i_op = &simple_dir_inode_operations; |
1779 | inode->i_fop = &simple_dir_operations; | 1757 | inode->i_fop = &simple_dir_operations; |
1780 | inode->i_ino = ++(*ino); | 1758 | inode->i_ino = ++(*ino); |
@@ -1783,8 +1761,8 @@ static int sel_make_dir(struct inode *dir, struct dentry *dentry, | |||
1783 | d_add(dentry, inode); | 1761 | d_add(dentry, inode); |
1784 | /* bump link count on parent directory, too */ | 1762 | /* bump link count on parent directory, too */ |
1785 | inc_nlink(dir); | 1763 | inc_nlink(dir); |
1786 | out: | 1764 | |
1787 | return ret; | 1765 | return 0; |
1788 | } | 1766 | } |
1789 | 1767 | ||
1790 | static int sel_fill_super(struct super_block *sb, void *data, int silent) | 1768 | static int sel_fill_super(struct super_block *sb, void *data, int silent) |
@@ -1820,11 +1798,10 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1820 | 1798 | ||
1821 | root_inode = sb->s_root->d_inode; | 1799 | root_inode = sb->s_root->d_inode; |
1822 | 1800 | ||
1801 | ret = -ENOMEM; | ||
1823 | dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME); | 1802 | dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME); |
1824 | if (!dentry) { | 1803 | if (!dentry) |
1825 | ret = -ENOMEM; | ||
1826 | goto err; | 1804 | goto err; |
1827 | } | ||
1828 | 1805 | ||
1829 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); | 1806 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); |
1830 | if (ret) | 1807 | if (ret) |
@@ -1832,17 +1809,16 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1832 | 1809 | ||
1833 | bool_dir = dentry; | 1810 | bool_dir = dentry; |
1834 | 1811 | ||
1812 | ret = -ENOMEM; | ||
1835 | dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME); | 1813 | dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME); |
1836 | if (!dentry) { | 1814 | if (!dentry) |
1837 | ret = -ENOMEM; | ||
1838 | goto err; | 1815 | goto err; |
1839 | } | ||
1840 | 1816 | ||
1817 | ret = -ENOMEM; | ||
1841 | inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO); | 1818 | inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO); |
1842 | if (!inode) { | 1819 | if (!inode) |
1843 | ret = -ENOMEM; | ||
1844 | goto err; | 1820 | goto err; |
1845 | } | 1821 | |
1846 | inode->i_ino = ++sel_last_ino; | 1822 | inode->i_ino = ++sel_last_ino; |
1847 | isec = (struct inode_security_struct *)inode->i_security; | 1823 | isec = (struct inode_security_struct *)inode->i_security; |
1848 | isec->sid = SECINITSID_DEVNULL; | 1824 | isec->sid = SECINITSID_DEVNULL; |
@@ -1853,11 +1829,10 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1853 | d_add(dentry, inode); | 1829 | d_add(dentry, inode); |
1854 | selinux_null = dentry; | 1830 | selinux_null = dentry; |
1855 | 1831 | ||
1832 | ret = -ENOMEM; | ||
1856 | dentry = d_alloc_name(sb->s_root, "avc"); | 1833 | dentry = d_alloc_name(sb->s_root, "avc"); |
1857 | if (!dentry) { | 1834 | if (!dentry) |
1858 | ret = -ENOMEM; | ||
1859 | goto err; | 1835 | goto err; |
1860 | } | ||
1861 | 1836 | ||
1862 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); | 1837 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); |
1863 | if (ret) | 1838 | if (ret) |
@@ -1867,11 +1842,10 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1867 | if (ret) | 1842 | if (ret) |
1868 | goto err; | 1843 | goto err; |
1869 | 1844 | ||
1845 | ret = -ENOMEM; | ||
1870 | dentry = d_alloc_name(sb->s_root, "initial_contexts"); | 1846 | dentry = d_alloc_name(sb->s_root, "initial_contexts"); |
1871 | if (!dentry) { | 1847 | if (!dentry) |
1872 | ret = -ENOMEM; | ||
1873 | goto err; | 1848 | goto err; |
1874 | } | ||
1875 | 1849 | ||
1876 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); | 1850 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); |
1877 | if (ret) | 1851 | if (ret) |
@@ -1881,11 +1855,10 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1881 | if (ret) | 1855 | if (ret) |
1882 | goto err; | 1856 | goto err; |
1883 | 1857 | ||
1858 | ret = -ENOMEM; | ||
1884 | dentry = d_alloc_name(sb->s_root, "class"); | 1859 | dentry = d_alloc_name(sb->s_root, "class"); |
1885 | if (!dentry) { | 1860 | if (!dentry) |
1886 | ret = -ENOMEM; | ||
1887 | goto err; | 1861 | goto err; |
1888 | } | ||
1889 | 1862 | ||
1890 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); | 1863 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); |
1891 | if (ret) | 1864 | if (ret) |
@@ -1893,11 +1866,10 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1893 | 1866 | ||
1894 | class_dir = dentry; | 1867 | class_dir = dentry; |
1895 | 1868 | ||
1869 | ret = -ENOMEM; | ||
1896 | dentry = d_alloc_name(sb->s_root, "policy_capabilities"); | 1870 | dentry = d_alloc_name(sb->s_root, "policy_capabilities"); |
1897 | if (!dentry) { | 1871 | if (!dentry) |
1898 | ret = -ENOMEM; | ||
1899 | goto err; | 1872 | goto err; |
1900 | } | ||
1901 | 1873 | ||
1902 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); | 1874 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); |
1903 | if (ret) | 1875 | if (ret) |
@@ -1905,12 +1877,11 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1905 | 1877 | ||
1906 | policycap_dir = dentry; | 1878 | policycap_dir = dentry; |
1907 | 1879 | ||
1908 | out: | 1880 | return 0; |
1909 | return ret; | ||
1910 | err: | 1881 | err: |
1911 | printk(KERN_ERR "SELinux: %s: failed while creating inodes\n", | 1882 | printk(KERN_ERR "SELinux: %s: failed while creating inodes\n", |
1912 | __func__); | 1883 | __func__); |
1913 | goto out; | 1884 | return ret; |
1914 | } | 1885 | } |
1915 | 1886 | ||
1916 | static struct dentry *sel_mount(struct file_system_type *fs_type, | 1887 | static struct dentry *sel_mount(struct file_system_type *fs_type, |
@@ -1934,14 +1905,16 @@ static int __init init_sel_fs(void) | |||
1934 | if (!selinux_enabled) | 1905 | if (!selinux_enabled) |
1935 | return 0; | 1906 | return 0; |
1936 | err = register_filesystem(&sel_fs_type); | 1907 | err = register_filesystem(&sel_fs_type); |
1937 | if (!err) { | 1908 | if (err) |
1938 | selinuxfs_mount = kern_mount(&sel_fs_type); | 1909 | return err; |
1939 | if (IS_ERR(selinuxfs_mount)) { | 1910 | |
1940 | printk(KERN_ERR "selinuxfs: could not mount!\n"); | 1911 | selinuxfs_mount = kern_mount(&sel_fs_type); |
1941 | err = PTR_ERR(selinuxfs_mount); | 1912 | if (IS_ERR(selinuxfs_mount)) { |
1942 | selinuxfs_mount = NULL; | 1913 | printk(KERN_ERR "selinuxfs: could not mount!\n"); |
1943 | } | 1914 | err = PTR_ERR(selinuxfs_mount); |
1915 | selinuxfs_mount = NULL; | ||
1944 | } | 1916 | } |
1917 | |||
1945 | return err; | 1918 | return err; |
1946 | } | 1919 | } |
1947 | 1920 | ||