public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf v1] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage
@ 2026-03-12  5:25 xulang
  2026-03-12 11:51 ` Paul Chaignon
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: xulang @ 2026-03-12  5:25 UTC (permalink / raw)
  To: bpf
  Cc: martin.lau, ast, daniel, andrii, eddyz87, song, yonghong.song,
	john.fastabend, kpsingh, sdf, haoluo, jolsa, kaiyanm, huyinhao,
	dzm91, kernel, linux-kernel, Lang Xu

From: Lang Xu <xulang@uniontech.com>

An out-of-bounds read occurs when copying element from a
BPF_MAP_TYPE_CGROUP_STORAGE map to another map type with the same
value_size that is not 8-byte aligned.

The issue happens when:
1. A CGROUP_STORAGE map is created with value_size not aligned to
   8 bytes (e.g., 4 bytes)
2. A HASH map is created with the same value_size (e.g., 4 bytes)
3. Update element in 2 with data in 1

In the kernel, map elements are typically aligned to 8 bytes. However,
bpf_cgroup_storage_calculate_size() allocates storage based on the exact
value_size without alignment. When copy_map_value_long() is called, it
assumes all map values are 8-byte aligned and rounds up the copy size,
leading to a 4-byte out-of-bounds read from the cgroup storage buffer.

This patch fixes the issue by ensuring cgroup storage allocates 8-byte
aligned buffers, matching the assumptions in copy_map_value_long().

Fixes: b741f1630346 ("bpf: introduce per-cpu cgroup local storage")
Reported-by: Kaiyan Mei <kaiyanm@hust.edu.cn>
Closes: https://lore.kernel.org/all/14e6c70c.6c121.19c0399d948.Coremail.kaiyanm@hust.edu.cn/
Signed-off-by: Lang Xu <xulang@uniontech.com>
---
 kernel/bpf/local_storage.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/kernel/bpf/local_storage.c b/kernel/bpf/local_storage.c
index 8fca0c64f7b1..54b32ba19194 100644
--- a/kernel/bpf/local_storage.c
+++ b/kernel/bpf/local_storage.c
@@ -487,14 +487,13 @@ static size_t bpf_cgroup_storage_calculate_size(struct bpf_map *map, u32 *pages)
 {
 	size_t size;
 
+	size = round_up(map->value_size, 8);
 	if (cgroup_storage_type(map) == BPF_CGROUP_STORAGE_SHARED) {
-		size = sizeof(struct bpf_storage_buffer) + map->value_size;
+		size += sizeof(struct bpf_storage_buffer);
 		*pages = round_up(sizeof(struct bpf_cgroup_storage) + size,
 				  PAGE_SIZE) >> PAGE_SHIFT;
 	} else {
-		size = map->value_size;
-		*pages = round_up(round_up(size, 8) * num_possible_cpus(),
-				  PAGE_SIZE) >> PAGE_SHIFT;
+		*pages = round_up(size * num_possible_cpus(), PAGE_SIZE) >> PAGE_SHIFT;
 	}
 
 	return size;
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH bpf v1] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage
  2026-03-12  5:25 [PATCH bpf v1] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage xulang
@ 2026-03-12 11:51 ` Paul Chaignon
  2026-03-12 16:41   ` Yonghong Song
  2026-03-12 16:46 ` Yonghong Song
  2026-03-13 20:34 ` Martin KaFai Lau
  2 siblings, 1 reply; 14+ messages in thread
From: Paul Chaignon @ 2026-03-12 11:51 UTC (permalink / raw)
  To: xulang
  Cc: bpf, martin.lau, ast, daniel, andrii, eddyz87, song,
	yonghong.song, john.fastabend, kpsingh, sdf, haoluo, jolsa,
	kaiyanm, huyinhao, dzm91, kernel, linux-kernel

On Thu, Mar 12, 2026 at 01:25:25PM +0800, xulang wrote:
> From: Lang Xu <xulang@uniontech.com>
> 
> An out-of-bounds read occurs when copying element from a
> BPF_MAP_TYPE_CGROUP_STORAGE map to another map type with the same
> value_size that is not 8-byte aligned.
> 
> The issue happens when:
> 1. A CGROUP_STORAGE map is created with value_size not aligned to
>    8 bytes (e.g., 4 bytes)
> 2. A HASH map is created with the same value_size (e.g., 4 bytes)
> 3. Update element in 2 with data in 1
> 
> In the kernel, map elements are typically aligned to 8 bytes. However,
> bpf_cgroup_storage_calculate_size() allocates storage based on the exact
> value_size without alignment. When copy_map_value_long() is called, it
> assumes all map values are 8-byte aligned and rounds up the copy size,
> leading to a 4-byte out-of-bounds read from the cgroup storage buffer.
> 
> This patch fixes the issue by ensuring cgroup storage allocates 8-byte
> aligned buffers, matching the assumptions in copy_map_value_long().

I don't think this bug is specific to the CGROUP_STORAGE maps. Wouldn't
it affect any copy from a non-percpu map into a percpu hashmap? The
reproducer in [1] copies from a BPF_MAP_TYPE_CGROUP_STORAGE map to a
BPF_MAP_TYPE_LRU_PERCPU_HASH map, but I suspect you'd hit the same bug
if copying from BPF_MAP_TYPE_HASH into BPF_MAP_TYPE_PERCPU_HASH because
for BPF_MAP_TYPE_HASH the value size is also not rounded up to a
multiple of 8.

1 - https://lore.kernel.org/all/14e6c70c.6c121.19c0399d948.Coremail.kaiyanm@hust.edu.cn/

> 
> Fixes: b741f1630346 ("bpf: introduce per-cpu cgroup local storage")
> Reported-by: Kaiyan Mei <kaiyanm@hust.edu.cn>
> Closes: https://lore.kernel.org/all/14e6c70c.6c121.19c0399d948.Coremail.kaiyanm@hust.edu.cn/
> Signed-off-by: Lang Xu <xulang@uniontech.com>
> ---
>  kernel/bpf/local_storage.c | 7 +++----
>  1 file changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/kernel/bpf/local_storage.c b/kernel/bpf/local_storage.c
> index 8fca0c64f7b1..54b32ba19194 100644
> --- a/kernel/bpf/local_storage.c
> +++ b/kernel/bpf/local_storage.c
> @@ -487,14 +487,13 @@ static size_t bpf_cgroup_storage_calculate_size(struct bpf_map *map, u32 *pages)
>  {
>  	size_t size;
>  
> +	size = round_up(map->value_size, 8);
>  	if (cgroup_storage_type(map) == BPF_CGROUP_STORAGE_SHARED) {
> -		size = sizeof(struct bpf_storage_buffer) + map->value_size;
> +		size += sizeof(struct bpf_storage_buffer);
>  		*pages = round_up(sizeof(struct bpf_cgroup_storage) + size,
>  				  PAGE_SIZE) >> PAGE_SHIFT;
>  	} else {
> -		size = map->value_size;
> -		*pages = round_up(round_up(size, 8) * num_possible_cpus(),
> -				  PAGE_SIZE) >> PAGE_SHIFT;
> +		*pages = round_up(size * num_possible_cpus(), PAGE_SIZE) >> PAGE_SHIFT;
>  	}
>  
>  	return size;
> -- 
> 2.51.0
> 
> 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH bpf v1] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage
  2026-03-12 11:51 ` Paul Chaignon
