正在 "Bad System Call" 使用 seccomp 过滤器
Getting "Bad System Call" working with seccomp filters
我刚刚开始学习 seccomp 过滤器,我正在使用 libseccomp v2.4.4。我尝试编写一个基本的白名单过滤器,它只允许写入名为 file1
的文件,但我在 STDOUT
中收到“错误的系统调用”消息。这是我的代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <seccomp.h>
#include <stdlib.h>
#include <errno.h>
int main(void)
{
FILE *fil = fopen("file1", "w");
scmp_filter_ctx filter = seccomp_init(SCMP_ACT_KILL);
if (filter==NULL || NULL==fil)
goto End1;
int chk1 = seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
SCMP_A0(SCMP_CMP_EQ, fileno(fil)));
int chk2 = seccomp_load(filter);
if (chk1<0 || chk2<0)
goto End;
fprintf(stdout,"Filter did not work correctly\n");
fprintf(fil,"Filter worked correctly\n");
End:
seccomp_release(filter); //releasing filter before closing file
fclose(fil);
End1:
return 0;
}
此外,我在 file1
中看不到任何输出。我只是一个初学者,不确定这里的很多事情,因为我是根据我的理解而不是参考来编写代码的。似乎是什么问题?
编辑:我完全删除了过滤器并简单地执行了
int main(void)
{
FILE *fil = fopen("file1", "w");
fprintf(stdout,"Filter did not work correctly\n");
fprintf(fil,"Filter worked correctly\n");
End:
fclose(fil);
End1:
return 0;
}
据此我观察到系统调用 fstat
、close
正如@pchaigno 在下面的答案中提到的,另外 mmap
、munmap
也被调用了。所以我必须允许这些系统调用以实现预期的行为。
调试
跟踪您的应用程序将揭示问题:
$ strace ./test
[...]
seccomp(SECCOMP_SET_MODE_FILTER, 0, {len=12, filter=0x55ace60a6600}) = 0
fstat(1, <unfinished ...>) = ?
+++ killed by SIGSYS (core dumped) +++
Bad system call (core dumped)
允许最少的系统调用集
您需要允许更多的系统调用,而不仅仅是 write(2)
才能让您的程序结束而不会出错。
fprintf()
需要fstat(2)
,fclose()
需要close(2)
,结束进程需要exit_group(2)
。
拒绝系统调用而不是终止进程
此外,如果您希望程序在未经授权的系统调用后继续 运行,则不应使用 SCMP_ACT_KILL
终止它。 SCMP_ACT_ERRNO(EPERM)
在这种情况下可能更合适。
结果
int main(void) {
FILE *fil = fopen("file1", "w");
scmp_filter_ctx filter = seccomp_init(SCMP_ACT_ERRNO(EPERM));
if (filter == NULL || NULL == fil)
return 1;
if (seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_A0(SCMP_CMP_EQ,fileno(fil))) < 0)
goto err;
if (seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0) < 0)
goto err;
if (seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(close), 0) < 0)
goto err;
if (seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0) < 0)
goto err;
if (seccomp_load(filter) < 0)
goto err;
fprintf(stdout, "Filter did not work correctly\n");
fprintf(fil, "Filter worked correctly\n");
err:
seccomp_release(filter); //releasing filter before closing file
fclose(fil);
return 0;
}
给我们:
$ ./test; echo file1
Filter worked correctly
我刚刚开始学习 seccomp 过滤器,我正在使用 libseccomp v2.4.4。我尝试编写一个基本的白名单过滤器,它只允许写入名为 file1
的文件,但我在 STDOUT
中收到“错误的系统调用”消息。这是我的代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <seccomp.h>
#include <stdlib.h>
#include <errno.h>
int main(void)
{
FILE *fil = fopen("file1", "w");
scmp_filter_ctx filter = seccomp_init(SCMP_ACT_KILL);
if (filter==NULL || NULL==fil)
goto End1;
int chk1 = seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
SCMP_A0(SCMP_CMP_EQ, fileno(fil)));
int chk2 = seccomp_load(filter);
if (chk1<0 || chk2<0)
goto End;
fprintf(stdout,"Filter did not work correctly\n");
fprintf(fil,"Filter worked correctly\n");
End:
seccomp_release(filter); //releasing filter before closing file
fclose(fil);
End1:
return 0;
}
此外,我在 file1
中看不到任何输出。我只是一个初学者,不确定这里的很多事情,因为我是根据我的理解而不是参考来编写代码的。似乎是什么问题?
编辑:我完全删除了过滤器并简单地执行了
int main(void)
{
FILE *fil = fopen("file1", "w");
fprintf(stdout,"Filter did not work correctly\n");
fprintf(fil,"Filter worked correctly\n");
End:
fclose(fil);
End1:
return 0;
}
据此我观察到系统调用 fstat
、close
正如@pchaigno 在下面的答案中提到的,另外 mmap
、munmap
也被调用了。所以我必须允许这些系统调用以实现预期的行为。
调试
跟踪您的应用程序将揭示问题:
$ strace ./test
[...]
seccomp(SECCOMP_SET_MODE_FILTER, 0, {len=12, filter=0x55ace60a6600}) = 0
fstat(1, <unfinished ...>) = ?
+++ killed by SIGSYS (core dumped) +++
Bad system call (core dumped)
允许最少的系统调用集
您需要允许更多的系统调用,而不仅仅是 write(2)
才能让您的程序结束而不会出错。
fprintf()
需要fstat(2)
,fclose()
需要close(2)
,结束进程需要exit_group(2)
。
拒绝系统调用而不是终止进程
此外,如果您希望程序在未经授权的系统调用后继续 运行,则不应使用 SCMP_ACT_KILL
终止它。 SCMP_ACT_ERRNO(EPERM)
在这种情况下可能更合适。
结果
int main(void) {
FILE *fil = fopen("file1", "w");
scmp_filter_ctx filter = seccomp_init(SCMP_ACT_ERRNO(EPERM));
if (filter == NULL || NULL == fil)
return 1;
if (seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_A0(SCMP_CMP_EQ,fileno(fil))) < 0)
goto err;
if (seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0) < 0)
goto err;
if (seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(close), 0) < 0)
goto err;
if (seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0) < 0)
goto err;
if (seccomp_load(filter) < 0)
goto err;
fprintf(stdout, "Filter did not work correctly\n");
fprintf(fil, "Filter worked correctly\n");
err:
seccomp_release(filter); //releasing filter before closing file
fclose(fil);
return 0;
}
给我们:
$ ./test; echo file1
Filter worked correctly