[步骤] Linux page_owner 排查工具的使用 (记录内存的使用情况)

正文:

步骤一:查看 page_owner 是否开启

1.1 通过 dmesg 命令查看 page_owner 是否开启

# dmesg | grep page_owner
[    1.149165] page_owner is disabled

(补充:当显示此类信息时则 page_owner 没有开启)

1.2 通过 /sys/kernel/debug/ 目录查看 page_ownerr 是否开启

# ls -l /sys/kernel/debug/page_owner
ls: cannot access /sys/kernel/debug/page_owner: No such file or directory.

(补充:当 /sys/kernel/debug/page_owner 文件不存在时则 page_owner 没有开启)

步骤二:开启 page_owner

2.1 开启 page_owner

# grubby --args="page_owner=on" --update-kernel=0

(注意:开启 page_owner 会额外占用一定量的内存)

2.2 重启系统

# reboot

2.3 确认 page_owner 已经开启

2.3.1 通过 dmesg 命令确认 page_owner 是否开启
# dmesg | grep page_owner
[    0.000000] Command line: BOOT_IMAGE=(hd0,gpt2)/vmlinuz-4.18.0-425.19.2.el8_7.x86_64 root=/dev/mapper/rootvg-rootlv ro ipv6.disable=1 audit=1 audit_backlog_limit=8192 crashkernel=auto resume=/dev/mapper/rootvg-swaplv rd.lvm.lv=rootvg/rootlv rd.lvm.lv=rootvg/swaplv rhgb quiet rd.shell=0 page_owner=on
[    0.000000] Kernel command line: BOOT_IMAGE=(hd0,gpt2)/vmlinuz-4.18.0-425.19.2.el8_7.x86_64 root=/dev/mapper/rootvg-rootlv ro ipv6.disable=1 audit=1 audit_backlog_limit=8192 crashkernel=auto resume=/dev/mapper/rootvg-swaplv rd.lvm.lv=rootvg/rootlv rd.lvm.lv=rootvg/swaplv rhgb quiet rd.shell=0 page_owner=o

(补充:当显示此类信息时则 page_owner 已经开启)

2.3.2 通过 /sys/kernel/debug/ 目录确认 page_ownerr 是否开启
# ls -l /sys/kernel/debug/page_owner
-r--------. 1 root root 0 Apr 13 14:36 /sys/kernel/debug/page_owner

(补充:当 /sys/kernel/debug/page_owner 文件存在时则 page_owner 已经开启)

步骤三:分析 page_owner 产生的记录

3.1 导出 page_owner 产生的记录

# cat /sys/kernel/debug/page_owner > page_owner_full.txt

(补充:这里以将 page_owner 产生的记录导出到名为 page_owner_full.txt 文件为例)


注意:
1) 此命令会产生体积很巨大的文件
2) 此命令会持续执行直到手动取消
3) 可以通过同时按下 “ctrl” 键和 “C” 键或者使用 kill 命令取消
4) 如果内存变化较快则可以让此命令多执行一会,反之则可以少执行一会

3.2 解析 page_owner 产生的记录

# page_owner_sort page_owner_full.txt sorted_page_owner.txt
loaded 42903
sorting ....
culling

(补充:这里以分析名为 page_owner_full.txt 的文件并将分析结果导入到 sorted_page_owner.txt 文件为例)

3.3 查看 page_owner 产生的记录

# less sorted_page_owner.txt
1 times:
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 48952109 ns, free_ts 0 ns
PFN 4096 type Unmovable Block 8 type Unmovable Flags 0xfffffc0000100(slab|node=0|zone=1|lastcpupid=0x1fffff)
 register_early_stack+0x28/0x60
 init_page_owner+0x30/0x2d0
 kernel_init_freeable+0x13c/0x232
 kernel_init+0xa/0x108

