[CRIU] [PATCH 3/5] sk-unix: Move name handling into separate routine
Cyrill Gorcunov
gorcunov at openvz.org
Thu Jul 23 12:22:38 PDT 2015
It gonna be extende to support relative names.
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
sk-unix.c | 170 +++++++++++++++++++++++++++++++++-----------------------------
1 file changed, 91 insertions(+), 79 deletions(-)
diff --git a/sk-unix.c b/sk-unix.c
index ee9b2495a2f5..16f04a8e0f64 100644
--- a/sk-unix.c
+++ b/sk-unix.c
@@ -366,21 +366,98 @@ const struct fdtype_ops unix_dump_ops = {
.dump = dump_one_unix_fd,
};
-static int unix_collect_one(const struct unix_diag_msg *m,
- struct rtattr **tb)
+/*
+ * Returns: < 0 on error, 0 if OK, 1 to skip the socket
+ */
+static int unix_process_name(struct unix_sk_desc *d, const struct unix_diag_msg *m, struct rtattr **tb)
{
- struct unix_sk_desc *d;
- char *name = NULL;
+ int len, mntns_root;
struct ns_id *ns;
- int ret = 0, mntns_root;
+ char *name;
ns = lookup_ns_by_id(root_item->ids->mnt_ns_id, &mnt_ns_desc);
- if (ns == NULL)
- return -1;
+ if (!ns)
+ return -ENOENT;
mntns_root = mntns_get_root_fd(ns);
if (mntns_root < 0)
- return -1;
+ return -ENOENT;
+
+ len = RTA_PAYLOAD(tb[UNIX_DIAG_NAME]);
+ name = xmalloc(len + 1);
+ if (!name)
+ return -ENOMEM;
+
+ memcpy(name, RTA_DATA(tb[UNIX_DIAG_NAME]), len);
+ name[len] = '\0';
+
+ if (name[0] != '\0') {
+ struct unix_diag_vfs *uv;
+ bool drop_path = false;
+ char rpath[PATH_MAX];
+ struct stat st;
+
+ if (name[0] != '/') {
+ pr_warn("Relative bind path '%s' unsupported\n", name);
+ goto skip;
+ }
+
+ if (!tb[UNIX_DIAG_VFS]) {
+ pr_err("Bound socket w/o inode %#x\n", m->udiag_ino);
+ goto skip;
+ }
+
+ uv = RTA_DATA(tb[UNIX_DIAG_VFS]);
+ snprintf(rpath, sizeof(rpath), ".%s", name);
+ if (fstatat(mntns_root, rpath, &st, 0)) {
+ if (errno != ENOENT) {
+ pr_warn("Can't stat socket %#x(%s), skipping: %m (err %d)\n",
+ m->udiag_ino, rpath, errno);
+ goto skip;
+ }
+
+ pr_info("unix: Dropping path %s for unlinked sk %#x\n",
+ name, m->udiag_ino);
+ drop_path = 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;
+ }
+
+ d->mode = st.st_mode;
+ d->uid = st.st_uid;
+ d->gid = st.st_gid;
+ }
+
+ d->namelen = len;
+ d->name = name;
+ return 0;
+
+skip:
+ xfree(name);
+ return 1;
+}
+
+static int unix_collect_one(const struct unix_diag_msg *m,
+ struct rtattr **tb)
+{
+ struct unix_sk_desc *d;
+ int ret = 0;
d = xzalloc(sizeof(*d));
if (!d)
@@ -403,77 +480,12 @@ static int unix_collect_one(const struct unix_diag_msg *m,
d->peer_ino = *(int *)RTA_DATA(tb[UNIX_DIAG_PEER]);
if (tb[UNIX_DIAG_NAME]) {
- int len = RTA_PAYLOAD(tb[UNIX_DIAG_NAME]);
-
- name = xmalloc(len + 1);
- if (!name)
+ ret = unix_process_name(d, m, tb);
+ if (ret < 0)
goto err;
-
- memcpy(name, RTA_DATA(tb[UNIX_DIAG_NAME]), len);
- name[len] = '\0';
-
- if (name[0] != '\0') {
- struct unix_diag_vfs *uv;
- struct stat st;
- char rpath[PATH_MAX];
- bool drop_path = false;
-
- if (name[0] != '/') {
- pr_warn("Relative bind path '%s' "
- "unsupported\n", name);
- goto skip;
- }
-
- if (!tb[UNIX_DIAG_VFS]) {
- pr_err("Bound socket w/o inode %#x\n",
- m->udiag_ino);
- goto skip;
- }
-
- uv = RTA_DATA(tb[UNIX_DIAG_VFS]);
- snprintf(rpath, sizeof(rpath), ".%s", name);
- if (fstatat(mntns_root, rpath, &st, 0)) {
- if (errno != ENOENT) {
- pr_warn("Can't stat socket %#x(%s), skipping: %m (err %d)\n",
- m->udiag_ino, rpath, errno);
- goto skip;
- }
-
- pr_info("unix: Dropping path %s for unlinked sk %#x\n",
- name, m->udiag_ino);
- drop_path = 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;
- }
-
- d->mode = st.st_mode;
- d->uid = st.st_uid;
- d->gid = st.st_gid;
- }
-
- d->namelen = len;
- d->name = name;
+ else if (ret == 1)
+ goto skip;
+ BUG_ON(ret != 0);
}
if (tb[UNIX_DIAG_ICONS]) {
@@ -527,7 +539,7 @@ err:
ret = -1;
skip:
xfree(d->icons);
- xfree(name);
+ xfree(d->name);
xfree(d);
return ret;
}
--
2.4.3
More information about the CRIU
mailing list