From: Tetsuo Handa <penguin-ker...@i-love.sakura.ne.jp>

[ Upstream commit 5797e861e402fff2bedce4ec8b7c89f4248b6073 ]

syzbot is reporting that tomoyo's quota check is racy [1]. But this check
is tolerant of some degree of inaccuracy. Thus, teach KCSAN to ignore
this data race.

[1] 
https://syzkaller.appspot.com/bug?id=999533deec7ba6337f8aa25d8bd1a4d5f7e50476

Reported-by: syzbot <syzbot+0789a72b46fd91431...@syzkaller.appspotmail.com>
Signed-off-by: Tetsuo Handa <penguin-ker...@i-love.sakura.ne.jp>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 security/tomoyo/file.c    | 16 ++++++++--------
 security/tomoyo/network.c |  8 ++++----
 security/tomoyo/util.c    | 24 ++++++++++++------------
 3 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 2a374b4da8f5c..cbe0dc87bb919 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -356,13 +356,13 @@ static bool tomoyo_merge_path_acl(struct tomoyo_acl_info 
*a,
 {
        u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head)
                ->perm;
-       u16 perm = *a_perm;
+       u16 perm = READ_ONCE(*a_perm);
        const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
        if (is_delete)
                perm &= ~b_perm;
        else
                perm |= b_perm;
-       *a_perm = perm;
+       WRITE_ONCE(*a_perm, perm);
        return !perm;
 }
 
@@ -428,14 +428,14 @@ static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info 
*a,
 {
        u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
                                         head)->perm;
-       u8 perm = *a_perm;
+       u8 perm = READ_ONCE(*a_perm);
        const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head)
                ->perm;
        if (is_delete)
                perm &= ~b_perm;
        else
                perm |= b_perm;
-       *a_perm = perm;
+       WRITE_ONCE(*a_perm, perm);
        return !perm;
 }
 
@@ -505,13 +505,13 @@ static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info 
*a,
 {
        u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head)
                ->perm;
-       u8 perm = *a_perm;
+       u8 perm = READ_ONCE(*a_perm);
        const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm;
        if (is_delete)
                perm &= ~b_perm;
        else
                perm |= b_perm;
-       *a_perm = perm;
+       WRITE_ONCE(*a_perm, perm);
        return !perm;
 }
 
@@ -640,14 +640,14 @@ static bool tomoyo_merge_path_number_acl(struct 
tomoyo_acl_info *a,
 {
        u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl,
                                          head)->perm;
-       u8 perm = *a_perm;
+       u8 perm = READ_ONCE(*a_perm);
        const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head)
                ->perm;
        if (is_delete)
                perm &= ~b_perm;
        else
                perm |= b_perm;
-       *a_perm = perm;
+       WRITE_ONCE(*a_perm, perm);
        return !perm;
 }
 
diff --git a/security/tomoyo/network.c b/security/tomoyo/network.c
index 9094f4b3b367b..2ea0da6e5180f 100644
--- a/security/tomoyo/network.c
+++ b/security/tomoyo/network.c
@@ -233,14 +233,14 @@ static bool tomoyo_merge_inet_acl(struct tomoyo_acl_info 
*a,
 {
        u8 * const a_perm =
                &container_of(a, struct tomoyo_inet_acl, head)->perm;
-       u8 perm = *a_perm;
+       u8 perm = READ_ONCE(*a_perm);
        const u8 b_perm = container_of(b, struct tomoyo_inet_acl, head)->perm;
 
        if (is_delete)
                perm &= ~b_perm;
        else
                perm |= b_perm;
-       *a_perm = perm;
+       WRITE_ONCE(*a_perm, perm);
        return !perm;
 }
 
@@ -259,14 +259,14 @@ static bool tomoyo_merge_unix_acl(struct tomoyo_acl_info 
*a,
 {
        u8 * const a_perm =
                &container_of(a, struct tomoyo_unix_acl, head)->perm;
-       u8 perm = *a_perm;
+       u8 perm = READ_ONCE(*a_perm);
        const u8 b_perm = container_of(b, struct tomoyo_unix_acl, head)->perm;
 
        if (is_delete)
                perm &= ~b_perm;
        else
                perm |= b_perm;
-       *a_perm = perm;
+       WRITE_ONCE(*a_perm, perm);
        return !perm;
 }
 
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c
index d3d9d9f1edb04..16d488f963b12 100644
--- a/security/tomoyo/util.c
+++ b/security/tomoyo/util.c
@@ -1020,30 +1020,30 @@ bool tomoyo_domain_quota_is_ok(struct 
tomoyo_request_info *r)
                u8 i;
                if (ptr->is_deleted)
                        continue;
+               /*
+                * Reading perm bitmap might race with tomoyo_merge_*() because
+                * caller does not hold tomoyo_policy_lock mutex. But exceeding
+                * max_learning_entry parameter by a few entries does not harm.
+                */
                switch (ptr->type) {
                case TOMOYO_TYPE_PATH_ACL:
-                       perm = container_of(ptr, struct tomoyo_path_acl, head)
-                               ->perm;
+                       data_race(perm = container_of(ptr, struct 
tomoyo_path_acl, head)->perm);
                        break;
                case TOMOYO_TYPE_PATH2_ACL:
-                       perm = container_of(ptr, struct tomoyo_path2_acl, head)
-                               ->perm;
+                       data_race(perm = container_of(ptr, struct 
tomoyo_path2_acl, head)->perm);
                        break;
                case TOMOYO_TYPE_PATH_NUMBER_ACL:
-                       perm = container_of(ptr, struct tomoyo_path_number_acl,
-                                           head)->perm;
+                       data_race(perm = container_of(ptr, struct 
tomoyo_path_number_acl, head)
+                                 ->perm);
                        break;
                case TOMOYO_TYPE_MKDEV_ACL:
-                       perm = container_of(ptr, struct tomoyo_mkdev_acl,
-                                           head)->perm;
+                       data_race(perm = container_of(ptr, struct 
tomoyo_mkdev_acl, head)->perm);
                        break;
                case TOMOYO_TYPE_INET_ACL:
-                       perm = container_of(ptr, struct tomoyo_inet_acl,
-                                           head)->perm;
+                       data_race(perm = container_of(ptr, struct 
tomoyo_inet_acl, head)->perm);
                        break;
                case TOMOYO_TYPE_UNIX_ACL:
-                       perm = container_of(ptr, struct tomoyo_unix_acl,
-                                           head)->perm;
+                       data_race(perm = container_of(ptr, struct 
tomoyo_unix_acl, head)->perm);
                        break;
                case TOMOYO_TYPE_MANUAL_TASK_ACL:
                        perm = 0;
-- 
2.27.0

Reply via email to