seccomp: support allowlist/denylist in profiles

parent 59410099
......@@ -17,7 +17,7 @@ lxc.hook.clone = @LXCHOOKDIR@/clonehostname
# Default legacy cgroup configuration
#
# CGroup whitelist
# CGroup allowlist
lxc.cgroup.devices.deny = a
## Allow any mknod (but not reading/writing the node)
lxc.cgroup.devices.allow = c *:* m
......@@ -46,7 +46,7 @@ lxc.cgroup.devices.allow = c 10:229 rwm
# Default unified cgroup configuration
#
# CGroup whitelist
# CGroup allowlist
lxc.cgroup2.devices.deny = a
## Allow any mknod (but not reading/writing the node)
lxc.cgroup2.devices.allow = c *:* m
......
2
blacklist
denylist
reject_force_umount # comment this to allow umount -f; not recommended
[all]
kexec_load errno 1
......
......@@ -10,7 +10,7 @@ pkgexamples_DATA = \
lxc-veth.conf \
lxc-complex.conf \
seccomp-v1.conf \
seccomp-v2-blacklist.conf \
seccomp-v2-denylist.conf \
seccomp-v2.conf
endif
......@@ -23,10 +23,10 @@ noinst_DATA = \
lxc-veth.conf.in \
lxc-complex.conf.in \
seccomp-v1.conf \
seccomp-v2-blacklist.conf \
seccomp-v2-denylist.conf \
seccomp-v2.conf
EXTRA_DIST = \
seccomp-v1.conf \
seccomp-v2-blacklist.conf \
seccomp-v2-denylist.conf \
seccomp-v2.conf
1
whitelist
allowlist
0
1
2
......
2
blacklist
denylist
# v2 allows comments after the second line, with '#' in first column,
# blacklist will allow syscalls by default
# denylist will allow syscalls by default
# if 'errno 0' was not appended to 'mknod' below, then the task would
# simply be killed when it tried to mknod. 'errno 0' means do not allow
# the container to mknod, but immediately return 0.
......
2
whitelist trap
# 'whitelist' would normally mean kill a task doing any syscall which is not
# whitelisted below. By appending 'trap' to the line, we will cause a SIGSYS
allowlist trap
# 'allowlist' would normally mean kill a task doing any syscall which is not
# allowlisted below. By appending 'trap' to the line, we will cause a SIGSYS
# to be sent to the task instead. 'errno 0' would mean don't allow the system
# call but immediately return 0. 'errno 22' would mean return EINVAL immediately.
[x86_64]
......@@ -20,5 +20,5 @@ read
write
mount
umount2
# Do note that this policy does not whitelist enough system calls to allow a
# Do note that this policy does not allowlist enough system calls to allow a
# system container to boot.
......@@ -2239,7 +2239,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
standard namespace identifiers as seen in the
<filename>/proc/PID/ns</filename> directory.
The <option>lxc.namespace.keep</option> is a
blacklist option, i.e. it is useful when enforcing that containers
denylist option, i.e. it is useful when enforcing that containers
must keep a specific set of namespaces.
-->
コンテナが、作成元のプロセスから継承する (新しい名前空間を作らずに元のプロセスの名前空間のまま実行する) 名前空間を指定します。継承する名前空間はスペース区切りのリストで指定します。指定する名前空間名は、<filename>/proc/PID/ns</filename> ディレクトリ内に存在する標準の名前空間指示子でなければなりません。<option>lxc.namespace.keep</option> はブラックリストを指定するオプションです。つまり、コンテナに特定の名前空間を使い続けることを強制したい場合に便利です。
......@@ -2660,18 +2660,18 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
<para>
<!--
Versions 1 and 2 are currently supported. In version 1, the
policy is a simple whitelist. The second line therefore must
read "whitelist", with the rest of the file containing one (numeric)
syscall number per line. Each syscall number is whitelisted,
while every unlisted number is blacklisted for use in the container
policy is a simple allowlist. The second line therefore must
read "allowlist", with the rest of the file containing one (numeric)
syscall number per line. Each syscall number is allowlisted,
while every unlisted number is denylisted for use in the container
-->
現時点では、バージョン番号は 1 と 2 をサポートしています。バージョン 1 では、ポリシーはシンプルなホワイトリストですので、2 行目は "whitelist" でなければなりません。
現時点では、バージョン番号は 1 と 2 をサポートしています。バージョン 1 では、ポリシーはシンプルなホワイトリストですので、2 行目は "allowlist" でなければなりません。
そして残りの行には 1 行に 1 つずつ、システムコール番号を書きます。各行のシステムコール番号がホワイトリスト化され、リストにない番号は、そのコンテナではブラックリストに入ります。
</para>
<para>
<!--
In version 2, the policy may be blacklist or whitelist,
In version 2, the policy may be denylist or allowlist,
supports per-rule and per-policy default actions, and supports
per-architecture system call resolution from textual names.
-->
......@@ -2679,7 +2679,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
</para>
<para>
<!--
An example blacklist policy, in which all system calls are
An example denylist policy, in which all system calls are
allowed except for mknod, which will simply do nothing and
return 0 (success), looks like:
-->
......@@ -2688,7 +2688,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
<programlisting>
2
blacklist
denylist
mknod errno 0
ioctl notify
</programlisting>
......
......@@ -1736,17 +1736,17 @@ proc proc proc nodev,noexec,nosuid 0 0
<para>
<!--
Versions 1 and 2 are currently supported. In version 1, the
policy is a simple whitelist. The second line therefore must
read "whitelist", with the rest of the file containing one (numeric)
syscall number per line. Each syscall number is whitelisted,
while every unlisted number is blacklisted for use in the container
policy is a simple allowlist. The second line therefore must
read "allowlist", with the rest of the file containing one (numeric)
syscall number per line. Each syscall number is allowlisted,
while every unlisted number is denylisted for use in the container
-->
현재는 버전1과 2만 지원된다. 버전 1에서는 정책은 단순한 화이트리스트이다. 그러므로 두번째 라인은 반드시 "whitelist"여야 한다. 파일의 나머지 내용은 한 줄에 하나의 시스템콜 번호로 채워진다. 화이트리스트에 없는 번호는 컨테이너에서 블랙리스트로 들어간다.
현재는 버전1과 2만 지원된다. 버전 1에서는 정책은 단순한 화이트리스트이다. 그러므로 두번째 라인은 반드시 "allowlist"여야 한다. 파일의 나머지 내용은 한 줄에 하나의 시스템콜 번호로 채워진다. 화이트리스트에 없는 번호는 컨테이너에서 블랙리스트로 들어간다.
</para>
<para>
<!--
In version 2, the policy may be blacklist or whitelist,
In version 2, the policy may be denylist or allowlist,
supports per-rule and per-policy default actions, and supports
per-architecture system call resolution from textual names.
-->
......@@ -1754,7 +1754,7 @@ proc proc proc nodev,noexec,nosuid 0 0
</para>
<para>
<!--
An example blacklist policy, in which all system calls are
An example denylist policy, in which all system calls are
allowed except for mknod, which will simply do nothing and
return 0 (success), looks like:
-->
......@@ -1762,7 +1762,7 @@ proc proc proc nodev,noexec,nosuid 0 0
</para>
<screen>
2
blacklist
denylist
mknod errno 0
</screen>
<variablelist>
......
......@@ -1676,7 +1676,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
standard namespace identifiers as seen in the
<filename>/proc/PID/ns</filename> directory.
The <option>lxc.namespace.keep</option> is a
blacklist option, i.e. it is useful when enforcing that containers
denylist option, i.e. it is useful when enforcing that containers
must keep a specific set of namespaces.
</para>
......@@ -1984,26 +1984,26 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
</para>
<para>
Versions 1 and 2 are currently supported. In version 1, the
policy is a simple whitelist. The second line therefore must
read "whitelist", with the rest of the file containing one (numeric)
syscall number per line. Each syscall number is whitelisted,
while every unlisted number is blacklisted for use in the container
policy is a simple allowlist. The second line therefore must
read "allowlist", with the rest of the file containing one (numeric)
syscall number per line. Each syscall number is allowlisted,
while every unlisted number is denylisted for use in the container
</para>
<para>
In version 2, the policy may be blacklist or whitelist,
In version 2, the policy may be denylist or allowlist,
supports per-rule and per-policy default actions, and supports
per-architecture system call resolution from textual names.
</para>
<para>
An example blacklist policy, in which all system calls are
An example denylist policy, in which all system calls are
allowed except for mknod, which will simply do nothing and
return 0 (success), looks like:
</para>
<programlisting>
2
blacklist
denylist
mknod errno 0
ioctl notify
</programlisting>
......
......@@ -174,7 +174,7 @@ struct bpf_program *bpf_program_new(uint32_t prog_type)
prog->prog_type = prog_type;
prog->kernel_fd = -EBADF;
/*
* By default a whitelist is used unless the user tells us otherwise.
* By default a allowlist is used unless the user tells us otherwise.
*/
prog->device_list_type = LXC_BPF_DEVICE_CGROUP_ALLOWLIST;
......
......@@ -99,7 +99,7 @@ static uint32_t get_v2_default_action(char *line)
while (*line == ' ')
line++;
/* After 'whitelist' or 'blacklist' comes default behavior. */
/* After 'allowlist' or 'denylist' comes default behavior. */
if (strncmp(line, "kill", 4) == 0) {
ret_action = SCMP_ACT_KILL;
} else if (strncmp(line, "errno", 5) == 0) {
......@@ -562,6 +562,27 @@ bool do_resolve_add_rule(uint32_t arch, char *line, scmp_filter_ctx ctx,
}
/*
* It is unfortunate, but we can't simply remove those terms since this would
* break way too many users.
*/
#define BACKWARDCOMPAT_TERMINOLOGY_DENYLIST "blacklist"
#define BACKWARDCOMPAT_TERMINOLOGY_ALLOWLIST "whitelist"
static inline bool is_denylist(const char *type)
{
return strnequal(type, "denylist", STRLITERALLEN("denylist")) ||
strnequal(type, BACKWARDCOMPAT_TERMINOLOGY_DENYLIST,
STRLITERALLEN(BACKWARDCOMPAT_TERMINOLOGY_DENYLIST));
}
static inline bool is_allowlist(const char *type)
{
return strnequal(type, "allowlist", STRLITERALLEN("allowlist")) ||
strnequal(type, BACKWARDCOMPAT_TERMINOLOGY_ALLOWLIST,
STRLITERALLEN(BACKWARDCOMPAT_TERMINOLOGY_ALLOWLIST));
}
/*
* v2 consists of
* [x86]
* open
......@@ -580,7 +601,7 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c
int ret;
char *p;
enum lxc_hostarch_t cur_rule_arch, native_arch;
bool blacklist = false;
bool denylist = false;
uint32_t default_policy_action = -1, default_rule_action = -1;
struct seccomp_v2_rule rule;
struct scmp_ctx_info {
......@@ -589,12 +610,10 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c
bool needs_merge[3];
} ctx;
if (strncmp(line, "blacklist", 9) == 0)
blacklist = true;
else if (strncmp(line, "whitelist", 9) != 0) {
ERROR("Bad seccomp policy style \"%s\"", line);
return -1;
}
if (is_denylist(line))
denylist = true;
else if (!is_allowlist(line))
return log_error(-EINVAL, "Bad seccomp policy style \"%s\"", line);
p = strchr(line, ' ');
if (p) {
......@@ -603,8 +622,8 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c
return -1;
}
/* for blacklist, allow any syscall which has no rule */
if (blacklist) {
/* for denylist, allow any syscall which has no rule */
if (denylist) {
if (default_policy_action == -1)
default_policy_action = SCMP_ACT_ALLOW;
......@@ -1079,7 +1098,7 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
* the second line has some directives
* then comes policy subject to the directives
* right now version must be '1' or '2'
* the directives must include 'whitelist'(version == 1 or 2) or 'blacklist'
* the directives must include 'allowlist'(version == 1 or 2) or 'denylist'
* (version == 2) and can include 'debug' (though debug is not yet supported).
*/
static int parse_config(FILE *f, struct lxc_conf *conf)
......@@ -1099,8 +1118,8 @@ static int parse_config(FILE *f, struct lxc_conf *conf)
goto bad_line;
}
if (version == 1 && !strstr(line, "whitelist")) {
ERROR("Only whitelist policy is supported");
if (version == 1 && !strstr(line, "allowlist")) {
ERROR("Only allowlist policy is supported");
goto bad_line;
}
......
......@@ -118,4 +118,14 @@ static inline ssize_t safe_strlcat(char *src, const char *append, size_t len)
return (ssize_t)new_len;
}
static inline bool strnequal(const char *str, const char *eq, size_t len)
{
return strncmp(str, eq, len) == 0;
}
static inline bool strequal(const char *str, const char *eq)
{
return strcmp(str, eq) == 0;
}
#endif /* __LXC_STRING_UTILS_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment