当前位置: 首页 > 工具软件 > apparmor > 使用案例 >

AppArmor测试中aa-genprof提示错误的问题及解决(1)

洪德寿
2023-12-01

零、背景

本系列之前文章讲述了AppArmor的源码下载、安装及使用,其功能基本正常(没有日志功能的问题待查)。但是前提是完全按照默认选项安装AppArmor,尤其是将Python3.10放在了/usr/lib/下。如果是安装在/usr/local/lib/下,则在使用中则会出现一些问题。本文就来描述笔者实际遇到的问题,以及分析排查过程和最终解决方法。

一、问题现象

安装好apparmor之后,在使用aa-genprof命令时出现以下错误:

$ aa-genprof 
Traceback (most recent call last):
  File "/usr/local/sbin/aa-genprof", line 23, in <module>
    import apparmor.aa as apparmor
ModuleNotFoundError: No module named 'apparmor'

提示aa-genprof脚本中的一句代码import apparmor.aa as apparmor出现错误,给出的提示是没有apparmor这个模块。

二、问题分析

到底有没有这个模块呢?看一下/usr/local/lib/下的内容:

$ ls -d /usr/local/lib/python3.10/site-packages
/usr/local/lib/python3.10/site-packages

模块在啊!为什么还提示没有呢?看一下sys.path里边有没有。在终端下运行python,在其中执行以下命令,命令及结果如下:

$ python
Python 3.10.5 (main, Apr 11 2023, 17:46:50) [GCC 12.1.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print(sys.path)
['', '/usr/local/lib/python310.zip', '/usr/local/lib/python3.10', '/usr/local/lib/python3.10/lib-dynload', '/usr/local/lib/python3.10/site-packages', '/usr/local/lib/python3.10/site-packages/pycairo-1.23.0-py3.10-linux-x86_64.egg', '/usr/local/lib/python3.10/site-packages/PyGObject-3.42.2-py3.10-linux-x86_64.egg', '/usr/local/lib/python3.10/site-packages/requests-2.28.1-py3.10.egg', '/usr/local/lib/python3.10/site-packages/certifi-2022.12.7-py3.10.egg', '/usr/local/lib/python3.10/site-packages/urllib3-1.26.14-py3.10.egg', '/usr/local/lib/python3.10/site-packages/idna-3.4-py3.10.egg', '/usr/local/lib/python3.10/site-packages/charset_normalizer-2.1.1-py3.10.egg', '/usr/local/lib/python3.10/site-packages/docutils-0.18.1-py3.10.egg', '/usr/local/lib/python3.10/site-packages/libvirt_python-9.0.0-py3.10-linux-x86_64.egg']
>>> 

可以看到,/usr/local/lib/python3.10/site-packages赫然在列!那为什么还提示找不到?这不是耍无赖嘛!

别急,到aa-genprof脚本中再次通过打印看一下sys.path里边有没有/usr/local/lib/python3.10/site-packages这个路径。在/usr/local/sbin/aa-genprof文件中添加打印语句,如下所示:

$ sudo vim /usr/local/sbin/aa-genprof
import argparse
import atexit
import os
import re
import subprocess
import sys
import time
print(sys.path) #在此处加打印
import apparmor.aa as apparmor
import apparmor.ui as aaui
from apparmor.common import AppArmorException, warn
from apparmor.fail import enable_aa_exception_handler
from apparmor.translations import init_translation

再次执行aa-genprof,结果如下:

$ aa-genprof 
['/usr/local/sbin', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/usr/lib/python3.10/site-packages', '/usr/lib/python3.10/site-packages/Mako-1.1.6-py3.10.egg', '/usr/lib/python3.10/site-packages/pycairo-1.20.1-py3.10-linux-x86_64.egg']
Traceback (most recent call last):
  File "/usr/local/sbin/aa-genprof", line 23, in <module>
    import apparmor.aa as apparmor
ModuleNotFoundError: No module named 'apparmor'

这次的sys.path中就没有/usr/local/lib/python3.10/site-packages的踪影了。所以并非是人家耍无赖,确实没有指明这个路径。

三、解决方法

这里不去深究为什么aa-genprof的运行环境下与直接运行python时的sys.path不同,而是基于这个环境寻找解决的方法。

这里要先进行一下知识补强,看一下Python的包导入机制以及PATHONPATH和sys.path等相关概念和作用。


  • Python包导入机制

参考博客:

python之如何修改包导入时的搜索路径_修改python导包路径_一秋闲谈的博客-CSDN博客

1. 包导入搜索机制

Python的import操作,其本质类似于我们日常在电脑上搜索指定文件名的文件。只不过,Python一般不会像我们那样,在本地磁盘全盘进行搜索,而是有其自己的控制机制,可以控制搜索的范围和顺序,这样可以保证效率,同时也可以做到一定程度的隔离。比如Python创建虚拟的运行环境就是基于这个原理,不同虚拟运行环境,Python安装路径、import搜索路径都是单独隔离的,而常用的虚拟环境维护和创建工具,其核心也是通过修改Python默认安装路径、版本、包搜索路径等信息达到目的。

一般情况下,import时,包搜索顺序和范围如下:

1)首先搜索运行命令当前文件夹,或者系统当前工作文件夹(可通过命令修改cwd);

2)其次搜索环境变量PYTHONPATH内的文件路径;

3)最后搜索Python安装路径内的sitepackages文件夹(一般通过pip安装的包,均会默认放到这个文件夹下,当然,也可简单的将自己的包放到这个文件夹下,这样也无需改变搜索路径)。

2. 修改搜索路径

核心思路,修改1中提到的三个搜索节点的值,即可改变包导入时的搜索范围。

