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