BGMXPCHelper now runs as an unprivileged user, instead of root.

BGMXPCHelper's install script now creates a user and group for
BGMXPCHelper to run as. This reduces the risk of BGMXPCHelper being used
for privilege escalation.
This commit is contained in:
Kyle Neideck 2016-04-07 00:48:36 +10:00
parent 690d6221d7
commit f3151e3159
4 changed files with 75 additions and 12 deletions

View file

@ -27,15 +27,14 @@
<string>Adaptive</string>
<!--
{{# TODO: Have post_install.sh create this user and group. Then uncomment this so BGMXPCHelper doesn't run #}}
{{# as root. #}}
{{# #}}
{{# <key>UserName</key> #}}
{{# <string>_BGMXPCHelper</string> #}}
{{# <key>GroupName</key> #}}
{{# <string>_BGMXPCHelper</string> #}}
{{# post_install.sh creates this user and group. #}}
-->
<key>UserName</key>
<string>{{BGMXPCHELPER_USER_NAME}}</string>
<key>GroupName</key>
<string>{{BGMXPCHELPER_GROUP_NAME}}</string>
<!--
{{# Uncomment this to log output from BGMXPCHelper. (It logs to syslog by default, so you'd have to change #}}
{{# that if you want logs to go to these files.) #}}

View file

@ -24,8 +24,8 @@
#
# Installs BGMXPCHelper's launchd plist file and "bootstraps" (registers/enables) it with launchd.
#
# When you install BGMXPCHelper with xcodebuild (Or Xcode itself. I can't figure out if that's
# possible) this script runs as the final build phase.
# When you install BGMXPCHelper with xcodebuild (or Xcode itself, if that's possible) this script
# runs as the final build phase.
#
# Check the environment variables we need from Xcode.
@ -58,10 +58,60 @@ if [[ $(bash "${RESOURCES_PATH}/safe_install_dir.sh" "${INSTALL_DIR}") != 1 ]];
"insecure. See safe_install_dir.sh for details." >&2
fi
HELPER_USER=_BGMXPCHelper
LAUNCHD_PLIST_INSTALL_PATH=/Library/LaunchDaemons
LAUNCHD_PLIST_FILENAME=com.bearisdriving.BGM.XPCHelper.plist
LAUNCHD_PLIST=${LAUNCHD_PLIST_INSTALL_PATH}/${LAUNCHD_PLIST_FILENAME}
# Create an unprivileged user for BGMXPCHelper to run as.
if [[ "$(dscl . -search /Users RecordName ${HELPER_USER})" == "" ]]; then
# Find an unused UID and GID. UIDs from 0 to 500 are reserved by OSX.
HELPER_UID=$(dscl . -list /Users UniqueID | \
awk '{ a[$2] } END { for (i=501; i in a; i++); print i }')
HELPER_GID=$(dscl . -list /Groups PrimaryGroupID | \
awk '{ a[$2] } END { for (i='${HELPER_UID}'; i in a; i++); print i }')
# Check the UID and GID.
NUMERIC_ID_REGEX='^[1-9][0-9]*$'
([[ "${HELPER_UID}" =~ ${NUMERIC_ID_REGEX} ]] && \
[[ ${HELPER_UID} -gt 500 ]] && \
[[ "$(dscl . -search /Users UniqueID ${HELPER_UID})" == "" ]]) || \
(echo "Internal error. Failed to generate a user ID. HELPER_UID=${HELPER_UID}" >&2; exit 1)
([[ "${HELPER_GID}" =~ ${NUMERIC_ID_REGEX} ]] && \
[[ ${HELPER_GID} -gt 500 ]] && \
[[ "$(dscl . -search /Groups PrimaryGroupID ${HELPER_GID})" == "" ]]) || \
(echo "Internal error. Failed to generate a group ID. HELPER_GID=${HELPER_GID}" >&2; exit 1)
# Create the group.
sudo dscl . -create /Groups/${HELPER_USER} PrimaryGroupID ${HELPER_GID}
sudo dscl . -create /Groups/${HELPER_USER} RealName "Background Music XPC Helper Group"
sudo dscl . -create /Groups/${HELPER_USER} Password '*'
# Create the user.
sudo dscl . -create /Users/${HELPER_USER} UniqueID ${HELPER_UID}
sudo dscl . -create /Users/${HELPER_USER} PrimaryGroupID ${HELPER_GID}
sudo dscl . -create /Users/${HELPER_USER} RealName "Background Music XPC Helper"
sudo dscl . -create /Users/${HELPER_USER} Password '*'
sudo dscl . -create /Users/${HELPER_USER} UserShell /usr/bin/false
sudo dscl . -create /Users/${HELPER_USER} NFSHomeDirectory /var/empty
sudo dscl . -delete /Users/${HELPER_USER} AuthenticationAuthority
# Add the user to the group
sudo dscl . -append /Groups/${HELPER_USER} GroupMembership ${HELPER_USER}
# Check the user and group were created.
[[ "$(dscl . -search /Users RecordName ${HELPER_USER})" != "" ]] || \
(echo "Internal error. Failed to ${HELPER_USER} user." >&2; exit 1)
[[ "$(dscl . -search /Groups RecordName ${HELPER_USER})" != "" ]] || \
(echo "Internal error. Failed to ${HELPER_USER} group." >&2; exit 1)
echo "Created ${HELPER_USER} user."
fi
# Copy the plist template into place.
sudo cp "${RESOURCES_PATH}/${LAUNCHD_PLIST_FILENAME}.template" "${LAUNCHD_PLIST}"
@ -81,6 +131,9 @@ EXECUTABLE_PATH_ESCAPED="${EXECUTABLE_PATH//\//\\/}"
sudo sed -i.tmp "s/{{PATH_TO_BGMXPCHELPER}}/${INSTALL_DIR_ESCAPED}/g" "${LAUNCHD_PLIST}"
# EXECUTABLE_PATH is set by Xcode, currently to "BGMXPCHelper.xpc/Contents/MacOS/BGMXPCHelper".
sudo sed -i.tmp "s/{{BGMXPCHELPER_EXECUTABLE_PATH}}/${EXECUTABLE_PATH_ESCAPED}/g" "${LAUNCHD_PLIST}"
sudo sed -i.tmp "s/{{BGMXPCHELPER_USER_NAME}}/${HELPER_USER}/g" "${LAUNCHD_PLIST}"
sudo sed -i.tmp "s/{{BGMXPCHELPER_GROUP_NAME}}/${HELPER_USER}/g" "${LAUNCHD_PLIST}"
# Remove template-only comments.
sudo sed -i.tmp 's/{{#.*#}}//g' "${LAUNCHD_PLIST}"

View file

@ -57,7 +57,18 @@ apps playing audio.
- Delete `Background Music.app` from `/Applications`.
- Delete `Background Music Device.driver` from `/Library/Audio/Plug-Ins/HAL`.
#### Optional
- Delete `BGMXPCHelper.xpc` from `/usr/local/libexec` or possibly `/Library/Application Support/Background Music`.
- Unregister BGMXPCHelper, delete its user and group, and delete its launchd.plist:
```shell
sudo launchctl bootout system /Library/LaunchDaemons/com.bearisdriving.BGM.XPCHelper.plist
sudo rm /Library/LaunchDaemons/com.bearisdriving.BGM.XPCHelper.plist
sudo dscl . -delete /Users/_BGMXPCHelper
sudo dscl . -delete /Groups/_BGMXPCHelper
```
- Pause apps that are playing audio, if you can.
- Restart `coreaudiod`:
[//]: # ( <sup>(Open `/Applications/Utilities/Terminal.app` and paste the following at the prompt.)</sup> )

View file

@ -155,9 +155,9 @@ show_spinner
# BGMXPCHelper
INSTALL_DIR=$(BGMApp/BGMXPCHelper/safe_install_dir.sh)
XPC_HELPER_INSTALL_DIR=$(BGMApp/BGMXPCHelper/safe_install_dir.sh)
echo "Installing $(bold_face BGMXPCHelper.xpc) to $(bold_face ${INSTALL_DIR})." \
echo "Installing $(bold_face BGMXPCHelper.xpc) to $(bold_face ${XPC_HELPER_INSTALL_DIR})." \
| tee -a ${LOG_FILE}
(set +e;
@ -166,7 +166,7 @@ sudo xcodebuild -project BGMApp/BGMApp.xcodeproj \
-configuration ${CONFIGURATION} \
RUN_CLANG_STATIC_ANALYZER=0 \
DSTROOT="/" \
INSTALL_PATH="${INSTALL_DIR}" \
INSTALL_PATH="${XPC_HELPER_INSTALL_DIR}" \
install >> ${LOG_FILE} 2>&1) &
show_spinner