2828#include  <linux/verification.h> 
2929#include  <linux/task_work.h> 
3030#include  <linux/irq_work.h> 
31+ #include  <linux/buildid.h> 
3132
3233#include  "../../lib/kstrtox.h" 
3334
@@ -1656,6 +1657,13 @@ static const struct bpf_func_proto bpf_kptr_xchg_proto = {
16561657	.arg2_btf_id   =  BPF_PTR_POISON ,
16571658};
16581659
1660+ struct  bpf_dynptr_file_impl  {
1661+ 	struct  freader  freader ;
1662+ 	/* 64 bit offset and size overriding 32 bit ones in bpf_dynptr_kern */ 
1663+ 	u64  offset ;
1664+ 	u64  size ;
1665+ };
1666+ 
16591667/* Since the upper 8 bits of dynptr->size is reserved, the 
16601668 * maximum supported size is 2^24 - 1. 
16611669 */ 
@@ -1686,13 +1694,36 @@ static enum bpf_dynptr_type bpf_dynptr_get_type(const struct bpf_dynptr_kern *pt
16861694
16871695u64  __bpf_dynptr_size (const  struct  bpf_dynptr_kern  * ptr )
16881696{
1697+ 	if  (bpf_dynptr_get_type (ptr ) ==  BPF_DYNPTR_TYPE_FILE ) {
1698+ 		struct  bpf_dynptr_file_impl  * df  =  ptr -> data ;
1699+ 
1700+ 		return  df -> size ;
1701+ 	}
1702+ 
16891703	return  ptr -> size  &  DYNPTR_SIZE_MASK ;
16901704}
16911705
1706+ static  void  bpf_dynptr_advance_offset (struct  bpf_dynptr_kern  * ptr , u64  off )
1707+ {
1708+ 	if  (bpf_dynptr_get_type (ptr ) ==  BPF_DYNPTR_TYPE_FILE ) {
1709+ 		struct  bpf_dynptr_file_impl  * df  =  ptr -> data ;
1710+ 
1711+ 		df -> offset  +=  off ;
1712+ 		return ;
1713+ 	}
1714+ 	ptr -> offset  +=  off ;
1715+ }
1716+ 
16921717static  void  bpf_dynptr_set_size (struct  bpf_dynptr_kern  * ptr , u64  new_size )
16931718{
16941719	u32  metadata  =  ptr -> size  &  ~DYNPTR_SIZE_MASK ;
16951720
1721+ 	if  (bpf_dynptr_get_type (ptr ) ==  BPF_DYNPTR_TYPE_FILE ) {
1722+ 		struct  bpf_dynptr_file_impl  * df  =  ptr -> data ;
1723+ 
1724+ 		df -> size  =  new_size ;
1725+ 		return ;
1726+ 	}
16961727	ptr -> size  =  (u32 )new_size  | metadata ;
16971728}
16981729
@@ -1701,6 +1732,25 @@ int bpf_dynptr_check_size(u64 size)
17011732	return  size  >  DYNPTR_MAX_SIZE  ? - E2BIG  : 0 ;
17021733}
17031734
1735+ static  int  bpf_file_fetch_bytes (struct  bpf_dynptr_file_impl  * df , u64  offset , void  * buf , u64  len )
1736+ {
1737+ 	const  void  * ptr ;
1738+ 
1739+ 	if  (!buf )
1740+ 		return  - EINVAL ;
1741+ 
1742+ 	df -> freader .buf  =  buf ;
1743+ 	df -> freader .buf_sz  =  len ;
1744+ 	ptr  =  freader_fetch (& df -> freader , offset  +  df -> offset , len );
1745+ 	if  (!ptr )
1746+ 		return  df -> freader .err ;
1747+ 
1748+ 	if  (ptr  !=  buf ) /* Force copying into the buffer */ 
1749+ 		memcpy (buf , ptr , len );
1750+ 
1751+ 	return  0 ;
1752+ }
1753+ 
17041754void  bpf_dynptr_init (struct  bpf_dynptr_kern  * ptr , void  * data ,
17051755		     enum  bpf_dynptr_type  type , u32  offset , u32  size )
17061756{
@@ -1781,6 +1831,8 @@ static int __bpf_dynptr_read(void *dst, u64 len, const struct bpf_dynptr_kern *s
17811831	case  BPF_DYNPTR_TYPE_SKB_META :
17821832		memmove (dst , bpf_skb_meta_pointer (src -> data , src -> offset  +  offset ), len );
17831833		return  0 ;
1834+ 	case  BPF_DYNPTR_TYPE_FILE :
1835+ 		return  bpf_file_fetch_bytes (src -> data , offset , dst , len );
17841836	default :
17851837		WARN_ONCE (true, "bpf_dynptr_read: unknown dynptr type %d\n" , type );
17861838		return  - EFAULT ;
@@ -2719,6 +2771,9 @@ __bpf_kfunc void *bpf_dynptr_slice(const struct bpf_dynptr *p, u64 offset,
27192771	}
27202772	case  BPF_DYNPTR_TYPE_SKB_META :
27212773		return  bpf_skb_meta_pointer (ptr -> data , ptr -> offset  +  offset );
2774+ 	case  BPF_DYNPTR_TYPE_FILE :
2775+ 		err  =  bpf_file_fetch_bytes (ptr -> data , offset , buffer__opt , buffer__szk );
2776+ 		return  err  ? NULL  : buffer__opt ;
27222777	default :
27232778		WARN_ONCE (true, "unknown dynptr type %d\n" , type );
27242779		return  NULL ;
@@ -2813,7 +2868,7 @@ __bpf_kfunc int bpf_dynptr_adjust(const struct bpf_dynptr *p, u64 start, u64 end
28132868	if  (start  >  size  ||  end  >  size )
28142869		return  - ERANGE ;
28152870
2816- 	ptr -> offset   +=   start ;
2871+ 	bpf_dynptr_advance_offset ( ptr ,  start ) ;
28172872	bpf_dynptr_set_size (ptr , end  -  start );
28182873
28192874	return  0 ;
@@ -4252,13 +4307,46 @@ __bpf_kfunc int bpf_task_work_schedule_resume(struct task_struct *task, struct b
42524307	return  bpf_task_work_schedule (task , tw , map__map , callback , aux__prog , TWA_RESUME );
42534308}
42544309
4255- __bpf_kfunc  int  bpf_dynptr_from_file (struct  file  * file , u32  flags , struct  bpf_dynptr  * ptr__uninit )
4310+ static  int  make_file_dynptr (struct  file  * file , u32  flags , bool  may_sleep ,
4311+ 			    struct  bpf_dynptr_kern  * ptr )
42564312{
4313+ 	struct  bpf_dynptr_file_impl  * state ;
4314+ 
4315+ 	/* flags is currently unsupported */ 
4316+ 	if  (flags ) {
4317+ 		bpf_dynptr_set_null (ptr );
4318+ 		return  - EINVAL ;
4319+ 	}
4320+ 
4321+ 	state  =  bpf_mem_alloc (& bpf_global_ma , sizeof (struct  bpf_dynptr_file_impl ));
4322+ 	if  (!state ) {
4323+ 		bpf_dynptr_set_null (ptr );
4324+ 		return  - ENOMEM ;
4325+ 	}
4326+ 	state -> offset  =  0 ;
4327+ 	state -> size  =  U64_MAX ; /* Don't restrict size, as file may change anyways */ 
4328+ 	freader_init_from_file (& state -> freader , NULL , 0 , file , may_sleep );
4329+ 	bpf_dynptr_init (ptr , state , BPF_DYNPTR_TYPE_FILE , 0 , 0 );
4330+ 	bpf_dynptr_set_rdonly (ptr );
42574331	return  0 ;
42584332}
42594333
4334+ __bpf_kfunc  int  bpf_dynptr_from_file (struct  file  * file , u32  flags , struct  bpf_dynptr  * ptr__uninit )
4335+ {
4336+ 	return  make_file_dynptr (file , flags , false, (struct  bpf_dynptr_kern  * )ptr__uninit );
4337+ }
4338+ 
42604339__bpf_kfunc  int  bpf_dynptr_file_discard (struct  bpf_dynptr  * dynptr )
42614340{
4341+ 	struct  bpf_dynptr_kern  * ptr  =  (struct  bpf_dynptr_kern  * )dynptr ;
4342+ 	struct  bpf_dynptr_file_impl  * df  =  ptr -> data ;
4343+ 
4344+ 	if  (!df )
4345+ 		return  0 ;
4346+ 
4347+ 	freader_cleanup (& df -> freader );
4348+ 	bpf_mem_free (& bpf_global_ma , df );
4349+ 	bpf_dynptr_set_null (ptr );
42624350	return  0 ;
42634351}
42644352
0 commit comments