Skip to content

Commit 6e71b04

Browse files
Chenbo Fengdavem330
Chenbo Feng
authored andcommitted
bpf: Add file mode configuration into bpf maps
Introduce the map read/write flags to the eBPF syscalls that returns the map fd. The flags is used to set up the file mode when construct a new file descriptor for bpf maps. To not break the backward capability, the f_flags is set to O_RDWR if the flag passed by syscall is 0. Otherwise it should be O_RDONLY or O_WRONLY. When the userspace want to modify or read the map content, it will check the file mode to see if it is allowed to make the change. Signed-off-by: Chenbo Feng <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> Acked-by: Daniel Borkmann <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent aec72f3 commit 6e71b04

File tree

11 files changed

+122
-26
lines changed

11 files changed

+122
-26
lines changed

Diff for: include/linux/bpf.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -315,11 +315,11 @@ void bpf_map_area_free(void *base);
315315

316316
extern int sysctl_unprivileged_bpf_disabled;
317317

318-
int bpf_map_new_fd(struct bpf_map *map);
318+
int bpf_map_new_fd(struct bpf_map *map, int flags);
319319
int bpf_prog_new_fd(struct bpf_prog *prog);
320320

321321
int bpf_obj_pin_user(u32 ufd, const char __user *pathname);
322-
int bpf_obj_get_user(const char __user *pathname);
322+
int bpf_obj_get_user(const char __user *pathname, int flags);
323323

324324
int bpf_percpu_hash_copy(struct bpf_map *map, void *key, void *value);
325325
int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value);
@@ -338,6 +338,8 @@ int bpf_fd_htab_map_update_elem(struct bpf_map *map, struct file *map_file,
338338
void *key, void *value, u64 map_flags);
339339
int bpf_fd_htab_map_lookup_elem(struct bpf_map *map, void *key, u32 *value);
340340

