split ->file_mmap() into ->mmap_addr()/->mmap_file()
Al Viro [Wed, 30 May 2012 17:30:51 +0000 (13:30 -0400)]
... i.e. file-dependent and address-dependent checks.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

fs/exec.c
include/linux/security.h
mm/mmap.c
mm/mremap.c
mm/nommu.c
security/apparmor/lsm.c
security/capability.c
security/commoncap.c
security/security.c
security/selinux/hooks.c
security/smack/smack_lsm.c

index 52c9e2f..a79786a 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -280,10 +280,6 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
        vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
        INIT_LIST_HEAD(&vma->anon_vma_chain);
 
-       err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1);
-       if (err)
-               goto err;
-
        err = insert_vm_struct(mm, vma);
        if (err)
                goto err;
index 4ad59c9..f1bae09 100644 (file)
@@ -87,9 +87,8 @@ extern int cap_inode_removexattr(struct dentry *dentry, const char *name);
 extern int cap_inode_need_killpriv(struct dentry *dentry);
 extern int cap_inode_killpriv(struct dentry *dentry);
 extern int cap_mmap_addr(unsigned long addr);
-extern int cap_file_mmap(struct file *file, unsigned long reqprot,
-                        unsigned long prot, unsigned long flags,
-                        unsigned long addr, unsigned long addr_only);
+extern int cap_mmap_file(struct file *file, unsigned long reqprot,
+                        unsigned long prot, unsigned long flags);
 extern int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags);
 extern int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
                          unsigned long arg4, unsigned long arg5);
@@ -587,15 +586,17 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *     simple integer value.  When @arg represents a user space pointer, it
  *     should never be used by the security module.
  *     Return 0 if permission is granted.
- * @file_mmap :
+ * @mmap_addr :
+ *     Check permissions for a mmap operation at @addr.
+ *     @addr contains virtual address that will be used for the operation.
+ *     Return 0 if permission is granted.
+ * @mmap_file :
  *     Check permissions for a mmap operation.  The @file may be NULL, e.g.
  *     if mapping anonymous memory.
  *     @file contains the file structure for file to map (may be NULL).
  *     @reqprot contains the protection requested by the application.
  *     @prot contains the protection that will be applied by the kernel.
  *     @flags contains the operational flags.
- *     @addr contains virtual address that will be used for the operation.
- *     @addr_only contains a boolean: 0 if file-backed VMA, otherwise 1.
  *     Return 0 if permission is granted.
  * @file_mprotect:
  *     Check permissions before changing memory access permissions.
@@ -1482,10 +1483,10 @@ struct security_operations {
        void (*file_free_security) (struct file *file);
        int (*file_ioctl) (struct file *file, unsigned int cmd,
                           unsigned long arg);
-       int (*file_mmap) (struct file *file,
+       int (*mmap_addr) (unsigned long addr);
+       int (*mmap_file) (struct file *file,
                          unsigned long reqprot, unsigned long prot,
-                         unsigned long flags, unsigned long addr,
-                         unsigned long addr_only);
+                         unsigned long flags);
        int (*file_mprotect) (struct vm_area_struct *vma,
                              unsigned long reqprot,
                              unsigned long prot);
@@ -1744,9 +1745,9 @@ 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_file_mmap(struct file *file, unsigned long reqprot,
-                       unsigned long prot, unsigned long flags,
-                       unsigned long addr, unsigned long addr_only);
+int security_mmap_file(struct file *file, unsigned long reqprot,
+                       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);
 int security_file_lock(struct file *file, unsigned int cmd);
@@ -2182,11 +2183,14 @@ static inline int security_file_ioctl(struct file *file, unsigned int cmd,
        return 0;
 }
 
-static inline int security_file_mmap(struct file *file, unsigned long reqprot,
+static inline int security_mmap_file(struct file *file, unsigned long reqprot,
                                     unsigned long prot,
-                                    unsigned long flags,
-                                    unsigned long addr,
-                                    unsigned long addr_only)
+                                    unsigned long flags)
+{
+       return 0;
+}
+
+static inline int security_mmap_addr(unsigned long addr)
 {
        return cap_mmap_addr(addr);
 }
index 83c5662..49283da 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1101,7 +1101,11 @@ static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
                }
        }
 
-       error = security_file_mmap(file, reqprot, prot, flags, addr, 0);
+       error = security_mmap_addr(addr);
+       if (error)
+               return error;
+
+       error = security_mmap_file(file, reqprot, prot, flags);
        if (error)
                return error;
 