@ 2026-03-12 16:41   ` Yonghong Song
  2026-03-12 18:02     ` Paul Chaignon
  0 siblings, 1 reply; 14+ messages in thread
From: Yonghong Song @ 2026-03-12 16:41 UTC (permalink / raw)
  To: Paul Chaignon, xulang
  Cc: bpf, martin.lau, ast, daniel, andrii, eddyz87, song,
	john.fastabend, kpsingh, sdf, haoluo, jolsa, kaiyanm, huyinhao,
	dzm91, kernel, linux-kernel



On 3/12/26 4:51 AM, Paul Chaignon wrote:
> On Thu, Mar 12, 2026 at 01:25:25PM +0800, xulang wrote:
>> From: Lang Xu <xulang@uniontech.com>
>>
>> An out-of-bounds read occurs when copying element from a
>> BPF_MAP_TYPE_CGROUP_STORAGE map to another map type with the same
>> value_size that is not 8-byte aligned.
>>
>> The issue happens when:
>> 1. A CGROUP_STORAGE map is created with value_size not aligned to
>>     8 bytes (e.g., 4 bytes)
>> 2. A HASH map is created with the same value_size (e.g., 4 bytes)
>> 3. Update element in 2 with data in 1
>>
>> In the kernel, map elements are typically aligned to 8 bytes. However,
>> bpf_cgroup_storage_calculate_size() allocates storage based on the exact
>> value_size without alignment. When copy_map_value_long() is called, it
>> assumes all map values are 8-byte aligned and rounds up the copy size,
>> leading to a 4-byte out-of-bounds read from the cgroup storage buffer.
>>
>> This patch fixes the issue by ensuring cgroup storage allocates 8-byte
>> aligned buffers, matching the assumptions in copy_map_value_long().
> I don't think this bug is specific to the CGROUP_STORAGE maps. Wouldn't
> it affect any copy from a non-percpu map into a percpu hashmap? The
> reproducer in [1] copies from a BPF_MAP_TYPE_CGROUP_STORAGE map to a
> BPF_MAP_TYPE_LRU_PERCPU_HASH map, but I suspect you'd hit the same bug
> if copying from BPF_MAP_TYPE_HASH into BPF_MAP_TYPE_PERCPU_HASH because
> for BPF_MAP_TYPE_HASH the value size is also not rounded up to a
> multiple of 8.

The BPF_MAP_TYPE_HASH table have value size rounds up to 8. See:

         if (percpu)
                 htab->elem_size += sizeof(void *);
         else
                 htab->elem_size += round_up(htab->map.value_size, 8);

The same for array size.

>
> 1 - https://lore.kernel.org/all/14e6c70c.6c121.19c0399d948.Coremail.kaiyanm@hust.edu.cn/
>
>> Fixes: b741f1630346 ("bpf: introduce per-cpu cgroup local storage")
>> Reported-by: Kaiyan Mei <kaiyanm@hust.edu.cn>
>> Closes: https://lore.kernel.org/all/14e6c70c.6c121.19c0399d948.Coremail.kaiyanm@hust.edu.cn/
>> Signed-off-by: Lang Xu <xulang@uniontech.com>
>> ---
>>   kernel/bpf/local_storage.c | 7 +++----
>>   1 file changed, 3 insertions(+), 4 deletions(-)
>>
>> diff --git a/kernel/bpf/local_storage.c b/kernel/bpf/local_storage.c
>> index 8fca0c64f7b1..54b32ba19194 100644
>> --- a/kernel/bpf/local_storage.c
>> +++ b/kernel/bpf/local_storage.c
>> @@ -487,14 +487,13 @@ static size_t bpf_cgroup_storage_calculate_size(struct bpf_map *map, u32 *pages)
>>   {
>>   	size_t size;
>>   
>> +	size = round_up(map->value_size, 8);
>>   	if (cgroup_storage_type(map) == BPF_CGROUP_STORAGE_SHARED) {
>> -		size = sizeof(struct bpf_storage_buffer) + map->value_size;
>> +		size += sizeof(struct bpf_storage_buffer);
>>   		*pages = round_up(sizeof(struct bpf_cgroup_storage) + size,
>>   				  PAGE_SIZE) >> PAGE_SHIFT;
>>   	} else {
>> -		size = map->value_size;
>> -		*pages = round_up(round_up(size, 8) * num_possible_cpus(),
>> -				  PAGE_SIZE) >> PAGE_SHIFT;
>> +		*pages = round_up(size * num_possible_cpus(), PAGE_SIZE) >> PAGE_SHIFT;
>>   	}
>>   
>>   	return size;
>> -- 
>> 2.51.0
>>
>>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH bpf v1] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage
  2026-03-12  5:25 [PATCH bpf v1] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage xulang
  2026-03-12 11:51 ` Paul Chaignon
@ 2026-03-12 16:46 ` Yonghong Song
  2026-03-13 20:34 ` Martin KaFai Lau
  2 siblings, 0 replies; 14+ messages in thread
From: Yonghong Song @ 2026-03-12 16:46 UTC (permalink / raw)
  To: xulang, bpf
  Cc: martin.lau, ast, daniel, andrii, eddyz87, song, john.fastabend,
	kpsingh, sdf, haoluo, jolsa, kaiyanm, huyinhao, dzm91, kernel,
	linux-kernel



On 3/11/26 10:25 PM, xulang wrote:
> From: Lang Xu <xulang@uniontech.com>
>
> An out-of-bounds read occurs when copying element from a
> BPF_MAP_TYPE_CGROUP_STORAGE map to another map type with the same
> value_size that is not 8-byte aligned.
>
> The issue happens when:
> 1. A CGROUP_STORAGE map is created with value_size not aligned to
>     8 bytes (e.g., 4 bytes)
> 2. A HASH map is created with the same value_size (e.g., 4 bytes)
> 3. Update element in 2 with data in 1
>
> In the kernel, map elements are typically aligned to 8 bytes. However,
> bpf_cgroup_storage_calculate_size() allocates storage based on the exact
> value_size without alignment. When copy_map_value_long() is called, it
> assumes all map values are 8-byte aligned and rounds up the copy size,
> leading to a 4-byte out-of-bounds read from the cgroup storage buffer.
>
> This patch fixes the issue by ensuring cgroup storage allocates 8-byte
> aligned buffers, matching the assumptions in copy_map_value_long().
>
> Fixes: b741f1630346 ("bpf: introduce per-cpu cgroup local storage")
> Reported-by: Kaiyan Mei <kaiyanm@hust.edu.cn>
> Closes: https://lore.kernel.org/all/14e6c70c.6c121.19c0399d948.Coremail.kaiyanm@hust.edu.cn/
> Signed-off-by: Lang Xu <xulang@uniontech.com>

Acked-by: Yonghong Song <yonghong.song@linux.dev>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH bpf v1] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage
  2026-03-12 16:41   ` Yonghong Song
