tomoyo: Suppress RCU warning at list_for_each_entry_rcu().
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Mon, 16 Dec 2019 10:16:48 +0000 (19:16 +0900)
committerTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Mon, 16 Dec 2019 14:02:27 +0000 (23:02 +0900)
John Garry has reported that allmodconfig kernel on arm64 causes flood of
"RCU-list traversed in non-reader section!!" warning. I don't know what
change caused this warning, but this warning is safe because TOMOYO uses
SRCU lock instead. Let's suppress this warning by explicitly telling that
the caller is holding SRCU lock.

Reported-and-tested-by: John Garry <john.garry@huawei.com>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
security/tomoyo/common.c
security/tomoyo/domain.c
security/tomoyo/group.c
security/tomoyo/util.c

index dd3d5942e6692457b505e137e0bd30ef6cb90dab..c36bafbcd77ee4fc29396cbd657c600589448e94 100644 (file)
@@ -951,7 +951,8 @@ static bool tomoyo_manager(void)
        exe = tomoyo_get_exe();
        if (!exe)
                return false;
-       list_for_each_entry_rcu(ptr, &tomoyo_kernel_namespace.policy_list[TOMOYO_ID_MANAGER], head.list) {
+       list_for_each_entry_rcu(ptr, &tomoyo_kernel_namespace.policy_list[TOMOYO_ID_MANAGER], head.list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (!ptr->head.is_deleted &&
                    (!tomoyo_pathcmp(domainname, ptr->manager) ||
                     !strcmp(exe, ptr->manager->name))) {
@@ -1095,7 +1096,8 @@ static int tomoyo_delete_domain(char *domainname)
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
                return -EINTR;
        /* Is there an active domain? */
-       list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
+       list_for_each_entry_rcu(domain, &tomoyo_domain_list, list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                /* Never delete tomoyo_kernel_domain */
                if (domain == &tomoyo_kernel_domain)
                        continue;
@@ -2778,7 +2780,8 @@ void tomoyo_check_profile(void)
 
        tomoyo_policy_loaded = true;
        pr_info("TOMOYO: 2.6.0\n");
-       list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
+       list_for_each_entry_rcu(domain, &tomoyo_domain_list, list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                const u8 profile = domain->profile;
                struct tomoyo_policy_namespace *ns = domain->ns;
 
index 8526a0a74023855bbf383e56528e7ebf8107a8a9..7869d6a9980bfc4e7c0cf70a826d7b5661aaef67 100644 (file)
@@ -41,7 +41,8 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
 
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
                return -ENOMEM;
-       list_for_each_entry_rcu(entry, list, list) {
+       list_for_each_entry_rcu(entry, list, list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (entry->is_deleted == TOMOYO_GC_IN_PROGRESS)
                        continue;
                if (!check_duplicate(entry, new_entry))
@@ -119,7 +120,8 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
        }
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
                goto out;
-       list_for_each_entry_rcu(entry, list, list) {
+       list_for_each_entry_rcu(entry, list, list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (entry->is_deleted == TOMOYO_GC_IN_PROGRESS)
                        continue;
                if (!tomoyo_same_acl_head(entry, new_entry) ||
@@ -166,7 +168,8 @@ void tomoyo_check_acl(struct tomoyo_request_info *r,
        u16 i = 0;
 
 retry:
-       list_for_each_entry_rcu(ptr, list, list) {
+       list_for_each_entry_rcu(ptr, list, list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (ptr->is_deleted || ptr->type != r->param_type)
                        continue;
                if (!check_entry(r, ptr))
@@ -298,7 +301,8 @@ static inline bool tomoyo_scan_transition
 {
        const struct tomoyo_transition_control *ptr;
 
-       list_for_each_entry_rcu(ptr, list, head.list) {
+       list_for_each_entry_rcu(ptr, list, head.list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (ptr->head.is_deleted || ptr->type != type)
                        continue;
                if (ptr->domainname) {
@@ -735,7 +739,8 @@ retry:
 
                /* Check 'aggregator' directive. */
                candidate = &exename;
-               list_for_each_entry_rcu(ptr, list, head.list) {
+               list_for_each_entry_rcu(ptr, list, head.list,
+                                       srcu_read_lock_held(&tomoyo_ss)) {
                        if (ptr->head.is_deleted ||
                            !tomoyo_path_matches_pattern(&exename,
                                                         ptr->original_name))
index a37c7dc66e4448e41a498b5005950e6d127833e3..1cecdd7975971224683fc5f660eaf5e29d2fdacf 100644 (file)
@@ -133,7 +133,8 @@ tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
 {
        struct tomoyo_path_group *member;
 
-       list_for_each_entry_rcu(member, &group->member_list, head.list) {
+       list_for_each_entry_rcu(member, &group->member_list, head.list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (member->head.is_deleted)
                        continue;
                if (!tomoyo_path_matches_pattern(pathname, member->member_name))
@@ -161,7 +162,8 @@ bool tomoyo_number_matches_group(const unsigned long min,
        struct tomoyo_number_group *member;
        bool matched = false;
 
-       list_for_each_entry_rcu(member, &group->member_list, head.list) {
+       list_for_each_entry_rcu(member, &group->member_list, head.list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (member->head.is_deleted)
                        continue;
                if (min > member->number.values[1] ||
@@ -191,7 +193,8 @@ bool tomoyo_address_matches_group(const bool is_ipv6, const __be32 *address,
        bool matched = false;
        const u8 size = is_ipv6 ? 16 : 4;
 
-       list_for_each_entry_rcu(member, &group->member_list, head.list) {
+       list_for_each_entry_rcu(member, &group->member_list, head.list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (member->head.is_deleted)
                        continue;
                if (member->address.is_ipv6 != is_ipv6)
index 52752e1a84ed8f9131d303896e3a3af7504247da..eba0b3395851e0ae4a3be8be16dc37f28dccd726 100644 (file)
@@ -594,7 +594,8 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
 
        name.name = domainname;
        tomoyo_fill_path_info(&name);
-       list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
+       list_for_each_entry_rcu(domain, &tomoyo_domain_list, list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (!domain->is_deleted &&
                    !tomoyo_pathcmp(&name, domain->domainname))
                        return domain;
@@ -1028,7 +1029,8 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
                return false;
        if (!domain)
                return true;
-       list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
+       list_for_each_entry_rcu(ptr, &domain->acl_info_list, list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                u16 perm;
                u8 i;