Bug 1181877

Summary: GCC 11: multipath-tools package fails
Product: [openSUSE] openSUSE Tumbleweed Reporter: Martin Liška <martin.liska>
Component: BasesystemAssignee: Martin Wilck <martin.wilck>
Status: RESOLVED FIXED QA Contact: E-mail List <qa-bugs>
Severity: Normal    
Priority: P5 - None CC: martin.liska
Version: Current   
Target Milestone: ---   
Hardware: Other   
OS: Other   
Whiteboard:
Found By: --- Services Priority:
Business Priority: Blocker: ---
Marketing QA Status: --- IT Deployment: ---
Bug Depends on:    
Bug Blocks: 1181859    

Description Martin Liška 2021-02-06 11:18:14 UTC
Fails here:
https://build.opensuse.org/package/live_build_log/openSUSE:Factory:Staging:Gcc7/multipath-tools/standard/x86_64

with:
[   43s] cc --std=gnu99  -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -Werror=return-type  -g -Werror -Wall -Wextra -Wformat=2 -Werror=implicit-int -Werror=implicit-function-declaration -Werror=format-security -Wno-clobbered -Wno-error=clobbered -Werror=cast-qual -Werror=discarded-qualifiers -pipe -DBIN_DIR=\"/sbin\" -DLIB_STRING=\"lib64\" -DRUN_DIR=\"run\" -MMD -MP -fPIE -DPIE -I../libmultipath -I../libmpathcmd -Wno-unused-parameter   -c -o test-lib.o test-lib.c
[   43s] make[1]: Leaving directory '/home/abuild/rpmbuild/BUILD/multipath-tools-0.8.5+12+suse.3b0e9ca/tests'
[   43s] make[1]: Entering directory '/home/abuild/rpmbuild/BUILD/multipath-tools-0.8.5+12+suse.3b0e9ca/tests'
[   43s] In file included from /usr/include/urcu/urcu-memb.h:35,
[   43s]                  from /usr/include/urcu/urcu.h:39,
[   43s]                  from /usr/include/urcu.h:2,
[   43s]                  from ../libmultipath/config.h:6,
[   43s]                  from ../libmultipath/structs_vec.h:5,
[   43s]                  from dmevents.c:30:
[   43s] ../multipathd/dmevents.c: In function 'dmevent_loop':
[   43s] ../multipathd/dmevents.c:355:17: error: '__sigsetjmp' accessing 200 bytes in a region of size 72 [-Werror=stringop-overflow=]
[   43s]   355 |                 pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock);
[   43s]       |                 ^~~~~~~~~~~~~~~~~~~~
[   43s] ../multipathd/dmevents.c:355:17: note: referencing argument 1 of type 'struct __jmp_buf_tag *'
[   43s] /usr/include/pthread.h:734:12: note: in a call to function '__sigsetjmp'
[   43s]   734 | extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __THROWNL;
[   43s]       |            ^~~~~~~~~~~
[   43s] ../multipathd/dmevents.c: In function 'wait_dmevents':
[   43s] ../multipathd/dmevents.c:390:9: error: '__sigsetjmp' accessing 200 bytes in a region of size 72 [-Werror=stringop-overflow=]
[   43s]   390 |         pthread_cleanup_push(rcu_unregister, NULL);
[   43s]       |         ^~~~~~~~~~~~~~~~~~~~
[   43s] ../multipathd/dmevents.c:390:9: note: referencing argument 1 of type 'struct __jmp_buf_tag *'
[   43s] /usr/include/pthread.h:734:12: note: in a call to function '__sigsetjmp'
[   43s]   734 | extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __THROWNL;
[   43s]       |            ^~~~~~~~~~~
[   43s] cc1: all warnings being treated as errors
[   43s] make[1]: *** [Makefile:63: dmevents.o] Error 1
[   43s] make[1]: Leaving directory '/home/abuild/rpmbuild/BUILD/multipath-tools-0.8.5+12+suse.3b0e9ca/tests'
[   43s] make[1]: *** Waiting for unfinished jobs....
[   43s] rm test-lib.o.wrap parser.o.wrap dmevents.o.wrap hwtable.o.wrap uevent.o.wrap util.o.wrap
[   43s] make: *** [Makefile:53: test] Error 2
[   43s] error: Bad exit status from /var/tmp/rpm-tmp.ra5XCt (%check)
Comment 1 Martin Wilck 2021-02-10 11:39:27 UTC
The failing program includes <setjmp.h> before <pthread.h>, which leads to the error message. Here is a minimal test program:

