Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 9 Apr 2016 13:32:42 +0000 (UTC)
From:      Jilles Tjoelker <jilles@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r297747 - in stable/10: sys/kern tools/regression/sysvsem
Message-ID:  <201604091332.u39DWglh072540@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jilles
Date: Sat Apr  9 13:32:42 2016
New Revision: 297747
URL: https://svnweb.freebsd.org/changeset/base/297747

Log:
  MFC r295385: semget(): Check for [EEXIST] error first.
  
  Although POSIX literally permits failing with [EINVAL] if IPC_CREAT and
  IPC_EXCL were both passed, the semaphore set already exists and has fewer
  semaphores than nsems, this does not allow an application to retry safely:
  if the [EINVAL] is actually because of the semmsl limit, an infinite loop
  would result.
  
  PR:		206927

Modified:
  stable/10/sys/kern/sysv_sem.c
  stable/10/tools/regression/sysvsem/semtest.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/kern/sysv_sem.c
==============================================================================
--- stable/10/sys/kern/sysv_sem.c	Sat Apr  9 13:15:34 2016	(r297746)
+++ stable/10/sys/kern/sysv_sem.c	Sat Apr  9 13:32:42 2016	(r297747)
@@ -877,6 +877,11 @@ sys_semget(struct thread *td, struct sem
 		}
 		if (semid < seminfo.semmni) {
 			DPRINTF(("found public key\n"));
+			if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) {
+				DPRINTF(("not exclusive\n"));
+				error = EEXIST;
+				goto done2;
+			}
 			if ((error = ipcperm(td, &sema[semid].u.sem_perm,
 			    semflg & 0700))) {
 				goto done2;
@@ -886,11 +891,6 @@ sys_semget(struct thread *td, struct sem
 				error = EINVAL;
 				goto done2;
 			}
-			if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) {
-				DPRINTF(("not exclusive\n"));
-				error = EEXIST;
-				goto done2;
-			}
 #ifdef MAC
 			error = mac_sysvsem_check_semget(cred, &sema[semid]);
 			if (error != 0)

Modified: stable/10/tools/regression/sysvsem/semtest.c
==============================================================================
--- stable/10/tools/regression/sysvsem/semtest.c	Sat Apr  9 13:15:34 2016	(r297746)
+++ stable/10/tools/regression/sysvsem/semtest.c	Sat Apr  9 13:32:42 2016	(r297747)
@@ -152,6 +152,15 @@ main(int argc, char *argv[])
 
 	print_semid_ds(&s_ds, 0600);
 
+	errno = 0;
+	if (semget(semkey, 1, IPC_CREAT | IPC_EXCL | 0600) != -1 ||
+	    errno != EEXIST)
+		err(1, "semget IPC_EXCL 1 did not fail with [EEXIST]");
+	errno = 0;
+	if (semget(semkey, 2, IPC_CREAT | IPC_EXCL | 0600) != -1 ||
+	    errno != EEXIST)
+		err(1, "semget IPC_EXCL 2 did not fail with [EEXIST]");
+
 	for (child_count = 0; child_count < 5; child_count++) {
 		switch ((child_pid = fork())) {
 		case -1:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201604091332.u39DWglh072540>