chromium/sandbox/policy/mac/common.sb

; Copyright 2017 The Chromium Authors
; Use of this source code is governed by a BSD-style license that can be
; found in the LICENSE file.
(version 1)

; Helper function to check if a param is set to true.
(define (param-true? str) (string=? (param str) "TRUE"))

; Helper function to determine if a parameter is defined or not.
(define (param-defined? str) (string? (param str)))

; Define constants for all of the parameter strings passed in.
(define browser-pid "BROWSER_PID")
(define bundle-id "BUNDLE_ID")
(define helper-bundle-id "HELPER_BUNDLE_ID")
(define bundle-path "BUNDLE_PATH")
(define component-path "COMPONENT_PATH")
(define disable-sandbox-denial-logging "DISABLE_SANDBOX_DENIAL_LOGGING")
(define enable-logging "ENABLE_LOGGING")
(define executable-path "EXECUTABLE_PATH")
(define homedir-as-literal "USER_HOMEDIR_AS_LITERAL")
(define log-file-path "LOG_FILE_PATH")
(define os-version (string->number (param "OS_VERSION")))
(define darwin-user-cache-dir "DARWIN_USER_CACHE_DIR")
(define darwin-user-dir "DARWIN_USER_DIR")
(define darwin-user-temp-dir "DARWIN_USER_TEMP_DIR")
; There are two separate flags for syscall filtering to allow it
; to be rolled out to one process type at a time, while still allowing
; local development.
(define filter-syscalls "FILTER_SYSCALLS")
(define filter-syscalls-debug "FILTER_SYSCALLS_DEBUG")

; Sandboxed processes which use Metal may need to disable the shader cache.
(define disable-metal-shader-cache "DISABLE_METAL_SHADER_CACHE")

; --enable-sandbox-logging causes the sandbox to log failures to the syslog.
(if (param-true? disable-sandbox-denial-logging)
  (deny default (with no-log))
  (deny default))

(if (param-true? enable-logging) (debug deny))

; Allow sending signals to self - https://crbug.com/20370
(allow signal (target self))

; TODO(rsesek): Lock down `(deny process-info*)`.
(allow process-info-pidinfo (target self))

; Consumes a subpath and appends it to the user's homedir path.
(define (user-homedir-path subpath)
  (string-append (param homedir-as-literal) subpath))

