1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2019 Facebook
4 * Copyright 2020 Google LLC.
7 #include <linux/rculist.h>
8 #include <linux/list.h>
9 #include <linux/hash.h>
10 #include <linux/types.h>
11 #include <linux/spinlock.h>
12 #include <linux/bpf.h>
13 #include <linux/bpf_local_storage.h>
15 #include <uapi/linux/sock_diag.h>
16 #include <uapi/linux/btf.h>
17 #include <linux/bpf_lsm.h>
18 #include <linux/btf_ids.h>
19 #include <linux/fdtable.h>
21 DEFINE_BPF_STORAGE_CACHE(inode_cache
);
23 static struct bpf_local_storage __rcu
**
24 inode_storage_ptr(void *owner
)
26 struct inode
*inode
= owner
;
27 struct bpf_storage_blob
*bsb
;
29 bsb
= bpf_inode(inode
);
35 static struct bpf_local_storage_data
*inode_storage_lookup(struct inode
*inode
,
39 struct bpf_local_storage
*inode_storage
;
40 struct bpf_local_storage_map
*smap
;
41 struct bpf_storage_blob
*bsb
;
43 bsb
= bpf_inode(inode
);
47 inode_storage
= rcu_dereference(bsb
->storage
);
51 smap
= (struct bpf_local_storage_map
*)map
;
52 return bpf_local_storage_lookup(inode_storage
, smap
, cacheit_lockit
);
55 void bpf_inode_storage_free(struct inode
*inode
)
57 struct bpf_local_storage_elem
*selem
;
58 struct bpf_local_storage
*local_storage
;
59 bool free_inode_storage
= false;
60 struct bpf_storage_blob
*bsb
;
63 bsb
= bpf_inode(inode
);
69 local_storage
= rcu_dereference(bsb
->storage
);
75 /* Netiher the bpf_prog nor the bpf-map's syscall
76 * could be modifying the local_storage->list now.
77 * Thus, no elem can be added-to or deleted-from the
78 * local_storage->list by the bpf_prog or by the bpf-map's syscall.
80 * It is racing with bpf_local_storage_map_free() alone
81 * when unlinking elem from the local_storage->list and
82 * the map's bucket->list.
84 raw_spin_lock_bh(&local_storage
->lock
);
85 hlist_for_each_entry_safe(selem
, n
, &local_storage
->list
, snode
) {
86 /* Always unlink from map before unlinking from
89 bpf_selem_unlink_map(selem
);
90 free_inode_storage
= bpf_selem_unlink_storage_nolock(
91 local_storage
, selem
, false);
93 raw_spin_unlock_bh(&local_storage
->lock
);
96 /* free_inoode_storage should always be true as long as
97 * local_storage->list was non-empty.
99 if (free_inode_storage
)
100 kfree_rcu(local_storage
, rcu
);
103 static void *bpf_fd_inode_storage_lookup_elem(struct bpf_map
*map
, void *key
)
105 struct bpf_local_storage_data
*sdata
;
114 sdata
= inode_storage_lookup(f
->f_inode
, map
, true);
116 return sdata
? sdata
->data
: NULL
;
119 static int bpf_fd_inode_storage_update_elem(struct bpf_map
*map
, void *key
,
120 void *value
, u64 map_flags
)
122 struct bpf_local_storage_data
*sdata
;
128 if (!f
|| !inode_storage_ptr(f
->f_inode
))
131 sdata
= bpf_local_storage_update(f
->f_inode
,
132 (struct bpf_local_storage_map
*)map
,
135 return PTR_ERR_OR_ZERO(sdata
);
138 static int inode_storage_delete(struct inode
*inode
, struct bpf_map
*map
)
140 struct bpf_local_storage_data
*sdata
;
142 sdata
= inode_storage_lookup(inode
, map
, false);
146 bpf_selem_unlink(SELEM(sdata
));
151 static int bpf_fd_inode_storage_delete_elem(struct bpf_map
*map
, void *key
)
161 err
= inode_storage_delete(f
->f_inode
, map
);
166 BPF_CALL_4(bpf_inode_storage_get
, struct bpf_map
*, map
, struct inode
*, inode
,
167 void *, value
, u64
, flags
)
169 struct bpf_local_storage_data
*sdata
;
171 if (flags
& ~(BPF_LOCAL_STORAGE_GET_F_CREATE
))
172 return (unsigned long)NULL
;
174 /* explicitly check that the inode_storage_ptr is not
175 * NULL as inode_storage_lookup returns NULL in this case and
176 * bpf_local_storage_update expects the owner to have a
177 * valid storage pointer.
179 if (!inode_storage_ptr(inode
))
180 return (unsigned long)NULL
;
182 sdata
= inode_storage_lookup(inode
, map
, true);
184 return (unsigned long)sdata
->data
;
186 /* This helper must only called from where the inode is gurranteed
187 * to have a refcount and cannot be freed.
189 if (flags
& BPF_LOCAL_STORAGE_GET_F_CREATE
) {
190 sdata
= bpf_local_storage_update(
191 inode
, (struct bpf_local_storage_map
*)map
, value
,
193 return IS_ERR(sdata
) ? (unsigned long)NULL
:
194 (unsigned long)sdata
->data
;
197 return (unsigned long)NULL
;
200 BPF_CALL_2(bpf_inode_storage_delete
,
201 struct bpf_map
*, map
, struct inode
*, inode
)
203 /* This helper must only called from where the inode is gurranteed
204 * to have a refcount and cannot be freed.
206 return inode_storage_delete(inode
, map
);
209 static int notsupp_get_next_key(struct bpf_map
*map
, void *key
,
215 static struct bpf_map
*inode_storage_map_alloc(union bpf_attr
*attr
)
217 struct bpf_local_storage_map
*smap
;
219 smap
= bpf_local_storage_map_alloc(attr
);
221 return ERR_CAST(smap
);
223 smap
->cache_idx
= bpf_local_storage_cache_idx_get(&inode_cache
);
227 static void inode_storage_map_free(struct bpf_map
*map
)
229 struct bpf_local_storage_map
*smap
;
231 smap
= (struct bpf_local_storage_map
*)map
;
232 bpf_local_storage_cache_idx_free(&inode_cache
, smap
->cache_idx
);
233 bpf_local_storage_map_free(smap
);
236 static int inode_storage_map_btf_id
;
237 const struct bpf_map_ops inode_storage_map_ops
= {
238 .map_meta_equal
= bpf_map_meta_equal
,
239 .map_alloc_check
= bpf_local_storage_map_alloc_check
,
240 .map_alloc
= inode_storage_map_alloc
,
241 .map_free
= inode_storage_map_free
,
242 .map_get_next_key
= notsupp_get_next_key
,
243 .map_lookup_elem
= bpf_fd_inode_storage_lookup_elem
,
244 .map_update_elem
= bpf_fd_inode_storage_update_elem
,
245 .map_delete_elem
= bpf_fd_inode_storage_delete_elem
,
246 .map_check_btf
= bpf_local_storage_map_check_btf
,
247 .map_btf_name
= "bpf_local_storage_map",
248 .map_btf_id
= &inode_storage_map_btf_id
,
249 .map_owner_storage_ptr
= inode_storage_ptr
,
252 BTF_ID_LIST_SINGLE(bpf_inode_storage_btf_ids
, struct, inode
)
254 const struct bpf_func_proto bpf_inode_storage_get_proto
= {
255 .func
= bpf_inode_storage_get
,
257 .ret_type
= RET_PTR_TO_MAP_VALUE_OR_NULL
,
258 .arg1_type
= ARG_CONST_MAP_PTR
,
259 .arg2_type
= ARG_PTR_TO_BTF_ID
,
260 .arg2_btf_id
= &bpf_inode_storage_btf_ids
[0],
261 .arg3_type
= ARG_PTR_TO_MAP_VALUE_OR_NULL
,
262 .arg4_type
= ARG_ANYTHING
,
265 const struct bpf_func_proto bpf_inode_storage_delete_proto
= {
266 .func
= bpf_inode_storage_delete
,
268 .ret_type
= RET_INTEGER
,
269 .arg1_type
= ARG_CONST_MAP_PTR
,
270 .arg2_type
= ARG_PTR_TO_BTF_ID
,
271 .arg2_btf_id
= &bpf_inode_storage_btf_ids
[0],