mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	bpf: Support variable length array in tracing programs
In /proc/net/ipv6_route, we have
  struct fib6_info {
    struct fib6_table *fib6_table;
    ...
    struct fib6_nh fib6_nh[0];
  }
  struct fib6_nh {
    struct fib_nh_common nh_common;
    struct rt6_info **rt6i_pcpu;
    struct rt6_exception_bucket *rt6i_exception_bucket;
  };
  struct fib_nh_common {
    ...
    u8 nhc_gw_family;
    ...
  }
The access:
  struct fib6_nh *fib6_nh = &rt->fib6_nh;
  ... fib6_nh->nh_common.nhc_gw_family ...
This patch ensures such an access is handled properly.
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Link: https://lore.kernel.org/bpf/20200509175916.2476853-1-yhs@fb.com
			
			
This commit is contained in:
		
							parent
							
								
									1d68f22b3d
								
							
						
					
					
						commit
						9c5f8a1008
					
				
					 1 changed files with 37 additions and 0 deletions
				
			
		|  | @ -3833,6 +3833,7 @@ int btf_struct_access(struct bpf_verifier_log *log, | |||
| 	const struct btf_type *mtype, *elem_type = NULL; | ||||
| 	const struct btf_member *member; | ||||
| 	const char *tname, *mname; | ||||
| 	u32 vlen; | ||||
| 
 | ||||
| again: | ||||
| 	tname = __btf_name_by_offset(btf_vmlinux, t->name_off); | ||||
|  | @ -3841,7 +3842,43 @@ int btf_struct_access(struct bpf_verifier_log *log, | |||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	vlen = btf_type_vlen(t); | ||||
| 	if (off + size > t->size) { | ||||
| 		/* If the last element is a variable size array, we may
 | ||||
| 		 * need to relax the rule. | ||||
| 		 */ | ||||
| 		struct btf_array *array_elem; | ||||
| 
 | ||||
| 		if (vlen == 0) | ||||
| 			goto error; | ||||
| 
 | ||||
| 		member = btf_type_member(t) + vlen - 1; | ||||
| 		mtype = btf_type_skip_modifiers(btf_vmlinux, member->type, | ||||
| 						NULL); | ||||
| 		if (!btf_type_is_array(mtype)) | ||||
| 			goto error; | ||||
| 
 | ||||
| 		array_elem = (struct btf_array *)(mtype + 1); | ||||
| 		if (array_elem->nelems != 0) | ||||
| 			goto error; | ||||
| 
 | ||||
| 		moff = btf_member_bit_offset(t, member) / 8; | ||||
| 		if (off < moff) | ||||
| 			goto error; | ||||
| 
 | ||||
| 		/* Only allow structure for now, can be relaxed for
 | ||||
| 		 * other types later. | ||||
| 		 */ | ||||
| 		elem_type = btf_type_skip_modifiers(btf_vmlinux, | ||||
| 						    array_elem->type, NULL); | ||||
| 		if (!btf_type_is_struct(elem_type)) | ||||
| 			goto error; | ||||
| 
 | ||||
| 		off = (off - moff) % elem_type->size; | ||||
| 		return btf_struct_access(log, elem_type, off, size, atype, | ||||
| 					 next_btf_id); | ||||
| 
 | ||||
| error: | ||||
| 		bpf_log(log, "access beyond struct %s at off %u size %u\n", | ||||
| 			tname, off, size); | ||||
| 		return -EACCES; | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Yonghong Song
						Yonghong Song