diff mbox series

[bpf-next,v2] libbpf: handle producer position overflow

Message ID 20230724132543.1282645-1-awerner32@gmail.com (mailing list archive)
State New, archived
Delegated to: BPF
Headers show
Series [bpf-next,v2] libbpf: handle producer position overflow | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for bpf-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 9 this patch: 9
netdev/cc_maintainers fail 11 maintainers not CCed: daniel@iogearbox.net yhs@fb.com kpsingh@kernel.org martin.lau@linux.dev john.fastabend@gmail.com song@kernel.org sdf@google.com andrii@kernel.org jolsa@kernel.org haoluo@google.com ast@kernel.org
netdev/build_clang success Errors and warnings before: 9 this patch: 9
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 9 this patch: 9
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 23 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-PR success PR summary
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-4 success Logs for build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-5 success Logs for build for x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-6 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-2 success Logs for build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-3 success Logs for build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-7 success Logs for test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-15 success Logs for test_progs_no_alu32 on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-19 success Logs for test_progs_no_alu32_parallel on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-22 success Logs for test_progs_parallel on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-25 success Logs for test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-9 success Logs for test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-10 success Logs for test_maps on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-11 success Logs for test_progs on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-13 success Logs for test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-14 success Logs for test_progs on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-17 success Logs for test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-18 success Logs for test_progs_no_alu32 on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-20 success Logs for test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-21 success Logs for test_progs_no_alu32_parallel on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-23 success Logs for test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-24 success Logs for test_progs_parallel on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-27 success Logs for test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-28 success Logs for test_verifier on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-29 success Logs for veristat
bpf/vmtest-bpf-next-VM_Test-26 success Logs for test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-12 success Logs for test_progs on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-16 success Logs for test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-8 success Logs for test_maps on s390x with gcc

Commit Message

Andrew Werner July 24, 2023, 1:25 p.m. UTC
Before this patch, the producer position could overflow `unsigned
long`, in which case libbpf would forever stop processing new writes to
the ringbuf. This patch addresses that bug by avoiding ordered
comparison between the consumer and producer position. If the consumer
position is greater than the producer position, the assumption is that
the producer has overflowed.

A more defensive check could be to ensure that the delta is within
the allowed range, but such defensive checks are neither present in
the kernel side code nor in libbpf. The overflow that this patch
handles can occur while the producer and consumer follow a correct
protocol.

A selftest was written to demonstrate the bug, and indeed this patch
allows the test to continue to make progress past the overflow.
However, the author was unable to create a testing environment on a
32-bit machine, and the test requires substantial memory and over 4
hours to hit the overflow point on a 64-bit machine. Thus, the test
is not included in this patch because of the impracticality of running
it.

Additionally, this patch adds commentary around a separate point to note
that the modular arithmetic is valid in the face of overflows, as that
fact may not be obvious to future readers.

v1->v2:
 - Fixed comment grammar.
 - Properly formatted subject line.

Reference:
[v1]: https://lore.kernel.org/bpf/20230724132404.1280848-1-awerner32@gmail.com/T/#u

Signed-off-by: Andrew Werner <awerner32@gmail.com>
---
 tools/lib/bpf/ringbuf.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

Comments

Hou Tao July 27, 2023, 2:14 a.m. UTC | #1
On 7/24/2023 9:25 PM, Andrew Werner wrote:
> Before this patch, the producer position could overflow `unsigned
> long`, in which case libbpf would forever stop processing new writes to
> the ringbuf. This patch addresses that bug by avoiding ordered
> comparison between the consumer and producer position. If the consumer
> position is greater than the producer position, the assumption is that
> the producer has overflowed.
>
> A more defensive check could be to ensure that the delta is within
> the allowed range, but such defensive checks are neither present in
> the kernel side code nor in libbpf. The overflow that this patch
> handles can occur while the producer and consumer follow a correct
> protocol.
>
> A selftest was written to demonstrate the bug, and indeed this patch
> allows the test to continue to make progress past the overflow.
> However, the author was unable to create a testing environment on a
> 32-bit machine, and the test requires substantial memory and over 4
> hours to hit the overflow point on a 64-bit machine. Thus, the test
> is not included in this patch because of the impracticality of running
> it.
>
> Additionally, this patch adds commentary around a separate point to note
> that the modular arithmetic is valid in the face of overflows, as that
> fact may not be obvious to future readers.
>
> v1->v2:
>  - Fixed comment grammar.
>  - Properly formatted subject line.
>
> Reference:
> [v1]: https://lore.kernel.org/bpf/20230724132404.1280848-1-awerner32@gmail.com/T/#u
>
> Signed-off-by: Andrew Werner <awerner32@gmail.com>

