]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-cgroup.c
strv: make iterator in STRV_FOREACH() declaread in the loop
[thirdparty/systemd.git] / src / core / dbus-cgroup.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
4ad49000 2
3dc5ca97
LP
3#include <arpa/inet.h>
4
5#include "af-list.h"
b5efdb8a 6#include "alloc-util.h"
078ba556 7#include "bpf-firewall.h"
9e009a14 8#include "bpf-foreign.h"
40af3d02 9#include "bus-get-properties.h"
718db961
LP
10#include "cgroup-util.h"
11#include "cgroup.h"
e30bbc90 12#include "core-varlink.h"
4ad49000 13#include "dbus-cgroup.h"
681ae88e 14#include "dbus-util.h"
66855de7 15#include "errno-util.h"
3ffd4af2 16#include "fd-util.h"
0d39fa9c 17#include "fileio.h"
84ebe6f0 18#include "in-addr-prefix-util.h"
60477eb9 19#include "ip-protocol-list.h"
eefc66aa 20#include "limits-util.h"
dcf4781c 21#include "parse-util.h"
3ffd4af2 22#include "path-util.h"
9cba32bc 23#include "percent-util.h"
a59cb62c 24#include "socket-util.h"
4ad49000 25
3a0f06c4
ZJS
26BUS_DEFINE_PROPERTY_GET(bus_property_get_tasks_max, "t", TasksMax, tasks_max_resolve);
27
718db961 28static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
4d824a4e 29static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_mode, managed_oom_mode, ManagedOOMMode);
4e806bfa 30static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_preference, managed_oom_preference, ManagedOOMPreference);
718db961 31
c72703e2 32static int property_get_cgroup_mask(
02638280
LP
33 sd_bus *bus,
34 const char *path,
35 const char *interface,
36 const char *property,
37 sd_bus_message *reply,
38 void *userdata,
39 sd_bus_error *error) {
40
c72703e2 41 CGroupMask *mask = userdata;
02638280
LP
42 int r;
43
44 assert(bus);
45 assert(reply);
02638280
LP
46
47 r = sd_bus_message_open_container(reply, 'a', "s");
48 if (r < 0)
49 return r;
50
fe96c0f8 51 for (CGroupController ctrl = 0; ctrl < _CGROUP_CONTROLLER_MAX; ctrl++) {
c72703e2 52 if ((*mask & CGROUP_CONTROLLER_TO_MASK(ctrl)) == 0)
02638280
LP
53 continue;
54
c72703e2 55 r = sd_bus_message_append(reply, "s", cgroup_controller_to_string(ctrl));
02638280
LP
56 if (r < 0)
57 return r;
58 }
59
60 return sd_bus_message_close_container(reply);
61}
62
c72703e2
CD
63static int property_get_delegate_controllers(
64 sd_bus *bus,
65 const char *path,
66 const char *interface,
67 const char *property,
68 sd_bus_message *reply,
69 void *userdata,
70 sd_bus_error *error) {
71
72 CGroupContext *c = userdata;
73
74 assert(bus);
75 assert(reply);
76 assert(c);
77
78 if (!c->delegate)
79 return sd_bus_message_append(reply, "as", 0);
80
81 return property_get_cgroup_mask(bus, path, interface, property, reply, &c->delegate_controllers, error);
82}
83
047f5d63
PH
84static int property_get_cpuset(
85 sd_bus *bus,
86 const char *path,
87 const char *interface,
88 const char *property,
89 sd_bus_message *reply,
90 void *userdata,
91 sd_bus_error *error) {
92
93 CPUSet *cpus = userdata;
94 _cleanup_free_ uint8_t *array = NULL;
95 size_t allocated;
96
97 assert(bus);
98 assert(reply);
99 assert(cpus);
100
101 (void) cpu_set_to_dbus(cpus, &array, &allocated);
102 return sd_bus_message_append_array(reply, 'y', array, allocated);
103}
104
13c31542
TH
105static int property_get_io_device_weight(
106 sd_bus *bus,
107 const char *path,
108 const char *interface,
109 const char *property,
110 sd_bus_message *reply,
111 void *userdata,
112 sd_bus_error *error) {
113
114 CGroupContext *c = userdata;
13c31542
TH
115 int r;
116
117 assert(bus);
118 assert(reply);
119 assert(c);
120
121 r = sd_bus_message_open_container(reply, 'a', "(st)");
122 if (r < 0)
123 return r;
124
125 LIST_FOREACH(device_weights, w, c->io_device_weights) {
126 r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
127 if (r < 0)
128 return r;
129 }
130
131 return sd_bus_message_close_container(reply);
132}
133
134static int property_get_io_device_limits(
135 sd_bus *bus,
136 const char *path,
137 const char *interface,
138 const char *property,
139 sd_bus_message *reply,
140 void *userdata,
141 sd_bus_error *error) {
142
143 CGroupContext *c = userdata;
13c31542
TH
144 int r;
145
146 assert(bus);
147 assert(reply);
148 assert(c);
149
150 r = sd_bus_message_open_container(reply, 'a', "(st)");
151 if (r < 0)
152 return r;
153
154 LIST_FOREACH(device_limits, l, c->io_device_limits) {
9be57249 155 CGroupIOLimitType type;
13c31542 156
9be57249
TH
157 type = cgroup_io_limit_type_from_string(property);
158 if (type < 0 || l->limits[type] == cgroup_io_limit_defaults[type])
13c31542
TH
159 continue;
160
9be57249 161 r = sd_bus_message_append(reply, "(st)", l->path, l->limits[type]);
13c31542
TH
162 if (r < 0)
163 return r;
164 }
165
166 return sd_bus_message_close_container(reply);
167}
168
6ae4283c
TH
169static int property_get_io_device_latency(
170 sd_bus *bus,
171 const char *path,
172 const char *interface,
173 const char *property,
174 sd_bus_message *reply,
175 void *userdata,
176 sd_bus_error *error) {
177
178 CGroupContext *c = userdata;
6ae4283c
TH
179 int r;
180
181 assert(bus);
182 assert(reply);
183 assert(c);
184
185 r = sd_bus_message_open_container(reply, 'a', "(st)");
186 if (r < 0)
187 return r;
188
189 LIST_FOREACH(device_latencies, l, c->io_device_latencies) {
190 r = sd_bus_message_append(reply, "(st)", l->path, l->target_usec);
191 if (r < 0)
192 return r;
193 }
194
195 return sd_bus_message_close_container(reply);
196}
197
718db961
LP
198static int property_get_blockio_device_weight(
199 sd_bus *bus,
200 const char *path,
201 const char *interface,
202 const char *property,
203 sd_bus_message *reply,
ebcf1f97
LP
204 void *userdata,
205 sd_bus_error *error) {
4ad49000 206
718db961 207 CGroupContext *c = userdata;
718db961 208 int r;
4ad49000 209
718db961
LP
210 assert(bus);
211 assert(reply);
4ad49000
LP
212 assert(c);
213
718db961
LP
214 r = sd_bus_message_open_container(reply, 'a', "(st)");
215 if (r < 0)
216 return r;
4ad49000
LP
217
218 LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
718db961
LP
219 r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
220 if (r < 0)
221 return r;
4ad49000
LP
222 }
223
718db961 224 return sd_bus_message_close_container(reply);
4ad49000
LP
225}
226
718db961
LP
227static int property_get_blockio_device_bandwidths(
228 sd_bus *bus,
229 const char *path,
230 const char *interface,
231 const char *property,
232 sd_bus_message *reply,
ebcf1f97
LP
233 void *userdata,
234 sd_bus_error *error) {
718db961
LP
235
236 CGroupContext *c = userdata;
718db961 237 int r;
4ad49000 238
718db961
LP
239 assert(bus);
240 assert(reply);
4ad49000
LP
241 assert(c);
242
718db961
LP
243 r = sd_bus_message_open_container(reply, 'a', "(st)");
244 if (r < 0)
245 return r;
4ad49000
LP
246
247 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
979d0311 248 uint64_t v;
4ad49000 249
979d0311
TH
250 if (streq(property, "BlockIOReadBandwidth"))
251 v = b->rbps;
252 else
253 v = b->wbps;
254
255 if (v == CGROUP_LIMIT_MAX)
4ad49000
LP
256 continue;
257
979d0311 258 r = sd_bus_message_append(reply, "(st)", b->path, v);
718db961
LP
259 if (r < 0)
260 return r;
4ad49000
LP
261 }
262
718db961 263 return sd_bus_message_close_container(reply);
4ad49000
LP
264}
265
718db961
LP
266static int property_get_device_allow(
267 sd_bus *bus,
268 const char *path,
269 const char *interface,
270 const char *property,
271 sd_bus_message *reply,
ebcf1f97
LP
272 void *userdata,
273 sd_bus_error *error) {
718db961
LP
274
275 CGroupContext *c = userdata;
718db961 276 int r;
4ad49000 277
718db961
LP
278 assert(bus);
279 assert(reply);
4ad49000
LP
280 assert(c);
281
718db961
LP
282 r = sd_bus_message_open_container(reply, 'a', "(ss)");
283 if (r < 0)
284 return r;
4ad49000
LP
285
286 LIST_FOREACH(device_allow, a, c->device_allow) {
4ad49000 287 unsigned k = 0;
718db961 288 char rwm[4];
4ad49000
LP
289
290 if (a->r)
718db961 291 rwm[k++] = 'r';
4ad49000 292 if (a->w)
718db961 293 rwm[k++] = 'w';
4ad49000 294 if (a->m)
718db961 295 rwm[k++] = 'm';
4ad49000 296
718db961 297 rwm[k] = 0;
4ad49000 298
718db961
LP
299 r = sd_bus_message_append(reply, "(ss)", a->path, rwm);
300 if (r < 0)
301 return r;
4ad49000
LP
302 }
303
718db961 304 return sd_bus_message_close_container(reply);
4ad49000
LP
305}
306
3dc5ca97
LP
307static int property_get_ip_address_access(
308 sd_bus *bus,
309 const char *path,
310 const char *interface,
311 const char *property,
312 sd_bus_message *reply,
313 void *userdata,
314 sd_bus_error *error) {
315
84ebe6f0
YW
316 Set **prefixes = userdata;
317 struct in_addr_prefix *i;
3dc5ca97
LP
318 int r;
319
84ebe6f0
YW
320 assert(prefixes);
321
3dc5ca97
LP
322 r = sd_bus_message_open_container(reply, 'a', "(iayu)");
323 if (r < 0)
324 return r;
325
84ebe6f0 326 SET_FOREACH(i, *prefixes) {
3dc5ca97
LP
327
328 r = sd_bus_message_open_container(reply, 'r', "iayu");
329 if (r < 0)
330 return r;
331
332 r = sd_bus_message_append(reply, "i", i->family);
333 if (r < 0)
334 return r;
335
336 r = sd_bus_message_append_array(reply, 'y', &i->address, FAMILY_ADDRESS_SIZE(i->family));
337 if (r < 0)
338 return r;
339
340 r = sd_bus_message_append(reply, "u", (uint32_t) i->prefixlen);
341 if (r < 0)
342 return r;
343
344 r = sd_bus_message_close_container(reply);
345 if (r < 0)
346 return r;
347 }
348
349 return sd_bus_message_close_container(reply);
350}
351
9e009a14
JK
352static int property_get_bpf_foreign_program(
353 sd_bus *bus,
354 const char *path,
355 const char *interface,
356 const char *property,
357 sd_bus_message *reply,
358 void *userdata,
359 sd_bus_error *error) {
360 CGroupContext *c = userdata;
9e009a14
JK
361 int r;
362
363 r = sd_bus_message_open_container(reply, 'a', "(ss)");
364 if (r < 0)
365 return r;
366
367 LIST_FOREACH(programs, p, c->bpf_foreign_programs) {
368 const char *attach_type = bpf_cgroup_attach_type_to_string(p->attach_type);
369
370 r = sd_bus_message_append(reply, "(ss)", attach_type, p->bpffs_path);
371 if (r < 0)
372 return r;
373 }
374
375 return sd_bus_message_close_container(reply);
376}
377
dcf4781c
JK
378static int property_get_socket_bind(
379 sd_bus *bus,
380 const char *path,
381 const char *interface,
382 const char *property,
383 sd_bus_message *reply,
384 void *userdata,
385 sd_bus_error *error) {
03677889
YW
386
387 CGroupSocketBindItem **items = userdata;
dcf4781c
JK
388 int r;
389
390 assert(items);
391
4883a04f 392 r = sd_bus_message_open_container(reply, 'a', "(iiqq)");
dcf4781c
JK
393 if (r < 0)
394 return r;
395
396 LIST_FOREACH(socket_bind_items, i, *items) {
4883a04f 397 r = sd_bus_message_append(reply, "(iiqq)", i->address_family, i->ip_protocol, i->nr_ports, i->port_min);
dcf4781c
JK
398 if (r < 0)
399 return r;
400 }
401
402 return sd_bus_message_close_container(reply);
403}
404
a59cb62c
MV
405static int property_get_restrict_network_interfaces(
406 sd_bus *bus,
407 const char *path,
408 const char *interface,
409 const char *property,
410 sd_bus_message *reply,
411 void *userdata,
412 sd_bus_error *error) {
413 int r;
414 CGroupContext *c = userdata;
415 char *iface;
416
417 assert(bus);
418 assert(reply);
419 assert(c);
420
421 r = sd_bus_message_open_container(reply, 'r', "bas");
422 if (r < 0)
423 return r;
424
425 r = sd_bus_message_append(reply, "b", c->restrict_network_interfaces_is_allow_list);
426 if (r < 0)
427 return r;
428
429 r = sd_bus_message_open_container(reply, 'a', "s");
430 if (r < 0)
431 return r;
432
433 SET_FOREACH(iface, c->restrict_network_interfaces) {
434 r = sd_bus_message_append(reply, "s", iface);
435 if (r < 0)
436 return r;
437 }
438
439 r = sd_bus_message_close_container(reply);
440 if (r < 0)
441 return r;
442
443 return sd_bus_message_close_container(reply);
444}
445
718db961
LP
446const sd_bus_vtable bus_cgroup_vtable[] = {
447 SD_BUS_VTABLE_START(0),
a931ad47 448 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0),
02638280 449 SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers, 0, 0),
610f780c 450 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
66ebf6c0
TH
451 SD_BUS_PROPERTY("CPUWeight", "t", NULL, offsetof(CGroupContext, cpu_weight), 0),
452 SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL, offsetof(CGroupContext, startup_cpu_weight), 0),
d53d9474
LP
453 SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0),
454 SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0),
ee26bcc0 455 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
10f28641 456 SD_BUS_PROPERTY("CPUQuotaPeriodUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_period_usec), 0),
047f5d63 457 SD_BUS_PROPERTY("AllowedCPUs", "ay", property_get_cpuset, offsetof(CGroupContext, cpuset_cpus), 0),
31d3a520 458 SD_BUS_PROPERTY("StartupAllowedCPUs", "ay", property_get_cpuset, offsetof(CGroupContext, startup_cpuset_cpus), 0),
047f5d63 459 SD_BUS_PROPERTY("AllowedMemoryNodes", "ay", property_get_cpuset, offsetof(CGroupContext, cpuset_mems), 0),
31d3a520 460 SD_BUS_PROPERTY("StartupAllowedMemoryNodes", "ay", property_get_cpuset, offsetof(CGroupContext, startup_cpuset_mems), 0),
13c31542
TH
461 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, io_accounting), 0),
462 SD_BUS_PROPERTY("IOWeight", "t", NULL, offsetof(CGroupContext, io_weight), 0),
463 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL, offsetof(CGroupContext, startup_io_weight), 0),
464 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight, 0, 0),
465 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0),
466 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0),
ac06a0cf
TH
467 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits, 0, 0),
468 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits, 0, 0),
6ae4283c 469 SD_BUS_PROPERTY("IODeviceLatencyTargetUSec", "a(st)", property_get_io_device_latency, 0, 0),
610f780c 470 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
d53d9474
LP
471 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL, offsetof(CGroupContext, blockio_weight), 0),
472 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL, offsetof(CGroupContext, startup_blockio_weight), 0),
610f780c
LP
473 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0),
474 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
475 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
476 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0),
c52db42b 477 SD_BUS_PROPERTY("DefaultMemoryLow", "t", NULL, offsetof(CGroupContext, default_memory_low), 0),
7e7223b3 478 SD_BUS_PROPERTY("DefaultMemoryMin", "t", NULL, offsetof(CGroupContext, default_memory_min), 0),
48422635 479 SD_BUS_PROPERTY("MemoryMin", "t", NULL, offsetof(CGroupContext, memory_min), 0),
da4d897e
TH
480 SD_BUS_PROPERTY("MemoryLow", "t", NULL, offsetof(CGroupContext, memory_low), 0),
481 SD_BUS_PROPERTY("MemoryHigh", "t", NULL, offsetof(CGroupContext, memory_high), 0),
482 SD_BUS_PROPERTY("MemoryMax", "t", NULL, offsetof(CGroupContext, memory_max), 0),
96e131ea 483 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL, offsetof(CGroupContext, memory_swap_max), 0),
610f780c
LP
484 SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0),
485 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0),
486 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0),
03a7b521 487 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, tasks_accounting), 0),
3a0f06c4 488 SD_BUS_PROPERTY("TasksMax", "t", bus_property_get_tasks_max, offsetof(CGroupContext, tasks_max), 0),
3dc5ca97
LP
489 SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, ip_accounting), 0),
490 SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_allow), 0),
491 SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_deny), 0),
fab34748
KL
492 SD_BUS_PROPERTY("IPIngressFilterPath", "as", NULL, offsetof(CGroupContext, ip_filters_ingress), 0),
493 SD_BUS_PROPERTY("IPEgressFilterPath", "as", NULL, offsetof(CGroupContext, ip_filters_egress), 0),
c72703e2 494 SD_BUS_PROPERTY("DisableControllers", "as", property_get_cgroup_mask, offsetof(CGroupContext, disable_controllers), 0),
4d824a4e
AZ
495 SD_BUS_PROPERTY("ManagedOOMSwap", "s", property_get_managed_oom_mode, offsetof(CGroupContext, moom_swap), 0),
496 SD_BUS_PROPERTY("ManagedOOMMemoryPressure", "s", property_get_managed_oom_mode, offsetof(CGroupContext, moom_mem_pressure), 0),
d9d3f05d 497 SD_BUS_PROPERTY("ManagedOOMMemoryPressureLimit", "u", NULL, offsetof(CGroupContext, moom_mem_pressure_limit), 0),
4e806bfa 498 SD_BUS_PROPERTY("ManagedOOMPreference", "s", property_get_managed_oom_preference, offsetof(CGroupContext, moom_preference), 0),
9e009a14 499 SD_BUS_PROPERTY("BPFProgram", "a(ss)", property_get_bpf_foreign_program, 0, 0),
4883a04f
JK
500 SD_BUS_PROPERTY("SocketBindAllow", "a(iiqq)", property_get_socket_bind, offsetof(CGroupContext, socket_bind_allow), 0),
501 SD_BUS_PROPERTY("SocketBindDeny", "a(iiqq)", property_get_socket_bind, offsetof(CGroupContext, socket_bind_deny), 0),
a59cb62c 502 SD_BUS_PROPERTY("RestrictNetworkInterfaces", "(bas)", property_get_restrict_network_interfaces, 0, 0),
718db961 503 SD_BUS_VTABLE_END
4ad49000 504};
8e2af478 505
a931ad47
LP
506static int bus_cgroup_set_transient_property(
507 Unit *u,
508 CGroupContext *c,
509 const char *name,
510 sd_bus_message *message,
2e59b241 511 UnitWriteFlags flags,
a931ad47
LP
512 sd_bus_error *error) {
513
514 int r;
515
516 assert(u);
517 assert(c);
518 assert(name);
519 assert(message);
520
2e59b241
LP
521 flags |= UNIT_PRIVATE;
522
a931ad47
LP
523 if (streq(name, "Delegate")) {
524 int b;
525
1d9cc876 526 if (!UNIT_VTABLE(u)->can_delegate)
1b09b81c 527 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
1d9cc876 528
a931ad47
LP
529 r = sd_bus_message_read(message, "b", &b);
530 if (r < 0)
531 return r;
532
2e59b241 533 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
a931ad47 534 c->delegate = b;
02638280
LP
535 c->delegate_controllers = b ? _CGROUP_MASK_ALL : 0;
536
2e59b241 537 unit_write_settingf(u, flags, name, "Delegate=%s", yes_no(b));
a931ad47
LP
538 }
539
02638280
LP
540 return 1;
541
25cc30c4 542 } else if (STR_IN_SET(name, "DelegateControllers", "DisableControllers")) {
02638280
LP
543 CGroupMask mask = 0;
544
25cc30c4 545 if (streq(name, "DelegateControllers") && !UNIT_VTABLE(u)->can_delegate)
1b09b81c 546 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
1d9cc876 547
02638280
LP
548 r = sd_bus_message_enter_container(message, 'a', "s");
549 if (r < 0)
550 return r;
551
552 for (;;) {
553 CGroupController cc;
554 const char *t;
555
556 r = sd_bus_message_read(message, "s", &t);
557 if (r < 0)
558 return r;
559 if (r == 0)
560 break;
561
562 cc = cgroup_controller_from_string(t);
563 if (cc < 0)
ef42f561 564 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown cgroup controller '%s'", t);
02638280
LP
565
566 mask |= CGROUP_CONTROLLER_TO_MASK(cc);
567 }
568
569 r = sd_bus_message_exit_container(message);
570 if (r < 0)
571 return r;
572
2e59b241 573 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
02638280
LP
574 _cleanup_free_ char *t = NULL;
575
576 r = cg_mask_to_string(mask, &t);
577 if (r < 0)
578 return r;
579
25cc30c4
AZ
580 if (streq(name, "DelegateControllers")) {
581
582 c->delegate = true;
583 if (mask == 0)
584 c->delegate_controllers = 0;
585 else
586 c->delegate_controllers |= mask;
587
588 unit_write_settingf(u, flags, name, "Delegate=%s", strempty(t));
02638280 589
25cc30c4
AZ
590 } else if (streq(name, "DisableControllers")) {
591
592 if (mask == 0)
593 c->disable_controllers = 0;
594 else
595 c->disable_controllers |= mask;
596
597 unit_write_settingf(u, flags, name, "%s=%s", name, strempty(t));
598 }
02638280
LP
599 }
600
fab34748
KL
601 return 1;
602 } else if (STR_IN_SET(name, "IPIngressFilterPath", "IPEgressFilterPath")) {
603 char ***filters;
604 size_t n = 0;
605
606 filters = streq(name, "IPIngressFilterPath") ? &c->ip_filters_ingress : &c->ip_filters_egress;
607 r = sd_bus_message_enter_container(message, 'a', "s");
608 if (r < 0)
609 return r;
610
611 for (;;) {
612 const char *path;
613
614 r = sd_bus_message_read(message, "s", &path);
615 if (r < 0)
616 return r;
617 if (r == 0)
618 break;
619
620 if (!path_is_normalized(path) || !path_is_absolute(path))
621 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects a normalized absolute path.", name);
622
623 if (!UNIT_WRITE_FLAGS_NOOP(flags) && !strv_contains(*filters, path)) {
624 r = strv_extend(filters, path);
625 if (r < 0)
626 return log_oom();
627 }
628 n++;
629 }
630 r = sd_bus_message_exit_container(message);
631 if (r < 0)
632 return r;
633
634 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
635 _cleanup_free_ char *buf = NULL;
636 _cleanup_fclose_ FILE *f = NULL;
fab34748
KL
637 size_t size = 0;
638
639 if (n == 0)
640 *filters = strv_free(*filters);
641
642 unit_invalidate_cgroup_bpf(u);
643 f = open_memstream_unlocked(&buf, &size);
644 if (!f)
645 return -ENOMEM;
646
647 fputs(name, f);
648 fputs("=\n", f);
649
650 STRV_FOREACH(entry, *filters)
651 fprintf(f, "%s=%s\n", name, *entry);
652
653 r = fflush_and_check(f);
654 if (r < 0)
655 return r;
656
657 unit_write_setting(u, flags, name, buf);
658
659 if (*filters) {
660 r = bpf_firewall_supported();
661 if (r < 0)
662 return r;
663 if (r != BPF_FIREWALL_SUPPORTED_WITH_MULTI) {
664 static bool warned = false;
665
666 log_full(warned ? LOG_DEBUG : LOG_WARNING,
fc103b3e 667 "Transient unit %s configures an IP firewall with BPF, but the local system does not support BPF/cgroup firewalling with multiple filters.\n"
fab34748
KL
668 "Starting this unit will fail! (This warning is only shown for the first started transient unit using IP firewalling.)", u->id);
669 warned = true;
670 }
671 }
672 }
673
9e009a14
JK
674 return 1;
675 } else if (streq(name, "BPFProgram")) {
676 const char *a, *p;
677 size_t n = 0;
678
679 r = sd_bus_message_enter_container(message, 'a', "(ss)");
680 if (r < 0)
681 return r;
682
683 while ((r = sd_bus_message_read(message, "(ss)", &a, &p)) > 0) {
684 int attach_type = bpf_cgroup_attach_type_from_string(a);
685 if (attach_type < 0)
686 return sd_bus_error_setf(
687 error,
688 SD_BUS_ERROR_INVALID_ARGS,
689 "%s expects a valid BPF attach type, got '%s'.",
690 name, a);
691
692 if (!path_is_normalized(p) || !path_is_absolute(p))
693 return sd_bus_error_setf(
694 error,
695 SD_BUS_ERROR_INVALID_ARGS,
696 "%s= expects a normalized absolute path.",
697 name);
698
699 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
700 r = cgroup_add_bpf_foreign_program(c, attach_type, p);
701 if (r < 0)
702 return r;
703 }
704 n++;
705 }
706 if (r < 0)
707 return r;
708
709 r = sd_bus_message_exit_container(message);
710 if (r < 0)
711 return r;
712
713 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
714 _cleanup_free_ char *buf = NULL;
715 _cleanup_fclose_ FILE *f = NULL;
9e009a14
JK
716 size_t size = 0;
717
718 if (n == 0)
719 while (c->bpf_foreign_programs)
720 cgroup_context_remove_bpf_foreign_program(c, c->bpf_foreign_programs);
721
722 f = open_memstream_unlocked(&buf, &size);
723 if (!f)
724 return -ENOMEM;
725
726 fputs(name, f);
727 fputs("=\n", f);
728
729 LIST_FOREACH(programs, fp, c->bpf_foreign_programs)
730 fprintf(f, "%s=%s:%s\n", name,
731 bpf_cgroup_attach_type_to_string(fp->attach_type),
732 fp->bpffs_path);
733
734 r = fflush_and_check(f);
735 if (r < 0)
736 return r;
737
738 unit_write_setting(u, flags, name, buf);
739
740 if (!LIST_IS_EMPTY(c->bpf_foreign_programs)) {
741 r = bpf_foreign_supported();
742 if (r < 0)
743 return r;
744 if (r == 0)
745 log_full(LOG_DEBUG,
746 "Transient unit %s configures a BPF program pinned to BPF "
747 "filesystem, but the local system does not support that.\n"
748 "Starting this unit will fail!", u->id);
749 }
750 }
751
a931ad47
LP
752 return 1;
753 }
754
755 return 0;
756}
757
681ae88e
YW
758static int bus_cgroup_set_boolean(
759 Unit *u,
760 const char *name,
761 bool *p,
762 CGroupMask mask,
763 sd_bus_message *message,
764 UnitWriteFlags flags,
765 sd_bus_error *error) {
766
767 int b, r;
768
769 assert(p);
770
771 r = sd_bus_message_read(message, "b", &b);
772 if (r < 0)
773 return r;
774
775 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
776 *p = b;
777 unit_invalidate_cgroup(u, mask);
778 unit_write_settingf(u, flags, name, "%s=%s", name, yes_no(b));
779 }
780
781 return 1;
782}
783
906bdbf5
YW
784#define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val) \
785 static int bus_cgroup_set_##function( \
786 Unit *u, \
787 const char *name, \
788 uint64_t *p, \
789 sd_bus_message *message, \
790 UnitWriteFlags flags, \
791 sd_bus_error *error) { \
792 \
793 uint64_t v; \
794 int r; \
795 \
796 assert(p); \
797 \
798 r = sd_bus_message_read(message, "t", &v); \
799 if (r < 0) \
800 return r; \
801 \
802 if (!check(v)) \
803 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
804 "Value specified in %s is out of range", name); \
805 \
806 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
807 *p = v; \
1454ab40 808 unit_invalidate_cgroup(u, mask); \
906bdbf5
YW
809 \
810 if (v == (val)) \
811 unit_write_settingf(u, flags, name, \
812 "%s=", name); \
813 else \
814 unit_write_settingf(u, flags, name, \
815 "%s=%" PRIu64, name, v); \
816 } \
817 \
818 return 1; \
819 }
820
821#define BUS_DEFINE_SET_CGROUP_LIMIT(function, mask, scale, minimum) \
822 static int bus_cgroup_set_##function( \
823 Unit *u, \
824 const char *name, \
825 uint64_t *p, \
826 sd_bus_message *message, \
827 UnitWriteFlags flags, \
828 sd_bus_error *error) { \
829 \
830 uint64_t v; \
831 int r; \
832 \
833 assert(p); \
834 \
835 r = sd_bus_message_read(message, "t", &v); \
836 if (r < 0) \
837 return r; \
838 \
839 if (v < minimum) \
840 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
841 "Value specified in %s is out of range", name); \
842 \
843 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
844 *p = v; \
1454ab40 845 unit_invalidate_cgroup(u, mask); \
906bdbf5
YW
846 \
847 if (v == CGROUP_LIMIT_MAX) \
848 unit_write_settingf(u, flags, name, \
849 "%s=infinity", name); \
850 else \
851 unit_write_settingf(u, flags, name, \
852 "%s=%" PRIu64, name, v); \
853 } \
854 \
855 return 1; \
856 } \
857 static int bus_cgroup_set_##function##_scale( \
858 Unit *u, \
859 const char *name, \
860 uint64_t *p, \
861 sd_bus_message *message, \
862 UnitWriteFlags flags, \
863 sd_bus_error *error) { \
864 \
865 uint64_t v; \
866 uint32_t raw; \
867 int r; \
868 \
869 assert(p); \
870 \
871 r = sd_bus_message_read(message, "u", &raw); \
872 if (r < 0) \
873 return r; \
874 \
875 v = scale(raw, UINT32_MAX); \
876 if (v < minimum || v >= UINT64_MAX) \
877 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
878 "Value specified in %s is out of range", name); \
879 \
880 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
906bdbf5 881 *p = v; \
1454ab40 882 unit_invalidate_cgroup(u, mask); \
906bdbf5 883 \
e617e2cc
ZJS
884 /* Prepare to chop off suffix */ \
885 assert_se(endswith(name, "Scale")); \
906bdbf5 886 \
9cba32bc 887 int scaled = UINT32_SCALE_TO_PERMYRIAD(raw); \
1ead0b2a 888 unit_write_settingf(u, flags, name, "%.*s=" PERMYRIAD_AS_PERCENT_FORMAT_STR, \
e617e2cc 889 (int)(strlen(name) - strlen("Scale")), name, \
1ead0b2a 890 PERMYRIAD_AS_PERCENT_FORMAT_VAL(scaled)); \
906bdbf5
YW
891 } \
892 \
893 return 1; \
894 }
895
6028d766 896DISABLE_WARNING_TYPE_LIMITS;
906bdbf5
YW
897BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight, CGROUP_MASK_CPU, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID);
898BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares, CGROUP_MASK_CPU, CGROUP_CPU_SHARES_IS_OK, CGROUP_CPU_SHARES_INVALID);
899BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight, CGROUP_MASK_IO, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID);
900BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight, CGROUP_MASK_BLKIO, CGROUP_BLKIO_WEIGHT_IS_OK, CGROUP_BLKIO_WEIGHT_INVALID);
901BUS_DEFINE_SET_CGROUP_LIMIT(memory, CGROUP_MASK_MEMORY, physical_memory_scale, 1);
311a0e2e 902BUS_DEFINE_SET_CGROUP_LIMIT(memory_protection, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
906bdbf5 903BUS_DEFINE_SET_CGROUP_LIMIT(swap, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
6028d766 904REENABLE_WARNING;
681ae88e 905
3a0f06c4
ZJS
906static int bus_cgroup_set_tasks_max(
907 Unit *u,
908 const char *name,
909 TasksMax *p,
910 sd_bus_message *message,
911 UnitWriteFlags flags,
912 sd_bus_error *error) {
913
914 uint64_t v;
915 int r;
916
917 assert(p);
918
919 r = sd_bus_message_read(message, "t", &v);
920 if (r < 0)
921 return r;
922
923 if (v < 1)
924 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
925 "Value specified in %s is out of range", name);
926
927 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
928 *p = (TasksMax) { .value = v, .scale = 0 }; /* When .scale==0, .value is the absolute value */
929 unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
930
931 if (v == CGROUP_LIMIT_MAX)
932 unit_write_settingf(u, flags, name,
933 "%s=infinity", name);
934 else
935 unit_write_settingf(u, flags, name,
936 "%s=%" PRIu64, name, v);
937 }
938
939 return 1;
940}
941
942static int bus_cgroup_set_tasks_max_scale(
943 Unit *u,
944 const char *name,
945 TasksMax *p,
946 sd_bus_message *message,
947 UnitWriteFlags flags,
948 sd_bus_error *error) {
949
950 uint32_t v;
951 int r;
952
953 assert(p);
954
955 r = sd_bus_message_read(message, "u", &v);
956 if (r < 0)
957 return r;
958
959 if (v < 1 || v >= UINT32_MAX)
960 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
961 "Value specified in %s is out of range", name);
962
963 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
964 *p = (TasksMax) { v, UINT32_MAX }; /* .scale is not 0, so this is interpreted as v/UINT32_MAX. */
965 unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
966
0877d4e0
ZJS
967 uint32_t scaled = DIV_ROUND_UP((uint64_t) v * 100U, (uint64_t) UINT32_MAX);
968 unit_write_settingf(u, flags, name, "%s=%" PRIu32 ".%" PRIu32 "%%", "TasksMax",
969 scaled / 10, scaled % 10);
3a0f06c4
ZJS
970 }
971
972 return 1;
973}
974
8e2af478
LP
975int bus_cgroup_set_property(
976 Unit *u,
977 CGroupContext *c,
978 const char *name,
718db961 979 sd_bus_message *message,
2e59b241 980 UnitWriteFlags flags,
718db961
LP
981 sd_bus_error *error) {
982
9be57249 983 CGroupIOLimitType iol_type;
718db961 984 int r;
8e2af478 985
8e2af478
LP
986 assert(u);
987 assert(c);
718db961
LP
988 assert(name);
989 assert(message);
8e2af478 990
2e59b241
LP
991 flags |= UNIT_PRIVATE;
992
681ae88e 993 if (streq(name, "CPUAccounting"))
f98c2585 994 return bus_cgroup_set_boolean(u, name, &c->cpu_accounting, get_cpu_accounting_mask(), message, flags, error);
8e2af478 995
681ae88e
YW
996 if (streq(name, "CPUWeight"))
997 return bus_cgroup_set_cpu_weight(u, name, &c->cpu_weight, message, flags, error);
8e2af478 998
681ae88e
YW
999 if (streq(name, "StartupCPUWeight"))
1000 return bus_cgroup_set_cpu_weight(u, name, &c->startup_cpu_weight, message, flags, error);
b42defe3 1001
681ae88e
YW
1002 if (streq(name, "CPUShares"))
1003 return bus_cgroup_set_cpu_shares(u, name, &c->cpu_shares, message, flags, error);
b42defe3 1004
681ae88e
YW
1005 if (streq(name, "StartupCPUShares"))
1006 return bus_cgroup_set_cpu_shares(u, name, &c->startup_cpu_shares, message, flags, error);
66ebf6c0 1007
681ae88e
YW
1008 if (streq(name, "IOAccounting"))
1009 return bus_cgroup_set_boolean(u, name, &c->io_accounting, CGROUP_MASK_IO, message, flags, error);
66ebf6c0 1010
681ae88e
YW
1011 if (streq(name, "IOWeight"))
1012 return bus_cgroup_set_io_weight(u, name, &c->io_weight, message, flags, error);
66ebf6c0 1013
681ae88e
YW
1014 if (streq(name, "StartupIOWeight"))
1015 return bus_cgroup_set_io_weight(u, name, &c->startup_io_weight, message, flags, error);
66ebf6c0 1016
681ae88e
YW
1017 if (streq(name, "BlockIOAccounting"))
1018 return bus_cgroup_set_boolean(u, name, &c->blockio_accounting, CGROUP_MASK_BLKIO, message, flags, error);
66ebf6c0 1019
681ae88e
YW
1020 if (streq(name, "BlockIOWeight"))
1021 return bus_cgroup_set_blockio_weight(u, name, &c->blockio_weight, message, flags, error);
66ebf6c0 1022
681ae88e
YW
1023 if (streq(name, "StartupBlockIOWeight"))
1024 return bus_cgroup_set_blockio_weight(u, name, &c->startup_blockio_weight, message, flags, error);
66ebf6c0 1025
681ae88e
YW
1026 if (streq(name, "MemoryAccounting"))
1027 return bus_cgroup_set_boolean(u, name, &c->memory_accounting, CGROUP_MASK_MEMORY, message, flags, error);
b42defe3 1028
311a0e2e
ZJS
1029 if (streq(name, "MemoryMin")) {
1030 r = bus_cgroup_set_memory_protection(u, name, &c->memory_min, message, flags, error);
1031 if (r > 0)
1032 c->memory_min_set = true;
1033 return r;
1034 }
48422635 1035
311a0e2e
ZJS
1036 if (streq(name, "MemoryLow")) {
1037 r = bus_cgroup_set_memory_protection(u, name, &c->memory_low, message, flags, error);
1038 if (r > 0)
1039 c->memory_low_set = true;
1040 return r;
1041 }
b42defe3 1042
311a0e2e
ZJS
1043 if (streq(name, "DefaultMemoryMin")) {
1044 r = bus_cgroup_set_memory_protection(u, name, &c->default_memory_min, message, flags, error);
1045 if (r > 0)
1046 c->default_memory_min_set = true;
1047 return r;
1048 }
7ad5439e 1049
311a0e2e
ZJS
1050 if (streq(name, "DefaultMemoryLow")) {
1051 r = bus_cgroup_set_memory_protection(u, name, &c->default_memory_low, message, flags, error);
1052 if (r > 0)
1053 c->default_memory_low_set = true;
1054 return r;
1055 }
c52db42b 1056
681ae88e
YW
1057 if (streq(name, "MemoryHigh"))
1058 return bus_cgroup_set_memory(u, name, &c->memory_high, message, flags, error);
b42defe3 1059
681ae88e 1060 if (streq(name, "MemorySwapMax"))
906bdbf5 1061 return bus_cgroup_set_swap(u, name, &c->memory_swap_max, message, flags, error);
95ae05c0 1062
681ae88e
YW
1063 if (streq(name, "MemoryMax"))
1064 return bus_cgroup_set_memory(u, name, &c->memory_max, message, flags, error);
d53d9474 1065
681ae88e
YW
1066 if (streq(name, "MemoryLimit"))
1067 return bus_cgroup_set_memory(u, name, &c->memory_limit, message, flags, error);
95ae05c0 1068
311a0e2e
ZJS
1069 if (streq(name, "MemoryMinScale")) {
1070 r = bus_cgroup_set_memory_protection_scale(u, name, &c->memory_min, message, flags, error);
1071 if (r > 0)
1072 c->memory_min_set = true;
1073 return r;
1074 }
48422635 1075
311a0e2e
ZJS
1076 if (streq(name, "MemoryLowScale")) {
1077 r = bus_cgroup_set_memory_protection_scale(u, name, &c->memory_low, message, flags, error);
1078 if (r > 0)
1079 c->memory_low_set = true;
1080 return r;
1081 }
c52db42b 1082
311a0e2e
ZJS
1083 if (streq(name, "DefaultMemoryMinScale")) {
1084 r = bus_cgroup_set_memory_protection_scale(u, name, &c->default_memory_min, message, flags, error);
1085 if (r > 0)
1086 c->default_memory_min_set = true;
1087 return r;
1088 }
7ad5439e 1089
311a0e2e
ZJS
1090 if (streq(name, "DefaultMemoryLowScale")) {
1091 r = bus_cgroup_set_memory_protection_scale(u, name, &c->default_memory_low, message, flags, error);
1092 if (r > 0)
1093 c->default_memory_low_set = true;
1094 return r;
1095 }
681ae88e
YW
1096
1097 if (streq(name, "MemoryHighScale"))
1098 return bus_cgroup_set_memory_scale(u, name, &c->memory_high, message, flags, error);
1099
1100 if (streq(name, "MemorySwapMaxScale"))
906bdbf5 1101 return bus_cgroup_set_swap_scale(u, name, &c->memory_swap_max, message, flags, error);
681ae88e
YW
1102
1103 if (streq(name, "MemoryMaxScale"))
1104 return bus_cgroup_set_memory_scale(u, name, &c->memory_max, message, flags, error);
95ae05c0 1105
681ae88e
YW
1106 if (streq(name, "MemoryLimitScale"))
1107 return bus_cgroup_set_memory_scale(u, name, &c->memory_limit, message, flags, error);
1108
60644c3d 1109 if (streq(name, "TasksAccounting"))
681ae88e
YW
1110 return bus_cgroup_set_boolean(u, name, &c->tasks_accounting, CGROUP_MASK_PIDS, message, flags, error);
1111
1112 if (streq(name, "TasksMax"))
1113 return bus_cgroup_set_tasks_max(u, name, &c->tasks_max, message, flags, error);
1114
1115 if (streq(name, "TasksMaxScale"))
1116 return bus_cgroup_set_tasks_max_scale(u, name, &c->tasks_max, message, flags, error);
1117
1118 if (streq(name, "CPUQuotaPerSecUSec")) {
b2f8b02e
LP
1119 uint64_t u64;
1120
1121 r = sd_bus_message_read(message, "t", &u64);
1122 if (r < 0)
1123 return r;
1124
1125 if (u64 <= 0)
1b09b81c 1126 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "CPUQuotaPerSecUSec= value out of range");
b2f8b02e 1127
2e59b241 1128 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
b2f8b02e 1129 c->cpu_quota_per_sec_usec = u64;
527ede0c 1130 u->warned_clamping_cpu_quota_period = false;
e7ab4d1a 1131 unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
2e59b241 1132
d4bf82fc 1133 if (c->cpu_quota_per_sec_usec == USEC_INFINITY)
2e59b241 1134 unit_write_setting(u, flags, "CPUQuota", "CPUQuota=");
d4bf82fc 1135 else
2e59b241
LP
1136 /* config_parse_cpu_quota() requires an integer, so truncating division is used on
1137 * purpose here. */
1138 unit_write_settingf(u, flags, "CPUQuota",
1139 "CPUQuota=%0.f%%",
1140 (double) (c->cpu_quota_per_sec_usec / 10000));
b2f8b02e
LP
1141 }
1142
1143 return 1;
1144
10f28641
FB
1145 } else if (streq(name, "CPUQuotaPeriodUSec")) {
1146 uint64_t u64;
1147
1148 r = sd_bus_message_read(message, "t", &u64);
1149 if (r < 0)
1150 return r;
1151
1152 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1153 c->cpu_quota_period_usec = u64;
527ede0c 1154 u->warned_clamping_cpu_quota_period = false;
10f28641
FB
1155 unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
1156 if (c->cpu_quota_period_usec == USEC_INFINITY)
1157 unit_write_setting(u, flags, "CPUQuotaPeriodSec", "CPUQuotaPeriodSec=");
5291f26d 1158 else
10f28641
FB
1159 unit_write_settingf(u, flags, "CPUQuotaPeriodSec",
1160 "CPUQuotaPeriodSec=%s",
5291f26d 1161 FORMAT_TIMESPAN(c->cpu_quota_period_usec, 1));
10f28641
FB
1162 }
1163
1164 return 1;
1165
31d3a520 1166 } else if (STR_IN_SET(name, "AllowedCPUs", "StartupAllowedCPUs", "AllowedMemoryNodes", "StartupAllowedMemoryNodes")) {
047f5d63
PH
1167 const void *a;
1168 size_t n;
1169 _cleanup_(cpu_set_reset) CPUSet new_set = {};
1170
1171 r = sd_bus_message_read_array(message, 'y', &a, &n);
1172 if (r < 0)
1173 return r;
1174
1175 r = cpu_set_from_dbus(a, n, &new_set);
1176 if (r < 0)
1177 return r;
1178
1179 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1180 _cleanup_free_ char *setstr = NULL;
31d3a520 1181 CPUSet *set = NULL;
047f5d63
PH
1182
1183 setstr = cpu_set_to_range_string(&new_set);
a897a7b8
LP
1184 if (!setstr)
1185 return -ENOMEM;
047f5d63
PH
1186
1187 if (streq(name, "AllowedCPUs"))
1188 set = &c->cpuset_cpus;
31d3a520
PM
1189 else if (streq(name, "StartupAllowedCPUs"))
1190 set = &c->startup_cpuset_cpus;
1191 else if (streq(name, "AllowedMemoryNodes"))
047f5d63 1192 set = &c->cpuset_mems;
31d3a520
PM
1193 else if (streq(name, "StartupAllowedMemoryNodes"))
1194 set = &c->startup_cpuset_mems;
1195
1196 assert(set);
047f5d63 1197
047f5d63 1198 cpu_set_reset(set);
a897a7b8
LP
1199 *set = new_set;
1200 new_set = (CPUSet) {};
1201
047f5d63 1202 unit_invalidate_cgroup(u, CGROUP_MASK_CPUSET);
a897a7b8 1203 unit_write_settingf(u, flags, name, "%s=%s", name, setstr);
047f5d63
PH
1204 }
1205
1206 return 1;
1207
9be57249 1208 } else if ((iol_type = cgroup_io_limit_type_from_string(name)) >= 0) {
13c31542 1209 const char *path;
13c31542
TH
1210 unsigned n = 0;
1211 uint64_t u64;
1212
13c31542
TH
1213 r = sd_bus_message_enter_container(message, 'a', "(st)");
1214 if (r < 0)
1215 return r;
1216
1217 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
1218
9d5e9b4a
LP
1219 if (!path_is_normalized(path))
1220 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
d9f7305f 1221
2e59b241 1222 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
03677889 1223 CGroupIODeviceLimit *a = NULL;
13c31542 1224
03677889 1225 LIST_FOREACH(device_limits, b, c->io_device_limits)
13c31542
TH
1226 if (path_equal(path, b->path)) {
1227 a = b;
1228 break;
1229 }
13c31542
TH
1230
1231 if (!a) {
9be57249
TH
1232 CGroupIOLimitType type;
1233
13c31542
TH
1234 a = new0(CGroupIODeviceLimit, 1);
1235 if (!a)
1236 return -ENOMEM;
1237
1238 a->path = strdup(path);
1239 if (!a->path) {
1240 free(a);
1241 return -ENOMEM;
1242 }
1243
9be57249
TH
1244 for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
1245 a->limits[type] = cgroup_io_limit_defaults[type];
13c31542
TH
1246
1247 LIST_PREPEND(device_limits, c->io_device_limits, a);
1248 }
1249
9be57249 1250 a->limits[iol_type] = u64;
13c31542
TH
1251 }
1252
1253 n++;
1254 }
1255 if (r < 0)
1256 return r;
1257
1258 r = sd_bus_message_exit_container(message);
1259 if (r < 0)
1260 return r;
1261
2e59b241 1262 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
13c31542
TH
1263 _cleanup_free_ char *buf = NULL;
1264 _cleanup_fclose_ FILE *f = NULL;
1265 size_t size = 0;
1266
03677889 1267 if (n == 0)
13c31542 1268 LIST_FOREACH(device_limits, a, c->io_device_limits)
9be57249 1269 a->limits[iol_type] = cgroup_io_limit_defaults[iol_type];
13c31542
TH
1270
1271 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
1272
2fe21124 1273 f = open_memstream_unlocked(&buf, &size);
13c31542
TH
1274 if (!f)
1275 return -ENOMEM;
1276
9be57249
TH
1277 fprintf(f, "%s=\n", name);
1278 LIST_FOREACH(device_limits, a, c->io_device_limits)
03677889
YW
1279 if (a->limits[iol_type] != cgroup_io_limit_defaults[iol_type])
1280 fprintf(f, "%s=%s %" PRIu64 "\n", name, a->path, a->limits[iol_type]);
13c31542
TH
1281
1282 r = fflush_and_check(f);
1283 if (r < 0)
1284 return r;
2e59b241 1285 unit_write_setting(u, flags, name, buf);
13c31542
TH
1286 }
1287
1288 return 1;
1289
1290 } else if (streq(name, "IODeviceWeight")) {
1291 const char *path;
1292 uint64_t weight;
1293 unsigned n = 0;
1294
1295 r = sd_bus_message_enter_container(message, 'a', "(st)");
1296 if (r < 0)
1297 return r;
1298
1299 while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
1300
9d5e9b4a
LP
1301 if (!path_is_normalized(path))
1302 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
d9f7305f 1303
13c31542 1304 if (!CGROUP_WEIGHT_IS_OK(weight) || weight == CGROUP_WEIGHT_INVALID)
1b09b81c 1305 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "IODeviceWeight= value out of range");
13c31542 1306
2e59b241 1307 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
03677889 1308 CGroupIODeviceWeight *a = NULL;
13c31542 1309
03677889 1310 LIST_FOREACH(device_weights, b, c->io_device_weights)
13c31542
TH
1311 if (path_equal(b->path, path)) {
1312 a = b;
1313 break;
1314 }
13c31542
TH
1315
1316 if (!a) {
1317 a = new0(CGroupIODeviceWeight, 1);
1318 if (!a)
1319 return -ENOMEM;
1320
1321 a->path = strdup(path);
1322 if (!a->path) {
1323 free(a);
1324 return -ENOMEM;
1325 }
fffbc1dc 1326 LIST_PREPEND(device_weights, c->io_device_weights, a);
13c31542
TH
1327 }
1328
1329 a->weight = weight;
1330 }
1331
1332 n++;
1333 }
1334
1335 r = sd_bus_message_exit_container(message);
1336 if (r < 0)
1337 return r;
1338
2e59b241 1339 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
13c31542
TH
1340 _cleanup_free_ char *buf = NULL;
1341 _cleanup_fclose_ FILE *f = NULL;
13c31542
TH
1342 size_t size = 0;
1343
03677889 1344 if (n == 0)
13c31542
TH
1345 while (c->io_device_weights)
1346 cgroup_context_free_io_device_weight(c, c->io_device_weights);
13c31542
TH
1347
1348 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
1349
2fe21124 1350 f = open_memstream_unlocked(&buf, &size);
13c31542
TH
1351 if (!f)
1352 return -ENOMEM;
1353
0d536673 1354 fputs("IODeviceWeight=\n", f);
13c31542
TH
1355 LIST_FOREACH(device_weights, a, c->io_device_weights)
1356 fprintf(f, "IODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
1357
1358 r = fflush_and_check(f);
1359 if (r < 0)
1360 return r;
2e59b241 1361 unit_write_setting(u, flags, name, buf);
6ae4283c
TH
1362 }
1363
1364 return 1;
1365
1366 } else if (streq(name, "IODeviceLatencyTargetUSec")) {
1367 const char *path;
1368 uint64_t target;
1369 unsigned n = 0;
1370
1371 r = sd_bus_message_enter_container(message, 'a', "(st)");
1372 if (r < 0)
1373 return r;
1374
1375 while ((r = sd_bus_message_read(message, "(st)", &path, &target)) > 0) {
1376
1377 if (!path_is_normalized(path))
1378 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
1379
1380 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
03677889 1381 CGroupIODeviceLatency *a = NULL;
6ae4283c 1382
03677889 1383 LIST_FOREACH(device_latencies, b, c->io_device_latencies)
6ae4283c
TH
1384 if (path_equal(b->path, path)) {
1385 a = b;
1386 break;
1387 }
6ae4283c
TH
1388
1389 if (!a) {
1390 a = new0(CGroupIODeviceLatency, 1);
1391 if (!a)
1392 return -ENOMEM;
1393
1394 a->path = strdup(path);
1395 if (!a->path) {
1396 free(a);
1397 return -ENOMEM;
1398 }
1399 LIST_PREPEND(device_latencies, c->io_device_latencies, a);
1400 }
1401
1402 a->target_usec = target;
1403 }
1404
1405 n++;
1406 }
1407
1408 r = sd_bus_message_exit_container(message);
1409 if (r < 0)
1410 return r;
1411
1412 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1413 _cleanup_free_ char *buf = NULL;
1414 _cleanup_fclose_ FILE *f = NULL;
6ae4283c
TH
1415 size_t size = 0;
1416
03677889 1417 if (n == 0)
6ae4283c
TH
1418 while (c->io_device_latencies)
1419 cgroup_context_free_io_device_latency(c, c->io_device_latencies);
6ae4283c
TH
1420
1421 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
1422
2fe21124 1423 f = open_memstream_unlocked(&buf, &size);
6ae4283c
TH
1424 if (!f)
1425 return -ENOMEM;
1426
6ae4283c
TH
1427 fputs("IODeviceLatencyTargetSec=\n", f);
1428 LIST_FOREACH(device_latencies, a, c->io_device_latencies)
1429 fprintf(f, "IODeviceLatencyTargetSec=%s %s\n",
5291f26d 1430 a->path, FORMAT_TIMESPAN(a->target_usec, 1));
6ae4283c
TH
1431
1432 r = fflush_and_check(f);
1433 if (r < 0)
1434 return r;
1435 unit_write_setting(u, flags, name, buf);
13c31542
TH
1436 }
1437
1438 return 1;
1439
cd0a7a8e 1440 } else if (STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
718db961 1441 const char *path;
f004c2ca 1442 bool read = true;
718db961
LP
1443 unsigned n = 0;
1444 uint64_t u64;
f004c2ca
G
1445
1446 if (streq(name, "BlockIOWriteBandwidth"))
1447 read = false;
1448
718db961
LP
1449 r = sd_bus_message_enter_container(message, 'a', "(st)");
1450 if (r < 0)
1451 return r;
f004c2ca 1452
718db961 1453 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
f004c2ca 1454
9d5e9b4a
LP
1455 if (!path_is_normalized(path))
1456 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
d9f7305f 1457
2e59b241 1458 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
03677889 1459 CGroupBlockIODeviceBandwidth *a = NULL;
f004c2ca 1460
03677889 1461 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths)
979d0311 1462 if (path_equal(path, b->path)) {
f004c2ca 1463 a = b;
f004c2ca
G
1464 break;
1465 }
f004c2ca 1466
718db961 1467 if (!a) {
f004c2ca
G
1468 a = new0(CGroupBlockIODeviceBandwidth, 1);
1469 if (!a)
1470 return -ENOMEM;
1471
979d0311
TH
1472 a->rbps = CGROUP_LIMIT_MAX;
1473 a->wbps = CGROUP_LIMIT_MAX;
f004c2ca
G
1474 a->path = strdup(path);
1475 if (!a->path) {
1476 free(a);
1477 return -ENOMEM;
1478 }
718db961
LP
1479
1480 LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
f004c2ca
G
1481 }
1482
979d0311
TH
1483 if (read)
1484 a->rbps = u64;
1485 else
1486 a->wbps = u64;
f004c2ca
G
1487 }
1488
1489 n++;
f004c2ca 1490 }
718db961
LP
1491 if (r < 0)
1492 return r;
f004c2ca 1493
9c96019d
LP
1494 r = sd_bus_message_exit_container(message);
1495 if (r < 0)
1496 return r;
1497
2e59b241 1498 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
f004c2ca
G
1499 _cleanup_free_ char *buf = NULL;
1500 _cleanup_fclose_ FILE *f = NULL;
f004c2ca
G
1501 size_t size = 0;
1502
03677889 1503 if (n == 0)
979d0311
TH
1504 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths) {
1505 if (read)
1506 a->rbps = CGROUP_LIMIT_MAX;
1507 else
1508 a->wbps = CGROUP_LIMIT_MAX;
1509 }
f004c2ca 1510
e7ab4d1a 1511 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
3051f187 1512
2fe21124 1513 f = open_memstream_unlocked(&buf, &size);
f004c2ca
G
1514 if (!f)
1515 return -ENOMEM;
1516
7d6884b6 1517 if (read) {
0d536673 1518 fputs("BlockIOReadBandwidth=\n", f);
7d6884b6 1519 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
979d0311
TH
1520 if (a->rbps != CGROUP_LIMIT_MAX)
1521 fprintf(f, "BlockIOReadBandwidth=%s %" PRIu64 "\n", a->path, a->rbps);
f004c2ca 1522 } else {
0d536673 1523 fputs("BlockIOWriteBandwidth=\n", f);
f004c2ca 1524 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
979d0311
TH
1525 if (a->wbps != CGROUP_LIMIT_MAX)
1526 fprintf(f, "BlockIOWriteBandwidth=%s %" PRIu64 "\n", a->path, a->wbps);
f004c2ca
G
1527 }
1528
1f2f874c
NC
1529 r = fflush_and_check(f);
1530 if (r < 0)
1531 return r;
2e59b241
LP
1532
1533 unit_write_setting(u, flags, name, buf);
6f68ecb4
G
1534 }
1535
1536 return 1;
1537
1538 } else if (streq(name, "BlockIODeviceWeight")) {
718db961 1539 const char *path;
d53d9474 1540 uint64_t weight;
6f68ecb4
G
1541 unsigned n = 0;
1542
718db961
LP
1543 r = sd_bus_message_enter_container(message, 'a', "(st)");
1544 if (r < 0)
1545 return r;
6f68ecb4 1546
d53d9474 1547 while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
6f68ecb4 1548
9d5e9b4a
LP
1549 if (!path_is_normalized(path))
1550 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
d9f7305f 1551
d53d9474 1552 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight) || weight == CGROUP_BLKIO_WEIGHT_INVALID)
1b09b81c 1553 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "BlockIODeviceWeight= out of range");
6f68ecb4 1554
2e59b241 1555 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
03677889 1556 CGroupBlockIODeviceWeight *a = NULL;
6f68ecb4 1557
03677889 1558 LIST_FOREACH(device_weights, b, c->blockio_device_weights)
6f68ecb4
G
1559 if (path_equal(b->path, path)) {
1560 a = b;
6f68ecb4
G
1561 break;
1562 }
6f68ecb4 1563
718db961 1564 if (!a) {
6f68ecb4
G
1565 a = new0(CGroupBlockIODeviceWeight, 1);
1566 if (!a)
1567 return -ENOMEM;
1568
1569 a->path = strdup(path);
1570 if (!a->path) {
1571 free(a);
1572 return -ENOMEM;
1573 }
fffbc1dc 1574 LIST_PREPEND(device_weights, c->blockio_device_weights, a);
6f68ecb4
G
1575 }
1576
d53d9474 1577 a->weight = weight;
6f68ecb4
G
1578 }
1579
1580 n++;
6f68ecb4
G
1581 }
1582
9c96019d
LP
1583 r = sd_bus_message_exit_container(message);
1584 if (r < 0)
1585 return r;
1586
2e59b241 1587 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
6f68ecb4
G
1588 _cleanup_free_ char *buf = NULL;
1589 _cleanup_fclose_ FILE *f = NULL;
6f68ecb4
G
1590 size_t size = 0;
1591
03677889 1592 if (n == 0)
6f68ecb4
G
1593 while (c->blockio_device_weights)
1594 cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
6f68ecb4 1595
e7ab4d1a 1596 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
3051f187 1597
2fe21124 1598 f = open_memstream_unlocked(&buf, &size);
6f68ecb4
G
1599 if (!f)
1600 return -ENOMEM;
1601
0d536673 1602 fputs("BlockIODeviceWeight=\n", f);
6f68ecb4 1603 LIST_FOREACH(device_weights, a, c->blockio_device_weights)
d53d9474 1604 fprintf(f, "BlockIODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
6f68ecb4 1605
1f2f874c
NC
1606 r = fflush_and_check(f);
1607 if (r < 0)
1608 return r;
2e59b241
LP
1609
1610 unit_write_setting(u, flags, name, buf);
f004c2ca
G
1611 }
1612
1613 return 1;
1614
7041efe9
LP
1615 } else if (streq(name, "DevicePolicy")) {
1616 const char *policy;
1617 CGroupDevicePolicy p;
1618
718db961
LP
1619 r = sd_bus_message_read(message, "s", &policy);
1620 if (r < 0)
1621 return r;
7041efe9 1622
7041efe9
LP
1623 p = cgroup_device_policy_from_string(policy);
1624 if (p < 0)
7211c853 1625 return p;
7041efe9 1626
2e59b241 1627 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
7041efe9 1628 c->device_policy = p;
e7ab4d1a 1629 unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
2e59b241 1630 unit_write_settingf(u, flags, name, "DevicePolicy=%s", policy);
7041efe9
LP
1631 }
1632
1633 return 1;
1634
1635 } else if (streq(name, "DeviceAllow")) {
718db961 1636 const char *path, *rwm;
7041efe9
LP
1637 unsigned n = 0;
1638
718db961
LP
1639 r = sd_bus_message_enter_container(message, 'a', "(ss)");
1640 if (r < 0)
1641 return r;
7041efe9 1642
718db961 1643 while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
7041efe9 1644
57e84e75 1645 if (!valid_device_allow_pattern(path) || strpbrk(path, WHITESPACE))
1b09b81c 1646 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires device node or pattern");
7041efe9
LP
1647
1648 if (isempty(rwm))
1649 rwm = "rwm";
57e84e75 1650 else if (!in_charset(rwm, "rwm"))
1b09b81c 1651 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires combination of rwm flags");
7041efe9 1652
2e59b241 1653 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
03677889 1654 CGroupDeviceAllow *a = NULL;
ad7bfffd 1655
03677889 1656 LIST_FOREACH(device_allow, b, c->device_allow)
06eb4e3b 1657 if (path_equal(b->path, path)) {
ad7bfffd 1658 a = b;
ad7bfffd
G
1659 break;
1660 }
ad7bfffd 1661
718db961 1662 if (!a) {
ad7bfffd
G
1663 a = new0(CGroupDeviceAllow, 1);
1664 if (!a)
1665 return -ENOMEM;
1666
1667 a->path = strdup(path);
1668 if (!a->path) {
1669 free(a);
1670 return -ENOMEM;
1671 }
718db961
LP
1672
1673 LIST_PREPEND(device_allow, c->device_allow, a);
7041efe9
LP
1674 }
1675
d7a0f1f4
FS
1676 a->r = strchr(rwm, 'r');
1677 a->w = strchr(rwm, 'w');
1678 a->m = strchr(rwm, 'm');
7041efe9
LP
1679 }
1680
c2756a68 1681 n++;
7041efe9 1682 }
43a99a7a
LP
1683 if (r < 0)
1684 return r;
7041efe9 1685
9c96019d
LP
1686 r = sd_bus_message_exit_container(message);
1687 if (r < 0)
1688 return r;
1689
2e59b241 1690 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
7041efe9
LP
1691 _cleanup_free_ char *buf = NULL;
1692 _cleanup_fclose_ FILE *f = NULL;
7041efe9
LP
1693 size_t size = 0;
1694
03677889 1695 if (n == 0)
7041efe9
LP
1696 while (c->device_allow)
1697 cgroup_context_free_device_allow(c, c->device_allow);
7041efe9 1698
e7ab4d1a 1699 unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
3051f187 1700
2fe21124 1701 f = open_memstream_unlocked(&buf, &size);
7041efe9
LP
1702 if (!f)
1703 return -ENOMEM;
1704
0d536673 1705 fputs("DeviceAllow=\n", f);
7041efe9
LP
1706 LIST_FOREACH(device_allow, a, c->device_allow)
1707 fprintf(f, "DeviceAllow=%s %s%s%s\n", a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
1708
1f2f874c
NC
1709 r = fflush_and_check(f);
1710 if (r < 0)
1711 return r;
2e59b241 1712 unit_write_setting(u, flags, name, buf);
7041efe9
LP
1713 }
1714
b42defe3 1715 return 1;
a931ad47 1716
3dc5ca97
LP
1717 } else if (streq(name, "IPAccounting")) {
1718 int b;
1719
1720 r = sd_bus_message_read(message, "b", &b);
1721 if (r < 0)
1722 return r;
1723
2e59b241 1724 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3dc5ca97
LP
1725 c->ip_accounting = b;
1726
1727 unit_invalidate_cgroup_bpf(u);
2e59b241 1728 unit_write_settingf(u, flags, name, "IPAccounting=%s", yes_no(b));
3dc5ca97
LP
1729 }
1730
1731 return 1;
1732
1733 } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) {
84ebe6f0 1734 _cleanup_set_free_ Set *new_prefixes = NULL;
3dc5ca97
LP
1735 size_t n = 0;
1736
3dc5ca97
LP
1737 r = sd_bus_message_enter_container(message, 'a', "(iayu)");
1738 if (r < 0)
1739 return r;
1740
1741 for (;;) {
1742 const void *ap;
1743 int32_t family;
1744 uint32_t prefixlen;
1745 size_t an;
1746
1747 r = sd_bus_message_enter_container(message, 'r', "iayu");
1748 if (r < 0)
1749 return r;
1750 if (r == 0)
1751 break;
1752
1753 r = sd_bus_message_read(message, "i", &family);
1754 if (r < 0)
1755 return r;
1756
1757 if (!IN_SET(family, AF_INET, AF_INET6))
e74f76ca 1758 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects IPv4 or IPv6 addresses only.", name);
3dc5ca97
LP
1759
1760 r = sd_bus_message_read_array(message, 'y', &ap, &an);
1761 if (r < 0)
1762 return r;
1763
1764 if (an != FAMILY_ADDRESS_SIZE(family))
e74f76ca 1765 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "IP address has wrong size for family (%s, expected %zu, got %zu)",
3dc5ca97
LP
1766 af_to_name(family), FAMILY_ADDRESS_SIZE(family), an);
1767
1768 r = sd_bus_message_read(message, "u", &prefixlen);
1769 if (r < 0)
1770 return r;
1771
1772 if (prefixlen > FAMILY_ADDRESS_SIZE(family)*8)
e74f76ca 1773 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));
3dc5ca97 1774
2e59b241 1775 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
84ebe6f0
YW
1776 struct in_addr_prefix prefix = {
1777 .family = family,
1778 .prefixlen = prefixlen,
1779 };
3dc5ca97 1780
84ebe6f0 1781 memcpy(&prefix.address, ap, an);
3dc5ca97 1782
84ebe6f0
YW
1783 r = in_addr_prefix_add(&new_prefixes, &prefix);
1784 if (r < 0)
1785 return r;
3dc5ca97
LP
1786 }
1787
1788 r = sd_bus_message_exit_container(message);
1789 if (r < 0)
1790 return r;
1791
1792 n++;
1793 }
1794
1795 r = sd_bus_message_exit_container(message);
1796 if (r < 0)
1797 return r;
1798
2e59b241 1799 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3dc5ca97
LP
1800 _cleanup_free_ char *buf = NULL;
1801 _cleanup_fclose_ FILE *f = NULL;
3dc5ca97 1802 size_t size = 0;
84ebe6f0
YW
1803 Set **prefixes;
1804 bool *reduced;
3dc5ca97
LP
1805
1806 unit_invalidate_cgroup_bpf(u);
2fe21124 1807 f = open_memstream_unlocked(&buf, &size);
3dc5ca97
LP
1808 if (!f)
1809 return -ENOMEM;
1810
84ebe6f0
YW
1811 prefixes = streq(name, "IPAddressAllow") ? &c->ip_address_allow : &c->ip_address_deny;
1812 reduced = streq(name, "IPAddressAllow") ? &c->ip_address_allow_reduced : &c->ip_address_deny_reduced;
3dc5ca97 1813
84ebe6f0
YW
1814 if (n == 0) {
1815 *reduced = true;
1816 *prefixes = set_free(*prefixes);
1817 fputs(name, f);
1818 fputs("=\n", f);
1819 } else {
1820 struct in_addr_prefix *p;
3dc5ca97 1821
84ebe6f0 1822 *reduced = false;
3dc5ca97 1823
84ebe6f0
YW
1824 r = in_addr_prefixes_merge(prefixes, new_prefixes);
1825 if (r < 0)
1826 return r;
1827
1828 SET_FOREACH(p, new_prefixes) {
1829 _cleanup_free_ char *buffer = NULL;
1830
1831 r = in_addr_prefix_to_string(p->family, &p->address, p->prefixlen, &buffer);
1832 if (r == -ENOMEM)
1833 return r;
1834 if (r < 0)
1835 continue;
1836
1837 fprintf(f, "%s=%s\n", name, buffer);
1838 }
3dc5ca97
LP
1839 }
1840
1841 r = fflush_and_check(f);
1842 if (r < 0)
1843 return r;
2e59b241
LP
1844
1845 unit_write_setting(u, flags, name, buf);
3dc5ca97
LP
1846 }
1847
03a7b521 1848 return 1;
a931ad47
LP
1849 }
1850
4d824a4e
AZ
1851 if (STR_IN_SET(name, "ManagedOOMSwap", "ManagedOOMMemoryPressure")) {
1852 ManagedOOMMode *cgroup_mode = streq(name, "ManagedOOMSwap") ? &c->moom_swap : &c->moom_mem_pressure;
1853 ManagedOOMMode m;
1854 const char *mode;
1855
1856 if (!UNIT_VTABLE(u)->can_set_managed_oom)
1857 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set %s for this unit type", name);
1858
1859 r = sd_bus_message_read(message, "s", &mode);
1860 if (r < 0)
1861 return r;
1862
1863 m = managed_oom_mode_from_string(mode);
1864 if (m < 0)
1865 return -EINVAL;
1866
1867 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1868 *cgroup_mode = m;
1869 unit_write_settingf(u, flags, name, "%s=%s", name, mode);
1870 }
1871
e30bbc90 1872 (void) manager_varlink_send_managed_oom_update(u);
4d824a4e
AZ
1873 return 1;
1874 }
1875
d9d3f05d 1876 if (streq(name, "ManagedOOMMemoryPressureLimit")) {
0a9f9344
AZ
1877 uint32_t v;
1878
4d824a4e
AZ
1879 if (!UNIT_VTABLE(u)->can_set_managed_oom)
1880 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set %s for this unit type", name);
1881
0a9f9344 1882 r = sd_bus_message_read(message, "u", &v);
e30bbc90
AZ
1883 if (r < 0)
1884 return r;
1885
0a9f9344 1886 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
d9d3f05d
LP
1887 c->moom_mem_pressure_limit = v;
1888 unit_write_settingf(u, flags, name,
1889 "ManagedOOMMemoryPressureLimit=" PERMYRIAD_AS_PERCENT_FORMAT_STR,
1890 PERMYRIAD_AS_PERCENT_FORMAT_VAL(UINT32_SCALE_TO_PERMYRIAD(v)));
0a9f9344
AZ
1891 }
1892
e30bbc90
AZ
1893 if (c->moom_mem_pressure == MANAGED_OOM_KILL)
1894 (void) manager_varlink_send_managed_oom_update(u);
1895
1896 return 1;
4d824a4e
AZ
1897 }
1898
4e806bfa
AZ
1899 if (streq(name, "ManagedOOMPreference")) {
1900 ManagedOOMPreference p;
1901 const char *pref;
1902
1903 r = sd_bus_message_read(message, "s", &pref);
1904 if (r < 0)
1905 return r;
1906
1907 p = managed_oom_preference_from_string(pref);
1908 if (p < 0)
925484aa 1909 return p;
4e806bfa
AZ
1910
1911 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1912 c->moom_preference = p;
1913 unit_write_settingf(u, flags, name, "ManagedOOMPreference=%s", pref);
1914 }
1915
1916 return 1;
1917 }
dcf4781c
JK
1918 if (STR_IN_SET(name, "SocketBindAllow", "SocketBindDeny")) {
1919 CGroupSocketBindItem **list;
1920 uint16_t nr_ports, port_min;
1921 size_t n = 0;
4883a04f 1922 int32_t family, ip_protocol;
dcf4781c
JK
1923
1924 list = streq(name, "SocketBindAllow") ? &c->socket_bind_allow : &c->socket_bind_deny;
1925
4883a04f 1926 r = sd_bus_message_enter_container(message, 'a', "(iiqq)");
dcf4781c
JK
1927 if (r < 0)
1928 return r;
1929
4883a04f 1930 while ((r = sd_bus_message_read(message, "(iiqq)", &family, &ip_protocol, &nr_ports, &port_min)) > 0) {
dcf4781c
JK
1931
1932 if (!IN_SET(family, AF_UNSPEC, AF_INET, AF_INET6))
1933 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects INET or INET6 family, if specified.", name);
1934
60477eb9
JK
1935 if (!IN_SET(ip_protocol, 0, IPPROTO_TCP, IPPROTO_UDP))
1936 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects TCP or UDP protocol, if specified.", name);
4883a04f 1937
dcf4781c
JK
1938 if (port_min + (uint32_t) nr_ports > (1 << 16))
1939 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects maximum port value lesser than 65536.", name);
1940
1941 if (port_min == 0 && nr_ports != 0)
1942 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects port range starting with positive value.", name);
1943
1944 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1945 _cleanup_free_ CGroupSocketBindItem *item = NULL;
1946
1947 item = new(CGroupSocketBindItem, 1);
1948 if (!item)
1949 return log_oom();
1950
1951 *item = (CGroupSocketBindItem) {
1952 .address_family = family,
4883a04f 1953 .ip_protocol = ip_protocol,
dcf4781c
JK
1954 .nr_ports = nr_ports,
1955 .port_min = port_min
1956 };
1957
1958 LIST_PREPEND(socket_bind_items, *list, TAKE_PTR(item));
1959 }
1960 n++;
1961 }
1962 if (r < 0)
1963 return r;
1964
1965 r = sd_bus_message_exit_container(message);
1966 if (r < 0)
1967 return r;
1968
1969 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1970 _cleanup_free_ char *buf = NULL;
1971 _cleanup_fclose_ FILE *f = NULL;
dcf4781c
JK
1972 size_t size = 0;
1973
1974 if (n == 0)
1975 cgroup_context_remove_socket_bind(list);
1976 else {
1977 if ((u->manager->cgroup_supported & CGROUP_MASK_BPF_SOCKET_BIND) == 0)
1978 log_full(LOG_DEBUG,
1979 "Unit %s configures source compiled BPF programs "
1980 "but the local system does not support that.\n"
1981 "Starting this unit will fail!", u->id);
1982 }
1983
1984 f = open_memstream_unlocked(&buf, &size);
1985 if (!f)
1986 return -ENOMEM;
1987
1988 fprintf(f, "%s:", name);
1989
1990 LIST_FOREACH(socket_bind_items, item, *list)
1991 cgroup_context_dump_socket_bind_item(item, f);
1992
1993 fputc('\n', f);
1994
1995 r = fflush_and_check(f);
1996 if (r < 0)
1997 return r;
1998
1999 unit_write_setting(u, flags, name, buf);
2000 }
2001
2002 return 1;
2003 }
a59cb62c
MV
2004 if (streq(name, "RestrictNetworkInterfaces")) {
2005 int is_allow_list;
2006 _cleanup_strv_free_ char **l = NULL;
2007
2008 r = sd_bus_message_enter_container(message, 'r', "bas");
2009 if (r < 0)
2010 return r;
2011
2012 r = sd_bus_message_read(message, "b", &is_allow_list);
2013 if (r < 0)
2014 return r;
2015
2016 r = sd_bus_message_read_strv(message, &l);
2017 if (r < 0)
2018 return r;
2019
2020 r = sd_bus_message_exit_container(message);
2021 if (r < 0)
2022 return r;
2023
2024 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2025 _cleanup_free_ char *joined = NULL;
a59cb62c
MV
2026
2027 if (strv_isempty(l)) {
2028 c->restrict_network_interfaces_is_allow_list = false;
2029 c->restrict_network_interfaces = set_free(c->restrict_network_interfaces);
2030
2031 unit_write_settingf(u, flags, name, "%s=", name);
2032 return 1;
2033 }
2034
2035 if (set_isempty(c->restrict_network_interfaces))
2036 c->restrict_network_interfaces_is_allow_list = is_allow_list;
2037
2038 STRV_FOREACH(s, l) {
2039 if (!ifname_valid(*s)) {
2040 log_full(LOG_WARNING, "Invalid interface name, ignoring: %s", *s);
2041 continue;
2042 }
2043 if (c->restrict_network_interfaces_is_allow_list != (bool) is_allow_list)
2044 free(set_remove(c->restrict_network_interfaces, *s));
2045 else {
2046 r = set_put_strdup(&c->restrict_network_interfaces, *s);
2047 if (r < 0)
2048 return log_oom();
2049 }
2050 }
2051
2052 joined = strv_join(l, " ");
2053 if (!joined)
2054 return -ENOMEM;
2055
2056 unit_write_settingf(u, flags, name, "%s=%s%s", name, is_allow_list ? "" : "~", joined);
2057 }
2058
2059 return 1;
2060 }
4e806bfa 2061
25cc30c4 2062 if (streq(name, "DisableControllers") || (u->transient && u->load_state == UNIT_STUB))
13ec20d4 2063 return bus_cgroup_set_transient_property(u, c, name, message, flags, error);
8e2af478
LP
2064
2065 return 0;
2066}