Skip to content

Commit 2e12256

Browse files
committed
keys: Replace uid/gid/perm permissions checking with an ACL
Replace the uid/gid/perm permissions checking on a key with an ACL to allow the SETATTR and SEARCH permissions to be split. This will also allow a greater range of subjects to represented. ============ WHY DO THIS? ============ The problem is that SETATTR and SEARCH cover a slew of actions, not all of which should be grouped together. For SETATTR, this includes actions that are about controlling access to a key: (1) Changing a key's ownership. (2) Changing a key's security information. (3) Setting a keyring's restriction. And actions that are about managing a key's lifetime: (4) Setting an expiry time. (5) Revoking a key. and (proposed) managing a key as part of a cache: (6) Invalidating a key. Managing a key's lifetime doesn't really have anything to do with controlling access to that key. Expiry time is awkward since it's more about the lifetime of the content and so, in some ways goes better with WRITE permission. It can, however, be set unconditionally by a process with an appropriate authorisation token for instantiating a key, and can also be set by the key type driver when a key is instantiated, so lumping it with the access-controlling actions is probably okay. As for SEARCH permission, that currently covers: (1) Finding keys in a keyring tree during a search. (2) Permitting keyrings to be joined. (3) Invalidation. But these don't really belong together either, since these actions really need to be controlled separately. Finally, there are number of special cases to do with granting the administrator special rights to invalidate or clear keys that I would like to handle with the ACL rather than key flags and special checks. =============== WHAT IS CHANGED =============== The SETATTR permission is split to create two new permissions: (1) SET_SECURITY - which allows the key's owner, group and ACL to be changed and a restriction to be placed on a keyring. (2) REVOKE - which allows a key to be revoked. The SEARCH permission is split to create: (1) SEARCH - which allows a keyring to be search and a key to be found. (2) JOIN - which allows a keyring to be joined as a session keyring. (3) INVAL - which allows a key to be invalidated. The WRITE permission is also split to create: (1) WRITE - which allows a key's content to be altered and links to be added, removed and replaced in a keyring. (2) CLEAR - which allows a keyring to be cleared completely. This is split out to make it possible to give just this to an administrator. (3) REVOKE - see above. Keys acquire ACLs which consist of a series of ACEs, and all that apply are unioned together. An ACE specifies a subject, such as: (*) Possessor - permitted to anyone who 'possesses' a key (*) Owner - permitted to the key owner (*) Group - permitted to the key group (*) Everyone - permitted to everyone Note that 'Other' has been replaced with 'Everyone' on the assumption that you wouldn't grant a permit to 'Other' that you wouldn't also grant to everyone else. Further subjects may be made available by later patches. The ACE also specifies a permissions mask. The set of permissions is now: VIEW Can view the key metadata READ Can read the key content WRITE Can update/modify the key content SEARCH Can find the key by searching/requesting LINK Can make a link to the key SET_SECURITY Can change owner, ACL, expiry INVAL Can invalidate REVOKE Can revoke JOIN Can join this keyring CLEAR Can clear this keyring The KEYCTL_SETPERM function is then deprecated. The KEYCTL_SET_TIMEOUT function then is permitted if SET_SECURITY is set, or if the caller has a valid instantiation auth token. The KEYCTL_INVALIDATE function then requires INVAL. The KEYCTL_REVOKE function then requires REVOKE. The KEYCTL_JOIN_SESSION_KEYRING function then requires JOIN to join an existing keyring. The JOIN permission is enabled by default for session keyrings and manually created keyrings only. ====================== BACKWARD COMPATIBILITY ====================== To maintain backward compatibility, KEYCTL_SETPERM will translate the permissions mask it is given into a new ACL for a key - unless KEYCTL_SET_ACL has been called on that key, in which case an error will be returned. It will convert possessor, owner, group and other permissions into separate ACEs, if each portion of the mask is non-zero. SETATTR permission turns on all of INVAL, REVOKE and SET_SECURITY. WRITE permission turns on WRITE, REVOKE and, if a keyring, CLEAR. JOIN is turned on if a keyring is being altered. The KEYCTL_DESCRIBE function translates the ACL back into a permissions mask to return depending on possessor, owner, group and everyone ACEs. It will make the following mappings: (1) INVAL, JOIN -> SEARCH (2) SET_SECURITY -> SETATTR (3) REVOKE -> WRITE if SETATTR isn't already set (4) CLEAR -> WRITE Note that the value subsequently returned by KEYCTL_DESCRIBE may not match the value set with KEYCTL_SETATTR. ======= TESTING ======= This passes the keyutils testsuite for all but a couple of tests: (1) tests/keyctl/dh_compute/badargs: The first wrong-key-type test now returns EOPNOTSUPP rather than ENOKEY as READ permission isn't removed if the type doesn't have ->read(). You still can't actually read the key. (2) tests/keyctl/permitting/valid: The view-other-permissions test doesn't work as Other has been replaced with Everyone in the ACL. Signed-off-by: David Howells <dhowells@redhat.com>
1 parent a58946c commit 2e12256