@ 2026-03-12 18:02     ` Paul Chaignon
  2026-03-12 19:58       ` Yonghong Song
  0 siblings, 1 reply; 14+ messages in thread
From: Paul Chaignon @ 2026-03-12 18:02 UTC (permalink / raw)
  To: Yonghong Song
  Cc: xulang, bpf, martin.lau, ast, daniel, andrii, eddyz87, song,
	john.fastabend, kpsingh, sdf, haoluo, jolsa, kaiyanm, huyinhao,
	dzm91, kernel, linux-kernel

On Thu, Mar 12, 2026 at 09:41:40AM -0700, Yonghong Song wrote:
> 
> 
> On 3/12/26 4:51 AM, Paul Chaignon wrote:
> > On Thu, Mar 12, 2026 at 01:25:25PM +0800, xulang wrote:
> > > From: Lang Xu <xulang@uniontech.com>
> > > 
> > > An out-of-bounds read occurs when copying element from a
> > > BPF_MAP_TYPE_CGROUP_STORAGE map to another map type with the same
> > > value_size that is not 8-byte aligned.
> > > 
> > > The issue happens when:
> > > 1. A CGROUP_STORAGE map is created with value_size not aligned to
> > >     8 bytes (e.g., 4 bytes)
> > > 2. A HASH map is created with the same value_size (e.g., 4 bytes)
> > > 3. Update element in 2 with data in 1
> > > 
> > > In the kernel, map elements are typically aligned to 8 bytes. However,
> > > bpf_cgroup_storage_calculate_size() allocates storage based on the exact
> > > value_size without alignment. When copy_map_value_long() is called, it
> > > assumes all map values are 8-byte aligned and rounds up the copy size,
> > > leading to a 4-byte out-of-bounds read from the cgroup storage buffer.
> > > 
> > > This patch fixes the issue by ensuring cgroup storage allocates 8-byte
> > > aligned buffers, matching the assumptions in copy_map_value_long().
> > I don't think this bug is specific to the CGROUP_STORAGE maps. Wouldn't
> > it affect any copy from a non-percpu map into a percpu hashmap? The
> > reproducer in [1] copies from a BPF_MAP_TYPE_CGROUP_STORAGE map to a
> > BPF_MAP_TYPE_LRU_PERCPU_HASH map, but I suspect you'd hit the same bug
> > if copying from BPF_MAP_TYPE_HASH into BPF_MAP_TYPE_PERCPU_HASH because
> > for BPF_MAP_TYPE_HASH the value size is also not rounded up to a
> > multiple of 8.
> 
> The BPF_MAP_TYPE_HASH table have value size rounds up to 8. See:
> 
>         if (percpu)
>                 htab->elem_size += sizeof(void *);
>         else
>                 htab->elem_size += round_up(htab->map.value_size, 8);
> 
> The same for array size.

My bad, I looked at the _alloc_check and assumed any round_up would be
reflected there :/ Given that:

Acked-by: Paul Chaignon <paul.chaignon@gmail.com>

I also had a look at other map types and they all seem to round up to 8
or to not be susceptible to the oob copy (ex., queue & stack). The one
for which I'm unsure is BPF_MAP_TYPE_*_CGROUP_STORAGE. It doesn't seem
to round up to 8, but I'm unsure it could be used to reproduce the copy.

On a related note, this is the sort of reproducer that would be good to
add in https://github.com/google/syzkaller/tree/master/sys/linux/test
because syzbot can easily learn from it and reach potentially similar
bugs.

> 
> > 
> > 1 - https://lore.kernel.org/all/14e6c70c.6c121.19c0399d948.Coremail.kaiyanm@hust.edu.cn/
> > 
> > > Fixes: b741f1630346 ("bpf: introduce per-cpu cgroup local storage")
> > > Reported-by: Kaiyan Mei <kaiyanm@hust.edu.cn>
> > > Closes: https://lore.kernel.org/all/14e6c70c.6c121.19c0399d948.Coremail.kaiyanm@hust.edu.cn/
> > > Signed-off-by: Lang Xu <xulang@uniontech.com>
> > > ---
> > >   kernel/bpf/local_storage.c | 7 +++----
> > >   1 file changed, 3 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/kernel/bpf/local_storage.c b/kernel/bpf/local_storage.c
> > > index 8fca0c64f7b1..54b32ba19194 100644
> > > --- a/kernel/bpf/local_storage.c
> > > +++ b/kernel/bpf/local_storage.c
> > > @@ -487,14 +487,13 @@ static size_t bpf_cgroup_storage_calculate_size(struct bpf_map *map, u32 *pages)
> > >   {
> > >   	size_t size;
> > > +	size = round_up(map->value_size, 8);
> > >   	if (cgroup_storage_type(map) == BPF_CGROUP_STORAGE_SHARED) {
> > > -		size = sizeof(struct bpf_storage_buffer) + map->value_size;
> > > +		size += sizeof(struct bpf_storage_buffer);
> > >   		*pages = round_up(sizeof(struct bpf_cgroup_storage) + size,
> > >   				  PAGE_SIZE) >> PAGE_SHIFT;
> > >   	} else {
> > > -		size = map->value_size;
> > > -		*pages = round_up(round_up(size, 8) * num_possible_cpus(),
> > > -				  PAGE_SIZE) >> PAGE_SHIFT;
> > > +		*pages = round_up(size * num_possible_cpus(), PAGE_SIZE) >> PAGE_SHIFT;
> > >   	}
> > >   	return size;
> > > -- 
> > > 2.51.0
> > > 
> > > 
> 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH bpf v1] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage
  2026-03-12 18:02     ` Paul Chaignon
@ 2026-03-12 19:58       ` Yonghong Song
  0 siblings, 0 replies; 14+ messages in thread
