summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/commoncap.c4
-rw-r--r--security/dummy.c14
-rw-r--r--security/keys/key.c18
-rw-r--r--security/security.c23
-rw-r--r--security/selinux/hooks.c98
-rw-r--r--security/selinux/nlmsgtab.c9
-rw-r--r--security/selinux/selinuxfs.c11
-rw-r--r--security/selinux/ss/services.c15
8 files changed, 99 insertions, 93 deletions
diff --git a/security/commoncap.c b/security/commoncap.c
index 8a6e097f99ea..841eb4e5c62b 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -60,8 +60,8 @@ int cap_settime(struct timespec *ts, struct timezone *tz)
int cap_ptrace (struct task_struct *parent, struct task_struct *child)
{
/* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
- if (!cap_issubset (child->cap_permitted, current->cap_permitted) &&
- !capable(CAP_SYS_PTRACE))
+ if (!cap_issubset(child->cap_permitted, parent->cap_permitted) &&
+ !__capable(parent, CAP_SYS_PTRACE))
return -EPERM;
return 0;
}
diff --git a/security/dummy.c b/security/dummy.c
index a678f094b72d..fd99429278e9 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -378,7 +378,7 @@ static int dummy_inode_removexattr (struct dentry *dentry, char *name)
return 0;
}
-static int dummy_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err)
+static int dummy_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
{
return -EOPNOTSUPP;
}
@@ -393,6 +393,11 @@ static int dummy_inode_listsecurity(struct inode *inode, char *buffer, size_t bu
return 0;
}
+static const char *dummy_inode_xattr_getsuffix(void)
+{
+ return NULL;
+}
+
static int dummy_file_permission (struct file *file, int mask)
{
return 0;
@@ -558,6 +563,11 @@ static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
return 0;
}
+static int dummy_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
+{
+ return -EOPNOTSUPP;
+}
+
static int dummy_msg_msg_alloc_security (struct msg_msg *msg)
{
return 0;
@@ -931,6 +941,7 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, inode_getxattr);
set_to_dummy_if_null(ops, inode_listxattr);
set_to_dummy_if_null(ops, inode_removexattr);
+ set_to_dummy_if_null(ops, inode_xattr_getsuffix);
set_to_dummy_if_null(ops, inode_getsecurity);
set_to_dummy_if_null(ops, inode_setsecurity);
set_to_dummy_if_null(ops, inode_listsecurity);
@@ -965,6 +976,7 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, task_reparent_to_init);
set_to_dummy_if_null(ops, task_to_inode);
set_to_dummy_if_null(ops, ipc_permission);
+ set_to_dummy_if_null(ops, ipc_getsecurity);
set_to_dummy_if_null(ops, msg_msg_alloc_security);
set_to_dummy_if_null(ops, msg_msg_free_security);
set_to_dummy_if_null(ops, msg_queue_alloc_security);
diff --git a/security/keys/key.c b/security/keys/key.c
index 99781b798312..a057e3311aad 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -1,6 +1,6 @@
/* key.c: basic authentication token and access key management
*
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -271,7 +271,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
* its description */
if (!not_in_quota) {
spin_lock(&user->lock);
- if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS &&
+ if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES
)
goto no_quota;
@@ -795,12 +795,16 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
goto error_3;
}
- /* search for an existing key of the same type and description in the
- * destination keyring
+ /* if it's possible to update this type of key, search for an existing
+ * key of the same type and description in the destination keyring and
+ * update that instead if possible
*/
- key_ref = __keyring_search_one(keyring_ref, ktype, description, 0);
- if (!IS_ERR(key_ref))
- goto found_matching_key;
+ if (ktype->update) {
+ key_ref = __keyring_search_one(keyring_ref, ktype, description,
+ 0);
+ if (!IS_ERR(key_ref))
+ goto found_matching_key;
+ }
/* decide on the permissions we want */
perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
diff --git a/security/security.c b/security/security.c
index f693e1f66b98..51ef509710b9 100644
--- a/security/security.c
+++ b/security/security.c
@@ -174,31 +174,8 @@ int mod_unreg_security(const char *name, struct security_operations *ops)
return security_ops->unregister_security(name, ops);
}
-/**
- * capable - calls the currently loaded security module's capable() function with the specified capability
- * @cap: the requested capability level.
- *
- * This function calls the currently loaded security module's capable()
- * function with a pointer to the current task and the specified @cap value.
- *
- * This allows the security module to implement the capable function call
- * however it chooses to.
- */
-int capable(int cap)
-{
- if (security_ops->capable(current, cap)) {
- /* capability denied */
- return 0;
- }
-
- /* capability granted */
- current->flags |= PF_SUPERPRIV;
- return 1;
-}
-
EXPORT_SYMBOL_GPL(register_security);
EXPORT_SYMBOL_GPL(unregister_security);
EXPORT_SYMBOL_GPL(mod_reg_security);
EXPORT_SYMBOL_GPL(mod_unreg_security);
-EXPORT_SYMBOL(capable);
EXPORT_SYMBOL(security_ops);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index ccaf988f3729..b61b9554bc27 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -119,6 +119,32 @@ static DEFINE_SPINLOCK(sb_security_lock);
static kmem_cache_t *sel_inode_cache;
+/* Return security context for a given sid or just the context
+ length if the buffer is null or length is 0 */
+static int selinux_getsecurity(u32 sid, void *buffer, size_t size)
+{
+ char *context;
+ unsigned len;
+ int rc;
+
+ rc = security_sid_to_context(sid, &context, &len);
+ if (rc)
+ return rc;
+
+ if (!buffer || !size)
+ goto getsecurity_exit;
+
+ if (size < len) {
+ len = -ERANGE;
+ goto getsecurity_exit;
+ }
+ memcpy(buffer, context, len);
+
+getsecurity_exit:
+ kfree(context);
+ return len;
+}
+
/* Allocate and free functions for each kind of security blob. */
static int task_alloc_security(struct task_struct *task)
@@ -2210,6 +2236,11 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name)
return -EACCES;
}
+static const char *selinux_inode_xattr_getsuffix(void)
+{
+ return XATTR_SELINUX_SUFFIX;
+}
+
/*
* Copy the in-core inode security context value to the user. If the
* getxattr() prior to this succeeded, check to see if we need to
@@ -2217,47 +2248,14 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name)
*
* Permission check is handled by selinux_inode_getxattr hook.
*/
-static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err)
+static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
{
struct inode_security_struct *isec = inode->i_security;
- char *context;
- unsigned len;
- int rc;
-
- if (strcmp(name, XATTR_SELINUX_SUFFIX)) {
- rc = -EOPNOTSUPP;
- goto out;
- }
-
- rc = security_sid_to_context(isec->sid, &context, &len);
- if (rc)
- goto out;
-
- /* Probe for required buffer size */
- if (!buffer || !size) {
- rc = len;
- goto out_free;
- }
- if (size < len) {
- rc = -ERANGE;
- goto out_free;
- }
+ if (strcmp(name, XATTR_SELINUX_SUFFIX))
+ return -EOPNOTSUPP;
- if (err > 0) {
- if ((len == err) && !(memcmp(context, buffer, len))) {
- /* Don't need to canonicalize value */
- rc = err;
- goto out_free;
- }
- memset(buffer, 0, size);
- }
- memcpy(buffer, context, len);
- rc = len;
-out_free:
- kfree(context);
-out:
- return rc;
+ return selinux_getsecurity(isec->sid, buffer, size);
}
static int selinux_inode_setsecurity(struct inode *inode, const char *name,
@@ -4054,6 +4052,13 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
return ipc_has_perm(ipcp, av);
}
+static int selinux_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
+{
+ struct ipc_security_struct *isec = ipcp->security;
+
+ return selinux_getsecurity(isec->sid, buffer, size);
+}
+
/* module stacking operations */
static int selinux_register_security (const char *name, struct security_operations *ops)
{
@@ -4095,8 +4100,7 @@ static int selinux_getprocattr(struct task_struct *p,
char *name, void *value, size_t size)
{
struct task_security_struct *tsec;
- u32 sid, len;
- char *context;
+ u32 sid;
int error;
if (current != p) {
@@ -4105,9 +4109,6 @@ static int selinux_getprocattr(struct task_struct *p,
return error;
}
- if (!size)
- return -ERANGE;
-
tsec = p->security;
if (!strcmp(name, "current"))
@@ -4124,16 +4125,7 @@ static int selinux_getprocattr(struct task_struct *p,
if (!sid)
return 0;
- error = security_sid_to_context(sid, &context, &len);
- if (error)
- return error;
- if (len > size) {
- kfree(context);
- return -ERANGE;
- }
- memcpy(value, context, len);
- kfree(context);
- return len;
+ return selinux_getsecurity(sid, value, size);
}
static int selinux_setprocattr(struct task_struct *p,
@@ -4291,6 +4283,7 @@ static struct security_operations selinux_ops = {
.inode_getxattr = selinux_inode_getxattr,
.inode_listxattr = selinux_inode_listxattr,
.inode_removexattr = selinux_inode_removexattr,
+ .inode_xattr_getsuffix = selinux_inode_xattr_getsuffix,
.inode_getsecurity = selinux_inode_getsecurity,
.inode_setsecurity = selinux_inode_setsecurity,
.inode_listsecurity = selinux_inode_listsecurity,
@@ -4328,6 +4321,7 @@ static struct security_operations selinux_ops = {
.task_to_inode = selinux_task_to_inode,
.ipc_permission = selinux_ipc_permission,
+ .ipc_getsecurity = selinux_ipc_getsecurity,
.msg_msg_alloc_security = selinux_msg_msg_alloc_security,
.msg_msg_free_security = selinux_msg_msg_free_security,
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index 85e399259832..b8f4d25cf335 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -106,6 +106,9 @@ static struct nlmsg_perm nlmsg_audit_perms[] =
{ AUDIT_LIST, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV },
{ AUDIT_ADD, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
{ AUDIT_DEL, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
+ { AUDIT_LIST_RULES, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV },
+ { AUDIT_ADD_RULE, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
+ { AUDIT_DEL_RULE, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
{ AUDIT_USER, NETLINK_AUDIT_SOCKET__NLMSG_RELAY },
{ AUDIT_SIGNAL_INFO, NETLINK_AUDIT_SOCKET__NLMSG_READ },
};
@@ -152,8 +155,10 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
break;
case SECCLASS_NETLINK_AUDIT_SOCKET:
- if (nlmsg_type >= AUDIT_FIRST_USER_MSG &&
- nlmsg_type <= AUDIT_LAST_USER_MSG) {
+ if ((nlmsg_type >= AUDIT_FIRST_USER_MSG &&
+ nlmsg_type <= AUDIT_LAST_USER_MSG) ||
+ (nlmsg_type >= AUDIT_FIRST_USER_MSG2 &&
+ nlmsg_type <= AUDIT_LAST_USER_MSG2)) {
*perm = NETLINK_AUDIT_SOCKET__NLMSG_RELAY;
} else {
err = nlmsg_perm(nlmsg_type, perm, nlmsg_audit_perms,
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index f5d78365488f..a4efc966f065 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -22,6 +22,7 @@
#include <linux/major.h>
#include <linux/seq_file.h>
#include <linux/percpu.h>
+#include <linux/audit.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
@@ -127,6 +128,10 @@ static ssize_t sel_write_enforce(struct file * file, const char __user * buf,
length = task_has_security(current, SECURITY__SETENFORCE);
if (length)
goto out;
+ audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
+ "enforcing=%d old_enforcing=%d auid=%u", new_value,
+ selinux_enforcing,
+ audit_get_loginuid(current->audit_context));
selinux_enforcing = new_value;
if (selinux_enforcing)
avc_ss_reset(0);
@@ -177,6 +182,9 @@ static ssize_t sel_write_disable(struct file * file, const char __user * buf,
length = selinux_disable();
if (length < 0)
goto out;
+ audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
+ "selinux=0 auid=%u",
+ audit_get_loginuid(current->audit_context));
}
length = count;
@@ -262,6 +270,9 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
length = ret;
else
length = count;
+ audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
+ "policy loaded auid=%u",
+ audit_get_loginuid(current->audit_context));
out:
mutex_unlock(&sel_mutex);
vfree(data);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 63e0b7f29cb5..61492485de84 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1759,19 +1759,22 @@ int security_set_bools(int len, int *values)
goto out;
}
- printk(KERN_INFO "security: committed booleans { ");
for (i = 0; i < len; i++) {
+ if (!!values[i] != policydb.bool_val_to_struct[i]->state) {
+ audit_log(current->audit_context, GFP_ATOMIC,
+ AUDIT_MAC_CONFIG_CHANGE,
+ "bool=%s val=%d old_val=%d auid=%u",
+ policydb.p_bool_val_to_name[i],
+ !!values[i],
+ policydb.bool_val_to_struct[i]->state,
+ audit_get_loginuid(current->audit_context));
+ }
if (values[i]) {
policydb.bool_val_to_struct[i]->state = 1;
} else {
policydb.bool_val_to_struct[i]->state = 0;
}
- if (i != 0)
- printk(", ");
- printk("%s:%d", policydb.p_bool_val_to_name[i],
- policydb.bool_val_to_struct[i]->state);
}
- printk(" }\n");
for (cur = policydb.cond_list; cur != NULL; cur = cur->next) {
rc = evaluate_cond_node(&policydb, cur);