Bug 1786885 - Add ChromeUtils::GetLibcConstants r=nika

ChromeUtils::GetLibcConstants() is a replacement for
nsIOSFileConstantsService providing OS.Consts.LIBC. The constants from
OS.Consts.Win have been inlined into subprocess_shared_win.js, since it was
already defining several other constants and it was the only consumer.

Differential Revision: https://phabricator.services.mozilla.com/D180358
This commit is contained in:
Barret Rennie 2023-07-11 16:32:14 +00:00
Родитель 804da488b4
Коммит 3efc235517
6 изменённых файлов: 116 добавлений и 73 удалений

Просмотреть файл

@ -61,6 +61,18 @@
#include "nsIException.h"
#include "VsyncSource.h"
#ifdef XP_UNIX
# include <errno.h>
# include <unistd.h>
# include <fcntl.h>
# include <poll.h>
# include <sys/wait.h>
# ifdef XP_LINUX
# include <sys/prctl.h>
# endif
#endif
namespace mozilla::dom {
/* static */
@ -973,6 +985,41 @@ void ChromeUtils::DefineESModuleGetters(const GlobalObject& global,
}
}
#ifdef XP_UNIX
/* static */
void ChromeUtils::GetLibcConstants(const GlobalObject&,
LibcConstants& aConsts) {
aConsts.mEINTR.Construct(EINTR);
aConsts.mEACCES.Construct(EACCES);
aConsts.mEAGAIN.Construct(EAGAIN);
aConsts.mEINVAL.Construct(EINVAL);
aConsts.mENOSYS.Construct(ENOSYS);
aConsts.mF_SETFD.Construct(F_SETFD);
aConsts.mF_SETFL.Construct(F_SETFL);
aConsts.mFD_CLOEXEC.Construct(FD_CLOEXEC);
aConsts.mAT_EACCESS.Construct(AT_EACCESS);
aConsts.mO_CREAT.Construct(O_CREAT);
aConsts.mO_NONBLOCK.Construct(O_NONBLOCK);
aConsts.mO_WRONLY.Construct(O_WRONLY);
aConsts.mPOLLERR.Construct(POLLERR);
aConsts.mPOLLHUP.Construct(POLLHUP);
aConsts.mPOLLIN.Construct(POLLIN);
aConsts.mPOLLNVAL.Construct(POLLNVAL);
aConsts.mPOLLOUT.Construct(POLLOUT);
aConsts.mWNOHANG.Construct(WNOHANG);
# ifdef XP_LINUX
aConsts.mPR_CAPBSET_READ.Construct(PR_CAPBSET_READ);
# endif
}
#endif
/* static */
void ChromeUtils::OriginAttributesToSuffix(
dom::GlobalObject& aGlobal, const dom::OriginAttributesDictionary& aAttrs,

Просмотреть файл

@ -226,6 +226,10 @@ class ChromeUtils {
JS::Handle<JSObject*> modules,
ErrorResult& aRv);
#ifdef XP_UNIX
static void GetLibcConstants(const GlobalObject&, LibcConstants& aConsts);
#endif
static void GetCallerLocation(const GlobalObject& global,
nsIPrincipal* principal,
JS::MutableHandle<JSObject*> aRetval);

Просмотреть файл

@ -289,6 +289,14 @@ namespace ChromeUtils {
[Throws]
undefined defineLazyGetter(object aTarget, any aName, object aLambda);
#ifdef XP_UNIX
/**
* Return platform-specific libc constants, such as errno values.
*/
LibcConstants getLibcConstants();
#endif
/**
* IF YOU ADD NEW METHODS HERE, MAKE SURE THEY ARE THREAD-SAFE.
*/
@ -1036,3 +1044,36 @@ enum JSRFPTarget {
"RoundWindowSize",
"SiteSpecificZoom",
};
#ifdef XP_UNIX
dictionary LibcConstants {
long EINTR;
long EACCES;
long EAGAIN;
long EINVAL;
long ENOSYS;
long F_SETFD;
long F_SETFL;
long FD_CLOEXEC;
long AT_EACCESS;
long O_CREAT;
long O_NONBLOCK;
long O_WRONLY;
long POLLIN;
long POLLOUT;
long POLLERR;
long POLLHUP;
long POLLNVAL;
long WNOHANG;
#ifdef XP_LINUX
long PR_CAPBSET_READ;
#endif
};
#endif

Просмотреть файл

@ -9,33 +9,10 @@ Services.scriptloader.loadSubScript(
this
);
const ERRNO = {
EACCES: 13,
EINVAL: 22,
get ENOSYS() {
const os = Services.appinfo.OS;
const lazy = {};
if (["Linux", "Android"].includes(os)) {
// https://github.com/torvalds/linux/blob/9a48d604672220545d209e9996c2a1edbb5637f6/include/uapi/asm-generic/errno.h#L18
return 38;
} else if (
["Darwin", "DragonFly", "FreeBSD", "OpenBSD", "NetBSD"].includes(os)
) {
/*
* Darwin: https://opensource.apple.com/source/xnu/xnu-201/bsd/sys/errno.h.auto.html
* DragonFly: https://github.com/DragonFlyBSD/DragonFlyBSD/blob/5e488df32cb01056a5b714a522e51c69ab7b4612/sys/sys/errno.h#L172
* FreeBSD: https://github.com/freebsd/freebsd-src/blob/7232e6dcc89b978825b30a537bca2e7d3a9b71bb/sys/sys/errno.h#L157
* OpenBSD: https://github.com/openbsd/src/blob/025fffe4c6e0113862ce4e1927e67517a2841502/sys/sys/errno.h#L151
* NetBSD: https://github.com/NetBSD/src/blob/ff24f695f5f53540b23b6bb4fa5c0b9d79b369e4/sys/sys/errno.h#L137
*/
return 78;
} else if (os === "WINNT") {
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/errno-constants?view=msvc-170
return 40;
}
throw new Error("Unsupported OS");
},
};
/* getLibcConstants is only present on *nix */
XPCOMUtils.defineLazyGetter(lazy, "LIBC", () => ChromeUtils.getLibcConstants());
/*
* This test is for executing system calls in content processes to validate
@ -167,20 +144,6 @@ function callFaccessat2(args) {
return rv;
}
// open syscall flags
function openWriteCreateFlags() {
Assert.ok(isMac() || isLinux());
if (isMac()) {
let O_WRONLY = 0x001;
let O_CREAT = 0x200;
return O_WRONLY | O_CREAT;
}
// Linux
let O_WRONLY = 0x01;
let O_CREAT = 0x40;
return O_WRONLY | O_CREAT;
}
// Returns the name of the native library needed for native syscalls
function getOSLib() {
switch (Services.appinfo.OS) {
@ -324,7 +287,7 @@ add_task(async function () {
if (isLinux() || isMac()) {
// open a file for writing in $HOME, this should fail
let path = fileInHomeDir().path;
let flags = openWriteCreateFlags();
let flags = lazy.LIBC.O_CREAT | lazy.LIBC.O_WRONLY;
let fd = await SpecialPowers.spawn(
browser,
[{ lib, path, flags }],
@ -339,7 +302,7 @@ add_task(async function () {
// macOS and work on Linux. The open handler in the content process closes
// the file for us
let path = fileInTempDir().path;
let flags = openWriteCreateFlags();
let flags = lazy.LIBC.O_CREAT | lazy.LIBC.O_WRONLY;
let fd = await SpecialPowers.spawn(
browser,
[{ lib, path, flags }],
@ -390,13 +353,11 @@ add_task(async function () {
if (isLinux()) {
// These constants are not portable.
const AT_EACCESS = 512;
const PR_CAPBSET_READ = 23;
// verify we block PR_CAPBSET_READ with EINVAL
let option = PR_CAPBSET_READ;
let option = lazy.LIBC.PR_CAPBSET_READ;
let rv = await SpecialPowers.spawn(browser, [{ lib, option }], callPrctl);
ok(rv === ERRNO.EINVAL, "prctl(PR_CAPBSET_READ) is blocked");
ok(rv === lazy.LIBC.EINVAL, "prctl(PR_CAPBSET_READ) is blocked");
const kernelVersion = await getKernelVersion();
const glibcVersion = getGlibcVersion();
@ -412,15 +373,18 @@ add_task(async function () {
[{ lib, dirfd, path, mode, flag: 0x01 }],
callFaccessat2
);
ok(rv === ERRNO.ENOSYS, "faccessat2 (flag=0x01) was blocked with ENOSYS");
ok(
rv === lazy.LIBC.ENOSYS,
"faccessat2 (flag=0x01) was blocked with ENOSYS"
);
rv = await SpecialPowers.spawn(
browser,
[{ lib, dirfd, path, mode, flag: AT_EACCESS }],
[{ lib, dirfd, path, mode, flag: lazy.LIBC.AT_EACCESS }],
callFaccessat2
);
ok(
rv === ERRNO.EACCES,
rv === lazy.LIBC.EACCES,
"faccessat2 (flag=0x200) was allowed, errno=EACCES"
);
} else {

Просмотреть файл

@ -5,13 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
if (typeof Components !== "undefined") {
/* global OS */
Cc["@mozilla.org/net/osfileconstantsservice;1"]
.getService(Ci.nsIOSFileConstantsService)
.init();
}
/* exported LIBC, libc */
// ctypes is either already available in the chrome worker scope, or defined
@ -21,7 +14,7 @@ if (typeof Components !== "undefined") {
// This file is loaded into the same scope as subprocess_shared.js.
/* import-globals-from subprocess_shared.js */
var LIBC = OS.Constants.libc;
var LIBC = ChromeUtils.getLibcConstants();
const LIBC_CHOICES = ["libc.so", "libSystem.B.dylib", "a.out"];

Просмотреть файл

@ -5,14 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
if (typeof Components !== "undefined") {
/* global OS */
Cc["@mozilla.org/net/osfileconstantsservice;1"]
.getService(Ci.nsIOSFileConstantsService)
.init();
}
/* exported LIBC, Win, createPipe, libc, win32 */
/* exported createPipe, libc, win32 */
// ctypes is either already available in the chrome worker scope, or defined
// in scope via loadSubScript.
@ -21,10 +14,6 @@ if (typeof Components !== "undefined") {
// This file is loaded into the same scope as subprocess_shared.js.
/* import-globals-from subprocess_shared.js */
const LIBC = OS.Constants.libc;
const Win = OS.Constants.Win;
const LIBC_CHOICES = ["kernel32.dll"];
var win32 = {
@ -99,8 +88,13 @@ Object.assign(win32, {
ERROR_BROKEN_PIPE: 109,
ERROR_INSUFFICIENT_BUFFER: 122,
FILE_ATTRIBUTE_NORMAL: 0x00000080,
FILE_FLAG_OVERLAPPED: 0x40000000,
GENERIC_WRITE: 0x40000000,
OPEN_EXISTING: 0x00000003,
PIPE_TYPE_BYTE: 0x00,
PIPE_ACCESS_INBOUND: 0x01,
@ -450,7 +444,7 @@ win32.Handle = function (handle) {
win32.createPipe = function (secAttr, readFlags = 0, writeFlags = 0, size = 0) {
readFlags |= win32.PIPE_ACCESS_INBOUND;
writeFlags |= Win.FILE_ATTRIBUTE_NORMAL;
writeFlags |= win32.FILE_ATTRIBUTE_NORMAL;
if (size == 0) {
size = 4096;
@ -471,7 +465,7 @@ win32.createPipe = function (secAttr, readFlags = 0, writeFlags = 0, size = 0) {
);
let isInvalid = handle =>
String(handle) == String(win32.HANDLE(Win.INVALID_HANDLE_VALUE));
String(handle) == String(win32.INVALID_HANDLE_VALUE);
if (isInvalid(readHandle)) {
return [];
@ -479,10 +473,10 @@ win32.createPipe = function (secAttr, readFlags = 0, writeFlags = 0, size = 0) {
let writeHandle = libc.CreateFileW(
pipeName,
Win.GENERIC_WRITE,
win32.GENERIC_WRITE,
0,
secAttr.address(),
Win.OPEN_EXISTING,
win32.OPEN_EXISTING,
writeFlags,
null
);