1 times:
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 48952566 ns, free_ts 0 ns
PFN 4097 type Unmovable Block 8 type Unmovable Flags 0xfffffc0000100(slab|node=0|zone=1|lastcpupid=0x1fffff)
 register_early_stack+0x28/0x60
 init_page_owner+0x30/0x2d0
 kernel_init_freeable+0x13c/0x232
 kernel_init+0xa/0x108
......

(补充:这里以查看名为 sorted_page_owner.txt 文件里的分析结果为例)

步骤四:关闭 page_owner

4.1 开启 page_owner

# grubby --remove-args="page_owner=on" --update-kernel=0

(注意:关闭 page_owner 会额外释放一定量的内存)

4.2 重启系统

# reboot

4.3 确认 page_owner 已关闭

4.3.1 通过 dmesg 命令确认 page_owner 是否关闭
# dmesg | grep page_owner
[    2.022585] page_owner is disabled

(补充:当显示此类信息时则 page_owner 没有开启)

4.3.2 通过 /sys/kernel/debug/ 目录确认 page_ownerr 是否关闭
# ls -l /sys/kernel/debug/page_owner
ls: cannot access '/sys/kernel/debug/page_owner': No such file or directory

(补充:当 /sys/kernel/debug/page_owner 文件不存在时则 page_owner 没有开启)

参考文献:

https://access.redhat.com/solutions/5609521

[内容] auditd 使用 (监控文件或目录的变化)

内容一:auditd 的管理

1.1 启动 auditd

1.1.1 启动 auditd
# service auditd restart
1.1.2 查看 auditd 状态
# auditctl -s
1.1.3 设置 auditd 开机自启
# chkconfig auditd on
1.1.4 查看 auditd 开机自启状态
# chkconfig --list auditd

1.2 查看 auditd 的规则

# auditctl -l

1.3 删除 auditd 的规则

1.3.1 永久删除 auditd 的所有规则
1.3.1.1 清空 /etc/audit/audit.rules 文件里的所有内容
# vi /etc/audit/audit.rules

删除里面的所有内容

1.3.1.2 让刚刚的设置生效
# service auditd restart

或者:

# augenrules
1.3.2 临时删除 auditd 的规则
1.3.2.1 临时删除 auditd 的所有规则
# auditctl -D

(补充:此操作重启后失效)

1.3.2.2 临时删除 auditd 的普通规则 (以 -w 开头的规则)
# auditctl -W <policy>

(补充:此操作重启后失效)

1.3.2.3 临时删除 auditd 的使用系统调用和过滤条件的监控规则 (以 -a 开头的规则)
# auditctl -d <policy>

(补充:此操作重启后失效)

1.4 显示 auditd 日志

1.4.1 显示 auditd 的所有日志
# cat /var/log/audit/audit.log
1.4.2 显示某文件或目录的日志
# ausearch -f <file/directory>
1.4.3 显示某关键词的日志
# ausearch -k <key_name>

1.5 生成 auditd 日志报告

# aureport -k

内容二:auditd 的规则

2.1 普通监控规则

2.1.1 普通监控规则的格式
2.1.1.1 普通监控规则的格式
-w <file/directory> -p <previlege> -k <key_name>


补充:
1) 文件名或目录名,需要绝对路径
2) 监控的权限,可以是 rwxa 其中的任意 1 个或多个,r 代表读权限、w 代表写权限,x 代表执行权限,a 代表文件类型
3) 此类日志的关键词

2.1.1.2 添加普通监控规则的格式
2.1.1.2.1 临时添加普通监控规则的格式
# auditctl -w <file/directory> -p <previlege> -k <key_name>
2.1.1.2.2 永久添加普通监控规则的格式
# vim /etc/audit/audit.rules

添加以下内容:

......
-w <file/directory> -p <previlege> -k <key_name>


注意:永久添加的规则后要重启 auditd 服务后才会生效

# service auditd restart

或者:

# augenrules