From: Yonghong Song @ 2026-03-12 19:58 UTC (permalink / raw)
  To: Paul Chaignon
  Cc: xulang, bpf, martin.lau, ast, daniel, andrii, eddyz87, song,
	john.fastabend, kpsingh, sdf, haoluo, jolsa, kaiyanm, huyinhao,
	dzm91, kernel, linux-kernel



On 3/12/26 11:02 AM, Paul Chaignon wrote:
> On Thu, Mar 12, 2026 at 09:41:40AM -0700, Yonghong Song wrote:
>>
>> On 3/12/26 4:51 AM, Paul Chaignon wrote:
>>> On Thu, Mar 12, 2026 at 01:25:25PM +0800, xulang wrote:
>>>> From: Lang Xu <xulang@uniontech.com>
>>>>
>>>> An out-of-bounds read occurs when copying element from a
>>>> BPF_MAP_TYPE_CGROUP_STORAGE map to another map type with the same
>>>> value_size that is not 8-byte aligned.
>>>>
>>>> The issue happens when:
>>>> 1. A CGROUP_STORAGE map is created with value_size not aligned to
>>>>      8 bytes (e.g., 4 bytes)
>>>> 2. A HASH map is created with the same value_size (e.g., 4 bytes)
>>>> 3. Update element in 2 with data in 1
>>>>
>>>> In the kernel, map elements are typically aligned to 8 bytes. However,
>>>> bpf_cgroup_storage_calculate_size() allocates storage based on the exact
>>>> value_size without alignment. When copy_map_value_long() is called, it
>>>> assumes all map values are 8-byte aligned and rounds up the copy size,
>>>> leading to a 4-byte out-of-bounds read from the cgroup storage buffer.
>>>>
>>>> This patch fixes the issue by ensuring cgroup storage allocates 8-byte
>>>> aligned buffers, matching the assumptions in copy_map_value_long().
>>> I don't think this bug is specific to the CGROUP_STORAGE maps. Wouldn't
>>> it affect any copy from a non-percpu map into a percpu hashmap? The
>>> reproducer in [1] copies from a BPF_MAP_TYPE_CGROUP_STORAGE map to a
>>> BPF_MAP_TYPE_LRU_PERCPU_HASH map, but I suspect you'd hit the same bug
>>> if copying from BPF_MAP_TYPE_HASH into BPF_MAP_TYPE_PERCPU_HASH because
>>> for BPF_MAP_TYPE_HASH the value size is also not rounded up to a
>>> multiple of 8.
>> The BPF_MAP_TYPE_HASH table have value size rounds up to 8. See:
>>
>>          if (percpu)
>>                  htab->elem_size += sizeof(void *);
>>          else
>>                  htab->elem_size += round_up(htab->map.value_size, 8);
>>
>> The same for array size.
> My bad, I looked at the _alloc_check and assumed any round_up would be
> reflected there :/ Given that:
>
> Acked-by: Paul Chaignon <paul.chaignon@gmail.com>
>
> I also had a look at other map types and they all seem to round up to 8
> or to not be susceptible to the oob copy (ex., queue & stack). The one
> for which I'm unsure is BPF_MAP_TYPE_*_CGROUP_STORAGE. It doesn't seem
> to round up to 8, but I'm unsure it could be used to reproduce the copy.

For cgroup local storage, I think we should be okay.

struct bpf_local_storage_elem {
         struct hlist_node map_node;     /* Linked to bpf_local_storage_map */
         struct hlist_node snode;        /* Linked to bpf_local_storage */
         struct bpf_local_storage __rcu *local_storage;
         union {
                 struct rcu_head rcu;
                 struct hlist_node free_node;    /* used to postpone
                                                  * bpf_selem_free
                                                  * after raw_spin_unlock
                                                  */
         };
         atomic_t state;
         bool use_kmalloc_nolock;
         /* 3 bytes hole */
         /* The data is stored in another cacheline to minimize
          * the number of cachelines access during a cache hit.
          */
         struct bpf_local_storage_data sdata ____cacheline_aligned;
};

struct bpf_local_storage_data {
         /* smap is used as the searching key when looking up
          * from the object's bpf_local_storage.
          *
          * Put it in the same cacheline as the data to minimize
          * the number of cachelines accessed during the cache hit case.
          */
         struct bpf_local_storage_map __rcu *smap;
         u8 data[] __aligned(8);
};

$ pahole -C bpf_local_storage_elem ../../linux-bld/vmlinux
struct bpf_local_storage_elem {
         struct hlist_node          map_node;             /*     0    16 */
         struct hlist_node          snode;                /*    16    16 */
         struct bpf_local_storage * local_storage;        /*    32     8 */
         union {
                 struct callback_head rcu __attribute__((__aligned__(8))); /*    40    16 */
                 struct hlist_node  free_node;            /*    40    16 */
         };                                               /*    40    16 */
         union {
                 struct callback_head       rcu __attribute__((__aligned__(8))); /*     0    16 */
                 struct hlist_node          free_node;            /*     0    16 */
         };

         atomic_t                   state;                /*    56     4 */
         bool                       use_kmalloc_nolock;   /*    60     1 */

         /* XXX 3 bytes hole, try to pack */

         /* --- cacheline 1 boundary (64 bytes) --- */
         struct bpf_local_storage_data sdata __attribute__((__aligned__(64))); /*    64     8 */

         /* XXX last struct has a flexible array */

         /* Force padding: */
         struct bpf_local_storage_data :64;
         struct bpf_local_storage_data :64;
         struct bpf_local_storage_data :64;
         struct bpf_local_storage_data :64;
         struct bpf_local_storage_data :64;
         struct bpf_local_storage_data :64;
         struct bpf_local_storage_data :64;

         /* size: 128, cachelines: 2, members: 7 */
         /* sum members: 69, holes: 1, sum holes: 3 */
         /* padding: 56 */
         /* forced alignments: 1, forced holes: 1, sum forced holes: 3 */
         /* flexible array members: end: 1 */
};


So th minimum size will be 72 (with elem size 0). If the elem size is 4,
the allocation size will be 76.

The allocation is using kmalloc so the size will be promoted to next
slub bucket which should be round of 8.

