[PATCH] selinux: fix sleeping allocation in security_context_to_sid (Was: + selinux-dopey-hack.patch added to -mm tree)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2008-05-13 at 01:10 -0700, akpm@xxxxxxxxxxxxxxxxxxxx wrote:
> From: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
> 
> BUG: sleeping function called from invalid context at mm/slab.c:3052
> in_atomic():1, irqs_disabled():0
> 3 locks held by S99local/2391:
>  #0:  (&type->i_mutex_dir_key#4){--..}, at: [<c017973c>] do_lookup+0x72/0x146
>  #1:  (&isec->lock){--..}, at: [<c01cc3e5>] inode_doinit_with_dentry+0x35/0x52f
>  #2:  (policy_rwlock){..-?}, at: [<c01d7f89>] security_context_to_sid_core+0x5e/0x157
> Pid: 2391, comm: S99local Not tainted 2.6.26-rc2 #1
>  [<c011863c>] __might_sleep+0xde/0xe5
>  [<c01706e5>] __kmalloc+0x52/0xd5
>  [<c01d7d9f>] string_to_context_struct+0x2e/0x1ba
>  [<c01d7fa3>] security_context_to_sid_core+0x78/0x157
>  [<c01d80a5>] security_context_to_sid_default+0x10/0x12
>  [<c01cc609>] inode_doinit_with_dentry+0x259/0x52f
>  [<c01cc8f1>] selinux_d_instantiate+0x12/0x14

Please use this patch instead.

Fix a sleeping function called from invalid context bug introduced by 
the deferred mapping of contexts support, which restructured the code 
into a helper and moved the locking to the caller.  Always use GFP_ATOMIC 
for allocating copies of the context  and remove the gfp_flags argument as it
is no longer used.  These allocations are generally small and transient.

Signed-off-by:  Stephen Smalley <sds@xxxxxxxxxxxxx>

---

 security/selinux/hooks.c            |    3 +--
 security/selinux/include/security.h |    2 +-
 security/selinux/ss/services.c      |   23 ++++++++++-------------
 3 files changed, 12 insertions(+), 16 deletions(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 59c6e98..9684270 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1194,8 +1194,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
 			rc = 0;
 		} else {
 			rc = security_context_to_sid_default(context, rc, &sid,
-							     sbsec->def_sid,
-							     GFP_NOFS);
+							     sbsec->def_sid);
 			if (rc) {
 				printk(KERN_WARNING "SELinux: %s:  context_to_sid(%s) "
 				       "returned %d for dev=%s ino=%ld\n",
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 7c54300..e8e24a2 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -99,7 +99,7 @@ int security_context_to_sid(const char *scontext, u32 scontext_len,
 	u32 *out_sid);
 
 int security_context_to_sid_default(const char *scontext, u32 scontext_len,
-				    u32 *out_sid, u32 def_sid, gfp_t gfp_flags);
+				    u32 *out_sid, u32 def_sid);
 
 int security_context_to_sid_force(const char *scontext, u32 scontext_len,
 				  u32 *sid);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index b86ac9d..498b084 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -735,8 +735,7 @@ static int string_to_context_struct(struct policydb *pol,
 				    const char *scontext,
 				    u32 scontext_len,
 				    struct context *ctx,
-				    u32 def_sid,
-				    gfp_t gfp_flags)
+				    u32 def_sid)
 {
 	char *scontext2 = NULL;
 	struct role_datum *role;
@@ -748,7 +747,7 @@ static int string_to_context_struct(struct policydb *pol,
 	context_init(ctx);
 
 	/* Copy the string so that we can modify the copy as we parse it. */
-	scontext2 = kmalloc(scontext_len+1, gfp_flags);
+	scontext2 = kmalloc(scontext_len+1, GFP_ATOMIC);
 	if (!scontext2) {
 		rc = -ENOMEM;
 		goto out;
@@ -827,8 +826,7 @@ out:
 }
 
 static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
-					u32 *sid, u32 def_sid, gfp_t gfp_flags,
-					int force)
+					u32 *sid, u32 def_sid, int force)
 {
 	struct context context;
 	int rc = 0;
@@ -850,9 +848,9 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
 	POLICY_RDLOCK;
 	rc = string_to_context_struct(&policydb, &sidtab,
 				      scontext, scontext_len,
-				      &context, def_sid, gfp_flags);
+				      &context, def_sid);
 	if (rc == -EINVAL && force) {
-		context.str = kmalloc(scontext_len+1, gfp_flags);
+		context.str = kmalloc(scontext_len+1, GFP_ATOMIC);
 		if (!context.str) {
 			rc = -ENOMEM;
 			goto out;
@@ -884,7 +882,7 @@ out:
 int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid)
 {
 	return security_context_to_sid_core(scontext, scontext_len,
-					    sid, SECSID_NULL, GFP_KERNEL, 0);
+					    sid, SECSID_NULL, 0);
 }
 
 /**
@@ -906,17 +904,17 @@ int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid)
  * memory is available, or 0 on success.
  */
 int security_context_to_sid_default(const char *scontext, u32 scontext_len,
-				    u32 *sid, u32 def_sid, gfp_t gfp_flags)
+				    u32 *sid, u32 def_sid)
 {
 	return security_context_to_sid_core(scontext, scontext_len,
-					    sid, def_sid, gfp_flags, 1);
+					    sid, def_sid, 1);
 }
 
 int security_context_to_sid_force(const char *scontext, u32 scontext_len,
 				  u32 *sid)
 {
 	return security_context_to_sid_core(scontext, scontext_len,
-					    sid, SECSID_NULL, GFP_KERNEL, 1);
+					    sid, SECSID_NULL, 1);
 }
 
 static int compute_sid_handle_invalid_context(
@@ -1340,8 +1338,7 @@ static int convert_context(u32 key,
 	if (c->str) {
 		struct context ctx;
 		rc = string_to_context_struct(args->newp, NULL, c->str,
-					      c->len, &ctx, SECSID_NULL,
-					      GFP_KERNEL);
+					      c->len, &ctx, SECSID_NULL);
 		if (!rc) {
 			printk(KERN_INFO
 		       "SELinux:  Context %s became valid (mapped).\n",


-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@xxxxxxxxxxxxx with
the words "unsubscribe selinux" without quotes as the message.

[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux