diff mbox series

efi: cper: avoid using get_seconds()

Message ID 20180618141811.3353245-1-arnd@arndb.de
State Accepted
Commit 7bb497092a34a2bbb16bad5385a0487dee18a769
Headers show
Series efi: cper: avoid using get_seconds() | expand

Commit Message

Arnd Bergmann June 18, 2018, 2:17 p.m. UTC
get_seconds() is deprecated because of the 32-bit time overflow
in y2038/y2106 on 32-bit architectures. The way it is used in
cper_next_record_id() causes an overflow in 2106 when unsigned UTC
seconds overflow, even on 64-bit architectures.

This starts using ktime_get_real_seconds() to give us more than 32 bits
of timestamp on all architectures, and then changes the algorithm to use
39 bits for the timestamp after the y2038 wrap date, plus an always-1
bit at the top. This gives us another 127 epochs of 136 years, with
strictly monotonically increasing sequence numbers across boots.

This is almost certainly overkill, but seems better than just extending
the deadline from 2038 to 2106.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>

---
 drivers/firmware/efi/cper.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

-- 
2.9.0

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Ard Biesheuvel June 18, 2018, 3:47 p.m. UTC | #1
On 18 June 2018 at 16:17, Arnd Bergmann <arnd@arndb.de> wrote:
> get_seconds() is deprecated because of the 32-bit time overflow

> in y2038/y2106 on 32-bit architectures. The way it is used in

> cper_next_record_id() causes an overflow in 2106 when unsigned UTC

> seconds overflow, even on 64-bit architectures.

>

> This starts using ktime_get_real_seconds() to give us more than 32 bits

> of timestamp on all architectures, and then changes the algorithm to use

> 39 bits for the timestamp after the y2038 wrap date, plus an always-1

> bit at the top. This gives us another 127 epochs of 136 years, with

> strictly monotonically increasing sequence numbers across boots.

>

> This is almost certainly overkill, but seems better than just extending

> the deadline from 2038 to 2106.

>

> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

> ---

>  drivers/firmware/efi/cper.c | 17 +++++++++++++++--

>  1 file changed, 15 insertions(+), 2 deletions(-)

>

> diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c

> index 3bf0dca378a6..b73fc4cab083 100644

> --- a/drivers/firmware/efi/cper.c

> +++ b/drivers/firmware/efi/cper.c

> @@ -48,8 +48,21 @@ u64 cper_next_record_id(void)

>  {

>         static atomic64_t seq;

>

> -       if (!atomic64_read(&seq))

> -               atomic64_set(&seq, ((u64)get_seconds()) << 32);

> +       if (!atomic64_read(&seq)) {

> +               time64_t time = ktime_get_real_seconds();

> +

> +               /*

> +                * This code is unlikely to still be needed in year 2106,

> +                * but just in case, let's use a few more bits for timestamps

> +                * after y2038 to be sure they keep increasing monotonically

> +                * for the next few hundred years...

> +                */

> +               if (time < 0x80000000)

> +                       atomic64_set(&seq, (ktime_get_real_seconds()) << 32);

> +               else

> +                       atomic64_set(&seq, 0x8000000000000000ull |

> +                                          ktime_get_real_seconds() << 24);

> +       }


Given that these values are never decoded and interpreted as
timestamps, can't we simply switch to the second flavour immediately?

>

>         return atomic64_inc_return(&seq);

>  }

> --

> 2.9.0

>

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Arnd Bergmann June 18, 2018, 3:49 p.m. UTC | #2
On Mon, Jun 18, 2018 at 5:47 PM, Ard Biesheuvel
<ard.biesheuvel@linaro.org> wrote:
> On 18 June 2018 at 16:17, Arnd Bergmann <arnd@arndb.de> wrote:


>> -               atomic64_set(&seq, ((u64)get_seconds()) << 32);

>> +       if (!atomic64_read(&seq)) {

>> +               time64_t time = ktime_get_real_seconds();

>> +

>> +               /*

>> +                * This code is unlikely to still be needed in year 2106,

>> +                * but just in case, let's use a few more bits for timestamps

>> +                * after y2038 to be sure they keep increasing monotonically

>> +                * for the next few hundred years...

>> +                */

>> +               if (time < 0x80000000)

>> +                       atomic64_set(&seq, (ktime_get_real_seconds()) << 32);

>> +               else

>> +                       atomic64_set(&seq, 0x8000000000000000ull |

>> +                                          ktime_get_real_seconds() << 24);

>> +       }

>

> Given that these values are never decoded and interpreted as

> timestamps, can't we simply switch to the second flavour immediately?


