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>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <c475f0d8-3bc9-4d65-8fce-586f4b75b4fc@linux.ibm.com>
Date: Thu, 13 Jun 2024 19:11:52 +0530
From: Nilay Shroff <nilay@...ux.ibm.com>
To: Keith Busch <kbusch@...nel.org>
Cc: Keith Busch <kbusch@...a.com>, linux-nvme@...ts.infradead.org,
        linux-kernel@...r.kernel.org, linux-kselftest@...r.kernel.org,
        hch@....de, sagi@...mberg.me, paulmck@...nel.org, davidgow@...gle.com,
        akpm@...ux-foundation.org, venkat88@...ux.vnet.ibm.com
Subject: Re: [PATCH 1/2] list: introduce a new cutting helper



On 6/13/24 18:26, Keith Busch wrote:
> On Thu, Jun 13, 2024 at 10:26:11AM +0530, Nilay Shroff wrote:
>> On 6/12/24 21:21, Keith Busch wrote:
>>> +static inline void list_cut(struct list_head *list,
>>> +		struct list_head *head, struct list_head *entry)
>>> +{
>>> +	list->next = entry;
>>> +	list->prev = head->prev;
>>> +	head->prev = entry->prev;
>>> +	entry->prev->next = head;
>>> +	entry->prev = list;
>>> +	list->prev->next = list;
>>> +}
>> I am wondering whether we really need the _rcu version of list_cut here?
>> I think that @head could point to an _rcu protected list and that's true 
>> for this patch. So there might be concurrent readers accessing @head using
>> _rcu list-traversal primitives, such as list_for_each_entry_rcu().
>>
>> An _rcu version of list_cut():
>>
>> static inline void list_cut_rcu(struct list_head *list,
>> 		struct list_head *head, struct list_head *entry)
>> {
>> 	list->next = entry;
>> 	list->prev = head->prev;
>> 	head->prev = entry->prev;
>> 	rcu_assign_pointer(list_next_rcu(entry->prev), head);
>> 	entry->prev = list;
>> 	list->prev->next = list;
>> }
> 
> I was initially thinking similiar, but this is really just doing a
> "list_del", and the rcu version calls the same generic __list_del()
> helper. To make this more clear, we could change
> 
> 	head->prev = entry->prev;
> 	entry->prev->next = head;
> 
> To just this:
> 
> 	__list_del(entry->prev, head);
> 
> And that also gets the "WRITE_ONCE" usage right.
Yeah this sounds reasonable.

> 
> But that's not the problem for the rcu case. It's the last line that's
> the problem:
> 
>  	list->prev->next = list;
> 
> We can't change forward pointers for any element being detached from
> @head because a reader iterating the list may see that new pointer value
> and end up in the wrong list, breaking iteration. A synchronize rcu
> needs to happen before forward pointers can be mucked with, so it still
> needs to be done in two steps. Oh bother...

Agree and probably we may break it down using this API:
static inline void list_cut_rcu(struct list_head *list,
 		struct list_head *head, struct list_head *entry, 
		void (*sync)(void))
{
 	list->next = entry;
 	list->prev = head->prev;
	__list_del(entry->prev, head);
	sync();
 	entry->prev = list;
 	list->prev->next = list;
}

Thanks,
--Nilay


 




Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