Changeset 260913 in webkit


Ignore:
Timestamp:
Apr 29, 2020, 1:39:03 PM (5 years ago)
Author:
mark.lam@apple.com
Message:

Freezing of Gigacage and JSC Configs should be thread safe.
https://bugs.webkit.org/show_bug.cgi?id=211201
<rdar://problem/62597619>

Reviewed by Yusuke Suzuki.

Source/bmalloc:

  • bmalloc/Gigacage.cpp:

(Gigacage::bmalloc::permanentlyFreezeGigacageConfig):

Source/JavaScriptCore:

If a client creates multiple VM instances in different threads concurrently, the
following race can occur:

Config::permanentlyFreeze() contains the following code:

if (!g_jscConfig.isPermanentlyFrozen) Point P1

g_jscConfig.isPermanentlyFrozen = true; Point P2

Let's say there are 2 threads T1 and T2.

  1. T1 creates a VM and gets to point P1, and sees that g_jscConfig.isPermanentlyFrozen is not set. T1 is about to execute P2 when it gets pre-empted.
  1. T2 creates a VM and gets to point P1, and sees that g_jscConfig.isPermanentlyFrozen is not set. T2 proceeds to point P2 and sets g_jscConfig.isPermanentlyFrozen to true. T2 goes on to freeze the Config and makes it not writable.
  1. T1 gets to run again, and proceeds to point P2. T1 tries to set g_jscConfig.isPermanentlyFrozen to true. But because the Config has been frozen against writes, the write to g_jscConfig.isPermanentlyFrozen results in a crash.

This is a classic TOCTOU bug. The fix is simply to ensure that only one thread
can enter Config::permanentlyFreeze() at a time.

Ditto for Gigacage::permanentlyFreezeGigacageConfig().

  • runtime/JSCConfig.cpp:

(JSC::Config::permanentlyFreeze):

Location:
trunk/Source
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r260906 r260913  
     12020-04-29  Mark Lam  <mark.lam@apple.com>
     2
     3        Freezing of Gigacage and JSC Configs should be thread safe.
     4        https://bugs.webkit.org/show_bug.cgi?id=211201
     5        <rdar://problem/62597619>
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        If a client creates multiple VM instances in different threads concurrently, the
     10        following race can occur:
     11
     12        Config::permanentlyFreeze() contains the following code:
     13
     14            if (!g_jscConfig.isPermanentlyFrozen)         // Point P1
     15                g_jscConfig.isPermanentlyFrozen = true;   // Point P2
     16
     17        Let's say there are 2 threads T1 and T2.
     18
     19        1. T1 creates a VM and gets to point P1, and sees that g_jscConfig.isPermanentlyFrozen is not set.
     20           T1 is about to execute P2 when it gets pre-empted.
     21
     22        2. T2 creates a VM and gets to point P1, and sees that g_jscConfig.isPermanentlyFrozen is not set.
     23           T2 proceeds to point P2 and sets g_jscConfig.isPermanentlyFrozen to true.
     24           T2 goes on to freeze the Config and makes it not writable.
     25
     26        3. T1 gets to run again, and proceeds to point P2.
     27           T1 tries to set g_jscConfig.isPermanentlyFrozen to true.
     28           But because the Config has been frozen against writes, the write to
     29           g_jscConfig.isPermanentlyFrozen results in a crash.
     30
     31        This is a classic TOCTOU bug.  The fix is simply to ensure that only one thread
     32        can enter Config::permanentlyFreeze() at a time.
     33
     34        Ditto for Gigacage::permanentlyFreezeGigacageConfig().
     35
     36        * runtime/JSCConfig.cpp:
     37        (JSC::Config::permanentlyFreeze):
     38
    1392020-04-29  Yusuke Suzuki  <ysuzuki@apple.com>
    240
  • trunk/Source/JavaScriptCore/runtime/JSCConfig.cpp

    r258857 r260913  
    11/*
    2  * Copyright (C) 2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019-2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727#include "JSCConfig.h"
    2828
     29#include <wtf/Lock.h>
    2930#include <wtf/ResourceUsage.h>
    3031#include <wtf/StdLibExtras.h>
     
    5455void Config::permanentlyFreeze()
    5556{
     57    static Lock configLock;
     58    auto locker = holdLock(configLock);
     59
    5660    RELEASE_ASSERT(roundUpToMultipleOf(pageSize(), ConfigSizeToProtect) == ConfigSizeToProtect);
    5761
  • trunk/Source/bmalloc/ChangeLog

    r260712 r260913  
     12020-04-29  Mark Lam  <mark.lam@apple.com>
     2
     3        Freezing of Gigacage and JSC Configs should be thread safe.
     4        https://bugs.webkit.org/show_bug.cgi?id=211201
     5        <rdar://problem/62597619>
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        * bmalloc/Gigacage.cpp:
     10        (Gigacage::bmalloc::permanentlyFreezeGigacageConfig):
     11
    1122020-04-25  Darin Adler  <darin@apple.com>
    213
  • trunk/Source/bmalloc/bmalloc/Gigacage.cpp

    r254781 r260913  
    11/*
    2  * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828#include "CryptoRandom.h"
    2929#include "Environment.h"
     30#include "Mutex.h"
    3031#include "ProcessCheck.h"
    3132#include "StaticPerProcess.h"
     
    3435#include "bmalloc.h"
    3536#include <cstdio>
    36 #include <mutex>
    3737
    3838#if BOS(DARWIN)
     
    118118static void permanentlyFreezeGigacageConfig()
    119119{
     120    static Mutex configLock;
     121    LockHolder locking(configLock);
     122
    120123    if (!g_gigacageConfig.isPermanentlyFrozen) {
    121124        unfreezeGigacageConfig();
Note: See TracChangeset for help on using the changeset viewer.