341+
int bpf_get_file_flag(int flags);
342+
341343
/* memcpy that is used with 8-byte aligned pointers, power-of-8 size and
342344
* forced to use 'long' read/writes to try to atomically copy long counters.
343345
* Best-effort only. No barriers here, since it _will_ race with concurrent
@@ -421,7 +423,7 @@ static inline void __bpf_prog_uncharge(struct user_struct *user, u32 pages)
421423
{
422424
}
423425

424-
static inline int bpf_obj_get_user(const char __user *pathname)
426+
static inline int bpf_obj_get_user(const char __user *pathname, int flags)
425427
{
426428
return -EOPNOTSUPP;
427429
}

Diff for: include/uapi/linux/bpf.h

+6
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,10 @@ enum bpf_attach_type {
218218

219219
#define BPF_OBJ_NAME_LEN 16U
220220

221+
/* Flags for accessing BPF object */
222+
#define BPF_F_RDONLY (1U << 3)
223+
#define BPF_F_WRONLY (1U << 4)
224+
221225
union bpf_attr {
222226
struct { /* anonymous struct used by BPF_MAP_CREATE command */
223227
__u32 map_type; /* one of enum bpf_map_type */
@@ -260,6 +264,7 @@ union bpf_attr {
260264
struct { /* anonymous struct used by BPF_OBJ_* commands */
261265
__aligned_u64 pathname;
262266
__u32 bpf_fd;
267+
__u32 file_flags;
263268
};
264269

265270
struct { /* anonymous struct used by BPF_PROG_ATTACH/DETACH commands */
@@ -287,6 +292,7 @@ union bpf_attr {
287292
__u32 map_id;
288293
};
289294
__u32 next_id;
295+
__u32 open_flags;
290296
};
291297

292298
struct { /* anonymous struct used by BPF_OBJ_GET_INFO_BY_FD */

Diff for: kernel/bpf/arraymap.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919

2020
#include "map_in_map.h"
2121

22+
#define ARRAY_CREATE_FLAG_MASK \
23+
(BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY)
24+
2225
static void bpf_array_free_percpu(struct bpf_array *array)
2326
{
2427
int i;
@@ -56,7 +59,8 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
5659

5760
/* check sanity of attributes */
5861
if (attr->max_entries == 0 || attr->key_size != 4 ||
59-
attr->value_size == 0 || attr->map_flags & ~BPF_F_NUMA_NODE ||
62+
attr->value_size == 0 ||
63+
attr->map_flags & ~ARRAY_CREATE_FLAG_MASK ||
6064
(percpu && numa_node != NUMA_NO_NODE))
6165
return ERR_PTR(-EINVAL);
6266

Diff for: kernel/bpf/devmap.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@
5050
#include <linux/bpf.h>
5151
#include <linux/filter.h>
5252

53+
#define DEV_CREATE_FLAG_MASK \
54+
(BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY)
55+
5356
struct bpf_dtab_netdev {
5457
struct net_device *dev;
5558
struct bpf_dtab *dtab;
@@ -80,7 +83,7 @@ static struct bpf_map *dev_map_alloc(union bpf_attr *attr)
8083

8184
/* check sanity of attributes */
8285
if (attr->max_entries == 0 || attr->key_size != 4 ||
83-
attr->value_size != 4 || attr->map_flags & ~BPF_F_NUMA_NODE)
86+
attr->value_size != 4 || attr->map_flags & ~DEV_CREATE_FLAG_MASK)
8487
return ERR_PTR(-EINVAL);
8588

8689
dtab = kzalloc(sizeof(*dtab), GFP_USER);

Diff for: kernel/bpf/hashtab.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@
1818
#include "bpf_lru_list.h"
1919
#include "map_in_map.h"
2020

21-
#define HTAB_CREATE_FLAG_MASK \
22-
(BPF_F_NO_PREALLOC | BPF_F_NO_COMMON_LRU | BPF_F_NUMA_NODE)
21+
#define HTAB_CREATE_FLAG_MASK \
22+
(BPF_F_NO_PREALLOC | BPF_F_NO_COMMON_LRU | BPF_F_NUMA_NODE | \
23+
BPF_F_RDONLY | BPF_F_WRONLY)
2324

2425
struct bucket {
2526
struct hlist_nulls_head head;

Diff for: kernel/bpf/inode.c

+10-5
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ int bpf_obj_pin_user(u32 ufd, const char __user *pathname)
295295
}
296296

297297
static void *bpf_obj_do_get(const struct filename *pathname,
298-
enum bpf_type *type)
298+
enum bpf_type *type, int flags)
299299
{
300300
struct inode *inode;
301301
struct path path;
@@ -307,7 +307,7 @@ static void *bpf_obj_do_get(const struct filename *pathname,
307307
return ERR_PTR(ret);
308308

309309
inode = d_backing_inode(path.dentry);
310-
ret = inode_permission(inode, MAY_WRITE);
310+
ret = inode_permission(inode, ACC_MODE(flags));
311311
if (ret)
312312
goto out;
313313

@@ -326,18 +326,23 @@ static void *bpf_obj_do_get(const struct filename *pathname,
326326
return ERR_PTR(ret);
327327
}
328328

329-
int bpf_obj_get_user(const char __user *pathname)
329+
int bpf_obj_get_user(const char __user *pathname, int flags)
330330
{
331331
enum bpf_type type = BPF_TYPE_UNSPEC;
332332
struct filename *pname;
333333
int ret = -ENOENT;
334+
int f_flags;
334335
void *raw;
335336

337+
f_flags = bpf_get_file_flag(flags);
338+
if (f_flags < 0)
339+
return f_flags;
340+
336341
pname = getname(pathname);
337342
if (IS_ERR(pname))
338343
return PTR_ERR(pname);
339344

340-
raw = bpf_obj_do_get(pname, &type);
345+
raw = bpf_obj_do_get(pname, &type, f_flags);
341346
if (IS_ERR(raw)) {
342347
ret = PTR_ERR(raw);
343348
goto out;
@@ -346,7 +351,7 @@ int bpf_obj_get_user(const char __user *pathname)
346351
if (type == BPF_TYPE_PROG)
347352
ret = bpf_prog_new_fd(raw);
348353
else if (type == BPF_TYPE_MAP)
349-
ret = bpf_map_new_fd(raw);
354+
ret = bpf_map_new_fd(raw, f_flags);
350355
else
351356
goto out;
352357

Diff for: kernel/bpf/lpm_trie.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,8 @@ static int trie_delete_elem(struct bpf_map *map, void *_key)
495495
#define LPM_KEY_SIZE_MAX LPM_KEY_SIZE(LPM_DATA_SIZE_MAX)
496496
#define LPM_KEY_SIZE_MIN LPM_KEY_SIZE(LPM_DATA_SIZE_MIN)
497497

498-
#define LPM_CREATE_FLAG_MASK (BPF_F_NO_PREALLOC | BPF_F_NUMA_NODE)
498+
#define LPM_CREATE_FLAG_MASK (BPF_F_NO_PREALLOC | BPF_F_NUMA_NODE | \
499+
BPF_F_RDONLY | BPF_F_WRONLY)
499500

500501
static struct bpf_map *trie_alloc(union bpf_attr *attr)
501502
{

Diff for: kernel/bpf/sockmap.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
#include <linux/list.h>
4141
#include <net/strparser.h>
4242

43+
#define SOCK_CREATE_FLAG_MASK \
44+
(BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY)
45+
4346
struct bpf_stab {
4447
struct bpf_map map;
4548
struct sock **sock_map;
@@ -489,7 +492,7 @@ static struct bpf_map *sock_map_alloc(union bpf_attr *attr)
489492

490493
/* check sanity of attributes */
491494
if (attr->max_entries == 0 || attr->key_size != 4 ||
492-
attr->value_size != 4 || attr->map_flags & ~BPF_F_NUMA_NODE)
495+
attr->value_size != 4 || attr->map_flags & ~SOCK_CREATE_FLAG_MASK)
493496
return ERR_PTR(-EINVAL);
494497

495498
if (attr->value_size > KMALLOC_MAX_SIZE)

Diff for: kernel/bpf/stackmap.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
#include <linux/perf_event.h>
1212
#include "percpu_freelist.h"
1313

14+
#define STACK_CREATE_FLAG_MASK \
15+
(BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY)
16+
1417
struct stack_map_bucket {
1518
struct pcpu_freelist_node fnode;
1619
u32 hash;
@@ -60,7 +63,7 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr)
6063
if (!capable(CAP_SYS_ADMIN))
6164
return ERR_PTR(-EPERM);
6265

63-
if (attr->map_flags & ~BPF_F_NUMA_NODE)
66+
if (attr->map_flags & ~STACK_CREATE_FLAG_MASK)
6467
return ERR_PTR(-EINVAL);
6568

6669
/* check sanity of attributes */

0 commit comments

Comments
 (0)