提交 caa016e8 编写于 作者: X xiacong

<feat>

新增特性:系统进程沙盒环境支持Seccomp-BPF

<body>
输出系统进程的系统调用配置文件,其中appspawn与nwebspawn采用独立的配置文件,其它系统进程为一套
提供解析系统调用配置文件的脚本
提供使能seccomp-bpf策略的接口
编译前利用脚本解析配置文件,生成对应的seccomp-bpf策略代码,并生成独立的动态库
Signed-off-by: Nxiacong <xiacong4@huawei.com>
上级 466ea295
......@@ -96,6 +96,15 @@
]
},
"name": "//base/startup/init/interfaces/innerkits/init_module_engine:libinit_module_engine"
},
{
"header": {
"header_base": "//base/startup/init/interfaces/innerkits/seccomp/include/",
"header_files": [
"seccomp_policy.h"
]
},
"name": "//base/startup/init/interfaces/innerkits/seccomp:seccomp"
}
],
"test": [
......
......@@ -288,6 +288,9 @@ if (defined(ohos_lite)) {
group("innergroup") {
deps = [ ":libbegetutil" ]
if (build_seccomp) {
deps += [ "seccomp:seccomp" ]
}
if (!defined(ohos_lite)) {
deps += [
":libbeget_proxy",
......
# Copyright (c) 2022 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/ohos.gni")
config("seccomp_public_config") {
include_dirs = [ "//base/startup/init/interfaces/innerkits/seccomp/include" ]
}
ohos_shared_library("seccomp") {
sources = [ "//base/startup/init/services/modules/seccomp/seccomp_policy.c" ]
public_configs = [ ":seccomp_public_config" ]
include_dirs = [ "//base/startup/init/services/modules/seccomp" ]
deps = [
"//base/startup/init/interfaces/innerkits:libbegetutil",
"//base/startup/init/services/modules/seccomp:appspawn_filter",
"//base/startup/init/services/modules/seccomp:system_filter",
]
license_file = "//base/startup/init/LICENSE"
part_name = "init"
install_enable = true
install_images = [
"system",
"updater",
"ramdisk",
]
}
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SECCOMP_POLICY_H
#define SECCOMP_POLICY_H
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef enum {
SYSTEM,
APPSPAWN,
APP
} PolicyType;
bool SetSeccompPolicy(PolicyType policy);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // SECCOMP_POLICY_H
......@@ -48,6 +48,12 @@
#include <selinux/selinux.h>
#endif // WITH_SELINUX
#ifdef WITH_SECCOMP
#include "seccomp_policy.h"
#define APPSPAWN_NAME ("appspawn")
#define NWEBSPAWN_NAME ("nwebspawn")
#endif
#ifndef TIOCSCTTY
#define TIOCSCTTY 0x540E
#endif
......@@ -62,6 +68,20 @@ static int SetAllAmbientCapability(void)
return SERVICE_SUCCESS;
}
#ifdef WITH_SECCOMP
static int SetSystemSeccompPolicy(const Service *service)
{
if (strncmp(APPSPAWN_NAME, service->name, strlen(APPSPAWN_NAME)) \
&& strncmp(NWEBSPAWN_NAME, service->name, strlen(NWEBSPAWN_NAME))) {
if (!SetSeccompPolicy(SYSTEM)) {
INIT_LOGE("init seccomp failed, name is %s\n", service->name);
return SERVICE_FAILURE;
}
}
return SERVICE_SUCCESS;
}
#endif
static int SetPerms(const Service *service)
{
INIT_CHECK_RETURN_VALUE(KeepCapability() == 0, SERVICE_FAILURE);
......@@ -271,9 +291,16 @@ static int InitServicePropertys(Service *service)
PublishHoldFds(service);
INIT_CHECK_ONLY_ELOG(BindCpuCore(service) == SERVICE_SUCCESS,
"binding core number failed for service %s", service->name);
#ifdef WITH_SECCOMP
INIT_ERROR_CHECK(SetSystemSeccompPolicy(service) == SERVICE_SUCCESS, return -1,
"service %s exit! set seccomp failed! err %d.", service->name, errno);
#endif
// permissions
INIT_ERROR_CHECK(SetPerms(service) == SERVICE_SUCCESS, _exit(PROCESS_EXIT_CODE),
"service %s exit! set perms failed! err %d.", service->name, errno);
// write pid
INIT_ERROR_CHECK(WritePid(service) == SERVICE_SUCCESS, _exit(PROCESS_EXIT_CODE),
"service %s exit! write pid failed!", service->name);
......
......@@ -86,6 +86,13 @@ ohos_executable("init") {
]
}
if (build_seccomp) {
cflags += [ "-DWITH_SECCOMP" ]
include_dirs +=
[ "//base/startup/init/interfaces/innerkits/seccomp/include" ]
deps += [ "//base/startup/init/services/modules/seccomp:seccomp_static" ]
}
if (build_selinux) {
include_dirs += [
"//third_party/selinux/libselinux/include/",
......
# Copyright (c) 2022 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//base/startup/init/begetd.gni")
import(
"//base/startup/init/services/modules/seccomp/scripts/seccomp_policy_fixer.gni")
import("//build/config/clang/clang.gni")
import("//build/ohos.gni")
import("//build/ohos/kernel/kernel.gni")
INIT_PART = "init"
action("syscall_to_nr_arm") {
script = "${clang_base_path}/bin/clang"
output_dir = target_gen_dir + "/libsyscall_to_nr_arm"
args = [
"-I",
rebase_path(
"//kernel/linux/patches/${linux_kernel_version}/prebuilts/usr/include/asm-arm"),
"-I",
rebase_path(
"//kernel/linux/patches/${linux_kernel_version}/prebuilts/usr/include"),
"-dD",
"-E",
"-Wall",
"-nostdinc",
"-o",
rebase_path(output_dir),
rebase_path("gen_syscall_name_nrs.c"),
]
outputs = [ output_dir ]
}
action("syscall_to_nr_arm64") {
script = "${clang_base_path}/bin/clang"
output_dir = target_gen_dir + "/libsyscall_to_nr_arm64"
args = [
"-I",
rebase_path(
"//kernel/linux/patches/${linux_kernel_version}/prebuilts/usr/include/asm-arm64"),
"-I",
rebase_path(
"//kernel/linux/patches/${linux_kernel_version}/prebuilts/usr/include"),
"-dD",
"-E",
"-Wall",
"-nostdinc",
"-o",
rebase_path(output_dir),
rebase_path("gen_syscall_name_nrs.c"),
]
outputs = [ output_dir ]
}
ohos_prebuilt_seccomp("system_filter") {
sources = []
if (target_cpu == "arm") {
sources += [ "seccomp_policy/system_arm.seccomp.policy" ]
} else if (target_cpu == "arm64") {
sources += [
# 64-bit machine also need check use 32-bit syscall
"seccomp_policy/system_arm.seccomp.policy",
"seccomp_policy/system_arm64.seccomp.policy",
]
}
filtername = "g_systemSeccompFilter"
include_dirs = [ "." ]
part_name = INIT_PART
subsystem_name = "startup"
install_enable = true
install_images = [
"system",
"ramdisk",
]
}
ohos_prebuilt_seccomp("appspawn_filter") {
sources = []
if (target_cpu == "arm") {
sources += [ "seccomp_policy/spawn_arm.seccomp.policy" ]
} else if (target_cpu == "arm64") {
sources += [
# 64-bit machine also need check use 32-bit syscall
"seccomp_policy/spawn_arm.seccomp.policy",
"seccomp_policy/spawn_arm64.seccomp.policy",
]
}
filtername = "g_appspawnSeccompFilter"
include_dirs = [ "." ]
part_name = INIT_PART
subsystem_name = "startup"
install_enable = true
install_images = [
"system",
"ramdisk",
]
}
ohos_static_library("seccomp_static") {
sources = [ "//base/startup/init/services/modules/seccomp/seccomp_policy.c" ]
include_dirs = [
"//base/startup/init/interfaces/innerkits/include",
"//base/startup/init/interfaces/innerkits/seccomp/include",
"//base/startup/init/services/modules/seccomp",
]
deps = [
":appspawn_filter",
":system_filter",
]
license_file = "//base/startup/init/LICENSE"
part_name = INIT_PART
subsystem_name = "startup"
}
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <asm/unistd.h>
\ No newline at end of file
# Copyright (c) 2022 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/config/python.gni")
import("//build/ohos.gni")
template("ohos_prebuilt_seccomp") {
assert(defined(invoker.sources), "source must be defined for ${target_name}.")
assert(defined(invoker.filtername),
"source must be defined for ${target_name}.")
_seccomp_filter_target = "gen_${target_name}"
_seccomp_filter_file = target_gen_dir + "/${target_name}.c"
action(_seccomp_filter_target) {
script = "//base/startup/init/services/modules/seccomp/scripts/generate_code_from_policy.py"
sources = invoker.sources
sources += get_target_outputs(
"//base/startup/init/services/modules/seccomp:syscall_to_nr_arm")
sources += get_target_outputs(
"//base/startup/init/services/modules/seccomp:syscall_to_nr_arm64")
deps = [
"//base/startup/init/services/modules/seccomp:syscall_to_nr_arm",
"//base/startup/init/services/modules/seccomp:syscall_to_nr_arm64",
]
args = []
foreach(source, sources) {
args += [
"--srcfiles",
rebase_path(source),
]
}
args += [
"--dstfile",
rebase_path(_seccomp_filter_file),
"--bpfArrayName",
invoker.filtername,
]
outputs = [ _seccomp_filter_file ]
}
ohos_shared_library(target_name) {
deps = [ ":${_seccomp_filter_target}" ]
sources = get_target_outputs(":${_seccomp_filter_target}")
if (defined(invoker.include_dirs)) {
include_dirs = invoker.include_dirs
}
if (defined(invoker.install_enable)) {
install_enable = invoker.install_enable
}
if (defined(invoker.part_name)) {
part_name = invoker.part_name
}
if (defined(invoker.subsystem_name)) {
subsystem_name = invoker.subsystem_name
}
if (defined(invoker.install_images)) {
install_images = invoker.install_images
}
}
}
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SECCOMP_FILTERS_H
#define SECCOMP_FILTERS_H
#include <stddef.h>
#include <linux/filter.h>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
extern const struct sock_filter g_appspawnSeccompFilter[];
extern const size_t g_appspawnSeccompFilterSize;
extern const struct sock_filter g_systemSeccompFilter[];
extern const size_t g_systemSeccompFilterSize;
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // SECCOMP_FILTERS_H
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "seccomp_policy.h"
#include "seccomp_filters.h"
#include "seccomp_utils.h"
#include <sys/syscall.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <assert.h>
#include <linux/audit.h>
#include <linux/seccomp.h>
#include <linux/filter.h>
#ifndef SECCOMP_SET_MODE_FILTER
#define SECCOMP_SET_MODE_FILTER (1)
#endif
static bool IsSupportFilterFlag(unsigned int filterFlag)
{
errno = 0;
int ret = syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER, filterFlag, NULL);
if (ret != -1 || errno != EFAULT) {
SECCOMP_LOGE("not support seccomp flag %u", filterFlag);
return false;
}
return true;
}
static bool InstallSeccompPolicy(const struct sock_filter* filter, size_t filterSize, unsigned int filterFlag)
{
unsigned int flag = 0;
struct sock_fprog prog = {
(unsigned short)filterSize,
(struct sock_filter*)filter
};
if (IsSupportFilterFlag(SECCOMP_FILTER_FLAG_TSYNC) && (filterFlag & SECCOMP_FILTER_FLAG_TSYNC)) {
flag |= SECCOMP_FILTER_FLAG_TSYNC;
}
if (IsSupportFilterFlag(SECCOMP_FILTER_FLAG_LOG) && (filterFlag & SECCOMP_FILTER_FLAG_LOG)) {
flag |= SECCOMP_FILTER_FLAG_LOG;
}
if (syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER, flag, &prog) != 0) {
SECCOMP_LOGE("SetSeccompFilter failed");
return false;
}
return true;
}
bool SetSeccompPolicy(PolicyType policy)
{
bool ret = false;
switch (policy) {
case SYSTEM:
ret = InstallSeccompPolicy(g_systemSeccompFilter, g_systemSeccompFilterSize, SECCOMP_FILTER_FLAG_LOG);
break;
case APPSPAWN:
ret = InstallSeccompPolicy(g_appspawnSeccompFilter, g_appspawnSeccompFilterSize, SECCOMP_FILTER_FLAG_LOG);
break;
default:
ret = false;
}
return ret;
}
# Copyright (c) 2022 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
@arch
arm
@returnValue
KILL_PROCESS
@mode
ONLY_CHECK_ARGS
@headFiles
"seccomp_filters.h"
@allowListWithArgs
setresuid32: if arg0 >= 10000 && arg1 >= 10000 && arg2 >= 10000
setresgid32: if arg0 >= 10000 && arg1 >= 10000 && arg2 >= 10000
\ No newline at end of file
# Copyright (c) 2022 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
@arch
arm64
@returnValue
KILL_PROCESS
@mode
ONLY_CHECK_ARGS
@headFiles
"seccomp_filters.h"
@allowListWithArgs
setresuid: if arg0 >= 10000 && arg1 >= 10000 && arg2 >= 10000
setresgid: if arg0 >= 10000 && arg1 >= 10000 && arg2 >= 10000
\ No newline at end of file
# Copyright (c) 2022 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
@arch
arm
@returnValue
KILL_PROCESS
@headFiles
"seccomp_filters.h"
@allowList
restart_syscall
exit
fork
read
write
open
close
unlink
execve
chdir
mknod
chmod
lseek
getpid
mount
ptrace
access
sync
kill
rename
mkdir
rmdir
dup
pipe
times
brk
acct
umount2
ioctl
setpgid
umask
chroot
dup2
getppid
setsid
sigaction
sethostname
setrlimit
getrusage
gettimeofday
settimeofday
symlink
readlink
swapon
reboot
munmap
truncate
fchmod
getpriority
setpriority
syslog
setitimer
getitimer
stat
wait4
swapoff
sysinfo
fsync
sigreturn
clone
setdomainname
uname
adjtimex
mprotect
init_module
delete_module
quotactl
getpgid
fchdir
personality
setfsuid
setfsgid
_llseek
_newselect
flock
msync
readv
writev
getsid
fdatasync
mlock
munlock
mlockall
munlockall
sched_setparam
sched_getparam
sched_setscheduler
sched_getscheduler
sched_yield
sched_get_priority_max
sched_get_priority_min
sched_rr_get_interval
nanosleep
mremap
poll
prctl
rt_sigreturn
rt_sigaction
rt_sigprocmask
rt_sigpending
rt_sigtimedwait
rt_sigqueueinfo
rt_sigsuspend
pread64
pwrite64
getcwd
capget
capset
sigaltstack
sendfile
vfork
ugetrlimit
mmap2
truncate64
ftruncate64
stat64
fstat64
lchown32
getuid32
getgid32
geteuid32
getegid32
setreuid32
setregid32
chown32
getgroups32
setgroups32
pivot_root
fchown32
setresuid32
getresuid32
setresgid32
getresgid32
setuid32
setgid32
getdents64
mincore
madvise
fcntl64
gettid
readahead
setxattr
lsetxattr
fsetxattr
getxattr
lgetxattr
fgetxattr
listxattr
llistxattr
flistxattr
removexattr
lremovexattr
fremovexattr
tkill
sendfile64
futex
sched_setaffinity
sched_getaffinity
io_setup
io_destroy
io_getevents
io_submit
io_cancel
exit_group
epoll_ctl
set_tid_address
timer_create
timer_settime
timer_gettime
timer_getoverrun
timer_delete
clock_settime
clock_gettime
clock_getres
clock_nanosleep
statfs64
fstatfs64
tgkill
fadvise64_64
waitid
socket
bind
connect
listen
accept
getsockname
getpeername
socketpair
sendto
recvfrom
shutdown
setsockopt
getsockopt
sendmsg
recvmsg
inotify_add_watch
inotify_rm_watch
openat
mkdirat
mknodat
fchownat
fstatat64
unlinkat
renameat
linkat
symlinkat
readlinkat
fchmodat
faccessat
pselect6
ppoll
unshare
set_robust_list
get_robust_list
splice
sync_file_range2
tee
vmsplice
getcpu
epoll_pwait
utimensat
timerfd_create
fallocate
timerfd_settime
timerfd_gettime
signalfd4
eventfd2
epoll_create1
dup3
pipe2
inotify_init1
preadv
pwritev
rt_tgsigqueueinfo
perf_event_open
recvmmsg
accept4
prlimit64
clock_adjtime
syncfs
sendmmsg
setns
process_vm_readv
process_vm_writev
finit_module
sched_setattr
sched_getattr
renameat2
seccomp
getrandom
memfd_create
bpf
execveat
userfaultfd
membarrier
mlock2
copy_file_range
preadv2
pwritev2
statx
clock_gettime64
clock_settime64
clock_adjtime64
clock_getres_time64
clock_nanosleep_time64
timer_gettime64
timer_settime64
timerfd_gettime64
timerfd_settime64
utimensat_time64
pselect6_time64
ppoll_time64
recvmmsg_time64
semtimedop_time64
rt_sigtimedwait_time64
futex_time64
sched_rr_get_interval_time64
pidfd_send_signal
pidfd_open
close_range
pidfd_getfd
process_madvise
cacheflush
set_tls
# Copyright (c) 2022 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
@arch
arm64
@returnValue
KILL_PROCESS
@headFiles
"seccomp_filters.h"
@allowList
io_setup
io_destroy
io_submit
io_cancel
io_getevents
setxattr
lsetxattr
fsetxattr
getxattr
lgetxattr
fgetxattr
listxattr
llistxattr
flistxattr
removexattr
lremovexattr
fremovexattr
getcwd
eventfd2
epoll_create1
epoll_ctl
epoll_pwait
dup
dup3
fcntl
inotify_init1
inotify_add_watch
inotify_rm_watch
ioctl
ioprio_set
ioprio_get
flock
mknodat
mkdirat
unlinkat
symlinkat
linkat
renameat
umount2
mount
pivot_root
statfs
fstatfs
truncate
ftruncate
fallocate
faccessat
chdir
fchdir
chroot
fchmod
fchmodat
fchownat
fchown
openat
close
pipe2
quotactl
getdents64
lseek
read
write
readv
writev
pread64
pwrite64
preadv
pwritev
sendfile
pselect6
ppoll
signalfd4
vmsplice
splice
tee
readlinkat
newfstatat
fstat
sync
fsync
fdatasync
sync_file_range
timerfd_create
timerfd_settime
timerfd_gettime
utimensat
acct
capget
capset
personality
exit
exit_group
waitid
set_tid_address
unshare
futex
set_robust_list
get_robust_list
nanosleep
getitimer
setitimer
init_module
delete_module
timer_create
timer_gettime
timer_getoverrun
timer_settime
timer_delete
clock_settime
clock_gettime
clock_getres
clock_nanosleep
syslog
ptrace
sched_setparam
sched_setscheduler
sched_getscheduler
sched_getparam
sched_setaffinity
sched_getaffinity
sched_yield
sched_get_priority_max
sched_get_priority_min
sched_rr_get_interval
restart_syscall
kill
tkill
tgkill
sigaltstack
rt_sigsuspend
rt_sigaction
rt_sigprocmask
rt_sigpending
rt_sigtimedwait
rt_sigqueueinfo
rt_sigreturn
setpriority
getpriority
reboot
setregid
setgid
setreuid
setuid
setresuid
getresuid
setresgid
getresgid
setfsuid
setfsgid
times
setpgid
getpgid
getsid
setsid
getgroups
setgroups
uname
sethostname
setdomainname
getrlimit
setrlimit
getrusage
umask
prctl
getcpu
gettimeofday
settimeofday
adjtimex
getpid
getppid
getuid
geteuid
getgid
getegid
gettid
sysinfo
socket
socketpair
bind
listen
accept
connect
getsockname
getpeername
sendto
recvfrom
setsockopt
getsockopt
shutdown
sendmsg
recvmsg
readahead
brk
munmap
mremap
clone
execve
mmap
fadvise64
swapon
swapoff
mprotect
msync
mlock
munlock
mlockall
munlockall
mincore
madvise
rt_tgsigqueueinfo
perf_event_open
accept4
recvmmsg
wait4
prlimit64
clock_adjtime
syncfs
setns
sendmmsg
process_vm_readv
process_vm_writev
finit_module
sched_setattr
sched_getattr
renameat2
seccomp
getrandom
memfd_create
bpf
execveat
userfaultfd
membarrier
mlock2
copy_file_range
preadv2
pwritev2
statx
pidfd_send_signal
pidfd_open
close_range
pidfd_getfd
process_madvise
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef BASE_STARTUP_SECCOMP_UTILS_H
#define BASE_STARTUP_SECCOMP_UTILS_H
#include <stddef.h>
#include <stdint.h>
#include "beget_ext.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#ifndef SECCOMP_DOMAIN
#define SECCOMP_DOMAIN (BASE_DOMAIN + 0xe)
#endif
#define SECCOMP_LABEL "SECCOMP"
#define SECCOMP_LOGI(fmt, ...) STARTUP_LOGI(SECCOMP_DOMAIN, SECCOMP_LABEL, fmt, ##__VA_ARGS__)
#define SECCOMP_LOGE(fmt, ...) STARTUP_LOGE(SECCOMP_DOMAIN, SECCOMP_LABEL, fmt, ##__VA_ARGS__)
#define SECCOMP_LOGV(fmt, ...) STARTUP_LOGV(SECCOMP_DOMAIN, SECCOMP_LABEL, fmt, ##__VA_ARGS__)
#ifdef INIT_AGENT
#define SECCOMP_DUMP printf
#else
#define SECCOMP_DUMP SECCOMP_LOGI
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif
\ No newline at end of file
......@@ -245,6 +245,13 @@ ohos_unittest("init_unittest") {
]
}
if (defined(build_seccomp) && build_seccomp) {
sources += [ "seccomp/seccomp_unittest.cpp" ]
include_dirs +=
[ "//base/startup/init/interfaces/innerkits/seccomp/include" ]
deps += [ "//base/startup/init/services/modules/seccomp:seccomp_static" ]
}
if (defined(build_selinux) && build_selinux) {
sources += [ "param/selinux_unittest.cpp" ]
include_dirs += [
......
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gtest/gtest.h>
#include <gtest/gtest.h>
#include <cstdlib>
#include <unistd.h>
#include <sys/wait.h>
#include <csignal>
#include <cerrno>
#include <cstring>
#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/syscall.h>
#include <asm/unistd.h>
#include <syscall.h>
#include <climits>
#include <linux/openat2.h>
#include "seccomp_policy.h"
using SyscallFunc = bool (*)(void);
using namespace testing::ext;
using namespace std;
namespace init_ut {
class SeccompUnitTest : public testing::Test {
public:
SeccompUnitTest() {};
virtual ~SeccompUnitTest() {};
static void SetUpTestCase() {};
static void TearDownTestCase() {};
void SetUp() {};
void TearDown() {};
void TestBody(void) {};
static void Handler(int s)
{
}
static pid_t StartChild(PolicyType type, SyscallFunc func)
{
pid_t pid = fork();
if (pid == 0) {
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
std::cout << "PR_SET_NO_NEW_PRIVS set fail " << std::endl;
exit(EXIT_FAILURE);
}
if (!SetSeccompPolicy(type)) {
std::cout << "SetSeccompPolicy set fail type is " << type << std::endl;
exit(EXIT_FAILURE);
}
if (!func()) {
std::cout << "func excute fail" << std::endl;
exit(EXIT_FAILURE);
}
std::cout << "func excute success" << std::endl;
exit(EXIT_SUCCESS);
}
return pid;
}
static int CheckSyscall(PolicyType type, SyscallFunc func, bool isAllow)
{
sigset_t set;
int status;
pid_t pid;
int flag = 0;
struct timespec waitTime = {5, 0};
sigemptyset(&set);
sigaddset(&set, SIGCHLD);
sigprocmask(SIG_BLOCK, &set, nullptr);
if (signal(SIGCHLD, handler) == nullptr) {
std::cout << "signal failed:" << strerror(errno) << std::endl;
}
pid = StartChild(type, func);
if (pid == -1) {
std::cout << "fork failed:" << strerror(errno) << std::endl;
return -1;
}
if (sigtimedwait(&set, nullptr, &waitTime) == -1) { /* Wait for 5 seconds */
if (errno == EAGAIN) {
flag = 1;
} else {
std::cout << "sigtimedwait failed:" << strerror(errno) << std::endl;
}
if (kill(pid, SIGKILL) == -1) {
std::cout << "kill failed::" << strerror(errno) << std::endl;
}
}
if (waitpid(pid, &status, 0) != pid) {
std::cout << "waitpid failed:" << strerror(errno) << std::endl;
return -1;
}
if (flag) {
std::cout << "Child process time out" << std::endl;
}
if (WEXITSTATUS(status) == EXIT_FAILURE) {
return -1;
}
if (WIFSIGNALED(status)) {
if (WTERMSIG(status) == SIGSYS) {
std::cout << "child process exit with SIGSYS" << std::endl;
return isAllow ? -1 : 0;
}
} else {
std::cout << "child process finished normally" << std::endl;
return isAllow ? 0 : -1;
}
return -1;
}
#if defined __aarch64__
static bool CheckOpenat2()
{
struct open_how how = {};
int fd = syscall(__NR_openat2, AT_FDCWD, ".", &how);
if (fd == -1) {
return false;
}
close(fd);
return true;
}
static bool CheckGetpid()
{
pid_t pid = 1;
pid = syscall(__NR_getpid);
if (pid > 1) {
return true;
}
return false;
}
static bool CheckGetuid()
{
uid_t uid = 0;
uid = syscall(__NR_getuid);
if (uid >= 0) {
return true;
}
return false;
}
static bool CheckSetresuidArgsInRange()
{
int ret = syscall(__NR_setresuid, 20000, 20000, 20000);
if (ret == 0) {
return true;
}
return false;
}
static bool CheckSetresuidArgsOutOfRange()
{
int ret = syscall(__NR_setresuid, 1000, 1000, 1000);
if (ret == 0) {
return true;
}
return false;
}
void TestSystemSycall()
{
// system blocklist
int ret = CheckSyscall(SYSTEM, CheckOpenat2, false);
EXPECT_EQ(ret, 0);
// system allowlist
ret = CheckSyscall(SYSTEM, CheckGetpid, true);
EXPECT_EQ(ret, 0);
}
void TestSetUidGidFilter()
{
// system blocklist
int ret = CheckSyscall(APPSPAWN, CheckSetresuidArgsOutOfRange, false);
EXPECT_EQ(ret, 0);
// system allowlist
ret = CheckSyscall(APPSPAWN, CheckSetresuidArgsInRange, true);
EXPECT_EQ(ret, 0);
}
#elif defined __arm__
static bool CheckGetuid32()
{
uid_t uid = syscall(__NR_getuid32);
if (uid >= 0) {
return true;
}
return false;
}
static bool CheckGetuid()
{
uid_t uid = syscall(__NR_getuid);
if (uid >= 0) {
return true;
}
return false;
}
static bool CheckSetresuid32ArgsInRange()
{
int ret = syscall(__NR_setresuid32, 20000, 20000, 20000);
if (ret == 0) {
return true;
}
return false;
}
static bool CheckSetresuid32ArgsOutOfRange()
{
int ret = syscall(__NR_setresuid32, 1000, 1000, 1000);
if (ret == 0) {
return true;
}
return false;
}
void TestSystemSycall()
{
// system blocklist
int ret = CheckSyscall(SYSTEM, CheckGetuid, false);
EXPECT_EQ(ret, 0);
// system allowlist
ret = CheckSyscall(SYSTEM, CheckGetuid32, true);
EXPECT_EQ(ret, 0);
}
void TestSetUidGidFilter()
{
// system blocklist
int ret = CheckSyscall(APPSPAWN, CheckSetresuid32ArgsOutOfRange, false);
EXPECT_EQ(ret, 0);
// system allowlist
ret = CheckSyscall(APPSPAWN, CheckSetresuid32ArgsInRange, true);
EXPECT_EQ(ret, 0);
}
#endif
};
HWTEST_F(SeccompUnitTest, TestSystemSycall, TestSize.Level1)
{
SeccompUnitTest test;
test.TestSystemSycall();
}
HWTEST_F(SeccompUnitTest, TestSetUidGidFilter, TestSize.Level1)
{
SeccompUnitTest test;
test.TestSystemSycall();
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册