• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2018 Michael Moese <mmoese@suse.com>
3  *
4  * SPDX-License-Identifier: GPL-2.0-or-later
5  */
6 /* The commit 0fb44559ffd6  af_unix: move unix_mknod() out of bindlock
7  * changed the behavior of bind() for STREAM UNIX domain sockets if
8  */
9 
10 #include <errno.h>
11 #include <limits.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #include "tst_kvercmp.h"
17 #include "tst_test.h"
18 #include "tst_safe_net.h"
19 
20 #define SNAME_A "socket.1"
21 #define SNAME_B "socket.2"
22 
23 static int sock1, sock2;
24 
run(void)25 void run(void)
26 {
27 	struct sockaddr_un sun1;
28 	struct sockaddr_un sun2;
29 
30 	sock1 = SAFE_SOCKET(PF_UNIX, SOCK_STREAM, 0);
31 
32 	memset(&sun1, 0, sizeof(sun1));
33 	memset(&sun2, 0, sizeof(sun2));
34 
35 	sun1.sun_family = AF_UNIX;
36 	sun2.sun_family = AF_UNIX;
37 
38 	if (sprintf(sun1.sun_path, "%s", SNAME_A) < (int) strlen(SNAME_A)) {
39 		tst_res(TFAIL, "sprintf failed");
40 		return;
41 	}
42 
43 	if (sprintf(sun2.sun_path, "%s", SNAME_B) < (int) strlen(SNAME_B)) {
44 		tst_res(TFAIL, "sprintf failed");
45 		return;
46 	}
47 
48 	SAFE_BIND(sock1, (struct sockaddr *)&sun1, sizeof(sun1));
49 
50 	/*
51 	 * Once a STREAM UNIX domain socket has been bound, it can't be
52 	 * rebound.
53 	 */
54 	if (bind(sock1, (struct sockaddr *)&sun2, sizeof(sun2)) == 0) {
55 		tst_res(TFAIL, "re-binding of socket succeeded");
56 		return;
57 	}
58 
59 	if (errno != EINVAL) {
60 		tst_res(TFAIL | TERRNO, "expected EINVAL");
61 		return;
62 	}
63 
64 	tst_res(TPASS, "bind() failed with EINVAL as expected");
65 
66 	sock2 = SAFE_SOCKET(PF_UNIX, SOCK_STREAM, 0);
67 
68 	/*
69 	 * Since a socket is already bound to the pathname, it can't be bound
70 	 * to a second socket. Expected error is EADDRINUSE.
71 	 */
72 	if (bind(sock2, (struct sockaddr *)&sun1, sizeof(sun1)) == 0) {
73 		tst_res(TFAIL, "bind() succeeded with already bound pathname!");
74 		return;
75 	}
76 
77 	if (errno != EADDRINUSE) {
78 		tst_res(TFAIL | TERRNO, "expected to fail with EADDRINUSE");
79 		return;
80 	}
81 
82 	tst_res(TPASS, "bind() failed with EADDRINUSE as expected");
83 }
84 
cleanup(void)85 static void cleanup(void)
86 {
87 	close(sock1);
88 	close(sock2);
89 }
90 
91 static struct tst_test test = {
92 	.cleanup = cleanup,
93 	.test_all = run,
94 	.needs_tmpdir = 1,
95 };
96