[3/5] fown: Don't fail on dumping files opened with O_PATH

Submitted by Cyrill Gorcunov on Dec. 7, 2018, 12:29 p.m.

Details

Message ID 20181207122948.26683-4-gorcunov@gmail.com
State New
Series "fown: Handle dead pids and O_PATH"
Headers show

Commit Message

Cyrill Gorcunov Dec. 7, 2018, 12:29 p.m.
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>
---
 criu/files-reg.c    | 16 +++++++++++-----
 criu/files.c        |  5 ++++-
 criu/pie/parasite.c | 13 +++++++++++++
 3 files changed, 28 insertions(+), 6 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/files-reg.c b/criu/files-reg.c
index c4f4e1616a85..a2042a512538 100644
--- a/criu/files-reg.c
+++ b/criu/files-reg.c
@@ -1777,11 +1777,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;
diff --git a/criu/files.c b/criu/files.c
index b12258ad2654..d96358b558b4 100644
--- a/criu/files.c
+++ b/criu/files.c
@@ -392,7 +392,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;
diff --git a/criu/pie/parasite.c b/criu/pie/parasite.c
index c32e31384fd8..f9e954484615 100644
--- a/criu/pie/parasite.c
+++ b/criu/pie/parasite.c
@@ -325,6 +325,19 @@  static int fill_fds_opts(struct parasite_drain_fd *fds, struct fd_opts *opts)
 
 		p->flags = (char)flags;
 
+		/*
+		 * For O_PATH opened files there is no owner at all.
+		 */
+		if (flags < 0) {
+			pr_err("fcntl(%d, F_GETFL) -> %d\n", fd, flags);
+			return -1;
+		}
+		flags = sys_fcntl(fd, F_GETFL, 0);
+		if (flags & O_PATH) {
+			p->fown.pid = 0;
+			continue;
+		}
+
 		ret = sys_fcntl(fd, F_GETOWN_EX, (long)&owner_ex);
 		if (ret) {
 			pr_err("fcntl(%d, F_GETOWN_EX) -> %d\n", fd, ret);

Comments

Andrei Vagin Dec. 11, 2018, 6:19 a.m.
On Fri, Dec 07, 2018 at 03:29:46PM +0300, Cyrill Gorcunov wrote:
> 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>
> ---
>  criu/files-reg.c    | 16 +++++++++++-----
>  criu/files.c        |  5 ++++-
>  criu/pie/parasite.c | 13 +++++++++++++
>  3 files changed, 28 insertions(+), 6 deletions(-)
> 
> diff --git a/criu/files-reg.c b/criu/files-reg.c
> index c4f4e1616a85..a2042a512538 100644
> --- a/criu/files-reg.c
> +++ b/criu/files-reg.c
> @@ -1777,11 +1777,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;
> diff --git a/criu/files.c b/criu/files.c
> index b12258ad2654..d96358b558b4 100644
> --- a/criu/files.c
> +++ b/criu/files.c
> @@ -392,7 +392,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;
> diff --git a/criu/pie/parasite.c b/criu/pie/parasite.c
> index c32e31384fd8..f9e954484615 100644
> --- a/criu/pie/parasite.c
> +++ b/criu/pie/parasite.c
> @@ -325,6 +325,19 @@ static int fill_fds_opts(struct parasite_drain_fd *fds, struct fd_opts *opts)
>  

                if (flags < 0) {
                        pr_err("fcntl(%d, F_GETFD) -> %d\n", fd, flags);
                        return -1;
                }


>  		p->flags = (char)flags;
>  
> +		/*
> +		 * For O_PATH opened files there is no owner at all.
> +		 */
> +		if (flags < 0) {
> +			pr_err("fcntl(%d, F_GETFL) -> %d\n", fd, flags);
> +			return -1;
> +		}


We already have the same code

> +		flags = sys_fcntl(fd, F_GETFL, 0);
> +		if (flags & O_PATH) {
> +			p->fown.pid = 0;
> +			continue;
> +		}
> +
>  		ret = sys_fcntl(fd, F_GETOWN_EX, (long)&owner_ex);
>  		if (ret) {
>  			pr_err("fcntl(%d, F_GETOWN_EX) -> %d\n", fd, ret);
> -- 
> 2.17.2
>