[Wayland-bugs] [Bug 100878] SIGSEGV on wl_list_insert

bugzilla-daemon at freedesktop.org bugzilla-daemon at freedesktop.org
Sat Apr 29 04:11:22 UTC 2017


https://bugs.freedesktop.org/show_bug.cgi?id=100878

            Bug ID: 100878
           Summary: SIGSEGV on wl_list_insert
           Product: Wayland
           Version: unspecified
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: medium
         Component: weston
          Assignee: wayland-bugs at lists.freedesktop.org
          Reporter: worknesday at gmail.com

As seen on SHA 9ad4de1f7ad411fcb5a62eb85e17cf96ae076a0f; no modification

At the bottom of the description, you can find stacktrace.

Analysis:
When I saw this issue, I did some digging around on wl_list type and I suspect
the seg fault arose from the design of the circular-doubly-linked lists
themselves.

If we look at wayland-util.h (where these list functions are declared), you can
see something odd and (potentially) dangerous:

    void
    wl_list_insert(struct wl_list *list, struct wl_list *elm);

    void
    wl_list_remove(struct wl_list *elm); // 

The problem here is that the *identity* of the list is subject to change as you
add/remove nodes -- especially wl_list_remove. If, say, you have a list

    struct wl_list *my_list; // initialized to some list with 3 elements

then you do

    wl_list_remove(my_list)

then you will lose the other elements and my_list is no longer valid nor
circular because wl_list_remove sets prev and next to NULL. Indeed,
wl_list_remove says so explicitly:

    /**
     * Removes an element from the list.
     *
     * \note This operation leaves \p elm in an invalid state.
     *
     * \param elm Link of the containing struct to remove from the list
     *
     * \memberof wl_list
     */

I think a better (robust) design is to wrap and hide the actual node pointers
so that
    1. we preserve the identity (pointer) of the list itself
    2. we can call wl_list_remove multiple times

I envision something like

    struct wl_list_node {
            /** Previous list element */
            struct wl_list_node *prev;
            /** Next list element */
            struct wl_list_node *next;
    };

and wl_list will be

    struct wl_list {
            struct wl_list_node *node;
    };

Then, removing a node would be something like

    // assert that node is an element of list
    void
    wl_list_remove(struct wl_list *list, struct wl_list_node *node);

So, you can snip node out of list. If list->node == node, then you can perform
a fixup (e.g. nudge list->node to the "next" element).

Thus, you ensure the integrity of the list.

I think this is the best option given the circumstance and I hope that I'm not
stepping on peoples' toes.


Stack trace:
    #0  0x00007ffff79a0313 in wl_list_insert () from
/usr/lib64/libwayland-server.so.0
    #1  0x00007fffeeae16cf in wl_signal_add (signal=<optimized out>,
listener=<optimized out>) at /usr/include/wayland-server-core.h:320
    #2  focus_state_set_focus (state=<optimized out>, surface=<optimized out>)
at desktop-shell/shell.c:735
    #3  0x00007fffeeae7435 in activate (shell=0x7820e0, view=<optimized out>,
seat=0x622100, flags=3) at desktop-shell/shell.c:3686
    #4  0x00007ffff7bc5d5d in weston_compositor_run_button_binding
(compositor=compositor at entry=0x614c60, pointer=pointer at entry=0x76c900, 
        time=time at entry=3071980015, button=button at entry=272,
state=state at entry=WL_POINTER_BUTTON_STATE_PRESSED) at libweston/bindings.c:368
    #5  0x00007ffff7bc13cd in notify_button (seat=seat at entry=0x622100,
time=3071980015, button=button at entry=272, 
        state=WL_POINTER_BUTTON_STATE_PRESSED) at libweston/input.c:1673
    #6  0x00007ffff531065b in x11_backend_deliver_button_event (event=0x7bc180,
b=0x622070) at libweston/compositor-x11.c:1230
    #7  x11_backend_handle_event (fd=<optimized out>, mask=<optimized out>,
data=0x622070) at libweston/compositor-x11.c:1422
    #8  0x00007ffff799dd12 in wl_event_loop_dispatch () from
/usr/lib64/libwayland-server.so.0
    #9  0x00007ffff799c1b5 in wl_display_run () from
/usr/lib64/libwayland-server.so.0
    #10 0x0000000000405719 in main (argc=1, argv=<optimized out>) at
compositor/main.c:1969

surface data:
    (gdb) p *es
    $6 = {resource = 0x7b2fb0, destroy_signal = {listener_list = {prev =
0x622190, next = 0x793a90}}, ...

    (gdb) p *es->destroy_signal.listener_list.prev
    $10 = {prev = 0x0, next = 0x7e1348}

-- 
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/wayland-bugs/attachments/20170429/4caec398/attachment.html>


More information about the wayland-bugs mailing list