Wed Aug 26 22:52:58 2020 UTC ()
Check that fstat returns the correct socket owner


(christos)
diff -r1.19 -r1.20 src/tests/net/net/t_unix.c

cvs diff -r1.19 -r1.20 src/tests/net/net/t_unix.c (expand / switch to unified diff)

--- src/tests/net/net/t_unix.c 2020/07/06 16:24:06 1.19
+++ src/tests/net/net/t_unix.c 2020/08/26 22:52:58 1.20
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: t_unix.c,v 1.19 2020/07/06 16:24:06 christos Exp $ */ 1/* $NetBSD: t_unix.c,v 1.20 2020/08/26 22:52:58 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2011 The NetBSD Foundation, Inc. 4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas. 8 * by Christos Zoulas.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -28,40 +28,41 @@ @@ -28,40 +28,41 @@
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE. 36 * POSSIBILITY OF SUCH DAMAGE.
37 */ 37 */
38 38
39#include <sys/cdefs.h> 39#include <sys/cdefs.h>
40#ifdef __RCSID 40#ifdef __RCSID
41__RCSID("$Id: t_unix.c,v 1.19 2020/07/06 16:24:06 christos Exp $"); 41__RCSID("$Id: t_unix.c,v 1.20 2020/08/26 22:52:58 christos Exp $");
42#else 42#else
43#define getprogname() argv[0] 43#define getprogname() argv[0]
44#endif 44#endif
45 45
46#ifdef __linux__ 46#ifdef __linux__
47#define LX -1 47#define LX -1
48#else 48#else
49#define LX 49#define LX
50#endif 50#endif
51#include <sys/param.h> 51#include <sys/param.h>
52#include <sys/socket.h> 52#include <sys/socket.h>
53#include <sys/un.h> 53#include <sys/un.h>
54#include <sys/wait.h> 54#include <sys/wait.h>
 55#include <sys/stat.h>
55#include <stdio.h> 56#include <stdio.h>
56#include <err.h> 57#include <err.h>
57#include <errno.h> 58#include <errno.h>
58#include <string.h> 59#include <string.h>
59#include <stddef.h> 60#include <stddef.h>
60#include <stdlib.h> 61#include <stdlib.h>
61#include <unistd.h> 62#include <unistd.h>
62#include <stdbool.h> 63#include <stdbool.h>
63 64
64#include "test.h" 65#include "test.h"
65 66
66#define OF offsetof(struct sockaddr_un, sun_path) 67#define OF offsetof(struct sockaddr_un, sun_path)
67 68
@@ -136,33 +137,60 @@ peercred(int s, uid_t *euid, gid_t *egid @@ -136,33 +137,60 @@ peercred(int s, uid_t *euid, gid_t *egid
136 if (getsockopt(s, 0, LOCAL_PEEREID, &cred, &crl) == -1) 137 if (getsockopt(s, 0, LOCAL_PEEREID, &cred, &crl) == -1)
137 return -1; 138 return -1;
138 *euid = cred.unp_euid; 139 *euid = cred.unp_euid;
139 *egid = cred.unp_egid; 140 *egid = cred.unp_egid;
140 *pid = cred.unp_pid; 141 *pid = cred.unp_pid;
141 return 0; 142 return 0;
142#else 143#else
143 *pid = -1; 144 *pid = -1;
144 return getpeereid(s, euid, egid); 145 return getpeereid(s, euid, egid);
145#endif 146#endif
146} 147}
147 148
148static int 149static int
149test(bool forkit, bool closeit, size_t len) 150check_cred(int fd, bool statit, pid_t checkpid, const char *s)
 151{
 152 pid_t pid;
 153 uid_t euid;
 154 gid_t egid;
 155
 156 if (statit) {
 157 struct stat st;
 158 if (fstat(fd, &st) == -1)
 159 FAIL("fstat (%s)", s);
 160 euid = st.st_uid;
 161 egid = st.st_gid;
 162 pid = checkpid;
 163 } else {
 164 if (peercred(fd, &euid, &egid, &pid) == -1)
 165 FAIL("peercred (%s)", s);
 166 }
 167 printf("%s(%s) euid=%jd egid=%jd pid=%jd\n",
 168 statit ? "fstat" : "peercred", s,
 169 (intmax_t)euid, (intmax_t)egid, (intmax_t)pid);
 170 CHECK_EQUAL(euid, geteuid(), s);
 171 CHECK_EQUAL(egid, getegid(), s);
 172 CHECK_EQUAL(pid, checkpid, s);
 173 return 0;
 174fail:
 175 return -1;
 176}
 177
 178static int
 179test(bool forkit, bool closeit, bool statit, size_t len)