@@ -1817,7 +1821,7 @@ int expand_downwards(struct vm_area_struct *vma,
                return -ENOMEM;
 
        address &= PAGE_MASK;
-       error = security_file_mmap(NULL, 0, 0, 0, address, 1);
+       error = security_mmap_addr(address);
        if (error)
                return error;
 
@@ -2205,7 +2209,7 @@ static unsigned long do_brk(unsigned long addr, unsigned long len)
        if (!len)
                return addr;
 
-       error = security_file_mmap(NULL, 0, 0, 0, addr, 1);
+       error = security_mmap_addr(addr);
        if (error)
                return error;
 
@@ -2561,7 +2565,7 @@ int install_special_mapping(struct mm_struct *mm,
        vma->vm_ops = &special_mapping_vmops;
        vma->vm_private_data = pages;
 
-       ret = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1);
+       ret = security_mmap_addr(vma->vm_start);
        if (ret)
                goto out;
 
index 169c53b..ebf1089 100644 (file)
@@ -371,7 +371,7 @@ static unsigned long mremap_to(unsigned long addr,
        if ((addr <= new_addr) && (addr+old_len) > new_addr)
                goto out;
 
-       ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1);
+       ret = security_mmap_addr(new_addr);
        if (ret)
                goto out;
 
@@ -532,7 +532,7 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
                        goto out;
                }
 
-               ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1);
+               ret = security_mmap_addr(new_addr);
                if (ret)
                        goto out;
                ret = move_vma(vma, addr, old_len, new_len, new_addr);
index de6084e..acfe419 100644 (file)
@@ -1047,7 +1047,10 @@ static int validate_mmap_request(struct file *file,
        }
 
        /* allow the security API to have its say */
-       ret = security_file_mmap(file, reqprot, prot, flags, addr, 0);
+       ret = security_mmap_addr(addr);
+       if (ret < 0)
+               return ret;
+       ret = security_mmap_file(file, reqprot, prot, flags);
        if (ret < 0)
                return ret;
 
index 8430d89..8ea39aa 100644 (file)
@@ -490,17 +490,9 @@ static int common_mmap(int op, struct file *file, unsigned long prot,
        return common_file_perm(op, file, mask);
 }
 
-static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
-                             unsigned long prot, unsigned long flags,
-                             unsigned long addr, unsigned long addr_only)
+static int apparmor_mmap_file(struct file *file, unsigned long reqprot,
+                             unsigned long prot, unsigned long flags)
 {
-       int rc = 0;
-
-       /* do DAC check */
-       rc = cap_mmap_addr(addr);
-       if (rc || addr_only)
-               return rc;
-
        return common_mmap(OP_FMMAP, file, prot, flags);
 }
 
@@ -646,7 +638,8 @@ static struct security_operations apparmor_ops = {
        .file_permission =              apparmor_file_permission,
        .file_alloc_security =          apparmor_file_alloc_security,
        .file_free_security =           apparmor_file_free_security,
-       .file_mmap =                    apparmor_file_mmap,
+       .mmap_file =                    apparmor_mmap_file,
+       .mmap_addr =                    cap_mmap_addr,
        .file_mprotect =                apparmor_file_mprotect,
        .file_lock =                    apparmor_file_lock,
 
index fca8896..61095df 100644 (file)
@@ -949,7 +949,8 @@ void __init security_fixup_ops(struct security_operations *ops)
        set_to_cap_if_null(ops, file_alloc_security);
        set_to_cap_if_null(ops, file_free_security);
        set_to_cap_if_null(ops, file_ioctl);
-       set_to_cap_if_null(ops, file_mmap);
+       set_to_cap_if_null(ops, mmap_addr);
+       set_to_cap_if_null(ops, mmap_file);
        set_to_cap_if_null(ops, file_mprotect);
        set_to_cap_if_null(ops, file_lock);
        set_to_cap_if_null(ops, file_fcntl);
index ebac361..6dbae46 100644 (file)
@@ -980,23 +980,8 @@ int cap_mmap_addr(unsigned long addr)
        return ret;
 }
 
