The arguments are the same as munmap() except that the start of the mapping is specified as an offset into the mshare region instead of as an address. Signed-off-by: Anthony Yznaga --- include/uapi/linux/msharefs.h | 7 +++++++ mm/mshare.c | 37 +++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/include/uapi/linux/msharefs.h b/include/uapi/linux/msharefs.h index ad129beeef62..fb0235d1e384 100644 --- a/include/uapi/linux/msharefs.h +++ b/include/uapi/linux/msharefs.h @@ -19,6 +19,7 @@ * msharefs specific ioctl commands */ #define MSHAREFS_CREATE_MAPPING _IOW('x', 0, struct mshare_create) +#define MSHAREFS_UNMAP _IOW('x', 1, struct mshare_unmap) struct mshare_create { __u64 region_offset; @@ -28,4 +29,10 @@ struct mshare_create { __u32 flags; __u32 fd; }; + +struct mshare_unmap { + __u64 region_offset; + __u64 size; +}; + #endif diff --git a/mm/mshare.c b/mm/mshare.c index ebec51e655e4..b1e02f5e1f60 100644 --- a/mm/mshare.c +++ b/mm/mshare.c @@ -394,11 +394,41 @@ msharefs_create_mapping(struct mshare_data *m_data, struct mshare_create *mcreat return error; } +static long +msharefs_unmap(struct mshare_data *m_data, struct mshare_unmap *munmap) +{ + struct mm_struct *host_mm = m_data->mm; + unsigned long mshare_start, mshare_end, mshare_size; + unsigned long region_offset = munmap->region_offset; + unsigned long size = munmap->size; + unsigned long addr; + int error; + + mshare_start = m_data->start; + mshare_size = m_data->size; + mshare_end = mshare_start + mshare_size; + addr = mshare_start + region_offset; + + if ((size > mshare_size) || (region_offset >= mshare_size) || + (addr + size > mshare_end)) + return -EINVAL; + + if (mmap_write_lock_killable(host_mm)) + return -EINTR; + + error = do_munmap(host_mm, addr, size, NULL); + + mmap_write_unlock(host_mm); + + return error; +} + static long msharefs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct mshare_data *m_data = filp->private_data; struct mshare_create mcreate; + struct mshare_unmap munmap; if (!mshare_is_initialized(m_data)) return -EINVAL; @@ -411,6 +441,13 @@ msharefs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return msharefs_create_mapping(m_data, &mcreate); + case MSHAREFS_UNMAP: + if (copy_from_user(&munmap, (struct mshare_unmap __user *)arg, + sizeof(munmap))) + return -EFAULT; + + return msharefs_unmap(m_data, &munmap); + default: return -ENOTTY; } -- 2.47.1