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: <96da5aa3-a6ff-aeee-430b-bc9958f5aefa@gmail.com>
Date:   Sun, 15 Nov 2020 22:19:22 +0100
From:   Maximilian Luz <luzmaximilian@...il.com>
To:     Bjorn Helgaas <helgaas@...nel.org>
Cc:     Krzysztof WilczyƄski <kw@...ux.com>,
        Bjorn Helgaas <bhelgaas@...gle.com>,
        Heiner Kallweit <hkallweit1@...il.com>,
        linux-pci@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH] PCI: Add sysfs attribute for PCI device power state

On 11/15/20 9:27 PM, Bjorn Helgaas wrote:

[...]

> I think something read from sysfs is a snapshot with no guarantee
> about how long it will remain valid, so I don't see a problem with the
> value being stale by the time userspace consumes it.

I agree on this, and the READ_ONCE won't protect against it. The
READ_ONCE would only protect against future changes, e.g. something like

     const char *state_names[] = { ... };

     // check if state is invalid
     if (READ(pci_dev->current_state) >= ARRAY_SIZE(state_names))
             return sprintf(..., "invalid");
     else    // look state up in table
             return sprintf(..., state_names[READ(pci_dev->current_state)])

Note that I've explicitly marked the problematic reads here: If those
are done separately, the invalidity check may pass, but by the time the
state name is looked up, the value may have changed and may be invalid.

Note further that if we have something like

     pci_power_t state = pci_dev->current_state;

the compiler is, in theory, free to replace each access to "state" with
a read to pci_dev->current_state. As far as I can tell, the whole point
of READ_ONCE is to prevent that and ensure that there is only one read.

Note also that something like this could be easily introduced by
changing the code in pci_power_name(), as that is likely inlined by the
compiler. I'm not entirely sure, but I think that the compiler is allowed
to, at least theoretically, split that into two reads here and inlining
might be done before further optimization.

On the other hand, the changes that could lead to issues above are
fairly unlikely to cause them as the compiler will _probably_ read the
value only once anyways.

> If there's a downside to doing two separate reads, we could mention
> that in the commit log or a comment.
> 
> If there's not a specific reason for using READ_ONCE(), I think we
> should omit it because using it in one place but not others suggests
> that there's something special about this place.

I'd argue that there is indeed something special about this place:
current_state is accessed without holding the device lock (unless I'm
mistaken and sysfs attributes do acquire the device lock automatically)
and the state is normally only accessed/changed under it.

Apart from (hopefully) preventing somewhat unlikely future issues and
highlighting that it is (somewhat of a) special case, the READ_ONCE does
not serve any purpose here. As the code is now, omitting it will not
cause any issues (or really should not make any difference in produced
code).

All in all, I'm not entirely sure that it's a good idea to drop the
READ_ONCE, but I'll defer to you for that judgement.

Regards,
Max

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