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>
24 #include "alloc-util.h"
25 #include "bpf-firewall.h"
27 #include "cgroup-util.h"
29 #include "dbus-cgroup.h"
32 #include "path-util.h"
34 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy
, cgroup_device_policy
, CGroupDevicePolicy
);
36 static int property_get_delegate_controllers(
39 const char *interface
,
41 sd_bus_message
*reply
,
43 sd_bus_error
*error
) {
45 CGroupContext
*c
= userdata
;
54 return sd_bus_message_append(reply
, "as", 0);
56 r
= sd_bus_message_open_container(reply
, 'a', "s");
60 for (cc
= 0; cc
< _CGROUP_CONTROLLER_MAX
; cc
++) {
61 if ((c
->delegate_controllers
& CGROUP_CONTROLLER_TO_MASK(cc
)) == 0)
64 r
= sd_bus_message_append(reply
, "s", cgroup_controller_to_string(cc
));
69 return sd_bus_message_close_container(reply
);
72 static int property_get_io_device_weight(
75 const char *interface
,
77 sd_bus_message
*reply
,
79 sd_bus_error
*error
) {
81 CGroupContext
*c
= userdata
;
82 CGroupIODeviceWeight
*w
;
89 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
93 LIST_FOREACH(device_weights
, w
, c
->io_device_weights
) {
94 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
99 return sd_bus_message_close_container(reply
);
102 static int property_get_io_device_limits(
105 const char *interface
,
106 const char *property
,
107 sd_bus_message
*reply
,
109 sd_bus_error
*error
) {
111 CGroupContext
*c
= userdata
;
112 CGroupIODeviceLimit
*l
;
119 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
123 LIST_FOREACH(device_limits
, l
, c
->io_device_limits
) {
124 CGroupIOLimitType type
;
126 type
= cgroup_io_limit_type_from_string(property
);
127 if (type
< 0 || l
->limits
[type
] == cgroup_io_limit_defaults
[type
])
130 r
= sd_bus_message_append(reply
, "(st)", l
->path
, l
->limits
[type
]);
135 return sd_bus_message_close_container(reply
);
138 static int property_get_blockio_device_weight(
141 const char *interface
,
142 const char *property
,
143 sd_bus_message
*reply
,
145 sd_bus_error
*error
) {
147 CGroupContext
*c
= userdata
;
148 CGroupBlockIODeviceWeight
*w
;
155 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
159 LIST_FOREACH(device_weights
, w
, c
->blockio_device_weights
) {
160 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
165 return sd_bus_message_close_container(reply
);
168 static int property_get_blockio_device_bandwidths(
171 const char *interface
,
172 const char *property
,
173 sd_bus_message
*reply
,
175 sd_bus_error
*error
) {
177 CGroupContext
*c
= userdata
;
178 CGroupBlockIODeviceBandwidth
*b
;
185 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
189 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
192 if (streq(property
, "BlockIOReadBandwidth"))
197 if (v
== CGROUP_LIMIT_MAX
)
200 r
= sd_bus_message_append(reply
, "(st)", b
->path
, v
);
205 return sd_bus_message_close_container(reply
);
208 static int property_get_device_allow(
211 const char *interface
,
212 const char *property
,
213 sd_bus_message
*reply
,
215 sd_bus_error
*error
) {
217 CGroupContext
*c
= userdata
;
218 CGroupDeviceAllow
*a
;
225 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
229 LIST_FOREACH(device_allow
, a
, c
->device_allow
) {
242 r
= sd_bus_message_append(reply
, "(ss)", a
->path
, rwm
);
247 return sd_bus_message_close_container(reply
);
250 static int property_get_ip_address_access(
253 const char *interface
,
254 const char *property
,
255 sd_bus_message
*reply
,
257 sd_bus_error
*error
) {
259 IPAddressAccessItem
** items
= userdata
, *i
;
262 r
= sd_bus_message_open_container(reply
, 'a', "(iayu)");
266 LIST_FOREACH(items
, i
, *items
) {
268 r
= sd_bus_message_open_container(reply
, 'r', "iayu");
272 r
= sd_bus_message_append(reply
, "i", i
->family
);
276 r
= sd_bus_message_append_array(reply
, 'y', &i
->address
, FAMILY_ADDRESS_SIZE(i
->family
));
280 r
= sd_bus_message_append(reply
, "u", (uint32_t) i
->prefixlen
);
284 r
= sd_bus_message_close_container(reply
);
289 return sd_bus_message_close_container(reply
);
292 const sd_bus_vtable bus_cgroup_vtable
[] = {
293 SD_BUS_VTABLE_START(0),
294 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool
, offsetof(CGroupContext
, delegate
), 0),
295 SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers
, 0, 0),
296 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, cpu_accounting
), 0),
297 SD_BUS_PROPERTY("CPUWeight", "t", NULL
, offsetof(CGroupContext
, cpu_weight
), 0),
298 SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL
, offsetof(CGroupContext
, startup_cpu_weight
), 0),
299 SD_BUS_PROPERTY("CPUShares", "t", NULL
, offsetof(CGroupContext
, cpu_shares
), 0),
300 SD_BUS_PROPERTY("StartupCPUShares", "t", NULL
, offsetof(CGroupContext
, startup_cpu_shares
), 0),
301 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, cpu_quota_per_sec_usec
), 0),
302 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, io_accounting
), 0),
303 SD_BUS_PROPERTY("IOWeight", "t", NULL
, offsetof(CGroupContext
, io_weight
), 0),
304 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_io_weight
), 0),
305 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight
, 0, 0),
306 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
307 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
308 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
309 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
310 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, blockio_accounting
), 0),
311 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL
, offsetof(CGroupContext
, blockio_weight
), 0),
312 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_blockio_weight
), 0),
313 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight
, 0, 0),
314 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
315 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
316 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, memory_accounting
), 0),
317 SD_BUS_PROPERTY("MemoryLow", "t", NULL
, offsetof(CGroupContext
, memory_low
), 0),
318 SD_BUS_PROPERTY("MemoryHigh", "t", NULL
, offsetof(CGroupContext
, memory_high
), 0),
319 SD_BUS_PROPERTY("MemoryMax", "t", NULL
, offsetof(CGroupContext
, memory_max
), 0),
320 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL
, offsetof(CGroupContext
, memory_swap_max
), 0),
321 SD_BUS_PROPERTY("MemoryLimit", "t", NULL
, offsetof(CGroupContext
, memory_limit
), 0),
322 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy
, offsetof(CGroupContext
, device_policy
), 0),
323 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow
, 0, 0),
324 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, tasks_accounting
), 0),
325 SD_BUS_PROPERTY("TasksMax", "t", NULL
, offsetof(CGroupContext
, tasks_max
), 0),
326 SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, ip_accounting
), 0),
327 SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_allow
), 0),
328 SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_deny
), 0),
332 static int bus_cgroup_set_transient_property(
336 sd_bus_message
*message
,
337 UnitWriteFlags flags
,
338 sd_bus_error
*error
) {
347 flags
|= UNIT_PRIVATE
;
349 if (streq(name
, "Delegate")) {
352 r
= sd_bus_message_read(message
, "b", &b
);
356 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
358 c
->delegate_controllers
= b
? _CGROUP_MASK_ALL
: 0;
360 unit_write_settingf(u
, flags
, name
, "Delegate=%s", yes_no(b
));
365 } else if (streq(name
, "DelegateControllers")) {
368 r
= sd_bus_message_enter_container(message
, 'a', "s");
376 r
= sd_bus_message_read(message
, "s", &t
);
382 cc
= cgroup_controller_from_string(t
);
384 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown cgroup contoller '%s'", t
);
386 mask
|= CGROUP_CONTROLLER_TO_MASK(cc
);
389 r
= sd_bus_message_exit_container(message
);
393 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
394 _cleanup_free_
char *t
= NULL
;
396 r
= cg_mask_to_string(mask
, &t
);
402 c
->delegate_controllers
= 0;
404 c
->delegate_controllers
|= mask
;
406 unit_write_settingf(u
, flags
, name
, "Delegate=%s", strempty(t
));
415 int bus_cgroup_set_property(
419 sd_bus_message
*message
,
420 UnitWriteFlags flags
,
421 sd_bus_error
*error
) {
423 CGroupIOLimitType iol_type
;
431 flags
|= UNIT_PRIVATE
;
433 if (streq(name
, "CPUAccounting")) {
436 r
= sd_bus_message_read(message
, "b", &b
);
440 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
441 c
->cpu_accounting
= b
;
442 unit_invalidate_cgroup(u
, CGROUP_MASK_CPUACCT
|CGROUP_MASK_CPU
);
443 unit_write_settingf(u
, flags
, name
, "CPUAccounting=%s", yes_no(b
));
448 } else if (streq(name
, "CPUWeight")) {
451 r
= sd_bus_message_read(message
, "t", &weight
);
455 if (!CGROUP_WEIGHT_IS_OK(weight
))
456 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "CPUWeight= value out of range");
458 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
459 c
->cpu_weight
= weight
;
460 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
462 if (weight
== CGROUP_WEIGHT_INVALID
)
463 unit_write_setting(u
, flags
, name
, "CPUWeight=");
465 unit_write_settingf(u
, flags
, name
, "CPUWeight=%" PRIu64
, weight
);
470 } else if (streq(name
, "StartupCPUWeight")) {
473 r
= sd_bus_message_read(message
, "t", &weight
);
477 if (!CGROUP_WEIGHT_IS_OK(weight
))
478 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "StartupCPUWeight= value out of range");
480 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
481 c
->startup_cpu_weight
= weight
;
482 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
484 if (weight
== CGROUP_CPU_SHARES_INVALID
)
485 unit_write_setting(u
, flags
, name
, "StartupCPUWeight=");
487 unit_write_settingf(u
, flags
, name
, "StartupCPUWeight=%" PRIu64
, weight
);
492 } else if (streq(name
, "CPUShares")) {
495 r
= sd_bus_message_read(message
, "t", &shares
);
499 if (!CGROUP_CPU_SHARES_IS_OK(shares
))
500 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "CPUShares= value out of range");
502 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
503 c
->cpu_shares
= shares
;
504 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
506 if (shares
== CGROUP_CPU_SHARES_INVALID
)
507 unit_write_setting(u
, flags
, name
, "CPUShares=");
509 unit_write_settingf(u
, flags
, name
, "CPUShares=%" PRIu64
, shares
);
514 } else if (streq(name
, "StartupCPUShares")) {
517 r
= sd_bus_message_read(message
, "t", &shares
);
521 if (!CGROUP_CPU_SHARES_IS_OK(shares
))
522 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "StartupCPUShares= value out of range");
524 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
525 c
->startup_cpu_shares
= shares
;
526 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
528 if (shares
== CGROUP_CPU_SHARES_INVALID
)
529 unit_write_setting(u
, flags
, name
, "StartupCPUShares=");
531 unit_write_settingf(u
, flags
, name
, "StartupCPUShares=%" PRIu64
, shares
);
536 } else if (streq(name
, "CPUQuotaPerSecUSec")) {
539 r
= sd_bus_message_read(message
, "t", &u64
);
544 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "CPUQuotaPerSecUSec= value out of range");
546 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
547 c
->cpu_quota_per_sec_usec
= u64
;
548 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
550 if (c
->cpu_quota_per_sec_usec
== USEC_INFINITY
)
551 unit_write_setting(u
, flags
, "CPUQuota", "CPUQuota=");
553 /* config_parse_cpu_quota() requires an integer, so truncating division is used on
555 unit_write_settingf(u
, flags
, "CPUQuota",
557 (double) (c
->cpu_quota_per_sec_usec
/ 10000));
562 } else if (streq(name
, "IOAccounting")) {
565 r
= sd_bus_message_read(message
, "b", &b
);
569 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
570 c
->io_accounting
= b
;
571 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
572 unit_write_settingf(u
, flags
, name
, "IOAccounting=%s", yes_no(b
));
577 } else if (streq(name
, "IOWeight")) {
580 r
= sd_bus_message_read(message
, "t", &weight
);
584 if (!CGROUP_WEIGHT_IS_OK(weight
))
585 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "IOWeight= value out of range");
587 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
588 c
->io_weight
= weight
;
589 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
591 if (weight
== CGROUP_WEIGHT_INVALID
)
592 unit_write_setting(u
, flags
, name
, "IOWeight=");
594 unit_write_settingf(u
, flags
, name
, "IOWeight=%" PRIu64
, weight
);
599 } else if (streq(name
, "StartupIOWeight")) {
602 r
= sd_bus_message_read(message
, "t", &weight
);
606 if (CGROUP_WEIGHT_IS_OK(weight
))
607 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "StartupIOWeight= value out of range");
609 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
610 c
->startup_io_weight
= weight
;
611 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
613 if (weight
== CGROUP_WEIGHT_INVALID
)
614 unit_write_setting(u
, flags
, name
, "StartupIOWeight=");
616 unit_write_settingf(u
, flags
, name
, "StartupIOWeight=%" PRIu64
, weight
);
621 } else if ((iol_type
= cgroup_io_limit_type_from_string(name
)) >= 0) {
626 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
630 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
632 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
633 CGroupIODeviceLimit
*a
= NULL
, *b
;
635 LIST_FOREACH(device_limits
, b
, c
->io_device_limits
) {
636 if (path_equal(path
, b
->path
)) {
643 CGroupIOLimitType type
;
645 a
= new0(CGroupIODeviceLimit
, 1);
649 a
->path
= strdup(path
);
655 for (type
= 0; type
< _CGROUP_IO_LIMIT_TYPE_MAX
; type
++)
656 a
->limits
[type
] = cgroup_io_limit_defaults
[type
];
658 LIST_PREPEND(device_limits
, c
->io_device_limits
, a
);
661 a
->limits
[iol_type
] = u64
;
669 r
= sd_bus_message_exit_container(message
);
673 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
674 CGroupIODeviceLimit
*a
;
675 _cleanup_free_
char *buf
= NULL
;
676 _cleanup_fclose_
FILE *f
= NULL
;
680 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
681 a
->limits
[iol_type
] = cgroup_io_limit_defaults
[iol_type
];
684 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
686 f
= open_memstream(&buf
, &size
);
690 fprintf(f
, "%s=\n", name
);
691 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
692 if (a
->limits
[iol_type
] != cgroup_io_limit_defaults
[iol_type
])
693 fprintf(f
, "%s=%s %" PRIu64
"\n", name
, a
->path
, a
->limits
[iol_type
]);
695 r
= fflush_and_check(f
);
698 unit_write_setting(u
, flags
, name
, buf
);
703 } else if (streq(name
, "IODeviceWeight")) {
708 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
712 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
714 if (!CGROUP_WEIGHT_IS_OK(weight
) || weight
== CGROUP_WEIGHT_INVALID
)
715 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "IODeviceWeight= value out of range");
717 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
718 CGroupIODeviceWeight
*a
= NULL
, *b
;
720 LIST_FOREACH(device_weights
, b
, c
->io_device_weights
) {
721 if (path_equal(b
->path
, path
)) {
728 a
= new0(CGroupIODeviceWeight
, 1);
732 a
->path
= strdup(path
);
737 LIST_PREPEND(device_weights
,c
->io_device_weights
, a
);
746 r
= sd_bus_message_exit_container(message
);
750 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
751 _cleanup_free_
char *buf
= NULL
;
752 _cleanup_fclose_
FILE *f
= NULL
;
753 CGroupIODeviceWeight
*a
;
757 while (c
->io_device_weights
)
758 cgroup_context_free_io_device_weight(c
, c
->io_device_weights
);
761 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
763 f
= open_memstream(&buf
, &size
);
767 fputs_unlocked("IODeviceWeight=\n", f
);
768 LIST_FOREACH(device_weights
, a
, c
->io_device_weights
)
769 fprintf(f
, "IODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
771 r
= fflush_and_check(f
);
774 unit_write_setting(u
, flags
, name
, buf
);
779 } else if (streq(name
, "BlockIOAccounting")) {
782 r
= sd_bus_message_read(message
, "b", &b
);
786 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
787 c
->blockio_accounting
= b
;
788 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
789 unit_write_settingf(u
, flags
, name
, "BlockIOAccounting=%s", yes_no(b
));
794 } else if (streq(name
, "BlockIOWeight")) {
797 r
= sd_bus_message_read(message
, "t", &weight
);
801 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
))
802 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "BlockIOWeight= value out of range");
804 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
805 c
->blockio_weight
= weight
;
806 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
808 if (weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
809 unit_write_setting(u
, flags
, name
, "BlockIOWeight=");
811 unit_write_settingf(u
, flags
, name
, "BlockIOWeight=%" PRIu64
, weight
);
816 } else if (streq(name
, "StartupBlockIOWeight")) {
819 r
= sd_bus_message_read(message
, "t", &weight
);
823 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
))
824 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "StartupBlockIOWeight= value out of range");
826 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
827 c
->startup_blockio_weight
= weight
;
828 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
830 if (weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
831 unit_write_setting(u
, flags
, name
, "StartupBlockIOWeight=");
833 unit_write_settingf(u
, flags
, name
, "StartupBlockIOWeight=%" PRIu64
, weight
);
838 } else if (STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
844 if (streq(name
, "BlockIOWriteBandwidth"))
847 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
851 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
853 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
854 CGroupBlockIODeviceBandwidth
*a
= NULL
, *b
;
856 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
857 if (path_equal(path
, b
->path
)) {
864 a
= new0(CGroupBlockIODeviceBandwidth
, 1);
868 a
->rbps
= CGROUP_LIMIT_MAX
;
869 a
->wbps
= CGROUP_LIMIT_MAX
;
870 a
->path
= strdup(path
);
876 LIST_PREPEND(device_bandwidths
, c
->blockio_device_bandwidths
, a
);
890 r
= sd_bus_message_exit_container(message
);
894 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
895 CGroupBlockIODeviceBandwidth
*a
;
896 _cleanup_free_
char *buf
= NULL
;
897 _cleanup_fclose_
FILE *f
= NULL
;
901 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
) {
903 a
->rbps
= CGROUP_LIMIT_MAX
;
905 a
->wbps
= CGROUP_LIMIT_MAX
;
909 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
911 f
= open_memstream(&buf
, &size
);
916 fputs_unlocked("BlockIOReadBandwidth=\n", f
);
917 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
918 if (a
->rbps
!= CGROUP_LIMIT_MAX
)
919 fprintf(f
, "BlockIOReadBandwidth=%s %" PRIu64
"\n", a
->path
, a
->rbps
);
921 fputs_unlocked("BlockIOWriteBandwidth=\n", f
);
922 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
923 if (a
->wbps
!= CGROUP_LIMIT_MAX
)
924 fprintf(f
, "BlockIOWriteBandwidth=%s %" PRIu64
"\n", a
->path
, a
->wbps
);
927 r
= fflush_and_check(f
);
931 unit_write_setting(u
, flags
, name
, buf
);
936 } else if (streq(name
, "BlockIODeviceWeight")) {
941 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
945 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
947 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
) || weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
948 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "BlockIODeviceWeight= out of range");
950 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
951 CGroupBlockIODeviceWeight
*a
= NULL
, *b
;
953 LIST_FOREACH(device_weights
, b
, c
->blockio_device_weights
) {
954 if (path_equal(b
->path
, path
)) {
961 a
= new0(CGroupBlockIODeviceWeight
, 1);
965 a
->path
= strdup(path
);
970 LIST_PREPEND(device_weights
,c
->blockio_device_weights
, a
);
979 r
= sd_bus_message_exit_container(message
);
983 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
984 _cleanup_free_
char *buf
= NULL
;
985 _cleanup_fclose_
FILE *f
= NULL
;
986 CGroupBlockIODeviceWeight
*a
;
990 while (c
->blockio_device_weights
)
991 cgroup_context_free_blockio_device_weight(c
, c
->blockio_device_weights
);
994 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
996 f
= open_memstream(&buf
, &size
);
1000 fputs_unlocked("BlockIODeviceWeight=\n", f
);
1001 LIST_FOREACH(device_weights
, a
, c
->blockio_device_weights
)
1002 fprintf(f
, "BlockIODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
1004 r
= fflush_and_check(f
);
1008 unit_write_setting(u
, flags
, name
, buf
);
1013 } else if (streq(name
, "MemoryAccounting")) {
1016 r
= sd_bus_message_read(message
, "b", &b
);
1020 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1021 c
->memory_accounting
= b
;
1022 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
1023 unit_write_settingf(u
, flags
, name
, "MemoryAccounting=%s", yes_no(b
));
1028 } else if (STR_IN_SET(name
, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax")) {
1031 r
= sd_bus_message_read(message
, "t", &v
);
1035 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= is too small", name
);
1037 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1038 if (streq(name
, "MemoryLow"))
1040 else if (streq(name
, "MemoryHigh"))
1042 else if (streq(name
, "MemorySwapMax"))
1043 c
->memory_swap_max
= v
;
1047 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
1049 if (v
== CGROUP_LIMIT_MAX
)
1050 unit_write_settingf(u
, flags
, name
, "%s=infinity", name
);
1052 unit_write_settingf(u
, flags
, name
, "%s=%" PRIu64
, name
, v
);
1057 } else if (STR_IN_SET(name
, "MemoryLowScale", "MemoryHighScale", "MemoryMaxScale", "MemorySwapMaxScale")) {
1061 r
= sd_bus_message_read(message
, "u", &raw
);
1065 v
= physical_memory_scale(raw
, UINT32_MAX
);
1066 if (v
<= 0 || v
== UINT64_MAX
)
1067 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= is out of range", name
);
1069 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1072 /* Chop off suffix */
1073 assert_se(e
= endswith(name
, "Scale"));
1074 name
= strndupa(name
, e
- name
);
1076 if (streq(name
, "MemoryLow"))
1078 else if (streq(name
, "MemoryHigh"))
1080 else if (streq(name
, "MemorySwapMaxScale"))
1081 c
->memory_swap_max
= v
;
1082 else /* MemoryMax */
1085 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
1086 unit_write_settingf(u
, flags
, name
, "%s=%" PRIu32
"%%", name
,
1087 (uint32_t) (DIV_ROUND_UP((uint64_t) raw
* 100U, (uint64_t) UINT32_MAX
)));
1092 } else if (streq(name
, "MemoryLimit")) {
1095 r
= sd_bus_message_read(message
, "t", &limit
);
1099 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= is too small", name
);
1101 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1102 c
->memory_limit
= limit
;
1103 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
1105 if (limit
== CGROUP_LIMIT_MAX
)
1106 unit_write_setting(u
, flags
, name
, "MemoryLimit=infinity");
1108 unit_write_settingf(u
, flags
, name
, "MemoryLimit=%" PRIu64
, limit
);
1113 } else if (streq(name
, "MemoryLimitScale")) {
1117 r
= sd_bus_message_read(message
, "u", &raw
);
1121 limit
= physical_memory_scale(raw
, UINT32_MAX
);
1122 if (limit
<= 0 || limit
== UINT64_MAX
)
1123 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= is out of range", name
);
1125 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1126 c
->memory_limit
= limit
;
1127 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
1128 unit_write_settingf(u
, flags
, "MemoryLimit", "MemoryLimit=%" PRIu32
"%%",
1129 (uint32_t) (DIV_ROUND_UP((uint64_t) raw
* 100U, (uint64_t) UINT32_MAX
)));
1134 } else if (streq(name
, "DevicePolicy")) {
1136 CGroupDevicePolicy p
;
1138 r
= sd_bus_message_read(message
, "s", &policy
);
1142 p
= cgroup_device_policy_from_string(policy
);
1146 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1147 c
->device_policy
= p
;
1148 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1149 unit_write_settingf(u
, flags
, name
, "DevicePolicy=%s", policy
);
1154 } else if (streq(name
, "DeviceAllow")) {
1155 const char *path
, *rwm
;
1158 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
1162 while ((r
= sd_bus_message_read(message
, "(ss)", &path
, &rwm
)) > 0) {
1164 if ((!path_startswith(path
, "/dev/") &&
1165 !path_startswith(path
, "/run/systemd/inaccessible/") &&
1166 !startswith(path
, "block-") &&
1167 !startswith(path
, "char-")) ||
1168 strpbrk(path
, WHITESPACE
))
1169 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires device node");
1174 if (!in_charset(rwm
, "rwm"))
1175 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires combination of rwm flags");
1177 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1178 CGroupDeviceAllow
*a
= NULL
, *b
;
1180 LIST_FOREACH(device_allow
, b
, c
->device_allow
) {
1181 if (path_equal(b
->path
, path
)) {
1188 a
= new0(CGroupDeviceAllow
, 1);
1192 a
->path
= strdup(path
);
1198 LIST_PREPEND(device_allow
, c
->device_allow
, a
);
1201 a
->r
= !!strchr(rwm
, 'r');
1202 a
->w
= !!strchr(rwm
, 'w');
1203 a
->m
= !!strchr(rwm
, 'm');
1211 r
= sd_bus_message_exit_container(message
);
1215 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1216 _cleanup_free_
char *buf
= NULL
;
1217 _cleanup_fclose_
FILE *f
= NULL
;
1218 CGroupDeviceAllow
*a
;
1222 while (c
->device_allow
)
1223 cgroup_context_free_device_allow(c
, c
->device_allow
);
1226 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1228 f
= open_memstream(&buf
, &size
);
1232 fputs_unlocked("DeviceAllow=\n", f
);
1233 LIST_FOREACH(device_allow
, a
, c
->device_allow
)
1234 fprintf(f
, "DeviceAllow=%s %s%s%s\n", a
->path
, a
->r
? "r" : "", a
->w
? "w" : "", a
->m
? "m" : "");
1236 r
= fflush_and_check(f
);
1239 unit_write_setting(u
, flags
, name
, buf
);
1244 } else if (streq(name
, "TasksAccounting")) {
1247 r
= sd_bus_message_read(message
, "b", &b
);
1251 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1252 c
->tasks_accounting
= b
;
1253 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
1254 unit_write_settingf(u
, flags
, name
, "TasksAccounting=%s", yes_no(b
));
1259 } else if (streq(name
, "TasksMax")) {
1262 r
= sd_bus_message_read(message
, "t", &limit
);
1266 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= is too small", name
);
1268 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1269 c
->tasks_max
= limit
;
1270 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
1272 if (limit
== (uint64_t) -1)
1273 unit_write_setting(u
, flags
, name
, "TasksMax=infinity");
1275 unit_write_settingf(u
, flags
, name
, "TasksMax=%" PRIu64
, limit
);
1280 } else if (streq(name
, "TasksMaxScale")) {
1284 r
= sd_bus_message_read(message
, "u", &raw
);
1288 limit
= system_tasks_max_scale(raw
, UINT32_MAX
);
1289 if (limit
<= 0 || limit
>= UINT64_MAX
)
1290 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= is out of range", name
);
1292 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1293 c
->tasks_max
= limit
;
1294 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
1295 unit_write_settingf(u
, flags
, name
, "TasksMax=%" PRIu32
"%%",
1296 (uint32_t) (DIV_ROUND_UP((uint64_t) raw
* 100U, (uint64_t) UINT32_MAX
)));
1301 } else if (streq(name
, "IPAccounting")) {
1304 r
= sd_bus_message_read(message
, "b", &b
);
1308 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1309 c
->ip_accounting
= b
;
1311 unit_invalidate_cgroup_bpf(u
);
1312 unit_write_settingf(u
, flags
, name
, "IPAccounting=%s", yes_no(b
));
1317 } else if (STR_IN_SET(name
, "IPAddressAllow", "IPAddressDeny")) {
1318 IPAddressAccessItem
**list
;
1321 list
= streq(name
, "IPAddressAllow") ? &c
->ip_address_allow
: &c
->ip_address_deny
;
1323 r
= sd_bus_message_enter_container(message
, 'a', "(iayu)");
1333 r
= sd_bus_message_enter_container(message
, 'r', "iayu");
1339 r
= sd_bus_message_read(message
, "i", &family
);
1343 if (!IN_SET(family
, AF_INET
, AF_INET6
))
1344 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects IPv4 or IPv6 addresses only.", name
);
1346 r
= sd_bus_message_read_array(message
, 'y', &ap
, &an
);
1350 if (an
!= FAMILY_ADDRESS_SIZE(family
))
1351 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "IP address has wrong size for family (%s, expected %zu, got %zu)",
1352 af_to_name(family
), FAMILY_ADDRESS_SIZE(family
), an
);
1354 r
= sd_bus_message_read(message
, "u", &prefixlen
);
1358 if (prefixlen
> FAMILY_ADDRESS_SIZE(family
)*8)
1359 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
));
1361 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1362 IPAddressAccessItem
*item
;
1364 item
= new0(IPAddressAccessItem
, 1);
1368 item
->family
= family
;
1369 item
->prefixlen
= prefixlen
;
1370 memcpy(&item
->address
, ap
, an
);
1372 LIST_PREPEND(items
, *list
, item
);
1375 r
= sd_bus_message_exit_container(message
);
1382 r
= sd_bus_message_exit_container(message
);
1386 *list
= ip_address_access_reduce(*list
);
1388 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1389 _cleanup_free_
char *buf
= NULL
;
1390 _cleanup_fclose_
FILE *f
= NULL
;
1391 IPAddressAccessItem
*item
;
1395 *list
= ip_address_access_free_all(*list
);
1397 unit_invalidate_cgroup_bpf(u
);
1398 f
= open_memstream(&buf
, &size
);
1402 fputs_unlocked(name
, f
);
1403 fputs_unlocked("=\n", f
);
1405 LIST_FOREACH(items
, item
, *list
) {
1406 char buffer
[CONST_MAX(INET_ADDRSTRLEN
, INET6_ADDRSTRLEN
)];
1409 if (!inet_ntop(item
->family
, &item
->address
, buffer
, sizeof(buffer
)))
1410 return errno
> 0 ? -errno
: -EINVAL
;
1412 fprintf(f
, "%s=%s/%u\n", name
, buffer
, item
->prefixlen
);
1415 r
= fflush_and_check(f
);
1419 unit_write_setting(u
, flags
, name
, buf
);
1422 r
= bpf_firewall_supported();
1426 static bool warned
= false;
1428 log_full(warned
? LOG_DEBUG
: LOG_WARNING
,
1429 "Transient unit %s configures an IP firewall, but the local system does not support BPF/cgroup firewalling.\n"
1430 "Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first started transient unit using IP firewalling.)", u
->id
);
1440 if (u
->transient
&& u
->load_state
== UNIT_STUB
) {
1441 r
= bus_cgroup_set_transient_property(u
, c
, name
, message
, flags
, error
);