Acked-by: Hou Tao <houtao1@huawei.com>
Jiri Olsa July 27, 2023, 8:33 a.m. UTC | #2
On Mon, Jul 24, 2023 at 09:25:45AM -0400, Andrew Werner wrote:
> Before this patch, the producer position could overflow `unsigned
> long`, in which case libbpf would forever stop processing new writes to
> the ringbuf. This patch addresses that bug by avoiding ordered
> comparison between the consumer and producer position. If the consumer
> position is greater than the producer position, the assumption is that
> the producer has overflowed.
> 
> A more defensive check could be to ensure that the delta is within
> the allowed range, but such defensive checks are neither present in
> the kernel side code nor in libbpf. The overflow that this patch
> handles can occur while the producer and consumer follow a correct
> protocol.
> 
> A selftest was written to demonstrate the bug, and indeed this patch
> allows the test to continue to make progress past the overflow.
> However, the author was unable to create a testing environment on a
> 32-bit machine, and the test requires substantial memory and over 4
> hours to hit the overflow point on a 64-bit machine. Thus, the test
> is not included in this patch because of the impracticality of running
> it.
> 
> Additionally, this patch adds commentary around a separate point to note
> that the modular arithmetic is valid in the face of overflows, as that
> fact may not be obvious to future readers.
> 
> v1->v2:
>  - Fixed comment grammar.
>  - Properly formatted subject line.
> 
> Reference:
> [v1]: https://lore.kernel.org/bpf/20230724132404.1280848-1-awerner32@gmail.com/T/#u
> 
> Signed-off-by: Andrew Werner <awerner32@gmail.com>
> ---
>  tools/lib/bpf/ringbuf.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/lib/bpf/ringbuf.c b/tools/lib/bpf/ringbuf.c
> index 02199364db13..2055f3099843 100644
> --- a/tools/lib/bpf/ringbuf.c
> +++ b/tools/lib/bpf/ringbuf.c
> @@ -237,7 +237,11 @@ static int64_t ringbuf_process_ring(struct ring *r)
>  	do {
>  		got_new_data = false;
>  		prod_pos = smp_load_acquire(r->producer_pos);
> -		while (cons_pos < prod_pos) {
> +
> +		/* Avoid signed comparisons between the positions; the producer
> +		 * position can overflow before the consumer position.
> +		 */
> +		while (cons_pos != prod_pos) {
>  			len_ptr = r->data + (cons_pos & r->mask);
>  			len = smp_load_acquire(len_ptr);
>  
> @@ -498,6 +502,11 @@ void *user_ring_buffer__reserve(struct user_ring_buffer *rb, __u32 size)
>  	prod_pos = smp_load_acquire(rb->producer_pos);
>  
>  	max_size = rb->mask + 1;
> +
> +	/* Note that this formulation is valid in the face of overflow of
> +	 * prod_pos so long as the delta between prod_pos and cons_pos is
> +	 * no greater than max_size.
> +	 */
>  	avail_size = max_size - (prod_pos - cons_pos);

hi,
the above hunk handles the case for 'prod_pos < cons_pos',

but it looks like we assume 'cons_pos < prod_pos' in above calculation,
should we check on that?

jirka


>  	/* Round up total size to a multiple of 8. */
>  	total_size = (size + BPF_RINGBUF_HDR_SZ + 7) / 8 * 8;
> -- 
> 2.39.2
> 
>
Andrew Werner July 27, 2023, 2:45 p.m. UTC | #3
On Thu, Jul 27, 2023 at 4:33 AM Jiri Olsa <olsajiri@gmail.com> wrote:
>
> On Mon, Jul 24, 2023 at 09:25:45AM -0400, Andrew Werner wrote:
> > Before this patch, the producer position could overflow `unsigned
> > long`, in which case libbpf would forever stop processing new writes to
> > the ringbuf. This patch addresses that bug by avoiding ordered
> > comparison between the consumer and producer position. If the consumer
> > position is greater than the producer position, the assumption is that
> > the producer has overflowed.
> >
> > A more defensive check could be to ensure that the delta is within
> > the allowed range, but such defensive checks are neither present in
> > the kernel side code nor in libbpf. The overflow that this patch
> > handles can occur while the producer and consumer follow a correct
> > protocol.
> >
> > A selftest was written to demonstrate the bug, and indeed this patch
> > allows the test to continue to make progress past the overflow.
> > However, the author was unable to create a testing environment on a
> > 32-bit machine, and the test requires substantial memory and over 4
> > hours to hit the overflow point on a 64-bit machine. Thus, the test
> > is not included in this patch because of the impracticality of running
> > it.
> >
> > Additionally, this patch adds commentary around a separate point to note
> > that the modular arithmetic is valid in the face of overflows, as that
> > fact may not be obvious to future readers.
> >
> > v1->v2:
> >  - Fixed comment grammar.
> >  - Properly formatted subject line.
> >
> > Reference:
> > [v1]: https://lore.kernel.org/bpf/20230724132404.1280848-1-awerner32@gmail.com/T/#u
> >
> > Signed-off-by: Andrew Werner <awerner32@gmail.com>
> > ---
> >  tools/lib/bpf/ringbuf.c | 11 ++++++++++-
> >  1 file changed, 10 insertions(+), 1 deletion(-)
> >
> > diff --git a/tools/lib/bpf/ringbuf.c b/tools/lib/bpf/ringbuf.c
> > index 02199364db13..2055f3099843 100644
> > --- a/tools/lib/bpf/ringbuf.c
> > +++ b/tools/lib/bpf/ringbuf.c
> > @@ -237,7 +237,11 @@ static int64_t ringbuf_process_ring(struct ring *r)
> >       do {
> >               got_new_data = false;
> >               prod_pos = smp_load_acquire(r->producer_pos);
> > -             while (cons_pos < prod_pos) {
> > +
> > +             /* Avoid signed comparisons between the positions; the producer
> > +              * position can overflow before the consumer position.
> > +              */
> > +             while (cons_pos != prod_pos) {
> >                       len_ptr = r->data + (cons_pos & r->mask);
> >                       len = smp_load_acquire(len_ptr);
> >
> > @@ -498,6 +502,11 @@ void *user_ring_buffer__reserve(struct user_ring_buffer *rb, __u32 size)
> >       prod_pos = smp_load_acquire(rb->producer_pos);
> >
> >       max_size = rb->mask + 1;
> > +
> > +     /* Note that this formulation is valid in the face of overflow of
> > +      * prod_pos so long as the delta between prod_pos and cons_pos is
> > +      * no greater than max_size.
> > +      */
> >       avail_size = max_size - (prod_pos - cons_pos);
>
> hi,
> the above hunk handles the case for 'prod_pos < cons_pos',
>
> but it looks like we assume 'cons_pos < prod_pos' in above calculation,
> should we check on that?
>
> jirka

The code there does work (perhaps surprisingly) even if the cons_pos is
less than the prod_pos, so long as that delta is no greater than max_size.
I added the commentary there because I too found it to be unintuitive.

Consider the following program. It will print "delta: 20".

```c
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

int main() {
    unsigned long cons_pos = ULONG_MAX - 9;
    unsigned long prod_pos = 10;
    printf("delta: %lu\n", prod_pos - cons_pos);
    return 0;
}
```

-Andrew

>
>
> >       /* Round up total size to a multiple of 8. */
> >       total_size = (size + BPF_RINGBUF_HDR_SZ + 7) / 8 * 8;
> > --
> > 2.39.2
> >
> >
Alexei Starovoitov Aug. 3, 2023, 3:41 a.m. UTC | #4
On Thu, Jul 27, 2023 at 7:48 AM Andrew Werner <andrew@dataexmachina.dev> wrote:
>
> On Thu, Jul 27, 2023 at 4:33 AM Jiri Olsa <olsajiri@gmail.com> wrote:
> >
> > On Mon, Jul 24, 2023 at 09:25:45AM -0400, Andrew Werner wrote:
> > > Before this patch, the producer position could overflow `unsigned
> > > long`, in which case libbpf would forever stop processing new writes to
> > > the ringbuf. This patch addresses that bug by avoiding ordered
> > > comparison between the consumer and producer position. If the consumer
> > > position is greater than the producer position, the assumption is that
> > > the producer has overflowed.
> > >
> > > A more defensive check could be to ensure that the delta is within
> > > the allowed range, but such defensive checks are neither present in
> > > the kernel side code nor in libbpf. The overflow that this patch
> > > handles can occur while the producer and consumer follow a correct
> > > protocol.
> > >
> > > A selftest was written to demonstrate the bug, and indeed this patch
> > > allows the test to continue to make progress past the overflow.
> > > However, the author was unable to create a testing environment on a
> > > 32-bit machine, and the test requires substantial memory and over 4
> > > hours to hit the overflow point on a 64-bit machine. Thus, the test
> > > is not included in this patch because of the impracticality of running
> > > it.

Are you saying on a 64-bit host you were able to overflow 64-bit integer
in 4 hours?
Interesting.
Please share the test anyway. As a patch or github link. Anything works.

> > >
> > > Additionally, this patch adds commentary around a separate point to note
> > > that the modular arithmetic is valid in the face of overflows, as that
> > > fact may not be obvious to future readers.
> > >
> > > v1->v2:
> > >  - Fixed comment grammar.
> > >  - Properly formatted subject line.
> > >
> > > Reference:
> > > [v1]: https://lore.kernel.org/bpf/20230724132404.1280848-1-awerner32@gmail.com/T/#u
> > >
> > > Signed-off-by: Andrew Werner <awerner32@gmail.com>
> > > ---
> > >  tools/lib/bpf/ringbuf.c | 11 ++++++++++-
> > >  1 file changed, 10 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/tools/lib/bpf/ringbuf.c b/tools/lib/bpf/ringbuf.c
> > > index 02199364db13..2055f3099843 100644
> > > --- a/tools/lib/bpf/ringbuf.c
> > > +++ b/tools/lib/bpf/ringbuf.c
> > > @@ -237,7 +237,11 @@ static int64_t ringbuf_process_ring(struct ring *r)
> > >       do {
> > >               got_new_data = false;
> > >               prod_pos = smp_load_acquire(r->producer_pos);
> > > -             while (cons_pos < prod_pos) {
> > > +
> > > +             /* Avoid signed comparisons between the positions; the producer
> > > +              * position can overflow before the consumer position.
> > > +              */
> > > +             while (cons_pos != prod_pos) {
> > >                       len_ptr = r->data + (cons_pos & r->mask);
> > >                       len = smp_load_acquire(len_ptr);
> > >
> > > @@ -498,6 +502,11 @@ void *user_ring_buffer__reserve(struct user_ring_buffer *rb, __u32 size)
> > >       prod_pos = smp_load_acquire(rb->producer_pos);
> > >
> > >       max_size = rb->mask + 1;
> > > +
> > > +     /* Note that this formulation is valid in the face of overflow of
> > > +      * prod_pos so long as the delta between prod_pos and cons_pos is
> > > +      * no greater than max_size.
> > > +      */
> > >       avail_size = max_size - (prod_pos - cons_pos);
> >
> > hi,
> > the above hunk handles the case for 'prod_pos < cons_pos',
> >
> > but it looks like we assume 'cons_pos < prod_pos' in above calculation,
> > should we check on that?
> >
> > jirka
>
> The code there does work (perhaps surprisingly) even if the cons_pos is
> less than the prod_pos, so long as that delta is no greater than max_size.
> I added the commentary there because I too found it to be unintuitive.
>
> Consider the following program. It will print "delta: 20".
>
> ```c
> #include <stdio.h>
> #include <stdlib.h>
> #include <limits.h>
>
> int main() {
>     unsigned long cons_pos = ULONG_MAX - 9;
>     unsigned long prod_pos = 10;
>     printf("delta: %lu\n", prod_pos - cons_pos);
>     return 0;
> }
> ```
>
> -Andrew
>
> >
> >
> > >       /* Round up total size to a multiple of 8. */
> > >       total_size = (size + BPF_RINGBUF_HDR_SZ + 7) / 8 * 8;
> > > --
> > > 2.39.2
> > >
> > >
>
Andrew Werner Aug. 3, 2023, 1:58 p.m. UTC | #5
On Wed, Aug 2, 2023 at 11:41 PM Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> On Thu, Jul 27, 2023 at 7:48 AM Andrew Werner <andrew@dataexmachina.dev> wrote:
> >
> > On Thu, Jul 27, 2023 at 4:33 AM Jiri Olsa <olsajiri@gmail.com> wrote:
> > >
> > > On Mon, Jul 24, 2023 at 09:25:45AM -0400, Andrew Werner wrote:
> > > > Before this patch, the producer position could overflow `unsigned
> > > > long`, in which case libbpf would forever stop processing new writes to
> > > > the ringbuf. This patch addresses that bug by avoiding ordered
> > > > comparison between the consumer and producer position. If the consumer
> > > > position is greater than the producer position, the assumption is that
> > > > the producer has overflowed.
> > > >
> > > > A more defensive check could be to ensure that the delta is within
> > > > the allowed range, but such defensive checks are neither present in
> > > > the kernel side code nor in libbpf. The overflow that this patch
> > > > handles can occur while the producer and consumer follow a correct
> > > > protocol.
> > > >
> > > > A selftest was written to demonstrate the bug, and indeed this patch
> > > > allows the test to continue to make progress past the overflow.
> > > > However, the author was unable to create a testing environment on a
> > > > 32-bit machine, and the test requires substantial memory and over 4
> > > > hours to hit the overflow point on a 64-bit machine. Thus, the test
> > > > is not included in this patch because of the impracticality of running
> > > > it.
>
> Are you saying on a 64-bit host you were able to overflow 64-bit integer
> in 4 hours?
> Interesting.
> Please share the test anyway. As a patch or github link. Anything works.

Here's a link to the test: https://github.com/ajwerner/bpf/commit/85e1240e7713

>
> > > >
> > > > Additionally, this patch adds commentary around a separate point to note
> > > > that the modular arithmetic is valid in the face of overflows, as that
> > > > fact may not be obvious to future readers.
> > > >
> > > > v1->v2:
> > > >  - Fixed comment grammar.
> > > >  - Properly formatted subject line.
> > > >
> > > > Reference:
> > > > [v1]: https://lore.kernel.org/bpf/20230724132404.1280848-1-awerner32@gmail.com/T/#u
> > > >
> > > > Signed-off-by: Andrew Werner <awerner32@gmail.com>
> > > > ---
> > > >  tools/lib/bpf/ringbuf.c | 11 ++++++++++-
> > > >  1 file changed, 10 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/tools/lib/bpf/ringbuf.c b/tools/lib/bpf/ringbuf.c
> > > > index 02199364db13..2055f3099843 100644
> > > > --- a/tools/lib/bpf/ringbuf.c
> > > > +++ b/tools/lib/bpf/ringbuf.c
> > > > @@ -237,7 +237,11 @@ static int64_t ringbuf_process_ring(struct ring *r)
> > > >       do {
> > > >               got_new_data = false;
> > > >               prod_pos = smp_load_acquire(r->producer_pos);
> > > > -             while (cons_pos < prod_pos) {
> > > > +
> > > > +             /* Avoid signed comparisons between the positions; the producer
> > > > +              * position can overflow before the consumer position.
> > > > +              */
> > > > +             while (cons_pos != prod_pos) {
> > > >                       len_ptr = r->data + (cons_pos & r->mask);
> > > >                       len = smp_load_acquire(len_ptr);
> > > >
> > > > @@ -498,6 +502,11 @@ void *user_ring_buffer__reserve(struct user_ring_buffer *rb, __u32 size)
> > > >       prod_pos = smp_load_acquire(rb->producer_pos);
> > > >
> > > >       max_size = rb->mask + 1;
> > > > +
> > > > +     /* Note that this formulation is valid in the face of overflow of
> > > > +      * prod_pos so long as the delta between prod_pos and cons_pos is
> > > > +      * no greater than max_size.
> > > > +      */
> > > >       avail_size = max_size - (prod_pos - cons_pos);
> > >
> > > hi,
> > > the above hunk handles the case for 'prod_pos < cons_pos',
> > >
> > > but it looks like we assume 'cons_pos < prod_pos' in above calculation,
> > > should we check on that?
> > >
> > > jirka
> >
> > The code there does work (perhaps surprisingly) even if the cons_pos is
> > less than the prod_pos, so long as that delta is no greater than max_size.
> > I added the commentary there because I too found it to be unintuitive.
> >
> > Consider the following program. It will print "delta: 20".
> >
> > ```c
> > #include <stdio.h>
> > #include <stdlib.h>
> > #include <limits.h>
> >
> > int main() {
> >     unsigned long cons_pos = ULONG_MAX - 9;
> >     unsigned long prod_pos = 10;
> >     printf("delta: %lu\n", prod_pos - cons_pos);
> >     return 0;
> > }
> > ```
> >
> > -Andrew
> >
> > >
> > >
> > > >       /* Round up total size to a multiple of 8. */
> > > >       total_size = (size + BPF_RINGBUF_HDR_SZ + 7) / 8 * 8;
> > > > --
> > > > 2.39.2
> > > >
> > > >
> >
diff mbox series

Patch

diff --git a/tools/lib/bpf/ringbuf.c b/tools/lib/bpf/ringbuf.c
index 02199364db13..2055f3099843 100644
--- a/tools/lib/bpf/ringbuf.c
+++ b/tools/lib/bpf/ringbuf.c
@@ -237,7 +237,11 @@  static int64_t ringbuf_process_ring(struct ring *r)
 	do {
 		got_new_data = false;
 		prod_pos = smp_load_acquire(r->producer_pos);
-		while (cons_pos < prod_pos) {
+
+		/* Avoid signed comparisons between the positions; the producer
+		 * position can overflow before the consumer position.
+		 */
+		while (cons_pos != prod_pos) {
 			len_ptr = r->data + (cons_pos & r->mask);
 			len = smp_load_acquire(len_ptr);
 
@@ -498,6 +502,11 @@  void *user_ring_buffer__reserve(struct user_ring_buffer *rb, __u32 size)
 	prod_pos = smp_load_acquire(rb->producer_pos);
 
 	max_size = rb->mask + 1;
+
+	/* Note that this formulation is valid in the face of overflow of
+	 * prod_pos so long as the delta between prod_pos and cons_pos is
+	 * no greater than max_size.
+	 */
 	avail_size = max_size - (prod_pos - cons_pos);
 	/* Round up total size to a multiple of 8. */
 	total_size = (size + BPF_RINGBUF_HDR_SZ + 7) / 8 * 8;