[CRIU] [PATCH 17/17] unix: test -- Add sk-unix01 test

Andrey Vagin avagin at virtuozzo.com
Thu May 3 08:28:15 MSK 2018


[root at fc24 criu]# python test/zdtm.py run -t zdtm/static/sk-unix01 -f uns --iter 10
=== Run 1/1 ================ zdtm/static/sk-unix01

======================= Run zdtm/static/sk-unix01 in uns =======================
Start test
Test is SUID
./sk-unix01 --pidfile=sk-unix01.pid --outfile=sk-unix01.out --dirname=sk-unix01.test
Run criu dump
Run criu restore
Run criu dump
=[log]=> dump/zdtm/static/sk-unix01/55/2/dump.log
------------------------ grep Error ------------------------
(00.232947) Dumping path for 3 fd via self 11 [/zdtm/static]
(00.233017) 87 fdinfo 4: pos:                0 flags:                2/0
(00.233039) 	Searching for socket 21b16 (family 1.0)
(00.233111) unix: Resolving relative name ~criu-0 for socket 0x21b16
(00.233204) Error (criu/sk-unix.c:321): unix: Can't resolve name for socket 0xb
(00.233230) ----------------------------------------
(00.233301) Error (criu/cr-dump.c:1446): Dump files (pid: 87) failed with -1
ip6tables-restore: invalid option -- 'w'
(00.262424) Unfreezing tasks into 1
(00.262479) 	Unseizing 74 into 1
(00.262506) 	Unseizing 87 into 1
(00.262564) Error (criu/cr-dump.c:1841): Dumping FAILED.
------------------------ ERROR OVER ------------------------
################# Test zdtm/static/sk-unix01 FAIL at CRIU dump #################
Send the 9 signal to  74
Wait for zdtm/static/sk-unix01(74) to die for 0.100000
##################################### FAIL #####################################