2.1.2 添加普通监控规则的案例
2.1.2.1 案例一:添加监控 /etc/nginx/nginx.conf 文件的读、写、执行和文件属性变化的规则
# auditctl -w /etc/nginx/nginx.conf

(补充:这里以临时添加监控 /etc/nginx/nginx.conf 文件的读、写、执行和文件属性变化的规则为例)

2.1.2.2 案例二:添加监控 /etc/nginx/nginx.conf 文件的读、写、执行和文件属性变化,并设置关键词为 nginx 的规则
# auditctl -w /etc/nginx/nginx.conf -p rwxa -k 'nginx'

(补充:这里以临时添加监控 /etc/nginx/nginx.conf 文件的读、写、执行和文件属性变化,并设置关键词为 nginx 的规则为例)

2.2 使用系统调用和过滤条件的监控规则

2.2.1 使用系统调用和过滤条件的监控规则的格式
2.2.1.1 使用系统调用和过滤条件的监控规则的格式
-a <action>,<filter> -S <system_call> -F <field>=<value> -k <key_name>


补充:
1) 和 用于确定事件被记录, 的值可以是 always 或者 never, 的值可以是 task、exit、user 或者 exclude
2) 是系统调用,Linux 系统调用的名称在 /usr/include/asm/unistd_64.h 文件中,可以将多个系统调用放在一个规则里,例:-S <system_call> -S <system_call> ……,或者 -S <system_call>,<system_call>……
3) 和 是过略条件,可以将多个过略条件放在一个规则里,-F <field>=<value> -F <field>=<value> ……
4) 是此类日志的关键词

2.2.1.2 添加使用系统调用和过滤条件的监控规则的格式
2.2.1.2.1 临时添加使用系统调用和过滤条件的监控规则的格式
# auditctl -a <action>,<filter> -S <system_call> -F <field>=<value> -k <key_name>
2.2.1.2.2 永久添加使用系统调用和过滤条件的监控规则的格式
# vim /etc/audit/audit.rules

添加以下内容:

......
-a <action>,<filter> -S <system_call> -F <field>=<value> -k <key_name>


注意:永久添加的规则后要重启 auditd 服务后才会生效

# service auditd restart

或者:

# augenrules

2.2.2 使用系统调用和过滤条件的监控规则的案例
2.2.2.1 案例一:监控所有 UID 大于 1000 的用户的删除操作,并设置关键词为 delete
# auditctl -a always,exit -S rmdir -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=unset -F auid!=4294967295 -k delete

(补充:这里以临时监控所有 UID 大于 1000 的用户删除操作为例)

(注意:这里的 -F auid!=4294967295 是为了排除 login UID 没有被设置的用户)

2.2.2.2 案例二:监控所有 UID 大于 1000 的用户的文件删除操作,并设置关键词为 delete
# auditctl -a always,exit -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=unset -F auid!=4294967295 -k delete

(补充:这里以临时监控所有 UID 大于 1000 的用户删除操作为例)

(注意:这里的 -F auid!=4294967295 是为了排除 login UID 没有被设置的用户)

2.2.2.3 案例三:监控所有网络连接
# auditctl -a always,exit -F arch=b64 -S socket
# auditctl -a always,exit -F arch=b64 -S connect
# auditctl -a always,exit -F arch=b64 -S sendmmsg
# auditctl -a always,exit -F arch=b64 -S sendmsg
# auditctl -a always,exit -F arch=b64 -S bind
# auditctl -a always,exit -F arch=b64 -S recvmsg
# auditctl -a always,exit -F arch=b64 -S close

(补充:这里以监控所有网络连接为例)

[内容] audit 常用的监控规则

内容一:监控 SELinux 配置文件

1.1 在 audit 添加监控 SELinux 配置文件的规则

# vim /etc/audit/rules.d/audit.rules

添加以下内容:

......
-w /etc/selinux/ -p wa -k MAC-policy
-w /usr/share/selinux/ -p wa -k MAC-policy

1.2 让添加的监控 SELinux 配置文件的规则生效

