From: "Philippe Mathieu-Daudé" <philmd@redhat.com>
To: Stefan Hajnoczi <stefanha@redhat.com>, qemu-devel@nongnu.org
Cc: Fam Zheng <fam@euphon.net>, Paolo Bonzini <pbonzini@redhat.com>,
	qemu-block@nongnu.org
Subject: Re: [PATCH 1/2] qemu/queue.h: clear linked list pointers on remove
Date: Mon, 24 Feb 2020 12:51:54 +0100	[thread overview]
Message-ID: <0a6d15b1-7936-82a2-0d65-a1b77c4c5cc1@redhat.com> (raw)
In-Reply-To: <20200224103406.1894923-2-stefanha@redhat.com>
On 2/24/20 11:34 AM, Stefan Hajnoczi wrote:
> Do not leave stale linked list pointers around after removal.  It's
> safer to set them to NULL so that use-after-removal results in an
> immediate segfault.
> 
> The RCU queue removal macros are unchanged since nodes may still be
> traversed after removal.
> 
> Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
>   include/qemu/queue.h | 19 +++++++++++++++----
>   1 file changed, 15 insertions(+), 4 deletions(-)
> 
> diff --git a/include/qemu/queue.h b/include/qemu/queue.h
> index 294db54eb1..456a5b01ee 100644
> --- a/include/qemu/queue.h
> +++ b/include/qemu/queue.h
> @@ -142,6 +142,8 @@ struct {                                                                \
>                   (elm)->field.le_next->field.le_prev =                   \
>                       (elm)->field.le_prev;                               \
>           *(elm)->field.le_prev = (elm)->field.le_next;                   \
> +        (elm)->field.le_next = NULL;                                    \
> +        (elm)->field.le_prev = NULL;                                    \
>   } while (/*CONSTCOND*/0)
OK.
>   
>   /*
> @@ -225,12 +227,15 @@ struct {                                                                \
>   } while (/*CONSTCOND*/0)
>   
>   #define QSLIST_REMOVE_HEAD(head, field) do {                             \
> -        (head)->slh_first = (head)->slh_first->field.sle_next;          \
> +        typeof((head)->slh_first) elm = (head)->slh_first;               \
> +        (head)->slh_first = elm->field.sle_next;                         \
> +        elm->field.sle_next = NULL;                                      \
>   } while (/*CONSTCOND*/0)
>   
>   #define QSLIST_REMOVE_AFTER(slistelm, field) do {                       \
> -        (slistelm)->field.sle_next =                                    \
> -            QSLIST_NEXT(QSLIST_NEXT((slistelm), field), field);         \
> +        typeof(slistelm) next = (slistelm)->field.sle_next;             \
> +        (slistelm)->field.sle_next = next->field.sle_next;              \
> +        next->field.sle_next = NULL;                                    \
>   } while (/*CONSTCOND*/0)
>   
>   #define QSLIST_REMOVE(head, elm, type, field) do {                      \
> @@ -241,6 +246,7 @@ struct {                                                                \
>           while (curelm->field.sle_next != (elm))                         \
>               curelm = curelm->field.sle_next;                            \
>           curelm->field.sle_next = curelm->field.sle_next->field.sle_next; \
> +        (elm)->field.sle_next = NULL;                                   \
>       }                                                                   \
>   } while (/*CONSTCOND*/0)
>   
> @@ -304,8 +310,10 @@ struct {                                                                \
>   } while (/*CONSTCOND*/0)
>   
>   #define QSIMPLEQ_REMOVE_HEAD(head, field) do {                          \
> -    if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL)\
> +    typeof((head)->sqh_first) elm = (head)->sqh_first;                  \
> +    if (((head)->sqh_first = elm->field.sqe_next) == NULL)              \
>           (head)->sqh_last = &(head)->sqh_first;                          \
Here you check elm for NULL ...
> +    elm->field.sqe_next = NULL;                                         \
... then you assign it.
>   } while (/*CONSTCOND*/0)
>   
>   #define QSIMPLEQ_SPLIT_AFTER(head, elm, field, removed) do {            \
> @@ -329,6 +337,7 @@ struct {                                                                \
>           if ((curelm->field.sqe_next =                                   \
>               curelm->field.sqe_next->field.sqe_next) == NULL)            \
>                   (head)->sqh_last = &(curelm)->field.sqe_next;           \
> +        (elm)->field.sqe_next = NULL;                                   \
>       }                                                                   \
>   } while (/*CONSTCOND*/0)
>   
> @@ -446,6 +455,8 @@ union {                                                                 \
>               (head)->tqh_circ.tql_prev = (elm)->field.tqe_circ.tql_prev; \
>           (elm)->field.tqe_circ.tql_prev->tql_next = (elm)->field.tqe_next; \
>           (elm)->field.tqe_circ.tql_prev = NULL;                          \
> +        (elm)->field.tqe_circ.tql_next = NULL;                          \
> +        (elm)->field.tqe_next = NULL;                                   \
>   } while (/*CONSTCOND*/0)
>   
>   /* remove @left, @right and all elements in between from @head */
> 
next prev parent reply	other threads:[~2020-02-24 11:52 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-24 10:34 [PATCH 0/2] qemu/queue.h: clear linked list pointers on remove Stefan Hajnoczi
2020-02-24 10:34 ` [PATCH 1/2] " Stefan Hajnoczi
2020-02-24 11:51   ` Philippe Mathieu-Daudé [this message]
2020-02-25  9:01     ` Stefan Hajnoczi
2020-02-24 10:34 ` [PATCH 2/2] aio-posix: remove confusing QLIST_SAFE_REMOVE() Stefan Hajnoczi
2020-02-24 10:55 ` [PATCH 0/2] qemu/queue.h: clear linked list pointers on remove no-reply
2020-02-24 11:39   ` Stefan Hajnoczi
2020-02-24 11:54     ` Philippe Mathieu-Daudé
2020-02-25  9:05       ` Stefan Hajnoczi
2020-02-25 10:06         ` Philippe Mathieu-Daudé
2020-03-09 16:40 ` Stefan Hajnoczi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox
  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):
  git send-email \
    --in-reply-to=0a6d15b1-7936-82a2-0d65-a1b77c4c5cc1@redhat.com \
    --to=philmd@redhat.com \
    --cc=fam@euphon.net \
    --cc=pbonzini@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY
  https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
  Be sure your reply has a Subject: header at the top and a blank line
  before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).