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: <20210924183858.GA25901@localhost>
Date:   Fri, 24 Sep 2021 14:38:58 -0400
From:   Mathieu Desnoyers <mathieu.desnoyers@...icios.com>
To:     Peter Zijlstra <peterz@...radead.org>
Cc:     Linus Torvalds <torvalds@...ux-foundation.org>, will@...nel.org,
        paulmck@...nel.org, stern@...land.harvard.edu,
        parri.andrea@...il.com, boqun.feng@...il.com, npiggin@...il.com,
        dhowells@...hat.com, j.alglave@....ac.uk, luc.maranget@...ia.fr,
        akiyks@...il.com, linux-kernel@...r.kernel.org,
        linux-toolchains@...r.kernel.org, linux-arch@...r.kernel.org
Subject: Re: [RFC] LKMM: Add volatile_if()

Hi,

Following the LPC2021 BoF about control dependency, I re-read the kernel
documentation about control dependency, and ended up thinking that what
we have now is utterly fragile.

Considering that the goal here is to prevent the compiler from being able to
optimize a conditional branch into something which lacks the control
dependency, while letting the compiler choose the best conditional
branch in each case, how about the following approach ?

#define ctrl_dep_eval(x)        ({ BUILD_BUG_ON(__builtin_constant_p((_Bool) x)); x; })
#define ctrl_dep_emit_loop(x)   ({ __label__ l_dummy; l_dummy: asm volatile goto ("" : : : "cc", "memory" : l_dummy); (x); })
#define ctrl_dep_if(x)          if ((ctrl_dep_eval(x) && ctrl_dep_emit_loop(1)) || ctrl_dep_emit_loop(0))

The idea is to forbid the compiler from considering the two branches as
identical by adding a dummy loop in each branch with an empty asm goto.
Considering that the compiler should not assume anything about the
contents of the asm goto (it's been designed so the generated assembly
can be modified at runtime), then the compiler can hardly know whether
each branch will trigger an infinite loop or not, which should prevent
unwanted optimisations.

With this approach, the following code now keeps the control dependency:

	z = READ_ONCE(var1);
        ctrl_dep_if (z)
                WRITE_ONCE(var2, 5);
        else
                WRITE_ONCE(var2, 5);

And the ctrl_dep_eval() checking the constant triggers a build error
for:

        y = READ_ONCE(var1);
        ctrl_dep_if (y % 1)
                WRITE_ONCE(var2, 5);
        else
                WRITE_ONCE(var2, 6);

Which is good to have to ensure the compiler don't end up removing the
conditional branch because the resulting evaluation ends up evaluating a
constant.

Thoughts ?

Thanks,

Mathieu

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