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"
33 #include "path-util.h"
35 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy
, cgroup_device_policy
, CGroupDevicePolicy
);
37 static int property_get_delegate_controllers(
40 const char *interface
,
42 sd_bus_message
*reply
,
44 sd_bus_error
*error
) {
46 CGroupContext
*c
= userdata
;
55 return sd_bus_message_append(reply
, "as", 0);
57 r
= sd_bus_message_open_container(reply
, 'a', "s");
61 for (cc
= 0; cc
< _CGROUP_CONTROLLER_MAX
; cc
++) {
62 if ((c
->delegate_controllers
& CGROUP_CONTROLLER_TO_MASK(cc
)) == 0)
65 r
= sd_bus_message_append(reply
, "s", cgroup_controller_to_string(cc
));
70 return sd_bus_message_close_container(reply
);
73 static int property_get_io_device_weight(
76 const char *interface
,
78 sd_bus_message
*reply
,
80 sd_bus_error
*error
) {
82 CGroupContext
*c
= userdata
;
83 CGroupIODeviceWeight
*w
;
90 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
94 LIST_FOREACH(device_weights
, w
, c
->io_device_weights
) {
95 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
100 return sd_bus_message_close_container(reply
);
103 static int property_get_io_device_limits(
106 const char *interface
,
107 const char *property
,
108 sd_bus_message
*reply
,
110 sd_bus_error
*error
) {
112 CGroupContext
*c
= userdata
;
113 CGroupIODeviceLimit
*l
;
120 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
124 LIST_FOREACH(device_limits
, l
, c
->io_device_limits
) {
125 CGroupIOLimitType type
;
127 type
= cgroup_io_limit_type_from_string(property
);
128 if (type
< 0 || l
->limits
[type
] == cgroup_io_limit_defaults
[type
])
131 r
= sd_bus_message_append(reply
, "(st)", l
->path
, l
->limits
[type
]);
136 return sd_bus_message_close_container(reply
);
139 static int property_get_blockio_device_weight(
142 const char *interface
,
143 const char *property
,
144 sd_bus_message
*reply
,
146 sd_bus_error
*error
) {
148 CGroupContext
*c
= userdata
;
149 CGroupBlockIODeviceWeight
*w
;
156 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
160 LIST_FOREACH(device_weights
, w
, c
->blockio_device_weights
) {
161 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
166 return sd_bus_message_close_container(reply
);
169 static int property_get_blockio_device_bandwidths(
172 const char *interface
,
173 const char *property
,
174 sd_bus_message
*reply
,
176 sd_bus_error
*error
) {
178 CGroupContext
*c
= userdata
;
179 CGroupBlockIODeviceBandwidth
*b
;
186 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
190 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
193 if (streq(property
, "BlockIOReadBandwidth"))
198 if (v
== CGROUP_LIMIT_MAX
)
201 r
= sd_bus_message_append(reply
, "(st)", b
->path
, v
);
206 return sd_bus_message_close_container(reply
);
209 static int property_get_device_allow(
212 const char *interface
,
213 const char *property
,
214 sd_bus_message
*reply
,
216 sd_bus_error
*error
) {
218 CGroupContext
*c
= userdata
;
219 CGroupDeviceAllow
*a
;
226 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
230 LIST_FOREACH(device_allow
, a
, c
->device_allow
) {
243 r
= sd_bus_message_append(reply
, "(ss)", a
->path
, rwm
);
248 return sd_bus_message_close_container(reply
);
251 static int property_get_ip_address_access(
254 const char *interface
,
255 const char *property
,
256 sd_bus_message
*reply
,
258 sd_bus_error
*error
) {
260 IPAddressAccessItem
** items
= userdata
, *i
;
263 r
= sd_bus_message_open_container(reply
, 'a', "(iayu)");
267 LIST_FOREACH(items
, i
, *items
) {
269 r
= sd_bus_message_open_container(reply
, 'r', "iayu");
273 r
= sd_bus_message_append(reply
, "i", i
->family
);
277 r
= sd_bus_message_append_array(reply
, 'y', &i
->address
, FAMILY_ADDRESS_SIZE(i
->family
));
281 r
= sd_bus_message_append(reply
, "u", (uint32_t) i
->prefixlen
);
285 r
= sd_bus_message_close_container(reply
);
290 return sd_bus_message_close_container(reply
);
293 const sd_bus_vtable bus_cgroup_vtable
[] = {
294 SD_BUS_VTABLE_START(0),
295 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool
, offsetof(CGroupContext
, delegate
), 0),
296 SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers
, 0, 0),
297 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, cpu_accounting
), 0),
298 SD_BUS_PROPERTY("CPUWeight", "t", NULL
, offsetof(CGroupContext
, cpu_weight
), 0),
299 SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL
, offsetof(CGroupContext
, startup_cpu_weight
), 0),
300 SD_BUS_PROPERTY("CPUShares", "t", NULL
, offsetof(CGroupContext
, cpu_shares
), 0),
301 SD_BUS_PROPERTY("StartupCPUShares", "t", NULL
, offsetof(CGroupContext
, startup_cpu_shares
), 0),
302 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, cpu_quota_per_sec_usec
), 0),
303 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, io_accounting
), 0),
304 SD_BUS_PROPERTY("IOWeight", "t", NULL
, offsetof(CGroupContext
, io_weight
), 0),
305 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_io_weight
), 0),
306 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight
, 0, 0),
307 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
308 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
309 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
310 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
311 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, blockio_accounting
), 0),
312 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL
, offsetof(CGroupContext
, blockio_weight
), 0),
313 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_blockio_weight
), 0),
314 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight
, 0, 0),
315 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
316 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
317 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, memory_accounting
), 0),
318 SD_BUS_PROPERTY("MemoryLow", "t", NULL
, offsetof(CGroupContext
, memory_low
), 0),
319 SD_BUS_PROPERTY("MemoryHigh", "t", NULL
, offsetof(CGroupContext
, memory_high
), 0),
320 SD_BUS_PROPERTY("MemoryMax", "t", NULL
, offsetof(CGroupContext
, memory_max
), 0),
321 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL
, offsetof(CGroupContext
, memory_swap_max
), 0),
322 SD_BUS_PROPERTY("MemoryLimit", "t", NULL
, offsetof(CGroupContext
, memory_limit
), 0),
323 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy
, offsetof(CGroupContext
, device_policy
), 0),
324 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow
, 0, 0),
325 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, tasks_accounting
), 0),
326 SD_BUS_PROPERTY("TasksMax", "t", NULL
, offsetof(CGroupContext
, tasks_max
), 0),
327 SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, ip_accounting
), 0),
328 SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_allow
), 0),
329 SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_deny
), 0),
333 static int bus_cgroup_set_transient_property(
337 sd_bus_message
*message
,
338 UnitWriteFlags flags
,
339 sd_bus_error
*error
) {
348 flags
|= UNIT_PRIVATE
;
350 if (streq(name
, "Delegate")) {
353 r
= sd_bus_message_read(message
, "b", &b
);
357 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
359 c
->delegate_controllers
= b
? _CGROUP_MASK_ALL
: 0;
361 unit_write_settingf(u
, flags
, name
, "Delegate=%s", yes_no(b
));
366 } else if (streq(name
, "DelegateControllers")) {
369 r
= sd_bus_message_enter_container(message
, 'a', "s");
377 r
= sd_bus_message_read(message
, "s", &t
);
383 cc
= cgroup_controller_from_string(t
);
385 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown cgroup contoller '%s'", t
);
387 mask
|= CGROUP_CONTROLLER_TO_MASK(cc
);
390 r
= sd_bus_message_exit_container(message
);
394 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
395 _cleanup_free_
char *t
= NULL
;
397 r
= cg_mask_to_string(mask
, &t
);
403 c
->delegate_controllers
= 0;
405 c
->delegate_controllers
|= mask
;
407 unit_write_settingf(u
, flags
, name
, "Delegate=%s", strempty(t
));
416 int bus_cgroup_set_property(
420 sd_bus_message
*message
,
421 UnitWriteFlags flags
,
422 sd_bus_error
*error
) {
424 CGroupIOLimitType iol_type
;
432 flags
|= UNIT_PRIVATE
;
434 if (streq(name
, "CPUAccounting")) {
437 r
= sd_bus_message_read(message
, "b", &b
);
441 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
442 c
->cpu_accounting
= b
;
443 unit_invalidate_cgroup(u
, CGROUP_MASK_CPUACCT
|CGROUP_MASK_CPU
);
444 unit_write_settingf(u
, flags
, name
, "CPUAccounting=%s", yes_no(b
));
449 } else if (STR_IN_SET(name
, "CPUWeight", "StartupCPUWeight")) {
452 r
= sd_bus_message_read(message
, "t", &weight
);
456 if (!CGROUP_WEIGHT_IS_OK(weight
))
457 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= value out of range", name
);
459 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
460 if (streq(name
, "CPUWeight"))
461 c
->cpu_weight
= weight
;
462 else /* "StartupCPUWeight" */
463 c
->startup_cpu_weight
= weight
;
465 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
467 if (weight
== CGROUP_WEIGHT_INVALID
)
468 unit_write_settingf(u
, flags
, name
, "%s=", name
);
470 unit_write_settingf(u
, flags
, name
, "%s=%" PRIu64
, name
, weight
);
475 } else if (STR_IN_SET(name
, "CPUShares", "StartupCPUShares")) {
478 r
= sd_bus_message_read(message
, "t", &shares
);
482 if (!CGROUP_CPU_SHARES_IS_OK(shares
))
483 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= value out of range", name
);
485 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
486 if (streq(name
, "CPUShares"))
487 c
->cpu_shares
= shares
;
488 else /* "StartupCPUShares" */
489 c
->startup_cpu_shares
= shares
;
491 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
493 if (shares
== CGROUP_CPU_SHARES_INVALID
)
494 unit_write_settingf(u
, flags
, name
, "%s=", name
);
496 unit_write_settingf(u
, flags
, name
, "%s=%" PRIu64
, name
, shares
);
501 } else if (streq(name
, "CPUQuotaPerSecUSec")) {
504 r
= sd_bus_message_read(message
, "t", &u64
);
509 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "CPUQuotaPerSecUSec= value out of range");
511 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
512 c
->cpu_quota_per_sec_usec
= u64
;
513 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
515 if (c
->cpu_quota_per_sec_usec
== USEC_INFINITY
)
516 unit_write_setting(u
, flags
, "CPUQuota", "CPUQuota=");
518 /* config_parse_cpu_quota() requires an integer, so truncating division is used on
520 unit_write_settingf(u
, flags
, "CPUQuota",
522 (double) (c
->cpu_quota_per_sec_usec
/ 10000));
527 } else if (streq(name
, "IOAccounting")) {
530 r
= sd_bus_message_read(message
, "b", &b
);
534 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
535 c
->io_accounting
= b
;
536 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
537 unit_write_settingf(u
, flags
, name
, "IOAccounting=%s", yes_no(b
));
542 } else if (STR_IN_SET(name
, "IOWeight", "StartupIOWeight")) {
545 r
= sd_bus_message_read(message
, "t", &weight
);
549 if (!CGROUP_WEIGHT_IS_OK(weight
))
550 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= value out of range", name
);
552 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
553 if (streq(name
, "IOWeight"))
554 c
->io_weight
= weight
;
555 else /* "StartupIOWeight" */
556 c
->startup_io_weight
= weight
;
558 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
560 if (weight
== CGROUP_WEIGHT_INVALID
)
561 unit_write_settingf(u
, flags
, name
, "%s=", name
);
563 unit_write_settingf(u
, flags
, name
, "%s=%" PRIu64
, name
, weight
);
568 } else if ((iol_type
= cgroup_io_limit_type_from_string(name
)) >= 0) {
573 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
577 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
579 if (!path_startswith(path
, "/dev") &&
580 !path_startswith(path
, "/run/systemd/inaccessible/"))
581 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
);
583 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
584 CGroupIODeviceLimit
*a
= NULL
, *b
;
586 LIST_FOREACH(device_limits
, b
, c
->io_device_limits
) {
587 if (path_equal(path
, b
->path
)) {
594 CGroupIOLimitType type
;
596 a
= new0(CGroupIODeviceLimit
, 1);
600 a
->path
= strdup(path
);
606 for (type
= 0; type
< _CGROUP_IO_LIMIT_TYPE_MAX
; type
++)
607 a
->limits
[type
] = cgroup_io_limit_defaults
[type
];
609 LIST_PREPEND(device_limits
, c
->io_device_limits
, a
);
612 a
->limits
[iol_type
] = u64
;
620 r
= sd_bus_message_exit_container(message
);
624 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
625 CGroupIODeviceLimit
*a
;
626 _cleanup_free_
char *buf
= NULL
;
627 _cleanup_fclose_
FILE *f
= NULL
;
631 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
632 a
->limits
[iol_type
] = cgroup_io_limit_defaults
[iol_type
];
635 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
637 f
= open_memstream(&buf
, &size
);
641 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
643 fprintf(f
, "%s=\n", name
);
644 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
645 if (a
->limits
[iol_type
] != cgroup_io_limit_defaults
[iol_type
])
646 fprintf(f
, "%s=%s %" PRIu64
"\n", name
, a
->path
, a
->limits
[iol_type
]);
648 r
= fflush_and_check(f
);
651 unit_write_setting(u
, flags
, name
, buf
);
656 } else if (streq(name
, "IODeviceWeight")) {
661 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
665 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
667 if (!path_startswith(path
, "/dev") &&
668 !path_startswith(path
, "/run/systemd/inaccessible/"))
669 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
);
671 if (!CGROUP_WEIGHT_IS_OK(weight
) || weight
== CGROUP_WEIGHT_INVALID
)
672 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "IODeviceWeight= value out of range");
674 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
675 CGroupIODeviceWeight
*a
= NULL
, *b
;
677 LIST_FOREACH(device_weights
, b
, c
->io_device_weights
) {
678 if (path_equal(b
->path
, path
)) {
685 a
= new0(CGroupIODeviceWeight
, 1);
689 a
->path
= strdup(path
);
694 LIST_PREPEND(device_weights
,c
->io_device_weights
, a
);
703 r
= sd_bus_message_exit_container(message
);
707 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
708 _cleanup_free_
char *buf
= NULL
;
709 _cleanup_fclose_
FILE *f
= NULL
;
710 CGroupIODeviceWeight
*a
;
714 while (c
->io_device_weights
)
715 cgroup_context_free_io_device_weight(c
, c
->io_device_weights
);
718 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
720 f
= open_memstream(&buf
, &size
);
724 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
726 fputs("IODeviceWeight=\n", f
);
727 LIST_FOREACH(device_weights
, a
, c
->io_device_weights
)
728 fprintf(f
, "IODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
730 r
= fflush_and_check(f
);
733 unit_write_setting(u
, flags
, name
, buf
);
738 } else if (streq(name
, "BlockIOAccounting")) {
741 r
= sd_bus_message_read(message
, "b", &b
);
745 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
746 c
->blockio_accounting
= b
;
747 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
748 unit_write_settingf(u
, flags
, name
, "BlockIOAccounting=%s", yes_no(b
));
753 } else if (STR_IN_SET(name
, "BlockIOWeight", "StartupBlockIOWeight")) {
756 r
= sd_bus_message_read(message
, "t", &weight
);
760 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
))
761 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= value out of range", name
);
763 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
764 if (streq(name
, "BlockIOWeight"))
765 c
->blockio_weight
= weight
;
766 else /* "StartupBlockIOWeight" */
767 c
->startup_blockio_weight
= weight
;
769 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
771 if (weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
772 unit_write_settingf(u
, flags
, name
, "%s=", name
);
774 unit_write_settingf(u
, flags
, name
, "%s=%" PRIu64
, name
, weight
);
779 } else if (STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
785 if (streq(name
, "BlockIOWriteBandwidth"))
788 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
792 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
794 if (!path_startswith(path
, "/dev") &&
795 !path_startswith(path
, "/run/systemd/inaccessible/"))
796 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
);
798 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
799 CGroupBlockIODeviceBandwidth
*a
= NULL
, *b
;
801 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
802 if (path_equal(path
, b
->path
)) {
809 a
= new0(CGroupBlockIODeviceBandwidth
, 1);
813 a
->rbps
= CGROUP_LIMIT_MAX
;
814 a
->wbps
= CGROUP_LIMIT_MAX
;
815 a
->path
= strdup(path
);
821 LIST_PREPEND(device_bandwidths
, c
->blockio_device_bandwidths
, a
);
835 r
= sd_bus_message_exit_container(message
);
839 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
840 CGroupBlockIODeviceBandwidth
*a
;
841 _cleanup_free_
char *buf
= NULL
;
842 _cleanup_fclose_
FILE *f
= NULL
;
846 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
) {
848 a
->rbps
= CGROUP_LIMIT_MAX
;
850 a
->wbps
= CGROUP_LIMIT_MAX
;
854 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
856 f
= open_memstream(&buf
, &size
);
860 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
863 fputs("BlockIOReadBandwidth=\n", f
);
864 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
865 if (a
->rbps
!= CGROUP_LIMIT_MAX
)
866 fprintf(f
, "BlockIOReadBandwidth=%s %" PRIu64
"\n", a
->path
, a
->rbps
);
868 fputs("BlockIOWriteBandwidth=\n", f
);
869 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
870 if (a
->wbps
!= CGROUP_LIMIT_MAX
)
871 fprintf(f
, "BlockIOWriteBandwidth=%s %" PRIu64
"\n", a
->path
, a
->wbps
);
874 r
= fflush_and_check(f
);
878 unit_write_setting(u
, flags
, name
, buf
);
883 } else if (streq(name
, "BlockIODeviceWeight")) {
888 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
892 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
894 if (!path_startswith(path
, "/dev") &&
895 !path_startswith(path
, "/run/systemd/inaccessible/"))
896 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
);
898 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
) || weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
899 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "BlockIODeviceWeight= out of range");
901 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
902 CGroupBlockIODeviceWeight
*a
= NULL
, *b
;
904 LIST_FOREACH(device_weights
, b
, c
->blockio_device_weights
) {
905 if (path_equal(b
->path
, path
)) {
912 a
= new0(CGroupBlockIODeviceWeight
, 1);
916 a
->path
= strdup(path
);
921 LIST_PREPEND(device_weights
,c
->blockio_device_weights
, a
);
930 r
= sd_bus_message_exit_container(message
);
934 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
935 _cleanup_free_
char *buf
= NULL
;
936 _cleanup_fclose_
FILE *f
= NULL
;
937 CGroupBlockIODeviceWeight
*a
;
941 while (c
->blockio_device_weights
)
942 cgroup_context_free_blockio_device_weight(c
, c
->blockio_device_weights
);
945 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
947 f
= open_memstream(&buf
, &size
);
951 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
953 fputs("BlockIODeviceWeight=\n", f
);
954 LIST_FOREACH(device_weights
, a
, c
->blockio_device_weights
)
955 fprintf(f
, "BlockIODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
957 r
= fflush_and_check(f
);
961 unit_write_setting(u
, flags
, name
, buf
);
966 } else if (streq(name
, "MemoryAccounting")) {
969 r
= sd_bus_message_read(message
, "b", &b
);
973 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
974 c
->memory_accounting
= b
;
975 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
976 unit_write_settingf(u
, flags
, name
, "MemoryAccounting=%s", yes_no(b
));
981 } else if (STR_IN_SET(name
, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit")) {
984 r
= sd_bus_message_read(message
, "t", &v
);
988 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= is too small", name
);
990 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
991 if (streq(name
, "MemoryLow"))
993 else if (streq(name
, "MemoryHigh"))
995 else if (streq(name
, "MemorySwapMax"))
996 c
->memory_swap_max
= v
;
997 else if (streq(name
, "MemoryMax"))
999 else /* "MemoryLimit" */
1000 c
->memory_limit
= v
;
1002 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
1004 if (v
== CGROUP_LIMIT_MAX
)
1005 unit_write_settingf(u
, flags
, name
, "%s=infinity", name
);
1007 unit_write_settingf(u
, flags
, name
, "%s=%" PRIu64
, name
, v
);
1012 } else if (STR_IN_SET(name
, "MemoryLowScale", "MemoryHighScale", "MemoryMaxScale", "MemorySwapMaxScale", "MemoryLimitScale")) {
1016 r
= sd_bus_message_read(message
, "u", &raw
);
1020 v
= physical_memory_scale(raw
, UINT32_MAX
);
1021 if (v
<= 0 || v
== UINT64_MAX
)
1022 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= is out of range", name
);
1024 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1027 /* Chop off suffix */
1028 assert_se(e
= endswith(name
, "Scale"));
1029 name
= strndupa(name
, e
- name
);
1031 if (streq(name
, "MemoryLow"))
1033 else if (streq(name
, "MemoryHigh"))
1035 else if (streq(name
, "MemorySwapMax"))
1036 c
->memory_swap_max
= v
;
1037 else if (streq(name
, "MemoryMax"))
1039 else /* "MemoryLimit" */
1040 c
->memory_limit
= v
;
1042 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
1043 unit_write_settingf(u
, flags
, name
, "%s=%" PRIu32
"%%", name
,
1044 (uint32_t) (DIV_ROUND_UP((uint64_t) raw
* 100U, (uint64_t) UINT32_MAX
)));
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
, "TasksAccounting")) {
1162 r
= sd_bus_message_read(message
, "b", &b
);
1166 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1167 c
->tasks_accounting
= b
;
1168 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
1169 unit_write_settingf(u
, flags
, name
, "TasksAccounting=%s", yes_no(b
));
1174 } else if (streq(name
, "TasksMax")) {
1177 r
= sd_bus_message_read(message
, "t", &limit
);
1181 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= is too small", name
);
1183 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1184 c
->tasks_max
= limit
;
1185 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
1187 if (limit
== (uint64_t) -1)
1188 unit_write_setting(u
, flags
, name
, "TasksMax=infinity");
1190 unit_write_settingf(u
, flags
, name
, "TasksMax=%" PRIu64
, limit
);
1195 } else if (streq(name
, "TasksMaxScale")) {
1199 r
= sd_bus_message_read(message
, "u", &raw
);
1203 limit
= system_tasks_max_scale(raw
, UINT32_MAX
);
1204 if (limit
<= 0 || limit
>= UINT64_MAX
)
1205 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= is out of range", name
);
1207 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1208 c
->tasks_max
= limit
;
1209 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
1210 unit_write_settingf(u
, flags
, name
, "TasksMax=%" PRIu32
"%%",
1211 (uint32_t) (DIV_ROUND_UP((uint64_t) raw
* 100U, (uint64_t) UINT32_MAX
)));
1216 } else if (streq(name
, "IPAccounting")) {
1219 r
= sd_bus_message_read(message
, "b", &b
);
1223 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1224 c
->ip_accounting
= b
;
1226 unit_invalidate_cgroup_bpf(u
);
1227 unit_write_settingf(u
, flags
, name
, "IPAccounting=%s", yes_no(b
));
1232 } else if (STR_IN_SET(name
, "IPAddressAllow", "IPAddressDeny")) {
1233 IPAddressAccessItem
**list
;
1236 list
= streq(name
, "IPAddressAllow") ? &c
->ip_address_allow
: &c
->ip_address_deny
;
1238 r
= sd_bus_message_enter_container(message
, 'a', "(iayu)");
1248 r
= sd_bus_message_enter_container(message
, 'r', "iayu");
1254 r
= sd_bus_message_read(message
, "i", &family
);
1258 if (!IN_SET(family
, AF_INET
, AF_INET6
))
1259 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects IPv4 or IPv6 addresses only.", name
);
1261 r
= sd_bus_message_read_array(message
, 'y', &ap
, &an
);
1265 if (an
!= FAMILY_ADDRESS_SIZE(family
))
1266 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "IP address has wrong size for family (%s, expected %zu, got %zu)",
1267 af_to_name(family
), FAMILY_ADDRESS_SIZE(family
), an
);
1269 r
= sd_bus_message_read(message
, "u", &prefixlen
);
1273 if (prefixlen
> FAMILY_ADDRESS_SIZE(family
)*8)
1274 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
));
1276 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1277 IPAddressAccessItem
*item
;
1279 item
= new0(IPAddressAccessItem
, 1);
1283 item
->family
= family
;
1284 item
->prefixlen
= prefixlen
;
1285 memcpy(&item
->address
, ap
, an
);
1287 LIST_PREPEND(items
, *list
, item
);
1290 r
= sd_bus_message_exit_container(message
);
1297 r
= sd_bus_message_exit_container(message
);
1301 *list
= ip_address_access_reduce(*list
);
1303 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1304 _cleanup_free_
char *buf
= NULL
;
1305 _cleanup_fclose_
FILE *f
= NULL
;
1306 IPAddressAccessItem
*item
;
1310 *list
= ip_address_access_free_all(*list
);
1312 unit_invalidate_cgroup_bpf(u
);
1313 f
= open_memstream(&buf
, &size
);
1317 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
1322 LIST_FOREACH(items
, item
, *list
) {
1323 char buffer
[CONST_MAX(INET_ADDRSTRLEN
, INET6_ADDRSTRLEN
)];
1326 if (!inet_ntop(item
->family
, &item
->address
, buffer
, sizeof(buffer
)))
1327 return errno
> 0 ? -errno
: -EINVAL
;
1329 fprintf(f
, "%s=%s/%u\n", name
, buffer
, item
->prefixlen
);
1332 r
= fflush_and_check(f
);
1336 unit_write_setting(u
, flags
, name
, buf
);
1339 r
= bpf_firewall_supported();
1343 static bool warned
= false;
1345 log_full(warned
? LOG_DEBUG
: LOG_WARNING
,
1346 "Transient unit %s configures an IP firewall, but the local system does not support BPF/cgroup firewalling.\n"
1347 "Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first started transient unit using IP firewalling.)", u
->id
);
1357 if (u
->transient
&& u
->load_state
== UNIT_STUB
)
1358 return bus_cgroup_set_transient_property(u
, c
, name
, message
, flags
, error
);