@@ -5249,6 +5249,22 @@ union bpf_attr {
* Pointer to the underlying dynptr data, NULL if the dynptr is
* read-only, if the dynptr is invalid, or if the offset and length
* is out of bounds.
+ *
+ * struct key *bpf_request_key_by_id(unsigned long id)
+ * Description
+ * Request a keyring by *id*.
+ *
+ * *id* can have the following values (some defined in
+ * verification.h): 0 for the primary keyring (immutable keyring of
+ * system keys); 1 for both the primary and secondary keyring
+ * (where keys can be added only if they are vouched for by
+ * existing keys in those keyrings); 2 for the platform keyring
+ * (primarily used by the integrity subsystem to verify a kexec'ed
+ * kerned image and, possibly, the initramfs signature); ULONG_MAX
+ * for the session keyring (for testing purposes).
+ * Return
+ * A non-NULL pointer if *id* is valid and not 0, a NULL pointer
+ * otherwise.
*/
#define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \
@@ -5455,6 +5471,7 @@ union bpf_attr {
FN(dynptr_read), \
FN(dynptr_write), \
FN(dynptr_data), \
+ FN(request_key_by_id), \
/* */
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
@@ -16,6 +16,7 @@
#include <linux/bpf_local_storage.h>
#include <linux/btf_ids.h>
#include <linux/ima.h>
+#include <linux/verification.h>
/* For every LSM hook that allows attachment of BPF programs, declare a nop
* function where a BPF program can be attached.
@@ -132,6 +133,31 @@ static const struct bpf_func_proto bpf_get_attach_cookie_proto = {
.arg1_type = ARG_PTR_TO_CTX,
};
+#ifdef CONFIG_KEYS
+BTF_ID_LIST_SINGLE(bpf_request_key_by_id_btf_ids, struct, key)
+
+BPF_CALL_1(bpf_request_key_by_id, unsigned long, id)
+{
+ const struct cred *cred = current_cred();
+
+ if (id > (unsigned long)VERIFY_USE_PLATFORM_KEYRING && id != ULONG_MAX)
+ return (unsigned long)NULL;
+
+ if (id == ULONG_MAX)
+ return (unsigned long)cred->session_keyring;
+
+ return id;
+}
+
+static const struct bpf_func_proto bpf_request_key_by_id_proto = {
+ .func = bpf_request_key_by_id,
+ .gpl_only = false,
+ .ret_type = RET_PTR_TO_BTF_ID_OR_NULL,
+ .ret_btf_id = &bpf_request_key_by_id_btf_ids[0],
+ .arg1_type = ARG_ANYTHING,
+};
+#endif /* CONFIG_KEYS */
+
static const struct bpf_func_proto *
bpf_lsm_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
{
@@ -158,6 +184,10 @@ bpf_lsm_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
return prog->aux->sleepable ? &bpf_ima_file_hash_proto : NULL;
case BPF_FUNC_get_attach_cookie:
return bpf_prog_has_trampoline(prog) ? &bpf_get_attach_cookie_proto : NULL;
+#ifdef CONFIG_KEYS
+ case BPF_FUNC_request_key_by_id:
+ return &bpf_request_key_by_id_proto;
+#endif /* CONFIG_KEYS */
default:
return tracing_prog_func_proto(func_id, prog);
}
@@ -635,6 +635,7 @@ class PrinterHelpers(Printer):
'struct bpf_timer',
'struct mptcp_sock',
'struct bpf_dynptr',
+ 'struct key',
]
known_types = {
'...',
@@ -686,6 +687,7 @@ class PrinterHelpers(Printer):
'struct bpf_timer',
'struct mptcp_sock',
'struct bpf_dynptr',
+ 'struct key',
}
mapped_types = {
'u8': '__u8',
@@ -5249,6 +5249,22 @@ union bpf_attr {
* Pointer to the underlying dynptr data, NULL if the dynptr is
* read-only, if the dynptr is invalid, or if the offset and length
* is out of bounds.
+ *
+ * struct key *bpf_request_key_by_id(unsigned long id)
+ * Description
+ * Request a keyring by *id*.
+ *
+ * *id* can have the following values (some defined in
+ * verification.h): 0 for the primary keyring (immutable keyring of
+ * system keys); 1 for both the primary and secondary keyring
+ * (where keys can be added only if they are vouched for by
+ * existing keys in those keyrings); 2 for the platform keyring
+ * (primarily used by the integrity subsystem to verify a kexec'ed
+ * kerned image and, possibly, the initramfs signature); ULONG_MAX
+ * for the session keyring (for testing purposes).
+ * Return
+ * A non-NULL pointer if *id* is valid and not 0, a NULL pointer
+ * otherwise.
*/
#define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \
@@ -5455,6 +5471,7 @@ union bpf_attr {
FN(dynptr_read), \
FN(dynptr_write), \
FN(dynptr_data), \
+ FN(request_key_by_id), \
/* */
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
Add the bpf_request_key_by_id() helper, so that an eBPF program can obtain a suitable key pointer to pass to the bpf_verify_pkcs7_signature() helper, to be introduced in a later patch. The passed identifier can have the following values: 0 for the primary keyring (immutable keyring of system keys); 1 for both the primary and secondary keyring (where keys can be added only if they are vouched for by existing keys in those keyrings); 2 for the platform keyring (primarily used by the integrity subsystem to verify a kexec'ed kerned image and, possibly, the initramfs signature); ULONG_MAX for the session keyring (for testing purposes). Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com> --- include/uapi/linux/bpf.h | 17 +++++++++++++++++ kernel/bpf/bpf_lsm.c | 30 ++++++++++++++++++++++++++++++ scripts/bpf_doc.py | 2 ++ tools/include/uapi/linux/bpf.h | 17 +++++++++++++++++ 4 files changed, 66 insertions(+)