1 /* SPDX-License-Identifier: LGPL-2.1+ */
7 #include "alloc-util.h"
8 #include "bpf-firewall.h"
10 #include "cgroup-util.h"
12 #include "dbus-cgroup.h"
13 #include "dbus-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_delegate_controllers(
23 const char *interface
,
25 sd_bus_message
*reply
,
27 sd_bus_error
*error
) {
29 CGroupContext
*c
= userdata
;
38 return sd_bus_message_append(reply
, "as", 0);
40 r
= sd_bus_message_open_container(reply
, 'a', "s");
44 for (cc
= 0; cc
< _CGROUP_CONTROLLER_MAX
; cc
++) {
45 if ((c
->delegate_controllers
& CGROUP_CONTROLLER_TO_MASK(cc
)) == 0)
48 r
= sd_bus_message_append(reply
, "s", cgroup_controller_to_string(cc
));
53 return sd_bus_message_close_container(reply
);
56 static int property_get_io_device_weight(
59 const char *interface
,
61 sd_bus_message
*reply
,
63 sd_bus_error
*error
) {
65 CGroupContext
*c
= userdata
;
66 CGroupIODeviceWeight
*w
;
73 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
77 LIST_FOREACH(device_weights
, w
, c
->io_device_weights
) {
78 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
83 return sd_bus_message_close_container(reply
);
86 static int property_get_io_device_limits(
89 const char *interface
,
91 sd_bus_message
*reply
,
93 sd_bus_error
*error
) {
95 CGroupContext
*c
= userdata
;
96 CGroupIODeviceLimit
*l
;
103 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
107 LIST_FOREACH(device_limits
, l
, c
->io_device_limits
) {
108 CGroupIOLimitType type
;
110 type
= cgroup_io_limit_type_from_string(property
);
111 if (type
< 0 || l
->limits
[type
] == cgroup_io_limit_defaults
[type
])
114 r
= sd_bus_message_append(reply
, "(st)", l
->path
, l
->limits
[type
]);
119 return sd_bus_message_close_container(reply
);
122 static int property_get_io_device_latency(
125 const char *interface
,
126 const char *property
,
127 sd_bus_message
*reply
,
129 sd_bus_error
*error
) {
131 CGroupContext
*c
= userdata
;
132 CGroupIODeviceLatency
*l
;
139 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
143 LIST_FOREACH(device_latencies
, l
, c
->io_device_latencies
) {
144 r
= sd_bus_message_append(reply
, "(st)", l
->path
, l
->target_usec
);
149 return sd_bus_message_close_container(reply
);
152 static int property_get_blockio_device_weight(
155 const char *interface
,
156 const char *property
,
157 sd_bus_message
*reply
,
159 sd_bus_error
*error
) {
161 CGroupContext
*c
= userdata
;
162 CGroupBlockIODeviceWeight
*w
;
169 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
173 LIST_FOREACH(device_weights
, w
, c
->blockio_device_weights
) {
174 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
179 return sd_bus_message_close_container(reply
);
182 static int property_get_blockio_device_bandwidths(
185 const char *interface
,
186 const char *property
,
187 sd_bus_message
*reply
,
189 sd_bus_error
*error
) {
191 CGroupContext
*c
= userdata
;
192 CGroupBlockIODeviceBandwidth
*b
;
199 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
203 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
206 if (streq(property
, "BlockIOReadBandwidth"))
211 if (v
== CGROUP_LIMIT_MAX
)
214 r
= sd_bus_message_append(reply
, "(st)", b
->path
, v
);
219 return sd_bus_message_close_container(reply
);
222 static int property_get_device_allow(
225 const char *interface
,
226 const char *property
,
227 sd_bus_message
*reply
,
229 sd_bus_error
*error
) {
231 CGroupContext
*c
= userdata
;
232 CGroupDeviceAllow
*a
;
239 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
243 LIST_FOREACH(device_allow
, a
, c
->device_allow
) {
256 r
= sd_bus_message_append(reply
, "(ss)", a
->path
, rwm
);
261 return sd_bus_message_close_container(reply
);
264 static int property_get_ip_address_access(
267 const char *interface
,
268 const char *property
,
269 sd_bus_message
*reply
,
271 sd_bus_error
*error
) {
273 IPAddressAccessItem
** items
= userdata
, *i
;
276 r
= sd_bus_message_open_container(reply
, 'a', "(iayu)");
280 LIST_FOREACH(items
, i
, *items
) {
282 r
= sd_bus_message_open_container(reply
, 'r', "iayu");
286 r
= sd_bus_message_append(reply
, "i", i
->family
);
290 r
= sd_bus_message_append_array(reply
, 'y', &i
->address
, FAMILY_ADDRESS_SIZE(i
->family
));
294 r
= sd_bus_message_append(reply
, "u", (uint32_t) i
->prefixlen
);
298 r
= sd_bus_message_close_container(reply
);
303 return sd_bus_message_close_container(reply
);
306 const sd_bus_vtable bus_cgroup_vtable
[] = {
307 SD_BUS_VTABLE_START(0),
308 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool
, offsetof(CGroupContext
, delegate
), 0),
309 SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers
, 0, 0),
310 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, cpu_accounting
), 0),
311 SD_BUS_PROPERTY("CPUWeight", "t", NULL
, offsetof(CGroupContext
, cpu_weight
), 0),
312 SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL
, offsetof(CGroupContext
, startup_cpu_weight
), 0),
313 SD_BUS_PROPERTY("CPUShares", "t", NULL
, offsetof(CGroupContext
, cpu_shares
), 0),
314 SD_BUS_PROPERTY("StartupCPUShares", "t", NULL
, offsetof(CGroupContext
, startup_cpu_shares
), 0),
315 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, cpu_quota_per_sec_usec
), 0),
316 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, io_accounting
), 0),
317 SD_BUS_PROPERTY("IOWeight", "t", NULL
, offsetof(CGroupContext
, io_weight
), 0),
318 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_io_weight
), 0),
319 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight
, 0, 0),
320 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
321 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
322 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
323 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
324 SD_BUS_PROPERTY("IODeviceLatencyTargetUSec", "a(st)", property_get_io_device_latency
, 0, 0),
325 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, blockio_accounting
), 0),
326 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL
, offsetof(CGroupContext
, blockio_weight
), 0),
327 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_blockio_weight
), 0),
328 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight
, 0, 0),
329 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
330 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
331 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, memory_accounting
), 0),
332 SD_BUS_PROPERTY("MemoryMin", "t", NULL
, offsetof(CGroupContext
, memory_min
), 0),
333 SD_BUS_PROPERTY("MemoryLow", "t", NULL
, offsetof(CGroupContext
, memory_low
), 0),
334 SD_BUS_PROPERTY("MemoryHigh", "t", NULL
, offsetof(CGroupContext
, memory_high
), 0),
335 SD_BUS_PROPERTY("MemoryMax", "t", NULL
, offsetof(CGroupContext
, memory_max
), 0),
336 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL
, offsetof(CGroupContext
, memory_swap_max
), 0),
337 SD_BUS_PROPERTY("MemoryLimit", "t", NULL
, offsetof(CGroupContext
, memory_limit
), 0),
338 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy
, offsetof(CGroupContext
, device_policy
), 0),
339 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow
, 0, 0),
340 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, tasks_accounting
), 0),
341 SD_BUS_PROPERTY("TasksMax", "t", NULL
, offsetof(CGroupContext
, tasks_max
), 0),
342 SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, ip_accounting
), 0),
343 SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_allow
), 0),
344 SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_deny
), 0),
348 static int bus_cgroup_set_transient_property(
352 sd_bus_message
*message
,
353 UnitWriteFlags flags
,
354 sd_bus_error
*error
) {
363 flags
|= UNIT_PRIVATE
;
365 if (streq(name
, "Delegate")) {
368 if (!UNIT_VTABLE(u
)->can_delegate
)
369 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
371 r
= sd_bus_message_read(message
, "b", &b
);
375 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
377 c
->delegate_controllers
= b
? _CGROUP_MASK_ALL
: 0;
379 unit_write_settingf(u
, flags
, name
, "Delegate=%s", yes_no(b
));
384 } else if (streq(name
, "DelegateControllers")) {
387 if (!UNIT_VTABLE(u
)->can_delegate
)
388 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
390 r
= sd_bus_message_enter_container(message
, 'a', "s");
398 r
= sd_bus_message_read(message
, "s", &t
);
404 cc
= cgroup_controller_from_string(t
);
406 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown cgroup controller '%s'", t
);
408 mask
|= CGROUP_CONTROLLER_TO_MASK(cc
);
411 r
= sd_bus_message_exit_container(message
);
415 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
416 _cleanup_free_
char *t
= NULL
;
418 r
= cg_mask_to_string(mask
, &t
);
424 c
->delegate_controllers
= 0;
426 c
->delegate_controllers
|= mask
;
428 unit_write_settingf(u
, flags
, name
, "Delegate=%s", strempty(t
));
437 static int bus_cgroup_set_boolean(
442 sd_bus_message
*message
,
443 UnitWriteFlags flags
,
444 sd_bus_error
*error
) {
450 r
= sd_bus_message_read(message
, "b", &b
);
454 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
456 unit_invalidate_cgroup(u
, mask
);
457 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, yes_no(b
));
463 #define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val) \
464 static int bus_cgroup_set_##function( \
468 sd_bus_message *message, \
469 UnitWriteFlags flags, \
470 sd_bus_error *error) { \
477 r = sd_bus_message_read(message, "t", &v); \
482 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
483 "Value specified in %s is out of range", name); \
485 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
487 unit_invalidate_cgroup(u, (mask)); \
490 unit_write_settingf(u, flags, name, \
493 unit_write_settingf(u, flags, name, \
494 "%s=%" PRIu64, name, v); \
500 #define BUS_DEFINE_SET_CGROUP_LIMIT(function, mask, scale, minimum) \
501 static int bus_cgroup_set_##function( \
505 sd_bus_message *message, \
506 UnitWriteFlags flags, \
507 sd_bus_error *error) { \
514 r = sd_bus_message_read(message, "t", &v); \
519 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
520 "Value specified in %s is out of range", name); \
522 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
524 unit_invalidate_cgroup(u, (mask)); \
526 if (v == CGROUP_LIMIT_MAX) \
527 unit_write_settingf(u, flags, name, \
528 "%s=infinity", name); \
530 unit_write_settingf(u, flags, name, \
531 "%s=%" PRIu64, name, v); \
536 static int bus_cgroup_set_##function##_scale( \
540 sd_bus_message *message, \
541 UnitWriteFlags flags, \
542 sd_bus_error *error) { \
550 r = sd_bus_message_read(message, "u", &raw); \
554 v = scale(raw, UINT32_MAX); \
555 if (v < minimum || v >= UINT64_MAX) \
556 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
557 "Value specified in %s is out of range", name); \
559 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
563 unit_invalidate_cgroup(u, (mask)); \
565 /* Chop off suffix */ \
566 assert_se(e = endswith(name, "Scale")); \
567 name = strndupa(name, e - name); \
569 unit_write_settingf(u, flags, name, "%s=%" PRIu32 "%%", name, \
570 (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX))); \
576 #pragma GCC diagnostic push
577 #pragma GCC diagnostic ignored "-Wtype-limits"
578 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight
, CGROUP_MASK_CPU
, CGROUP_WEIGHT_IS_OK
, CGROUP_WEIGHT_INVALID
);
579 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares
, CGROUP_MASK_CPU
, CGROUP_CPU_SHARES_IS_OK
, CGROUP_CPU_SHARES_INVALID
);
580 BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight
, CGROUP_MASK_IO
, CGROUP_WEIGHT_IS_OK
, CGROUP_WEIGHT_INVALID
);
581 BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight
, CGROUP_MASK_BLKIO
, CGROUP_BLKIO_WEIGHT_IS_OK
, CGROUP_BLKIO_WEIGHT_INVALID
);
582 BUS_DEFINE_SET_CGROUP_LIMIT(memory
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 1);
583 BUS_DEFINE_SET_CGROUP_LIMIT(swap
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 0);
584 BUS_DEFINE_SET_CGROUP_LIMIT(tasks_max
, CGROUP_MASK_PIDS
, system_tasks_max_scale
, 1);
585 #pragma GCC diagnostic pop
587 int bus_cgroup_set_property(
591 sd_bus_message
*message
,
592 UnitWriteFlags flags
,
593 sd_bus_error
*error
) {
595 CGroupIOLimitType iol_type
;
603 flags
|= UNIT_PRIVATE
;
605 if (streq(name
, "CPUAccounting"))
606 return bus_cgroup_set_boolean(u
, name
, &c
->cpu_accounting
, CGROUP_MASK_CPUACCT
|CGROUP_MASK_CPU
, message
, flags
, error
);
608 if (streq(name
, "CPUWeight"))
609 return bus_cgroup_set_cpu_weight(u
, name
, &c
->cpu_weight
, message
, flags
, error
);
611 if (streq(name
, "StartupCPUWeight"))
612 return bus_cgroup_set_cpu_weight(u
, name
, &c
->startup_cpu_weight
, message
, flags
, error
);
614 if (streq(name
, "CPUShares"))
615 return bus_cgroup_set_cpu_shares(u
, name
, &c
->cpu_shares
, message
, flags
, error
);
617 if (streq(name
, "StartupCPUShares"))
618 return bus_cgroup_set_cpu_shares(u
, name
, &c
->startup_cpu_shares
, message
, flags
, error
);
620 if (streq(name
, "IOAccounting"))
621 return bus_cgroup_set_boolean(u
, name
, &c
->io_accounting
, CGROUP_MASK_IO
, message
, flags
, error
);
623 if (streq(name
, "IOWeight"))
624 return bus_cgroup_set_io_weight(u
, name
, &c
->io_weight
, message
, flags
, error
);
626 if (streq(name
, "StartupIOWeight"))
627 return bus_cgroup_set_io_weight(u
, name
, &c
->startup_io_weight
, message
, flags
, error
);
629 if (streq(name
, "BlockIOAccounting"))
630 return bus_cgroup_set_boolean(u
, name
, &c
->blockio_accounting
, CGROUP_MASK_BLKIO
, message
, flags
, error
);
632 if (streq(name
, "BlockIOWeight"))
633 return bus_cgroup_set_blockio_weight(u
, name
, &c
->blockio_weight
, message
, flags
, error
);
635 if (streq(name
, "StartupBlockIOWeight"))
636 return bus_cgroup_set_blockio_weight(u
, name
, &c
->startup_blockio_weight
, message
, flags
, error
);
638 if (streq(name
, "MemoryAccounting"))
639 return bus_cgroup_set_boolean(u
, name
, &c
->memory_accounting
, CGROUP_MASK_MEMORY
, message
, flags
, error
);
641 if (streq(name
, "MemoryMin"))
642 return bus_cgroup_set_memory(u
, name
, &c
->memory_min
, message
, flags
, error
);
644 if (streq(name
, "MemoryLow"))
645 return bus_cgroup_set_memory(u
, name
, &c
->memory_low
, message
, flags
, error
);
647 if (streq(name
, "MemoryHigh"))
648 return bus_cgroup_set_memory(u
, name
, &c
->memory_high
, message
, flags
, error
);
650 if (streq(name
, "MemorySwapMax"))
651 return bus_cgroup_set_swap(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
653 if (streq(name
, "MemoryMax"))
654 return bus_cgroup_set_memory(u
, name
, &c
->memory_max
, message
, flags
, error
);
656 if (streq(name
, "MemoryLimit"))
657 return bus_cgroup_set_memory(u
, name
, &c
->memory_limit
, message
, flags
, error
);
659 if (streq(name
, "MemoryMinScale"))
660 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_min
, message
, flags
, error
);
662 if (streq(name
, "MemoryLowScale"))
663 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_low
, message
, flags
, error
);
665 if (streq(name
, "MemoryHighScale"))
666 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_high
, message
, flags
, error
);
668 if (streq(name
, "MemorySwapMaxScale"))
669 return bus_cgroup_set_swap_scale(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
671 if (streq(name
, "MemoryMaxScale"))
672 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_max
, message
, flags
, error
);
674 if (streq(name
, "MemoryLimitScale"))
675 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_limit
, message
, flags
, error
);
677 if (streq(name
, "TasksAccounting"))
678 return bus_cgroup_set_boolean(u
, name
, &c
->tasks_accounting
, CGROUP_MASK_PIDS
, message
, flags
, error
);
680 if (streq(name
, "TasksMax"))
681 return bus_cgroup_set_tasks_max(u
, name
, &c
->tasks_max
, message
, flags
, error
);
683 if (streq(name
, "TasksMaxScale"))
684 return bus_cgroup_set_tasks_max_scale(u
, name
, &c
->tasks_max
, message
, flags
, error
);
686 if (streq(name
, "CPUQuotaPerSecUSec")) {
689 r
= sd_bus_message_read(message
, "t", &u64
);
694 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "CPUQuotaPerSecUSec= value out of range");
696 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
697 c
->cpu_quota_per_sec_usec
= u64
;
698 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
700 if (c
->cpu_quota_per_sec_usec
== USEC_INFINITY
)
701 unit_write_setting(u
, flags
, "CPUQuota", "CPUQuota=");
703 /* config_parse_cpu_quota() requires an integer, so truncating division is used on
705 unit_write_settingf(u
, flags
, "CPUQuota",
707 (double) (c
->cpu_quota_per_sec_usec
/ 10000));
712 } else if ((iol_type
= cgroup_io_limit_type_from_string(name
)) >= 0) {
717 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
721 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
723 if (!path_is_normalized(path
))
724 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
726 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
727 CGroupIODeviceLimit
*a
= NULL
, *b
;
729 LIST_FOREACH(device_limits
, b
, c
->io_device_limits
) {
730 if (path_equal(path
, b
->path
)) {
737 CGroupIOLimitType type
;
739 a
= new0(CGroupIODeviceLimit
, 1);
743 a
->path
= strdup(path
);
749 for (type
= 0; type
< _CGROUP_IO_LIMIT_TYPE_MAX
; type
++)
750 a
->limits
[type
] = cgroup_io_limit_defaults
[type
];
752 LIST_PREPEND(device_limits
, c
->io_device_limits
, a
);
755 a
->limits
[iol_type
] = u64
;
763 r
= sd_bus_message_exit_container(message
);
767 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
768 CGroupIODeviceLimit
*a
;
769 _cleanup_free_
char *buf
= NULL
;
770 _cleanup_fclose_
FILE *f
= NULL
;
774 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
775 a
->limits
[iol_type
] = cgroup_io_limit_defaults
[iol_type
];
778 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
780 f
= open_memstream(&buf
, &size
);
784 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
786 fprintf(f
, "%s=\n", name
);
787 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
788 if (a
->limits
[iol_type
] != cgroup_io_limit_defaults
[iol_type
])
789 fprintf(f
, "%s=%s %" PRIu64
"\n", name
, a
->path
, a
->limits
[iol_type
]);
791 r
= fflush_and_check(f
);
794 unit_write_setting(u
, flags
, name
, buf
);
799 } else if (streq(name
, "IODeviceWeight")) {
804 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
808 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
810 if (!path_is_normalized(path
))
811 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
813 if (!CGROUP_WEIGHT_IS_OK(weight
) || weight
== CGROUP_WEIGHT_INVALID
)
814 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "IODeviceWeight= value out of range");
816 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
817 CGroupIODeviceWeight
*a
= NULL
, *b
;
819 LIST_FOREACH(device_weights
, b
, c
->io_device_weights
) {
820 if (path_equal(b
->path
, path
)) {
827 a
= new0(CGroupIODeviceWeight
, 1);
831 a
->path
= strdup(path
);
836 LIST_PREPEND(device_weights
, c
->io_device_weights
, a
);
845 r
= sd_bus_message_exit_container(message
);
849 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
850 _cleanup_free_
char *buf
= NULL
;
851 _cleanup_fclose_
FILE *f
= NULL
;
852 CGroupIODeviceWeight
*a
;
856 while (c
->io_device_weights
)
857 cgroup_context_free_io_device_weight(c
, c
->io_device_weights
);
860 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
862 f
= open_memstream(&buf
, &size
);
866 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
868 fputs("IODeviceWeight=\n", f
);
869 LIST_FOREACH(device_weights
, a
, c
->io_device_weights
)
870 fprintf(f
, "IODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
872 r
= fflush_and_check(f
);
875 unit_write_setting(u
, flags
, name
, buf
);
880 } else if (streq(name
, "IODeviceLatencyTargetUSec")) {
885 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
889 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &target
)) > 0) {
891 if (!path_is_normalized(path
))
892 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
894 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
895 CGroupIODeviceLatency
*a
= NULL
, *b
;
897 LIST_FOREACH(device_latencies
, b
, c
->io_device_latencies
) {
898 if (path_equal(b
->path
, path
)) {
905 a
= new0(CGroupIODeviceLatency
, 1);
909 a
->path
= strdup(path
);
914 LIST_PREPEND(device_latencies
, c
->io_device_latencies
, a
);
917 a
->target_usec
= target
;
923 r
= sd_bus_message_exit_container(message
);
927 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
928 _cleanup_free_
char *buf
= NULL
;
929 _cleanup_fclose_
FILE *f
= NULL
;
930 char ts
[FORMAT_TIMESPAN_MAX
];
931 CGroupIODeviceLatency
*a
;
935 while (c
->io_device_latencies
)
936 cgroup_context_free_io_device_latency(c
, c
->io_device_latencies
);
939 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
941 f
= open_memstream(&buf
, &size
);
945 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
947 fputs("IODeviceLatencyTargetSec=\n", f
);
948 LIST_FOREACH(device_latencies
, a
, c
->io_device_latencies
)
949 fprintf(f
, "IODeviceLatencyTargetSec=%s %s\n",
950 a
->path
, format_timespan(ts
, sizeof(ts
), a
->target_usec
, 1));
952 r
= fflush_and_check(f
);
955 unit_write_setting(u
, flags
, name
, buf
);
960 } else if (STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
966 if (streq(name
, "BlockIOWriteBandwidth"))
969 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
973 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
975 if (!path_is_normalized(path
))
976 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
978 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
979 CGroupBlockIODeviceBandwidth
*a
= NULL
, *b
;
981 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
982 if (path_equal(path
, b
->path
)) {
989 a
= new0(CGroupBlockIODeviceBandwidth
, 1);
993 a
->rbps
= CGROUP_LIMIT_MAX
;
994 a
->wbps
= CGROUP_LIMIT_MAX
;
995 a
->path
= strdup(path
);
1001 LIST_PREPEND(device_bandwidths
, c
->blockio_device_bandwidths
, a
);
1015 r
= sd_bus_message_exit_container(message
);
1019 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1020 CGroupBlockIODeviceBandwidth
*a
;
1021 _cleanup_free_
char *buf
= NULL
;
1022 _cleanup_fclose_
FILE *f
= NULL
;
1026 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
) {
1028 a
->rbps
= CGROUP_LIMIT_MAX
;
1030 a
->wbps
= CGROUP_LIMIT_MAX
;
1034 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
1036 f
= open_memstream(&buf
, &size
);
1040 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
1043 fputs("BlockIOReadBandwidth=\n", f
);
1044 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
1045 if (a
->rbps
!= CGROUP_LIMIT_MAX
)
1046 fprintf(f
, "BlockIOReadBandwidth=%s %" PRIu64
"\n", a
->path
, a
->rbps
);
1048 fputs("BlockIOWriteBandwidth=\n", f
);
1049 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
1050 if (a
->wbps
!= CGROUP_LIMIT_MAX
)
1051 fprintf(f
, "BlockIOWriteBandwidth=%s %" PRIu64
"\n", a
->path
, a
->wbps
);
1054 r
= fflush_and_check(f
);
1058 unit_write_setting(u
, flags
, name
, buf
);
1063 } else if (streq(name
, "BlockIODeviceWeight")) {
1068 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1072 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
1074 if (!path_is_normalized(path
))
1075 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1077 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
) || weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
1078 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "BlockIODeviceWeight= out of range");
1080 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1081 CGroupBlockIODeviceWeight
*a
= NULL
, *b
;
1083 LIST_FOREACH(device_weights
, b
, c
->blockio_device_weights
) {
1084 if (path_equal(b
->path
, path
)) {
1091 a
= new0(CGroupBlockIODeviceWeight
, 1);
1095 a
->path
= strdup(path
);
1100 LIST_PREPEND(device_weights
, c
->blockio_device_weights
, a
);
1109 r
= sd_bus_message_exit_container(message
);
1113 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1114 _cleanup_free_
char *buf
= NULL
;
1115 _cleanup_fclose_
FILE *f
= NULL
;
1116 CGroupBlockIODeviceWeight
*a
;
1120 while (c
->blockio_device_weights
)
1121 cgroup_context_free_blockio_device_weight(c
, c
->blockio_device_weights
);
1124 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
1126 f
= open_memstream(&buf
, &size
);
1130 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
1132 fputs("BlockIODeviceWeight=\n", f
);
1133 LIST_FOREACH(device_weights
, a
, c
->blockio_device_weights
)
1134 fprintf(f
, "BlockIODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
1136 r
= fflush_and_check(f
);
1140 unit_write_setting(u
, flags
, name
, buf
);
1145 } else if (streq(name
, "DevicePolicy")) {
1147 CGroupDevicePolicy p
;
1149 r
= sd_bus_message_read(message
, "s", &policy
);
1153 p
= cgroup_device_policy_from_string(policy
);
1157 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1158 c
->device_policy
= p
;
1159 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1160 unit_write_settingf(u
, flags
, name
, "DevicePolicy=%s", policy
);
1165 } else if (streq(name
, "DeviceAllow")) {
1166 const char *path
, *rwm
;
1169 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
1173 while ((r
= sd_bus_message_read(message
, "(ss)", &path
, &rwm
)) > 0) {
1175 if (!valid_device_allow_pattern(path
) || strpbrk(path
, WHITESPACE
))
1176 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires device node or pattern");
1180 else if (!in_charset(rwm
, "rwm"))
1181 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires combination of rwm flags");
1183 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1184 CGroupDeviceAllow
*a
= NULL
, *b
;
1186 LIST_FOREACH(device_allow
, b
, c
->device_allow
) {
1187 if (path_equal(b
->path
, path
)) {
1194 a
= new0(CGroupDeviceAllow
, 1);
1198 a
->path
= strdup(path
);
1204 LIST_PREPEND(device_allow
, c
->device_allow
, a
);
1207 a
->r
= !!strchr(rwm
, 'r');
1208 a
->w
= !!strchr(rwm
, 'w');
1209 a
->m
= !!strchr(rwm
, 'm');
1217 r
= sd_bus_message_exit_container(message
);
1221 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1222 _cleanup_free_
char *buf
= NULL
;
1223 _cleanup_fclose_
FILE *f
= NULL
;
1224 CGroupDeviceAllow
*a
;
1228 while (c
->device_allow
)
1229 cgroup_context_free_device_allow(c
, c
->device_allow
);
1232 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1234 f
= open_memstream(&buf
, &size
);
1238 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
1240 fputs("DeviceAllow=\n", f
);
1241 LIST_FOREACH(device_allow
, a
, c
->device_allow
)
1242 fprintf(f
, "DeviceAllow=%s %s%s%s\n", a
->path
, a
->r
? "r" : "", a
->w
? "w" : "", a
->m
? "m" : "");
1244 r
= fflush_and_check(f
);
1247 unit_write_setting(u
, flags
, name
, buf
);
1252 } else if (streq(name
, "IPAccounting")) {
1255 r
= sd_bus_message_read(message
, "b", &b
);
1259 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1260 c
->ip_accounting
= b
;
1262 unit_invalidate_cgroup_bpf(u
);
1263 unit_write_settingf(u
, flags
, name
, "IPAccounting=%s", yes_no(b
));
1268 } else if (STR_IN_SET(name
, "IPAddressAllow", "IPAddressDeny")) {
1269 IPAddressAccessItem
**list
;
1272 list
= streq(name
, "IPAddressAllow") ? &c
->ip_address_allow
: &c
->ip_address_deny
;
1274 r
= sd_bus_message_enter_container(message
, 'a', "(iayu)");
1284 r
= sd_bus_message_enter_container(message
, 'r', "iayu");
1290 r
= sd_bus_message_read(message
, "i", &family
);
1294 if (!IN_SET(family
, AF_INET
, AF_INET6
))
1295 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects IPv4 or IPv6 addresses only.", name
);
1297 r
= sd_bus_message_read_array(message
, 'y', &ap
, &an
);
1301 if (an
!= FAMILY_ADDRESS_SIZE(family
))
1302 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "IP address has wrong size for family (%s, expected %zu, got %zu)",
1303 af_to_name(family
), FAMILY_ADDRESS_SIZE(family
), an
);
1305 r
= sd_bus_message_read(message
, "u", &prefixlen
);
1309 if (prefixlen
> FAMILY_ADDRESS_SIZE(family
)*8)
1310 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
));
1312 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1313 IPAddressAccessItem
*item
;
1315 item
= new0(IPAddressAccessItem
, 1);
1319 item
->family
= family
;
1320 item
->prefixlen
= prefixlen
;
1321 memcpy(&item
->address
, ap
, an
);
1323 LIST_PREPEND(items
, *list
, item
);
1326 r
= sd_bus_message_exit_container(message
);
1333 r
= sd_bus_message_exit_container(message
);
1337 *list
= ip_address_access_reduce(*list
);
1339 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1340 _cleanup_free_
char *buf
= NULL
;
1341 _cleanup_fclose_
FILE *f
= NULL
;
1342 IPAddressAccessItem
*item
;
1346 *list
= ip_address_access_free_all(*list
);
1348 unit_invalidate_cgroup_bpf(u
);
1349 f
= open_memstream(&buf
, &size
);
1353 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
1358 LIST_FOREACH(items
, item
, *list
) {
1359 char buffer
[CONST_MAX(INET_ADDRSTRLEN
, INET6_ADDRSTRLEN
)];
1362 if (!inet_ntop(item
->family
, &item
->address
, buffer
, sizeof(buffer
)))
1363 return errno
> 0 ? -errno
: -EINVAL
;
1365 fprintf(f
, "%s=%s/%u\n", name
, buffer
, item
->prefixlen
);
1368 r
= fflush_and_check(f
);
1372 unit_write_setting(u
, flags
, name
, buf
);
1375 r
= bpf_firewall_supported();
1378 if (r
== BPF_FIREWALL_UNSUPPORTED
) {
1379 static bool warned
= false;
1381 log_full(warned
? LOG_DEBUG
: LOG_WARNING
,
1382 "Transient unit %s configures an IP firewall, but the local system does not support BPF/cgroup firewalling.\n"
1383 "Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first started transient unit using IP firewalling.)", u
->id
);
1393 if (u
->transient
&& u
->load_state
== UNIT_STUB
)
1394 return bus_cgroup_set_transient_property(u
, c
, name
, message
, flags
, error
);