1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
12 #include "alloc-util.h"
13 #include "bpf-firewall.h"
15 #include "cgroup-util.h"
17 #include "dbus-cgroup.h"
18 #include "dbus-util.h"
21 #include "path-util.h"
23 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy
, cgroup_device_policy
, CGroupDevicePolicy
);
25 static int property_get_delegate_controllers(
28 const char *interface
,
30 sd_bus_message
*reply
,
32 sd_bus_error
*error
) {
34 CGroupContext
*c
= userdata
;
43 return sd_bus_message_append(reply
, "as", 0);
45 r
= sd_bus_message_open_container(reply
, 'a', "s");
49 for (cc
= 0; cc
< _CGROUP_CONTROLLER_MAX
; cc
++) {
50 if ((c
->delegate_controllers
& CGROUP_CONTROLLER_TO_MASK(cc
)) == 0)
53 r
= sd_bus_message_append(reply
, "s", cgroup_controller_to_string(cc
));
58 return sd_bus_message_close_container(reply
);
61 static int property_get_io_device_weight(
64 const char *interface
,
66 sd_bus_message
*reply
,
68 sd_bus_error
*error
) {
70 CGroupContext
*c
= userdata
;
71 CGroupIODeviceWeight
*w
;
78 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
82 LIST_FOREACH(device_weights
, w
, c
->io_device_weights
) {
83 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
88 return sd_bus_message_close_container(reply
);
91 static int property_get_io_device_limits(
94 const char *interface
,
96 sd_bus_message
*reply
,
98 sd_bus_error
*error
) {
100 CGroupContext
*c
= userdata
;
101 CGroupIODeviceLimit
*l
;
108 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
112 LIST_FOREACH(device_limits
, l
, c
->io_device_limits
) {
113 CGroupIOLimitType type
;
115 type
= cgroup_io_limit_type_from_string(property
);
116 if (type
< 0 || l
->limits
[type
] == cgroup_io_limit_defaults
[type
])
119 r
= sd_bus_message_append(reply
, "(st)", l
->path
, l
->limits
[type
]);
124 return sd_bus_message_close_container(reply
);
127 static int property_get_blockio_device_weight(
130 const char *interface
,
131 const char *property
,
132 sd_bus_message
*reply
,
134 sd_bus_error
*error
) {
136 CGroupContext
*c
= userdata
;
137 CGroupBlockIODeviceWeight
*w
;
144 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
148 LIST_FOREACH(device_weights
, w
, c
->blockio_device_weights
) {
149 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
154 return sd_bus_message_close_container(reply
);
157 static int property_get_blockio_device_bandwidths(
160 const char *interface
,
161 const char *property
,
162 sd_bus_message
*reply
,
164 sd_bus_error
*error
) {
166 CGroupContext
*c
= userdata
;
167 CGroupBlockIODeviceBandwidth
*b
;
174 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
178 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
181 if (streq(property
, "BlockIOReadBandwidth"))
186 if (v
== CGROUP_LIMIT_MAX
)
189 r
= sd_bus_message_append(reply
, "(st)", b
->path
, v
);
194 return sd_bus_message_close_container(reply
);
197 static int property_get_device_allow(
200 const char *interface
,
201 const char *property
,
202 sd_bus_message
*reply
,
204 sd_bus_error
*error
) {
206 CGroupContext
*c
= userdata
;
207 CGroupDeviceAllow
*a
;
214 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
218 LIST_FOREACH(device_allow
, a
, c
->device_allow
) {
231 r
= sd_bus_message_append(reply
, "(ss)", a
->path
, rwm
);
236 return sd_bus_message_close_container(reply
);
239 static int property_get_ip_address_access(
242 const char *interface
,
243 const char *property
,
244 sd_bus_message
*reply
,
246 sd_bus_error
*error
) {
248 IPAddressAccessItem
** items
= userdata
, *i
;
251 r
= sd_bus_message_open_container(reply
, 'a', "(iayu)");
255 LIST_FOREACH(items
, i
, *items
) {
257 r
= sd_bus_message_open_container(reply
, 'r', "iayu");
261 r
= sd_bus_message_append(reply
, "i", i
->family
);
265 r
= sd_bus_message_append_array(reply
, 'y', &i
->address
, FAMILY_ADDRESS_SIZE(i
->family
));
269 r
= sd_bus_message_append(reply
, "u", (uint32_t) i
->prefixlen
);
273 r
= sd_bus_message_close_container(reply
);
278 return sd_bus_message_close_container(reply
);
281 const sd_bus_vtable bus_cgroup_vtable
[] = {
282 SD_BUS_VTABLE_START(0),
283 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool
, offsetof(CGroupContext
, delegate
), 0),
284 SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers
, 0, 0),
285 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, cpu_accounting
), 0),
286 SD_BUS_PROPERTY("CPUWeight", "t", NULL
, offsetof(CGroupContext
, cpu_weight
), 0),
287 SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL
, offsetof(CGroupContext
, startup_cpu_weight
), 0),
288 SD_BUS_PROPERTY("CPUShares", "t", NULL
, offsetof(CGroupContext
, cpu_shares
), 0),
289 SD_BUS_PROPERTY("StartupCPUShares", "t", NULL
, offsetof(CGroupContext
, startup_cpu_shares
), 0),
290 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, cpu_quota_per_sec_usec
), 0),
291 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, io_accounting
), 0),
292 SD_BUS_PROPERTY("IOWeight", "t", NULL
, offsetof(CGroupContext
, io_weight
), 0),
293 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_io_weight
), 0),
294 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight
, 0, 0),
295 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
296 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
297 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
298 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
299 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, blockio_accounting
), 0),
300 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL
, offsetof(CGroupContext
, blockio_weight
), 0),
301 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_blockio_weight
), 0),
302 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight
, 0, 0),
303 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
304 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
305 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, memory_accounting
), 0),
306 SD_BUS_PROPERTY("MemoryLow", "t", NULL
, offsetof(CGroupContext
, memory_low
), 0),
307 SD_BUS_PROPERTY("MemoryHigh", "t", NULL
, offsetof(CGroupContext
, memory_high
), 0),
308 SD_BUS_PROPERTY("MemoryMax", "t", NULL
, offsetof(CGroupContext
, memory_max
), 0),
309 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL
, offsetof(CGroupContext
, memory_swap_max
), 0),
310 SD_BUS_PROPERTY("MemoryLimit", "t", NULL
, offsetof(CGroupContext
, memory_limit
), 0),
311 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy
, offsetof(CGroupContext
, device_policy
), 0),
312 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow
, 0, 0),
313 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, tasks_accounting
), 0),
314 SD_BUS_PROPERTY("TasksMax", "t", NULL
, offsetof(CGroupContext
, tasks_max
), 0),
315 SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, ip_accounting
), 0),
316 SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_allow
), 0),
317 SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_deny
), 0),
321 static int bus_cgroup_set_transient_property(
325 sd_bus_message
*message
,
326 UnitWriteFlags flags
,
327 sd_bus_error
*error
) {
336 flags
|= UNIT_PRIVATE
;
338 if (streq(name
, "Delegate")) {
341 if (!UNIT_VTABLE(u
)->can_delegate
)
342 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
344 r
= sd_bus_message_read(message
, "b", &b
);
348 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
350 c
->delegate_controllers
= b
? _CGROUP_MASK_ALL
: 0;
352 unit_write_settingf(u
, flags
, name
, "Delegate=%s", yes_no(b
));
357 } else if (streq(name
, "DelegateControllers")) {
360 if (!UNIT_VTABLE(u
)->can_delegate
)
361 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
363 r
= sd_bus_message_enter_container(message
, 'a', "s");
371 r
= sd_bus_message_read(message
, "s", &t
);
377 cc
= cgroup_controller_from_string(t
);
379 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown cgroup contoller '%s'", t
);
381 mask
|= CGROUP_CONTROLLER_TO_MASK(cc
);
384 r
= sd_bus_message_exit_container(message
);
388 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
389 _cleanup_free_
char *t
= NULL
;
391 r
= cg_mask_to_string(mask
, &t
);
397 c
->delegate_controllers
= 0;
399 c
->delegate_controllers
|= mask
;
401 unit_write_settingf(u
, flags
, name
, "Delegate=%s", strempty(t
));
410 static int bus_cgroup_set_boolean(
415 sd_bus_message
*message
,
416 UnitWriteFlags flags
,
417 sd_bus_error
*error
) {
423 r
= sd_bus_message_read(message
, "b", &b
);
427 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
429 unit_invalidate_cgroup(u
, mask
);
430 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, yes_no(b
));
436 #define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val) \
437 static int bus_cgroup_set_##function( \
441 sd_bus_message *message, \
442 UnitWriteFlags flags, \
443 sd_bus_error *error) { \
450 r = sd_bus_message_read(message, "t", &v); \
455 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
456 "Value specified in %s is out of range", name); \
458 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
460 unit_invalidate_cgroup(u, (mask)); \
463 unit_write_settingf(u, flags, name, \
466 unit_write_settingf(u, flags, name, \
467 "%s=%" PRIu64, name, v); \
473 #define BUS_DEFINE_SET_CGROUP_LIMIT(function, mask, scale, minimum) \
474 static int bus_cgroup_set_##function( \
478 sd_bus_message *message, \
479 UnitWriteFlags flags, \
480 sd_bus_error *error) { \
487 r = sd_bus_message_read(message, "t", &v); \
492 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
493 "Value specified in %s is out of range", name); \
495 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
497 unit_invalidate_cgroup(u, (mask)); \
499 if (v == CGROUP_LIMIT_MAX) \
500 unit_write_settingf(u, flags, name, \
501 "%s=infinity", name); \
503 unit_write_settingf(u, flags, name, \
504 "%s=%" PRIu64, name, v); \
509 static int bus_cgroup_set_##function##_scale( \
513 sd_bus_message *message, \
514 UnitWriteFlags flags, \
515 sd_bus_error *error) { \
523 r = sd_bus_message_read(message, "u", &raw); \
527 v = scale(raw, UINT32_MAX); \
528 if (v < minimum || v >= UINT64_MAX) \
529 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
530 "Value specified in %s is out of range", name); \
532 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
536 unit_invalidate_cgroup(u, (mask)); \
538 /* Chop off suffix */ \
539 assert_se(e = endswith(name, "Scale")); \
540 name = strndupa(name, e - name); \
542 unit_write_settingf(u, flags, name, "%s=%" PRIu32 "%%", name, \
543 (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX))); \
549 #pragma GCC diagnostic push
550 #pragma GCC diagnostic ignored "-Wtype-limits"
551 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight
, CGROUP_MASK_CPU
, CGROUP_WEIGHT_IS_OK
, CGROUP_WEIGHT_INVALID
);
552 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares
, CGROUP_MASK_CPU
, CGROUP_CPU_SHARES_IS_OK
, CGROUP_CPU_SHARES_INVALID
);
553 BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight
, CGROUP_MASK_IO
, CGROUP_WEIGHT_IS_OK
, CGROUP_WEIGHT_INVALID
);
554 BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight
, CGROUP_MASK_BLKIO
, CGROUP_BLKIO_WEIGHT_IS_OK
, CGROUP_BLKIO_WEIGHT_INVALID
);
555 BUS_DEFINE_SET_CGROUP_LIMIT(memory
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 1);
556 BUS_DEFINE_SET_CGROUP_LIMIT(swap
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 0);
557 BUS_DEFINE_SET_CGROUP_LIMIT(tasks_max
, CGROUP_MASK_PIDS
, system_tasks_max_scale
, 1);
558 #pragma GCC diagnostic pop
560 int bus_cgroup_set_property(
564 sd_bus_message
*message
,
565 UnitWriteFlags flags
,
566 sd_bus_error
*error
) {
568 CGroupIOLimitType iol_type
;
576 flags
|= UNIT_PRIVATE
;
578 if (streq(name
, "CPUAccounting"))
579 return bus_cgroup_set_boolean(u
, name
, &c
->cpu_accounting
, CGROUP_MASK_CPUACCT
|CGROUP_MASK_CPU
, message
, flags
, error
);
581 if (streq(name
, "CPUWeight"))
582 return bus_cgroup_set_cpu_weight(u
, name
, &c
->cpu_weight
, message
, flags
, error
);
584 if (streq(name
, "StartupCPUWeight"))
585 return bus_cgroup_set_cpu_weight(u
, name
, &c
->startup_cpu_weight
, message
, flags
, error
);
587 if (streq(name
, "CPUShares"))
588 return bus_cgroup_set_cpu_shares(u
, name
, &c
->cpu_shares
, message
, flags
, error
);
590 if (streq(name
, "StartupCPUShares"))
591 return bus_cgroup_set_cpu_shares(u
, name
, &c
->startup_cpu_shares
, message
, flags
, error
);
593 if (streq(name
, "IOAccounting"))
594 return bus_cgroup_set_boolean(u
, name
, &c
->io_accounting
, CGROUP_MASK_IO
, message
, flags
, error
);
596 if (streq(name
, "IOWeight"))
597 return bus_cgroup_set_io_weight(u
, name
, &c
->io_weight
, message
, flags
, error
);
599 if (streq(name
, "StartupIOWeight"))
600 return bus_cgroup_set_io_weight(u
, name
, &c
->startup_io_weight
, message
, flags
, error
);
602 if (streq(name
, "BlockIOAccounting"))
603 return bus_cgroup_set_boolean(u
, name
, &c
->blockio_accounting
, CGROUP_MASK_BLKIO
, message
, flags
, error
);
605 if (streq(name
, "BlockIOWeight"))
606 return bus_cgroup_set_blockio_weight(u
, name
, &c
->blockio_weight
, message
, flags
, error
);
608 if (streq(name
, "StartupBlockIOWeight"))
609 return bus_cgroup_set_blockio_weight(u
, name
, &c
->startup_blockio_weight
, message
, flags
, error
);
611 if (streq(name
, "MemoryAccounting"))
612 return bus_cgroup_set_boolean(u
, name
, &c
->memory_accounting
, CGROUP_MASK_MEMORY
, message
, flags
, error
);
614 if (streq(name
, "MemoryLow"))
615 return bus_cgroup_set_memory(u
, name
, &c
->memory_low
, message
, flags
, error
);
617 if (streq(name
, "MemoryHigh"))
618 return bus_cgroup_set_memory(u
, name
, &c
->memory_high
, message
, flags
, error
);
620 if (streq(name
, "MemorySwapMax"))
621 return bus_cgroup_set_swap(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
623 if (streq(name
, "MemoryMax"))
624 return bus_cgroup_set_memory(u
, name
, &c
->memory_max
, message
, flags
, error
);
626 if (streq(name
, "MemoryLimit"))
627 return bus_cgroup_set_memory(u
, name
, &c
->memory_limit
, message
, flags
, error
);
629 if (streq(name
, "MemoryLowScale"))
630 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_low
, message
, flags
, error
);
632 if (streq(name
, "MemoryHighScale"))
633 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_high
, message
, flags
, error
);
635 if (streq(name
, "MemorySwapMaxScale"))
636 return bus_cgroup_set_swap_scale(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
638 if (streq(name
, "MemoryMaxScale"))
639 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_max
, message
, flags
, error
);
641 if (streq(name
, "MemoryLimitScale"))
642 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_limit
, message
, flags
, error
);
644 if (streq(name
, "TasksAccounting"))
645 return bus_cgroup_set_boolean(u
, name
, &c
->tasks_accounting
, CGROUP_MASK_PIDS
, message
, flags
, error
);
647 if (streq(name
, "TasksMax"))
648 return bus_cgroup_set_tasks_max(u
, name
, &c
->tasks_max
, message
, flags
, error
);
650 if (streq(name
, "TasksMaxScale"))
651 return bus_cgroup_set_tasks_max_scale(u
, name
, &c
->tasks_max
, message
, flags
, error
);
653 if (streq(name
, "CPUQuotaPerSecUSec")) {
656 r
= sd_bus_message_read(message
, "t", &u64
);
661 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "CPUQuotaPerSecUSec= value out of range");
663 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
664 c
->cpu_quota_per_sec_usec
= u64
;
665 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
667 if (c
->cpu_quota_per_sec_usec
== USEC_INFINITY
)
668 unit_write_setting(u
, flags
, "CPUQuota", "CPUQuota=");
670 /* config_parse_cpu_quota() requires an integer, so truncating division is used on
672 unit_write_settingf(u
, flags
, "CPUQuota",
674 (double) (c
->cpu_quota_per_sec_usec
/ 10000));
679 } else if ((iol_type
= cgroup_io_limit_type_from_string(name
)) >= 0) {
684 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
688 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
690 if (!path_startswith(path
, "/dev") &&
691 !path_startswith(path
, "/run/systemd/inaccessible/"))
692 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s specified in %s= is not a device file in /dev", name
, path
);
694 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
695 CGroupIODeviceLimit
*a
= NULL
, *b
;
697 LIST_FOREACH(device_limits
, b
, c
->io_device_limits
) {
698 if (path_equal(path
, b
->path
)) {
705 CGroupIOLimitType type
;
707 a
= new0(CGroupIODeviceLimit
, 1);
711 a
->path
= strdup(path
);
717 for (type
= 0; type
< _CGROUP_IO_LIMIT_TYPE_MAX
; type
++)
718 a
->limits
[type
] = cgroup_io_limit_defaults
[type
];
720 LIST_PREPEND(device_limits
, c
->io_device_limits
, a
);
723 a
->limits
[iol_type
] = u64
;
731 r
= sd_bus_message_exit_container(message
);
735 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
736 CGroupIODeviceLimit
*a
;
737 _cleanup_free_
char *buf
= NULL
;
738 _cleanup_fclose_
FILE *f
= NULL
;
742 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
743 a
->limits
[iol_type
] = cgroup_io_limit_defaults
[iol_type
];
746 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
748 f
= open_memstream(&buf
, &size
);
752 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
754 fprintf(f
, "%s=\n", name
);
755 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
756 if (a
->limits
[iol_type
] != cgroup_io_limit_defaults
[iol_type
])
757 fprintf(f
, "%s=%s %" PRIu64
"\n", name
, a
->path
, a
->limits
[iol_type
]);
759 r
= fflush_and_check(f
);
762 unit_write_setting(u
, flags
, name
, buf
);
767 } else if (streq(name
, "IODeviceWeight")) {
772 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
776 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
778 if (!path_startswith(path
, "/dev") &&
779 !path_startswith(path
, "/run/systemd/inaccessible/"))
780 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s specified in %s= is not a device file in /dev", name
, path
);
782 if (!CGROUP_WEIGHT_IS_OK(weight
) || weight
== CGROUP_WEIGHT_INVALID
)
783 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "IODeviceWeight= value out of range");
785 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
786 CGroupIODeviceWeight
*a
= NULL
, *b
;
788 LIST_FOREACH(device_weights
, b
, c
->io_device_weights
) {
789 if (path_equal(b
->path
, path
)) {
796 a
= new0(CGroupIODeviceWeight
, 1);
800 a
->path
= strdup(path
);
805 LIST_PREPEND(device_weights
, c
->io_device_weights
, a
);
814 r
= sd_bus_message_exit_container(message
);
818 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
819 _cleanup_free_
char *buf
= NULL
;
820 _cleanup_fclose_
FILE *f
= NULL
;
821 CGroupIODeviceWeight
*a
;
825 while (c
->io_device_weights
)
826 cgroup_context_free_io_device_weight(c
, c
->io_device_weights
);
829 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
831 f
= open_memstream(&buf
, &size
);
835 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
837 fputs("IODeviceWeight=\n", f
);
838 LIST_FOREACH(device_weights
, a
, c
->io_device_weights
)
839 fprintf(f
, "IODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
841 r
= fflush_and_check(f
);
844 unit_write_setting(u
, flags
, name
, buf
);
849 } else if (STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
855 if (streq(name
, "BlockIOWriteBandwidth"))
858 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
862 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
864 if (!path_startswith(path
, "/dev") &&
865 !path_startswith(path
, "/run/systemd/inaccessible/"))
866 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s specified in %s= is not a device file in /dev", name
, path
);
868 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
869 CGroupBlockIODeviceBandwidth
*a
= NULL
, *b
;
871 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
872 if (path_equal(path
, b
->path
)) {
879 a
= new0(CGroupBlockIODeviceBandwidth
, 1);
883 a
->rbps
= CGROUP_LIMIT_MAX
;
884 a
->wbps
= CGROUP_LIMIT_MAX
;
885 a
->path
= strdup(path
);
891 LIST_PREPEND(device_bandwidths
, c
->blockio_device_bandwidths
, a
);
905 r
= sd_bus_message_exit_container(message
);
909 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
910 CGroupBlockIODeviceBandwidth
*a
;
911 _cleanup_free_
char *buf
= NULL
;
912 _cleanup_fclose_
FILE *f
= NULL
;
916 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
) {
918 a
->rbps
= CGROUP_LIMIT_MAX
;
920 a
->wbps
= CGROUP_LIMIT_MAX
;
924 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
926 f
= open_memstream(&buf
, &size
);
930 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
933 fputs("BlockIOReadBandwidth=\n", f
);
934 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
935 if (a
->rbps
!= CGROUP_LIMIT_MAX
)
936 fprintf(f
, "BlockIOReadBandwidth=%s %" PRIu64
"\n", a
->path
, a
->rbps
);
938 fputs("BlockIOWriteBandwidth=\n", f
);
939 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
940 if (a
->wbps
!= CGROUP_LIMIT_MAX
)
941 fprintf(f
, "BlockIOWriteBandwidth=%s %" PRIu64
"\n", a
->path
, a
->wbps
);
944 r
= fflush_and_check(f
);
948 unit_write_setting(u
, flags
, name
, buf
);
953 } else if (streq(name
, "BlockIODeviceWeight")) {
958 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
962 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
964 if (!path_startswith(path
, "/dev") &&
965 !path_startswith(path
, "/run/systemd/inaccessible/"))
966 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s specified in %s= is not a device file in /dev", name
, path
);
968 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
) || weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
969 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "BlockIODeviceWeight= out of range");
971 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
972 CGroupBlockIODeviceWeight
*a
= NULL
, *b
;
974 LIST_FOREACH(device_weights
, b
, c
->blockio_device_weights
) {
975 if (path_equal(b
->path
, path
)) {
982 a
= new0(CGroupBlockIODeviceWeight
, 1);
986 a
->path
= strdup(path
);
991 LIST_PREPEND(device_weights
, c
->blockio_device_weights
, a
);
1000 r
= sd_bus_message_exit_container(message
);
1004 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1005 _cleanup_free_
char *buf
= NULL
;
1006 _cleanup_fclose_
FILE *f
= NULL
;
1007 CGroupBlockIODeviceWeight
*a
;
1011 while (c
->blockio_device_weights
)
1012 cgroup_context_free_blockio_device_weight(c
, c
->blockio_device_weights
);
1015 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
1017 f
= open_memstream(&buf
, &size
);
1021 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
1023 fputs("BlockIODeviceWeight=\n", f
);
1024 LIST_FOREACH(device_weights
, a
, c
->blockio_device_weights
)
1025 fprintf(f
, "BlockIODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
1027 r
= fflush_and_check(f
);
1031 unit_write_setting(u
, flags
, name
, buf
);
1036 } else if (streq(name
, "DevicePolicy")) {
1038 CGroupDevicePolicy p
;
1040 r
= sd_bus_message_read(message
, "s", &policy
);
1044 p
= cgroup_device_policy_from_string(policy
);
1048 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1049 c
->device_policy
= p
;
1050 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1051 unit_write_settingf(u
, flags
, name
, "DevicePolicy=%s", policy
);
1056 } else if (streq(name
, "DeviceAllow")) {
1057 const char *path
, *rwm
;
1060 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
1064 while ((r
= sd_bus_message_read(message
, "(ss)", &path
, &rwm
)) > 0) {
1066 if ((!is_deviceallow_pattern(path
) &&
1067 !path_startswith(path
, "/run/systemd/inaccessible/")) ||
1068 strpbrk(path
, WHITESPACE
))
1069 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires device node");
1074 if (!in_charset(rwm
, "rwm"))
1075 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires combination of rwm flags");
1077 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1078 CGroupDeviceAllow
*a
= NULL
, *b
;
1080 LIST_FOREACH(device_allow
, b
, c
->device_allow
) {
1081 if (path_equal(b
->path
, path
)) {
1088 a
= new0(CGroupDeviceAllow
, 1);
1092 a
->path
= strdup(path
);
1098 LIST_PREPEND(device_allow
, c
->device_allow
, a
);
1101 a
->r
= !!strchr(rwm
, 'r');
1102 a
->w
= !!strchr(rwm
, 'w');
1103 a
->m
= !!strchr(rwm
, 'm');
1111 r
= sd_bus_message_exit_container(message
);
1115 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1116 _cleanup_free_
char *buf
= NULL
;
1117 _cleanup_fclose_
FILE *f
= NULL
;
1118 CGroupDeviceAllow
*a
;
1122 while (c
->device_allow
)
1123 cgroup_context_free_device_allow(c
, c
->device_allow
);
1126 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1128 f
= open_memstream(&buf
, &size
);
1132 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
1134 fputs("DeviceAllow=\n", f
);
1135 LIST_FOREACH(device_allow
, a
, c
->device_allow
)
1136 fprintf(f
, "DeviceAllow=%s %s%s%s\n", a
->path
, a
->r
? "r" : "", a
->w
? "w" : "", a
->m
? "m" : "");
1138 r
= fflush_and_check(f
);
1141 unit_write_setting(u
, flags
, name
, buf
);
1146 } else if (streq(name
, "IPAccounting")) {
1149 r
= sd_bus_message_read(message
, "b", &b
);
1153 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1154 c
->ip_accounting
= b
;
1156 unit_invalidate_cgroup_bpf(u
);
1157 unit_write_settingf(u
, flags
, name
, "IPAccounting=%s", yes_no(b
));
1162 } else if (STR_IN_SET(name
, "IPAddressAllow", "IPAddressDeny")) {
1163 IPAddressAccessItem
**list
;
1166 list
= streq(name
, "IPAddressAllow") ? &c
->ip_address_allow
: &c
->ip_address_deny
;
1168 r
= sd_bus_message_enter_container(message
, 'a', "(iayu)");
1178 r
= sd_bus_message_enter_container(message
, 'r', "iayu");
1184 r
= sd_bus_message_read(message
, "i", &family
);
1188 if (!IN_SET(family
, AF_INET
, AF_INET6
))
1189 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects IPv4 or IPv6 addresses only.", name
);
1191 r
= sd_bus_message_read_array(message
, 'y', &ap
, &an
);
1195 if (an
!= FAMILY_ADDRESS_SIZE(family
))
1196 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "IP address has wrong size for family (%s, expected %zu, got %zu)",
1197 af_to_name(family
), FAMILY_ADDRESS_SIZE(family
), an
);
1199 r
= sd_bus_message_read(message
, "u", &prefixlen
);
1203 if (prefixlen
> FAMILY_ADDRESS_SIZE(family
)*8)
1204 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
));
1206 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1207 IPAddressAccessItem
*item
;
1209 item
= new0(IPAddressAccessItem
, 1);
1213 item
->family
= family
;
1214 item
->prefixlen
= prefixlen
;
1215 memcpy(&item
->address
, ap
, an
);
1217 LIST_PREPEND(items
, *list
, item
);
1220 r
= sd_bus_message_exit_container(message
);
1227 r
= sd_bus_message_exit_container(message
);
1231 *list
= ip_address_access_reduce(*list
);
1233 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1234 _cleanup_free_
char *buf
= NULL
;
1235 _cleanup_fclose_
FILE *f
= NULL
;
1236 IPAddressAccessItem
*item
;
1240 *list
= ip_address_access_free_all(*list
);
1242 unit_invalidate_cgroup_bpf(u
);
1243 f
= open_memstream(&buf
, &size
);
1247 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
1252 LIST_FOREACH(items
, item
, *list
) {
1253 char buffer
[CONST_MAX(INET_ADDRSTRLEN
, INET6_ADDRSTRLEN
)];
1256 if (!inet_ntop(item
->family
, &item
->address
, buffer
, sizeof(buffer
)))
1257 return errno
> 0 ? -errno
: -EINVAL
;
1259 fprintf(f
, "%s=%s/%u\n", name
, buffer
, item
->prefixlen
);
1262 r
= fflush_and_check(f
);
1266 unit_write_setting(u
, flags
, name
, buf
);
1269 r
= bpf_firewall_supported();
1272 if (r
== BPF_FIREWALL_UNSUPPORTED
) {
1273 static bool warned
= false;
1275 log_full(warned
? LOG_DEBUG
: LOG_WARNING
,
1276 "Transient unit %s configures an IP firewall, but the local system does not support BPF/cgroup firewalling.\n"
1277 "Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first started transient unit using IP firewalling.)", u
->id
);
1287 if (u
->transient
&& u
->load_state
== UNIT_STUB
)
1288 return bus_cgroup_set_transient_property(u
, c
, name
, message
, flags
, error
);