Module Name:    src
Committed By:   christos
Date:           Thu Aug 27 14:00:01 UTC 2020

Modified Files:
        src/tests/net/net: t_unix.c

Log Message:
- when running as root, create the socket under a different uid/gid to verify
  that it works properly with different users opening the socket.
- verify that linux works the same for both getpeereid() and fstat()


To generate a diff of this commit:
cvs rdiff -u -r1.20 -r1.21 src/tests/net/net/t_unix.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/tests/net/net/t_unix.c
diff -u src/tests/net/net/t_unix.c:1.20 src/tests/net/net/t_unix.c:1.21
--- src/tests/net/net/t_unix.c:1.20	Wed Aug 26 18:52:58 2020
+++ src/tests/net/net/t_unix.c	Thu Aug 27 10:00:01 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: t_unix.c,v 1.20 2020/08/26 22:52:58 christos Exp $	*/
+/*	$NetBSD: t_unix.c,v 1.21 2020/08/27 14:00:01 christos Exp $	*/
 
 /*-
  * Copyright (c) 2011 The NetBSD Foundation, Inc.
@@ -36,9 +36,10 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#define _GNU_SOURCE
 #include <sys/cdefs.h>
 #ifdef __RCSID
-__RCSID("$Id: t_unix.c,v 1.20 2020/08/26 22:52:58 christos Exp $");
+__RCSID("$Id: t_unix.c,v 1.21 2020/08/27 14:00:01 christos Exp $");
 #else
 #define getprogname() argv[0]
 #endif
@@ -58,12 +59,19 @@ __RCSID("$Id: t_unix.c,v 1.20 2020/08/26
 #include <errno.h>
 #include <string.h>
 #include <stddef.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdbool.h>
 
 #include "test.h"
 
+#define UID 666
+#define GID 999
+
+uid_t srvruid, clntuid;
+gid_t srvrgid, clntgid;
+
 #define OF offsetof(struct sockaddr_un, sun_path)
 
 static void
@@ -130,28 +138,42 @@ fail:
 static int
 peercred(int s, uid_t *euid, gid_t *egid, pid_t *pid)
 {
+#ifdef SO_PEERCRED
+	/* Linux */
+# define unpcbid ucred
+# define unp_euid uid
+# define unp_egid gid
+# define unp_pid pid
+# define LOCAL_PEEREID SO_PEERCRED
+# define LEVEL SOL_SOCKET
+#else
+# define LEVEL 0
+#endif
+
 #ifdef LOCAL_PEEREID
+	/* NetBSD */
 	struct unpcbid cred;
 	socklen_t crl;
 	crl = sizeof(cred);
-	if (getsockopt(s, 0, LOCAL_PEEREID, &cred, &crl) == -1)
+	if (getsockopt(s, LEVEL, LOCAL_PEEREID, &cred, &crl) == -1)
 		return -1;
 	*euid = cred.unp_euid;
 	*egid = cred.unp_egid;
 	*pid = cred.unp_pid;
 	return 0;
 #else
+	/* FreeBSD */
 	*pid = -1;
 	return getpeereid(s, euid, egid);
 #endif
 }
 
 static int
-check_cred(int fd, bool statit, pid_t checkpid, const char *s)
+check_cred(int fd, bool statit, pid_t checkpid, pid_t otherpid, const char *s)
 {
 	pid_t pid;
-	uid_t euid;
-	gid_t egid;
+	uid_t euid, uid;
+	gid_t egid, gid;
 
 	if (statit) {
 		struct stat st;
@@ -167,8 +189,28 @@ check_cred(int fd, bool statit, pid_t ch
 	printf("%s(%s) euid=%jd egid=%jd pid=%jd\n",
 	    statit ? "fstat" : "peercred", s,
 	    (intmax_t)euid, (intmax_t)egid, (intmax_t)pid);
-	CHECK_EQUAL(euid, geteuid(), s);
-	CHECK_EQUAL(egid, getegid(), s);
+
+	if (statit) {
+		if (strcmp(s, "server") == 0) {
+			uid = srvruid;
+			gid = srvrgid;
+		} else {
+			uid = clntuid;
+			gid = clntgid;
+		}
+	} else {
+		if (checkpid != otherpid && strcmp(s, "server") == 0) {
+			uid = clntuid;
+			gid = clntgid;
+		} else {
+			uid = srvruid;
+			gid = srvrgid;
+		}
+	}
+	fflush(stdout);
+	
+	CHECK_EQUAL(euid, uid, s);
+	CHECK_EQUAL(egid, gid, s);
 	CHECK_EQUAL(pid, checkpid, s);
 	return 0;
 fail:
@@ -187,6 +229,8 @@ test(bool forkit, bool closeit, bool sta
 	socklen_t peer_addrlen;
 	struct sockaddr_un peer_addr;
 
+	srvruid = geteuid();
+	srvrgid = getegid();
 	srvrpid = clntpid = getpid();
 	srvr = socket(AF_UNIX, SOCK_STREAM, 0);
 	if (srvr == -1)
@@ -207,6 +251,8 @@ test(bool forkit, bool closeit, bool sta
 #endif
 	sun->sun_family = AF_UNIX;
 
+	unlink(sun->sun_path);
+
 	if (bind(srvr, (struct sockaddr *)sun, sl) == -1) {
 		if (errno == EINVAL && sl >= 256) {
 			close(srvr);
@@ -214,6 +260,8 @@ test(bool forkit, bool closeit, bool sta
 		}
 		FAIL("bind");
 	}
+	if (chmod(sun->sun_path, 0777) == -1)
+		FAIL("chmod `%s'", sun->sun_path);
 
 	if (listen(srvr, SOMAXCONN) == -1)
 		FAIL("listen");
@@ -223,10 +271,25 @@ test(bool forkit, bool closeit, bool sta
 		case 0:	/* child */
 			srvrpid = getppid();
 			clntpid = getpid();
+			if (srvruid == 0) {
+				clntuid = UID;
+				clntgid = GID;
+				setgid(clntgid);
+				setegid(clntgid);
+				setuid(clntuid);
+				seteuid(clntuid);
+			} else {
+				clntuid = srvruid;
+				clntgid = srvrgid;
+			}
 			break;
 		case -1:
 			FAIL("fork");
 		default:
+			if (srvruid == 0) {
+				clntuid = UID;
+				clntgid = GID;
+			}
 			break;
 		}
 	}
@@ -238,7 +301,7 @@ test(bool forkit, bool closeit, bool sta
 
 		if (connect(clnt, (const struct sockaddr *)sun, sl) == -1)
 			FAIL("connect");
-		check_cred(clnt, statit, srvrpid, "client");
+		check_cred(clnt, statit, srvrpid, clntpid, "client");
 
 	}
 
@@ -261,7 +324,7 @@ test(bool forkit, bool closeit, bool sta
 	}
 
 	if (srvrpid == getpid()) {
-		check_cred(acpt, statit, clntpid, "server");
+		check_cred(acpt, statit, clntpid, srvrpid, "server");
 		if ((sock_addr = calloc(1, slen)) == NULL)
 			FAIL("calloc");
 		sock_addrlen = slen;

Reply via email to