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 static struct sockaddr_un sun1, sun2;
25
run(void)26 static void run(void)
27 {
28 /*
29 * Once a STREAM UNIX domain socket has been bound, it can't be
30 * rebound.
31 */
32 TST_EXP_FAIL(bind(sock1, (struct sockaddr *)&sun2, sizeof(sun2)),
33 EINVAL, "re-bind() socket");
34
35 /*
36 * Since a socket is already bound to the pathname, it can't be bound
37 * to a second socket. Expected error is EADDRINUSE.
38 */
39 TST_EXP_FAIL(bind(sock2, (struct sockaddr *)&sun1, sizeof(sun1)),
40 EADDRINUSE, "bind() with bound pathname");
41
42 /*
43 * Kernel is buggy since it creates the node in fileystem first, then
44 * locks the socket and does all the checks and the node is not removed
45 * in the error path. For now we will unlink the node here so that the
46 * test works fine when the run() function is executed in a loop.
47 */
48 unlink(SNAME_B);
49 }
50
setup(void)51 static void setup(void)
52 {
53 sock1 = SAFE_SOCKET(PF_UNIX, SOCK_STREAM, 0);
54 sock2 = SAFE_SOCKET(PF_UNIX, SOCK_STREAM, 0);
55
56 sun1.sun_family = AF_UNIX;
57 sun2.sun_family = AF_UNIX;
58
59 if (sprintf(sun1.sun_path, "%s", SNAME_A) < (int) strlen(SNAME_A)) {
60 tst_res(TFAIL, "sprintf failed");
61 return;
62 }
63
64 if (sprintf(sun2.sun_path, "%s", SNAME_B) < (int) strlen(SNAME_B)) {
65 tst_res(TFAIL, "sprintf failed");
66 return;
67 }
68
69 SAFE_BIND(sock1, (struct sockaddr *)&sun1, sizeof(sun1));
70 }
71
cleanup(void)72 static void cleanup(void)
73 {
74 SAFE_CLOSE(sock1);
75 SAFE_CLOSE(sock2);
76 }
77
78 static struct tst_test test = {
79 .setup = setup,
80 .cleanup = cleanup,
81 .test_all = run,
82 .needs_tmpdir = 1,
83 };
84