aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/Makefile4
-rw-r--r--security/capability.c8
-rw-r--r--security/commoncap.c4
-rw-r--r--security/keys/proc.c4
-rw-r--r--security/keys/process_keys.c2
-rw-r--r--security/lsm_audit.c2
-rw-r--r--security/security.c9
-rw-r--r--security/selinux/avc.c205
-rw-r--r--security/selinux/hooks.c174
-rw-r--r--security/selinux/include/av_perm_to_string.h1
-rw-r--r--security/selinux/include/av_permissions.h1
-rw-r--r--security/selinux/include/avc.h55
-rw-r--r--security/selinux/include/netlabel.h4
-rw-r--r--security/selinux/include/xfrm.h8
-rw-r--r--security/selinux/netlabel.c2
-rw-r--r--security/selinux/ss/services.c142
-rw-r--r--security/selinux/xfrm.c4
-rw-r--r--security/smack/smack.h2
-rw-r--r--security/smack/smack_access.c11
-rw-r--r--security/smack/smack_lsm.c10
-rw-r--r--security/tomoyo/common.c30
-rw-r--r--security/tomoyo/common.h2
-rw-r--r--security/tomoyo/domain.c42
-rw-r--r--security/tomoyo/tomoyo.c10
-rw-r--r--security/tomoyo/tomoyo.h3
25 files changed, 355 insertions, 384 deletions
diff --git a/security/Makefile b/security/Makefile
index b56e7f9ecbc2..95ecc06392d7 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -16,9 +16,7 @@ obj-$(CONFIG_SECURITYFS) += inode.o
# Must precede capability.o in order to stack properly.
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
-ifeq ($(CONFIG_AUDIT),y)
-obj-$(CONFIG_SECURITY_SMACK) += lsm_audit.o
-endif
+obj-$(CONFIG_AUDIT) += lsm_audit.o
obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o
obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
diff --git a/security/capability.c b/security/capability.c
index 88f752e8152c..1b943f54b2ea 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -396,6 +396,11 @@ static int cap_kernel_create_files_as(struct cred *new, struct inode *inode)
return 0;
}
+static int cap_kernel_module_request(void)
+{
+ return 0;
+}
+
static int cap_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
{
return 0;
@@ -854,7 +859,7 @@ struct security_operations default_security_ops = {
void security_fixup_ops(struct security_operations *ops)
{
- set_to_cap_if_null(ops, ptrace_may_access);
+ set_to_cap_if_null(ops, ptrace_access_check);
set_to_cap_if_null(ops, ptrace_traceme);
set_to_cap_if_null(ops, capget);
set_to_cap_if_null(ops, capset);
@@ -945,6 +950,7 @@ void security_fixup_ops(struct security_operations *ops)
set_to_cap_if_null(ops, cred_commit);
set_to_cap_if_null(ops, kernel_act_as);
set_to_cap_if_null(ops, kernel_create_files_as);
+ set_to_cap_if_null(ops, kernel_module_request);
set_to_cap_if_null(ops, task_setuid);
set_to_cap_if_null(ops, task_fix_setuid);
set_to_cap_if_null(ops, task_setgid);
diff --git a/security/commoncap.c b/security/commoncap.c
index e3097c0a1311..fe30751a6cd9 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -101,7 +101,7 @@ int cap_settime(struct timespec *ts, struct timezone *tz)
}
/**
- * cap_ptrace_may_access - Determine whether the current process may access
+ * cap_ptrace_access_check - Determine whether the current process may access
* another
* @child: The process to be accessed
* @mode: The mode of attachment.
@@ -109,7 +109,7 @@ int cap_settime(struct timespec *ts, struct timezone *tz)
* Determine whether a process may access another, returning 0 if permission
* granted, -ve if denied.
*/
-int cap_ptrace_may_access(struct task_struct *child, unsigned int mode)
+int cap_ptrace_access_check(struct task_struct *child, unsigned int mode)
{
int ret = 0;
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 769f9bdfd2b3..39793c774f33 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -120,6 +120,7 @@ static int proc_keys_open(struct inode *inode, struct file *file)
}
static void *proc_keys_start(struct seq_file *p, loff_t *_pos)
+ __acquires(key_serial_lock)
{
struct rb_node *_p;
loff_t pos = *_pos;
@@ -144,6 +145,7 @@ static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos)
}
static void proc_keys_stop(struct seq_file *p, void *v)
+ __releases(key_serial_lock)
{
spin_unlock(&key_serial_lock);
}
@@ -257,6 +259,7 @@ static int proc_key_users_open(struct inode *inode, struct file *file)
}
static void *proc_key_users_start(struct seq_file *p, loff_t *_pos)
+ __acquires(key_user_lock)
{
struct rb_node *_p;
loff_t pos = *_pos;
@@ -281,6 +284,7 @@ static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos)
}
static void proc_key_users_stop(struct seq_file *p, void *v)
+ __releases(key_user_lock)
{
spin_unlock(&key_user_lock);
}
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 276d27882ce8..ed929af466d3 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -702,7 +702,7 @@ long join_session_keyring(const char *name)
/* only permit this if there's a single thread in the thread group -
* this avoids us having to adjust the creds on all threads and risking
* ENOMEM */
- if (!is_single_threaded(current))
+ if (!current_is_single_threaded())
return -EMLINK;
new = prepare_creds();
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 94b868494b31..500aad0ebd6a 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -220,6 +220,8 @@ static void dump_common_audit_data(struct audit_buffer *ab,
}
switch (a->type) {
+ case LSM_AUDIT_NO_AUDIT:
+ return;
case LSM_AUDIT_DATA_IPC:
audit_log_format(ab, " key=%d ", a->u.ipc_id);
break;
diff --git a/security/security.c b/security/security.c
index dc7674fbfc7a..0e993f42ce3d 100644
--- a/security/security.c
+++ b/security/security.c
@@ -124,9 +124,9 @@ int register_security(struct security_operations *ops)
/* Security operations */
-int security_ptrace_may_access(struct task_struct *child, unsigned int mode)
+int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
{
- return security_ops->ptrace_may_access(child, mode);
+ return security_ops->ptrace_access_check(child, mode);
}
int security_ptrace_traceme(struct task_struct *parent)
@@ -709,6 +709,11 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode)
return security_ops->kernel_create_files_as(new, inode);
}
+int security_kernel_module_request(void)
+{
+ return security_ops->kernel_module_request();
+}
+
int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
{
return security_ops->task_setuid(id0, id1, id2, flags);
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index b2ab60859832..e3d19014259b 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -137,7 +137,7 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
* @tclass: target security class
* @av: access vector
*/
-void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
+static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
{
const char **common_pts = NULL;
u32 common_base = 0;
@@ -492,23 +492,35 @@ out:
return node;
}
-static inline void avc_print_ipv6_addr(struct audit_buffer *ab,
- struct in6_addr *addr, __be16 port,
- char *name1, char *name2)
+/**
+ * avc_audit_pre_callback - SELinux specific information
+ * will be called by generic audit code
+ * @ab: the audit buffer
+ * @a: audit_data
+ */
+static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
{
- if (!ipv6_addr_any(addr))
- audit_log_format(ab, " %s=%pI6", name1, addr);
- if (port)
- audit_log_format(ab, " %s=%d", name2, ntohs(port));
+ struct common_audit_data *ad = a;
+ audit_log_format(ab, "avc: %s ",
+ ad->selinux_audit_data.denied ? "denied" : "granted");
+ avc_dump_av(ab, ad->selinux_audit_data.tclass,
+ ad->selinux_audit_data.audited);
+ audit_log_format(ab, " for ");
}
-static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
- __be16 port, char *name1, char *name2)
+/**
+ * avc_audit_post_callback - SELinux specific information
+ * will be called by generic audit code
+ * @ab: the audit buffer
+ * @a: audit_data
+ */
+static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
{
- if (addr)
- audit_log_format(ab, " %s=%pI4", name1, &addr);
- if (port)
- audit_log_format(ab, " %s=%d", name2, ntohs(port));
+ struct common_audit_data *ad = a;
+ audit_log_format(ab, " ");
+ avc_dump_query(ab, ad->selinux_audit_data.ssid,
+ ad->selinux_audit_data.tsid,
+ ad->selinux_audit_data.tclass);
}
/**
@@ -532,13 +544,10 @@ static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
*/
void avc_audit(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
- struct av_decision *avd, int result, struct avc_audit_data *a)
+ struct av_decision *avd, int result, struct common_audit_data *a)
{
- struct task_struct *tsk = current;
- struct inode *inode = NULL;
+ struct common_audit_data stack_data;
u32 denied, audited;
- struct audit_buffer *ab;
-
denied = requested & ~avd->allowed;
if (denied) {
audited = denied;
@@ -551,144 +560,20 @@ void avc_audit(u32 ssid, u32 tsid,
if (!(audited & avd->auditallow))
return;
}
-
- ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC);
- if (!ab)
- return; /* audit_panic has been called */
- audit_log_format(ab, "avc: %s ", denied ? "denied" : "granted");
- avc_dump_av(ab, tclass, audited);
- audit_log_format(ab, " for ");
- if (a && a->tsk)
- tsk = a->tsk;
- if (tsk && tsk->pid) {
- audit_log_format(ab, " pid=%d comm=", tsk->pid);
- audit_log_untrustedstring(ab, tsk->comm);
+ if (!a) {
+ a = &stack_data;
+ memset(a, 0, sizeof(*a));
+ a->type = LSM_AUDIT_NO_AUDIT;
}
- if (a) {
- switch (a->type) {
- case AVC_AUDIT_DATA_IPC:
- audit_log_format(ab, " key=%d", a->u.ipc_id);
- break;
- case AVC_AUDIT_DATA_CAP:
- audit_log_format(ab, " capability=%d", a->u.cap);
- break;
- case AVC_AUDIT_DATA_FS:
- if (a->u.fs.path.dentry) {
- struct dentry *dentry = a->u.fs.path.dentry;
- if (a->u.fs.path.mnt) {
- audit_log_d_path(ab, "path=",
- &a->u.fs.path);
- } else {
- audit_log_format(ab, " name=");
- audit_log_untrustedstring(ab, dentry->d_name.name);
- }
- inode = dentry->d_inode;
- } else if (a->u.fs.inode) {
- struct dentry *dentry;
- inode = a->u.fs.inode;
- dentry = d_find_alias(inode);
- if (dentry) {
- audit_log_format(ab, " name=");
- audit_log_untrustedstring(ab, dentry->d_name.name);
- dput(dentry);
- }
- }
- if (inode)
- audit_log_format(ab, " dev=%s ino=%lu",
- inode->i_sb->s_id,
- inode->i_ino);
- break;
- case AVC_AUDIT_DATA_NET:
- if (a->u.net.sk) {
- struct sock *sk = a->u.net.sk;
- struct unix_sock *u;
- int len = 0;
- char *p = NULL;
-
- switch (sk->sk_family) {
- case AF_INET: {
- struct inet_sock *inet = inet_sk(sk);
-
- avc_print_ipv4_addr(ab, inet->rcv_saddr,
- inet->sport,
- "laddr", "lport");
- avc_print_ipv4_addr(ab, inet->daddr,
- inet->dport,
- "faddr", "fport");
- break;
- }
- case AF_INET6: {
- struct inet_sock *inet = inet_sk(sk);
- struct ipv6_pinfo *inet6 = inet6_sk(sk);
-
- avc_print_ipv6_addr(ab, &inet6->rcv_saddr,
- inet->sport,
- "laddr", "lport");
- avc_print_ipv6_addr(ab, &inet6->daddr,
- inet->dport,
- "faddr", "fport");
- break;
- }
- case AF_UNIX:
- u = unix_sk(sk);
- if (u->dentry) {
- struct path path = {
- .dentry = u->dentry,
- .mnt = u->mnt
- };
- audit_log_d_path(ab, "path=",
- &path);
- break;
- }
- if (!u->addr)
- break;
- len = u->addr->len-sizeof(short);
- p = &u->addr->name->sun_path[0];
- audit_log_format(ab, " path=");
- if (*p)
- audit_log_untrustedstring(ab, p);
- else
- audit_log_n_hex(ab, p, len);
- break;
- }
- }
-
- switch (a->u.net.family) {
- case AF_INET:
- avc_print_ipv4_addr(ab, a->u.net.v4info.saddr,
- a->u.net.sport,
- "saddr", "src");
- avc_print_ipv4_addr(ab, a->u.net.v4info.daddr,
- a->u.net.dport,
- "daddr", "dest");
- break;
- case AF_INET6:
- avc_print_ipv6_addr(ab, &a->u.net.v6info.saddr,
- a->u.net.sport,
- "saddr", "src");
- avc_print_ipv6_addr(ab, &a->u.net.v6info.daddr,
- a->u.net.dport,
- "daddr", "dest");
- break;
- }
- if (a->u.net.netif > 0) {
- struct net_device *dev;
-
- /* NOTE: we always use init's namespace */
- dev = dev_get_by_index(&init_net,
- a->u.net.netif);
- if (dev) {
- audit_log_format(ab, " netif=%s",
- dev->name);
- dev_put(dev);
- }
- }
- break;
- }
- }
- audit_log_format(ab, " ");
- avc_dump_query(ab, ssid, tsid, tclass);
- audit_log_end(ab);
+ a->selinux_audit_data.tclass = tclass;
+ a->selinux_audit_data.requested = requested;
+ a->selinux_audit_data.ssid = ssid;
+ a->selinux_audit_data.tsid = tsid;
+ a->selinux_audit_data.audited = audited;
+ a->selinux_audit_data.denied = denied;
+ a->lsm_pre_audit = avc_audit_pre_callback;
+ a->lsm_post_audit = avc_audit_post_callback;
+ common_lsm_audit(a);
}
/**
@@ -956,7 +841,7 @@ out:
* another -errno upon other errors.
*/
int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
- u32 requested, struct avc_audit_data *auditdata)
+ u32 requested, struct common_audit_data *auditdata)
{
struct av_decision avd;
int rc;
@@ -970,3 +855,9 @@ u32 avc_policy_seqno(void)
{
return avc_cache.latest_notif;
}
+
+void avc_disable(void)
+{
+ if (avc_node_cachep)
+ kmem_cache_destroy(avc_node_cachep);
+}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8d8b69c5664e..6d0b1ccb5b99 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1479,14 +1479,14 @@ static int task_has_capability(struct task_struct *tsk,
const struct cred *cred,
int cap, int audit)
{
- struct avc_audit_data ad;
+ struct common_audit_data ad;
struct av_decision avd;
u16 sclass;
u32 sid = cred_sid(cred);
u32 av = CAP_TO_MASK(cap);
int rc;
- AVC_AUDIT_DATA_INIT(&ad, CAP);
+ COMMON_AUDIT_DATA_INIT(&ad, CAP);
ad.tsk = tsk;
ad.u.cap = cap;
@@ -1525,10 +1525,10 @@ static int task_has_system(struct task_struct *tsk,
static int inode_has_perm(const struct cred *cred,
struct inode *inode,
u32 perms,
- struct avc_audit_data *adp)
+ struct common_audit_data *adp)
{
struct inode_security_struct *isec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
u32 sid;
if (unlikely(IS_PRIVATE(inode)))
@@ -1539,7 +1539,7 @@ static int inode_has_perm(const struct cred *cred,
if (!adp) {
adp = &ad;
- AVC_AUDIT_DATA_INIT(&ad, FS);
+ COMMON_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.inode = inode;
}
@@ -1555,9 +1555,9 @@ static inline int dentry_has_perm(const struct cred *cred,
u32 av)
{
struct inode *inode = dentry->d_inode;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
- AVC_AUDIT_DATA_INIT(&ad, FS);
+ COMMON_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path.mnt = mnt;
ad.u.fs.path.dentry = dentry;
return inode_has_perm(cred, inode, av, &ad);
@@ -1577,11 +1577,11 @@ static int file_has_perm(const struct cred *cred,
{
struct file_security_struct *fsec = file->f_security;
struct inode *inode = file->f_path.dentry->d_inode;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
u32 sid = cred_sid(cred);
int rc;
- AVC_AUDIT_DATA_INIT(&ad, FS);
+ COMMON_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path = file->f_path;
if (sid != fsec->sid) {
@@ -1612,7 +1612,7 @@ static int may_create(struct inode *dir,
struct inode_security_struct *dsec;
struct superblock_security_struct *sbsec;
u32 sid, newsid;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
int rc;
dsec = dir->i_security;
@@ -1621,7 +1621,7 @@ static int may_create(struct inode *dir,
sid = tsec->sid;
newsid = tsec->create_sid;
- AVC_AUDIT_DATA_INIT(&ad, FS);
+ COMMON_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path.dentry = dentry;
rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
@@ -1665,7 +1665,7 @@ static int may_link(struct inode *dir,
{
struct inode_security_struct *dsec, *isec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
u32 sid = current_sid();
u32 av;
int rc;
@@ -1673,7 +1673,7 @@ static int may_link(struct inode *dir,
dsec = dir->i_security;
isec = dentry->d_inode->i_security;
- AVC_AUDIT_DATA_INIT(&ad, FS);
+ COMMON_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path.dentry = dentry;
av = DIR__SEARCH;
@@ -1708,7 +1708,7 @@ static inline int may_rename(struct inode *old_dir,
struct dentry *new_dentry)
{
struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
u32 sid = current_sid();
u32 av;
int old_is_dir, new_is_dir;
@@ -1719,7 +1719,7 @@ static inline int may_rename(struct inode *old_dir,
old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
new_dsec = new_dir->i_security;
- AVC_AUDIT_DATA_INIT(&ad, FS);
+ COMMON_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path.dentry = old_dentry;
rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
@@ -1761,7 +1761,7 @@ static inline int may_rename(struct inode *old_dir,
static int superblock_has_perm(const struct cred *cred,
struct super_block *sb,
u32 perms,
- struct avc_audit_data *ad)
+ struct common_audit_data *ad)
{
struct superblock_security_struct *sbsec;
u32 sid = cred_sid(cred);
@@ -1855,12 +1855,12 @@ static inline u32 open_file_to_av(struct file *file)
/* Hook functions begin here. */
-static int selinux_ptrace_may_access(struct task_struct *child,
+static int selinux_ptrace_access_check(struct task_struct *child,
unsigned int mode)
{
int rc;
- rc = cap_ptrace_may_access(child, mode);
+ rc = cap_ptrace_access_check(child, mode);
if (rc)
return rc;
@@ -2101,7 +2101,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
const struct task_security_struct *old_tsec;
struct task_security_struct *new_tsec;
struct inode_security_struct *isec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
struct inode *inode = bprm->file->f_path.dentry->d_inode;
int rc;
@@ -2139,7 +2139,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
return rc;
}
- AVC_AUDIT_DATA_INIT(&ad, FS);
+ COMMON_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path = bprm->file->f_path;
if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
@@ -2232,7 +2232,7 @@ extern struct dentry *selinux_null;
static inline void flush_unauthorized_files(const struct cred *cred,
struct files_struct *files)
{
- struct avc_audit_data ad;
+ struct common_audit_data ad;
struct file *file, *devnull = NULL;
struct tty_struct *tty;
struct fdtable *fdt;
@@ -2266,7 +2266,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
/* Revalidate access to inherited open files. */
- AVC_AUDIT_DATA_INIT(&ad, FS);
+ COMMON_AUDIT_DATA_INIT(&ad, FS);
spin_lock(&files->file_lock);
for (;;) {
@@ -2515,7 +2515,7 @@ out:
static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
{
const struct cred *cred = current_cred();
- struct avc_audit_data ad;
+ struct common_audit_data ad;
int rc;
rc = superblock_doinit(sb, data);
@@ -2526,7 +2526,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
if (flags & MS_KERNMOUNT)
return 0;
- AVC_AUDIT_DATA_INIT(&ad, FS);
+ COMMON_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path.dentry = sb->s_root;
return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
}
@@ -2534,9 +2534,9 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
static int selinux_sb_statfs(struct dentry *dentry)
{
const struct cred *cred = current_cred();
- struct avc_audit_data ad;
+ struct common_audit_data ad;
- AVC_AUDIT_DATA_INIT(&ad, FS);
+ COMMON_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path.dentry = dentry->d_sb->s_root;
return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
}
@@ -2756,7 +2756,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
struct inode *inode = dentry->d_inode;
struct inode_security_struct *isec = inode->i_security;
struct superblock_security_struct *sbsec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
u32 newsid, sid = current_sid();
int rc = 0;
@@ -2770,7 +2770,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
if (!is_owner_or_cap(inode))
return -EPERM;
- AVC_AUDIT_DATA_INIT(&ad, FS);
+ COMMON_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path.dentry = dentry;
rc = avc_has_perm(sid, isec->sid, isec->sclass,
@@ -2939,11 +2939,6 @@ static int selinux_revalidate_file_permission(struct file *file, int mask)
const struct cred *cred = current_cred();
struct inode *inode = file->f_path.dentry->d_inode;
- if (!mask) {
- /* No permission to check. Existence test. */
- return 0;
- }
-
/* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
mask |= MAY_APPEND;
@@ -2954,10 +2949,20 @@ static int selinux_revalidate_file_permission(struct file *file, int mask)
static int selinux_file_permission(struct file *file, int mask)
{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct file_security_struct *fsec = file->f_security;
+ struct inode_security_struct *isec = inode->i_security;
+ u32 sid = current_sid();
+
if (!mask)
/* No permission to check. Existence test. */
return 0;
+ if (sid == fsec->sid && fsec->isid == isec->sid &&
+ fsec->pseqno == avc_policy_seqno())
+ /* No change since dentry_open check. */
+ return 0;
+
return selinux_revalidate_file_permission(file, mask);
}
@@ -3292,6 +3297,11 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
return 0;
}
+static int selinux_kernel_module_request(void)
+{
+ return task_has_system(current, SYSTEM__MODULE_REQUEST);
+}
+
static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
{
return current_has_perm(p, PROCESS__SETPGID);
@@ -3409,7 +3419,7 @@ static void selinux_task_to_inode(struct task_struct *p,
/* Returns error only if unable to parse addresses */
static int selinux_parse_skb_ipv4(struct sk_buff *skb,
- struct avc_audit_data *ad, u8 *proto)
+ struct common_audit_data *ad, u8 *proto)
{
int offset, ihlen, ret = -EINVAL;
struct iphdr _iph, *ih;
@@ -3490,7 +3500,7 @@ out:
/* Returns error only if unable to parse addresses */
static int selinux_parse_skb_ipv6(struct sk_buff *skb,
- struct avc_audit_data *ad, u8 *proto)
+ struct common_audit_data *ad, u8 *proto)
{
u8 nexthdr;
int ret = -EINVAL, offset;
@@ -3561,7 +3571,7 @@ out:
#endif /* IPV6 */
-static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
+static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
char **_addrp, int src, u8 *proto)
{
char *addrp;
@@ -3643,7 +3653,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock,
u32 perms)
{
struct inode_security_struct *isec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
u32 sid;
int err = 0;
@@ -3653,7 +3663,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock,
goto out;
sid = task_sid(task);
- AVC_AUDIT_DATA_INIT(&ad, NET);
+ COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.sk = sock->sk;
err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
@@ -3740,7 +3750,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
if (family == PF_INET || family == PF_INET6) {
char *addrp;
struct inode_security_struct *isec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
struct sockaddr_in *addr4 = NULL;
struct sockaddr_in6 *addr6 = NULL;
unsigned short snum;
@@ -3769,7 +3779,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
snum, &sid);
if (err)
goto out;
- AVC_AUDIT_DATA_INIT(&ad, NET);
+ COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.sport = htons(snum);
ad.u.net.family = family;
err = avc_has_perm(isec->sid, sid,
@@ -3802,7 +3812,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
if (err)
goto out;
- AVC_AUDIT_DATA_INIT(&ad, NET);
+ COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.sport = htons(snum);
ad.u.net.family = family;
@@ -3836,7 +3846,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
isec = SOCK_INODE(sock)->i_security;
if (isec->sclass == SECCLASS_TCP_SOCKET ||
isec->sclass == SECCLASS_DCCP_SOCKET) {
- struct avc_audit_data ad;
+ struct common_audit_data ad;
struct sockaddr_in *addr4 = NULL;
struct sockaddr_in6 *addr6 = NULL;
unsigned short snum;
@@ -3861,7 +3871,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
perm = (isec->sclass == SECCLASS_TCP_SOCKET) ?
TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
- AVC_AUDIT_DATA_INIT(&ad, NET);
+ COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.dport = htons(snum);
ad.u.net.family = sk->sk_family;
err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad);
@@ -3951,13 +3961,13 @@ static int selinux_socket_unix_stream_connect(struct socket *sock,
struct sk_security_struct *ssec;
struct inode_security_struct *isec;
struct inode_security_struct *other_isec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
int err;
isec = SOCK_INODE(sock)->i_security;
other_isec = SOCK_INODE(other)->i_security;
- AVC_AUDIT_DATA_INIT(&ad, NET);
+ COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.sk = other->sk;
err = avc_has_perm(isec->sid, other_isec->sid,
@@ -3983,13 +3993,13 @@ static int selinux_socket_unix_may_send(struct socket *sock,
{
struct inode_security_struct *isec;
struct inode_security_struct *other_isec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
int err;
isec = SOCK_INODE(sock)->i_security;
other_isec = SOCK_INODE(other)->i_security;
- AVC_AUDIT_DATA_INIT(&ad, NET);
+ COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.sk = other->sk;
err = avc_has_perm(isec->sid, other_isec->sid,
@@ -4002,7 +4012,7 @@ static int selinux_socket_unix_may_send(struct socket *sock,
static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
u32 peer_sid,
- struct avc_audit_data *ad)
+ struct common_audit_data *ad)
{
int err;
u32 if_sid;
@@ -4030,10 +4040,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
struct sk_security_struct *sksec = sk->sk_security;
u32 peer_sid;
u32 sk_sid = sksec->sid;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
char *addrp;
- AVC_AUDIT_DATA_INIT(&ad, NET);
+ COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.netif = skb->iif;
ad.u.net.family = family;
err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
@@ -4071,7 +4081,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
struct sk_security_struct *sksec = sk->sk_security;
u16 family = sk->sk_family;
u32 sk_sid = sksec->sid;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
char *addrp;
u8 secmark_active;
u8 peerlbl_active;
@@ -4095,7 +4105,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
if (!secmark_active && !peerlbl_active)
return 0;
- AVC_AUDIT_DATA_INIT(&ad, NET);
+ COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.netif = skb->iif;
ad.u.net.family = family;
err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
@@ -4353,7 +4363,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
int err;
char *addrp;
u32 peer_sid;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
u8 secmark_active;
u8 netlbl_active;
u8 peerlbl_active;
@@ -4370,7 +4380,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
return NF_DROP;
- AVC_AUDIT_DATA_INIT(&ad, NET);
+ COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.netif = ifindex;
ad.u.net.family = family;
if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
@@ -4458,7 +4468,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
{
struct sock *sk = skb->sk;
struct sk_security_struct *sksec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
char *addrp;
u8 proto;
@@ -4466,7 +4476,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
return NF_ACCEPT;
sksec = sk->sk_security;
- AVC_AUDIT_DATA_INIT(&ad, NET);
+ COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.netif = ifindex;
ad.u.net.family = family;
if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
@@ -4490,7 +4500,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
u32 secmark_perm;
u32 peer_sid;
struct sock *sk;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
char *addrp;
u8 secmark_active;
u8 peerlbl_active;
@@ -4549,7 +4559,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
secmark_perm = PACKET__SEND;
}
- AVC_AUDIT_DATA_INIT(&ad, NET);
+ COMMON_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.netif = ifindex;
ad.u.net.family = family;
if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
@@ -4619,13 +4629,13 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
static int selinux_netlink_recv(struct sk_buff *skb, int capability)
{
int err;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
err = cap_netlink_recv(skb, capability);
if (err)
return err;
- AVC_AUDIT_DATA_INIT(&ad, CAP);
+ COMMON_AUDIT_DATA_INIT(&ad, CAP);
ad.u.cap = capability;
return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid,
@@ -4684,12 +4694,12 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
u32 perms)
{
struct ipc_security_struct *isec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
u32 sid = current_sid();
isec = ipc_perms->security;
- AVC_AUDIT_DATA_INIT(&ad, IPC);
+ COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = ipc_perms->key;
return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
@@ -4709,7 +4719,7 @@ static void selinux_msg_msg_free_security(struct msg_msg *msg)
static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
{
struct ipc_security_struct *isec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
u32 sid = current_sid();
int rc;
@@ -4719,7 +4729,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
isec = msq->q_perm.security;
- AVC_AUDIT_DATA_INIT(&ad, IPC);
+ COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = msq->q_perm.key;
rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
@@ -4739,12 +4749,12 @@ static void selinux_msg_queue_free_security(struct msg_queue *msq)
static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
{
struct ipc_security_struct *isec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
u32 sid = current_sid();
isec = msq->q_perm.security;
- AVC_AUDIT_DATA_INIT(&ad, IPC);
+ COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = msq->q_perm.key;
return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
@@ -4783,7 +4793,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
{
struct ipc_security_struct *isec;
struct msg_security_struct *msec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
u32 sid = current_sid();
int rc;
@@ -4804,7 +4814,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
return rc;
}
- AVC_AUDIT_DATA_INIT(&ad, IPC);
+ COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = msq->q_perm.key;
/* Can this process write to the queue? */
@@ -4828,14 +4838,14 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
{
struct ipc_security_struct *isec;
struct msg_security_struct *msec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
u32 sid = task_sid(target);
int rc;
isec = msq->q_perm.security;
msec = msg->security;
- AVC_AUDIT_DATA_INIT(&ad, IPC);
+ COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = msq->q_perm.key;
rc = avc_has_perm(sid, isec->sid,
@@ -4850,7 +4860,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
static int selinux_shm_alloc_security(struct shmid_kernel *shp)
{
struct ipc_security_struct *isec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
u32 sid = current_sid();
int rc;
@@ -4860,7 +4870,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
isec = shp->shm_perm.security;
- AVC_AUDIT_DATA_INIT(&ad, IPC);
+ COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = shp->shm_perm.key;
rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
@@ -4880,12 +4890,12 @@ static void selinux_shm_free_security(struct shmid_kernel *shp)
static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
{
struct ipc_security_struct *isec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
u32 sid = current_sid();
isec = shp->shm_perm.security;
- AVC_AUDIT_DATA_INIT(&ad, IPC);
+ COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = shp->shm_perm.key;
return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
@@ -4942,7 +4952,7 @@ static int selinux_shm_shmat(struct shmid_kernel *shp,
static int selinux_sem_alloc_security(struct sem_array *sma)
{
struct ipc_security_struct *isec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
u32 sid = current_sid();
int rc;
@@ -4952,7 +4962,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
isec = sma->sem_perm.security;
- AVC_AUDIT_DATA_INIT(&ad, IPC);
+ COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = sma->sem_perm.key;
rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
@@ -4972,12 +4982,12 @@ static void selinux_sem_free_security(struct sem_array *sma)
static int selinux_sem_associate(struct sem_array *sma, int semflg)
{
struct ipc_security_struct *isec;
- struct avc_audit_data ad;
+ struct common_audit_data ad;
u32 sid = current_sid();
isec = sma->sem_perm.security;
- AVC_AUDIT_DATA_INIT(&ad, IPC);
+ COMMON_AUDIT_DATA_INIT(&ad, IPC);
ad.u.ipc_id = sma->sem_perm.key;
return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
@@ -5195,7 +5205,7 @@ static int selinux_setprocattr(struct task_struct *p,
/* Only allow single threaded processes to change context */
error = -EPERM;
- if (!is_single_threaded(p)) {
+ if (!current_is_single_threaded()) {
error = security_bounded_transition(tsec->sid, sid);
if (error)
goto abort_change;
@@ -5323,7 +5333,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
static struct security_operations selinux_ops = {
.name = "selinux",
- .ptrace_may_access = selinux_ptrace_may_access,
+ .ptrace_access_check = selinux_ptrace_access_check,
.ptrace_traceme = selinux_ptrace_traceme,
.capget = selinux_capget,
.capset = selinux_capset,
@@ -5400,6 +5410,7 @@ static struct security_operations selinux_ops = {
.cred_prepare = selinux_cred_prepare,
.kernel_act_as = selinux_kernel_act_as,
.kernel_create_files_as = selinux_kernel_create_files_as,
+ .kernel_module_request = selinux_kernel_module_request,
.task_setpgid = selinux_task_setpgid,
.task_getpgid = selinux_task_getpgid,
.task_getsid = selinux_task_getsid,
@@ -5691,6 +5702,9 @@ int selinux_disable(void)
selinux_disabled = 1;
selinux_enabled = 0;
+ /* Try to destroy the avc node cache */
+ avc_disable();
+
/* Reset security_ops to the secondary module, dummy or capability. */
security_ops = secondary_ops;
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index 31df1d7c1aee..2b683ad83d21 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -107,6 +107,7 @@
S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read")
S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod")
S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, "syslog_console")
+ S_(SECCLASS_SYSTEM, SYSTEM__MODULE_REQUEST, "module_request")
S_(SECCLASS_CAPABILITY, CAPABILITY__CHOWN, "chown")
S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_OVERRIDE, "dac_override")
S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_READ_SEARCH, "dac_read_search")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index d645192ee950..21c722669902 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -508,6 +508,7 @@
#define SYSTEM__SYSLOG_READ 0x00000002UL
#define SYSTEM__SYSLOG_MOD 0x00000004UL
#define SYSTEM__SYSLOG_CONSOLE 0x00000008UL
+#define SYSTEM__MODULE_REQUEST 0x00000010UL
#define CAPABILITY__CHOWN 0x00000001UL
#define CAPABILITY__DAC_OVERRIDE 0x00000002UL
#define CAPABILITY__DAC_READ_SEARCH 0x00000004UL
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index d12ff1a9c0aa..e94e82f73818 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -13,6 +13,7 @@
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/audit.h>
+#include <linux/lsm_audit.h>
#include <linux/in6.h>
#include <linux/path.h>
#include <asm/system.h>
@@ -36,48 +37,6 @@ struct inode;
struct sock;
struct sk_buff;
-/* Auxiliary data to use in generating the audit record. */
-struct avc_audit_data {
- char type;
-#define AVC_AUDIT_DATA_FS 1
-#define AVC_AUDIT_DATA_NET 2
-#define AVC_AUDIT_DATA_CAP 3
-#define AVC_AUDIT_DATA_IPC 4
- struct task_struct *tsk;
- union {
- struct {
- struct path path;
- struct inode *inode;
- } fs;
- struct {
- int netif;
- struct sock *sk;
- u16 family;
- __be16 dport;
- __be16 sport;
- union {
- struct {
- __be32 daddr;
- __be32 saddr;
- } v4;
- struct {
- struct in6_addr daddr;
- struct in6_addr saddr;
- } v6;
- } fam;
- } net;
- int cap;
- int ipc_id;
- } u;
-};
-
-#define v4info fam.v4
-#define v6info fam.v6
-
-/* Initialize an AVC audit data structure. */
-#define AVC_AUDIT_DATA_INIT(_d,_t) \
- { memset((_d), 0, sizeof(struct avc_audit_data)); (_d)->type = AVC_AUDIT_DATA_##_t; }
-
/*
* AVC statistics
*/
@@ -98,7 +57,9 @@ void __init avc_init(void);
void avc_audit(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
- struct av_decision *avd, int result, struct avc_audit_data *auditdata);
+ struct av_decision *avd,
+ int result,
+ struct common_audit_data *a);
#define AVC_STRICT 1 /* Ignore permissive mode. */
int avc_has_perm_noaudit(u32 ssid, u32 tsid,
@@ -108,7 +69,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
int avc_has_perm(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
- struct avc_audit_data *auditdata);
+ struct common_audit_data *auditdata);
u32 avc_policy_seqno(void);
@@ -127,13 +88,13 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
u32 events, u32 ssid, u32 tsid,
u16 tclass, u32 perms);
-/* Shows permission in human readable form */
-void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av);
-
/* Exported to selinuxfs */
int avc_get_hash_stats(char *page);
extern unsigned int avc_cache_threshold;
+/* Attempt to free avc node cache */
+void avc_disable(void);
+
#ifdef CONFIG_SECURITY_SELINUX_AVC_STATS
DECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats);
#endif
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
index b4b5b9b2f0be..8d7384280a7a 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -59,7 +59,7 @@ int selinux_netlbl_socket_post_create(struct sock *sk, u16 family);
int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
struct sk_buff *skb,
u16 family,
- struct avc_audit_data *ad);
+ struct common_audit_data *ad);
int selinux_netlbl_socket_setsockopt(struct socket *sock,
int level,
int optname);
@@ -129,7 +129,7 @@ static inline int selinux_netlbl_socket_post_create(struct sock *sk,
static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
struct sk_buff *skb,
u16 family,
- struct avc_audit_data *ad)
+ struct common_audit_data *ad)
{
return 0;
}
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 289e24b39e3e..13128f9a3e5a 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -41,9 +41,9 @@ static inline int selinux_xfrm_enabled(void)
}
int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb,
- struct avc_audit_data *ad);
+ struct common_audit_data *ad);
int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
- struct avc_audit_data *ad, u8 proto);
+ struct common_audit_data *ad, u8 proto);
int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
static inline void selinux_xfrm_notify_policyload(void)
@@ -57,13 +57,13 @@ static inline int selinux_xfrm_enabled(void)
}
static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
- struct avc_audit_data *ad)
+ struct common_audit_data *ad)
{
return 0;
}
static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
- struct avc_audit_data *ad, u8 proto)
+ struct common_audit_data *ad, u8 proto)
{
return 0;
}
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 2e984413c7b2..e68823741ad5 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -342,7 +342,7 @@ int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
struct sk_buff *skb,
u16 family,
- struct avc_audit_data *ad)
+ struct common_audit_data *ad)
{
int rc;
u32 nlbl_sid;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 500e6f78e115..ff17820d35ec 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -22,6 +22,11 @@
*
* Added validation of kernel classes and permissions
*
+ * Updated: KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * Added support for bounds domain and audit messaged on masked permissions
+ *
+ * Copyright (C) 2008, 2009 NEC Corporation
* Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
* Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
* Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC
@@ -279,6 +284,95 @@ mls_ops:
}
/*
+ * security_dump_masked_av - dumps masked permissions during
+ * security_compute_av due to RBAC, MLS/Constraint and Type bounds.
+ */
+static int dump_masked_av_helper(void *k, void *d, void *args)
+{
+ struct perm_datum *pdatum = d;
+ char **permission_names = args;
+
+ BUG_ON(pdatum->value < 1 || pdatum->value > 32);
+
+ permission_names[pdatum->value - 1] = (char *)k;
+
+ return 0;
+}
+
+static void security_dump_masked_av(struct context *scontext,
+ struct context *tcontext,
+ u16 tclass,
+ u32 permissions,
+ const char *reason)
+{
+ struct common_datum *common_dat;
+ struct class_datum *tclass_dat;
+ struct audit_buffer *ab;
+ char *tclass_name;
+ char *scontext_name = NULL;
+ char *tcontext_name = NULL;
+ char *permission_names[32];
+ int index, length;
+ bool need_comma = false;
+
+ if (!permissions)
+ return;
+
+ tclass_name = policydb.p_class_val_to_name[tclass - 1];
+ tclass_dat = policydb.class_val_to_struct[tclass - 1];
+ common_dat = tclass_dat->comdatum;
+
+ /* init permission_names */
+ if (common_dat &&
+ hashtab_map(common_dat->permissions.table,
+ dump_masked_av_helper, permission_names) < 0)
+ goto out;
+
+ if (hashtab_map(tclass_dat->permissions.table,
+ dump_masked_av_helper, permission_names) < 0)
+ goto out;
+
+ /* get scontext/tcontext in text form */
+ if (context_struct_to_string(scontext,
+ &scontext_name, &length) < 0)
+ goto out;
+
+ if (context_struct_to_string(tcontext,
+ &tcontext_name, &length) < 0)
+ goto out;
+
+ /* audit a message */
+ ab = audit_log_start(current->audit_context,
+ GFP_ATOMIC, AUDIT_SELINUX_ERR);
+ if (!ab)
+ goto out;
+
+ audit_log_format(ab, "op=security_compute_av reason=%s "
+ "scontext=%s tcontext=%s tclass=%s perms=",
+ reason, scontext_name, tcontext_name, tclass_name);
+
+ for (index = 0; index < 32; index++) {
+ u32 mask = (1 << index);
+
+ if ((mask & permissions) == 0)
+ continue;
+
+ audit_log_format(ab, "%s%s",
+ need_comma ? "," : "",
+ permission_names[index]
+ ? permission_names[index] : "????");
+ need_comma = true;
+ }
+ audit_log_end(ab);
+out:
+ /* release scontext/tcontext */
+ kfree(tcontext_name);
+ kfree(scontext_name);
+
+ return;
+}
+
+/*
* security_boundary_permission - drops violated permissions
* on boundary constraint.
*/
@@ -347,28 +441,12 @@ static void type_attribute_bounds_av(struct context *scontext,
}
if (masked) {
- struct audit_buffer *ab;
- char *stype_name
- = policydb.p_type_val_to_name[source->value - 1];
- char *ttype_name
- = policydb.p_type_val_to_name[target->value - 1];
- char *tclass_name
- = policydb.p_class_val_to_name[tclass - 1];
-
/* mask violated permissions */
avd->allowed &= ~masked;
- /* notice to userspace via audit message */
- ab = audit_log_start(current->audit_context,
- GFP_ATOMIC, AUDIT_SELINUX_ERR);
- if (!ab)
- return;
-
- audit_log_format(ab, "av boundary violation: "
- "source=%s target=%s tclass=%s",
- stype_name, ttype_name, tclass_name);
- avc_dump_av(ab, tclass, masked);
- audit_log_end(ab);
+ /* audit masked permissions */
+ security_dump_masked_av(scontext, tcontext,
+ tclass, masked, "bounds");
}
}
@@ -480,7 +558,7 @@ static int context_struct_compute_av(struct context *scontext,
if ((constraint->permissions & (avd->allowed)) &&
!constraint_expr_eval(scontext, tcontext, NULL,
constraint->expr)) {
- avd->allowed = (avd->allowed) & ~(constraint->permissions);
+ avd->allowed &= ~(constraint->permissions);
}
constraint = constraint->next;
}
@@ -499,8 +577,8 @@ static int context_struct_compute_av(struct context *scontext,
break;
}
if (!ra)
- avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION |
- PROCESS__DYNTRANSITION);
+ avd->allowed &= ~(PROCESS__TRANSITION |
+ PROCESS__DYNTRANSITION);
}
/*
@@ -687,6 +765,26 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
}
index = type->bounds;
}
+
+ if (rc) {
+ char *old_name = NULL;
+ char *new_name = NULL;
+ int length;
+
+ if (!context_struct_to_string(old_context,
+ &old_name, &length) &&
+ !context_struct_to_string(new_context,
+ &new_name, &length)) {
+ audit_log(current->audit_context,
+ GFP_ATOMIC, AUDIT_SELINUX_ERR,
+ "op=security_bounded_transition "
+ "result=denied "
+ "oldcontext=%s newcontext=%s",
+ old_name, new_name);
+ }
+ kfree(new_name);
+ kfree(old_name);
+ }
out:
read_unlock(&policy_rwlock);
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 72b18452e1a1..f3cb9ed731a9 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -401,7 +401,7 @@ int selinux_xfrm_state_delete(struct xfrm_state *x)
* gone thru the IPSec process.
*/
int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
- struct avc_audit_data *ad)
+ struct common_audit_data *ad)
{
int i, rc = 0;
struct sec_path *sp;
@@ -442,7 +442,7 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
* checked in the selinux_xfrm_state_pol_flow_match hook above.
*/
int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
- struct avc_audit_data *ad, u8 proto)
+ struct common_audit_data *ad, u8 proto)
{
struct dst_entry *dst;
int rc = 0;
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 243bec175be0..c6e9acae72e4 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -275,7 +275,7 @@ static inline void smk_ad_init(struct smk_audit_info *a, const char *func,
{
memset(a, 0, sizeof(*a));
a->a.type = type;
- a->a.function = func;
+ a->a.smack_audit_data.function = func;
}
static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a,
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 513dc1aa16dd..0f9ac8146900 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -240,8 +240,9 @@ static inline void smack_str_from_perm(char *string, int access)
static void smack_log_callback(struct audit_buffer *ab, void *a)
{
struct common_audit_data *ad = a;
- struct smack_audit_data *sad = &ad->lsm_priv.smack_audit_data;
- audit_log_format(ab, "lsm=SMACK fn=%s action=%s", ad->function,
+ struct smack_audit_data *sad = &ad->smack_audit_data;
+ audit_log_format(ab, "lsm=SMACK fn=%s action=%s",
+ ad->smack_audit_data.function,
sad->result ? "denied" : "granted");
audit_log_format(ab, " subject=");
audit_log_untrustedstring(ab, sad->subject);
@@ -274,11 +275,11 @@ void smack_log(char *subject_label, char *object_label, int request,
if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
return;
- if (a->function == NULL)
- a->function = "unknown";
+ if (a->smack_audit_data.function == NULL)
+ a->smack_audit_data.function = "unknown";
/* end preparing the audit data */
- sad = &a->lsm_priv.smack_audit_data;
+ sad = &a->smack_audit_data;
smack_str_from_perm(request_buffer, request);
sad->subject = subject_label;
sad->object = object_label;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 0023182078c7..c243a2b25832 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -91,7 +91,7 @@ struct inode_smack *new_inode_smack(char *smack)
*/
/**
- * smack_ptrace_may_access - Smack approval on PTRACE_ATTACH
+ * smack_ptrace_access_check - Smack approval on PTRACE_ATTACH
* @ctp: child task pointer
* @mode: ptrace attachment mode
*
@@ -99,13 +99,13 @@ struct inode_smack *new_inode_smack(char *smack)
*
* Do the capability checks, and require read and write.
*/
-static int smack_ptrace_may_access(struct task_struct *ctp, unsigned int mode)
+static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
{
int rc;
struct smk_audit_info ad;
char *sp, *tsp;
- rc = cap_ptrace_may_access(ctp, mode);
+ rc = cap_ptrace_access_check(ctp, mode);
if (rc != 0)
return rc;
@@ -2464,7 +2464,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
/*
* Perfectly reasonable for this to be NULL
*/
- if (sip == NULL || sip->sin_family != PF_INET)
+ if (sip == NULL || sip->sin_family != AF_INET)
return 0;
return smack_netlabel_send(sock->sk, sip);
@@ -3032,7 +3032,7 @@ static void smack_release_secctx(char *secdata, u32 seclen)
struct security_operations smack_ops = {
.name = "smack",
- .ptrace_may_access = smack_ptrace_may_access,
+ .ptrace_access_check = smack_ptrace_access_check,
.ptrace_traceme = smack_ptrace_traceme,
.syslog = smack_syslog,
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index fdd1f4b8c448..3c8bd8ee0b95 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -1285,6 +1285,36 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
}
/**
+ * tomoyo_delete_domain - Delete a domain.
+ *
+ * @domainname: The name of domain.
+ *
+ * Returns 0.
+ */
+static int tomoyo_delete_domain(char *domainname)
+{
+ struct tomoyo_domain_info *domain;
+ struct tomoyo_path_info name;
+
+ name.name = domainname;
+ tomoyo_fill_path_info(&name);
+ down_write(&tomoyo_domain_list_lock);
+ /* Is there an active domain? */
+ list_for_each_entry(domain, &tomoyo_domain_list, list) {
+ /* Never delete tomoyo_kernel_domain */
+ if (domain == &tomoyo_kernel_domain)
+ continue;
+ if (domain->is_deleted ||
+ tomoyo_pathcmp(domain->domainname, &name))
+ continue;
+ domain->is_deleted = true;
+ break;
+ }
+ up_write(&tomoyo_domain_list_lock);
+ return 0;
+}
+
+/**
* tomoyo_write_domain_policy - Write domain policy.
*
* @head: Pointer to "struct tomoyo_io_buffer".
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 6d6ba09af457..31df541911f7 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -339,8 +339,6 @@ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain);
const char *tomoyo_get_msg(const bool is_enforce);
/* Convert single path operation to operation name. */
const char *tomoyo_sp2keyword(const u8 operation);
-/* Delete a domain. */
-int tomoyo_delete_domain(char *data);
/* Create "alias" entry in exception policy. */
int tomoyo_write_alias_policy(char *data, const bool is_delete);
/*
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index 1d8b16960576..fcf52accce2b 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -717,38 +717,6 @@ int tomoyo_write_alias_policy(char *data, const bool is_delete)
return tomoyo_update_alias_entry(data, cp, is_delete);
}
-/* Domain create/delete handler. */
-
-/**
- * tomoyo_delete_domain - Delete a domain.
- *
- * @domainname: The name of domain.
- *
- * Returns 0.
- */
-int tomoyo_delete_domain(char *domainname)
-{
- struct tomoyo_domain_info *domain;
- struct tomoyo_path_info name;
-
- name.name = domainname;
- tomoyo_fill_path_info(&name);
- down_write(&tomoyo_domain_list_lock);
- /* Is there an active domain? */
- list_for_each_entry(domain, &tomoyo_domain_list, list) {
- /* Never delete tomoyo_kernel_domain */
- if (domain == &tomoyo_kernel_domain)
- continue;
- if (domain->is_deleted ||
- tomoyo_pathcmp(domain->domainname, &name))
- continue;
- domain->is_deleted = true;
- break;
- }
- up_write(&tomoyo_domain_list_lock);
- return 0;
-}
-
/**
* tomoyo_find_or_assign_new_domain - Create a domain.
*
@@ -818,13 +786,11 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
/**
* tomoyo_find_next_domain - Find a domain.
*
- * @bprm: Pointer to "struct linux_binprm".
- * @next_domain: Pointer to pointer to "struct tomoyo_domain_info".
+ * @bprm: Pointer to "struct linux_binprm".
*
* Returns 0 on success, negative value otherwise.
*/
-int tomoyo_find_next_domain(struct linux_binprm *bprm,
- struct tomoyo_domain_info **next_domain)
+int tomoyo_find_next_domain(struct linux_binprm *bprm)
{
/*
* This function assumes that the size of buffer returned by
@@ -946,9 +912,11 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm,
tomoyo_set_domain_flag(old_domain, false,
TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED);
out:
+ if (!domain)
+ domain = old_domain;
+ bprm->cred->security = domain;
tomoyo_free(real_program_name);
tomoyo_free(symlink_program_name);
- *next_domain = domain ? domain : old_domain;
tomoyo_free(tmp);
return retval;
}
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 3194d09fe0f4..35a13e7915e4 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -61,14 +61,8 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
* Execute permission is checked against pathname passed to do_execve()
* using current domain.
*/
- if (!domain) {
- struct tomoyo_domain_info *next_domain = NULL;
- int retval = tomoyo_find_next_domain(bprm, &next_domain);
-
- if (!retval)
- bprm->cred->security = next_domain;
- return retval;
- }
+ if (!domain)
+ return tomoyo_find_next_domain(bprm);
/*
* Read permission is checked against interpreters using next domain.
* '1' is the result of open_to_namei_flags(O_RDONLY).
diff --git a/security/tomoyo/tomoyo.h b/security/tomoyo/tomoyo.h
index 0fd588a629cf..cd6ba0bf7069 100644
--- a/security/tomoyo/tomoyo.h
+++ b/security/tomoyo/tomoyo.h
@@ -31,8 +31,7 @@ int tomoyo_check_2path_perm(struct tomoyo_domain_info *domain,
struct path *path2);
int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
struct file *filp);
-int tomoyo_find_next_domain(struct linux_binprm *bprm,
- struct tomoyo_domain_info **next_domain);
+int tomoyo_find_next_domain(struct linux_binprm *bprm);
/* Index numbers for Access Controls. */