From: Mimi Zohar <zohar@linux.vnet.ibm.com>
To: selinux@tycho.nsa.gov
Cc: zohar@us.ibm.com, safford@watson.ibm.com, sailer@us.ibm.com
Subject: [RFC] [Patch 4/4] integrity: SELinux LIM calls
Date: Fri, 21 Sep 2007 10:05:22 -0400 [thread overview]
Message-ID: <1190383522.11091.31.camel@localhost.localdomain> (raw)
[RFC]integrity: SELinux patch
This patch verifies and measures file integrity, by adding
the new Linux Integrity Modules(LIM) API calls to SElinux.
This patch defines a new 'integrity' class with the permission
'measure'. Measurement calls are made in selinux_file_mmap(),
selinux_bprm_check_security, and selinux_inode_permission(),
based on policy. (Additional calls might be required.)
Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
---
Index: linux-2.6.23-rc6-mm1/security/selinux/hooks.c
===================================================================
--- linux-2.6.23-rc6-mm1.orig/security/selinux/hooks.c
+++ linux-2.6.23-rc6-mm1/security/selinux/hooks.c
@@ -69,6 +69,7 @@
#include <linux/audit.h>
#include <linux/string.h>
#include <linux/selinux.h>
+#include <linux/integrity.h>
#include <linux/mutex.h>
#include "avc.h"
@@ -844,6 +845,7 @@ static int inode_doinit_with_dentry(stru
char *context = NULL;
unsigned len = 0;
int rc = 0;
+ int status;
if (isec->initialized)
goto out;
@@ -888,34 +890,12 @@ static int inode_doinit_with_dentry(stru
}
len = INITCONTEXTLEN;
- context = kmalloc(len, GFP_KERNEL);
- if (!context) {
- rc = -ENOMEM;
+ rc = integrity_verify_metadata(dentry, XATTR_NAME_SELINUX,
+ &context, &len, &status);
+ if (rc == -ENOMEM) {
dput(dentry);
goto out_unlock;
}
- rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
- context, len);
- if (rc == -ERANGE) {
- /* Need a larger buffer. Query for the right size. */
- rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
- NULL, 0);
- if (rc < 0) {
- dput(dentry);
- goto out_unlock;
- }
- kfree(context);
- len = rc;
- context = kmalloc(len, GFP_KERNEL);
- if (!context) {
- rc = -ENOMEM;
- dput(dentry);
- goto out_unlock;
- }
- rc = inode->i_op->getxattr(dentry,
- XATTR_NAME_SELINUX,
- context, len);
- }
dput(dentry);
if (rc < 0) {
if (rc != -ENODATA) {
@@ -929,6 +909,14 @@ static int inode_doinit_with_dentry(stru
sid = sbsec->def_sid;
rc = 0;
} else {
+ if (status == INTEGRITY_FAIL) {
+ printk(KERN_WARNING "%s: verify_metadata "
+ "failed for dev=%s ino=%ld\n",
+ __FUNCTION__,
+ inode->i_sb->s_id, inode->i_ino);
+ kfree(context);
+ goto out_unlock;
+ }
rc = security_context_to_sid_default(context, rc, &sid,
sbsec->def_sid);
if (rc) {
@@ -1698,9 +1686,87 @@ static int selinux_bprm_set_security(str
return 0;
}
-static int selinux_bprm_check_security (struct linux_binprm *bprm)
+static int selinux_verify_metadata(struct dentry *dentry)
{
- return secondary_ops->bprm_check_security(bprm);
+ int rc, status;
+
+ if (!dentry)
+ return 0;
+
+ rc = integrity_verify_metadata(dentry, NULL, NULL, NULL, &status);
+ if (rc == -EOPNOTSUPP)
+ return 0;
+ if (rc < 0)
+ goto out;
+
+ if (status != INTEGRITY_PASS) /* FAIL | NO_LABEL */
+ rc = -EACCES;
+out:
+ return rc;
+}
+
+static int selinux_verify_data(struct dentry *dentry, struct file *file)
+{
+ int rc, status;
+
+ if (!dentry && !file)
+ return 0;
+
+ rc = integrity_verify_data(dentry, file, &status);
+ if (rc < 0)
+ return 0;
+
+ if (status != INTEGRITY_PASS)
+ rc = -EACCES;
+
+ return rc;
+}
+
+/*
+ * Measure based on new 'integrity' class policy
+ */
+static void selinux_measure(struct inode *inode, struct dentry *dentry,
+ struct file *file, char *filename,
+ int mask)
+{
+ int rc = 1;
+ struct inode_security_struct *isec = inode->i_security;
+ struct task_security_struct *tsec = current->security;
+ struct av_decision avd;
+
+ if (!S_ISREG(inode->i_mode))
+ return;
+
+ rc = avc_has_perm_noaudit(tsec->sid, isec->sid, SECCLASS_INTEGRITY,
+ INTEGRITY__MEASURE, AVC_STRICT, &avd);
+ if (rc == 0)
+ integrity_measure(inode, dentry, file, filename, mask);
+ return;
+}
+
+/* The OS protects against an executable file, already open for write,
+ * from being executed in deny_write_access() and an executable file
+ * already open for execute, from being modified in get_write_access().
+ * So we can be certain that what we verify and measure here is actually
+ * what is being executed.
+ */
+static int selinux_bprm_check_security(struct linux_binprm *bprm)
+{
+ struct dentry *dentry = bprm->file->f_dentry;
+ int rc;
+
+ rc = secondary_ops->bprm_check_security(bprm);
+ if (rc != 0)
+ return rc;
+
+ rc = selinux_verify_metadata(dentry);
+ if (rc == 0) {
+ rc = selinux_verify_data(dentry, bprm->file);
+ if (rc == 0)
+ selinux_measure(dentry->d_inode, dentry, bprm->file,
+ bprm->filename, MAY_EXEC);
+ }
+ return rc;
}
@@ -2252,6 +2318,30 @@ static int selinux_inode_follow_link(str
return dentry_has_perm(current, NULL, dentry, FILE__READ);
}
+static char *get_fname(struct dentry *dentry, struct vfsmount *mnt,
+ char **buf)
+{
+ char *fname = NULL;
+ char *path = NULL;
+
+ path = (char *)__get_free_page(GFP_KERNEL);
+ if (path) {
+ fname = d_path(dentry, mnt, path, PAGE_SIZE);
+ *buf = path;
+ }
+
+ if (!fname) /* no choice, use short name */
+ fname = (!dentry->d_name.name) ?
+ (char *)dentry->d_iname : (char *)dentry->d_name.name;
+ return fname;
+}
+
+static void free_fname(char *path)
+{
+ if (path)
+ free_page((unsigned long)path);
+}
+
static int selinux_inode_permission(struct inode *inode, int mask,
struct nameidata *nd)
{
@@ -2266,8 +2356,29 @@ static int selinux_inode_permission(stru
return 0;
}
- return inode_has_perm(current, inode,
+ rc = inode_has_perm(current, inode,
file_mask_to_av(inode->i_mode, mask), NULL);
+ if (rc != 0)
+ return rc;
+
+ if (mask & ~MAY_EXEC) { /* measure executables later */
+ struct dentry *dentry = NULL;
+ char *path = NULL;
+ char *fname = NULL;
+
+ /* The file name is not required, but only a hint.
+ * When possible, supply a fully qualified path name.
+ */
+ if (nd) {
+ dentry = nd->dentry;
+ fname = get_fname(nd->dentry, nd->mnt, &path);
+ }
+
+ selinux_measure(inode, dentry, NULL, fname, mask);
+ if (path)
+ free_fname(path);
+ }
+ return rc;
}
static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
@@ -2588,8 +2699,18 @@ static int selinux_file_mmap(struct file
if (selinux_checkreqprot)
prot = reqprot;
- return file_map_prot_check(file, prot,
- (flags & MAP_TYPE) == MAP_SHARED);
+ rc = file_map_prot_check(file, prot, (flags & MAP_TYPE) == MAP_SHARED);
+ if (file && file->f_dentry && rc == 0) {
+ rc = selinux_verify_metadata(file->f_dentry);
+ if (rc == 0) {
+ rc = selinux_verify_data(NULL, file);
+ if (rc == 0)
+ selinux_measure(file->f_dentry->d_inode,
+ file->f_dentry, file,
+ NULL, MAY_EXEC);
+ }
+ }
+ return rc;
}
static int selinux_file_mprotect(struct vm_area_struct *vma,
@@ -2631,7 +2752,6 @@ static int selinux_file_mprotect(struct
return rc;
}
#endif
-
return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
}
Index: linux-2.6.23-rc6-mm1/security/selinux/include/av_permissions.h
===================================================================
--- linux-2.6.23-rc6-mm1.orig/security/selinux/include/av_permissions.h
+++ linux-2.6.23-rc6-mm1/security/selinux/include/av_permissions.h
@@ -824,3 +824,4 @@
#define DCCP_SOCKET__NODE_BIND 0x00400000UL
#define DCCP_SOCKET__NAME_CONNECT 0x00800000UL
#define MEMPROTECT__MMAP_ZERO 0x00000001UL
+#define INTEGRITY__MEASURE 0x00000001UL
Index: linux-2.6.23-rc6-mm1/security/selinux/include/av_perm_to_string.h
===================================================================
--- linux-2.6.23-rc6-mm1.orig/security/selinux/include/av_perm_to_string.h
+++ linux-2.6.23-rc6-mm1/security/selinux/include/av_perm_to_string.h
@@ -159,3 +159,4 @@
S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind")
S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect")
S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero")
+ S_(SECCLASS_INTEGRITY, INTEGRITY__MEASURE, "measure")
Index: linux-2.6.23-rc6-mm1/security/selinux/include/flask.h
===================================================================
--- linux-2.6.23-rc6-mm1.orig/security/selinux/include/flask.h
+++ linux-2.6.23-rc6-mm1/security/selinux/include/flask.h
@@ -50,6 +50,7 @@
#define SECCLASS_KEY 58
#define SECCLASS_DCCP_SOCKET 60
#define SECCLASS_MEMPROTECT 61
+#define SECCLASS_INTEGRITY 62
/*
* Security identifier indices for initial entities
Index: linux-2.6.23-rc6-mm1/security/selinux/include/class_to_string.h
===================================================================
--- linux-2.6.23-rc6-mm1.orig/security/selinux/include/class_to_string.h
+++ linux-2.6.23-rc6-mm1/security/selinux/include/class_to_string.h
@@ -64,3 +64,4 @@
S_(NULL)
S_("dccp_socket")
S_("memprotect")
+ S_("integrity")
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
next reply other threads:[~2007-09-21 13:59 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-21 14:05 Mimi Zohar [this message]
2007-09-21 14:48 ` [RFC] [Patch 4/4] integrity: SELinux LIM calls Stephen Smalley
2007-09-24 19:54 ` Mimi Zohar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1190383522.11091.31.camel@localhost.localdomain \
--to=zohar@linux.vnet.ibm.com \
--cc=safford@watson.ibm.com \
--cc=sailer@us.ibm.com \
--cc=selinux@tycho.nsa.gov \
--cc=zohar@us.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.