1 /* SPDX-License-Identifier: LGPL-2.1+ */
6 #include "alloc-util.h"
7 #include "bpf-firewall.h"
9 #include "cgroup-util.h"
11 #include "dbus-cgroup.h"
12 #include "dbus-util.h"
15 #include "limits-util.h"
16 #include "path-util.h"
18 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy
, cgroup_device_policy
, CGroupDevicePolicy
);
20 static int property_get_cgroup_mask(
23 const char *interface
,
25 sd_bus_message
*reply
,
27 sd_bus_error
*error
) {
29 CGroupMask
*mask
= userdata
;
30 CGroupController ctrl
;
36 r
= sd_bus_message_open_container(reply
, 'a', "s");
40 for (ctrl
= 0; ctrl
< _CGROUP_CONTROLLER_MAX
; ctrl
++) {
41 if ((*mask
& CGROUP_CONTROLLER_TO_MASK(ctrl
)) == 0)
44 r
= sd_bus_message_append(reply
, "s", cgroup_controller_to_string(ctrl
));
49 return sd_bus_message_close_container(reply
);
52 static int property_get_delegate_controllers(
55 const char *interface
,
57 sd_bus_message
*reply
,
59 sd_bus_error
*error
) {
61 CGroupContext
*c
= userdata
;
68 return sd_bus_message_append(reply
, "as", 0);
70 return property_get_cgroup_mask(bus
, path
, interface
, property
, reply
, &c
->delegate_controllers
, error
);
73 static int property_get_io_device_weight(
76 const char *interface
,
78 sd_bus_message
*reply
,
80 sd_bus_error
*error
) {
82 CGroupContext
*c
= userdata
;
83 CGroupIODeviceWeight
*w
;
90 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
94 LIST_FOREACH(device_weights
, w
, c
->io_device_weights
) {
95 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
100 return sd_bus_message_close_container(reply
);
103 static int property_get_io_device_limits(
106 const char *interface
,
107 const char *property
,
108 sd_bus_message
*reply
,
110 sd_bus_error
*error
) {
112 CGroupContext
*c
= userdata
;
113 CGroupIODeviceLimit
*l
;
120 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
124 LIST_FOREACH(device_limits
, l
, c
->io_device_limits
) {
125 CGroupIOLimitType type
;
127 type
= cgroup_io_limit_type_from_string(property
);
128 if (type
< 0 || l
->limits
[type
] == cgroup_io_limit_defaults
[type
])
131 r
= sd_bus_message_append(reply
, "(st)", l
->path
, l
->limits
[type
]);
136 return sd_bus_message_close_container(reply
);
139 static int property_get_io_device_latency(
142 const char *interface
,
143 const char *property
,
144 sd_bus_message
*reply
,
146 sd_bus_error
*error
) {
148 CGroupContext
*c
= userdata
;
149 CGroupIODeviceLatency
*l
;
156 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
160 LIST_FOREACH(device_latencies
, l
, c
->io_device_latencies
) {
161 r
= sd_bus_message_append(reply
, "(st)", l
->path
, l
->target_usec
);
166 return sd_bus_message_close_container(reply
);
169 static int property_get_blockio_device_weight(
172 const char *interface
,
173 const char *property
,
174 sd_bus_message
*reply
,
176 sd_bus_error
*error
) {
178 CGroupContext
*c
= userdata
;
179 CGroupBlockIODeviceWeight
*w
;
186 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
190 LIST_FOREACH(device_weights
, w
, c
->blockio_device_weights
) {
191 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
196 return sd_bus_message_close_container(reply
);
199 static int property_get_blockio_device_bandwidths(
202 const char *interface
,
203 const char *property
,
204 sd_bus_message
*reply
,
206 sd_bus_error
*error
) {
208 CGroupContext
*c
= userdata
;
209 CGroupBlockIODeviceBandwidth
*b
;
216 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
220 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
223 if (streq(property
, "BlockIOReadBandwidth"))
228 if (v
== CGROUP_LIMIT_MAX
)
231 r
= sd_bus_message_append(reply
, "(st)", b
->path
, v
);
236 return sd_bus_message_close_container(reply
);
239 static int property_get_device_allow(
242 const char *interface
,
243 const char *property
,
244 sd_bus_message
*reply
,
246 sd_bus_error
*error
) {
248 CGroupContext
*c
= userdata
;
249 CGroupDeviceAllow
*a
;
256 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
260 LIST_FOREACH(device_allow
, a
, c
->device_allow
) {
273 r
= sd_bus_message_append(reply
, "(ss)", a
->path
, rwm
);
278 return sd_bus_message_close_container(reply
);
281 static int property_get_ip_address_access(
284 const char *interface
,
285 const char *property
,
286 sd_bus_message
*reply
,
288 sd_bus_error
*error
) {
290 IPAddressAccessItem
** items
= userdata
, *i
;
293 r
= sd_bus_message_open_container(reply
, 'a', "(iayu)");
297 LIST_FOREACH(items
, i
, *items
) {
299 r
= sd_bus_message_open_container(reply
, 'r', "iayu");
303 r
= sd_bus_message_append(reply
, "i", i
->family
);
307 r
= sd_bus_message_append_array(reply
, 'y', &i
->address
, FAMILY_ADDRESS_SIZE(i
->family
));
311 r
= sd_bus_message_append(reply
, "u", (uint32_t) i
->prefixlen
);
315 r
= sd_bus_message_close_container(reply
);
320 return sd_bus_message_close_container(reply
);
323 const sd_bus_vtable bus_cgroup_vtable
[] = {
324 SD_BUS_VTABLE_START(0),
325 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool
, offsetof(CGroupContext
, delegate
), 0),
326 SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers
, 0, 0),
327 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, cpu_accounting
), 0),
328 SD_BUS_PROPERTY("CPUWeight", "t", NULL
, offsetof(CGroupContext
, cpu_weight
), 0),
329 SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL
, offsetof(CGroupContext
, startup_cpu_weight
), 0),
330 SD_BUS_PROPERTY("CPUShares", "t", NULL
, offsetof(CGroupContext
, cpu_shares
), 0),
331 SD_BUS_PROPERTY("StartupCPUShares", "t", NULL
, offsetof(CGroupContext
, startup_cpu_shares
), 0),
332 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, cpu_quota_per_sec_usec
), 0),
333 SD_BUS_PROPERTY("CPUQuotaPeriodUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, cpu_quota_period_usec
), 0),
334 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, io_accounting
), 0),
335 SD_BUS_PROPERTY("IOWeight", "t", NULL
, offsetof(CGroupContext
, io_weight
), 0),
336 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_io_weight
), 0),
337 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight
, 0, 0),
338 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
339 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
340 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
341 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
342 SD_BUS_PROPERTY("IODeviceLatencyTargetUSec", "a(st)", property_get_io_device_latency
, 0, 0),
343 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, blockio_accounting
), 0),
344 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL
, offsetof(CGroupContext
, blockio_weight
), 0),
345 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_blockio_weight
), 0),
346 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight
, 0, 0),
347 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
348 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
349 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, memory_accounting
), 0),
350 SD_BUS_PROPERTY("DefaultMemoryLow", "t", NULL
, offsetof(CGroupContext
, default_memory_low
), 0),
351 SD_BUS_PROPERTY("DefaultMemoryMin", "t", NULL
, offsetof(CGroupContext
, default_memory_min
), 0),
352 SD_BUS_PROPERTY("MemoryMin", "t", NULL
, offsetof(CGroupContext
, memory_min
), 0),
353 SD_BUS_PROPERTY("MemoryLow", "t", NULL
, offsetof(CGroupContext
, memory_low
), 0),
354 SD_BUS_PROPERTY("MemoryHigh", "t", NULL
, offsetof(CGroupContext
, memory_high
), 0),
355 SD_BUS_PROPERTY("MemoryMax", "t", NULL
, offsetof(CGroupContext
, memory_max
), 0),
356 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL
, offsetof(CGroupContext
, memory_swap_max
), 0),
357 SD_BUS_PROPERTY("MemoryLimit", "t", NULL
, offsetof(CGroupContext
, memory_limit
), 0),
358 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy
, offsetof(CGroupContext
, device_policy
), 0),
359 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow
, 0, 0),
360 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, tasks_accounting
), 0),
361 SD_BUS_PROPERTY("TasksMax", "t", NULL
, offsetof(CGroupContext
, tasks_max
), 0),
362 SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, ip_accounting
), 0),
363 SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_allow
), 0),
364 SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_deny
), 0),
365 SD_BUS_PROPERTY("DisableControllers", "as", property_get_cgroup_mask
, offsetof(CGroupContext
, disable_controllers
), 0),
369 static int bus_cgroup_set_transient_property(
373 sd_bus_message
*message
,
374 UnitWriteFlags flags
,
375 sd_bus_error
*error
) {
384 flags
|= UNIT_PRIVATE
;
386 if (streq(name
, "Delegate")) {
389 if (!UNIT_VTABLE(u
)->can_delegate
)
390 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
392 r
= sd_bus_message_read(message
, "b", &b
);
396 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
398 c
->delegate_controllers
= b
? _CGROUP_MASK_ALL
: 0;
400 unit_write_settingf(u
, flags
, name
, "Delegate=%s", yes_no(b
));
405 } else if (STR_IN_SET(name
, "DelegateControllers", "DisableControllers")) {
408 if (streq(name
, "DelegateControllers") && !UNIT_VTABLE(u
)->can_delegate
)
409 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
411 r
= sd_bus_message_enter_container(message
, 'a', "s");
419 r
= sd_bus_message_read(message
, "s", &t
);
425 cc
= cgroup_controller_from_string(t
);
427 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown cgroup controller '%s'", t
);
429 mask
|= CGROUP_CONTROLLER_TO_MASK(cc
);
432 r
= sd_bus_message_exit_container(message
);
436 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
437 _cleanup_free_
char *t
= NULL
;
439 r
= cg_mask_to_string(mask
, &t
);
443 if (streq(name
, "DelegateControllers")) {
447 c
->delegate_controllers
= 0;
449 c
->delegate_controllers
|= mask
;
451 unit_write_settingf(u
, flags
, name
, "Delegate=%s", strempty(t
));
453 } else if (streq(name
, "DisableControllers")) {
456 c
->disable_controllers
= 0;
458 c
->disable_controllers
|= mask
;
460 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, strempty(t
));
470 static int bus_cgroup_set_boolean(
475 sd_bus_message
*message
,
476 UnitWriteFlags flags
,
477 sd_bus_error
*error
) {
483 r
= sd_bus_message_read(message
, "b", &b
);
487 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
489 unit_invalidate_cgroup(u
, mask
);
490 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, yes_no(b
));
496 #define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val) \
497 static int bus_cgroup_set_##function( \
501 sd_bus_message *message, \
502 UnitWriteFlags flags, \
503 sd_bus_error *error) { \
510 r = sd_bus_message_read(message, "t", &v); \
515 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
516 "Value specified in %s is out of range", name); \
518 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
520 unit_invalidate_cgroup(u, (mask)); \
523 unit_write_settingf(u, flags, name, \
526 unit_write_settingf(u, flags, name, \
527 "%s=%" PRIu64, name, v); \
533 #define BUS_DEFINE_SET_CGROUP_LIMIT(function, mask, scale, minimum) \
534 static int bus_cgroup_set_##function( \
538 sd_bus_message *message, \
539 UnitWriteFlags flags, \
540 sd_bus_error *error) { \
547 r = sd_bus_message_read(message, "t", &v); \
552 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
553 "Value specified in %s is out of range", name); \
555 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
557 unit_invalidate_cgroup(u, (mask)); \
559 if (v == CGROUP_LIMIT_MAX) \
560 unit_write_settingf(u, flags, name, \
561 "%s=infinity", name); \
563 unit_write_settingf(u, flags, name, \
564 "%s=%" PRIu64, name, v); \
569 static int bus_cgroup_set_##function##_scale( \
573 sd_bus_message *message, \
574 UnitWriteFlags flags, \
575 sd_bus_error *error) { \
583 r = sd_bus_message_read(message, "u", &raw); \
587 v = scale(raw, UINT32_MAX); \
588 if (v < minimum || v >= UINT64_MAX) \
589 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
590 "Value specified in %s is out of range", name); \
592 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
596 unit_invalidate_cgroup(u, (mask)); \
598 /* Chop off suffix */ \
599 assert_se(e = endswith(name, "Scale")); \
600 name = strndupa(name, e - name); \
602 unit_write_settingf(u, flags, name, "%s=%" PRIu32 "%%", name, \
603 (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX))); \
609 #pragma GCC diagnostic push
610 #pragma GCC diagnostic ignored "-Wtype-limits"
611 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight
, CGROUP_MASK_CPU
, CGROUP_WEIGHT_IS_OK
, CGROUP_WEIGHT_INVALID
);
612 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares
, CGROUP_MASK_CPU
, CGROUP_CPU_SHARES_IS_OK
, CGROUP_CPU_SHARES_INVALID
);
613 BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight
, CGROUP_MASK_IO
, CGROUP_WEIGHT_IS_OK
, CGROUP_WEIGHT_INVALID
);
614 BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight
, CGROUP_MASK_BLKIO
, CGROUP_BLKIO_WEIGHT_IS_OK
, CGROUP_BLKIO_WEIGHT_INVALID
);
615 BUS_DEFINE_SET_CGROUP_LIMIT(memory
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 1);
616 BUS_DEFINE_SET_CGROUP_LIMIT(memory_protection
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 0);
617 BUS_DEFINE_SET_CGROUP_LIMIT(swap
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 0);
618 BUS_DEFINE_SET_CGROUP_LIMIT(tasks_max
, CGROUP_MASK_PIDS
, system_tasks_max_scale
, 1);
619 #pragma GCC diagnostic pop
621 int bus_cgroup_set_property(
625 sd_bus_message
*message
,
626 UnitWriteFlags flags
,
627 sd_bus_error
*error
) {
629 CGroupIOLimitType iol_type
;
637 flags
|= UNIT_PRIVATE
;
639 if (streq(name
, "CPUAccounting"))
640 return bus_cgroup_set_boolean(u
, name
, &c
->cpu_accounting
, get_cpu_accounting_mask(), message
, flags
, error
);
642 if (streq(name
, "CPUWeight"))
643 return bus_cgroup_set_cpu_weight(u
, name
, &c
->cpu_weight
, message
, flags
, error
);
645 if (streq(name
, "StartupCPUWeight"))
646 return bus_cgroup_set_cpu_weight(u
, name
, &c
->startup_cpu_weight
, message
, flags
, error
);
648 if (streq(name
, "CPUShares"))
649 return bus_cgroup_set_cpu_shares(u
, name
, &c
->cpu_shares
, message
, flags
, error
);
651 if (streq(name
, "StartupCPUShares"))
652 return bus_cgroup_set_cpu_shares(u
, name
, &c
->startup_cpu_shares
, message
, flags
, error
);
654 if (streq(name
, "IOAccounting"))
655 return bus_cgroup_set_boolean(u
, name
, &c
->io_accounting
, CGROUP_MASK_IO
, message
, flags
, error
);
657 if (streq(name
, "IOWeight"))
658 return bus_cgroup_set_io_weight(u
, name
, &c
->io_weight
, message
, flags
, error
);
660 if (streq(name
, "StartupIOWeight"))
661 return bus_cgroup_set_io_weight(u
, name
, &c
->startup_io_weight
, message
, flags
, error
);
663 if (streq(name
, "BlockIOAccounting"))
664 return bus_cgroup_set_boolean(u
, name
, &c
->blockio_accounting
, CGROUP_MASK_BLKIO
, message
, flags
, error
);
666 if (streq(name
, "BlockIOWeight"))
667 return bus_cgroup_set_blockio_weight(u
, name
, &c
->blockio_weight
, message
, flags
, error
);
669 if (streq(name
, "StartupBlockIOWeight"))
670 return bus_cgroup_set_blockio_weight(u
, name
, &c
->startup_blockio_weight
, message
, flags
, error
);
672 if (streq(name
, "MemoryAccounting"))
673 return bus_cgroup_set_boolean(u
, name
, &c
->memory_accounting
, CGROUP_MASK_MEMORY
, message
, flags
, error
);
675 if (streq(name
, "MemoryMin"))
676 return bus_cgroup_set_memory_protection(u
, name
, &c
->memory_min
, message
, flags
, error
);
678 if (streq(name
, "MemoryLow"))
679 return bus_cgroup_set_memory_protection(u
, name
, &c
->memory_low
, message
, flags
, error
);
681 if (streq(name
, "DefaultMemoryMin"))
682 return bus_cgroup_set_memory_protection(u
, name
, &c
->default_memory_min
, message
, flags
, error
);
684 if (streq(name
, "DefaultMemoryLow"))
685 return bus_cgroup_set_memory_protection(u
, name
, &c
->default_memory_low
, message
, flags
, error
);
687 if (streq(name
, "MemoryHigh"))
688 return bus_cgroup_set_memory(u
, name
, &c
->memory_high
, message
, flags
, error
);
690 if (streq(name
, "MemorySwapMax"))
691 return bus_cgroup_set_swap(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
693 if (streq(name
, "MemoryMax"))
694 return bus_cgroup_set_memory(u
, name
, &c
->memory_max
, message
, flags
, error
);
696 if (streq(name
, "MemoryLimit"))
697 return bus_cgroup_set_memory(u
, name
, &c
->memory_limit
, message
, flags
, error
);
699 if (streq(name
, "MemoryMinScale"))
700 return bus_cgroup_set_memory_protection_scale(u
, name
, &c
->memory_min
, message
, flags
, error
);
702 if (streq(name
, "MemoryLowScale"))
703 return bus_cgroup_set_memory_protection_scale(u
, name
, &c
->memory_low
, message
, flags
, error
);
705 if (streq(name
, "DefaultMemoryMinScale"))
706 return bus_cgroup_set_memory_protection_scale(u
, name
, &c
->default_memory_min
, message
, flags
, error
);
708 if (streq(name
, "DefaultMemoryLowScale"))
709 return bus_cgroup_set_memory_protection_scale(u
, name
, &c
->default_memory_low
, message
, flags
, error
);
711 if (streq(name
, "MemoryHighScale"))
712 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_high
, message
, flags
, error
);
714 if (streq(name
, "MemorySwapMaxScale"))
715 return bus_cgroup_set_swap_scale(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
717 if (streq(name
, "MemoryMaxScale"))
718 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_max
, message
, flags
, error
);
720 if (streq(name
, "MemoryLimitScale"))
721 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_limit
, message
, flags
, error
);
723 if (streq(name
, "TasksAccounting"))
724 return bus_cgroup_set_boolean(u
, name
, &c
->tasks_accounting
, CGROUP_MASK_PIDS
, message
, flags
, error
);
726 if (streq(name
, "TasksMax"))
727 return bus_cgroup_set_tasks_max(u
, name
, &c
->tasks_max
, message
, flags
, error
);
729 if (streq(name
, "TasksMaxScale"))
730 return bus_cgroup_set_tasks_max_scale(u
, name
, &c
->tasks_max
, message
, flags
, error
);
732 if (streq(name
, "CPUQuotaPerSecUSec")) {
735 r
= sd_bus_message_read(message
, "t", &u64
);
740 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "CPUQuotaPerSecUSec= value out of range");
742 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
743 c
->cpu_quota_per_sec_usec
= u64
;
744 u
->warned_clamping_cpu_quota_period
= false;
745 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
747 if (c
->cpu_quota_per_sec_usec
== USEC_INFINITY
)
748 unit_write_setting(u
, flags
, "CPUQuota", "CPUQuota=");
750 /* config_parse_cpu_quota() requires an integer, so truncating division is used on
752 unit_write_settingf(u
, flags
, "CPUQuota",
754 (double) (c
->cpu_quota_per_sec_usec
/ 10000));
759 } else if (streq(name
, "CPUQuotaPeriodUSec")) {
762 r
= sd_bus_message_read(message
, "t", &u64
);
766 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
767 c
->cpu_quota_period_usec
= u64
;
768 u
->warned_clamping_cpu_quota_period
= false;
769 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
770 if (c
->cpu_quota_period_usec
== USEC_INFINITY
)
771 unit_write_setting(u
, flags
, "CPUQuotaPeriodSec", "CPUQuotaPeriodSec=");
773 char v
[FORMAT_TIMESPAN_MAX
];
774 unit_write_settingf(u
, flags
, "CPUQuotaPeriodSec",
775 "CPUQuotaPeriodSec=%s",
776 format_timespan(v
, sizeof(v
), c
->cpu_quota_period_usec
, 1));
782 } else if ((iol_type
= cgroup_io_limit_type_from_string(name
)) >= 0) {
787 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
791 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
793 if (!path_is_normalized(path
))
794 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
796 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
797 CGroupIODeviceLimit
*a
= NULL
, *b
;
799 LIST_FOREACH(device_limits
, b
, c
->io_device_limits
) {
800 if (path_equal(path
, b
->path
)) {
807 CGroupIOLimitType type
;
809 a
= new0(CGroupIODeviceLimit
, 1);
813 a
->path
= strdup(path
);
819 for (type
= 0; type
< _CGROUP_IO_LIMIT_TYPE_MAX
; type
++)
820 a
->limits
[type
] = cgroup_io_limit_defaults
[type
];
822 LIST_PREPEND(device_limits
, c
->io_device_limits
, a
);
825 a
->limits
[iol_type
] = u64
;
833 r
= sd_bus_message_exit_container(message
);
837 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
838 CGroupIODeviceLimit
*a
;
839 _cleanup_free_
char *buf
= NULL
;
840 _cleanup_fclose_
FILE *f
= NULL
;
844 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
845 a
->limits
[iol_type
] = cgroup_io_limit_defaults
[iol_type
];
848 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
850 f
= open_memstream_unlocked(&buf
, &size
);
854 fprintf(f
, "%s=\n", name
);
855 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
856 if (a
->limits
[iol_type
] != cgroup_io_limit_defaults
[iol_type
])
857 fprintf(f
, "%s=%s %" PRIu64
"\n", name
, a
->path
, a
->limits
[iol_type
]);
859 r
= fflush_and_check(f
);
862 unit_write_setting(u
, flags
, name
, buf
);
867 } else if (streq(name
, "IODeviceWeight")) {
872 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
876 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
878 if (!path_is_normalized(path
))
879 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
881 if (!CGROUP_WEIGHT_IS_OK(weight
) || weight
== CGROUP_WEIGHT_INVALID
)
882 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "IODeviceWeight= value out of range");
884 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
885 CGroupIODeviceWeight
*a
= NULL
, *b
;
887 LIST_FOREACH(device_weights
, b
, c
->io_device_weights
) {
888 if (path_equal(b
->path
, path
)) {
895 a
= new0(CGroupIODeviceWeight
, 1);
899 a
->path
= strdup(path
);
904 LIST_PREPEND(device_weights
, c
->io_device_weights
, a
);
913 r
= sd_bus_message_exit_container(message
);
917 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
918 _cleanup_free_
char *buf
= NULL
;
919 _cleanup_fclose_
FILE *f
= NULL
;
920 CGroupIODeviceWeight
*a
;
924 while (c
->io_device_weights
)
925 cgroup_context_free_io_device_weight(c
, c
->io_device_weights
);
928 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
930 f
= open_memstream_unlocked(&buf
, &size
);
934 fputs("IODeviceWeight=\n", f
);
935 LIST_FOREACH(device_weights
, a
, c
->io_device_weights
)
936 fprintf(f
, "IODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
938 r
= fflush_and_check(f
);
941 unit_write_setting(u
, flags
, name
, buf
);
946 } else if (streq(name
, "IODeviceLatencyTargetUSec")) {
951 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
955 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &target
)) > 0) {
957 if (!path_is_normalized(path
))
958 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
960 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
961 CGroupIODeviceLatency
*a
= NULL
, *b
;
963 LIST_FOREACH(device_latencies
, b
, c
->io_device_latencies
) {
964 if (path_equal(b
->path
, path
)) {
971 a
= new0(CGroupIODeviceLatency
, 1);
975 a
->path
= strdup(path
);
980 LIST_PREPEND(device_latencies
, c
->io_device_latencies
, a
);
983 a
->target_usec
= target
;
989 r
= sd_bus_message_exit_container(message
);
993 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
994 _cleanup_free_
char *buf
= NULL
;
995 _cleanup_fclose_
FILE *f
= NULL
;
996 char ts
[FORMAT_TIMESPAN_MAX
];
997 CGroupIODeviceLatency
*a
;
1001 while (c
->io_device_latencies
)
1002 cgroup_context_free_io_device_latency(c
, c
->io_device_latencies
);
1005 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
1007 f
= open_memstream_unlocked(&buf
, &size
);
1011 fputs("IODeviceLatencyTargetSec=\n", f
);
1012 LIST_FOREACH(device_latencies
, a
, c
->io_device_latencies
)
1013 fprintf(f
, "IODeviceLatencyTargetSec=%s %s\n",
1014 a
->path
, format_timespan(ts
, sizeof(ts
), a
->target_usec
, 1));
1016 r
= fflush_and_check(f
);
1019 unit_write_setting(u
, flags
, name
, buf
);
1024 } else if (STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1030 if (streq(name
, "BlockIOWriteBandwidth"))
1033 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1037 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
1039 if (!path_is_normalized(path
))
1040 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1042 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1043 CGroupBlockIODeviceBandwidth
*a
= NULL
, *b
;
1045 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
1046 if (path_equal(path
, b
->path
)) {
1053 a
= new0(CGroupBlockIODeviceBandwidth
, 1);
1057 a
->rbps
= CGROUP_LIMIT_MAX
;
1058 a
->wbps
= CGROUP_LIMIT_MAX
;
1059 a
->path
= strdup(path
);
1065 LIST_PREPEND(device_bandwidths
, c
->blockio_device_bandwidths
, a
);
1079 r
= sd_bus_message_exit_container(message
);
1083 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1084 CGroupBlockIODeviceBandwidth
*a
;
1085 _cleanup_free_
char *buf
= NULL
;
1086 _cleanup_fclose_
FILE *f
= NULL
;
1090 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
) {
1092 a
->rbps
= CGROUP_LIMIT_MAX
;
1094 a
->wbps
= CGROUP_LIMIT_MAX
;
1098 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
1100 f
= open_memstream_unlocked(&buf
, &size
);
1105 fputs("BlockIOReadBandwidth=\n", f
);
1106 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
1107 if (a
->rbps
!= CGROUP_LIMIT_MAX
)
1108 fprintf(f
, "BlockIOReadBandwidth=%s %" PRIu64
"\n", a
->path
, a
->rbps
);
1110 fputs("BlockIOWriteBandwidth=\n", f
);
1111 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
1112 if (a
->wbps
!= CGROUP_LIMIT_MAX
)
1113 fprintf(f
, "BlockIOWriteBandwidth=%s %" PRIu64
"\n", a
->path
, a
->wbps
);
1116 r
= fflush_and_check(f
);
1120 unit_write_setting(u
, flags
, name
, buf
);
1125 } else if (streq(name
, "BlockIODeviceWeight")) {
1130 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1134 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
1136 if (!path_is_normalized(path
))
1137 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1139 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
) || weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
1140 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "BlockIODeviceWeight= out of range");
1142 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1143 CGroupBlockIODeviceWeight
*a
= NULL
, *b
;
1145 LIST_FOREACH(device_weights
, b
, c
->blockio_device_weights
) {
1146 if (path_equal(b
->path
, path
)) {
1153 a
= new0(CGroupBlockIODeviceWeight
, 1);
1157 a
->path
= strdup(path
);
1162 LIST_PREPEND(device_weights
, c
->blockio_device_weights
, a
);
1171 r
= sd_bus_message_exit_container(message
);
1175 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1176 _cleanup_free_
char *buf
= NULL
;
1177 _cleanup_fclose_
FILE *f
= NULL
;
1178 CGroupBlockIODeviceWeight
*a
;
1182 while (c
->blockio_device_weights
)
1183 cgroup_context_free_blockio_device_weight(c
, c
->blockio_device_weights
);
1186 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
1188 f
= open_memstream_unlocked(&buf
, &size
);
1192 fputs("BlockIODeviceWeight=\n", f
);
1193 LIST_FOREACH(device_weights
, a
, c
->blockio_device_weights
)
1194 fprintf(f
, "BlockIODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
1196 r
= fflush_and_check(f
);
1200 unit_write_setting(u
, flags
, name
, buf
);
1205 } else if (streq(name
, "DevicePolicy")) {
1207 CGroupDevicePolicy p
;
1209 r
= sd_bus_message_read(message
, "s", &policy
);
1213 p
= cgroup_device_policy_from_string(policy
);
1217 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1218 c
->device_policy
= p
;
1219 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1220 unit_write_settingf(u
, flags
, name
, "DevicePolicy=%s", policy
);
1225 } else if (streq(name
, "DeviceAllow")) {
1226 const char *path
, *rwm
;
1229 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
1233 while ((r
= sd_bus_message_read(message
, "(ss)", &path
, &rwm
)) > 0) {
1235 if (!valid_device_allow_pattern(path
) || strpbrk(path
, WHITESPACE
))
1236 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires device node or pattern");
1240 else if (!in_charset(rwm
, "rwm"))
1241 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires combination of rwm flags");
1243 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1244 CGroupDeviceAllow
*a
= NULL
, *b
;
1246 LIST_FOREACH(device_allow
, b
, c
->device_allow
) {
1247 if (path_equal(b
->path
, path
)) {
1254 a
= new0(CGroupDeviceAllow
, 1);
1258 a
->path
= strdup(path
);
1264 LIST_PREPEND(device_allow
, c
->device_allow
, a
);
1267 a
->r
= !!strchr(rwm
, 'r');
1268 a
->w
= !!strchr(rwm
, 'w');
1269 a
->m
= !!strchr(rwm
, 'm');
1277 r
= sd_bus_message_exit_container(message
);
1281 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1282 _cleanup_free_
char *buf
= NULL
;
1283 _cleanup_fclose_
FILE *f
= NULL
;
1284 CGroupDeviceAllow
*a
;
1288 while (c
->device_allow
)
1289 cgroup_context_free_device_allow(c
, c
->device_allow
);
1292 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1294 f
= open_memstream_unlocked(&buf
, &size
);
1298 fputs("DeviceAllow=\n", f
);
1299 LIST_FOREACH(device_allow
, a
, c
->device_allow
)
1300 fprintf(f
, "DeviceAllow=%s %s%s%s\n", a
->path
, a
->r
? "r" : "", a
->w
? "w" : "", a
->m
? "m" : "");
1302 r
= fflush_and_check(f
);
1305 unit_write_setting(u
, flags
, name
, buf
);
1310 } else if (streq(name
, "IPAccounting")) {
1313 r
= sd_bus_message_read(message
, "b", &b
);
1317 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1318 c
->ip_accounting
= b
;
1320 unit_invalidate_cgroup_bpf(u
);
1321 unit_write_settingf(u
, flags
, name
, "IPAccounting=%s", yes_no(b
));
1326 } else if (STR_IN_SET(name
, "IPAddressAllow", "IPAddressDeny")) {
1327 IPAddressAccessItem
**list
;
1330 list
= streq(name
, "IPAddressAllow") ? &c
->ip_address_allow
: &c
->ip_address_deny
;
1332 r
= sd_bus_message_enter_container(message
, 'a', "(iayu)");
1342 r
= sd_bus_message_enter_container(message
, 'r', "iayu");
1348 r
= sd_bus_message_read(message
, "i", &family
);
1352 if (!IN_SET(family
, AF_INET
, AF_INET6
))
1353 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects IPv4 or IPv6 addresses only.", name
);
1355 r
= sd_bus_message_read_array(message
, 'y', &ap
, &an
);
1359 if (an
!= FAMILY_ADDRESS_SIZE(family
))
1360 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "IP address has wrong size for family (%s, expected %zu, got %zu)",
1361 af_to_name(family
), FAMILY_ADDRESS_SIZE(family
), an
);
1363 r
= sd_bus_message_read(message
, "u", &prefixlen
);
1367 if (prefixlen
> FAMILY_ADDRESS_SIZE(family
)*8)
1368 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Prefix length %" PRIu32
" too large for address family %s.", prefixlen
, af_to_name(family
));
1370 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1371 IPAddressAccessItem
*item
;
1373 item
= new0(IPAddressAccessItem
, 1);
1377 item
->family
= family
;
1378 item
->prefixlen
= prefixlen
;
1379 memcpy(&item
->address
, ap
, an
);
1381 LIST_PREPEND(items
, *list
, item
);
1384 r
= sd_bus_message_exit_container(message
);
1391 r
= sd_bus_message_exit_container(message
);
1395 *list
= ip_address_access_reduce(*list
);
1397 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1398 _cleanup_free_
char *buf
= NULL
;
1399 _cleanup_fclose_
FILE *f
= NULL
;
1400 IPAddressAccessItem
*item
;
1404 *list
= ip_address_access_free_all(*list
);
1406 unit_invalidate_cgroup_bpf(u
);
1407 f
= open_memstream_unlocked(&buf
, &size
);
1414 LIST_FOREACH(items
, item
, *list
) {
1415 char buffer
[CONST_MAX(INET_ADDRSTRLEN
, INET6_ADDRSTRLEN
)];
1418 if (!inet_ntop(item
->family
, &item
->address
, buffer
, sizeof(buffer
)))
1419 return errno
> 0 ? -errno
: -EINVAL
;
1421 fprintf(f
, "%s=%s/%u\n", name
, buffer
, item
->prefixlen
);
1424 r
= fflush_and_check(f
);
1428 unit_write_setting(u
, flags
, name
, buf
);
1431 r
= bpf_firewall_supported();
1434 if (r
== BPF_FIREWALL_UNSUPPORTED
) {
1435 static bool warned
= false;
1437 log_full(warned
? LOG_DEBUG
: LOG_WARNING
,
1438 "Transient unit %s configures an IP firewall, but the local system does not support BPF/cgroup firewalling.\n"
1439 "Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first started transient unit using IP firewalling.)", u
->id
);
1449 if (streq(name
, "DisableControllers") || (u
->transient
&& u
->load_state
== UNIT_STUB
))
1450 return bus_cgroup_set_transient_property(u
, c
, name
, message
, flags
, error
);