On 2019/09/20 10:00, joshua stein wrote:
> While the Chrome port uses separate files in /etc/chromium for
> unveil file lists, these patches use new comma-separated
> about:config keys for them.

> onts r,/etc/machine-id r,/etc/mailcap r,/tmp rwc,/usr/bin/lpr rx,/usr/local=
> /bin/gio-launch-desktop rx,/usr/local/lib r,/usr/local/firefox r,/usr/local=
> /lib/firefox rx,/usr/local/share r,/usr/share/locale r,/var/cache/fontconfi=
> g r,/usr/X11R6/lib r,/usr/X11R6/share r,/var/run rw,~/.XCompose r,~/.Xautho=

Ports shouldn't use hardcoded /usr/local - the diff attached uses
${LOCALBASE}/${TRUEPREFIX} instead of /usr/local as appropriate,
${X11BASE} instead of /usr/X11R6, ${SYSCONFDIR} for the /etc files
that comes from ports rather than base, and ${SUBST_CMD} in
post-patch to substitute them for the correct paths.

fwiw, I'm a bit worried about the per-user config for this, will the
list be copied as-is to individual user prefs (my test build isn't done
yet) .. The list will definitely need to be updated in the future and
that won't work if users have to hand apply the changes to their own
profile. (Also it makes life difficult for multi-user installs ..).

? .todo
Index: Makefile
===================================================================
RCS file: /cvs/ports/www/mozilla-firefox/Makefile,v
retrieving revision 1.394
diff -u -p -r1.394 Makefile
--- Makefile    18 Sep 2019 16:58:05 -0000      1.394
+++ Makefile    20 Sep 2019 16:33:33 -0000
@@ -10,6 +10,8 @@ MOZILLA_BRANCH =      release
 MOZILLA_PROJECT =      firefox
 MOZILLA_CODENAME =     browser
 
