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