[CRIU] [PATCH] zdtm: unlinked socket with dentry alias

Pavel Emelyanov xemul at parallels.com
Mon Sep 28 11:46:24 PDT 2015


On 09/28/2015 05:38 PM, Stanislav Kinsburskiy wrote:
> There can be an unlinked UNIX socket, which dentry has a linked alias,
> pointing to the same inode.
> To check, that such socket is migrated successfully, test perform the
> following:
> 
> Before suspend:
> 1) Creates UNIX socket and binds it.
> 2) Created hard link to the binded path.
> 3) Unlinks original UNIX bind path.
> 3) Forks a child, listen to unlinked socket and accepting connection.
> 
> After resume:
> 1) Create UNIX socket and binds it to socket link.
> 2) Connects to socket.
> 3) Child have to accept the connection.
> 
> Signed-off-by: Stanislav Kinsburskiy <skinsbursky at parallels.com>
> ---
>  test/zdtm/live/static/Makefile                   |    1 
>  test/zdtm/live/static/deleted_unix_sock_linked.c |  196 ++++++++++++++++++++++

I don't see it in zdtm.sh list :) Does it fail? Why?

>  2 files changed, 197 insertions(+)
>  create mode 100644 test/zdtm/live/static/deleted_unix_sock_linked.c
> 
> diff --git a/test/zdtm/live/static/Makefile b/test/zdtm/live/static/Makefile
> index c3a9929..35a8b74 100644
> --- a/test/zdtm/live/static/Makefile
> +++ b/test/zdtm/live/static/Makefile
> @@ -140,6 +140,7 @@ TST_FILE	=				\
>  		link10				\
>  		file_attr			\
>  		deleted_unix_sock		\
> +		deleted_unix_sock_linked	\
>  		sk-unix-rel			\
>  		deleted_dev			\
>  		unlink_fstat00			\
> diff --git a/test/zdtm/live/static/deleted_unix_sock_linked.c b/test/zdtm/live/static/deleted_unix_sock_linked.c
> new file mode 100644
> index 0000000..3712fb2
> --- /dev/null
> +++ b/test/zdtm/live/static/deleted_unix_sock_linked.c
> @@ -0,0 +1,196 @@
> +#include <errno.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include <signal.h>
> +#include <string.h>
> +#include <sys/wait.h>
> +#include <sys/socket.h>
> +#include <sys/un.h>
> +
> +#include "zdtmtst.h"
> +
> +const char *test_doc	= "Create a unix socket, bind to it, then create a hardlink and destroy socket before "
> +			  "migration; check that the child can accept connection to unlinked binded socket via linked one.";
> +const char *test_author	= "Stanislav Kinsbursky <skinsbursky at odin.com>";
> +
> +char *filename;
> +TEST_OPTION(filename, string, "file name", 1);
> +
> +static int fill_sock_name(struct sockaddr_un *name, const char *filename)
> +{
> +	if (strlen(filename) >= sizeof(name->sun_path))
> +		return -1;
> +
> +	name->sun_family = AF_LOCAL;
> +	strcpy(name->sun_path, filename);
> +	return 0;
> +}
> +
> +static int setup_deleted_sock_linked(const char *linkname)
> +{
> +	struct sockaddr_un name;
> +	int sock;
> +
> +	if (fill_sock_name(&name, filename) < 0) {
> +		err("filename \"%s\" is too long", filename);
> +		return -1;
> +	}
> +
> +	sock = socket(PF_LOCAL, SOCK_STREAM, 0);
> +	if (sock < 0) {
> +		err("can't create socket: %m");
> +		return -1;
> +	}
> +
> +	if (bind(sock, (struct sockaddr *) &name, SUN_LEN(&name)) < 0) {
> +		err("can't bind to socket \"%s\": %m", filename);
> +		goto err;
> +	}
> +
> +	if (link(filename, linkname)) {
> +		err("can't create link: %m");
> +		return -1;
> +	}
> +
> +	if (unlink(filename)) {
> +		err("can't unlink %s: %m", filename);
> +		goto err;
> +	}
> +
> +	return sock;
> +err:
> +	close(sock);
> +	return -1;
> +}
> +
> +static int connect_linked_sock(char *filename)
> +{
> +	struct sockaddr_un name;
> +	int sock;
> +
> +	if (fill_sock_name(&name, filename) < 0) {
> +		fail("failed to fill linked socket name: %m", filename);
> +		return -1;
> +	}
> +
> +	sock = socket(PF_LOCAL, SOCK_STREAM, 0);
> +	if (sock < 0) {
> +		fail("can't create socket: %m");
> +		return -1;
> +	}
> +
> +	if (connect(sock, (struct sockaddr *) &name, SUN_LEN(&name)) < 0) {
> +		err("failed to connect to %s: %m", filename);
> +		goto err;
> +	}
> +
> +	return sock;
> +err:
> +	close(sock);
> +	return -1;
> +}
> +
> +int main(int argc, char ** argv)
> +{
> +	int deleted_sock, conn_sock, ret;
> +	pid_t pid;
> +	char linkname[108];
> +
> +	test_init(argc, argv);
> +
> +	snprintf(linkname, 108, "%s-link", filename);
> +
> +	deleted_sock = setup_deleted_sock_linked(linkname);
> +	if (deleted_sock < 0) {
> +		err("can't create socket: %m");
> +		return -1;
> +	}
> +
> +	pid = test_fork();
> +	if (pid < 0) {
> +		err("can't fork: %m\n");
> +		exit(1);
> +	}
> +
> +	if (pid == 0) {	/* child waits for connection on the unlinked socket and returns */
> +		int acc_sock;
> +
> +		if (listen(deleted_sock, 1)) {
> +			err("failed to listen to deleted socket: %m");
> +			_exit(1);
> +		}
> +
> +		test_waitsig();
> +
> +		acc_sock = accept(deleted_sock, NULL, NULL);
> +		if (acc_sock < 0) {
> +			err("failed to accept connection on unlinked socket: %m");
> +			_exit(1);
> +		}
> +
> +		if (close(deleted_sock)) {
> +			err("can't close unlinked socket: %m");
> +			_exit(1);
> +		}
> +
> +		if (close(acc_sock)) {
> +			err("can't close accepted socket: %m");
> +			_exit(1);
> +		}
> +
> +		exit(0);
> +	}
> +
> +	if (close(deleted_sock)) {
> +		err("close failed: %m\n");
> +		goto out_kill;
> +	}
> +
> +	test_daemon();
> +	test_waitsig();
> +
> +	conn_sock = connect_linked_sock(linkname);
> +	if (conn_sock < 0)
> +		goto out_kill;
> +
> +	if (close(conn_sock)) {
> +		fail("connected socket close failed: %m\n");
> +		goto out_kill;
> +	}
> +
> +	if (kill(pid, SIGTERM)) {
> +		fail("terminating the child failed: %m\n");
> +		goto out_link;
> +	}
> +
> +	if (wait(&ret) != pid) {
> +		fail("wait() returned wrong pid %d: %m\n", pid);
> +		goto out_link;
> +	}
> +
> +	if (WIFEXITED(ret)) {
> +		ret = WEXITSTATUS(ret);
> +		if (ret) {
> +			fail("child exited with nonzero code %d (%s)\n", ret, strerror(ret));
> +			goto out_link;
> +		}
> +	}
> +	if (WIFSIGNALED(ret)) {
> +		fail("child exited on unexpected signal %d\n", WTERMSIG(ret));
> +		goto out_link;
> +	}
> +
> +	if (unlink(filename) != -1 || errno != ENOENT) {
> +		fail("file %s should have been deleted before migration: unlink: %m\n");
> +		goto out_link;
> +	}
> +
> +	pass();
> +
> +out_kill:
> +	kill(pid, SIGTERM);
> +out_link:
> +	if (unlink(linkname))
> +		err("can't unlink %s: %m\n", filename);
> +	return 0;
> +}
> 
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu
> .
> 



More information about the CRIU mailing list