# service auditd restart

1.3 确认添加的监控 SELinux 配置文件的规则已生效

# auditctl -l | grep -i selinux

内容二:监控 AppArmor 配置文件

2.1 在 audit 添加监控 AppArmor 配置文件的规则

# vim /etc/audit/rules.d/audit.rules

添加以下内容:

......
-w /etc/apparmor/ -p wa -k MAC-policy
-w /etc/apparmor.d/ -p wa -k MAC-policy

2.2 让添加的监控 AppArmor 配置文件的规则生效

# service auditd restart

2.3 确认添加的监控 AppArmor 配置文件的规则已生效

# auditctl -l | grep -i apparmor

[步骤] auditd 的设置 (日志保存时间)

方法一:通过 auditd 配置文件设置

1.1 设置 auditd 日志的保存时间

# vim /etc/audit/auditd.conf

确保部分内容如下:

......
local_events = yes
......
write_logs = yes
......
log_file = /var/log/audit/audit.log
......
max_log_file = 8
......
num_logs =5
......
max_log_file_action = ROTATE
......


补充:这里以
1) 开启 auditd 日志 (local_events = yes) (write_logs = yes)
2) 将 auditd 日志写入 /var/log/audit/audit.log 文件 (log_file = /var/log/audit/audit.log)
3) auditd 日志每达到 8M 大小就将旧的 auditd 日志进行备份并创建新的 auditd 日志 (max_log_file = 8) (max_log_file_action = ROTATE),也可以修改成: max_log_file_action = keep_logs
4) 旧的 auditd 日志保存 5 份 (num_logs =5)
为例

1.2 让设置的 auditd 时间生效

# service auditd restart

方法二:通过 logrotate 配置文件设置

2.1 设置 auditd 日志的保存时间

# vim /etc/logrotate.d/auditd

创建以下内容:

/var/log/audit/*
{
rotate 30
daily
missingok
compress
delaycompress
postrotate
touch /var/log/audit/audit.log ||:
chmod 0600 /var/log/audit/audit.log ||:
service auditd restart
endscript
}


补充:这里以:
1) 备份的日志文件保留 30 份 (rotate 30)
2) 每天将现在的日志文件进行备份并生成新的日志文件 (dayly)

2.2 让设置的 auditd 时间生效

# systemctl restart logrotate.service

[步骤] auditd 日志时间转换成可读格式以后再显示

方法一:通过创建额外的脚本实现 adutitd 日志时间格式的转换

1.1 创建用于 auditd 转换日志时间格式的脚本

# vim time_format_conversion.pl

创建以下内容:

s/(1\d{9})/localtime($1)/e

(补充:这里以创建名为 time_format_conversion.pl 的用于转换 auditd 日志时间格式的脚本为例)

1.2 转换 auditd 日志时间格式

# cat /var/log/audit/audit.log | perl -p time_format_conversion.pl

或者:

# less /var/log/audit/audit.log | perl -p time_format_conversion.pl

或者:

# more /var/log/audit/audit.log | perl -p time_format_conversion.pl

或者:

# head /var/log/audit/audit.log | perl -p time_format_conversion.pl

或者:

# tail /var/log/audit/audit.log | perl -p time_format_conversion.pl

或者:

# tail -f /var/log/audit/audit.log | perl -p time_format_conversion.pl

(补充:这里以使用名为 time_format_conversion.pl 的用于转换 auditd 日志时间格式的脚本为例)

方法二:使用 /usr/sbin/ausearch 命令实现 adutitd 日志时间格式的转换

# /usr/sbin/ausearch --start $(date +\%m/\%d/\%Y -d "-1 month") -i --input-logs | egrep "/sftp*[0-9a-zA-Z].*txt.*nametype=" | grep -v Log.txt | awk '{print $2,$3,$6}' | uniq

(补充:这里以显示在 /sftp 目录下以 txt 结尾的文件的 auditd 日志为例)