150{ 180{
151 size_t slen; 181 size_t slen;
152 socklen_t sl; 182 socklen_t sl;
153 int srvr = -1, clnt = -1, acpt = -1; 183 int srvr = -1, clnt = -1, acpt = -1;
154 uid_t euid; 
155 gid_t egid; 
156 pid_t srvrpid, clntpid; 184 pid_t srvrpid, clntpid;
157 struct sockaddr_un *sock_addr = NULL, *sun = NULL; 185 struct sockaddr_un *sock_addr = NULL, *sun = NULL;
158 socklen_t sock_addrlen; 186 socklen_t sock_addrlen;
159 socklen_t peer_addrlen; 187 socklen_t peer_addrlen;
160 struct sockaddr_un peer_addr; 188 struct sockaddr_un peer_addr;
161 189
162 srvrpid = clntpid = getpid(); 190 srvrpid = clntpid = getpid();
163 srvr = socket(AF_UNIX, SOCK_STREAM, 0); 191 srvr = socket(AF_UNIX, SOCK_STREAM, 0);
164 if (srvr == -1) 192 if (srvr == -1)
165 FAIL("socket(server)"); 193 FAIL("socket(server)");
166 194
167 slen = len + OF + 1; 195 slen = len + OF + 1;
168  196
@@ -194,72 +222,56 @@ test(bool forkit, bool closeit, size_t l @@ -194,72 +222,56 @@ test(bool forkit, bool closeit, size_t l
194 switch (clntpid = fork()) { 222 switch (clntpid = fork()) {
195 case 0: /* child */ 223 case 0: /* child */
196 srvrpid = getppid(); 224 srvrpid = getppid();
197 clntpid = getpid(); 225 clntpid = getpid();
198 break; 226 break;
199 case -1: 227 case -1:
200 FAIL("fork"); 228 FAIL("fork");
201 default: 229 default:
202 break; 230 break;
203 } 231 }
204 } 232 }
205 233
206 if (clntpid == getpid()) { 234 if (clntpid == getpid()) {
207 pid_t pid = srvrpid; 
208 clnt = socket(AF_UNIX, SOCK_STREAM, 0); 235 clnt = socket(AF_UNIX, SOCK_STREAM, 0);
209 if (clnt == -1) 236 if (clnt == -1)
210 FAIL("socket(client)"); 237 FAIL("socket(client)");
211 238
212 if (connect(clnt, (const struct sockaddr *)sun, sl) == -1) 239 if (connect(clnt, (const struct sockaddr *)sun, sl) == -1)
213 FAIL("connect"); 240 FAIL("connect");
 241 check_cred(clnt, statit, srvrpid, "client");
214 242
215 if (peercred(clnt, &euid, &egid, &pid) == -1) 
216 FAIL("peercred (client)"); 
217 printf("peercred(client) euid=%jd egid=%jd pid=%jd\n", 
218 (intmax_t)euid, (intmax_t)egid, (intmax_t)pid); 
219 CHECK_EQUAL(euid, geteuid(), "client"); 
220 CHECK_EQUAL(egid, getegid(), "client"); 
221 CHECK_EQUAL(pid, srvrpid, "client"); 
222 } 243 }
223 244
224 if (srvrpid == getpid()) { 245 if (srvrpid == getpid()) {
225 acpt = acc(srvr); 246 acpt = acc(srvr);
226 
227 peer_addrlen = sizeof(peer_addr); 247 peer_addrlen = sizeof(peer_addr);
228 memset(&peer_addr, 0, sizeof(peer_addr)); 248 memset(&peer_addr, 0, sizeof(peer_addr));
229 if (getpeername(acpt, (struct sockaddr *)&peer_addr, 249 if (getpeername(acpt, (struct sockaddr *)&peer_addr,
230 &peer_addrlen) == -1) 250 &peer_addrlen) == -1)
231 FAIL("getpeername"); 251 FAIL("getpeername");
232 print("peer", &peer_addr, peer_addrlen); 252 print("peer", &peer_addr, peer_addrlen);
233 } 253 }
234 254
235 if (clntpid == getpid()) { 255 if (clntpid == getpid()) {
236 if (closeit) { 256 if (closeit) {
237 if (close(clnt) == -1) 257 if (close(clnt) == -1)
238 FAIL("close"); 258 FAIL("close");
239 clnt = -1; 259 clnt = -1;
240 } 260 }
241 } 261 }
242 262
243 if (srvrpid == getpid()) { 263 if (srvrpid == getpid()) {
244 pid_t pid = clntpid; 264 check_cred(acpt, statit, clntpid, "server");
245 if (peercred(acpt, &euid, &egid, &pid) == -1) 
246 FAIL("peercred (server)"); 
247 printf("peercred(server) euid=%jd egid=%jd pid=%jd\n", 
248 (intmax_t)euid, (intmax_t)egid, (intmax_t)pid); 
249 CHECK_EQUAL(euid, geteuid(), "server"); 
250 CHECK_EQUAL(egid, getegid(), "server"); 
251 CHECK_EQUAL(pid, clntpid, "server"); 
252 
253 if ((sock_addr = calloc(1, slen)) == NULL) 265 if ((sock_addr = calloc(1, slen)) == NULL)
254 FAIL("calloc"); 266 FAIL("calloc");
255 sock_addrlen = slen; 267 sock_addrlen = slen;
256 if (getsockname(srvr, (struct sockaddr *)sock_addr, 268 if (getsockname(srvr, (struct sockaddr *)sock_addr,
257 &sock_addrlen) == -1) 269 &sock_addrlen) == -1)
258 FAIL("getsockname"); 270 FAIL("getsockname");
259 print("sock", sock_addr, sock_addrlen); 271 print("sock", sock_addr, sock_addrlen);
260 272
261 if (sock_addr->sun_family != AF_UNIX) 273 if (sock_addr->sun_family != AF_UNIX)
262 FAIL("sock_addr->sun_family %d != AF_UNIX", 274 FAIL("sock_addr->sun_family %d != AF_UNIX",
263 sock_addr->sun_family); 275 sock_addr->sun_family);
264 276
265 len += OF; 277 len += OF;
@@ -312,85 +324,101 @@ fail: @@ -312,85 +324,101 @@ fail:
312#ifndef TEST 324#ifndef TEST
313 325
314ATF_TC(sockaddr_un_len_exceed); 326ATF_TC(sockaddr_un_len_exceed);
315ATF_TC_HEAD(sockaddr_un_len_exceed, tc) 327ATF_TC_HEAD(sockaddr_un_len_exceed, tc)
316{ 328{
317 329
318 atf_tc_set_md_var(tc, "descr", "Check that exceeding the size of " 330 atf_tc_set_md_var(tc, "descr", "Check that exceeding the size of "
319 "unix domain sockets does not trash memory or kernel when " 331 "unix domain sockets does not trash memory or kernel when "
320 "exceeding the size of the fixed sun_path"); 332 "exceeding the size of the fixed sun_path");
321} 333}
322 334
323ATF_TC_BODY(sockaddr_un_len_exceed, tc) 335ATF_TC_BODY(sockaddr_un_len_exceed, tc)
324{ 336{
325 ATF_REQUIRE_MSG(test(false, false, 254) == -1, 337 ATF_REQUIRE_MSG(test(false, false, false, 254) == -1,
326 "test(false, false, 254): %s", strerror(errno)); 338 "test(false, false, false, 254): %s", strerror(errno));
327} 339}
328 340
329ATF_TC(sockaddr_un_len_max); 341ATF_TC(sockaddr_un_len_max);
330ATF_TC_HEAD(sockaddr_un_len_max, tc) 342ATF_TC_HEAD(sockaddr_un_len_max, tc)
331{ 343{
332 344
333 atf_tc_set_md_var(tc, "descr", "Check that we can use the maximum " 345 atf_tc_set_md_var(tc, "descr", "Check that we can use the maximum "
334 "unix domain socket pathlen (253): 255 - sizeof(sun_len) - " 346 "unix domain socket pathlen (253): 255 - sizeof(sun_len) - "
335 "sizeof(sun_family)"); 347 "sizeof(sun_family)");
336} 348}
337 349
338ATF_TC_BODY(sockaddr_un_len_max, tc) 350ATF_TC_BODY(sockaddr_un_len_max, tc)
339{ 351{
340 ATF_REQUIRE_MSG(test(false, false, 253) == 0, 352 ATF_REQUIRE_MSG(test(false, false, false, 253) == 0,
341 "test(false, false, 253): %s", strerror(errno)); 353 "test(false, false, false, 253): %s", strerror(errno));
342} 354}
343 355
344ATF_TC(sockaddr_un_closed); 356ATF_TC(sockaddr_un_closed);
345ATF_TC_HEAD(sockaddr_un_closed, tc) 357ATF_TC_HEAD(sockaddr_un_closed, tc)
346{ 358{
347 359
348 atf_tc_set_md_var(tc, "descr", "Check that we can use the accepted " 360 atf_tc_set_md_var(tc, "descr", "Check that we can use the accepted "
349 "address of unix domain socket when closed"); 361 "address of unix domain socket when closed");
350} 362}
351 363
352ATF_TC_BODY(sockaddr_un_closed, tc) 364ATF_TC_BODY(sockaddr_un_closed, tc)
353{ 365{
354 ATF_REQUIRE_MSG(test(false, true, 100) == 0, 366 ATF_REQUIRE_MSG(test(false, true, false, 100) == 0,
355 "test(false, true, 100): %s", strerror(errno)); 367 "test(false, true, false, 100): %s", strerror(errno));
356} 368}
357 369
358ATF_TC(sockaddr_un_local_peereid); 370ATF_TC(sockaddr_un_local_peereid);
359ATF_TC_HEAD(sockaddr_un_local_peereid, tc) 371ATF_TC_HEAD(sockaddr_un_local_peereid, tc)
360{ 372{
361 373
362 atf_tc_set_md_var(tc, "descr", "Check that we get the right information" 374 atf_tc_set_md_var(tc, "descr", "Check that we get the right information"
363 " from LOCAL_PEEREID"); 375 " from LOCAL_PEEREID");
364} 376}
365 377
366ATF_TC_BODY(sockaddr_un_local_peereid, tc) 378ATF_TC_BODY(sockaddr_un_local_peereid, tc)
367{ 379{
368 ATF_REQUIRE_MSG(test(true, true, 100) == 0, 380 ATF_REQUIRE_MSG(test(true, true, false, 100) == 0,
369 "test(true, true, 100): %s", strerror(errno)); 381 "test(true, true, false, 100): %s", strerror(errno));
 382}
 383
 384ATF_TC(sockaddr_un_fstat);
 385ATF_TC_HEAD(sockaddr_un_fstat, tc)
 386{
 387
 388 atf_tc_set_md_var(tc, "descr", "Check that we get the right information"
 389 " from fstat");
 390}
 391
 392ATF_TC_BODY(sockaddr_un_fstat, tc)
 393{
 394 ATF_REQUIRE_MSG(test(true, true, true, 100) == 0,
 395 "test(true, true, true, 100): %s", strerror(errno));
370} 396}
371 397
372ATF_TP_ADD_TCS(tp) 398ATF_TP_ADD_TCS(tp)
373{ 399{
374 400
375 ATF_TP_ADD_TC(tp, sockaddr_un_len_exceed); 401 ATF_TP_ADD_TC(tp, sockaddr_un_len_exceed);
376 ATF_TP_ADD_TC(tp, sockaddr_un_len_max); 402 ATF_TP_ADD_TC(tp, sockaddr_un_len_max);
377 ATF_TP_ADD_TC(tp, sockaddr_un_closed); 403 ATF_TP_ADD_TC(tp, sockaddr_un_closed);
378 ATF_TP_ADD_TC(tp, sockaddr_un_local_peereid); 404 ATF_TP_ADD_TC(tp, sockaddr_un_local_peereid);
 405 ATF_TP_ADD_TC(tp, sockaddr_un_fstat);
379 return atf_no_error(); 406 return atf_no_error();
380} 407}
381#else 408#else
382int 409int
383main(int argc, char *argv[]) 410main(int argc, char *argv[])
384{ 411{
385 size_t len; 412 size_t len;
386 413
387 if (argc == 1) { 414 if (argc == 1) {
388 fprintf(stderr, "Usage: %s <len>\n", getprogname()); 415 fprintf(stderr, "Usage: %s <len>\n", getprogname());
389 return EXIT_FAILURE; 416 return EXIT_FAILURE;
390 } 417 }
391 test(false, false, atoi(argv[1])); 418 test(false, false, false, atoi(argv[1]));
392 test(false, true, atoi(argv[1])); 419 test(false, true, false, atoi(argv[1]));
393 test(true, false, atoi(argv[1])); 420 test(true, false, false, atoi(argv[1]));
394 test(true, true, atoi(argv[1])); 421 test(true, true, false, atoi(argv[1]));
 422 test(true, true, true, atoi(argv[1]));
395} 423}
396#endif 424#endif