Received: by 2002:a25:e7d8:0:0:0:0:0 with SMTP id e207csp475831ybh; Tue, 10 Mar 2020 02:22:00 -0700 (PDT) X-Google-Smtp-Source: ADFU+vt+nc+CllRHs2fNOlPqKoaZ3+8O67tzu5gTkrEfPj2facXp7Ipg/5l1dXk+lTDgBODzgdum X-Received: by 2002:a9d:649a:: with SMTP id g26mr16463104otl.266.1583832120643; Tue, 10 Mar 2020 02:22:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1583832120; cv=none; d=google.com; s=arc-20160816; b=tceoT/wACPtuIFS09oiuGXILbos8PqyMzy+iqx3JK56ClAwMAzIxwbwDuq69Nxsv8z 9b7ijbO57YGUJZm1+6I4AzKnJAlsVpS0LW5H609Zmblq5Rp8qncmkxsMFXz1r4E2lsFJ WOv67cJlqpRvqhVkzGr2GJQW5tCRgx0wp9S3EjZW4C2piEF0DmQcctRdGC8aR1uISzvG Id3mgkmY5ODFxC8TI7e1/ysWqeCP9Qdl2+41f+VqLl3uWKUG1TYLeuqatk6iFIu6cXe/ /pS8DTxzMs9J/zZXVHgnKrdEAo3kVjHpwhoo48eQpIQrJNbSENkE/DHWty9C/F7MKwD/ nNTQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from; bh=59Ha+YTD4mZp00jzWdZtzVL/amDsFEz2rI0s6VFhpzE=; b=CXwak/ykQCbvDKYv3bHEUldqGRM9Y457SXjN7oBWJ2sD7gu6wkxx9Td5iZmbcJztcD jSYou5d+p/d7zRbgh5rA2jpUuM1wuARoLI2LmszU96MPK/w1lWAzueZRsoRb0ZsgtMCJ w4yT+uw+WYrg6ZMl3Ou3ZpHj+7NF1UEDtsmTCjRvpouMu/Io2pJqGrYPgBXD2vkFT0nc Uhzuz8vmMo2Jg+a139iEUhOHPuttT5YXVBMB4hgUh/plRBi3EysZ9dpiz+BGdWPZmFf5 THccxiOcC41SaCuvrkFpKO4ipv6+67SY3fBZx2W8L9w+2hoqeq0aEH1ILoboNQnxbUMR OMkw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e2si2808774otr.30.2020.03.10.02.21.48; Tue, 10 Mar 2020 02:22:00 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726295AbgCJJV1 (ORCPT + 99 others); Tue, 10 Mar 2020 05:21:27 -0400 Received: from mail.fireflyinternet.com ([109.228.58.192]:49462 "EHLO fireflyinternet.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726202AbgCJJV1 (ORCPT ); Tue, 10 Mar 2020 05:21:27 -0400 X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from build.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 20505102-1500050 for multiple; Tue, 10 Mar 2020 09:21:20 +0000 From: Chris Wilson To: linux-kernel@vger.kernel.org Cc: intel-gfx@lists.freedesktop.org, Chris Wilson , Andrew Morton , "Paul E. McKenney" , Randy Dunlap , stable@vger.kernel.org Subject: [PATCH] list: Prevent compiler reloads inside 'safe' list iteration Date: Tue, 10 Mar 2020 09:21:19 +0000 Message-Id: <20200310092119.14965-1-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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. Signed-off-by: Chris Wilson Cc: Andrew Morton Cc: "Paul E. McKenney" Cc: Randy Dunlap Cc: stable@vger.kernel.org --- include/linux/list.h | 50 +++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/include/linux/list.h b/include/linux/list.h index 884216db3246..c4d215d02259 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -536,6 +536,17 @@ static inline void list_splice_tail_init(struct list_head *list, #define list_next_entry(pos, member) \ 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 @@ -544,6 +555,17 @@ static inline void list_splice_tail_init(struct list_head *list, #define list_prev_entry(pos, member) \ 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. @@ -686,9 +708,9 @@ static inline void list_splice_tail_init(struct list_head *list, */ #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(struct list_head *list, * 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(struct list_head *list, * 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(struct list_head *list, */ #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(struct list_head *list, * 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. -- 2.20.1