• Linus Torvalds's avatar
    fbmem: fix remove_conflicting_framebuffers races · 712f3147
    Linus Torvalds authored
    When a register_framebuffer() call results in us removing old
    conflicting framebuffers, the new registration_lock doesn't protect that
    situation.  And we can't just add the same locking to the function,
    because these functions call each other: register_framebuffer() calls
    remove_conflicting_framebuffers, which in turn calls
    unregister_framebuffer for any conflicting entry.
    
    In order to fix it, this just creates wrapper functions around all three
    functions and makes the versions that actually do the work be called
    "do_xxx()", leaving just the wrapper that gets the lock and calls the
    worker function.
    
    So the rule becomes simply that "do_xxxx()" has to be called with the
    lock held, and now do_register_framebuffer() can just call
    do_remove_conflicting_framebuffers(), and that in turn can call
    _do_unregister_framebuffer(), and there is no deadlock, and we can hold
    the registration lock over the whole sequence, fixing the races.
    
    It also makes error cases simpler, and fixes one situation where we
    would return from unregister_framebuffer() without releasing the lock,
    pointed out by Bruno Prémont.
    Tested-by: default avatarBruno Prémont <bonbons@linux-vserver.org>
    Tested-by: default avatarAnca Emanuel <anca.emanuel@gmail.com>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    712f3147
fbmem.c 44.6 KB