Skip to content

Commit

Permalink
mm updates
Browse files Browse the repository at this point in the history
  • Loading branch information
robcore committed Nov 29, 2016
1 parent 9b0a25c commit 47d3721
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 70 deletions.
6 changes: 3 additions & 3 deletions fs/aio.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@ static int aio_setup_ring(struct kioctx *ctx)
info->mmap_size = nr_pages * PAGE_SIZE;
dprintk("attempting mmap of %lu bytes\n", info->mmap_size);
down_write(&ctx->mm->mmap_sem);
info->mmap_base = do_mmap(NULL, 0, info->mmap_size,
PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE,
0);
info->mmap_base = do_mmap_pgoff(NULL, 0, info->mmap_size,
PROT_READ|PROT_WRITE,
MAP_ANONYMOUS|MAP_PRIVATE, 0);
if (IS_ERR((void *)info->mmap_base)) {
up_write(&ctx->mm->mmap_sem);
info->mmap_size = 0;
Expand Down
2 changes: 1 addition & 1 deletion include/linux/mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1504,7 +1504,7 @@ extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned lo
extern unsigned long mmap_region(struct file *file, unsigned long addr,
unsigned long len, unsigned long flags,
vm_flags_t vm_flags, unsigned long pgoff);
extern unsigned long do_mmap(struct file *, unsigned long,
extern unsigned long do_mmap_pgoff(struct file *, unsigned long,
unsigned long, unsigned long,
unsigned long, unsigned long);
extern int do_munmap(struct mm_struct *, unsigned long, size_t);
Expand Down
7 changes: 3 additions & 4 deletions include/linux/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -1756,8 +1756,8 @@ int security_file_permission(struct file *file, int mask);
int security_file_alloc(struct file *file);
void security_file_free(struct file *file);
int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
int security_mmap_file(struct file *file, unsigned long reqprot,
unsigned long prot, unsigned long flags);
int security_mmap_file(struct file *file, unsigned long prot,
unsigned long flags);
int security_mmap_addr(unsigned long addr);
int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
unsigned long prot);
Expand Down Expand Up @@ -2214,8 +2214,7 @@ static inline int security_file_ioctl(struct file *file, unsigned int cmd,
return 0;
}

static inline int security_mmap_file(struct file *file, unsigned long reqprot,
unsigned long prot,
static inline int security_mmap_file(struct file *file, unsigned long prot,
unsigned long flags)
{
return 0;
Expand Down
7 changes: 6 additions & 1 deletion ipc/shm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1039,6 +1039,10 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
sfd->file = shp->shm_file;
sfd->vm_ops = NULL;

err = security_mmap_file(file, prot, flags);
if (err)
goto out_fput;

down_write(&current->mm->mmap_sem);
if (addr && !(shmflg & SHM_REMAP)) {
err = -EINVAL;
Expand All @@ -1053,14 +1057,15 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
goto invalid;
}

user_addr = do_mmap (file, addr, size, prot, flags, 0);
user_addr = do_mmap_pgoff(file, addr, size, prot, flags, 0);
*raddr = user_addr;
err = 0;
if (IS_ERR_VALUE(user_addr))
err = (long)user_addr;
invalid:
up_write(&current->mm->mmap_sem);

out_fput:
fput(file);

out_nattch:
Expand Down
36 changes: 9 additions & 27 deletions mm/mmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -995,14 +995,13 @@ static inline unsigned long round_hint_to_min(unsigned long hint)
* The caller must hold down_write(&current->mm->mmap_sem).
*/

static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flags, unsigned long pgoff)
{
struct mm_struct * mm = current->mm;
struct inode *inode;
vm_flags_t vm_flags;
int error;
unsigned long reqprot = prot;
#ifdef CONFIG_SDCARD_FS
if (file && (file->f_path.mnt->mnt_sb->s_magic == SDCARDFS_SUPER_MAGIC))
Expand Down Expand Up @@ -1129,37 +1128,27 @@ static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
}
}

error = security_mmap_addr(addr);
if (error)
return error;

error = security_mmap_file(file, reqprot, prot, flags);
if (error)
return error;

return mmap_region(file, addr, len, flags, vm_flags, pgoff);
}

unsigned long do_mmap(struct file *file, unsigned long addr,
unsigned long vm_mmap(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flag, unsigned long offset)
{
unsigned long ret;
struct mm_struct *mm = current->mm;

if (unlikely(offset + PAGE_ALIGN(len) < offset))
return -EINVAL;
if (unlikely(offset & ~PAGE_MASK))
return -EINVAL;
return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
}

unsigned long vm_mmap(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flag, unsigned long offset)
{
unsigned long ret;
struct mm_struct *mm = current->mm;

down_write(&mm->mmap_sem);
ret = do_mmap(file, addr, len, prot, flag, offset);
ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
up_write(&mm->mmap_sem);
return ret;
}
Expand Down Expand Up @@ -1672,7 +1661,9 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
if (addr & ~PAGE_MASK)
return -EINVAL;

return arch_rebalance_pgtables(addr, len);
addr = arch_rebalance_pgtables(addr, len);
error = security_mmap_addr(addr);
return error ? error : addr;
}

EXPORT_SYMBOL(get_unmapped_area);
Expand Down Expand Up @@ -2229,7 +2220,6 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)

return 0;
}
EXPORT_SYMBOL(do_munmap);

