| From 5797e861e402fff2bedce4ec8b7c89f4248b6073 Mon Sep 17 00:00:00 2001 |
| From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> |
| Date: Mon, 1 Feb 2021 11:52:11 +0900 |
| Subject: tomoyo: ignore data race while checking quota |
| |
| From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> |
| |
| commit 5797e861e402fff2bedce4ec8b7c89f4248b6073 upstream. |
| |
| 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+0789a72b46fd91431bd8@syzkaller.appspotmail.com> |
| Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| security/tomoyo/file.c | 16 ++++++++-------- |
| security/tomoyo/network.c | 8 ++++---- |
| security/tomoyo/util.c | 24 ++++++++++++------------ |
| 3 files changed, 24 insertions(+), 24 deletions(-) |
| |
| --- a/security/tomoyo/file.c |
| +++ b/security/tomoyo/file.c |
| @@ -362,14 +362,14 @@ static bool tomoyo_merge_path_acl(struct |
| { |
| 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; |
| } |
| |
| @@ -437,7 +437,7 @@ static bool tomoyo_merge_mkdev_acl(struc |
| { |
| 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; |
| |
| @@ -445,7 +445,7 @@ static bool tomoyo_merge_mkdev_acl(struc |
| perm &= ~b_perm; |
| else |
| perm |= b_perm; |
| - *a_perm = perm; |
| + WRITE_ONCE(*a_perm, perm); |
| return !perm; |
| } |
| |
| @@ -517,14 +517,14 @@ static bool tomoyo_merge_path2_acl(struc |
| { |
| 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; |
| } |
| |
| @@ -655,7 +655,7 @@ static bool tomoyo_merge_path_number_acl |
| { |
| 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; |
| |
| @@ -663,7 +663,7 @@ static bool tomoyo_merge_path_number_acl |
| perm &= ~b_perm; |
| else |
| perm |= b_perm; |
| - *a_perm = perm; |
| + WRITE_ONCE(*a_perm, perm); |
| return !perm; |
| } |
| |
| --- a/security/tomoyo/network.c |
| +++ b/security/tomoyo/network.c |
| @@ -233,14 +233,14 @@ static bool tomoyo_merge_inet_acl(struct |
| { |
| 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 |
| { |
| 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; |
| } |
| |
| --- a/security/tomoyo/util.c |
| +++ b/security/tomoyo/util.c |
| @@ -1058,30 +1058,30 @@ bool tomoyo_domain_quota_is_ok(struct to |
| |
| 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; |