Index: sysv_ipc.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/sysv_ipc.c,v
retrieving revision 1.25
diff -u -r1.25 sysv_ipc.c
--- sysv_ipc.c	31 May 2003 23:17:30 -0000	1.25
+++ sysv_ipc.c	31 May 2003 23:21:45 -0000
@@ -76,22 +76,39 @@
 	int mode;
 {
 	struct ucred *cred = td->td_ucred;
+	int error;
 
 	/* Check for user match. */
 	if (cred->cr_uid != perm->cuid && cred->cr_uid != perm->uid) {
-		if (mode & IPC_M)
-			return (suser(td) == 0 ? 0 : EPERM);
-		/* Check for group match. */
+		/*
+		 * For a non-create/owner, we require privilege to
+		 * modify the object protections.  Note: some other
+		 * implementations permit IPC_M to be delegated to
+		 * unprivileged non-creator/owner uids/gids.
+		 */
+		if (mode & IPC_M) {
+			error = suser(td);
+			if (error)
+				return (error);
+		}
+		/*
+		 * Try to match against group; if not, fall back on
+		 * other.
+		 */
 		mode >>= 3;
 		if (!groupmember(perm->gid, cred) &&
 		    !groupmember(perm->cgid, cred))
 			/* Check for `other' match. */
 			mode >>= 3;
+	} else {
+		/*
+		 * Always permit the creator/owner to update the object
+		 * protections regardless of whether the object mode
+		 * permits it.
+		 */
+		if (mode & IPC_M)
+			return (0);
 	}
-
-	if (mode & IPC_M)
-		return (0);
-
 
 	if ((mode & perm->mode) != mode) {
 		if (suser(td) != 0)

