History

bpf: reject program if a __user tagged memory accessed in kernel way

BPF verifier supports direct memory access for BPF_PROG_TYPE_TRACING type of bpf programs, e.g., a->b. If "a" is a pointer pointing to kernel memory, bpf verifier will allow user to write code in C like a->b and the verifier will translate it to a kernel load properly. If "a" is a pointer to user memory, it is expected that bpf developer should be bpf_probe_read_user() helper to get the value a->b. Without utilizing BTF __user tagging information, current verifier will assume that a->b is a kernel memory access and this may generate incorrect result. Now BTF contains __user information, it can check whether the pointer points to a user memory or not. If it is, the verifier can reject the program and force users to use bpf_probe_read_user() helper explicitly. In the future, we can easily extend btf_add_space for other address space tagging, for example, rcu/percpu etc.

Yonghong Song committed 4 years ago

Commit c6f1bfe1 parent 7472d5a6 files · +71 −24Browse files

Unified · Split

6 files
  1. include/linux/bpf.h +6 −3
  2. include/linux/btf.h +5 −0
  3. kernel/bpf/btf.c +28 −6
  4. kernel/bpf/verifier.c +24 −11
  5. net/bpf/bpf_dummy_struct_ops.c +4 −2
  6. net/ipv4/bpf_tcp_ca.c +4 −2
