Commit ff967070 authored by Pavel Emelyanov's avatar Pavel Emelyanov Committed by Andrei Vagin

vma: Move non-root map_files handling into subroutine

Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 7b2870f5
...@@ -208,6 +208,94 @@ static int vma_get_mapfile_flags(struct vma_area *vma, DIR *mfd, char *path) ...@@ -208,6 +208,94 @@ static int vma_get_mapfile_flags(struct vma_area *vma, DIR *mfd, char *path)
return 0; 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, static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd,
struct vma_file_info *vfi, struct vma_file_info *vfi,
struct vma_file_info *prev_vfi, struct vma_file_info *prev_vfi,
...@@ -296,90 +384,8 @@ static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd, ...@@ -296,90 +384,8 @@ static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd,
return -1; return -1;
} }
if (errno == EPERM && !opts.aufs) { if (errno == EPERM && !opts.aufs)
int fd; return vma_get_mapfile_user(fname, vma, vfi, vm_file_fd, path);
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;
}
pr_perror("Can't open map_files"); pr_perror("Can't open map_files");
return -1; return -1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment