On Sat, 5 Aug 2023 08:49:25 +0200
Landry Breuil <[email protected]> wrote:

> I'm not sure i'll be able to look into it, but i'd rather *not* document
> 'workarounds' for issues until we're sure the issue isnt fixable. Maybe
> it's pledge/unveil related, maybe not. Using ktrace to figure out which
> files the browser tries to access when handling date-related functions
> might help... and if it's not an issue happening only on OpenBSD, then
> dealing with upstream is the way to go.

I used ktrace.  It's unveil.  The fix is to add "/etc/localtime r"
to /etc/firefox/unveil.content

The problem happens during dst (daylight saving time, summer time).
Firefox has its own dst rules, but needs the name of my zone, which is
"America/New_York".  It tries to realpath(3) /etc/localtime, but this
fails, so Firefox turns off dst.  Then my time is wrong, 1 hour too
early.  The Sweden v US game will be at 5 AM, but Firefox says 4 AM.

I put the attached date.html in ~/Downloads and did
$ ktrace -di firefox date.html
$ kdump -T|less

87580 is a content process and has called unveil and pledge.  I have
not fixed unveil.content, so realpath(3) /etc/localtime will fail.

 87580 firefox  1691262219.551380 CALL  open(0xcf362a14bb6,0<O_RDONLY>)
 87580 firefox  1691262219.551385 NAMI  "/etc/localtime"
 87580 firefox  1691262219.551412 RET   open 27/0x1b

This is libc doing open(2) /etc/localtime.  This succeeds because
pledge(2) allows it.  Firefox uses libc's localtime_r(3) to find my
offset from GMT.  libc has the dst rules for America/New_York, but
Firefox turns off libc's dst, gets GMT - 5.  (dst is GMT - 4.)

SpiderMonkey calls localtime_r(3) in
firefox-116.0/js/src/vm/DateTime.cpp

 87580 firefox  1691262219.551467 CALL  open(0x70a30d969880,0<O_RDONLY>)
 87580 firefox  1691262219.551470 NAMI  "/usr/share/zoneinfo/posixrules"
 87580 firefox  1691262219.551478 RET   open 27/0x1b

I guess that libc also opens posixrules.

 87580 firefox  1691262219.567404 CALL  __realpath(0xcf2d3c617f7,0x70a30d971970)
 87580 firefox  1691262219.567406 NAMI  "/etc/localtime"
 87580 firefox  1691262219.567420 RET   __realpath -1 errno 2 No such file or 
directory

This is the problem; Firefox's copy of ICU is calling realpath(3) on
/etc/localtime but unveil(2) hides it.  This is realpath(TZDEFAULT, _)
in firefox-116.0/intl/icu/source/common/putil.cpp

The path "/usr/share/zoneinfo/America/New_York" would cause ICU to
apply some dst rules for America/New_York.  Without the path, ICU
fails to apply dst, and SpiderMonkey stays on GMT - 5 (no dst).

I didn't study the next calls.  I saw a failure to open the
directory /usr/share/zoneinfo/ but I didn't try to unveil it.

 87580 firefox  1691262219.567434 CALL  
open(0xcf2d3c5cd55,0x30000<O_RDONLY|O_CLOEXEC|O_DIRECTORY>)
 87580 firefox  1691262219.567437 NAMI  "/usr/share/zoneinfo/"
 87580 firefox  1691262219.567443 RET   open -1 errno 2 No such file or 
directory
 ...
 87580 firefox  1691262219.567574 CALL  open(0x70a30d96d530,0<O_RDONLY>)
 87580 firefox  1691262219.567576 NAMI  "/usr/share/zoneinfo/GMT"
 87580 firefox  1691262219.567582 RET   open 27/0x1b
 ...
 87580 firefox  1691262219.567618 CALL  open(0x70a30d968c50,0<O_RDONLY>)
 87580 firefox  1691262219.567620 NAMI  "/usr/share/zoneinfo/posixrules"
 87580 firefox  1691262219.567652 RET   open 27/0x1b
 ...
 87580 firefox  1691262219.596748 CALL  __realpath(0xcf2d3c617f7,0x70a30d970bc0)
 87580 firefox  1691262219.596751 NAMI  "/etc/localtime"
 87580 firefox  1691262219.596779 RET   __realpath -1 errno 2 No such file or 
directory
 87580 firefox  1691262219.596781 CALL  
open(0xcf2d3c5cd55,0x30000<O_RDONLY|O_CLOEXEC|O_DIRECTORY>)
 87580 firefox  1691262219.596785 NAMI  "/usr/share/zoneinfo/"
 87580 firefox  1691262219.596791 RET   open -1 errno 2 No such file or 
directory
<textarea id="said" rows="24" cols="80">
</textarea>

<script>
  var said = document.getElementById("said");
  function say(what) {
      said.textContent += what + "\n";
  }

  /* Sweden v United States */
  var when = new Date(Date.UTC(2023, 7, 6, 9));
  say("epoch + " + when.getTime() / 1000 + " s");

  function say_in(tz) {
      var opts = {dateStyle: "long", timeStyle: "long"};
      if (tz !== "Local")
          opts.timeZone = tz;
      say(tz + " = " + when.toLocaleString("en", opts));
  }
  say_in("UTC");
  say_in("Australia/Sydney");
  say_in("America/Edmonton");
  say_in("America/New_York");
  say_in("Local");
</script>

Reply via email to