cmake可见性和AppArmor示例
This commit is contained in:
parent
0eeb4a7bb6
commit
4b4b933e3d
19 changed files with 661 additions and 0 deletions
123
AppArmor/demo1/run.sh
Executable file
123
AppArmor/demo1/run.sh
Executable file
|
|
@ -0,0 +1,123 @@
|
|||
#!/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 "===== Pre‑cleanup: 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 ratelimit(kauditd callbacks suppressed),
|
||||
# 把随后 demo 真正的 DENIED 审计事件一并丢弃。
|
||||
log "pre‑cleanup 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}"
|
||||
Loading…
Add table
Add a link
Reference in a new issue