Skip to content

Commit 1dfcd83

Browse files
committed
Merge branch 'bpf-fixes'
Alexei Starovoitov says: ==================== bpf: fix several bugs First two patches address bugs found by Jann Horn. Last patch is a minor samples fix spotted during the testing. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents bd34cf6 + 569cc39 commit 1dfcd83

File tree

5 files changed

+73
-38
lines changed

5 files changed

+73
-38
lines changed

include/linux/bpf.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,13 @@ void bpf_register_prog_type(struct bpf_prog_type_list *tl);
171171
void bpf_register_map_type(struct bpf_map_type_list *tl);
172172

173173
struct bpf_prog *bpf_prog_get(u32 ufd);
174+
struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog);
174175
void bpf_prog_put(struct bpf_prog *prog);
175176
void bpf_prog_put_rcu(struct bpf_prog *prog);
176177

177178
struct bpf_map *bpf_map_get_with_uref(u32 ufd);
178179
struct bpf_map *__bpf_map_get(struct fd f);
179-
void bpf_map_inc(struct bpf_map *map, bool uref);
180+
struct bpf_map *bpf_map_inc(struct bpf_map *map, bool uref);
180181
void bpf_map_put_with_uref(struct bpf_map *map);
181182
void bpf_map_put(struct bpf_map *map);
182183
int bpf_map_precharge_memlock(u32 pages);

kernel/bpf/inode.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ static void *bpf_any_get(void *raw, enum bpf_type type)
3131
{
3232
switch (type) {
3333
case BPF_TYPE_PROG:
34-
atomic_inc(&((struct bpf_prog *)raw)->aux->refcnt);
34+
raw = bpf_prog_inc(raw);
3535
break;
3636
case BPF_TYPE_MAP:
37-
bpf_map_inc(raw, true);
37+
raw = bpf_map_inc(raw, true);
3838
break;
3939
default:
4040
WARN_ON_ONCE(1);
@@ -297,7 +297,8 @@ static void *bpf_obj_do_get(const struct filename *pathname,
297297
goto out;
298298

299299
raw = bpf_any_get(inode->i_private, *type);
300-
touch_atime(&path);
300+
if (!IS_ERR(raw))
301+
touch_atime(&path);
301302

302303
path_put(&path);
303304
return raw;

kernel/bpf/syscall.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -218,11 +218,18 @@ struct bpf_map *__bpf_map_get(struct fd f)
218218
return f.file->private_data;
219219
}
220220

221-
void bpf_map_inc(struct bpf_map *map, bool uref)
221+
/* prog's and map's refcnt limit */
222+
#define BPF_MAX_REFCNT 32768
223+
224+
struct bpf_map *bpf_map_inc(struct bpf_map *map, bool uref)
222225
{
223-
atomic_inc(&map->refcnt);
226+
if (atomic_inc_return(&map->refcnt) > BPF_MAX_REFCNT) {
227+
atomic_dec(&map->refcnt);
228+
return ERR_PTR(-EBUSY);
229+
}
224230
if (uref)
225231
atomic_inc(&map->usercnt);
232+
return map;
226233
}
227234

228235
struct bpf_map *bpf_map_get_with_uref(u32 ufd)
@@ -234,7 +241,7 @@ struct bpf_map *bpf_map_get_with_uref(u32 ufd)
234241
if (IS_ERR(map))
235242
return map;
236243

237-
bpf_map_inc(map, true);
244+
map = bpf_map_inc(map, true);
238245
fdput(f);
239246

240247
return map;
@@ -658,6 +665,15 @@ static struct bpf_prog *__bpf_prog_get(struct fd f)
658665
return f.file->private_data;
659666
}
660667

668+
struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog)
669+
{
670+
if (atomic_inc_return(&prog->aux->refcnt) > BPF_MAX_REFCNT) {
671+
atomic_dec(&prog->aux->refcnt);
672+
return ERR_PTR(-EBUSY);
673+
}
674+
return prog;
675+
}
676+
661677
/* called by sockets/tracing/seccomp before attaching program to an event
662678
* pairs with bpf_prog_put()
663679
*/
@@ -670,7 +686,7 @@ struct bpf_prog *bpf_prog_get(u32 ufd)
670686
if (IS_ERR(prog))
671687
return prog;
672688

673-
atomic_inc(&prog->aux->refcnt);
689+
prog = bpf_prog_inc(prog);
674690
fdput(f);
675691

676692
return prog;