>
> On a related note, this is the sort of reproducer that would be good to
> add in https://github.com/google/syzkaller/tree/master/sys/linux/test
> because syzbot can easily learn from it and reach potentially similar
> bugs.
>
>>> 1 - https://lore.kernel.org/all/14e6c70c.6c121.19c0399d948.Coremail.kaiyanm@hust.edu.cn/
>>>
>>>> Fixes: b741f1630346 ("bpf: introduce per-cpu cgroup local storage")
>>>> Reported-by: Kaiyan Mei <kaiyanm@hust.edu.cn>
>>>> Closes: https://lore.kernel.org/all/14e6c70c.6c121.19c0399d948.Coremail.kaiyanm@hust.edu.cn/
>>>> Signed-off-by: Lang Xu <xulang@uniontech.com>
>>>> ---
>>>>    kernel/bpf/local_storage.c | 7 +++----
>>>>    1 file changed, 3 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/kernel/bpf/local_storage.c b/kernel/bpf/local_storage.c
>>>> index 8fca0c64f7b1..54b32ba19194 100644
>>>> --- a/kernel/bpf/local_storage.c
>>>> +++ b/kernel/bpf/local_storage.c
>>>> @@ -487,14 +487,13 @@ static size_t bpf_cgroup_storage_calculate_size(struct bpf_map *map, u32 *pages)
>>>>    {
>>>>    	size_t size;
>>>> +	size = round_up(map->value_size, 8);
>>>>    	if (cgroup_storage_type(map) == BPF_CGROUP_STORAGE_SHARED) {
>>>> -		size = sizeof(struct bpf_storage_buffer) + map->value_size;
>>>> +		size += sizeof(struct bpf_storage_buffer);
>>>>    		*pages = round_up(sizeof(struct bpf_cgroup_storage) + size,
>>>>    				  PAGE_SIZE) >> PAGE_SHIFT;
>>>>    	} else {
>>>> -		size = map->value_size;
>>>> -		*pages = round_up(round_up(size, 8) * num_possible_cpus(),
>>>> -				  PAGE_SIZE) >> PAGE_SHIFT;
>>>> +		*pages = round_up(size * num_possible_cpus(), PAGE_SIZE) >> PAGE_SHIFT;
>>>>    	}
>>>>    	return size;
>>>> -- 
>>>> 2.51.0
>>>>
>>>>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH bpf v1] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage
  2026-03-12  5:25 [PATCH bpf v1] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage xulang
  2026-03-12 11:51 ` Paul Chaignon
  2026-03-12 16:46 ` Yonghong Song
@ 2026-03-13 20:34 ` Martin KaFai Lau
  2026-03-16 13:51   ` xulang
  2 siblings, 1 reply; 14+ messages in thread
From: Martin KaFai Lau @ 2026-03-13 20:34 UTC (permalink / raw)
  To: xulang, yonghong.song, Paul Chaignon
  Cc: bpf, ast, daniel, andrii, eddyz87, song, john.fastabend, kpsingh,
	sdf, haoluo, jolsa, kaiyanm, huyinhao, dzm91, kernel,
	linux-kernel



On 3/11/26 10:25 PM, xulang wrote:
> From: Lang Xu <xulang@uniontech.com>
> 
> An out-of-bounds read occurs when copying element from a
> BPF_MAP_TYPE_CGROUP_STORAGE map to another map type with the same
> value_size that is not 8-byte aligned.
> 
> The issue happens when:
> 1. A CGROUP_STORAGE map is created with value_size not aligned to
>     8 bytes (e.g., 4 bytes)
> 2. A HASH map is created with the same value_size (e.g., 4 bytes)
> 3. Update element in 2 with data in 1

Please create a selftest for this.

pw-bot: cr

> 
> In the kernel, map elements are typically aligned to 8 bytes. However,
> bpf_cgroup_storage_calculate_size() allocates storage based on the exact
> value_size without alignment. When copy_map_value_long() is called, it
> assumes all map values are 8-byte aligned and rounds up the copy size,
> leading to a 4-byte out-of-bounds read from the cgroup storage buffer.
> 
> This patch fixes the issue by ensuring cgroup storage allocates 8-byte
> aligned buffers, matching the assumptions in copy_map_value_long().

This is fixing the src side of the "copy_map_value_long(map, dst, src)".
The src could also be from a skb? What is the value_size that the 
verifier is checking for bpf_map_update_elem?


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH bpf v1] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage
  2026-03-13 20:34 ` Martin KaFai Lau
@ 2026-03-16 13:51   ` xulang
  2026-03-16 20:50     ` Martin KaFai Lau
  0 siblings, 1 reply; 14+ messages in thread
From: xulang @ 2026-03-16 13:51 UTC (permalink / raw)
  To: martin.lau
  Cc: andrii, ast, bpf, daniel, dzm91, eddyz87, haoluo, huyinhao,
	john.fastabend, jolsa, kaiyanm, kernel, kpsingh, linux-kernel,
	paul.chaignon, sdf, song, xulang, yonghong.song

From: Lang Xu <xulang@uniontech.com>

> Please create a selftest for this.

Going to do that. To stably reproduce this bug, I need the KASAN
config enabled, how do I ensure it's enabled during a selftest cycle,
by adding the line below to the 'config'? not quite sure.

--- a/tools/testing/selftests/bpf/config
+++ b/tools/testing/selftests/bpf/config
@@ -46,6 +46,7 @@ CONFIG_IPV6_GRE=y
 CONFIG_IPV6_SEG6_BPF=y
 CONFIG_IPV6_SIT=y
 CONFIG_IPV6_TUNNEL=y
+CONFIG_KASAN=y
 CONFIG_KEYS=y
 CONFIG_LIRC=y
 CONFIG_LWTUNNEL=y

> This is fixing the src side of the "copy_map_value_long(map, dst, src)".
> The src could also be from a skb? What is the value_size that the
> verifier is checking for bpf_map_update_elem?

The value_size checked by verifier is exactly the size with which
the map is defined, i.e., not the size rounded up to 8-byte by kernel

As for bpf_map_update_elem->..->copy_map_value_long, 'src' couldn't be from
'skb' which mismatches the expected ptr-type of 'bpf_map_update_elem',
I've tried codes like these:

1. bpf_map_update_elem(&lru_map, &key, skb, BPF_ANY);
2. bpf_map_update_elem(&lru_map, &key, skb->sk, BPF_ANY);  // null checked
3. bpf_map_update_elem(&lru_map, &key, skb->flow_keys, BPF_ANY);

All these ptrs mismatch the expected ptr-type, which can be detected by the verifier.
The verifier complains with msg like 'R3 type=ctx expected=fp, pkt, pkt_meta, map_key,
map_value, mem, ringbuf_mem, buf, trusted_ptr'

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH bpf v1] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage
  2026-03-16 13:51   ` xulang
