From: Lennart Poettering Date: Tue, 5 Sep 2017 09:16:35 +0000 (+0200) Subject: core: support IP firewalling to be configured for transient units X-Git-Tag: v235~60^2~24 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3dc5ca9787fcc08317d5e6a689cb1e7eb9ba5384;p=platform%2Fupstream%2Fsystemd.git core: support IP firewalling to be configured for transient units --- diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index c1026e3..3bb4108 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -17,6 +17,9 @@ along with systemd; If not, see . ***/ +#include + +#include "af-list.h" #include "alloc-util.h" #include "bus-util.h" #include "cgroup-util.h" @@ -206,6 +209,48 @@ static int property_get_device_allow( return sd_bus_message_close_container(reply); } +static int property_get_ip_address_access( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + IPAddressAccessItem** items = userdata, *i; + int r; + + r = sd_bus_message_open_container(reply, 'a', "(iayu)"); + if (r < 0) + return r; + + LIST_FOREACH(items, i, *items) { + + r = sd_bus_message_open_container(reply, 'r', "iayu"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "i", i->family); + if (r < 0) + return r; + + r = sd_bus_message_append_array(reply, 'y', &i->address, FAMILY_ADDRESS_SIZE(i->family)); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "u", (uint32_t) i->prefixlen); + if (r < 0) + return r; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + const sd_bus_vtable bus_cgroup_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0), @@ -239,6 +284,9 @@ const sd_bus_vtable bus_cgroup_vtable[] = { SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0), SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, tasks_accounting), 0), SD_BUS_PROPERTY("TasksMax", "t", NULL, offsetof(CGroupContext, tasks_max), 0), + SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, ip_accounting), 0), + SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_allow), 0), + SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_deny), 0), SD_BUS_VTABLE_END }; @@ -1133,6 +1181,7 @@ int bus_cgroup_set_property( } return 1; + } else if (streq(name, "TasksMaxScale")) { uint64_t limit; uint32_t raw; @@ -1153,6 +1202,126 @@ int bus_cgroup_set_property( } return 1; + + } else if (streq(name, "IPAccounting")) { + int b; + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + if (mode != UNIT_CHECK) { + c->ip_accounting = b; + + unit_invalidate_cgroup_bpf(u); + unit_write_drop_in_private(u, mode, name, b ? "IPAccounting=yes" : "IPAccounting=no"); + } + + return 1; + + } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) { + IPAddressAccessItem **list; + size_t n = 0; + + list = streq(name, "IPAddressAllow") ? &c->ip_address_allow : &c->ip_address_deny; + + r = sd_bus_message_enter_container(message, 'a', "(iayu)"); + if (r < 0) + return r; + + for (;;) { + const void *ap; + int32_t family; + uint32_t prefixlen; + size_t an; + + r = sd_bus_message_enter_container(message, 'r', "iayu"); + if (r < 0) + return r; + if (r == 0) + break; + + r = sd_bus_message_read(message, "i", &family); + if (r < 0) + return r; + + if (!IN_SET(family, AF_INET, AF_INET6)) + return sd_bus_error_set_errnof(error, EINVAL, "IPAddressAllow= expects IPv4 or IPv6 addresses only."); + + r = sd_bus_message_read_array(message, 'y', &ap, &an); + if (r < 0) + return r; + + if (an != FAMILY_ADDRESS_SIZE(family)) + return sd_bus_error_set_errnof(error, EINVAL, "IP address has wrong size for family (%s, expected %zu, got %zu)", + af_to_name(family), FAMILY_ADDRESS_SIZE(family), an); + + r = sd_bus_message_read(message, "u", &prefixlen); + if (r < 0) + return r; + + if (prefixlen > FAMILY_ADDRESS_SIZE(family)*8) + return sd_bus_error_set_errnof(error, EINVAL, "Prefix length too large for family."); + + if (mode != UNIT_CHECK) { + IPAddressAccessItem *item; + + item = new0(IPAddressAccessItem, 1); + if (!item) + return -ENOMEM; + + item->family = family; + item->prefixlen = prefixlen; + memcpy(&item->address, ap, an); + + LIST_PREPEND(items, *list, item); + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + n++; + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (mode != UNIT_CHECK) { + _cleanup_free_ char *buf = NULL; + _cleanup_fclose_ FILE *f = NULL; + IPAddressAccessItem *item; + size_t size = 0; + + if (n == 0) + *list = ip_address_access_free_all(*list); + + unit_invalidate_cgroup_bpf(u); + f = open_memstream(&buf, &size); + if (!f) + return -ENOMEM; + + fputs_unlocked(name, f); + fputs_unlocked("=\n", f); + + LIST_FOREACH(items, item, *list) { + char buffer[CONST_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)]; + + errno = 0; + if (!inet_ntop(item->family, &item->address, buffer, sizeof(buffer))) + return errno > 0 ? -errno : -EINVAL; + + fprintf(f, "%s=%s/%u\n", name, buffer, item->prefixlen); + } + + r = fflush_and_check(f); + if (r < 0) + return r; + unit_write_drop_in_private(u, mode, name, buf); + } + + return 1; } if (u->transient && u->load_state == UNIT_STUB) { diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index d6b1199..d216df4 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -28,6 +28,8 @@ #include "errno-list.h" #include "escape.h" #include "hashmap.h" +#include "hostname-util.h" +#include "in-addr-util.h" #include "list.h" #include "locale-util.h" #include "mount-util.h" @@ -66,6 +68,31 @@ int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) { &u->job_path); } +static int bus_append_ip_address_access(sd_bus_message *m, int family, const union in_addr_union *prefix, unsigned char prefixlen) { + int r; + + assert(m); + assert(prefix); + + r = sd_bus_message_open_container(m, 'r', "iayu"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "i", family); + if (r < 0) + return r; + + r = sd_bus_message_append_array(m, 'y', prefix, FAMILY_ADDRESS_SIZE(family)); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "u", prefixlen); + if (r < 0) + return r; + + return sd_bus_message_close_container(m); +} + int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) { const char *eq, *field; UnitDependency dep; @@ -207,13 +234,13 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen r = sd_bus_message_append(m, "sv", sn, "t", l.rlim_cur); } else if (STR_IN_SET(field, - "CPUAccounting", "MemoryAccounting", "IOAccounting", "BlockIOAccounting", "TasksAccounting", - "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies", - "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "TTYVTDisallocate", "RemainAfterExit", - "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers", "NoNewPrivileges", - "SyslogLevelPrefix", "Delegate", "RemainAfterElapse", "MemoryDenyWriteExecute", - "RestrictRealtime", "DynamicUser", "RemoveIPC", "ProtectKernelTunables", - "ProtectKernelModules", "ProtectControlGroups", "MountAPIVFS", + "CPUAccounting", "MemoryAccounting", "IOAccounting", "BlockIOAccounting", + "TasksAccounting", "IPAccounting", "SendSIGHUP", "SendSIGKILL", "WakeSystem", + "DefaultDependencies", "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "TTYVTDisallocate", + "RemainAfterExit", "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers", + "NoNewPrivileges", "SyslogLevelPrefix", "Delegate", "RemainAfterElapse", + "MemoryDenyWriteExecute", "RestrictRealtime", "DynamicUser", "RemoveIPC", + "ProtectKernelTunables", "ProtectKernelModules", "ProtectControlGroups", "MountAPIVFS", "CPUSchedulingResetOnFork", "LockPersonality")) { r = parse_boolean(eq); @@ -433,6 +460,98 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen r = sd_bus_message_append(m, "v", "a(st)", 1, path, u); } + } else if (STR_IN_SET(field, "IPAddressAllow", "IPAddressDeny")) { + + if (isempty(eq)) + r = sd_bus_message_append(m, "v", "a(iayu)", 0); + else { + unsigned char prefixlen; + union in_addr_union prefix = {}; + int family; + + r = sd_bus_message_open_container(m, 'v', "a(iayu)"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "(iayu)"); + if (r < 0) + return bus_log_create_error(r); + + if (streq(eq, "any")) { + /* "any" is a shortcut for 0.0.0.0/0 and ::/0 */ + + r = bus_append_ip_address_access(m, AF_INET, &prefix, 0); + if (r < 0) + return bus_log_create_error(r); + + r = bus_append_ip_address_access(m, AF_INET6, &prefix, 0); + if (r < 0) + return bus_log_create_error(r); + + } else if (is_localhost(eq)) { + /* "localhost" is a shortcut for 127.0.0.0/8 and ::1/128 */ + + prefix.in.s_addr = htobe32(0x7f000000); + r = bus_append_ip_address_access(m, AF_INET, &prefix, 8); + if (r < 0) + return bus_log_create_error(r); + + prefix.in6 = (struct in6_addr) IN6ADDR_LOOPBACK_INIT; + r = bus_append_ip_address_access(m, AF_INET6, &prefix, 128); + if (r < 0) + return r; + + } else if (streq(eq, "link-local")) { + + /* "link-local" is a shortcut for 169.254.0.0/16 and fe80::/64 */ + + prefix.in.s_addr = htobe32((UINT32_C(169) << 24 | UINT32_C(254) << 16)); + r = bus_append_ip_address_access(m, AF_INET, &prefix, 16); + if (r < 0) + return bus_log_create_error(r); + + prefix.in6 = (struct in6_addr) { + .__in6_u.__u6_addr32[0] = htobe32(0xfe800000) + }; + r = bus_append_ip_address_access(m, AF_INET6, &prefix, 64); + if (r < 0) + return bus_log_create_error(r); + + } else if (streq(eq, "multicast")) { + + /* "multicast" is a shortcut for 224.0.0.0/4 and ff00::/8 */ + + prefix.in.s_addr = htobe32((UINT32_C(224) << 24)); + r = bus_append_ip_address_access(m, AF_INET, &prefix, 4); + if (r < 0) + return bus_log_create_error(r); + + prefix.in6 = (struct in6_addr) { + .__in6_u.__u6_addr32[0] = htobe32(0xff000000) + }; + r = bus_append_ip_address_access(m, AF_INET6, &prefix, 8); + if (r < 0) + return bus_log_create_error(r); + + } else { + r = in_addr_prefix_from_string_auto(eq, &family, &prefix, &prefixlen); + if (r < 0) + return log_error_errno(r, "Failed to parse IP address prefix: %s", eq); + + r = bus_append_ip_address_access(m, family, &prefix, prefixlen); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + } + } else if (streq(field, "CPUSchedulingPolicy")) { int n;