Re: + list-prevent-compiler-reloads-inside-safe-list-iteration.patch added to -mm tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Mar 11, 2020 at 07:58:09PM -0700, Andrew Morton wrote:
> 
> The patch titled
>      Subject: lib/list: prevent compiler reloads inside 'safe' list iteration
> has been added to the -mm tree.  Its filename is
>      list-prevent-compiler-reloads-inside-safe-list-iteration.patch
> 
> This patch should soon appear at
>     http://ozlabs.org/~akpm/mmots/broken-out/list-prevent-compiler-reloads-inside-safe-list-iteration.patch
> and later at
>     http://ozlabs.org/~akpm/mmotm/broken-out/list-prevent-compiler-reloads-inside-safe-list-iteration.patch
> 
> Before you just go and hit "reply", please:
>    a) Consider who else should be cc'ed
>    b) Prefer to cc a suitable mailing list as well
>    c) Ideally: find the original patch on the mailing list and do a
>       reply-to-all to that, adding suitable additional cc's
> 
> *** Remember to use Documentation/process/submit-checklist.rst when testing your code ***
> 
> The -mm tree is included into linux-next and is updated
> there every 3-4 working days
> 
> ------------------------------------------------------
> From: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
> Subject: lib/list: prevent compiler reloads inside 'safe' list iteration
> 
> Instruct the compiler to read the next element in the list iteration
> once, and that it is not allowed to reload the value from the stale
> element later. This is important as during the course of the safe
> iteration, the stale element may be poisoned (unbeknownst to the
> compiler).
> 
> This helps prevent kcsan warnings over 'unsafe' conduct in releasing the
> list elements during list_for_each_entry_safe() and friends.
> 
> Link: http://lkml.kernel.org/r/20200310092119.14965-1-chris@xxxxxxxxxxxxxxxxxx
> Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
> Cc: "Paul E. McKenney" <paulmck@xxxxxxxxxx>
> Cc: Randy Dunlap <rdunlap@xxxxxxxxxxxxx>
> Cc: David Laight <David.Laight@xxxxxxxxxx>
> Cc: Mark Rutland <mark.rutland@xxxxxxx>
> Cc: Marco Elver <elver@xxxxxxxxxx>
> Cc: <stable@xxxxxxxxxxxxxxx>
> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>

One possible concern is that we are overloading the suffix "_safe()",
but that looks better to me than yet another explosion of this API.
It would be good to have uses, of course.

Reviewed-by: Paul E. McKenney <paulmck@xxxxxxxxxx>

> ---
> 
>  include/linux/list.h |   50 +++++++++++++++++++++++++++++------------
>  1 file changed, 36 insertions(+), 14 deletions(-)
> 
> --- a/include/linux/list.h~list-prevent-compiler-reloads-inside-safe-list-iteration
> +++ a/include/linux/list.h
> @@ -537,6 +537,17 @@ static inline void list_splice_tail_init
>  	list_entry((pos)->member.next, typeof(*(pos)), member)
>  
>  /**
> + * list_next_entry_safe - get the next element in list [once]
> + * @pos:	the type * to cursor
> + * @member:	the name of the list_head within the struct.
> + *
> + * Like list_next_entry() but prevents the compiler from reloading the
> + * next element.
> + */
> +#define list_next_entry_safe(pos, member) \
> +	list_entry(READ_ONCE((pos)->member.next), typeof(*(pos)), member)
> +
> +/**
>   * list_prev_entry - get the prev element in list
>   * @pos:	the type * to cursor
>   * @member:	the name of the list_head within the struct.
> @@ -545,6 +556,17 @@ static inline void list_splice_tail_init
>  	list_entry((pos)->member.prev, typeof(*(pos)), member)
>  
>  /**
> + * list_prev_entry_safe - get the prev element in list [once]
> + * @pos:	the type * to cursor
> + * @member:	the name of the list_head within the struct.
> + *
> + * Like list_prev_entry() but prevents the compiler from reloading the
> + * previous element.
> + */
> +#define list_prev_entry_safe(pos, member) \
> +	list_entry(READ_ONCE((pos)->member.prev), typeof(*(pos)), member)
> +
> +/**
>   * list_for_each	-	iterate over a list
>   * @pos:	the &struct list_head to use as a loop cursor.
>   * @head:	the head for your list.
> @@ -686,9 +708,9 @@ static inline void list_splice_tail_init
>   */
>  #define list_for_each_entry_safe(pos, n, head, member)			\
>  	for (pos = list_first_entry(head, typeof(*pos), member),	\
> -		n = list_next_entry(pos, member);			\
> +		n = list_next_entry_safe(pos, member);			\
>  	     &pos->member != (head); 					\
> -	     pos = n, n = list_next_entry(n, member))
> +	     pos = n, n = list_next_entry_safe(n, member))
>  
>  /**
>   * list_for_each_entry_safe_continue - continue list iteration safe against removal
> @@ -700,11 +722,11 @@ static inline void list_splice_tail_init
>   * Iterate over list of given type, continuing after current point,
>   * safe against removal of list entry.
>   */
> -#define list_for_each_entry_safe_continue(pos, n, head, member) 		\
> -	for (pos = list_next_entry(pos, member), 				\
> -		n = list_next_entry(pos, member);				\
> -	     &pos->member != (head);						\
> -	     pos = n, n = list_next_entry(n, member))
> +#define list_for_each_entry_safe_continue(pos, n, head, member) 	\
> +	for (pos = list_next_entry(pos, member), 			\
> +		n = list_next_entry_safe(pos, member);			\
> +	     &pos->member != (head);					\
> +	     pos = n, n = list_next_entry_safe(n, member))
>  
>  /**
>   * list_for_each_entry_safe_from - iterate over list from current point safe against removal
> @@ -716,10 +738,10 @@ static inline void list_splice_tail_init
>   * Iterate over list of given type from current point, safe against
>   * removal of list entry.
>   */
> -#define list_for_each_entry_safe_from(pos, n, head, member) 			\
> -	for (n = list_next_entry(pos, member);					\
> -	     &pos->member != (head);						\
> -	     pos = n, n = list_next_entry(n, member))
> +#define list_for_each_entry_safe_from(pos, n, head, member) 		\
> +	for (n = list_next_entry_safe(pos, member);			\
> +	     &pos->member != (head);					\
> +	     pos = n, n = list_next_entry_safe(n, member))
>  
>  /**
>   * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
> @@ -733,9 +755,9 @@ static inline void list_splice_tail_init
>   */
>  #define list_for_each_entry_safe_reverse(pos, n, head, member)		\
>  	for (pos = list_last_entry(head, typeof(*pos), member),		\
> -		n = list_prev_entry(pos, member);			\
> +		n = list_prev_entry_safe(pos, member);			\
>  	     &pos->member != (head); 					\
> -	     pos = n, n = list_prev_entry(n, member))
> +	     pos = n, n = list_prev_entry_safe(n, member))
>  
>  /**
>   * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
> @@ -750,7 +772,7 @@ static inline void list_splice_tail_init
>   * completing the current iteration of the loop body.
>   */
>  #define list_safe_reset_next(pos, n, member)				\
> -	n = list_next_entry(pos, member)
> +	n = list_next_entry_safe(pos, member)
>  
>  /*
>   * Double linked lists with a single pointer list head.
> _
> 
> Patches currently in -mm which might be from chris@xxxxxxxxxxxxxxxxxx are
> 
> list-prevent-compiler-reloads-inside-safe-list-iteration.patch
> 



[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux