From owner-freebsd-bugs@FreeBSD.ORG Mon Nov 19 17:00:01 2012 Return-Path: Delivered-To: freebsd-bugs@smarthost.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 65A4B49B for ; Mon, 19 Nov 2012 17:00:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) by mx1.freebsd.org (Postfix) with ESMTP id 39A018FC18 for ; Mon, 19 Nov 2012 17:00:01 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.5/8.14.5) with ESMTP id qAJH01Ir033639 for ; Mon, 19 Nov 2012 17:00:01 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.5/8.14.5/Submit) id qAJH01Jf033638; Mon, 19 Nov 2012 17:00:01 GMT (envelope-from gnats) Resent-Date: Mon, 19 Nov 2012 17:00:01 GMT Resent-Message-Id: <201211191700.qAJH01Jf033638@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Anton Lavrentiev Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id A96EC400 for ; Mon, 19 Nov 2012 16:53:50 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from red.freebsd.org (red.freebsd.org [IPv6:2001:4f8:fff6::22]) by mx1.freebsd.org (Postfix) with ESMTP id 85F008FC14 for ; Mon, 19 Nov 2012 16:53:50 +0000 (UTC) Received: from red.freebsd.org (localhost [127.0.0.1]) by red.freebsd.org (8.14.5/8.14.5) with ESMTP id qAJGro5c034895 for ; Mon, 19 Nov 2012 16:53:50 GMT (envelope-from nobody@red.freebsd.org) Received: (from nobody@localhost) by red.freebsd.org (8.14.5/8.14.5/Submit) id qAJGroBH034894; Mon, 19 Nov 2012 16:53:50 GMT (envelope-from nobody) Message-Id: <201211191653.qAJGroBH034894@red.freebsd.org> Date: Mon, 19 Nov 2012 16:53:50 GMT From: Anton Lavrentiev To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Subject: misc/173724: SYSV semaphore adjustment incorrect for SETVAL for array with 2 or more semaphores X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Nov 2012 17:00:01 -0000 >Number: 173724 >Category: misc >Synopsis: SYSV semaphore adjustment incorrect for SETVAL for array with 2 or more semaphores >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon Nov 19 17:00:00 UTC 2012 >Closed-Date: >Last-Modified: >Originator: Anton Lavrentiev >Release: 8.3-RELEASE-p3 FreeBSD 8.3-RELEASE-p3 #0: Mon Jun 11 23:52:38 UTC 2012 >Organization: >Environment: >Description: SYSV semaphore adjustment is not done correctly for arrays with more than one semathore. #include #include #include #include #include #define BUG1 #define BUG2 #define SEMKEY 1 union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* array for GETALL, SETALL */ }; static void doCriticalWork(void) { return; } int main(void) { struct sembuf lock[2]; int n, semid; if ((semid = semget(SEMKEY, 2, IPC_CREAT | 0666)) < 0) { perror("semget(IPC_CREATE)"); return 1; } #ifdef BUG1 lock[0].sem_num = 0; lock[0].sem_op = 0; lock[0].sem_flg = IPC_NOWAIT; lock[1].sem_num = 0; lock[1].sem_op = 1; #ifdef BUG2 lock[1].sem_flg = SEM_UNDO; #else lock[1].sem_flg = 0; #endif if (semop(semid, lock, 2) != 0) { perror("semop(LOCK[0])"); return 1; } #endif for (n = 0; ; ++n) { static const union semun arg = { 0 }; int error; printf("Iteration %d\n", n); lock[0].sem_num = 1; lock[0].sem_op = 0; /* precondition: [1] == 0 */ lock[0].sem_flg = 0; lock[1].sem_num = 1; lock[1].sem_op = 1; /* postcondition: [1] == 1 */ lock[1].sem_flg = SEM_UNDO; if (semop(semid, lock, 2) < 0) { error = errno; fprintf(stderr, "semop(LOCK[1]): %d, %s\n", error, strerror(error)); break; } doCriticalWork(); #if 1 if (semctl(semid, 1, SETVAL, arg) < 0) { error = errno; fprintf(stderr, "semctl(UNLOCK[1]): %d, %s\n", error, strerror(error)); break; } #else lock[0].sem_num = 1; lock[0].sem_op = -1; lock[0].sem_flg = SEM_UNDO | IPC_NOWAIT; if (semop(semid, lock, 1) < 0) { error = errno; fprintf(stderr, "semop(UNLOCK[1]): %d, %s\n", error, strerror(error)); break; } #endif } return 1; } >How-To-Repeat: Compile and run the code shown in the problem description. It will stop at iteration 16384 suggesting the UNDO adjustment value overflow with ERANGE (which should have not happened because SETVAL should have cleared all the UNDO adjustments on each loop iteration). >Fix: The probable cause is the implementation semundo_clear() found in sys/kern/sysv_sem.c . FYI, originally the bug was found on CYGWIN, which adopts the similar FreeBSD code to implement the semaphore arrays. >Release-Note: >Audit-Trail: >Unformatted: