2005-10-07 14:07:45

by David Howells

[permalink] [raw]
Subject: [PATCH] Keys: Split key permissions checking into a .c file


The attached patch splits key permissions checking out of key-ui.h and moves
it into a .c file. It's quite large and called quite a lot, and it's about to
get bigger with the addition of LSM support for keys...

key_any_permission() is also discarded as it's no longer used.

Signed-Off-By: David Howells <[email protected]>
---
warthog>diffstat -p1 keys-split-2614rc3.diff
include/linux/key-ui.h | 91 ++-------------------------------------------
security/keys/Makefile | 1
security/keys/permission.c | 70 ++++++++++++++++++++++++++++++++++
3 files changed, 76 insertions(+), 86 deletions(-)

diff -uNrp linux-2.6.14-rc3-keys/include/linux/key-ui.h linux-2.6.14-rc3-keys-split/include/linux/key-ui.h
--- linux-2.6.14-rc3-keys/include/linux/key-ui.h 2005-10-03 10:48:38.000000000 +0100
+++ linux-2.6.14-rc3-keys-split/include/linux/key-ui.h 2005-10-07 14:07:05.000000000 +0100
@@ -38,97 +38,16 @@ struct keyring_list {
struct key *keys[0];
};

-
/*
* check to see whether permission is granted to use a key in the desired way
*/
-static inline int key_permission(const key_ref_t key_ref, key_perm_t perm)
-{
- struct key *key = key_ref_to_ptr(key_ref);
- key_perm_t kperm;
-
- if (is_key_possessed(key_ref))
- kperm = key->perm >> 24;
- else if (key->uid == current->fsuid)
- kperm = key->perm >> 16;
- else if (key->gid != -1 &&
- key->perm & KEY_GRP_ALL &&
- in_group_p(key->gid)
- )
- kperm = key->perm >> 8;
- else
- kperm = key->perm;
-
- kperm = kperm & perm & KEY_ALL;
-
- return kperm == perm;
-}
-
-/*
- * check to see whether permission is granted to use a key in at least one of
- * the desired ways
- */
-static inline int key_any_permission(const key_ref_t key_ref, key_perm_t perm)
-{
- struct key *key = key_ref_to_ptr(key_ref);
- key_perm_t kperm;
-
- if (is_key_possessed(key_ref))
- kperm = key->perm >> 24;
- else if (key->uid == current->fsuid)
- kperm = key->perm >> 16;
- else if (key->gid != -1 &&
- key->perm & KEY_GRP_ALL &&
- in_group_p(key->gid)
- )
- kperm = key->perm >> 8;
- else
- kperm = key->perm;
+extern int key_task_permission(const key_ref_t key_ref,
+ struct task_struct *context,
+ key_perm_t perm);

- kperm = kperm & perm & KEY_ALL;
-
- return kperm != 0;
-}
-
-static inline int key_task_groups_search(struct task_struct *tsk, gid_t gid)
-{
- int ret;
-
- task_lock(tsk);
- ret = groups_search(tsk->group_info, gid);
- task_unlock(tsk);
- return ret;
-}
-
-static inline int key_task_permission(const key_ref_t key_ref,
- struct task_struct *context,
- key_perm_t perm)
+static inline int key_permission(const key_ref_t key_ref, key_perm_t perm)
{
- struct key *key = key_ref_to_ptr(key_ref);
- key_perm_t kperm;
-
- if (is_key_possessed(key_ref)) {
- kperm = key->perm >> 24;
- }
- else if (key->uid == context->fsuid) {
- kperm = key->perm >> 16;
- }
- else if (key->gid != -1 &&
- key->perm & KEY_GRP_ALL && (
- key->gid == context->fsgid ||
- key_task_groups_search(context, key->gid)
- )
- ) {
- kperm = key->perm >> 8;
- }
- else {
- kperm = key->perm;
- }
-
- kperm = kperm & perm & KEY_ALL;
-
- return kperm == perm;
-
+ return key_task_permission(key_ref, current, perm);
}

extern key_ref_t lookup_user_key(struct task_struct *context,
diff -uNrp linux-2.6.14-rc3-keys/security/keys/Makefile linux-2.6.14-rc3-keys-split/security/keys/Makefile
--- linux-2.6.14-rc3-keys/security/keys/Makefile 2005-08-30 13:56:44.000000000 +0100
+++ linux-2.6.14-rc3-keys-split/security/keys/Makefile 2005-10-07 14:05:57.000000000 +0100
@@ -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 -uNrp linux-2.6.14-rc3-keys/security/keys/permission.c linux-2.6.14-rc3-keys-split/security/keys/permission.c
--- linux-2.6.14-rc3-keys/security/keys/permission.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.14-rc3-keys-split/security/keys/permission.c 2005-10-07 14:06:35.000000000 +0100
@@ -0,0 +1,70 @@
+/* permission.c: key permission determination
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells ([email protected])
+ *
+ * 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 "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 top 8-bits of permissions for keys the caller possesses */
+ if (is_key_possessed(key_ref)) {
+ kperm = key->perm >> 24;
+ goto use_these_perms;
+ }
+
+ /* 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:
+ kperm = kperm & perm & KEY_ALL;
+
+ return kperm == perm;
+
+} /* end key_task_permission() */
+
+EXPORT_SYMBOL(key_task_permission);


2005-10-07 15:41:39

by David Howells

[permalink] [raw]
Subject: [PATCH] Keys: Possessor permissions should be additive


This patch makes the possessor permissions on a key additive with
user/group/other permissions on the same key.

This permits extra rights to be granted to the possessor of a key without
taking away any rights conferred by them owning the key or having common group
membership.

This needs to be applied on top of the patch ensubjected:

[PATCH] Keys: Split key permissions checking into a .c file

Signed-Off-By: David Howells <[email protected]>
---
warthog>diffstat -p1 keys-addperm-2614rc3.diff
security/keys/permission.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)

