[16/17] unix: Add support of ghost sockets

Submitted by Andrei Vagin on April 4, 2018, 7 a.m.

Details

Message ID 20180404070029.GA31330@outlook.office365.com
State New
Series "unix: Add support for ghost unix sockets"
Headers show

Commit Message

Andrei Vagin April 4, 2018, 7 a.m.
On Tue, Apr 03, 2018 at 12:18:33PM -0700, Andrei Vagin wrote:
> On Sun, Apr 01, 2018 at 11:07:42PM +0300, Cyrill Gorcunov wrote:
> > @@ -1826,6 +1906,127 @@ static int init_unix_sk_info(struct unix_sk_info *ui, UnixSkEntry *ue)
> >  	INIT_LIST_HEAD(&ui->connected);
> >  	INIT_LIST_HEAD(&ui->node);
> >  	INIT_LIST_HEAD(&ui->scm_fles);
> > +	INIT_LIST_HEAD(&ui->ghost_node);
> > +	INIT_LIST_HEAD(&ui->ghost_wait_head);
> > +	INIT_LIST_HEAD(&ui->ghost_waiter);
> > +
> > +	return 0;
> > +}
> > +
> > +#define GHOST_NAME_FMT		"~criu-%u"
> > +#define GHOST_NAME_FMT_PREFIX	6 /* num of chars before counter */
> > +
> > +static int ghost_new_name(char *name, size_t namelen,
> > +			  char **name_new, size_t *namelen_new)
> 
> I think we don't need to generate a new unique name for deleted sockets.
> 
> We can use the old scheme, but before deleting a file, we need to open
> it with O_PATH and save a file descriptor in fdstore, then we can use it
> to connect peer sockets.
>

Pls take a look at the attached patch.

Patch hide | download patch | download mbox

diff --git a/criu/sk-unix.c b/criu/sk-unix.c
index 0b0fa699c..3bf1f4592 100644
--- a/criu/sk-unix.c
+++ b/criu/sk-unix.c
@@ -905,6 +905,8 @@  struct unix_sk_info {
 	u8 listen:1;
 	u8 is_connected:1;
 	u8 peer_queue_restored:1; /* Set in 1 after we restore peer's queue */
+
+	int fdstore_id;
 };
 
 struct scm_fle {
@@ -1237,6 +1239,77 @@  err:
 	return -1;
 }
 
