apparmor使用心得

发布于:2025-07-22 ⋅ 阅读:(15) ⋅ 点赞:(0)

1.再配置前,最好先安装下sudo apt install apparmor-*,我这ubuntu22.04默认有工具没装全
2.官方wiki:https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorMonitoring(较有用)
3.debian文档:https://manpages.debian.org/bookworm/apparmor/apparmor_parser.8.en.html(用处不太大)
4.一个成功可用的例子:

#include <tunables/global>

profile /home/lzs/workspace/test/test.sh {
    /home/lzs/workspace/test/test.sh rk,
    # ===== 核心修复 =====
    # 1. 必须先声明拒绝规则
    /home/lzs/workspace/** rwlk,
    #audit deny /home/lzs/workspace/output/* rwxl,
    #deny /home/lzs/workspace/output/.* rwkl,
    # 2. 然后声明脚本权限
    # 其他必要规则(如临时文件、库等)
    /home/lzs/workspace/test/** rw,
    deny /home/lzs/workspace/output/* rwkl,
    capability dac_read_search,
    /bin/sh ix,
    /usr/bin/* ix,
    /usr/lib/** rm,
    /lib/** rm,
    /etc/ld.so.cache r,
    /usr/share/** r,
    /etc/** r,
    signal (receive) peer=/home/lzs/workspace/test/test.sh,
    signal (receive) peer=unconfined,  # 如果需要与其他未受限制的进程交互
    /dev/pts/[0-9]* rw,
    capability dac_override,
}

5.调试的经验:
在配置好了直接执行还无法生效时,可以使用aa-exec执行,先确保此方法直接执行生效了,再编写system服务,system服务也生效了,再来看直接执行未生效是否解决;此外使用tail -f /var/log/syslog时刻关注测试的脚本执行情况,通过ai解析排查;下面是几种加载apparmor策略的方式,其中system服务的,如果我配置好之后执行了sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh,实际上已经不用再在system服务中再次指定

如果想 不通过 aa-exec 但仍让 /home/lzs/workspace/test/test.sh 按定义好的 AppArmor 策略执行,可以通过以下方法实现。核心思路是 让脚本在启动时自动加载对应的 AppArmor 策略,或 利用系统服务或启动脚本强制应用策略。
方法 1:直接运行脚本时手动加载策略(推荐)
步骤

确保策略已加载到 AppArmor
使用 apparmor_parser 将策略文件加载到内核(无需通过 aa-exec):

bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

-r 表示重新加载(如果策略已存在,先卸载再加载)。
确认策略已激活:

bash

sudo apparmor_status | grep test.sh

直接运行脚本
由于策略已加载到内核,脚本运行时会自动继承该策略的约束:

bash

sudo /home/lzs/workspace/test/test.sh

关键点:脚本必须以 与策略定义匹配的方式运行(如策略是针对 root 用户执行的,则需用 sudo)。

验证策略是否生效
检查日志确认脚本是否被策略限制:

bash

sudo dmesg | grep apparmor

    如果策略生效,日志会显示 apparmor="ALLOWED" 或 apparmor="DENIED"(根据操作是否被允许)。

方法 2:通过 systemd 服务强制应用策略

如果脚本是作为服务运行的(如后台守护进程),可以在 systemd 单元文件中指定 AppArmorProfile,让系统自动加载策略。
步骤

创建或修改 systemd 服务文件
编辑 /etc/systemd/system/test-script.service:

ini

[Unit]
Description=Test Script with AppArmor
After=network.target

[Service]
Type=simple
ExecStart=/home/lzs/workspace/test/test.sh
User=root # 根据策略要求调整用户
AppArmorProfile=/etc/apparmor.d/home.lzs.workspace.test.test.sh # 指定策略路径
Restart=on-failure

[Install]

WantedBy=multi-user.target

重新加载 systemd 并启动服务

bash

sudo systemctl daemon-reload
sudo systemctl start test-script.service

sudo systemctl status test-script.service # 检查是否运行正常

验证策略是否生效
查看服务日志和 AppArmor 日志:

bash

journalctl -u test-script.service -f # 实时查看服务日志

sudo dmesg | grep apparmor             # 检查 AppArmor 拒绝事件

方法 3:通过 cron 定时任务强制应用策略

如果脚本是通过 cron 运行的,可以在 crontab 中指定 AppArmor 策略(需结合 aa-exec 或手动加载策略)。
步骤

手动加载策略(与方法 1 相同)

bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

编辑 crontab
直接运行脚本(策略已加载到内核):

bash

sudo crontab -e

添加任务(例如每分钟运行一次):

plaintext

          • /home/lzs/workspace/test/test.sh

验证
检查 cron 日志和 AppArmor 日志:

bash

sudo tail -f /var/log/syslog | grep cron

sudo dmesg | grep apparmor

方法 4:通过 wrapper 脚本强制加载策略

创建一个包装脚本(wrapper),在运行目标脚本前先确保策略已加载。
步骤

创建包装脚本 /usr/local/bin/run-test-with-apparmor.sh

bash

#!/bin/bash

加载策略(如果未加载)

if ! sudo apparmor_status | grep -q “home.lzs.workspace.test.test.sh”; then
sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh
fi

运行目标脚本

sudo /home/lzs/workspace/test/test.sh

赋予执行权限

bash

sudo chmod +x /usr/local/bin/run-test-with-apparmor.sh

直接运行包装脚本

bash

sudo /usr/local/bin/run-test-with-apparmor.sh

6.一些调试记录(含问题)

New Chat
Document Hub
Image Studio

Recent Chats
Aparmor Debuggi
使用ifconfig修改IP
if [ ${ROS_VERS
如何将linux 编译的可执
变化点分析表完成的节点是
More...

chanalzs

Ernie 4.5 Turbo
为什么我配置了/etc/apparmor.d/home.lzs.workspace.test规则,对system服务和aa-exec执行都有效,命令行直接启动就无效呢,是终端有什么策略覆盖了么

要为通过 ros2 run 启动的 ROS 2 节点(如 camera_pkg 的 camera_node)配置 AppArmor 权限,需确保 AppArmor 规则能正确匹配 ROS 2 节点的实际执行路径。以下是详细步骤:
1. 确认节点的实际执行路径

ROS 2 的 ros2 run 会通过 Python 或原生二进制启动节点,具体路径取决于包的安装方式:

    Python 脚本节点:通常位于 install/<pkg_name>/lib/<pkg_name>/<node_name> 或 ~/.ros/ 下的 Python 文件。
    编译后的二进制节点:位于 install/<pkg_name>/lib/<pkg_name>/<node_name>。

查找路径的方法:

bash

# 方法1:通过 ros2 命令查找节点路径

ros2 pkg executables camera_pkg | grep camera_node

 

# 方法2:通过进程信息查找(启动节点后)

ps -aux | grep camera_node

假设输出路径为:
/home/lzs/ros2_ws/install/camera_pkg/lib/camera_pkg/camera_node
2. 创建 AppArmor 配置文件

根据节点的绝对路径创建配置文件,命名规则为:
/etc/apparmor.d/<替换路径中的斜杠为点>
例如:

bash

sudo nano /etc/apparmor.d/home.lzs.ros2_ws.install.camera_pkg.lib.camera_pkg.camera_node

3. 编写 AppArmor 规则

在配置文件中定义权限,例如:

# 允许访问特定目录(如 /opt/ros_data)

/opt/ros_data/** rw,

 

# 允许访问设备(如摄像头)

/dev/video0 rw,

 

# 允许网络通信(ROS 2 默认使用 UDP/TCP)

network,

 

# 允许访问 ROS 2 日志目录

/home/lzs/.ros/log/** rw,

 

# 允许访问共享库(根据实际需要调整)

/usr/lib/** rm,

完整示例:

profile home.lzs.ros2_ws.install.camera_pkg.lib.camera_pkg.camera_node {

  # 文件访问

  /opt/ros_data/** rw,

  /home/lzs/.ros/log/** rw,

 

  # 设备访问

  /dev/video0 rw,

 

  # 网络权限

  network,

 

  # 共享库

  /usr/lib/** rm,

 

  # 禁止访问其他敏感目录(可选)

  deny /etc/** r,

  deny /root/** rwk,

}

4. 加载配置

bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.ros2_ws.install.camera_pkg.lib.camera_pkg.camera_node

5. 验证配置
检查进程是否受限制

启动节点后,通过以下命令验证:

bash

ps -Z | grep camera_node

输出应显示:
home.lzs.ros2_ws.install.camera_pkg.lib.camera_pkg.camera_node
测试权限

    正常情况:节点应能访问配置中允许的目录(如 /opt/ros_data)。
    拒绝情况:尝试访问未授权的目录(如 /root)会被阻止,并在 /var/log/syslog 中记录:

    bash

    sudo grep apparmor /var/log/syslog | grep DENIED

6. 处理 ROS 2 的特殊情况
动态加载的 Python 节点

如果节点是 Python 脚本(通过 ros2 run 调用),需匹配 Python 解释器的路径:

bash

which python3

输出可能是 /usr/bin/python3,则配置文件应为:

/etc/apparmor.d/usr.bin.python3

并在规则中限制脚本路径:

profile usr.bin.python3 {

  # 允许加载 ROS 2 Python 节点

  /home/lzs/ros2_ws/install/camera_pkg/lib/camera_pkg/camera_node.py r,

  /opt/ros/** r,

  ...

}

DDS 通信权限

ROS 2 依赖 DDS(如 Fast DDS、Cyclone DDS),可能需要额外网络规则:

# 允许 UDP 多播(ROS 2 默认使用)

network udp,

network raw,

7. 调试技巧

    强制生成拒绝日志:在配置中添加 audit 标志:

profile home.lzs.ros2_ws.install.camera_pkg.lib.camera_pkg.camera_node {

  audit deny /tmp/** rw,  # 记录对 /tmp 的拒绝操作

  ...

}

临时放宽权限:使用 complain 模式监控行为而不阻止:

bash

    sudo aa-complain /etc/apparmor.d/home.lzs.ros2_ws.install.camera_pkg.lib.camera_pkg.camera_node

总结

    确认节点路径:通过 ros2 pkg executables 或 ps 查找。
    创建匹配的配置文件:替换路径中的 / 为 .。
    定义精确权限:限制文件、设备、网络访问。
    加载并验证:使用 apparmor_parser 和 ps -Z 检查。
    处理 Python/DDS 特殊情况:根据实际运行时调整规则。

通过以上步骤,您可以为 ROS 2 节点配置严格的 AppArmor 权限,同时确保其正常运行。
Regenerate
如果我的进程是通过ros2 run 启动的,比如ros2 run camera_pkg camera_node,如何配置它指定目录的权限?

针对您配置的AppArmor规则在system服务和aa-exec下有效,但命令行直接启动无效的问题,可能的原因及解决方案如下:
1. 终端进程未继承AppArmor配置

    现象:当通过命令行直接启动脚本时,终端进程(如bash或zsh)可能未加载对应的AppArmor配置,导致子进程(您的脚本)继承了终端的宽松策略。
    验证方法:
        使用ps -Z查看命令行启动的脚本进程的AppArmor模式:

        bash

ps -Z -p $(pgrep -f test.sh)

如果输出显示unconfined,说明未加载配置。
对比system服务启动的进程:

bash

    systemctl status <your_service>  # 查看服务进程的AppArmor模式

解决方案:

    显式指定配置文件:通过aa-exec强制加载配置:

    bash

aa-exec -p /etc/apparmor.d/home.lzs.workspace.test.sh -- /home/lzs/workspace/test/test.sh

修改终端启动方式:在终端中直接使用apparmor_parser临时加载配置:

bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.sh

        /home/lzs/workspace/test/test.sh  # 再次尝试启动

2. 配置文件路径或命名不匹配

    现象:AppArmor配置文件的命名必须与可执行文件的绝对路径严格匹配(斜杠替换为点)。例如:
        脚本路径为/home/lzs/workspace/test/test.sh,则配置文件应为:

    /etc/apparmor.d/home.lzs.workspace.test.test.sh

    如果路径或文件名拼写错误,AppArmor会静默忽略配置。

验证方法:

    检查配置文件是否存在:

    bash

ls -l /etc/apparmor.d/home.lzs.workspace.test.test.sh

使用aa-status查看已加载的配置:

bash

        sudo aa-status | grep test.sh

    解决方案:
        修正配置文件名,确保与脚本路径完全一致。
        如果脚本通过相对路径启动,需在配置文件中使用绝对路径规则。

3. 终端环境变量或权限差异

    现象:终端启动的脚本可能因环境变量(如PATH、USER)或权限不同,导致访问路径变化,从而绕过AppArmor规则。
    验证方法:
        在脚本中打印当前路径和环境变量:

        bash

#!/bin/bash

echo "Current PATH: $PATH"

echo "Current USER: $USER"

    # 触发被拒绝的操作(如访问/dev/pts/4)

    对比system服务启动时的日志(/var/log/syslog或journalctl)。

解决方案:

    在AppArmor配置中显式允许所需路径:

        /dev/pts/[0-9]* rw,

        限制脚本的环境变量(如通过env命令或systemd的Environment=选项)。

4. 终端的AppArmor模式覆盖

    现象:某些终端模拟器(如gnome-terminal、tmux)可能以独立进程运行,并加载了不同的AppArmor配置(如unconfined)。
    验证方法:
        检查终端进程的AppArmor模式:

        bash

        ps -Z -p $(pgrep gnome-terminal)  # 或其他终端模拟器

        如果终端进程为unconfined,其子进程可能继承此模式。
    解决方案:
        为终端模拟器配置AppArmor规则(需谨慎操作,可能影响稳定性)。
        改用aa-exec或systemd用户服务启动脚本。

推荐操作步骤

    验证配置文件加载:

    bash

sudo aa-status | grep test.sh

如果未加载,手动重新加载:

bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

检查进程模式:

bash

ps -Z -p $(pgrep -f test.sh)

确保输出包含home.lzs.workspace.test.test.sh。

简化测试:

    创建一个最小化测试脚本:

    bash

echo "#!/bin/bash" > /tmp/test_apparmor.sh

echo "touch /tmp/apparmor_test" >> /tmp/test_apparmor.sh

chmod +x /tmp/test_apparmor.sh

配置对应的AppArmor规则:

/tmp/test_apparmor.sh {

  /tmp/apparmor_test w,

}

分别通过命令行和aa-exec测试:

bash

/tmp/test_apparmor.sh  # 直接运行

    aa-exec -p /etc/apparmor.d/tmp.test_apparmor -- /tmp/test_apparmor.sh

检查日志:

    查看AppArmor拒绝日志:

    bash

        sudo grep apparmor /var/log/syslog

通过以上步骤,您应能定位到具体原因(如配置未加载、路径不匹配或终端环境问题)。如果问题仍存在,建议提供sudo aa-status和sudo grep apparmor /var/log/syslog的输出以便进一步分析。
为什么我配置了/etc/apparmor.d/home.lzs.workspace.test规则,对system服务和aa-exec执行都有效,命令行直接启动就无效呢,是终端有什么策略覆盖了么

这个错误表明你的 AppArmor 策略文件 /etc/apparmor.d/home.lzs.workspace.test.test.sh 存在 语法错误,具体是:

    错误类型:syntax error, unexpected TOK_CAPABILITY, expecting TOK_END_OF_RULE
    原因:在策略文件中,capability 规则的语法不正确,可能是:
        缺少逗号(,)或分号(;)。
        capability 规则放在了错误的位置(如 profile 定义之外)。
        使用了错误的格式(如 capability=dac_override 而不是 capability dac_override,)。

如何修复?
1. 检查策略文件语法

运行以下命令检查语法:

bash

sudo apparmor_parser -Q /etc/apparmor.d/home.lzs.workspace.test.test.sh

如果仍有错误,请手动检查文件内容。
2. 正确的 capability 语法

在 AppArmor 策略中,capability 规则的正确写法是:

capability dac_override,

或(如果允许多个能力):

capability dac_override,

capability setuid,

注意:

    每个 capability 规则必须以 逗号(,)结尾(除非是最后一行)。
    不能写成 capability=dac_override(这是 auditctl 或 seccomp 的语法,不是 AppArmor)。

3. 示例修复

假设你的策略文件原本是这样的(错误示例):

# 错误写法(缺少逗号,或使用 `=`)

capability=dac_override

或

# 错误写法(`capability` 放在了错误的位置)

profile /home/lzs/workspace/test/test.sh {

  /dev/pts/* rw,

  capability=dac_override  # ❌ 错误语法

}

修正后的写法:

bash

sudo nano /etc/apparmor.d/home.lzs.workspace.test.test.sh

修改为:

profile /home/lzs/workspace/test/test.sh {

  # 允许访问伪终端

  /dev/pts/[0-9]* rw,

 

  # 允许 CAP_DAC_OVERRIDE 能力

  capability dac_override,

 

  # 其他规则...

}

4. 重新加载策略

修复后,重新加载 AppArmor 策略:

bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

如果仍然报错,请检查:

    是否有多余的 { 或 }。
    是否在 capability 之后漏掉了逗号。

5. 调试技巧

如果仍然不确定问题,可以:

    简化策略文件,只保留最基本的规则:

profile /home/lzs/workspace/test/test.sh {

  /dev/pts/[0-9]* rw,

  capability dac_override,

    }

    逐行添加规则,直到找到导致错误的行。

常见 AppArmor 语法错误

错误类型	示例	修复方法
缺少逗号	capability dac_override	改为 capability dac_override,
错误位置	capability 放在 profile 之外	确保它在 { ... } 内部
拼写错误	capabilty(少了一个 i)	改为 capability
无效能力名	capability root,	改为 capability dac_override,
最终建议

    确保 capability 规则在 profile { ... } 内部。
    每个规则以逗号结尾(除非是最后一行)。
    避免 = 符号(AppArmor 策略使用空格分隔,如 capability dac_override)。
    使用 sudo apparmor_parser -Q 检查语法。

如果仍有问题,请提供完整的策略文件内容(cat /etc/apparmor.d/home.lzs.workspace.test.test.sh),我可以帮你进一步排查! 🚀
? 14 ? /etc/apparmor.d/home.lzs.workspace.test.test.sh in profile /etc/apparmor.d/home.lzs.workspace.test.test.sh ?AppArmor?????:syntax error, unexpected TOK_CAPABILITY, expecting TOK_END_OF_RULE

从新的日志来看,/home/lzs/workspace/test/test.sh 脚本又触发了 两个新的 AppArmor 拒绝事件:

    拒绝访问 /dev/pts/4(伪终端设备):

apparmor="DENIED" operation="open" class="file" profile="/home/lzs/workspace/test/test.sh" name="/dev/pts/4" pid=171848 comm="test.sh" requested_mask="wr" denied_mask="wr" fsuid=0 ouid=0

    操作:尝试以读写模式 (wr) 打开 /dev/pts/4(通常用于终端交互)。
    可能原因:脚本可能调用了 ssh、tmux、screen 或直接操作终端设备。

拒绝 dac_override 能力(绕过文件权限检查):

    apparmor="DENIED" operation="capable" class="cap" profile="/home/lzs/workspace/test/test.sh" pid=171951 comm="test.sh" capability=1 capname="dac_override"

        操作:脚本尝试使用 CAP_DAC_OVERRIDE 能力(通常用于 root 绕过文件读/写/执行权限检查)。
        可能原因:脚本可能调用了 sudo、chmod 或直接尝试以 root 权限访问受限文件。

问题分析
1. 为什么脚本需要访问 /dev/pts/4?

    如果脚本调用了 交互式命令(如 ssh、tmux、screen 或 gnome-terminal),这些程序会尝试打开终端设备 (/dev/pts/*)。
    如果脚本本身是 后台服务(如 systemd 启动的),它可能不需要终端访问,但某些依赖库可能误触发。

2. 为什么脚本需要 dac_override 能力?

    常见于:
        脚本尝试用 root 权限修改文件权限(如 chmod 777 /some/file)。
        脚本调用了 sudo 或直接调用了需要 root 的系统调用(如 setuid())。
        某些工具(如 docker、wireshark)默认需要 CAP_DAC_OVERRIDE。

解决方案
1. 允许访问 /dev/pts/*

在 AppArmor 策略文件中添加:

bash

sudo nano /etc/apparmor.d/home.lzs.workspace.test.test.sh

添加以下规则:

# 允许访问伪终端(谨慎使用)

/dev/pts/[0-9]* rw,

然后重新加载策略:

bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

2. 允许 dac_override 能力

在策略文件中添加:

# 允许 CAP_DAC_OVERRIDE(谨慎使用)

capability dac_override,

然后重新加载策略:

bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

⚠️ 注意:dac_override 是高权限操作,可能绕过文件系统安全检查,建议优先修复脚本逻辑,而非直接授权。
3. 检查脚本依赖

如果脚本调用了 ssh、tmux 或其他终端程序,考虑:

    改用非交互模式(如 ssh -T 禁用终端分配)。
    避免直接操作 /dev/pts/*(普通脚本通常不需要)。

如果脚本必须使用 dac_override,检查是否可以改用更安全的替代方案:

    用 chmod 修改文件属主/组,而非直接 CAP_DAC_OVERRIDE。
    用 sudo 提权特定命令(而非整个脚本)。

4. 调试脚本行为

用 strace 跟踪脚本的系统调用:

bash

sudo strace -f -e trace=file,capability /home/lzs/workspace/test/test.sh

重点关注:

    是否真的需要 /dev/pts/4(可能是某个子进程触发的)。
    是否真的需要 dac_override(可能是某个库或命令调用的)。

最佳实践建议

    避免在脚本中直接操作终端设备(如 /dev/pts/*)。
    避免滥用 CAP_DAC_OVERRIDE,改用 sudo 提权特定命令。
    优先调整脚本逻辑,而非放宽 AppArmor 策略。
    如果必须放宽策略,限制为最小必要权限(如仅允许特定路径或能力)。

常见问题
Q1:为什么 systemd 启动的脚本会触发这些限制?

    如果 systemd 服务配置了 AppArmorProfile= 或系统默认启用了 AppArmor,所有通过 systemd 启动的进程都会受策略限制。

Q2:如何彻底禁用 AppArmor 对该脚本的限制?

    将策略设为 unconfined(不推荐):

    bash

echo "/home/lzs/workspace/test/test.sh { }" | sudo tee /etc/apparmor.d/home.lzs.workspace.test.test.sh

    sudo systemctl restart apparmor

Q3:如果脚本是 Python/Bash 脚本,如何检查内部调用的命令?

    用 bash -x 或 python -m trace 调试:

    bash

bash -x /home/lzs/workspace/test/test.sh

或

bash

    python -m trace --trace /home/lzs/workspace/test/test.py

最终结论

当前问题是由于 AppArmor 策略限制了脚本访问终端设备 (/dev/pts/4) 和使用高权限能力 (dac_override)。建议:

    优先修改脚本,避免不必要的终端操作和高权限调用。
    或调整 AppArmor 策略,仅放行必要权限(如 /dev/pts/* rw 和 capability dac_override)。
    避免直接禁用 AppArmor,除非是临时调试。

如果仍有问题,请提供:

    脚本内容(cat /home/lzs/workspace/test/test.sh)。
    AppArmor 策略文件内容(sudo cat /etc/apparmor.d/home.lzs.workspace.test.test.sh)。
    sudo aa-status 的输出。

(1753096428.192:945): apparmor="DENIED" operation="open" class="file" profile="/home/lzs/workspace/test/test.sh" name="/dev/pts/4" pid=171848 comm="test.sh" requested_mask="wr" denied_mask="wr" fsuid=0 ouid=0
Jul 21 19:13:53 lzs-Precision-3591 kernel: [ 9471.823660] audit: type=1400 audit(1753096433.206:946): apparmor="DENIED" operation="capable" class="cap" profile="/home/lzs/workspace/test/test.sh" pid=171951 comm="test.sh" capability=1  capname="dac_override"

从新的日志来看,/home/lzs/workspace/test/test.sh 脚本再次因 AppArmor 策略限制 被拒绝创建 /cat.log 文件(mknod 操作)。以下是更详细的解决方案:
问题分析

    关键日志:

    audit: type=1400 audit(1753096326.610:939): apparmor="DENIED" operation="mknod" class="file" profile="/home/lzs/workspace/test/test.sh" name="/cat.log" pid=170094 comm="test.sh" requested_mask="c" denied_mask="c" fsuid=0 ouid=0

        操作:mknod(创建文件或设备节点)。
        目标文件:/cat.log(根目录下的文件,通常需要 root 权限)。
        问题:AppArmor 策略 /home/lzs/workspace/test/test.sh 禁止了该操作。
    可能原因:
        脚本尝试 > 重定向或 mkfifo 创建 /cat.log,但 AppArmor 策略未授权。
        /cat.log 位于 根目录 (/),普通用户(包括 root)可能无法直接写入(取决于系统权限)。

解决方案
1. 修改脚本,避免写入受限路径

最佳实践:不要在根目录 (/) 创建文件,改用 /tmp 或用户目录:

bash

#!/bin/bash

# 修改前(触发 AppArmor 拒绝)

echo "Test log" > /cat.log

 

# 修改后(推荐)

LOG_FILE="/tmp/cat.log"  # 或 "$HOME/cat.log"

echo "Test log" > "$LOG_FILE"

2. 调整 AppArmor 策略(允许访问 /cat.log)

如果必须写入 /cat.log,需修改 AppArmor 策略:

    找到策略文件:

    bash

sudo find /etc/apparmor.d -name "*test.sh*"  # 通常策略文件路径

如果找不到,可能是动态生成的临时策略,需检查 systemd 或 aa-autodep 的配置。

编辑策略文件(如 /etc/apparmor.d/home.lzs.workspace.test.test.sh):

bash

sudo nano /etc/apparmor.d/home.lzs.workspace.test.test.sh

添加允许规则:

# 允许写入 /cat.log(需确保路径正确)

/cat.log w,

# 或允许写入任意文件(宽松策略,不推荐)

/** w,

重新加载策略:

bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

    sudo systemctl restart test-script.service  # 如果通过 systemd 运行

3. 检查文件系统权限

即使 AppArmor 允许,/cat.log 的父目录 (/) 可能禁止写入:

bash

ls -ld /  # 检查根目录权限

    如果权限为 drwxr-xr-x(默认),只有 root 可以写入。
    解决方案:
        使用 sudo 运行脚本(不推荐长期使用)。
        改用 /tmp 或用户目录(推荐)。

4. 临时禁用 AppArmor(仅调试)

如果问题紧急,可临时将策略设为 complain 模式(允许操作但记录日志):

bash

sudo aa-complain /etc/apparmor.d/home.lzs.workspace.test.test.sh

sudo systemctl restart test-script.service

注意:生产环境不建议长期禁用安全策略。
调试步骤

    确认脚本行为:

    bash

sudo strace -f -e trace=file /home/lzs/workspace/test/test.sh  # 查看文件操作

检查是否真的尝试创建 /cat.log。

检查 AppArmor 日志:

bash

sudo dmesg | grep apparmor  # 查看最近拒绝记录

sudo aa-status              # 确认策略是否加载

测试宽松策略:
如果调整策略后仍失败,尝试完全放行目录:

    /home/lzs/workspace/test/** rw,

常见问题
Q1:为什么 systemd 执行脚本时会触发 AppArmor?

    如果 systemd 服务配置了 AppArmorProfile= 或系统默认启用了 AppArmor,所有通过 systemd 启动的进程都会受策略限制。

Q2:如何永久禁用 AppArmor 对该脚本的限制?

    删除或注释策略文件中的相关规则,然后重启 AppArmor:

    bash

sudo rm /etc/apparmor.d/home.lzs.workspace.test.test.sh

    sudo systemctl restart apparmor

Q3:如果 /cat.log 是符号链接,如何处理?

    AppArmor 默认不跟踪符号链接,需在策略中添加目标路径的权限:

    /real/path/to/cat.log w,

最终结论

根本原因是 AppArmor 策略禁止脚本创建 /cat.log。建议:

    优先修改脚本,使用可写目录(如 /tmp)。
    或调整 AppArmor 策略,显式允许对 /cat.log 的访问。
    避免直接禁用 AppArmor,除非是临时调试。

如果仍有问题,请提供以下信息以便进一步分析:

    脚本内容(cat /home/lzs/workspace/test/test.sh)。
    AppArmor 策略文件内容(sudo cat /etc/apparmor.d/home.lzs.workspace.test.test.sh)。
    sudo aa-status 的输出。

Jul 21 19:12:06 lzs-Precision-3591 kernel: [ 9365.219197] audit: type=1400 audit(1753096326.610:939): apparmor="DENIED" operation="mknod" class="file" profile="/home/lzs/workspace/test/test.sh" name="/cat.log" pid=170094 comm="test.sh" requested_mask="c" denied_mask="c" fsuid=0 ouid=0

从日志来看,systemd 在执行 /home/lzs/workspace/test/test.sh 时触发了 AppArmor 拒绝,具体原因是脚本尝试创建文件 /cat.log(mknod 操作),但 AppArmor 策略禁止了该操作。
问题分析

    错误原因:
        脚本 /home/lzs/workspace/test/test.sh 试图创建或写入 /cat.log(可能是 > 重定向或 mkfifo 操作)。
        AppArmor 策略 /home/lzs/workspace/test/test.sh 明确禁止了 mknod(文件创建)操作。
    关键日志:

    audit: type=1400 audit(1753096160.139:765): apparmor="DENIED" operation="mknod" class="file" profile="/home/lzs/workspace/test/test.sh" name="/cat.log" pid=166841 comm="test.sh" requested_mask="c" denied_mask="c" fsuid=0 ouid=0

        operation="mknod":脚本尝试创建文件。
        name="/cat.log":目标文件路径。
        requested_mask="c":请求 create 权限,但被策略拒绝。

解决方案
1. 修改 AppArmor 策略(推荐)

如果 /cat.log 是脚本必需的文件,需调整 AppArmor 策略以允许访问:

    找到策略文件:

    bash

sudo find /etc/apparmor.d -name "*test.sh*"  # 通常策略文件路径

如果找不到,可能是动态生成的临时策略,需检查 systemd 或 aa-autodep 的配置。

编辑策略文件(如 /etc/apparmor.d/home.lzs.workspace.test.test.sh):

bash

sudo nano /etc/apparmor.d/home.lzs.workspace.test.test.sh

添加允许规则(根据实际需求选择):

# 允许写入 /cat.log(需确保路径正确)

/cat.log w,

# 或允许写入任意文件(宽松策略,不推荐)

/** w,

重新加载策略:

bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

    sudo systemctl restart test-script.service

2. 修改脚本路径(避免受限目录)

如果 /cat.log 是脚本生成的日志文件,建议改用可写目录(如 /tmp 或用户目录):

bash

#!/bin/bash

# 将硬编码路径改为可写目录

LOG_FILE="/tmp/cat.log"  # 或 "$HOME/cat.log"

echo "Test log" > "$LOG_FILE"

3. 临时禁用 AppArmor(仅调试)

如果问题紧急,可临时将策略设为 complain 模式(允许操作但记录日志):

bash

sudo aa-complain /etc/apparmor.d/home.lzs.workspace.test.test.sh

sudo systemctl restart test-script.service

注意:生产环境不建议长期禁用安全策略。
4. 检查脚本是否真的需要 mknod

如果脚本中包含 mkfifo 或类似操作(创建命名管道),需明确在 AppArmor 策略中允许:

# 允许创建 FIFO 管道

 /cat.log mknod,

调试步骤

    确认脚本行为:

    bash

sudo strace -f -e trace=file /home/lzs/workspace/test/test.sh  # 查看文件操作

检查是否真的尝试创建 /cat.log。

检查 AppArmor 日志:

bash

sudo dmesg | grep apparmor  # 查看最近拒绝记录

sudo aa-status              # 确认策略是否加载

测试宽松策略:
如果调整策略后仍失败,尝试完全放行目录:

    /home/lzs/workspace/test/** rw,

常见问题
Q1:为什么 systemd 执行脚本时会触发 AppArmor?

    如果 systemd 服务配置了 AppArmorProfile= 或系统默认启用了 AppArmor,所有通过 systemd 启动的进程都会受策略限制。

Q2:如何永久禁用 AppArmor 对该脚本的限制?

    删除或注释策略文件中的相关规则,然后重启 AppArmor:

    bash

sudo rm /etc/apparmor.d/home.lzs.workspace.test.test.sh

    sudo systemctl restart apparmor

Q3:如果 /cat.log 是符号链接,如何处理?

    AppArmor 默认不跟踪符号链接,需在策略中添加目标路径的权限:

    /real/path/to/cat.log w,

最终结论

根本原因是 AppArmor 策略禁止脚本创建 /cat.log。建议:

    优先修改脚本,使用可写目录(如 /tmp)。
    或调整 AppArmor 策略,显式允许对 /cat.log 的访问。
    避免直接禁用 AppArmor,除非是临时调试。

如果仍有问题,请提供 cat /home/lzs/workspace/test/test.sh 和 sudo aa-status 的输出,以便进一步分析!
Jul 21 19:09:20 lzs-Precision-3591 kernel: [ 9198.743035] audit: type=1400 audit(1753096160.139:765): apparmor="DENIED" operation="mknod" class="file" profile="/home/lzs/workspace/test/test.sh" name="/cat.log" pid=166841 comm="test.sh" requested_mask="c" denied_mask="c" fsuid=0 ouid=0

从日志来看,systemd 启动服务时遇到了 Exec format error(执行格式错误),这通常意味着:

    脚本没有正确的 Shebang(如 #!/bin/bash),导致系统不知道如何解释该文件。
    脚本的二进制格式与系统不兼容(如 Windows 换行符 \r\n 或错误的文件权限)。
    脚本路径或文件本身损坏(如非可执行文件被误命名为 .sh)。

解决方案
1. 检查脚本的 Shebang 和内容

确保脚本第一行是有效的 Shebang(如 #!/bin/bash 或 #!/bin/sh),例如:

bash

#!/bin/bash

echo "Hello, this is a test script."

    修复方法:

    bash

sudo nano /home/lzs/workspace/test/test.sh  # 编辑脚本,确保第一行是 Shebang

    chmod +x /home/lzs/workspace/test/test.sh   # 重新添加执行权限

2. 检查文件格式(是否包含 Windows 换行符)

如果脚本在 Windows 上编辑过,可能包含 \r\n 换行符,导致 Linux 无法解析。

    检查方法:

    bash

cat -v /home/lzs/workspace/test/test.sh  # 查看是否有 `^M`(表示 Windows 换行符)

file /home/lzs/workspace/test/test.sh    # 检查文件类型(应显示 "Bourne-Again shell script")

修复方法:

bash

sudo apt install dos2unix  # 安装转换工具

    dos2unix /home/lzs/workspace/test/test.sh  # 转换换行符

3. 检查脚本是否为二进制文件或损坏

如果脚本不是文本文件(如误上传了二进制文件),systemd 会报 Exec format error。

    检查方法:

    bash

    head -n 5 /home/lzs/workspace/test/test.sh  # 查看前几行是否是可读的 shell 命令

    修复方法:
    如果文件损坏,重新创建脚本或从备份恢复。

4. 检查 systemd 服务配置

确保 test-script.service 中的 ExecStart 路径正确,且没有多余参数:

ini

[Service]

ExecStart=/home/lzs/workspace/test/test.sh  # 确保路径正确,无引号或特殊字符

    错误示例(会导致 Exec format error):

    ini

ExecStart="/home/lzs/workspace/test/test.sh arg1"  # systemd 会尝试将整个字符串当作二进制路径

正确写法(如需传递参数):

ini

    ExecStart=/bin/bash /home/lzs/workspace/test/test.sh arg1

5. 检查 AppArmor 策略是否阻止执行

虽然 Exec format error 通常与脚本本身有关,但 AppArmor 策略如果限制了 exec 操作,也可能导致类似错误。

    检查策略:

    bash

sudo aa-status | grep test.sh  # 确认策略是否允许执行

临时放宽策略:

bash

sudo aa-complain /etc/apparmor.d/home.lzs.workspace.test.test.sh

    sudo systemctl restart test-script.service

调试步骤总结

    验证脚本内容:

    bash

head -n 3 /home/lzs/workspace/test/test.sh  # 检查 Shebang 和基本语法

bash -n /home/lzs/workspace/test/test.sh    # 检查语法错误(不执行)

手动运行脚本:

bash

sudo /home/lzs/workspace/test/test.sh       # 测试是否能直接运行

检查 systemd 日志:

bash

journalctl -u test-script.service -b --no-pager  # 查看最近启动日志

修复后重启服务:

bash

sudo systemctl daemon-reload

    sudo systemctl restart test-script.service

常见问题补充
Q1:为什么 Exec format error 不提示具体原因?

    systemd 的 EXEC 阶段错误通常直接返回内核级错误(如 ENOEXEC),不会详细说明是 Shebang 缺失、文件损坏还是权限问题。需手动排查。

Q2:如果脚本依赖环境变量怎么办?

    在 systemd 服务文件中显式设置 Environment:

    ini

[Service]

Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

    Environment="MY_VAR=value"

Q3:如何让 systemd 输出脚本的错误信息?

    在服务文件中添加调试选项:

    ini

[Service]

ExecStart=/bin/bash -x /home/lzs/workspace/test/test.sh  # -x 打印执行过程

StandardOutput=journal

    StandardError=journal

    然后通过 journalctl -u test-script.service 查看详细输出。

最终结论

Exec format error 大概率是以下原因之一:

    脚本缺少 Shebang(如 #!/bin/bash)。
    脚本包含 Windows 换行符(\r\n)。
    systemd 服务配置错误(如 ExecStart 格式不正确)。

按上述步骤检查后,服务应能正常启动。如果仍有问题,请提供 head -n 10 /home/lzs/workspace/test/test.sh 和 journalctl -u test-script.service -n 50 --no-pager 的输出以便进一步分析!
Jul 21 19:02:22 lzs-Precision-3591 systemd[158780]: test-script.service: Failed to execute /home/lzs/workspace/test/test.sh: Exec format error
Jul 21 19:02:22 lzs-Precision-3591 systemd[158780]: test-script.service: Failed at step EXEC spawning /home/lzs/workspace/test/test.sh: Exec format error

从日志来看,systemd 服务 test-script.service 启动失败,原因是 无法确定用户凭证(Failed to determine user credentials: No such process),并且在尝试以指定用户身份运行脚本时失败(Failed at step USER spawning)。这通常与 systemd 服务配置中的用户设置问题 或 脚本路径/权限问题 有关。
问题原因分析

    User= 指定的用户不存在或无权限
        服务文件中可能指定了 User=lzs 或其他用户,但该用户不存在,或用户的主目录/权限有问题。
        如果未显式指定 User=,systemd 默认以 root 运行,但可能因环境问题失败。
    脚本路径或权限问题
        脚本 /home/lzs/workspace/test/test.sh 可能不存在、无执行权限,或路径包含特殊字符(如空格、中文)。
        如果脚本依赖其他文件或环境变量,可能因 systemd 的默认环境限制而失败。
    AppArmor 策略冲突
        虽然策略已加载,但可能限制了 systemd 的某些操作(如访问 /proc 或 /sys),导致进程无法启动。

解决方案
1. 检查并修复服务文件配置

编辑 /etc/systemd/system/test-script.service,确保以下关键配置正确:

ini

[Unit]

Description=Test Script with AppArmor

After=network.target

 

[Service]

Type=simple

ExecStart=/home/lzs/workspace/test/test.sh  # 确保路径绝对且无特殊字符

User=root  # 或指定有效用户(如 lzs,需确认用户存在)

WorkingDirectory=/home/lzs/workspace/test  # 可选:设置工作目录

AppArmorProfile=/etc/apparmor.d/home.lzs.workspace.test.test.sh  # 确保策略路径正确

Restart=on-failure

Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"  # 显式设置 PATH

 

[Install]

WantedBy=multi-user.target

关键修改点

    User=:
        如果脚本需要 root 权限,直接使用 User=root。
        如果需普通用户,确保用户存在(如 User=lzs),并检查 /home/lzs 权限:

        bash

    sudo -u lzs ls /home/lzs/workspace/test/test.sh  # 测试用户能否访问脚本

ExecStart=:

    使用绝对路径,避免相对路径或环境变量(如 ~/)。
    如果路径包含空格或特殊字符,用引号包裹:

    ini

        ExecStart="/home/lzs/My Scripts/test.sh"

    Environment="PATH=...":
        systemd 默认环境较简洁,显式设置 PATH 避免脚本找不到命令。

2. 检查脚本权限和内容

确保脚本有执行权限且内容无错误:

bash

chmod +x /home/lzs/workspace/test/test.sh  # 添加执行权限

chown root:root /home/lzs/workspace/test/test.sh  # 如果以 root 运行,确保所有者正确

测试脚本能否手动运行

bash

sudo /home/lzs/workspace/test/test.sh  # 以 root 运行(与服务配置一致)

如果手动运行失败,需先修复脚本问题(如依赖缺失、语法错误)。
3. 重新加载 systemd 并启动服务

bash

sudo systemctl daemon-reload          # 重新加载服务文件

sudo systemctl reset-failed test-script.service  # 清除之前的失败状态

sudo systemctl start test-script.service

sudo systemctl status test-script.service --no-pager  # 查看详细状态

检查日志

bash

journalctl -u test-script.service -f  # 实时查看服务日志

sudo dmesg | grep apparmor            # 检查 AppArmor 是否拒绝操作

4. 调试技巧

如果仍失败,可临时修改服务文件以获取更多信息:

ini

[Service]

...

StandardOutput=journal  # 输出到 journalctl

StandardError=journal

然后通过 journalctl -u test-script.service 查看完整错误。
常见问题补充
Q1:为什么 User= 导致失败?

    如果用户不存在或用户的主目录不可访问(如 /home/lzs 权限为 700 且脚本依赖其他文件),systemd 会无法切换用户。
    解决:检查用户是否存在:

    bash

    id lzs  # 如果用户不存在,需创建用户或改用 root

Q2:AppArmor 策略是否影响服务启动?

    如果策略禁止了 systemd 的某些操作(如 fork() 或访问 /proc),可能导致进程无法创建。
    解决:临时放宽策略测试:

    bash

sudo aa-complain /etc/apparmor.d/home.lzs.workspace.test.test.sh  # 切换为 complain 模式

    sudo systemctl restart test-script.service

    如果服务启动成功,说明原策略需调整(如添加 ptrace read, 或 /proc/** rw,)。

总结

    检查服务文件:确保 User=、ExecStart=、PATH 配置正确。
    验证脚本权限:确保脚本可执行且依赖完整。
    查看日志:通过 journalctl 和 dmesg 定位具体错误。
    调试策略:如怀疑 AppArmor 限制,临时切换为 complain 模式测试。

按上述步骤操作后,服务应能正常启动。如果仍有问题,请提供 journalctl -u test-script.service 的完整日志以便进一步分析!
Jul 21 18:57:50 lzs-Precision-3591 systemd[1]: Started Test Script with AppArmor.
Jul 21 18:57:50 lzs-Precision-3591 systemd[154009]: test-script.service: Failed to determine user credentials: No such process
Jul 21 18:57:50 lzs-Precision-3591 systemd[154009]: test-script.service: Failed at step USER spawning /home/lzs/workspace/test/test.sh: No such process

从你的 sudo apparmor_status | grep test.sh 输出可以看出,AppArmor 策略 /home/lzs/workspace/test/test.sh 已经加载到内核并处于 enforce(强制)模式。这意味着:

    策略已生效,脚本运行时会自动受该策略约束。
    无需通过 aa-exec,直接运行脚本即可应用策略。

接下来如何验证策略是否真正生效?
1. 直接运行脚本并检查日志

bash

sudo /home/lzs/workspace/test/test.sh

然后查看 AppArmor 日志,确认是否有 ALLOWED 或 DENIED 记录:

bash

sudo dmesg | grep apparmor

或使用 aa-logprof(需安装 apparmor-utils):

bash

sudo aa-logprof

这会分析最近的 AppArmor 日志,并提示是否有策略违规。
2. 测试策略是否限制脚本行为

如果策略限制了某些操作(如禁止访问 /etc/shadow),可以在脚本中添加测试代码:

bash

#!/bin/bash

echo "Testing AppArmor policy..."

cat /etc/shadow  # 如果策略禁止,会触发 DENIED 日志

然后运行脚本并检查日志:

bash

sudo /home/lzs/workspace/test/test.sh

sudo dmesg | grep apparmor

如果策略生效,你会看到类似:

[ 1234.567890] audit: type=1400 audit(1234567890.123:123): apparmor="DENIED" operation="open" profile="/home/lzs/workspace/test/test.sh" name="/etc/shadow" pid=1234 comm="cat" requested_mask="r" denied_mask="r" fsuid=0 ouid=0

3. 如果策略未生效?
可能原因

    策略路径不匹配
        确保策略文件中的路径 /home/lzs/workspace/test/test.sh 与实际脚本路径完全一致(包括大小写和符号链接)。
        检查策略文件内容:

        bash

    cat /etc/apparmor.d/home.lzs.workspace.test.test.sh

策略未正确加载

    重新加载策略:

    bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

确认策略状态:

bash

    sudo apparmor_status | grep test.sh

脚本运行方式与策略不匹配

    如果策略限定 root 用户执行,但脚本以普通用户运行,策略不会生效。确保:

    bash

        sudo /home/lzs/workspace/test/test.sh

总结

    策略已加载(apparmor_status 显示正常),直接运行脚本即可应用策略。
    验证策略是否生效:
        运行脚本后检查 dmesg | grep apparmor。
        测试策略限制的操作(如访问禁止的文件)。
    如果策略未生效:
        检查策略路径是否匹配。
        重新加载策略。
        确保脚本以正确的用户(如 root)运行。

现在你可以直接运行脚本,AppArmor 会自动应用策略限制!
sudo apparmor_status | grep test.sh
   /home/lzs/workspace/test/test.sh

如果想 不通过 aa-exec 但仍让 /home/lzs/workspace/test/test.sh 按定义好的 AppArmor 策略执行,可以通过以下方法实现。核心思路是 让脚本在启动时自动加载对应的 AppArmor 策略,或 利用系统服务或启动脚本强制应用策略。
方法 1:直接运行脚本时手动加载策略(推荐)
步骤

    确保策略已加载到 AppArmor
    使用 apparmor_parser 将策略文件加载到内核(无需通过 aa-exec):

    bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

    -r 表示重新加载(如果策略已存在,先卸载再加载)。
    确认策略已激活:

    bash

    sudo apparmor_status | grep test.sh

直接运行脚本
由于策略已加载到内核,脚本运行时会自动继承该策略的约束:

bash

sudo /home/lzs/workspace/test/test.sh

    关键点:脚本必须以 与策略定义匹配的方式运行(如策略是针对 root 用户执行的,则需用 sudo)。

验证策略是否生效
检查日志确认脚本是否被策略限制:

bash

    sudo dmesg | grep apparmor

        如果策略生效,日志会显示 apparmor="ALLOWED" 或 apparmor="DENIED"(根据操作是否被允许)。

方法 2:通过 systemd 服务强制应用策略

如果脚本是作为服务运行的(如后台守护进程),可以在 systemd 单元文件中指定 AppArmorProfile,让系统自动加载策略。
步骤

    创建或修改 systemd 服务文件
    编辑 /etc/systemd/system/test-script.service:

    ini

[Unit]

Description=Test Script with AppArmor

After=network.target

 

[Service]

Type=simple

ExecStart=/home/lzs/workspace/test/test.sh

User=root  # 根据策略要求调整用户

AppArmorProfile=/etc/apparmor.d/home.lzs.workspace.test.test.sh  # 指定策略路径

Restart=on-failure

 

[Install]

WantedBy=multi-user.target

重新加载 systemd 并启动服务

bash

sudo systemctl daemon-reload

sudo systemctl start test-script.service

sudo systemctl status test-script.service  # 检查是否运行正常

验证策略是否生效
查看服务日志和 AppArmor 日志:

bash

journalctl -u test-script.service -f  # 实时查看服务日志

    sudo dmesg | grep apparmor             # 检查 AppArmor 拒绝事件

方法 3:通过 cron 定时任务强制应用策略

如果脚本是通过 cron 运行的,可以在 crontab 中指定 AppArmor 策略(需结合 aa-exec 或手动加载策略)。
步骤

    手动加载策略(与方法 1 相同)

    bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

编辑 crontab
直接运行脚本(策略已加载到内核):

bash

sudo crontab -e

添加任务(例如每分钟运行一次):

plaintext

* * * * * /home/lzs/workspace/test/test.sh

验证
检查 cron 日志和 AppArmor 日志:

bash

sudo tail -f /var/log/syslog | grep cron

    sudo dmesg | grep apparmor

方法 4:通过 wrapper 脚本强制加载策略

创建一个包装脚本(wrapper),在运行目标脚本前先确保策略已加载。
步骤

    创建包装脚本 /usr/local/bin/run-test-with-apparmor.sh

    bash

#!/bin/bash

# 加载策略(如果未加载)

if ! sudo apparmor_status | grep -q "home.lzs.workspace.test.test.sh"; then

    sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

fi

# 运行目标脚本

sudo /home/lzs/workspace/test/test.sh

赋予执行权限

bash

sudo chmod +x /usr/local/bin/run-test-with-apparmor.sh

直接运行包装脚本

bash

    sudo /usr/local/bin/run-test-with-apparmor.sh

常见问题与解决
Q1:直接运行脚本后,AppArmor 日志没有记录?

    可能原因:
        策略未正确加载(检查 sudo apparmor_status)。
        脚本未触发策略限制的操作(如仅读取允许的文件)。
    解决:
        重新加载策略:

        bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

在脚本中添加测试操作(如尝试读取策略禁止的文件):

bash

        cat /etc/shadow  # 如果策略禁止,会触发 DENIED 日志

Q2:策略生效但脚本无法正常运行?

    可能原因:
        策略过于严格,阻止了脚本必需的操作(如访问 /tmp 或库文件)。
    解决:
        编辑策略文件,添加缺失的权限(如 /tmp/** rw,)。
        重新加载策略:

        bash

        sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

总结

方法	适用场景	是否需要 aa-exec	关键步骤
直接运行(手动加载策略)	临时测试或简单脚本	❌ 否	1. sudo apparmor_parser -r /path/to/profile
2. 直接运行脚本
systemd 服务	后台守护进程	❌ 否	1. 在服务文件中指定 AppArmorProfile
2. sudo systemctl start service
cron 定时任务	定时执行的脚本	❌ 否	1. 手动加载策略
2. 在 crontab 中直接运行脚本
包装脚本	需要额外逻辑(如自动加载策略)	❌ 否	1. 创建包装脚本
2. 在包装脚本中加载策略并运行目标脚本

推荐方案:

    临时测试 → 方法 1(直接运行 + 手动加载策略)。
    生产环境 → 方法 2(systemd 服务)或方法 4(包装脚本)。
    定时任务 → 方法 3(cron + 手动加载策略)。

我想不通过aa-exec但也让我的test.sh也按定义好的策略执行应该怎么办

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh 的作用是 以指定的 AppArmor 配置文件(/home/lzs/workspace/test/test.sh)加载安全策略,并执行该脚本。其中,aa-exec 是 AppArmor 提供的工具,用于在特定安全上下文中运行程序。以下是详细解析:
1. 命令组成与作用

    sudo
    以超级用户权限执行后续命令,确保 AppArmor 策略加载和脚本执行具有足够权限。

    aa-exec
    AppArmor 的核心工具,用于在指定的安全策略(profile)下运行程序。其作用包括:
        加载策略:根据 -p 参数指定的路径,加载对应的 AppArmor 配置文件。
        限制进程行为:确保进程仅能访问策略中明确定义的资源(如文件、网络、信号等)。
        隔离风险:若脚本尝试执行策略禁止的操作(如读取未授权文件),AppArmor 会阻止并记录日志。

    -p /home/lzs/workspace/test/test.sh
    指定要加载的 AppArmor 策略文件路径。该文件定义了脚本 /home/lzs/workspace/test/test.sh 的权限规则(如允许读取哪些文件、发送哪些信号等)。

    -- /home/lzs/workspace/test/test.sh
    -- 是分隔符,表示后续参数为要执行的程序及其参数。此处直接运行脚本本身。

2. 典型应用场景

    安全加固脚本执行
    若脚本需要访问敏感资源(如系统文件、数据库),但直接运行可能因权限过高导致风险,可通过 AppArmor 策略限制其行为。例如:

    plaintext

# 示例策略片段(/home/lzs/workspace/test/test.sh)

/home/lzs/workspace/test/test.sh r,  # 允许读取脚本自身

/bin/sh ix,                          # 允许执行 shell

/var/log/app.log w,                  # 允许写入日志文件

signal (receive) peer=unconfined,     # 允许接收信号

deny /etc/shadow r,                  # 禁止读取密码文件

通过 aa-exec 加载此策略后,脚本仅能执行允许的操作,其他行为(如读取 /etc/shadow)会被阻止。

调试 AppArmor 策略
在开发策略时,可通过 aa-exec 临时加载策略并测试脚本行为,观察日志确认是否符合预期。例如:

bash

    sudo aa-exec -p /etc/apparmor.d/usr.bin.cat -- cat /home/lzs/workspace/output/test.txt

    若策略未允许读取该文件,日志会记录 apparmor="DENIED" operation="open"。

3. 对比直接运行脚本的差异

执行方式	权限控制	安全上下文	适用场景
直接运行 ./test.sh	依赖系统默认权限(如用户、组)	无额外限制	普通脚本,无需安全隔离
sudo aa-exec -p ... -- ...	由 AppArmor 策略显式定义	进程受策略约束,行为可审计	高风险脚本,需精细权限控制
4. 常见问题与解决

    策略文件不存在或路径错误
    若 -p 指定的路径无效,aa-exec 会报错:

    bash

Error: Unable to load profile /home/lzs/workspace/test/test.sh

解决:检查路径是否正确,或使用 sudo apparmor_parser -r /path/to/profile 手动加载策略。

策略未允许操作
若脚本尝试执行策略禁止的操作(如读取 /etc/shadow),日志会记录拒绝事件:

bash

sudo dmesg | grep apparmor

解决:编辑策略文件,添加所需权限(如 /etc/shadow r,),然后重新加载。

aa-exec 未安装
若系统未安装 AppArmor 工具包,会提示命令未找到。
解决:安装 AppArmor:

bash

sudo apt-get install apparmor apparmor-utils  # Debian/Ubuntu

    sudo yum install apparmor apparmor-utils      # RHEL/CentOS

总结

sudo aa-exec -p /path/to/profile -- /path/to/script 的作用是 在 AppArmor 策略的严格约束下执行脚本,确保进程行为符合安全规范。它适用于需要隔离风险、精细控制权限的场景,是 Linux 系统安全加固的重要工具之一。
sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh 的作用是啥,aa-exec的作用?

这个错误表明 AppArmor 拒绝了 cat 进程(由 /home/lzs/workspace/test/test.sh 触发)读取 /home/lzs/workspace/output/test.txt 文件。以下是详细分析和解决方案:
错误原因

    文件访问被拒绝
        您的脚本 /home/lzs/workspace/test/test.sh 或其调用的命令(如 cat)尝试读取 /home/lzs/workspace/output/test.txt,但 AppArmor 配置未明确允许。
        文件所有者是 ouid=1000(普通用户),而进程以 fsuid=0(root)运行,可能触发权限检查。
    可能的原因
        脚本中直接或间接调用了 cat 读取该文件(例如 cat /home/lzs/workspace/output/test.txt)。
        AppArmor 配置未包含对 /home/lzs/workspace/output/ 目录的读取权限。

解决方案
1. 修改 AppArmor 配置文件

    编辑 /etc/apparmor.d/home.lzs.workspace.test.test.sh,添加对目标文件的读取权限:

    plaintext

profile /home/lzs/workspace/test/test.sh {

  # 允许读取脚本本身

  /home/lzs/workspace/test/test.sh r,

 

  # 允许执行 /bin/sh 和相关命令

  /bin/sh ix,

  /usr/bin/* ix,

 

  # 允许读取目标文件(关键修改)

  /home/lzs/workspace/output/test.txt r,

 

  # 如果需要访问整个目录

  /home/lzs/workspace/output/** r,

 

  # 其他必要规则(如临时目录、库路径等)

  /lib/** r,

  /usr/lib/** r,

  /tmp/** rw,

  /var/tmp/** rw,

}

重新加载配置:

bash

    sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

2. 检查脚本是否真的需要读取该文件

    确认脚本中是否有直接或间接调用 cat 或其他工具读取该文件的代码:

    bash

    grep -n "cat /home/lzs/workspace/output/test.txt" /home/lzs/workspace/test/test.sh

        如果不需要读取该文件,移除相关代码。
        如果需要,确保 AppArmor 配置中明确允许访问。

3. 检查文件权限

    确认文件 /home/lzs/workspace/output/test.txt 的权限是否允许 root 用户读取:

    bash

ls -l /home/lzs/workspace/output/test.txt

    如果权限不足(如仅用户 1000 可读),可以调整权限:

    bash

sudo chmod 644 /home/lzs/workspace/output/test.txt  # 允许所有用户读取

或调整所有者:

bash

        sudo chown root:root /home/lzs/workspace/output/test.txt

4. 临时放宽 AppArmor 限制(测试用)

    如果问题紧急,可以临时切换 AppArmor 到 complain 模式(仅记录不阻止):

    bash

sudo aa-complain /home/lzs/workspace/test/test.sh

    测试脚本是否能正常运行:

    bash

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

确认无报错后,再调整配置文件并切换回 enforce 模式:

bash

        sudo aa-enforce /home/lzs/workspace/test/test.sh

5. 监控 AppArmor 日志

    实时查看拒绝事件,确认是否还有其他被阻止的文件或操作:

    bash

sudo tail -f /var/log/audit/audit.log | grep apparmor

    或使用 dmesg:

    bash

        dmesg | grep apparmor

验证步骤

    更新 AppArmor 配置后,重新加载并测试:

    bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

检查是否仍有 DENIED 日志:

bash

    sudo dmesg | grep apparmor

    如果问题解决,确认脚本输出是否符合预期。

总结

    根本原因:AppArmor 配置未允许访问 /home/lzs/workspace/output/test.txt,导致 cat 命令被阻止。
    推荐操作:
        在 AppArmor 配置中添加 /home/lzs/workspace/output/test.txt r, 或 /home/lzs/workspace/output/** r,。
        检查文件权限和所有者,确保 root 用户可以读取。
        如果不需要读取该文件,移除脚本中的相关代码。

如果问题仍未解决,请提供以下信息:

    完整的 AppArmor 配置文件内容。
    脚本中涉及文件读取的片段。
    ls -l /home/lzs/workspace/output/test.txt 的输出。

Jul 21 18:42:35 lzs-Precision-3591 kernel: [ 7593.887966] audit: type=1400 audit(1753094555.277:439): apparmor="DENIED" operation="open" class="file" profile="/home/lzs/workspace/test/test.sh" name="/home/lzs/workspace/output/test.txt" pid=138066 comm="cat" requested_mask="r" denied_mask="r" fsuid=0 ouid=1000

这个错误表明 AppArmor 拒绝了 sh 进程(由 /home/lzs/workspace/test/test.sh 触发)接收 SIGINT(中断信号,通常是 Ctrl+C 触发的信号)。以下是详细分析和解决方案:
错误原因

    信号接收被拒绝
        您的脚本 /home/lzs/workspace/test/test.sh 或其子进程(如 sh)尝试接收 SIGINT 信号(例如用户按下 Ctrl+C),但 AppArmor 配置未明确允许。
        通常,SIGINT 是进程间通信(IPC)的一部分,AppArmor 默认可能限制某些信号的传递。
    可能的原因
        脚本中调用了某些命令(如 trap 或直接处理信号),但 AppArmor 配置未包含信号接收规则。
        可能是脚本尝试向自身或其他进程发送/接收信号,但 AppArmor 策略阻止了这一行为。

解决方案
1. 修改 AppArmor 配置文件

    编辑 /etc/apparmor.d/home.lzs.workspace.test.test.sh,添加对信号接收的权限:

    plaintext

profile /home/lzs/workspace/test/test.sh {

  # 允许读取脚本本身

  /home/lzs/workspace/test/test.sh r,

 

  # 允许执行 /bin/sh 和相关命令

  /bin/sh ix,

  /usr/bin/* ix,

 

  # 允许接收信号(关键修改)

  signal (receive) peer=/home/lzs/workspace/test/test.sh,

  signal (receive) peer=unconfined,  # 如果需要与其他未受限制的进程交互

 

  # 其他必要规则(如临时目录、库路径等)

  /lib/** r,

  /usr/lib/** r,

  /tmp/** rw,

  /var/tmp/** rw,

}

重新加载配置:

bash

    sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

2. 检查脚本是否真的需要处理信号

    如果脚本中使用了 trap 或其他信号处理逻辑(例如捕获 SIGINT),确保 AppArmor 允许相关操作:

    bash

    grep -n "trap" /home/lzs/workspace/test/test.sh

        如果不需要信号处理,可以移除相关代码。
        如果需要,确保 AppArmor 配置中明确允许信号接收。

3. 临时放宽 AppArmor 限制(测试用)

    如果问题紧急,可以临时切换 AppArmor 到 complain 模式(仅记录不阻止):

    bash

sudo aa-complain /home/lzs/workspace/test/test.sh

    测试脚本是否能正常运行(包括 Ctrl+C 中断):

    bash

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

确认无报错后,再调整配置文件并切换回 enforce 模式:

bash

        sudo aa-enforce /home/lzs/workspace/test/test.sh

4. 检查进程间通信(IPC)需求

    如果脚本涉及多进程通信(如 & 后台进程、wait 等),可能需要更宽松的信号规则:

    plaintext

signal (receive) peer=unconfined,  # 允许与未受限制的进程交互

    signal (send) peer=unconfined,     # 允许发送信号

5. 监控 AppArmor 日志

    实时查看拒绝事件,确认是否还有其他被阻止的信号或操作:

    bash

sudo tail -f /var/log/audit/audit.log | grep apparmor

    或使用 dmesg:

    bash

        dmesg | grep apparmor

验证步骤

    更新 AppArmor 配置后,重新加载并测试:

    bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

在另一个终端尝试发送 SIGINT(Ctrl+C),检查是否被正确处理。
检查是否仍有 DENIED 日志:

bash

    sudo dmesg | grep apparmor

    如果问题解决,确认脚本行为是否符合预期。

总结

    根本原因:AppArmor 配置未允许 /home/lzs/workspace/test/test.sh 接收 SIGINT 信号,导致中断操作被阻止。
    推荐操作:
        在 AppArmor 配置中添加 signal (receive) peer=/home/lzs/workspace/test/test.sh,。
        检查脚本中是否需要信号处理逻辑,移除不必要的代码。
        如果涉及多进程通信,放宽信号规则(如允许与 unconfined 进程交互)。

如果问题仍未解决,请提供以下信息:

    完整的 AppArmor 配置文件内容。
    脚本中涉及信号处理或多进程通信的片段。
    audit.log 或 dmesg 中的完整错误上下文。

Jul 21 18:41:19 lzs-Precision-3591 kernel: [ 7518.120257] audit: type=1400 audit(1753094479.509:427): apparmor="DENIED" operation="signal" class="signal" profile="/home/lzs/workspace/test/test.sh" pid=136798 comm="sh" requested_mask="receive" denied_mask="receive" signal=int peer="/home/lzs/workspace/test/test.sh"

这个错误表明 AppArmor 拒绝了 cat 进程(由 /home/lzs/workspace/test/test.sh 触发)读取 /usr/share/locale-langpack/zh_CN/LC_MESSAGES/libc.mo 文件,这是 GNU C 库(glibc)的中文语言翻译文件(用于错误消息本地化)。以下是详细分析和解决方案:
错误原因

    文件访问被拒绝
        您的脚本 /home/lzs/workspace/test/test.sh 或其调用的命令(如 cat)尝试读取 /usr/share/locale-langpack/zh_CN/LC_MESSAGES/libc.mo,但 AppArmor 配置未明确允许。
        该文件是 glibc 的多语言支持文件,通常由系统工具(如 gettext 或 cat)在输出本地化错误消息时访问。
    可能的原因
        脚本中调用了某些命令(如 cat、grep 或其他输出错误消息的工具),这些工具尝试加载本地化翻译文件。
        AppArmor 配置未包含对 /usr/share/locale-langpack/ 目录的访问规则。

解决方案
1. 修改 AppArmor 配置文件

    编辑 /etc/apparmor.d/home.lzs.workspace.test.test.sh,添加对 /usr/share/locale-langpack/ 目录的读取权限:

    plaintext

profile /home/lzs/workspace/test/test.sh {

  # 允许读取脚本本身

  /home/lzs/workspace/test/test.sh r,

 

  # 允许执行 /bin/sh 和相关命令

  /bin/sh ix,

  /usr/bin/* ix,

 

  # 允许读取语言翻译文件(关键修改)

  /usr/share/locale-langpack/** r,

 

  # 其他必要规则(如临时目录、库路径等)

  /lib/** r,

  /usr/lib/** r,

  /tmp/** rw,

  /var/tmp/** rw,

}

重新加载配置:

bash

    sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

2. 检查脚本是否真的需要访问语言文件

    如果脚本不需要本地化支持(如输出中文错误消息),可能是某个命令(如 cat)间接触发了访问。建议:
        使用 strace 跟踪脚本执行,确认哪个命令触发了文件访问:

        bash

        sudo strace -f -e openat /home/lzs/workspace/test/test.sh 2>&1 | grep locale-langpack

        如果发现无关命令触发了访问,考虑移除或替换该命令(例如,避免使用 cat 读取可能触发本地化的文件)。

3. 临时放宽 AppArmor 限制(测试用)

    如果问题紧急,可以临时切换 AppArmor 到 complain 模式(仅记录不阻止):

    bash

sudo aa-complain /home/lzs/workspace/test/test.sh

    测试脚本是否能正常运行:

    bash

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

确认无报错后,再调整配置文件并切换回 enforce 模式:

bash

        sudo aa-enforce /home/lzs/workspace/test/test.sh

4. 检查系统语言环境配置

    确认当前语言环境是否设置为中文(zh_CN):

    bash

locale

    如果不需要中文本地化,可以临时切换为英文环境:

    bash

export LANG=en_US.UTF-8

        export LC_ALL=en_US.UTF-8

        但更推荐在 AppArmor 配置中显式允许语言文件访问,因为其他工具可能仍会尝试加载翻译。

5. 监控 AppArmor 日志

    实时查看拒绝事件,确认是否还有其他被阻止的文件或操作:

    bash

sudo tail -f /var/log/audit/audit.log | grep apparmor

    或使用 dmesg:

    bash

        dmesg | grep apparmor

验证步骤

    更新 AppArmor 配置后,重新加载并测试:

    bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

检查是否仍有 DENIED 日志:

bash

    sudo dmesg | grep apparmor

    如果问题解决,确认脚本输出是否符合预期。

总结

    根本原因:AppArmor 配置未允许访问 /usr/share/locale-langpack/zh_CN/LC_MESSAGES/libc.mo,导致本地化相关操作被阻止。
    推荐操作:
        在 AppArmor 配置中添加 /usr/share/locale-langpack/** r,。
        使用 strace 确认触发访问的具体命令。
        如果不需要本地化支持,可以忽略此错误(但更推荐显式允许访问)。

如果问题仍未解决,请提供以下信息:

    完整的 AppArmor 配置文件内容。
    脚本中涉及输出或文件读取的片段。
    strace 或 audit.log 中的完整错误上下文。

Jul 21 18:39:39 lzs-Precision-3591 kernel: [ 7418.323933] audit: type=1400 audit(1753094379.713:399): apparmor="DENIED" operation="open" class="file" profile="/home/lzs/workspace/test/test.sh" name="/usr/share/locale-langpack/zh_CN/LC_MESSAGES/libc.mo" pid=135098 comm="cat" requested_mask="r" denied_mask="r" fsuid=0 ouid=0

这个错误表明 AppArmor 拒绝了 sleep 进程(由 /home/lzs/workspace/test/test.sh 触发)读取 /etc/ld.so.cache 文件,这是 Linux 动态链接库的缓存文件。以下是详细分析和解决方案:
错误原因

    文件访问被拒绝
        您的脚本 /home/lzs/workspace/test/test.sh 或其调用的命令(如 sleep)尝试读取 /etc/ld.so.cache,但 AppArmor 配置未明确允许。
        /etc/ld.so.cache 是动态链接器(ld.so)使用的缓存文件,通常由 root 拥有(ouid=0),且需要读权限(requested_mask="r")。
    可能的原因
        脚本中调用了某些命令(如 ldconfig、动态链接的可执行文件),间接触发了对 /etc/ld.so.cache 的读取。
        AppArmor 配置未包含对系统关键文件(如 /etc/ld.so.cache)的访问规则。

解决方案
1. 修改 AppArmor 配置文件

    编辑 /etc/apparmor.d/home.lzs.workspace.test.test.sh,添加对 /etc/ld.so.cache 的读取权限:

    plaintext

profile /home/lzs/workspace/test/test.sh {

  # 允许读取脚本本身

  /home/lzs/workspace/test/test.sh r,

 

  # 允许执行 /bin/sh 和相关命令

  /bin/sh ix,

  /usr/bin/* ix,

 

  # 允许读取 /etc/ld.so.cache(关键修改)

  /etc/ld.so.cache r,

 

  # 其他必要规则(如临时目录、库路径等)

  /lib/** r,

  /usr/lib/** r,

  /tmp/** rw,

  /var/tmp/** rw,

}

重新加载配置:

bash

    sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

2. 检查脚本是否真的需要访问 /etc/ld.so.cache

    如果脚本未直接调用动态链接库相关命令,可能是某个子进程(如 sleep)间接触发了访问。建议:
        使用 strace 跟踪脚本执行,确认哪个命令触发了文件访问:

        bash

        sudo strace -f -e openat /home/lzs/workspace/test/test.sh 2>&1 | grep ld.so.cache

        如果发现无关命令触发了访问,考虑移除或替换该命令。

3. 临时放宽 AppArmor 限制(测试用)

    如果问题紧急,可以临时切换 AppArmor 到 complain 模式(仅记录不阻止):

    bash

sudo aa-complain /home/lzs/workspace/test/test.sh

    测试脚本是否能正常运行:

    bash

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

确认无报错后,再调整配置文件并切换回 enforce 模式:

bash

        sudo aa-enforce /home/lzs/workspace/test/test.sh

4. 检查系统库路径权限

    确保动态链接库路径(如 /lib/、/usr/lib/)的权限正确:

    bash

    ls -ld /lib /usr/lib /etc/ld.so.cache

        正常情况下,/etc/ld.so.cache 应为 -rw-r--r--(644),所有者可为 root。

5. 监控 AppArmor 日志

    实时查看拒绝事件,确认是否还有其他被阻止的文件或操作:

    bash

sudo tail -f /var/log/audit/audit.log | grep apparmor

    或使用 dmesg:

    bash

        dmesg | grep apparmor

验证步骤

    更新 AppArmor 配置后,重新加载并测试:

    bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

检查是否仍有 DENIED 日志:

bash

    sudo dmesg | grep apparmor

    如果问题解决,确认脚本输出是否符合预期。

总结

    根本原因:AppArmor 配置未允许访问 /etc/ld.so.cache,导致动态链接相关操作被阻止。
    推荐操作:
        在 AppArmor 配置中添加 /etc/ld.so.cache r,。
        使用 strace 确认触发访问的具体命令。
        如果不需要动态链接库操作,移除脚本中相关命令。

如果问题仍未解决,请提供以下信息:

    完整的 AppArmor 配置文件内容。
    脚本中涉及动态链接或库调用的片段。
    strace 或 audit.log 中的完整错误上下文。

(1753094292.167:364): apparmor="DENIED" operation="open" class="file" profile="/home/lzs/workspace/test/test.sh" name="/etc/ld.so.cache" pid=133598 comm="sleep" requested_mask="r" denied_mask="r" fsuid=0 ouid=0

这个错误表明 AppArmor 拒绝了 sh 进程使用 dac_read_search 能力(Capability 2),这是 Linux 的另一种权限控制机制,通常用于绕过文件读权限检查(如以 root 身份读取受限文件)。以下是详细分析和解决方案:
错误原因

    dac_read_search 能力被拒绝
        您的脚本 /home/lzs/workspace/test/test.sh 或其调用的命令(如 sh)尝试使用 dac_read_search 能力(Capability 2),但 AppArmor 配置未明确允许。
        此能力通常用于:
            以 root 身份读取无权限的文件(如 /etc/shadow)。
            绕过目录的执行权限检查(如 cd 到无 x 权限的目录)。
    脚本可能尝试访问受限文件或目录
        例如:读取 /etc/shadow、访问 /root/ 目录或调用需要 root 读权限的命令。
    AppArmor 默认严格限制
        除非显式配置,否则 AppArmor 会阻止进程使用任何特权能力。

解决方案
1. 修改 AppArmor 配置文件

    编辑 /etc/apparmor.d/home.lzs.workspace.test.test.sh,添加对 dac_read_search 能力的允许:

    plaintext

profile /home/lzs/workspace/test/test.sh {

  # 允许读取脚本本身

  /home/lzs/workspace/test/test.sh r,

 

  # 允许执行 /bin/sh 和相关命令

  /bin/sh ix,

  /usr/bin/* ix,

 

  # 允许使用 dac_read_search 能力(关键修改)

  capability dac_read_search,

 

  # 其他必要规则(如文件访问、临时目录等)

  /tmp/** rw,

  /var/tmp/** rw,

}

重新加载配置:

bash

    sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

2. 检查脚本是否真的需要特权读取

    如果脚本不需要读取受限文件,可能是误调用了需要 root 读权限的命令(如 cat /etc/shadow)。建议:
        审查脚本内容,移除不必要的特权操作。
        使用 strace 跟踪脚本执行,确认哪个命令触发了能力请求:

        bash

        sudo strace -f -e capset /home/lzs/workspace/test/test.sh

3. 临时放宽 AppArmor 限制(测试用)

    如果问题紧急,可以临时切换 AppArmor 到 complain 模式(仅记录不阻止):

    bash

sudo aa-complain /home/lzs/workspace/test/test.sh

    测试脚本是否能正常运行:

    bash

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

确认无报错后,再调整配置文件并切换回 enforce 模式:

bash

        sudo aa-enforce /home/lzs/workspace/test/test.sh

4. 替代方案:使用 sudo 明确授权

    如果脚本必须读取受限文件(如 /etc/shadow),建议:
        在 AppArmor 配置中严格限制可访问的文件路径(避免过度放权)。
        通过 sudo 单独授权特定命令(而非全局 dac_read_search):

        bash

# 在脚本中替换特权命令为:

sudo cat /etc/shadow

在 /etc/sudoers 中配置精细权限(使用 visudo):

plaintext

        lzs ALL=(root) NOPASSWD: /usr/bin/cat /etc/shadow

5. 监控 AppArmor 日志

    实时查看拒绝事件,确认是否还有其他被阻止的能力或文件:

    bash

sudo tail -f /var/log/audit/audit.log | grep apparmor

    或使用 dmesg:

    bash

        dmesg | grep apparmor

验证步骤

    更新 AppArmor 配置后,重新加载并测试:

    bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

检查是否仍有 DENIED 日志:

bash

    sudo dmesg | grep apparmor

    如果问题解决,确认脚本输出是否符合预期。

总结

    根本原因:AppArmor 配置未允许 dac_read_search 能力,导致脚本无法读取受限文件或目录。
    推荐操作:
        如果脚本确实需要特权读取,修改 AppArmor 配置添加 capability dac_read_search,。
        如果不需要特权读取,检查脚本并移除相关操作。
        使用 strace 或 sudo 精确控制特权命令。

如果问题仍未解决,请提供以下信息:

    完整的 AppArmor 配置文件内容。
    脚本中涉及文件读取或特权命令的片段。
    strace 或 audit.log 中的完整错误上下文。

Jul 21 18:28:47 lzs-Precision-3591 kernel: [ 6766.411522] audit: type=1400 audit(1753093727.799:192): apparmor="DENIED" operation="capable" class="cap" profile="/home/lzs/workspace/test/test.sh" pid=123916 comm="sh" capability=2  capname="dac_read_search"

这个错误表明 AppArmor 拒绝了 sh 进程使用 dac_override 能力(Capability),这是 Linux 的一种权限控制机制,通常用于绕过文件权限检查(如以 root 身份读写无权限的文件)。以下是详细分析和解决方案:
错误原因

    dac_override 能力被拒绝
        您的脚本 /home/lzs/workspace/test/test.sh 或其调用的命令(如 sh)尝试使用 dac_override 能力(Capability 1),但 AppArmor 配置未明确允许。
        此能力通常用于:
            以 root 身份修改文件所有者/权限(如 chown、chmod)。
            绕过普通用户的文件读/写限制。
    脚本可能执行了特权操作
        例如:尝试修改 /etc/ 下的文件、访问受限设备或调用需要 root 权限的命令。
    AppArmor 默认严格限制
        除非显式配置,否则 AppArmor 会阻止进程使用任何特权能力。

解决方案
1. 修改 AppArmor 配置文件

    编辑 /etc/apparmor.d/home.lzs.workspace.test.test.sh,添加对 dac_override 能力的允许:

    plaintext

profile /home/lzs/workspace/test/test.sh {

  # 允许读取脚本本身

  /home/lzs/workspace/test/test.sh r,

 

  # 允许执行 /bin/sh 和相关命令

  /bin/sh ix,

  /usr/bin/* ix,

 

  # 允许使用 dac_override 能力(关键修改)

  capability dac_override,

 

  # 其他必要规则(如文件访问、临时目录等)

  /tmp/** rw,

  /var/tmp/** rw,

}

重新加载配置:

bash

    sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

2. 检查脚本是否真的需要特权

    如果脚本不需要修改文件权限或所有者,可能是误调用了需要 root 权限的命令(如 chown、systemctl)。建议:
        审查脚本内容,移除不必要的特权操作。
        使用 strace 跟踪脚本执行,确认哪个命令触发了能力请求:

        bash

        sudo strace -f -e capset /home/lzs/workspace/test/test.sh

3. 临时放宽 AppArmor 限制(测试用)

    如果问题紧急,可以临时切换 AppArmor 到 complain 模式(仅记录不阻止):

    bash

sudo aa-complain /home/lzs/workspace/test/test.sh

    测试脚本是否能正常运行:

    bash

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

确认无报错后,再调整配置文件并切换回 enforce 模式:

bash

        sudo aa-enforce /home/lzs/workspace/test/test.sh

4. 替代方案:使用 sudo 明确授权

    如果脚本必须执行特权操作(如修改系统文件),建议:
        在 AppArmor 配置中严格限制可访问的文件路径(避免过度放权)。
        通过 sudo 单独授权特定命令(而非全局 dac_override):

        bash

# 在脚本中替换特权命令为:

sudo chown root:root /path/to/file

在 /etc/sudoers 中配置精细权限(使用 visudo):

plaintext

        lzs ALL=(root) NOPASSWD: /bin/chown root:root /specific/path

5. 监控 AppArmor 日志

    实时查看拒绝事件,确认是否还有其他被阻止的能力或文件:

    bash

sudo tail -f /var/log/audit/audit.log | grep apparmor

    或使用 dmesg:

    bash

        dmesg | grep apparmor

验证步骤

    更新 AppArmor 配置后,重新加载并测试:

    bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

检查是否仍有 DENIED 日志:

bash

    sudo dmesg | grep apparmor

    如果问题解决,确认脚本输出是否符合预期。

总结

    根本原因:AppArmor 配置未允许 dac_override 能力,导致脚本无法执行特权操作。
    推荐操作:
        如果脚本确实需要特权,修改 AppArmor 配置添加 capability dac_override,。
        如果不需要特权,检查脚本并移除相关操作。
        使用 strace 或 sudo 精确控制特权命令。

如果问题仍未解决,请提供以下信息:

    完整的 AppArmor 配置文件内容。
    脚本中涉及文件操作或特权命令的片段。
    strace 或 audit.log 中的完整错误上下文。

Jul 21 18:24:53 lzs-Precision-3591 kernel: [ 6532.392636] audit: type=1400 audit(1753093493.778:184): apparmor="DENIED" operation="capable" class="cap" profile="/home/lzs/workspace/test/test.sh" pid=119923 comm="sh" capability=1  capname="dac_override"

这个错误表明 AppArmor 再次拒绝了 sh 进程访问 /etc/locale.alias 文件,这是国际化(i18n)配置的另一个关键文件。以下是详细分析和解决方案:
错误原因

    AppArmor 配置未覆盖 /etc/locale.alias
        您的 AppArmor 配置文件 /home/lzs/workspace/test/test.sh 未明确允许访问 /etc/locale.alias,导致 glibc 在初始化语言环境时被阻止。
    国际化文件依赖链
        当脚本或其调用的程序(如 sh)尝试加载语言环境时,会依次访问:
            /etc/locale.alias(别名映射文件)
            /usr/share/locale/(基础翻译文件)
            /usr/share/locale-langpack/(扩展翻译文件)
        之前解决了 /usr/share/locale-langpack/ 的访问问题,但未覆盖 /etc/locale.alias。
    脚本以 root 身份运行(fsuid=0)
        通过 sudo aa-exec 运行的脚本继承了 root 权限,但 AppArmor 仍会按配置文件限制访问,即使对 root 生效。

解决方案
1. 更新 AppArmor 配置文件

    编辑 /etc/apparmor.d/home.lzs.workspace.test.test.sh,添加对 /etc/locale.alias 的读取权限:

    plaintext

profile /home/lzs/workspace/test/test.sh {

  # 允许读取脚本本身

  /home/lzs/workspace/test/test.sh r,

 

  # 允许执行 /bin/sh 和相关命令

  /bin/sh ix,

  /usr/bin/* ix,

 

  # 允许访问国际化文件(关键修改)

  /etc/locale.alias r,  # 新增:允许读取别名文件

  /usr/share/locale/** r,

  /usr/share/locale-langpack/** r,

 

  # 其他必要规则(如临时文件、库等)

  /tmp/** rw,

  /var/tmp/** rw,

}

重新加载配置:

bash

    sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

2. 验证文件权限

    确认 /etc/locale.alias 对所有用户可读(通常应为 644):

    bash

ls -l /etc/locale.alias

    输出示例:

    plaintext

-rw-r--r-- 1 root root 2500 Oct 10 10:00 /etc/locale.alias

如果权限不足(如 600),需修复权限:

bash

        sudo chmod 644 /etc/locale.alias

3. 临时绕过国际化(测试用)

    如果脚本不需要国际化支持,强制使用 C 语言环境(避免加载任何 .mo 或别名文件):

    bash

    sudo aa-exec -p /home/lzs/workspace/test/test.sh -- env LC_ALL=C /home/lzs/workspace/test/test.sh

        如果问题解决,说明确实是国际化文件访问导致的问题,需按方案 1 调整 AppArmor 规则。

4. 检查系统语言环境配置

    确认系统默认语言环境是否有效:

    bash

locale

    如果输出包含 LANG= 或 LC_*= 但指向无效路径(如已删除的语言包),可能导致频繁访问国际化文件。重置为通用配置:

    bash

        sudo update-locale LANG=en_US.UTF-8

5. 监控 AppArmor 日志

    实时查看拒绝事件,确认是否还有其他被阻止的文件:

    bash

sudo tail -f /var/log/audit/audit.log | grep apparmor

    或使用 dmesg:

    bash

        dmesg | grep apparmor

验证步骤

    更新 AppArmor 配置后,重新加载并测试:

    bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

检查是否仍有 DENIED 日志:

bash

    sudo dmesg | grep apparmor

    如果问题解决,确认脚本输出是否符合预期。

总结

    根本原因:AppArmor 配置未放行 /etc/locale.alias,导致语言环境初始化失败。
    推荐操作:
        修改 AppArmor 配置,添加 /etc/locale.alias r 规则。
        确保文件权限为 644。
        如果不需要国际化,通过 env LC_ALL=C 临时绕过。
        检查系统语言环境配置是否有效。

如果问题仍未解决,请提供以下信息:

    完整的 AppArmor 配置文件内容。
    locale 命令的输出。
    ls -l /etc/locale.alias 的输出。

[ 6418.227931] audit: type=1400 audit(1753093379.613:177): apparmor="DENIED" operation="open" class="file" profile="/home/lzs/workspace/test/test.sh" name="/etc/locale.alias" pid=117949 comm="sh" requested_mask="r" denied_mask="r" fsuid=0 ouid=0

这个错误表明 AppArmor 拒绝了 sh 进程访问 /usr/share/locale-langpack/zh_CN/LC_MESSAGES/libc.mo 文件,导致脚本可能因国际化(i18n)文件加载失败而异常终止。以下是详细分析和解决方案:
错误原因

    AppArmor 配置限制
        您的 AppArmor 配置文件 /home/lzs/workspace/test/test.sh 未明确允许访问 /usr/share/locale-langpack/ 目录下的文件。
        当脚本或其调用的程序(如 sh)尝试读取国际化文件(如 libc.mo)时,AppArmor 会阻止访问。
    脚本依赖国际化文件
        脚本或其调用的命令(如 echo、printf 或其他工具)可能依赖 glibc 的国际化支持,需要加载 .mo 文件(多语言翻译文件)。
    路径未覆盖
        默认情况下,AppArmor 配置可能仅放行了脚本本身和必要的二进制文件,但未包含 /usr/share/locale* 等路径。

解决方案
1. 修改 AppArmor 配置文件

    编辑或创建 AppArmor 配置文件(如 /etc/apparmor.d/home.lzs.workspace.test.test.sh),添加对国际化文件的访问规则:

    plaintext

# /etc/apparmor.d/home.lzs.workspace.test.test.sh

profile /home/lzs/workspace/test/test.sh {

  # 允许读取脚本本身

  /home/lzs/workspace/test/test.sh r,

 

  # 允许执行 /bin/sh 和相关命令

  /bin/sh ix,

  /usr/bin/* ix,

 

  # 允许访问国际化文件(关键修改)

  /usr/share/locale/** r,

  /usr/share/locale-langpack/** r,

 

  # 其他必要规则(如临时文件、库等)

  /tmp/** rw,

  /var/tmp/** rw,

}

重新加载配置:

bash

    sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

2. 临时放宽 AppArmor 限制(测试用)

    如果问题紧急,可以临时切换 AppArmor 到 complain 模式(仅记录不阻止):

    bash

sudo aa-complain /home/lzs/workspace/test/test.sh

    测试脚本是否能正常运行:

    bash

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

确认无报错后,再调整配置文件并切换回 enforce 模式:

bash

        sudo aa-enforce /home/lzs/workspace/test/test.sh

3. 检查脚本是否依赖特定语言环境

    如果脚本不需要国际化支持,可以强制使用 C 语言环境(避免加载 .mo 文件):

    bash

    sudo aa-exec -p /home/lzs/workspace/test/test.sh -- env LC_ALL=C /home/lzs/workspace/test/test.sh

        如果问题解决,说明确实是国际化文件访问导致的问题,需按方案 1 调整 AppArmor 规则。

4. 验证 AppArmor 日志

    实时监控 AppArmor 拒绝事件:

    bash

sudo tail -f /var/log/audit/audit.log | grep apparmor

    或使用 dmesg 查看最近日志:

    bash

        dmesg | grep apparmor

5. 检查文件是否存在

    确认被拒绝的文件路径是否存在:

    bash

ls -l /usr/share/locale-langpack/zh_CN/LC_MESSAGES/libc.mo

    如果路径不存在,可能是系统未安装完整的语言包。安装中文语言包(Ubuntu/Debian):

    bash

        sudo apt install language-pack-zh-hans

验证步骤

    更新 AppArmor 配置后,重新加载并测试:

    bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

检查是否仍有 DENIED 日志:

bash

    sudo dmesg | grep apparmor

    如果问题解决,确认脚本输出是否符合预期。

总结

    根本原因:AppArmor 配置未放行 /usr/share/locale* 路径,导致脚本无法加载国际化文件。
    推荐操作:
        修改 AppArmor 配置,添加 /usr/share/locale/** r 和 /usr/share/locale-langpack/** r 规则。
        如果不需要国际化,通过 env LC_ALL=C 临时绕过。
        检查系统是否安装了完整的语言包。

如果问题仍未解决,请提供以下信息:

    完整的 AppArmor 配置文件内容。
    ls -l /usr/share/locale-langpack/zh_CN/LC_MESSAGES/ 的输出。
    脚本中是否显式调用了需要国际化的命令(如 gettext)。

[ 6101.855345] audit: type=1400 audit(1753093063.239:163): apparmor="DENIED" operation="open" class="file" profile="/home/lzs/workspace/test/test.sh" name="/usr/share/locale-langpack/zh_CN/LC_MESSAGES/libc.mo" pid=112383 comm="sh" requested_mask="r" denied_mask="r" fsuid=0 ouid=0

这个错误表明 aa-exec 虽然成功启动了,但目标脚本 /home/lzs/workspace/test/test.sh 没有可执行权限,导致无法运行。以下是详细分析和解决方案:
错误原因

    文件权限不足
        脚本文件 /home/lzs/workspace/test/test.sh 可能缺少可执行权限(x 权限)。
        即使通过 aa-exec 指定了 AppArmor 配置,系统仍会检查基本的文件权限。
    AppArmor 配置未生效
        如果配置文件未正确加载,aa-exec 可能无法按预期限制或放行权限(但当前错误是基础权限问题,与 AppArmor 无关)。
    文件系统挂载为 noexec
        如果 /home 或脚本所在分区挂载时添加了 noexec 选项,即使文件有 x 权限也无法执行(较少见)。

解决方案
1. 添加可执行权限

    运行以下命令为脚本添加可执行权限:

    bash

chmod +x /home/lzs/workspace/test/test.sh

再次尝试通过 aa-exec 运行:

bash

    sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

2. 检查文件权限和所有者

    确认脚本的所有者和权限:

    bash

ls -l /home/lzs/workspace/test/test.sh

    输出示例:

    plaintext

        -rwxr-xr-- 1 lzs lzs 120 Oct 10 10:00 /home/lzs/workspace/test/test.sh

        确保所有者(lzs)有 rwx 权限,其他用户至少有 rx 权限(如果通过 sudo 运行,通常不受其他用户权限影响)。

3. 验证 AppArmor 配置

    如果脚本仍无法运行,可能是 AppArmor 配置限制了访问。检查配置文件是否包含对脚本路径的明确允许:

    plaintext

# /etc/apparmor.d/home.lzs.workspace.test.test.sh

profile /home/lzs/workspace/test/test.sh {

  # 允许读取和执行脚本本身

  /home/lzs/workspace/test/test.sh r,

  # 允许执行脚本(如果通过解释器运行)

  /bin/bash ix,

}

重新加载配置:

bash

    sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

4. 检查文件系统挂载选项

    确认分区是否挂载为 noexec:

    bash

mount | grep /home

    如果输出包含 noexec,需重新挂载为可执行(需 root 权限):

    bash

        sudo mount -o remount,exec /home

        注意:修改挂载选项可能影响安全性,建议优先修复文件权限。

5. 直接运行测试

    绕过 aa-exec 直接运行脚本,确认是否为 AppArmor 问题:

    bash

    /home/lzs/workspace/test/test.sh

        如果仍报 Permission denied,则问题与 AppArmor 无关,需检查文件权限或 SELinux(如果启用)。

6. 检查 SELinux 状态(如适用)

    如果系统启用 SELinux,可能阻止执行:

    bash

getenforce

    如果输出为 Enforcing,尝试临时禁用测试:

    bash

sudo setenforce 0

        /home/lzs/workspace/test/test.sh

        若问题解决,需调整 SELinux 策略而非 AppArmor。

验证步骤

    确认脚本权限:

    bash

ls -l /home/lzs/workspace/test/test.sh

尝试直接运行:

bash

/home/lzs/workspace/test/test.sh

通过 aa-exec 运行并检查 AppArmor 日志:

bash

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

    sudo dmesg | grep apparmor

总结

    根本原因:脚本文件缺少可执行权限(x),或文件系统挂载为 noexec。
    推荐操作:
        运行 chmod +x /home/lzs/workspace/test/test.sh。
        确认文件权限和所有者正确。
        检查 AppArmor 配置是否允许执行脚本。
        排除文件系统或 SELinux 的干扰。

如果问题仍未解决,请提供以下信息:

    ls -l /home/lzs/workspace/test/test.sh 的输出。
    mount | grep /home 的输出。
    sudo aa-status 中是否显示您的配置已加载。

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh 
/bin/sh: /home/lzs/workspace/test/test.sh: Permission denied

这个错误表明 aa-exec 在尝试运行 /home/lzs/workspace/test/test.sh 时,系统无法找到动态链接库 libtinfo.so.6。这通常是由于环境配置问题或库文件缺失导致的。以下是详细的解决方案:
错误原因分析

    动态链接库缺失
        libtinfo.so.6 是 ncurses 或 libtinfo 库的一部分,通常由 libncurses6 或 libtinfo6 软件包提供。
        如果系统未安装该库,或安装的版本不匹配(如 libtinfo.so.5 而非 libtinfo.so.6),会导致此错误。
    aa-exec 的环境隔离
        aa-exec 会以指定的 AppArmor 配置启动进程,但可能不会继承完整的用户环境(如 LD_LIBRARY_PATH),导致动态链接器无法找到库文件。
    脚本解释器问题
        如果 test.sh 的 shebang(如 #!/bin/bash)指向的解释器依赖 libtinfo.so.6,但该库在 aa-exec 的环境中不可见,也会触发此错误。

解决方案
1. 安装缺失的库

    Ubuntu/Debian:

    bash

sudo apt update

sudo apt install libtinfo6  # 或 libncurses6

CentOS/RHEL:

bash

sudo yum install ncurses-libs

Arch Linux:

bash

    sudo pacman -S ncurses

2. 检查库文件是否存在

    确认库文件是否已安装但路径未包含在动态链接器的搜索路径中:

    bash

ldconfig -p | grep libtinfo.so.6

    如果无输出,尝试手动创建符号链接(假设库文件实际存在但版本不同):

    bash

        sudo ln -s /usr/lib/libtinfo.so.5 /usr/lib/libtinfo.so.6

        注意:此方法需确保库版本兼容,否则可能导致运行时错误。

3. 显式指定库路径

    在运行 aa-exec 前,临时设置 LD_LIBRARY_PATH 包含库文件所在目录:

    bash

export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH

    sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

        替换 /usr/lib/x86_64-linux-gnu 为实际的库路径(可通过 ldconfig -v | grep libtinfo 查找)。

4. 直接运行脚本(绕过 aa-exec 测试)

    先确认脚本本身能否正常运行:

    bash

    /home/lzs/workspace/test/test.sh

        如果同样报错,说明问题与 AppArmor 无关,需修复环境依赖。

5. 检查 AppArmor 配置

    如果库文件路径受限(如 /usr/lib 未在配置中允许),需在 AppArmor 配置文件中添加规则:

    plaintext

# /etc/apparmor.d/home.lzs.workspace.test.test.sh

profile /home/lzs/workspace/test/test.sh {

  # 允许访问库文件路径

  /usr/lib/** rm,

  /lib/** rm,

}

    重新加载配置:

    bash

        sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

6. 使用 strace 调试

    跟踪进程启动过程,定位库加载失败的具体原因:

    bash

    strace -f -e openat sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh 2>&1 | grep libtinfo

验证步骤

    确认库文件已安装且路径正确:

    bash

ls -l /usr/lib*/libtinfo.so*

尝试直接运行脚本(不通过 aa-exec)以排除环境问题。
使用 LD_DEBUG=libs 查看动态链接器行为:

bash

    LD_DEBUG=libs sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

总结

    根本原因:aa-exec 的环境缺少 libtinfo.so.6 库,或动态链接器无法找到该库。
    推荐操作:
        安装 libtinfo6 或兼容版本。
        通过 LD_LIBRARY_PATH 显式指定库路径。
        检查 AppArmor 配置是否限制了必要的库访问路径。

如果问题仍未解决,请提供以下信息以便进一步分析:

    操作系统版本(cat /etc/os-release)。
    ldconfig -p | grep libtinfo 的输出。
    完整的 aa-exec 命令及错误日志。

sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh 
/bin/sh: error while loading shared libraries: libtinfo.so.6: cannot open shared object file: No such file or directory

从您提供的命令和输出来看,虽然您尝试重新加载 AppArmor 配置文件(sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh),但目标脚本 test.sh 仍然以 unconfined 模式运行,未受到您定义的 AppArmor 配置文件的限制。以下是详细分析和解决方案:
问题原因

    配置文件未正确关联到进程
        您的配置文件路径为 /etc/apparmor.d/home.lzs.workspace.test.test.sh,但 AppArmor 要求配置文件中的 profile 名称必须与目标进程的路径或名称严格匹配。
        当前 ps -auxZ 输出显示 test.sh 以 unconfined 运行,说明 AppArmor 未识别到对应的配置文件。
    配置文件可能未生效
        如果配置文件语法错误或路径不匹配,apparmor_parser 可能静默失败(即使未报错)。

解决方案
1. 检查配置文件内容

    确保配置文件中声明的 profile 名称与目标脚本的路径或名称一致。例如:

    plaintext

# /etc/apparmor.d/home.lzs.workspace.test.test.sh

profile /home/lzs/workspace/test/test.sh {

  # 您的规则(如 deny)

  deny /home/lzs/workspace/output/** rwkl,

    }

    关键点:profile 后的路径必须与 ps -auxZ 中显示的进程路径(/home/lzs/workspace/test/test.sh)完全一致。

2. 强制重新加载并验证语法

    删除缓存后重新加载配置:

    bash

sudo rm /etc/apparmor.d/cache/home.lzs.workspace.test.test.sh

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

检查语法错误:

bash

    sudo apparmor_parser -Q /etc/apparmor.d/home.lzs.workspace.test.test.sh

3. 确认配置是否生效

    列出已加载的配置,检查是否包含您的配置文件:

    bash

    sudo apparmor_status | grep test.sh

    如果配置未加载,可能是路径或名称不匹配。

4. 直接指定进程的 AppArmor 配置

    如果脚本是通过解释器(如 bash)运行的,可能需要为解释器(如 /usr/bin/bash)定义配置,或通过 aa-exec 强制绑定配置:

    bash

    sudo aa-exec -p /home/lzs/workspace/test/test.sh -- /home/lzs/workspace/test/test.sh

5. 调试模式

    启用调试日志,观察配置加载过程:

    bash

    sudo apparmor_parser -v --debug /etc/apparmor.d/home.lzs.workspace.test.test.sh

验证步骤

    重启脚本并检查状态
        重新运行脚本后,通过以下命令确认其 AppArmor 状态:

        bash

    ps -auxZ | grep test.sh

    预期输出应显示配置文件名称(如 home.lzs.workspace.test.test.sh),而非 unconfined。

触发违规测试

    在脚本中添加尝试访问受限路径的操作(如 cat /etc/shadow),然后检查审计日志:

    bash

        sudo dmesg | grep apparmor

常见问题

    配置文件命名规则
    AppArmor 默认将配置文件路径中的 / 替换为 .(如 /etc/apparmor.d/home.lzs.workspace.test.test.sh 对应配置名 home.lzs.workspace.test.test.sh)。确保 profile 声明与之一致。

    解释器脚本的限制
    如果 test.sh 是通过 bash test.sh 运行的,AppArmor 可能仅限制 bash 而非脚本本身。建议直接为脚本路径定义配置。

总结

当前问题表明 AppArmor 配置文件未正确关联到 test.sh 进程。请按以下顺序排查:

    确认配置文件中的 profile 名称与脚本路径一致。
    强制重新加载配置并检查语法。
    使用 aa-exec 或直接路径确保进程受配置限制。
    通过审计日志验证规则是否生效。

如果仍有问题,请提供配置文件内容和 sudo apparmor_parser -v --debug 的输出以便进一步分析。
sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh 
lzs@lzs-Precision-3591:~/workspace/test$ ps -aux -Z | grep unconfined | grep test
unconfined                      kernoops    1545  0.0  0.0  13092  2120 ?        Ss   16:36   0:00 /usr/sbin/kerneloops --test
unconfined                      lzs        97467  0.0  0.0  13516  3872 pts/1    S+   18:03   0:00 sh test.sh
unconfined                      lzs        98592  0.0  0.0  12644  2288 pts/2    S+   18:04   0:00 grep --color=auto test

追踪 AppArmor 违规行为

AppArmor 会将事件记录到系统的审计日志中。对于 Ubuntu 16.04 及更早版本的系统,此功能默认由 systemd 处理;对于 SuSE/SLES 系统,日志位于 /var/log/audit/audit.log。重新加载配置文件后,您应能看到许多类似于以下 wkhtmltopdf 的记录:

1月12日 17:01:57 ip-192-0-2-121 audit[19164]: AVC apparmor="STATUS" operation="profile_replace" profile="unconfined" name="/usr/local/bin/wkhtmltopdf" pid=19164 comm="apparmor_parser"

在较新版本的 AppArmor 中,记录可能如下:

1月12日 17:01:57 ip-192-0-2-121 audit[19164]: AVC apparmor="STATUS" operation="profile_replace" info="same as current profile, skipping" operation="profile_replace" profile="unconfined" name="/usr/local/bin/wkhtmltopdf" pid=19164 comm="apparmor_parser"

违规行为会显示在同一日志中:

1月12日 17:42:03 ip-192-0-2-121 audit[19164]: AVC apparmor="DENIED" operation="open" profile="/usr/local/bin/wkhtmltopdf" name="/etc/passwd" pid=12112 comm="wkhtmltopdf" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

此记录表明,AppArmor 阻止了尝试读取 /etc/passwd 的操作。
翻译:Track AppArmor violations

AppArmor will log events to the system’s audit-log. For Ubuntu systems 16.04 and older this by default is handled in systemd. For SuSE/SLES system, this is found in /var/log/audit/audit.log. After reloading your profiles you should see many entries similar to this wkhtmltopdf one:

Jan 12 17:01:57 ip-192-0-2-121 audit[19164]: AVC apparmor="STATUS" operation="profile_replace" profile="unconfined" name="/usr/local/bin/wkhtmltopdf" pid=19164 comm="apparmor_parser"

Or in newer AppArmor versions:

Jan 12 17:01:57 ip-192-0-2-121 audit[19164]: AVC apparmor="STATUS" operation="profile_replace" info="same as current profile, skipping" operation="profile_replace" profile="unconfined" name="/usr/local/bin/wkhtmltopdf" pid=19164 comm="apparmor_parser"

Violations will show up the same log:

Jan 12 17:42:03 ip-192-0-2-121 audit[19164]: AVC apparmor="DENIED" operation="open" profile="/usr/local/bin/wkhtmltopdf" name="/etc/passwd" pid=12112 comm="wkhtmltopdf" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

Which shows that AppArmor denied an attempt to read /etc/passwd.

从您提供的日志来看,AppArmor 并未实际加载或更新您的配置文件,而是跳过了替换操作(profile_replace),原因是当前配置与已加载的配置完全相同(same as current profile, skipping)。这解释了为什么您的 deny 规则未生效——配置根本未被重新加载。
问题原因分析

    配置未修改
        如果您直接运行 sudo apparmor_parser 加载同一个配置文件,而文件内容未更改,AppArmor 会检测到配置无变化并跳过加载。
        日志中的 profile="unconfined" 表示当前进程(apparmor_parser)本身未受 AppArmor 限制,但目标配置 /home/lzs/workspace/test/test.sh 的加载被跳过。
    配置路径或名称不匹配
        确保您加载的配置文件路径与日志中的 name="/home/lzs/workspace/test/test.sh" 完全一致。
        如果配置文件中声明的名称(如 profile 或 path)与文件名或目标路径不符,可能导致加载失败。
    语法错误未被检测
        如果配置文件存在语法错误,apparmor_parser 可能会静默失败(尤其是使用 --debug 时)。建议显式检查语法:

        bash

        sudo apparmor_parser -Q /etc/apparmor.d/home.lzs.workspace.test.test.sh

解决方案
1. 强制重新加载配置

    使用 -r(replace)或 -R(reload)选项强制覆盖现有配置:

    bash

    sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

    如果仍提示 same as current profile,说明文件内容确实未变化。

2. 检查配置文件内容

    确保配置文件中明确声明了目标路径,例如:

    plaintext

profile /home/lzs/workspace/test/test.sh {

  # 您的规则(包括 deny)

  deny /home/lzs/workspace/output/** rwkl,

    }

    关键点:配置文件中的 profile 名称必须与日志中的 name="..." 一致。

3. 验证配置是否生效

    检查当前加载的配置:

    bash

sudo apparmor_status | grep test.sh

或查看进程的 AppArmor 状态:

bash

    ps auxZ | grep test.sh  # 检查目标进程的配置文件是否匹配

4. 调试模式深入检查

    使用 --debug 时,添加 -v 参数输出详细日志:

    bash

    sudo apparmor_parser -v --debug /etc/apparmor.d/home.lzs.workspace.test.test.sh

    观察输出中是否有 Parsed rules 或 Rejected rules 的提示。

5. 临时切换到 Complain 模式

    如果怀疑规则过于严格导致配置未加载,先切换到 complain 模式记录违规行为:

    bash

sudo aa-complain /home/lzs/workspace/test/test.sh

运行脚本后检查日志:

bash

    sudo dmesg | grep apparmor

常见误区

    文件名与配置内容不一致
        例如:配置文件名为 home.lzs.workspace.test.test.sh,但内部声明的 profile 名为 test.sh,可能导致加载异常。
    通配符冲突
        如果同时存在 /** 和 deny 规则,宽泛的 allow 可能覆盖 deny。建议优先测试精简规则。
    未重启服务
        修改配置后,重启 AppArmor 服务以确保生效:

        bash

        sudo systemctl restart apparmor

下一步建议

    确认配置文件内容:检查 deny 规则是否在正确的 profile 块内。
    强制重新加载:使用 -r 或删除旧配置后再加载:

    bash

sudo rm /etc/apparmor.d/cache/home.lzs.workspace.test.test.sh

    sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

    检查日志:通过 audit.log 或 journalctl 确认是否有 DENIED 记录。

如果问题仍未解决,请提供以下信息以便进一步诊断:

    完整的配置文件内容(去除敏感信息)。
    运行 sudo aa-status 的输出。
    触发 deny 规则的具体操作(如执行的命令或脚本行为)。

Jul 21 16:16:21 lzs-Precision-3591 audit[1204181]: AVC apparmor="STATUS" operation="profile_replace" info="same as current profile, skipping" profile="unconfined" name="/home/lzs/workspace/test/test.sh" pid=1204181 comm="apparmor_parser"
Jul 21 16:16:21 lzs-Precision-3591 kernel: audit: type=1400 audit(1753085781.059:149): apparmor="STATUS" operation="profile_replace" info="same as current profile, skipping" profile="unconfined" name="/home/lzs/workspace/test/test.sh" pid=1204181 comm="apparmor_parser"

针对您提供的 apparmor_parser --debug 输出和 deny 规则未生效的问题,结合AppArmor的配置原理和常见调试方法,以下是可能的原因和解决方案:
1. 规则语法问题

    问题:AppArmor的deny规则需要明确匹配路径和权限,且路径通配符需谨慎使用。
        您的配置中 link: (/**) 允许所有路径的符号链接创建,这可能覆盖了其他deny规则。
        如果deny规则的路径或权限不匹配实际访问行为,规则不会生效。
    解决方案:
        精确路径:替换/**为具体路径,例如:

        plaintext

        deny /home/lzs/workspace/output/** l,  # 仅禁止输出目录的符号链接

        明确权限:确保deny的权限(如r、w、x、l等)与操作匹配。例如,禁止读取需显式写deny /path r,。

2. 规则作用域冲突

    问题:AppArmor规则按顺序匹配,后续规则可能覆盖前面的deny。
        如果allow规则在deny之后,或包含更宽泛的路径(如/**),会导致deny失效。
    解决方案:
        调整规则顺序:将deny规则放在allow之前,或使用更具体的路径。
        避免通配符滥用:减少/**的使用,改用精确路径或目录级通配(如/path/*)。

3. 配置文件未重新加载

    问题:修改配置文件后未重新加载,导致旧规则生效。

    解决方案:
        重新加载配置文件:

        bash

sudo apparmor_parser -r /etc/apparmor.d/home.lzs.workspace.test.test.sh

或重启AppArmor服务:

bash

        sudo systemctl restart apparmor

4. 工作模式影响

    问题:若配置文件处于complain模式,deny规则仅记录违规行为而不阻止操作。

    解决方案:
        检查当前模式:

        bash

sudo aa-status

切换到enforce模式:

bash

        sudo aa-enforce /etc/apparmor.d/home.lzs.workspace.test.test.sh

5. 日志排查

    问题:AppArmor的违规行为通常记录在日志中,但未被查看。

    解决方案:
        查看系统日志:

        bash

sudo journalctl -xe | grep apparmor

或审计日志:

bash

        sudo cat /var/log/audit/audit.log | grep apparmor

        根据日志中的DENIED信息调整规则。

6. 测试建议

    最小化测试:创建一个仅包含deny规则的简单配置文件,逐步添加其他规则,定位冲突点。
    示例配置:

    plaintext

/home/lzs/workspace/test/test.sh {

  # 仅允许读取脚本自身

  /home/lzs/workspace/test/test.sh r,

 

  # 禁止输出目录的所有操作

  deny /home/lzs/workspace/output/** rwkl,

 

  # 允许特定文件读取(可选)

  /home/lzs/workspace/input/data.txt r,

    }

总结

您的deny规则未生效可能是由于路径通配符过于宽泛、规则顺序冲突或配置未重新加载。建议按以下步骤排查:

    检查日志确认违规行为是否被记录。
    精简路径通配符,避免/**覆盖deny。
    重新加载配置并切换到enforce模式。
    通过最小化测试验证规则效果。

如果问题仍未解决,可提供具体的deny规则和日志片段,以便进一步分析。
为什么我上面的deny未生效

It looks like you're debugging an AppArmor profile for a shell script located at /home/lzs/workspace/test/test.sh. The output you've shared shows the parsed AppArmor profile rules for this script. Here's a breakdown of what this means:
Debug Output Explanation:

    Profile Name:

Name: /home/lzs/workspace/test/test.sh

    This is the name of the AppArmor profile, which corresponds to the path of the executable (test.sh).

Mode:

    The Mode field is empty in the first line, which might indicate the default enforcement mode (likely enforce or complain depending on how the profile was loaded).

Entries:

    The profile contains two main access rules:
        First Entry:

Mode: rk:rk Name: (/home/lzs/workspace/test/test.sh)

    This grants the script read (r) and execute (k) permissions on itself (/home/lzs/workspace/test/test.sh).
    rk:rk means the profile allows the script to be read and executed by the owner (likely lzs).

Second Entry:

Mode: ralk:ralk Name: (/home/lzs/workspace/output/**)

            link: (/**)

                This grants read (r), append (a), link (l), and execute (k) permissions on all files and directories under /home/lzs/workspace/output/**.
                ralk:ralk suggests the owner (likely lzs) has these permissions.
                The link: (/**) part indicates that the script can also create or follow symbolic links anywhere in the filesystem (/**), which is a broad permission and could be a security concern.

Observations:

    Broad Permissions:
        The link: (/**) rule is very permissive and could allow the script to bypass filesystem restrictions by creating or following symlinks anywhere. This is often undesirable from a security standpoint.
        The ralk permissions on /home/lzs/workspace/output/** are also quite broad, allowing the script to read, append to, link, and execute files in that directory.
    Potential Issues:
        If this is a test script, the broad permissions might be intentional, but in a production environment, you'd typically want to restrict access further (e.g., only allow reading/writing to specific files or directories).
        The link: (/**) rule is particularly risky and should be reviewed.

Recommendations:

    Restrict Symlink Permissions:
        If the script doesn't need to create or follow symlinks outside of /home/lzs/workspace/output/, remove the link: (/**) rule or restrict it to a specific directory.
    Narrow Down Permissions:
        Instead of /** for links, specify a more restrictive path, e.g.:

    link: (/home/lzs/workspace/output/**)

    Similarly, review whether append (a) and execute (k) are truly needed for files in /home/lzs/workspace/output/**.

Test in Complain Mode:

    Before enforcing the profile, run AppArmor in complain mode to log potential violations without blocking them:

sudo aa-complain /home/lzs/workspace/test/test.sh

After testing, you can switch back to enforce mode:

    sudo aa-enforce /home/lzs/workspace/test/test.sh

Audit the Profile:

    Use aa-logprof to analyze logs and refine the profile:

        sudo aa-logprof

Example of a More Restrictive Profile:

If the script only needs to read itself and write to specific files in /home/lzs/workspace/output/, a tighter profile might look like this:

/home/lzs/workspace/test/test.sh {

  # Allow reading and executing the script itself

  /home/lzs/workspace/test/test.sh rk,

 

  # Allow reading and writing to specific files in output/

  /home/lzs/workspace/output/ r,

  /home/lzs/workspace/output/** rw,

 

  # Deny symlinks outside of output/ (or restrict further)

  deny /home/lzs/workspace/output/** l,

}

Let me know if you'd like help refining this profile further!
sudo apparmor_parser --debug /etc/apparmor.d/home.lzs.workspace.test.test.sh
----- Debugging built structures -----
Name:		/home/lzs/workspace/test/test.sh
Mode: 
--- Entries ---
Mode:	rk:rk	Name:	(/home/lzs/workspace/test/test.sh)
Mode:	ralk:ralk	Name:	(/home/lzs/workspace/output/**)
	link:	(/**)
Writing Desk
Document Hub
Image Studio
Translation

Prompts


AI-generated content cannot be guaranteed to be accurate. Please refer to the "Terms of Service" and "Privacy Policy" for details.


网站公告

今日签到

点亮在社区的每一天
去签到