Bug 1302711 - Add Linux content sandbox level 6, for ioctl lockdown. r=gcp

The sandbox already limits `ioctl` attack surface by restricting what
files can be opened (you can't call a device's `ioctl` handler if you
can't get a fd for that device), but it's always good to have defense in
depth, especially when it can be implemented this simply.

The new policy is default-deny, allowing only a couple ioctls that
are really fcntls; others may be added as needed.

The old, default-allow policy (which blocked only tty ioctls) is still
available by lowering the pref `security.sandbox.content.level` to 5,
and for now that is also the case in safe mode.  (The safe mode sandbox
lowering may be removed in the future once this is better tested.)

Differential Revision: https://phabricator.services.mozilla.com/D249017
This commit is contained in:
Jed Davis
2025-05-22 05:02:27 +00:00
committed by jedavis@mozilla.com
parent c94714433d
commit 3c314e648e
4 changed files with 17 additions and 5 deletions

View File

@@ -1583,12 +1583,13 @@ pref("browser.bookmarks.editDialog.maxRecentFolders", 7);
// 5 -> blocks access to GL / DRI / display servers
// (formerly the separate pref `security.sandbox.content.headless`)
// (side effect: sets MOZ_HEADLESS for content processes)
// 6 -> default-deny for ioctl
//
// The purpose of this setting is to allow Linux users or distros to disable
// the sandbox while we fix their problems, or to allow running Firefox with
// exotic configurations we can't reasonably support out of the box.
//
pref("security.sandbox.content.level", 5);
pref("security.sandbox.content.level", 6);
// Introduced as part of bug 1608558. Linux is currently the only platform
// that uses a sandbox level for the socket process. There are currently
// only 2 levels:

View File

@@ -7,6 +7,7 @@
#include "mozilla/SandboxSettings.h"
#include "mozISandboxSettings.h"
#include "nsServiceManagerUtils.h"
#include "nsAppRunner.h"
#include "mozilla/Components.h"
#include "mozilla/Preferences.h"
@@ -20,7 +21,6 @@
#ifdef XP_WIN
# include "mozilla/gfx/gfxVars.h"
# include "mozilla/WindowsVersion.h"
# include "nsAppRunner.h"
# include "nsExceptionHandler.h"
# include "PDMFactory.h"
#endif // XP_WIN
@@ -172,6 +172,10 @@ int GetEffectiveContentSandboxLevel() {
if (level > 3 && !StaticPrefs::media_cubeb_sandbox()) {
level = 3;
}
// Turn off ioctl lockdown in safe mode, until it's gotten more testing.
if (level > 5 && gSafeMode) {
level = 5;
}
#endif
#if defined(XP_WIN)
// Sandbox level 8, which uses a USER_RESTRICTED access token level, breaks if

View File

@@ -556,6 +556,12 @@ void RunTestsContent(SandboxTestingChild* child) {
munmap(mapping, kMapSize);
}
child->ErrnoValueTest("ioctl_dma_buf"_ns, ENOSYS, [] {
// Attempt an arbitrary non-tty ioctl, on the wrong type of fd; if
// allowed it would fail with ENOTTY (see the RDD tests) but in
// this sandbox it should be blocked (ENOSYS).
return ioctl(0, _IOW('b', 0, uint64_t), nullptr);
});
# endif // XP_LINUX
# ifdef XP_MACOSX

View File

@@ -1485,9 +1485,10 @@ class ContentSandboxPolicy : public SandboxPolicyCommon {
return If(request == FIOCLEX, Allow())
// Rust's stdlib also uses FIONBIO instead of equivalent fcntls.
.ElseIf(request == FIONBIO, Allow())
// Allow anything that isn't a tty ioctl, for now; bug 1302711
// will cover changing this to a default-deny policy.
.ElseIf(shifted_type != kTtyIoctls, Allow())
// Allow anything that isn't a tty ioctl, if level < 6
.ElseIf(
BelowLevel(6) ? shifted_type != kTtyIoctls : BoolConst(false),
Allow())
.Else(SandboxPolicyCommon::EvaluateSyscall(sysno));
}