+REVISION =     0
+
 WRKDIST =      ${WRKDIR}/${MOZILLA_DIST}-${MOZILLA_DIST_VERSION:C/b[0-9]*//}
 HOMEPAGE =     https://www.mozilla.org/firefox/
 SO_VERSION =   84.0
@@ -74,6 +76,10 @@ SUBST_VARS +=        LOCALBASE X11BASE
 
 show-commit:
        @curl -s 
https://releases.mozilla.org/pub/mozilla.org/firefox/releases/${MOZILLA_VERSION}/SOURCE|
 awk -F / '/^https:\/\/hg/ {print $$7 }'
+
+post-patch:
+       ${SUBST_CMD} ${WRKSRC}/toolkit/system/gnome/nsGIOService.cpp \
+               ${WRKSRC}/browser/app/profile/firefox.js
 
 post-install:
        ${SUBST_MAN} ${FILESDIR}/mozilla-firefox.1 \
Index: patches/patch-browser_app_profile_firefox_js
===================================================================
RCS file: patches/patch-browser_app_profile_firefox_js
diff -N patches/patch-browser_app_profile_firefox_js
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-browser_app_profile_firefox_js        20 Sep 2019 16:33:33 
-0000
@@ -0,0 +1,33 @@
+$OpenBSD$
+
+sandbox GPU process on OpenBSD with pledge()
+https://bugzilla.mozilla.org/show_bug.cgi?id=1580268
+
+enhance sandbox on OpenBSD with unveil()
+https://bugzilla.mozilla.org/show_bug.cgi?id=1580271
+
+Index: browser/app/profile/firefox.js
+--- browser/app/profile/firefox.js.orig
++++ browser/app/profile/firefox.js
+@@ -1130,11 +1130,18 @@ pref("security.sandbox.content.syscall_whitelist", "")
+ #endif
+ 
+ #if defined(XP_OPENBSD) && defined(MOZ_SANDBOX)
++pref("security.sandbox.content.level", 1);
++
+ // default pledge strings for the main & content processes, cf bug 1457092
+-// broad list for now, has to be refined over time
+ pref("security.sandbox.pledge.main", "stdio rpath wpath cpath inet proc exec 
prot_exec flock ps sendfd recvfd dns vminfo tty drm unix fattr getpw mcast");
+-pref("security.sandbox.content.level", 1);
+-pref("security.sandbox.pledge.content", "stdio rpath wpath cpath inet recvfd 
sendfd prot_exec unix drm ps");
++pref("security.sandbox.pledge.content", "stdio rpath wpath cpath recvfd 
sendfd prot_exec unix drm ps");
++// and for gpu, bug 1580268
++pref("security.sandbox.pledge.gpu", "stdio rpath wpath cpath ps sendfd recvfd 
drm dns unix prot_exec");
++
++// default file paths unveiled to each process, bug 1580271
++pref("security.sandbox.unveil.main", "/dev/urandom r,/dev/video rw,/etc/fonts 
r,${SYSCONFDIR}/machine-id r,${SYSCONFDIR}/mailcap r,/tmp rwc,/usr/bin/lpr 
rx,${LOCALBASE}/bin/gio-launch-desktop rx,${LOCALBASE}/lib 
r,${TRUEPREFIX}/firefox r,${TRUEPREFIX}/lib/firefox rx,${LOCALBASE}/share 
r,/usr/share/locale r,/var/cache/fontconfig r,${X11BASE}/lib r,${X11BASE}/share 
r,/var/run rw,~/.XCompose r,~/.Xauthority r,~/.Xdefaults r,~/.fontconfig 
r,~/.fonts r,~/.fonts.conf r,~/.fonts.conf.d r,~/.icons r,~/.mailcap 
r,~/.mime.types r,~/.mozilla rwc,~/.pki rwc,~/.sndio rwc,~/.terminfo 
r,$XDG_CACHE_HOME/dconf rwc,$XDG_CACHE_HOME/thumbnails 
rwc,$XDG_CONFIG_HOME/dconf r,$XDG_CONFIG_HOME/fontconfig 
r,$XDG_CONFIG_HOME/gtk-3.0 r,$XDG_CONFIG_HOME/mimeapps.list 
r,$XDG_CONFIG_HOME/mozilla rwc,$XDG_CONFIG_HOME/user-dirs.dirs 
r,$XDG_DATA_HOME/applications rwc,$XDG_DATA_HOME/applnk r,$XDG_DATA_HOME/fonts 
r,$XDG_DATA_HOME/glib-2.0 r,$XDG_DATA_HOME/icons r,$XDG_DATA_HOME/mime 
r,$XDG_DATA_HOME/recently-used.xbel rwc,$XDG_DATA_HOME/themes r,~/Downloads 
rwc");
++pref("security.sandbox.unveil.content", "/dev/drm0 rw,/etc/fonts 
r,${SYSCONFDIR}/machine-id r,/tmp rwc,${LOCALBASE}/lib r,${TRUEPREFIX}/firefox 
r,${TRUEPREFIX}/lib/firefox rx,${LOCALBASE}/share r,/usr/share/locale 
r,/var/cache/fontconfig r,${X11BASE}/lib r,${X11BASE}/share r,/var/run 
rw,~/.XCompose r,~/.Xauthority r,~/.Xdefaults r,~/.fontconfig r,~/.fonts 
r,~/.fonts.conf r,~/.fonts.conf.d r,~/.icons r,~/.mozilla rwc,~/.pki 
rwc,~/.sndio rwc,~/.terminfo r,$XDG_CACHE_HOME/dconf 
rwc,$XDG_CACHE_HOME/thumbnails rwc,$XDG_CONFIG_HOME/dconf 
r,$XDG_CONFIG_HOME/fontconfig r,$XDG_CONFIG_HOME/gtk-3.0 
r,$XDG_CONFIG_HOME/mimeapps.list r,$XDG_CONFIG_HOME/mozilla 
rwc,$XDG_CONFIG_HOME/user-dirs.dirs r,$XDG_DATA_HOME/applications 
r,$XDG_DATA_HOME/applnk r,$XDG_DATA_HOME/fonts r,$XDG_DATA_HOME/glib-2.0 
r,$XDG_DATA_HOME/icons r,$XDG_DATA_HOME/mime r,$XDG_DATA_HOME/themes 
r,~/Downloads r");
++pref("security.sandbox.unveil.gpu", "/dev/drm0 rw,/tmp 
rwc,${TRUEPREFIX}/lib/firefox r,${LOCALBASE}/lib/gdk-pixbuf-2.0 
r,${X11BASE}/lib r,/usr/share/locale r,${LOCALBASE}/share r,~/.Xauthority r");
+ #endif
+ 
+ #if defined(MOZ_SANDBOX)
Index: patches/patch-dom_ipc_ContentChild_cpp
===================================================================
RCS file: patches/patch-dom_ipc_ContentChild_cpp
diff -N patches/patch-dom_ipc_ContentChild_cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-dom_ipc_ContentChild_cpp      20 Sep 2019 16:33:33 -0000
@@ -0,0 +1,170 @@
+$OpenBSD$
+
+sandbox GPU process on OpenBSD with pledge()
+https://bugzilla.mozilla.org/show_bug.cgi?id=1580268
+
+enhance sandbox on OpenBSD with unveil()
+https://bugzilla.mozilla.org/show_bug.cgi?id=1580271
+
+Index: dom/ipc/ContentChild.cpp
+--- dom/ipc/ContentChild.cpp.orig
++++ dom/ipc/ContentChild.cpp
+@@ -126,6 +126,7 @@
+ #    include "mozilla/Sandbox.h"
+ #  elif defined(__OpenBSD__)
+ #    include <unistd.h>
++#    include "SpecialSystemDirectory.h"
+ #  endif
+ #endif
+ 
+@@ -4048,47 +4049,132 @@ void ContentChild::HoldBrowsingContextGroup(BrowsingCo
+ }  // namespace dom
+ 
+ #if defined(__OpenBSD__) && defined(MOZ_SANDBOX)
+-#  include <unistd.h>
+ 
+ static LazyLogModule sPledgeLog("SandboxPledge");
+ 
+ bool StartOpenBSDSandbox(GeckoProcessType type) {
+   nsAutoCString promisesString;
+   nsAutoCString processTypeString;
++  nsAutoCString unveilString;
+ 
+   switch (type) {
+     case GeckoProcessType_Default:
+       processTypeString = "main";
+       Preferences::GetCString("security.sandbox.pledge.main", promisesString);
++      Preferences::GetCString("security.sandbox.unveil.main", unveilString);
+       break;
+ 
+     case GeckoProcessType_Content:
+       processTypeString = "content";
+-      Preferences::GetCString("security.sandbox.pledge.content",
+-                              promisesString);
++      Preferences::GetCString("security.sandbox.pledge.content", 
promisesString);
++      Preferences::GetCString("security.sandbox.unveil.content", 
unveilString);
+       break;
+ 
++    case GeckoProcessType_GPU:
++      processTypeString = "gpu";
++      Preferences::GetCString("security.sandbox.pledge.gpu", promisesString);
++      Preferences::GetCString("security.sandbox.unveil.gpu", unveilString);
++      break;
++
+     default:
+       MOZ_ASSERT(false, "unknown process type");
+       return false;
+-  };
++  }
+ 
+-  if (pledge(promisesString.get(), NULL) == -1) {
+-    if (errno == EINVAL) {
+-      MOZ_LOG(sPledgeLog, LogLevel::Error,
+-              ("pledge promises for %s process is a malformed string: '%s'\n",
+-               processTypeString.get(), promisesString.get()));
+-    } else if (errno == EPERM) {
+-      MOZ_LOG(
+-          sPledgeLog, LogLevel::Error,
+-          ("pledge promises for %s process can't elevate privileges: '%s'\n",
+-           processTypeString.get(), promisesString.get()));
++  if (!PR_GetEnv("MOZ_DISABLE_UNVEIL")) {
++    nsresult rv;
++
++    nsCOMPtr<nsIFile> homeDir;
++    rv = GetSpecialSystemDirectory(Unix_HomeDirectory, 
getter_AddRefs(homeDir));
++    if (NS_FAILED(rv)) {
++      mozilla::ipc::FatalError("failed getting home directory", false);
+     }
+-    return false;
+-  } else {
+-    MOZ_LOG(sPledgeLog, LogLevel::Debug,
+-            ("pledged %s process with promises: '%s'\n",
++
++    bool anyUnveils = false;
++
++    for (const nsACString& tChunk : unveilString.Split(',')) {
++      nsAutoCString chunk;
++      chunk.Append(tChunk);
++
++      chunk.CompressWhitespace(true, true);
++      if (chunk.IsEmpty()) {
++        continue;
++      }
++
++      int32_t space = chunk.FindChar(' ');
++      if (space <= 0) {
++        mozilla::ipc::FatalError(nsPrintfCString("%s: invalid unveil "
++          "format \"%s\"", PromiseFlatCString(processTypeString).get(),
++          chunk.get()).get(), false);
++      }
++
++      nsCString uPath(Substring(chunk, 0, space));
++      nsCString perms(Substring(chunk, space + 1, chunk.Length() - space - 
1));
++
++      // Expand $XDG_CONFIG_HOME to the environment variable, or ~/.config
++      nsCString xdgConfigHome(PR_GetEnv("XDG_CONFIG_HOME"));
++      if (xdgConfigHome.IsEmpty()) {
++        xdgConfigHome = "~/.config";
++      }
++      uPath.ReplaceSubstring("$XDG_CONFIG_HOME", xdgConfigHome.get());
++
++      // Expand $XDG_CACHE_HOME to the environment variable, or ~/.cache
++      nsCString xdgCacheHome(PR_GetEnv("XDG_CACHE_HOME"));
++      if (xdgCacheHome.IsEmpty()) {
++        xdgCacheHome = "~/.cache";
++      }
++      uPath.ReplaceSubstring("$XDG_CACHE_HOME", xdgCacheHome.get());
++
++      // Expand $XDG_DATA_HOME to the environment variable, or ~/.local/share
++      nsCString xdgDataHome(PR_GetEnv("XDG_DATA_HOME"));
++      if (xdgDataHome.IsEmpty()) {
++        xdgDataHome = "~/.local/share";
++      }
++      uPath.ReplaceSubstring("$XDG_DATA_HOME", xdgDataHome.get());
++
++      // Expand leading ~ to the user's home directory
++      if (uPath.FindChar('~') == 0) {
++        nsCString tHome(homeDir->NativePath());
++        tHome.Append(Substring(uPath, 1, uPath.Length() - 1));
++        uPath = tHome.get();
++      }
++
++      MOZ_LOG(sPledgeLog, LogLevel::Debug, ("%s: unveil(%s, %s)\n",
++        processTypeString.get(), uPath.get(), perms.get()));
++      int ret = unveil(uPath.get(), perms.get());
++      if (ret != 0 && ret != ENOENT) {
++        mozilla::ipc::FatalError(nsPrintfCString("%s: unveil(%s, %s) failed: 
%d",
++          processTypeString.get(), uPath.get(), perms.get(), errno).get(),
++          false);
++      }
++
++      anyUnveils = true;
++    }
++
++    if (!anyUnveils) {
++      mozilla::ipc::FatalError(nsPrintfCString("failed parsing unveil string "
++        "\"%s\"", unveilString.get()).get(), false);
++    }
++  }
++
++  if (!PR_GetEnv("MOZ_DISABLE_PLEDGE")) {
++    if (pledge(promisesString.get(), nullptr) == -1) {
++      if (errno == EINVAL) {
++        MOZ_LOG(sPledgeLog, LogLevel::Error,
++                ("pledge promises for %s process is a malformed string: 
'%s'\n",
++                 processTypeString.get(), promisesString.get()));
++      } else if (errno == EPERM) {
++        MOZ_LOG(
++            sPledgeLog, LogLevel::Error,
++            ("pledge promises for %s process can't elevate privileges: 
'%s'\n",
+              processTypeString.get(), promisesString.get()));
++      }
++      return false;
++    } else {
++      MOZ_LOG(sPledgeLog, LogLevel::Debug,
++              ("pledged %s process with promises: '%s'\n",
++               processTypeString.get(), promisesString.get()));
++    }
+   }
+   return true;
+ }
Index: patches/patch-gfx_ipc_GPUParent_cpp
===================================================================
RCS file: patches/patch-gfx_ipc_GPUParent_cpp
diff -N patches/patch-gfx_ipc_GPUParent_cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-gfx_ipc_GPUParent_cpp 20 Sep 2019 16:33:33 -0000
@@ -0,0 +1,28 @@
+$OpenBSD$
+
+sandbox GPU process on OpenBSD with pledge()
+https://bugzilla.mozilla.org/show_bug.cgi?id=1580268
+
+Index: gfx/ipc/GPUParent.cpp
+--- gfx/ipc/GPUParent.cpp.orig
++++ gfx/ipc/GPUParent.cpp
+@@ -57,6 +57,8 @@
+ #  include "mozilla/WindowsVersion.h"
+ #  include <process.h>
+ #  include <dwrite.h>
++#elif defined(__OpenBSD__) && defined(MOZ_SANDBOX)
++#  include "mozilla/SandboxSettings.h"
+ #endif
+ #ifdef MOZ_WIDGET_GTK
+ #  include <gtk/gtk.h>
+@@ -122,6 +124,10 @@ bool GPUParent::Init(base::ProcessId aParentPid, const
+   mlg::InitializeMemoryReporters();
+ #if defined(XP_WIN)
+   DeviceManagerDx::Init();
++#endif
++
++#if defined(__OpenBSD__) && defined(MOZ_SANDBOX)
++  StartOpenBSDSandbox(GeckoProcessType_GPU);
+ #endif
+ 
+   CompositorThreadHolder::Start();
Index: patches/patch-toolkit_system_gnome_nsGIOService_cpp
===================================================================
RCS file: patches/patch-toolkit_system_gnome_nsGIOService_cpp
diff -N patches/patch-toolkit_system_gnome_nsGIOService_cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-toolkit_system_gnome_nsGIOService_cpp 20 Sep 2019 16:33:33 
-0000
@@ -0,0 +1,29 @@
+$OpenBSD$
+
+enhance sandbox on OpenBSD with unveil()
+https://bugzilla.mozilla.org/show_bug.cgi?id=1580271
+
+Index: toolkit/system/gnome/nsGIOService.cpp
+--- toolkit/system/gnome/nsGIOService.cpp.orig
++++ toolkit/system/gnome/nsGIOService.cpp
+@@ -497,7 +497,20 @@ nsGIOService::GetAppForMimeType(const nsACString& aMim
+     return NS_ERROR_NOT_AVAILABLE;
+   }
+ 
++#if defined(__OpenBSD__) && defined(MOZ_SANDBOX)
++  // g_app_info_get_default_for_type will fail on OpenBSD's veiled filesystem
++  // since we most likely don't have direct access to the binaries that are
++  // registered as defaults for this type.  Fake it up by just executing
++  // xdg-open via gio-launch-desktop (which we do have access to) and letting
++  // it figure out which program to execute for this MIME type
++  GAppInfo* app_info = g_app_info_create_from_commandline(
++    "${LOCALBASE}/bin/xdg-open",
++    nsPrintfCString("System default for %s", content_type).get(),
++    G_APP_INFO_CREATE_NONE, NULL);
++#else
+   GAppInfo* app_info = g_app_info_get_default_for_type(content_type, false);
++#endif
++
+   if (app_info) {
+     nsGIOMimeApp* mozApp = new nsGIOMimeApp(app_info);
+     NS_ENSURE_TRUE(mozApp, NS_ERROR_OUT_OF_MEMORY);
Index: pkg/README
===================================================================
RCS file: /cvs/ports/www/mozilla-firefox/pkg/README,v
retrieving revision 1.24
diff -u -p -r1.24 README
--- pkg/README  11 Jun 2019 06:01:20 -0000      1.24
+++ pkg/README  20 Sep 2019 16:33:33 -0000
@@ -28,6 +28,46 @@ right click, choose New String. Set the 
 "network.protocol-handler.app.mailto" and the value to the path to
 your mailer.
 
+pledge(2) and unveil(2) Support
+===============================
+Firefox on OpenBSD is secured with pledge(2) and unveil(2) to limit
+the system calls and filesystem access that each of Firefox's three
+process types (main, content, and GPU) is permitted.  By default,
+only ~/Downloads and /tmp can be written to when downloading files,
+or viewing them as file:// URLs.
+
+To add a specific path as writable for downloads, add it to the
+security.sandbox.unveil.main about:config key with "rw" permissions.
+To add a directory from which files can be uploaded, add it with just
+the "r" permission.
+To add a path that can be viewed as a file:// URL, it must also be
+added to the security.sandbox.unveil.content about:config key with
+"r" permissions.
+
+3rd-Party MIME Handlers
+=======================
+Due to unveil(2) limiting filesystem access, only the default MIME
+handler registered for a given type can be chosen when opening a
+downloaded file.  For example, to use the mupdf package to read
+PDFs, it must be registered as the default with XDG:
+
+       $ xdg-mime default mupdf.desktop application/pdf
+
+The current default for a given type can be viewed with xdg-mime's
+query command:
+
+       $ xdg-mime query default application/pdf
+
+The older mailcap-format handlers are also supported, but the path
+being executed must be explicitly added to the
+security.sandbox.unveil.main about:config key with "rx" permissions.
+For example, a ~/.mailcap file specifying:
+
+       application/pdf; ${LOCALBASE}/bin/xpdf %s
+
+must have "${LOCALBASE}/bin/xpdf rx" added to the unveil list for it to
+appear as an option in the "Open With" drop-down.
+
 Debugging
 =========
 If you encounter crashes, you might want to build the debug FLAVOR of
@@ -35,9 +75,10 @@ this package, and run firefox inside egd
 debugging logs and traces (for all threads!).
 If this is a pledge violation, you should figure out which codepath
 in which process leads to calling a forbidden syscall, and which pledge
-is missing from the two default sets configured in
-security.sandbox.pledge.main and security.sandbox.pledge.content
-about:config keys. MOZ_LOG=SandboxPledge:5 should help.
+is missing from the three default sets configured in
+security.sandbox.pledge.main, security.sandbox.pledge.content, and
+security.sandbox.pledge.gpu about:config keys.
+MOZ_LOG=SandboxPledge:5 should help.
 Bug reports without enough information will be ignored.
 
 Note that if you're using NIS or your profile is located on a NFS share,
@@ -50,12 +91,16 @@ security.sandbox.pledge.content in about
 If you're not running sndiod(8) you will need to add 'audio' to
 security.sandbox.pledge.main in about:config.
 
+To disable pledge support when troubleshooting, set the
+MOZ_DISABLE_PLEDGE environment variable before starting Firefox.
+Similarly, to disable unveil support, set MOZ_DISABLE_UNVEIL.
+
 D-BUS
 =====
 For proper integration with various desktop-oriented components, firefox
 needs a session bus instance running.
 If you're not running a desktop environment that takes care of it,
-refer to /usr/local/share/doc/pkg-readmes/dbus-* to configure your
+refer to ${LOCALBASE}/share/doc/pkg-readmes/dbus to configure your
 session startup script to start one.
 Without a session bus running, the port is faking one (see
 https://bugzilla.mozilla.org/show_bug.cgi?id=1466593), but GLIB might still try

Reply via email to