File tree

45 files changed

+857
-324
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+857
-324
lines changed

Documentation/security/keys/core.rst

Lines changed: 100 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ Each key has a number of attributes:
5757
type provides an operation to perform a match between the description on a
5858
key and a criterion string.
5959

60-
* Each key has an owner user ID, a group ID and a permissions mask. These
61-
are used to control what a process may do to a key from userspace, and
62-
whether a kernel service will be able to find the key.
60+
* Each key has an owner user ID, a group ID and an ACL. These are used to
61+
control what a process may do to a key from userspace, and whether a
62+
kernel service will be able to find the key.
6363

6464
* Each key can be set to expire at a specific time by the key type's
6565
instantiation function. Keys can also be immortal.
@@ -198,43 +198,110 @@ The key service provides a number of features besides keys:
198198
Key Access Permissions
199199
======================
200200

201-
Keys have an owner user ID, a group access ID, and a permissions mask. The mask
202-
has up to eight bits each for possessor, user, group and other access. Only
203-
six of each set of eight bits are defined. These permissions granted are:
201+
Keys have an owner user ID, a group ID and an ACL. The ACL is made up of a
202+
sequence of ACEs that each contain three elements:
204203

205-
* View
204+
* The type of subject.
205+
* The subject.
206206

207-
This permits a key or keyring's attributes to be viewed - including key
208-
type and description.
207+
These two together indicate the subject to whom the permits are granted.
208+
The type can be one of:
209209

210-
* Read
210+
* ``KEY_ACE_SUBJ_STANDARD``
211211

212-
This permits a key's payload to be viewed or a keyring's list of linked
213-
keys.
212+
The subject is a standard 'macro' type. The subject can be one of:
213+
214+
* ``KEY_ACE_EVERYONE``
215+
216+
The permits are granted to everyone. It replaces the old 'other'
217+
type on the assumption that you wouldn't grant a permission to other
218+
that you you wouldn't grant to everyone else.
219+
220+
* ``KEY_ACE_OWNER``
221+
222+
The permits are granted to the owner of the key (key->uid).
223+
224+
* ``KEY_ACE_GROUP``
225+
226+
The permits are granted to the key's group (key->gid).
227+
228+
* ``KEY_ACE_POSSESSOR``
229+
230+
The permits are granted to anyone who possesses the key.
231+
232+
* The set of permits granted to the subject. These include:
233+
234+
* ``KEY_ACE_VIEW``
235+
236+
This permits a key or keyring's attributes to be viewed - including the
237+
key type and description.
238+
239+
* ``KEY_ACE_READ``
240+
241+
This permits a key's payload to be viewed or a keyring's list of linked
242+
keys.
214243

