sk-unix: rework unix_resolve_name

- use exit_code instead of returning ret
- replace -errno return with -1
- move fallback to if (!kdat.sk_unix_file)
- fix readlinkat error checking (ret < 0 && ret >= PATH_MAX) by using
  read_fd_link helper

Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This commit is contained in:
Pavel Tikhomirov 2023-03-28 12:36:45 +08:00 committed by Andrei Vagin
parent de39bd2bd1
commit 5c8cdceec2

View file

@ -645,78 +645,71 @@ static int unix_resolve_name_old(int lfd, uint32_t id, struct unix_sk_desc *d, U
static int unix_resolve_name(int lfd, uint32_t id, struct unix_sk_desc *d, UnixSkEntry *ue, const struct fd_parms *p)
{
char *name = d->name;
char path[PATH_MAX], tmp[PATH_MAX];
char path[PATH_MAX];
struct stat st;
int fd, proc_fd, mnt_id, ret;
int fd, ret;
int exit_code = -1;
if (d->namelen == 0 || name[0] == '\0')
return 0;
if (kdat.sk_unix_file && (root_ns_mask & CLONE_NEWNS)) {
if (get_mnt_id(lfd, &mnt_id))
if (!kdat.sk_unix_file) {
pr_warn("Trying to resolve unix socket with obsolete method\n");
if (unix_resolve_name_old(lfd, id, d, ue, p)) {
pr_err("Unable to resolve unix socket name with obsolete method. "
"Try a linux kernel newer than 4.10\n");
return -1;
ue->mnt_id = mnt_id;
ue->has_mnt_id = true;
}
return 0;
}
fd = ioctl(lfd, SIOCUNIXFILE);
if (fd < 0) {
pr_warn("Unable to get a socket file descriptor with SIOCUNIXFILE ioctl: %s\n", strerror(errno));
goto fallback;
pr_perror("Unable to get a socket file descriptor with SIOCUNIXFILE ioctl");
return -1;
}
ret = fstat(fd, &st);
if (ret) {
if (root_ns_mask & CLONE_NEWNS) {
struct fdinfo_common fdinfo = { .mnt_id = -1 };
if (parse_fdinfo(fd, FD_TYPES__UND, &fdinfo))
goto out;
ue->mnt_id = fdinfo.mnt_id;
ue->has_mnt_id = true;
}
if (fstat(fd, &st)) {
pr_perror("Unable to fstat socket fd");
return -1;
goto out;
}
d->mode = st.st_mode;
d->uid = st.st_uid;
d->gid = st.st_gid;
proc_fd = get_service_fd(PROC_FD_OFF);
if (proc_fd < 0) {
pr_err("Unable to get service fd for proc\n");
return -1;
}
snprintf(tmp, sizeof(tmp), "self/fd/%d", fd);
ret = readlinkat(proc_fd, tmp, path, PATH_MAX);
if (ret < 0 && ret >= PATH_MAX) {
pr_perror("Unable to readlink %s", tmp);
ret = read_fd_link(fd, path, sizeof(path));
if (ret < 0)
goto out;
}
path[ret] = 0;
d->deleted = strip_deleted(path, ret);
if (name[0] != '/') {
ret = cut_path_ending(path, name);
if (ret) {
pr_err("Unable too resolve %s from %s\n", name, path);
if (cut_path_ending(path, name)) {
pr_err("Unable too cut %s from %s\n", name, path);
goto out;
}
ue->name_dir = xstrdup(path);
if (!ue->name_dir) {
ret = -ENOMEM;
if (!ue->name_dir)
goto out;
}
pr_debug("Resolved socket relative name %s to %s/%s\n", name, ue->name_dir, name);
}
ret = 0;
exit_code = 0;
out:
close(fd);
return ret;
fallback:
pr_warn("Trying to resolve unix socket with obsolete method\n");
ret = unix_resolve_name_old(lfd, id, d, ue, p);
if (ret < 0)
pr_err("Unable to resolve unix socket name with obsolete method. Try a linux kernel newer than 4.10\n");
return ret;
return exit_code;
}
/*