219 lines
8.0 KiB
Bash
219 lines
8.0 KiB
Bash
# -*- mode: sh; -*-
|
|
# vim: ft=sh
|
|
# This file is intended to be a wrapper to /etc/rc.d/rc.subr
|
|
# that makes it easy to run software inside of chroot jails.
|
|
# It handles the copying of programs by automatically detecting
|
|
# and installing required shared libraries.
|
|
#
|
|
# NOTE: This file sources /etc/rc.d/rc.subr! DO NOT source it yourself.
|
|
#
|
|
# To use this file, simply include it as
|
|
# . /etc/rc.d/chroot_base
|
|
# Then, use the provided functions in rc_pre and rc_post to
|
|
# set up the chroot jail.
|
|
#
|
|
# The following variables MUST be defined BEFORE sourcing this file:
|
|
# chroot_exec - program to run inside chroot jail
|
|
# chroot_user - user to drop permissions to inside of chroot
|
|
# chroot_group - group to drop permissions to inside of chroot
|
|
# chroot_root - path of chroot jail. Should be owned by root:wheel
|
|
# and writable only by root
|
|
#
|
|
# The following variables MAY be defined BEFORE sourcing this file:
|
|
# chroot_home - if set, the value of $HOME is set to this before the program is started
|
|
# chroot_bin - if set, programs will be coppied here instead of to /bin. See chroot_env_exec
|
|
# for information about adding this to $PATH
|
|
# chroot_env_exec - if set, will be used as the path to the 'env' program in the chroot. You
|
|
# must install and remove this program yourself. If this is set and chroot_bin
|
|
# set, chroot bin will be added to PATH
|
|
# chroot_lib - if set, libraries will be coppied here instead of /usr/lib and it will be added
|
|
# to $LD_LIBRARY_PATH
|
|
# chroot_no_ldso - if set to YES, this script will not touch ld.so in the jail
|
|
# chroot_no_vars - if set to YES, this script will not set any of the daemon* variables or pexp.
|
|
# In addition, you may ignore all the variables except chroot_root
|
|
#
|
|
# The following function are defined by this script:
|
|
# chroot_install - copy files to the chroot
|
|
# chroot_install_program - copy a program and all of its libraries into the chroot
|
|
# chroot_rm - delete files from the chroot
|
|
# chroot_rm_program - delete a program from the chroot along with all of its libraries
|
|
# chroot_mkdev - create device files in the chroot's /dev
|
|
# chroot_mknull - create /dev/null in the chroot
|
|
|
|
# Internal variables used by functions
|
|
_chroot_root_dir="${chroot_root%/}/"
|
|
if [ -z "${chroot_home}" ]; then
|
|
_chroot_user_home="$(grep "${chroot_user}" /etc/passwd | cut -d ":" -f6)"
|
|
else
|
|
_chroot_user_home="${chroot_home}"
|
|
fi
|
|
if [ -z "${chroot_bin}" ]; then
|
|
_chroot_bin_dir="${_chroot_root_dir}bin/"
|
|
_chroot_env_path="PATH='$(getconf PATH)'"
|
|
else
|
|
chroot_bin="${chroot_bin%/}"
|
|
_chroot_bin_dir="${_chroot_root_dir}${chroot_bin#/}/"
|
|
_chroot_env_path="PATH='${chroot_bin}:$(getconf PATH)'"
|
|
fi
|
|
if [ -z "${chroot_lib}" ]; then
|
|
_chroot_lib_dir="${_chroot_root_dir}usr/lib/"
|
|
else
|
|
chroot_lib="${chroot_lib%/}"
|
|
_chroot_lib_dir="${_chroot_root_dir}${chroot_lib#/}/"
|
|
_chroot_env_ld="LD_LIBRARY_PATH='${chroot_lib}'"
|
|
fi
|
|
_chroot_chroot_cmd="/usr/sbin/chroot -u '${chroot_user}' -g '${chroot_user}' '${chroot_root}'"
|
|
|
|
# find our env command
|
|
if [ -z "${chroot_env_exec}" ]; then
|
|
# There is no env inside the chroot, therefore we run it before chroot
|
|
# However, this means we cannon env PATH because the chroot resets it
|
|
_chroot_env_cmd="/usr/bin/env HOME='${_chroot_user_home}' ${_chroot_env_ld}"
|
|
else
|
|
# The user has put env inside the chroot
|
|
# Run it inside, allowing us to set path
|
|
_chroot_inside_env_cmd="${chroot_env_exec} HOME='${_chroot_user_home}' ${_chroot_env_ld} ${_chroot_env_path}"
|
|
fi
|
|
|
|
# Set normal rc.subr variables from chroot_* variables
|
|
if [ "${chroot_no_vars}" != "YES" ]; then
|
|
daemon_user="root"
|
|
daemon="${_chroot_env_cmd} ${_chroot_chroot_cmd} ${_chroot_inside_env_cmd} ${chroot_exec}"
|
|
fi
|
|
|
|
# Source rc.subr
|
|
. /etc/rc.d/rc.subr
|
|
|
|
# Fix the pexp for the chroot
|
|
if [ "${chroot_no_vars}" != "YES" ]; then
|
|
pexp="$(eval echo ${chroot_exec}${daemon_flags:+ ${daemon_flags}})"
|
|
fi
|
|
|
|
# usage: chroot_install [files ...]
|
|
# Copy files into the chroot. Permissions, owner, group, and flags are preserved.
|
|
function chroot_install {
|
|
for file in ${@}; do
|
|
local rel_file
|
|
if echo "${file}" | grep -E '^/' >/dev/null; then
|
|
rel_file="$(echo "${file}" | cut -c '2-')" # remove leading /
|
|
else
|
|
rel_file="${file}"
|
|
fi
|
|
local dir="$(dirname "${rel_file}")"
|
|
if ! [ -d "${_chroot_root_dir}${dir}" ]; then
|
|
mkdir -p "${_chroot_root_dir}${dir}"
|
|
echo "Created '${_chroot_root_dir}${dir}'"
|
|
fi
|
|
cp -Rp "${file}" "${_chroot_root_dir}${rel_file}"
|
|
echo "Installed '${file}' to '${_chroot_root_dir}${rel_file}'"
|
|
done
|
|
}
|
|
|
|
# usage: chroot_install_program <file> [name]
|
|
# Install the program FILE and all of its shared library dependencies
|
|
# to the chroot. Dependencies are found with ldd. If NAME is provided,
|
|
# the program will be coppied as NAME.
|
|
#
|
|
# NOTE: By default, the program is installed to /bin in the chroot
|
|
function chroot_install_program {
|
|
echo "Installing dependencies for '${1}':"
|
|
for dep in $(ldd "${1}" | tail -n '+4' | grep -Eo '/.+$'); do
|
|
if [ "${dep}" == "/usr/libexec/ld.so" ]; then
|
|
if [ "${chroot_no_ldso}" != "YES" ]; then
|
|
if ! [ -d "${_chroot_root_dir}usr/libexec" ]; then
|
|
mkdir -p "${_chroot_root_dir}usr/libexec"
|
|
echo " - Created '${_chroot_root_dir}usr/libexec'"
|
|
fi
|
|
install -o root -g bin -m 0444 "${dep}" "${_chroot_root_dir}usr/libexec/ld.so"
|
|
echo " - Installed '${dep}' to '${_chroot_root_dir}usr/libexec/ld.so'"
|
|
fi
|
|
else
|
|
if ! [ -d "${_chroot_lib_dir}" ]; then
|
|
mkdir -p "${_chroot_lib_dir}"
|
|
echo " - Created '${_chroot_lib_dir}'"
|
|
fi
|
|
local name="$(basename "${dep}")"
|
|
install -o root -g bin -m 0444 "${dep}" "${_chroot_lib_dir}${name}"
|
|
echo " - Installed '${dep}' to '${_chroot_lib_dir}${name}'"
|
|
fi
|
|
done
|
|
if ! [ -d "${_chroot_bin_dir}" ]; then
|
|
mkdir -p "${_chroot_bin_dir}"
|
|
echo "Created '${_chroot_bin_dir}'"
|
|
fi
|
|
local name
|
|
if [ -z "${2}" ]; then
|
|
name="$(basename "${1}")"
|
|
else
|
|
name="${2}"
|
|
fi
|
|
install -o root -g bin -m 0755 "${1}" "${_chroot_bin_dir}${name}"
|
|
echo "Installed '${1}' to '${_chroot_bin_dir}${name}'"
|
|
}
|
|
|
|
# usage: chroot_rm_program <file>
|
|
# Find all libraries of program with ldd and delete them.
|
|
# Then, delete the program FILE from /bin of the chroot.
|
|
#
|
|
# EXAMPLE:
|
|
# The usage
|
|
# chroot_rm_program "/usr/local/bin/git"
|
|
# would run ldd on /bin/git in the chroot and delete all the
|
|
# resulting libraries. It would then remove /bin/git from the
|
|
# chroot.
|
|
function chroot_rm_program {
|
|
local name="$(basename "${1}")"
|
|
local path="${_chroot_bin_dir}${name}"
|
|
echo "Deleting dependencies for '${1}'"
|
|
for dep in $(ldd "${path}" | tail -n '+4' | grep -Eo '/.+$'); do
|
|
if [ "${dep}" == "/usr/libexec/ld.so" ]; then
|
|
if [ "${chroot_no_ldso}" != "YES" ]; then
|
|
rm -f "${_chroot_root_dir}usr/libexec/ld.so"
|
|
echo " - Deleted '${_chroot_root_dir}usr/libexec/ld.so'"
|
|
fi
|
|
else
|
|
local name="$(basename "${dep}")"
|
|
rm -f "${_chroot_lib_dir}${name}"
|
|
echo " - Deleted '${_chroot_lib_dir}${name}'"
|
|
fi
|
|
done
|
|
rm -f "${path}"
|
|
echo "Deleted '${path}'"
|
|
}
|
|
|
|
# usage: chroot_rm [files ...]
|
|
# Remove files from the chroot
|
|
function chroot_rm {
|
|
for file in ${@}; do
|
|
if echo "${file}" | grep -E '^/' >/dev/null; then
|
|
file="$(echo "${file}" | cut -c '2-')" # remove leading /
|
|
fi
|
|
rm -rf "${_chroot_root_dir}${file}"
|
|
echo "Deleted '${_chroot_root_dir}${file}'"
|
|
done
|
|
}
|
|
|
|
# usage: chroot_mkdev [names ...]
|
|
# Runs /dev/MAKEDEV with NAMES as the argument in the chroot's
|
|
# /dev directory
|
|
function chroot_mkdev {
|
|
if ! [ -d "${_chroot_root_dir}dev" ]; then
|
|
mkdir "${_chroot_root_dir}dev"
|
|
echo "Created '${_chroot_root_dir}dev'"
|
|
fi
|
|
(cd "${_chroot_root_dir}dev" && /dev/MAKEDEV "$@")
|
|
echo "Created device files for '$@' in '${_chroot_root_dir}dev'"
|
|
}
|
|
|
|
# usage: chroot_mknull
|
|
# This is a convinience function that creates /dev/null in the
|
|
# chroot.
|
|
function chroot_mknull {
|
|
if ! [ -d "${_chroot_root_dir}dev" ]; then
|
|
mkdir "${_chroot_root_dir}dev"
|
|
echo "Created '${_chroot_root_dir}dev'"
|
|
fi
|
|
mknod -m 0666 "${_chroot_root_dir}dev/null" c 2 2
|
|
echo "Created /dev/null as '${_chroot_root_dir}dev/null'"
|
|
}
|