-/*
- * cap_file_mmap - check if able to map given addr
- * @file: unused
- * @reqprot: unused
- * @prot: unused
- * @flags: unused
- * @addr: address attempting to be mapped
- * @addr_only: unused
- *
- * If the process is attempting to map memory below dac_mmap_min_addr they need
- * CAP_SYS_RAWIO.  The other parameters to this function are unused by the
- * capability security module.  Returns 0 if this mapping should be allowed
- * -EPERM if not.
- */
-int cap_file_mmap(struct file *file, unsigned long reqprot,
-                 unsigned long prot, unsigned long flags,
-                 unsigned long addr, unsigned long addr_only)
+int cap_mmap_file(struct file *file, unsigned long reqprot,
+                 unsigned long prot, unsigned long flags)
 {
-       return cap_mmap_addr(addr);
+       return 0;
 }
index 5497a57..d91c66d 100644 (file)
@@ -657,18 +657,22 @@ int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        return security_ops->file_ioctl(file, cmd, arg);
 }
 
-int security_file_mmap(struct file *file, unsigned long reqprot,
-                       unsigned long prot, unsigned long flags,
-                       unsigned long addr, unsigned long addr_only)
+int security_mmap_file(struct file *file, unsigned long reqprot,
+                       unsigned long prot, unsigned long flags)
 {
        int ret;
 
-       ret = security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only);
+       ret = security_ops->mmap_file(file, reqprot, prot, flags);
        if (ret)
                return ret;
        return ima_file_mmap(file, prot);
 }
 
+int security_mmap_addr(unsigned long addr)
+{
+       return security_ops->mmap_addr(addr);
+}
+
 int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
                            unsigned long prot)
 {
index 25c125e..372ec65 100644 (file)
@@ -3083,9 +3083,7 @@ error:
        return rc;
 }
 
-static int selinux_file_mmap(struct file *file, unsigned long reqprot,
-                            unsigned long prot, unsigned long flags,
-                            unsigned long addr, unsigned long addr_only)
+static int selinux_mmap_addr(unsigned long addr)
 {
        int rc = 0;
        u32 sid = current_sid();
@@ -3104,10 +3102,12 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot,
        }
 
        /* do DAC check on address space usage */
-       rc = cap_mmap_addr(addr);
-       if (rc || addr_only)
-               return rc;
+       return cap_mmap_addr(addr);
+}
 
+static int selinux_mmap_file(struct file *file, unsigned long reqprot,
+                            unsigned long prot, unsigned long flags)
+{
        if (selinux_checkreqprot)
                prot = reqprot;
 
@@ -5570,7 +5570,8 @@ static struct security_operations selinux_ops = {
        .file_alloc_security =          selinux_file_alloc_security,
        .file_free_security =           selinux_file_free_security,
        .file_ioctl =                   selinux_file_ioctl,
-       .file_mmap =                    selinux_file_mmap,
+       .mmap_file =                    selinux_mmap_file,
+       .mmap_addr =                    selinux_mmap_addr,
        .file_mprotect =                selinux_file_mprotect,
        .file_lock =                    selinux_file_lock,
        .file_fcntl =                   selinux_file_fcntl,
index a621977..ee0bb57 100644 (file)
@@ -1171,7 +1171,7 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
 }
 
 /**
- * smack_file_mmap :
+ * smack_mmap_file :
  * Check permissions for a mmap operation.  The @file may be NULL, e.g.
  * if mapping anonymous memory.
  * @file contains the file structure for file to map (may be NULL).
@@ -1180,10 +1180,9 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
  * @flags contains the operational flags.
  * Return 0 if permission is granted.
  */
-static int smack_file_mmap(struct file *file,
+static int smack_mmap_file(struct file *file,
                           unsigned long reqprot, unsigned long prot,
-                          unsigned long flags, unsigned long addr,
-                          unsigned long addr_only)
+                          unsigned long flags)
 {
        struct smack_known *skp;
        struct smack_rule *srp;
@@ -1198,11 +1197,6 @@ static int smack_file_mmap(struct file *file,
        int tmay;
        int rc;
 
-       /* do DAC check on address space usage */
-       rc = cap_mmap_addr(addr);
-       if (rc || addr_only)
-               return rc;
-
        if (file == NULL || file->f_dentry == NULL)
                return 0;
 
@@ -3482,7 +3476,8 @@ struct security_operations smack_ops = {
        .file_ioctl =                   smack_file_ioctl,
        .file_lock =                    smack_file_lock,
        .file_fcntl =                   smack_file_fcntl,
-       .file_mmap =                    smack_file_mmap,
+       .mmap_file =                    smack_mmap_file,
+       .mmap_addr =                    cap_mmap_addr,
        .file_set_fowner =              smack_file_set_fowner,
        .file_send_sigiotask =          smack_file_send_sigiotask,
        .file_receive =                 smack_file_receive,