也没什么事情,就想配置一下apparmor这一强制访问控制系统……吗?

好吧,虽然并没有完全达到原有的目的。不过,apparmor也是一个很不错的能够为程序配置权限的工具呢。

在此记录一下配置过程。

安装与基本配置

安装apparmor包

在manjaro中,aopparmor未默认安装和配置,使用 pacman -Syu apparmor 命令来安装apparmor的用户态程序。

配置内核参数

嗯……archwiki关于apparmor的页面1中要求设置内核参数 lsm=lockdown,yama,apparmor,bpf 。以让linux内核允许apparmor控制权限访问控制。

可以选择在grub的配置文件中设置这个参数2,使用所喜欢的文本编辑器打开grub的配置文件3,此处为 /etc/default/grub ,打开文件后找到 GRUB_CMDLINE_LINUX 字段,添加相关内核参数,多个参数中间使用空格隔开

1
sudo nano /etc/default/grub
1
GRUB_CMDLINE_LINUX="lsm=lockdown,yama,apparmor,bpf"

如果没找到 GRUB_CMDLINE_LINUX ,查找 GRUB_CMDLINE_LINUX_DEFAULT 应该也可以,如果需要设置多个内核参数,各个参数之间使用空格隔开。 注意,添加此内核时,如果不知道在做什么,不要改动grub配置文件的其他初始参数,错误的内核参数有可能导致启动失败和/或其他未预料的行为

配置完成后,执行 grub-mkconfig -o /boot/grub/grub.cfg 更新grub.cfg,并重启计算机。然后应该就完成内核参数的配置了。可以查看 /sys/kernel/security/lsm 或使用 aa-enabled 命令来验证这一点

1
aa-enabled
1
Yes

如果输出结果为类似于这样的 Yes 就表示apparmor内核部分配置成功

安装audit审计程序

在arch系中,apparmor很多工具依赖于audit审计程序,使用 pacman -Syu audit 来安装此软件包。

然后,可选设置内核参数 audit=1 来在开机时启用审计框架。如果没有此内核参数,则可能导致在审计守护进程前运行的进程无法被正常审计4

规则配置

通过概要分析工具为chromium创建规则

创建一个新的规则是一个比较麻烦的事情,但是幸运的是,apparmor提供了 aa-genprof aa-logprof 等工具能够方便的从审计日志中,生成配置文件的工具。

执行 sudo aa-genprof /usr/bin/chromium ,启动对chromium的审计。此时,该工具会创建一个新的配置文件(如果没有创建过的话)5,并将该配置文件设置为 抱怨模式 (不阻止访问,但是会在日志中记录),

嗯……如果配置了消息提醒的话,此时大概就能看到大量违规消息刷屏了(嗯……直接刷了一千多……)。

然后,启动chromium,然后正常使用,尽可能多的使用这个软件的功能,以便获知这个软件要正常工作需要获得哪些权限。apparmor默认以白名单模式对程序的权限进行限制,也就是,如果没有在配置文件中赋予权限,那么,apparmor将会默认拒绝此权限访问。

在另外一个终端执行 sudo aa-logprof 开始自动化配置规则文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ sudo aa-logprof
Updating AppArmor profiles in /etc/apparmor.d.
Reading log entries from /var/log/audit/audit.log.
Complain-mode changes:

