bool ip_address_allow_localhost;
bool ip_address_allow_other;
+ bool ip_filters_custom_ingress;
+ bool ip_filters_custom_egress;
+
char *keyring_mode;
bool lock_personality;
bool memory_deny_write_execute;
uint64_t restrict_namespaces;
bool restrict_realtime;
+ bool restrict_suid_sgid;
char *root_directory;
char *root_image;
const char *url;
uint64_t weight;
uint64_t range;
- int (*assess)(const struct security_assessor *a, const struct security_info *info, const void *data, uint64_t *ret_badness, char **ret_description);
+ int (*assess)(
+ const struct security_assessor *a,
+ const struct security_info *info,
+ const void *data,
+ uint64_t *ret_badness,
+ char **ret_description);
size_t offset;
uint64_t parameter;
bool default_dependencies_only;
assert(ret_badness);
assert(ret_description);
- if (!info->ip_address_deny_all) {
+ if (info->ip_filters_custom_ingress || info->ip_filters_custom_egress) {
+ d = strdup("Service defines custom ingress/egress IP filters with BPF programs");
+ b = 0;
+ } else if (!info->ip_address_deny_all) {
d = strdup("Service does not define an IP address whitelist");
b = 10;
} else if (info->ip_address_allow_other) {
d = strdup("Service defines IP address whitelist with non-localhost entries");
b = 5;
} else if (info->ip_address_allow_localhost) {
- d = strdup("Service defines IP address whitelits with only localhost entries");
+ d = strdup("Service defines IP address whitelist with only localhost entries");
b = 2;
} else {
d = strdup("Service blocks all IP address ranges");
.assess = assess_bool,
.offset = offsetof(struct security_info, restrict_realtime),
},
+ {
+ .id = "RestrictSUIDSGID=",
+ .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictSUIDSGID=",
+ .description_good = "SUID/SGID file creation by service is restricted",
+ .description_bad = "Service may create SUID/SGID files",
+ .weight = 1000,
+ .range = 1,
+ .assess = assess_bool,
+ .offset = offsetof(struct security_info, restrict_suid_sgid),
+ },
{
.id = "RestrictNamespaces=~CLONE_NEWUSER",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
uint64_t badness;
void *data;
- data = (uint8_t*) info + a->offset;
+ data = (uint8_t *) info + a->offset;
if (a->default_dependencies_only && !info->default_dependencies) {
badness = UINT64_MAX;
if (color)
(void) table_set_color(details_table, cell, color);
- r = table_add_cell(details_table, &cell, TABLE_STRING, a->id);
- if (r < 0)
- return log_error_errno(r, "Failed to add cell to table: %m");
- if (a->url)
- (void) table_set_url(details_table, cell, a->url);
-
- r = table_add_cell(details_table, NULL, TABLE_STRING, description);
- if (r < 0)
- return log_error_errno(r, "Failed to add cell to table: %m");
-
- r = table_add_cell(details_table, &cell, TABLE_UINT64, &a->weight);
- if (r < 0)
- return log_error_errno(r, "Failed to add cell to table: %m");
- (void) table_set_align_percent(details_table, cell, 100);
-
- r = table_add_cell(details_table, &cell, TABLE_UINT64, &badness);
- if (r < 0)
- return log_error_errno(r, "Failed to add cell to table: %m");
- (void) table_set_align_percent(details_table, cell, 100);
-
- r = table_add_cell(details_table, &cell, TABLE_UINT64, &a->range);
- if (r < 0)
- return log_error_errno(r, "Failed to add cell to table: %m");
- (void) table_set_align_percent(details_table, cell, 100);
-
- r = table_add_cell(details_table, &cell, TABLE_EMPTY, NULL);
+ r = table_add_many(details_table,
+ TABLE_STRING, a->id, TABLE_SET_URL, a->url,
+ TABLE_STRING, description,
+ TABLE_UINT64, a->weight, TABLE_SET_ALIGN_PERCENT, 100,
+ TABLE_UINT64, badness, TABLE_SET_ALIGN_PERCENT, 100,
+ TABLE_UINT64, a->range, TABLE_SET_ALIGN_PERCENT, 100,
+ TABLE_EMPTY, TABLE_SET_ALIGN_PERCENT, 100);
if (r < 0)
- return log_error_errno(r, "Failed to add cell to table: %m");
- (void) table_set_align_percent(details_table, cell, 100);
+ return log_error_errno(r, "Failed to add cells to table: %m");
}
}
+ assert(weight_sum > 0);
+
if (details_table) {
size_t row;
return log_error_errno(r, "Failed to output table: %m");
}
- assert(weight_sum > 0);
exposure = DIV_ROUND_UP(badness_sum * 100U, weight_sum);
for (i = 0; i < ELEMENTSOF(badness_table); i++)
return sd_bus_message_exit_container(m);
}
+static int property_read_ip_filters(
+ sd_bus *bus,
+ const char *member,
+ sd_bus_message *m,
+ sd_bus_error *error,
+ void *userdata) {
+
+ struct security_info *info = userdata;
+ _cleanup_(strv_freep) char **l = NULL;
+ int r;
+
+ assert(bus);
+ assert(member);
+ assert(m);
+
+ r = sd_bus_message_read_strv(m, &l);
+ if (r < 0)
+ return r;
+
+ if (streq(member, "IPIngressFilterPath"))
+ info->ip_filters_custom_ingress = !strv_isempty(l);
+ else if (streq(member, "IPEgressFilterPath"))
+ info->ip_filters_custom_ingress = !strv_isempty(l);
+
+ return 0;
+}
+
static int property_read_device_allow(
sd_bus *bus,
const char *member,
{ "FragmentPath", "s", NULL, offsetof(struct security_info, fragment_path) },
{ "IPAddressAllow", "a(iayu)", property_read_ip_address_allow, 0 },
{ "IPAddressDeny", "a(iayu)", property_read_ip_address_allow, 0 },
+ { "IPIngressFilterPath", "as", property_read_ip_filters, 0 },
+ { "IPEgressFilterPath", "as", property_read_ip_filters, 0 },
{ "Id", "s", NULL, offsetof(struct security_info, id) },
{ "KeyringMode", "s", NULL, offsetof(struct security_info, keyring_mode) },
{ "LoadState", "s", NULL, offsetof(struct security_info, load_state) },
{ "RestrictAddressFamilies", "(bas)", property_read_restrict_address_families, 0 },
{ "RestrictNamespaces", "t", NULL, offsetof(struct security_info, restrict_namespaces) },
{ "RestrictRealtime", "b", NULL, offsetof(struct security_info, restrict_realtime) },
+ { "RestrictSUIDSGID", "b", NULL, offsetof(struct security_info, restrict_suid_sgid) },
{ "RootDirectory", "s", NULL, offsetof(struct security_info, root_directory) },
{ "RootImage", "s", NULL, offsetof(struct security_info, root_image) },
{ "SupplementaryGroups", "as", NULL, offsetof(struct security_info, supplementary_groups) },
if (!path)
return log_oom();
- r = bus_map_all_properties(bus,
- "org.freedesktop.systemd1",
- path,
- security_map,
- BUS_MAP_STRDUP|BUS_MAP_BOOLEAN_AS_BOOL,
- &error,
- NULL,
- info);
+ r = bus_map_all_properties(
+ bus,
+ "org.freedesktop.systemd1",
+ path,
+ security_map,
+ BUS_MAP_STRDUP | BUS_MAP_BOOLEAN_AS_BOOL,
+ &error,
+ NULL,
+ info);
if (r < 0)
return log_error_errno(r, "Failed to get unit properties: %s", bus_error_message(&error, r));
return 0;
}
-static int analyze_security_one(sd_bus *bus, const char *name, Table* overview_table, AnalyzeSecurityFlags flags) {
+static int analyze_security_one(sd_bus *bus, const char *name, Table *overview_table, AnalyzeSecurityFlags flags) {
_cleanup_(security_info_free) struct security_info info = {
.default_dependencies = true,
.capability_bounding_set = UINT64_MAX,
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"ListUnits",
- &error, &reply,
+ &error,
+ &reply,
NULL);
if (r < 0)
return log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r));
if (!endswith(info.id, ".service"))
continue;
- if (!GREEDY_REALLOC(list, allocated, n+2))
+ if (!GREEDY_REALLOC(list, allocated, n + 2))
return log_oom();
copy = strdup(info.id);