diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/commoncap.c | 4 | ||||
-rw-r--r-- | security/dummy.c | 14 | ||||
-rw-r--r-- | security/keys/key.c | 18 | ||||
-rw-r--r-- | security/security.c | 23 | ||||
-rw-r--r-- | security/selinux/hooks.c | 98 | ||||
-rw-r--r-- | security/selinux/nlmsgtab.c | 9 | ||||
-rw-r--r-- | security/selinux/selinuxfs.c | 11 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 15 |
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); |