Profile:  /usr/bin/chromium
Path:     /home/tntwiki/.cache/chromium/Default/Cache/todelete_f953df125a331817_0_2
New Mode: owner w
Severity: 6

 [1 - include <abstractions/lxc/container-base>]
  2 - include <abstractions/lxc/start-container> 
  3 - owner /home/*/.cache/chromium/Default/Cache/todelete_f953df125a331817_0_2 w, 
  4 - owner /home/tntwiki/.cache/chromium/Default/Cache/todelete_f953df125a331817_0_2 w, 
(A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish

这里提供了4个选项,分别为,载入其他配置文件(1,2) include abstractions/lxc/container-base|start-container ,而3-4则是在用户是文件所有者的情况下,赋予该程序匹配对应字符串的路径的访问权限。按对应的数字选项规则。此处选择3(输入3)

而下面一行则是对此规则允许的操作,其具体含义如下

  • (A)llow 允许此规则
  • (D)eny 将此规则标记为拒绝,如果应用拒绝规则,匹配路径的访问会被无条件拒绝。
  • (I)gnore 忽略此条
  • (G)lob 将路径末尾改为通配符号以匹配此目录下所有文件,如果路径末尾为/*则改为**以允许递归匹配目录访问
  • Glob with (E)xtension 类似于G,但是保留文件后戳名
  • (N)ew 编辑规则当前,如果结果不匹配路径则会提示
  • Audi(t) 将此条目标记为审计,标记为审计的不会拒绝访问,但是被访问时将会在日志时记录此访问。
  • (O)wner permissions off 关闭所有者模式(owner),改为无条件允许访问。
  • Abo(r)t 中止
  • (F)inish 结束(无提示退出)

首先,此处先输入3下g,将路径改为类似于 /home/*/.config/chromium/** 这样的格式(毕竟~/.config/chromium明显是chromium的配置文件路径嘛,肯定不能不给权限的),然后按a允许此规则进入下一条。

当aa-logprof当前所获取的所有违规记录都分配完成后(允许/阻止/忽略),其将会会提示是否保存,类似于下栏所示

1
2
3
4
5
6
7
= Changed Local Profiles =

The following local profiles were changed. Would you like to save them?

 [1 - /usr/bin/chromium]
(S)ave Changes / Save Selec(t)ed Profile / [(V)iew Changes] / View Changes b/w (C)lean profiles / Abo(r)t
Writing updated profile for /usr/bin/chromium.

这时可以输入s保存配置内容。6

不过,由于使用aa-logprof时,受审计的软件可能并不一定真的申请了所有功能所必须的权限7,所以可能需要重复多次进行此步骤,和需要尽可能多和尽可能长的使用软件,以完善配置文件。

当规则文件基本完成后,回到aa-genprof的终端,输入F退出。按F退出后,配置的规则将会被以强制模式重新载入,在决定完成之前,好好完善规则吧。

手动对配置文件进行调整,添加一些额外的限制,以及配置文件格式简述

当然,通过概要分析所生成的配置可能并不全面或太过宽松,它只会对监控到的触犯规则的部分提醒配置,而可能会想对一些东西进行额外限制,并且也不会使用预设的别名等以简化配置。

此处以之前所配置的chromium配置文件为例,记录一下配置文件的格式并手动修改一些规则内容。

注意,该chromium配置存在删节和定制化配置,直接复制不加修改可能导致chromium无法正常启动或使用功能,以及遇到预料外的权限问题。

/etc/apparmor.d/usr.bin.chromium :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
abi <abi/3.0>,
#配置文件版本,告诉apparmor应该以何种配置文件语法解析文件,不同版本的语法有微妙的不同

include <tunables/global>
#载入外部规则配置tunables/global,路径位于/etc/apparmor.d/tunables/global

/usr/bin/chromium {   #此块为/usr/bin/chromium程序设置权限限制
#载入外部配置列表
  include <abstractions/apache2-common> 
  include <abstractions/audio>
  include <abstractions/base>
  include <abstractions/bash>
  include <abstractions/consoles>
  include <abstractions/fonts>
  include <abstractions/ubuntu-browsers.d/plugins-common>
  include <abstractions/user-tmp>
#不太清楚……但是chromium要用到这个权限
  capability sys_admin,
  capability sys_ptrace,
#同上
  ptrace read peer=/usr/bin/chromium//null-/usr/bin/xdg-settings,
  ptrace read peer=/usr/bin/chromium//null-/usr/lib/chromium/chromium,
#此部分阻止chromium访问不想访问的文件
  deny owner /home/*/*.xls r,
  deny owner /home/*/.* r,
  deny owner /home/*/.*/** r,
  deny owner /home/*/private/* r,
#此部分监控并阻止chromium访问不想访问的文件,如果程序触犯此规则,阻止的同时也会在日志中记录
  audit deny owner @{HOME}/.gnupg r,
  audit deny owner @{HOME}/.ssh r,
#此部分特许chromium访问文件
  /etc/hosts r,
  /etc/ld.so.cache r,
  /etc/machine-id r,
  /proc/ r,
  /proc/** r,
  /run/dbus/system_bus_socket rw,
  /sys/** r,
  /usr/bin/basename mrix,
  /usr/bin/bash ix,
  /usr/bin/chromium mr,
  /usr/bin/cut mrix,
  /usr/bin/dbus-send mrix,
  /usr/bin/readlink mrix,
  /usr/bin/uname mrix,
  /usr/bin/which mrix,
  /usr/bin/xdg-settings mrix,
  /usr/bin/xprop mrix,
  /usr/lib/chromium/chromium mrix,
  /usr/share/glib-2.0/** r,
  /usr/share/icons/ r,
  /usr/share/icons/** r,
  /usr/share/mime/* r,
  /usr/share/pixmaps/ r,
#此部分特许chromium访问文件——如果执行chromium的用户是这个文件的所有者的话
  owner /dev/** rw,
  owner /home/*/ r,
  owner /home/*/.Xauthority r,
  owner /home/*/.cache/** r,
  owner /home/*/.cache/chromium/** rw,
  owner /home/*/.cache/mesa_shader_cache/** wk,
  owner /home/*/.config/chromium/** k,
  owner /home/*/.config/chromium/** rw,
  owner /home/*/.config/gtk-3.0/bookmarks r,
  owner /home/*/.config/user-dirs.dirs r,
  owner /home/*/.cups/* r,
  owner /home/*/.icons/ r,
  owner /home/*/.local/share/ r,
  owner /home/*/.local/share/applications/ r,
  owner /home/*/.local/share/applications/* r,
  owner /home/*/.local/share/applications/wine/ r,
  owner /home/*/.local/share/icons/ r,
  owner /home/*/.local/share/icons/**/ r,
  owner /home/*/.local/share/mime/* r,
  owner /home/*/.local/share/recently-used.xbel rw,
  owner /home/*/.local/share/recently-used.xbel.* rw,
  owner /home/*/download/ r,
  owner /home/*/documents/ r,
  owner /home/tntwiki/.config/dconf/user r,
  owner /proc/** rw,
  owner @{HOME} r,
  owner @{HOME}/download/** rw,
  owner @{HOME}/documents rw,
  owner @{HOME}/documents/** rw,
}

一个apparmor规则文件,如上面的代码块所述,一般具有以下内容

abi

告诉apparmor应该以何种规则语法版本解析配置文件,有v2和v3两种版本,这两种版本有微妙不同。

生成的配置文件会默认填写此值,如无特别必要无需修改。

1
abi <abi/3.0>,

include

导入一个外部配置文件,也可以记为 #include (#和include中间不能有空格等其他符号,否则会解释为注释)

1
include <tunables/global>

这个也能在下面的规则块中使用。

规则块

规则块会匹配块开头的命令,并会对符合条件的命令文件使用该块内所设置的限制,默认情况是白名单(在块内明确许可的资源请求才会放行)

可以对块开头的命令使用模式匹配语法匹配多个文件。

  • apparmor模式匹配

    apparmor支持使用模式匹配语法来匹配多个文件,其支持如下语法

    • “*” 匹配任意字符,不包括"/"。比如 /home/*/test 能匹配路径 /home/user/test ,但是,不能匹配 /home/user/log/test 这个路径。即,不能递归匹配目录,只能匹配当前目录
    • “**” 匹配包括"/“的任意字符, 比如 /home/**/test 现在能匹配 /home/user/log/test 了。
    • “?” 匹配不是”/“的单个字符。
    • “{}” 交替,匹配大括号内使用逗号”,“分割的备选字符列表。如 /bin/{bash,zsh,fish} 能够同时匹配 /bin/bash,/bin/zsh,/bin/fish这三个文件。
    • “{*^}” 交替排除,类似于*,匹配当前目录下所有文件,但是排除符合大括号内的字符列表的文件,比如 /etc/{*^shadow} ,匹配/etc下的所有文件,但是不包括 /etc/shadow 。
    • “{**^}” 类似于**的交替排除,能够递归匹配子目录,但排除大括号内的字符列表。

    未完全列举,如需要完整语法可访问apparmor规则文件介绍(en)8

  • 文件访问权限

    apparmor支持3种文件操作权限关键字,其分别为 audit,deny,owner

    关键字 匹配后的操作类型
    不设置权限关键字的情况下,表示无条件特许文件操作
    owner 仅在执行程序的用户是文件所有者的情况下,许可文件操作
    audit 不阻止文件操作,但是会记录该程序对此文件的操作记录
    deny 无提示阻止文件操作,可与audit连用以审计操作记录

    同时,apparmor支持对多种文件操作类型进行管理,其简表如下

    关键字 权限
    r 读取文件内容,或文件夹内文件列表
    w 创建/删除/修改文件的权限
    l 链接到文件的权限
    k 锁定文件的权限
    m 内存映射可执行文件的权限(没看懂……?)
    x 执行程序的权限

    关于设置文件访问权限的例子

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    /{usr/bin,bin}/bash rx,
    #赋予读取和执行bash命令的权限
    
    owner /home/*/download/** rw,
    owner @{HOME}/download/** rw,
    #赋予对下载文件夹的访问权限,允许读取和保存文件在此文件夹,但是仅在执行程序的用户是文件所有者的情况下允许此操作,可以使用@{HOME}代替表示家目录
    
    audit @{HOME}/download w,
    #监控此程序对~/download文件夹的写操作,由于上面已赋予对此文件夹的写操作,因此apparmor不会阻止此写入操作
    
    audit deny @{HOME}/.gnupg rw,
    #明确阻止对~/.gnupg的读写操作,并记录程序对此文件夹的访问记录
    
    deny @{HOME}/.ssh rw,
    #明确阻止对~/.ssh的访问,但不记录程序对此文件夹的访问记录
    

其他

为apparmor配置提醒

有时候,每天去翻apparmor的违规记录可能有些麻烦,所以,如果可以的话,最好能够在有程序违反规则时发出消息提醒用户现在有程序违反预设的规则,这时可以设置消息提醒。

参考archwiki的介绍1,配置一下触犯规则的提醒

添加一个特定的用户组(这里是 audit ,也可以使用已有的用户组,比如说 wheel)

1
2
#添加audit用户组
sudo groupadd -r audit

并将该组添加至audit允许访问列表中,编辑 /etc/audit/auditd.conf9,将 log_group 的值改成刚刚添加的用户组 audit

1
log_group = audit

将当前使用的用户加入audit用户组,以允许当前用户(主要是apparmor提醒程序)访问audit审计日志,然后重启计算机。

1
sudo gpasswd -a tntwiki audit

然后,就可以直接访问审计日志了。

现在,执行 aa-notify -p -s 3 -w 3 -f /var/log/audit/audit.log 来启动apparmor的违规提醒吧。

嗯,apparmor的消息提醒有一些非默认安装的可选依赖,如 python-notify2 。如果无法正常执行,执行 pacman -Sy --asdeps python-notify2 以手动安装依赖。

文末,碎碎念

嗯,完成了呢……?一篇关于apparmor的文章。不过,本来想用apparmor限制其他程序对一个想保密的一个文件夹访问的,但是……这个虽然对启用配置的程序默认是白名单方式授权,但是,对于系统执行程序却是黑名单……没有配置相关配置文件的程序,apparmor根本不管呢……?如果要弄全局限制的话,很麻烦……,需要apparmor第一个启动什么的10……而且各种替代方法也很难弄11……

所以,本来打算限制绝大多数程序访问某个特定的文件夹……做不到呢……?所以只能拿来限制一些重点程序的权限了……? 比如说chromium?

嗯……由于apparmor配置问题……chromium炸了……相关配置已用 aa-disable 命令禁用……

就这样,写了好几天,姑且,这篇新博客,是完成了呢……?就这样结束吧,嗯。

脚注