文件访问:一个程序打开失败,而另一个程序打开失败

Mei*_*Mei 5 mysql kernel apparmor

这是最不寻常的事情。我正在尝试使用不同的 my.cnf 启动 mysqld(因此我可以在没有冲突的情况下运行两个 MySQL 守护程序)。该文件是 /etc/mysql/my2.cnf 但 mysql 不会打开它。

当我运行此命令时:

sudo -u mysql strace /usr/sbin/mysqld --defaults-file=/etc/mysql/my2.cnf
Run Code Online (Sandbox Code Playgroud)

我在输出中看到这一点:

stat("/etc/mysql/my2.cnf", {st_mode=S_IFREG|0644, st_size=3574, ...}) = 0
open("/etc/mysql/my2.cnf", O_RDONLY)    = -1 EACCES (Permission denied)
Run Code Online (Sandbox Code Playgroud)

但是,当我将命令更改为:

sudo -u mysql strace cat /etc/mysql/my2.cnf > /dev/null
Run Code Online (Sandbox Code Playgroud)

我在输出中看到这一点:

fstat(1, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
open("/etc/mysql/my2.cnf", O_RDONLY)    = 3
Run Code Online (Sandbox Code Playgroud)

相同的用户 - 相同的内核调用 - 不同的结果!

我检查了文件权限 - 和扩展权限:

# ls -l $PWD/my2.cnf
-rw-r--r-- 1 root root 3574 2011-07-08 10:04 /etc/mysql/my2.cnf
# lsattr $PWD/my2.cnf
-----------------e- /etc/mysql/my2.cnf
Run Code Online (Sandbox Code Playgroud)

我是否被 AppArmour 或 SELinux 的某些部分所困扰?我在日志(包括 daemon.log、syslog 或消息)中没有看到类似的内容。

我该如何解决这个问题?

Mei*_*Mei 4

没有人回答,所以我会告诉你我发现了什么。

简而言之,问题如下:当/etc/mysql/my2.cnf访问该文件时cat,我们看到:

open("/etc/mysql/my2.cnf", O_RDONLY)    = 3
Run Code Online (Sandbox Code Playgroud)

然而,当mysqld进行相同的调用时,它会得到不同的答案:

open("/etc/mysql/my2.cnf", O_RDONLY)    = -1 EACCES (Permission denied)
Run Code Online (Sandbox Code Playgroud)

因此,答案就在内核中。cat内核中的某些东西正在区分 by和 by对 open(2) 的调用mysqld。我唯一想到的是 AppArmor。

搜索系统上的软件包发现了几个与 AppArmor 相关的软件包。列出包中的文件出现命令apparmor_status;运行这表明它mysqld确实包含在 AppArmor 中:

# apparmor_status
apparmor module is loaded.
6 profiles are loaded.
6 profiles are in enforce mode.
   /sbin/dhclient3
   /usr/lib/NetworkManager/nm-dhcp-client.action
   /usr/lib/connman/scripts/dhclient-script
   /usr/sbin/mysqld
   /usr/sbin/ntpd
   /usr/sbin/tcpdump
0 profiles are in complain mode.
3 processes have profiles defined.
3 processes are in enforce mode :
   /usr/sbin/mysqld (22699) 
   /usr/sbin/mysqld (6808) 
   /usr/sbin/ntpd (2800) 
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.
Run Code Online (Sandbox Code Playgroud)

阅读 apparmor(7) 的手册页显示配置文件存储在/etc/apparmor.d; 查看该目录会出现该文件usr.sbin.mysqld。原来这是要修改的文件。

修改文件很简单,复制原始标准目录和文件的条目并将它们放入新的目录和文件中。完成此操作后,使用service apparmor restart.

我从未在系统日志中看到任何有关“审核”的消息(来自 AppArmor)。其原因是消息发送到/var/log/audit/audit.log而不是syslogor messages。该文件包含如下条目:

type=APPARMOR_DENIED msg=audit(1310141055.025:256):  operation="mknod" pid=28765 parent=28764 profile="/usr/sbin/mysqld" requested_mask="c::" de
nied_mask="c::" fsuid=104 ouid=104 name="/var/log/mysql2/error.log"
type=APPARMOR_DENIED msg=audit(1310141055.025:257):  operation="open" pid=28765 parent=28764 profile="/usr/sbin/mysqld" requested_mask="r::" den
ied_mask="r::" fsuid=104 ouid=104 name="/var/lib/mysql2/mysql/plugin.frm"
type=APPARMOR_DENIED msg=audit(1310141055.035:258):  operation="open" pid=28765 parent=28764 profile="/usr/sbin/mysqld" requested_mask="rw::" de
nied_mask="rw::" fsuid=104 ouid=104 name="/var/lib/mysql2/ibdata1"
type=APPARMOR_DENIED msg=audit(1310141097.085:259):  operation="open" pid=28780 parent=28779 profile="/usr/sbin/mysqld" requested_mask="::r" den
ied_mask="::r" fsuid=104 ouid=0 name="/etc/mysql/my2.cnf"
type=APPARMOR_DENIED msg=audit(1310141177.636:260):  operation="open" pid=28841 parent=28840 profile="/usr/sbin/mysqld" requested_mask="::r" den
ied_mask="::r" fsuid=104 ouid=0 name="/etc/mysql/my2.cnf"
type=APPARMOR_DENIED msg=audit(1310141614.953:261):  operation="open" pid=28903 parent=28902 profile="/usr/sbin/mysqld" requested_mask="::r" denied_mask="::r" fsuid=104 ouid=0 name="/etc/mysql/my2.cnf"
type=APPARMOR_DENIED msg=audit(1310141665.113:262):  operation="open" pid=28916 parent=28915 profile="/usr/sbin/mysqld" requested_mask="::r" denied_mask="::r" fsuid=104 ouid=0 name="/etc/mysql/my2.cnf"
type=APPARMOR_DENIED msg=audit(1310141739.863:263):  operation="open" pid=28926 parent=28925 profile="/usr/sbin/mysqld" requested_mask="::r" denied_mask="::r" fsuid=104 ouid=0 name="/etc/mysql/my2.cnf"
type=APPARMOR_DENIED msg=audit(1310142253.323:264):  operation="open" pid=28962 parent=19377 profile="/usr/sbin/mysqld" requested_mask="::r" denied_mask="::r" fsuid=104 ouid=0 name="/etc/mysql/conf2.d/"
Run Code Online (Sandbox Code Playgroud)

这证明了我的推理和调查:AppArmor 拒绝了 open(2) 请求。

现在我知道要寻找什么了,我找到了与此相关的博客文章——一篇早在 2008 年就发表的文章。