1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2018 Michael Moese <[email protected]>
4*49cdfc7eSAndroid Build Coastguard Worker */
5*49cdfc7eSAndroid Build Coastguard Worker /* The commit 0fb44559ffd6 af_unix: move unix_mknod() out of bindlock
6*49cdfc7eSAndroid Build Coastguard Worker * changed the behavior of bind() for STREAM UNIX domain sockets if
7*49cdfc7eSAndroid Build Coastguard Worker */
8*49cdfc7eSAndroid Build Coastguard Worker
9*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
10*49cdfc7eSAndroid Build Coastguard Worker #include <limits.h>
11*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
12*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
13*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
14*49cdfc7eSAndroid Build Coastguard Worker
15*49cdfc7eSAndroid Build Coastguard Worker #include "tst_kvercmp.h"
16*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
17*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_net.h"
18*49cdfc7eSAndroid Build Coastguard Worker
19*49cdfc7eSAndroid Build Coastguard Worker #define SNAME_A "socket.1"
20*49cdfc7eSAndroid Build Coastguard Worker #define SNAME_B "socket.2"
21*49cdfc7eSAndroid Build Coastguard Worker
22*49cdfc7eSAndroid Build Coastguard Worker static int sock1, sock2;
23*49cdfc7eSAndroid Build Coastguard Worker static struct sockaddr_un sun1, sun2;
24*49cdfc7eSAndroid Build Coastguard Worker
run(void)25*49cdfc7eSAndroid Build Coastguard Worker static void run(void)
26*49cdfc7eSAndroid Build Coastguard Worker {
27*49cdfc7eSAndroid Build Coastguard Worker /*
28*49cdfc7eSAndroid Build Coastguard Worker * Once a STREAM UNIX domain socket has been bound, it can't be
29*49cdfc7eSAndroid Build Coastguard Worker * rebound.
30*49cdfc7eSAndroid Build Coastguard Worker */
31*49cdfc7eSAndroid Build Coastguard Worker TST_EXP_FAIL(bind(sock1, (struct sockaddr *)&sun2, sizeof(sun2)),
32*49cdfc7eSAndroid Build Coastguard Worker EINVAL, "re-bind() socket");
33*49cdfc7eSAndroid Build Coastguard Worker
34*49cdfc7eSAndroid Build Coastguard Worker /*
35*49cdfc7eSAndroid Build Coastguard Worker * Since a socket is already bound to the pathname, it can't be bound
36*49cdfc7eSAndroid Build Coastguard Worker * to a second socket. Expected error is EADDRINUSE.
37*49cdfc7eSAndroid Build Coastguard Worker */
38*49cdfc7eSAndroid Build Coastguard Worker TST_EXP_FAIL(bind(sock2, (struct sockaddr *)&sun1, sizeof(sun1)),
39*49cdfc7eSAndroid Build Coastguard Worker EADDRINUSE, "bind() with bound pathname");
40*49cdfc7eSAndroid Build Coastguard Worker
41*49cdfc7eSAndroid Build Coastguard Worker /*
42*49cdfc7eSAndroid Build Coastguard Worker * Kernel is buggy since it creates the node in fileystem first, then
43*49cdfc7eSAndroid Build Coastguard Worker * locks the socket and does all the checks and the node is not removed
44*49cdfc7eSAndroid Build Coastguard Worker * in the error path. For now we will unlink the node here so that the
45*49cdfc7eSAndroid Build Coastguard Worker * test works fine when the run() function is executed in a loop.
46*49cdfc7eSAndroid Build Coastguard Worker * From v5.14-rc1 the kernel has fix above issue.
47*49cdfc7eSAndroid Build Coastguard Worker */
48*49cdfc7eSAndroid Build Coastguard Worker if (tst_kvercmp(5, 14, 0) >= 0)
49*49cdfc7eSAndroid Build Coastguard Worker TST_EXP_FAIL(unlink(SNAME_B), ENOENT, "check exist of SNAME_B");
50*49cdfc7eSAndroid Build Coastguard Worker else
51*49cdfc7eSAndroid Build Coastguard Worker unlink(SNAME_B);
52*49cdfc7eSAndroid Build Coastguard Worker }
53*49cdfc7eSAndroid Build Coastguard Worker
setup(void)54*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
55*49cdfc7eSAndroid Build Coastguard Worker {
56*49cdfc7eSAndroid Build Coastguard Worker sock1 = SAFE_SOCKET(PF_UNIX, SOCK_STREAM, 0);
57*49cdfc7eSAndroid Build Coastguard Worker sock2 = SAFE_SOCKET(PF_UNIX, SOCK_STREAM, 0);
58*49cdfc7eSAndroid Build Coastguard Worker
59*49cdfc7eSAndroid Build Coastguard Worker sun1.sun_family = AF_UNIX;
60*49cdfc7eSAndroid Build Coastguard Worker sun2.sun_family = AF_UNIX;
61*49cdfc7eSAndroid Build Coastguard Worker
62*49cdfc7eSAndroid Build Coastguard Worker if (sprintf(sun1.sun_path, "%s", SNAME_A) < (int) strlen(SNAME_A)) {
63*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "sprintf failed");
64*49cdfc7eSAndroid Build Coastguard Worker return;
65*49cdfc7eSAndroid Build Coastguard Worker }
66*49cdfc7eSAndroid Build Coastguard Worker
67*49cdfc7eSAndroid Build Coastguard Worker if (sprintf(sun2.sun_path, "%s", SNAME_B) < (int) strlen(SNAME_B)) {
68*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "sprintf failed");
69*49cdfc7eSAndroid Build Coastguard Worker return;
70*49cdfc7eSAndroid Build Coastguard Worker }
71*49cdfc7eSAndroid Build Coastguard Worker
72*49cdfc7eSAndroid Build Coastguard Worker SAFE_BIND(sock1, (struct sockaddr *)&sun1, sizeof(sun1));
73*49cdfc7eSAndroid Build Coastguard Worker }
74*49cdfc7eSAndroid Build Coastguard Worker
cleanup(void)75*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
76*49cdfc7eSAndroid Build Coastguard Worker {
77*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(sock1);
78*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(sock2);
79*49cdfc7eSAndroid Build Coastguard Worker }
80*49cdfc7eSAndroid Build Coastguard Worker
81*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
82*49cdfc7eSAndroid Build Coastguard Worker .setup = setup,
83*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup,
84*49cdfc7eSAndroid Build Coastguard Worker .test_all = run,
85*49cdfc7eSAndroid Build Coastguard Worker .needs_tmpdir = 1,
86*49cdfc7eSAndroid Build Coastguard Worker };
87