215-
* Write
244+
* ``KEY_ACE_WRITE``
216245

217-
This permits a key's payload to be instantiated or updated, or it allows a
218-
link to be added to or removed from a keyring.
246+
This permits a key's payload to be instantiated or updated, or it allows
247+
a link to be added to or removed from a keyring.
219248

220-
* Search
249+
* ``KEY_ACE_SEARCH``
221250

222-
This permits keyrings to be searched and keys to be found. Searches can
223-
only recurse into nested keyrings that have search permission set.
251+
This permits keyrings to be searched and keys to be found. Searches can
252+
only recurse into nested keyrings that have search permission set.
224253

225-
* Link
254+
* ``KEY_ACE_LINK``
226255

227-
This permits a key or keyring to be linked to. To create a link from a
228-
keyring to a key, a process must have Write permission on the keyring and
229-
Link permission on the key.
256+
This permits a key or keyring to be linked to. To create a link from a
257+
keyring to a key, a process must have Write permission on the keyring
258+
and Link permission on the key.
230259

231-
* Set Attribute
260+
* ``KEY_ACE_SET_SECURITY``
232261

233-
This permits a key's UID, GID and permissions mask to be changed.
262+
This permits a key's UID, GID and permissions mask to be changed.
263+
264+
* ``KEY_ACE_INVAL``
265+
266+
This permits a key to be invalidated with KEYCTL_INVALIDATE.
267+
268+
* ``KEY_ACE_REVOKE``
269+
270+
This permits a key to be revoked with KEYCTL_REVOKE.
271+
272+
* ``KEY_ACE_JOIN``
273+
274+
This permits a keyring to be joined as a session by
275+
KEYCTL_JOIN_SESSION_KEYRING or KEYCTL_SESSION_TO_PARENT.
276+
277+
* ``KEY_ACE_CLEAR``
278+
279+
This permits a keyring to be cleared.
234280

235281
For changing the ownership, group ID or permissions mask, being the owner of
236282
the key or having the sysadmin capability is sufficient.
237283

284+
The legacy KEYCTL_SETPERM and KEYCTL_DESCRIBE functions can only see/generate
285+
View, Read, Write, Search, Link and SetAttr permits, and do this for each of
286+
possessor, user, group and other permission sets as a 32-bit flag mask. These
287+
will be approximated/inferred:
288+
289+
SETPERM Permit Implied ACE Permit
290+
=============== =======================
291+
Search Inval, Join
292+
Write Revoke, Clear
293+
Setattr Set Security, Revoke
294+
295+
ACE Permit Described as
296+
=============== =======================
297+
Inval Search
298+
Join Search
299+
Revoke Write (unless Setattr)
300+
Clear write
301+
Set Security Setattr
302+
303+
'Other' will be approximated as/inferred from the 'Everyone' subject.
304+
238305

239306
SELinux Support
240307
===============
@@ -1084,7 +1151,8 @@ payload contents" for more information.
10841151

10851152
struct key *request_key(const struct key_type *type,
10861153
const char *description,
1087-
const char *callout_info);
1154+
const char *callout_info,
1155+
struct key_acl *acl);
10881156
10891157
This is used to request a key or keyring with a description that matches
10901158
the description specified according to the key type's match_preparse()
@@ -1099,6 +1167,8 @@ payload contents" for more information.
10991167
If successful, the key will have been attached to the default keyring for
11001168
implicitly obtained request-key keys, as set by KEYCTL_SET_REQKEY_KEYRING.
11011169

1170+
If a key is created, it will be given the specified ACL.
1171+
11021172
See also Documentation/security/keys/request-key.rst.
11031173

11041174