diff -uNrp linux-2.6.14-rc3-keys-split/security/keys/permission.c linux-2.6.14-rc3-keys-addperm/security/keys/permission.c
--- linux-2.6.14-rc3-keys-split/security/keys/permission.c 2005-10-07 14:06:35.000000000 +0100
+++ linux-2.6.14-rc3-keys-addperm/security/keys/permission.c 2005-10-07 16:29:59.000000000 +0100
@@ -27,12 +27,6 @@ int key_task_permission(const key_ref_t

key = key_ref_to_ptr(key_ref);

- /* use the top 8-bits of permissions for keys the caller possesses */
- if (is_key_possessed(key_ref)) {
- kperm = key->perm >> 24;
- goto use_these_perms;
- }
-
/* use the second 8-bits of permissions for keys the caller owns */
if (key->uid == context->fsuid) {
kperm = key->perm >> 16;
@@ -61,6 +55,12 @@ int key_task_permission(const key_ref_t
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;

return kperm == perm;

2005-10-07 15:58:04

by David Howells

[permalink] [raw]
Subject: [PATCH] Keys: Add LSM hooks for key management [try #2]


The attached patch adds LSM hooks for key management facilities. The notable
changes are:

(1) The key struct now supports a security pointer for the use of security
modules. This will permit key labelling and restrictions on which
programs may access a key.

(2) Security modules get a chance to note (or abort) the allocation of a key.

(3) The key permission checking can now be enhanced by the security modules;
the permissions check consults LSM if all other checks bear out.

(4) The key permissions checking functions now return an error code rather
than a boolean value.

(5) An extra permission has been added to govern the modification of
attributes (UID, GID, permissions).

Note that there isn't an LSM hook specifically for each keyctl() operation,
but rather the permissions hook allows control of individual operations based
on the permission request bits.

Key management access control through LSM is enabled by automatically if both
CONFIG_KEYS and CONFIG_SECURITY are enabled.

This should be applied on top of the patch ensubjected:

[PATCH] Keys: Possessor permissions should be additive


Signed-Off-By: David Howells <[email protected]>
---
warthog>diffstat -p1 keys-lsm-2614rc3-2.diff
Documentation/keys.txt | 22 +++++++-----
include/linux/key-ui.h | 3 +
include/linux/key.h | 13 +++++--
include/linux/security.h | 73 +++++++++++++++++++++++++++++++++++++++++++
security/dummy.c | 23 +++++++++++++
security/keys/key.c | 56 +++++++++++++++++++++++---------
security/keys/keyctl.c | 13 ++++---
security/keys/keyring.c | 21 +++++++-----
security/keys/permission.c | 7 +++-
security/keys/process_keys.c | 9 ++---
10 files changed, 191 insertions(+), 49 deletions(-)

diff -uNrp linux-2.6.14-rc3-keys-addperm/Documentation/keys.txt linux-2.6.14-rc3-keys-lsm/Documentation/keys.txt
--- linux-2.6.14-rc3-keys-addperm/Documentation/keys.txt 2005-10-07 14:46:31.000000000 +0100
+++ linux-2.6.14-rc3-keys-lsm/Documentation/keys.txt 2005-10-07 16:33:26.000000000 +0100
@@ -196,7 +196,7 @@ KEY ACCESS PERMISSIONS

Keys have an owner user ID, a group access ID, and a permissions mask. The mask
has up to eight bits each for possessor, user, group and other access. Only
-five of each set of eight bits are defined. These permissions granted are:
+six of each set of eight bits are defined. These permissions granted are:

(*) View

@@ -224,6 +224,10 @@ five of each set of eight bits are defin
keyring to a key, a process must have Write permission on the keyring and
Link permission on the key.

+ (*) Set Attribute
+
+ This permits a key's UID, GID and permissions mask to be changed.
+
For changing the ownership, group ID or permissions mask, being the owner of
the key or having the sysadmin capability is sufficient.

@@ -242,15 +246,15 @@ about the status of the key service:
this way:

SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY
- 00000001 I----- 39 perm 1f1f0000 0 0 keyring _uid_ses.0: 1/4
- 00000002 I----- 2 perm 1f1f0000 0 0 keyring _uid.0: empty
- 00000007 I----- 1 perm 1f1f0000 0 0 keyring _pid.1: empty
- 0000018d I----- 1 perm 1f1f0000 0 0 keyring _pid.412: empty
- 000004d2 I--Q-- 1 perm 1f1f0000 32 -1 keyring _uid.32: 1/4
- 000004d3 I--Q-- 3 perm 1f1f0000 32 -1 keyring _uid_ses.32: empty
+ 00000001 I----- 39 perm 1f3f0000 0 0 keyring _uid_ses.0: 1/4
+ 00000002 I----- 2 perm 1f3f0000 0 0 keyring _uid.0: empty
+ 00000007 I----- 1 perm 1f3f0000 0 0 keyring _pid.1: empty
+ 0000018d I----- 1 perm 1f3f0000 0 0 keyring _pid.412: empty
+ 000004d2 I--Q-- 1 perm 1f3f0000 32 -1 keyring _uid.32: 1/4
+ 000004d3 I--Q-- 3 perm 1f3f0000 32 -1 keyring _uid_ses.32: empty
00000892 I--QU- 1 perm 1f000000 0 0 user metal:copper: 0
- 00000893 I--Q-N 1 35s 1f1f0000 0 0 user metal:silver: 0
- 00000894 I--Q-- 1 10h 001f0000 0 0 user metal:gold: 0
+ 00000893 I--Q-N 1 35s 1f3f0000 0 0 user metal:silver: 0
+ 00000894 I--Q-- 1 10h 003f0000 0 0 user metal:gold: 0

The flags are:

diff -uNrp linux-2.6.14-rc3-keys-addperm/include/linux/key.h linux-2.6.14-rc3-keys-lsm/include/linux/key.h
--- linux-2.6.14-rc3-keys-addperm/include/linux/key.h 2005-10-05 11:50:22.000000000 +0100
+++ linux-2.6.14-rc3-keys-lsm/include/linux/key.h 2005-10-07 15:46:29.000000000 +0100
@@ -40,28 +40,32 @@ struct key;
#define KEY_POS_WRITE 0x04000000 /* possessor can update key payload / add link to keyring */
#define KEY_POS_SEARCH 0x08000000 /* possessor can find a key in search / search a keyring */
#define KEY_POS_LINK 0x10000000 /* possessor can create a link to a key/keyring */
-#define KEY_POS_ALL 0x1f000000
+#define KEY_POS_SETATTR 0x20000000 /* possessor can set key attributes */
+#define KEY_POS_ALL 0x3f000000

#define KEY_USR_VIEW 0x00010000 /* user permissions... */
#define KEY_USR_READ 0x00020000
#define KEY_USR_WRITE 0x00040000
#define KEY_USR_SEARCH 0x00080000
#define KEY_USR_LINK 0x00100000
-#define KEY_USR_ALL 0x001f0000
+#define KEY_USR_SETATTR 0x00200000
+#define KEY_USR_ALL 0x003f0000

#define KEY_GRP_VIEW 0x00000100 /* group permissions... */
#define KEY_GRP_READ 0x00000200
#define KEY_GRP_WRITE 0x00000400
#define KEY_GRP_SEARCH 0x00000800
#define KEY_GRP_LINK 0x00001000
-#define KEY_GRP_ALL 0x00001f00
+#define KEY_GRP_SETATTR 0x00002000
+#define KEY_GRP_ALL 0x00003f00

#define KEY_OTH_VIEW 0x00000001 /* third party permissions... */
#define KEY_OTH_READ 0x00000002
#define KEY_OTH_WRITE 0x00000004
#define KEY_OTH_SEARCH 0x00000008
#define KEY_OTH_LINK 0x00000010
-#define KEY_OTH_ALL 0x0000001f
+#define KEY_OTH_SETATTR 0x00000020
+#define KEY_OTH_ALL 0x0000003f

struct seq_file;
struct user_struct;
@@ -119,6 +123,7 @@ struct key {
struct key_type *type; /* type of key */
struct rw_semaphore sem; /* change vs change sem */
struct key_user *user; /* owner of this key */
+ void *security; /* security data for this key */
time_t expiry; /* time at which key expires (or 0) */
uid_t uid;
gid_t gid;
diff -uNrp linux-2.6.14-rc3-keys-addperm/include/linux/key-ui.h linux-2.6.14-rc3-keys-lsm/include/linux/key-ui.h
--- linux-2.6.14-rc3-keys-addperm/include/linux/key-ui.h 2005-10-07 14:07:05.000000000 +0100
+++ linux-2.6.14-rc3-keys-lsm/include/linux/key-ui.h 2005-10-07 16:15:09.000000000 +0100
@@ -24,7 +24,8 @@ extern spinlock_t key_serial_lock;
#define KEY_WRITE 0x04 /* require permission to update / modify */
#define KEY_SEARCH 0x08 /* require permission to search (keyring) or find (key) */
#define KEY_LINK 0x10 /* require permission to link */
-#define KEY_ALL 0x1f /* all the above permissions */
+#define KEY_SETATTR 0x20 /* require permission to change attributes */
+#define KEY_ALL 0x3f /* all the above permissions */

/*
* the keyring payload contains a list of the keys to which the keyring is
diff -uNrp linux-2.6.14-rc3-keys-addperm/include/linux/security.h linux-2.6.14-rc3-keys-lsm/include/linux/security.h
--- linux-2.6.14-rc3-keys-addperm/include/linux/security.h 2005-10-03 10:48:39.000000000 +0100
+++ linux-2.6.14-rc3-keys-lsm/include/linux/security.h 2005-10-07 16:01:33.000000000 +0100
@@ -30,6 +30,7 @@
#include <linux/shm.h>
#include <linux/msg.h>
#include <linux/sched.h>
+#include <linux/key.h>

struct ctl_table;

@@ -785,6 +786,27 @@ struct swap_info_struct;
* @sk_free_security:
* Deallocate security structure.
*
+ * Security hooks affecting all Key Management operations
+ *
+ * @key_alloc:
+ * Permit allocation of a key and assign security data. Note that key does
+ * not have a serial number assigned at this point.
+ * @key points to the key.
+ * Return 0 if permission is granted, -ve error otherwise.
+ * @key_free:
+ * Notification of destruction; free security data.
+ * @key points to the key.
+ * No return value.
+ * @key_permission:
+ * See whether a specific operational right is granted to a process on a
+ * key.
+ * @key_ref refers to the key (key pointer + possession attribute bit).
+ * @context points to the process to provide the context against which to
+ * evaluate the security data on the key.
+ * @perm describes the combination of permissions required of this key.
+ * Return 1 if permission granted, 0 if permission denied and -ve it the
+ * normal permissions model should be effected.
+ *
* Security hooks affecting all System V IPC operations.
*
* @ipc_permission:
@@ -1213,6 +1235,17 @@ struct security_operations {
int (*sk_alloc_security) (struct sock *sk, int family, int priority);
void (*sk_free_security) (struct sock *sk);
#endif /* CONFIG_SECURITY_NETWORK */
+
+ /* key management security hooks */
+#ifdef CONFIG_KEYS
+ int (*key_alloc)(struct key *key);
+ void (*key_free)(struct key *key);
+ int (*key_permission)(key_ref_t key_ref,
+ struct task_struct *context,
+ key_perm_t perm);
+
+#endif /* CONFIG_KEYS */
+
};

/* global variables */
@@ -2763,5 +2796,45 @@ static inline void security_sk_free(stru
}
#endif /* CONFIG_SECURITY_NETWORK */

+#ifdef CONFIG_KEYS
+#ifdef CONFIG_SECURITY
+static inline int security_key_alloc(struct key *key)
+{
+ return security_ops->key_alloc(key);
+}
+
+static inline void security_key_free(struct key *key)
+{
+ security_ops->key_free(key);
+}
+
+static inline int security_key_permission(key_ref_t key_ref,
+ struct task_struct *context,
+ key_perm_t perm)
+{
+ return security_ops->key_permission(key_ref, context, perm);
+}
+
+#else
+
+static inline int security_key_alloc(struct key *key)
+{
+ return 0;
+}
+
+static inline void security_key_free(struct key *key)
+{
+}
+
+static inline int security_key_permission(key_ref_t key_ref,
+ struct task_struct *context,
+ key_perm_t perm)
+{
+ return -1;
+}
+
+#endif
+#endif /* CONFIG_KEYS */
+
#endif /* ! __LINUX_SECURITY_H */

diff -uNrp linux-2.6.14-rc3-keys-addperm/security/dummy.c linux-2.6.14-rc3-keys-lsm/security/dummy.c
--- linux-2.6.14-rc3-keys-addperm/security/dummy.c 2005-10-03 10:48:43.000000000 +0100
+++ linux-2.6.14-rc3-keys-lsm/security/dummy.c 2005-10-07 16:36:00.000000000 +0100
@@ -803,6 +803,23 @@ static int dummy_setprocattr(struct task
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
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 -uNrp linux-2.6.14-rc3-keys-addperm/security/keys/key.c linux-2.6.14-rc3-keys-lsm/security/keys/key.c
--- linux-2.6.14-rc3-keys-addperm/security/keys/key.c 2005-10-03 10:48:43.000000000 +0100
+++ linux-2.6.14-rc3-keys-lsm/security/keys/key.c 2005-10-07 16:07:17.000000000 +0100
@@ -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 ([email protected])
*
* 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"
@@ -253,6 +254,7 @@ struct key *key_alloc(struct key_type *t
struct key_user *user = NULL;
struct key *key;
size_t desclen, quotalen;
+ int ret;

key = ERR_PTR(-EINVAL);
if (!desc || !*desc)
@@ -305,6 +307,7 @@ struct key *key_alloc(struct key_type *t
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 +318,34 @@ struct key *key_alloc(struct key_type *t
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);
+ if (!not_in_quota) {
+ spin_lock(&user->lock);
+ user->qnkeys--;
+ user->qnbytes -= quotalen;
+ spin_unlock(&user->lock);
+ }
+ key_user_put(user);
+ key = ERR_PTR(ret);
+ goto error;
+
+no_memory_3:
kmem_cache_free(key_jar, key);
- no_memory_2:
+no_memory_2:
if (!not_in_quota) {
spin_lock(&user->lock);
user->qnkeys--;
@@ -332,11 +353,11 @@ struct key *key_alloc(struct key_type *t
spin_unlock(&user->lock);
}
key_user_put(user);
- no_memory_1:
+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 +577,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);
@@ -700,8 +723,8 @@ static inline key_ref_t __key_update(key
int ret;

/* need write permission on the key to update it */
- ret = -EACCES;
- if (!key_permission(key_ref, KEY_WRITE))
+ ret = key_permission(key_ref, KEY_WRITE);
+ if (ret < 0)
goto error;

ret = -EEXIST;
@@ -711,7 +734,6 @@ static inline key_ref_t __key_update(key
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);
@@ -768,9 +790,11 @@ key_ref_t key_create_or_update(key_ref_t

/* if we're going to allocate a new key, we're going to have
* to modify the keyring */
- key_ref = ERR_PTR(-EACCES);
- if (!key_permission(keyring_ref, KEY_WRITE))
+ 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
@@ -780,8 +804,8 @@ key_ref_t key_create_or_update(key_ref_t
goto found_matching_key;

/* decide on the permissions we want */
- perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK;
- 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_POS_READ | KEY_USR_READ;
@@ -840,16 +864,16 @@ int key_update(key_ref_t key_ref, const
key_check(key);

/* the key must be writable */
- ret = -EACCES;
- if (!key_permission(key_ref, 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 -uNrp linux-2.6.14-rc3-keys-addperm/security/keys/keyctl.c linux-2.6.14-rc3-keys-lsm/security/keys/keyctl.c
--- linux-2.6.14-rc3-keys-addperm/security/keys/keyctl.c 2005-10-03 10:48:43.000000000 +0100
+++ linux-2.6.14-rc3-keys-lsm/security/keys/keyctl.c 2005-10-07 15:49:36.000000000 +0100
@@ -624,8 +624,8 @@ long keyctl_keyring_search(key_serial_t

/* link the resulting key to the destination keyring if we can */
if (dest_ref) {
- ret = -EACCES;
- if (!key_permission(key_ref, KEY_LINK))
+ ret = key_permission(key_ref, KEY_LINK);
+ if (ret < 0)
goto error6;

ret = key_link(key_ref_to_ptr(dest_ref), key_ref_to_ptr(key_ref));
@@ -676,8 +676,11 @@ long keyctl_read_key(key_serial_t keyid,
key = key_ref_to_ptr(key_ref);

/* see if we can read it directly */
- if (key_permission(key_ref, KEY_READ))
+ 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
@@ -726,7 +729,7 @@ long keyctl_chown_key(key_serial_t id, u
if (uid == (uid_t) -1 && gid == (gid_t) -1)
goto error;

- key_ref = lookup_user_key(NULL, id, 1, 1, 0);
+ key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR);
if (IS_ERR(key_ref)) {
ret = PTR_ERR(key_ref);
goto error;
@@ -786,7 +789,7 @@ long keyctl_setperm_key(key_serial_t id,
if (perm & ~(KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL))
goto error;

- key_ref = lookup_user_key(NULL, id, 1, 1, 0);
+ key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR);
if (IS_ERR(key_ref)) {
ret = PTR_ERR(key_ref);
goto error;
diff -uNrp linux-2.6.14-rc3-keys-addperm/security/keys/keyring.c linux-2.6.14-rc3-keys-lsm/security/keys/keyring.c
--- linux-2.6.14-rc3-keys-addperm/security/keys/keyring.c 2005-10-03 10:48:43.000000000 +0100
+++ linux-2.6.14-rc3-keys-lsm/security/keys/keyring.c 2005-10-07 16:11:56.000000000 +0100
@@ -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 *de
int ret;

keyring = key_alloc(&key_type_keyring, description,
- uid, gid, KEY_POS_ALL | 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);
@@ -359,9 +362,11 @@ key_ref_t keyring_search_aux(key_ref_t k
key_check(keyring);

/* top keyring must have search permission to begin the search */
- key_ref = ERR_PTR(-EACCES);
- if (!key_task_permission(keyring_ref, context, KEY_SEARCH))
+ err = key_task_permission(keyring_ref, context, KEY_SEARCH);
+ if (err < 0) {
+ key_ref = ERR_PTR(err);
goto error;
+ }

key_ref = ERR_PTR(-ENOTDIR);
if (keyring->type != &key_type_keyring)
@@ -402,8 +407,8 @@ descend:
continue;

/* key must have search permissions */
- if (!key_task_permission(make_key_ref(key, possessed),
- 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 */
@@ -430,7 +435,7 @@ ascend:
continue;

if (!key_task_permission(make_key_ref(key, possessed),
- context, KEY_SEARCH))
+ context, KEY_SEARCH) < 0)
continue;

/* stack the current position */
@@ -521,7 +526,7 @@ key_ref_t __keyring_search_one(key_ref_t
(!key->type->match ||
key->type->match(key, description)) &&
key_permission(make_key_ref(key, possessed),
- perm) &&
+ perm) < 0 &&
!test_bit(KEY_FLAG_REVOKED, &key->flags)
)
goto found;
@@ -617,7 +622,7 @@ struct key *find_keyring_by_name(const c
continue;

if (!key_permission(make_key_ref(keyring, 0),
- KEY_SEARCH))
+ KEY_SEARCH) < 0)
continue;

/* found a potential candidate, but we still need to
diff -uNrp linux-2.6.14-rc3-keys-addperm/security/keys/permission.c linux-2.6.14-rc3-keys-lsm/security/keys/permission.c
--- linux-2.6.14-rc3-keys-addperm/security/keys/permission.c 2005-10-07 16:29:59.000000000 +0100
+++ linux-2.6.14-rc3-keys-lsm/security/keys/permission.c 2005-10-07 16:21:07.000000000 +0100
@@ -10,6 +10,7 @@
*/

#include <linux/module.h>
+#include <linux/security.h>
#include "internal.h"

/*****************************************************************************/
@@ -63,7 +64,11 @@ use_these_perms:

kperm = kperm & perm & KEY_ALL;

- return kperm == perm;
+ if (kperm != perm)
+ return -EACCES;
+
+ /* let LSM be the final arbiter */
+ return security_key_permission(key_ref, context, perm);

} /* end key_task_permission() */

diff -uNrp linux-2.6.14-rc3-keys-addperm/security/keys/process_keys.c linux-2.6.14-rc3-keys-lsm/security/keys/process_keys.c
--- linux-2.6.14-rc3-keys-addperm/security/keys/process_keys.c 2005-10-03 10:48:43.000000000 +0100
+++ linux-2.6.14-rc3-keys-lsm/security/keys/process_keys.c 2005-10-07 16:12:14.000000000 +0100
@@ -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_POS_ALL | 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_POS_ALL | 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
@@ -666,9 +666,8 @@ key_ref_t lookup_user_key(struct task_st
goto invalid_key;

/* check the permissions */
- ret = -EACCES;
-
- if (!key_task_permission(key_ref, context, perm))
+ ret = key_task_permission(key_ref, context, perm);
+ if (ret < 0)
goto invalid_key;

error:

2005-10-07 16:09:23

by David Howells

[permalink] [raw]
Subject: [PATCH] Keys: Remove key duplication


The attached patch removes the key duplication stuff since there's nothing
that uses it, no way to get at it and it's awkward to deal with for LSM
purposes.

This patch should be applied on top of the one ensubjected:

[PATCH] Keys: Add LSM hooks for key management [try #2]

Signed-Off-By: David Howells <[email protected]>
---
warthog>diffstat -p1 keys-nodup-2614rc3.diff
Documentation/keys.txt | 18 ------------
include/keys/user-type.h | 1
include/linux/key.h | 8 -----
security/keys/key.c | 56 ++-----------------------------------
security/keys/keyring.c | 64 -------------------------------------------
security/keys/user_defined.c | 32 ---------------------
6 files changed, 3 insertions(+), 176 deletions(-)

diff -uNrp linux-2.6.14-rc3-keys-lsm/Documentation/keys.txt linux-2.6.14-rc3-keys-nodup/Documentation/keys.txt
--- linux-2.6.14-rc3-keys-lsm/Documentation/keys.txt 2005-10-07 16:33:26.000000000 +0100
+++ linux-2.6.14-rc3-keys-nodup/Documentation/keys.txt 2005-10-07 16:59:59.000000000 +0100
@@ -860,24 +860,6 @@ The structure has a number of fields, so
It is safe to sleep in this method.


- (*) int (*duplicate)(struct key *key, const struct key *source);
-
- If this type of key can be duplicated, then this method should be
- provided. It is called to copy the payload attached to the source into the
- new key. The data length on the new key will have been updated and the
- quota adjusted already.
-
- This method will be called with the source key's semaphore read-locked to
- prevent its payload from being changed, thus RCU constraints need not be
- applied to the source key.
-
- This method does not have to lock the destination key in order to attach a
- payload. The fact that KEY_FLAG_INSTANTIATED is not set in key->flags
- prevents anything else from gaining access to the key.
-
- It is safe to sleep in this method.
-
-
(*) int (*update)(struct key *key, const void *data, size_t datalen);

If this type of key can be updated, then this method should be provided.
diff -uNrp linux-2.6.14-rc3-keys-lsm/include/keys/user-type.h linux-2.6.14-rc3-keys-nodup/include/keys/user-type.h
--- linux-2.6.14-rc3-keys-lsm/include/keys/user-type.h 2005-10-05 11:44:54.000000000 +0100
+++ linux-2.6.14-rc3-keys-nodup/include/keys/user-type.h 2005-10-07 17:03:19.000000000 +0100
@@ -35,7 +35,6 @@ struct user_key_payload {
extern struct key_type key_type_user;

extern int user_instantiate(struct key *key, const void *data, size_t datalen);
-extern int user_duplicate(struct key *key, const struct key *source);
extern int user_update(struct key *key, const void *data, size_t datalen);
extern int user_match(const struct key *key, const void *criterion);
extern void user_destroy(struct key *key);
diff -uNrp linux-2.6.14-rc3-keys-lsm/include/linux/key.h linux-2.6.14-rc3-keys-nodup/include/linux/key.h
--- linux-2.6.14-rc3-keys-lsm/include/linux/key.h 2005-10-07 15:46:29.000000000 +0100
+++ linux-2.6.14-rc3-keys-nodup/include/linux/key.h 2005-10-07 17:00:08.000000000 +0100
@@ -193,14 +193,6 @@ struct key_type {
*/
int (*instantiate)(struct key *key, const void *data, size_t datalen);

- /* duplicate a key of this type (optional)
- * - the source key will be locked against change
- * - the new description will be attached
- * - the quota will have been adjusted automatically from
- * source->quotalen
- */
- int (*duplicate)(struct key *key, const struct key *source);
-
/* update a key of this type (optional)
* - this method should call key_payload_reserve() to recalculate the
* quota consumption
diff -uNrp linux-2.6.14-rc3-keys-lsm/security/keys/key.c linux-2.6.14-rc3-keys-nodup/security/keys/key.c
--- linux-2.6.14-rc3-keys-lsm/security/keys/key.c 2005-10-07 16:07:17.000000000 +0100
+++ linux-2.6.14-rc3-keys-nodup/security/keys/key.c 2005-10-07 16:59:20.000000000 +0100
@@ -241,9 +241,9 @@ static inline void key_alloc_serial(stru
/*
* allocate a key of the specified type
* - update the user's quota to reflect the existence of the key
- * - called from a key-type operation with key_types_sem read-locked by either
- * key_create_or_update() or by key_duplicate(); this prevents unregistration
- * of the key type
+ * - called from a key-type operation with key_types_sem read-locked by
+ * key_create_or_update()
+ * - this prevents unregistration of the key type
* - upon return the key is as yet uninstantiated; the caller needs to either
* instantiate the key or discard it before returning
*/
@@ -890,56 +890,6 @@ EXPORT_SYMBOL(key_update);

/*****************************************************************************/
/*
- * duplicate a key, potentially with a revised description
- * - must be supported by the keytype (keyrings for instance can be duplicated)
- */
-struct key *key_duplicate(struct key *source, const char *desc)
-{
- struct key *key;
- int ret;
-
- key_check(source);
-
- if (!desc)
- desc = source->description;
-
- down_read(&key_types_sem);
-
- ret = -EINVAL;
- if (!source->type->duplicate)
- goto error;
-
- /* allocate and instantiate a key */
- key = key_alloc(source->type, desc, current->fsuid, current->fsgid,
- source->perm, 0);
- if (IS_ERR(key))
- goto error_k;
-
- down_read(&source->sem);
- ret = key->type->duplicate(key, source);
- up_read(&source->sem);
- if (ret < 0)
- goto error2;
-
- atomic_inc(&key->user->nikeys);
- set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
-
- error_k:
- up_read(&key_types_sem);
- out:
- return key;
-
- error2:
- key_put(key);
- error:
- up_read(&key_types_sem);
- key = ERR_PTR(ret);
- goto out;
-
-} /* end key_duplicate() */
-
-/*****************************************************************************/
-/*
* revoke a key
*/
void key_revoke(struct key *key)
diff -uNrp linux-2.6.14-rc3-keys-lsm/security/keys/keyring.c linux-2.6.14-rc3-keys-nodup/security/keys/keyring.c
--- linux-2.6.14-rc3-keys-lsm/security/keys/keyring.c 2005-10-07 16:11:56.000000000 +0100
+++ linux-2.6.14-rc3-keys-nodup/security/keys/keyring.c 2005-10-07 16:59:30.000000000 +0100
@@ -48,7 +48,6 @@ static inline unsigned keyring_hash(cons
*/
static int keyring_instantiate(struct key *keyring,
const void *data, size_t datalen);
-static int keyring_duplicate(struct key *keyring, const struct key *source);
static int keyring_match(const struct key *keyring, const void *criterion);
static void keyring_destroy(struct key *keyring);
static void keyring_describe(const struct key *keyring, struct seq_file *m);
@@ -59,7 +58,6 @@ struct key_type key_type_keyring = {
.name = "keyring",
.def_datalen = sizeof(struct keyring_list),
.instantiate = keyring_instantiate,
- .duplicate = keyring_duplicate,
.match = keyring_match,
.destroy = keyring_destroy,
.describe = keyring_describe,
@@ -120,68 +118,6 @@ static int keyring_instantiate(struct ke

/*****************************************************************************/
/*
- * duplicate the list of subscribed keys from a source keyring into this one
- */
-static int keyring_duplicate(struct key *keyring, const struct key *source)
-{
- struct keyring_list *sklist, *klist;
- unsigned max;
- size_t size;
- int loop, ret;
-
- const unsigned limit =
- (PAGE_SIZE - sizeof(*klist)) / sizeof(struct key *);
-
- ret = 0;
-
- /* find out how many keys are currently linked */
- rcu_read_lock();
- sklist = rcu_dereference(source->payload.subscriptions);
- max = 0;
- if (sklist)
- max = sklist->nkeys;
- rcu_read_unlock();
-
- /* allocate a new payload and stuff load with key links */
- if (max > 0) {
- BUG_ON(max > limit);
-
- max = (max + 3) & ~3;
- if (max > limit)
- max = limit;
-
- ret = -ENOMEM;
- size = sizeof(*klist) + sizeof(struct key *) * max;
- klist = kmalloc(size, GFP_KERNEL);
- if (!klist)
- goto error;
-
- /* set links */
- rcu_read_lock();
- sklist = rcu_dereference(source->payload.subscriptions);
-
- klist->maxkeys = max;
- klist->nkeys = sklist->nkeys;
- memcpy(klist->keys,
- sklist->keys,
- sklist->nkeys * sizeof(struct key *));
-
- for (loop = klist->nkeys - 1; loop >= 0; loop--)
- atomic_inc(&klist->keys[loop]->usage);
-
- rcu_read_unlock();
-
- rcu_assign_pointer(keyring->payload.subscriptions, klist);
- ret = 0;
- }
-
- error:
- return ret;
-
-} /* end keyring_duplicate() */
-
-/*****************************************************************************/
-/*
* match keyrings on their name
*/
static int keyring_match(const struct key *keyring, const void *description)
diff -uNrp linux-2.6.14-rc3-keys-lsm/security/keys/user_defined.c linux-2.6.14-rc3-keys-nodup/security/keys/user_defined.c
--- linux-2.6.14-rc3-keys-lsm/security/keys/user_defined.c 2005-10-05 11:37:04.000000000 +0100
+++ linux-2.6.14-rc3-keys-nodup/security/keys/user_defined.c 2005-10-07 16:59:41.000000000 +0100
@@ -26,7 +26,6 @@
struct key_type key_type_user = {
.name = "user",
.instantiate = user_instantiate,
- .duplicate = user_duplicate,
.update = user_update,
.match = user_match,
.destroy = user_destroy,
@@ -73,37 +72,6 @@ EXPORT_SYMBOL(user_instantiate);

/*****************************************************************************/
/*
- * duplicate a user defined key
- * - both keys' semaphores are locked against further modification
- * - the new key cannot yet be accessed
- */
-int user_duplicate(struct key *key, const struct key *source)
-{
- struct user_key_payload *upayload, *spayload;
- int ret;
-
- /* just copy the payload */
- ret = -ENOMEM;
- upayload = kmalloc(sizeof(*upayload) + source->datalen, GFP_KERNEL);
- if (upayload) {
- spayload = rcu_dereference(source->payload.data);
- BUG_ON(source->datalen != spayload->datalen);
-
- upayload->datalen = key->datalen = spayload->datalen;
- memcpy(upayload->data, spayload->data, key->datalen);
-
- key->payload.data = upayload;
- ret = 0;
- }
-
- return ret;
-
-} /* end user_duplicate() */
-
-EXPORT_SYMBOL(user_duplicate);
-
-/*****************************************************************************/
-/*
* dispose of the old data from an updated user defined key
*/
static void user_update_rcu_disposal(struct rcu_head *rcu)

2005-10-07 22:04:41

by Chris Wright

[permalink] [raw]
Subject: Re: [Keyrings] [PATCH] Keys: Add LSM hooks for key management [try #2]

* David Howells ([email protected]) wrote:
> +static inline int security_key_permission(key_ref_t key_ref,
> + struct task_struct *context,
> + key_perm_t perm)
> +{
> + return -1;
> +}

No solid reason on that one, might as well be 0 for consistency.

Other than that, looks good. It's going to conflict with some pending
changes I have, how shall we work that? I can put all of these in that
queue?

thanks,
-chris

2005-10-07 23:34:30

by David Howells

[permalink] [raw]
Subject: Re: [Keyrings] [PATCH] Keys: Add LSM hooks for key management [try #2]

Chris Wright <[email protected]> wrote:

> > +{
> > + return -1;
> > +}
>
> No solid reason on that one, might as well be 0 for consistency.

Grrr! That needs to be zero otherwise it'll deny everything by default. I'd
fallen over that one and fixed it, but I must've forgotten to rediff the patch
before submitting it.

David

2005-10-07 23:35:57

by Chris Wright

[permalink] [raw]
Subject: Re: [Keyrings] [PATCH] Keys: Add LSM hooks for key management [try #2]

* David Howells ([email protected]) wrote:
> Chris Wright <[email protected]> wrote:
>
> > > +{
> > > + return -1;
> > > +}
> >
> > No solid reason on that one, might as well be 0 for consistency.
>
> Grrr! That needs to be zero otherwise it'll deny everything by default. I'd
> fallen over that one and fixed it, but I must've forgotten to rediff the patch
> before submitting it.

I thought that too at first, which is why I flagged it at first. But I
think it's actually not a real problem, because isn't that !CONFIG_KEYS?
So, I think it's just cosmetic.

2005-10-07 23:39:10

by David Howells

[permalink] [raw]
Subject: Re: [Keyrings] [PATCH] Keys: Add LSM hooks for key management [try #2]

Chris Wright <[email protected]> wrote:

> I thought that too at first, which is why I flagged it at first. But I
> think it's actually not a real problem, because isn't that !CONFIG_KEYS?
> So, I think it's just cosmetic.

It is a problem; at least I found it to be one. And no it isn't !CONFIG_KEYS.

David

2005-10-07 23:45:26

by David Howells

[permalink] [raw]
Subject: Re: [Keyrings] [PATCH] Keys: Add LSM hooks for key management [try #2]


Hi Chris,

David Howells <[email protected]> wrote:

> > I thought that too at first, which is why I flagged it at first. But I
> > think it's actually not a real problem, because isn't that !CONFIG_KEYS?
> > So, I think it's just cosmetic.
>
> It is a problem; at least I found it to be one. And no it isn't !CONFIG_KEYS.

It's not one I'd fixed earlier. I fixed the same problem, but in the dummy
routines. It's contingent on CONFIG_KEYS and !CONFIG_SECURITY. Would you be
willing to whip up a patch to change it? I'd do it, but I'm currently logged
in on my laptop over a 9600 baud modem connection.

Thanks!
David

2005-10-07 23:46:18

by Chris Wright

[permalink] [raw]
Subject: Re: [Keyrings] [PATCH] Keys: Add LSM hooks for key management [try #2]

* David Howells ([email protected]) wrote:
> Chris Wright <[email protected]> wrote:
>
> > I thought that too at first, which is why I flagged it at first. But I
> > think it's actually not a real problem, because isn't that !CONFIG_KEYS?
> > So, I think it's just cosmetic.
>
> It is a problem; at least I found it to be one. And no it isn't !CONFIG_KEYS.

Ah, right, that's the other ifdef there.

2005-10-07 23:47:06

by Chris Wright

[permalink] [raw]
Subject: Re: [Keyrings] [PATCH] Keys: Add LSM hooks for key management [try #2]

* David Howells ([email protected]) wrote:
>
> Hi Chris,
>
> David Howells <[email protected]> wrote:
>
> > > I thought that too at first, which is why I flagged it at first. But I
> > > think it's actually not a real problem, because isn't that !CONFIG_KEYS?
> > > So, I think it's just cosmetic.
> >
> > It is a problem; at least I found it to be one. And no it isn't !CONFIG_KEYS.
>
> It's not one I'd fixed earlier. I fixed the same problem, but in the dummy
> routines. It's contingent on CONFIG_KEYS and !CONFIG_SECURITY. Would you be
> willing to whip up a patch to change it? I'd do it, but I'm currently logged
> in on my laptop over a 9600 baud modem connection.

No problem.

thanks,
-chris

2005-10-08 06:52:04

by Chris Wright

[permalink] [raw]
Subject: [PATCH] Keys: Add LSM hooks for key management [try #3]

From: David Howells <[email protected]>

The attached patch adds LSM hooks for key management facilities. The notable
changes are:

(1) The key struct now supports a security pointer for the use of security
modules. This will permit key labelling and restrictions on which
programs may access a key.

(2) Security modules get a chance to note (or abort) the allocation of a key.

(3) The key permission checking can now be enhanced by the security modules;
the permissions check consults LSM if all other checks bear out.

(4) The key permissions checking functions now return an error code rather
than a boolean value.

(5) An extra permission has been added to govern the modification of
attributes (UID, GID, permissions).

Note that there isn't an LSM hook specifically for each keyctl() operation,
but rather the permissions hook allows control of individual operations based
on the permission request bits.

Key management access control through LSM is enabled by automatically if both
CONFIG_KEYS and CONFIG_SECURITY are enabled.

This should be applied on top of the patch ensubjected:

[PATCH] Keys: Possessor permissions should be additive


Signed-Off-By: David Howells <[email protected]>
Signed-off-by: Chris Wright <[email protected]>
---
Documentation/keys.txt | 22 +++++++-----
include/linux/key-ui.h | 3 +
include/linux/key.h | 13 +++++--
include/linux/security.h | 73 +++++++++++++++++++++++++++++++++++++++++++
security/dummy.c | 23 +++++++++++++
security/keys/key.c | 56 +++++++++++++++++++++++---------
security/keys/keyctl.c | 13 ++++---
security/keys/keyring.c | 21 +++++++-----
security/keys/permission.c | 7 +++-
security/keys/process_keys.c | 9 ++---
10 files changed, 191 insertions(+), 49 deletions(-)

Index: linus-2.6/Documentation/keys.txt
===================================================================
--- linus-2.6.orig/Documentation/keys.txt
+++ linus-2.6/Documentation/keys.txt
@@ -196,7 +196,7 @@ KEY ACCESS PERMISSIONS

Keys have an owner user ID, a group access ID, and a permissions mask. The mask
has up to eight bits each for possessor, user, group and other access. Only
-five of each set of eight bits are defined. These permissions granted are:
+six of each set of eight bits are defined. These permissions granted are:

(*) View

@@ -224,6 +224,10 @@ five of each set of eight bits are defin
keyring to a key, a process must have Write permission on the keyring and
Link permission on the key.

+ (*) Set Attribute
+
+ This permits a key's UID, GID and permissions mask to be changed.
+
For changing the ownership, group ID or permissions mask, being the owner of
the key or having the sysadmin capability is sufficient.

@@ -242,15 +246,15 @@ about the status of the key service:
this way:

SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY
- 00000001 I----- 39 perm 1f1f0000 0 0 keyring _uid_ses.0: 1/4
- 00000002 I----- 2 perm 1f1f0000 0 0 keyring _uid.0: empty
- 00000007 I----- 1 perm 1f1f0000 0 0 keyring _pid.1: empty
- 0000018d I----- 1 perm 1f1f0000 0 0 keyring _pid.412: empty
- 000004d2 I--Q-- 1 perm 1f1f0000 32 -1 keyring _uid.32: 1/4
- 000004d3 I--Q-- 3 perm 1f1f0000 32 -1 keyring _uid_ses.32: empty
+ 00000001 I----- 39 perm 1f3f0000 0 0 keyring _uid_ses.0: 1/4
+ 00000002 I----- 2 perm 1f3f0000 0 0 keyring _uid.0: empty
+ 00000007 I----- 1 perm 1f3f0000 0 0 keyring _pid.1: empty
+ 0000018d I----- 1 perm 1f3f0000 0 0 keyring _pid.412: empty
+ 000004d2 I--Q-- 1 perm 1f3f0000 32 -1 keyring _uid.32: 1/4
+ 000004d3 I--Q-- 3 perm 1f3f0000 32 -1 keyring _uid_ses.32: empty
00000892 I--QU- 1 perm 1f000000 0 0 user metal:copper: 0
- 00000893 I--Q-N 1 35s 1f1f0000 0 0 user metal:silver: 0
- 00000894 I--Q-- 1 10h 001f0000 0 0 user metal:gold: 0
+ 00000893 I--Q-N 1 35s 1f3f0000 0 0 user metal:silver: 0
+ 00000894 I--Q-- 1 10h 003f0000 0 0 user metal:gold: 0

The flags are:

Index: linus-2.6/include/linux/key.h
===================================================================
--- linus-2.6.orig/include/linux/key.h
+++ linus-2.6/include/linux/key.h
@@ -40,28 +40,32 @@ struct key;
#define KEY_POS_WRITE 0x04000000 /* possessor can update key payload / add link to keyring */
#define KEY_POS_SEARCH 0x08000000 /* possessor can find a key in search / search a keyring */
#define KEY_POS_LINK 0x10000000 /* possessor can create a link to a key/keyring */
-#define KEY_POS_ALL 0x1f000000
+#define KEY_POS_SETATTR 0x20000000 /* possessor can set key attributes */
+#define KEY_POS_ALL 0x3f000000

#define KEY_USR_VIEW 0x00010000 /* user permissions... */
#define KEY_USR_READ 0x00020000
#define KEY_USR_WRITE 0x00040000
#define KEY_USR_SEARCH 0x00080000
#define KEY_USR_LINK 0x00100000
-#define KEY_USR_ALL 0x001f0000
+#define KEY_USR_SETATTR 0x00200000
+#define KEY_USR_ALL 0x003f0000

#define KEY_GRP_VIEW 0x00000100 /* group permissions... */
#define KEY_GRP_READ 0x00000200
#define KEY_GRP_WRITE 0x00000400
#define KEY_GRP_SEARCH 0x00000800
#define KEY_GRP_LINK 0x00001000
-#define KEY_GRP_ALL 0x00001f00
+#define KEY_GRP_SETATTR 0x00002000
+#define KEY_GRP_ALL 0x00003f00

#define KEY_OTH_VIEW 0x00000001 /* third party permissions... */
#define KEY_OTH_READ 0x00000002
#define KEY_OTH_WRITE 0x00000004
#define KEY_OTH_SEARCH 0x00000008
#define KEY_OTH_LINK 0x00000010
-#define KEY_OTH_ALL 0x0000001f
+#define KEY_OTH_SETATTR 0x00000020
+#define KEY_OTH_ALL 0x0000003f

struct seq_file;
struct user_struct;
@@ -119,6 +123,7 @@ struct key {
struct key_type *type; /* type of key */
struct rw_semaphore sem; /* change vs change sem */
struct key_user *user; /* owner of this key */
+ void *security; /* security data for this key */
time_t expiry; /* time at which key expires (or 0) */
uid_t uid;
gid_t gid;
Index: linus-2.6/include/linux/key-ui.h
===================================================================
--- linus-2.6.orig/include/linux/key-ui.h
+++ linus-2.6/include/linux/key-ui.h
@@ -24,7 +24,8 @@ extern spinlock_t key_serial_lock;
#define KEY_WRITE 0x04 /* require permission to update / modify */
#define KEY_SEARCH 0x08 /* require permission to search (keyring) or find (key) */
#define KEY_LINK 0x10 /* require permission to link */
-#define KEY_ALL 0x1f /* all the above permissions */
+#define KEY_SETATTR 0x20 /* require permission to change attributes */
+#define KEY_ALL 0x3f /* all the above permissions */

/*
* the keyring payload contains a list of the keys to which the keyring is
Index: linus-2.6/include/linux/security.h
===================================================================
--- linus-2.6.orig/include/linux/security.h
+++ linus-2.6/include/linux/security.h
@@ -30,6 +30,7 @@
#include <linux/shm.h>
#include <linux/msg.h>
#include <linux/sched.h>
+#include <linux/key.h>

struct ctl_table;

@@ -785,6 +786,27 @@ struct swap_info_struct;
* @sk_free_security:
* Deallocate security structure.
*
+ * Security hooks affecting all Key Management operations
+ *
+ * @key_alloc:
+ * Permit allocation of a key and assign security data. Note that key does
+ * not have a serial number assigned at this point.
+ * @key points to the key.
+ * Return 0 if permission is granted, -ve error otherwise.
+ * @key_free:
+ * Notification of destruction; free security data.
+ * @key points to the key.
+ * No return value.
+ * @key_permission:
+ * See whether a specific operational right is granted to a process on a
+ * key.
+ * @key_ref refers to the key (key pointer + possession attribute bit).
+ * @context points to the process to provide the context against which to
+ * evaluate the security data on the key.
+ * @perm describes the combination of permissions required of this key.
+ * Return 1 if permission granted, 0 if permission denied and -ve it the
+ * normal permissions model should be effected.
+ *
* Security hooks affecting all System V IPC operations.
*
* @ipc_permission:
@@ -1213,6 +1235,17 @@ struct security_operations {
int (*sk_alloc_security) (struct sock *sk, int family, int priority);
void (*sk_free_security) (struct sock *sk);
#endif /* CONFIG_SECURITY_NETWORK */
+
+ /* key management security hooks */
+#ifdef CONFIG_KEYS
+ int (*key_alloc)(struct key *key);
+ void (*key_free)(struct key *key);
+ int (*key_permission)(key_ref_t key_ref,
+ struct task_struct *context,
+ key_perm_t perm);
+
+#endif /* CONFIG_KEYS */
+
};

/* global variables */
@@ -2763,5 +2796,45 @@ static inline void security_sk_free(stru
}
#endif /* CONFIG_SECURITY_NETWORK */

+#ifdef CONFIG_KEYS
+#ifdef CONFIG_SECURITY
+static inline int security_key_alloc(struct key *key)
+{
+ return security_ops->key_alloc(key);
+}
+
+static inline void security_key_free(struct key *key)
+{
+ security_ops->key_free(key);
+}
+
+static inline int security_key_permission(key_ref_t key_ref,
+ struct task_struct *context,
+ key_perm_t perm)
+{
+ return security_ops->key_permission(key_ref, context, perm);
+}
+
+#else
+
+static inline int security_key_alloc(struct key *key)
+{
+ return 0;
+}
+
+static inline void security_key_free(struct key *key)
+{
+}
+
+static inline int security_key_permission(key_ref_t key_ref,
+ struct task_struct *context,
+ key_perm_t perm)
+{
+ return 0;
+}
+
+#endif
+#endif /* CONFIG_KEYS */
+
#endif /* ! __LINUX_SECURITY_H */

Index: linus-2.6/security/dummy.c
===================================================================
--- linus-2.6.orig/security/dummy.c
+++ linus-2.6/security/dummy.c
@@ -803,6 +803,23 @@ static int dummy_setprocattr(struct task
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
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 */
+
}

Index: linus-2.6/security/keys/key.c
===================================================================
--- linus-2.6.orig/security/keys/key.c
+++ linus-2.6/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 ([email protected])
*
* 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"
@@ -253,6 +254,7 @@ struct key *key_alloc(struct key_type *t
struct key_user *user = NULL;
struct key *key;
size_t desclen, quotalen;
+ int ret;

key = ERR_PTR(-EINVAL);
if (!desc || !*desc)
@@ -305,6 +307,7 @@ struct key *key_alloc(struct key_type *t
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 +318,34 @@ struct key *key_alloc(struct key_type *t
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);
+ if (!not_in_quota) {
+ spin_lock(&user->lock);
+ user->qnkeys--;
+ user->qnbytes -= quotalen;
+ spin_unlock(&user->lock);
+ }
+ key_user_put(user);
+ key = ERR_PTR(ret);
+ goto error;
+
+no_memory_3:
kmem_cache_free(key_jar, key);
- no_memory_2:
+no_memory_2:
if (!not_in_quota) {
spin_lock(&user->lock);
user->qnkeys--;
@@ -332,11 +353,11 @@ struct key *key_alloc(struct key_type *t
spin_unlock(&user->lock);
}
key_user_put(user);
- no_memory_1:
+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 +577,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);
@@ -700,8 +723,8 @@ static inline key_ref_t __key_update(key
int ret;

/* need write permission on the key to update it */
- ret = -EACCES;
- if (!key_permission(key_ref, KEY_WRITE))
+ ret = key_permission(key_ref, KEY_WRITE);
+ if (ret < 0)
goto error;

ret = -EEXIST;
@@ -711,7 +734,6 @@ static inline key_ref_t __key_update(key
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);
@@ -768,9 +790,11 @@ key_ref_t key_create_or_update(key_ref_t

/* if we're going to allocate a new key, we're going to have
* to modify the keyring */
- key_ref = ERR_PTR(-EACCES);
- if (!key_permission(keyring_ref, KEY_WRITE))
+ 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
@@ -780,8 +804,8 @@ key_ref_t key_create_or_update(key_ref_t
goto found_matching_key;

/* decide on the permissions we want */
- perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK;
- 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_POS_READ | KEY_USR_READ;
@@ -840,16 +864,16 @@ int key_update(key_ref_t key_ref, const
key_check(key);

/* the key must be writable */
- ret = -EACCES;
- if (!key_permission(key_ref, 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);
Index: linus-2.6/security/keys/keyctl.c
===================================================================
--- linus-2.6.orig/security/keys/keyctl.c
+++ linus-2.6/security/keys/keyctl.c
@@ -624,8 +624,8 @@ long keyctl_keyring_search(key_serial_t

/* link the resulting key to the destination keyring if we can */
if (dest_ref) {
- ret = -EACCES;
- if (!key_permission(key_ref, KEY_LINK))
+ ret = key_permission(key_ref, KEY_LINK);
+ if (ret < 0)
goto error6;

ret = key_link(key_ref_to_ptr(dest_ref), key_ref_to_ptr(key_ref));
@@ -676,8 +676,11 @@ long keyctl_read_key(key_serial_t keyid,
key = key_ref_to_ptr(key_ref);

/* see if we can read it directly */
- if (key_permission(key_ref, KEY_READ))
+ 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
@@ -726,7 +729,7 @@ long keyctl_chown_key(key_serial_t id, u
if (uid == (uid_t) -1 && gid == (gid_t) -1)
goto error;

- key_ref = lookup_user_key(NULL, id, 1, 1, 0);
+ key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR);
if (IS_ERR(key_ref)) {
ret = PTR_ERR(key_ref);
goto error;
@@ -786,7 +789,7 @@ long keyctl_setperm_key(key_serial_t id,
if (perm & ~(KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL))
goto error;

- key_ref = lookup_user_key(NULL, id, 1, 1, 0);
+ key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR);
if (IS_ERR(key_ref)) {
ret = PTR_ERR(key_ref);
goto error;
Index: linus-2.6/security/keys/keyring.c
===================================================================
--- linus-2.6.orig/security/keys/keyring.c
+++ linus-2.6/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 *de
int ret;

keyring = key_alloc(&key_type_keyring, description,
- uid, gid, KEY_POS_ALL | 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);
@@ -359,9 +362,11 @@ key_ref_t keyring_search_aux(key_ref_t k
key_check(keyring);

/* top keyring must have search permission to begin the search */
- key_ref = ERR_PTR(-EACCES);
- if (!key_task_permission(keyring_ref, context, KEY_SEARCH))
+ err = key_task_permission(keyring_ref, context, KEY_SEARCH);
+ if (err < 0) {
+ key_ref = ERR_PTR(err);
goto error;
+ }

key_ref = ERR_PTR(-ENOTDIR);
if (keyring->type != &key_type_keyring)
@@ -402,8 +407,8 @@ descend:
continue;

/* key must have search permissions */
- if (!key_task_permission(make_key_ref(key, possessed),
- 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 */
@@ -430,7 +435,7 @@ ascend:
continue;

if (!key_task_permission(make_key_ref(key, possessed),
- context, KEY_SEARCH))
+ context, KEY_SEARCH) < 0)
continue;

/* stack the current position */
@@ -521,7 +526,7 @@ key_ref_t __keyring_search_one(key_ref_t
(!key->type->match ||
key->type->match(key, description)) &&
key_permission(make_key_ref(key, possessed),
- perm) &&
+ perm) < 0 &&
!test_bit(KEY_FLAG_REVOKED, &key->flags)
)
goto found;
@@ -617,7 +622,7 @@ struct key *find_keyring_by_name(const c
continue;

if (!key_permission(make_key_ref(keyring, 0),
- KEY_SEARCH))
+ KEY_SEARCH) < 0)
continue;

/* found a potential candidate, but we still need to
Index: linus-2.6/security/keys/permission.c
===================================================================
--- linus-2.6.orig/security/keys/permission.c
+++ linus-2.6/security/keys/permission.c
@@ -10,6 +10,7 @@
*/

#include <linux/module.h>
+#include <linux/security.h>
#include "internal.h"

/*****************************************************************************/
@@ -63,7 +64,11 @@ use_these_perms:

kperm = kperm & perm & KEY_ALL;

- return kperm == perm;
+ if (kperm != perm)
+ return -EACCES;
+
+ /* let LSM be the final arbiter */
+ return security_key_permission(key_ref, context, perm);

} /* end key_task_permission() */

Index: linus-2.6/security/keys/process_keys.c
===================================================================
--- linus-2.6.orig/security/keys/process_keys.c
+++ linus-2.6/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_POS_ALL | 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_POS_ALL | 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
@@ -666,9 +666,8 @@ key_ref_t lookup_user_key(struct task_st
goto invalid_key;

/* check the permissions */
- ret = -EACCES;
-
- if (!key_task_permission(key_ref, context, perm))
+ ret = key_task_permission(key_ref, context, perm);
+ if (ret < 0)
goto invalid_key;

error:

2005-11-01 14:17:04

by David Howells

[permalink] [raw]
Subject: [PATCH] Keys: Remove incorrect and obsolete '!' operators


The attached patch removes a couple of incorrect and obsolete '!' operators
left over from the conversion of the key permission functions from true/false
returns to zero/error returns.

Signed-Off-By: David Howells <[email protected]>
---
warthog>diffstat -p1 keys-debang-2614rc5mm1.diff
security/keys/keyring.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)

diff -uNrp linux-2.6.14-rc5-mm1/security/keys/keyring.c linux-2.6.14-rc5-mm1-keys/security/keys/keyring.c
--- linux-2.6.14-rc5-mm1/security/keys/keyring.c 2005-11-01 13:22:53.000000000 +0000
+++ linux-2.6.14-rc5-mm1-keys/security/keys/keyring.c 2005-11-01 13:40:52.000000000 +0000
@@ -434,8 +434,8 @@ ascend:
if (sp >= KEYRING_SEARCH_MAX_DEPTH)
continue;

- if (!key_task_permission(make_key_ref(key, possessed),
- context, KEY_SEARCH) < 0)
+ if (key_task_permission(make_key_ref(key, possessed),
+ context, KEY_SEARCH) < 0)
continue;

/* stack the current position */
@@ -621,8 +621,8 @@ struct key *find_keyring_by_name(const c
if (strcmp(keyring->description, name) != 0)
continue;

- if (!key_permission(make_key_ref(keyring, 0),
- KEY_SEARCH) < 0)
+ if (key_permission(make_key_ref(keyring, 0),
+ KEY_SEARCH) < 0)
continue;

/* found a potential candidate, but we still need to