kernel/bpf/verifier.c

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -239,16 +239,6 @@ static const char * const reg_type_str[] = {
239239
[CONST_IMM] = "imm",
240240
};
241241

242-
static const struct {
243-
int map_type;
244-
int func_id;
245-
} func_limit[] = {
246-
{BPF_MAP_TYPE_PROG_ARRAY, BPF_FUNC_tail_call},
247-
{BPF_MAP_TYPE_PERF_EVENT_ARRAY, BPF_FUNC_perf_event_read},
248-
{BPF_MAP_TYPE_PERF_EVENT_ARRAY, BPF_FUNC_perf_event_output},
249-
{BPF_MAP_TYPE_STACK_TRACE, BPF_FUNC_get_stackid},
250-
};
251-
252242
static void print_verifier_state(struct verifier_env *env)
253243
{
254244
enum bpf_reg_type t;
@@ -921,27 +911,52 @@ static int check_func_arg(struct verifier_env *env, u32 regno,
921911

922912
static int check_map_func_compatibility(struct bpf_map *map, int func_id)
923913
{
924-
bool bool_map, bool_func;
925-
int i;
926-
927914
if (!map)
928915
return 0;
929916

930-
for (i = 0; i < ARRAY_SIZE(func_limit); i++) {
931-
bool_map = (map->map_type == func_limit[i].map_type);
932-
bool_func = (func_id == func_limit[i].func_id);
933-
/* only when map & func pair match it can continue.
934-
* don't allow any other map type to be passed into
935-
* the special func;
936-
*/
937-
if (bool_func && bool_map != bool_func) {
938-
verbose("cannot pass map_type %d into func %d\n",
939-
map->map_type, func_id);
940-
return -EINVAL;
941-
}
917+
/* We need a two way check, first is from map perspective ... */
918+
switch (map->map_type) {
919+
case BPF_MAP_TYPE_PROG_ARRAY:
920+
if (func_id != BPF_FUNC_tail_call)
921+
goto error;
922+
break;
923+
case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
924+
if (func_id != BPF_FUNC_perf_event_read &&
925+
func_id != BPF_FUNC_perf_event_output)
926+
goto error;
927+
break;
928+
case BPF_MAP_TYPE_STACK_TRACE:
929+
if (func_id != BPF_FUNC_get_stackid)
930+
goto error;
931+
break;
932+
default:
933+
break;
934+
}
935+
936+
/* ... and second from the function itself. */
937+
switch (func_id) {
938+
case BPF_FUNC_tail_call:
939+
if (map->map_type != BPF_MAP_TYPE_PROG_ARRAY)
940+
goto error;
941+
break;
942+
case BPF_FUNC_perf_event_read:
943+
case BPF_FUNC_perf_event_output:
944+
if (map->map_type != BPF_MAP_TYPE_PERF_EVENT_ARRAY)
945+
goto error;
946+
break;
947+
case BPF_FUNC_get_stackid:
948+
if (map->map_type != BPF_MAP_TYPE_STACK_TRACE)
949+
goto error;
950+
break;
951+
default:
952+
break;
942953
}
943954

944955
return 0;
956+
error:
957+
verbose("cannot pass map_type %d into func %d\n",
958+
map->map_type, func_id);
959+
return -EINVAL;
945960
}
946961

947962
static int check_call(struct verifier_env *env, int func_id)
@@ -2049,15 +2064,18 @@ static int replace_map_fd_with_map_ptr(struct verifier_env *env)
20492064
return -E2BIG;
20502065
}
20512066

2052-
/* remember this map */
2053-
env->used_maps[env->used_map_cnt++] = map;
2054-
20552067
/* hold the map. If the program is rejected by verifier,
20562068
* the map will be released by release_maps() or it
20572069
* will be used by the valid program until it's unloaded
20582070
* and all maps are released in free_bpf_prog_info()
20592071
*/
2060-
bpf_map_inc(map, false);
2072+
map = bpf_map_inc(map, false);
2073+
if (IS_ERR(map)) {
2074+
fdput(f);
2075+
return PTR_ERR(map);
2076+
}
2077+
env->used_maps[env->used_map_cnt++] = map;
2078+
20612079
fdput(f);
20622080
next_insn:
20632081
insn++;

samples/bpf/trace_output_kern.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ int bpf_prog1(struct pt_regs *ctx)
1818
u64 cookie;
1919
} data;
2020

21-
memset(&data, 0, sizeof(data));
2221
data.pid = bpf_get_current_pid_tgid();
2322
data.cookie = 0x12345678;
2423

0 commit comments

Comments
 (0)