Skip to content

Commit b88f0fd

Browse files
authored
Merge pull request #30305 from yuwata/seccomp-fix
seccomp: override the default action only when the filter is allow-list
2 parents 8244f39 + 78b2ad7 commit b88f0fd

File tree

1 file changed

+65
-20
lines changed

1 file changed

+65
-20
lines changed

src/shared/seccomp-util.c

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,28 +1080,72 @@ static int add_syscall_filter_set(
10801080
return 0;
10811081
}
10821082

1083+
static uint32_t override_default_action(uint32_t default_action) {
1084+
/* When the requested filter is an allow-list, and the default action is something critical, we
1085+
* install ENOSYS as the default action, but it will only apply to syscalls which are not in the
1086+
* @known set. */
1087+
1088+
if (default_action == SCMP_ACT_ALLOW)
1089+
return default_action;
1090+
1091+
#ifdef SCMP_ACT_LOG
1092+
if (default_action == SCMP_ACT_LOG)
1093+
return default_action;
1094+
#endif
1095+
1096+
return SCMP_ACT_ERRNO(ENOSYS);
1097+
}
1098+
10831099
int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action, bool log_missing) {
1084-
uint32_t arch;
1100+
uint32_t arch, default_action_override;
10851101
int r;
10861102

10871103
assert(set);
10881104

10891105
/* The one-stop solution: allocate a seccomp object, add the specified filter to it, and apply it. Once for
10901106
* each local arch. */
10911107

1108+
default_action_override = override_default_action(default_action);
1109+
10921110
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
10931111
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
1112+
_cleanup_strv_free_ char **added = NULL;
10941113

10951114
log_trace("Operating on architecture: %s", seccomp_arch_to_string(arch));
10961115

1097-
r = seccomp_init_for_arch(&seccomp, arch, default_action);
1116+
r = seccomp_init_for_arch(&seccomp, arch, default_action_override);
10981117
if (r < 0)
10991118
return r;
11001119

1101-
r = add_syscall_filter_set(seccomp, set, action, NULL, log_missing, NULL);
1120+
r = add_syscall_filter_set(seccomp, set, action, NULL, log_missing, &added);
11021121
if (r < 0)
11031122
return log_debug_errno(r, "Failed to add filter set: %m");
11041123

1124+
if (default_action != default_action_override)
1125+
NULSTR_FOREACH(name, syscall_filter_sets[SYSCALL_FILTER_SET_KNOWN].value) {
1126+
int id;
1127+
1128+
id = seccomp_syscall_resolve_name(name);
1129+
if (id < 0)
1130+
continue;
1131+
1132+
/* Ignore the syscall if it was already handled above */
1133+
if (strv_contains(added, name))
1134+
continue;
1135+
1136+
r = seccomp_rule_add_exact(seccomp, default_action, id, 0);
1137+
if (r < 0 && r != -EDOM) /* EDOM means that the syscall is not available for arch */
1138+
return log_debug_errno(r, "Failed to add rule for system call %s() / %d: %m",
1139+
name, id);
1140+
}
1141+
1142+
#if (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR >= 5) || SCMP_VER_MAJOR > 2
1143+
/* We have a large filter here, so let's turn on the binary tree mode if possible. */
1144+
r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_OPTIMIZE, 2);
1145+
if (r < 0)
1146+
log_warning_errno(r, "Failed to set SCMP_FLTATR_CTL_OPTIMIZE, ignoring: %m");
1147+
#endif
1148+
11051149
r = seccomp_load(seccomp);
11061150
if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
11071151
return r;
@@ -1114,7 +1158,7 @@ int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilter
11141158
}
11151159

11161160
int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* filter, uint32_t action, bool log_missing) {
1117-
uint32_t arch;
1161+
uint32_t arch, default_action_override;
11181162
int r;
11191163

11201164
/* Similar to seccomp_load_syscall_filter_set(), but takes a raw Hashmap* of syscalls, instead
@@ -1123,15 +1167,15 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* filter
11231167
if (hashmap_isempty(filter) && default_action == SCMP_ACT_ALLOW)
11241168
return 0;
11251169

1170+
default_action_override = override_default_action(default_action);
1171+
11261172
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
11271173
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
11281174
void *syscall_id, *val;
11291175

11301176
log_trace("Operating on architecture: %s", seccomp_arch_to_string(arch));
11311177

1132-
/* We install ENOSYS as the default action, but it will only apply to syscalls which are not
1133-
* in the @known set. */
1134-
r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ERRNO(ENOSYS));
1178+
r = seccomp_init_for_arch(&seccomp, arch, default_action_override);
11351179
if (r < 0)
11361180
return r;
11371181

@@ -1166,22 +1210,23 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* filter
11661210
}
11671211
}
11681212

1169-
NULSTR_FOREACH(name, syscall_filter_sets[SYSCALL_FILTER_SET_KNOWN].value) {
1170-
int id;
1213+
if (default_action != default_action_override)
1214+
NULSTR_FOREACH(name, syscall_filter_sets[SYSCALL_FILTER_SET_KNOWN].value) {
1215+
int id;
11711216

1172-
id = seccomp_syscall_resolve_name(name);
1173-
if (id < 0)
1174-
continue;
1217+
id = seccomp_syscall_resolve_name(name);
1218+
if (id < 0)
1219+
continue;
11751220

1176-
/* Ignore the syscall if it was already handled above */
1177-
if (hashmap_contains(filter, INT_TO_PTR(id + 1)))
1178-
continue;
1221+
/* Ignore the syscall if it was already handled above */
1222+
if (hashmap_contains(filter, INT_TO_PTR(id + 1)))
1223+
continue;
11791224

1180-
r = seccomp_rule_add_exact(seccomp, default_action, id, 0);
1181-
if (r < 0 && r != -EDOM) /* EDOM means that the syscall is not available for arch */
1182-
return log_debug_errno(r, "Failed to add rule for system call %s() / %d: %m",
1183-
name, id);
1184-
}
1225+
r = seccomp_rule_add_exact(seccomp, default_action, id, 0);
1226+
if (r < 0 && r != -EDOM) /* EDOM means that the syscall is not available for arch */
1227+
return log_debug_errno(r, "Failed to add rule for system call %s() / %d: %m",
1228+
name, id);
1229+
}
11851230

11861231
#if (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR >= 5) || SCMP_VER_MAJOR > 2
11871232
/* We have a large filter here, so let's turn on the binary tree mode if possible. */

0 commit comments

Comments
 (0)