| /* |
| * Copyright (c) 2018 Michael Moese <mmoese@suse.com> |
| * |
| * SPDX-License-Identifier: GPL-2.0-or-later |
| */ |
| /* The commit 0fb44559ffd6 af_unix: move unix_mknod() out of bindlock |
| * changed the behavior of bind() for STREAM UNIX domain sockets if |
| */ |
| |
| #include <errno.h> |
| #include <limits.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "tst_kvercmp.h" |
| #include "tst_test.h" |
| #include "tst_safe_net.h" |
| |
| #define SNAME_A "socket.1" |
| #define SNAME_B "socket.2" |
| |
| static int sock1, sock2; |
| |
| void run(void) |
| { |
| struct sockaddr_un sun1; |
| struct sockaddr_un sun2; |
| |
| sock1 = SAFE_SOCKET(PF_UNIX, SOCK_STREAM, 0); |
| |
| memset(&sun1, 0, sizeof(sun1)); |
| memset(&sun2, 0, sizeof(sun2)); |
| |
| sun1.sun_family = AF_UNIX; |
| sun2.sun_family = AF_UNIX; |
| |
| if (sprintf(sun1.sun_path, "%s", SNAME_A) < (int) strlen(SNAME_A)) { |
| tst_res(TFAIL, "sprintf failed"); |
| return; |
| } |
| |
| if (sprintf(sun2.sun_path, "%s", SNAME_B) < (int) strlen(SNAME_B)) { |
| tst_res(TFAIL, "sprintf failed"); |
| return; |
| } |
| |
| SAFE_BIND(sock1, (struct sockaddr *)&sun1, sizeof(sun1)); |
| |
| /* |
| * Once a STREAM UNIX domain socket has been bound, it can't be |
| * rebound. |
| */ |
| if (bind(sock1, (struct sockaddr *)&sun2, sizeof(sun2)) == 0) { |
| tst_res(TFAIL, "re-binding of socket succeeded"); |
| return; |
| } |
| |
| if (errno != EINVAL) { |
| tst_res(TFAIL | TERRNO, "expected EINVAL"); |
| return; |
| } |
| |
| tst_res(TPASS, "bind() failed with EINVAL as expected"); |
| |
| sock2 = SAFE_SOCKET(PF_UNIX, SOCK_STREAM, 0); |
| |
| /* |
| * Since a socket is already bound to the pathname, it can't be bound |
| * to a second socket. Expected error is EADDRINUSE. |
| */ |
| if (bind(sock2, (struct sockaddr *)&sun1, sizeof(sun1)) == 0) { |
| tst_res(TFAIL, "bind() succeeded with already bound pathname!"); |
| return; |
| } |
| |
| if (errno != EADDRINUSE) { |
| tst_res(TFAIL | TERRNO, "expected to fail with EADDRINUSE"); |
| return; |
| } |
| |
| tst_res(TPASS, "bind() failed with EADDRINUSE as expected"); |
| } |
| |
| static void cleanup(void) |
| { |
| close(sock1); |
| close(sock2); |
| } |
| |
| static struct tst_test test = { |
| .cleanup = cleanup, |
| .test_all = run, |
| .needs_tmpdir = 1, |
| }; |