Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

SELinux: fix sleeping allocation in security_context_to_sid

Fix a sleeping function called from invalid context bug by moving allocation
to the callers prior to taking the policy rdlock.

Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: James Morris <jmorris@namei.org>

authored by

Stephen Smalley and committed by
James Morris
9a59daa0 12b29f34

+40 -30
+40 -30
security/selinux/ss/services.c
··· 730 730 return security_sid_to_context_core(sid, scontext, scontext_len, 1); 731 731 } 732 732 733 + /* 734 + * Caveat: Mutates scontext. 735 + */ 733 736 static int string_to_context_struct(struct policydb *pol, 734 737 struct sidtab *sidtabp, 735 - const char *scontext, 738 + char *scontext, 736 739 u32 scontext_len, 737 740 struct context *ctx, 738 - u32 def_sid, 739 - gfp_t gfp_flags) 741 + u32 def_sid) 740 742 { 741 - char *scontext2 = NULL; 742 743 struct role_datum *role; 743 744 struct type_datum *typdatum; 744 745 struct user_datum *usrdatum; ··· 748 747 749 748 context_init(ctx); 750 749 751 - /* Copy the string so that we can modify the copy as we parse it. */ 752 - scontext2 = kmalloc(scontext_len+1, gfp_flags); 753 - if (!scontext2) { 754 - rc = -ENOMEM; 755 - goto out; 756 - } 757 - memcpy(scontext2, scontext, scontext_len); 758 - scontext2[scontext_len] = 0; 759 - 760 750 /* Parse the security context. */ 761 751 762 752 rc = -EINVAL; 763 - scontextp = (char *) scontext2; 753 + scontextp = (char *) scontext; 764 754 765 755 /* Extract the user. */ 766 756 p = scontextp; ··· 801 809 if (rc) 802 810 goto out; 803 811 804 - if ((p - scontext2) < scontext_len) { 812 + if ((p - scontext) < scontext_len) { 805 813 rc = -EINVAL; 806 814 goto out; 807 815 } ··· 814 822 } 815 823 rc = 0; 816 824 out: 817 - kfree(scontext2); 818 825 return rc; 819 826 } 820 827 ··· 821 830 u32 *sid, u32 def_sid, gfp_t gfp_flags, 822 831 int force) 823 832 { 833 + char *scontext2, *str = NULL; 824 834 struct context context; 825 835 int rc = 0; 826 836 ··· 831 839 for (i = 1; i < SECINITSID_NUM; i++) { 832 840 if (!strcmp(initial_sid_to_string[i], scontext)) { 833 841 *sid = i; 834 - goto out; 842 + return 0; 835 843 } 836 844 } 837 845 *sid = SECINITSID_KERNEL; 838 - goto out; 846 + return 0; 839 847 } 840 848 *sid = SECSID_NULL; 841 849 850 + /* Copy the string so that we can modify the copy as we parse it. */ 851 + scontext2 = kmalloc(scontext_len+1, gfp_flags); 852 + if (!scontext2) 853 + return -ENOMEM; 854 + memcpy(scontext2, scontext, scontext_len); 855 + scontext2[scontext_len] = 0; 856 + 857 + if (force) { 858 + /* Save another copy for storing in uninterpreted form */ 859 + str = kstrdup(scontext2, gfp_flags); 860 + if (!str) { 861 + kfree(scontext2); 862 + return -ENOMEM; 863 + } 864 + } 865 + 842 866 POLICY_RDLOCK; 843 867 rc = string_to_context_struct(&policydb, &sidtab, 844 - scontext, scontext_len, 845 - &context, def_sid, gfp_flags); 868 + scontext2, scontext_len, 869 + &context, def_sid); 846 870 if (rc == -EINVAL && force) { 847 - context.str = kmalloc(scontext_len+1, gfp_flags); 848 - if (!context.str) { 849 - rc = -ENOMEM; 850 - goto out; 851 - } 852 - memcpy(context.str, scontext, scontext_len); 853 - context.str[scontext_len] = 0; 871 + context.str = str; 854 872 context.len = scontext_len; 873 + str = NULL; 855 874 } else if (rc) 856 875 goto out; 857 876 rc = sidtab_context_to_sid(&sidtab, &context, sid); ··· 870 867 context_destroy(&context); 871 868 out: 872 869 POLICY_RDUNLOCK; 870 + kfree(scontext2); 871 + kfree(str); 873 872 return rc; 874 873 } 875 874 ··· 1344 1339 1345 1340 if (c->str) { 1346 1341 struct context ctx; 1347 - rc = string_to_context_struct(args->newp, NULL, c->str, 1348 - c->len, &ctx, SECSID_NULL, 1349 - GFP_KERNEL); 1342 + s = kstrdup(c->str, GFP_KERNEL); 1343 + if (!s) { 1344 + rc = -ENOMEM; 1345 + goto out; 1346 + } 1347 + rc = string_to_context_struct(args->newp, NULL, s, 1348 + c->len, &ctx, SECSID_NULL); 1349 + kfree(s); 1350 1350 if (!rc) { 1351 1351 printk(KERN_INFO 1352 1352 "SELinux: Context %s became valid (mapped).\n",