[PATCH 2/3] security: define security_page_mkwrite

From: Serge E . Hallyn
Date: Tue Aug 08 2006 - 11:25:23 EST


Define a security_page_mkwrite() hook which is called before making
a page writable. This can be used by security modules after revoking
write access to a vma, in order to avoid reacquiring write access,
without having to manually change the file->f_mode.

The intended user of this hook is the SLIM security module, which
needs the ability to revoke write access to an open file when a
process' integrity level is lowered.

Signed-off-by: Serge E. Hallyn <serue@xxxxxxxxxx>
---
include/linux/security.h | 21 +++++++++++++++++++++
mm/memory.c | 11 +++++++++++
security/dummy.c | 7 +++++++
3 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index f753038..5515188 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -410,6 +410,14 @@ #ifdef CONFIG_SECURITY
* the size of the buffer required.
* Returns number of bytes used/required on success.
*
+ * Security hooks for page operations
+ *
+ * @page_mkwrite:
+ * Check for permission to make a page table entry writable.
+ * @vma is the vma to which the page belongs
+ * @p is the struct page wanting to be made writable
+ * Return 0 if permission is granted.
+ *
* Security hooks for file operations
*
* @file_permission:
@@ -1198,6 +1206,7 @@ struct security_operations {
int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags);
int (*inode_listsecurity)(struct inode *inode, char *buffer, size_t buffer_size);

+ int (*page_mkwrite) (struct vm_area_struct *vma, struct page *p);
int (*file_permission) (struct file * file, int mask);
int (*file_alloc_security) (struct file * file);
void (*file_free_security) (struct file * file);
@@ -1738,6 +1747,12 @@ static inline int security_inode_listsec
return security_ops->inode_listsecurity(inode, buffer, buffer_size);
}

+static inline int security_page_mkwrite(struct vm_area_struct *vma,
+ struct page *p)
+{
+ return security_ops->page_mkwrite(vma, p);
+}
+
static inline int security_file_permission (struct file *file, int mask)
{
return security_ops->file_permission (file, mask);
@@ -2405,6 +2420,12 @@ static inline int security_inode_listsec
return 0;
}

+static inline int security_page_mkwrite(struct vm_area_struct *vma,
+ struct page *p)
+{
+ return 0;
+}
+
static inline int security_file_permission (struct file *file, int mask)
{
return 0;
diff --git a/mm/memory.c b/mm/memory.c
index 109e986..c4ed919 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -49,6 +49,7 @@ #include <linux/rmap.h>
#include <linux/module.h>
#include <linux/delayacct.h>
#include <linux/init.h>
+#include <linux/security.h>

#include <asm/pgalloc.h>
#include <asm/uaccess.h>
@@ -1466,6 +1467,12 @@ static int do_wp_page(struct mm_struct *

if (unlikely((vma->vm_flags & (VM_SHARED|VM_WRITE)) ==
(VM_SHARED|VM_WRITE))) {
+ ret = security_page_mkwrite(vma, old_page);
+ if (ret) {
+ page_cache_release(old_page);
+ return VM_FAULT_SIGBUS;
+ }
+
if (vma->vm_ops && vma->vm_ops->page_mkwrite) {
/*
* Notify the address space that the page is about to
@@ -2144,6 +2151,10 @@ retry:
/* if the page will be shareable, see if the backing
* address space wants to know that the page is about
* to become writable */
+ if (security_page_mkwrite(vma, new_page)) {
+ page_cache_release(new_page);
+ return VM_FAULT_SIGBUS;
+ }
if (vma->vm_ops->page_mkwrite &&
vma->vm_ops->page_mkwrite(vma, new_page) < 0
) {
diff --git a/security/dummy.c b/security/dummy.c
index bbbfda7..20e838e 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -397,6 +397,12 @@ static const char *dummy_inode_xattr_get
return NULL;
}

+static inline int dummy_page_mkwrite(struct vm_area_struct *vma,
+ struct page *p)
+{
+ return 0;
+}
+
static int dummy_file_permission (struct file *file, int mask)
{
return 0;
@@ -968,6 +974,7 @@ void security_fixup_ops (struct security
set_to_dummy_if_null(ops, inode_getsecurity);
set_to_dummy_if_null(ops, inode_setsecurity);
set_to_dummy_if_null(ops, inode_listsecurity);
+ set_to_dummy_if_null(ops, page_mkwrite);
set_to_dummy_if_null(ops, file_permission);
set_to_dummy_if_null(ops, file_alloc_security);
set_to_dummy_if_null(ops, file_free_security);
--
1.4.1.1

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/