@@ -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+
10831099int 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
11161160int 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