mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +01:00
Merge from trunk revision 1805:
Attached is a patch to make the initscript not fail if /tmp is full by converting the comm(1) usage on temporary files to an embedded awk script. On both Ubuntu and OpenSUSE, a version of awk (mawk in Ubuntu, gawk in OpenSUSE) is either a direct or indirect dependency on the minimal or base package set, and the original reporter also mentioned that an awk-based solution would be palatable in a way that converting to bash, or using perl or python here would not be. In the embedded awk script, I've tried to avoid gawk or mawk specific behaviors or extensions; e.g. this is the reason for the call to sort on the output of the awk script, rather than using gawk's asort(). But please let me know if you see anything that shouldn't be portable across awk implementations. An additional issue that is fixed in both scripts is handling child profiles (e.g. hats) during reload. If child profiles are filtered out (via grep -v '//') of the list to consider, then on reloading a profile where a child profile has been removed or renamed, that child profile will continue to stick around. However, if the profile containing child profiles is removed entirely, if the initscript attempts to unload the child profiles after the parent is removed, this will fail because they were unloaded when the parent was unloaded. Thus I removed any filtering of child profiles out, but do a post-awk reverse sort which guarantees that any child profiles will be removed before their parent is. I also added the LC_COLLATE=C (based on the Ubuntu version) to the sort call to ensure a consistent sort order. To restate, the problem with the existing code is that it creates temporary files in $TMPDIR (by default /tmp) and if that partition is full, problems with the reload action ensue. Alternate solutions include switching the initscript to use bash and its <$() extension or setting TMPDIR to /dev/shm/. The former is unpalatable to some (particularly for an initscript), and for the latter, /dev/shm is only guaranteed to exist on GNU libc based systems (glibc apparently expects /dev/shm to exist for its POSIX shared memory implementation; see shm_overview(7)). So to me, awk (sans GNU extensions) looks to be the least bad option here. Nominated-By: Steve Beattie <sbeattie@ubuntu.com> Acked-By: John Johansen <john.johansen@canonical.com> Bug: https://launchpad.net/bugs/775785
This commit is contained in:
parent
3dfebc380d
commit
3186b09035
1 changed files with 29 additions and 25 deletions
|
@ -83,15 +83,6 @@ SECURITYFS=/sys/kernel/security
|
||||||
SUBDOMAINFS_MOUNTPOINT=$(grep subdomainfs /etc/fstab | \
|
SUBDOMAINFS_MOUNTPOINT=$(grep subdomainfs /etc/fstab | \
|
||||||
sed -e 's|^[[:space:]]*[^[:space:]]\+[[:space:]]\+\(/[^[:space:]]*\)[[:space:]]\+subdomainfs.*$|\1|' 2> /dev/null)
|
sed -e 's|^[[:space:]]*[^[:space:]]\+[[:space:]]\+\(/[^[:space:]]*\)[[:space:]]\+subdomainfs.*$|\1|' 2> /dev/null)
|
||||||
|
|
||||||
if [ -d "/var/lib/${MODULE}" ] ; then
|
|
||||||
APPARMOR_TMPDIR="/var/lib/${MODULE}"
|
|
||||||
elif [ -d "/var/lib/${OLD_MODULE}" ] ; then
|
|
||||||
APPARMOR_TMPDIR="/var/lib/${OLD_MODULE}"
|
|
||||||
else
|
|
||||||
APPARMOR_TMPDIR="/tmp"
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
# keep exit status from parser during profile load. 0 is good, 1 is bad
|
# keep exit status from parser during profile load. 0 is good, 1 is bad
|
||||||
STATUS=0
|
STATUS=0
|
||||||
|
|
||||||
|
@ -223,7 +214,6 @@ parse_profiles() {
|
||||||
|
|
||||||
profiles_names_list() {
|
profiles_names_list() {
|
||||||
# run the parser on all of the apparmor profiles
|
# run the parser on all of the apparmor profiles
|
||||||
TMPFILE=$1
|
|
||||||
if [ ! -f "$PARSER" ]; then
|
if [ ! -f "$PARSER" ]; then
|
||||||
aa_log_failure_msg "- AppArmor parser not found"
|
aa_log_failure_msg "- AppArmor parser not found"
|
||||||
exit 1
|
exit 1
|
||||||
|
@ -236,9 +226,9 @@ profiles_names_list() {
|
||||||
|
|
||||||
for profile in $PROFILE_DIR/*; do
|
for profile in $PROFILE_DIR/*; do
|
||||||
if skip_profile "${profile}" && [ -f "${profile}" ] ; then
|
if skip_profile "${profile}" && [ -f "${profile}" ] ; then
|
||||||
LIST_ADD=$($PARSER $ABSTRACTIONS -N "$profile" | grep -v '//')
|
LIST_ADD=$($PARSER $ABSTRACTIONS -N "$profile" )
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo "$LIST_ADD" >>$TMPFILE
|
echo "$LIST_ADD"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
@ -409,18 +399,16 @@ remove_profiles() {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
retval=0
|
retval=0
|
||||||
#the list of profiles isn't stable once we start adding or removing
|
# We filter child profiles as removing the parent will remove
|
||||||
#them so store to tmp first (in reverse order so hat profiles are removed first)
|
# the children
|
||||||
MODULE_PLIST=$(mktemp ${APPARMOR_TMPDIR}/tmp.XXXXXXXX)
|
sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" \
|
||||||
sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" | sort -r > "$MODULE_PLIST"
|
LC_COLLATE=C sort | grep -v // | while read profile ; do
|
||||||
cat "$MODULE_PLIST" | while read profile ; do
|
|
||||||
echo -n "$profile" > "$SFS_MOUNTPOINT/.remove"
|
echo -n "$profile" > "$SFS_MOUNTPOINT/.remove"
|
||||||
rc=$?
|
rc=$?
|
||||||
if [ ${rc} -ne 0 ] ; then
|
if [ ${rc} -ne 0 ] ; then
|
||||||
retval=${rc}
|
retval=${rc}
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
rm "$MODULE_PLIST"
|
|
||||||
return ${retval}
|
return ${retval}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,17 +450,33 @@ __apparmor_restart() {
|
||||||
|
|
||||||
configure_owlsm
|
configure_owlsm
|
||||||
parse_profiles reload
|
parse_profiles reload
|
||||||
PNAMES_LIST=$(mktemp ${APPARMOR_TMPDIR}/tmp.XXXXXXXX)
|
|
||||||
profiles_names_list ${PNAMES_LIST}
|
|
||||||
MODULE_PLIST=$(mktemp ${APPARMOR_TMPDIR}/tmp.XXXXXXXX)
|
|
||||||
# Clean out running profiles not associated with the current profile
|
# Clean out running profiles not associated with the current profile
|
||||||
# set, excluding the libvirt dynamically generated profiles.
|
# set, excluding the libvirt dynamically generated profiles.
|
||||||
sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" | egrep -v '^libvirt-[0-9a-f\-]+$' | sort >"$MODULE_PLIST"
|
# Note that we reverse sort the list of profiles to remove to
|
||||||
sort "$PNAMES_LIST" | comm -2 -3 "$MODULE_PLIST" - | while IFS= read profile ; do
|
# ensure that child profiles (e.g. hats) are removed before the
|
||||||
|
# parent. We *do* need to remove the child profile and not rely
|
||||||
|
# on removing the parent profile when the profile has had its
|
||||||
|
# child profile names changed.
|
||||||
|
profiles_names_list | awk '
|
||||||
|
BEGIN {
|
||||||
|
while (getline < "'${SFS_MOUNTPOINT}'/profiles" ) {
|
||||||
|
str = sub(/ \((enforce|complain)\)$/, "", $0);
|
||||||
|
if (match($0, /^libvirt-[0-9a-f\-]+$/) == 0)
|
||||||
|
arr[$str] = $str
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ if (length(arr[$0]) > 0) { delete arr[$0] } }
|
||||||
|
|
||||||
|
END {
|
||||||
|
for (key in arr)
|
||||||
|
if (length(arr[key]) > 0) {
|
||||||
|
printf("%s\n", arr[key])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' | LC_COLLATE=C sort -r | while IFS= read profile ; do
|
||||||
echo -n "$profile" > "$SFS_MOUNTPOINT/.remove"
|
echo -n "$profile" > "$SFS_MOUNTPOINT/.remove"
|
||||||
done
|
done
|
||||||
rm "$MODULE_PLIST"
|
|
||||||
rm "$PNAMES_LIST"
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue