1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <arpa/inet.h>
4 
5 #include "af-list.h"
6 #include "alloc-util.h"
7 #include "bpf-firewall.h"
8 #include "bpf-foreign.h"
9 #include "bus-get-properties.h"
10 #include "cgroup-util.h"
11 #include "cgroup.h"
12 #include "core-varlink.h"
13 #include "dbus-cgroup.h"
14 #include "dbus-util.h"
15 #include "errno-util.h"
16 #include "fd-util.h"
17 #include "fileio.h"
18 #include "in-addr-prefix-util.h"
19 #include "ip-protocol-list.h"
20 #include "limits-util.h"
21 #include "parse-util.h"
22 #include "path-util.h"
23 #include "percent-util.h"
24 #include "socket-util.h"
25 
26 BUS_DEFINE_PROPERTY_GET(bus_property_get_tasks_max, "t", TasksMax, tasks_max_resolve);
27 
28 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
29 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_mode, managed_oom_mode, ManagedOOMMode);
30 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_preference, managed_oom_preference, ManagedOOMPreference);
31 
property_get_cgroup_mask(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)32 static int property_get_cgroup_mask(
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 
41         CGroupMask *mask = userdata;
42         int r;
43 
44         assert(bus);
45         assert(reply);
46 
47         r = sd_bus_message_open_container(reply, 'a', "s");
48         if (r < 0)
49                 return r;
50 
51         for (CGroupController ctrl = 0; ctrl < _CGROUP_CONTROLLER_MAX; ctrl++) {
52                 if ((*mask & CGROUP_CONTROLLER_TO_MASK(ctrl)) == 0)
53                         continue;
54 
55                 r = sd_bus_message_append(reply, "s", cgroup_controller_to_string(ctrl));
56                 if (r < 0)
57                         return r;
58         }
59 
60         return sd_bus_message_close_container(reply);
61 }
62 
property_get_delegate_controllers(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)63 static 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 
property_get_cpuset(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)84 static 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 
property_get_io_device_weight(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)105 static 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;
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 
property_get_io_device_limits(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)134 static 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;
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) {
155                 CGroupIOLimitType type;
156 
157                 type = cgroup_io_limit_type_from_string(property);
158                 if (type < 0 || l->limits[type] == cgroup_io_limit_defaults[type])
159                         continue;
160 
161                 r = sd_bus_message_append(reply, "(st)", l->path, l->limits[type]);
162                 if (r < 0)
163                         return r;
164         }
165 
166         return sd_bus_message_close_container(reply);
167 }
168 
property_get_io_device_latency(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)169 static 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;
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 
property_get_blockio_device_weight(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)198 static 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,
204                 void *userdata,
205                 sd_bus_error *error) {
206 
207         CGroupContext *c = userdata;
208         int r;
209 
210         assert(bus);
211         assert(reply);
212         assert(c);
213 
214         r = sd_bus_message_open_container(reply, 'a', "(st)");
215         if (r < 0)
216                 return r;
217 
218         LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
219                 r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
220                 if (r < 0)
221                         return r;
222         }
223 
224         return sd_bus_message_close_container(reply);
225 }
226 
property_get_blockio_device_bandwidths(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)227 static 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,
233                 void *userdata,
234                 sd_bus_error *error) {
235 
236         CGroupContext *c = userdata;
237         int r;
238 
239         assert(bus);
240         assert(reply);
241         assert(c);
242 
243         r = sd_bus_message_open_container(reply, 'a', "(st)");
244         if (r < 0)
245                 return r;
246 
247         LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
248                 uint64_t v;
249 
250                 if (streq(property, "BlockIOReadBandwidth"))
251                         v = b->rbps;
252                 else
253                         v = b->wbps;
254 
255                 if (v == CGROUP_LIMIT_MAX)
256                         continue;
257 
258                 r = sd_bus_message_append(reply, "(st)", b->path, v);
259                 if (r < 0)
260                         return r;
261         }
262 
263         return sd_bus_message_close_container(reply);
264 }
265 
property_get_device_allow(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)266 static 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,
272                 void *userdata,
273                 sd_bus_error *error) {
274 
275         CGroupContext *c = userdata;
276         int r;
277 
278         assert(bus);
279         assert(reply);
280         assert(c);
281 
282         r = sd_bus_message_open_container(reply, 'a', "(ss)");
283         if (r < 0)
284                 return r;
285 
286         LIST_FOREACH(device_allow, a, c->device_allow) {
287                 unsigned k = 0;
288                 char rwm[4];
289 
290                 if (a->r)
291                         rwm[k++] = 'r';
292                 if (a->w)
293                         rwm[k++] = 'w';
294                 if (a->m)
295                         rwm[k++] = 'm';
296 
297                 rwm[k] = 0;
298 
299                 r = sd_bus_message_append(reply, "(ss)", a->path, rwm);
300                 if (r < 0)
301                         return r;
302         }
303 
304         return sd_bus_message_close_container(reply);
305 }
306 
property_get_ip_address_access(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)307 static 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 
316         Set **prefixes = userdata;
317         struct in_addr_prefix *i;
318         int r;
319 
320         assert(prefixes);
321 
322         r = sd_bus_message_open_container(reply, 'a', "(iayu)");
323         if (r < 0)
324                 return r;
325 
326         SET_FOREACH(i, *prefixes) {
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 
property_get_bpf_foreign_program(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)352 static 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;
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 
property_get_socket_bind(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)378 static 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) {
386 
387         CGroupSocketBindItem **items = userdata;
388         int r;
389 
390         assert(items);
391 
392         r = sd_bus_message_open_container(reply, 'a', "(iiqq)");
393         if (r < 0)
394                 return r;
395 
396         LIST_FOREACH(socket_bind_items, i, *items) {
397                 r = sd_bus_message_append(reply, "(iiqq)", i->address_family, i->ip_protocol, i->nr_ports, i->port_min);
398                 if (r < 0)
399                         return r;
400         }
401 
402         return sd_bus_message_close_container(reply);
403 }
404 
property_get_restrict_network_interfaces(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)405 static 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 
446 const sd_bus_vtable bus_cgroup_vtable[] = {
447         SD_BUS_VTABLE_START(0),
448         SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0),
449         SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers, 0, 0),
450         SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
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),
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),
455         SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
456         SD_BUS_PROPERTY("CPUQuotaPeriodUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_period_usec), 0),
457         SD_BUS_PROPERTY("AllowedCPUs", "ay", property_get_cpuset, offsetof(CGroupContext, cpuset_cpus), 0),
458         SD_BUS_PROPERTY("StartupAllowedCPUs", "ay", property_get_cpuset, offsetof(CGroupContext, startup_cpuset_cpus), 0),
459         SD_BUS_PROPERTY("AllowedMemoryNodes", "ay", property_get_cpuset, offsetof(CGroupContext, cpuset_mems), 0),
460         SD_BUS_PROPERTY("StartupAllowedMemoryNodes", "ay", property_get_cpuset, offsetof(CGroupContext, startup_cpuset_mems), 0),
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),
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),
469         SD_BUS_PROPERTY("IODeviceLatencyTargetUSec", "a(st)", property_get_io_device_latency, 0, 0),
470         SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
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),
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),
477         SD_BUS_PROPERTY("DefaultMemoryLow", "t", NULL, offsetof(CGroupContext, default_memory_low), 0),
478         SD_BUS_PROPERTY("DefaultMemoryMin", "t", NULL, offsetof(CGroupContext, default_memory_min), 0),
479         SD_BUS_PROPERTY("MemoryMin", "t", NULL, offsetof(CGroupContext, memory_min), 0),
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),
483         SD_BUS_PROPERTY("MemorySwapMax", "t", NULL, offsetof(CGroupContext, memory_swap_max), 0),
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),
487         SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, tasks_accounting), 0),
488         SD_BUS_PROPERTY("TasksMax", "t", bus_property_get_tasks_max, offsetof(CGroupContext, tasks_max), 0),
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),
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),
494         SD_BUS_PROPERTY("DisableControllers", "as", property_get_cgroup_mask, offsetof(CGroupContext, disable_controllers), 0),
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),
497         SD_BUS_PROPERTY("ManagedOOMMemoryPressureLimit", "u", NULL, offsetof(CGroupContext, moom_mem_pressure_limit), 0),
498         SD_BUS_PROPERTY("ManagedOOMPreference", "s", property_get_managed_oom_preference, offsetof(CGroupContext, moom_preference), 0),
499         SD_BUS_PROPERTY("BPFProgram", "a(ss)", property_get_bpf_foreign_program, 0, 0),
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),
502         SD_BUS_PROPERTY("RestrictNetworkInterfaces", "(bas)", property_get_restrict_network_interfaces, 0, 0),
503         SD_BUS_VTABLE_END
504 };
505 
bus_cgroup_set_transient_property(Unit * u,CGroupContext * c,const char * name,sd_bus_message * message,UnitWriteFlags flags,sd_bus_error * error)506 static int bus_cgroup_set_transient_property(
507                 Unit *u,
508                 CGroupContext *c,
509                 const char *name,
510                 sd_bus_message *message,
511                 UnitWriteFlags flags,
512                 sd_bus_error *error) {
513 
514         int r;
515 
516         assert(u);
517         assert(c);
518         assert(name);
519         assert(message);
520 
521         flags |= UNIT_PRIVATE;
522 
523         if (streq(name, "Delegate")) {
524                 int b;
525 
526                 if (!UNIT_VTABLE(u)->can_delegate)
527                         return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
528 
529                 r = sd_bus_message_read(message, "b", &b);
530                 if (r < 0)
531                         return r;
532 
533                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
534                         c->delegate = b;
535                         c->delegate_controllers = b ? _CGROUP_MASK_ALL : 0;
536 
537                         unit_write_settingf(u, flags, name, "Delegate=%s", yes_no(b));
538                 }
539 
540                 return 1;
541 
542         } else if (STR_IN_SET(name, "DelegateControllers", "DisableControllers")) {
543                 CGroupMask mask = 0;
544 
545                 if (streq(name, "DelegateControllers") && !UNIT_VTABLE(u)->can_delegate)
546                         return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
547 
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)
564                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown cgroup controller '%s'", t);
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 
573                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
574                         _cleanup_free_ char *t = NULL;
575 
576                         r = cg_mask_to_string(mask, &t);
577                         if (r < 0)
578                                 return r;
579 
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));
589 
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                         }
599                 }
600 
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;
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,
667                                                  "Transient unit %s configures an IP firewall with BPF, but the local system does not support BPF/cgroup firewalling with multiple filters.\n"
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 
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;
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 
752                 return 1;
753         }
754 
755         return 0;
756 }
757 
bus_cgroup_set_boolean(Unit * u,const char * name,bool * p,CGroupMask mask,sd_bus_message * message,UnitWriteFlags flags,sd_bus_error * error)758 static 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 
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;                                         \
808                         unit_invalidate_cgroup(u, mask);                \
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;                                         \
845                         unit_invalidate_cgroup(u, mask);                \
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)) {                    \
881                         *p = v;                                         \
882                         unit_invalidate_cgroup(u, mask);                \
883                                                                         \
884                         /* Prepare to chop off suffix */                \
885                         assert_se(endswith(name, "Scale"));             \
886                                                                         \
887                         int scaled = UINT32_SCALE_TO_PERMYRIAD(raw);    \
888                         unit_write_settingf(u, flags, name, "%.*s=" PERMYRIAD_AS_PERCENT_FORMAT_STR, \
889                                             (int)(strlen(name) - strlen("Scale")), name, \
890                                             PERMYRIAD_AS_PERCENT_FORMAT_VAL(scaled)); \
891                 }                                                       \
892                                                                         \
893                 return 1;                                               \
894         }
895 
896 DISABLE_WARNING_TYPE_LIMITS;
897 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight, CGROUP_MASK_CPU, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID);
898 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares, CGROUP_MASK_CPU, CGROUP_CPU_SHARES_IS_OK, CGROUP_CPU_SHARES_INVALID);
899 BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight, CGROUP_MASK_IO, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID);
900 BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight, CGROUP_MASK_BLKIO, CGROUP_BLKIO_WEIGHT_IS_OK, CGROUP_BLKIO_WEIGHT_INVALID);
901 BUS_DEFINE_SET_CGROUP_LIMIT(memory, CGROUP_MASK_MEMORY, physical_memory_scale, 1);
902 BUS_DEFINE_SET_CGROUP_LIMIT(memory_protection, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
903 BUS_DEFINE_SET_CGROUP_LIMIT(swap, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
904 REENABLE_WARNING;
905 
bus_cgroup_set_tasks_max(Unit * u,const char * name,TasksMax * p,sd_bus_message * message,UnitWriteFlags flags,sd_bus_error * error)906 static 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 
bus_cgroup_set_tasks_max_scale(Unit * u,const char * name,TasksMax * p,sd_bus_message * message,UnitWriteFlags flags,sd_bus_error * error)942 static 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 
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);
970         }
971 
972         return 1;
973 }
974 
bus_cgroup_set_property(Unit * u,CGroupContext * c,const char * name,sd_bus_message * message,UnitWriteFlags flags,sd_bus_error * error)975 int bus_cgroup_set_property(
976                 Unit *u,
977                 CGroupContext *c,
978                 const char *name,
979                 sd_bus_message *message,
980                 UnitWriteFlags flags,
981                 sd_bus_error *error) {
982 
983         CGroupIOLimitType iol_type;
984         int r;
985 
986         assert(u);
987         assert(c);
988         assert(name);
989         assert(message);
990 
991         flags |= UNIT_PRIVATE;
992 
993         if (streq(name, "CPUAccounting"))
994                 return bus_cgroup_set_boolean(u, name, &c->cpu_accounting, get_cpu_accounting_mask(), message, flags, error);
995 
996         if (streq(name, "CPUWeight"))
997                 return bus_cgroup_set_cpu_weight(u, name, &c->cpu_weight, message, flags, error);
998 
999         if (streq(name, "StartupCPUWeight"))
1000                 return bus_cgroup_set_cpu_weight(u, name, &c->startup_cpu_weight, message, flags, error);
1001 
1002         if (streq(name, "CPUShares"))
1003                 return bus_cgroup_set_cpu_shares(u, name, &c->cpu_shares, message, flags, error);
1004 
1005         if (streq(name, "StartupCPUShares"))
1006                 return bus_cgroup_set_cpu_shares(u, name, &c->startup_cpu_shares, message, flags, error);
1007 
1008         if (streq(name, "IOAccounting"))
1009                 return bus_cgroup_set_boolean(u, name, &c->io_accounting, CGROUP_MASK_IO, message, flags, error);
1010 
1011         if (streq(name, "IOWeight"))
1012                 return bus_cgroup_set_io_weight(u, name, &c->io_weight, message, flags, error);
1013 
1014         if (streq(name, "StartupIOWeight"))
1015                 return bus_cgroup_set_io_weight(u, name, &c->startup_io_weight, message, flags, error);
1016 
1017         if (streq(name, "BlockIOAccounting"))
1018                 return bus_cgroup_set_boolean(u, name, &c->blockio_accounting, CGROUP_MASK_BLKIO, message, flags, error);
1019 
1020         if (streq(name, "BlockIOWeight"))
1021                 return bus_cgroup_set_blockio_weight(u, name, &c->blockio_weight, message, flags, error);
1022 
1023         if (streq(name, "StartupBlockIOWeight"))
1024                 return bus_cgroup_set_blockio_weight(u, name, &c->startup_blockio_weight, message, flags, error);
1025 
1026         if (streq(name, "MemoryAccounting"))
1027                 return bus_cgroup_set_boolean(u, name, &c->memory_accounting, CGROUP_MASK_MEMORY, message, flags, error);
1028 
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         }
1035 
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         }
1042 
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         }
1049 
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         }
1056 
1057         if (streq(name, "MemoryHigh"))
1058                 return bus_cgroup_set_memory(u, name, &c->memory_high, message, flags, error);
1059 
1060         if (streq(name, "MemorySwapMax"))
1061                 return bus_cgroup_set_swap(u, name, &c->memory_swap_max, message, flags, error);
1062 
1063         if (streq(name, "MemoryMax"))
1064                 return bus_cgroup_set_memory(u, name, &c->memory_max, message, flags, error);
1065 
1066         if (streq(name, "MemoryLimit"))
1067                 return bus_cgroup_set_memory(u, name, &c->memory_limit, message, flags, error);
1068 
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         }
1075 
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         }
1082 
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         }
1089 
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         }
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"))
1101                 return bus_cgroup_set_swap_scale(u, name, &c->memory_swap_max, message, flags, error);
1102 
1103         if (streq(name, "MemoryMaxScale"))
1104                 return bus_cgroup_set_memory_scale(u, name, &c->memory_max, message, flags, error);
1105 
1106         if (streq(name, "MemoryLimitScale"))
1107                 return bus_cgroup_set_memory_scale(u, name, &c->memory_limit, message, flags, error);
1108 
1109         if (streq(name, "TasksAccounting"))
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")) {
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)
1126                         return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "CPUQuotaPerSecUSec= value out of range");
1127 
1128                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1129                         c->cpu_quota_per_sec_usec = u64;
1130                         u->warned_clamping_cpu_quota_period = false;
1131                         unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
1132 
1133                         if (c->cpu_quota_per_sec_usec == USEC_INFINITY)
1134                                 unit_write_setting(u, flags, "CPUQuota", "CPUQuota=");
1135                         else
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));
1141                 }
1142 
1143                 return 1;
1144 
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;
1154                         u->warned_clamping_cpu_quota_period = false;
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=");
1158                         else
1159                                 unit_write_settingf(u, flags, "CPUQuotaPeriodSec",
1160                                                     "CPUQuotaPeriodSec=%s",
1161                                                     FORMAT_TIMESPAN(c->cpu_quota_period_usec, 1));
1162                 }
1163 
1164                 return 1;
1165 
1166         } else if (STR_IN_SET(name, "AllowedCPUs", "StartupAllowedCPUs", "AllowedMemoryNodes", "StartupAllowedMemoryNodes")) {
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;
1181                         CPUSet *set = NULL;
1182 
1183                         setstr = cpu_set_to_range_string(&new_set);
1184                         if (!setstr)
1185                                 return -ENOMEM;
1186 
1187                         if (streq(name, "AllowedCPUs"))
1188                                 set = &c->cpuset_cpus;
1189                         else if (streq(name, "StartupAllowedCPUs"))
1190                                 set = &c->startup_cpuset_cpus;
1191                         else if (streq(name, "AllowedMemoryNodes"))
1192                                 set = &c->cpuset_mems;
1193                         else if (streq(name, "StartupAllowedMemoryNodes"))
1194                                 set = &c->startup_cpuset_mems;
1195 
1196                         assert(set);
1197 
1198                         cpu_set_reset(set);
1199                         *set = new_set;
1200                         new_set = (CPUSet) {};
1201 
1202                         unit_invalidate_cgroup(u, CGROUP_MASK_CPUSET);
1203                         unit_write_settingf(u, flags, name, "%s=%s", name, setstr);
1204                 }
1205 
1206                 return 1;
1207 
1208         } else if ((iol_type = cgroup_io_limit_type_from_string(name)) >= 0) {
1209                 const char *path;
1210                 unsigned n = 0;
1211                 uint64_t u64;
1212 
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 
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);
1221 
1222                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1223                                 CGroupIODeviceLimit *a = NULL;
1224 
1225                                 LIST_FOREACH(device_limits, b, c->io_device_limits)
1226                                         if (path_equal(path, b->path)) {
1227                                                 a = b;
1228                                                 break;
1229                                         }
1230 
1231                                 if (!a) {
1232                                         CGroupIOLimitType type;
1233 
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 
1244                                         for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
1245                                                 a->limits[type] = cgroup_io_limit_defaults[type];
1246 
1247                                         LIST_PREPEND(device_limits, c->io_device_limits, a);
1248                                 }
1249 
1250                                 a->limits[iol_type] = u64;
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 
1262                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1263                         _cleanup_free_ char *buf = NULL;
1264                         _cleanup_fclose_ FILE *f = NULL;
1265                         size_t size = 0;
1266 
1267                         if (n == 0)
1268                                 LIST_FOREACH(device_limits, a, c->io_device_limits)
1269                                         a->limits[iol_type] = cgroup_io_limit_defaults[iol_type];
1270 
1271                         unit_invalidate_cgroup(u, CGROUP_MASK_IO);
1272 
1273                         f = open_memstream_unlocked(&buf, &size);
1274                         if (!f)
1275                                 return -ENOMEM;
1276 
1277                         fprintf(f, "%s=\n", name);
1278                         LIST_FOREACH(device_limits, a, c->io_device_limits)
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]);
1281 
1282                         r = fflush_and_check(f);
1283                         if (r < 0)
1284                                 return r;
1285                         unit_write_setting(u, flags, name, buf);
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 
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);
1303 
1304                         if (!CGROUP_WEIGHT_IS_OK(weight) || weight == CGROUP_WEIGHT_INVALID)
1305                                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "IODeviceWeight= value out of range");
1306 
1307                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1308                                 CGroupIODeviceWeight *a = NULL;
1309 
1310                                 LIST_FOREACH(device_weights, b, c->io_device_weights)
1311                                         if (path_equal(b->path, path)) {
1312                                                 a = b;
1313                                                 break;
1314                                         }
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                                         }
1326                                         LIST_PREPEND(device_weights, c->io_device_weights, a);
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 
1339                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1340                         _cleanup_free_ char *buf = NULL;
1341                         _cleanup_fclose_ FILE *f = NULL;
1342                         size_t size = 0;
1343 
1344                         if (n == 0)
1345                                 while (c->io_device_weights)
1346                                         cgroup_context_free_io_device_weight(c, c->io_device_weights);
1347 
1348                         unit_invalidate_cgroup(u, CGROUP_MASK_IO);
1349 
1350                         f = open_memstream_unlocked(&buf, &size);
1351                         if (!f)
1352                                 return -ENOMEM;
1353 
1354                         fputs("IODeviceWeight=\n", f);
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;
1361                         unit_write_setting(u, flags, name, buf);
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)) {
1381                                 CGroupIODeviceLatency *a = NULL;
1382 
1383                                 LIST_FOREACH(device_latencies, b, c->io_device_latencies)
1384                                         if (path_equal(b->path, path)) {
1385                                                 a = b;
1386                                                 break;
1387                                         }
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;
1415                         size_t size = 0;
1416 
1417                         if (n == 0)
1418                                 while (c->io_device_latencies)
1419                                         cgroup_context_free_io_device_latency(c, c->io_device_latencies);
1420 
1421                         unit_invalidate_cgroup(u, CGROUP_MASK_IO);
1422 
1423                         f = open_memstream_unlocked(&buf, &size);
1424                         if (!f)
1425                                 return -ENOMEM;
1426 
1427                         fputs("IODeviceLatencyTargetSec=\n", f);
1428                         LIST_FOREACH(device_latencies, a, c->io_device_latencies)
1429                                 fprintf(f, "IODeviceLatencyTargetSec=%s %s\n",
1430                                         a->path, FORMAT_TIMESPAN(a->target_usec, 1));
1431 
1432                         r = fflush_and_check(f);
1433                         if (r < 0)
1434                                 return r;
1435                         unit_write_setting(u, flags, name, buf);
1436                 }
1437 
1438                 return 1;
1439 
1440         } else if (STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1441                 const char *path;
1442                 bool read = true;
1443                 unsigned n = 0;
1444                 uint64_t u64;
1445 
1446                 if (streq(name, "BlockIOWriteBandwidth"))
1447                         read = false;
1448 
1449                 r = sd_bus_message_enter_container(message, 'a', "(st)");
1450                 if (r < 0)
1451                         return r;
1452 
1453                 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
1454 
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);
1457 
1458                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1459                                 CGroupBlockIODeviceBandwidth *a = NULL;
1460 
1461                                 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths)
1462                                         if (path_equal(path, b->path)) {
1463                                                 a = b;
1464                                                 break;
1465                                         }
1466 
1467                                 if (!a) {
1468                                         a = new0(CGroupBlockIODeviceBandwidth, 1);
1469                                         if (!a)
1470                                                 return -ENOMEM;
1471 
1472                                         a->rbps = CGROUP_LIMIT_MAX;
1473                                         a->wbps = CGROUP_LIMIT_MAX;
1474                                         a->path = strdup(path);
1475                                         if (!a->path) {
1476                                                 free(a);
1477                                                 return -ENOMEM;
1478                                         }
1479 
1480                                         LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
1481                                 }
1482 
1483                                 if (read)
1484                                         a->rbps = u64;
1485                                 else
1486                                         a->wbps = u64;
1487                         }
1488 
1489                         n++;
1490                 }
1491                 if (r < 0)
1492                         return r;
1493 
1494                 r = sd_bus_message_exit_container(message);
1495                 if (r < 0)
1496                         return r;
1497 
1498                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1499                         _cleanup_free_ char *buf = NULL;
1500                         _cleanup_fclose_ FILE *f = NULL;
1501                         size_t size = 0;
1502 
1503                         if (n == 0)
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                                 }
1510 
1511                         unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
1512 
1513                         f = open_memstream_unlocked(&buf, &size);
1514                         if (!f)
1515                                 return -ENOMEM;
1516 
1517                         if (read) {
1518                                 fputs("BlockIOReadBandwidth=\n", f);
1519                                 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
1520                                         if (a->rbps != CGROUP_LIMIT_MAX)
1521                                                 fprintf(f, "BlockIOReadBandwidth=%s %" PRIu64 "\n", a->path, a->rbps);
1522                         } else {
1523                                 fputs("BlockIOWriteBandwidth=\n", f);
1524                                 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
1525                                         if (a->wbps != CGROUP_LIMIT_MAX)
1526                                                 fprintf(f, "BlockIOWriteBandwidth=%s %" PRIu64 "\n", a->path, a->wbps);
1527                         }
1528 
1529                         r = fflush_and_check(f);
1530                         if (r < 0)
1531                                 return r;
1532 
1533                         unit_write_setting(u, flags, name, buf);
1534                 }
1535 
1536                 return 1;
1537 
1538         } else if (streq(name, "BlockIODeviceWeight")) {
1539                 const char *path;
1540                 uint64_t weight;
1541                 unsigned n = 0;
1542 
1543                 r = sd_bus_message_enter_container(message, 'a', "(st)");
1544                 if (r < 0)
1545                         return r;
1546 
1547                 while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
1548 
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);
1551 
1552                         if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight) || weight == CGROUP_BLKIO_WEIGHT_INVALID)
1553                                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "BlockIODeviceWeight= out of range");
1554 
1555                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1556                                 CGroupBlockIODeviceWeight *a = NULL;
1557 
1558                                 LIST_FOREACH(device_weights, b, c->blockio_device_weights)
1559                                         if (path_equal(b->path, path)) {
1560                                                 a = b;
1561                                                 break;
1562                                         }
1563 
1564                                 if (!a) {
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                                         }
1574                                         LIST_PREPEND(device_weights, c->blockio_device_weights, a);
1575                                 }
1576 
1577                                 a->weight = weight;
1578                         }
1579 
1580                         n++;
1581                 }
1582 
1583                 r = sd_bus_message_exit_container(message);
1584                 if (r < 0)
1585                         return r;
1586 
1587                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1588                         _cleanup_free_ char *buf = NULL;
1589                         _cleanup_fclose_ FILE *f = NULL;
1590                         size_t size = 0;
1591 
1592                         if (n == 0)
1593                                 while (c->blockio_device_weights)
1594                                         cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
1595 
1596                         unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
1597 
1598                         f = open_memstream_unlocked(&buf, &size);
1599                         if (!f)
1600                                 return -ENOMEM;
1601 
1602                         fputs("BlockIODeviceWeight=\n", f);
1603                         LIST_FOREACH(device_weights, a, c->blockio_device_weights)
1604                                 fprintf(f, "BlockIODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
1605 
1606                         r = fflush_and_check(f);
1607                         if (r < 0)
1608                                 return r;
1609 
1610                         unit_write_setting(u, flags, name, buf);
1611                 }
1612 
1613                 return 1;
1614 
1615         } else if (streq(name, "DevicePolicy")) {
1616                 const char *policy;
1617                 CGroupDevicePolicy p;
1618 
1619                 r = sd_bus_message_read(message, "s", &policy);
1620                 if (r < 0)
1621                         return r;
1622 
1623                 p = cgroup_device_policy_from_string(policy);
1624                 if (p < 0)
1625                         return p;
1626 
1627                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1628                         c->device_policy = p;
1629                         unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
1630                         unit_write_settingf(u, flags, name, "DevicePolicy=%s", policy);
1631                 }
1632 
1633                 return 1;
1634 
1635         } else if (streq(name, "DeviceAllow")) {
1636                 const char *path, *rwm;
1637                 unsigned n = 0;
1638 
1639                 r = sd_bus_message_enter_container(message, 'a', "(ss)");
1640                 if (r < 0)
1641                         return r;
1642 
1643                 while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
1644 
1645                         if (!valid_device_allow_pattern(path) || strpbrk(path, WHITESPACE))
1646                                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires device node or pattern");
1647 
1648                         if (isempty(rwm))
1649                                 rwm = "rwm";
1650                         else if (!in_charset(rwm, "rwm"))
1651                                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires combination of rwm flags");
1652 
1653                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1654                                 CGroupDeviceAllow *a = NULL;
1655 
1656                                 LIST_FOREACH(device_allow, b, c->device_allow)
1657                                         if (path_equal(b->path, path)) {
1658                                                 a = b;
1659                                                 break;
1660                                         }
1661 
1662                                 if (!a) {
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                                         }
1672 
1673                                         LIST_PREPEND(device_allow, c->device_allow, a);
1674                                 }
1675 
1676                                 a->r = strchr(rwm, 'r');
1677                                 a->w = strchr(rwm, 'w');
1678                                 a->m = strchr(rwm, 'm');
1679                         }
1680 
1681                         n++;
1682                 }
1683                 if (r < 0)
1684                         return r;
1685 
1686                 r = sd_bus_message_exit_container(message);
1687                 if (r < 0)
1688                         return r;
1689 
1690                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1691                         _cleanup_free_ char *buf = NULL;
1692                         _cleanup_fclose_ FILE *f = NULL;
1693                         size_t size = 0;
1694 
1695                         if (n == 0)
1696                                 while (c->device_allow)
1697                                         cgroup_context_free_device_allow(c, c->device_allow);
1698 
1699                         unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
1700 
1701                         f = open_memstream_unlocked(&buf, &size);
1702                         if (!f)
1703                                 return -ENOMEM;
1704 
1705                         fputs("DeviceAllow=\n", f);
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 
1709                         r = fflush_and_check(f);
1710                         if (r < 0)
1711                                 return r;
1712                         unit_write_setting(u, flags, name, buf);
1713                 }
1714 
1715                 return 1;
1716 
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 
1724                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1725                         c->ip_accounting = b;
1726 
1727                         unit_invalidate_cgroup_bpf(u);
1728                         unit_write_settingf(u, flags, name, "IPAccounting=%s", yes_no(b));
1729                 }
1730 
1731                 return 1;
1732 
1733         } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) {
1734                 _cleanup_set_free_ Set *new_prefixes = NULL;
1735                 size_t n = 0;
1736 
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))
1758                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects IPv4 or IPv6 addresses only.", name);
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))
1765                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "IP address has wrong size for family (%s, expected %zu, got %zu)",
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)
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));
1774 
1775                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1776                                 struct in_addr_prefix prefix = {
1777                                         .family = family,
1778                                         .prefixlen = prefixlen,
1779                                 };
1780 
1781                                 memcpy(&prefix.address, ap, an);
1782 
1783                                 r = in_addr_prefix_add(&new_prefixes, &prefix);
1784                                 if (r < 0)
1785                                         return r;
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 
1799                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1800                         _cleanup_free_ char *buf = NULL;
1801                         _cleanup_fclose_ FILE *f = NULL;
1802                         size_t size = 0;
1803                         Set **prefixes;
1804                         bool *reduced;
1805 
1806                         unit_invalidate_cgroup_bpf(u);
1807                         f = open_memstream_unlocked(&buf, &size);
1808                         if (!f)
1809                                 return -ENOMEM;
1810 
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;
1813 
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;
1821 
1822                                 *reduced = false;
1823 
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                                 }
1839                         }
1840 
1841                         r = fflush_and_check(f);
1842                         if (r < 0)
1843                                 return r;
1844 
1845                         unit_write_setting(u, flags, name, buf);
1846                 }
1847 
1848                 return 1;
1849         }
1850 
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 
1872                 (void) manager_varlink_send_managed_oom_update(u);
1873                 return 1;
1874         }
1875 
1876         if (streq(name, "ManagedOOMMemoryPressureLimit")) {
1877                 uint32_t v;
1878 
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 
1882                 r = sd_bus_message_read(message, "u", &v);
1883                 if (r < 0)
1884                         return r;
1885 
1886                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
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)));
1891                 }
1892 
1893                 if (c->moom_mem_pressure == MANAGED_OOM_KILL)
1894                         (void) manager_varlink_send_managed_oom_update(u);
1895 
1896                 return 1;
1897         }
1898 
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)
1909                         return p;
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         }
1918         if (STR_IN_SET(name, "SocketBindAllow", "SocketBindDeny")) {
1919                 CGroupSocketBindItem **list;
1920                 uint16_t nr_ports, port_min;
1921                 size_t n = 0;
1922                 int32_t family, ip_protocol;
1923 
1924                 list = streq(name, "SocketBindAllow") ? &c->socket_bind_allow : &c->socket_bind_deny;
1925 
1926                 r = sd_bus_message_enter_container(message, 'a', "(iiqq)");
1927                 if (r < 0)
1928                         return r;
1929 
1930                 while ((r = sd_bus_message_read(message, "(iiqq)", &family, &ip_protocol, &nr_ports, &port_min)) > 0) {
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 
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);
1937 
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,
1953                                         .ip_protocol = ip_protocol,
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;
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         }
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;
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         }
2061 
2062         if (streq(name, "DisableControllers") || (u->transient && u->load_state == UNIT_STUB))
2063                 return bus_cgroup_set_transient_property(u, c, name, message, flags, error);
2064 
2065         return 0;
2066 }
2067