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