[CRIU] [PATCH 2/2] unix: don't drop the path on unix sockets if they don't exist
Tycho Andersen
tycho.andersen at canonical.com
Wed Jun 22 10:35:02 PDT 2016
For standalone unix sockets, listen() will fail if we haven't called bind()
with an actual address. If we remove the name on dump, we won't call
bind(), and thus sockets in this state will fail to restore.
Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
criu/sk-unix.c | 30 ++++++++++++++++--------------
images/sk-unix.proto | 1 +
test/zdtm/static/deleted_standalone_unix.c | 7 +++++++
3 files changed, 24 insertions(+), 14 deletions(-)
diff --git a/criu/sk-unix.c b/criu/sk-unix.c
index ca6673e..c44c5cf 100644
--- a/criu/sk-unix.c
+++ b/criu/sk-unix.c
@@ -72,6 +72,7 @@ struct unix_sk_desc {
unsigned int nr_icons;
unsigned int *icons;
unsigned char shutdown;
+ bool deleted;
mode_t mode;
uid_t uid;
@@ -337,6 +338,11 @@ static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
perms->gid = userns_gid(sk->gid);
}
+ if (sk->deleted) {
+ ue->has_deleted = true;
+ ue->deleted = sk->deleted;
+ }
+
sk_encode_shutdown(ue, sk->shutdown);
if (ue->peer) {
@@ -503,7 +509,7 @@ static int unix_process_name(struct unix_sk_desc *d, const struct unix_diag_msg
if (name[0] != '\0') {
struct unix_diag_vfs *uv;
- bool drop_path = false;
+ bool deleted = false;
char rpath[PATH_MAX];
struct ns_id *ns;
struct stat st;
@@ -554,30 +560,21 @@ static int unix_process_name(struct unix_sk_desc *d, const struct unix_diag_msg
pr_info("unix: Dropping path %s for unlinked sk %#x\n",
name, m->udiag_ino);
- drop_path = true;
+ deleted = true;
} else if ((st.st_ino != uv->udiag_vfs_ino) ||
!phys_stat_dev_match(st.st_dev, uv->udiag_vfs_dev, ns, name)) {
pr_info("unix: Dropping path %s for unlinked bound "
"sk %#x.%#x real %#x.%#x\n",
name, (int)st.st_dev, (int)st.st_ino,
(int)uv->udiag_vfs_dev, (int)uv->udiag_vfs_ino);
- drop_path = true;
- }
-
- if (drop_path) {
- /*
- * When a socket is bound to unlinked file, we
- * just drop his name, since no one will access
- * it via one.
- */
- xfree(name);
- len = 0;
- name = NULL;
+ deleted = true;
}
d->mode = st.st_mode;
d->uid = st.st_uid;
d->gid = st.st_gid;
+
+ d->deleted = deleted;
}
postprone:
@@ -1225,6 +1222,11 @@ out:
if (restore_socket_opts(sk, ui->ue->opts))
return -1;
+ if (ui->ue->deleted && unlink((char *)ui->ue->name.data) < 0) {
+ pr_perror("failed to unlink %s\n", ui->ue->name.data);
+ return -1;
+ }
+
return sk;
}
diff --git a/images/sk-unix.proto b/images/sk-unix.proto
index aa2bcf7..75ec3bf 100644
--- a/images/sk-unix.proto
+++ b/images/sk-unix.proto
@@ -45,4 +45,5 @@ message unix_sk_entry {
* Relative socket name may have prefix.
*/
optional string name_dir = 14;
+ optional bool deleted = 15;
}
diff --git a/test/zdtm/static/deleted_standalone_unix.c b/test/zdtm/static/deleted_standalone_unix.c
index 9288a6d..cd4d42a 100644
--- a/test/zdtm/static/deleted_standalone_unix.c
+++ b/test/zdtm/static/deleted_standalone_unix.c
@@ -4,6 +4,7 @@
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <sys/un.h>
#include "zdtmtst.h"
@@ -31,6 +32,7 @@ int main(int argc, char **argv)
{
struct sockaddr_un addr;
int sk, ret = 1;
+ struct stat sb;
test_init(argc, argv);
@@ -68,6 +70,11 @@ int main(int argc, char **argv)
goto out;
}
+ if (stat(addr.sun_path, &sb) == 0 || errno != ENOENT) {
+ fail("%s exists after restore\n", addr.sun_path);
+ goto out;
+ }
+
pass();
ret = 0;
out:
--
2.7.4
More information about the CRIU
mailing list