Home | History | Annotate | Download | only in bind
      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