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 UnitSetPropertiesMode mode
,
338 sd_bus_error
*error
) {
347 if (streq(name
, "Delegate")) {
350 r
= sd_bus_message_read(message
, "b", &b
);
354 if (mode
!= UNIT_CHECK
) {
356 c
->delegate_controllers
= b
? _CGROUP_MASK_ALL
: 0;
358 unit_write_drop_in_private(u
, mode
, name
, b
? "Delegate=yes" : "Delegate=no");
363 } else if (streq(name
, "DelegateControllers")) {
366 r
= sd_bus_message_enter_container(message
, 'a', "s");
374 r
= sd_bus_message_read(message
, "s", &t
);
380 cc
= cgroup_controller_from_string(t
);
382 return sd_bus_error_set_errnof(error
, EINVAL
, "Unknown cgroup contoller '%s'", t
);
384 mask
|= CGROUP_CONTROLLER_TO_MASK(cc
);
387 r
= sd_bus_message_exit_container(message
);
391 if (mode
!= UNIT_CHECK
) {
392 _cleanup_free_
char *t
= NULL
;
394 r
= cg_mask_to_string(mask
, &t
);
400 c
->delegate_controllers
= 0;
402 c
->delegate_controllers
|= mask
;
404 unit_write_drop_in_private_format(u
, mode
, name
, "Delegate=%s", strempty(t
));
413 int bus_cgroup_set_property(
417 sd_bus_message
*message
,
418 UnitSetPropertiesMode mode
,
419 sd_bus_error
*error
) {
421 CGroupIOLimitType iol_type
;
429 if (streq(name
, "CPUAccounting")) {
432 r
= sd_bus_message_read(message
, "b", &b
);
436 if (mode
!= UNIT_CHECK
) {
437 c
->cpu_accounting
= b
;
438 unit_invalidate_cgroup(u
, CGROUP_MASK_CPUACCT
|CGROUP_MASK_CPU
);
439 unit_write_drop_in_private(u
, mode
, name
, b
? "CPUAccounting=yes" : "CPUAccounting=no");
444 } else if (streq(name
, "CPUWeight")) {
447 r
= sd_bus_message_read(message
, "t", &weight
);
451 if (!CGROUP_WEIGHT_IS_OK(weight
))
452 return sd_bus_error_set_errnof(error
, EINVAL
, "CPUWeight value out of range");
454 if (mode
!= UNIT_CHECK
) {
455 c
->cpu_weight
= weight
;
456 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
458 if (weight
== CGROUP_WEIGHT_INVALID
)
459 unit_write_drop_in_private(u
, mode
, name
, "CPUWeight=");
461 unit_write_drop_in_private_format(u
, mode
, name
, "CPUWeight=%" PRIu64
, weight
);
466 } else if (streq(name
, "StartupCPUWeight")) {
469 r
= sd_bus_message_read(message
, "t", &weight
);
473 if (!CGROUP_WEIGHT_IS_OK(weight
))
474 return sd_bus_error_set_errnof(error
, EINVAL
, "StartupCPUWeight value out of range");
476 if (mode
!= UNIT_CHECK
) {
477 c
->startup_cpu_weight
= weight
;
478 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
480 if (weight
== CGROUP_CPU_SHARES_INVALID
)
481 unit_write_drop_in_private(u
, mode
, name
, "StartupCPUWeight=");
483 unit_write_drop_in_private_format(u
, mode
, name
, "StartupCPUWeight=%" PRIu64
, weight
);
488 } else if (streq(name
, "CPUShares")) {
491 r
= sd_bus_message_read(message
, "t", &shares
);
495 if (!CGROUP_CPU_SHARES_IS_OK(shares
))
496 return sd_bus_error_set_errnof(error
, EINVAL
, "CPUShares value out of range");
498 if (mode
!= UNIT_CHECK
) {
499 c
->cpu_shares
= shares
;
500 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
502 if (shares
== CGROUP_CPU_SHARES_INVALID
)
503 unit_write_drop_in_private(u
, mode
, name
, "CPUShares=");
505 unit_write_drop_in_private_format(u
, mode
, name
, "CPUShares=%" PRIu64
, shares
);
510 } else if (streq(name
, "StartupCPUShares")) {
513 r
= sd_bus_message_read(message
, "t", &shares
);
517 if (!CGROUP_CPU_SHARES_IS_OK(shares
))
518 return sd_bus_error_set_errnof(error
, EINVAL
, "StartupCPUShares value out of range");
520 if (mode
!= UNIT_CHECK
) {
521 c
->startup_cpu_shares
= shares
;
522 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
524 if (shares
== CGROUP_CPU_SHARES_INVALID
)
525 unit_write_drop_in_private(u
, mode
, name
, "StartupCPUShares=");
527 unit_write_drop_in_private_format(u
, mode
, name
, "StartupCPUShares=%" PRIu64
, shares
);
532 } else if (streq(name
, "CPUQuotaPerSecUSec")) {
535 r
= sd_bus_message_read(message
, "t", &u64
);
540 return sd_bus_error_set_errnof(error
, EINVAL
, "CPUQuotaPerSecUSec value out of range");
542 if (mode
!= UNIT_CHECK
) {
543 c
->cpu_quota_per_sec_usec
= u64
;
544 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
545 if (c
->cpu_quota_per_sec_usec
== USEC_INFINITY
)
546 unit_write_drop_in_private_format(u
, mode
, "CPUQuota",
549 /* config_parse_cpu_quota() requires an integer, so
550 * truncating division is used on purpose here. */
551 unit_write_drop_in_private_format(u
, mode
, "CPUQuota",
553 (double) (c
->cpu_quota_per_sec_usec
/ 10000));
558 } else if (streq(name
, "IOAccounting")) {
561 r
= sd_bus_message_read(message
, "b", &b
);
565 if (mode
!= UNIT_CHECK
) {
566 c
->io_accounting
= b
;
567 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
568 unit_write_drop_in_private(u
, mode
, name
, b
? "IOAccounting=yes" : "IOAccounting=no");
573 } else if (streq(name
, "IOWeight")) {
576 r
= sd_bus_message_read(message
, "t", &weight
);
580 if (!CGROUP_WEIGHT_IS_OK(weight
))
581 return sd_bus_error_set_errnof(error
, EINVAL
, "IOWeight value out of range");
583 if (mode
!= UNIT_CHECK
) {
584 c
->io_weight
= weight
;
585 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
587 if (weight
== CGROUP_WEIGHT_INVALID
)
588 unit_write_drop_in_private(u
, mode
, name
, "IOWeight=");
590 unit_write_drop_in_private_format(u
, mode
, name
, "IOWeight=%" PRIu64
, weight
);
595 } else if (streq(name
, "StartupIOWeight")) {
598 r
= sd_bus_message_read(message
, "t", &weight
);
602 if (CGROUP_WEIGHT_IS_OK(weight
))
603 return sd_bus_error_set_errnof(error
, EINVAL
, "StartupIOWeight value out of range");
605 if (mode
!= UNIT_CHECK
) {
606 c
->startup_io_weight
= weight
;
607 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
609 if (weight
== CGROUP_WEIGHT_INVALID
)
610 unit_write_drop_in_private(u
, mode
, name
, "StartupIOWeight=");
612 unit_write_drop_in_private_format(u
, mode
, name
, "StartupIOWeight=%" PRIu64
, weight
);
617 } else if ((iol_type
= cgroup_io_limit_type_from_string(name
)) >= 0) {
622 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
626 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
628 if (mode
!= UNIT_CHECK
) {
629 CGroupIODeviceLimit
*a
= NULL
, *b
;
631 LIST_FOREACH(device_limits
, b
, c
->io_device_limits
) {
632 if (path_equal(path
, b
->path
)) {
639 CGroupIOLimitType type
;
641 a
= new0(CGroupIODeviceLimit
, 1);
645 a
->path
= strdup(path
);
651 for (type
= 0; type
< _CGROUP_IO_LIMIT_TYPE_MAX
; type
++)
652 a
->limits
[type
] = cgroup_io_limit_defaults
[type
];
654 LIST_PREPEND(device_limits
, c
->io_device_limits
, a
);
657 a
->limits
[iol_type
] = u64
;
665 r
= sd_bus_message_exit_container(message
);
669 if (mode
!= UNIT_CHECK
) {
670 CGroupIODeviceLimit
*a
;
671 _cleanup_free_
char *buf
= NULL
;
672 _cleanup_fclose_
FILE *f
= NULL
;
676 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
677 a
->limits
[iol_type
] = cgroup_io_limit_defaults
[iol_type
];
680 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
682 f
= open_memstream(&buf
, &size
);
686 fprintf(f
, "%s=\n", name
);
687 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
688 if (a
->limits
[iol_type
] != cgroup_io_limit_defaults
[iol_type
])
689 fprintf(f
, "%s=%s %" PRIu64
"\n", name
, a
->path
, a
->limits
[iol_type
]);
691 r
= fflush_and_check(f
);
694 unit_write_drop_in_private(u
, mode
, name
, buf
);
699 } else if (streq(name
, "IODeviceWeight")) {
704 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
708 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
710 if (!CGROUP_WEIGHT_IS_OK(weight
) || weight
== CGROUP_WEIGHT_INVALID
)
711 return sd_bus_error_set_errnof(error
, EINVAL
, "IODeviceWeight out of range");
713 if (mode
!= UNIT_CHECK
) {
714 CGroupIODeviceWeight
*a
= NULL
, *b
;
716 LIST_FOREACH(device_weights
, b
, c
->io_device_weights
) {
717 if (path_equal(b
->path
, path
)) {
724 a
= new0(CGroupIODeviceWeight
, 1);
728 a
->path
= strdup(path
);
733 LIST_PREPEND(device_weights
,c
->io_device_weights
, a
);
742 r
= sd_bus_message_exit_container(message
);
746 if (mode
!= UNIT_CHECK
) {
747 _cleanup_free_
char *buf
= NULL
;
748 _cleanup_fclose_
FILE *f
= NULL
;
749 CGroupIODeviceWeight
*a
;
753 while (c
->io_device_weights
)
754 cgroup_context_free_io_device_weight(c
, c
->io_device_weights
);
757 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
759 f
= open_memstream(&buf
, &size
);
763 fputs_unlocked("IODeviceWeight=\n", f
);
764 LIST_FOREACH(device_weights
, a
, c
->io_device_weights
)
765 fprintf(f
, "IODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
767 r
= fflush_and_check(f
);
770 unit_write_drop_in_private(u
, mode
, name
, buf
);
775 } else if (streq(name
, "BlockIOAccounting")) {
778 r
= sd_bus_message_read(message
, "b", &b
);
782 if (mode
!= UNIT_CHECK
) {
783 c
->blockio_accounting
= b
;
784 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
785 unit_write_drop_in_private(u
, mode
, name
, b
? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
790 } else if (streq(name
, "BlockIOWeight")) {
793 r
= sd_bus_message_read(message
, "t", &weight
);
797 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
))
798 return sd_bus_error_set_errnof(error
, EINVAL
, "BlockIOWeight value out of range");
800 if (mode
!= UNIT_CHECK
) {
801 c
->blockio_weight
= weight
;
802 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
804 if (weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
805 unit_write_drop_in_private(u
, mode
, name
, "BlockIOWeight=");
807 unit_write_drop_in_private_format(u
, mode
, name
, "BlockIOWeight=%" PRIu64
, weight
);
812 } else if (streq(name
, "StartupBlockIOWeight")) {
815 r
= sd_bus_message_read(message
, "t", &weight
);
819 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
))
820 return sd_bus_error_set_errnof(error
, EINVAL
, "StartupBlockIOWeight value out of range");
822 if (mode
!= UNIT_CHECK
) {
823 c
->startup_blockio_weight
= weight
;
824 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
826 if (weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
827 unit_write_drop_in_private(u
, mode
, name
, "StartupBlockIOWeight=");
829 unit_write_drop_in_private_format(u
, mode
, name
, "StartupBlockIOWeight=%" PRIu64
, weight
);
834 } else if (STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
840 if (streq(name
, "BlockIOWriteBandwidth"))
843 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
847 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
849 if (mode
!= UNIT_CHECK
) {
850 CGroupBlockIODeviceBandwidth
*a
= NULL
, *b
;
852 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
853 if (path_equal(path
, b
->path
)) {
860 a
= new0(CGroupBlockIODeviceBandwidth
, 1);
864 a
->rbps
= CGROUP_LIMIT_MAX
;
865 a
->wbps
= CGROUP_LIMIT_MAX
;
866 a
->path
= strdup(path
);
872 LIST_PREPEND(device_bandwidths
, c
->blockio_device_bandwidths
, a
);
886 r
= sd_bus_message_exit_container(message
);
890 if (mode
!= UNIT_CHECK
) {
891 CGroupBlockIODeviceBandwidth
*a
;
892 _cleanup_free_
char *buf
= NULL
;
893 _cleanup_fclose_
FILE *f
= NULL
;
897 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
) {
899 a
->rbps
= CGROUP_LIMIT_MAX
;
901 a
->wbps
= CGROUP_LIMIT_MAX
;
905 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
907 f
= open_memstream(&buf
, &size
);
912 fputs_unlocked("BlockIOReadBandwidth=\n", f
);
913 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
914 if (a
->rbps
!= CGROUP_LIMIT_MAX
)
915 fprintf(f
, "BlockIOReadBandwidth=%s %" PRIu64
"\n", a
->path
, a
->rbps
);
917 fputs_unlocked("BlockIOWriteBandwidth=\n", f
);
918 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
919 if (a
->wbps
!= CGROUP_LIMIT_MAX
)
920 fprintf(f
, "BlockIOWriteBandwidth=%s %" PRIu64
"\n", a
->path
, a
->wbps
);
923 r
= fflush_and_check(f
);
926 unit_write_drop_in_private(u
, mode
, name
, buf
);
931 } else if (streq(name
, "BlockIODeviceWeight")) {
936 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
940 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
942 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
) || weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
943 return sd_bus_error_set_errnof(error
, EINVAL
, "BlockIODeviceWeight out of range");
945 if (mode
!= UNIT_CHECK
) {
946 CGroupBlockIODeviceWeight
*a
= NULL
, *b
;
948 LIST_FOREACH(device_weights
, b
, c
->blockio_device_weights
) {
949 if (path_equal(b
->path
, path
)) {
956 a
= new0(CGroupBlockIODeviceWeight
, 1);
960 a
->path
= strdup(path
);
965 LIST_PREPEND(device_weights
,c
->blockio_device_weights
, a
);
974 r
= sd_bus_message_exit_container(message
);
978 if (mode
!= UNIT_CHECK
) {
979 _cleanup_free_
char *buf
= NULL
;
980 _cleanup_fclose_
FILE *f
= NULL
;
981 CGroupBlockIODeviceWeight
*a
;
985 while (c
->blockio_device_weights
)
986 cgroup_context_free_blockio_device_weight(c
, c
->blockio_device_weights
);
989 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
991 f
= open_memstream(&buf
, &size
);
995 fputs_unlocked("BlockIODeviceWeight=\n", f
);
996 LIST_FOREACH(device_weights
, a
, c
->blockio_device_weights
)
997 fprintf(f
, "BlockIODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
999 r
= fflush_and_check(f
);
1002 unit_write_drop_in_private(u
, mode
, name
, buf
);
1007 } else if (streq(name
, "MemoryAccounting")) {
1010 r
= sd_bus_message_read(message
, "b", &b
);
1014 if (mode
!= UNIT_CHECK
) {
1015 c
->memory_accounting
= b
;
1016 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
1017 unit_write_drop_in_private(u
, mode
, name
, b
? "MemoryAccounting=yes" : "MemoryAccounting=no");
1022 } else if (STR_IN_SET(name
, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax")) {
1025 r
= sd_bus_message_read(message
, "t", &v
);
1029 return sd_bus_error_set_errnof(error
, EINVAL
, "%s= is too small", name
);
1031 if (mode
!= UNIT_CHECK
) {
1032 if (streq(name
, "MemoryLow"))
1034 else if (streq(name
, "MemoryHigh"))
1036 else if (streq(name
, "MemorySwapMax"))
1037 c
->memory_swap_max
= v
;
1041 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
1043 if (v
== CGROUP_LIMIT_MAX
)
1044 unit_write_drop_in_private_format(u
, mode
, name
, "%s=infinity", name
);
1046 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%" PRIu64
, name
, v
);
1051 } else if (STR_IN_SET(name
, "MemoryLowScale", "MemoryHighScale", "MemoryMaxScale")) {
1055 r
= sd_bus_message_read(message
, "u", &raw
);
1059 v
= physical_memory_scale(raw
, UINT32_MAX
);
1060 if (v
<= 0 || v
== UINT64_MAX
)
1061 return sd_bus_error_set_errnof(error
, EINVAL
, "%s= is out of range", name
);
1063 if (mode
!= UNIT_CHECK
) {
1066 /* Chop off suffix */
1067 assert_se(e
= endswith(name
, "Scale"));
1068 name
= strndupa(name
, e
- name
);
1070 if (streq(name
, "MemoryLow"))
1072 else if (streq(name
, "MemoryHigh"))
1077 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
1078 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%" PRIu32
"%%", name
,
1079 (uint32_t) (DIV_ROUND_UP((uint64_t) raw
* 100U, (uint64_t) UINT32_MAX
)));
1084 } else if (streq(name
, "MemoryLimit")) {
1087 r
= sd_bus_message_read(message
, "t", &limit
);
1091 return sd_bus_error_set_errnof(error
, EINVAL
, "%s= is too small", name
);
1093 if (mode
!= UNIT_CHECK
) {
1094 c
->memory_limit
= limit
;
1095 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
1097 if (limit
== (uint64_t) -1)
1098 unit_write_drop_in_private(u
, mode
, name
, "MemoryLimit=infinity");
1100 unit_write_drop_in_private_format(u
, mode
, name
, "MemoryLimit=%" PRIu64
, limit
);
1105 } else if (streq(name
, "MemoryLimitScale")) {
1109 r
= sd_bus_message_read(message
, "u", &raw
);
1113 limit
= physical_memory_scale(raw
, UINT32_MAX
);
1114 if (limit
<= 0 || limit
== UINT64_MAX
)
1115 return sd_bus_error_set_errnof(error
, EINVAL
, "%s= is out of range", name
);
1117 if (mode
!= UNIT_CHECK
) {
1118 c
->memory_limit
= limit
;
1119 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
1120 unit_write_drop_in_private_format(u
, mode
, "MemoryLimit", "MemoryLimit=%" PRIu32
"%%",
1121 (uint32_t) (DIV_ROUND_UP((uint64_t) raw
* 100U, (uint64_t) UINT32_MAX
)));
1126 } else if (streq(name
, "DevicePolicy")) {
1128 CGroupDevicePolicy p
;
1130 r
= sd_bus_message_read(message
, "s", &policy
);
1134 p
= cgroup_device_policy_from_string(policy
);
1138 if (mode
!= UNIT_CHECK
) {
1139 c
->device_policy
= p
;
1140 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1141 unit_write_drop_in_private_format(u
, mode
, name
, "DevicePolicy=%s", policy
);
1146 } else if (streq(name
, "DeviceAllow")) {
1147 const char *path
, *rwm
;
1150 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
1154 while ((r
= sd_bus_message_read(message
, "(ss)", &path
, &rwm
)) > 0) {
1156 if ((!path_startswith(path
, "/dev/") &&
1157 !path_startswith(path
, "/run/systemd/inaccessible/") &&
1158 !startswith(path
, "block-") &&
1159 !startswith(path
, "char-")) ||
1160 strpbrk(path
, WHITESPACE
))
1161 return sd_bus_error_set_errnof(error
, EINVAL
, "DeviceAllow= requires device node");
1166 if (!in_charset(rwm
, "rwm"))
1167 return sd_bus_error_set_errnof(error
, EINVAL
, "DeviceAllow= requires combination of rwm flags");
1169 if (mode
!= UNIT_CHECK
) {
1170 CGroupDeviceAllow
*a
= NULL
, *b
;
1172 LIST_FOREACH(device_allow
, b
, c
->device_allow
) {
1173 if (path_equal(b
->path
, path
)) {
1180 a
= new0(CGroupDeviceAllow
, 1);
1184 a
->path
= strdup(path
);
1190 LIST_PREPEND(device_allow
, c
->device_allow
, a
);
1193 a
->r
= !!strchr(rwm
, 'r');
1194 a
->w
= !!strchr(rwm
, 'w');
1195 a
->m
= !!strchr(rwm
, 'm');
1203 r
= sd_bus_message_exit_container(message
);
1207 if (mode
!= UNIT_CHECK
) {
1208 _cleanup_free_
char *buf
= NULL
;
1209 _cleanup_fclose_
FILE *f
= NULL
;
1210 CGroupDeviceAllow
*a
;
1214 while (c
->device_allow
)
1215 cgroup_context_free_device_allow(c
, c
->device_allow
);
1218 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1220 f
= open_memstream(&buf
, &size
);
1224 fputs_unlocked("DeviceAllow=\n", f
);
1225 LIST_FOREACH(device_allow
, a
, c
->device_allow
)
1226 fprintf(f
, "DeviceAllow=%s %s%s%s\n", a
->path
, a
->r
? "r" : "", a
->w
? "w" : "", a
->m
? "m" : "");
1228 r
= fflush_and_check(f
);
1231 unit_write_drop_in_private(u
, mode
, name
, buf
);
1236 } else if (streq(name
, "TasksAccounting")) {
1239 r
= sd_bus_message_read(message
, "b", &b
);
1243 if (mode
!= UNIT_CHECK
) {
1244 c
->tasks_accounting
= b
;
1245 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
1246 unit_write_drop_in_private(u
, mode
, name
, b
? "TasksAccounting=yes" : "TasksAccounting=no");
1251 } else if (streq(name
, "TasksMax")) {
1254 r
= sd_bus_message_read(message
, "t", &limit
);
1258 return sd_bus_error_set_errnof(error
, EINVAL
, "%s= is too small", name
);
1260 if (mode
!= UNIT_CHECK
) {
1261 c
->tasks_max
= limit
;
1262 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
1264 if (limit
== (uint64_t) -1)
1265 unit_write_drop_in_private(u
, mode
, name
, "TasksMax=infinity");
1267 unit_write_drop_in_private_format(u
, mode
, name
, "TasksMax=%" PRIu64
, limit
);
1272 } else if (streq(name
, "TasksMaxScale")) {
1276 r
= sd_bus_message_read(message
, "u", &raw
);
1280 limit
= system_tasks_max_scale(raw
, UINT32_MAX
);
1281 if (limit
<= 0 || limit
>= UINT64_MAX
)
1282 return sd_bus_error_set_errnof(error
, EINVAL
, "%s= is out of range", name
);
1284 if (mode
!= UNIT_CHECK
) {
1285 c
->tasks_max
= limit
;
1286 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
1287 unit_write_drop_in_private_format(u
, mode
, name
, "TasksMax=%" PRIu32
"%%",
1288 (uint32_t) (DIV_ROUND_UP((uint64_t) raw
* 100U, (uint64_t) UINT32_MAX
)));
1293 } else if (streq(name
, "IPAccounting")) {
1296 r
= sd_bus_message_read(message
, "b", &b
);
1300 if (mode
!= UNIT_CHECK
) {
1301 c
->ip_accounting
= b
;
1303 unit_invalidate_cgroup_bpf(u
);
1304 unit_write_drop_in_private(u
, mode
, name
, b
? "IPAccounting=yes" : "IPAccounting=no");
1309 } else if (STR_IN_SET(name
, "IPAddressAllow", "IPAddressDeny")) {
1310 IPAddressAccessItem
**list
;
1313 list
= streq(name
, "IPAddressAllow") ? &c
->ip_address_allow
: &c
->ip_address_deny
;
1315 r
= sd_bus_message_enter_container(message
, 'a', "(iayu)");
1325 r
= sd_bus_message_enter_container(message
, 'r', "iayu");
1331 r
= sd_bus_message_read(message
, "i", &family
);
1335 if (!IN_SET(family
, AF_INET
, AF_INET6
))
1336 return sd_bus_error_set_errnof(error
, EINVAL
, "%s= expects IPv4 or IPv6 addresses only.", name
);
1338 r
= sd_bus_message_read_array(message
, 'y', &ap
, &an
);
1342 if (an
!= FAMILY_ADDRESS_SIZE(family
))
1343 return sd_bus_error_set_errnof(error
, EINVAL
, "IP address has wrong size for family (%s, expected %zu, got %zu)",
1344 af_to_name(family
), FAMILY_ADDRESS_SIZE(family
), an
);
1346 r
= sd_bus_message_read(message
, "u", &prefixlen
);
1350 if (prefixlen
> FAMILY_ADDRESS_SIZE(family
)*8)
1351 return sd_bus_error_set_errnof(error
, EINVAL
, "Prefix length %" PRIu32
" too large for address family %s.", prefixlen
, af_to_name(family
));
1353 if (mode
!= UNIT_CHECK
) {
1354 IPAddressAccessItem
*item
;
1356 item
= new0(IPAddressAccessItem
, 1);
1360 item
->family
= family
;
1361 item
->prefixlen
= prefixlen
;
1362 memcpy(&item
->address
, ap
, an
);
1364 LIST_PREPEND(items
, *list
, item
);
1367 r
= sd_bus_message_exit_container(message
);
1374 r
= sd_bus_message_exit_container(message
);
1378 *list
= ip_address_access_reduce(*list
);
1380 if (mode
!= UNIT_CHECK
) {
1381 _cleanup_free_
char *buf
= NULL
;
1382 _cleanup_fclose_
FILE *f
= NULL
;
1383 IPAddressAccessItem
*item
;
1387 *list
= ip_address_access_free_all(*list
);
1389 unit_invalidate_cgroup_bpf(u
);
1390 f
= open_memstream(&buf
, &size
);
1394 fputs_unlocked(name
, f
);
1395 fputs_unlocked("=\n", f
);
1397 LIST_FOREACH(items
, item
, *list
) {
1398 char buffer
[CONST_MAX(INET_ADDRSTRLEN
, INET6_ADDRSTRLEN
)];
1401 if (!inet_ntop(item
->family
, &item
->address
, buffer
, sizeof(buffer
)))
1402 return errno
> 0 ? -errno
: -EINVAL
;
1404 fprintf(f
, "%s=%s/%u\n", name
, buffer
, item
->prefixlen
);
1407 r
= fflush_and_check(f
);
1410 unit_write_drop_in_private(u
, mode
, name
, buf
);
1413 r
= bpf_firewall_supported();
1417 static bool warned
= false;
1419 log_full(warned
? LOG_DEBUG
: LOG_WARNING
,
1420 "Transient unit %s configures an IP firewall, but the local system does not support BPF/cgroup firewalling.\n"
1421 "Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first started transient unit using IP firewalling.)", u
->id
);
1431 if (u
->transient
&& u
->load_state
== UNIT_STUB
) {
1432 r
= bus_cgroup_set_transient_property(u
, c
, name
, message
, mode
, error
);