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