+static int connect_by_fd(int sk, int fdstore_id)
+{
+	struct sockaddr_un addr;
+	int fd, cwd = -1, root = -1, fd_dir;
+	int exit_code = -1, len;
+
+	fd = fdstore_get(fdstore_id);
+	if (fd < 0)
+		return -1;
+
+	cwd = open(".", O_PATH);
+	if (cwd < 0) {
+		pr_perror("Unable to open .");
+		goto out;
+	}
+	root = open("/", O_PATH);
+	if (cwd < 0) {
+		pr_perror("Unable to open /");
+		goto out;
+	}
+
+	fd_dir = open_proc(PROC_SELF, "fd");
+	if (fd_dir < 0)
+		goto out;
+	if (fchdir(fd_dir)) {
+		pr_perror("change working directory");
+		close(fd_dir);
+		goto out;
+	}
+	close(fd_dir);
+	if (chroot(".")) {
+		pr_perror("Unable to change root directory");
+		goto out;
+	}
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+	len = snprintf(addr.sun_path, UNIX_PATH_MAX, "%d", fd);
+	if (connect(sk, (struct sockaddr *)&addr,
+				sizeof(addr.sun_family) +
+				len) < 0) {
+		pr_perror("Unable to connect\n");
+		return -1;
+	}
+
+	exit_code = 0;
+out:
+	if (root >= 0) {
+		if (fchdir(root)) {
+			exit_code = -1;
+			pr_perror("Unable to change working directory");
+		}
+		if (chroot(".")) {
+			exit_code = -1;
+			pr_perror("Unable to change root directory");
+		}
+		close(root);
+	}
+	if (cwd >= 0) {
+		if (fchdir(cwd)) {
+			exit_code = -1;
+			pr_perror("Unable to change working directory");
+		}
+		close(cwd);
+	}
+	set_proc_self_fd(-1);
+	close(fd);
+
+	return exit_code;
+}
+
 static int post_open_standalone(struct file_desc *d, int fd)
 {
 	struct unix_sk_info *ui;
@@ -1271,6 +1344,12 @@  static int post_open_standalone(struct file_desc *d, int fd)
 
 	pr_info("\tConnect %#x to %#x\n", ui->ue->ino, peer->ue->ino);
 
+	if (peer->fdstore_id >=0) {
+		if (connect_by_fd(fd, peer->fdstore_id) < 0)
+			return -1;
+		goto restore_queue;
+	}
+
 	if (prep_unix_sk_cwd(peer, &cwd_fd, NULL, &ns_fd))
 		return -1;
 
@@ -1300,7 +1379,7 @@  static int bind_deleted_unix_sk(int sk, struct unix_sk_info *ui,
 					struct sockaddr_un *addr)
 {
 	char temp[PATH_MAX];
-	int ret;
+	int ret, fd;
 
 	pr_info("found duplicate unix socket bound at %s\n", addr->sun_path);
 
@@ -1325,6 +1404,16 @@  static int bind_deleted_unix_sk(int sk, struct unix_sk_info *ui,
 		return -1;;
 	}
 
+	fd = open(addr->sun_path, O_PATH);
+	if (fd < 0) {
+		pr_perror("Unable to open %s", addr->sun_path);
+		return -1;
+	}
+	ui->fdstore_id = fdstore_add(fd);
+	if (ui->fdstore_id < 0)
+		return -1;
+	close(fd);
+
 	ret = rename(temp, addr->sun_path);
 	if (ret < 0) {
 		pr_perror("couldn't move socket back");
@@ -1376,6 +1465,18 @@  static int bind_unix_sk(int sk, struct unix_sk_info *ui)
 			pr_perror("Can't bind socket");
 			goto done;
 		}
+	} else if (ui->ue->deleted) {
+		int fd;
+
+		fd = open(addr.sun_path, O_PATH);
+		if (fd < 0) {
+			pr_perror("Unable to open %s", addr.sun_path);
+			return -1;
+		}
+		ui->fdstore_id = fdstore_add(fd);
+		if (ui->fdstore_id < 0)
+			return -1;
+		close(fd);
 	}
 
 	if (*ui->name && ui->ue->file_perms) {
@@ -1857,6 +1958,7 @@  static int collect_one_unixsk(void *o, ProtobufCMessage *base, struct cr_img *i)
 		ui->peer_resolve.actor = post_prepare_unix_sk;
 		add_post_prepare_cb(&ui->peer_resolve);
 	}
+	ui->fdstore_id = -1;
 
 	list_add_tail(&ui->list, &unix_sockets);
 	return file_desc_add(&ui->d, ui->ue->id, &unix_desc_ops);
diff --git a/test/zdtm/static/sk-unix01.c b/test/zdtm/static/sk-unix01.c
index 024338c24..ece4b2a56 100644
--- a/test/zdtm/static/sk-unix01.c
+++ b/test/zdtm/static/sk-unix01.c
@@ -204,7 +204,7 @@  int main(int argc, char **argv)
 	}
 	unlink(filename);
 
-	rmdir(subdir_dg);
+//	rmdir(subdir_dg);
 
 	/*
 	 * STREAM sockets
@@ -262,8 +262,8 @@  int main(int argc, char **argv)
 
 	unlink(filename);
 
-	rmdir(subdir_dg);
-	rmdir(subdir_st);
+//	rmdir(subdir_dg);
+//	rmdir(subdir_st);
 
 	test_daemon();
 	test_waitsig();

Comments

Cyrill Gorcunov April 4, 2018, 7:27 a.m.
On Wed, Apr 04, 2018 at 12:00:30AM -0700, Andrei Vagin wrote:
> > 
> > I think we don't need to generate a new unique name for deleted sockets.
> > 
> > We can use the old scheme, but before deleting a file, we need to open
> > it with O_PATH and save a file descriptor in fdstore, then we can use it
> > to connect peer sockets.
> >
> 
> Pls take a look at the attached patch. 

I suppose it passes the test, so I'm more than fine with it!
Merge it into criu-dev please and lets move on :)
Andrei Vagin April 4, 2018, 5:38 p.m.
On Wed, Apr 04, 2018 at 10:27:33AM +0300, Cyrill Gorcunov wrote:
> On Wed, Apr 04, 2018 at 12:00:30AM -0700, Andrei Vagin wrote:
> > > 
> > > I think we don't need to generate a new unique name for deleted sockets.
> > > 
> > > We can use the old scheme, but before deleting a file, we need to open
> > > it with O_PATH and save a file descriptor in fdstore, then we can use it
> > > to connect peer sockets.
> > >
> > 
> > Pls take a look at the attached patch. 
> 
> I suppose it passes the test, so I'm more than fine with it!
> Merge it into criu-dev please and lets move on :)

It is POC. It doesn't support a case, when a socket directory was
deleted, maybe something else, so you need to improve it.
Cyrill Gorcunov April 4, 2018, 6:32 p.m.
On Wed, Apr 04, 2018 at 10:38:18AM -0700, Andrei Vagin wrote:
> > 
> > I suppose it passes the test, so I'm more than fine with it!
> > Merge it into criu-dev please and lets move on :)
> 
> It is POC. It doesn't support a case, when a socket directory was
> deleted, maybe something else, so you need to improve it.

I think the cases where subdirs are to be created is different
case and we can handle it on top later.