1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <arpa/inet.h>
22 #include <stdio_ext.h>
25 #include "alloc-util.h"
26 #include "bpf-firewall.h"
28 #include "cgroup-util.h"
30 #include "dbus-cgroup.h"
31 #include "dbus-util.h"
34 #include "path-util.h"
36 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy
, cgroup_device_policy
, CGroupDevicePolicy
);
38 static int property_get_delegate_controllers(
41 const char *interface
,
43 sd_bus_message
*reply
,
45 sd_bus_error
*error
) {
47 CGroupContext
*c
= userdata
;
56 return sd_bus_message_append(reply
, "as", 0);
58 r
= sd_bus_message_open_container(reply
, 'a', "s");
62 for (cc
= 0; cc
< _CGROUP_CONTROLLER_MAX
; cc
++) {
63 if ((c
->delegate_controllers
& CGROUP_CONTROLLER_TO_MASK(cc
)) == 0)
66 r
= sd_bus_message_append(reply
, "s", cgroup_controller_to_string(cc
));
71 return sd_bus_message_close_container(reply
);
74 static int property_get_io_device_weight(
77 const char *interface
,
79 sd_bus_message
*reply
,
81 sd_bus_error
*error
) {
83 CGroupContext
*c
= userdata
;
84 CGroupIODeviceWeight
*w
;
91 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
95 LIST_FOREACH(device_weights
, w
, c
->io_device_weights
) {
96 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
101 return sd_bus_message_close_container(reply
);
104 static int property_get_io_device_limits(
107 const char *interface
,
108 const char *property
,
109 sd_bus_message
*reply
,
111 sd_bus_error
*error
) {
113 CGroupContext
*c
= userdata
;
114 CGroupIODeviceLimit
*l
;
121 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
125 LIST_FOREACH(device_limits
, l
, c
->io_device_limits
) {
126 CGroupIOLimitType type
;
128 type
= cgroup_io_limit_type_from_string(property
);
129 if (type
< 0 || l
->limits
[type
] == cgroup_io_limit_defaults
[type
])
132 r
= sd_bus_message_append(reply
, "(st)", l
->path
, l
->limits
[type
]);
137 return sd_bus_message_close_container(reply
);
140 static int property_get_blockio_device_weight(
143 const char *interface
,
144 const char *property
,
145 sd_bus_message
*reply
,
147 sd_bus_error
*error
) {
149 CGroupContext
*c
= userdata
;
150 CGroupBlockIODeviceWeight
*w
;
157 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
161 LIST_FOREACH(device_weights
, w
, c
->blockio_device_weights
) {
162 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
167 return sd_bus_message_close_container(reply
);
170 static int property_get_blockio_device_bandwidths(
173 const char *interface
,
174 const char *property
,
175 sd_bus_message
*reply
,
177 sd_bus_error
*error
) {
179 CGroupContext
*c
= userdata
;
180 CGroupBlockIODeviceBandwidth
*b
;
187 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
191 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
194 if (streq(property
, "BlockIOReadBandwidth"))
199 if (v
== CGROUP_LIMIT_MAX
)
202 r
= sd_bus_message_append(reply
, "(st)", b
->path
, v
);
207 return sd_bus_message_close_container(reply
);
210 static int property_get_device_allow(
213 const char *interface
,
214 const char *property
,
215 sd_bus_message
*reply
,
217 sd_bus_error
*error
) {
219 CGroupContext
*c
= userdata
;
220 CGroupDeviceAllow
*a
;
227 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
231 LIST_FOREACH(device_allow
, a
, c
->device_allow
) {
244 r
= sd_bus_message_append(reply
, "(ss)", a
->path
, rwm
);
249 return sd_bus_message_close_container(reply
);
252 static int property_get_ip_address_access(
255 const char *interface
,
256 const char *property
,
257 sd_bus_message
*reply
,
259 sd_bus_error
*error
) {
261 IPAddressAccessItem
** items
= userdata
, *i
;
264 r
= sd_bus_message_open_container(reply
, 'a', "(iayu)");
268 LIST_FOREACH(items
, i
, *items
) {
270 r
= sd_bus_message_open_container(reply
, 'r', "iayu");
274 r
= sd_bus_message_append(reply
, "i", i
->family
);
278 r
= sd_bus_message_append_array(reply
, 'y', &i
->address
, FAMILY_ADDRESS_SIZE(i
->family
));
282 r
= sd_bus_message_append(reply
, "u", (uint32_t) i
->prefixlen
);
286 r
= sd_bus_message_close_container(reply
);
291 return sd_bus_message_close_container(reply
);
294 const sd_bus_vtable bus_cgroup_vtable
[] = {
295 SD_BUS_VTABLE_START(0),
296 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool
, offsetof(CGroupContext
, delegate
), 0),
297 SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers
, 0, 0),
298 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, cpu_accounting
), 0),
299 SD_BUS_PROPERTY("CPUWeight", "t", NULL
, offsetof(CGroupContext
, cpu_weight
), 0),
300 SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL
, offsetof(CGroupContext
, startup_cpu_weight
), 0),
301 SD_BUS_PROPERTY("CPUShares", "t", NULL
, offsetof(CGroupContext
, cpu_shares
), 0),
302 SD_BUS_PROPERTY("StartupCPUShares", "t", NULL
, offsetof(CGroupContext
, startup_cpu_shares
), 0),
303 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, cpu_quota_per_sec_usec
), 0),
304 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, io_accounting
), 0),
305 SD_BUS_PROPERTY("IOWeight", "t", NULL
, offsetof(CGroupContext
, io_weight
), 0),
306 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_io_weight
), 0),
307 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight
, 0, 0),
308 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
309 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
310 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
311 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
312 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, blockio_accounting
), 0),
313 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL
, offsetof(CGroupContext
, blockio_weight
), 0),
314 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_blockio_weight
), 0),
315 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight
, 0, 0),
316 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
317 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
318 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, memory_accounting
), 0),
319 SD_BUS_PROPERTY("MemoryLow", "t", NULL
, offsetof(CGroupContext
, memory_low
), 0),
320 SD_BUS_PROPERTY("MemoryHigh", "t", NULL
, offsetof(CGroupContext
, memory_high
), 0),
321 SD_BUS_PROPERTY("MemoryMax", "t", NULL
, offsetof(CGroupContext
, memory_max
), 0),
322 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL
, offsetof(CGroupContext
, memory_swap_max
), 0),
323 SD_BUS_PROPERTY("MemoryLimit", "t", NULL
, offsetof(CGroupContext
, memory_limit
), 0),
324 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy
, offsetof(CGroupContext
, device_policy
), 0),
325 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow
, 0, 0),
326 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, tasks_accounting
), 0),
327 SD_BUS_PROPERTY("TasksMax", "t", NULL
, offsetof(CGroupContext
, tasks_max
), 0),
328 SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, ip_accounting
), 0),
329 SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_allow
), 0),
330 SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_deny
), 0),
334 static int bus_cgroup_set_transient_property(
338 sd_bus_message
*message
,
339 UnitWriteFlags flags
,
340 sd_bus_error
*error
) {
349 flags
|= UNIT_PRIVATE
;
351 if (streq(name
, "Delegate")) {
354 if (!UNIT_VTABLE(u
)->can_delegate
)
355 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
357 r
= sd_bus_message_read(message
, "b", &b
);
361 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
363 c
->delegate_controllers
= b
? _CGROUP_MASK_ALL
: 0;
365 unit_write_settingf(u
, flags
, name
, "Delegate=%s", yes_no(b
));
370 } else if (streq(name
, "DelegateControllers")) {
373 if (!UNIT_VTABLE(u
)->can_delegate
)
374 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
376 r
= sd_bus_message_enter_container(message
, 'a', "s");
384 r
= sd_bus_message_read(message
, "s", &t
);
390 cc
= cgroup_controller_from_string(t
);
392 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown cgroup contoller '%s'", t
);
394 mask
|= CGROUP_CONTROLLER_TO_MASK(cc
);
397 r
= sd_bus_message_exit_container(message
);
401 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
402 _cleanup_free_
char *t
= NULL
;
404 r
= cg_mask_to_string(mask
, &t
);
410 c
->delegate_controllers
= 0;
412 c
->delegate_controllers
|= mask
;
414 unit_write_settingf(u
, flags
, name
, "Delegate=%s", strempty(t
));
423 static int bus_cgroup_set_boolean(
428 sd_bus_message
*message
,
429 UnitWriteFlags flags
,
430 sd_bus_error
*error
) {
436 r
= sd_bus_message_read(message
, "b", &b
);
440 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
442 unit_invalidate_cgroup(u
, mask
);
443 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, yes_no(b
));
449 #define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val) \
450 static int bus_cgroup_set_##function( \
454 sd_bus_message *message, \
455 UnitWriteFlags flags, \
456 sd_bus_error *error) { \
463 r = sd_bus_message_read(message, "t", &v); \
468 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
469 "Value specified in %s is out of range", name); \
471 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
473 unit_invalidate_cgroup(u, (mask)); \
476 unit_write_settingf(u, flags, name, \
479 unit_write_settingf(u, flags, name, \
480 "%s=%" PRIu64, name, v); \
486 #define BUS_DEFINE_SET_CGROUP_LIMIT(function, mask, scale, minimum) \
487 static int bus_cgroup_set_##function( \
491 sd_bus_message *message, \
492 UnitWriteFlags flags, \
493 sd_bus_error *error) { \
500 r = sd_bus_message_read(message, "t", &v); \
505 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
506 "Value specified in %s is out of range", name); \
508 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
510 unit_invalidate_cgroup(u, (mask)); \
512 if (v == CGROUP_LIMIT_MAX) \
513 unit_write_settingf(u, flags, name, \
514 "%s=infinity", name); \
516 unit_write_settingf(u, flags, name, \
517 "%s=%" PRIu64, name, v); \
522 static int bus_cgroup_set_##function##_scale( \
526 sd_bus_message *message, \
527 UnitWriteFlags flags, \
528 sd_bus_error *error) { \
536 r = sd_bus_message_read(message, "u", &raw); \
540 v = scale(raw, UINT32_MAX); \
541 if (v < minimum || v >= UINT64_MAX) \
542 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
543 "Value specified in %s is out of range", name); \
545 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
549 unit_invalidate_cgroup(u, (mask)); \
551 /* Chop off suffix */ \
552 assert_se(e = endswith(name, "Scale")); \
553 name = strndupa(name, e - name); \
555 unit_write_settingf(u, flags, name, "%s=%" PRIu32 "%%", name, \
556 (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX))); \
562 #pragma GCC diagnostic push
563 #pragma GCC diagnostic ignored "-Wtype-limits"
564 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight
, CGROUP_MASK_CPU
, CGROUP_WEIGHT_IS_OK
, CGROUP_WEIGHT_INVALID
);
565 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares
, CGROUP_MASK_CPU
, CGROUP_CPU_SHARES_IS_OK
, CGROUP_CPU_SHARES_INVALID
);
566 BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight
, CGROUP_MASK_IO
, CGROUP_WEIGHT_IS_OK
, CGROUP_WEIGHT_INVALID
);
567 BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight
, CGROUP_MASK_BLKIO
, CGROUP_BLKIO_WEIGHT_IS_OK
, CGROUP_BLKIO_WEIGHT_INVALID
);
568 BUS_DEFINE_SET_CGROUP_LIMIT(memory
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 1);
569 BUS_DEFINE_SET_CGROUP_LIMIT(swap
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 0);
570 BUS_DEFINE_SET_CGROUP_LIMIT(tasks_max
, CGROUP_MASK_PIDS
, system_tasks_max_scale
, 1);
571 #pragma GCC diagnostic pop
573 int bus_cgroup_set_property(
577 sd_bus_message
*message
,
578 UnitWriteFlags flags
,
579 sd_bus_error
*error
) {
581 CGroupIOLimitType iol_type
;
589 flags
|= UNIT_PRIVATE
;
591 if (streq(name
, "CPUAccounting"))
592 return bus_cgroup_set_boolean(u
, name
, &c
->cpu_accounting
, CGROUP_MASK_CPUACCT
|CGROUP_MASK_CPU
, message
, flags
, error
);
594 if (streq(name
, "CPUWeight"))
595 return bus_cgroup_set_cpu_weight(u
, name
, &c
->cpu_weight
, message
, flags
, error
);
597 if (streq(name
, "StartupCPUWeight"))
598 return bus_cgroup_set_cpu_weight(u
, name
, &c
->startup_cpu_weight
, message
, flags
, error
);
600 if (streq(name
, "CPUShares"))
601 return bus_cgroup_set_cpu_shares(u
, name
, &c
->cpu_shares
, message
, flags
, error
);
603 if (streq(name
, "StartupCPUShares"))
604 return bus_cgroup_set_cpu_shares(u
, name
, &c
->startup_cpu_shares
, message
, flags
, error
);
606 if (streq(name
, "IOAccounting"))
607 return bus_cgroup_set_boolean(u
, name
, &c
->io_accounting
, CGROUP_MASK_IO
, message
, flags
, error
);
609 if (streq(name
, "IOWeight"))
610 return bus_cgroup_set_io_weight(u
, name
, &c
->io_weight
, message
, flags
, error
);
612 if (streq(name
, "StartupIOWeight"))
613 return bus_cgroup_set_io_weight(u
, name
, &c
->startup_io_weight
, message
, flags
, error
);
615 if (streq(name
, "BlockIOAccounting"))
616 return bus_cgroup_set_boolean(u
, name
, &c
->blockio_accounting
, CGROUP_MASK_BLKIO
, message
, flags
, error
);
618 if (streq(name
, "BlockIOWeight"))
619 return bus_cgroup_set_blockio_weight(u
, name
, &c
->blockio_weight
, message
, flags
, error
);
621 if (streq(name
, "StartupBlockIOWeight"))
622 return bus_cgroup_set_blockio_weight(u
, name
, &c
->startup_blockio_weight
, message
, flags
, error
);
624 if (streq(name
, "MemoryAccounting"))
625 return bus_cgroup_set_boolean(u
, name
, &c
->memory_accounting
, CGROUP_MASK_MEMORY
, message
, flags
, error
);
627 if (streq(name
, "MemoryLow"))
628 return bus_cgroup_set_memory(u
, name
, &c
->memory_low
, message
, flags
, error
);
630 if (streq(name
, "MemoryHigh"))
631 return bus_cgroup_set_memory(u
, name
, &c
->memory_high
, message
, flags
, error
);
633 if (streq(name
, "MemorySwapMax"))
634 return bus_cgroup_set_swap(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
636 if (streq(name
, "MemoryMax"))
637 return bus_cgroup_set_memory(u
, name
, &c
->memory_max
, message
, flags
, error
);
639 if (streq(name
, "MemoryLimit"))
640 return bus_cgroup_set_memory(u
, name
, &c
->memory_limit
, message
, flags
, error
);
642 if (streq(name
, "MemoryLowScale"))
643 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_low
, message
, flags
, error
);
645 if (streq(name
, "MemoryHighScale"))
646 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_high
, message
, flags
, error
);
648 if (streq(name
, "MemorySwapMaxScale"))
649 return bus_cgroup_set_swap_scale(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
651 if (streq(name
, "MemoryMaxScale"))
652 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_max
, message
, flags
, error
);
654 if (streq(name
, "MemoryLimitScale"))
655 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_limit
, message
, flags
, error
);
657 if (streq(name
, "TasksAccounting"))
658 return bus_cgroup_set_boolean(u
, name
, &c
->tasks_accounting
, CGROUP_MASK_PIDS
, message
, flags
, error
);
660 if (streq(name
, "TasksMax"))
661 return bus_cgroup_set_tasks_max(u
, name
, &c
->tasks_max
, message
, flags
, error
);
663 if (streq(name
, "TasksMaxScale"))
664 return bus_cgroup_set_tasks_max_scale(u
, name
, &c
->tasks_max
, message
, flags
, error
);
666 if (streq(name
, "CPUQuotaPerSecUSec")) {
669 r
= sd_bus_message_read(message
, "t", &u64
);
674 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "CPUQuotaPerSecUSec= value out of range");
676 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
677 c
->cpu_quota_per_sec_usec
= u64
;
678 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
680 if (c
->cpu_quota_per_sec_usec
== USEC_INFINITY
)
681 unit_write_setting(u
, flags
, "CPUQuota", "CPUQuota=");
683 /* config_parse_cpu_quota() requires an integer, so truncating division is used on
685 unit_write_settingf(u
, flags
, "CPUQuota",
687 (double) (c
->cpu_quota_per_sec_usec
/ 10000));
692 } else if ((iol_type
= cgroup_io_limit_type_from_string(name
)) >= 0) {
697 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
701 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
703 if (!path_startswith(path
, "/dev") &&
704 !path_startswith(path
, "/run/systemd/inaccessible/"))
705 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
);
707 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
708 CGroupIODeviceLimit
*a
= NULL
, *b
;
710 LIST_FOREACH(device_limits
, b
, c
->io_device_limits
) {
711 if (path_equal(path
, b
->path
)) {
718 CGroupIOLimitType type
;
720 a
= new0(CGroupIODeviceLimit
, 1);
724 a
->path
= strdup(path
);
730 for (type
= 0; type
< _CGROUP_IO_LIMIT_TYPE_MAX
; type
++)
731 a
->limits
[type
] = cgroup_io_limit_defaults
[type
];
733 LIST_PREPEND(device_limits
, c
->io_device_limits
, a
);
736 a
->limits
[iol_type
] = u64
;
744 r
= sd_bus_message_exit_container(message
);
748 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
749 CGroupIODeviceLimit
*a
;
750 _cleanup_free_
char *buf
= NULL
;
751 _cleanup_fclose_
FILE *f
= NULL
;
755 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
756 a
->limits
[iol_type
] = cgroup_io_limit_defaults
[iol_type
];
759 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
761 f
= open_memstream(&buf
, &size
);
765 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
767 fprintf(f
, "%s=\n", name
);
768 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
769 if (a
->limits
[iol_type
] != cgroup_io_limit_defaults
[iol_type
])
770 fprintf(f
, "%s=%s %" PRIu64
"\n", name
, a
->path
, a
->limits
[iol_type
]);
772 r
= fflush_and_check(f
);
775 unit_write_setting(u
, flags
, name
, buf
);
780 } else if (streq(name
, "IODeviceWeight")) {
785 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
789 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
791 if (!path_startswith(path
, "/dev") &&
792 !path_startswith(path
, "/run/systemd/inaccessible/"))
793 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
);
795 if (!CGROUP_WEIGHT_IS_OK(weight
) || weight
== CGROUP_WEIGHT_INVALID
)
796 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "IODeviceWeight= value out of range");
798 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
799 CGroupIODeviceWeight
*a
= NULL
, *b
;
801 LIST_FOREACH(device_weights
, b
, c
->io_device_weights
) {
802 if (path_equal(b
->path
, path
)) {
809 a
= new0(CGroupIODeviceWeight
, 1);
813 a
->path
= strdup(path
);
818 LIST_PREPEND(device_weights
, c
->io_device_weights
, a
);
827 r
= sd_bus_message_exit_container(message
);
831 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
832 _cleanup_free_
char *buf
= NULL
;
833 _cleanup_fclose_
FILE *f
= NULL
;
834 CGroupIODeviceWeight
*a
;
838 while (c
->io_device_weights
)
839 cgroup_context_free_io_device_weight(c
, c
->io_device_weights
);
842 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
844 f
= open_memstream(&buf
, &size
);
848 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
850 fputs("IODeviceWeight=\n", f
);
851 LIST_FOREACH(device_weights
, a
, c
->io_device_weights
)
852 fprintf(f
, "IODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
854 r
= fflush_and_check(f
);
857 unit_write_setting(u
, flags
, name
, buf
);
862 } else if (STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
868 if (streq(name
, "BlockIOWriteBandwidth"))
871 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
875 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
877 if (!path_startswith(path
, "/dev") &&
878 !path_startswith(path
, "/run/systemd/inaccessible/"))
879 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
);
881 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
882 CGroupBlockIODeviceBandwidth
*a
= NULL
, *b
;
884 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
885 if (path_equal(path
, b
->path
)) {
892 a
= new0(CGroupBlockIODeviceBandwidth
, 1);
896 a
->rbps
= CGROUP_LIMIT_MAX
;
897 a
->wbps
= CGROUP_LIMIT_MAX
;
898 a
->path
= strdup(path
);
904 LIST_PREPEND(device_bandwidths
, c
->blockio_device_bandwidths
, a
);
918 r
= sd_bus_message_exit_container(message
);
922 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
923 CGroupBlockIODeviceBandwidth
*a
;
924 _cleanup_free_
char *buf
= NULL
;
925 _cleanup_fclose_
FILE *f
= NULL
;
929 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
) {
931 a
->rbps
= CGROUP_LIMIT_MAX
;
933 a
->wbps
= CGROUP_LIMIT_MAX
;
937 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
939 f
= open_memstream(&buf
, &size
);
943 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
946 fputs("BlockIOReadBandwidth=\n", f
);
947 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
948 if (a
->rbps
!= CGROUP_LIMIT_MAX
)
949 fprintf(f
, "BlockIOReadBandwidth=%s %" PRIu64
"\n", a
->path
, a
->rbps
);
951 fputs("BlockIOWriteBandwidth=\n", f
);
952 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
953 if (a
->wbps
!= CGROUP_LIMIT_MAX
)
954 fprintf(f
, "BlockIOWriteBandwidth=%s %" PRIu64
"\n", a
->path
, a
->wbps
);
957 r
= fflush_and_check(f
);
961 unit_write_setting(u
, flags
, name
, buf
);
966 } else if (streq(name
, "BlockIODeviceWeight")) {
971 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
975 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
977 if (!path_startswith(path
, "/dev") &&
978 !path_startswith(path
, "/run/systemd/inaccessible/"))
979 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
);
981 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
) || weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
982 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "BlockIODeviceWeight= out of range");
984 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
985 CGroupBlockIODeviceWeight
*a
= NULL
, *b
;
987 LIST_FOREACH(device_weights
, b
, c
->blockio_device_weights
) {
988 if (path_equal(b
->path
, path
)) {
995 a
= new0(CGroupBlockIODeviceWeight
, 1);
999 a
->path
= strdup(path
);
1004 LIST_PREPEND(device_weights
, c
->blockio_device_weights
, a
);
1013 r
= sd_bus_message_exit_container(message
);
1017 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1018 _cleanup_free_
char *buf
= NULL
;
1019 _cleanup_fclose_
FILE *f
= NULL
;
1020 CGroupBlockIODeviceWeight
*a
;
1024 while (c
->blockio_device_weights
)
1025 cgroup_context_free_blockio_device_weight(c
, c
->blockio_device_weights
);
1028 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
1030 f
= open_memstream(&buf
, &size
);
1034 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
1036 fputs("BlockIODeviceWeight=\n", f
);
1037 LIST_FOREACH(device_weights
, a
, c
->blockio_device_weights
)
1038 fprintf(f
, "BlockIODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
1040 r
= fflush_and_check(f
);
1044 unit_write_setting(u
, flags
, name
, buf
);
1049 } else if (streq(name
, "DevicePolicy")) {
1051 CGroupDevicePolicy p
;
1053 r
= sd_bus_message_read(message
, "s", &policy
);
1057 p
= cgroup_device_policy_from_string(policy
);
1061 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1062 c
->device_policy
= p
;
1063 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1064 unit_write_settingf(u
, flags
, name
, "DevicePolicy=%s", policy
);
1069 } else if (streq(name
, "DeviceAllow")) {
1070 const char *path
, *rwm
;
1073 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
1077 while ((r
= sd_bus_message_read(message
, "(ss)", &path
, &rwm
)) > 0) {
1079 if ((!is_deviceallow_pattern(path
) &&
1080 !path_startswith(path
, "/run/systemd/inaccessible/")) ||
1081 strpbrk(path
, WHITESPACE
))
1082 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires device node");
1087 if (!in_charset(rwm
, "rwm"))
1088 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires combination of rwm flags");
1090 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1091 CGroupDeviceAllow
*a
= NULL
, *b
;
1093 LIST_FOREACH(device_allow
, b
, c
->device_allow
) {
1094 if (path_equal(b
->path
, path
)) {
1101 a
= new0(CGroupDeviceAllow
, 1);
1105 a
->path
= strdup(path
);
1111 LIST_PREPEND(device_allow
, c
->device_allow
, a
);
1114 a
->r
= !!strchr(rwm
, 'r');
1115 a
->w
= !!strchr(rwm
, 'w');
1116 a
->m
= !!strchr(rwm
, 'm');
1124 r
= sd_bus_message_exit_container(message
);
1128 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1129 _cleanup_free_
char *buf
= NULL
;
1130 _cleanup_fclose_
FILE *f
= NULL
;
1131 CGroupDeviceAllow
*a
;
1135 while (c
->device_allow
)
1136 cgroup_context_free_device_allow(c
, c
->device_allow
);
1139 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1141 f
= open_memstream(&buf
, &size
);
1145 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
1147 fputs("DeviceAllow=\n", f
);
1148 LIST_FOREACH(device_allow
, a
, c
->device_allow
)
1149 fprintf(f
, "DeviceAllow=%s %s%s%s\n", a
->path
, a
->r
? "r" : "", a
->w
? "w" : "", a
->m
? "m" : "");
1151 r
= fflush_and_check(f
);
1154 unit_write_setting(u
, flags
, name
, buf
);
1159 } else if (streq(name
, "IPAccounting")) {
1162 r
= sd_bus_message_read(message
, "b", &b
);
1166 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1167 c
->ip_accounting
= b
;
1169 unit_invalidate_cgroup_bpf(u
);
1170 unit_write_settingf(u
, flags
, name
, "IPAccounting=%s", yes_no(b
));
1175 } else if (STR_IN_SET(name
, "IPAddressAllow", "IPAddressDeny")) {
1176 IPAddressAccessItem
**list
;
1179 list
= streq(name
, "IPAddressAllow") ? &c
->ip_address_allow
: &c
->ip_address_deny
;
1181 r
= sd_bus_message_enter_container(message
, 'a', "(iayu)");
1191 r
= sd_bus_message_enter_container(message
, 'r', "iayu");
1197 r
= sd_bus_message_read(message
, "i", &family
);
1201 if (!IN_SET(family
, AF_INET
, AF_INET6
))
1202 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects IPv4 or IPv6 addresses only.", name
);
1204 r
= sd_bus_message_read_array(message
, 'y', &ap
, &an
);
1208 if (an
!= FAMILY_ADDRESS_SIZE(family
))
1209 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "IP address has wrong size for family (%s, expected %zu, got %zu)",
1210 af_to_name(family
), FAMILY_ADDRESS_SIZE(family
), an
);
1212 r
= sd_bus_message_read(message
, "u", &prefixlen
);
1216 if (prefixlen
> FAMILY_ADDRESS_SIZE(family
)*8)
1217 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
));
1219 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1220 IPAddressAccessItem
*item
;
1222 item
= new0(IPAddressAccessItem
, 1);
1226 item
->family
= family
;
1227 item
->prefixlen
= prefixlen
;
1228 memcpy(&item
->address
, ap
, an
);
1230 LIST_PREPEND(items
, *list
, item
);
1233 r
= sd_bus_message_exit_container(message
);
1240 r
= sd_bus_message_exit_container(message
);
1244 *list
= ip_address_access_reduce(*list
);
1246 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1247 _cleanup_free_
char *buf
= NULL
;
1248 _cleanup_fclose_
FILE *f
= NULL
;
1249 IPAddressAccessItem
*item
;
1253 *list
= ip_address_access_free_all(*list
);
1255 unit_invalidate_cgroup_bpf(u
);
1256 f
= open_memstream(&buf
, &size
);
1260 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
1265 LIST_FOREACH(items
, item
, *list
) {
1266 char buffer
[CONST_MAX(INET_ADDRSTRLEN
, INET6_ADDRSTRLEN
)];
1269 if (!inet_ntop(item
->family
, &item
->address
, buffer
, sizeof(buffer
)))
1270 return errno
> 0 ? -errno
: -EINVAL
;
1272 fprintf(f
, "%s=%s/%u\n", name
, buffer
, item
->prefixlen
);
1275 r
= fflush_and_check(f
);
1279 unit_write_setting(u
, flags
, name
, buf
);
1282 r
= bpf_firewall_supported();
1285 if (r
== BPF_FIREWALL_UNSUPPORTED
) {
1286 static bool warned
= false;
1288 log_full(warned
? LOG_DEBUG
: LOG_WARNING
,
1289 "Transient unit %s configures an IP firewall, but the local system does not support BPF/cgroup firewalling.\n"
1290 "Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first started transient unit using IP firewalling.)", u
->id
);
1300 if (u
->transient
&& u
->load_state
== UNIT_STUB
)
1301 return bus_cgroup_set_transient_property(u
, c
, name
, message
, flags
, error
);