include/linux/bpf.h+6−3
@@ -332,7 +332,10 @@ enum bpf_type_flag { · 331 unmodified lines
332 */332 */
333 MEM_ALLOC = BIT(2 + BPF_BASE_TYPE_BITS),333 MEM_ALLOC = BIT(2 + BPF_BASE_TYPE_BITS),
334 334
335 __BPF_TYPE_LAST_FLAG = MEM_ALLOC,335 /* MEM is in user address space. */
336 MEM_USER = BIT(3 + BPF_BASE_TYPE_BITS),
337
338 __BPF_TYPE_LAST_FLAG = MEM_USER,
336};339};
337 340
338/* Max number of base types. */341/* Max number of base types. */
@@ -588,7 +591,7 @@ struct bpf_verifier_ops { · 249 unmodified lines
588 const struct btf *btf,591 const struct btf *btf,
589 const struct btf_type *t, int off, int size,592 const struct btf_type *t, int off, int size,
590 enum bpf_access_type atype,593 enum bpf_access_type atype,
591 u32 *next_btf_id);594 u32 *next_btf_id, enum bpf_type_flag *flag);
592};595};
593 596
594struct bpf_prog_offload_ops {597struct bpf_prog_offload_ops {
@@ -1780,7 +1783,7 @@ static inline bool bpf_tracing_btf_ctx_access(int off, int size, · 1185 unmodified lines
1780int btf_struct_access(struct bpf_verifier_log *log, const struct btf *btf,1783int btf_struct_access(struct bpf_verifier_log *log, const struct btf *btf,
1781 const struct btf_type *t, int off, int size,1784 const struct btf_type *t, int off, int size,
1782 enum bpf_access_type atype,1785 enum bpf_access_type atype,
1783 u32 *next_btf_id);1786 u32 *next_btf_id, enum bpf_type_flag *flag);
1784bool btf_struct_ids_match(struct bpf_verifier_log *log,1787bool btf_struct_ids_match(struct bpf_verifier_log *log,
1785 const struct btf *btf, u32 id, int off,1788 const struct btf *btf, u32 id, int off,
1786 const struct btf *need_btf, u32 need_type_id);1789 const struct btf *need_btf, u32 need_type_id);
include/linux/btf.h+5−0
@@ -238,6 +238,11 @@ static inline bool btf_type_is_var(const struct btf_type *t) · 237 unmodified lines
238 return BTF_INFO_KIND(t->info) == BTF_KIND_VAR;238 return BTF_INFO_KIND(t->info) == BTF_KIND_VAR;
239}239}
240 240
241static inline bool btf_type_is_type_tag(const struct btf_type *t)
242{
243 return BTF_INFO_KIND(t->info) == BTF_KIND_TYPE_TAG;
244}
245
241/* union is only a special case of struct:246/* union is only a special case of struct:
242 * all its offsetof(member) == 0247 * all its offsetof(member) == 0
243 */248 */
kernel/bpf/btf.c+28−6
@@ -4886,6 +4886,7 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type, · 4885 unmodified lines
4886 const char *tname = prog->aux->attach_func_name;4886 const char *tname = prog->aux->attach_func_name;
4887 struct bpf_verifier_log *log = info->log;4887 struct bpf_verifier_log *log = info->log;
4888 const struct btf_param *args;4888 const struct btf_param *args;
4889 const char *tag_value;
4889 u32 nr_args, arg;4890 u32 nr_args, arg;
4890 int i, ret;4891 int i, ret;
4891 4892
@@ -5038,6 +5039,13 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type, · 146 unmodified lines
5038 info->btf = btf;5039 info->btf = btf;
5039 info->btf_id = t->type;5040 info->btf_id = t->type;
5040 t = btf_type_by_id(btf, t->type);5041 t = btf_type_by_id(btf, t->type);
5042
5043 if (btf_type_is_type_tag(t)) {
5044 tag_value = __btf_name_by_offset(btf, t->name_off);
5045 if (strcmp(tag_value, "user") == 0)
5046 info->reg_type |= MEM_USER;
5047 }
5048
5041 /* skip modifiers */5049 /* skip modifiers */
5042 while (btf_type_is_modifier(t)) {5050 while (btf_type_is_modifier(t)) {
5043 info->btf_id = t->type;5051 info->btf_id = t->type;
@@ -5064,12 +5072,12 @@ enum bpf_struct_walk_result { · 20 unmodified lines
5064 5072
5065static int btf_struct_walk(struct bpf_verifier_log *log, const struct btf *btf,5073static int btf_struct_walk(struct bpf_verifier_log *log, const struct btf *btf,
5066 const struct btf_type *t, int off, int size,5074 const struct btf_type *t, int off, int size,
5067 u32 *next_btf_id)5075 u32 *next_btf_id, enum bpf_type_flag *flag)
5068{5076{
5069 u32 i, moff, mtrue_end, msize = 0, total_nelems = 0;5077 u32 i, moff, mtrue_end, msize = 0, total_nelems = 0;
5070 const struct btf_type *mtype, *elem_type = NULL;5078 const struct btf_type *mtype, *elem_type = NULL;
5071 const struct btf_member *member;5079 const struct btf_member *member;
5072 const char *tname, *mname;5080 const char *tname, *mname, *tag_value;
5073 u32 vlen, elem_id, mid;5081 u32 vlen, elem_id, mid;
5074 5082
5075again:5083again:
@@ -5253,7 +5261,8 @@ error: · 177 unmodified lines
5253 }5261 }
5254 5262
5255 if (btf_type_is_ptr(mtype)) {5263 if (btf_type_is_ptr(mtype)) {
5256 const struct btf_type *stype;5264 const struct btf_type *stype, *t;
5265 enum bpf_type_flag tmp_flag = 0;
5257 u32 id;5266 u32 id;
5258 5267
5259 if (msize != size || off != moff) {5268 if (msize != size || off != moff) {
@@ -5262,9 +5271,19 @@ error: · 2 unmodified lines
5262 mname, moff, tname, off, size);5271 mname, moff, tname, off, size);
5263 return -EACCES;5272 return -EACCES;
5264 }5273 }
5274
5275 /* check __user tag */
5276 t = btf_type_by_id(btf, mtype->type);
5277 if (btf_type_is_type_tag(t)) {
5278 tag_value = __btf_name_by_offset(btf, t->name_off);
5279 if (strcmp(tag_value, "user") == 0)
5280 tmp_flag = MEM_USER;
5281 }
5282
5265 stype = btf_type_skip_modifiers(btf, mtype->type, &id);5283 stype = btf_type_skip_modifiers(btf, mtype->type, &id);
5266 if (btf_type_is_struct(stype)) {5284 if (btf_type_is_struct(stype)) {
5267 *next_btf_id = id;5285 *next_btf_id = id;
5286 *flag = tmp_flag;
5268 return WALK_PTR;5287 return WALK_PTR;
5269 }5288 }
5270 }5289 }
@@ -5291,13 +5310,14 @@ error: · 20 unmodified lines
5291int btf_struct_access(struct bpf_verifier_log *log, const struct btf *btf,5310int btf_struct_access(struct bpf_verifier_log *log, const struct btf *btf,
5292 const struct btf_type *t, int off, int size,5311 const struct btf_type *t, int off, int size,
5293 enum bpf_access_type atype __maybe_unused,5312 enum bpf_access_type atype __maybe_unused,
5294 u32 *next_btf_id)5313 u32 *next_btf_id, enum bpf_type_flag *flag)
5295{5314{
5315 enum bpf_type_flag tmp_flag = 0;
5296 int err;5316 int err;
5297 u32 id;5317 u32 id;
5298 5318
5299 do {5319 do {
5300 err = btf_struct_walk(log, btf, t, off, size, &id);5320 err = btf_struct_walk(log, btf, t, off, size, &id, &tmp_flag);
5301 5321
5302 switch (err) {5322 switch (err) {
5303 case WALK_PTR:5323 case WALK_PTR:
@@ -5305,6 +5325,7 @@ int btf_struct_access(struct bpf_verifier_log *log, const struct btf *btf, · 1 unmodified line
5305 * we're done.5325 * we're done.
5306 */5326 */
5307 *next_btf_id = id;5327 *next_btf_id = id;
5328 *flag = tmp_flag;
5308 return PTR_TO_BTF_ID;5329 return PTR_TO_BTF_ID;
5309 case WALK_SCALAR:5330 case WALK_SCALAR:
5310 return SCALAR_VALUE;5331 return SCALAR_VALUE;
@@ -5349,6 +5370,7 @@ bool btf_struct_ids_match(struct bpf_verifier_log *log, · 38 unmodified lines
5349 const struct btf *need_btf, u32 need_type_id)5370 const struct btf *need_btf, u32 need_type_id)
5350{5371{
5351 const struct btf_type *type;5372 const struct btf_type *type;
5373 enum bpf_type_flag flag;
5352 int err;5374 int err;
5353 5375
5354 /* Are we already done? */5376 /* Are we already done? */
@@ -5359,7 +5381,7 @@ again: · 4 unmodified lines
5359 type = btf_type_by_id(btf, id);5381 type = btf_type_by_id(btf, id);
5360 if (!type)5382 if (!type)
5361 return false;5383 return false;
5362 err = btf_struct_walk(log, btf, type, off, 1, &id);5384 err = btf_struct_walk(log, btf, type, off, 1, &id, &flag);
5363 if (err != WALK_STRUCT)5385 if (err != WALK_STRUCT)
5364 return false;5386 return false;
5365 5387
kernel/bpf/verifier.c+24−11
@@ -536,7 +536,7 @@ static bool is_cmpxchg_insn(const struct bpf_insn *insn) · 535 unmodified lines
536static const char *reg_type_str(struct bpf_verifier_env *env,536static const char *reg_type_str(struct bpf_verifier_env *env,
537 enum bpf_reg_type type)537 enum bpf_reg_type type)
538{538{
539 char postfix[16] = {0}, prefix[16] = {0};539 char postfix[16] = {0}, prefix[32] = {0};
540 static const char * const str[] = {540 static const char * const str[] = {
541 [NOT_INIT] = "?",541 [NOT_INIT] = "?",
542 [SCALAR_VALUE] = "inv",542 [SCALAR_VALUE] = "inv",
@@ -570,9 +570,11 @@ static const char *reg_type_str(struct bpf_verifier_env *env, · 27 unmodified lines
570 }570 }
571 571
572 if (type & MEM_RDONLY)572 if (type & MEM_RDONLY)
573 strncpy(prefix, "rdonly_", 16);573 strncpy(prefix, "rdonly_", 32);
574 if (type & MEM_ALLOC)574 if (type & MEM_ALLOC)
575 strncpy(prefix, "alloc_", 16);575 strncpy(prefix, "alloc_", 32);
576 if (type & MEM_USER)
577 strncpy(prefix, "user_", 32);
576 578
577 snprintf(env->type_str_buf, TYPE_STR_BUF_LEN, "%s%s%s",579 snprintf(env->type_str_buf, TYPE_STR_BUF_LEN, "%s%s%s",
578 prefix, str[base_type(type)], postfix);580 prefix, str[base_type(type)], postfix);
@@ -1547,14 +1549,15 @@ static void mark_reg_not_init(struct bpf_verifier_env *env, · 968 unmodified lines
1547static void mark_btf_ld_reg(struct bpf_verifier_env *env,1549static void mark_btf_ld_reg(struct bpf_verifier_env *env,
1548 struct bpf_reg_state *regs, u32 regno,1550 struct bpf_reg_state *regs, u32 regno,
1549 enum bpf_reg_type reg_type,1551 enum bpf_reg_type reg_type,
1550 struct btf *btf, u32 btf_id)1552 struct btf *btf, u32 btf_id,
1553 enum bpf_type_flag flag)
1551{1554{
1552 if (reg_type == SCALAR_VALUE) {1555 if (reg_type == SCALAR_VALUE) {
1553 mark_reg_unknown(env, regs, regno);1556 mark_reg_unknown(env, regs, regno);
1554 return;1557 return;
1555 }1558 }
1556 mark_reg_known_zero(env, regs, regno);1559 mark_reg_known_zero(env, regs, regno);
1557 regs[regno].type = PTR_TO_BTF_ID;1560 regs[regno].type = PTR_TO_BTF_ID | flag;
1558 regs[regno].btf = btf;1561 regs[regno].btf = btf;
1559 regs[regno].btf_id = btf_id;1562 regs[regno].btf_id = btf_id;
1560}1563}
@@ -4152,6 +4155,7 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, · 2591 unmodified lines
4152 struct bpf_reg_state *reg = regs + regno;4155 struct bpf_reg_state *reg = regs + regno;
4153 const struct btf_type *t = btf_type_by_id(reg->btf, reg->btf_id);4156 const struct btf_type *t = btf_type_by_id(reg->btf, reg->btf_id);
4154 const char *tname = btf_name_by_offset(reg->btf, t->name_off);4157 const char *tname = btf_name_by_offset(reg->btf, t->name_off);
4158 enum bpf_type_flag flag = 0;
4155 u32 btf_id;4159 u32 btf_id;
4156 int ret;4160 int ret;
4157 4161
@@ -4171,9 +4175,16 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, · 13 unmodified lines
4171 return -EACCES;4175 return -EACCES;
4172 }4176 }
4173 4177
4178 if (reg->type & MEM_USER) {
4179 verbose(env,
4180 "R%d is ptr_%s access user memory: off=%d\n",
4181 regno, tname, off);
4182 return -EACCES;
4183 }
4184
4174 if (env->ops->btf_struct_access) {4185 if (env->ops->btf_struct_access) {
4175 ret = env->ops->btf_struct_access(&env->log, reg->btf, t,4186 ret = env->ops->btf_struct_access(&env->log, reg->btf, t,
4176 off, size, atype, &btf_id);4187 off, size, atype, &btf_id, &flag);
4177 } else {4188 } else {
4178 if (atype != BPF_READ) {4189 if (atype != BPF_READ) {
4179 verbose(env, "only read is supported\n");4190 verbose(env, "only read is supported\n");
@@ -4181,14 +4192,14 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, · 1 unmodified line
4181 }4192 }
4182 4193
4183 ret = btf_struct_access(&env->log, reg->btf, t, off, size,4194 ret = btf_struct_access(&env->log, reg->btf, t, off, size,
4184 atype, &btf_id);4195 atype, &btf_id, &flag);
4185 }4196 }
4186 4197
4187 if (ret < 0)4198 if (ret < 0)
4188 return ret;4199 return ret;
4189 4200
4190 if (atype == BPF_READ && value_regno >= 0)4201 if (atype == BPF_READ && value_regno >= 0)
4191 mark_btf_ld_reg(env, regs, value_regno, ret, reg->btf, btf_id);4202 mark_btf_ld_reg(env, regs, value_regno, ret, reg->btf, btf_id, flag);
4192 4203
4193 return 0;4204 return 0;
4194}4205}
@@ -4201,6 +4212,7 @@ static int check_ptr_to_map_access(struct bpf_verifier_env *env, · 6 unmodified lines
4201{4212{
4202 struct bpf_reg_state *reg = regs + regno;4213 struct bpf_reg_state *reg = regs + regno;
4203 struct bpf_map *map = reg->map_ptr;4214 struct bpf_map *map = reg->map_ptr;
4215 enum bpf_type_flag flag = 0;
4204 const struct btf_type *t;4216 const struct btf_type *t;
4205 const char *tname;4217 const char *tname;
4206 u32 btf_id;4218 u32 btf_id;
@@ -4238,12 +4250,12 @@ static int check_ptr_to_map_access(struct bpf_verifier_env *env, · 31 unmodified lines
4238 return -EACCES;4250 return -EACCES;
4239 }4251 }
4240 4252
4241 ret = btf_struct_access(&env->log, btf_vmlinux, t, off, size, atype, &btf_id);4253 ret = btf_struct_access(&env->log, btf_vmlinux, t, off, size, atype, &btf_id, &flag);
4242 if (ret < 0)4254 if (ret < 0)
4243 return ret;4255 return ret;
4244 4256
4245 if (value_regno >= 0)4257 if (value_regno >= 0)
4246 mark_btf_ld_reg(env, regs, value_regno, ret, btf_vmlinux, btf_id);4258 mark_btf_ld_reg(env, regs, value_regno, ret, btf_vmlinux, btf_id, flag);
4247 4259
4248 return 0;4260 return 0;
4249}4261}
@@ -4444,7 +4456,8 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn · 194 unmodified lines
4444 if (err < 0)4456 if (err < 0)
4445 return err;4457 return err;
4446 4458
4447 err = check_ctx_access(env, insn_idx, off, size, t, &reg_type, &btf, &btf_id);4459 err = check_ctx_access(env, insn_idx, off, size, t, &reg_type, &btf,
4460 &btf_id);
4448 if (err)4461 if (err)
4449 verbose_linfo(env, insn_idx, "; ");4462 verbose_linfo(env, insn_idx, "; ");
4450 if (!err && t == BPF_READ && value_regno >= 0) {4463 if (!err && t == BPF_READ && value_regno >= 0) {
net/bpf/bpf_dummy_struct_ops.c+4−2
@@ -145,7 +145,8 @@ static int bpf_dummy_ops_btf_struct_access(struct bpf_verifier_log *log, · 144 unmodified lines
145 const struct btf *btf,145 const struct btf *btf,
146 const struct btf_type *t, int off,146 const struct btf_type *t, int off,
147 int size, enum bpf_access_type atype,147 int size, enum bpf_access_type atype,
148 u32 *next_btf_id)148 u32 *next_btf_id,
149 enum bpf_type_flag *flag)
149{150{
150 const struct btf_type *state;151 const struct btf_type *state;
151 s32 type_id;152 s32 type_id;
@@ -162,7 +163,8 @@ static int bpf_dummy_ops_btf_struct_access(struct bpf_verifier_log *log, · 10 unmodified lines
162 return -EACCES;163 return -EACCES;
163 }164 }
164 165
165 err = btf_struct_access(log, btf, t, off, size, atype, next_btf_id);166 err = btf_struct_access(log, btf, t, off, size, atype, next_btf_id,
167 flag);
166 if (err < 0)168 if (err < 0)
167 return err;169 return err;
168 170
net/ipv4/bpf_tcp_ca.c+4−2
@@ -96,12 +96,14 @@ static int bpf_tcp_ca_btf_struct_access(struct bpf_verifier_log *log, · 95 unmodified lines
96 const struct btf *btf,96 const struct btf *btf,
97 const struct btf_type *t, int off,97 const struct btf_type *t, int off,
98 int size, enum bpf_access_type atype,98 int size, enum bpf_access_type atype,
99 u32 *next_btf_id)99 u32 *next_btf_id,
100 enum bpf_type_flag *flag)
100{101{
101 size_t end;102 size_t end;
102 103
103 if (atype == BPF_READ)104 if (atype == BPF_READ)
104 return btf_struct_access(log, btf, t, off, size, atype, next_btf_id);105 return btf_struct_access(log, btf, t, off, size, atype, next_btf_id,
106 flag);
105 107
106 if (t != tcp_sock_type) {108 if (t != tcp_sock_type) {
107 bpf_log(log, "only read is supported\n");109 bpf_log(log, "only read is supported\n");