@modelprofile.com/browser-runtime 3.2.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1230 @@
1
+ import * as plugins from './plugins.js';
2
+ import { BrowserRuntimeError } from './errors.js';
3
+ import { randomId } from './utils.js';
4
+ const metadataSchema = 1;
5
+ const maximumMetadataBytes = 4096;
6
+ const maximumProcFileBytes = 2 * 1024 * 1024;
7
+ const anchorInitializationAttempts = 200;
8
+ const generationIdPattern = /^[A-Za-z0-9_-]{32}$/u;
9
+ const hashPattern = /^[a-f0-9]{64}$/u;
10
+ const bootIdPattern = /^[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/u;
11
+ const unsignedIntegerPattern = /^(?:0|[1-9][0-9]{0,24})$/u;
12
+ const isMissingError = (errorArg) => (errorArg.code === 'ENOENT'
13
+ || errorArg.code === 'ESRCH');
14
+ const normalizeOwnershipError = (errorArg) => (errorArg instanceof BrowserRuntimeError
15
+ ? errorArg
16
+ : new BrowserRuntimeError('FENCED', 'runtime ownership could not be verified'));
17
+ const statIdentityMatches = (leftArg, rightArg) => leftArg.dev === rightArg.dev && leftArg.ino === rightArg.ino;
18
+ const parseProcessStartTicks = (statTextArg, expectedPidArg) => {
19
+ if (plugins.Buffer.byteLength(statTextArg, 'utf8') === 0
20
+ || plugins.Buffer.byteLength(statTextArg, 'utf8') > 16 * 1024
21
+ || /[\u0000\r]/u.test(statTextArg))
22
+ throw new BrowserRuntimeError('FENCED', 'process identity is malformed');
23
+ const statText = statTextArg.endsWith('\n') ? statTextArg.slice(0, -1) : statTextArg;
24
+ if (statText.includes('\n')) {
25
+ throw new BrowserRuntimeError('FENCED', 'process identity is malformed');
26
+ }
27
+ const commandStart = statText.indexOf(' (');
28
+ const commandEnd = statText.lastIndexOf(') ');
29
+ if (commandStart <= 0 || commandEnd < commandStart + 2) {
30
+ throw new BrowserRuntimeError('FENCED', 'process identity is malformed');
31
+ }
32
+ const pidText = statText.slice(0, commandStart);
33
+ const fieldsAfterCommand = statText.slice(commandEnd + 2).split(' ');
34
+ const processStartTicks = fieldsAfterCommand[19];
35
+ if (!/^[1-9][0-9]{0,9}$/u.test(pidText)
36
+ || fieldsAfterCommand.length < 20
37
+ || !processStartTicks
38
+ || !unsignedIntegerPattern.test(processStartTicks))
39
+ throw new BrowserRuntimeError('FENCED', 'process identity is malformed');
40
+ if (expectedPidArg !== undefined && Number(pidText) !== expectedPidArg) {
41
+ throw new BrowserRuntimeError('FENCED', 'process identity is malformed');
42
+ }
43
+ return processStartTicks;
44
+ };
45
+ export class BrowserRuntimeOwnership {
46
+ runtimeDirectory;
47
+ lockPath;
48
+ anchorDirectory;
49
+ generationsRoot;
50
+ legacyProfileRoot;
51
+ legacyArtifactRoot;
52
+ uid;
53
+ procRoot;
54
+ now;
55
+ beforeMetadataPublication;
56
+ beforeGenerationRemoval;
57
+ onOwnershipLost;
58
+ directoryHandle;
59
+ directoryIdentity;
60
+ anchorDirectoryHandle;
61
+ anchorDirectoryIdentity;
62
+ anchorIdentity;
63
+ namedMutex;
64
+ namedMutexLease;
65
+ lockHandle;
66
+ lockIdentity;
67
+ createdLock = false;
68
+ leaseLost = false;
69
+ metadata;
70
+ generation;
71
+ acquirePromise;
72
+ releasePromise;
73
+ constructor(optionsArg) {
74
+ this.runtimeDirectory = plugins.path.resolve(optionsArg.runtimeDirectory);
75
+ this.lockPath = plugins.path.join(this.runtimeDirectory, 'runtime.lock');
76
+ this.anchorDirectory = plugins.path.join(this.runtimeDirectory, 'runtime.mutex');
77
+ this.generationsRoot = plugins.path.join(this.runtimeDirectory, 'generations');
78
+ this.legacyProfileRoot = plugins.path.join(this.runtimeDirectory, 'profiles');
79
+ this.legacyArtifactRoot = plugins.path.join(this.runtimeDirectory, 'artifacts');
80
+ this.uid = optionsArg.uid;
81
+ this.procRoot = optionsArg.testing?.procRoot ?? '/proc';
82
+ this.now = optionsArg.testing?.now ?? Date.now;
83
+ this.beforeMetadataPublication = optionsArg.testing?.beforeMetadataPublication;
84
+ this.beforeGenerationRemoval = optionsArg.testing?.beforeGenerationRemoval;
85
+ this.onOwnershipLost = optionsArg.onOwnershipLost;
86
+ }
87
+ get owned() {
88
+ return Boolean(this.metadata?.state === 'active'
89
+ && this.generation
90
+ && this.namedMutexLease?.state === 'active'
91
+ && !this.leaseLost);
92
+ }
93
+ get cleanupPending() {
94
+ return Boolean(this.lockHandle
95
+ || this.anchorDirectoryHandle
96
+ || this.directoryHandle
97
+ || (this.namedMutexLease && this.namedMutexLease.state !== 'released'));
98
+ }
99
+ acquire() {
100
+ if (this.owned)
101
+ return Promise.resolve({ ...this.generation });
102
+ if (this.acquirePromise)
103
+ return this.acquirePromise;
104
+ if (this.releasePromise)
105
+ return this.releasePromise.then(() => this.acquire());
106
+ const operation = this.acquireInternal().finally(() => {
107
+ if (this.acquirePromise === operation)
108
+ this.acquirePromise = undefined;
109
+ });
110
+ this.acquirePromise = operation;
111
+ return operation;
112
+ }
113
+ release(reasonArg = 'stop') {
114
+ if (this.releasePromise)
115
+ return this.releasePromise;
116
+ if (!this.namedMutexLease
117
+ && !this.lockHandle
118
+ && !this.anchorDirectoryHandle
119
+ && !this.directoryHandle)
120
+ return Promise.resolve();
121
+ const operation = this.releaseInternal(reasonArg).catch((error) => {
122
+ throw normalizeOwnershipError(error);
123
+ }).finally(() => {
124
+ if (this.releasePromise === operation)
125
+ this.releasePromise = undefined;
126
+ });
127
+ this.releasePromise = operation;
128
+ return operation;
129
+ }
130
+ /** @internal */
131
+ async assertCurrentOwnership() {
132
+ if (!this.owned)
133
+ throw new BrowserRuntimeError('FENCED', 'runtime ownership is unavailable');
134
+ await this.assertRuntimeDirectoryCurrent();
135
+ await this.assertNativeAnchorCurrent();
136
+ await this.assertLockPathCurrent();
137
+ }
138
+ async acquireInternal() {
139
+ try {
140
+ await this.openAndValidateRuntimeDirectory();
141
+ await this.openAndValidateAnchorDirectory();
142
+ await this.acquireNativeLease();
143
+ const lockKind = await this.openAndClassifyLock();
144
+ if (lockKind.kind === 'new') {
145
+ await this.adoptCreatedLockLayout();
146
+ }
147
+ else if (lockKind.kind === 'legacy') {
148
+ await this.adoptLegacyLock();
149
+ }
150
+ else {
151
+ await this.reclaimMetadataGeneration(lockKind.metadata);
152
+ }
153
+ const generation = await this.publishGeneration();
154
+ return { ...generation };
155
+ }
156
+ catch (error) {
157
+ const normalized = normalizeOwnershipError(error);
158
+ if (this.metadata?.state === 'active' && this.generation) {
159
+ try {
160
+ await this.release('startup-failure');
161
+ }
162
+ catch {
163
+ throw new BrowserRuntimeError('FENCED', 'runtime startup cleanup is incomplete');
164
+ }
165
+ }
166
+ else {
167
+ if (this.createdLock) {
168
+ let cleanupError;
169
+ try {
170
+ await this.unlinkCreatedLock();
171
+ }
172
+ catch (error) {
173
+ cleanupError = error;
174
+ }
175
+ if (cleanupError && this.createdLock) {
176
+ throw new BrowserRuntimeError('FENCED', 'runtime startup cleanup is incomplete');
177
+ }
178
+ if (cleanupError) {
179
+ await this.closePassiveHandles().catch(() => {
180
+ throw new BrowserRuntimeError('FENCED', 'runtime startup cleanup is incomplete');
181
+ });
182
+ throw new BrowserRuntimeError('FENCED', 'runtime startup cleanup is incomplete');
183
+ }
184
+ }
185
+ await this.closePassiveHandles();
186
+ }
187
+ throw normalized;
188
+ }
189
+ }
190
+ async openAndValidateRuntimeDirectory() {
191
+ const createdPath = await plugins.fsPromises.mkdir(this.runtimeDirectory, {
192
+ recursive: true,
193
+ mode: 0o700,
194
+ });
195
+ let pathStat = await plugins.fsPromises.lstat(this.runtimeDirectory, { bigint: true });
196
+ if (!pathStat.isDirectory()
197
+ || pathStat.isSymbolicLink()
198
+ || pathStat.uid !== BigInt(this.uid))
199
+ throw new BrowserRuntimeError('FENCED', 'runtime directory is not private');
200
+ if (createdPath !== undefined) {
201
+ await plugins.fsPromises.chmod(this.runtimeDirectory, 0o700);
202
+ pathStat = await plugins.fsPromises.lstat(this.runtimeDirectory, { bigint: true });
203
+ }
204
+ if ((pathStat.mode & 511n) !== 448n) {
205
+ throw new BrowserRuntimeError('FENCED', 'runtime directory is not private');
206
+ }
207
+ const realPath = await plugins.fsPromises.realpath(this.runtimeDirectory);
208
+ if (realPath !== this.runtimeDirectory) {
209
+ throw new BrowserRuntimeError('FENCED', 'runtime directory path is not canonical');
210
+ }
211
+ const handle = await plugins.fsPromises.open(this.runtimeDirectory, plugins.fs.constants.O_RDONLY
212
+ | plugins.fs.constants.O_DIRECTORY
213
+ | plugins.fs.constants.O_NOFOLLOW);
214
+ this.directoryHandle = handle;
215
+ let handleStat = await handle.stat({ bigint: true });
216
+ if (createdPath !== undefined) {
217
+ await handle.chmod(0o700);
218
+ await plugins.fsPromises.chmod(this.runtimeDirectory, 0o700);
219
+ [pathStat, handleStat] = await Promise.all([
220
+ plugins.fsPromises.lstat(this.runtimeDirectory, { bigint: true }),
221
+ handle.stat({ bigint: true }),
222
+ ]);
223
+ }
224
+ if (!handleStat.isDirectory()
225
+ || handleStat.uid !== BigInt(this.uid)
226
+ || (handleStat.mode & 511n) !== 448n
227
+ || !statIdentityMatches(pathStat, handleStat)) {
228
+ throw new BrowserRuntimeError('FENCED', 'runtime directory identity changed');
229
+ }
230
+ const pathHash = plugins.crypto.createHash('sha256')
231
+ .update(this.runtimeDirectory, 'utf8')
232
+ .digest('hex');
233
+ const device = String(handleStat.dev);
234
+ const inode = String(handleStat.ino);
235
+ const hash = plugins.crypto.createHash('sha256')
236
+ .update(`${this.uid}\0${device}\0${inode}\0${pathHash}`, 'utf8')
237
+ .digest('hex');
238
+ this.directoryIdentity = { uid: this.uid, device, inode, hash };
239
+ }
240
+ async openAndValidateAnchorDirectory() {
241
+ await this.ensurePrivateDirectory(this.anchorDirectory, this.runtimeDirectory);
242
+ const handle = await plugins.fsPromises.open(this.anchorDirectory, plugins.fs.constants.O_RDONLY
243
+ | plugins.fs.constants.O_DIRECTORY
244
+ | plugins.fs.constants.O_NOFOLLOW);
245
+ try {
246
+ const [pathStat, handleStat] = await Promise.all([
247
+ plugins.fsPromises.lstat(this.anchorDirectory, { bigint: true }),
248
+ handle.stat({ bigint: true }),
249
+ ]);
250
+ if (!pathStat.isDirectory()
251
+ || pathStat.isSymbolicLink()
252
+ || pathStat.uid !== BigInt(this.uid)
253
+ || (pathStat.mode & 511n) !== 448n
254
+ || !statIdentityMatches(pathStat, handleStat)
255
+ || String(handleStat.dev) !== this.directoryIdentity.device)
256
+ throw new BrowserRuntimeError('FENCED', 'runtime mutex anchor directory is unsafe');
257
+ this.anchorDirectoryHandle = handle;
258
+ this.anchorDirectoryIdentity = handleStat;
259
+ }
260
+ catch (error) {
261
+ await handle.close().catch(() => undefined);
262
+ throw error;
263
+ }
264
+ }
265
+ async acquireNativeLease() {
266
+ const identity = this.directoryIdentity;
267
+ let mutex;
268
+ try {
269
+ mutex = new plugins.smartipc.NamedMutex(`@modelprofile.com/browser-runtime:v1:${identity.uid}:${identity.device}:${identity.inode}:${identity.hash}`, { directoryPath: this.anchorDirectory });
270
+ }
271
+ catch {
272
+ throw new BrowserRuntimeError('FENCED', 'runtime native ownership backend is unavailable');
273
+ }
274
+ await this.ensurePermanentAnchor(mutex.anchorPath);
275
+ let lease;
276
+ try {
277
+ lease = await mutex.tryAcquire();
278
+ }
279
+ catch {
280
+ throw new BrowserRuntimeError('FENCED', 'runtime native ownership could not be verified');
281
+ }
282
+ if (!lease)
283
+ throw new BrowserRuntimeError('LOCKED');
284
+ this.namedMutex = mutex;
285
+ this.namedMutexLease = lease;
286
+ this.leaseLost = false;
287
+ this.anchorIdentity = await plugins.fsPromises.lstat(mutex.anchorPath, { bigint: true });
288
+ await this.assertNativeAnchorCurrent();
289
+ }
290
+ async ensurePermanentAnchor(anchorPathArg) {
291
+ if (!this.pathIsWithin(this.anchorDirectory, anchorPathArg)
292
+ || plugins.path.dirname(anchorPathArg) !== this.anchorDirectory)
293
+ throw new BrowserRuntimeError('FENCED', 'runtime mutex anchor escaped containment');
294
+ const anchorName = plugins.path.basename(anchorPathArg);
295
+ const entries = await plugins.fsPromises.readdir(this.anchorDirectory, { withFileTypes: true });
296
+ if (entries.some((entry) => entry.name !== anchorName)) {
297
+ throw new BrowserRuntimeError('FENCED', 'runtime mutex anchor directory is ambiguous');
298
+ }
299
+ let handle;
300
+ try {
301
+ handle = await plugins.fsPromises.open(anchorPathArg, plugins.fs.constants.O_RDWR
302
+ | plugins.fs.constants.O_CREAT
303
+ | plugins.fs.constants.O_EXCL
304
+ | plugins.fs.constants.O_NOFOLLOW, 0o600);
305
+ }
306
+ catch (error) {
307
+ if (error.code !== 'EEXIST')
308
+ throw error;
309
+ for (let attempt = 0; attempt < anchorInitializationAttempts; attempt += 1) {
310
+ const stat = await plugins.fsPromises.lstat(anchorPathArg, { bigint: true });
311
+ if (stat.isFile()
312
+ && !stat.isSymbolicLink()
313
+ && stat.uid === BigInt(this.uid)
314
+ && stat.nlink === 1n
315
+ && stat.size === 0n
316
+ && String(stat.dev) === this.directoryIdentity.device) {
317
+ const mode = stat.mode & 511n;
318
+ if (mode === 384n)
319
+ return;
320
+ if ((mode & 127n) !== 0n) {
321
+ throw new BrowserRuntimeError('FENCED', 'runtime mutex anchor is unsafe');
322
+ }
323
+ await new Promise((resolve) => setTimeout(resolve, 10));
324
+ continue;
325
+ }
326
+ throw new BrowserRuntimeError('FENCED', 'runtime mutex anchor is unsafe');
327
+ }
328
+ throw new BrowserRuntimeError('FENCED', 'runtime mutex anchor initialization is incomplete');
329
+ }
330
+ try {
331
+ await handle.chmod(0o600);
332
+ await plugins.fsPromises.chmod(anchorPathArg, 0o600);
333
+ const [pathStat, handleStat] = await Promise.all([
334
+ plugins.fsPromises.lstat(anchorPathArg, { bigint: true }),
335
+ handle.stat({ bigint: true }),
336
+ ]);
337
+ this.assertPrivateAnchorStat(pathStat);
338
+ this.assertPrivateAnchorStat(handleStat);
339
+ if (!statIdentityMatches(pathStat, handleStat)) {
340
+ throw new BrowserRuntimeError('FENCED', 'runtime mutex anchor identity changed');
341
+ }
342
+ await handle.sync();
343
+ await this.anchorDirectoryHandle.sync();
344
+ }
345
+ finally {
346
+ await handle.close();
347
+ }
348
+ }
349
+ assertPrivateAnchorStat(statArg) {
350
+ if (!statArg.isFile()
351
+ || statArg.isSymbolicLink()
352
+ || statArg.uid !== BigInt(this.uid)
353
+ || (statArg.mode & 511n) !== 384n
354
+ || statArg.nlink !== 1n
355
+ || statArg.size !== 0n
356
+ || String(statArg.dev) !== this.directoryIdentity.device)
357
+ throw new BrowserRuntimeError('FENCED', 'runtime mutex anchor is unsafe');
358
+ }
359
+ async assertNativeAnchorCurrent() {
360
+ if (!this.namedMutex
361
+ || !this.namedMutexLease
362
+ || this.namedMutexLease.state !== 'active'
363
+ || !this.anchorIdentity
364
+ || !this.anchorDirectoryHandle
365
+ || !this.anchorDirectoryIdentity
366
+ || this.leaseLost)
367
+ throw new BrowserRuntimeError('FENCED', 'runtime native ownership is unavailable');
368
+ const [directoryPathStat, directoryHandleStat, anchorStat] = await Promise.all([
369
+ plugins.fsPromises.lstat(this.anchorDirectory, { bigint: true }),
370
+ this.anchorDirectoryHandle.stat({ bigint: true }),
371
+ plugins.fsPromises.lstat(this.namedMutex.anchorPath, { bigint: true }),
372
+ ]);
373
+ if (!directoryPathStat.isDirectory()
374
+ || directoryPathStat.isSymbolicLink()
375
+ || directoryPathStat.uid !== BigInt(this.uid)
376
+ || (directoryPathStat.mode & 511n) !== 448n
377
+ || !statIdentityMatches(this.anchorDirectoryIdentity, directoryPathStat)
378
+ || !statIdentityMatches(this.anchorDirectoryIdentity, directoryHandleStat)
379
+ || String(directoryHandleStat.dev) !== this.directoryIdentity.device)
380
+ throw new BrowserRuntimeError('FENCED', 'runtime mutex anchor directory identity changed');
381
+ this.assertPrivateAnchorStat(anchorStat);
382
+ if (!statIdentityMatches(this.anchorIdentity, anchorStat)) {
383
+ throw new BrowserRuntimeError('FENCED', 'runtime mutex anchor identity changed');
384
+ }
385
+ }
386
+ /** @internal */
387
+ async forceOwnershipLossForTesting() {
388
+ if (!this.namedMutexLease || this.leaseLost)
389
+ return;
390
+ let releaseError;
391
+ try {
392
+ await this.namedMutexLease.release();
393
+ }
394
+ catch (error) {
395
+ releaseError = error;
396
+ }
397
+ this.leaseLost = true;
398
+ this.onOwnershipLost?.();
399
+ if (releaseError) {
400
+ throw new BrowserRuntimeError('FENCED', 'runtime native ownership release is uncertain');
401
+ }
402
+ }
403
+ async openAndClassifyLock() {
404
+ let handle;
405
+ try {
406
+ handle = await plugins.fsPromises.open(this.lockPath, plugins.fs.constants.O_RDWR
407
+ | plugins.fs.constants.O_CREAT
408
+ | plugins.fs.constants.O_EXCL
409
+ | plugins.fs.constants.O_NOFOLLOW, 0o600);
410
+ }
411
+ catch (error) {
412
+ if (error.code !== 'EEXIST')
413
+ throw error;
414
+ const pathStat = await this.readPrivateLockPathStat();
415
+ handle = await plugins.fsPromises.open(this.lockPath, plugins.fs.constants.O_RDWR | plugins.fs.constants.O_NOFOLLOW);
416
+ let handleStat;
417
+ try {
418
+ handleStat = await this.validateLockHandle(handle);
419
+ }
420
+ catch (validationError) {
421
+ await handle.close().catch(() => undefined);
422
+ throw validationError;
423
+ }
424
+ if (!statIdentityMatches(pathStat, handleStat)) {
425
+ await handle.close();
426
+ throw new BrowserRuntimeError('FENCED', 'runtime lock identity changed');
427
+ }
428
+ this.lockHandle = handle;
429
+ this.lockIdentity = handleStat;
430
+ await this.assertLockPathCurrent();
431
+ if (handleStat.size === 0n)
432
+ return { kind: 'legacy' };
433
+ return { kind: 'metadata', metadata: await this.readMetadata() };
434
+ }
435
+ this.lockHandle = handle;
436
+ this.createdLock = true;
437
+ await handle.chmod(0o600);
438
+ const initialHandleStat = await handle.stat({ bigint: true });
439
+ const initialPathStat = await plugins.fsPromises.lstat(this.lockPath, { bigint: true });
440
+ if (!initialHandleStat.isFile()
441
+ || !initialPathStat.isFile()
442
+ || initialPathStat.isSymbolicLink()
443
+ || !statIdentityMatches(initialHandleStat, initialPathStat)
444
+ || initialHandleStat.uid !== BigInt(this.uid)
445
+ || initialHandleStat.nlink !== 1n
446
+ || initialHandleStat.size !== 0n)
447
+ throw new BrowserRuntimeError('FENCED', 'runtime lock is unsafe');
448
+ this.lockIdentity = initialHandleStat;
449
+ await plugins.fsPromises.chmod(this.lockPath, 0o600);
450
+ await handle.chmod(0o600);
451
+ this.lockIdentity = await this.validateLockHandle(handle);
452
+ await this.assertLockPathCurrent();
453
+ await this.directoryHandle.sync();
454
+ return { kind: 'new' };
455
+ }
456
+ async readPrivateLockPathStat() {
457
+ let stat;
458
+ try {
459
+ stat = await plugins.fsPromises.lstat(this.lockPath, { bigint: true });
460
+ }
461
+ catch (error) {
462
+ if (isMissingError(error)) {
463
+ throw new BrowserRuntimeError('FENCED', 'runtime lock identity changed');
464
+ }
465
+ throw error;
466
+ }
467
+ this.assertPrivateLockStat(stat);
468
+ return stat;
469
+ }
470
+ async validateLockHandle(handleArg) {
471
+ const stat = await handleArg.stat({ bigint: true });
472
+ this.assertPrivateLockStat(stat);
473
+ return stat;
474
+ }
475
+ assertPrivateLockStat(statArg) {
476
+ if (!statArg.isFile()
477
+ || statArg.isSymbolicLink()
478
+ || statArg.uid !== BigInt(this.uid)
479
+ || (statArg.mode & 511n) !== 384n
480
+ || statArg.nlink !== 1n
481
+ || statArg.size > BigInt(maximumMetadataBytes))
482
+ throw new BrowserRuntimeError('FENCED', 'runtime lock is unsafe');
483
+ }
484
+ async assertLockPathCurrent() {
485
+ if (!this.lockHandle || !this.lockIdentity) {
486
+ throw new BrowserRuntimeError('FENCED', 'runtime lock is unavailable');
487
+ }
488
+ const [pathStat, handleStat] = await Promise.all([
489
+ this.readPrivateLockPathStat(),
490
+ this.validateLockHandle(this.lockHandle),
491
+ ]);
492
+ if (!statIdentityMatches(this.lockIdentity, pathStat)
493
+ || !statIdentityMatches(this.lockIdentity, handleStat))
494
+ throw new BrowserRuntimeError('FENCED', 'runtime lock identity changed');
495
+ }
496
+ async adoptCreatedLockLayout() {
497
+ await this.assertRuntimeEntries(new Set([
498
+ 'runtime.lock',
499
+ 'runtime.mutex',
500
+ 'profiles',
501
+ 'artifacts',
502
+ ]));
503
+ await this.validateOptionalPrivateDirectory(this.legacyProfileRoot);
504
+ await this.validateOptionalPrivateDirectory(this.legacyArtifactRoot);
505
+ const [profileInspection, profileEntries, artifactEntries] = await Promise.all([
506
+ this.inspectProfileProcesses([this.legacyProfileRoot]),
507
+ this.readOptionalDirectoryEntries(this.legacyProfileRoot),
508
+ this.readOptionalDirectoryEntries(this.legacyArtifactRoot),
509
+ ]);
510
+ if (profileInspection === 'held')
511
+ throw new BrowserRuntimeError('LOCKED');
512
+ if (profileInspection === 'indeterminate') {
513
+ throw new BrowserRuntimeError('FENCED', 'legacy runtime process ownership is indeterminate');
514
+ }
515
+ if (profileEntries.length > 0 || artifactEntries.length > 0) {
516
+ throw new BrowserRuntimeError('FENCED', 'legacy runtime roots are not empty');
517
+ }
518
+ await this.assertLockPathCurrent();
519
+ await this.assertNativeAnchorCurrent();
520
+ await this.assertRuntimeDirectoryCurrent();
521
+ const [currentProfileEntries, currentArtifactEntries] = await Promise.all([
522
+ this.readOptionalDirectoryEntries(this.legacyProfileRoot),
523
+ this.readOptionalDirectoryEntries(this.legacyArtifactRoot),
524
+ ]);
525
+ if (currentProfileEntries.length > 0 || currentArtifactEntries.length > 0) {
526
+ throw new BrowserRuntimeError('FENCED', 'legacy runtime roots changed');
527
+ }
528
+ await this.removePrivateDirectory(this.legacyProfileRoot);
529
+ await this.removePrivateDirectory(this.legacyArtifactRoot);
530
+ await this.directoryHandle.sync();
531
+ }
532
+ async unlinkCreatedLock() {
533
+ if (!this.createdLock)
534
+ return;
535
+ if (!this.lockHandle) {
536
+ throw new BrowserRuntimeError('FENCED', 'created runtime lock is unavailable');
537
+ }
538
+ await this.assertNativeAnchorCurrent();
539
+ await this.assertRuntimeDirectoryCurrent();
540
+ const [pathStat, handleStat] = await Promise.all([
541
+ plugins.fsPromises.lstat(this.lockPath, { bigint: true }),
542
+ this.lockHandle.stat({ bigint: true }),
543
+ ]);
544
+ if (!pathStat.isFile()
545
+ || pathStat.isSymbolicLink()
546
+ || !handleStat.isFile()
547
+ || pathStat.uid !== BigInt(this.uid)
548
+ || handleStat.uid !== BigInt(this.uid)
549
+ || pathStat.nlink !== 1n
550
+ || handleStat.nlink !== 1n
551
+ || String(pathStat.dev) !== this.directoryIdentity.device
552
+ || !statIdentityMatches(pathStat, handleStat)
553
+ || (this.lockIdentity && !statIdentityMatches(this.lockIdentity, handleStat)))
554
+ throw new BrowserRuntimeError('FENCED', 'created runtime lock identity changed');
555
+ await plugins.fsPromises.unlink(this.lockPath);
556
+ this.createdLock = false;
557
+ await this.directoryHandle.sync();
558
+ }
559
+ async adoptLegacyLock() {
560
+ await this.assertRuntimeEntries(new Set([
561
+ 'runtime.lock',
562
+ 'runtime.mutex',
563
+ 'profiles',
564
+ 'artifacts',
565
+ ]));
566
+ await this.validateOptionalPrivateDirectory(this.legacyProfileRoot);
567
+ await this.validateOptionalPrivateDirectory(this.legacyArtifactRoot);
568
+ const [descriptorInspection, profileInspection, predatesBoot] = await Promise.all([
569
+ this.inspectLegacyLockDescriptors(),
570
+ this.inspectProfileProcesses([this.legacyProfileRoot]),
571
+ this.legacyLockPredatesCurrentBoot(),
572
+ ]);
573
+ if (descriptorInspection === 'held' || profileInspection === 'held') {
574
+ throw new BrowserRuntimeError('LOCKED');
575
+ }
576
+ if (descriptorInspection === 'indeterminate' || profileInspection === 'indeterminate') {
577
+ throw new BrowserRuntimeError('FENCED', 'legacy runtime ownership is indeterminate');
578
+ }
579
+ if (!predatesBoot) {
580
+ throw new BrowserRuntimeError('FENCED', 'same-boot legacy runtime ownership is unsafe');
581
+ }
582
+ await this.assertLockPathCurrent();
583
+ if (!await this.legacyLockPredatesCurrentBoot()) {
584
+ throw new BrowserRuntimeError('FENCED', 'legacy runtime lock timestamp changed');
585
+ }
586
+ await this.assertNativeAnchorCurrent();
587
+ await this.assertRuntimeDirectoryCurrent();
588
+ await this.removePrivateDirectory(this.legacyProfileRoot);
589
+ await this.removePrivateDirectory(this.legacyArtifactRoot);
590
+ await this.directoryHandle.sync();
591
+ }
592
+ async legacyLockPredatesCurrentBoot() {
593
+ const bootTimeNs = await this.readBootTimeNs();
594
+ const [pathStat, handleStat] = await Promise.all([
595
+ this.readPrivateLockPathStat(),
596
+ this.validateLockHandle(this.lockHandle),
597
+ ]);
598
+ if (!statIdentityMatches(this.lockIdentity, pathStat)
599
+ || !statIdentityMatches(this.lockIdentity, handleStat))
600
+ throw new BrowserRuntimeError('FENCED', 'legacy runtime lock identity changed');
601
+ const pathTimestamps = [pathStat.birthtimeNs, pathStat.ctimeNs, pathStat.mtimeNs];
602
+ const handleTimestamps = [handleStat.birthtimeNs, handleStat.ctimeNs, handleStat.mtimeNs];
603
+ if (pathTimestamps.some((timestamp, index) => (timestamp <= 0n || timestamp !== handleTimestamps[index])))
604
+ throw new BrowserRuntimeError('FENCED', 'legacy runtime lock timestamps are ambiguous');
605
+ return pathTimestamps.every((timestamp) => timestamp < bootTimeNs);
606
+ }
607
+ async readBootTimeNs() {
608
+ const procStat = await this.readBoundedFile(plugins.path.join(this.procRoot, 'stat'), maximumProcFileBytes);
609
+ if (/\u0000|\r/u.test(procStat)) {
610
+ throw new BrowserRuntimeError('FENCED', 'boot timestamp is malformed');
611
+ }
612
+ const bootTimeLines = procStat.split('\n').filter((line) => line.startsWith('btime'));
613
+ if (bootTimeLines.length !== 1) {
614
+ throw new BrowserRuntimeError('FENCED', 'boot timestamp is malformed');
615
+ }
616
+ const match = /^btime ([1-9][0-9]{0,19})$/u.exec(bootTimeLines[0]);
617
+ if (!match)
618
+ throw new BrowserRuntimeError('FENCED', 'boot timestamp is malformed');
619
+ const bootTimeNs = BigInt(match[1]) * 1000000000n;
620
+ const now = this.now();
621
+ if (!Number.isSafeInteger(now) || now < 0) {
622
+ throw new BrowserRuntimeError('FENCED', 'current timestamp is unavailable');
623
+ }
624
+ const nowNs = BigInt(now) * 1000000n;
625
+ if (bootTimeNs > nowNs) {
626
+ throw new BrowserRuntimeError('FENCED', 'boot timestamp is in the future');
627
+ }
628
+ return bootTimeNs;
629
+ }
630
+ async reclaimMetadataGeneration(metadataArg) {
631
+ this.assertMetadataDirectoryIdentity(metadataArg);
632
+ await this.assertRuntimeEntries(new Set([
633
+ 'runtime.lock',
634
+ 'runtime.mutex',
635
+ 'generations',
636
+ ]));
637
+ await this.validateOptionalPrivateDirectory(this.generationsRoot);
638
+ const generationDirectory = this.generationPath(metadataArg.generationId);
639
+ const entries = await this.readOptionalDirectoryEntries(this.generationsRoot);
640
+ if (entries.some((entry) => entry.name !== metadataArg.generationId)) {
641
+ throw new BrowserRuntimeError('FENCED', 'runtime generation ownership is ambiguous');
642
+ }
643
+ await this.validateOptionalGeneration(generationDirectory);
644
+ const profileInspection = await this.inspectProfileProcesses([
645
+ plugins.path.join(generationDirectory, 'profiles'),
646
+ ]);
647
+ if (profileInspection === 'held')
648
+ throw new BrowserRuntimeError('LOCKED');
649
+ if (profileInspection === 'indeterminate') {
650
+ throw new BrowserRuntimeError('FENCED', 'runtime process ownership is indeterminate');
651
+ }
652
+ await this.assertLockPathCurrent();
653
+ await this.assertNativeAnchorCurrent();
654
+ await this.assertRuntimeDirectoryCurrent();
655
+ await this.beforeGenerationRemoval?.('stale');
656
+ await this.assertLockPathCurrent();
657
+ await this.assertNativeAnchorCurrent();
658
+ await this.assertRuntimeDirectoryCurrent();
659
+ await this.removePrivateDirectory(generationDirectory);
660
+ await this.syncOptionalDirectory(this.generationsRoot);
661
+ }
662
+ async publishGeneration() {
663
+ const identity = this.directoryIdentity;
664
+ const generationId = randomId(24);
665
+ const metadata = {
666
+ schema: metadataSchema,
667
+ state: 'active',
668
+ uid: this.uid,
669
+ runtimeDirectoryDevice: identity.device,
670
+ runtimeDirectoryInode: identity.inode,
671
+ runtimeDirectoryHash: identity.hash,
672
+ bootId: await this.readBootId(),
673
+ pid: process.pid,
674
+ processStartTicks: parseProcessStartTicks(await this.readBoundedFile(plugins.path.join(this.procRoot, 'self', 'stat'), 16 * 1024), process.pid),
675
+ generationId,
676
+ nonce: randomId(24),
677
+ };
678
+ const generationDirectory = this.generationPath(generationId);
679
+ const generation = {
680
+ generationId,
681
+ generationDirectory,
682
+ profileRoot: plugins.path.join(generationDirectory, 'profiles'),
683
+ artifactRoot: plugins.path.join(generationDirectory, 'artifacts'),
684
+ };
685
+ await this.beforeMetadataPublication?.();
686
+ await this.writeMetadata(metadata);
687
+ this.metadata = metadata;
688
+ this.generation = generation;
689
+ await this.ensurePrivateDirectory(this.generationsRoot, this.runtimeDirectory);
690
+ const entries = await this.readOptionalDirectoryEntries(this.generationsRoot);
691
+ if (entries.length > 0) {
692
+ throw new BrowserRuntimeError('FENCED', 'runtime generation root is not empty');
693
+ }
694
+ await this.ensurePrivateDirectory(generationDirectory, this.generationsRoot);
695
+ await this.syncOptionalDirectory(this.generationsRoot);
696
+ return generation;
697
+ }
698
+ async releaseInternal(reasonArg) {
699
+ if (this.leaseLost) {
700
+ await this.closePassiveHandles().catch(() => undefined);
701
+ throw new BrowserRuntimeError('FENCED', 'runtime ownership was lost');
702
+ }
703
+ if (this.createdLock) {
704
+ await this.unlinkCreatedLock();
705
+ await this.closeOwnershipHandles();
706
+ this.metadata = undefined;
707
+ this.generation = undefined;
708
+ return;
709
+ }
710
+ const metadata = this.metadata;
711
+ const generation = this.generation;
712
+ if (metadata?.state === 'active' && generation) {
713
+ await this.assertLockPathCurrent();
714
+ await this.assertNativeAnchorCurrent();
715
+ await this.validateOptionalGeneration(generation.generationDirectory);
716
+ await this.assertLockPathCurrent();
717
+ await this.assertNativeAnchorCurrent();
718
+ await this.assertRuntimeDirectoryCurrent();
719
+ await this.beforeGenerationRemoval?.(reasonArg);
720
+ await this.assertLockPathCurrent();
721
+ await this.assertNativeAnchorCurrent();
722
+ await this.assertRuntimeDirectoryCurrent();
723
+ await this.removePrivateDirectory(generation.generationDirectory);
724
+ await this.syncOptionalDirectory(this.generationsRoot);
725
+ const relinquished = { ...metadata, state: 'relinquished' };
726
+ await this.writeMetadata(relinquished);
727
+ this.metadata = relinquished;
728
+ }
729
+ await this.closeOwnershipHandles();
730
+ this.metadata = undefined;
731
+ this.generation = undefined;
732
+ }
733
+ async closePassiveHandles() {
734
+ try {
735
+ await this.closeOwnershipHandles();
736
+ }
737
+ finally {
738
+ this.metadata = undefined;
739
+ this.generation = undefined;
740
+ }
741
+ }
742
+ async closeOwnershipHandles() {
743
+ const errors = [];
744
+ if (this.lockHandle) {
745
+ await this.lockHandle.close().then(() => {
746
+ this.lockHandle = undefined;
747
+ this.lockIdentity = undefined;
748
+ }, (error) => errors.push(error));
749
+ }
750
+ if (this.anchorDirectoryHandle) {
751
+ await this.anchorDirectoryHandle.close().then(() => {
752
+ this.anchorDirectoryHandle = undefined;
753
+ this.anchorDirectoryIdentity = undefined;
754
+ }, (error) => errors.push(error));
755
+ }
756
+ if (this.directoryHandle) {
757
+ await this.directoryHandle.close().then(() => {
758
+ this.directoryHandle = undefined;
759
+ this.directoryIdentity = undefined;
760
+ }, (error) => errors.push(error));
761
+ }
762
+ if (this.namedMutexLease) {
763
+ await this.namedMutexLease.release().then(() => {
764
+ this.namedMutexLease = undefined;
765
+ this.namedMutex = undefined;
766
+ this.anchorIdentity = undefined;
767
+ this.leaseLost = false;
768
+ }, (error) => errors.push(error));
769
+ }
770
+ if (errors.length > 0) {
771
+ throw new BrowserRuntimeError('FENCED', 'runtime ownership handles could not be closed');
772
+ }
773
+ }
774
+ async readMetadata() {
775
+ const stat = await this.lockHandle.stat({ bigint: true });
776
+ if (stat.size <= 0n || stat.size > BigInt(maximumMetadataBytes)) {
777
+ throw new BrowserRuntimeError('FENCED', 'runtime lock metadata is malformed');
778
+ }
779
+ const bytes = plugins.Buffer.alloc(Number(stat.size));
780
+ let bytesRead = 0;
781
+ while (bytesRead < bytes.byteLength) {
782
+ const result = await this.lockHandle.read(bytes, bytesRead, bytes.byteLength - bytesRead, bytesRead);
783
+ if (result.bytesRead <= 0) {
784
+ throw new BrowserRuntimeError('FENCED', 'runtime lock metadata is unreadable');
785
+ }
786
+ bytesRead += result.bytesRead;
787
+ }
788
+ let text;
789
+ try {
790
+ text = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
791
+ }
792
+ catch {
793
+ throw new BrowserRuntimeError('FENCED', 'runtime lock metadata is malformed');
794
+ }
795
+ if (!text.endsWith('\n') || text.slice(0, -1).includes('\n')) {
796
+ throw new BrowserRuntimeError('FENCED', 'runtime lock metadata is malformed');
797
+ }
798
+ const serialized = text.slice(0, -1);
799
+ let parsed;
800
+ try {
801
+ parsed = JSON.parse(serialized);
802
+ }
803
+ catch {
804
+ throw new BrowserRuntimeError('FENCED', 'runtime lock metadata is malformed');
805
+ }
806
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
807
+ throw new BrowserRuntimeError('FENCED', 'runtime lock metadata is malformed');
808
+ }
809
+ const record = parsed;
810
+ const expectedKeys = [
811
+ 'schema',
812
+ 'state',
813
+ 'uid',
814
+ 'runtimeDirectoryDevice',
815
+ 'runtimeDirectoryInode',
816
+ 'runtimeDirectoryHash',
817
+ 'bootId',
818
+ 'pid',
819
+ 'processStartTicks',
820
+ 'generationId',
821
+ 'nonce',
822
+ ];
823
+ if (Object.keys(record).length !== expectedKeys.length
824
+ || expectedKeys.some((key) => !(key in record))
825
+ || record.schema !== metadataSchema
826
+ || (record.state !== 'active' && record.state !== 'relinquished')
827
+ || !Number.isSafeInteger(record.uid)
828
+ || record.uid < 1
829
+ || typeof record.runtimeDirectoryDevice !== 'string'
830
+ || !unsignedIntegerPattern.test(record.runtimeDirectoryDevice)
831
+ || typeof record.runtimeDirectoryInode !== 'string'
832
+ || !unsignedIntegerPattern.test(record.runtimeDirectoryInode)
833
+ || typeof record.runtimeDirectoryHash !== 'string'
834
+ || !hashPattern.test(record.runtimeDirectoryHash)
835
+ || typeof record.bootId !== 'string'
836
+ || !bootIdPattern.test(record.bootId)
837
+ || !Number.isSafeInteger(record.pid)
838
+ || record.pid < 1
839
+ || typeof record.processStartTicks !== 'string'
840
+ || !unsignedIntegerPattern.test(record.processStartTicks)
841
+ || typeof record.generationId !== 'string'
842
+ || !generationIdPattern.test(record.generationId)
843
+ || typeof record.nonce !== 'string'
844
+ || !generationIdPattern.test(record.nonce)
845
+ || JSON.stringify(record) !== serialized)
846
+ throw new BrowserRuntimeError('FENCED', 'runtime lock metadata is malformed');
847
+ return record;
848
+ }
849
+ async writeMetadata(metadataArg) {
850
+ await this.assertLockPathCurrent();
851
+ await this.assertNativeAnchorCurrent();
852
+ const bytes = plugins.Buffer.from(`${JSON.stringify(metadataArg)}\n`, 'utf8');
853
+ if (bytes.byteLength > maximumMetadataBytes) {
854
+ throw new BrowserRuntimeError('FENCED', 'runtime lock metadata exceeds its bound');
855
+ }
856
+ let written = 0;
857
+ while (written < bytes.byteLength) {
858
+ const result = await this.lockHandle.write(bytes, written, bytes.byteLength - written, written);
859
+ if (result.bytesWritten <= 0) {
860
+ throw new BrowserRuntimeError('FENCED', 'runtime lock metadata write was incomplete');
861
+ }
862
+ written += result.bytesWritten;
863
+ }
864
+ await this.lockHandle.truncate(bytes.byteLength);
865
+ await this.lockHandle.sync();
866
+ this.createdLock = false;
867
+ await this.assertLockPathCurrent();
868
+ await this.assertNativeAnchorCurrent();
869
+ }
870
+ assertMetadataDirectoryIdentity(metadataArg) {
871
+ const identity = this.directoryIdentity;
872
+ if (metadataArg.uid !== identity.uid
873
+ || metadataArg.runtimeDirectoryDevice !== identity.device
874
+ || metadataArg.runtimeDirectoryInode !== identity.inode
875
+ || metadataArg.runtimeDirectoryHash !== identity.hash)
876
+ throw new BrowserRuntimeError('FENCED', 'runtime metadata belongs to another directory');
877
+ }
878
+ async inspectLegacyLockDescriptors() {
879
+ const lockIdentity = this.lockIdentity;
880
+ let indeterminate = false;
881
+ for (const pid of await this.listOwnedProcessIds()) {
882
+ let descriptorNames;
883
+ try {
884
+ descriptorNames = await plugins.fsPromises.readdir(plugins.path.join(this.procRoot, String(pid), 'fd'));
885
+ }
886
+ catch {
887
+ const uidState = await this.processStillExists(pid);
888
+ if (uidState === 'missing' || uidState === 'other')
889
+ continue;
890
+ indeterminate = true;
891
+ continue;
892
+ }
893
+ for (const descriptorName of descriptorNames) {
894
+ if (!/^(?:0|[1-9][0-9]*)$/u.test(descriptorName)) {
895
+ indeterminate = true;
896
+ continue;
897
+ }
898
+ const descriptor = Number(descriptorName);
899
+ if (pid === process.pid && descriptor === this.lockHandle.fd)
900
+ continue;
901
+ try {
902
+ const stat = await plugins.fsPromises.stat(plugins.path.join(this.procRoot, String(pid), 'fd', descriptorName), { bigint: true });
903
+ if (stat.dev === lockIdentity.dev && stat.ino === lockIdentity.ino)
904
+ return 'held';
905
+ }
906
+ catch (error) {
907
+ if (isMissingError(error))
908
+ continue;
909
+ indeterminate = true;
910
+ }
911
+ }
912
+ }
913
+ return indeterminate ? 'indeterminate' : 'clear';
914
+ }
915
+ async inspectProfileProcesses(profileRootsArg) {
916
+ const roots = profileRootsArg.map((root) => plugins.path.resolve(root));
917
+ let indeterminate = false;
918
+ for (const pid of await this.listOwnedProcessIds()) {
919
+ let cmdline;
920
+ try {
921
+ cmdline = await this.readBoundedBuffer(plugins.path.join(this.procRoot, String(pid), 'cmdline'), maximumProcFileBytes);
922
+ }
923
+ catch {
924
+ const uidState = await this.processStillExists(pid);
925
+ if (uidState === 'missing' || uidState === 'other')
926
+ continue;
927
+ indeterminate = true;
928
+ continue;
929
+ }
930
+ if (cmdline.byteLength === 0) {
931
+ if (!await this.processIsZombie(pid))
932
+ indeterminate = true;
933
+ continue;
934
+ }
935
+ let cmdlineText;
936
+ try {
937
+ cmdlineText = new TextDecoder('utf-8', { fatal: true }).decode(cmdline);
938
+ }
939
+ catch {
940
+ indeterminate = true;
941
+ continue;
942
+ }
943
+ const argumentsList = cmdlineText.split('\0');
944
+ if (argumentsList.at(-1) === '')
945
+ argumentsList.pop();
946
+ for (let index = 0; index < argumentsList.length; index += 1) {
947
+ const argument = argumentsList[index];
948
+ let profilePath;
949
+ if (argument === '--user-data-dir') {
950
+ profilePath = argumentsList[index + 1];
951
+ }
952
+ else if (argument.startsWith('--user-data-dir=')) {
953
+ profilePath = argument.slice('--user-data-dir='.length);
954
+ }
955
+ if (!profilePath || !plugins.path.isAbsolute(profilePath))
956
+ continue;
957
+ const resolved = plugins.path.resolve(profilePath);
958
+ if (roots.some((root) => resolved === root || this.pathIsWithin(root, resolved))) {
959
+ return 'held';
960
+ }
961
+ }
962
+ }
963
+ return indeterminate ? 'indeterminate' : 'clear';
964
+ }
965
+ async listOwnedProcessIds() {
966
+ let entries;
967
+ try {
968
+ entries = await plugins.fsPromises.readdir(this.procRoot, { withFileTypes: true });
969
+ }
970
+ catch {
971
+ throw new BrowserRuntimeError('FENCED', 'process inspection is unavailable');
972
+ }
973
+ const processIds = [];
974
+ let indeterminate = false;
975
+ for (const entry of entries) {
976
+ if (!/^[1-9][0-9]{0,9}$/u.test(entry.name))
977
+ continue;
978
+ const pid = Number(entry.name);
979
+ try {
980
+ const stat = await plugins.fsPromises.lstat(plugins.path.join(this.procRoot, entry.name), { bigint: true });
981
+ if (!stat.isDirectory() || stat.isSymbolicLink()) {
982
+ indeterminate = true;
983
+ continue;
984
+ }
985
+ }
986
+ catch (error) {
987
+ if (isMissingError(error))
988
+ continue;
989
+ indeterminate = true;
990
+ continue;
991
+ }
992
+ const uidState = await this.processStillExists(pid);
993
+ if (uidState === 'same')
994
+ processIds.push(pid);
995
+ else if (uidState === 'indeterminate')
996
+ indeterminate = true;
997
+ }
998
+ if (indeterminate) {
999
+ throw new BrowserRuntimeError('FENCED', 'process inspection is indeterminate');
1000
+ }
1001
+ return processIds.sort((left, right) => {
1002
+ if (left === process.pid)
1003
+ return -1;
1004
+ if (right === process.pid)
1005
+ return 1;
1006
+ return left - right;
1007
+ });
1008
+ }
1009
+ async processStillExists(pidArg) {
1010
+ const processPath = plugins.path.join(this.procRoot, String(pidArg));
1011
+ try {
1012
+ const status = await this.readBoundedFile(plugins.path.join(processPath, 'status'), 64 * 1024);
1013
+ return this.parseProcessUidState(status);
1014
+ }
1015
+ catch (error) {
1016
+ if (!isMissingError(error))
1017
+ return 'indeterminate';
1018
+ try {
1019
+ await plugins.fsPromises.lstat(processPath, { bigint: true });
1020
+ return 'indeterminate';
1021
+ }
1022
+ catch (statError) {
1023
+ return isMissingError(statError) ? 'missing' : 'indeterminate';
1024
+ }
1025
+ }
1026
+ }
1027
+ parseProcessUidState(statusArg) {
1028
+ if (/\u0000|\r/u.test(statusArg))
1029
+ return 'indeterminate';
1030
+ const uidLines = statusArg.split('\n').filter((line) => line.startsWith('Uid:'));
1031
+ if (uidLines.length !== 1)
1032
+ return 'indeterminate';
1033
+ const match = /^Uid:\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s*$/u.exec(uidLines[0]);
1034
+ if (!match)
1035
+ return 'indeterminate';
1036
+ const ids = match.slice(1).map(Number);
1037
+ if (ids.some((id) => !Number.isSafeInteger(id) || id < 0 || id > 0xffff_ffff)) {
1038
+ return 'indeterminate';
1039
+ }
1040
+ if (ids.every((id) => id === this.uid))
1041
+ return 'same';
1042
+ if (ids.every((id) => id !== this.uid))
1043
+ return 'other';
1044
+ return 'indeterminate';
1045
+ }
1046
+ async processIsZombie(pidArg) {
1047
+ try {
1048
+ const status = await this.readBoundedFile(plugins.path.join(this.procRoot, String(pidArg), 'status'), 64 * 1024);
1049
+ return /^State:\s+Z(?:\s|$)/mu.test(status);
1050
+ }
1051
+ catch {
1052
+ return false;
1053
+ }
1054
+ }
1055
+ async readBootId() {
1056
+ const rawBootId = await this.readBoundedFile(plugins.path.join(this.procRoot, 'sys', 'kernel', 'random', 'boot_id'), 64);
1057
+ const bootId = rawBootId.endsWith('\n') ? rawBootId.slice(0, -1) : rawBootId;
1058
+ if (bootId.includes('\n') || bootId.includes('\r') || !bootIdPattern.test(bootId)) {
1059
+ throw new BrowserRuntimeError('FENCED', 'boot identity is malformed');
1060
+ }
1061
+ return bootId;
1062
+ }
1063
+ async readBoundedFile(pathArg, maximumBytesArg) {
1064
+ const bytes = await this.readBoundedBuffer(pathArg, maximumBytesArg);
1065
+ try {
1066
+ return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
1067
+ }
1068
+ catch {
1069
+ throw new BrowserRuntimeError('FENCED', 'process metadata is malformed');
1070
+ }
1071
+ }
1072
+ async readBoundedBuffer(pathArg, maximumBytesArg) {
1073
+ const bytes = await plugins.fsPromises.readFile(pathArg);
1074
+ if (bytes.byteLength > maximumBytesArg) {
1075
+ throw new BrowserRuntimeError('FENCED', 'process metadata exceeds its bound');
1076
+ }
1077
+ return bytes;
1078
+ }
1079
+ generationPath(generationIdArg) {
1080
+ if (!generationIdPattern.test(generationIdArg)) {
1081
+ throw new BrowserRuntimeError('FENCED', 'runtime generation identity is malformed');
1082
+ }
1083
+ const generationPath = plugins.path.join(this.generationsRoot, generationIdArg);
1084
+ if (!this.pathIsWithin(this.generationsRoot, generationPath)) {
1085
+ throw new BrowserRuntimeError('FENCED', 'runtime generation escaped containment');
1086
+ }
1087
+ return generationPath;
1088
+ }
1089
+ pathIsWithin(rootArg, candidateArg) {
1090
+ const relative = plugins.path.relative(rootArg, candidateArg);
1091
+ return relative.length > 0 && relative !== '..'
1092
+ && !relative.startsWith(`..${plugins.path.sep}`)
1093
+ && !plugins.path.isAbsolute(relative);
1094
+ }
1095
+ async assertRuntimeEntries(allowedNamesArg) {
1096
+ await this.assertRuntimeDirectoryCurrent();
1097
+ const entries = await plugins.fsPromises.readdir(this.runtimeDirectory, { withFileTypes: true });
1098
+ if (entries.some((entry) => !allowedNamesArg.has(entry.name))) {
1099
+ throw new BrowserRuntimeError('FENCED', 'runtime directory contains unknown state');
1100
+ }
1101
+ }
1102
+ async assertRuntimeDirectoryCurrent() {
1103
+ if (!this.directoryHandle || !this.directoryIdentity) {
1104
+ throw new BrowserRuntimeError('FENCED', 'runtime directory is unavailable');
1105
+ }
1106
+ const [pathStat, handleStat] = await Promise.all([
1107
+ plugins.fsPromises.lstat(this.runtimeDirectory, { bigint: true }),
1108
+ this.directoryHandle.stat({ bigint: true }),
1109
+ ]);
1110
+ if (!pathStat.isDirectory()
1111
+ || pathStat.isSymbolicLink()
1112
+ || pathStat.uid !== BigInt(this.uid)
1113
+ || (pathStat.mode & 511n) !== 448n
1114
+ || !statIdentityMatches(pathStat, handleStat)
1115
+ || String(handleStat.dev) !== this.directoryIdentity.device
1116
+ || String(handleStat.ino) !== this.directoryIdentity.inode)
1117
+ throw new BrowserRuntimeError('FENCED', 'runtime directory identity changed');
1118
+ }
1119
+ async ensurePrivateDirectory(pathArg, parentArg) {
1120
+ if (!this.pathIsWithin(parentArg, pathArg)) {
1121
+ throw new BrowserRuntimeError('FENCED', 'runtime path escaped containment');
1122
+ }
1123
+ let created = false;
1124
+ try {
1125
+ await plugins.fsPromises.mkdir(pathArg, { recursive: false, mode: 0o700 });
1126
+ created = true;
1127
+ }
1128
+ catch (error) {
1129
+ if (error.code !== 'EEXIST')
1130
+ throw error;
1131
+ }
1132
+ if (created) {
1133
+ await plugins.fsPromises.chmod(pathArg, 0o700);
1134
+ const handle = await plugins.fsPromises.open(pathArg, plugins.fs.constants.O_RDONLY
1135
+ | plugins.fs.constants.O_DIRECTORY
1136
+ | plugins.fs.constants.O_NOFOLLOW);
1137
+ try {
1138
+ await handle.chmod(0o700);
1139
+ await plugins.fsPromises.chmod(pathArg, 0o700);
1140
+ const [pathStat, handleStat] = await Promise.all([
1141
+ plugins.fsPromises.lstat(pathArg, { bigint: true }),
1142
+ handle.stat({ bigint: true }),
1143
+ ]);
1144
+ if (!pathStat.isDirectory()
1145
+ || pathStat.isSymbolicLink()
1146
+ || pathStat.uid !== BigInt(this.uid)
1147
+ || (pathStat.mode & 511n) !== 448n
1148
+ || !statIdentityMatches(pathStat, handleStat))
1149
+ throw new BrowserRuntimeError('FENCED', 'runtime directory state is unsafe');
1150
+ await handle.sync();
1151
+ }
1152
+ finally {
1153
+ await handle.close();
1154
+ }
1155
+ await this.syncDirectory(parentArg);
1156
+ }
1157
+ await this.validateOptionalPrivateDirectory(pathArg, false);
1158
+ }
1159
+ async validateOptionalPrivateDirectory(pathArg, allowMissingArg = true) {
1160
+ let stat;
1161
+ try {
1162
+ stat = await plugins.fsPromises.lstat(pathArg, { bigint: true });
1163
+ }
1164
+ catch (error) {
1165
+ if (allowMissingArg && isMissingError(error))
1166
+ return false;
1167
+ throw error;
1168
+ }
1169
+ if (!stat.isDirectory()
1170
+ || stat.isSymbolicLink()
1171
+ || stat.uid !== BigInt(this.uid)
1172
+ || (stat.mode & 511n) !== 448n)
1173
+ throw new BrowserRuntimeError('FENCED', 'runtime directory state is unsafe');
1174
+ return true;
1175
+ }
1176
+ async validateOptionalGeneration(generationDirectoryArg) {
1177
+ if (!await this.validateOptionalPrivateDirectory(generationDirectoryArg))
1178
+ return;
1179
+ const entries = await plugins.fsPromises.readdir(generationDirectoryArg, { withFileTypes: true });
1180
+ if (entries.some((entry) => entry.name !== 'profiles' && entry.name !== 'artifacts')) {
1181
+ throw new BrowserRuntimeError('FENCED', 'runtime generation contains unknown state');
1182
+ }
1183
+ await this.validateOptionalPrivateDirectory(plugins.path.join(generationDirectoryArg, 'profiles'));
1184
+ await this.validateOptionalPrivateDirectory(plugins.path.join(generationDirectoryArg, 'artifacts'));
1185
+ }
1186
+ async removePrivateDirectory(pathArg) {
1187
+ if (!this.pathIsWithin(this.runtimeDirectory, pathArg)) {
1188
+ throw new BrowserRuntimeError('FENCED', 'runtime cleanup escaped containment');
1189
+ }
1190
+ if (!await this.validateOptionalPrivateDirectory(pathArg))
1191
+ return;
1192
+ await plugins.fsPromises.rm(pathArg, {
1193
+ recursive: true,
1194
+ force: false,
1195
+ maxRetries: 3,
1196
+ retryDelay: 50,
1197
+ });
1198
+ }
1199
+ async readOptionalDirectoryEntries(pathArg) {
1200
+ try {
1201
+ return await plugins.fsPromises.readdir(pathArg, { withFileTypes: true });
1202
+ }
1203
+ catch (error) {
1204
+ if (isMissingError(error))
1205
+ return [];
1206
+ throw error;
1207
+ }
1208
+ }
1209
+ async syncOptionalDirectory(pathArg) {
1210
+ try {
1211
+ await this.syncDirectory(pathArg);
1212
+ }
1213
+ catch (error) {
1214
+ if (!isMissingError(error))
1215
+ throw error;
1216
+ }
1217
+ }
1218
+ async syncDirectory(pathArg) {
1219
+ const handle = await plugins.fsPromises.open(pathArg, plugins.fs.constants.O_RDONLY
1220
+ | plugins.fs.constants.O_DIRECTORY
1221
+ | plugins.fs.constants.O_NOFOLLOW);
1222
+ try {
1223
+ await handle.sync();
1224
+ }
1225
+ finally {
1226
+ await handle.close();
1227
+ }
1228
+ }
1229
+ }
1230
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5ydW50aW1lb3duZXJzaGlwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5ydW50aW1lb3duZXJzaGlwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRXRDLE1BQU0sY0FBYyxHQUFHLENBQUMsQ0FBQztBQUN6QixNQUFNLG9CQUFvQixHQUFHLElBQUksQ0FBQztBQUNsQyxNQUFNLG9CQUFvQixHQUFHLENBQUMsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQzdDLE1BQU0sNEJBQTRCLEdBQUcsR0FBRyxDQUFDO0FBQ3pDLE1BQU0sbUJBQW1CLEdBQUcsc0JBQXNCLENBQUM7QUFDbkQsTUFBTSxXQUFXLEdBQUcsaUJBQWlCLENBQUM7QUFDdEMsTUFBTSxhQUFhLEdBQUcsNEVBQTRFLENBQUM7QUFDbkcsTUFBTSxzQkFBc0IsR0FBRywyQkFBMkIsQ0FBQztBQWtEM0QsTUFBTSxjQUFjLEdBQUcsQ0FBQyxRQUFpQixFQUFXLEVBQUUsQ0FBQyxDQUNwRCxRQUFrQyxDQUFDLElBQUksS0FBSyxRQUFRO09BQ2pELFFBQWtDLENBQUMsSUFBSSxLQUFLLE9BQU8sQ0FDeEQsQ0FBQztBQUVGLE1BQU0sdUJBQXVCLEdBQUcsQ0FBQyxRQUFpQixFQUF1QixFQUFFLENBQUMsQ0FDMUUsUUFBUSxZQUFZLG1CQUFtQjtJQUNyQyxDQUFDLENBQUMsUUFBUTtJQUNWLENBQUMsQ0FBQyxJQUFJLG1CQUFtQixDQUFDLFFBQVEsRUFBRSx5Q0FBeUMsQ0FBQyxDQUNqRixDQUFDO0FBRUYsTUFBTSxtQkFBbUIsR0FBRyxDQUMxQixPQUErQixFQUMvQixRQUFnQyxFQUN2QixFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcs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