summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--security/dummy.c27
-rw-r--r--security/keys/Makefile1
-rw-r--r--security/keys/internal.h26
-rw-r--r--security/keys/key.c128
-rw-r--r--security/keys/keyctl.c306
-rw-r--r--security/keys/keyring.c91
-rw-r--r--security/keys/permission.c75
-rw-r--r--security/keys/proc.c2
-rw-r--r--security/keys/process_keys.c167
-rw-r--r--security/keys/request_key.c38
-rw-r--r--security/keys/request_key_auth.c5
-rw-r--r--security/keys/user_defined.c49
-rw-r--r--security/selinux/hooks.c115
-rw-r--r--security/selinux/netif.c3
-rw-r--r--security/selinux/selinuxfs.c97
-rw-r--r--security/selinux/ss/conditional.c12
-rw-r--r--security/selinux/ss/ebitmap.c9
-rw-r--r--security/selinux/ss/hashtab.c6
-rw-r--r--security/selinux/ss/mls.c5
-rw-r--r--security/selinux/ss/policydb.c69
-rw-r--r--security/selinux/ss/services.c11
21 files changed, 723 insertions, 519 deletions
diff --git a/security/dummy.c b/security/dummy.c
index 9623a61dfc76..3ca5f2b828a0 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -377,7 +377,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)
+static int dummy_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err)
{
return -EOPNOTSUPP;
}
@@ -768,7 +768,7 @@ static int dummy_socket_getpeersec(struct socket *sock, char __user *optval,
return -ENOPROTOOPT;
}
-static inline int dummy_sk_alloc_security (struct sock *sk, int family, int priority)
+static inline int dummy_sk_alloc_security (struct sock *sk, int family, gfp_t priority)
{
return 0;
}
@@ -803,6 +803,23 @@ static int dummy_setprocattr(struct task_struct *p, char *name, void *value, siz
return -EINVAL;
}
+#ifdef CONFIG_KEYS
+static inline int dummy_key_alloc(struct key *key)
+{
+ return 0;
+}
+
+static inline void dummy_key_free(struct key *key)
+{
+}
+
+static inline int dummy_key_permission(key_ref_t key_ref,
+ struct task_struct *context,
+ key_perm_t perm)
+{
+ return 0;
+}
+#endif /* CONFIG_KEYS */
struct security_operations dummy_security_ops;
@@ -954,5 +971,11 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, sk_alloc_security);
set_to_dummy_if_null(ops, sk_free_security);
#endif /* CONFIG_SECURITY_NETWORK */
+#ifdef CONFIG_KEYS
+ set_to_dummy_if_null(ops, key_alloc);
+ set_to_dummy_if_null(ops, key_free);
+ set_to_dummy_if_null(ops, key_permission);
+#endif /* CONFIG_KEYS */
+
}
diff --git a/security/keys/Makefile b/security/keys/Makefile
index c392d750b208..5145adfb6a05 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -6,6 +6,7 @@ obj-y := \
key.o \
keyring.o \
keyctl.o \
+ permission.o \
process_keys.o \
request_key.o \
request_key_auth.o \
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 46c8602661c9..db99ed434f3a 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -71,26 +71,26 @@ extern void keyring_publish_name(struct key *keyring);
extern int __key_link(struct key *keyring, struct key *key);
-extern struct key *__keyring_search_one(struct key *keyring,
- const struct key_type *type,
- const char *description,
- key_perm_t perm);
+extern key_ref_t __keyring_search_one(key_ref_t keyring_ref,
+ const struct key_type *type,
+ const char *description,
+ key_perm_t perm);
extern struct key *keyring_search_instkey(struct key *keyring,
key_serial_t target_id);
typedef int (*key_match_func_t)(const struct key *, const void *);
-extern struct key *keyring_search_aux(struct key *keyring,
- struct task_struct *tsk,
- struct key_type *type,
- const void *description,
- key_match_func_t match);
+extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,
+ struct task_struct *tsk,
+ struct key_type *type,
+ const void *description,
+ key_match_func_t match);
-extern struct key *search_process_keyrings(struct key_type *type,
- const void *description,
- key_match_func_t match,
- struct task_struct *tsk);
+extern key_ref_t search_process_keyrings(struct key_type *type,
+ const void *description,
+ key_match_func_t match,
+ struct task_struct *tsk);
extern struct key *find_keyring_by_name(const char *name, key_serial_t bound);
diff --git a/security/keys/key.c b/security/keys/key.c
index fb89f9844465..01bcfecb7eae 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-5 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/security.h>
#include <linux/workqueue.h>
#include <linux/err.h>
#include "internal.h"
@@ -114,8 +115,7 @@ struct key_user *key_user_lookup(uid_t uid)
found:
atomic_inc(&user->usage);
spin_unlock(&key_user_lock);
- if (candidate)
- kfree(candidate);
+ kfree(candidate);
out:
return user;
@@ -253,6 +253,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
struct key_user *user = NULL;
struct key *key;
size_t desclen, quotalen;
+ int ret;
key = ERR_PTR(-EINVAL);
if (!desc || !*desc)
@@ -305,6 +306,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
key->flags = 0;
key->expiry = 0;
key->payload.data = NULL;
+ key->security = NULL;
if (!not_in_quota)
key->flags |= 1 << KEY_FLAG_IN_QUOTA;
@@ -315,16 +317,21 @@ struct key *key_alloc(struct key_type *type, const char *desc,
key->magic = KEY_DEBUG_MAGIC;
#endif
+ /* let the security module know about the key */
+ ret = security_key_alloc(key);
+ if (ret < 0)
+ goto security_error;
+
/* publish the key by giving it a serial number */
atomic_inc(&user->nkeys);
key_alloc_serial(key);
- error:
+error:
return key;
- no_memory_3:
+security_error:
+ kfree(key->description);
kmem_cache_free(key_jar, key);
- no_memory_2:
if (!not_in_quota) {
spin_lock(&user->lock);
user->qnkeys--;
@@ -332,11 +339,24 @@ struct key *key_alloc(struct key_type *type, const char *desc,
spin_unlock(&user->lock);
}
key_user_put(user);
- no_memory_1:
+ key = ERR_PTR(ret);
+ goto error;
+
+no_memory_3:
+ kmem_cache_free(key_jar, key);
+no_memory_2:
+ if (!not_in_quota) {
+ spin_lock(&user->lock);
+ user->qnkeys--;
+ user->qnbytes -= quotalen;
+ spin_unlock(&user->lock);
+ }
+ key_user_put(user);
+no_memory_1:
key = ERR_PTR(-ENOMEM);
goto error;
- no_quota:
+no_quota:
spin_unlock(&user->lock);
key_user_put(user);
key = ERR_PTR(-EDQUOT);
@@ -556,6 +576,8 @@ static void key_cleanup(void *data)
key_check(key);
+ security_key_free(key);
+
/* deal with the user's key tracking and quota */
if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
spin_lock(&key->user->lock);
@@ -693,14 +715,15 @@ void key_type_put(struct key_type *ktype)
* - the key has an incremented refcount
* - we need to put the key if we get an error
*/
-static inline struct key *__key_update(struct key *key, const void *payload,
- size_t plen)
+static inline key_ref_t __key_update(key_ref_t key_ref,
+ const void *payload, size_t plen)
{
+ struct key *key = key_ref_to_ptr(key_ref);
int ret;
/* need write permission on the key to update it */
- ret = -EACCES;
- if (!key_permission(key, KEY_WRITE))
+ ret = key_permission(key_ref, KEY_WRITE);
+ if (ret < 0)
goto error;
ret = -EEXIST;
@@ -710,7 +733,6 @@ static inline struct key *__key_update(struct key *key, const void *payload,
down_write(&key->sem);
ret = key->type->update(key, payload, plen);
-
if (ret == 0)
/* updating a negative key instantiates it */
clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
@@ -719,12 +741,12 @@ static inline struct key *__key_update(struct key *key, const void *payload,
if (ret < 0)
goto error;
- out:
- return key;
+out:
+ return key_ref;
- error:
+error:
key_put(key);
- key = ERR_PTR(ret);
+ key_ref = ERR_PTR(ret);
goto out;
} /* end __key_update() */
@@ -734,52 +756,58 @@ static inline struct key *__key_update(struct key *key, const void *payload,
* search the specified keyring for a key of the same description; if one is
* found, update it, otherwise add a new one
*/
-struct key *key_create_or_update(struct key *keyring,
- const char *type,
- const char *description,
- const void *payload,
- size_t plen,
- int not_in_quota)
+key_ref_t key_create_or_update(key_ref_t keyring_ref,
+ const char *type,
+ const char *description,
+ const void *payload,
+ size_t plen,
+ int not_in_quota)
{
struct key_type *ktype;
- struct key *key = NULL;
+ struct key *keyring, *key = NULL;
key_perm_t perm;
+ key_ref_t key_ref;
int ret;
- key_check(keyring);
-
/* look up the key type to see if it's one of the registered kernel
* types */
ktype = key_type_lookup(type);
if (IS_ERR(ktype)) {
- key = ERR_PTR(-ENODEV);
+ key_ref = ERR_PTR(-ENODEV);
goto error;
}
- ret = -EINVAL;
+ key_ref = ERR_PTR(-EINVAL);
if (!ktype->match || !ktype->instantiate)
goto error_2;
+ keyring = key_ref_to_ptr(keyring_ref);
+
+ key_check(keyring);
+
+ down_write(&keyring->sem);
+
+ /* if we're going to allocate a new key, we're going to have
+ * to modify the keyring */
+ ret = key_permission(keyring_ref, KEY_WRITE);
+ if (ret < 0) {
+ key_ref = ERR_PTR(ret);
+ goto error_3;
+ }
+
/* search for an existing key of the same type and description in the
* destination keyring
*/
- down_write(&keyring->sem);
-
- key = __keyring_search_one(keyring, ktype, description, 0);
- if (!IS_ERR(key))
+ key_ref = __keyring_search_one(keyring_ref, ktype, description, 0);
+ if (!IS_ERR(key_ref))
goto found_matching_key;
- /* if we're going to allocate a new key, we're going to have to modify
- * the keyring */
- ret = -EACCES;
- if (!key_permission(keyring, KEY_WRITE))
- goto error_3;
-
/* decide on the permissions we want */
- perm = KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK;
+ perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
+ perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR;
if (ktype->read)
- perm |= KEY_USR_READ;
+ perm |= KEY_POS_READ | KEY_USR_READ;
if (ktype == &key_type_keyring || ktype->update)
perm |= KEY_USR_WRITE;
@@ -788,7 +816,7 @@ struct key *key_create_or_update(struct key *keyring,
key = key_alloc(ktype, description, current->fsuid, current->fsgid,
perm, not_in_quota);
if (IS_ERR(key)) {
- ret = PTR_ERR(key);
+ key_ref = ERR_PTR(PTR_ERR(key));
goto error_3;
}
@@ -796,15 +824,18 @@ struct key *key_create_or_update(struct key *keyring,
ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL);
if (ret < 0) {
key_put(key);
- key = ERR_PTR(ret);
+ key_ref = ERR_PTR(ret);
+ goto error_3;
}
+ key_ref = make_key_ref(key, is_key_possessed(keyring_ref));
+
error_3:
up_write(&keyring->sem);
error_2:
key_type_put(ktype);
error:
- return key;
+ return key_ref;
found_matching_key:
/* we found a matching key, so we're going to try to update it
@@ -813,7 +844,7 @@ struct key *key_create_or_update(struct key *keyring,
up_write(&keyring->sem);
key_type_put(ktype);
- key = __key_update(key, payload, plen);
+ key_ref = __key_update(key_ref, payload, plen);
goto error;
} /* end key_create_or_update() */
@@ -824,23 +855,24 @@ EXPORT_SYMBOL(key_create_or_update);
/*
* update a key
*/
-int key_update(struct key *key, const void *payload, size_t plen)
+int key_update(key_ref_t key_ref, const void *payload, size_t plen)
{
+ struct key *key = key_ref_to_ptr(key_ref);
int ret;
key_check(key);
/* the key must be writable */
- ret = -EACCES;
- if (!key_permission(key, KEY_WRITE))
+ ret = key_permission(key_ref, KEY_WRITE);
+ if (ret < 0)
goto error;
/* attempt to update it if supported */
ret = -EOPNOTSUPP;
if (key->type->update) {
down_write(&key->sem);
- ret = key->type->update(key, payload, plen);
+ ret = key->type->update(key, payload, plen);
if (ret == 0)
/* updating a negative key instantiates it */
clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index a6516a64b297..b7a468fabdf9 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -34,7 +34,7 @@ asmlinkage long sys_add_key(const char __user *_type,
size_t plen,
key_serial_t ringid)
{
- struct key *keyring, *key;
+ key_ref_t keyring_ref, key_ref;
char type[32], *description;
void *payload;
long dlen, ret;
@@ -86,25 +86,25 @@ asmlinkage long sys_add_key(const char __user *_type,
}
/* find the target keyring (which must be writable) */
- keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
- if (IS_ERR(keyring)) {
- ret = PTR_ERR(keyring);
+ keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
+ if (IS_ERR(keyring_ref)) {
+ ret = PTR_ERR(keyring_ref);
goto error3;
}
/* create or update the requested key and add it to the target
* keyring */
- key = key_create_or_update(keyring, type, description,
- payload, plen, 0);
- if (!IS_ERR(key)) {
- ret = key->serial;
- key_put(key);
+ key_ref = key_create_or_update(keyring_ref, type, description,
+ payload, plen, 0);
+ if (!IS_ERR(key_ref)) {
+ ret = key_ref_to_ptr(key_ref)->serial;
+ key_ref_put(key_ref);
}
else {
- ret = PTR_ERR(key);
+ ret = PTR_ERR(key_ref);
}
- key_put(keyring);
+ key_ref_put(keyring_ref);
error3:
kfree(payload);
error2:
@@ -131,7 +131,8 @@ asmlinkage long sys_request_key(const char __user *_type,
key_serial_t destringid)
{
struct key_type *ktype;
- struct key *key, *dest;
+ struct key *key;
+ key_ref_t dest_ref;
char type[32], *description, *callout_info;
long dlen, ret;
@@ -187,11 +188,11 @@ asmlinkage long sys_request_key(const char __user *_type,
}
/* get the destination keyring if specified */
- dest = NULL;
+ dest_ref = NULL;
if (destringid) {
- dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
- if (IS_ERR(dest)) {
- ret = PTR_ERR(dest);
+ dest_ref = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
+ if (IS_ERR(dest_ref)) {
+ ret = PTR_ERR(dest_ref);
goto error3;
}
}
@@ -204,7 +205,8 @@ asmlinkage long sys_request_key(const char __user *_type,
}
/* do the search */
- key = request_key_and_link(ktype, description, callout_info, dest);
+ key = request_key_and_link(ktype, description, callout_info,
+ key_ref_to_ptr(dest_ref));
if (IS_ERR(key)) {
ret = PTR_ERR(key);
goto error5;
@@ -216,7 +218,7 @@ asmlinkage long sys_request_key(const char __user *_type,
error5:
key_type_put(ktype);
error4:
- key_put(dest);
+ key_ref_put(dest_ref);
error3:
kfree(callout_info);
error2:
@@ -234,17 +236,17 @@ asmlinkage long sys_request_key(const char __user *_type,
*/
long keyctl_get_keyring_ID(key_serial_t id, int create)
{
- struct key *key;
+ key_ref_t key_ref;
long ret;
- key = lookup_user_key(NULL, id, create, 0, KEY_SEARCH);
- if (IS_ERR(key)) {
- ret = PTR_ERR(key);
+ key_ref = lookup_user_key(NULL, id, create, 0, KEY_SEARCH);
+ if (IS_ERR(key_ref)) {
+ ret = PTR_ERR(key_ref);
goto error;
}
- ret = key->serial;
- key_put(key);
+ ret = key_ref_to_ptr(key_ref)->serial;
+ key_ref_put(key_ref);
error:
return ret;
@@ -302,7 +304,7 @@ long keyctl_update_key(key_serial_t id,
const void __user *_payload,
size_t plen)
{
- struct key *key;
+ key_ref_t key_ref;
void *payload;
long ret;
@@ -324,16 +326,16 @@ long keyctl_update_key(key_serial_t id,
}
/* find the target key (which must be writable) */
- key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE);
- if (IS_ERR(key)) {
- ret = PTR_ERR(key);
+ key_ref = lookup_user_key(NULL, id, 0, 0, KEY_WRITE);
+ if (IS_ERR(key_ref)) {
+ ret = PTR_ERR(key_ref);
goto error2;
}
/* update the key */
- ret = key_update(key, payload, plen);
+ ret = key_update(key_ref, payload, plen);
- key_put(key);
+ key_ref_put(key_ref);
error2:
kfree(payload);
error:
@@ -349,19 +351,19 @@ long keyctl_update_key(key_serial_t id,
*/
long keyctl_revoke_key(key_serial_t id)
{
- struct key *key;
+ key_ref_t key_ref;
long ret;
- key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE);
- if (IS_ERR(key)) {
- ret = PTR_ERR(key);
+ key_ref = lookup_user_key(NULL, id, 0, 0, KEY_WRITE);
+ if (IS_ERR(key_ref)) {
+ ret = PTR_ERR(key_ref);
goto error;
}
- key_revoke(key);
+ key_revoke(key_ref_to_ptr(key_ref));
ret = 0;
- key_put(key);
+ key_ref_put(key_ref);
error:
return ret;
@@ -375,18 +377,18 @@ long keyctl_revoke_key(key_serial_t id)
*/
long keyctl_keyring_clear(key_serial_t ringid)
{
- struct key *keyring;
+ key_ref_t keyring_ref;
long ret;
- keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
- if (IS_ERR(keyring)) {
- ret = PTR_ERR(keyring);
+ keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
+ if (IS_ERR(keyring_ref)) {
+ ret = PTR_ERR(keyring_ref);
goto error;
}
- ret = keyring_clear(keyring);
+ ret = keyring_clear(key_ref_to_ptr(keyring_ref));
- key_put(keyring);
+ key_ref_put(keyring_ref);
error:
return ret;
@@ -401,26 +403,26 @@ long keyctl_keyring_clear(key_serial_t ringid)
*/
long keyctl_keyring_link(key_serial_t id, key_serial_t ringid)
{
- struct key *keyring, *key;
+ key_ref_t keyring_ref, key_ref;
long ret;
- keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
- if (IS_ERR(keyring)) {
- ret = PTR_ERR(keyring);
+ keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
+ if (IS_ERR(keyring_ref)) {
+ ret = PTR_ERR(keyring_ref);
goto error;
}
- key = lookup_user_key(NULL, id, 1, 0, KEY_LINK);
- if (IS_ERR(key)) {
- ret = PTR_ERR(key);
+ key_ref = lookup_user_key(NULL, id, 1, 0, KEY_LINK);
+ if (IS_ERR(key_ref)) {
+ ret = PTR_ERR(key_ref);
goto error2;
}
- ret = key_link(keyring, key);
+ ret = key_link(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref));
- key_put(key);
+ key_ref_put(key_ref);
error2:
- key_put(keyring);
+ key_ref_put(keyring_ref);
error:
return ret;
@@ -435,26 +437,26 @@ long keyctl_keyring_link(key_serial_t id, key_serial_t ringid)
*/
long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid)
{
- struct key *keyring, *key;
+ key_ref_t keyring_ref, key_ref;
long ret;
- keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_WRITE);
- if (IS_ERR(keyring)) {
- ret = PTR_ERR(keyring);
+ keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_WRITE);
+ if (IS_ERR(keyring_ref)) {
+ ret = PTR_ERR(keyring_ref);
goto error;
}
- key = lookup_user_key(NULL, id, 0, 0, 0);
- if (IS_ERR(key)) {
- ret = PTR_ERR(key);
+ key_ref = lookup_user_key(NULL, id, 0, 0, 0);
+ if (IS_ERR(key_ref)) {
+ ret = PTR_ERR(key_ref);
goto error2;
}
- ret = key_unlink(keyring, key);
+ ret = key_unlink(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref));
- key_put(key);
+ key_ref_put(key_ref);
error2:
- key_put(keyring);
+ key_ref_put(keyring_ref);
error:
return ret;
@@ -476,24 +478,26 @@ long keyctl_describe_key(key_serial_t keyid,
size_t buflen)
{
struct key *key, *instkey;
+ key_ref_t key_ref;
char *tmpbuf;
long ret;
- key = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW);
- if (IS_ERR(key)) {
+ key_ref = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW);
+ if (IS_ERR(key_ref)) {
/* viewing a key under construction is permitted if we have the
* authorisation token handy */
- if (PTR_ERR(key) == -EACCES) {
+ if (PTR_ERR(key_ref) == -EACCES) {
instkey = key_get_instantiation_authkey(keyid);
if (!IS_ERR(instkey)) {
key_put(instkey);
- key = lookup_user_key(NULL, keyid, 0, 1, 0);
- if (!IS_ERR(key))
+ key_ref = lookup_user_key(NULL, keyid,
+ 0, 1, 0);
+ if (!IS_ERR(key_ref))
goto okay;
}
}
- ret = PTR_ERR(key);
+ ret = PTR_ERR(key_ref);
goto error;
}
@@ -504,13 +508,16 @@ okay:
if (!tmpbuf)
goto error2;
+ key = key_ref_to_ptr(key_ref);
+
ret = snprintf(tmpbuf, PAGE_SIZE - 1,
- "%s;%d;%d;%06x;%s",
- key->type->name,
- key->uid,
- key->gid,
- key->perm,
- key->description ? key->description :""
+ "%s;%d;%d;%08x;%s",
+ key_ref_to_ptr(key_ref)->type->name,
+ key_ref_to_ptr(key_ref)->uid,
+ key_ref_to_ptr(key_ref)->gid,
+ key_ref_to_ptr(key_ref)->perm,
+ key_ref_to_ptr(key_ref)->description ?
+ key_ref_to_ptr(key_ref)->description : ""
);
/* include a NUL char at the end of the data */
@@ -530,7 +537,7 @@ okay:
kfree(tmpbuf);
error2:
- key_put(key);
+ key_ref_put(key_ref);
error:
return ret;
@@ -552,7 +559,7 @@ long keyctl_keyring_search(key_serial_t ringid,
key_serial_t destringid)
{
struct key_type *ktype;
- struct key *keyring, *key, *dest;
+ key_ref_t keyring_ref, key_ref, dest_ref;
char type[32], *description;
long dlen, ret;
@@ -581,18 +588,18 @@ long keyctl_keyring_search(key_serial_t ringid,
goto error2;
/* get the keyring at which to begin the search */
- keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH);
- if (IS_ERR(keyring)) {
- ret = PTR_ERR(keyring);
+ keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH);
+ if (IS_ERR(keyring_ref)) {
+ ret = PTR_ERR(keyring_ref);
goto error2;
}
/* get the destination keyring if specified */
- dest = NULL;
+ dest_ref = NULL;
if (destringid) {
- dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
- if (IS_ERR(dest)) {
- ret = PTR_ERR(dest);
+ dest_ref = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
+ if (IS_ERR(dest_ref)) {
+ ret = PTR_ERR(dest_ref);
goto error3;
}
}
@@ -605,9 +612,9 @@ long keyctl_keyring_search(key_serial_t ringid,
}
/* do the search */
- key = keyring_search(keyring, ktype, description);
- if (IS_ERR(key)) {
- ret = PTR_ERR(key);
+ key_ref = keyring_search(keyring_ref, ktype, description);
+ if (IS_ERR(key_ref)) {
+ ret = PTR_ERR(key_ref);
/* treat lack or presence of a negative key the same */
if (ret == -EAGAIN)
@@ -616,26 +623,26 @@ long keyctl_keyring_search(key_serial_t ringid,
}
/* link the resulting key to the destination keyring if we can */
- if (dest) {
- ret = -EACCES;
- if (!key_permission(key, KEY_LINK))
+ if (dest_ref) {
+ ret = key_permission(key_ref, KEY_LINK);
+ if (ret < 0)
goto error6;
- ret = key_link(dest, key);
+ ret = key_link(key_ref_to_ptr(dest_ref), key_ref_to_ptr(key_ref));
if (ret < 0)
goto error6;
}
- ret = key->serial;
+ ret = key_ref_to_ptr(key_ref)->serial;
error6:
- key_put(key);
+ key_ref_put(key_ref);
error5:
key_type_put(ktype);
error4:
- key_put(dest);
+ key_ref_put(dest_ref);
error3:
- key_put(keyring);
+ key_ref_put(keyring_ref);
error2:
kfree(description);
error:
@@ -645,16 +652,6 @@ long keyctl_keyring_search(key_serial_t ringid,
/*****************************************************************************/
/*
- * see if the key we're looking at is the target key
- */
-static int keyctl_read_key_same(const struct key *key, const void *target)
-{
- return key == target;
-
-} /* end keyctl_read_key_same() */
-
-/*****************************************************************************/
-/*
* read a user key's payload
* - the keyring must be readable or the key must be searchable from the
* process's keyrings
@@ -665,38 +662,36 @@ static int keyctl_read_key_same(const struct key *key, const void *target)
*/
long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
{
- struct key *key, *skey;
+ struct key *key;
+ key_ref_t key_ref;
long ret;
/* find the key first */
- key = lookup_user_key(NULL, keyid, 0, 0, 0);
- if (!IS_ERR(key)) {
- /* see if we can read it directly */
- if (key_permission(key, KEY_READ))
- goto can_read_key;
-
- /* we can't; see if it's searchable from this process's
- * keyrings
- * - we automatically take account of the fact that it may be
- * dangling off an instantiation key
- */
- skey = search_process_keyrings(key->type, key,
- keyctl_read_key_same, current);
- if (!IS_ERR(skey))
- goto can_read_key2;
-
- ret = PTR_ERR(skey);
- if (ret == -EAGAIN)
- ret = -EACCES;
- goto error2;
+ key_ref = lookup_user_key(NULL, keyid, 0, 0, 0);
+ if (IS_ERR(key_ref)) {
+ ret = -ENOKEY;
+ goto error;
}
- ret = -ENOKEY;
- goto error;
+ key = key_ref_to_ptr(key_ref);
+
+ /* see if we can read it directly */
+ ret = key_permission(key_ref, KEY_READ);
+ if (ret == 0)
+ goto can_read_key;
+ if (ret != -EACCES)
+ goto error;
+
+ /* we can't; see if it's searchable from this process's keyrings
+ * - we automatically take account of the fact that it may be
+ * dangling off an instantiation key
+ */
+ if (!is_key_possessed(key_ref)) {
+ ret = -EACCES;
+ goto error2;
+ }
/* the key is probably readable - now try to read it */
- can_read_key2:
- key_put(skey);
can_read_key:
ret = key_validate(key);
if (ret == 0) {
@@ -727,18 +722,21 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
{
struct key *key;
+ key_ref_t key_ref;
long ret;
ret = 0;
if (uid == (uid_t) -1 && gid == (gid_t) -1)
goto error;
- key = lookup_user_key(NULL, id, 1, 1, 0);
- if (IS_ERR(key)) {
- ret = PTR_ERR(key);
+ key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR);
+ if (IS_ERR(key_ref)) {
+ ret = PTR_ERR(key_ref);
goto error;
}
+ key = key_ref_to_ptr(key_ref);
+
/* make the changes with the locks held to prevent chown/chown races */
ret = -EACCES;
down_write(&key->sem);
@@ -784,18 +782,21 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
{
struct key *key;
+ key_ref_t key_ref;
long ret;
ret = -EINVAL;
- if (perm & ~(KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL))
+ if (perm & ~(KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL))
goto error;
- key = lookup_user_key(NULL, id, 1, 1, 0);
- if (IS_ERR(key)) {
- ret = PTR_ERR(key);
+ key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR);
+ if (IS_ERR(key_ref)) {
+ ret = PTR_ERR(key_ref);
goto error;
}
+ key = key_ref_to_ptr(key_ref);
+
/* make the changes with the locks held to prevent chown/chmod races */
ret = -EACCES;
down_write(&key->sem);
@@ -824,7 +825,8 @@ long keyctl_instantiate_key(key_serial_t id,
key_serial_t ringid)
{
struct request_key_auth *rka;
- struct key *instkey, *keyring;
+ struct key *instkey;
+ key_ref_t keyring_ref;
void *payload;
long ret;
@@ -857,21 +859,21 @@ long keyctl_instantiate_key(key_serial_t id,
/* find the destination keyring amongst those belonging to the
* requesting task */
- keyring = NULL;
+ keyring_ref = NULL;
if (ringid) {
- keyring = lookup_user_key(rka->context, ringid, 1, 0,
- KEY_WRITE);
- if (IS_ERR(keyring)) {
- ret = PTR_ERR(keyring);
+ keyring_ref = lookup_user_key(rka->context, ringid, 1, 0,
+ KEY_WRITE);
+ if (IS_ERR(keyring_ref)) {
+ ret = PTR_ERR(keyring_ref);
goto error3;
}
}
/* instantiate the key and link it into a keyring */
ret = key_instantiate_and_link(rka->target_key, payload, plen,
- keyring, instkey);
+ key_ref_to_ptr(keyring_ref), instkey);
- key_put(keyring);
+ key_ref_put(keyring_ref);
error3:
key_put(instkey);
error2:
@@ -889,7 +891,8 @@ long keyctl_instantiate_key(key_serial_t id,
long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
{
struct request_key_auth *rka;
- struct key *instkey, *keyring;
+ struct key *instkey;
+ key_ref_t keyring_ref;
long ret;
/* find the instantiation authorisation key */
@@ -903,19 +906,20 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
/* find the destination keyring if present (which must also be
* writable) */
- keyring = NULL;
+ keyring_ref = NULL;
if (ringid) {
- keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
- if (IS_ERR(keyring)) {
- ret = PTR_ERR(keyring);
+ keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
+ if (IS_ERR(keyring_ref)) {
+ ret = PTR_ERR(keyring_ref);
goto error2;
}
}
/* instantiate the key and link it into a keyring */
- ret = key_negate_and_link(rka->target_key, timeout, keyring, instkey);
+ ret = key_negate_and_link(rka->target_key, timeout,
+ key_ref_to_ptr(keyring_ref), instkey);
- key_put(keyring);
+ key_ref_put(keyring_ref);
error2:
key_put(instkey);
error:
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 9c208c756df8..4e9fa8be44b8 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/security.h>
#include <linux/seq_file.h>
#include <linux/err.h>
#include <asm/uaccess.h>
@@ -309,7 +310,9 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
int ret;
keyring = key_alloc(&key_type_keyring, description,
- uid, gid, KEY_USR_ALL, not_in_quota);
+ uid, gid,
+ (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
+ not_in_quota);
if (!IS_ERR(keyring)) {
ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL);
@@ -333,12 +336,13 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
* - we rely on RCU to prevent the keyring lists from disappearing on us
* - we return -EAGAIN if we didn't find any matching key
* - we return -ENOKEY if we only found negative matching keys
+ * - we propagate the possession attribute from the keyring ref to the key ref
*/
-struct key *keyring_search_aux(struct key *keyring,
- struct task_struct *context,
- struct key_type *type,
- const void *description,
- key_match_func_t match)
+key_ref_t keyring_search_aux(key_ref_t keyring_ref,
+ struct task_struct *context,
+ struct key_type *type,
+ const void *description,
+ key_match_func_t match)
{
struct {
struct keyring_list *keylist;
@@ -347,29 +351,35 @@ struct key *keyring_search_aux(struct key *keyring,
struct keyring_list *keylist;
struct timespec now;
- struct key *key;
+ unsigned long possessed;
+ struct key *keyring, *key;
+ key_ref_t key_ref;
long err;
int sp, kix;
+ keyring = key_ref_to_ptr(keyring_ref);
+ possessed = is_key_possessed(keyring_ref);
key_check(keyring);
- rcu_read_lock();
-
/* top keyring must have search permission to begin the search */
- key = ERR_PTR(-EACCES);
- if (!key_task_permission(keyring, context, KEY_SEARCH))
+ err = key_task_permission(keyring_ref, context, KEY_SEARCH);
+ if (err < 0) {
+ key_ref = ERR_PTR(err);
goto error;
+ }
- key = ERR_PTR(-ENOTDIR);
+ key_ref = ERR_PTR(-ENOTDIR);
if (keyring->type != &key_type_keyring)
goto error;
+ rcu_read_lock();
+
now = current_kernel_time();
err = -EAGAIN;
sp = 0;
/* start processing a new keyring */
- descend:
+descend:
if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
goto not_this_keyring;
@@ -397,7 +407,8 @@ struct key *keyring_search_aux(struct key *keyring,
continue;
/* key must have search permissions */
- if (!key_task_permission(key, context, KEY_SEARCH))
+ if (key_task_permission(make_key_ref(key, possessed),
+ context, KEY_SEARCH) < 0)
continue;
/* we set a different error code if we find a negative key */
@@ -411,7 +422,7 @@ struct key *keyring_search_aux(struct key *keyring,
/* search through the keyrings nested in this one */
kix = 0;
- ascend:
+ascend:
for (; kix < keylist->nkeys; kix++) {
key = keylist->keys[kix];
if (key->type != &key_type_keyring)
@@ -423,7 +434,8 @@ struct key *keyring_search_aux(struct key *keyring,
if (sp >= KEYRING_SEARCH_MAX_DEPTH)
continue;
- if (!key_task_permission(key, context, KEY_SEARCH))
+ if (key_task_permission(make_key_ref(key, possessed),
+ context, KEY_SEARCH) < 0)
continue;
/* stack the current position */
@@ -438,7 +450,7 @@ struct key *keyring_search_aux(struct key *keyring,
/* the keyring we're looking at was disqualified or didn't contain a
* matching key */
- not_this_keyring:
+not_this_keyring:
if (sp > 0) {
/* resume the processing of a keyring higher up in the tree */
sp--;
@@ -447,16 +459,18 @@ struct key *keyring_search_aux(struct key *keyring,
goto ascend;
}
- key = ERR_PTR(err);
- goto error;
+ key_ref = ERR_PTR(err);
+ goto error_2;
/* we found a viable match */
- found:
+found:
atomic_inc(&key->usage);
key_check(key);
- error:
+ key_ref = make_key_ref(key, possessed);
+error_2:
rcu_read_unlock();
- return key;
+error:
+ return key_ref;
} /* end keyring_search_aux() */
@@ -469,9 +483,9 @@ struct key *keyring_search_aux(struct key *keyring,
* - we return -EAGAIN if we didn't find any matching key
* - we return -ENOKEY if we only found negative matching keys
*/
-struct key *keyring_search(struct key *keyring,
- struct key_type *type,
- const char *description)
+key_ref_t keyring_search(key_ref_t keyring,
+ struct key_type *type,
+ const char *description)
{
if (!type->match)
return ERR_PTR(-ENOKEY);
@@ -488,15 +502,19 @@ EXPORT_SYMBOL(keyring_search);
* search the given keyring only (no recursion)
* - keyring must be locked by caller
*/
-struct key *__keyring_search_one(struct key *keyring,
- const struct key_type *ktype,
- const char *description,
- key_perm_t perm)
+key_ref_t __keyring_search_one(key_ref_t keyring_ref,
+ const struct key_type *ktype,
+ const char *description,
+ key_perm_t perm)
{
struct keyring_list *klist;
- struct key *key;
+ unsigned long possessed;
+ struct key *keyring, *key;
int loop;
+ keyring = key_ref_to_ptr(keyring_ref);
+ possessed = is_key_possessed(keyring_ref);
+
rcu_read_lock();
klist = rcu_dereference(keyring->payload.subscriptions);
@@ -507,21 +525,21 @@ struct key *__keyring_search_one(struct key *keyring,
if (key->type == ktype &&
(!key->type->match ||
key->type->match(key, description)) &&
- key_permission(key, perm) &&
+ key_permission(make_key_ref(key, possessed),
+ perm) == 0 &&
!test_bit(KEY_FLAG_REVOKED, &key->flags)
)
goto found;
}
}
- key = ERR_PTR(-ENOKEY);
- goto error;
+ rcu_read_unlock();
+ return ERR_PTR(-ENOKEY);
found:
atomic_inc(&key->usage);
- error:
rcu_read_unlock();
- return key;
+ return make_key_ref(key, possessed);
} /* end __keyring_search_one() */
@@ -603,7 +621,8 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound)
if (strcmp(keyring->description, name) != 0)
continue;
- if (!key_permission(keyring, KEY_SEARCH))
+ if (key_permission(make_key_ref(keyring, 0),
+ KEY_SEARCH) < 0)
continue;
/* found a potential candidate, but we still need to
diff --git a/security/keys/permission.c b/security/keys/permission.c
new file mode 100644
index 000000000000..e7f579c0eaf5
--- /dev/null
+++ b/security/keys/permission.c
@@ -0,0 +1,75 @@
+/* permission.c: key permission determination
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/security.h>
+#include "internal.h"
+
+/*****************************************************************************/
+/*
+ * check to see whether permission is granted to use a key in the desired way,
+ * but permit the security modules to override
+ */
+int key_task_permission(const key_ref_t key_ref,
+ struct task_struct *context,
+ key_perm_t perm)
+{
+ struct key *key;
+ key_perm_t kperm;
+ int ret;
+
+ key = key_ref_to_ptr(key_ref);
+
+ /* use the second 8-bits of permissions for keys the caller owns */
+ if (key->uid == context->fsuid) {
+ kperm = key->perm >> 16;
+ goto use_these_perms;
+ }
+
+ /* use the third 8-bits of permissions for keys the caller has a group
+ * membership in common with */
+ if (key->gid != -1 && key->perm & KEY_GRP_ALL) {
+ if (key->gid == context->fsgid) {
+ kperm = key->perm >> 8;
+ goto use_these_perms;
+ }
+
+ task_lock(context);
+ ret = groups_search(context->group_info, key->gid);
+ task_unlock(context);
+
+ if (ret) {
+ kperm = key->perm >> 8;
+ goto use_these_perms;
+ }
+ }
+
+ /* otherwise use the least-significant 8-bits */
+ kperm = key->perm;
+
+use_these_perms:
+ /* use the top 8-bits of permissions for keys the caller possesses
+ * - possessor permissions are additive with other permissions
+ */
+ if (is_key_possessed(key_ref))
+ kperm |= key->perm >> 24;
+
+ kperm = kperm & perm & KEY_ALL;
+
+ if (kperm != perm)
+ return -EACCES;
+
+ /* let LSM be the final arbiter */
+ return security_key_permission(key_ref, context, perm);
+
+} /* end key_task_permission() */
+
+EXPORT_SYMBOL(key_task_permission);
diff --git a/security/keys/proc.c b/security/keys/proc.c
index c55cf1fd0826..12b750e51fbf 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -167,7 +167,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
#define showflag(KEY, LETTER, FLAG) \
(test_bit(FLAG, &(KEY)->flags) ? LETTER : '-')
- seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %06x %5d %5d %-9.9s ",
+ seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ",
key->serial,
showflag(key, 'I', KEY_FLAG_INSTANTIATED),
showflag(key, 'R', KEY_FLAG_REVOKED),
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index c089f78fb94e..566b1cc0118a 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -39,7 +39,7 @@ struct key root_user_keyring = {
.type = &key_type_keyring,
.user = &root_key_user,
.sem = __RWSEM_INITIALIZER(root_user_keyring.sem),
- .perm = KEY_USR_ALL,
+ .perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
.flags = 1 << KEY_FLAG_INSTANTIATED,
.description = "_uid.0",
#ifdef KEY_DEBUGGING
@@ -54,7 +54,7 @@ struct key root_session_keyring = {
.type = &key_type_keyring,
.user = &root_key_user,
.sem = __RWSEM_INITIALIZER(root_session_keyring.sem),
- .perm = KEY_USR_ALL,
+ .perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
.flags = 1 << KEY_FLAG_INSTANTIATED,
.description = "_uid_ses.0",
#ifdef KEY_DEBUGGING
@@ -98,7 +98,7 @@ int alloc_uid_keyring(struct user_struct *user)
user->session_keyring = session_keyring;
ret = 0;
- error:
+error:
return ret;
} /* end alloc_uid_keyring() */
@@ -156,7 +156,7 @@ int install_thread_keyring(struct task_struct *tsk)
ret = 0;
key_put(old);
- error:
+error:
return ret;
} /* end install_thread_keyring() */
@@ -193,7 +193,7 @@ int install_process_keyring(struct task_struct *tsk)
}
ret = 0;
- error:
+error:
return ret;
} /* end install_process_keyring() */
@@ -236,7 +236,7 @@ static int install_session_keyring(struct task_struct *tsk,
/* we're using RCU on the pointer */
synchronize_rcu();
key_put(old);
- error:
+error:
return ret;
} /* end install_session_keyring() */
@@ -376,13 +376,13 @@ void key_fsgid_changed(struct task_struct *tsk)
* - we return -EAGAIN if we didn't find any matching key
* - we return -ENOKEY if we found only negative matching keys
*/
-struct key *search_process_keyrings(struct key_type *type,
- const void *description,
- key_match_func_t match,
- struct task_struct *context)
+key_ref_t search_process_keyrings(struct key_type *type,
+ const void *description,
+ key_match_func_t match,
+ struct task_struct *context)
{
struct request_key_auth *rka;
- struct key *key, *ret, *err, *instkey;
+ key_ref_t key_ref, ret, err, instkey_ref;
/* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
* searchable, but we failed to find a key or we found a negative key;
@@ -391,46 +391,48 @@ struct key *search_process_keyrings(struct key_type *type,
*
* in terms of priority: success > -ENOKEY > -EAGAIN > other error
*/
- key = NULL;
+ key_ref = NULL;
ret = NULL;
err = ERR_PTR(-EAGAIN);
/* search the thread keyring first */
if (context->thread_keyring) {
- key = keyring_search_aux(context->thread_keyring,
- context, type, description, match);
- if (!IS_ERR(key))
+ key_ref = keyring_search_aux(
+ make_key_ref(context->thread_keyring, 1),
+ context, type, description, match);
+ if (!IS_ERR(key_ref))
goto found;
- switch (PTR_ERR(key)) {
+ switch (PTR_ERR(key_ref)) {
case -EAGAIN: /* no key */
if (ret)
break;
case -ENOKEY: /* negative key */
- ret = key;
+ ret = key_ref;
break;
default:
- err = key;
+ err = key_ref;
break;
}
}
/* search the process keyring second */
if (context->signal->process_keyring) {
- key = keyring_search_aux(context->signal->process_keyring,
- context, type, description, match);
- if (!IS_ERR(key))
+ key_ref = keyring_search_aux(
+ make_key_ref(context->signal->process_keyring, 1),
+ context, type, description, match);
+ if (!IS_ERR(key_ref))
goto found;
- switch (PTR_ERR(key)) {
+ switch (PTR_ERR(key_ref)) {
case -EAGAIN: /* no key */
if (ret)
break;
case -ENOKEY: /* negative key */
- ret = key;
+ ret = key_ref;
break;
default:
- err = key;
+ err = key_ref;
break;
}
}
@@ -438,23 +440,25 @@ struct key *search_process_keyrings(struct key_type *type,
/* search the session keyring */
if (context->signal->session_keyring) {
rcu_read_lock();
- key = keyring_search_aux(
- rcu_dereference(context->signal->session_keyring),
+ key_ref = keyring_search_aux(
+ make_key_ref(rcu_dereference(
+ context->signal->session_keyring),
+ 1),
context, type, description, match);
rcu_read_unlock();
- if (!IS_ERR(key))
+ if (!IS_ERR(key_ref))
goto found;
- switch (PTR_ERR(key)) {
+ switch (PTR_ERR(key_ref)) {
case -EAGAIN: /* no key */
if (ret)
break;
case -ENOKEY: /* negative key */
- ret = key;
+ ret = key_ref;
break;
default:
- err = key;
+ err = key_ref;
break;
}
@@ -465,51 +469,54 @@ struct key *search_process_keyrings(struct key_type *type,
goto no_key;
rcu_read_lock();
- instkey = __keyring_search_one(
- rcu_dereference(context->signal->session_keyring),
+ instkey_ref = __keyring_search_one(
+ make_key_ref(rcu_dereference(
+ context->signal->session_keyring),
+ 1),
&key_type_request_key_auth, NULL, 0);
rcu_read_unlock();
- if (IS_ERR(instkey))
+ if (IS_ERR(instkey_ref))
goto no_key;
- rka = instkey->payload.data;
+ rka = key_ref_to_ptr(instkey_ref)->payload.data;
- key = search_process_keyrings(type, description, match,
- rka->context);
- key_put(instkey);
+ key_ref = search_process_keyrings(type, description, match,
+ rka->context);
+ key_ref_put(instkey_ref);
- if (!IS_ERR(key))
+ if (!IS_ERR(key_ref))
goto found;
- switch (PTR_ERR(key)) {
+ switch (PTR_ERR(key_ref)) {
case -EAGAIN: /* no key */
if (ret)
break;
case -ENOKEY: /* negative key */
- ret = key;
+ ret = key_ref;
break;
default:
- err = key;
+ err = key_ref;
break;
}
}
/* or search the user-session keyring */
else {
- key = keyring_search_aux(context->user->session_keyring,
- context, type, description, match);
- if (!IS_ERR(key))
+ key_ref = keyring_search_aux(
+ make_key_ref(context->user->session_keyring, 1),
+ context, type, description, match);
+ if (!IS_ERR(key_ref))
goto found;
- switch (PTR_ERR(key)) {
+ switch (PTR_ERR(key_ref)) {
case -EAGAIN: /* no key */
if (ret)
break;
case -ENOKEY: /* negative key */
- ret = key;
+ ret = key_ref;
break;
default:
- err = key;
+ err = key_ref;
break;
}
}
@@ -517,29 +524,40 @@ struct key *search_process_keyrings(struct key_type *type,
no_key:
/* no key - decide on the error we're going to go for */
- key = ret ? ret : err;
+ key_ref = ret ? ret : err;
found:
- return key;
+ return key_ref;
} /* end search_process_keyrings() */
/*****************************************************************************/
/*
+ * see if the key we're looking at is the target key
+ */
+static int lookup_user_key_possessed(const struct key *key, const void *target)
+{
+ return key == target;
+
+} /* end lookup_user_key_possessed() */
+
+/*****************************************************************************/
+/*
* lookup a key given a key ID from userspace with a given permissions mask
* - don't create special keyrings unless so requested
* - partially constructed keys aren't found unless requested
*/
-struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
- int create, int partial, key_perm_t perm)
+key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
+ int create, int partial, key_perm_t perm)
{
+ key_ref_t key_ref, skey_ref;
struct key *key;
int ret;
if (!context)
context = current;
- key = ERR_PTR(-ENOKEY);
+ key_ref = ERR_PTR(-ENOKEY);
switch (id) {
case KEY_SPEC_THREAD_KEYRING:
@@ -556,6 +574,7 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
key = context->thread_keyring;
atomic_inc(&key->usage);
+ key_ref = make_key_ref(key, 1);
break;
case KEY_SPEC_PROCESS_KEYRING:
@@ -572,6 +591,7 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
key = context->signal->process_keyring;
atomic_inc(&key->usage);
+ key_ref = make_key_ref(key, 1);
break;
case KEY_SPEC_SESSION_KEYRING:
@@ -579,7 +599,7 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
/* always install a session keyring upon access if one
* doesn't exist yet */
ret = install_session_keyring(
- context, context->user->session_keyring);
+ context, context->user->session_keyring);
if (ret < 0)
goto error;
}
@@ -588,16 +608,19 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
key = rcu_dereference(context->signal->session_keyring);
atomic_inc(&key->usage);
rcu_read_unlock();
+ key_ref = make_key_ref(key, 1);
break;
case KEY_SPEC_USER_KEYRING:
key = context->user->uid_keyring;
atomic_inc(&key->usage);
+ key_ref = make_key_ref(key, 1);
break;
case KEY_SPEC_USER_SESSION_KEYRING:
key = context->user->session_keyring;
atomic_inc(&key->usage);
+ key_ref = make_key_ref(key, 1);
break;
case KEY_SPEC_GROUP_KEYRING:
@@ -606,13 +629,28 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
goto error;
default:
- key = ERR_PTR(-EINVAL);
+ key_ref = ERR_PTR(-EINVAL);
if (id < 1)
goto error;
key = key_lookup(id);
- if (IS_ERR(key))
+ if (IS_ERR(key)) {
+ key_ref = ERR_PTR(PTR_ERR(key));
goto error;
+ }
+
+ key_ref = make_key_ref(key, 0);
+
+ /* check to see if we possess the key */
+ skey_ref = search_process_keyrings(key->type, key,
+ lookup_user_key_possessed,
+ current);
+
+ if (!IS_ERR(skey_ref)) {
+ key_put(key);
+ key_ref = skey_ref;
+ }
+
break;
}
@@ -628,17 +666,16 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
goto invalid_key;
/* check the permissions */
- ret = -EACCES;
-
- if (!key_task_permission(key, context, perm))
+ ret = key_task_permission(key_ref, context, perm);
+ if (ret < 0)
goto invalid_key;
- error:
- return key;
+error:
+ return key_ref;
- invalid_key:
- key_put(key);
- key = ERR_PTR(ret);
+invalid_key:
+ key_ref_put(key_ref);
+ key_ref = ERR_PTR(ret);
goto error;
} /* end lookup_user_key() */
@@ -694,9 +731,9 @@ long join_session_keyring(const char *name)
ret = keyring->serial;
key_put(keyring);
- error2:
+error2:
up(&key_session_sem);
- error:
+error:
return ret;
} /* end join_session_keyring() */
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 90c1506d007c..5cc4bba70db6 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -7,6 +7,8 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ * See Documentation/keys-request-key.txt
*/
#include <linux/module.h>
@@ -129,7 +131,7 @@ static struct key *__request_key_construction(struct key_type *type,
/* create a key and add it to the queue */
key = key_alloc(type, description,
- current->fsuid, current->fsgid, KEY_USR_ALL, 0);
+ current->fsuid, current->fsgid, KEY_POS_ALL, 0);
if (IS_ERR(key))
goto alloc_failed;
@@ -365,14 +367,24 @@ struct key *request_key_and_link(struct key_type *type,
{
struct key_user *user;
struct key *key;
+ key_ref_t key_ref;
kenter("%s,%s,%s,%p",
type->name, description, callout_info, dest_keyring);
/* search all the process keyrings for a key */
- key = search_process_keyrings(type, description, type->match, current);
+ key_ref = search_process_keyrings(type, description, type->match,
+ current);
+
+ kdebug("search 1: %p", key_ref);
- if (PTR_ERR(key) == -EAGAIN) {
+ if (!IS_ERR(key_ref)) {
+ key = key_ref_to_ptr(key_ref);
+ }
+ else if (PTR_ERR(key_ref) != -EAGAIN) {
+ key = ERR_PTR(PTR_ERR(key_ref));
+ }
+ else {
/* the search failed, but the keyrings were searchable, so we
* should consult userspace if we can */
key = ERR_PTR(-ENOKEY);
@@ -384,7 +396,7 @@ struct key *request_key_and_link(struct key_type *type,
if (!user)
goto nomem;
- do {
+ for (;;) {
if (signal_pending(current))
goto interrupted;
@@ -397,10 +409,22 @@ struct key *request_key_and_link(struct key_type *type,
/* someone else made the key we want, so we need to
* search again as it might now be available to us */
- key = search_process_keyrings(type, description,
- type->match, current);
+ key_ref = search_process_keyrings(type, description,
+ type->match,
+ current);
+
+ kdebug("search 2: %p", key_ref);
- } while (PTR_ERR(key) == -EAGAIN);
+ if (!IS_ERR(key_ref)) {
+ key = key_ref_to_ptr(key_ref);
+ break;
+ }
+
+ if (PTR_ERR(key_ref) != -EAGAIN) {
+ key = ERR_PTR(PTR_ERR(key_ref));
+ break;
+ }
+ }
key_user_put(user);
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index f22264632229..a8e4069d48cb 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -7,6 +7,8 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ * See Documentation/keys-request-key.txt
*/
#include <linux/module.h>
@@ -96,6 +98,7 @@ static void request_key_auth_destroy(struct key *key)
kenter("{%d}", key->serial);
key_put(rka->target_key);
+ kfree(rka);
} /* end request_key_auth_destroy() */
@@ -126,7 +129,7 @@ struct key *request_key_auth_new(struct key *target, struct key **_rkakey)
rkakey = key_alloc(&key_type_request_key_auth, desc,
current->fsuid, current->fsgid,
- KEY_USR_VIEW, 1);
+ KEY_POS_VIEW | KEY_USR_VIEW, 1);
if (IS_ERR(rkakey)) {
key_put(keyring);
kleave("= %ld", PTR_ERR(rkakey));
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index e446acba73d3..cbda3b2780a1 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -15,18 +15,10 @@
#include <linux/slab.h>
#include <linux/seq_file.h>
#include <linux/err.h>
+#include <keys/user-type.h>
#include <asm/uaccess.h>
#include "internal.h"
-static int user_instantiate(struct key *key, const void *data, size_t datalen);
-static int user_duplicate(struct key *key, const struct key *source);
-static int user_update(struct key *key, const void *data, size_t datalen);
-static int user_match(const struct key *key, const void *criterion);
-static void user_destroy(struct key *key);
-static void user_describe(const struct key *user, struct seq_file *m);
-static long user_read(const struct key *key,
- char __user *buffer, size_t buflen);
-
/*
* user defined keys take an arbitrary string as the description and an
* arbitrary blob of data as the payload
@@ -42,19 +34,13 @@ struct key_type key_type_user = {
.read = user_read,
};
-struct user_key_payload {
- struct rcu_head rcu; /* RCU destructor */
- unsigned short datalen; /* length of this data */
- char data[0]; /* actual data */
-};
-
EXPORT_SYMBOL_GPL(key_type_user);
/*****************************************************************************/
/*
* instantiate a user defined key
*/
-static int user_instantiate(struct key *key, const void *data, size_t datalen)
+int user_instantiate(struct key *key, const void *data, size_t datalen)
{
struct user_key_payload *upayload;
int ret;
@@ -78,18 +64,20 @@ static int user_instantiate(struct key *key, const void *data, size_t datalen)
rcu_assign_pointer(key->payload.data, upayload);
ret = 0;
- error:
+error:
return ret;
} /* end user_instantiate() */
+EXPORT_SYMBOL_GPL(user_instantiate);
+
/*****************************************************************************/
/*
* duplicate a user defined key
* - both keys' semaphores are locked against further modification
* - the new key cannot yet be accessed
*/
-static int user_duplicate(struct key *key, const struct key *source)
+int user_duplicate(struct key *key, const struct key *source)
{
struct user_key_payload *upayload, *spayload;
int ret;
@@ -112,6 +100,8 @@ static int user_duplicate(struct key *key, const struct key *source)
} /* end user_duplicate() */
+EXPORT_SYMBOL_GPL(user_duplicate);
+
/*****************************************************************************/
/*
* dispose of the old data from an updated user defined key
@@ -131,7 +121,7 @@ static void user_update_rcu_disposal(struct rcu_head *rcu)
* update a user defined key
* - the key's semaphore is write-locked
*/
-static int user_update(struct key *key, const void *data, size_t datalen)
+int user_update(struct key *key, const void *data, size_t datalen)
{
struct user_key_payload *upayload, *zap;
int ret;
@@ -163,26 +153,30 @@ static int user_update(struct key *key, const void *data, size_t datalen)
call_rcu(&zap->rcu, user_update_rcu_disposal);
- error:
+error:
return ret;
} /* end user_update() */
+EXPORT_SYMBOL_GPL(user_update);
+
/*****************************************************************************/
/*
* match users on their name
*/
-static int user_match(const struct key *key, const void *description)
+int user_match(const struct key *key, const void *description)
{
return strcmp(key->description, description) == 0;
} /* end user_match() */
+EXPORT_SYMBOL_GPL(user_match);
+
/*****************************************************************************/
/*
* dispose of the data dangling from the corpse of a user
*/
-static void user_destroy(struct key *key)
+void user_destroy(struct key *key)
{
struct user_key_payload *upayload = key->payload.data;
@@ -190,11 +184,13 @@ static void user_destroy(struct key *key)
} /* end user_destroy() */
+EXPORT_SYMBOL_GPL(user_destroy);
+
/*****************************************************************************/
/*
* describe the user key
*/
-static void user_describe(const struct key *key, struct seq_file *m)
+void user_describe(const struct key *key, struct seq_file *m)
{
seq_puts(m, key->description);
@@ -202,13 +198,14 @@ static void user_describe(const struct key *key, struct seq_file *m)
} /* end user_describe() */
+EXPORT_SYMBOL_GPL(user_describe);
+
/*****************************************************************************/
/*
* read the key data
* - the key's semaphore is read-locked
*/
-static long user_read(const struct key *key,
- char __user *buffer, size_t buflen)
+long user_read(const struct key *key, char __user *buffer, size_t buflen)
{
struct user_key_payload *upayload;
long ret;
@@ -228,3 +225,5 @@ static long user_read(const struct key *key,
return ret;
} /* end user_read() */
+
+EXPORT_SYMBOL_GPL(user_read);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 6e4937fe062b..fc774436a264 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -122,11 +122,10 @@ static int task_alloc_security(struct task_struct *task)
{
struct task_security_struct *tsec;
- tsec = kmalloc(sizeof(struct task_security_struct), GFP_KERNEL);
+ tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
if (!tsec)
return -ENOMEM;
- memset(tsec, 0, sizeof(struct task_security_struct));
tsec->magic = SELINUX_MAGIC;
tsec->task = task;
tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
@@ -151,11 +150,10 @@ static int inode_alloc_security(struct inode *inode)
struct task_security_struct *tsec = current->security;
struct inode_security_struct *isec;
- isec = kmalloc(sizeof(struct inode_security_struct), GFP_KERNEL);
+ isec = kzalloc(sizeof(struct inode_security_struct), GFP_KERNEL);
if (!isec)
return -ENOMEM;
- memset(isec, 0, sizeof(struct inode_security_struct));
init_MUTEX(&isec->sem);
INIT_LIST_HEAD(&isec->list);
isec->magic = SELINUX_MAGIC;
@@ -193,11 +191,10 @@ static int file_alloc_security(struct file *file)
struct task_security_struct *tsec = current->security;
struct file_security_struct *fsec;
- fsec = kmalloc(sizeof(struct file_security_struct), GFP_ATOMIC);
+ fsec = kzalloc(sizeof(struct file_security_struct), GFP_ATOMIC);
if (!fsec)
return -ENOMEM;
- memset(fsec, 0, sizeof(struct file_security_struct));
fsec->magic = SELINUX_MAGIC;
fsec->file = file;
if (tsec && tsec->magic == SELINUX_MAGIC) {
@@ -227,11 +224,10 @@ static int superblock_alloc_security(struct super_block *sb)
{
struct superblock_security_struct *sbsec;
- sbsec = kmalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
+ sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
if (!sbsec)
return -ENOMEM;
- memset(sbsec, 0, sizeof(struct superblock_security_struct));
init_MUTEX(&sbsec->sem);
INIT_LIST_HEAD(&sbsec->list);
INIT_LIST_HEAD(&sbsec->isec_head);
@@ -262,18 +258,17 @@ static void superblock_free_security(struct super_block *sb)
}
#ifdef CONFIG_SECURITY_NETWORK
-static int sk_alloc_security(struct sock *sk, int family, int priority)
+static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
{
struct sk_security_struct *ssec;
if (family != PF_UNIX)
return 0;
- ssec = kmalloc(sizeof(*ssec), priority);
+ ssec = kzalloc(sizeof(*ssec), priority);
if (!ssec)
return -ENOMEM;
- memset(ssec, 0, sizeof(*ssec));
ssec->magic = SELINUX_MAGIC;
ssec->sk = sk;
ssec->peer_sid = SECINITSID_UNLABELED;
@@ -630,6 +625,16 @@ static inline u16 inode_mode_to_security_class(umode_t mode)
return SECCLASS_FILE;
}
+static inline int default_protocol_stream(int protocol)
+{
+ return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
+}
+
+static inline int default_protocol_dgram(int protocol)
+{
+ return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
+}
+
static inline u16 socket_type_to_security_class(int family, int type, int protocol)
{
switch (family) {
@@ -646,10 +651,16 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
case PF_INET6:
switch (type) {
case SOCK_STREAM:
- return SECCLASS_TCP_SOCKET;
+ if (default_protocol_stream(protocol))
+ return SECCLASS_TCP_SOCKET;
+ else
+ return SECCLASS_RAWIP_SOCKET;
case SOCK_DGRAM:
- return SECCLASS_UDP_SOCKET;
- case SOCK_RAW:
+ if (default_protocol_dgram(protocol))
+ return SECCLASS_UDP_SOCKET;
+ else
+ return SECCLASS_RAWIP_SOCKET;
+ default:
return SECCLASS_RAWIP_SOCKET;
}
break;
@@ -1467,11 +1478,10 @@ static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
{
struct bprm_security_struct *bsec;
- bsec = kmalloc(sizeof(struct bprm_security_struct), GFP_KERNEL);
+ bsec = kzalloc(sizeof(struct bprm_security_struct), GFP_KERNEL);
if (!bsec)
return -ENOMEM;
- memset(bsec, 0, sizeof *bsec);
bsec->magic = SELINUX_MAGIC;
bsec->bprm = bprm;
bsec->sid = SECINITSID_UNLABELED;
@@ -1599,7 +1609,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
if (tty) {
file_list_lock();
- file = list_entry(tty->tty_files.next, typeof(*file), f_list);
+ file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list);
if (file) {
/* Revalidate access to controlling tty.
Use inode_has_perm on the tty inode directly rather
@@ -1976,6 +1986,9 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
inode_security_set_sid(inode, newsid);
+ if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
+ return -EOPNOTSUPP;
+
if (name) {
namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL);
if (!namep)
@@ -2195,12 +2208,6 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
static int selinux_inode_getxattr (struct dentry *dentry, char *name)
{
- struct inode *inode = dentry->d_inode;
- struct superblock_security_struct *sbsec = inode->i_sb->s_security;
-
- if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
- return -EOPNOTSUPP;
-
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
}
@@ -2231,33 +2238,54 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name)
return -EACCES;
}
-static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size)
+/*
+ * 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
+ * canonicalize the value to be finally returned to the user.
+ *
+ * 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)
{
struct inode_security_struct *isec = inode->i_security;
char *context;
unsigned len;
int rc;
- /* Permission check handled by selinux_inode_getxattr hook.*/
-
- if (strcmp(name, XATTR_SELINUX_SUFFIX))
- return -EOPNOTSUPP;
+ if (strcmp(name, XATTR_SELINUX_SUFFIX)) {
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
rc = security_sid_to_context(isec->sid, &context, &len);
if (rc)
- return rc;
+ goto out;
+ /* Probe for required buffer size */
if (!buffer || !size) {
- kfree(context);
- return len;
+ rc = len;
+ goto out_free;
}
+
if (size < len) {
- kfree(context);
- return -ERANGE;
+ rc = -ERANGE;
+ goto out_free;
+ }
+
+ 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);
- return len;
+out:
+ return rc;
}
static int selinux_inode_setsecurity(struct inode *inode, const char *name,
@@ -2688,8 +2716,7 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info, int si
if (rc)
return rc;
- if (info && ((unsigned long)info == 1 ||
- (unsigned long)info == 2 || SI_FROMKERNEL(info)))
+ if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
return 0;
if (!sig)
@@ -2970,6 +2997,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
/*
* If PF_INET or PF_INET6, check name_bind permission for the port.
+ * Multiple address binding for SCTP is not supported yet: we just
+ * check the first address now.
*/
family = sock->sk->sk_family;
if (family == PF_INET || family == PF_INET6) {
@@ -3014,12 +3043,12 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
goto out;
}
- switch(sk->sk_protocol) {
- case IPPROTO_TCP:
+ switch(isec->sclass) {
+ case SECCLASS_TCP_SOCKET:
node_perm = TCP_SOCKET__NODE_BIND;
break;
- case IPPROTO_UDP:
+ case SECCLASS_UDP_SOCKET:
node_perm = UDP_SOCKET__NODE_BIND;
break;
@@ -3362,7 +3391,7 @@ out:
return err;
}
-static int selinux_sk_alloc_security(struct sock *sk, int family, int priority)
+static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
{
return sk_alloc_security(sk, family, priority);
}
@@ -3581,11 +3610,10 @@ static int ipc_alloc_security(struct task_struct *task,
struct task_security_struct *tsec = task->security;
struct ipc_security_struct *isec;
- isec = kmalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
+ isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
if (!isec)
return -ENOMEM;
- memset(isec, 0, sizeof(struct ipc_security_struct));
isec->magic = SELINUX_MAGIC;
isec->sclass = sclass;
isec->ipc_perm = perm;
@@ -3613,11 +3641,10 @@ static int msg_msg_alloc_security(struct msg_msg *msg)
{
struct msg_security_struct *msec;
- msec = kmalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
+ msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
if (!msec)
return -ENOMEM;
- memset(msec, 0, sizeof(struct msg_security_struct));
msec->magic = SELINUX_MAGIC;
msec->msg = msg;
msec->sid = SECINITSID_UNLABELED;
diff --git a/security/selinux/netif.c b/security/selinux/netif.c
index 718d7be9f4dd..b10c34e8a743 100644
--- a/security/selinux/netif.c
+++ b/security/selinux/netif.c
@@ -114,13 +114,12 @@ static struct sel_netif *sel_netif_lookup(struct net_device *dev)
if (likely(netif != NULL))
goto out;
- new = kmalloc(sizeof(*new), GFP_ATOMIC);
+ new = kzalloc(sizeof(*new), GFP_ATOMIC);
if (!new) {
netif = ERR_PTR(-ENOMEM);
goto out;
}
- memset(new, 0, sizeof(*new));
nsec = &new->nsec;
ret = security_netif_sid(dev->name, &nsec->if_sid, &nsec->msg_sid);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 8eb140dd2e4b..0e1352a555c8 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -105,7 +105,7 @@ static ssize_t sel_write_enforce(struct file * file, const char __user * buf,
ssize_t length;
int new_value;
- if (count < 0 || count >= PAGE_SIZE)
+ if (count >= PAGE_SIZE)
return -ENOMEM;
if (*ppos != 0) {
/* No partial writes. */
@@ -155,7 +155,7 @@ static ssize_t sel_write_disable(struct file * file, const char __user * buf,
int new_value;
extern int selinux_disable(void);
- if (count < 0 || count >= PAGE_SIZE)
+ if (count >= PAGE_SIZE)
return -ENOMEM;
if (*ppos != 0) {
/* No partial writes. */
@@ -242,7 +242,7 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
goto out;
}
- if ((count < 0) || (count > 64 * 1024 * 1024)
+ if ((count > 64 * 1024 * 1024)
|| (data = vmalloc(count)) == NULL) {
length = -ENOMEM;
goto out;
@@ -271,46 +271,38 @@ static struct file_operations sel_load_ops = {
.write = sel_write_load,
};
-
-static ssize_t sel_write_context(struct file * file, const char __user * buf,
- size_t count, loff_t *ppos)
-
+static ssize_t sel_write_context(struct file * file, char *buf, size_t size)
{
- char *page;
- u32 sid;
+ char *canon;
+ u32 sid, len;
ssize_t length;
length = task_has_security(current, SECURITY__CHECK_CONTEXT);
if (length)
return length;
- if (count < 0 || count >= PAGE_SIZE)
- return -ENOMEM;
- if (*ppos != 0) {
- /* No partial writes. */
- return -EINVAL;
- }
- page = (char*)get_zeroed_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
- length = -EFAULT;
- if (copy_from_user(page, buf, count))
- goto out;
+ length = security_context_to_sid(buf, size, &sid);
+ if (length < 0)
+ return length;
- length = security_context_to_sid(page, count, &sid);
+ length = security_sid_to_context(sid, &canon, &len);
if (length < 0)
+ return length;
+
+ if (len > SIMPLE_TRANSACTION_LIMIT) {
+ printk(KERN_ERR "%s: context size (%u) exceeds payload "
+ "max\n", __FUNCTION__, len);
+ length = -ERANGE;
goto out;
+ }
- length = count;
+ memcpy(buf, canon, len);
+ length = len;
out:
- free_page((unsigned long) page);
+ kfree(canon);
return length;
}
-static struct file_operations sel_context_ops = {
- .write = sel_write_context,
-};
-
static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf,
size_t count, loff_t *ppos)
{
@@ -332,7 +324,7 @@ static ssize_t sel_write_checkreqprot(struct file * file, const char __user * bu
if (length)
return length;
- if (count < 0 || count >= PAGE_SIZE)
+ if (count >= PAGE_SIZE)
return -ENOMEM;
if (*ppos != 0) {
/* No partial writes. */
@@ -375,6 +367,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
[SEL_RELABEL] = sel_write_relabel,
[SEL_USER] = sel_write_user,
[SEL_MEMBER] = sel_write_member,
+ [SEL_CONTEXT] = sel_write_context,
};
static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
@@ -424,15 +417,13 @@ static ssize_t sel_write_access(struct file * file, char *buf, size_t size)
return length;
length = -ENOMEM;
- scon = kmalloc(size+1, GFP_KERNEL);
+ scon = kzalloc(size+1, GFP_KERNEL);
if (!scon)
return length;
- memset(scon, 0, size+1);
- tcon = kmalloc(size+1, GFP_KERNEL);
+ tcon = kzalloc(size+1, GFP_KERNEL);
if (!tcon)
goto out;
- memset(tcon, 0, size+1);
length = -EINVAL;
if (sscanf(buf, "%s %s %hu %x", scon, tcon, &tclass, &req) != 4)
@@ -475,15 +466,13 @@ static ssize_t sel_write_create(struct file * file, char *buf, size_t size)
return length;
length = -ENOMEM;
- scon = kmalloc(size+1, GFP_KERNEL);
+ scon = kzalloc(size+1, GFP_KERNEL);
if (!scon)
return length;
- memset(scon, 0, size+1);
- tcon = kmalloc(size+1, GFP_KERNEL);
+ tcon = kzalloc(size+1, GFP_KERNEL);
if (!tcon)
goto out;
- memset(tcon, 0, size+1);
length = -EINVAL;
if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
@@ -536,15 +525,13 @@ static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size)
return length;
length = -ENOMEM;
- scon = kmalloc(size+1, GFP_KERNEL);
+ scon = kzalloc(size+1, GFP_KERNEL);
if (!scon)
return length;
- memset(scon, 0, size+1);
- tcon = kmalloc(size+1, GFP_KERNEL);
+ tcon = kzalloc(size+1, GFP_KERNEL);
if (!tcon)
goto out;
- memset(tcon, 0, size+1);
length = -EINVAL;
if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
@@ -595,15 +582,13 @@ static ssize_t sel_write_user(struct file * file, char *buf, size_t size)
return length;
length = -ENOMEM;
- con = kmalloc(size+1, GFP_KERNEL);
+ con = kzalloc(size+1, GFP_KERNEL);
if (!con)
return length;
- memset(con, 0, size+1);
- user = kmalloc(size+1, GFP_KERNEL);
+ user = kzalloc(size+1, GFP_KERNEL);
if (!user)
goto out;
- memset(user, 0, size+1);
length = -EINVAL;
if (sscanf(buf, "%s %s", con, user) != 2)
@@ -658,15 +643,13 @@ static ssize_t sel_write_member(struct file * file, char *buf, size_t size)
return length;
length = -ENOMEM;
- scon = kmalloc(size+1, GFP_KERNEL);
+ scon = kzalloc(size+1, GFP_KERNEL);
if (!scon)
return length;
- memset(scon, 0, size+1);
- tcon = kmalloc(size+1, GFP_KERNEL);
+ tcon = kzalloc(size+1, GFP_KERNEL);
if (!tcon)
goto out;
- memset(tcon, 0, size+1);
length = -EINVAL;
if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
@@ -739,7 +722,7 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
if (!filep->f_op)
goto out;
- if (count < 0 || count > PAGE_SIZE) {
+ if (count > PAGE_SIZE) {
ret = -EINVAL;
goto out;
}
@@ -800,7 +783,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
if (!filep->f_op)
goto out;
- if (count < 0 || count >= PAGE_SIZE) {
+ if (count >= PAGE_SIZE) {
length = -ENOMEM;
goto out;
}
@@ -858,7 +841,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
if (!filep->f_op)
goto out;
- if (count < 0 || count >= PAGE_SIZE) {
+ if (count >= PAGE_SIZE) {
length = -ENOMEM;
goto out;
}
@@ -879,7 +862,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
if (sscanf(page, "%d", &new_value) != 1)
goto out;
- if (new_value) {
+ if (new_value && bool_pending_values) {
security_set_bools(bool_num, bool_pending_values);
}
@@ -924,7 +907,7 @@ static void sel_remove_bools(struct dentry *de)
file_list_lock();
list_for_each(p, &sb->s_files) {
- struct file * filp = list_entry(p, struct file, f_list);
+ struct file * filp = list_entry(p, struct file, f_u.fu_list);
struct dentry * dentry = filp->f_dentry;
if (dentry->d_parent != de) {
@@ -952,6 +935,7 @@ static int sel_make_bools(void)
/* remove any existing files */
kfree(bool_pending_values);
+ bool_pending_values = NULL;
sel_remove_bools(dir);
@@ -1002,6 +986,7 @@ out:
}
return ret;
err:
+ kfree(values);
d_genocide(dir);
ret = -ENOMEM;
goto out;
@@ -1030,7 +1015,7 @@ static ssize_t sel_write_avc_cache_threshold(struct file * file,
ssize_t ret;
int new_value;
- if (count < 0 || count >= PAGE_SIZE) {
+ if (count >= PAGE_SIZE) {
ret = -ENOMEM;
goto out;
}
@@ -1228,7 +1213,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
static struct tree_descr selinux_files[] = {
[SEL_LOAD] = {"load", &sel_load_ops, S_IRUSR|S_IWUSR},
[SEL_ENFORCE] = {"enforce", &sel_enforce_ops, S_IRUGO|S_IWUSR},
- [SEL_CONTEXT] = {"context", &sel_context_ops, S_IRUGO|S_IWUGO},
+ [SEL_CONTEXT] = {"context", &transaction_ops, S_IRUGO|S_IWUGO},
[SEL_ACCESS] = {"access", &transaction_ops, S_IRUGO|S_IWUGO},
[SEL_CREATE] = {"create", &transaction_ops, S_IRUGO|S_IWUGO},
[SEL_RELABEL] = {"relabel", &transaction_ops, S_IRUGO|S_IWUGO},
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index daf288007460..d2737edba541 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -220,10 +220,9 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
u32 len;
int rc;
- booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL);
+ booldatum = kzalloc(sizeof(struct cond_bool_datum), GFP_KERNEL);
if (!booldatum)
return -1;
- memset(booldatum, 0, sizeof(struct cond_bool_datum));
rc = next_entry(buf, fp, sizeof buf);
if (rc < 0)
@@ -321,10 +320,9 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
goto err;
}
- list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL);
+ list = kzalloc(sizeof(struct cond_av_list), GFP_KERNEL);
if (!list)
goto err;
- memset(list, 0, sizeof(*list));
list->node = node_ptr;
if (!data->head)
@@ -414,11 +412,10 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
if (rc < 0)
goto err;
- expr = kmalloc(sizeof(struct cond_expr), GFP_KERNEL);
+ expr = kzalloc(sizeof(struct cond_expr), GFP_KERNEL);
if (!expr) {
goto err;
}
- memset(expr, 0, sizeof(struct cond_expr));
expr->expr_type = le32_to_cpu(buf[0]);
expr->bool = le32_to_cpu(buf[1]);
@@ -460,10 +457,9 @@ int cond_read_list(struct policydb *p, void *fp)
len = le32_to_cpu(buf[0]);
for (i = 0; i < len; i++) {
- node = kmalloc(sizeof(struct cond_node), GFP_KERNEL);
+ node = kzalloc(sizeof(struct cond_node), GFP_KERNEL);
if (!node)
goto err;
- memset(node, 0, sizeof(struct cond_node));
if (cond_read_node(p, node, fp) != 0)
goto err;
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index d515154128cc..47024a6e1844 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -39,12 +39,11 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
n = src->node;
prev = NULL;
while (n) {
- new = kmalloc(sizeof(*new), GFP_ATOMIC);
+ new = kzalloc(sizeof(*new), GFP_ATOMIC);
if (!new) {
ebitmap_destroy(dst);
return -ENOMEM;
}
- memset(new, 0, sizeof(*new));
new->startbit = n->startbit;
new->map = n->map;
new->next = NULL;
@@ -150,10 +149,9 @@ int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
if (!value)
return 0;
- new = kmalloc(sizeof(*new), GFP_ATOMIC);
+ new = kzalloc(sizeof(*new), GFP_ATOMIC);
if (!new)
return -ENOMEM;
- memset(new, 0, sizeof(*new));
new->startbit = bit & ~(MAPSIZE - 1);
new->map = (MAPBIT << (bit - new->startbit));
@@ -232,13 +230,12 @@ int ebitmap_read(struct ebitmap *e, void *fp)
printk(KERN_ERR "security: ebitmap: truncated map\n");
goto bad;
}
- n = kmalloc(sizeof(*n), GFP_KERNEL);
+ n = kzalloc(sizeof(*n), GFP_KERNEL);
if (!n) {
printk(KERN_ERR "security: ebitmap: out of memory\n");
rc = -ENOMEM;
goto bad;
}
- memset(n, 0, sizeof(*n));
n->startbit = le32_to_cpu(buf[0]);
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c
index 26661fcc00ce..24e5ec957630 100644
--- a/security/selinux/ss/hashtab.c
+++ b/security/selinux/ss/hashtab.c
@@ -15,11 +15,10 @@ struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key),
struct hashtab *p;
u32 i;
- p = kmalloc(sizeof(*p), GFP_KERNEL);
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL)
return p;
- memset(p, 0, sizeof(*p));
p->size = size;
p->nel = 0;
p->hash_value = hash_value;
@@ -55,10 +54,9 @@ int hashtab_insert(struct hashtab *h, void *key, void *datum)
if (cur && (h->keycmp(h, key, cur->key) == 0))
return -EEXIST;
- newnode = kmalloc(sizeof(*newnode), GFP_KERNEL);
+ newnode = kzalloc(sizeof(*newnode), GFP_KERNEL);
if (newnode == NULL)
return -ENOMEM;
- memset(newnode, 0, sizeof(*newnode));
newnode->key = key;
newnode->datum = datum;
if (prev) {
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index aaefac2921f1..640d0bfdbc68 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -262,8 +262,11 @@ int mls_context_to_sid(char oldc,
struct cat_datum *catdatum, *rngdatum;
int l, rc = -EINVAL;
- if (!selinux_mls_enabled)
+ if (!selinux_mls_enabled) {
+ if (def_sid != SECSID_NULL && oldc)
+ *scontext += strlen(*scontext);
return 0;
+ }
/*
* No MLS component to the security context, try and map to
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 0a758323a9cf..0ac311dc8371 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -121,12 +121,11 @@ static int roles_init(struct policydb *p)
int rc;
struct role_datum *role;
- role = kmalloc(sizeof(*role), GFP_KERNEL);
+ role = kzalloc(sizeof(*role), GFP_KERNEL);
if (!role) {
rc = -ENOMEM;
goto out;
}
- memset(role, 0, sizeof(*role));
role->value = ++p->p_roles.nprim;
if (role->value != OBJECT_R_VAL) {
rc = -EINVAL;
@@ -633,25 +632,27 @@ void policydb_destroy(struct policydb *p)
cond_policydb_destroy(p);
for (tr = p->role_tr; tr; tr = tr->next) {
- if (ltr) kfree(ltr);
+ kfree(ltr);
ltr = tr;
}
- if (ltr) kfree(ltr);
+ kfree(ltr);
for (ra = p->role_allow; ra; ra = ra -> next) {
- if (lra) kfree(lra);
+ kfree(lra);
lra = ra;
}
- if (lra) kfree(lra);
+ kfree(lra);
for (rt = p->range_tr; rt; rt = rt -> next) {
- if (lrt) kfree(lrt);
+ kfree(lrt);
lrt = rt;
}
- if (lrt) kfree(lrt);
+ kfree(lrt);
- for (i = 0; i < p->p_types.nprim; i++)
- ebitmap_destroy(&p->type_attr_map[i]);
+ if (p->type_attr_map) {
+ for (i = 0; i < p->p_types.nprim; i++)
+ ebitmap_destroy(&p->type_attr_map[i]);
+ }
kfree(p->type_attr_map);
return;
@@ -849,12 +850,11 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
__le32 buf[2];
u32 len;
- perdatum = kmalloc(sizeof(*perdatum), GFP_KERNEL);
+ perdatum = kzalloc(sizeof(*perdatum), GFP_KERNEL);
if (!perdatum) {
rc = -ENOMEM;
goto out;
}
- memset(perdatum, 0, sizeof(*perdatum));
rc = next_entry(buf, fp, sizeof buf);
if (rc < 0)
@@ -891,12 +891,11 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp)
u32 len, nel;
int i, rc;
- comdatum = kmalloc(sizeof(*comdatum), GFP_KERNEL);
+ comdatum = kzalloc(sizeof(*comdatum), GFP_KERNEL);
if (!comdatum) {
rc = -ENOMEM;
goto out;
}
- memset(comdatum, 0, sizeof(*comdatum));
rc = next_entry(buf, fp, sizeof buf);
if (rc < 0)
@@ -948,10 +947,9 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons,
lc = NULL;
for (i = 0; i < ncons; i++) {
- c = kmalloc(sizeof(*c), GFP_KERNEL);
+ c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c)
return -ENOMEM;
- memset(c, 0, sizeof(*c));
if (lc) {
lc->next = c;
@@ -967,10 +965,9 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons,
le = NULL;
depth = -1;
for (j = 0; j < nexpr; j++) {
- e = kmalloc(sizeof(*e), GFP_KERNEL);
+ e = kzalloc(sizeof(*e), GFP_KERNEL);
if (!e)
return -ENOMEM;
- memset(e, 0, sizeof(*e));
if (le) {
le->next = e;
@@ -1031,12 +1028,11 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
u32 len, len2, ncons, nel;
int i, rc;
- cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL);
+ cladatum = kzalloc(sizeof(*cladatum), GFP_KERNEL);
if (!cladatum) {
rc = -ENOMEM;
goto out;
}
- memset(cladatum, 0, sizeof(*cladatum));
rc = next_entry(buf, fp, sizeof(u32)*6);
if (rc < 0)
@@ -1125,12 +1121,11 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
__le32 buf[2];
u32 len;
- role = kmalloc(sizeof(*role), GFP_KERNEL);
+ role = kzalloc(sizeof(*role), GFP_KERNEL);
if (!role) {
rc = -ENOMEM;
goto out;
}
- memset(role, 0, sizeof(*role));
rc = next_entry(buf, fp, sizeof buf);
if (rc < 0)
@@ -1186,12 +1181,11 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
__le32 buf[3];
u32 len;
- typdatum = kmalloc(sizeof(*typdatum),GFP_KERNEL);
+ typdatum = kzalloc(sizeof(*typdatum),GFP_KERNEL);
if (!typdatum) {
rc = -ENOMEM;
return rc;
}
- memset(typdatum, 0, sizeof(*typdatum));
rc = next_entry(buf, fp, sizeof buf);
if (rc < 0)
@@ -1259,12 +1253,11 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
__le32 buf[2];
u32 len;
- usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL);
+ usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL);
if (!usrdatum) {
rc = -ENOMEM;
goto out;
}
- memset(usrdatum, 0, sizeof(*usrdatum));
rc = next_entry(buf, fp, sizeof buf);
if (rc < 0)
@@ -1314,12 +1307,11 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
__le32 buf[2];
u32 len;
- levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC);
+ levdatum = kzalloc(sizeof(*levdatum), GFP_ATOMIC);
if (!levdatum) {
rc = -ENOMEM;
goto out;
}
- memset(levdatum, 0, sizeof(*levdatum));
rc = next_entry(buf, fp, sizeof buf);
if (rc < 0)
@@ -1366,12 +1358,11 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
__le32 buf[3];
u32 len;
- catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC);
+ catdatum = kzalloc(sizeof(*catdatum), GFP_ATOMIC);
if (!catdatum) {
rc = -ENOMEM;
goto out;
}
- memset(catdatum, 0, sizeof(*catdatum));
rc = next_entry(buf, fp, sizeof buf);
if (rc < 0)
@@ -1565,12 +1556,11 @@ int policydb_read(struct policydb *p, void *fp)
nel = le32_to_cpu(buf[0]);
ltr = NULL;
for (i = 0; i < nel; i++) {
- tr = kmalloc(sizeof(*tr), GFP_KERNEL);
+ tr = kzalloc(sizeof(*tr), GFP_KERNEL);
if (!tr) {
rc = -ENOMEM;
goto bad;
}
- memset(tr, 0, sizeof(*tr));
if (ltr) {
ltr->next = tr;
} else {
@@ -1591,12 +1581,11 @@ int policydb_read(struct policydb *p, void *fp)
nel = le32_to_cpu(buf[0]);
lra = NULL;
for (i = 0; i < nel; i++) {
- ra = kmalloc(sizeof(*ra), GFP_KERNEL);
+ ra = kzalloc(sizeof(*ra), GFP_KERNEL);
if (!ra) {
rc = -ENOMEM;
goto bad;
}
- memset(ra, 0, sizeof(*ra));
if (lra) {
lra->next = ra;
} else {
@@ -1625,12 +1614,11 @@ int policydb_read(struct policydb *p, void *fp)
nel = le32_to_cpu(buf[0]);
l = NULL;
for (j = 0; j < nel; j++) {
- c = kmalloc(sizeof(*c), GFP_KERNEL);
+ c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c) {
rc = -ENOMEM;
goto bad;
}
- memset(c, 0, sizeof(*c));
if (l) {
l->next = c;
} else {
@@ -1741,12 +1729,11 @@ int policydb_read(struct policydb *p, void *fp)
if (rc < 0)
goto bad;
len = le32_to_cpu(buf[0]);
- newgenfs = kmalloc(sizeof(*newgenfs), GFP_KERNEL);
+ newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL);
if (!newgenfs) {
rc = -ENOMEM;
goto bad;
}
- memset(newgenfs, 0, sizeof(*newgenfs));
newgenfs->fstype = kmalloc(len + 1,GFP_KERNEL);
if (!newgenfs->fstype) {
@@ -1788,12 +1775,11 @@ int policydb_read(struct policydb *p, void *fp)
goto bad;
len = le32_to_cpu(buf[0]);
- newc = kmalloc(sizeof(*newc), GFP_KERNEL);
+ newc = kzalloc(sizeof(*newc), GFP_KERNEL);
if (!newc) {
rc = -ENOMEM;
goto bad;
}
- memset(newc, 0, sizeof(*newc));
newc->u.name = kmalloc(len + 1,GFP_KERNEL);
if (!newc->u.name) {
@@ -1841,12 +1827,11 @@ int policydb_read(struct policydb *p, void *fp)
nel = le32_to_cpu(buf[0]);
lrt = NULL;
for (i = 0; i < nel; i++) {
- rt = kmalloc(sizeof(*rt), GFP_KERNEL);
+ rt = kzalloc(sizeof(*rt), GFP_KERNEL);
if (!rt) {
rc = -ENOMEM;
goto bad;
}
- memset(rt, 0, sizeof(*rt));
if (lrt)
lrt->next = rt;
else
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index aecdded55e74..44eb4d74908d 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1531,12 +1531,11 @@ int security_get_user_sids(u32 fromsid,
}
usercon.user = user->value;
- mysids = kmalloc(maxnel*sizeof(*mysids), GFP_ATOMIC);
+ mysids = kcalloc(maxnel, sizeof(*mysids), GFP_ATOMIC);
if (!mysids) {
rc = -ENOMEM;
goto out_unlock;
}
- memset(mysids, 0, maxnel*sizeof(*mysids));
ebitmap_for_each_bit(&user->roles, rnode, i) {
if (!ebitmap_node_get_bit(rnode, i))
@@ -1566,13 +1565,12 @@ int security_get_user_sids(u32 fromsid,
mysids[mynel++] = sid;
} else {
maxnel += SIDS_NEL;
- mysids2 = kmalloc(maxnel*sizeof(*mysids2), GFP_ATOMIC);
+ mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC);
if (!mysids2) {
rc = -ENOMEM;
kfree(mysids);
goto out_unlock;
}
- memset(mysids2, 0, maxnel*sizeof(*mysids2));
memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
kfree(mysids);
mysids = mysids2;
@@ -1714,12 +1712,11 @@ int security_get_bools(int *len, char ***names, int **values)
goto out;
}
- *names = (char**)kmalloc(sizeof(char*) * *len, GFP_ATOMIC);
+ *names = (char**)kcalloc(*len, sizeof(char*), GFP_ATOMIC);
if (!*names)
goto err;
- memset(*names, 0, sizeof(char*) * *len);
- *values = (int*)kmalloc(sizeof(int) * *len, GFP_ATOMIC);
+ *values = (int*)kcalloc(*len, sizeof(int), GFP_ATOMIC);
if (!*values)
goto err;