76d8aeabfe
The attached patch changes the key implementation in a number of ways: (1) It removes the spinlock from the key structure. (2) The key flags are now accessed using atomic bitops instead of write-locking the key spinlock and using C bitwise operators. The three instantiation flags are dealt with with the construction semaphore held during the request_key/instantiate/negate sequence, thus rendering the spinlock superfluous. The key flags are also now bit numbers not bit masks. (3) The key payload is now accessed using RCU. This permits the recursive keyring search algorithm to be simplified greatly since no locks need be taken other than the usual RCU preemption disablement. Searching now does not require any locks or semaphores to be held; merely that the starting keyring be pinned. (4) The keyring payload now includes an RCU head so that it can be disposed of by call_rcu(). This requires that the payload be copied on unlink to prevent introducing races in copy-down vs search-up. (5) The user key payload is now a structure with the data following it. It includes an RCU head like the keyring payload and for the same reason. It also contains a data length because the data length in the key may be changed on another CPU whilst an RCU protected read is in progress on the payload. This would then see the supposed RCU payload and the on-key data length getting out of sync. I'm tempted to drop the key's datalen entirely, except that it's used in conjunction with quota management and so is a little tricky to get rid of. (6) Update the keys documentation. Signed-Off-By: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
100 lines
2.6 KiB
C
100 lines
2.6 KiB
C
/* key-ui.h: key userspace interface stuff for use by keyfs
|
|
*
|
|
* 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
|
|
* 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.
|
|
*/
|
|
|
|
#ifndef _LINUX_KEY_UI_H
|
|
#define _LINUX_KEY_UI_H
|
|
|
|
#include <linux/key.h>
|
|
|
|
/* the key tree */
|
|
extern struct rb_root key_serial_tree;
|
|
extern spinlock_t key_serial_lock;
|
|
|
|
/* required permissions */
|
|
#define KEY_VIEW 0x01 /* require permission to view attributes */
|
|
#define KEY_READ 0x02 /* require permission to read content */
|
|
#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 */
|
|
|
|
/*
|
|
* the keyring payload contains a list of the keys to which the keyring is
|
|
* subscribed
|
|
*/
|
|
struct keyring_list {
|
|
struct rcu_head rcu; /* RCU deletion hook */
|
|
unsigned short maxkeys; /* max keys this list can hold */
|
|
unsigned short nkeys; /* number of keys currently held */
|
|
unsigned short delkey; /* key to be unlinked by RCU */
|
|
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 struct key *key, key_perm_t perm)
|
|
{
|
|
key_perm_t kperm;
|
|
|
|
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 struct key *key, key_perm_t perm)
|
|
{
|
|
key_perm_t kperm;
|
|
|
|
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 != 0;
|
|
}
|
|
|
|
|
|
extern struct key *lookup_user_key(key_serial_t id, int create, int part,
|
|
key_perm_t perm);
|
|
|
|
extern long join_session_keyring(const char *name);
|
|
|
|
extern struct key_type *key_type_lookup(const char *type);
|
|
extern void key_type_put(struct key_type *ktype);
|
|
|
|
#define key_negative_timeout 60 /* default timeout on a negative key's existence */
|
|
|
|
|
|
#endif /* _LINUX_KEY_UI_H */
|