[CRIU] [PATCH 2/5] vma: Move non-root map_files handling into subroutine

Pavel Emelyanov xemul at virtuozzo.com
Fri Feb 10 03:33:06 PST 2017


Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
 criu/proc_parse.c | 174 ++++++++++++++++++++++++++++--------------------------
 1 file changed, 90 insertions(+), 84 deletions(-)

diff --git a/criu/proc_parse.c b/criu/proc_parse.c
index b52135e..83c363b 100644
--- a/criu/proc_parse.c
+++ b/criu/proc_parse.c
@@ -208,6 +208,94 @@ static int vma_get_mapfile_flags(struct vma_area *vma, DIR *mfd, char *path)
 	return 0;
 }
 
+static int vma_get_mapfile_user(char *fname, struct vma_area *vma,
+			   struct vma_file_info *vfi, int *vm_file_fd,
+			   const char *path)
+{
+	int fd;
+	dev_t vfi_dev;
+
+	/*
+	 * Kernel prohibits reading map_files for users. The
+	 * best we can do here is fill stat using the information
+	 * from smaps file and ... hope for the better :\
+	 *
+	 * Here we'll miss AIO-s and sockets :(
+	 */
+
+	if (fname[0] == '\0') {
+		/*
+		 * Another bad thing is that kernel first checks
+		 * for permission access to ANY map_files link,
+		 * then checks for its existence. So we have to
+		 * check for file path being empty to "emulate"
+		 * the ENOENT case.
+		 */
+
+		if (vfi->dev_maj != 0 || vfi->dev_min != 0 || vfi->ino != 0) {
+			pr_err("Strange file mapped at %lx [%s]:%d.%d.%ld\n",
+			       (unsigned long)vma->e->start, fname,
+			       vfi->dev_maj, vfi->dev_min, vfi->ino);
+			return -1;
+		}
+
+		return 0;
+	} else if (fname[0] != '/') {
+		/*
+		 * This should be some kind of
+		 * special mapping like [heap], [vdso]
+		 * and such, the caller should take care
+		 * of the @fname and vma status.
+		 */
+		return 0;
+	}
+
+	vfi_dev = makedev(vfi->dev_maj, vfi->dev_min);
+	if (is_anon_shmem_map(vfi_dev)) {
+		if (!(vma->e->flags & MAP_SHARED))
+			return -1;
+
+		vma->e->flags  |= MAP_ANONYMOUS;
+		vma->e->status |= VMA_ANON_SHARED;
+		vma->e->shmid = vfi->ino;
+
+		if (!strncmp(fname, "/SYSV", 5))
+			vma->e->status |= VMA_AREA_SYSVIPC;
+
+		return 0;
+	}
+
+	pr_info("Failed to open map_files/%s, try to go via [%s] path\n", path, fname);
+	fd = open(fname, O_RDONLY);
+	if (fd < 0) {
+		pr_perror("Can't open mapped [%s]", fname);
+		return -1;
+	}
+
+	vma->vmst = xmalloc(sizeof(struct stat));
+	if (!vma->vmst) {
+		close(fd);
+		return -1;
+	}
+
+	if (fstat(fd, vma->vmst) < 0) {
+		pr_perror("Can't stat [%s]", fname);
+		close(fd);
+		return -1;
+	}
+
+	if (vma->vmst->st_dev != vfi_dev ||
+			vma->vmst->st_ino != vfi->ino) {
+		pr_err("Failed to resolve mapping %lx filename\n",
+		       (unsigned long)vma->e->start);
+		close(fd);
+		return -1;
+	}
+
+	*vm_file_fd = fd;
+	return 0;
+}
+
 static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd,
 			   struct vma_file_info *vfi,
 			   struct vma_file_info *prev_vfi,
@@ -296,90 +384,8 @@ static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd,
 			return -1;
 		}
 
-		if (errno == EPERM && !opts.aufs) {
-			int fd;
-			dev_t vfi_dev;
-
-			/*
-			 * Kernel prohibits reading map_files for users. The
-			 * best we can do here is fill stat using the information
-			 * from smaps file and ... hope for the better :\
-			 *
-			 * Here we'll miss AIO-s and sockets :(
-			 */
-
-			if (fname[0] == '\0') {
-				/*
-				 * Another bad thing is that kernel first checks
-				 * for permission access to ANY map_files link,
-				 * then checks for its existence. So we have to
-				 * check for file path being empty to "emulate"
-				 * the ENOENT case.
-				 */
-
-				if (vfi->dev_maj != 0 || vfi->dev_min != 0 || vfi->ino != 0) {
-					pr_err("Strange file mapped at %lx [%s]:%d.%d.%ld\n",
-					       (unsigned long)vma->e->start, fname,
-					       vfi->dev_maj, vfi->dev_min, vfi->ino);
-					return -1;
-				}
-
-				return 0;
-			} else if (fname[0] != '/') {
-				/*
-				 * This should be some kind of
-				 * special mapping like [heap], [vdso]
-				 * and such, the caller should take care
-				 * of the @fname and vma status.
-				 */
-				return 0;
-			}
-
-			vfi_dev = makedev(vfi->dev_maj, vfi->dev_min);
-			if (is_anon_shmem_map(vfi_dev)) {
-				if (!(vma->e->flags & MAP_SHARED))
-					return -1;
-
-				vma->e->flags  |= MAP_ANONYMOUS;
-				vma->e->status |= VMA_ANON_SHARED;
-				vma->e->shmid = vfi->ino;
-
-				if (!strncmp(fname, "/SYSV", 5))
-					vma->e->status |= VMA_AREA_SYSVIPC;
-
-				return 0;
-			}
-
-			pr_info("Failed to open map_files/%s, try to go via [%s] path\n", path, fname);
-			fd = open(fname, O_RDONLY);
-			if (fd < 0) {
-				pr_perror("Can't open mapped [%s]", fname);
-				return -1;
-			}
-
-			vma->vmst = xmalloc(sizeof(struct stat));
-			if (!vma->vmst) {
-				close(fd);
-				return -1;
-			}
-
-			if (fstat(fd, vma->vmst) < 0) {
-				pr_perror("Can't stat [%s]", fname);
-				close(fd);
-				return -1;
-			}
-
-			if (vma->vmst->st_dev != vfi_dev ||
-					vma->vmst->st_ino != vfi->ino) {
-				pr_err("Failed to resolve mapping %lx filename\n",
-				       (unsigned long)vma->e->start);
-				close(fd);
-				return -1;
-			}
-
-			*vm_file_fd = fd;
-			return 0;
-		}
+		if (errno == EPERM && !opts.aufs)
+			return vma_get_mapfile_user(fname, vma, vfi, vm_file_fd, path);
 
 		pr_perror("Can't open map_files");
 		return -1;
-- 
2.5.0



More information about the CRIU mailing list