]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-cgroup.c
test: add tests for syscall:errno style in SystemCallFilter=
[thirdparty/systemd.git] / src / core / dbus-cgroup.c
CommitLineData
4ad49000
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2013 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
3dc5ca97
LP
20#include <arpa/inet.h>
21
22#include "af-list.h"
b5efdb8a 23#include "alloc-util.h"
078ba556 24#include "bpf-firewall.h"
718db961 25#include "bus-util.h"
718db961
LP
26#include "cgroup-util.h"
27#include "cgroup.h"
4ad49000 28#include "dbus-cgroup.h"
3ffd4af2 29#include "fd-util.h"
0d39fa9c 30#include "fileio.h"
3ffd4af2 31#include "path-util.h"
4ad49000 32
718db961
LP
33static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
34
13c31542
TH
35static int property_get_io_device_weight(
36 sd_bus *bus,
37 const char *path,
38 const char *interface,
39 const char *property,
40 sd_bus_message *reply,
41 void *userdata,
42 sd_bus_error *error) {
43
44 CGroupContext *c = userdata;
45 CGroupIODeviceWeight *w;
46 int r;
47
48 assert(bus);
49 assert(reply);
50 assert(c);
51
52 r = sd_bus_message_open_container(reply, 'a', "(st)");
53 if (r < 0)
54 return r;
55
56 LIST_FOREACH(device_weights, w, c->io_device_weights) {
57 r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
58 if (r < 0)
59 return r;
60 }
61
62 return sd_bus_message_close_container(reply);
63}
64
65static int property_get_io_device_limits(
66 sd_bus *bus,
67 const char *path,
68 const char *interface,
69 const char *property,
70 sd_bus_message *reply,
71 void *userdata,
72 sd_bus_error *error) {
73
74 CGroupContext *c = userdata;
75 CGroupIODeviceLimit *l;
76 int r;
77
78 assert(bus);
79 assert(reply);
80 assert(c);
81
82 r = sd_bus_message_open_container(reply, 'a', "(st)");
83 if (r < 0)
84 return r;
85
86 LIST_FOREACH(device_limits, l, c->io_device_limits) {
9be57249 87 CGroupIOLimitType type;
13c31542 88
9be57249
TH
89 type = cgroup_io_limit_type_from_string(property);
90 if (type < 0 || l->limits[type] == cgroup_io_limit_defaults[type])
13c31542
TH
91 continue;
92
9be57249 93 r = sd_bus_message_append(reply, "(st)", l->path, l->limits[type]);
13c31542
TH
94 if (r < 0)
95 return r;
96 }
97
98 return sd_bus_message_close_container(reply);
99}
100
718db961
LP
101static int property_get_blockio_device_weight(
102 sd_bus *bus,
103 const char *path,
104 const char *interface,
105 const char *property,
106 sd_bus_message *reply,
ebcf1f97
LP
107 void *userdata,
108 sd_bus_error *error) {
4ad49000 109
718db961 110 CGroupContext *c = userdata;
4ad49000 111 CGroupBlockIODeviceWeight *w;
718db961 112 int r;
4ad49000 113
718db961
LP
114 assert(bus);
115 assert(reply);
4ad49000
LP
116 assert(c);
117
718db961
LP
118 r = sd_bus_message_open_container(reply, 'a', "(st)");
119 if (r < 0)
120 return r;
4ad49000
LP
121
122 LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
718db961
LP
123 r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
124 if (r < 0)
125 return r;
4ad49000
LP
126 }
127
718db961 128 return sd_bus_message_close_container(reply);
4ad49000
LP
129}
130
718db961
LP
131static int property_get_blockio_device_bandwidths(
132 sd_bus *bus,
133 const char *path,
134 const char *interface,
135 const char *property,
136 sd_bus_message *reply,
ebcf1f97
LP
137 void *userdata,
138 sd_bus_error *error) {
718db961
LP
139
140 CGroupContext *c = userdata;
4ad49000 141 CGroupBlockIODeviceBandwidth *b;
718db961 142 int r;
4ad49000 143
718db961
LP
144 assert(bus);
145 assert(reply);
4ad49000
LP
146 assert(c);
147
718db961
LP
148 r = sd_bus_message_open_container(reply, 'a', "(st)");
149 if (r < 0)
150 return r;
4ad49000
LP
151
152 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
979d0311 153 uint64_t v;
4ad49000 154
979d0311
TH
155 if (streq(property, "BlockIOReadBandwidth"))
156 v = b->rbps;
157 else
158 v = b->wbps;
159
160 if (v == CGROUP_LIMIT_MAX)
4ad49000
LP
161 continue;
162
979d0311 163 r = sd_bus_message_append(reply, "(st)", b->path, v);
718db961
LP
164 if (r < 0)
165 return r;
4ad49000
LP
166 }
167
718db961 168 return sd_bus_message_close_container(reply);
4ad49000
LP
169}
170
718db961
LP
171static int property_get_device_allow(
172 sd_bus *bus,
173 const char *path,
174 const char *interface,
175 const char *property,
176 sd_bus_message *reply,
ebcf1f97
LP
177 void *userdata,
178 sd_bus_error *error) {
718db961
LP
179
180 CGroupContext *c = userdata;
4ad49000 181 CGroupDeviceAllow *a;
718db961 182 int r;
4ad49000 183
718db961
LP
184 assert(bus);
185 assert(reply);
4ad49000
LP
186 assert(c);
187
718db961
LP
188 r = sd_bus_message_open_container(reply, 'a', "(ss)");
189 if (r < 0)
190 return r;
4ad49000
LP
191
192 LIST_FOREACH(device_allow, a, c->device_allow) {
4ad49000 193 unsigned k = 0;
718db961 194 char rwm[4];
4ad49000
LP
195
196 if (a->r)
718db961 197 rwm[k++] = 'r';
4ad49000 198 if (a->w)
718db961 199 rwm[k++] = 'w';
4ad49000 200 if (a->m)
718db961 201 rwm[k++] = 'm';
4ad49000 202
718db961 203 rwm[k] = 0;
4ad49000 204
718db961
LP
205 r = sd_bus_message_append(reply, "(ss)", a->path, rwm);
206 if (r < 0)
207 return r;
4ad49000
LP
208 }
209
718db961 210 return sd_bus_message_close_container(reply);
4ad49000
LP
211}
212
3dc5ca97
LP
213static int property_get_ip_address_access(
214 sd_bus *bus,
215 const char *path,
216 const char *interface,
217 const char *property,
218 sd_bus_message *reply,
219 void *userdata,
220 sd_bus_error *error) {
221
222 IPAddressAccessItem** items = userdata, *i;
223 int r;
224
225 r = sd_bus_message_open_container(reply, 'a', "(iayu)");
226 if (r < 0)
227 return r;
228
229 LIST_FOREACH(items, i, *items) {
230
231 r = sd_bus_message_open_container(reply, 'r', "iayu");
232 if (r < 0)
233 return r;
234
235 r = sd_bus_message_append(reply, "i", i->family);
236 if (r < 0)
237 return r;
238
239 r = sd_bus_message_append_array(reply, 'y', &i->address, FAMILY_ADDRESS_SIZE(i->family));
240 if (r < 0)
241 return r;
242
243 r = sd_bus_message_append(reply, "u", (uint32_t) i->prefixlen);
244 if (r < 0)
245 return r;
246
247 r = sd_bus_message_close_container(reply);
248 if (r < 0)
249 return r;
250 }
251
252 return sd_bus_message_close_container(reply);
253}
254
718db961
LP
255const sd_bus_vtable bus_cgroup_vtable[] = {
256 SD_BUS_VTABLE_START(0),
a931ad47 257 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0),
610f780c 258 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
66ebf6c0
TH
259 SD_BUS_PROPERTY("CPUWeight", "t", NULL, offsetof(CGroupContext, cpu_weight), 0),
260 SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL, offsetof(CGroupContext, startup_cpu_weight), 0),
d53d9474
LP
261 SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0),
262 SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0),
ee26bcc0 263 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
13c31542
TH
264 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, io_accounting), 0),
265 SD_BUS_PROPERTY("IOWeight", "t", NULL, offsetof(CGroupContext, io_weight), 0),
266 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL, offsetof(CGroupContext, startup_io_weight), 0),
267 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight, 0, 0),
268 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0),
269 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0),
ac06a0cf
TH
270 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits, 0, 0),
271 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits, 0, 0),
610f780c 272 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
d53d9474
LP
273 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL, offsetof(CGroupContext, blockio_weight), 0),
274 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL, offsetof(CGroupContext, startup_blockio_weight), 0),
610f780c
LP
275 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0),
276 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
277 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
278 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0),
da4d897e
TH
279 SD_BUS_PROPERTY("MemoryLow", "t", NULL, offsetof(CGroupContext, memory_low), 0),
280 SD_BUS_PROPERTY("MemoryHigh", "t", NULL, offsetof(CGroupContext, memory_high), 0),
281 SD_BUS_PROPERTY("MemoryMax", "t", NULL, offsetof(CGroupContext, memory_max), 0),
96e131ea 282 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL, offsetof(CGroupContext, memory_swap_max), 0),
610f780c
LP
283 SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0),
284 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0),
285 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0),
03a7b521
LP
286 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, tasks_accounting), 0),
287 SD_BUS_PROPERTY("TasksMax", "t", NULL, offsetof(CGroupContext, tasks_max), 0),
3dc5ca97
LP
288 SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, ip_accounting), 0),
289 SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_allow), 0),
290 SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_deny), 0),
718db961 291 SD_BUS_VTABLE_END
4ad49000 292};
8e2af478 293
a931ad47
LP
294static int bus_cgroup_set_transient_property(
295 Unit *u,
296 CGroupContext *c,
297 const char *name,
298 sd_bus_message *message,
299 UnitSetPropertiesMode mode,
300 sd_bus_error *error) {
301
302 int r;
303
304 assert(u);
305 assert(c);
306 assert(name);
307 assert(message);
308
309 if (streq(name, "Delegate")) {
310 int b;
311
312 r = sd_bus_message_read(message, "b", &b);
313 if (r < 0)
314 return r;
315
316 if (mode != UNIT_CHECK) {
317 c->delegate = b;
b27b4b51 318 unit_write_drop_in_private(u, mode, name, b ? "Delegate=yes" : "Delegate=no");
a931ad47
LP
319 }
320
321 return 1;
322 }
323
324 return 0;
325}
326
8e2af478
LP
327int bus_cgroup_set_property(
328 Unit *u,
329 CGroupContext *c,
330 const char *name,
718db961 331 sd_bus_message *message,
8e2af478 332 UnitSetPropertiesMode mode,
718db961
LP
333 sd_bus_error *error) {
334
9be57249 335 CGroupIOLimitType iol_type;
718db961 336 int r;
8e2af478 337
8e2af478
LP
338 assert(u);
339 assert(c);
718db961
LP
340 assert(name);
341 assert(message);
8e2af478
LP
342
343 if (streq(name, "CPUAccounting")) {
718db961 344 int b;
8e2af478 345
718db961
LP
346 r = sd_bus_message_read(message, "b", &b);
347 if (r < 0)
348 return r;
8e2af478
LP
349
350 if (mode != UNIT_CHECK) {
8e2af478 351 c->cpu_accounting = b;
e7ab4d1a 352 unit_invalidate_cgroup(u, CGROUP_MASK_CPUACCT|CGROUP_MASK_CPU);
b27b4b51 353 unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes" : "CPUAccounting=no");
b42defe3
LP
354 }
355
356 return 1;
357
66ebf6c0
TH
358 } else if (streq(name, "CPUWeight")) {
359 uint64_t weight;
360
361 r = sd_bus_message_read(message, "t", &weight);
362 if (r < 0)
363 return r;
364
365 if (!CGROUP_WEIGHT_IS_OK(weight))
366 return sd_bus_error_set_errnof(error, EINVAL, "CPUWeight value out of range");
367
368 if (mode != UNIT_CHECK) {
369 c->cpu_weight = weight;
370 unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
371
372 if (weight == CGROUP_WEIGHT_INVALID)
373 unit_write_drop_in_private(u, mode, name, "CPUWeight=");
374 else
375 unit_write_drop_in_private_format(u, mode, name, "CPUWeight=%" PRIu64, weight);
376 }
377
378 return 1;
379
380 } else if (streq(name, "StartupCPUWeight")) {
381 uint64_t weight;
382
383 r = sd_bus_message_read(message, "t", &weight);
384 if (r < 0)
385 return r;
386
387 if (!CGROUP_WEIGHT_IS_OK(weight))
388 return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUWeight value out of range");
389
390 if (mode != UNIT_CHECK) {
391 c->startup_cpu_weight = weight;
392 unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
393
394 if (weight == CGROUP_CPU_SHARES_INVALID)
395 unit_write_drop_in_private(u, mode, name, "StartupCPUWeight=");
396 else
397 unit_write_drop_in_private_format(u, mode, name, "StartupCPUWeight=%" PRIu64, weight);
398 }
399
400 return 1;
401
b42defe3 402 } else if (streq(name, "CPUShares")) {
d53d9474 403 uint64_t shares;
b42defe3 404
d53d9474 405 r = sd_bus_message_read(message, "t", &shares);
718db961
LP
406 if (r < 0)
407 return r;
b42defe3 408
d53d9474
LP
409 if (!CGROUP_CPU_SHARES_IS_OK(shares))
410 return sd_bus_error_set_errnof(error, EINVAL, "CPUShares value out of range");
b42defe3
LP
411
412 if (mode != UNIT_CHECK) {
d53d9474 413 c->cpu_shares = shares;
e7ab4d1a 414 unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
d53d9474
LP
415
416 if (shares == CGROUP_CPU_SHARES_INVALID)
b27b4b51 417 unit_write_drop_in_private(u, mode, name, "CPUShares=");
d53d9474 418 else
b27b4b51 419 unit_write_drop_in_private_format(u, mode, name, "CPUShares=%" PRIu64, shares);
8e2af478
LP
420 }
421
422 return 1;
423
95ae05c0 424 } else if (streq(name, "StartupCPUShares")) {
d53d9474 425 uint64_t shares;
95ae05c0 426
d53d9474 427 r = sd_bus_message_read(message, "t", &shares);
95ae05c0
WC
428 if (r < 0)
429 return r;
430
d53d9474
LP
431 if (!CGROUP_CPU_SHARES_IS_OK(shares))
432 return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUShares value out of range");
95ae05c0
WC
433
434 if (mode != UNIT_CHECK) {
d53d9474 435 c->startup_cpu_shares = shares;
e7ab4d1a 436 unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
d53d9474
LP
437
438 if (shares == CGROUP_CPU_SHARES_INVALID)
b27b4b51 439 unit_write_drop_in_private(u, mode, name, "StartupCPUShares=");
d53d9474 440 else
b27b4b51 441 unit_write_drop_in_private_format(u, mode, name, "StartupCPUShares=%" PRIu64, shares);
95ae05c0
WC
442 }
443
444 return 1;
445
b2f8b02e
LP
446 } else if (streq(name, "CPUQuotaPerSecUSec")) {
447 uint64_t u64;
448
449 r = sd_bus_message_read(message, "t", &u64);
450 if (r < 0)
451 return r;
452
453 if (u64 <= 0)
454 return sd_bus_error_set_errnof(error, EINVAL, "CPUQuotaPerSecUSec value out of range");
455
456 if (mode != UNIT_CHECK) {
457 c->cpu_quota_per_sec_usec = u64;
e7ab4d1a 458 unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
d4bf82fc
ZJS
459 if (c->cpu_quota_per_sec_usec == USEC_INFINITY)
460 unit_write_drop_in_private_format(u, mode, "CPUQuota",
461 "CPUQuota=");
462 else
463 /* config_parse_cpu_quota() requires an integer, so
464 * truncating division is used on purpose here. */
465 unit_write_drop_in_private_format(u, mode, "CPUQuota",
466 "CPUQuota=%0.f%%",
467 (double) (c->cpu_quota_per_sec_usec / 10000));
b2f8b02e
LP
468 }
469
470 return 1;
471
13c31542
TH
472 } else if (streq(name, "IOAccounting")) {
473 int b;
474
475 r = sd_bus_message_read(message, "b", &b);
476 if (r < 0)
477 return r;
478
479 if (mode != UNIT_CHECK) {
480 c->io_accounting = b;
481 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
b27b4b51 482 unit_write_drop_in_private(u, mode, name, b ? "IOAccounting=yes" : "IOAccounting=no");
13c31542
TH
483 }
484
485 return 1;
486
487 } else if (streq(name, "IOWeight")) {
488 uint64_t weight;
489
490 r = sd_bus_message_read(message, "t", &weight);
491 if (r < 0)
492 return r;
493
494 if (!CGROUP_WEIGHT_IS_OK(weight))
495 return sd_bus_error_set_errnof(error, EINVAL, "IOWeight value out of range");
496
497 if (mode != UNIT_CHECK) {
498 c->io_weight = weight;
499 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
500
501 if (weight == CGROUP_WEIGHT_INVALID)
b27b4b51 502 unit_write_drop_in_private(u, mode, name, "IOWeight=");
13c31542 503 else
b27b4b51 504 unit_write_drop_in_private_format(u, mode, name, "IOWeight=%" PRIu64, weight);
13c31542
TH
505 }
506
507 return 1;
508
509 } else if (streq(name, "StartupIOWeight")) {
510 uint64_t weight;
511
512 r = sd_bus_message_read(message, "t", &weight);
513 if (r < 0)
514 return r;
515
516 if (CGROUP_WEIGHT_IS_OK(weight))
517 return sd_bus_error_set_errnof(error, EINVAL, "StartupIOWeight value out of range");
518
519 if (mode != UNIT_CHECK) {
520 c->startup_io_weight = weight;
521 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
522
523 if (weight == CGROUP_WEIGHT_INVALID)
b27b4b51 524 unit_write_drop_in_private(u, mode, name, "StartupIOWeight=");
13c31542 525 else
b27b4b51 526 unit_write_drop_in_private_format(u, mode, name, "StartupIOWeight=%" PRIu64, weight);
13c31542
TH
527 }
528
529 return 1;
530
9be57249 531 } else if ((iol_type = cgroup_io_limit_type_from_string(name)) >= 0) {
13c31542 532 const char *path;
13c31542
TH
533 unsigned n = 0;
534 uint64_t u64;
535
13c31542
TH
536 r = sd_bus_message_enter_container(message, 'a', "(st)");
537 if (r < 0)
538 return r;
539
540 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
541
542 if (mode != UNIT_CHECK) {
543 CGroupIODeviceLimit *a = NULL, *b;
544
545 LIST_FOREACH(device_limits, b, c->io_device_limits) {
546 if (path_equal(path, b->path)) {
547 a = b;
548 break;
549 }
550 }
551
552 if (!a) {
9be57249
TH
553 CGroupIOLimitType type;
554
13c31542
TH
555 a = new0(CGroupIODeviceLimit, 1);
556 if (!a)
557 return -ENOMEM;
558
559 a->path = strdup(path);
560 if (!a->path) {
561 free(a);
562 return -ENOMEM;
563 }
564
9be57249
TH
565 for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
566 a->limits[type] = cgroup_io_limit_defaults[type];
13c31542
TH
567
568 LIST_PREPEND(device_limits, c->io_device_limits, a);
569 }
570
9be57249 571 a->limits[iol_type] = u64;
13c31542
TH
572 }
573
574 n++;
575 }
576 if (r < 0)
577 return r;
578
579 r = sd_bus_message_exit_container(message);
580 if (r < 0)
581 return r;
582
583 if (mode != UNIT_CHECK) {
584 CGroupIODeviceLimit *a;
585 _cleanup_free_ char *buf = NULL;
586 _cleanup_fclose_ FILE *f = NULL;
587 size_t size = 0;
588
589 if (n == 0) {
590 LIST_FOREACH(device_limits, a, c->io_device_limits)
9be57249 591 a->limits[iol_type] = cgroup_io_limit_defaults[iol_type];
13c31542
TH
592 }
593
594 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
595
596 f = open_memstream(&buf, &size);
597 if (!f)
598 return -ENOMEM;
599
9be57249
TH
600 fprintf(f, "%s=\n", name);
601 LIST_FOREACH(device_limits, a, c->io_device_limits)
602 if (a->limits[iol_type] != cgroup_io_limit_defaults[iol_type])
603 fprintf(f, "%s=%s %" PRIu64 "\n", name, a->path, a->limits[iol_type]);
13c31542
TH
604
605 r = fflush_and_check(f);
606 if (r < 0)
607 return r;
608 unit_write_drop_in_private(u, mode, name, buf);
609 }
610
611 return 1;
612
613 } else if (streq(name, "IODeviceWeight")) {
614 const char *path;
615 uint64_t weight;
616 unsigned n = 0;
617
618 r = sd_bus_message_enter_container(message, 'a', "(st)");
619 if (r < 0)
620 return r;
621
622 while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
623
624 if (!CGROUP_WEIGHT_IS_OK(weight) || weight == CGROUP_WEIGHT_INVALID)
625 return sd_bus_error_set_errnof(error, EINVAL, "IODeviceWeight out of range");
626
627 if (mode != UNIT_CHECK) {
628 CGroupIODeviceWeight *a = NULL, *b;
629
630 LIST_FOREACH(device_weights, b, c->io_device_weights) {
631 if (path_equal(b->path, path)) {
632 a = b;
633 break;
634 }
635 }
636
637 if (!a) {
638 a = new0(CGroupIODeviceWeight, 1);
639 if (!a)
640 return -ENOMEM;
641
642 a->path = strdup(path);
643 if (!a->path) {
644 free(a);
645 return -ENOMEM;
646 }
647 LIST_PREPEND(device_weights,c->io_device_weights, a);
648 }
649
650 a->weight = weight;
651 }
652
653 n++;
654 }
655
656 r = sd_bus_message_exit_container(message);
657 if (r < 0)
658 return r;
659
660 if (mode != UNIT_CHECK) {
661 _cleanup_free_ char *buf = NULL;
662 _cleanup_fclose_ FILE *f = NULL;
663 CGroupIODeviceWeight *a;
664 size_t size = 0;
665
666 if (n == 0) {
667 while (c->io_device_weights)
668 cgroup_context_free_io_device_weight(c, c->io_device_weights);
669 }
670
671 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
672
673 f = open_memstream(&buf, &size);
674 if (!f)
675 return -ENOMEM;
676
4b61c875 677 fputs_unlocked("IODeviceWeight=\n", f);
13c31542
TH
678 LIST_FOREACH(device_weights, a, c->io_device_weights)
679 fprintf(f, "IODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
680
681 r = fflush_and_check(f);
682 if (r < 0)
683 return r;
684 unit_write_drop_in_private(u, mode, name, buf);
685 }
686
687 return 1;
688
8e2af478 689 } else if (streq(name, "BlockIOAccounting")) {
718db961 690 int b;
8e2af478 691
718db961
LP
692 r = sd_bus_message_read(message, "b", &b);
693 if (r < 0)
694 return r;
8e2af478
LP
695
696 if (mode != UNIT_CHECK) {
8e2af478 697 c->blockio_accounting = b;
e7ab4d1a 698 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
b27b4b51 699 unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
8e2af478
LP
700 }
701
702 return 1;
b42defe3
LP
703
704 } else if (streq(name, "BlockIOWeight")) {
d53d9474 705 uint64_t weight;
b42defe3 706
d53d9474 707 r = sd_bus_message_read(message, "t", &weight);
718db961
LP
708 if (r < 0)
709 return r;
b42defe3 710
d53d9474
LP
711 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight))
712 return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight value out of range");
b42defe3
LP
713
714 if (mode != UNIT_CHECK) {
d53d9474 715 c->blockio_weight = weight;
e7ab4d1a 716 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
d53d9474
LP
717
718 if (weight == CGROUP_BLKIO_WEIGHT_INVALID)
b27b4b51 719 unit_write_drop_in_private(u, mode, name, "BlockIOWeight=");
d53d9474 720 else
b27b4b51 721 unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%" PRIu64, weight);
b42defe3
LP
722 }
723
724 return 1;
95ae05c0
WC
725
726 } else if (streq(name, "StartupBlockIOWeight")) {
d53d9474 727 uint64_t weight;
95ae05c0 728
d53d9474 729 r = sd_bus_message_read(message, "t", &weight);
95ae05c0
WC
730 if (r < 0)
731 return r;
732
6fb09269 733 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight))
d53d9474 734 return sd_bus_error_set_errnof(error, EINVAL, "StartupBlockIOWeight value out of range");
95ae05c0
WC
735
736 if (mode != UNIT_CHECK) {
d53d9474 737 c->startup_blockio_weight = weight;
e7ab4d1a 738 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
d53d9474
LP
739
740 if (weight == CGROUP_BLKIO_WEIGHT_INVALID)
b27b4b51 741 unit_write_drop_in_private(u, mode, name, "StartupBlockIOWeight=");
d53d9474 742 else
b27b4b51 743 unit_write_drop_in_private_format(u, mode, name, "StartupBlockIOWeight=%" PRIu64, weight);
95ae05c0
WC
744 }
745
746 return 1;
b42defe3 747
cd0a7a8e 748 } else if (STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
718db961 749 const char *path;
f004c2ca 750 bool read = true;
718db961
LP
751 unsigned n = 0;
752 uint64_t u64;
f004c2ca
G
753
754 if (streq(name, "BlockIOWriteBandwidth"))
755 read = false;
756
718db961
LP
757 r = sd_bus_message_enter_container(message, 'a', "(st)");
758 if (r < 0)
759 return r;
f004c2ca 760
718db961 761 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
f004c2ca
G
762
763 if (mode != UNIT_CHECK) {
718db961 764 CGroupBlockIODeviceBandwidth *a = NULL, *b;
f004c2ca
G
765
766 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
979d0311 767 if (path_equal(path, b->path)) {
f004c2ca 768 a = b;
f004c2ca
G
769 break;
770 }
771 }
772
718db961 773 if (!a) {
f004c2ca
G
774 a = new0(CGroupBlockIODeviceBandwidth, 1);
775 if (!a)
776 return -ENOMEM;
777
979d0311
TH
778 a->rbps = CGROUP_LIMIT_MAX;
779 a->wbps = CGROUP_LIMIT_MAX;
f004c2ca
G
780 a->path = strdup(path);
781 if (!a->path) {
782 free(a);
783 return -ENOMEM;
784 }
718db961
LP
785
786 LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
f004c2ca
G
787 }
788
979d0311
TH
789 if (read)
790 a->rbps = u64;
791 else
792 a->wbps = u64;
f004c2ca
G
793 }
794
795 n++;
f004c2ca 796 }
718db961
LP
797 if (r < 0)
798 return r;
f004c2ca 799
9c96019d
LP
800 r = sd_bus_message_exit_container(message);
801 if (r < 0)
802 return r;
803
f004c2ca 804 if (mode != UNIT_CHECK) {
979d0311 805 CGroupBlockIODeviceBandwidth *a;
f004c2ca
G
806 _cleanup_free_ char *buf = NULL;
807 _cleanup_fclose_ FILE *f = NULL;
f004c2ca
G
808 size_t size = 0;
809
810 if (n == 0) {
979d0311
TH
811 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths) {
812 if (read)
813 a->rbps = CGROUP_LIMIT_MAX;
814 else
815 a->wbps = CGROUP_LIMIT_MAX;
816 }
f004c2ca
G
817 }
818
e7ab4d1a 819 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
3051f187 820
f004c2ca
G
821 f = open_memstream(&buf, &size);
822 if (!f)
823 return -ENOMEM;
824
7d6884b6 825 if (read) {
4b61c875 826 fputs_unlocked("BlockIOReadBandwidth=\n", f);
7d6884b6 827 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
979d0311
TH
828 if (a->rbps != CGROUP_LIMIT_MAX)
829 fprintf(f, "BlockIOReadBandwidth=%s %" PRIu64 "\n", a->path, a->rbps);
f004c2ca 830 } else {
4b61c875 831 fputs_unlocked("BlockIOWriteBandwidth=\n", f);
f004c2ca 832 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
979d0311
TH
833 if (a->wbps != CGROUP_LIMIT_MAX)
834 fprintf(f, "BlockIOWriteBandwidth=%s %" PRIu64 "\n", a->path, a->wbps);
f004c2ca
G
835 }
836
1f2f874c
NC
837 r = fflush_and_check(f);
838 if (r < 0)
839 return r;
6f68ecb4
G
840 unit_write_drop_in_private(u, mode, name, buf);
841 }
842
843 return 1;
844
845 } else if (streq(name, "BlockIODeviceWeight")) {
718db961 846 const char *path;
d53d9474 847 uint64_t weight;
6f68ecb4
G
848 unsigned n = 0;
849
718db961
LP
850 r = sd_bus_message_enter_container(message, 'a', "(st)");
851 if (r < 0)
852 return r;
6f68ecb4 853
d53d9474 854 while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
6f68ecb4 855
d53d9474 856 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight) || weight == CGROUP_BLKIO_WEIGHT_INVALID)
718db961 857 return sd_bus_error_set_errnof(error, EINVAL, "BlockIODeviceWeight out of range");
6f68ecb4
G
858
859 if (mode != UNIT_CHECK) {
718db961 860 CGroupBlockIODeviceWeight *a = NULL, *b;
6f68ecb4
G
861
862 LIST_FOREACH(device_weights, b, c->blockio_device_weights) {
863 if (path_equal(b->path, path)) {
864 a = b;
6f68ecb4
G
865 break;
866 }
867 }
868
718db961 869 if (!a) {
6f68ecb4
G
870 a = new0(CGroupBlockIODeviceWeight, 1);
871 if (!a)
872 return -ENOMEM;
873
874 a->path = strdup(path);
875 if (!a->path) {
876 free(a);
877 return -ENOMEM;
878 }
718db961 879 LIST_PREPEND(device_weights,c->blockio_device_weights, a);
6f68ecb4
G
880 }
881
d53d9474 882 a->weight = weight;
6f68ecb4
G
883 }
884
885 n++;
6f68ecb4
G
886 }
887
9c96019d
LP
888 r = sd_bus_message_exit_container(message);
889 if (r < 0)
890 return r;
891
6f68ecb4
G
892 if (mode != UNIT_CHECK) {
893 _cleanup_free_ char *buf = NULL;
894 _cleanup_fclose_ FILE *f = NULL;
895 CGroupBlockIODeviceWeight *a;
896 size_t size = 0;
897
898 if (n == 0) {
899 while (c->blockio_device_weights)
900 cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
901 }
902
e7ab4d1a 903 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
3051f187 904
6f68ecb4
G
905 f = open_memstream(&buf, &size);
906 if (!f)
907 return -ENOMEM;
908
4b61c875 909 fputs_unlocked("BlockIODeviceWeight=\n", f);
6f68ecb4 910 LIST_FOREACH(device_weights, a, c->blockio_device_weights)
d53d9474 911 fprintf(f, "BlockIODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
6f68ecb4 912
1f2f874c
NC
913 r = fflush_and_check(f);
914 if (r < 0)
915 return r;
f004c2ca
G
916 unit_write_drop_in_private(u, mode, name, buf);
917 }
918
919 return 1;
920
8e2af478 921 } else if (streq(name, "MemoryAccounting")) {
718db961 922 int b;
8e2af478 923
718db961
LP
924 r = sd_bus_message_read(message, "b", &b);
925 if (r < 0)
926 return r;
8e2af478
LP
927
928 if (mode != UNIT_CHECK) {
b42defe3 929 c->memory_accounting = b;
e7ab4d1a 930 unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
b27b4b51 931 unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes" : "MemoryAccounting=no");
8e2af478
LP
932 }
933
934 return 1;
8e2af478 935
96e131ea 936 } else if (STR_IN_SET(name, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax")) {
da4d897e
TH
937 uint64_t v;
938
939 r = sd_bus_message_read(message, "t", &v);
940 if (r < 0)
941 return r;
cd0a7a8e
LP
942 if (v <= 0)
943 return sd_bus_error_set_errnof(error, EINVAL, "%s= is too small", name);
da4d897e
TH
944
945 if (mode != UNIT_CHECK) {
946 if (streq(name, "MemoryLow"))
947 c->memory_low = v;
948 else if (streq(name, "MemoryHigh"))
949 c->memory_high = v;
96e131ea
WC
950 else if (streq(name, "MemorySwapMax"))
951 c->memory_swap_max = v;
da4d897e
TH
952 else
953 c->memory_max = v;
954
955 unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
956
957 if (v == CGROUP_LIMIT_MAX)
799ec134 958 unit_write_drop_in_private_format(u, mode, name, "%s=infinity", name);
da4d897e 959 else
b27b4b51 960 unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64, name, v);
da4d897e
TH
961 }
962
963 return 1;
964
f7903e8d 965 } else if (STR_IN_SET(name, "MemoryLowScale", "MemoryHighScale", "MemoryMaxScale")) {
d58d600e
LP
966 uint32_t raw;
967 uint64_t v;
968
969 r = sd_bus_message_read(message, "u", &raw);
970 if (r < 0)
971 return r;
972
973 v = physical_memory_scale(raw, UINT32_MAX);
974 if (v <= 0 || v == UINT64_MAX)
975 return sd_bus_error_set_errnof(error, EINVAL, "%s= is out of range", name);
976
977 if (mode != UNIT_CHECK) {
978 const char *e;
979
980 /* Chop off suffix */
f7903e8d 981 assert_se(e = endswith(name, "Scale"));
d58d600e
LP
982 name = strndupa(name, e - name);
983
984 if (streq(name, "MemoryLow"))
985 c->memory_low = v;
986 else if (streq(name, "MemoryHigh"))
987 c->memory_high = v;
988 else
989 c->memory_max = v;
990
991 unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
f7903e8d
LP
992 unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu32 "%%", name,
993 (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
d58d600e
LP
994 }
995
996 return 1;
997
ddca82ac 998 } else if (streq(name, "MemoryLimit")) {
718db961 999 uint64_t limit;
b42defe3 1000
718db961
LP
1001 r = sd_bus_message_read(message, "t", &limit);
1002 if (r < 0)
1003 return r;
cd0a7a8e
LP
1004 if (limit <= 0)
1005 return sd_bus_error_set_errnof(error, EINVAL, "%s= is too small", name);
b42defe3
LP
1006
1007 if (mode != UNIT_CHECK) {
ddca82ac 1008 c->memory_limit = limit;
e7ab4d1a 1009 unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
03a7b521
LP
1010
1011 if (limit == (uint64_t) -1)
b27b4b51 1012 unit_write_drop_in_private(u, mode, name, "MemoryLimit=infinity");
03a7b521 1013 else
b27b4b51 1014 unit_write_drop_in_private_format(u, mode, name, "MemoryLimit=%" PRIu64, limit);
b42defe3
LP
1015 }
1016
7041efe9
LP
1017 return 1;
1018
f7903e8d 1019 } else if (streq(name, "MemoryLimitScale")) {
d58d600e
LP
1020 uint64_t limit;
1021 uint32_t raw;
1022
1023 r = sd_bus_message_read(message, "u", &raw);
1024 if (r < 0)
1025 return r;
1026
1027 limit = physical_memory_scale(raw, UINT32_MAX);
1028 if (limit <= 0 || limit == UINT64_MAX)
1029 return sd_bus_error_set_errnof(error, EINVAL, "%s= is out of range", name);
1030
1031 if (mode != UNIT_CHECK) {
1032 c->memory_limit = limit;
1033 unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
f7903e8d
LP
1034 unit_write_drop_in_private_format(u, mode, "MemoryLimit", "MemoryLimit=%" PRIu32 "%%",
1035 (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
d58d600e
LP
1036 }
1037
1038 return 1;
1039
7041efe9
LP
1040 } else if (streq(name, "DevicePolicy")) {
1041 const char *policy;
1042 CGroupDevicePolicy p;
1043
718db961
LP
1044 r = sd_bus_message_read(message, "s", &policy);
1045 if (r < 0)
1046 return r;
7041efe9 1047
7041efe9
LP
1048 p = cgroup_device_policy_from_string(policy);
1049 if (p < 0)
1050 return -EINVAL;
1051
1052 if (mode != UNIT_CHECK) {
7041efe9 1053 c->device_policy = p;
e7ab4d1a 1054 unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
b27b4b51 1055 unit_write_drop_in_private_format(u, mode, name, "DevicePolicy=%s", policy);
7041efe9
LP
1056 }
1057
1058 return 1;
1059
1060 } else if (streq(name, "DeviceAllow")) {
718db961 1061 const char *path, *rwm;
7041efe9
LP
1062 unsigned n = 0;
1063
718db961
LP
1064 r = sd_bus_message_enter_container(message, 'a', "(ss)");
1065 if (r < 0)
1066 return r;
7041efe9 1067
718db961 1068 while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
7041efe9 1069
27458ed6
LP
1070 if ((!path_startswith(path, "/dev/") &&
1071 !path_startswith(path, "/run/systemd/inaccessible/") &&
90060676
LP
1072 !startswith(path, "block-") &&
1073 !startswith(path, "char-")) ||
1074 strpbrk(path, WHITESPACE))
1075 return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires device node");
7041efe9
LP
1076
1077 if (isempty(rwm))
1078 rwm = "rwm";
1079
718db961
LP
1080 if (!in_charset(rwm, "rwm"))
1081 return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires combination of rwm flags");
7041efe9 1082
7041efe9 1083 if (mode != UNIT_CHECK) {
718db961 1084 CGroupDeviceAllow *a = NULL, *b;
ad7bfffd
G
1085
1086 LIST_FOREACH(device_allow, b, c->device_allow) {
06eb4e3b 1087 if (path_equal(b->path, path)) {
ad7bfffd 1088 a = b;
ad7bfffd
G
1089 break;
1090 }
1091 }
1092
718db961 1093 if (!a) {
ad7bfffd
G
1094 a = new0(CGroupDeviceAllow, 1);
1095 if (!a)
1096 return -ENOMEM;
1097
1098 a->path = strdup(path);
1099 if (!a->path) {
1100 free(a);
1101 return -ENOMEM;
1102 }
718db961
LP
1103
1104 LIST_PREPEND(device_allow, c->device_allow, a);
7041efe9
LP
1105 }
1106
1107 a->r = !!strchr(rwm, 'r');
1108 a->w = !!strchr(rwm, 'w');
1109 a->m = !!strchr(rwm, 'm');
7041efe9
LP
1110 }
1111
c2756a68 1112 n++;
7041efe9 1113 }
43a99a7a
LP
1114 if (r < 0)
1115 return r;
7041efe9 1116
9c96019d
LP
1117 r = sd_bus_message_exit_container(message);
1118 if (r < 0)
1119 return r;
1120
7041efe9
LP
1121 if (mode != UNIT_CHECK) {
1122 _cleanup_free_ char *buf = NULL;
1123 _cleanup_fclose_ FILE *f = NULL;
1124 CGroupDeviceAllow *a;
1125 size_t size = 0;
1126
1127 if (n == 0) {
1128 while (c->device_allow)
1129 cgroup_context_free_device_allow(c, c->device_allow);
1130 }
1131
e7ab4d1a 1132 unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
3051f187 1133
7041efe9
LP
1134 f = open_memstream(&buf, &size);
1135 if (!f)
1136 return -ENOMEM;
1137
4b61c875 1138 fputs_unlocked("DeviceAllow=\n", f);
7041efe9
LP
1139 LIST_FOREACH(device_allow, a, c->device_allow)
1140 fprintf(f, "DeviceAllow=%s %s%s%s\n", a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
1141
1f2f874c
NC
1142 r = fflush_and_check(f);
1143 if (r < 0)
1144 return r;
b9ec9359 1145 unit_write_drop_in_private(u, mode, name, buf);
7041efe9
LP
1146 }
1147
b42defe3 1148 return 1;
a931ad47 1149
03a7b521
LP
1150 } else if (streq(name, "TasksAccounting")) {
1151 int b;
1152
1153 r = sd_bus_message_read(message, "b", &b);
1154 if (r < 0)
1155 return r;
1156
1157 if (mode != UNIT_CHECK) {
1158 c->tasks_accounting = b;
e7ab4d1a 1159 unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
b27b4b51 1160 unit_write_drop_in_private(u, mode, name, b ? "TasksAccounting=yes" : "TasksAccounting=no");
03a7b521
LP
1161 }
1162
1163 return 1;
1164
1165 } else if (streq(name, "TasksMax")) {
1166 uint64_t limit;
1167
1168 r = sd_bus_message_read(message, "t", &limit);
1169 if (r < 0)
1170 return r;
83f8e808
LP
1171 if (limit <= 0)
1172 return sd_bus_error_set_errnof(error, EINVAL, "%s= is too small", name);
03a7b521
LP
1173
1174 if (mode != UNIT_CHECK) {
1175 c->tasks_max = limit;
e7ab4d1a 1176 unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
03a7b521
LP
1177
1178 if (limit == (uint64_t) -1)
b27b4b51 1179 unit_write_drop_in_private(u, mode, name, "TasksMax=infinity");
03a7b521 1180 else
b27b4b51 1181 unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu64, limit);
03a7b521
LP
1182 }
1183
83f8e808 1184 return 1;
3dc5ca97 1185
83f8e808
LP
1186 } else if (streq(name, "TasksMaxScale")) {
1187 uint64_t limit;
1188 uint32_t raw;
1189
1190 r = sd_bus_message_read(message, "u", &raw);
1191 if (r < 0)
1192 return r;
1193
1194 limit = system_tasks_max_scale(raw, UINT32_MAX);
1195 if (limit <= 0 || limit >= UINT64_MAX)
1196 return sd_bus_error_set_errnof(error, EINVAL, "%s= is out of range", name);
1197
1198 if (mode != UNIT_CHECK) {
1199 c->tasks_max = limit;
1200 unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
1201 unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu32 "%%",
1202 (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
1203 }
1204
3dc5ca97
LP
1205 return 1;
1206
1207 } else if (streq(name, "IPAccounting")) {
1208 int b;
1209
1210 r = sd_bus_message_read(message, "b", &b);
1211 if (r < 0)
1212 return r;
1213
1214 if (mode != UNIT_CHECK) {
1215 c->ip_accounting = b;
1216
1217 unit_invalidate_cgroup_bpf(u);
1218 unit_write_drop_in_private(u, mode, name, b ? "IPAccounting=yes" : "IPAccounting=no");
1219 }
1220
1221 return 1;
1222
1223 } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) {
1224 IPAddressAccessItem **list;
1225 size_t n = 0;
1226
1227 list = streq(name, "IPAddressAllow") ? &c->ip_address_allow : &c->ip_address_deny;
1228
1229 r = sd_bus_message_enter_container(message, 'a', "(iayu)");
1230 if (r < 0)
1231 return r;
1232
1233 for (;;) {
1234 const void *ap;
1235 int32_t family;
1236 uint32_t prefixlen;
1237 size_t an;
1238
1239 r = sd_bus_message_enter_container(message, 'r', "iayu");
1240 if (r < 0)
1241 return r;
1242 if (r == 0)
1243 break;
1244
1245 r = sd_bus_message_read(message, "i", &family);
1246 if (r < 0)
1247 return r;
1248
1249 if (!IN_SET(family, AF_INET, AF_INET6))
4fe66c86 1250 return sd_bus_error_set_errnof(error, EINVAL, "%s= expects IPv4 or IPv6 addresses only.", name);
3dc5ca97
LP
1251
1252 r = sd_bus_message_read_array(message, 'y', &ap, &an);
1253 if (r < 0)
1254 return r;
1255
1256 if (an != FAMILY_ADDRESS_SIZE(family))
1257 return sd_bus_error_set_errnof(error, EINVAL, "IP address has wrong size for family (%s, expected %zu, got %zu)",
1258 af_to_name(family), FAMILY_ADDRESS_SIZE(family), an);
1259
1260 r = sd_bus_message_read(message, "u", &prefixlen);
1261 if (r < 0)
1262 return r;
1263
1264 if (prefixlen > FAMILY_ADDRESS_SIZE(family)*8)
4fe66c86 1265 return sd_bus_error_set_errnof(error, EINVAL, "Prefix length %" PRIu32 " too large for address family %s.", prefixlen, af_to_name(family));
3dc5ca97
LP
1266
1267 if (mode != UNIT_CHECK) {
1268 IPAddressAccessItem *item;
1269
1270 item = new0(IPAddressAccessItem, 1);
1271 if (!item)
1272 return -ENOMEM;
1273
1274 item->family = family;
1275 item->prefixlen = prefixlen;
1276 memcpy(&item->address, ap, an);
1277
1278 LIST_PREPEND(items, *list, item);
1279 }
1280
1281 r = sd_bus_message_exit_container(message);
1282 if (r < 0)
1283 return r;
1284
1285 n++;
1286 }
1287
1288 r = sd_bus_message_exit_container(message);
1289 if (r < 0)
1290 return r;
1291
1274b6c6
LP
1292 *list = ip_address_access_reduce(*list);
1293
3dc5ca97
LP
1294 if (mode != UNIT_CHECK) {
1295 _cleanup_free_ char *buf = NULL;
1296 _cleanup_fclose_ FILE *f = NULL;
1297 IPAddressAccessItem *item;
1298 size_t size = 0;
1299
1300 if (n == 0)
1301 *list = ip_address_access_free_all(*list);
1302
1303 unit_invalidate_cgroup_bpf(u);
1304 f = open_memstream(&buf, &size);
1305 if (!f)
1306 return -ENOMEM;
1307
1308 fputs_unlocked(name, f);
1309 fputs_unlocked("=\n", f);
1310
1311 LIST_FOREACH(items, item, *list) {
1312 char buffer[CONST_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
1313
1314 errno = 0;
1315 if (!inet_ntop(item->family, &item->address, buffer, sizeof(buffer)))
1316 return errno > 0 ? -errno : -EINVAL;
1317
1318 fprintf(f, "%s=%s/%u\n", name, buffer, item->prefixlen);
1319 }
1320
1321 r = fflush_and_check(f);
1322 if (r < 0)
1323 return r;
1324 unit_write_drop_in_private(u, mode, name, buf);
078ba556
LP
1325
1326 if (*list) {
1327 r = bpf_firewall_supported();
1328 if (r < 0)
1329 return r;
1330 if (r == 0)
1331 log_warning("Transient unit %s configures an IP firewall, but the local system does not support BPF/cgroup firewalling.\n"
1332 "Proceeding WITHOUT firewalling in effect!", u->id);
1333 }
3dc5ca97
LP
1334 }
1335
03a7b521 1336 return 1;
a931ad47
LP
1337 }
1338
1339 if (u->transient && u->load_state == UNIT_STUB) {
1340 r = bus_cgroup_set_transient_property(u, c, name, message, mode, error);
1341 if (r != 0)
1342 return r;
1343
b42defe3 1344 }
8e2af478
LP
1345
1346 return 0;
1347}