On Fri, Apr 27, 2018 at 02:35:05PM +0300, Cyrill Gorcunov wrote:
> To test the case where sockets are removed
> together with directory they are living in.
> 
> Signed-off-by: Cyrill Gorcunov <gorcunov at gmail.com>
> ---
>  test/zdtm/static/Makefile       |   1 +
>  test/zdtm/static/sk-unix01.c    | 324 ++++++++++++++++++++++++++++++++++++++++
>  test/zdtm/static/sk-unix01.desc |   1 +
>  3 files changed, 326 insertions(+)
>  create mode 100644 test/zdtm/static/sk-unix01.c
>  create mode 100644 test/zdtm/static/sk-unix01.desc
> 
> diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
> index 244b7070640e..bec6d1102105 100644
> --- a/test/zdtm/static/Makefile
> +++ b/test/zdtm/static/Makefile
> @@ -345,6 +345,7 @@ TST_DIR		=				\
>  		autofs				\
>  		del_standalone_un		\
>  		sk-unix-mntns			\
> +		sk-unix01			\
>  
>  TST_DIR_FILE	=				\
>  		chroot				\
> diff --git a/test/zdtm/static/sk-unix01.c b/test/zdtm/static/sk-unix01.c
> new file mode 100644
> index 000000000000..33254989a870
> --- /dev/null
> +++ b/test/zdtm/static/sk-unix01.c
> @@ -0,0 +1,324 @@
> +#ifndef _GNU_SOURCE
> +# define _GNU_SOURCE
> +#endif
> +
> +#include <stdlib.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <stdbool.h>
> +#include <limits.h>
> +#include <errno.h>
> +#include <dirent.h>
> +
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +#include <sys/un.h>
> +#include <sys/stat.h>
> +
> +#include "zdtmtst.h"
> +
> +const char *test_doc	= "Check that deleted unix sockets with dirs are restored correctly";
> +const char *test_author	= "Cyrill Gorcunov <gorcunov at openvz.org>";
> +
> +char *dirname;
> +TEST_OPTION(dirname, string, "directory name", 1);
> +
> +static int fill_sock_name(struct sockaddr_un *name, const char *filename)
> +{
> +	char *cwd;
> +
> +	cwd = get_current_dir_name();
> +	if (strlen(filename) + strlen(cwd) + 1 >= sizeof(name->sun_path)) {
> +		pr_err("Name %s/%s is too long for socket\n",
> +		       cwd, filename);
> +		return -1;
> +	}
> +
> +	name->sun_family = AF_LOCAL;
> +	snprintf(name->sun_path, sizeof(name->sun_path), "%s/%s", cwd, filename);
> +	return 0;
> +}
> +
> +static int sk_alloc_bind(int type, struct sockaddr_un *addr)
> +{
> +	int sk;
> +
> +	sk = socket(PF_UNIX, type, 0);
> +	if (sk < 0) {
> +		pr_perror("socket");
> +		return -1;
> +	}
> +
> +	if (addr && bind(sk, (const struct sockaddr *)addr, sizeof(*addr))) {
> +		pr_perror("bind %s", addr->sun_path);
> +		close(sk);
> +		return -1;
> +	}
> +
> +	return sk;
> +}
> +
> +static int sk_alloc_connect(int type, struct sockaddr_un *addr)
> +{
> +	int sk;
> +
> +	sk = socket(PF_UNIX, type, 0);
> +	if (sk < 0) {
> +		pr_perror("socket");
> +		return -1;
> +	}
> +
> +	if (connect(sk, (const struct sockaddr *)addr, sizeof(*addr))) {
> +		pr_perror("connect %s", addr->sun_path);
> +		close(sk);
> +		return -1;
> +	}
> +
> +	return sk;
> +}
> +
> +int main(int argc, char **argv)
> +{
> +	int c1 = 1, c2 = 0, c3 = 3, c4 = 0;
> +	int c5 = 5, c6 = 0, c7 = 7, c8 = 0;
> +	int c9 = 8, c10 = 0;
> +	char filename[PATH_MAX];
> +	char subdir_dg[PATH_MAX];
> +	char subdir_st[PATH_MAX];
> +	struct sockaddr_un addr_from;
> +	struct sockaddr_un addr;
> +	int sk_dgram_pair[2];
> +	int sk_dgram[4];
> +	socklen_t len;
> +	int sk_st[5];
> +	DIR *dir;
> +
> +	test_init(argc, argv);
> +
> +	/*
> +	 * All sockets are under dir to not clash
> +	 * with other tests.
> +	 */
> +	if (mkdir(dirname, 0755) < 0) {
> +		if (errno != EEXIST) {
> +			pr_perror("Can't create %s", dirname);
> +			return 1;
> +		}
> +	}
> +
> +	/*
> +	 * Subdir for dgram sockets.
> +	 */
> +	snprintf(subdir_dg, sizeof(subdir_dg), "%s/%s", dirname, "dg");
> +	if (mkdir(subdir_dg, 0755) < 0) {
> +		if (errno != EEXIST) {
> +			pr_perror("Can't create %s", subdir_dg);
> +			return 1;
> +		}
> +	}
> +
> +	/*
> +	 * Subdir for stream sockets.
> +	 */
> +	snprintf(subdir_st, sizeof(subdir_st), "%s/%s", dirname, "st");
> +	if (mkdir(subdir_st, 0755) < 0) {
> +		if (errno != EEXIST) {
> +			pr_perror("Can't create %s", subdir_st);
> +			return 1;
> +		}
> +	}
> +
> +	/*
> +	 * DGRAM sockets
> +	 *
> +	 *  - create 2 sockets
> +	 *  - bind first to subdired
> +	 *  - connect second to it
> +	 *  - delete socket on fs
> +	 *  - do the same for second pair with same name
> +	 *  - delete socket on fs
> +	 */
> +
> +	snprintf(filename, sizeof(filename), "%s/%s", subdir_dg, "sk-dt");
> +	if (fill_sock_name(&addr, filename) < 0) {
> +		pr_err("%s is too long for socket\n", filename);
> +		return 1;
> +	}
> +	unlink(addr.sun_path);
> +
> +	sk_dgram[0] = sk_alloc_bind(SOCK_DGRAM, &addr);
> +	if (sk_dgram[0] < 0)
> +		return 1;
> +	test_msg("sk-dt: alloc/bind %d\n", sk_dgram[0]);
> +
> +	sk_dgram[1] = sk_alloc_connect(SOCK_DGRAM, &addr);
> +	if (sk_dgram[1] < 0)
> +		return 1;
> +	test_msg("sk-dt: alloc/connect %d\n", sk_dgram[1]);
> +
> +	unlink(addr.sun_path);
> +
> +	sk_dgram[2] = sk_alloc_bind(SOCK_DGRAM, &addr);
> +	if (sk_dgram[2] < 0)
> +		return 1;
> +	test_msg("sk-dt: alloc/bind %d\n", sk_dgram[2]);
> +
> +	sk_dgram[3] = sk_alloc_connect(SOCK_DGRAM, &addr);
> +	if (sk_dgram[3] < 0)
> +		return 1;
> +	test_msg("sk-dt: alloc/connect %d\n", sk_dgram[3]);
> +
> +	unlink(addr.sun_path);
> +
> +	/*
> +	 * DGRAM paired sockets. Just bind both to the same name.
> +	 */
> +	if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sk_dgram_pair)) {
> +		pr_perror("Can't create dgram pair");
> +		return 1;
> +	}
> +	test_msg("sk-dgp: sockpair %d %d\n",
> +		 sk_dgram_pair[0], sk_dgram_pair[1]);
> +	snprintf(filename, sizeof(filename), "%s/%s", subdir_dg, "sk-dtp");
> +
> +	if (fill_sock_name(&addr, filename) < 0) {
> +		pr_err("%s is too long for socket\n", filename);
> +		return 1;
> +	}
> +
> +	if (bind(sk_dgram_pair[0], (const struct sockaddr *)&addr, sizeof(addr))) {
> +		pr_perror("bind %d to %s", sk_dgram_pair[0], addr.sun_path);
> +		return -1;
> +	}
> +	unlink(addr.sun_path);
> +	if (bind(sk_dgram_pair[1], (const struct sockaddr *)&addr, sizeof(addr))) {
> +		pr_perror("bind %d to %s", sk_dgram_pair[1], addr.sun_path);
> +		return -1;
> +	}
> +	unlink(addr.sun_path);
> +
> +	/*
> +	 * Drop subdirectory.
> +	 */
> +	rmdir(subdir_dg);
> +
> +	/*
> +	 * STREAM sockets
> +	 *
> +	 *  - create server, bind to subdired
> +	 *  - create client
> +	 *  - connect to server
> +	 *  - delete socket on fs
> +	 *  - bind again to subdired
> +	 *  - connect to server
> +	 *  - delete socket on fs
> +	 */
> +	snprintf(filename, sizeof(filename), "%s/%s", subdir_st, "sk-st");
> +	if (fill_sock_name(&addr, filename) < 0) {
> +		pr_err("%s is too long for socket\n", filename);
> +		return 1;
> +	}
> +	unlink(addr.sun_path);
> +
> +	sk_st[0] = sk_alloc_bind(SOCK_STREAM, &addr);
> +	if (sk_st[0] < 0)
> +		return 1;
> +	test_msg("sk-st: alloc/bind/listen %d\n", sk_st[0]);
> +
> +	if (listen(sk_st[0], 16)) {
> +		pr_perror("Can't listen on socket");
> +		return 1;
> +	}
> +
> +	sk_st[1] = sk_alloc_connect(SOCK_STREAM, &addr);
> +	if (sk_st[1] < 0)
> +		return 1;
> +	test_msg("sk-st: alloc/connect %d\n", sk_st[1]);
> +
> +	len = sizeof(addr_from);
> +	sk_st[2] = accept(sk_st[0], (struct sockaddr *)&addr_from, &len);
> +	if (sk_st[2] < 0) {
> +		pr_perror("Can't accept on socket");
> +		return 1;
> +	}
> +	test_msg("sk-st: accept %d\n", sk_st[2]);
> +
> +	sk_st[3] = sk_alloc_connect(SOCK_STREAM, &addr);
> +	if (sk_st[3] < 0)
> +		return 1;
> +	test_msg("sk-st: alloc/connect %d\n", sk_st[3]);
> +
> +	len = sizeof(addr_from);
> +	sk_st[4] = accept(sk_st[0], (struct sockaddr *)&addr_from, &len);
> +	if (sk_st[4] < 0) {
> +		pr_perror("Can't accept on socket");
> +		return 1;
> +	}
> +	test_msg("sk-st: accept %d\n", sk_st[4]);
> +
> +	unlink(addr.sun_path);
> +
> +	/*
> +	 * Drop subdirectory.
> +	 */
> +	rmdir(subdir_st);
> +
> +	test_daemon();
> +	test_waitsig();
> +
> +	if (write(sk_dgram[1], &c1, 1) != 1	||
> +	    read(sk_dgram[0], &c2, 1) != 1	||
> +	    write(sk_dgram[3], &c3, 1) != 1	||
> +	    read(sk_dgram[2], &c4, 1) != 1) {
> +		fail("Unable to send/receive a message on dgram");
> +		return 1;
> +	}
> +
> +	if (c1 != c2 || c3 != c4) {
> +		fail("Vals mismatch on dgram: c1 %d c2 %d c3 %d c4 %d",
> +		     c1, c2, c3, c4);
> +		return 1;
> +	}
> +
> +	if (write(sk_dgram_pair[1], &c9, 1) != 1 ||
> +	    read(sk_dgram_pair[0], &c10, 1) != 1) {
> +		fail("Unable to send/receive a message on paired dgram");
> +		return 1;
> +	}
> +
> +	if (c9 != c10) {
> +		fail("Vals mismatch on dgram: c9 %d c10 %d",
> +		     c9, c10);
> +		return 1;
> +	}
> +
> +	if (write(sk_st[2], &c5, 1) != 1	||
> +	    read(sk_st[1], &c6, 1) != 1		||
> +	    write(sk_st[4], &c7, 1) != 1	||
> +	    read(sk_st[3], &c8, 1) != 1) {
> +		fail("Unable to send/receive a message on stream");
> +		return 1;
> +	}
> +
> +	if (c5 != c6 || c7 != c8) {
> +		fail("Vals mismatch on stream: c5 %d c6 %d c7 %d c8 %d",
> +		     c5, c6, c7, c8);
> +		return 1;
> +	}
> +
> +	dir = opendir(subdir_dg);
> +	if (dir != NULL || errno != ENOENT) {
> +		fail("Directory %s is not deteled", subdir_dg);
> +		return 1;
> +	}
> +
> +	dir = opendir(subdir_st);
> +	if (dir != NULL || errno != ENOENT) {
> +		fail("Directory %s is not deteled", subdir_st);
> +		return 1;
> +	}
> +
> +	pass();
> +	return 0;
> +}
> diff --git a/test/zdtm/static/sk-unix01.desc b/test/zdtm/static/sk-unix01.desc
> new file mode 100644
> index 000000000000..2651c4d7789b
> --- /dev/null
> +++ b/test/zdtm/static/sk-unix01.desc
> @@ -0,0 +1 @@
> +{'flavor': 'h ns uns', 'flags': 'suid'}
> -- 
> 2.14.3
> 


More information about the CRIU mailing list