@@ -1107,7 +1177,8 @@ payload contents" for more information.
11071177
struct key *request_key_tag(const struct key_type *type,
11081178
const char *description,
11091179
struct key_tag *domain_tag,
1110-
const char *callout_info);
1180+
const char *callout_info,
1181+
struct key_acl *acl);
11111182
11121183
This is identical to request_key(), except that a domain tag may be
11131184
specifies that causes search algorithm to only match keys matching that
@@ -1122,7 +1193,8 @@ payload contents" for more information.
11221193
struct key_tag *domain_tag,
11231194
const void *callout_info,
11241195
size_t callout_len,
1125-
void *aux);
1196+
void *aux,
1197+
struct key_acl *acl);
11261198
11271199
This is identical to request_key_tag(), except that the auxiliary data is
11281200
passed to the key_type->request_key() op if it exists, and the
@@ -1195,7 +1267,7 @@ payload contents" for more information.
11951267

11961268
struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
11971269
const struct cred *cred,
1198-
key_perm_t perm,
1270+
struct key_acl *acl,
11991271
struct key_restriction *restrict_link,
12001272
unsigned long flags,
12011273
struct key *dest);

Documentation/security/keys/request-key.rst

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ The process starts by either the kernel requesting a service by calling
1111

1212
struct key *request_key(const struct key_type *type,
1313
const char *description,
14-
const char *callout_info);
14+
const char *callout_info,
15+
struct key_acl *acl);
1516

1617
or::
1718

1819
struct key *request_key_tag(const struct key_type *type,
1920
const char *description,
2021
const struct key_tag *domain_tag,
21-
const char *callout_info);
22+
const char *callout_info,
23+
struct key_acl *acl);
2224

2325
or::
2426

@@ -27,7 +29,8 @@ or::
2729
const struct key_tag *domain_tag,
2830
const char *callout_info,
2931
size_t callout_len,
30-
void *aux);
32+
void *aux,
33+
struct key_acl *acl);
3134

3235
or::
3336

certs/blacklist.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,7 @@ int mark_hash_blacklisted(const char *hash)
9393
hash,
9494
NULL,
9595
0,
96-
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
97-
KEY_USR_VIEW),
96+
&internal_key_acl,
9897
KEY_ALLOC_NOT_IN_QUOTA |
9998
KEY_ALLOC_BUILT_IN);
10099
if (IS_ERR(key)) {
@@ -153,9 +152,7 @@ static int __init blacklist_init(void)
153152
keyring_alloc(".blacklist",
154153
KUIDT_INIT(0), KGIDT_INIT(0),
155154
current_cred(),
156-
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
157-
KEY_USR_VIEW | KEY_USR_READ |
158-
KEY_USR_SEARCH,
155+
&internal_keyring_acl,
159156
KEY_ALLOC_NOT_IN_QUOTA |
160157
KEY_FLAG_KEEP,
161158
NULL, NULL);

certs/system_keyring.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,7 @@ static __init int system_trusted_keyring_init(void)
103103
builtin_trusted_keys =
104104
keyring_alloc(".builtin_trusted_keys",
105105
KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
106-
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
107-
KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH),
108-
KEY_ALLOC_NOT_IN_QUOTA,
106+
&internal_key_acl, KEY_ALLOC_NOT_IN_QUOTA,
109107
NULL, NULL);
110108
if (IS_ERR(builtin_trusted_keys))
111109
panic("Can't allocate builtin trusted keyring\n");
@@ -114,10 +112,7 @@ static __init int system_trusted_keyring_init(void)
114112
secondary_trusted_keys =
115113
keyring_alloc(".secondary_trusted_keys",
116114
KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
117-
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
118-
KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH |
119-
KEY_USR_WRITE),
120-
KEY_ALLOC_NOT_IN_QUOTA,
115+
&internal_writable_keyring_acl, KEY_ALLOC_NOT_IN_QUOTA,
121116
get_builtin_and_secondary_restriction(),
122117
NULL);
123118
if (IS_ERR(secondary_trusted_keys))
@@ -167,8 +162,7 @@ static __init int load_system_certificate_list(void)
167162
NULL,
168163
p,
169164
plen,
170-
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
171-
KEY_USR_VIEW | KEY_USR_READ),
165+
&internal_key_acl,
172166
KEY_ALLOC_NOT_IN_QUOTA |
173167
KEY_ALLOC_BUILT_IN |
174168
KEY_ALLOC_BYPASS_RESTRICTION);

