Modify SIP in normally booted system
I have MacBook Pro (2017) with macOS High Sierra (10.13.6). I have SIP and amfi disabled. I want to enable a part / the majority of SIP (e.g. csrutil enable --without fs
) without having to reboot into the recovery partition and run the csrutil
command there.
I tried to modify the nvram variable csr-active-config
using nvram csr-active-config="w%01%00%00"
, but it returned an error: nvram: Error setting variable - 'csr-active-config': (iokit/common) general error
. Modifying the variable name gave successful result:
# nvram ccsr-active-config="w%01%00%00"
# nvram ccsr-active-config
ccsr-active-config w%01%00%00
Which indicated that there is still something protecting the SIP configuration even when SIP is completely disabled:
# csrutil status
System Integrity Protection status: disabled.
Note that I can change boot-args
variable with nvram
because I disabled SIP:
# nvram boot-args="amfi_get_out_of_my_way=0x1"
# nvram boot-args
boot-args amfi_get_out_of_my_way=0x1
There is only one relevant log message while setting SIP nvram:
ERROR 09:47:22.096544 +0800 kernel Sandbox: nvram(92857) System Policy: deny(1) nvram-set csr-active-config
Is it possible to change SIP configuration to become stricter (not less strict) booting into Recovery OS?
Preferably, the solution can enforce SIP configuration as soon as it's changed. The following logs in Console when I do chmod -x /bin/ls
make me think it's possible:
INFO 11:07:38.852242 +0800 sandboxd Symbolicator for chmod[94599] is NULL.
ERROR 11:07:38.862934 +0800 sandboxd Failed to produce a full report for: chmod[94599].
ERROR 11:07:38.863015 +0800 sandboxd Sandbox: chmod(94599) System Policy: allow file-write-mode /bin/ls
Your Mac can be configured so that you can enable a part / the majority of SIP without having to reboot into the recovery partition and run the csrutil
command there. However, a reboot of macOS will still be necessary for any changes to take effect. This answer proposes one such configuration for use with Intel Macs. Although, adaption for use with Apple Silicon Macs seems theoretically possible.
The csrutil command sets the firmware NVRAM variable csr-active-config
. The macOS operating system reads this 32 bit integer variable at startup to determine which parts of SIP to enable. Instead of using the csrutil
command, this answer uses a bash script named mkcsrfile
to create a csr.bin
file containing the desired value for the csr-active-config
variable. The format of this file is defined in this answer. Instead of booting to macOS by default, this answer changes the default to boot an UEFI Shell instead. This shell executes a script stored in the file startup.nsh
. This script first copies the csr-active-config
value from the csr.bin
file to NVRAM, then boots macOS.
The bits of the csr-active-config
variable are defined in the csr.h
file. A version of this file can be found in opensource.apple.com. This developer.apple.com thread defines some additional csrutil
arguments for the enable
command. The relationship between these bits and select csrutil
commands and arguments is summarized in the table below for macOS High Sierra version 10.13.6.
Note: The table below can vary between versions of macOS (OS X). For example, the table for Big Sur and Monterey can be found at this answer.
csrutil commands with optional arguments |
csr- active- config |
CSR_ ALLOW_ UNTRUSTED_ KEXTS =0x001 |
CSR_ ALLOW_ UNRESTRICTED_ FS =0x002 |
CSR_ ALLOW_ TASK_ FOR_ PID =0x004 |
CSR_ ALLOW_ KERNEL_ DEBUGGER =0x008 |
CSR_ ALLOW_ APPLE_ INTERNAL =0x010 |
CSR_ ALLOW_ UNRESTRICTED_ DTRACE =0x020 |
CSR_ ALLOW_ UNRESTRICTED_ NVRAM =0x040 |
CSR_ ALLOW_ DEVICE_ CONFIGURATION =0x080 |
CSR_ ALLOW_ ANY_ RECOVERY_ OS =0x100 |
CSR_ ALLOW_ UNAPPROVED_ KEXTS =0x200 |
CSR_ ALLOW_ EXECUTABLE_ POLICY_ OVERRIDE =0x400 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
enable | 0x00000010 | ⚫ | ||||||||||
enable ‑‑no‑internal | 0x00000000 | |||||||||||
enable ‑‑without kext |
0x00000011 | ⚫ | ⚫ | |||||||||
enable ‑‑without fs |
0x00000012 | ⚫ | ⚫ | |||||||||
enable ‑‑without debug |
0x00000014 | ⚫ | ⚫ | |||||||||
enable ‑‑without dtrace |
0x00000030 | ⚫ | ⚫ | |||||||||
enable ‑‑without nvram |
0x00000050 | ⚫ | ⚫ | |||||||||
disable | 0x00000077 | ⚫ | ⚫ | ⚫ | ⚫ | ⚫ | ⚫ |
Examples of Use
Once the Mac is configured, the mkcsrfile
command can be used from macOS. Some examples are given below.
-
Enable except for fs and internal.
The
csr-active-config
variable needs to be set0x00000012
, which can be done from macOS Recovery by using the command shown below.csrutil enable --without fs
This answer offers the following command, which can be entered from macOS, as one possible replacement for the above command.
mkcsrfile 0x12
-
Enable except for fs, debug, dtrace and internal.
The
csr-active-config
variable needs to be set0x00000036
, which can be done from macOS Recovery by using the command shown below.csrutil enable --without fs --without debug --without dtrace
Any one of the following commands, which can be entered from macOS, could be used to replace the above command. The first command shown below has three arguments which will be ORed together bitwise by the
mkcsrfile
script.mkcsrfile 0x12 0x14 0x30
Instead, a single argument can be used, where the bitwise OR operations are explicitly entered. This shown in the command below.
mkcsrfile "0x12|0x14|0x30"
Finally, you could perform the bitwise OR operations yourself and just enter the result, as shown below.
mkcsrfile 0x36
-
Enable except for fs, debug and dtrace.
The
csr-active-config
variable needs to be set0x00000026
, which can be done from macOS Recovery by using the command shown below.Note: The
--no-internal
option sets theCSR_ALLOW_APPLE_INTERNAL
(0x10
) bit to zero.csrutil enable --no-internal --without fs --without debug --without dtrace
Any one of the following commands, which can be entered from macOS, could be used to replace the above command. The first command shown below has three arguments which will be ORed together bitwise by the
mkcsrfile
script. Here, each argument has theCSR_ALLOW_APPLE_INTERNAL
(0x10
) bit set to zero,mkcsrfile 2 4 0x20
Instead, a single argument can be used, where the bitwise operations are explicitly entered. This shown in the command below.
mkcsrfile "~10&(0x12|0x14|0x30)"
Finally, you could perform the bitwise operations yourself and just enter the result, as shown below.
mkcsrfile 0x26
Steps to Configure an Intel Mac
-
Download an UEFI Shell v1.
The Arch Linux wiki web site section Obtaining UEFI Shell provides a link to Precompiled UEFI Shell v1 binaries from TianoCore. Since you have a Intel-based Mac, you will need to download the X64 version of the
Shell_Full.efi
file to yourDownloads
folder.Note: If any user can confirm that the Arm version works on a Mac with Apple silicon, then post a comment so this answer can be updated.
-
Install UEFI Shell binary and startup script files to the EFI partition.
Create a file containing the UEFI shell script shown below. Save as
startup.nsh
in yourDownloads
folder.@echo -off set -v uuid E43602C1-8CFF-4F74-AEC7-98E645C7BBEE set -v file csr.bin if "%StartupDelay%" == "" then set StartupDelay 0 endif set -v found nothing for %a in "" 1 2 3 4 5 6 for %b in 0 1 2 3 4 5 6 7 8 9 a b c d e f if not %found% == boot then if exist fs%a%b:\%uuid%\System\Library\CoreServices\boot.efi then alias -v macos fs%a%b:\%uuid%\System\Library\CoreServices\boot.efi if %found% == startup then goto BREAK endif set -v found boot endif endif if not %found% == startup then if exist fs%a%b:\EFI\BOOT\startup.nsh then fs%a%b: cd \EFI\BOOT if exist %file% then dmpstore -l %file% rm %file% endif if %found% == boot then goto BREAK endif set -v found startup endif endif endfor endfor alias -v macos "echo ^"Missing macOS^"" :BREAK macos ver ver -s
Next, you will need replace the UUID of
E43602C1-8CFF-4F74-AEC7-98E645C7BBEE
in thestartup.nsh
file with the volume UUID shown in the output from the command below.diskutil info / | grep "Volume UUID"
Finally, enter the commands below to install the shell and script files to the EFI partition. If the desired EFI partition is not
disk0s1
, then make the appropriate substitutions.cd ~/Downloads sudo diskutil mount disk0s1 mkdir -p /Volumes/EFI/EFI/BOOT bless --folder /Volumes/EFI/EFI/BOOT --label "UEFI Shell" mv Shell_Full.efi /Volumes/EFI/EFI/BOOT/bootx64.efi mv startup.nsh /Volumes/EFI/EFI/BOOT/. dot_clean -m /Volumes/EFI/EFI/BOOT diskutil unmount disk0s1
-
Install
mkcsrfile
command as a bash script.Create a file containing the bash script shown below. Save as
mkcsrfile
in yourDownloads
folder,#!/bin/bash if [[ $0 != "$BASH_SOURCE" ]]; then bash "$BASH_SOURCE" "$@" fi trap exit ERR main() { local "file=/Volumes/EFI/EFI/BOOT/csr.bin" local "unmount=no" "value=0" operand data if [[ ! -e /Volumes/EFI ]]; then sudo diskutil mount disk0s1 unmount="yes" fi for operand in "$@"; do value="$((value|($operand)))" done printf -v value "%08X" "$value" echo "Setting to 0x$value" data="240000006300730072002d006100630074006900760065002d0063006f00" data+="6e0066006900670000001061437c2aabbb4ba880fe41995c9f8207000000" data+="04000000${value:6}${value:4:2}${value:2:2}${value::2}" xxd -r -p - "$file" <<<"$data" if [[ $unmount == yes ]]; then sleep 0.1 diskutil unmount disk0s1 fi } main "$@"
Next, if the desired EFI partition is not
disk0s1
, then replace the two occurrences of thedisk0s1
identifier in themkcsrfile
file with the desired EFI partition identifier.Finally, enter the commands below to install the
mkcsrfile
file to the/usr/local/bin
folder.cd ~/Downloads chmod 755 mkcsrfile sudo chown root:wheel mkcsrfile sudo mkdir -p /usr/local/bin sudo mv mkcsrfile /usr/local/bin/. sudo xattr -c /usr/local/bin/mkcsrfile
-
Change the default to boot from the UEFI shell.
Restart the Mac and immediately hold down the option key until the Mac Startup Manager icons appear. Next, hold down the control key while selecting to boot from the "UEFI Shell".
Note: When you first boot from the UEFI Shell there will be a startup delay. There should be no delay on subsequent boots.