I considered that, but the downside would be that all future filenames would
come before all past file names. I don't know if the order is important at
all, but the current implementation at least looks like it's intended to keep
all file names strictly sorted across boots.

         Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Ard Biesheuvel June 18, 2018, 3:50 p.m. UTC | #3
On 18 June 2018 at 17:49, Arnd Bergmann <arnd@arndb.de> wrote:
> On Mon, Jun 18, 2018 at 5:47 PM, Ard Biesheuvel

> <ard.biesheuvel@linaro.org> wrote:

>> On 18 June 2018 at 16:17, Arnd Bergmann <arnd@arndb.de> wrote:

>

>>> -               atomic64_set(&seq, ((u64)get_seconds()) << 32);

>>> +       if (!atomic64_read(&seq)) {

>>> +               time64_t time = ktime_get_real_seconds();

>>> +

>>> +               /*

>>> +                * This code is unlikely to still be needed in year 2106,

>>> +                * but just in case, let's use a few more bits for timestamps

>>> +                * after y2038 to be sure they keep increasing monotonically

>>> +                * for the next few hundred years...

>>> +                */

>>> +               if (time < 0x80000000)

>>> +                       atomic64_set(&seq, (ktime_get_real_seconds()) << 32);

>>> +               else

>>> +                       atomic64_set(&seq, 0x8000000000000000ull |

>>> +                                          ktime_get_real_seconds() << 24);

>>> +       }

>>

>> Given that these values are never decoded and interpreted as

>> timestamps, can't we simply switch to the second flavour immediately?

>

> I considered that, but the downside would be that all future filenames would

> come before all past file names.


Won't we have that same problem in 2038?

> I don't know if the order is important at

> all, but the current implementation at least looks like it's intended to keep

> all file names strictly sorted across boots.

>

>          Arnd

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Ard Biesheuvel June 18, 2018, 3:56 p.m. UTC | #4
On 18 June 2018 at 17:54, Arnd Bergmann <arnd@arndb.de> wrote:
> On Mon, Jun 18, 2018 at 5:50 PM, Ard Biesheuvel

> <ard.biesheuvel@linaro.org> wrote:

>> On 18 June 2018 at 17:49, Arnd Bergmann <arnd@arndb.de> wrote:

>>> On Mon, Jun 18, 2018 at 5:47 PM, Ard Biesheuvel

>>> <ard.biesheuvel@linaro.org> wrote:

>>>> On 18 June 2018 at 16:17, Arnd Bergmann <arnd@arndb.de> wrote:

>>>

>>>>> -               atomic64_set(&seq, ((u64)get_seconds()) << 32);

>>>>> +       if (!atomic64_read(&seq)) {

>>>>> +               time64_t time = ktime_get_real_seconds();

>>>>> +

>>>>> +               /*

>>>>> +                * This code is unlikely to still be needed in year 2106,

>>>>> +                * but just in case, let's use a few more bits for timestamps

>>>>> +                * after y2038 to be sure they keep increasing monotonically

>>>>> +                * for the next few hundred years...

>>>>> +                */

>>>>> +               if (time < 0x80000000)

>>>>> +                       atomic64_set(&seq, (ktime_get_real_seconds()) << 32);

>>>>> +               else

>>>>> +                       atomic64_set(&seq, 0x8000000000000000ull |

>>>>> +                                          ktime_get_real_seconds() << 24);

>>>>> +       }

>>>>

>>>> Given that these values are never decoded and interpreted as

>>>> timestamps, can't we simply switch to the second flavour immediately?

>>>

>>> I considered that, but the downside would be that all future filenames would

>>> come before all past file names.

>>

>> Won't we have that same problem in 2038?

>

> No, it goes from 0x7fffffff00000000 to 0x8000000000000000, followed

> by 0x8000000001000000.

>


Ah, right. I'm with you now :-)

I'll queue this in the efi tree.
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox series

Patch

diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 3bf0dca378a6..b73fc4cab083 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -48,8 +48,21 @@  u64 cper_next_record_id(void)
 {
 	static atomic64_t seq;
 
-	if (!atomic64_read(&seq))
-		atomic64_set(&seq, ((u64)get_seconds()) << 32);
+	if (!atomic64_read(&seq)) {
+		time64_t time = ktime_get_real_seconds();
+
+		/*
+		 * This code is unlikely to still be needed in year 2106,
+		 * but just in case, let's use a few more bits for timestamps
+		 * after y2038 to be sure they keep increasing monotonically
+		 * for the next few hundred years...
+		 */
+		if (time < 0x80000000)
+			atomic64_set(&seq, (ktime_get_real_seconds()) << 32);
+		else
+			atomic64_set(&seq, 0x8000000000000000ull |
+					   ktime_get_real_seconds() << 24);
+	}
 
 	return atomic64_inc_return(&seq);
 }