drivers/md/dm-crypt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2035,7 +2035,7 @@ static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string
20352035
return -ENOMEM;
20362036

20372037
key = request_key(key_string[0] == 'l' ? &key_type_logon : &key_type_user,
2038-
key_desc + 1, NULL);
2038+
key_desc + 1, NULL, NULL);
20392039
if (IS_ERR(key)) {
20402040
kzfree(new_key_string);
20412041
return PTR_ERR(key);

drivers/nvdimm/security.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ static struct key *nvdimm_request_key(struct nvdimm *nvdimm)
5555
struct device *dev = &nvdimm->dev;
5656

5757
sprintf(desc, "%s%s", NVDIMM_PREFIX, nvdimm->dimm_id);
58-
key = request_key(&key_type_encrypted, desc, "");
58+
key = request_key(&key_type_encrypted, desc, "", NULL);
5959
if (IS_ERR(key)) {
6060
if (PTR_ERR(key) == -ENOKEY)
6161
dev_dbg(dev, "request_key() found no key\n");

fs/afs/security.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ struct key *afs_request_key(struct afs_cell *cell)
3232

3333
_debug("key %s", cell->anonymous_key->description);
3434
key = request_key(&key_type_rxrpc, cell->anonymous_key->description,
35-
NULL);
35+
NULL, NULL);
3636
if (IS_ERR(key)) {
3737
if (PTR_ERR(key) != -ENOKEY) {
3838
_leave(" = %ld", PTR_ERR(key));

fs/cifs/cifs_spnego.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,25 @@
3232
#include "cifsproto.h"
3333
static const struct cred *spnego_cred;
3434

35+
static struct key_acl cifs_spnego_key_acl = {
36+
.usage = REFCOUNT_INIT(1),
37+
.nr_ace = 2,
38+
.possessor_viewable = true,
39+
.aces = {
40+
KEY_POSSESSOR_ACE(KEY_ACE_VIEW | KEY_ACE_SEARCH | KEY_ACE_READ),
41+
KEY_OWNER_ACE(KEY_ACE_VIEW),
42+
}
43+
};
44+
45+
static struct key_acl cifs_spnego_keyring_acl = {
46+
.usage = REFCOUNT_INIT(1),
47+
.nr_ace = 2,
48+
.aces = {
49+
KEY_POSSESSOR_ACE(KEY_ACE_SEARCH | KEY_ACE_WRITE),
50+
KEY_OWNER_ACE(KEY_ACE_VIEW | KEY_ACE_READ | KEY_ACE_CLEAR),
51+
}
52+
};
53+
3554
/* create a new cifs key */
3655
static int
3756
cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
@@ -170,7 +189,8 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
170189

171190
cifs_dbg(FYI, "key description = %s\n", description);
172191
saved_cred = override_creds(spnego_cred);
173-
spnego_key = request_key(&cifs_spnego_key_type, description, "");
192+
spnego_key = request_key(&cifs_spnego_key_type, description, "",
193+
&cifs_spnego_key_acl);
174194
revert_creds(saved_cred);
175195

176196
#ifdef CONFIG_CIFS_DEBUG2
@@ -207,8 +227,7 @@ init_cifs_spnego(void)
207227

208228
keyring = keyring_alloc(".cifs_spnego",
209229
GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
210-
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
211-
KEY_USR_VIEW | KEY_USR_READ,
230+
&cifs_spnego_keyring_acl,
212231
KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
213232
if (IS_ERR(keyring)) {
214233
ret = PTR_ERR(keyring);

0 commit comments

Comments
 (0)