1 /* 2 * Copyright (c) 2018 Michael Moese <mmoese (at) suse.com> 3 * 4 * SPDX-License-Identifier: GPL-2.0-or-later 5 */ 6 /* The commit 0fb44559ffd6 af_unix: move unix_mknod() out of bindlock 7 * changed the behavior of bind() for STREAM UNIX domain sockets if 8 */ 9 10 #include <errno.h> 11 #include <limits.h> 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 16 #include "tst_kvercmp.h" 17 #include "tst_test.h" 18 #include "tst_safe_net.h" 19 20 #define SNAME_A "socket.1" 21 #define SNAME_B "socket.2" 22 23 static int sock1, sock2; 24 25 void run(void) 26 { 27 struct sockaddr_un sun1; 28 struct sockaddr_un sun2; 29 30 sock1 = SAFE_SOCKET(PF_UNIX, SOCK_STREAM, 0); 31 32 memset(&sun1, 0, sizeof(sun1)); 33 memset(&sun2, 0, sizeof(sun2)); 34 35 sun1.sun_family = AF_UNIX; 36 sun2.sun_family = AF_UNIX; 37 38 if (sprintf(sun1.sun_path, "%s", SNAME_A) < (int) strlen(SNAME_A)) { 39 tst_res(TFAIL, "sprintf failed"); 40 return; 41 } 42 43 if (sprintf(sun2.sun_path, "%s", SNAME_B) < (int) strlen(SNAME_B)) { 44 tst_res(TFAIL, "sprintf failed"); 45 return; 46 } 47 48 SAFE_BIND(sock1, (struct sockaddr *)&sun1, sizeof(sun1)); 49 50 /* 51 * Once a STREAM UNIX domain socket has been bound, it can't be 52 * rebound. 53 */ 54 if (bind(sock1, (struct sockaddr *)&sun2, sizeof(sun2)) == 0) { 55 tst_res(TFAIL, "re-binding of socket succeeded"); 56 return; 57 } 58 59 if (errno != EINVAL) { 60 tst_res(TFAIL | TERRNO, "expected EINVAL"); 61 return; 62 } 63 64 tst_res(TPASS, "bind() failed with EINVAL as expected"); 65 66 sock2 = SAFE_SOCKET(PF_UNIX, SOCK_STREAM, 0); 67 68 /* 69 * Since a socket is already bound to the pathname, it can't be bound 70 * to a second socket. Expected error is EADDRINUSE. 71 */ 72 if (bind(sock2, (struct sockaddr *)&sun1, sizeof(sun1)) == 0) { 73 tst_res(TFAIL, "bind() succeeded with already bound pathname!"); 74 return; 75 } 76 77 if (errno != EADDRINUSE) { 78 tst_res(TFAIL | TERRNO, "expected to fail with EADDRINUSE"); 79 return; 80 } 81 82 tst_res(TPASS, "bind() failed with EADDRINUSE as expected"); 83 } 84 85 static void cleanup(void) 86 { 87 close(sock1); 88 close(sock2); 89 } 90 91 static struct tst_test test = { 92 .cleanup = cleanup, 93 .test_all = run, 94 .needs_tmpdir = 1, 95 }; 96