; A function that specific profiles (i.e. renderer) can call to allow
; font rendering.
(define (allow-font-access)
  (begin
    (allow file-read-data
      (subpath "/Library/Fonts")
      (subpath "/System/Library/Fonts")
      (subpath (user-homedir-path "/Library/Fonts"))
    )
    (allow mach-lookup
      ; https://crbug.com/756145, https://crbug.com/786615
      (global-name "com.apple.FontObjectsServer")
      (global-name "com.apple.fonts")
    )
    ; To allow accessing downloaded and other hidden fonts in
    ; /System/Library/Asssets/com_apple_MobileAsset_Font*.
    ; (https://crbug.com/662686)
    (allow file-read* (extension "com.apple.app-sandbox.read"))))

; A function that profiles can call to allow forcibly disabling the Metal shader
; cache in lieu of poking necessary holes in the sandbox for it.
; See https://crbug.com/1159113
(define (maybe-disable-metal-shader-cache)
  (if (param-true? disable-metal-shader-cache)
    (let ((metal-cache-dir (subpath (string-append (param darwin-user-cache-dir)
                                                   "/com.apple.metal"))))
      (deny file-read* metal-cache-dir)
      (deny file-write* metal-cache-dir)
      #t)
    #f))

; A function profiles can call to enable the requisite file access needed for
; Metal shader compilation to work with the shader cache.
;
; Metal shader compilation may be offloaded to a helper process that needs
; access to the user cache directory in order to cache its work to disk.
; If this sandbox is applied to an executable that is not within an app bundle,
; such as in a unit test, the helper-bundle-id parameter will not be set and
; issuing sandbox extensions to the Metal cache directories will not be allowed.
; See https://crbug.com/1453813
(define (maybe-allow-metal-shader-cache-access)
  (begin
    (if (param helper-bundle-id)
      (let ((helper-bundle-cache-dir
            (string-append (param darwin-user-cache-dir)
                            "/" (param helper-bundle-id))))
        (allow file-issue-extension
          (require-all
            (extension-class "com.apple.app-sandbox.read-write")
            (require-any
              (subpath (string-append helper-bundle-cache-dir
                                      "/com.apple.metalfe"))
              (subpath (string-append helper-bundle-cache-dir
                                      "/com.apple.gpuarchiver")))))))))

; Reads of signed Mach-O blobs created by the CVMS server.
; https://crbug.com/850021
(define (allow-cvms-blobs)
  (begin
    (allow file-read* file-write-unlink
      (prefix "/private/tmp/cvmsCodeSignObj"))
    (allow file-read*
      (extension "com.apple.cvms.kernel")
      (prefix "/private/var/db/CVMS/cvmsCodeSignObj"))
))

; Allow logging for all processes.
(allow file-write*
  (require-all
    (path (param log-file-path))
    (vnode-type REGULAR-FILE)))

; Allow component builds to work.
(if (param-defined? component-path)
  (allow file-read* (subpath (param component-path))))

(allow process-exec (path (param executable-path)))
(allow file-read* (path (param executable-path)))

; The browser exposes Mach services at "bundle-id.service-name.browser-pid".
; This macro is a helper for doing the string concatenation.
(define (browser-service-name service-name)
  (global-name (string-append (param bundle-id)
                              "." service-name "."
                              (param browser-pid))))

(allow mach-lookup
  (browser-service-name "MachPortRendezvousServer")
)

; Allow realpath() to work.
(allow file-read-metadata (subpath "/"))

; All processes can read the bundle contents.
(allow file-read* (subpath (param bundle-path)))

; A sandbox bug on macOS 11 and 12 causes the sandbox to see any paths within
; the data volume (/System/Volumes/Data) outside of system firm link locations
; (listed in /usr/share/firmlinks) as though they were not on the data volume,
; causing it to deny access to user paths containing the data volume mount point
; as a prefix. This is filed as https://openradar.appspot.com/FB9738355 and
; tracked at https://crbug.com/1266490. Although macOS 10.15 also has the root
; volume split, this bug does not appear to affect that OS version.
;
; When the bundle path appears in the data volume, this causes the sandbox to
; deny access to the bundle.
;
; This is not a problem in normal use, as typical bundle paths, while on the
; data volume, will be in system firm link locations such as /Applications or
; /Users. As a workaround for other cases where the bundle may be present on the
; data volume but not in a system firm link location, configure the sandbox with
; an alternate bundle path so that it permits access to the bundle.
(define (string-prefix? str prefix)
  (let ((l (string-length prefix)))
    (if (< (string-length str) l)
      #f
      (equal? (substring str 0 l) prefix)
    )
  )
)
(define data-volume-root "/System/Volumes/Data/")
(when (string-prefix? (param bundle-path) data-volume-root)
  (define (strip-leading-chars str count)
    (substring str count (string-length str))
  )
  (allow file-read*
         (subpath (strip-leading-chars (param bundle-path)
                                       (- (string-length data-volume-root) 1))))
)

; Allow reads of system libraries and frameworks.
(allow file-read*
  (subpath "/System/Library/CoreServices/CoreTypes.bundle")
  (subpath "/System/Library/CoreServices/SystemVersion.bundle")
  (subpath "/System/Library/Frameworks")
  (subpath "/System/Library/Preferences/Logging")
  (subpath "/System/Library/PrivateFrameworks")
  (subpath "/usr/lib")
)

; In some circumstances, Safari updates are installed below /Library/Apple and
; SafariServices.framework in /System/Library/Frameworks is replaced with a
; symlink into that directory tree. These paths must be readable to allow
; the framework to be loaded.
(allow file-read*
  (subpath "/Library/Apple/System/Library/Frameworks")
  (subpath "/Library/Apple/System/Library/PrivateFrameworks")
)

; Reads from /etc.
; This is read by CFPrefs calling getpwuid in a loop. libinfo then fails to
; contact any of the opendirectoryd mach services, and falls back to
; the /etc/passwd file for the user info. The access is OK because
; no actual password hashes are in /etc/passwd anymore.
(allow file-read-data (path "/private/etc/passwd"))

; Access to /dev.
(allow file-ioctl file-read-data file-write-data
  (require-all
    (path "/dev/dtracehelper")
    (vnode-type CHARACTER-DEVICE)))

(allow file-read-data
  (path "/dev/null")
  (path "/dev/random")
  (path "/dev/urandom")
)

(allow file-read* (subpath "/private/var/db/timezone"))
(allow file-read-data (subpath "/usr/share/zoneinfo.default"))

; Reads from /Library.
(allow file-read-data
  (path "/Library/Managed Preferences/.GlobalPreferences.plist")
  (path "/Library/Preferences/.GlobalPreferences.plist")
  (path (string-append "/Library/Managed Preferences/" (param bundle-id) ".plist"))
  (path (string-append "/Library/Preferences/" (param bundle-id) ".plist"))
  (regex #"/Library/Managed Preferences/.*/\.GlobalPreferences\.plist")
  (regex (string-append #"/Library/Managed Preferences/.*/" (regex-quote (param bundle-id)) #"\.plist"))
)

; Reads from /System.
(allow file-read-data
  (path "/System/Library/CoreServices/SystemVersion.plist")
  (path "/System/Library/CoreServices/SystemVersionCompat.plist") ; https://crbug.com/1108832
  (path "/System/Library/CoreServices/checkfixlist")
)

; From /System/Library/Sandbox/Profiles/dyld-support.sb on macOS 13.
(if (>= os-version 1300)
  (allow file-read* file-map-executable
    (subpath "/System/Cryptexes/App")
    (subpath "/System/Cryptexes/OS")
    (subpath "/System/Volumes/Preboot/Cryptexes/App/System")
    (subpath "/System/Volumes/Preboot/Cryptexes/OS")
  )
)

; Reads from /usr.
(allow file-read-data
  (subpath "/usr/share/icu")
  (subpath "/usr/share/locale")
)

; Access to the home directory.
(allow file-read-data
  (path (string-append (user-homedir-path "/Library/Preferences/") (param bundle-id) ".plist"))
  (path (user-homedir-path "/Library/Preferences/.GlobalPreferences.plist"))
  (path (user-homedir-path "/Library/Preferences/.GlobalPreferences_m.plist"))
  (prefix (user-homedir-path "/Library/Preferences/ByHost/.GlobalPreferences"))
  (path (user-homedir-path "/Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist"))
)

; Mach IPC needed by all Chromium Helper instances.
(allow mach-lookup
  (global-name "com.apple.logd")  ; https://crbug.com/792229
  (global-name "com.apple.system.logger")
  (global-name "com.apple.system.opendirectoryd.libinfo")  ; https://crbug.com/792228
)

; sysctls permitted.
(allow sysctl-read
  (sysctl-name "hw.activecpu")
  (sysctl-name "hw.busfrequency_compat")
  (sysctl-name "hw.byteorder")
  (sysctl-name "hw.cacheconfig")
  (sysctl-name "hw.cachelinesize_compat")
  (sysctl-name "hw.cpufamily")
  (sysctl-name "hw.cpufrequency_compat")
  (sysctl-name "hw.cputype")
  (sysctl-name "hw.l1dcachesize_compat")
  (sysctl-name "hw.l1icachesize_compat")
  (sysctl-name "hw.l2cachesize_compat")
  (sysctl-name "hw.l3cachesize_compat")
  (sysctl-name "hw.logicalcpu_max")
  (sysctl-name "hw.machine")
  (sysctl-name "hw.ncpu")
  (sysctl-name "hw.nperflevels")
  (sysctl-name "hw.optional.arm.FEAT_BF16")
  (sysctl-name "hw.optional.arm.FEAT_DotProd")
  (sysctl-name "hw.optional.arm.FEAT_FCMA")
  (sysctl-name "hw.optional.arm.FEAT_FHM")
  (sysctl-name "hw.optional.arm.FEAT_FP16")
  (sysctl-name "hw.optional.arm.FEAT_I8MM")
  (sysctl-name "hw.optional.arm.FEAT_JSCVT")
  (sysctl-name "hw.optional.arm.FEAT_LSE")
  (sysctl-name "hw.optional.arm.FEAT_RDM")
  (sysctl-name "hw.optional.arm.FEAT_SHA512")
  (sysctl-name "hw.optional.armv8_2_sha512")
  (sysctl-name "hw.packages")
  (sysctl-name "hw.pagesize_compat")
  (sysctl-name "hw.physicalcpu_max")
  (sysctl-name "hw.tbfrequency_compat")
  (sysctl-name "hw.vectorunit")
  (sysctl-name "kern.hostname")
  (sysctl-name "kern.maxfilesperproc")
  (sysctl-name "kern.osproductversion")
  (sysctl-name "kern.osrelease")
  (sysctl-name "kern.ostype")
  (sysctl-name "kern.osvariant_status")
  (sysctl-name "kern.osversion")
  (sysctl-name "kern.secure_kernel")
  (sysctl-name "kern.usrstack64")
  (sysctl-name "kern.version")
  (sysctl-name "sysctl.proc_cputype")
  (sysctl-name-prefix "hw.perflevel")
)

(allow network-outbound
  (literal "/private/var/run/asl_input")
  (literal "/private/var/run/syslog")
)

; This is available in 10.15+, and rolled out as a Finch experiment.
(if (param-true? filter-syscalls)
  (when (defined? 'syscall-unix)
    (allow syscall-unix
      (syscall-number SYS___disable_threadsignal)
      (syscall-number SYS___mac_syscall)
      (syscall-number SYS___pthread_kill)
      (syscall-number SYS___pthread_markcancel)
      (syscall-number SYS___pthread_sigmask)
      (syscall-number SYS___semwait_signal)
      (syscall-number SYS___semwait_signal_nocancel)
      (syscall-number SYS_access)
      (syscall-number SYS_bsdthread_create)
      (syscall-number SYS_bsdthread_ctl)
      (syscall-number SYS_bsdthread_register)
      (syscall-number SYS_bsdthread_terminate)
      (syscall-number SYS_close)
      (syscall-number SYS_close_nocancel)
      (syscall-number SYS_csops_audittoken)
      (syscall-number SYS_exit)
      (syscall-number SYS_fcntl)
      (syscall-number SYS_fileport_makefd)
      (syscall-number SYS_fileport_makeport)
      (syscall-number SYS_fstat64)
      (syscall-number SYS_fstatat64)
      (syscall-number SYS_fstatfs64)
      (syscall-number SYS_getattrlist)
      (syscall-number SYS_getattrlistbulk)
      (syscall-number SYS_getaudit_addr)
      (syscall-number SYS_getdirentries64)
      (syscall-number SYS_geteuid)
      (syscall-number SYS_getgid)
      (syscall-number SYS_gethostuuid)
      (syscall-number SYS_getpid)
      (syscall-number SYS_getppid)
      (syscall-number SYS_getpriority)
      (syscall-number SYS_getrlimit)
      (syscall-number SYS_gettimeofday)
      (syscall-number SYS_getuid)
      (syscall-number SYS_ioctl)
      (syscall-number SYS_issetugid)
      (syscall-number SYS_kdebug_trace64)
      (syscall-number SYS_kevent64)
      (syscall-number SYS_kevent_id)
      (syscall-number SYS_kevent_qos)
      (syscall-number SYS_kqueue)
      (syscall-number SYS_lstat64)
      (syscall-number SYS_madvise)
      (syscall-number SYS_mmap)
      (syscall-number SYS_mprotect)
      (syscall-number SYS_munmap)
      (syscall-number SYS_open)
      (syscall-number SYS_open_dprotected_np)
      (syscall-number SYS_open_nocancel)
      (syscall-number SYS_pread)
      (syscall-number SYS_proc_info)
      (syscall-number SYS_psynch_mutexdrop)
      (syscall-number SYS_psynch_mutexwait)
      (syscall-number SYS_psynch_rw_downgrade)
      (syscall-number SYS_psynch_rw_longrdlock)
      (syscall-number SYS_psynch_rw_rdlock)
      (syscall-number SYS_psynch_rw_unlock)
      (syscall-number SYS_psynch_rw_unlock2)
      (syscall-number SYS_psynch_rw_upgrade)
      (syscall-number SYS_psynch_rw_wrlock)
      (syscall-number SYS_psynch_rw_yieldwrlock)
      (syscall-number SYS_read)
      (syscall-number SYS_read_nocancel)
      (syscall-number SYS_readlink)
      (syscall-number SYS_shm_open)
      (syscall-number SYS_sigaction)
      (syscall-number SYS_sigprocmask)
      (syscall-number SYS_sigreturn)
      (syscall-number SYS_stat64)
      (syscall-number SYS_statfs64)
      (syscall-number SYS_sysctl)
      (syscall-number SYS_sysctlbyname)
      (syscall-number SYS_thread_selfid)
      (syscall-number SYS_ulock_wait)
      (syscall-number SYS_ulock_wake)
      (syscall-number SYS_workq_kernreturn)
      (syscall-number SYS_workq_open)
)))

; Explicit denials. These are already covered by the blanket `(deny default)`,
; but benefit from explanation as to why they're denied.
(deny mach-lookup
  ; CFPreferences falls back to in-process access to preference plists, known as
  ; direct mode, when cfprefsd is inaccessible. This in-process access ensures
  ; that our sandbox policy limits which preference domains can be accessed via
  ; CFPreferences or NSUserDefaults.
  (global-name "com.apple.cfprefsd.daemon")
)