raptor:~ lee$ xattr -l /System
com.apple.rootless:
raptor:~ lee$ xattr -l /bin
com.apple.FinderInfo:
00000000 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 |........@.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020
com.apple.rootless:
raptor:~ lee$ xattr -l /sbin
com.apple.FinderInfo:
00000000 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 |........@.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020
com.apple.rootless:
raptor:~ lee$ xattr -l /usr
com.apple.FinderInfo:
00000000 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 |........@.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020
com.apple.rootless:
raptor:~ lee$ xattr -l /usr/local
raptor:~ lee$
On each location, we’ve got a com.apple.FinderInfo attribute and a com.apple.rootless attribute. By way of comparison, the last location, /usr/local, is unprotected and has no extended attributes.
The com.apple.FinderInfo attribute was touched on a couple of years ago in our OS X Mavericks review:
As a nod toward modernity, Finder Info is exposed in OS X through a “fake” extended attribute named com.apple.FinderInfo. The code that reads and writes extended attributes for files on HFS+ volumes checks to see if the attribute name is com.apple.FinderInfo and then branches to another code path that reads the actual HFS+ Finder Info record from the file system. (The resource fork is exposed in a similar way under the com.apple.ResourceFork attribute name.)
The FinderInfo flags shown on /bin, /sbin, and /usr don’t have anything to do with SIP—instead, they mark the folders as hidden folders. You can actually set that on objects yourself if you’d like:
raptor:~ lee$ mkdir mydir
raptor:~ lee$ chflags hidden mydir
raptor:~ lee$ xattr -l mydir
com.apple.FinderInfo:
00000000 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 |........@.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020
This is also why /System doesn’t have that particular extended attribute—unlike the others, /System isn’t a hidden directory.
The thing that we do care about is that com.apple.rootless attribute. That’s the SIP attribute, marking the directory and its child object as protected. It works, too—on Yosemite and earlier, we can toggle these directories’ hidden flags to off, but trying to do so in El Cap results in the same “Operation not permitted” error as you get when trying to do any writes to a protected location:
raptor:~ lee$ sudo chflags nohidden /usr
chflags: /usr: Operation not permitted
raptor:~ lee$ sudo xattr -d com.apple.FinderInfo /usr
xattr: [Errno 1] Operation not permitted: '/usr'
The list of file system objects granted to the com.apple.rootless attribute—along with those specifically exempted from it—is found at /System/Library/Sandbox/rootless.conf. As expected, the list contains the four prime protected SIP locations. However, it also contains a whole slew of additional SIP objects, including a bunch of core OS X applications:
raptor:~ lee$ cat /System/Library/Sandbox/rootless.conf
/Applications/App Store.app
/Applications/Automator.app
/Applications/Calculator.app
/Applications/Calendar.app
/Applications/Chess.app
/Applications/Contacts.app
/Applications/Dashboard.app
/Applications/Dictionary.app
/Applications/DVD Player.app
/Applications/FaceTime.app
/Applications/Font Book.app
/Applications/Game Center.app
/Applications/Image Capture.app
/Applications/Launchpad.app
/Applications/Mail.app
/Applications/Maps.app
/Applications/Messages.app
/Applications/Mission Control.app
/Applications/Notes.app
/Applications/Photo Booth.app
/Applications/Photos.app
/Applications/Preview.app
/Applications/QuickTime Player.app
/Applications/Reminders.app
/Applications/Safari.app
/Applications/Stickies.app
/Applications/System Preferences.app
/Applications/TextEdit.app
/Applications/Time Machine.app
/Applications/Utilities/Activity Monitor.app
/Applications/Utilities/AirPort Utility.app
/Applications/Utilities/Audio MIDI Setup.app
/Applications/Utilities/Bluetooth File Exchange.app
/Applications/Utilities/Boot Camp Assistant.app
/Applications/Utilities/ColorSync Utility.app
/Applications/Utilities/Console.app
/Applications/Utilities/Digital Color Meter.app
/Applications/Utilities/Disk Utility.app
/Applications/Utilities/Feedback Assistant.app
/Applications/Utilities/Grab.app
/Applications/Utilities/Grapher.app
/Applications/Utilities/Keychain Access.app
/Applications/Utilities/Migration Assistant.app
/Applications/Utilities/Script Editor.app
/Applications/Utilities/System Information.app
/Applications/Utilities/Terminal.app
/Applications/Utilities/VoiceOver Utility.app
/Library/Preferences/SystemConfiguration/com.apple.Boot.plist
/System
* /System/Library/Caches
booter /System/Library/CoreServices
* /System/Library/CoreServices/Photo Library Migration Utility.app
/System/Library/CoreServices/RawCamera.bundle
* /System/Library/Extensions
/System/Library/Extensions/*
UpdateSettings /System/Library/LaunchDaemons/com.apple.UpdateSettings.plist
* /System/Library/Speech
* /System/Library/User Template
/bin
dyld /private/var/db/dyld
/sbin
/usr
* /usr/libexec/cups
* /usr/local
* /usr/share/man
# symlinks
/etc
/tmp
/var
The list is organized in columns, with the leftmost containing an account or group that is allowed to write to the location. Entries with nothing in the first column are wholly protected by SIP. Entries prefaced with an asterisk (the wildcard character), on the other hand, allow writes by any account (look, for instance, at /usr/local—the asterisk in front of it means anyone can write to it). The list is effectively an additive permission list, and subdirectories inherit their parent directories’ SIP protection—for example, /usr/local has to be specifically excepted because its parent, /usr, is listed. You can add things to /System/Library/Extensions, but you can’t change anything there, because /System/Library/Extensions/* is listed. Unlisted locations aren’t watched by SIP—and, yes, SIP also protects the rootless.conf file from being modified. That was the first thing we tried.