(1)通过修改sys.path变量

sys.path变量,管理的是Python包搜索路径内所有文件夹路径(即当前文件夹、PYTHONPATH环境变量内的路径、python默认安装路径),该变量是个列表,可以通过sys.path.append或者sys.path.insert等方法,将自己希望导入时被搜索的路径添加到该列表变量内即可。

注意:该方法只会在运行时生效,一旦退出,便失效。

(2)通过修改PYTHONPATH环境变量

PYTHONPATH环境变量,是管理Python包导入时的搜索路径的变量,故可以通过向该环境变量内添加路径的方式来修改搜索路径,且该方法因为是修改了环境变量,故也是永久的,且影响也是全局的。

针对运行Ubuntu系统(其它Linux的应该也适用)的电脑,修改该环境变量的方法如下:

1)打开~/.bashrc文件,如果没有,则通过touch命令创建;

2)在文件内写上 export PYTHONPATH=<your own dir>:$PYTHONPATH。比如你希望将~/test路径添加至该环境变量,则export PYTHONPATH=~/test :$PYTHONPATH;

3)在命令行执行 source ~/.bashrc(主要是让系统重新加载运行该文件,以使此次修改生效)。

(3)通过添加**.pth文件

以上两个办法,要么是临时修改,要么是全局修改影响面太大,而第三种方式可谓兼具前两种方法的特点。

可以在指定Python安装目录下的site-packages目录文件夹内添加一个**.pth文件,在该文件内逐行添加自己希望被搜索的路径即可。

  • PATH、PYTHONPATH 和 sys.path 的区别

参考博客:

python的path是什么意思_python:PATH、PYTHONPATH 和 sys.path 的区别_weixin_39685697的博客-CSDN博客

共同点

所有在它们路径里面的module都可以被import。

1. PATH

在PATH中的一些命令,例如 *.exe,可以直接被运行,而不用明确的路径,我们在给Python安装一些packages的时候,有一些Scripts被安装到/Scripts文件夹中,如果/Scripts文件夹路径不在 PATH 中,会有提示。

2. PYTHONPATH

如果我们使用PYTHONPATH中的modules,那么在运行python前,就要把path加到 os.environ['PYTHONPATH'],在运行python后再加,那些模块不能直接被导入。

3. sys.path

sys.path初始化的时候有两部分:os.environ['PYTHONPATH']、默认的安装依赖的一些路径(例如python安装的根目录和pythonxx.zip)。与PYTHONPATH不同,sys.path可以在 Python运行后添加我们的module path,然后直接import。

可以通过os.environ['PYTHONPATH']来传递我们的module path;也可以给python添加自定义的module path,让python在运行的时候自动加到sys.path中,方法是在/Lib/site-packages/中添加*.pth文件,在文件里面加上module path。


在此我们选择第二种方法,即设置PYTHONPATH进行搜索路径的修改(添加)。在终端下执行以下命令:

$ export PYTHONPATH=/usr/local/lib/python3.10/site-packages
$ echo $PYTHONPATH
/usr/local/lib/python3.10/site-packages

添加环境变量PYTHONPATH后,再次执行aa-genprof命令,结果如下:

$ aa-genprof 
['/usr/local/sbin', '/usr/local/lib/python3.10/site-packages', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/usr/lib/python3.10/site-packages', '/usr/lib/python3.10/site-packages/Mako-1.1.6-py3.10.egg', '/usr/lib/python3.10/site-packages/pycairo-1.20.1-py3.10-linux-x86_64.egg']
usage: aa-genprof [-h] [-d DIR] [-f FILE] [-j] program
aa-genprof: error: the following arguments are required: program

可以看到,sys.path中已经有了/usr/local/lib/python3.10/site-packages,之前的“ModuleNotFoundError: No module named 'apparmor'”错误解决了。

但是又出现了新的错误:aa-genprof: error: the following arguments are required: program。

其实这并不能算是错误,而是调用aa-genprof时没有传递参数,因此打印出的用法提示。与之前(详见本系列之前文章)一样,传入参数test_app,即调用aa-genprof命令为test_app添加访问控制规则。命令及结果如下所示:

$ aa-genprof test_app
Updating AppArmor profiles in /usr/local/etc/apparmor.d.

WARNING: Error reading file /usr/local/etc/apparmor.d/home.penghao.AppArmor.sample_code.test_app, skipping.
    [Errno 13] Permission denied: '/usr/local/etc/apparmor.d/home.penghao.AppArmor.sample_code.test_app'
Traceback (most recent call last):
  File "/usr/local/sbin/aa-genprof", line 117, in <module>
    apparmor.helpers[program] = apparmor.get_profile_flags(profile_filename, program)
  File "/usr/local/lib/python3.10/site-packages/apparmor/aa.py", line 616, in get_profile_flags
    with open_file_read(filename) as f_in:
  File "/usr/local/lib/python3.10/site-packages/apparmor/common.py", line 188, in open_file_read
    return open_file_anymode('r', path, encoding)
  File "/usr/local/lib/python3.10/site-packages/apparmor/common.py", line 202, in open_file_anymode
    return open(path, mode, encoding=encoding, errors='surrogateescape')
PermissionError: [Errno 13] Permission denied: '/usr/local/etc/apparmor.d/home.penghao.AppArmor.sample_code.test_app'


An unexpected error occurred!

For details, see /tmp/apparmor-bugreport-k1h4p8aa.txt
Please consider reporting a bug at https://gitlab.com/apparmor/apparmor/-/issues
and attach this file.

还是有错误。这次的错误与权限有关了。具体怎样解决?请参见下一篇文章。

 类似资料: