[3/9] kerndat: check the SIOCUNIXFILE ioctl for unix sockets

Submitted by Andrey Vagin on March 16, 2018, 5:24 p.m.

Details

Message ID 20180316172430.7815-4-avagin@virtuozzo.com
State Accepted
Series "unix: restore sockets in proper mount namespaces"
Commit 5a35774f81be649797ced4d440232a1185add424
Headers show

Commit Message

Andrey Vagin March 16, 2018, 5:24 p.m.
This ioctl opens a file to which a socket is bound and
returns a file descriptor. This file descriptor can be used to get
mnt_id and a file path.

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
---
 criu/cr-check.c        |  9 +++++++++
 criu/include/kerndat.h |  1 +
 criu/include/sockets.h |  1 +
 criu/kerndat.c         |  2 ++
 criu/sk-unix.c         | 29 +++++++++++++++++++++++++++++
 5 files changed, 42 insertions(+)

Patch hide | download patch | download mbox

diff --git a/criu/cr-check.c b/criu/cr-check.c
index 793ec6486..ff4d9a4bb 100644
--- a/criu/cr-check.c
+++ b/criu/cr-check.c
@@ -1070,6 +1070,14 @@  static int check_sk_netns(void)
 	return 0;
 }
 
+static int check_sk_unix_file(void)
+{
+	if (!kdat.sk_unix_file)
+		return -1;
+
+	return 0;
+}
+
 static int check_ns_pid(void)
 {
 	if (!kdat.has_nspid)
@@ -1294,6 +1302,7 @@  static struct feature_list feature_list[] = {
 	{ "uffd-noncoop", check_uffd_noncoop },
 	{ "can_map_vdso", check_can_map_vdso},
 	{ "sk_ns", check_sk_netns },
+	{ "sk_unix_file", check_sk_unix_file },
 	{ "nsid", check_nsid },
 	{ "link_nsid", check_link_nsid},
 	{ "ns_pid", check_ns_pid},
diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h
index 0f4b55fa6..28a84fb0d 100644
--- a/criu/include/kerndat.h
+++ b/criu/include/kerndat.h
@@ -48,6 +48,7 @@  struct kerndat_s {
 	enum loginuid_func luid;
 	bool compat_cr;
 	bool sk_ns;
+	bool sk_unix_file;
 	bool tun_ns;
 	enum pagemap_func pmap;
 	unsigned int has_xtlocks;
diff --git a/criu/include/sockets.h b/criu/include/sockets.h
index cb233b9f9..db3304288 100644
--- a/criu/include/sockets.h
+++ b/criu/include/sockets.h
@@ -95,5 +95,6 @@  extern int set_netns(uint32_t ns_id);
 #endif
 
 extern int kerndat_socket_netns(void);
+extern int kerndat_socket_unix_file(void);
 
 #endif /* __CR_SOCKETS_H__ */
diff --git a/criu/kerndat.c b/criu/kerndat.c
index 313f6307c..798cb1627 100644
--- a/criu/kerndat.c
+++ b/criu/kerndat.c
@@ -1086,6 +1086,8 @@  int kerndat_init(void)
 	if (!ret)
 		ret = kerndat_tun_netns();
 	if (!ret)
+		ret = kerndat_socket_unix_file();
+	if (!ret)
 		ret = kerndat_nsid();
 	if (!ret)
 		ret = kerndat_link_nsid();
diff --git a/criu/sk-unix.c b/criu/sk-unix.c
index 7303446a6..2fd9ec126 100644
--- a/criu/sk-unix.c
+++ b/criu/sk-unix.c
@@ -29,6 +29,7 @@ 
 #include "external.h"
 #include "crtools.h"
 #include "fdstore.h"
+#include "kerndat.h"
 
 #include "protobuf.h"
 #include "images/sk-unix.pb-c.h"
@@ -196,6 +197,34 @@  static int write_unix_entry(struct unix_sk_desc *sk)
 	return ret;
 }
 
+#ifndef SIOCUNIXFILE
+#define SIOCUNIXFILE (SIOCPROTOPRIVATE + 0) /* open a socket file with O_PATH */
+#endif
+
+int kerndat_socket_unix_file(void)
+{
+	int sk, fd;
+
+	sk = socket(AF_UNIX, SOCK_DGRAM, 0);
+	if (sk < 0) {
+		pr_perror("Unable to create socket");
+		return -1;
+	}
+	fd = ioctl(sk, SIOCUNIXFILE);
+	if (fd < 0 && errno != ENOENT) {
+		pr_warn("Unable to open a socket file: %m\n");
+		kdat.sk_unix_file = false;
+		close(sk);
+		return 0;
+	}
+	close(sk);
+	close(fd);
+
+	kdat.sk_unix_file = true;
+
+	return 0;
+}
+
 static int resolve_rel_name(struct unix_sk_desc *sk, const struct fd_parms *p)
 {
 	rel_name_desc_t *rel_name = sk->rel_name;