aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Smalley <sds@tycho.nsa.gov>2008-05-14 10:33:55 -0400
committerJames Morris <jmorris@namei.org>2008-07-14 01:01:35 -0400
commit9a59daa03df72526d234b91dd3e32ded5aebd3ef (patch)
tree9ba6797d509a5657be7f47f55e630f06a489174d
parent12b29f34558b9b45a2c6eabd4f3c6be939a3980f (diff)
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>
-rw-r--r--security/selinux/ss/services.c70
1 files changed, 40 insertions, 30 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index b86ac9da6cf3..2d5e5a3a8aa9 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -730,15 +730,16 @@ int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len)
730 return security_sid_to_context_core(sid, scontext, scontext_len, 1); 730 return security_sid_to_context_core(sid, scontext, scontext_len, 1);
731} 731}
732 732
733/*
734 * Caveat: Mutates scontext.
735 */
733static int string_to_context_struct(struct policydb *pol, 736static int string_to_context_struct(struct policydb *pol,
734 struct sidtab *sidtabp, 737 struct sidtab *sidtabp,
735 const char *scontext, 738 char *scontext,
736 u32 scontext_len, 739 u32 scontext_len,
737 struct context *ctx, 740 struct context *ctx,
738 u32 def_sid, 741 u32 def_sid)
739 gfp_t gfp_flags)
740{ 742{
741 char *scontext2 = NULL;
742 struct role_datum *role; 743 struct role_datum *role;
743 struct type_datum *typdatum; 744 struct type_datum *typdatum;
744 struct user_datum *usrdatum; 745 struct user_datum *usrdatum;
@@ -747,19 +748,10 @@ static int string_to_context_struct(struct policydb *pol,
747 748
748 context_init(ctx); 749 context_init(ctx);
749 750
750 /* Copy the string so that we can modify the copy as we parse it. */
751 scontext2 = kmalloc(scontext_len+1, gfp_flags);
752 if (!scontext2) {
753 rc = -ENOMEM;
754 goto out;
755 }
756 memcpy(scontext2, scontext, scontext_len);
757 scontext2[scontext_len] = 0;
758
759 /* Parse the security context. */ 751 /* Parse the security context. */
760 752
761 rc = -EINVAL; 753 rc = -EINVAL;
762 scontextp = (char *) scontext2; 754 scontextp = (char *) scontext;
763 755
764 /* Extract the user. */ 756 /* Extract the user. */
765 p = scontextp; 757 p = scontextp;
@@ -809,7 +801,7 @@ static int string_to_context_struct(struct policydb *pol,
809 if (rc) 801 if (rc)
810 goto out; 802 goto out;
811 803
812 if ((p - scontext2) < scontext_len) { 804 if ((p - scontext) < scontext_len) {
813 rc = -EINVAL; 805 rc = -EINVAL;
814 goto out; 806 goto out;
815 } 807 }
@@ -822,7 +814,6 @@ static int string_to_context_struct(struct policydb *pol,
822 } 814 }
823 rc = 0; 815 rc = 0;
824out: 816out:
825 kfree(scontext2);
826 return rc; 817 return rc;
827} 818}
828 819
@@ -830,6 +821,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
830 u32 *sid, u32 def_sid, gfp_t gfp_flags, 821 u32 *sid, u32 def_sid, gfp_t gfp_flags,
831 int force) 822 int force)
832{ 823{
824 char *scontext2, *str = NULL;
833 struct context context; 825 struct context context;
834 int rc = 0; 826 int rc = 0;
835 827
@@ -839,27 +831,38 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
839 for (i = 1; i < SECINITSID_NUM; i++) { 831 for (i = 1; i < SECINITSID_NUM; i++) {
840 if (!strcmp(initial_sid_to_string[i], scontext)) { 832 if (!strcmp(initial_sid_to_string[i], scontext)) {
841 *sid = i; 833 *sid = i;
842 goto out; 834 return 0;
843 } 835 }
844 } 836 }
845 *sid = SECINITSID_KERNEL; 837 *sid = SECINITSID_KERNEL;
846 goto out; 838 return 0;
847 } 839 }
848 *sid = SECSID_NULL; 840 *sid = SECSID_NULL;
849 841
842 /* Copy the string so that we can modify the copy as we parse it. */
843 scontext2 = kmalloc(scontext_len+1, gfp_flags);
844 if (!scontext2)
845 return -ENOMEM;
846 memcpy(scontext2, scontext, scontext_len);
847 scontext2[scontext_len] = 0;
848
849 if (force) {
850 /* Save another copy for storing in uninterpreted form */
851 str = kstrdup(scontext2, gfp_flags);
852 if (!str) {
853 kfree(scontext2);
854 return -ENOMEM;
855 }
856 }
857
850 POLICY_RDLOCK; 858 POLICY_RDLOCK;
851 rc = string_to_context_struct(&policydb, &sidtab, 859 rc = string_to_context_struct(&policydb, &sidtab,
852 scontext, scontext_len, 860 scontext2, scontext_len,
853 &context, def_sid, gfp_flags); 861 &context, def_sid);
854 if (rc == -EINVAL && force) { 862 if (rc == -EINVAL && force) {
855 context.str = kmalloc(scontext_len+1, gfp_flags); 863 context.str = str;
856 if (!context.str) {
857 rc = -ENOMEM;
858 goto out;
859 }
860 memcpy(context.str, scontext, scontext_len);
861 context.str[scontext_len] = 0;
862 context.len = scontext_len; 864 context.len = scontext_len;
865 str = NULL;
863 } else if (rc) 866 } else if (rc)
864 goto out; 867 goto out;
865 rc = sidtab_context_to_sid(&sidtab, &context, sid); 868 rc = sidtab_context_to_sid(&sidtab, &context, sid);
@@ -867,6 +870,8 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
867 context_destroy(&context); 870 context_destroy(&context);
868out: 871out:
869 POLICY_RDUNLOCK; 872 POLICY_RDUNLOCK;
873 kfree(scontext2);
874 kfree(str);
870 return rc; 875 return rc;
871} 876}
872 877
@@ -1339,9 +1344,14 @@ static int convert_context(u32 key,
1339 1344
1340 if (c->str) { 1345 if (c->str) {
1341 struct context ctx; 1346 struct context ctx;
1342 rc = string_to_context_struct(args->newp, NULL, c->str, 1347 s = kstrdup(c->str, GFP_KERNEL);
1343 c->len, &ctx, SECSID_NULL, 1348 if (!s) {
1344 GFP_KERNEL); 1349 rc = -ENOMEM;
1350 goto out;
1351 }
1352 rc = string_to_context_struct(args->newp, NULL, s,
1353 c->len, &ctx, SECSID_NULL);
1354 kfree(s);
1345 if (!rc) { 1355 if (!rc) {
1346 printk(KERN_INFO 1356 printk(KERN_INFO
1347 "SELinux: Context %s became valid (mapped).\n", 1357 "SELinux: Context %s became valid (mapped).\n",