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