aboutsummaryrefslogtreecommitdiff
path: root/security/selinux
diff options
context:
space:
mode:
authorWaiman Long <Waiman.Long@hp.com>2014-06-23 11:28:51 -0400
committerMister Oyster <oysterized@gmail.com>2017-05-24 02:55:34 +0200
commit2e8c2417e625053e86760b6f5acbd9a51b5ef7a3 (patch)
tree98a14ac641c4c73fe90b96d0484edca3789537b5 /security/selinux
parent983b50c955c01182e809679f00d0e799d2177425 (diff)
selinux: no recursive read_lock of policy_rwlock in security_genfs_sid()
With the introduction of fair queued rwlock, recursive read_lock() may hang the offending process if there is a write_lock() somewhere in between. With recursive read_lock checking enabled, the following error was reported: ============================================= [ INFO: possible recursive locking detected ] 3.16.0-rc1 #2 Tainted: G E --------------------------------------------- load_policy/708 is trying to acquire lock: (policy_rwlock){.+.+..}, at: [<ffffffff8125b32a>] security_genfs_sid+0x3a/0x170 but task is already holding lock: (policy_rwlock){.+.+..}, at: [<ffffffff8125b48c>] security_fs_use+0x2c/0x110 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(policy_rwlock); lock(policy_rwlock); This patch fixes the occurrence of recursive read_lock() of policy_rwlock by adding a helper function __security_genfs_sid() which requires caller to take the lock before calling it. The security_fs_use() was then modified to call the new helper function. Signed-off-by: Waiman Long <Waiman.Long@hp.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: Paul Moore <pmoore@redhat.com> Conflicts: security/selinux/ss/services.c (Adapted for Shamu 3.10 Kernel) Signed-off-by: franciscofranco <franciscofranco.1990@gmail.com> Signed-off-by: Pranav Vashi <neobuddy89@gmail.com>
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/ss/services.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 983420cf6..343f7dece 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2435,7 +2435,7 @@ out:
}
/**
- * security_genfs_sid - Obtain a SID for a file in a filesystem
+ * __security_genfs_sid - Helper to obtain a SID for a file in a filesystem
* @fstype: filesystem type
* @path: path from root of mount
* @sclass: file security class
@@ -2444,11 +2444,13 @@ out:
* Obtain a SID to use for a file in a filesystem that
* cannot support xattr or use a fixed labeling behavior like
* transition SIDs or task SIDs.
+ *
+ * The caller must acquire the policy_rwlock before calling this function.
*/
-int security_genfs_sid(const char *fstype,
- char *path,
- u16 orig_sclass,
- u32 *sid)
+static inline int __security_genfs_sid(const char *fstype,
+ char *path,
+ u16 orig_sclass,
+ u32 *sid)
{
int len;
u16 sclass;
@@ -2459,8 +2461,6 @@ int security_genfs_sid(const char *fstype,
while (path[0] == '/' && path[1] == '/')
path++;
- read_lock(&policy_rwlock);
-
sclass = unmap_class(orig_sclass);
*sid = SECINITSID_UNLABELED;
@@ -2494,11 +2494,33 @@ int security_genfs_sid(const char *fstype,
*sid = c->sid[0];
rc = 0;
out:
- read_unlock(&policy_rwlock);
return rc;
}
/**
+ * security_genfs_sid - Obtain a SID for a file in a filesystem
+ * @fstype: filesystem type
+ * @path: path from root of mount
+ * @sclass: file security class
+ * @sid: SID for path
+ *
+ * Acquire policy_rwlock before calling __security_genfs_sid() and release
+ * it afterward.
+ */
+int security_genfs_sid(const char *fstype,
+ char *path,
+ u16 orig_sclass,
+ u32 *sid)
+{
+ int retval;
+
+ read_lock(&policy_rwlock);
+ retval = __security_genfs_sid(fstype, path, orig_sclass, sid);
+ read_unlock(&policy_rwlock);
+ return retval;
+}
+
+/**
* security_fs_use - Determine how to handle labeling for a filesystem.
* @fstype: filesystem type
* @behavior: labeling behavior
@@ -2531,7 +2553,7 @@ int security_fs_use(
}
*sid = c->sid[0];
} else {
- rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, sid);
+ rc = __security_genfs_sid(fstype, "/", SECCLASS_DIR, sid);
if (rc) {
*behavior = SECURITY_FS_USE_NONE;
rc = 0;