[CRIU] [PATCH 07/11] sk-unix: Fix path resolving for sockets with abs symlinks in paths

Cyrill Gorcunov gorcunov at openvz.org
Tue Aug 2 08:34:33 PDT 2016


From: Cyrill Gorcunov <gorcunov at virtuozzo.com>

Signed-off-by: Cyrill Gorcunov <gorcunov at virtuozzo.com>
---
 criu/sk-unix.c | 44 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 39 insertions(+), 5 deletions(-)

diff --git a/criu/sk-unix.c b/criu/sk-unix.c
index 2bab17faf434..4c716230af74 100644
--- a/criu/sk-unix.c
+++ b/criu/sk-unix.c
@@ -227,8 +227,9 @@ static int resolve_rel_name(struct unix_sk_desc *sk, const struct fd_parms *p)
 
 	for (i = 0; i < ARRAY_SIZE(dirs); i++) {
 		char dir[PATH_MAX], path[PATH_MAX];
+		int ret, root_fd;
 		struct stat st;
-		int ret;
+		int errno_save;
 
 		snprintf(path, sizeof(path), "/proc/%d/%s", p->pid, dirs[i]);
 		ret = readlink(path, dir, sizeof(dir));
@@ -238,10 +239,18 @@ static int resolve_rel_name(struct unix_sk_desc *sk, const struct fd_parms *p)
 		}
 		dir[ret] = 0;
 
+		if (cr_set_root(mntns_root, &root_fd))
+			goto err;
+
 		snprintf(path, sizeof(path), ".%s/%s", dir, sk->name);
-		if (fstatat(mntns_root, path, &st, 0)) {
-			if (errno == ENOENT)
+		ret = fstatat(mntns_root, path, &st, 0);
+		errno_save = errno;
+		if (cr_restore_root(root_fd))
+			goto err;
+		if (ret) {
+			if (errno_save == ENOENT)
 				continue;
+			pr_perror("Unable to stat %s", path);
 			goto err;
 		}
 
@@ -510,10 +519,11 @@ 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 deleted = false;
+		int mntns_root, root_fd;
+		bool drop_path = false;
 		char rpath[PATH_MAX];
 		struct ns_id *ns;
 		struct stat st;
-		int mntns_root;
 
 		if (!tb[UNIX_DIAG_VFS]) {
 			pr_err("Bound socket w/o inode %#x\n", m->udiag_ino);
@@ -550,11 +560,19 @@ static int unix_process_name(struct unix_sk_desc *d, const struct unix_diag_msg
 			goto postprone;
 		}
 
+		ret = cr_set_root(mntns_root, &root_fd);
+		if (ret)
+			goto out;
+
 		snprintf(rpath, sizeof(rpath), ".%s", name);
-		if (fstatat(mntns_root, rpath, &st, 0)) {
+		ret = fstatat(mntns_root, rpath, &st, 0);
+		if (ret) {
 			if (errno != ENOENT) {
 				pr_warn("Can't stat socket %#x(%s), skipping: %m (err %d)\n",
 					m->udiag_ino, rpath, errno);
+				ret = cr_restore_root(root_fd);
+				if (ret)
+					goto out;
 				goto skip;
 			}
 
@@ -568,6 +586,22 @@ static int unix_process_name(struct unix_sk_desc *d, const struct unix_diag_msg
 				name, (int)st.st_dev, (int)st.st_ino,
 				(int)uv->udiag_vfs_dev, (int)uv->udiag_vfs_ino);
 			deleted = true;
+			drop_path = true;
+		}
+
+		ret = cr_restore_root(root_fd);
+		if (ret)
+			goto out;
+
+		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;
 		}
 
 		d->mode = st.st_mode;
-- 
2.7.4



More information about the CRIU mailing list