int vm_munmap(unsigned long start, size_t len)
{
Expand Down Expand Up @@ -2277,10 +2267,6 @@ static unsigned long do_brk(unsigned long addr, unsigned long len)
if (!len)
return addr;

error = security_mmap_addr(addr);
if (error)
return error;

flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;

error = get_unmapped_area(NULL, addr, len, 0, MAP_FIXED);
Expand Down Expand Up @@ -2623,10 +2609,6 @@ int install_special_mapping(struct mm_struct *mm,
vma->vm_ops = &special_mapping_vmops;
vma->vm_private_data = pages;

ret = security_mmap_addr(vma->vm_start);
if (ret)
goto out;

ret = insert_vm_struct(mm, vma);
if (ret)
goto out;
Expand Down
7 changes: 0 additions & 7 deletions mm/mremap.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,10 +372,6 @@ static unsigned long mremap_to(unsigned long addr,
if ((addr <= new_addr) && (addr+old_len) > new_addr)
goto out;

ret = security_mmap_addr(new_addr);
if (ret)
goto out;

ret = do_munmap(mm, new_addr, new_len);
if (ret)
goto out;
Expand Down Expand Up @@ -533,9 +529,6 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
goto out;
}

ret = security_mmap_addr(new_addr);
if (ret)
goto out;
ret = move_vma(vma, addr, old_len, new_len, new_addr);
}
out:
Expand Down
38 changes: 17 additions & 21 deletions mm/nommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,6 @@ static int validate_mmap_request(struct file *file,
unsigned long *_capabilities)
{
unsigned long capabilities, rlen;
unsigned long reqprot = prot;
int ret;

/* do the simple checks first */
Expand Down Expand Up @@ -1049,9 +1048,6 @@ static int validate_mmap_request(struct file *file,

/* allow the security API to have its say */
ret = security_mmap_addr(addr);
if (ret < 0)
return ret;
ret = security_mmap_file(file, reqprot, prot, flags);
if (ret < 0)
return ret;

Expand Down Expand Up @@ -1237,7 +1233,7 @@ static int do_mmap_private(struct vm_area_struct *vma,
/*
* handle mapping creation for uClinux
*/
static unsigned long do_mmap_pgoff(struct file *file,
unsigned long do_mmap_pgoff(struct file *file,
unsigned long addr,
unsigned long len,
unsigned long prot,
Expand Down Expand Up @@ -1473,27 +1469,24 @@ static unsigned long do_mmap_pgoff(struct file *file,
return -ENOMEM;
}

unsigned long do_mmap(struct file *file, unsigned long addr,
unsigned long vm_mmap(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flag, unsigned long offset)
{
unsigned long ret;
struct mm_struct *mm = current->mm;

if (unlikely(offset + PAGE_ALIGN(len) < offset))
return -EINVAL;
if (unlikely(offset & ~PAGE_MASK))
return -EINVAL;
return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
}

unsigned long vm_mmap(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flag, unsigned long offset)
{
unsigned long ret;
struct mm_struct *mm = current->mm;

down_write(&mm->mmap_sem);
ret = do_mmap(file, addr, len, prot, flag, offset);
up_write(&mm->mmap_sem);
ret = security_mmap_file(file, prot, flag);
if (!ret) {
down_write(&mm->mmap_sem);
ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
up_write(&mm->mmap_sem);
}
return ret;
}
EXPORT_SYMBOL(vm_mmap);
Expand All @@ -1514,9 +1507,12 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,

flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);

down_write(&current->mm->mmap_sem);
retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
up_write(&current->mm->mmap_sem);
ret = security_mmap_file(file, prot, flags);
if (!ret) {
down_write(&current->mm->mmap_sem);
retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
up_write(&current->mm->mmap_sem);
}

if (file)
fput(file);
Expand Down
2 changes: 0 additions & 2 deletions net/sched/sch_atm.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
#include <net/netlink.h>
#include <net/pkt_sched.h>

extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */

/*
* The ATM queuing discipline provides a framework for invoking classifiers
* (aka "filters"), which in turn select classes of this queuing discipline.
Expand Down
45 changes: 41 additions & 4 deletions security/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
#include <linux/ima.h>
#include <linux/evm.h>
#include <linux/fsnotify.h>
#include <linux/mman.h>
#include <linux/mount.h>
#include <linux/personality.h>
#include <net/flow.h>

#define MAX_LSM_EVM_XATTR 2
Expand Down Expand Up @@ -681,12 +684,46 @@ int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return security_ops->file_ioctl(file, cmd, arg);
}

int security_mmap_file(struct file *file, unsigned long reqprot,
unsigned long prot, unsigned long flags)
static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
{
int ret;
/*
* Does we have PROT_READ and does the application expect
* it to imply PROT_EXEC? If not, nothing to talk about...
*/
if ((prot & (PROT_READ | PROT_EXEC)) != PROT_READ)
return prot;
if (!(current->personality & READ_IMPLIES_EXEC))
return prot;
/*
* if that's an anonymous mapping, let it.
*/
if (!file)
return prot | PROT_EXEC;
/*
* ditto if it's not on noexec mount, except that on !MMU we need
* BDI_CAP_EXEC_MMAP (== VM_MAYEXEC) in this case
*/
if (!(file->f_path.mnt->mnt_flags & MNT_NOEXEC)) {
#ifndef CONFIG_MMU
unsigned long caps = 0;
struct address_space *mapping = file->f_mapping;
if (mapping && mapping->backing_dev_info)
caps = mapping->backing_dev_info->capabilities;
if (!(caps & BDI_CAP_EXEC_MAP))
return prot;
#endif
return prot | PROT_EXEC;
}
/* anything on noexec mount won't get PROT_EXEC */
return prot;
}

ret = security_ops->mmap_file(file, reqprot, prot, flags);
int security_mmap_file(struct file *file, unsigned long prot,
unsigned long flags)
{
int ret;
ret = security_ops->mmap_file(file, prot,
mmap_prot(file, prot), flags);
if (ret)
return ret;
return ima_file_mmap(file, prot);
Expand Down

0 comments on commit 47d3721

Please sign in to comment.