linux-imx/ipc
Konstantin Khlebnikov 91182754da ipc/msg: fix race around refcount
In older kernels (before v3.10) ipc_rcu_hdr->refcount was non-atomic int.
There was possuble double-free bug: do_msgsnd() calls ipc_rcu_putref() under
msq->q_perm->lock and RCU, while freequeue() calls it while it holds only
'rw_mutex', so there is no sinchronization between them. Two function
decrements '2' non-atomically, they both can get '0' as result.

do_msgsnd()					freequeue()

msq = msg_lock_check(ns, msqid);
...
ipc_rcu_getref(msq);
msg_unlock(msq);
schedule();
						(caller locks spinlock)
						expunge_all(msq, -EIDRM);
						ss_wakeup(&msq->q_senders, 1);
						msg_rmid(ns, msq);
						msg_unlock(msq);
ipc_lock_by_ptr(&msq->q_perm);
ipc_rcu_putref(msq);				ipc_rcu_putref(msq);
< both may get get --(...)->refcount == 0 >

This patch locks ipc_lock and RCU around ipc_rcu_putref in freequeue.
( RCU protects memory for spin_unlock() )

Similar bugs might be in other users of ipc_rcu_putref().

In the mainline this has been fixed in v3.10 indirectly in commmit
6062a8dc05
("ipc,sem: fine grained locking for semtimedop") by Rik van Riel.
That commit optimized locking and converted refcount into atomic.

I'm not sure that anybody should care about this bug: it's very-very unlikely
and no longer exists in actual mainline. I've found this just by looking into
the code, probably this never happens in real life.

Signed-off-by: Konstantin Khlebnikov <k.khlebnikov@samsung.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
2014-04-09 02:20:45 +01:00
..
compat_mq.c ipc: initialize structure memory to zero for compat functions 2010-10-27 18:03:13 -07:00
compat.c ipc: initialize structure memory to zero for compat functions 2010-10-27 18:03:13 -07:00
ipc_sysctl.c ipc: introduce shm_rmid_forced sysctl 2011-07-26 16:49:44 -07:00
ipcns_notifier.c ipc: do not use a negative value to re-enable msgmni automatic recomputing 2008-07-25 10:53:42 -07:00
Makefile Add generic sys_ipc wrapper 2010-03-12 15:52:32 -08:00
mq_sysctl.c sysctl ipc: Remove dead binary sysctl support code. 2009-11-12 02:04:54 -08:00
mqueue.c ... and the same kind of leak for mqueue 2011-12-09 00:40:21 -05:00
msg.c ipc/msg: fix race around refcount 2014-04-09 02:20:45 +01:00
msgutil.c ipc, msg: fix message length check for negative values 2014-01-03 04:33:21 +00:00
namespace.c ns proc: Add support for the ipc namespace 2011-05-10 14:35:47 -07:00
sem.c ipc/sem.c: remove private structures from public header file 2011-11-02 16:07:01 -07:00
shm.c ipc: sysv shared memory limited to 8TiB 2013-05-13 15:02:30 +01:00
syscall.c ppc64 sys_ipc breakage in 2.6.34-rc2 2010-03-22 09:57:19 -07:00
util.c ipc,rcu: Convert call_rcu(ipc_immediate_free) to kfree_rcu() 2011-07-20 14:10:16 -07:00
util.h ipc, msg: fix message length check for negative values 2014-01-03 04:33:21 +00:00