Created
May 27, 2020 12:34
-
-
Save sinkap/1d213d17fb82a5e8ffdc3f320ec37d79 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h | |
index af74712af585..2499ff451857 100644 | |
--- a/include/linux/bpf_lsm.h | |
+++ b/include/linux/bpf_lsm.h | |
@@ -17,9 +17,23 @@ | |
#include <linux/lsm_hook_defs.h> | |
#undef LSM_HOOK | |
+struct bpf_lsm_storage { | |
+ struct bpf_local_storage __rcu *storage; | |
+}; | |
+ | |
+extern struct lsm_blob_sizes bpf_lsm_blob_sizes; | |
+ | |
int bpf_lsm_verify_prog(struct bpf_verifier_log *vlog, | |
const struct bpf_prog *prog); | |
+static inline struct bpf_lsm_storage *bpf_inode_storage(const struct inode *inode) | |
+{ | |
+ if (unlikely(!inode->i_security)) | |
+ return NULL; | |
+ | |
+ return inode->i_security + bpf_lsm_blob_sizes.lbs_inode; | |
+} | |
+ | |
#else /* !CONFIG_BPF_LSM */ | |
static inline int bpf_lsm_verify_prog(struct bpf_verifier_log *vlog, | |
diff --git a/kernel/bpf/bpf_local_storage.c b/kernel/bpf/bpf_local_storage.c | |
index 01dd8eb751da..3e12c1eaea58 100644 | |
--- a/kernel/bpf/bpf_local_storage.c | |
+++ b/kernel/bpf/bpf_local_storage.c | |
@@ -13,6 +13,7 @@ | |
#include <net/sock.h> | |
#include <uapi/linux/sock_diag.h> | |
#include <uapi/linux/btf.h> | |
+#include <linux/bpf_lsm.h> | |
static atomic_t cache_idx; | |
@@ -170,6 +171,7 @@ static struct bpf_local_storage_elem *sk_selem_alloc( | |
static void __unlink_local_storage(struct bpf_local_storage *local_storage, | |
bool uncharge_omem) | |
{ | |
+ struct bpf_lsm_storage *bls; | |
struct inode *inode; | |
struct sock *sk; | |
@@ -186,8 +188,11 @@ static void __unlink_local_storage(struct bpf_local_storage *local_storage, | |
break; | |
case BPF_LOCAL_STORAGE_INODE: | |
inode = local_storage->inode; | |
- /* After this RCU_INIT, sk may be freed and cannot be used */ | |
- RCU_INIT_POINTER(inode->inode_bpf_storage, NULL); | |
+ bls = bpf_inode_storage(inode); | |
+ if (!bls) | |
+ return; | |
+ | |
+ RCU_INIT_POINTER(bls->storage, NULL); | |
local_storage->inode = NULL; | |
break; | |
} | |
@@ -356,8 +361,13 @@ static struct bpf_local_storage_data *inode_storage_lookup( | |
{ | |
struct bpf_local_storage *inode_storage; | |
struct bpf_local_storage_map *smap; | |
+ struct bpf_lsm_storage *bls; | |
- inode_storage = rcu_dereference(inode->inode_bpf_storage); | |
+ bls = bpf_inode_storage(inode); | |
+ if (!bls) | |
+ return ERR_PTR(-ENOENT); | |
+ | |
+ inode_storage = rcu_dereference(bls->storage); | |
if (!inode_storage) | |
return NULL; | |
@@ -465,9 +475,14 @@ static int inode_storage_alloc(struct inode *inode, | |
struct bpf_local_storage_map *smap, | |
struct bpf_local_storage_elem *first_selem) | |
{ | |
+ struct bpf_lsm_storage *bls; | |
struct bpf_local_storage *curr; | |
int err; | |
+ bls = bpf_inode_storage(inode); | |
+ if (!bls) | |
+ return -EINVAL; | |
+ | |
curr = bpf_local_storage_alloc(smap); | |
if (!curr) | |
return -ENOMEM; | |
@@ -479,7 +494,7 @@ static int inode_storage_alloc(struct inode *inode, | |
selem_link_map(smap, first_selem); | |
err = publish_local_storage(first_selem, | |
- (struct bpf_local_storage **)&inode->inode_bpf_storage, curr); | |
+ (struct bpf_local_storage **)&bls->storage, curr); | |
if (err) { | |
kfree(curr); | |
return err; | |
@@ -524,6 +539,7 @@ static struct bpf_local_storage_data *local_storage_update( | |
struct bpf_local_storage *local_storage; | |
struct bpf_local_storage_map *smap; | |
enum bpf_local_storage_type stype; | |
+ struct bpf_lsm_storage * bls; | |
struct inode *inode; | |
struct sock *sk; | |
int err; | |
@@ -545,7 +561,8 @@ static struct bpf_local_storage_data *local_storage_update( | |
break; | |
case BPF_LOCAL_STORAGE_INODE: | |
inode = owner; | |
- local_storage = rcu_dereference(inode->inode_bpf_storage); | |
+ bls = bpf_inode_storage(inode); | |
+ local_storage = rcu_dereference(bls->storage); | |
break; | |
} | |
@@ -742,10 +759,15 @@ void bpf_inode_storage_free(struct inode *inode) | |
struct bpf_local_storage_elem *selem; | |
struct bpf_local_storage *local_storage; | |
bool free_inode_storage = false; | |
+ struct bpf_lsm_storage *bls; | |
struct hlist_node *n; | |
rcu_read_lock(); | |
- local_storage = rcu_dereference(inode->inode_bpf_storage); | |
+ bls = bpf_inode_storage(inode); | |
+ if (!bls) | |
+ return; | |
+ | |
+ local_storage = rcu_dereference(bls->storage); | |
if (!local_storage) { | |
rcu_read_unlock(); | |
return; | |
diff --git a/security/bpf/hooks.c b/security/bpf/hooks.c | |
index 32d32d485451..153f54c92e1c 100644 | |
--- a/security/bpf/hooks.c | |
+++ b/security/bpf/hooks.c | |
@@ -3,14 +3,18 @@ | |
/* | |
* Copyright (C) 2020 Google LLC. | |
*/ | |
+#include <linux/bpf_local_storage.h> | |
#include <linux/lsm_hooks.h> | |
#include <linux/bpf_lsm.h> | |
+ | |
+ | |
static struct security_hook_list bpf_lsm_hooks[] __lsm_ro_after_init = { | |
#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ | |
LSM_HOOK_INIT(NAME, bpf_lsm_##NAME), | |
#include <linux/lsm_hook_defs.h> | |
#undef LSM_HOOK | |
+ LSM_HOOK_INIT(inode_free_security, bpf_inode_storage_free), | |
}; | |
static int __init bpf_lsm_init(void) | |
@@ -20,7 +24,12 @@ static int __init bpf_lsm_init(void) | |
return 0; | |
} | |
+struct lsm_blob_sizes bpf_lsm_blob_sizes __lsm_ro_after_init = { | |
+ .lbs_inode = sizeof(struct bpf_lsm_storage), | |
+}; | |
+ | |
DEFINE_LSM(bpf) = { | |
.name = "bpf", | |
.init = bpf_lsm_init, | |
+ .blobs = &bpf_lsm_blob_sizes | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment