fbmem: fix remove_conflicting_framebuffers races
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 13 May 2011 23:16:41 +0000 (16:16 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 14 May 2011 17:23:44 +0000 (10:23 -0700)
commit712f3147aee0fbbbbed2da20b21b272c5505125e
tree02bf6ff00f1978b4165c2c2d4554606bae65107e
parentc47747fde931c02455683bd00ea43eaa62f35b0e
fbmem: fix remove_conflicting_framebuffers races

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: Bruno PrĂ©mont <bonbons@linux-vserver.org>
Tested-by: Anca Emanuel <anca.emanuel@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/video/fbmem.c