examples/AppArmor/demo1/run.sh

123 lines
4.6 KiB
Bash
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# 运行方法:
# step1: chmod +x run.sh demo_shell.sh
# step2: sudo sh run.sh
set -e
WORK_DIR=$(cd "$(dirname "$0")" && pwd)
cd "${WORK_DIR}"
if [ "$(id -u)" -ne 0 ];then
echo "please run with sudo: sudo sh run.sh"
exit 1
fi
ELF_BIN="${WORK_DIR}/demo_app"
SCRIPT_FILE="${WORK_DIR}/demo_shell.sh"
PROFILE_ELF_NAME="home.fnzhang.aa_demo.demo_app"
PROFILE_SCRIPT_NAME="home.fnzhang.aa_demo.demo_shell"
PROFILE_ELF="/etc/apparmor.d/${PROFILE_ELF_NAME}"
PROFILE_SCRIPT="/etc/apparmor.d/${PROFILE_SCRIPT_NAME}"
REPORT="${WORK_DIR}/report.txt"
> "${REPORT}"
log(){
echo "$1"
echo "$1" >> "${REPORT}"
}
echo "========================================"
echo "AppArmor Demo start, workdir: ${WORK_DIR}"
echo "========================================"
# ========== 【前置清理:解决上次残留冲突】 ==========
log ""
log "===== Precleanup: remove leftover profile ====="
# 卸载内核中可能残留的旧 profile-R 按 profile 名卸载)
apparmor_parser -R "${PROFILE_ELF}" 2>/dev/null || true
apparmor_parser -R "${PROFILE_SCRIPT}" 2>/dev/null || true
# 清掉 /etc/apparmor.d 下旧文件(含上次失败残留的错误 profile
rm -f "${PROFILE_ELF}" "${PROFILE_SCRIPT}"
# 注意:不使用 systemctl reload apparmor —— 它会重载全部 200+ 个 profile
# 触发内核 printk ratelimitkauditd callbacks suppressed
# 把随后 demo 真正的 DENIED 审计事件一并丢弃。
log "precleanup done"
# ========== Step1 compile C elf ==========
log ""
log "===== Step1 compile C elf ====="
gcc "${WORK_DIR}/demo_app.c" -o "${ELF_BIN}"
chmod +x "${ELF_BIN}"
log "compile done: ${ELF_BIN}"
# ========== Step2 validate profile syntax ==========
log ""
log "===== Step2 validate profile syntax ====="
apparmor_parser -Q "${WORK_DIR}/profile.elf" && log "profile.elf syntax OK"
apparmor_parser -Q "${WORK_DIR}/profile.script" && log "profile.script syntax OK"
# ========== Step3 install profile ==========
log ""
log "===== Step3 install profile ====="
cp "${WORK_DIR}/profile.elf" "${PROFILE_ELF}"
cp "${WORK_DIR}/profile.script" "${PROFILE_SCRIPT}"
apparmor_parser -r -W "${PROFILE_ELF}" || { rm -f "${PROFILE_ELF}"; log "ERROR: elf profile load failed"; exit 1; }
apparmor_parser -r -W "${PROFILE_SCRIPT}" || { rm -f "${PROFILE_SCRIPT}"; log "ERROR: script profile load failed"; exit 1; }
log "profile installed & enforce enabled"
# 等待内核 audit ratelimit 窗口恢复,避免 DENIED 事件被 printk ratelimit 吞掉
sleep 6
# ========== Step4 run elf demo_app ==========
log ""
log "===== Step4 run elf demo_app ====="
rm -f /tmp/demo_elf.log /tmp/demo_forbidden.log
"${ELF_BIN}" 2>&1 | tee -a "${REPORT}" || log "(demo_app returned non-zero / was killed - expected)"
log "-- verify /tmp/demo_elf.log exists (allowed write):"
ls -l /tmp/demo_elf.log 2>&1 | tee -a "${REPORT}"
# ========== Step5 run shell script ==========
log ""
log "===== Step5 run shell script ====="
rm -f /tmp/demo_sh.log /tmp/demo_forbidden.log
"${SCRIPT_FILE}" 2>&1 | tee -a "${REPORT}" || log "(demo_shell.sh returned non-zero / was killed - expected)"
log "-- verify /tmp/demo_sh.log exists (allowed write):"
ls -l /tmp/demo_sh.log 2>&1 | tee -a "${REPORT}"
# ========== Step6 aa-status snapshot ==========
log ""
log "===== Step6 aa-status snapshot ====="
aa-status --json 2>/dev/null | python3 -c "
import json,sys
d = json.load(sys.stdin)
for name, mode in sorted(d.get('profiles', {}).items()):
if 'demo_app' in name or 'demo_shell' in name:
print(f' {name}: {mode}')
" | tee -a "${REPORT}"
# ========== Step7 check deny evidences ==========
log ""
log "===== Step7 AppArmor DENIED logs ====="
# 等 ratelimit 窗口过去再收集sleep 6 已在 Step3 后做过,这里直接查)
dmesg 2>/dev/null | grep -iE 'apparmor=\"DENIED\"' | grep -iE 'demo_app|demo_shell' | tail -10 | tee -a "${REPORT}" \
|| journalctl -k -b --no-pager 2>/dev/null | grep -iE 'apparmor=\"DENIED\"' | grep -iE 'demo_app|demo_shell' | tail -10 | tee -a "${REPORT}"
if [ -z "$(dmesg 2>/dev/null | grep 'apparmor=\"DENIED\"' | grep -iE 'demo_app|demo_shell')" ]; then
log "(提示: 若此处为空, 可能被内核 printk ratelimit 抑制; 显式 deny 规则本身不产生日志)"
fi
# ========== Step8 clean resources ==========
log ""
log "===== Step8 clean resources ====="
apparmor_parser -R "${PROFILE_ELF}" 2>/dev/null || true
apparmor_parser -R "${PROFILE_SCRIPT}" 2>/dev/null || true
rm -f "${PROFILE_ELF}" "${PROFILE_SCRIPT}"
rm -f "${ELF_BIN}"
rm -f /tmp/demo_elf.log /tmp/demo_sh.log /tmp/demo_forbidden.log
log ""
log "========================================"
log "Demo finished, report file: ${REPORT}"