#include <setjmp.h>
#include <pthread.h>

void dummy(void *arg)
{}

int main(void)
{
	pthread_cleanup_push(dummy, NULL);
	pthread_cleanup_pop(1);
        return 0;
}

Compiling this with "gcc-11 -Werror=stringop-overflow" causes the same error message:

> fail.c: In function 'main':
> fail.c:9:9: error: '__sigsetjmp' accessing 200 bytes in a region of size 72 > [-Werror=stringop-overflow=]
>     9 |         pthread_cleanup_push(dummy, NULL);
>       |         ^~~~~~~~~~~~~~~~~~~~
> fail.c:9:9: note: referencing argument 1 of type 'struct __jmp_buf_tag *'
> /usr/include/pthread.h:734:12: note: in a call to function '__sigsetjmp'
>   734 | extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __THROWNL;
>       |            ^~~~~~~~~~~

The problem is that __sigsetjmp is defined differently:

/usr/include/setjmp.h uses an array parameter:

> extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) __attribute__ ((__nothrow__));

/usr/include/pthread.h has just a pointer parameter:

> struct __jmp_buf_tag;
> extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __attribute__ ((__nothrow__));

Including "setjmp.h" first will apparently enable range checking by gcc, which leads to the error.

The expansion of pthread_cleanup_push() contains:

__sigsetjmp ((struct __jmp_buf_tag *) (void *) __cancel_buf.__cancel_jmp_buf, 0)

where __cancel_buf.__cancel_jmp_buf is declared as

> typedef struct
> {
>   struct
>   {
>     __jmp_buf __cancel_jmp_buf;
>     int __mask_was_saved;
>   } __cancel_jmp_buf[1];
>   void *__pad[4];
> } __pthread_unwind_buf_t __attribute__ ((__aligned__));

So it has indeed size 72. I have no idea where gcc sees "accessing 200 bytes" though. struct jmp_buf_tag is 84 bytes unless I'm very mistaken:

> typedef long int __jmp_buf[8];
> struct __jmp_buf_tag
>   {
>   __jmp_buf __jmpbuf;      // 64 bytes
>     int __mask_was_saved;  // 4 bytes
>    __sigset_t __saved_mask;  // 1024/64 = 16 bytes
>  };

That's still a mismatch, but I don't see 200 bytes anywhere.

I can work around this by including <pthread.h> before <setjmp.h>. I need <setjmp.h> because of the cmocka test framework.

But this still needs to be passed back to the toolchain team, as both pthread.h and setjmp.h are in your realm.

Please double-check.
Comment 2 Martin Liška 2021-02-10 13:14:20 UTC
Thank you for the investigation, it's:
https://sourceware.org/bugzilla/show_bug.cgi?id=26647

and it's fixed in the latest glibc release 2.33
(right now in :B staging project).
Comment 3 Martin Wilck 2021-02-10 14:44:06 UTC
I've pushed my workaround to Base:System, and created a SR for openSUSE:Factory:Staging:Gcc7 (sr#870922).
Comment 4 OBSbugzilla Bot 2021-03-11 21:30:12 UTC
This is an autogenerated message for OBS integration:
This bug (1181877) was mentioned in
https://build.opensuse.org/request/show/878403 Factory / multipath-tools
Comment 7 OBSbugzilla Bot 2021-03-12 16:20:18 UTC
This is an autogenerated message for OBS integration:
This bug (1181877) was mentioned in
https://build.opensuse.org/request/show/878591 Factory / multipath-tools
Comment 8 OBSbugzilla Bot 2021-03-12 17:40:31 UTC
This is an autogenerated message for OBS integration:
This bug (1181877) was mentioned in
https://build.opensuse.org/request/show/878610 Factory / multipath-tools