lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <04197578-4FD6-48B7-A132-2A8539E35E56@gmail.com>
Date:   Sat, 22 Jul 2023 23:00:18 +0800
From:   Alan Huang <mmpgouride@...il.com>
To:     David Laight <David.Laight@...LAB.COM>
Cc:     Joel Fernandes <joel@...lfernandes.org>,
        "Paul E. McKenney" <paulmck@...nel.org>,
        Eric Dumazet <edumazet@...gle.com>,
        "roman.gushchin@...ux.dev" <roman.gushchin@...ux.dev>,
        "linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
        "netdev@...r.kernel.org" <netdev@...r.kernel.org>,
        "rcu@...r.kernel.org" <rcu@...r.kernel.org>
Subject: Re: Question about the barrier() in hlist_nulls_for_each_entry_rcu()


> 2023年7月22日 22:06,David Laight <David.Laight@...LAB.COM> 写道:
> 
> ....
>>> Found a related discussion:
>>> 
>>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102714
>>> 
>>> Looks like GCC 10, 11 have been backported, not sure whether GCC 8 has been backported.
>>> 
>>> So, I have the following questions:
>>> 
>>> Given that some people might not update their GCC, do they need to be notified?
>>> 
>>> Do we need to CC Linus?
>> 
>> No need.
>> 
>> I put the following code into a kernel module:
>> 
>> typedef struct list_head_shit {
>> int next;
>> struct list_head *first;
>> } list_head_shit;
>> 
>> static void noinline so_shit(void) {
>> list_head_shit *head = (list_head_shit *)kmalloc(sizeof(list_head_shit), GFP_KERNEL);
>> head->first = 0;
>> head->next = 1;
>> 
>> READ_ONCE(head->first);
>> READ_ONCE(head->first);
>> 
>> kfree(head);
>> }
>> 
>> x86_64-linux-gnu-gcc-11 generate the following code:
>> 
>> 0000000000000000 <so_shit>:
>>   0: 48 8b 3d 00 00 00 00 mov    0x0(%rip),%rdi        # 7 <so_shit+0x7>
>>   7: ba 10 00 00 00        mov    $0x10,%edx
>>   c: be c0 0c 00 00       mov    $0xcc0,%esi
>>  11: e8 00 00 00 00       call   16 <so_shit+0x16>
>>  16: 48 c7 40 08 00 00 00 movq   $0x0,0x8(%rax)
>>  1d: 00
>>  1e: 48 89 c7              mov    %rax,%rdi
>>  21: c7 00 01 00 00 00     movl   $0x1,(%rax)
>>  27: 48 8b 47 08           mov    0x8(%rdi),%rax  # READ_ONCE here
>>  2b: 48 8b 47 08           mov    0x8(%rdi),%rax  # READ_ONCE here
>>  2f: e9 00 00 00 00       jmp    34 <so_shit+0x34>
>>  34: 66 66 2e 0f 1f 84 00 data16 cs nopw 0x0(%rax,%rax,1)
>>  3b: 00 00 00 00
>>  3f: 90                    nop
>> 
>> The conclusion is that we can rely on READ_ONCE when writing kernel code.
>> 
>> The kernel’s READ_ONCE is different with the one Joel wrote yesterday. (Joel’s is the same as the old
>> ACCESS_ONCE)
> 
> You do need to reproduce the error with code that looks like
> the loop in the (old) udp.c code.
> 
> Then see if changing the implementation of READ_ONCE() from
> a simple 'volatile' access the newer variant makes a difference.
> 
> You also need to check with the oldest version of gcc that is
> still supported - that is much older than gcc 11.
> 
> In the udp code the volatile access was on a pointer (which should
> qualify as a scaler type) so it may well be the inlining bug you
> mentioned earlier, not the 'volatile on non-scaler' feature that
> READ_ONCE() fixed.
> That fix hasn't been back-ported to all the versions of gcc
> that the kernel build supports.

Well, the same compiler, the kernel’s READ_ONCE:

static int noinline foo(int a, int b, int c) {
	b = a + 1;
	c = READ_ONCE(b) + 1;
	a = c + 1;
	return a;
}

0000000000000040 <foo.constprop.0>:
  40:	b8 04 00 00 00       	mov    $0x4,%eax
  45:	c3                   		ret

Example from:

	https://stackoverflow.com/questions/70380510/non-conforming-optimizations-of-volatile-in-gcc-11-1

Change the code to:

static int noinline foo(int a, volatile int b, int c) {
	b = a + 1;
	c = b + 1;
	a = c + 1;
	return a;
}

Doesn’t help.

BTW, Clang works fine, even the function is inlined.

> 
> David
> 
> -
> Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
> Registration No: 1397386 (Wales)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