[CRIU] [PATCH] zdtm: unlinked socket with dentry alias
Stanislav Kinsburskiy
skinsbursky at odin.com
Tue Sep 29 01:47:02 PDT 2015
28.09.2015 20:46, Pavel Emelyanov пишет:
> 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?
It fails for rhel6 kernel. So the test was created for it.
But since zdtm in maintained in CRIU now, I sent it here.
And, probably, it can be useful for CRIU as well, if you don't have such
a test case.
>
>> 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