1 /* General persistent per-UID keyrings register
3 * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
12 #include <linux/user_namespace.h>
13 #include <linux/cred.h>
17 unsigned persistent_keyring_expiry
= 3 * 24 * 3600; /* Expire after 3 days of non-use */
20 * Create the persistent keyring register for the current user namespace.
22 * Called with the namespace's sem locked for writing.
24 static int key_create_persistent_register(struct user_namespace
*ns
)
26 struct key
*reg
= keyring_alloc(".persistent_register",
27 KUIDT_INIT(0), KGIDT_INIT(0),
29 ((KEY_POS_ALL
& ~KEY_POS_SETATTR
) |
30 KEY_USR_VIEW
| KEY_USR_READ
),
31 KEY_ALLOC_NOT_IN_QUOTA
, NULL
, NULL
);
35 ns
->persistent_keyring_register
= reg
;
40 * Create the persistent keyring for the specified user.
42 * Called with the namespace's sem locked for writing.
44 static key_ref_t
key_create_persistent(struct user_namespace
*ns
, kuid_t uid
,
45 struct keyring_index_key
*index_key
)
47 struct key
*persistent
;
48 key_ref_t reg_ref
, persistent_ref
;
50 if (!ns
->persistent_keyring_register
) {
51 long err
= key_create_persistent_register(ns
);
55 reg_ref
= make_key_ref(ns
->persistent_keyring_register
, true);
56 persistent_ref
= find_key_to_update(reg_ref
, index_key
);
58 return persistent_ref
;
61 persistent
= keyring_alloc(index_key
->description
,
62 uid
, INVALID_GID
, current_cred(),
63 ((KEY_POS_ALL
& ~KEY_POS_SETATTR
) |
64 KEY_USR_VIEW
| KEY_USR_READ
),
65 KEY_ALLOC_NOT_IN_QUOTA
, NULL
,
66 ns
->persistent_keyring_register
);
67 if (IS_ERR(persistent
))
68 return ERR_CAST(persistent
);
70 return make_key_ref(persistent
, true);
74 * Get the persistent keyring for a specific UID and link it to the nominated
77 static long key_get_persistent(struct user_namespace
*ns
, kuid_t uid
,
80 struct keyring_index_key index_key
;
81 struct key
*persistent
;
82 key_ref_t reg_ref
, persistent_ref
;
86 /* Look in the register if it exists */
87 index_key
.type
= &key_type_keyring
;
88 index_key
.description
= buf
;
89 index_key
.desc_len
= sprintf(buf
, "_persistent.%u", from_kuid(ns
, uid
));
91 if (ns
->persistent_keyring_register
) {
92 reg_ref
= make_key_ref(ns
->persistent_keyring_register
, true);
93 down_read(&ns
->persistent_keyring_register_sem
);
94 persistent_ref
= find_key_to_update(reg_ref
, &index_key
);
95 up_read(&ns
->persistent_keyring_register_sem
);
101 /* It wasn't in the register, so we'll need to create it. We might
102 * also need to create the register.
104 down_write(&ns
->persistent_keyring_register_sem
);
105 persistent_ref
= key_create_persistent(ns
, uid
, &index_key
);
106 up_write(&ns
->persistent_keyring_register_sem
);
107 if (!IS_ERR(persistent_ref
))
110 return PTR_ERR(persistent_ref
);
113 ret
= key_task_permission(persistent_ref
, current_cred(), KEY_NEED_LINK
);
115 persistent
= key_ref_to_ptr(persistent_ref
);
116 ret
= key_link(key_ref_to_ptr(dest_ref
), persistent
);
118 key_set_timeout(persistent
, persistent_keyring_expiry
);
119 ret
= persistent
->serial
;
123 key_ref_put(persistent_ref
);
128 * Get the persistent keyring for a specific UID and link it to the nominated
131 long keyctl_get_persistent(uid_t _uid
, key_serial_t destid
)
133 struct user_namespace
*ns
= current_user_ns();
138 /* -1 indicates the current user */
139 if (_uid
== (uid_t
)-1) {
142 uid
= make_kuid(ns
, _uid
);
146 /* You can only see your own persistent cache if you're not
147 * sufficiently privileged.
149 if (!uid_eq(uid
, current_uid()) &&
150 !uid_eq(uid
, current_euid()) &&
151 !ns_capable(ns
, CAP_SETUID
))
155 /* There must be a destination keyring */
156 dest_ref
= lookup_user_key(destid
, KEY_LOOKUP_CREATE
, KEY_NEED_WRITE
);
157 if (IS_ERR(dest_ref
))
158 return PTR_ERR(dest_ref
);
159 if (key_ref_to_ptr(dest_ref
)->type
!= &key_type_keyring
) {
164 ret
= key_get_persistent(ns
, uid
, dest_ref
);
167 key_ref_put(dest_ref
);