@ 2026-03-16 20:50     ` Martin KaFai Lau
  2026-03-16 21:22       ` Ihor Solodrai
                         ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Martin KaFai Lau @ 2026-03-16 20:50 UTC (permalink / raw)
  To: xulang
  Cc: andrii, ast, bpf, daniel, dzm91, eddyz87, haoluo, huyinhao,
	john.fastabend, jolsa, kaiyanm, kernel, kpsingh, linux-kernel,
	paul.chaignon, sdf, song, yonghong.song, ihor.solodrai



On 3/16/26 6:51 AM, xulang wrote:
> From: Lang Xu <xulang@uniontech.com>
> 
>> Please create a selftest for this.
> 
> Going to do that. To stably reproduce this bug, I need the KASAN
> config enabled, how do I ensure it's enabled during a selftest cycle,
> by adding the line below to the 'config'? not quite sure.
> 
> --- a/tools/testing/selftests/bpf/config
> +++ b/tools/testing/selftests/bpf/config
> @@ -46,6 +46,7 @@ CONFIG_IPV6_GRE=y
>   CONFIG_IPV6_SEG6_BPF=y
>   CONFIG_IPV6_SIT=y
>   CONFIG_IPV6_TUNNEL=y
> +CONFIG_KASAN=y

I would leave out this config change from this fix for now. cc: Ihor to 
consider enabling it for bpf-next.

It is still useful to have a selftest for this case. I always have KASAN 
turned on when running selftests.


>> This is fixing the src side of the "copy_map_value_long(map, dst, src)".
>> The src could also be from a skb? What is the value_size that the
>> verifier is checking for bpf_map_update_elem?
> 
> The value_size checked by verifier is exactly the size with which
> the map is defined, i.e., not the size rounded up to 8-byte by kernel

If the verifier ensures only 4-bytes, I am not sure if the helper should 
read 8-bytes.

> 
> As for bpf_map_update_elem->..->copy_map_value_long, 'src' couldn't be from
> 'skb' which mismatches the expected ptr-type of 'bpf_map_update_elem',
> I've tried codes like these:
> 
> 1. bpf_map_update_elem(&lru_map, &key, skb, BPF_ANY);
> 2. bpf_map_update_elem(&lru_map, &key, skb->sk, BPF_ANY);  // null checked
> 3. bpf_map_update_elem(&lru_map, &key, skb->flow_keys, BPF_ANY);
> 
> All these ptrs mismatch the expected ptr-type, which can be detected by the verifier.
> The verifier complains with msg like 'R3 type=ctx expected=fp, pkt, pkt_meta, map_key,
> map_value, mem, ringbuf_mem, buf, trusted_ptr'

I meant the __sk_buff->data. Take a look at how skb->data can be used in 
the selftests. __sk_buff->data may not have readable bytes rounded up to 
8. Just one example that the src cannot always be fixed by allocating more.

 From looking at git history on pcpu_init_value, the issue should be 
introduced in commit d3bec0138bfb.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH bpf v1] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage
  2026-03-16 20:50     ` Martin KaFai Lau
@ 2026-03-16 21:22       ` Ihor Solodrai
  2026-03-17 10:02       ` [PATCH bpf 0/2] bpf: Fix and test cgroup storage OOB issue xulang
       [not found]       ` <20260317100227.2157104-1-xulang@uniontech.com>
  2 siblings, 0 replies; 14+ messages in thread
From: Ihor Solodrai @ 2026-03-16 21:22 UTC (permalink / raw)
  To: Martin KaFai Lau, xulang
  Cc: andrii, ast, bpf, daniel, dzm91, eddyz87, haoluo, huyinhao,
	john.fastabend, jolsa, kaiyanm, kernel, kpsingh, linux-kernel,
	paul.chaignon, sdf, song, yonghong.song

On 3/16/26 1:50 PM, Martin KaFai Lau wrote:
> 
> 
> On 3/16/26 6:51 AM, xulang wrote:
>> From: Lang Xu <xulang@uniontech.com>
>>
>>> Please create a selftest for this.
>>
>> Going to do that. To stably reproduce this bug, I need the KASAN
>> config enabled, how do I ensure it's enabled during a selftest cycle,
>> by adding the line below to the 'config'? not quite sure.
>>
>> --- a/tools/testing/selftests/bpf/config
>> +++ b/tools/testing/selftests/bpf/config
>> @@ -46,6 +46,7 @@ CONFIG_IPV6_GRE=y
>>   CONFIG_IPV6_SEG6_BPF=y
>>   CONFIG_IPV6_SIT=y
>>   CONFIG_IPV6_TUNNEL=y
>> +CONFIG_KASAN=y
> 
> I would leave out this config change from this fix for now. cc: Ihor to consider enabling it for bpf-next.
> 
> It is still useful to have a selftest for this case. I always have KASAN turned on when running selftests.

Hi Martin. BPF CI has been running with KASAN since July 2025.
We only disabled it on s390x due to frequent OOMs, x86_64 and 
aarch64 are covered.

For BPF CI it's not important whether CONFIG_KASAN=y is enabled
in tools/testing/selftests/bpf/config, as long as it's not =n

> 
> 
>>> [...]


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH bpf 0/2] bpf: Fix and test cgroup storage OOB issue
  2026-03-16 20:50     ` Martin KaFai Lau
  2026-03-16 21:22       ` Ihor Solodrai
@ 2026-03-17 10:02       ` xulang
       [not found]       ` <20260317100227.2157104-1-xulang@uniontech.com>
  2 siblings, 0 replies; 14+ messages in thread
From: xulang @ 2026-03-17 10:02 UTC (permalink / raw)
  To: martin.lau
  Cc: andrii, ast, bpf, daniel, dzm91, eddyz87, haoluo, ihor.solodrai,
	john.fastabend, jolsa, kaiyanm, kernel, kpsingh, linux-kernel,
	paul.chaignon, sdf, song, xulang, yonghong.song

This series fixes an out-of-bounds read in BPF cgroup storage when the
value_size is not 8-byte aligned. The fix ensures proper alignment during
buffer allocation, and a test case is added to prevent regression.

