]> git.karo-electronics.de Git - karo-tx-linux.git/commit
ipc/sem.c: avoid overflow of semop undo (semadj) value
authorPetr Mladek <pmladek@suse.cz>
Fri, 3 Jan 2014 03:10:36 +0000 (14:10 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Fri, 3 Jan 2014 03:10:36 +0000 (14:10 +1100)
commita4108c67e7df262bbaf85e39c2185db6062c5def
tree2b382c9907f3bf9ef2ef727ae39511f5cd9334d8
parent4d6ff2cbe16e8339a8c00c4bfd83e79a3478eda1
ipc/sem.c: avoid overflow of semop undo (semadj) value

When trying to understand semop code, I found a small mistake in the check
for semadj (undo) value overflow.  The new undo value is not stored
immediately and next potential checks are done against the old value.

The failing scenario is not much practical.  One semop call has to do more
operations on the same semaphore.  Also semval and semadj must have
different values, so there has to be some operations without SEM_UNDO
flag.  For example:

struct sembuf depositor_op[1];
struct sembuf collector_op[2];

depositor_op[0].sem_num = 0;
depositor_op[0].sem_op = 20000;
depositor_op[0].sem_flg = 0;

collector_op[0].sem_num = 0;
collector_op[0].sem_op = -10000;
collector_op[0].sem_flg = SEM_UNDO;
collector_op[1].sem_num = 0;
collector_op[1].sem_op = -10000;
collector_op[1].sem_flg = SEM_UNDO;

if (semop(semid, depositor_op, 1) == -1)
{ perror("Failed to do 1st deposit"); return 1; }

if (semop(semid, collector_op, 2) == -1)
{ perror("Failed to do 1st collect"); return 1; }

if (semop(semid, depositor_op, 1) == -1)
{ perror("Failed to do 2nd deposit"); return 1; }

if (semop(semid, collector_op, 2) == -1)
{ perror("Failed to do 2nd collect"); return 1; }

return 0;

It passes without error now but the semadj value has overflown in the 2nd
collector operation.

Signed-off-by: Petr Mladek <pmladek@suse.cz>
Acked-by: Davidlohr Bueso <davidlohr@hp.com>
Acked-by: Manfred Spraul <manfred@colorfullife.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
ipc/sem.c