mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-01-23 02:14:37 +00:00
unix: test -- Add sk-unix01 test
To test the case where sockets are removed together with directory they are living in. Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com> Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This commit is contained in:
parent
47aade336d
commit
27c3c21a8c
3 changed files with 369 additions and 0 deletions
|
|
@ -344,6 +344,7 @@ TST_DIR = \
|
|||
autofs \
|
||||
del_standalone_un \
|
||||
sk-unix-mntns \
|
||||
sk-unix01 \
|
||||
|
||||
TST_DIR_FILE = \
|
||||
chroot \
|
||||
|
|
|
|||
367
test/zdtm/static/sk-unix01.c
Normal file
367
test/zdtm/static/sk-unix01.c
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
#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@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;
|
||||
ssprintf(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[9];
|
||||
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.
|
||||
*/
|
||||
ssprintf(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.
|
||||
*/
|
||||
ssprintf(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
|
||||
* - create 3 more sockets
|
||||
* - bind /connect to same name, where one is deleted
|
||||
*/
|
||||
|
||||
ssprintf(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 %s\n", sk_dgram[0], addr.sun_path);
|
||||
|
||||
sk_dgram[1] = sk_alloc_connect(SOCK_DGRAM, &addr);
|
||||
if (sk_dgram[1] < 0)
|
||||
return 1;
|
||||
unlink(addr.sun_path);
|
||||
test_msg("sk-dt: alloc/connect/unlink %d %s\n", sk_dgram[1], 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 %s\n", sk_dgram[2], addr.sun_path);
|
||||
|
||||
sk_dgram[3] = sk_alloc_connect(SOCK_DGRAM, &addr);
|
||||
if (sk_dgram[3] < 0)
|
||||
return 1;
|
||||
unlink(addr.sun_path);
|
||||
test_msg("sk-dt: alloc/connect/unlink %d %s\n", sk_dgram[3], addr.sun_path);
|
||||
|
||||
ssprintf(filename, "%s/%s", dirname, "sole");
|
||||
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[4] = sk_alloc_bind(SOCK_DGRAM, &addr);
|
||||
if (sk_dgram[4] < 0)
|
||||
return 1;
|
||||
test_msg("sk-dt: alloc/bind %d %s\n", sk_dgram[4], addr.sun_path);
|
||||
|
||||
sk_dgram[5] = sk_alloc_connect(SOCK_DGRAM, &addr);
|
||||
if (sk_dgram[5] < 0)
|
||||
return 1;
|
||||
unlink(addr.sun_path);
|
||||
test_msg("sk-dt: alloc/connect/unlink %d %s\n", sk_dgram[5], addr.sun_path);
|
||||
|
||||
sk_dgram[6] = sk_alloc_bind(SOCK_DGRAM, &addr);
|
||||
if (sk_dgram[6] < 0)
|
||||
return 1;
|
||||
test_msg("sk-dt: alloc/bind %d %s\n", sk_dgram[6], addr.sun_path);
|
||||
|
||||
sk_dgram[7] = sk_alloc_connect(SOCK_DGRAM, &addr);
|
||||
if (sk_dgram[7] < 0)
|
||||
return 1;
|
||||
unlink(addr.sun_path);
|
||||
test_msg("sk-dt: alloc/connect/unlink %d %s\n", sk_dgram[7], addr.sun_path);
|
||||
|
||||
sk_dgram[8] = sk_alloc_bind(SOCK_DGRAM, &addr);
|
||||
if (sk_dgram[8] < 0)
|
||||
return 1;
|
||||
test_msg("sk-dt: alloc/bind %d %s\n", sk_dgram[8], addr.sun_path);
|
||||
|
||||
if (dup2(sk_dgram[4], 110) < 0 || dup2(sk_dgram[6], 100) < 0) {
|
||||
pr_perror("Can't move socket");
|
||||
return 1;
|
||||
}
|
||||
close(sk_dgram[4]);
|
||||
sk_dgram[4] = 110;
|
||||
close(sk_dgram[6]);
|
||||
sk_dgram[6] = 100;
|
||||
|
||||
/*
|
||||
* 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]);
|
||||
ssprintf(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
|
||||
*/
|
||||
ssprintf(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;
|
||||
}
|
||||
1
test/zdtm/static/sk-unix01.desc
Normal file
1
test/zdtm/static/sk-unix01.desc
Normal file
|
|
@ -0,0 +1 @@
|
|||
{'flavor': 'h ns uns', 'flags': 'suid'}
|
||||
Loading…
Add table
Add a link
Reference in a new issue