Lang Xu (2):
  bpf: Fix OOB in bpf_obj_memcpy for cgroup storage
  selftests/bpf: Add test for cgroup storage OOB read

 kernel/bpf/local_storage.c                    |  7 ++-
 .../selftests/bpf/prog_tests/cgroup_storage.c | 42 ++++++++++++++++++
 .../selftests/bpf/progs/cgroup_storage.c      | 43 +++++++++++++++++++
 3 files changed, 88 insertions(+), 4 deletions(-)

-- 
2.51.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH bpf 1/2] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage
       [not found]       ` <20260317100227.2157104-1-xulang@uniontech.com>
@ 2026-03-17 10:02         ` xulang
  2026-03-25  1:36           ` Martin KaFai Lau
  2026-03-17 10:02         ` [PATCH bpf 2/2] selftests/bpf: Add test for cgroup storage OOB read xulang
  1 sibling, 1 reply; 14+ messages in thread
From: xulang @ 2026-03-17 10:02 UTC (permalink / raw)
  To: martin.lau
  Cc: andrii, ast, bpf, daniel, dzm91, eddyz87, haoluo, ihor.solodrai,
	john.fastabend, jolsa, kaiyanm, kernel, kpsingh, linux-kernel,
	paul.chaignon, sdf, song, xulang, yonghong.song

From: Lang Xu <xulang@uniontech.com>

An out-of-bounds read occurs when copying element from a
BPF_MAP_TYPE_CGROUP_STORAGE map to another map type with the same
value_size that is not 8-byte aligned.

The issue happens when:
1. A CGROUP_STORAGE map is created with value_size not aligned to
   8 bytes (e.g., 4 bytes)
2. A HASH map is created with the same value_size (e.g., 4 bytes)
3. Update element in 2 with data in 1

In the kernel, map elements are typically aligned to 8 bytes. However,
bpf_cgroup_storage_calculate_size() allocates storage based on the exact
value_size without alignment. When copy_map_value_long() is called, it
assumes all map values are 8-byte aligned and rounds up the copy size,
leading to a 4-byte out-of-bounds read from the cgroup storage buffer.

This patch fixes the issue by ensuring cgroup storage allocates 8-byte
aligned buffers, matching the assumptions in copy_map_value_long().

Fixes: b741f1630346 ("bpf: introduce per-cpu cgroup local storage")
Reported-by: Kaiyan Mei <kaiyanm@hust.edu.cn>
Closes: https://lore.kernel.org/all/14e6c70c.6c121.19c0399d948.Coremail.kaiyanm@hust.edu.cn/
Signed-off-by: Lang Xu <xulang@uniontech.com>
---
 kernel/bpf/local_storage.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/kernel/bpf/local_storage.c b/kernel/bpf/local_storage.c
index 8fca0c64f7b1..54b32ba19194 100644
--- a/kernel/bpf/local_storage.c
+++ b/kernel/bpf/local_storage.c
@@ -487,14 +487,13 @@ static size_t bpf_cgroup_storage_calculate_size(struct bpf_map *map, u32 *pages)
 {
 	size_t size;
 
+	size = round_up(map->value_size, 8);
 	if (cgroup_storage_type(map) == BPF_CGROUP_STORAGE_SHARED) {
-		size = sizeof(struct bpf_storage_buffer) + map->value_size;
+		size += sizeof(struct bpf_storage_buffer);
 		*pages = round_up(sizeof(struct bpf_cgroup_storage) + size,
 				  PAGE_SIZE) >> PAGE_SHIFT;
 	} else {
-		size = map->value_size;
-		*pages = round_up(round_up(size, 8) * num_possible_cpus(),
-				  PAGE_SIZE) >> PAGE_SHIFT;
+		*pages = round_up(size * num_possible_cpus(), PAGE_SIZE) >> PAGE_SHIFT;
 	}
 
 	return size;
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH bpf 2/2] selftests/bpf: Add test for cgroup storage OOB read
       [not found]       ` <20260317100227.2157104-1-xulang@uniontech.com>
  2026-03-17 10:02         ` [PATCH bpf 1/2] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage xulang
