fown: Don't fail on dumping files opened with O_PATH

O_PATH opened files are special: they have empty
file operations in kernel space, so there not that
much we can do with them, even setting position is
not allowed. Same applies to a signal number for
owner settings.

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Co-developed-by: Alexander Mikhalitsyn <alexander@mihalicyn.com>
Signed-off-by: Alexander Mikhalitsyn (Virtuozzo) <alexander@mihalicyn.com>
This commit is contained in:
Cyrill Gorcunov 2020-02-07 15:59:45 +03:00 committed by Andrei Vagin
parent 58fd63042c
commit f167d1f4e9
3 changed files with 64 additions and 32 deletions

View file

@ -1776,11 +1776,17 @@ static int do_open_reg(int ns_root_fd, struct reg_file_info *rfi, void *arg)
if (fd < 0)
return fd;
if ((rfi->rfe->pos != -1ULL) &&
lseek(fd, rfi->rfe->pos, SEEK_SET) < 0) {
pr_perror("Can't restore file pos");
close(fd);
return -1;
/*
* O_PATH opened files carry empty fops in kernel,
* just ignore positioning at all.
*/
if (!(rfi->rfe->flags & O_PATH)) {
if (rfi->rfe->pos != -1ULL &&
lseek(fd, rfi->rfe->pos, SEEK_SET) < 0) {
pr_perror("Can't restore file pos");
close(fd);
return -1;
}
}
return fd;

View file

@ -399,7 +399,10 @@ static int fill_fd_params(struct pid *owner_pid, int fd, int lfd,
pr_info("%d fdinfo %d: pos: %#16"PRIx64" flags: %16o/%#x\n",
owner_pid->real, fd, p->pos, p->flags, (int)p->fd_flags);
ret = fcntl(lfd, F_GETSIG, 0);
if (p->flags & O_PATH)
ret = 0;
else
ret = fcntl(lfd, F_GETSIG, 0);
if (ret < 0) {
pr_perror("Can't get owner signum on %d", lfd);
return -1;

View file

@ -317,15 +317,60 @@ grps_err:
return -1;
}
static int fill_fds_fown(int fd, struct fd_opts *p)
{
int flags, ret;
struct f_owner_ex owner_ex;
uint32_t v[2];
/*
* For O_PATH opened files there is no owner at all.
*/
flags = sys_fcntl(fd, F_GETFL, 0);
if (flags < 0) {
pr_err("fcntl(%d, F_GETFL) -> %d\n", fd, flags);
return -1;
}
if (flags & O_PATH) {
p->fown.pid = 0;
return 0;
}
ret = sys_fcntl(fd, F_GETOWN_EX, (long)&owner_ex);
if (ret) {
pr_err("fcntl(%d, F_GETOWN_EX) -> %d\n", fd, ret);
return -1;
}
/*
* Simple case -- nothing is changed.
*/
if (owner_ex.pid == 0) {
p->fown.pid = 0;
return 0;
}
ret = sys_fcntl(fd, F_GETOWNER_UIDS, (long)&v);
if (ret) {
pr_err("fcntl(%d, F_GETOWNER_UIDS) -> %d\n", fd, ret);
return -1;
}
p->fown.uid = v[0];
p->fown.euid = v[1];
p->fown.pid_type = owner_ex.type;
p->fown.pid = owner_ex.pid;
return 0;
}
static int fill_fds_opts(struct parasite_drain_fd *fds, struct fd_opts *opts)
{
int i;
for (i = 0; i < fds->nr_fds; i++) {
int flags, fd = fds->fds[i], ret;
int flags, fd = fds->fds[i];
struct fd_opts *p = opts + i;
struct f_owner_ex owner_ex;
uint32_t v[2];
flags = sys_fcntl(fd, F_GETFD, 0);
if (flags < 0) {
@ -335,30 +380,8 @@ static int fill_fds_opts(struct parasite_drain_fd *fds, struct fd_opts *opts)
p->flags = (char)flags;
ret = sys_fcntl(fd, F_GETOWN_EX, (long)&owner_ex);
if (ret) {
pr_err("fcntl(%d, F_GETOWN_EX) -> %d\n", fd, ret);
if (fill_fds_fown(fd, p))
return -1;
}
/*
* Simple case -- nothing is changed.
*/
if (owner_ex.pid == 0) {
p->fown.pid = 0;
continue;
}
ret = sys_fcntl(fd, F_GETOWNER_UIDS, (long)&v);
if (ret) {
pr_err("fcntl(%d, F_GETOWNER_UIDS) -> %d\n", fd, ret);
return -1;
}
p->fown.uid = v[0];
p->fown.euid = v[1];
p->fown.pid_type = owner_ex.type;
p->fown.pid = owner_ex.pid;
}
return 0;