【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
**开源地址:https://docs.qq.com/doc/DSmxTbFJ1cmN1R2dB **
通常有两种方法:
利用prctl(2)
的PR_GET_SECCOMP的参数获取当前进程的seccomp状态。
-
返回值0表示没有使用seccomp;
-
返回值2表示使用了seccomp并处于SECCOMP_MODE_FILTER模式;
-
其他情况进程会被SIGKILL信号杀死。
从Linux3.8开始,可以利用/proc/$pid/status中的Seccomp字段查看。如果没有seccomp字段,说明内核不支持seccomp。
- 举例:
查看mysql服务的seccomp的状态,发现并没有进入安全限制模式。
cat /proc/pidof mysqld
/status
输出
Name: mysqld
…
Seccomp: 0
Seccomp_filters: 0
在sandbox环境下执行 python3 脚本,
查看次进程的seccomp的状态,发现进程处于SECCOMP_MODE_FILTER模式 。
Name: python3
…
Seccomp: 2
Seccomp_filters: 1
- 代码示例
使用 syscall
调用 execve,如果没有安全限制的话,会正常进入 shell
#include<unistd.h>
#include<sys/syscall.h>
#include<seccomp.h>
int main() {
scmp_filter_ctx ctx; // scmp 过滤上下文
ctx = seccomp_init(SCMP_ACT_ALLOW); // 初始化过滤状态为允许所有系统调用
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0); // 添加需要限制的系统调用
seccomp_load(ctx); // 装载上下文
char *filename = “/bin/sh”;
char *argv[] = {“/bin/sh”, NULL};
char *envp[] = {NULL};
syscall(SYS_execve, filename, argv, envp); // execve
return 0;
}
编译
gcc -o ban ban.c -l seccomp
须先实现安装
sudo apt install libseccomp-dev libseccomp2 seccomp
运行程序
songyangji@SongyangJi-Ubuntu-DeskStop:~/桌面$ ./ban
错误的系统调用 (核心已转储) # Bad system call (core dumped)
SCMP_SYS
根据系统调用名获取系统调用号,虽然你可以直接使用 __NR_syscall
直接指定,但是为了跨平台最好使用它获取。
int SCMP_SYS(syscall_name);
scmp_filter_ctx
结构体定义
typedef void * scmp_filter_ctx;
seccmp的过滤器上下文,保存、传递了我们传入的系统调用过滤条件。
seccomp_init
- 函数说明:
seccomp_init的作用就是初始化 scmp_filter_ctx结构。
需要注意的是,任何其他libseccomp中的函数调用,必须在seccomp_init之后。
- 函数定义
scmp_filter_ctx seccomp_init(uint32_t def_action);
- 返回值
成功返回scmp_filter_ctx(过滤器上下文) ctx;
失败返回NULL
- 参数说明
def_action用于指定默认行为,有效动作值如下:(当线程调用了seccomp
过滤规则中没有相关配置规则的系统调用时触发)
- SCMP_ACT_KILL
线程将会被内核以SIGSYS信号终止;
- SCMP_ACT_KILL_PROCESS
整个进程被终止;
- SCMP_ACT_TRAP
线程将会抛出一个SIGSYS信号;
- SCMP_ACT_ERRNO(uint16_t errno)
线程调用与筛选规则匹配的系统调用时,它将收到一个errno的返回值;
- SCMP_ACT_TRACE(uint16_t msg_num)
略
- SCMP_ACT_LOG
不会对调用系统调用的线程产生任何影响,但系统调用会被记录到日志。
- SCMP_ACT_ALLOW
不会对调用系统调用的线程产生任何影响。
seccomp_rule_addXXX
函数说明:
这个函数组都会向当前seccomp过滤器添加新的过滤规则。
调用应用程序提供的所有过滤器规则被组合成一个联合,并带有额外的逻辑来消除冗余的系统调用过滤器。
例如,如果添加了一条规则,该规则允许给定的系统调用具有一组特定的参数值,
然后又添加了一条规则,该规则允许相同的系统调用而不管参数值如何,
那么第一个更具体的规则将有效地从过滤器中删除第二个更通用的规则。
函数定义
int seccomp_rule_add(scmp_filter_ctx ctx, uint32_t action,
int syscall, unsigned int arg_cnt, …);
int seccomp_rule_add_exact(scmp_filter_ctx ctx, uint32_t action,
int syscall, unsigned int arg_cnt, …);
int seccomp_rule_add_array(scmp_filter_ctx ctx,
uint32_t action, int syscall,
unsigned int arg_cnt,
const struct scmp_arg_cmp *arg_array);
int seccomp_rule_add_exact_array(scmp_filter_ctx ctx,
uint32_t action, int syscall,
unsigned int arg_cnt,
const struct scmp_arg_cmp *arg_array);
参数说明
-
- action有效动作值如下:(当线程调用了
seccomp
过滤规则中有相关配置规则的系统调用时触发)
- action有效动作值如下:(当线程调用了
-
SCMP_ACT_KILL
线程将会被内核终止;
- SCMP_ACT_KILL_PROCESS
整个进程被终止;
- SCMP_ACT_TRAP
线程将会抛出一个SIGSYS信号;
- SCMP_ACT_ERRNO(uint16_t errno)
线程调用与筛选规则匹配的系统调用时,它将收到一个errno的返回值;
- SCMP_ACT_TRACE(uint16_t msg_num)
略
- SCMP_ACT_LOG
会对调用系统调用的线程产生任何影响,但系统调用会被记录到日志。
- SCMP_ACT_ALLOW
不会对调用系统调用的线程产生任何影响(也就是允许调用这个system call)。
- SCMP_ACT_NOTIFY
略
-
- arg_cnt 指定规则配置的系统调用的参数的匹配情况的个数(因为后面是一个变长数组)
-
- 边长数组的元素是
scmp_arg_cmp
结构体,定义如下。
- 边长数组的元素是
系统调用的参数比较规则相关定义:
/**
- Comparison operators
*/
enum scmp_compare {
_SCMP_CMP_MIN = 0,
SCMP_CMP_NE = 1, /**< not equal */
SCMP_CMP_LT = 2, /**< less than */
SCMP_CMP_LE = 3, /**< less than or equal */
SCMP_CMP_EQ = 4, /**< equal */
SCMP_CMP_GE = 5, /**< greater than or equal */
SCMP_CMP_GT = 6, /**< greater than */
SCMP_CMP_MASKED_EQ = 7, /**< masked equality */
_SCMP_CMP_MAX,
};
/**
- Argument datum
*/
typedef uint64_t scmp_datum_t;
/**
- Argument / Value comparison definition
*/
struct scmp_arg_cmp {
unsigned int arg; /**< argument number, starting at 0 */
enum scmp_compare op; /**< the comparison op, e.g. SCMP_CMP_* */
scmp_datum_t datum_a;
scmp_datum_t datum_b;
};
有效比较操作值( op )如下:
- SCMP_CMP_NE
参数值不等于基准值时匹配,例如:
SCMP_CMP( arg , SCMP_CMP_NE , datum )
- SCMP_CMP_LT
参数值小于基准值时匹配,例如:
SCMP_CMP( arg , SCMP_CMP_LT , datum )
- SCMP_CMP_LE
参数值小于或等于基准值时匹配,例如:
SCMP_CMP( arg , SCMP_CMP_LE , datum )
- SCMP_CMP_EQ
参数值等于基准值时匹配,例如:
SCMP_CMP( arg , SCMP_CMP_EQ , datum )
- SCMP_CMP_GE