@ 2026-03-17 10:02         ` xulang
  1 sibling, 0 replies; 14+ messages in thread
From: xulang @ 2026-03-17 10:02 UTC (permalink / raw)
  To: martin.lau
  Cc: andrii, ast, bpf, daniel, dzm91, eddyz87, haoluo, ihor.solodrai,
	john.fastabend, jolsa, kaiyanm, kernel, kpsingh, linux-kernel,
	paul.chaignon, sdf, song, xulang, yonghong.song

From: Lang Xu <xulang@uniontech.com>

Add a test case to reproduce the out-of-bounds read issue when copying
from cgroup storage maps with unaligned value_size.

The test creates:
1. A CGROUP_STORAGE map with 4-byte value (not 8-byte aligned)
2. A LRU_PERCPU_HASH map with 4-byte value (same size)

When a socket is created in the cgroup, the BPF program triggers
bpf_map_update_elem() which calls copy_map_value_long(). This function
rounds up the copy size to 8 bytes, but the cgroup storage buffer is
only 4 bytes, causing an OOB read (before the fix).

Link: https://lore.kernel.org/all/204030CBF30066BE+20260312052525.1254217-1-xulang@uniontech.com/
Signed-off-by: Lang Xu <xulang@uniontech.com>
---
 .../selftests/bpf/prog_tests/cgroup_storage.c | 42 ++++++++++++++++++
 .../selftests/bpf/progs/cgroup_storage.c      | 43 +++++++++++++++++++
 2 files changed, 85 insertions(+)

diff --git a/tools/testing/selftests/bpf/prog_tests/cgroup_storage.c b/tools/testing/selftests/bpf/prog_tests/cgroup_storage.c
index cf395715ced4..5b56dc893e73 100644
--- a/tools/testing/selftests/bpf/prog_tests/cgroup_storage.c
+++ b/tools/testing/selftests/bpf/prog_tests/cgroup_storage.c
@@ -1,5 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 
+#include <unistd.h>
+#include <sys/socket.h>
 #include <test_progs.h>
 #include "cgroup_helpers.h"
 #include "network_helpers.h"
@@ -94,3 +96,43 @@ void test_cgroup_storage(void)
 	close(cgroup_fd);
 	cleanup_cgroup_environment();
 }
+
+void test_cgroup_storage_oob(void)
+{
+	struct cgroup_storage *skel;
+	int cgroup_fd, sock_fd;
+
+	cgroup_fd = cgroup_setup_and_join(TEST_CGROUP);
+	if (!ASSERT_OK_FD(cgroup_fd, "create cgroup"))
+		return;
+
+	/* Load and attach BPF program */
+	skel = cgroup_storage__open_and_load();
+	if (!ASSERT_OK_PTR(skel, "cgroup_storage__open_and_load"))
+		goto cleanup_cgroup;
+
+	skel->links.trigger_oob = bpf_program__attach_cgroup(skel->progs.trigger_oob,
+							      cgroup_fd);
+	if (!ASSERT_OK_PTR(skel->links.trigger_oob, "attach_cgroup"))
+		goto cleanup_skel;
+
+	/* Create a socket to trigger cgroup/sock_create hook.
+	 * This will execute our BPF program and trigger the OOB read
+	 * if the bug is present (before the fix).
+	 */
+	sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (!ASSERT_OK_FD(sock_fd, "create socket"))
+		goto cleanup_skel;
+
+	close(sock_fd);
+
+	/* If we reach here without a kernel panic or KASAN report,
+	 * the test passes (the fix is working).
+	 */
+
+cleanup_skel:
+	cgroup_storage__destroy(skel);
+cleanup_cgroup:
+	close(cgroup_fd);
+	cleanup_cgroup_environment();
+}
diff --git a/tools/testing/selftests/bpf/progs/cgroup_storage.c b/tools/testing/selftests/bpf/progs/cgroup_storage.c
index db1e4d2d3281..59da1d95e5b9 100644
--- a/tools/testing/selftests/bpf/progs/cgroup_storage.c
+++ b/tools/testing/selftests/bpf/progs/cgroup_storage.c
@@ -21,4 +21,47 @@ int bpf_prog(struct __sk_buff *skb)
 	return (*counter & 1);
 }
 
+/* Maps for OOB test */
+struct {
+	__uint(type, BPF_MAP_TYPE_CGROUP_STORAGE);
+	__type(key, struct bpf_cgroup_storage_key);
+	__type(value, __u32);  /* 4-byte value - not 8-byte aligned */
+} cgroup_storage_oob SEC(".maps");
+
+struct {
+	__uint(type, BPF_MAP_TYPE_LRU_PERCPU_HASH);
+	__uint(max_entries, 1);
+	__type(key, __u32);
+	__type(value, __u32);  /* 4-byte value - same as cgroup storage */
+} lru_map SEC(".maps");
+
+SEC("cgroup/sock_create")
+int trigger_oob(struct bpf_sock *sk)
+{
+	__u32 key = 0;
+	__u32 *cgroup_val;
+	__u32 value = 0x12345678;
+
+	/* Get cgroup storage value */
+	cgroup_val = bpf_get_local_storage(&cgroup_storage_oob, 0);
+	if (!cgroup_val)
+		return 0;
+
+	/* Initialize cgroup storage */
+	*cgroup_val = value;
+
+	/* This triggers the OOB read:
+	 * bpf_map_update_elem() -> htab_map_update_elem() ->
+	 * pcpu_init_value() -> copy_map_value_long() ->
+	 * bpf_obj_memcpy(..., long_memcpy=true) ->
+	 * bpf_long_memcpy(dst, src, round_up(4, 8))
+	 *
+	 * The copy size is rounded up to 8 bytes, but cgroup_val
+	 * points to a 4-byte buffer, causing a 4-byte OOB read.
+	 */
+	bpf_map_update_elem(&lru_map, &key, cgroup_val, BPF_ANY);
+
+	return 1;
+}
+
 char _license[] SEC("license") = "GPL";
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH bpf 1/2] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage
  2026-03-17 10:02         ` [PATCH bpf 1/2] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage xulang
@ 2026-03-25  1:36           ` Martin KaFai Lau
  0 siblings, 0 replies; 14+ messages in thread
From: Martin KaFai Lau @ 2026-03-25  1:36 UTC (permalink / raw)
  To: xulang
  Cc: andrii, ast, bpf, daniel, dzm91, eddyz87, haoluo, ihor.solodrai,
	john.fastabend, jolsa, kaiyanm, kernel, kpsingh, linux-kernel,
	paul.chaignon, sdf, song, yonghong.song

On 3/17/26 3:02 AM, xulang wrote:
> From: Lang Xu <xulang@uniontech.com>
> 
> An out-of-bounds read occurs when copying element from a
> BPF_MAP_TYPE_CGROUP_STORAGE map to another map type with the same
> value_size that is not 8-byte aligned.
> 
> The issue happens when:
> 1. A CGROUP_STORAGE map is created with value_size not aligned to
>     8 bytes (e.g., 4 bytes)
> 2. A HASH map is created with the same value_size (e.g., 4 bytes)
> 3. Update element in 2 with data in 1
> 
> In the kernel, map elements are typically aligned to 8 bytes. However,
> bpf_cgroup_storage_calculate_size() allocates storage based on the exact
> value_size without alignment. When copy_map_value_long() is called, it
> assumes all map values are 8-byte aligned and rounds up the copy size,
> leading to a 4-byte out-of-bounds read from the cgroup storage buffer.
> 
> This patch fixes the issue by ensuring cgroup storage allocates 8-byte
> aligned buffers, matching the assumptions in copy_map_value_long().

Comments from v1 are not addressed. Please address or disagree with them 
before reposting.

The cover letter did not reach the bpf list and patchwork — something is 
wrong with the reply-to. In general, avoid reply-to for multiple 
patches. This makes the thread unmanageable. The revision number is also 
missing in the subject.

Please read submitting-patches.rst before posting again, in particular 
"The canonical patch format" and "In-Reply-To" sections. Test it with 
your inbox first.

pw-bot: cr


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2026-03-25  1:37 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-12  5:25 [PATCH bpf v1] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage xulang
2026-03-12 11:51 ` Paul Chaignon
2026-03-12 16:41   ` Yonghong Song
2026-03-12 18:02     ` Paul Chaignon
2026-03-12 19:58       ` Yonghong Song
2026-03-12 16:46 ` Yonghong Song
2026-03-13 20:34 ` Martin KaFai Lau
2026-03-16 13:51   ` xulang
2026-03-16 20:50     ` Martin KaFai Lau
2026-03-16 21:22       ` Ihor Solodrai
2026-03-17 10:02       ` [PATCH bpf 0/2] bpf: Fix and test cgroup storage OOB issue xulang
     [not found]       ` <20260317100227.2157104-1-xulang@uniontech.com>
2026-03-17 10:02         ` [PATCH bpf 1/2] bpf: Fix OOB in bpf_obj_memcpy for cgroup storage xulang
2026-03-25  1:36           ` Martin KaFai Lau
2026-03-17 10:02         ` [PATCH bpf 2/2] selftests/bpf: Add test for cgroup storage OOB read xulang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox