lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <7e8c1cf0-fccf-1ed9-40ed-3a13b2287cf8@fb.com>
Date:   Tue, 18 Feb 2020 20:03:06 -0800
From:   Yonghong Song <yhs@...com>
To:     Hillf Danton <hdanton@...a.com>
CC:     syzbot <syzbot+122b5421d14e68f29cd1@...kaller.appspotmail.com>,
        <andriin@...com>, <ast@...nel.org>, <bpf@...r.kernel.org>,
        <daniel@...earbox.net>, <kafai@...com>,
        <linux-kernel@...r.kernel.org>, <netdev@...r.kernel.org>,
        <songliubraving@...com>, <syzkaller-bugs@...glegroups.com>
Subject: Re: possible deadlock in bpf_lru_push_free



On 2/18/20 6:15 PM, Hillf Danton wrote:
> 
> Hey
> 
> On Tue, 18 Feb 2020 15:55:02 -0800 Yonghong Song wrote:
>>
>> Thanks for Martin for explanation! I think changing l->hash_node.next is
>> unsafe here as another thread may execute on a different cpu and
>> traverse the same list. It will see hash_node.next = NULL and it is
> 
> Good catch.
> 
>> unexpected.
>>
>> How about the following patch?
>>
> Looks nicer, thanks :P
> 
>> diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
>> index 2d182c4ee9d9..246ef0f2e985 100644
>> --- a/kernel/bpf/hashtab.c
>> +++ b/kernel/bpf/hashtab.c
>> @@ -56,6 +56,7 @@ struct htab_elem {
>>                           union {
>>                                   struct bpf_htab *htab;
>>                                   struct pcpu_freelist_node fnode;
>> +                               struct htab_elem *link;
>>                           };
>>                   };
>>           };
>> @@ -1256,6 +1257,7 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
>>           void __user *ukeys = u64_to_user_ptr(attr->batch.keys);
>>           void *ubatch = u64_to_user_ptr(attr->batch.in_batch);
>>           u32 batch, max_count, size, bucket_size;
>> +       struct htab_elem *node_to_free = NULL;
>>           u64 elem_map_flags, map_flags;
>>           struct hlist_nulls_head *head;
>>           struct hlist_nulls_node *n;
>> @@ -1370,9 +1372,14 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
>>                   }
>>                   if (do_delete) {
>>                           hlist_nulls_del_rcu(&l->hash_node);
>> -                       if (is_lru_map)
>> -                               bpf_lru_push_free(&htab->lru, &l->lru_node);
>> -                       else
>> +                       if (is_lru_map) {
>> +                               /* l->hnode overlaps with *l->hash_node.pprev
> 
> nit: looks like you mean l->link

Yes, my previous attempt uses "hnode" and later changed to "link" but 
forget to change the comments.

Will post a patch soon.

> 
>> +                                * in memory. l->hash_node.pprev has been
>> +                                * poisoned and nobody should access it.
>> +                                */
>> +                               l->link = node_to_free;
>> +                               node_to_free = l;
>> +                       } else
>>                                   free_htab_elem(htab, l);
>>                   }
>>                   dst_key += key_size;
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