chiark / gitweb /
fix spelling of privilege
[elogind.git] / src / core / load-fragment.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7   Copyright 2012 Holger Hans Peter Freyther
8
9   systemd is free software; you can redistribute it and/or modify it
10   under the terms of the GNU Lesser General Public License as published by
11   the Free Software Foundation; either version 2.1 of the License, or
12   (at your option) any later version.
13
14   systemd is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <linux/oom.h>
24 #include <assert.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <sched.h>
30 #include <sys/prctl.h>
31 #include <sys/mount.h>
32 #include <linux/fs.h>
33 #include <sys/stat.h>
34 #include <sys/time.h>
35 #include <sys/resource.h>
36 #include <sys/types.h>
37 #include <grp.h>
38
39 #ifdef HAVE_SECCOMP
40 #include <seccomp.h>
41 #endif
42
43 #include "sd-messages.h"
44 #include "unit.h"
45 #include "strv.h"
46 #include "conf-parser.h"
47 #include "load-fragment.h"
48 #include "log.h"
49 #include "ioprio.h"
50 #include "securebits.h"
51 #include "missing.h"
52 #include "unit-name.h"
53 #include "unit-printf.h"
54 #include "utf8.h"
55 #include "path-util.h"
56 #include "env-util.h"
57 #include "cgroup.h"
58 #include "bus-util.h"
59 #include "bus-error.h"
60 #include "errno-list.h"
61 #include "af-list.h"
62
63 #ifdef HAVE_SECCOMP
64 #include "seccomp-util.h"
65 #endif
66
67 #if !defined(HAVE_SYSV_COMPAT) || !defined(HAVE_SECCOMP) || !defined(HAVE_PAM) || !defined(HAVE_SELINUX) || !defined(HAVE_SMACK) || !defined(HAVE_APPARMOR)
68 int config_parse_warn_compat(
69                 const char *unit,
70                 const char *filename,
71                 unsigned line,
72                 const char *section,
73                 unsigned section_line,
74                 const char *lvalue,
75                 int ltype,
76                 const char *rvalue,
77                 void *data,
78                 void *userdata) {
79
80         log_syntax(unit, LOG_DEBUG, filename, line, EINVAL,
81                    "Support for option %s= has been disabled at compile time and is ignored",
82                    lvalue);
83         return 0;
84 }
85 #endif
86
87 int config_parse_unit_deps(const char* unit,
88                            const char *filename,
89                            unsigned line,
90                            const char *section,
91                            unsigned section_line,
92                            const char *lvalue,
93                            int ltype,
94                            const char *rvalue,
95                            void *data,
96                            void *userdata) {
97
98         UnitDependency d = ltype;
99         Unit *u = userdata;
100         char *w, *state;
101         size_t l;
102
103         assert(filename);
104         assert(lvalue);
105         assert(rvalue);
106
107         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
108                 _cleanup_free_ char *t = NULL, *k = NULL;
109                 int r;
110
111                 t = strndup(w, l);
112                 if (!t)
113                         return log_oom();
114
115                 r = unit_name_printf(u, t, &k);
116                 if (r < 0) {
117                         log_syntax(unit, LOG_ERR, filename, line, -r,
118                                    "Failed to resolve specifiers, ignoring: %s", strerror(-r));
119                         continue;
120                 }
121
122                 r = unit_add_dependency_by_name(u, d, k, NULL, true);
123                 if (r < 0)
124                         log_syntax(unit, LOG_ERR, filename, line, -r,
125                                    "Failed to add dependency on %s, ignoring: %s", k, strerror(-r));
126         }
127
128         return 0;
129 }
130
131 int config_parse_unit_string_printf(const char *unit,
132                                     const char *filename,
133                                     unsigned line,
134                                     const char *section,
135                                     unsigned section_line,
136                                     const char *lvalue,
137                                     int ltype,
138                                     const char *rvalue,
139                                     void *data,
140                                     void *userdata) {
141
142         Unit *u = userdata;
143         _cleanup_free_ char *k = NULL;
144         int r;
145
146         assert(filename);
147         assert(lvalue);
148         assert(rvalue);
149         assert(u);
150
151         r = unit_full_printf(u, rvalue, &k);
152         if (r < 0)
153                 log_syntax(unit, LOG_ERR, filename, line, -r,
154                            "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
155
156         return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype,
157                                    k ? k : rvalue, data, userdata);
158 }
159
160 int config_parse_unit_strv_printf(const char *unit,
161                                   const char *filename,
162                                   unsigned line,
163                                   const char *section,
164                                   unsigned section_line,
165                                   const char *lvalue,
166                                   int ltype,
167                                   const char *rvalue,
168                                   void *data,
169                                   void *userdata) {
170
171         Unit *u = userdata;
172         _cleanup_free_ char *k = NULL;
173         int r;
174
175         assert(filename);
176         assert(lvalue);
177         assert(rvalue);
178         assert(u);
179
180         r = unit_full_printf(u, rvalue, &k);
181         if (r < 0)
182                 log_syntax(unit, LOG_ERR, filename, line, -r,
183                            "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
184
185         return config_parse_strv(unit, filename, line, section, section_line, lvalue, ltype,
186                                  k ? k : rvalue, data, userdata);
187 }
188
189 int config_parse_unit_path_printf(const char *unit,
190                                   const char *filename,
191                                   unsigned line,
192                                   const char *section,
193                                   unsigned section_line,
194                                   const char *lvalue,
195                                   int ltype,
196                                   const char *rvalue,
197                                   void *data,
198                                   void *userdata) {
199
200         Unit *u = userdata;
201         _cleanup_free_ char *k = NULL;
202         int r;
203
204         assert(filename);
205         assert(lvalue);
206         assert(rvalue);
207         assert(u);
208
209         r = unit_full_printf(u, rvalue, &k);
210         if (r < 0)
211                 log_syntax(unit, LOG_ERR, filename, line, -r,
212                            "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
213
214         return config_parse_path(unit, filename, line, section, section_line, lvalue, ltype,
215                                  k ? k : rvalue, data, userdata);
216 }
217
218 int config_parse_socket_listen(const char *unit,
219                                const char *filename,
220                                unsigned line,
221                                const char *section,
222                                unsigned section_line,
223                                const char *lvalue,
224                                int ltype,
225                                const char *rvalue,
226                                void *data,
227                                void *userdata) {
228
229         SocketPort *p, *tail;
230         Socket *s;
231         int r;
232
233         assert(filename);
234         assert(lvalue);
235         assert(rvalue);
236         assert(data);
237
238         s = SOCKET(data);
239
240         if (isempty(rvalue)) {
241                 /* An empty assignment removes all ports */
242                 socket_free_ports(s);
243                 return 0;
244         }
245
246         p = new0(SocketPort, 1);
247         if (!p)
248                 return log_oom();
249
250         if (ltype != SOCKET_SOCKET) {
251
252                 p->type = ltype;
253                 r = unit_full_printf(UNIT(s), rvalue, &p->path);
254                 if (r < 0) {
255                         p->path = strdup(rvalue);
256                         if (!p->path) {
257                                 free(p);
258                                 return log_oom();
259                         } else
260                                 log_syntax(unit, LOG_ERR, filename, line, -r,
261                                            "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
262                 }
263
264                 path_kill_slashes(p->path);
265
266         } else if (streq(lvalue, "ListenNetlink")) {
267                 _cleanup_free_ char  *k = NULL;
268
269                 p->type = SOCKET_SOCKET;
270                 r = unit_full_printf(UNIT(s), rvalue, &k);
271                 if (r < 0)
272                         log_syntax(unit, LOG_ERR, filename, line, -r,
273                                    "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
274
275                 r = socket_address_parse_netlink(&p->address, k ? k : rvalue);
276                 if (r < 0) {
277                         log_syntax(unit, LOG_ERR, filename, line, -r,
278                                    "Failed to parse address value, ignoring: %s", rvalue);
279                         free(p);
280                         return 0;
281                 }
282
283         } else {
284                 _cleanup_free_ char *k = NULL;
285
286                 p->type = SOCKET_SOCKET;
287                 r = unit_full_printf(UNIT(s), rvalue, &k);
288                 if (r < 0)
289                         log_syntax(unit, LOG_ERR, filename, line, -r,
290                                    "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
291
292                 r = socket_address_parse(&p->address, k ? k : rvalue);
293                 if (r < 0) {
294                         log_syntax(unit, LOG_ERR, filename, line, -r,
295                                    "Failed to parse address value, ignoring: %s", rvalue);
296                         free(p);
297                         return 0;
298                 }
299
300                 if (streq(lvalue, "ListenStream"))
301                         p->address.type = SOCK_STREAM;
302                 else if (streq(lvalue, "ListenDatagram"))
303                         p->address.type = SOCK_DGRAM;
304                 else {
305                         assert(streq(lvalue, "ListenSequentialPacket"));
306                         p->address.type = SOCK_SEQPACKET;
307                 }
308
309                 if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
310                         log_syntax(unit, LOG_ERR, filename, line, ENOTSUP,
311                                    "Address family not supported, ignoring: %s", rvalue);
312                         free(p);
313                         return 0;
314                 }
315         }
316
317         p->fd = -1;
318         p->socket = s;
319
320         if (s->ports) {
321                 LIST_FIND_TAIL(port, s->ports, tail);
322                 LIST_INSERT_AFTER(port, s->ports, tail, p);
323         } else
324                 LIST_PREPEND(port, s->ports, p);
325
326         return 0;
327 }
328
329 int config_parse_socket_bind(const char *unit,
330                              const char *filename,
331                              unsigned line,
332                              const char *section,
333                              unsigned section_line,
334                              const char *lvalue,
335                              int ltype,
336                              const char *rvalue,
337                              void *data,
338                              void *userdata) {
339
340         Socket *s;
341         SocketAddressBindIPv6Only b;
342
343         assert(filename);
344         assert(lvalue);
345         assert(rvalue);
346         assert(data);
347
348         s = SOCKET(data);
349
350         b = socket_address_bind_ipv6_only_from_string(rvalue);
351         if (b < 0) {
352                 int r;
353
354                 r = parse_boolean(rvalue);
355                 if (r < 0) {
356                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
357                                    "Failed to parse bind IPv6 only value, ignoring: %s", rvalue);
358                         return 0;
359                 }
360
361                 s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
362         } else
363                 s->bind_ipv6_only = b;
364
365         return 0;
366 }
367
368 int config_parse_exec_nice(const char *unit,
369                            const char *filename,
370                            unsigned line,
371                            const char *section,
372                            unsigned section_line,
373                            const char *lvalue,
374                            int ltype,
375                            const char *rvalue,
376                            void *data,
377                            void *userdata) {
378
379         ExecContext *c = data;
380         int priority, r;
381
382         assert(filename);
383         assert(lvalue);
384         assert(rvalue);
385         assert(data);
386
387         r = safe_atoi(rvalue, &priority);
388         if (r < 0) {
389                 log_syntax(unit, LOG_ERR, filename, line, -r,
390                            "Failed to parse nice priority, ignoring: %s. ", rvalue);
391                 return 0;
392         }
393
394         if (priority < PRIO_MIN || priority >= PRIO_MAX) {
395                 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
396                            "Nice priority out of range, ignoring: %s", rvalue);
397                 return 0;
398         }
399
400         c->nice = priority;
401         c->nice_set = true;
402
403         return 0;
404 }
405
406 int config_parse_exec_oom_score_adjust(const char* unit,
407                                        const char *filename,
408                                        unsigned line,
409                                        const char *section,
410                                        unsigned section_line,
411                                        const char *lvalue,
412                                        int ltype,
413                                        const char *rvalue,
414                                        void *data,
415                                        void *userdata) {
416
417         ExecContext *c = data;
418         int oa, r;
419
420         assert(filename);
421         assert(lvalue);
422         assert(rvalue);
423         assert(data);
424
425         r = safe_atoi(rvalue, &oa);
426         if (r < 0) {
427                 log_syntax(unit, LOG_ERR, filename, line, -r,
428                            "Failed to parse the OOM score adjust value, ignoring: %s", rvalue);
429                 return 0;
430         }
431
432         if (oa < OOM_SCORE_ADJ_MIN || oa > OOM_SCORE_ADJ_MAX) {
433                 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
434                            "OOM score adjust value out of range, ignoring: %s", rvalue);
435                 return 0;
436         }
437
438         c->oom_score_adjust = oa;
439         c->oom_score_adjust_set = true;
440
441         return 0;
442 }
443
444 int config_parse_exec(const char *unit,
445                       const char *filename,
446                       unsigned line,
447                       const char *section,
448                       unsigned section_line,
449                       const char *lvalue,
450                       int ltype,
451                       const char *rvalue,
452                       void *data,
453                       void *userdata) {
454
455         ExecCommand **e = data, *nce;
456         char *path, **n;
457         unsigned k;
458         int r;
459
460         assert(filename);
461         assert(lvalue);
462         assert(rvalue);
463         assert(e);
464
465         e += ltype;
466
467         if (isempty(rvalue)) {
468                 /* An empty assignment resets the list */
469                 exec_command_free_list(*e);
470                 *e = NULL;
471                 return 0;
472         }
473
474         /* We accept an absolute path as first argument, or
475          * alternatively an absolute prefixed with @ to allow
476          * overriding of argv[0]. */
477         for (;;) {
478                 int i;
479                 char *w;
480                 size_t l;
481                 char *state;
482                 bool honour_argv0 = false, ignore = false;
483
484                 path = NULL;
485                 nce = NULL;
486                 n = NULL;
487
488                 rvalue += strspn(rvalue, WHITESPACE);
489
490                 if (rvalue[0] == 0)
491                         break;
492
493                 for (i = 0; i < 2; i++) {
494                         if (rvalue[0] == '-' && !ignore) {
495                                 ignore = true;
496                                 rvalue ++;
497                         }
498
499                         if (rvalue[0] == '@' && !honour_argv0) {
500                                 honour_argv0 = true;
501                                 rvalue ++;
502                         }
503                 }
504
505                 if (*rvalue != '/') {
506                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
507                                    "Executable path is not absolute, ignoring: %s", rvalue);
508                         return 0;
509                 }
510
511                 k = 0;
512                 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
513                         if (strneq(w, ";", MAX(l, 1U)))
514                                 break;
515
516                         k++;
517                 }
518
519                 n = new(char*, k + !honour_argv0);
520                 if (!n)
521                         return log_oom();
522
523                 k = 0;
524                 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
525                         if (strneq(w, ";", MAX(l, 1U)))
526                                 break;
527                         else if (strneq(w, "\\;", MAX(l, 1U)))
528                                 w ++;
529
530                         if (honour_argv0 && w == rvalue) {
531                                 assert(!path);
532
533                                 path = strndup(w, l);
534                                 if (!path) {
535                                         r = log_oom();
536                                         goto fail;
537                                 }
538
539                                 if (!utf8_is_valid(path)) {
540                                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
541                                         r = 0;
542                                         goto fail;
543                                 }
544
545                         } else {
546                                 char *c;
547
548                                 c = n[k++] = cunescape_length(w, l);
549                                 if (!c) {
550                                         r = log_oom();
551                                         goto fail;
552                                 }
553
554                                 if (!utf8_is_valid(c)) {
555                                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
556                                         r = 0;
557                                         goto fail;
558                                 }
559                         }
560                 }
561
562                 n[k] = NULL;
563
564                 if (!n[0]) {
565                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
566                                    "Invalid command line, ignoring: %s", rvalue);
567                         r = 0;
568                         goto fail;
569                 }
570
571                 if (!path) {
572                         path = strdup(n[0]);
573                         if (!path) {
574                                 r = log_oom();
575                                 goto fail;
576                         }
577                 }
578
579                 assert(path_is_absolute(path));
580
581                 nce = new0(ExecCommand, 1);
582                 if (!nce) {
583                         r = log_oom();
584                         goto fail;
585                 }
586
587                 nce->argv = n;
588                 nce->path = path;
589                 nce->ignore = ignore;
590
591                 path_kill_slashes(nce->path);
592
593                 exec_command_append_list(e, nce);
594
595                 rvalue = state;
596         }
597
598         return 0;
599
600 fail:
601         n[k] = NULL;
602         strv_free(n);
603         free(path);
604         free(nce);
605
606         return r;
607 }
608
609 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
610 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
611
612 int config_parse_socket_bindtodevice(const char* unit,
613                                      const char *filename,
614                                      unsigned line,
615                                      const char *section,
616                                      unsigned section_line,
617                                      const char *lvalue,
618                                      int ltype,
619                                      const char *rvalue,
620                                      void *data,
621                                      void *userdata) {
622
623         Socket *s = data;
624         char *n;
625
626         assert(filename);
627         assert(lvalue);
628         assert(rvalue);
629         assert(data);
630
631         if (rvalue[0] && !streq(rvalue, "*")) {
632                 n = strdup(rvalue);
633                 if (!n)
634                         return log_oom();
635         } else
636                 n = NULL;
637
638         free(s->bind_to_device);
639         s->bind_to_device = n;
640
641         return 0;
642 }
643
644 DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier");
645 DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier");
646
647 int config_parse_exec_io_class(const char *unit,
648                                const char *filename,
649                                unsigned line,
650                                const char *section,
651                                unsigned section_line,
652                                const char *lvalue,
653                                int ltype,
654                                const char *rvalue,
655                                void *data,
656                                void *userdata) {
657
658         ExecContext *c = data;
659         int x;
660
661         assert(filename);
662         assert(lvalue);
663         assert(rvalue);
664         assert(data);
665
666         x = ioprio_class_from_string(rvalue);
667         if (x < 0) {
668                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
669                            "Failed to parse IO scheduling class, ignoring: %s", rvalue);
670                 return 0;
671         }
672
673         c->ioprio = IOPRIO_PRIO_VALUE(x, IOPRIO_PRIO_DATA(c->ioprio));
674         c->ioprio_set = true;
675
676         return 0;
677 }
678
679 int config_parse_exec_io_priority(const char *unit,
680                                   const char *filename,
681                                   unsigned line,
682                                   const char *section,
683                                   unsigned section_line,
684                                   const char *lvalue,
685                                   int ltype,
686                                   const char *rvalue,
687                                   void *data,
688                                   void *userdata) {
689
690         ExecContext *c = data;
691         int i, r;
692
693         assert(filename);
694         assert(lvalue);
695         assert(rvalue);
696         assert(data);
697
698         r = safe_atoi(rvalue, &i);
699         if (r < 0 || i < 0 || i >= IOPRIO_BE_NR) {
700                 log_syntax(unit, LOG_ERR, filename, line, -r,
701                            "Failed to parse IO priority, ignoring: %s", rvalue);
702                 return 0;
703         }
704
705         c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i);
706         c->ioprio_set = true;
707
708         return 0;
709 }
710
711 int config_parse_exec_cpu_sched_policy(const char *unit,
712                                        const char *filename,
713                                        unsigned line,
714                                        const char *section,
715                                        unsigned section_line,
716                                        const char *lvalue,
717                                        int ltype,
718                                        const char *rvalue,
719                                        void *data,
720                                        void *userdata) {
721
722
723         ExecContext *c = data;
724         int x;
725
726         assert(filename);
727         assert(lvalue);
728         assert(rvalue);
729         assert(data);
730
731         x = sched_policy_from_string(rvalue);
732         if (x < 0) {
733                 log_syntax(unit, LOG_ERR, filename, line, -x,
734                            "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
735                 return 0;
736         }
737
738         c->cpu_sched_policy = x;
739         /* Moving to or from real-time policy? We need to adjust the priority */
740         c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(x), sched_get_priority_max(x));
741         c->cpu_sched_set = true;
742
743         return 0;
744 }
745
746 int config_parse_exec_cpu_sched_prio(const char *unit,
747                                      const char *filename,
748                                      unsigned line,
749                                      const char *section,
750                                      unsigned section_line,
751                                      const char *lvalue,
752                                      int ltype,
753                                      const char *rvalue,
754                                      void *data,
755                                      void *userdata) {
756
757         ExecContext *c = data;
758         int i, min, max, r;
759
760         assert(filename);
761         assert(lvalue);
762         assert(rvalue);
763         assert(data);
764
765         r = safe_atoi(rvalue, &i);
766         if (r < 0) {
767                 log_syntax(unit, LOG_ERR, filename, line, -r,
768                            "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
769                 return 0;
770         }
771
772         /* On Linux RR/FIFO range from 1 to 99 and OTHER/BATCH may only be 0 */
773         min = sched_get_priority_min(c->cpu_sched_policy);
774         max = sched_get_priority_max(c->cpu_sched_policy);
775
776         if (i < min || i > max) {
777                 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
778                            "CPU scheduling priority is out of range, ignoring: %s", rvalue);
779                 return 0;
780         }
781
782         c->cpu_sched_priority = i;
783         c->cpu_sched_set = true;
784
785         return 0;
786 }
787
788 int config_parse_exec_cpu_affinity(const char *unit,
789                                    const char *filename,
790                                    unsigned line,
791                                    const char *section,
792                                    unsigned section_line,
793                                    const char *lvalue,
794                                    int ltype,
795                                    const char *rvalue,
796                                    void *data,
797                                    void *userdata) {
798
799         ExecContext *c = data;
800         char *w;
801         size_t l;
802         char *state;
803
804         assert(filename);
805         assert(lvalue);
806         assert(rvalue);
807         assert(data);
808
809         if (isempty(rvalue)) {
810                 /* An empty assignment resets the CPU list */
811                 if (c->cpuset)
812                         CPU_FREE(c->cpuset);
813                 c->cpuset = NULL;
814                 return 0;
815         }
816
817         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
818                 _cleanup_free_ char *t = NULL;
819                 int r;
820                 unsigned cpu;
821
822                 t = strndup(w, l);
823                 if (!t)
824                         return log_oom();
825
826                 r = safe_atou(t, &cpu);
827
828                 if (!c->cpuset) {
829                         c->cpuset = cpu_set_malloc(&c->cpuset_ncpus);
830                         if (!c->cpuset)
831                                 return log_oom();
832                 }
833
834                 if (r < 0 || cpu >= c->cpuset_ncpus) {
835                         log_syntax(unit, LOG_ERR, filename, line, ERANGE,
836                                    "Failed to parse CPU affinity '%s', ignoring: %s", t, rvalue);
837                         return 0;
838                 }
839
840                 CPU_SET_S(cpu, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset);
841         }
842
843         return 0;
844 }
845
846 int config_parse_exec_capabilities(const char *unit,
847                                    const char *filename,
848                                    unsigned line,
849                                    const char *section,
850                                    unsigned section_line,
851                                    const char *lvalue,
852                                    int ltype,
853                                    const char *rvalue,
854                                    void *data,
855                                    void *userdata) {
856
857         ExecContext *c = data;
858         cap_t cap;
859
860         assert(filename);
861         assert(lvalue);
862         assert(rvalue);
863         assert(data);
864
865         cap = cap_from_text(rvalue);
866         if (!cap) {
867                 log_syntax(unit, LOG_ERR, filename, line, errno,
868                            "Failed to parse capabilities, ignoring: %s", rvalue);
869                 return 0;
870         }
871
872         if (c->capabilities)
873                 cap_free(c->capabilities);
874         c->capabilities = cap;
875
876         return 0;
877 }
878
879 int config_parse_exec_secure_bits(const char *unit,
880                                   const char *filename,
881                                   unsigned line,
882                                   const char *section,
883                                   unsigned section_line,
884                                   const char *lvalue,
885                                   int ltype,
886                                   const char *rvalue,
887                                   void *data,
888                                   void *userdata) {
889
890         ExecContext *c = data;
891         char *w;
892         size_t l;
893         char *state;
894
895         assert(filename);
896         assert(lvalue);
897         assert(rvalue);
898         assert(data);
899
900         if (isempty(rvalue)) {
901                 /* An empty assignment resets the field */
902                 c->secure_bits = 0;
903                 return 0;
904         }
905
906         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
907                 if (first_word(w, "keep-caps"))
908                         c->secure_bits |= 1<<SECURE_KEEP_CAPS;
909                 else if (first_word(w, "keep-caps-locked"))
910                         c->secure_bits |= 1<<SECURE_KEEP_CAPS_LOCKED;
911                 else if (first_word(w, "no-setuid-fixup"))
912                         c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP;
913                 else if (first_word(w, "no-setuid-fixup-locked"))
914                         c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP_LOCKED;
915                 else if (first_word(w, "noroot"))
916                         c->secure_bits |= 1<<SECURE_NOROOT;
917                 else if (first_word(w, "noroot-locked"))
918                         c->secure_bits |= 1<<SECURE_NOROOT_LOCKED;
919                 else {
920                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
921                                    "Failed to parse secure bits, ignoring: %s", rvalue);
922                         return 0;
923                 }
924         }
925
926         return 0;
927 }
928
929 int config_parse_bounding_set(const char *unit,
930                               const char *filename,
931                               unsigned line,
932                               const char *section,
933                               unsigned section_line,
934                               const char *lvalue,
935                               int ltype,
936                               const char *rvalue,
937                               void *data,
938                               void *userdata) {
939
940         uint64_t *capability_bounding_set_drop = data;
941         char *w;
942         size_t l;
943         char *state;
944         bool invert = false;
945         uint64_t sum = 0;
946
947         assert(filename);
948         assert(lvalue);
949         assert(rvalue);
950         assert(data);
951
952         if (rvalue[0] == '~') {
953                 invert = true;
954                 rvalue++;
955         }
956
957         /* Note that we store this inverted internally, since the
958          * kernel wants it like this. But we actually expose it
959          * non-inverted everywhere to have a fully normalized
960          * interface. */
961
962         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
963                 _cleanup_free_ char *t = NULL;
964                 int r;
965                 cap_value_t cap;
966
967                 t = strndup(w, l);
968                 if (!t)
969                         return log_oom();
970
971                 r = cap_from_name(t, &cap);
972                 if (r < 0) {
973                         log_syntax(unit, LOG_ERR, filename, line, errno,
974                                    "Failed to parse capability in bounding set, ignoring: %s", t);
975                         continue;
976                 }
977
978                 sum |= ((uint64_t) 1ULL) << (uint64_t) cap;
979         }
980
981         if (invert)
982                 *capability_bounding_set_drop |= sum;
983         else
984                 *capability_bounding_set_drop |= ~sum;
985
986         return 0;
987 }
988
989 int config_parse_limit(const char *unit,
990                        const char *filename,
991                        unsigned line,
992                        const char *section,
993                        unsigned section_line,
994                        const char *lvalue,
995                        int ltype,
996                        const char *rvalue,
997                        void *data,
998                        void *userdata) {
999
1000         struct rlimit **rl = data;
1001         unsigned long long u;
1002
1003         assert(filename);
1004         assert(lvalue);
1005         assert(rvalue);
1006         assert(data);
1007
1008         rl += ltype;
1009
1010         if (streq(rvalue, "infinity"))
1011                 u = (unsigned long long) RLIM_INFINITY;
1012         else {
1013                 int r;
1014
1015                 r = safe_atollu(rvalue, &u);
1016                 if (r < 0) {
1017                         log_syntax(unit, LOG_ERR, filename, line, -r,
1018                                    "Failed to parse resource value, ignoring: %s", rvalue);
1019                         return 0;
1020                 }
1021         }
1022
1023         if (!*rl) {
1024                 *rl = new(struct rlimit, 1);
1025                 if (!*rl)
1026                         return log_oom();
1027         }
1028
1029         (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) u;
1030         return 0;
1031 }
1032
1033 #ifdef HAVE_SYSV_COMPAT
1034 int config_parse_sysv_priority(const char *unit,
1035                                const char *filename,
1036                                unsigned line,
1037                                const char *section,
1038                                unsigned section_line,
1039                                const char *lvalue,
1040                                int ltype,
1041                                const char *rvalue,
1042                                void *data,
1043                                void *userdata) {
1044
1045         int *priority = data;
1046         int i, r;
1047
1048         assert(filename);
1049         assert(lvalue);
1050         assert(rvalue);
1051         assert(data);
1052
1053         r = safe_atoi(rvalue, &i);
1054         if (r < 0 || i < 0) {
1055                 log_syntax(unit, LOG_ERR, filename, line, -r,
1056                            "Failed to parse SysV start priority, ignoring: %s", rvalue);
1057                 return 0;
1058         }
1059
1060         *priority = (int) i;
1061         return 0;
1062 }
1063 #endif
1064
1065 DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
1066
1067 int config_parse_kill_signal(const char *unit,
1068                              const char *filename,
1069                              unsigned line,
1070                              const char *section,
1071                              unsigned section_line,
1072                              const char *lvalue,
1073                              int ltype,
1074                              const char *rvalue,
1075                              void *data,
1076                              void *userdata) {
1077
1078         int *sig = data;
1079         int r;
1080
1081         assert(filename);
1082         assert(lvalue);
1083         assert(rvalue);
1084         assert(sig);
1085
1086         r = signal_from_string_try_harder(rvalue);
1087         if (r <= 0) {
1088                 log_syntax(unit, LOG_ERR, filename, line, -r,
1089                            "Failed to parse kill signal, ignoring: %s", rvalue);
1090                 return 0;
1091         }
1092
1093         *sig = r;
1094         return 0;
1095 }
1096
1097 int config_parse_exec_mount_flags(const char *unit,
1098                                   const char *filename,
1099                                   unsigned line,
1100                                   const char *section,
1101                                   unsigned section_line,
1102                                   const char *lvalue,
1103                                   int ltype,
1104                                   const char *rvalue,
1105                                   void *data,
1106                                   void *userdata) {
1107
1108         ExecContext *c = data;
1109         char *w;
1110         size_t l;
1111         char *state;
1112         unsigned long flags = 0;
1113
1114         assert(filename);
1115         assert(lvalue);
1116         assert(rvalue);
1117         assert(data);
1118
1119         FOREACH_WORD_SEPARATOR(w, l, rvalue, ", ", state) {
1120                 _cleanup_free_ char *t;
1121
1122                 t = strndup(w, l);
1123                 if (!t)
1124                         return log_oom();
1125
1126                 if (streq(t, "shared"))
1127                         flags = MS_SHARED;
1128                 else if (streq(t, "slave"))
1129                         flags = MS_SLAVE;
1130                 else if (streq(w, "private"))
1131                         flags = MS_PRIVATE;
1132                 else {
1133                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse mount flag %s, ignoring: %s", t, rvalue);
1134                         return 0;
1135                 }
1136         }
1137
1138         c->mount_flags = flags;
1139         return 0;
1140 }
1141
1142 int config_parse_exec_selinux_context(
1143                 const char *unit,
1144                 const char *filename,
1145                 unsigned line,
1146                 const char *section,
1147                 unsigned section_line,
1148                 const char *lvalue,
1149                 int ltype,
1150                 const char *rvalue,
1151                 void *data,
1152                 void *userdata) {
1153
1154         ExecContext *c = data;
1155         Unit *u = userdata;
1156         bool ignore;
1157         char *k;
1158         int r;
1159
1160         assert(filename);
1161         assert(lvalue);
1162         assert(rvalue);
1163         assert(data);
1164
1165         if (isempty(rvalue)) {
1166                 free(c->selinux_context);
1167                 c->selinux_context = NULL;
1168                 c->selinux_context_ignore = false;
1169                 return 0;
1170         }
1171
1172         if (rvalue[0] == '-') {
1173                 ignore = true;
1174                 rvalue++;
1175         } else
1176                 ignore = false;
1177
1178         r = unit_name_printf(u, rvalue, &k);
1179         if (r < 0) {
1180                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1181                 return 0;
1182         }
1183
1184         free(c->selinux_context);
1185         c->selinux_context = k;
1186         c->selinux_context_ignore = ignore;
1187
1188         return 0;
1189 }
1190
1191 int config_parse_exec_apparmor_profile(
1192                 const char *unit,
1193                 const char *filename,
1194                 unsigned line,
1195                 const char *section,
1196                 unsigned section_line,
1197                 const char *lvalue,
1198                 int ltype,
1199                 const char *rvalue,
1200                 void *data,
1201                 void *userdata) {
1202
1203         ExecContext *c = data;
1204         Unit *u = userdata;
1205         bool ignore;
1206         char *k;
1207         int r;
1208
1209         assert(filename);
1210         assert(lvalue);
1211         assert(rvalue);
1212         assert(data);
1213
1214         if (isempty(rvalue)) {
1215                 free(c->apparmor_profile);
1216                 c->apparmor_profile = NULL;
1217                 c->apparmor_profile_ignore = false;
1218                 return 0;
1219         }
1220
1221         if (rvalue[0] == '-') {
1222                 ignore = true;
1223                 rvalue++;
1224         } else
1225                 ignore = false;
1226
1227         r = unit_name_printf(u, rvalue, &k);
1228         if (r < 0) {
1229                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1230                 return 0;
1231         }
1232
1233         free(c->apparmor_profile);
1234         c->apparmor_profile = k;
1235         c->apparmor_profile_ignore = ignore;
1236
1237         return 0;
1238 }
1239
1240 int config_parse_timer(const char *unit,
1241                        const char *filename,
1242                        unsigned line,
1243                        const char *section,
1244                        unsigned section_line,
1245                        const char *lvalue,
1246                        int ltype,
1247                        const char *rvalue,
1248                        void *data,
1249                        void *userdata) {
1250
1251         Timer *t = data;
1252         usec_t u = 0;
1253         TimerValue *v;
1254         TimerBase b;
1255         CalendarSpec *c = NULL;
1256
1257         assert(filename);
1258         assert(lvalue);
1259         assert(rvalue);
1260         assert(data);
1261
1262         if (isempty(rvalue)) {
1263                 /* Empty assignment resets list */
1264                 timer_free_values(t);
1265                 return 0;
1266         }
1267
1268         b = timer_base_from_string(lvalue);
1269         if (b < 0) {
1270                 log_syntax(unit, LOG_ERR, filename, line, -b,
1271                            "Failed to parse timer base, ignoring: %s", lvalue);
1272                 return 0;
1273         }
1274
1275         if (b == TIMER_CALENDAR) {
1276                 if (calendar_spec_from_string(rvalue, &c) < 0) {
1277                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1278                                    "Failed to parse calendar specification, ignoring: %s",
1279                                    rvalue);
1280                         return 0;
1281                 }
1282         } else {
1283                 if (parse_sec(rvalue, &u) < 0) {
1284                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1285                                    "Failed to parse timer value, ignoring: %s",
1286                                    rvalue);
1287                         return 0;
1288                 }
1289         }
1290
1291         v = new0(TimerValue, 1);
1292         if (!v)
1293                 return log_oom();
1294
1295         v->base = b;
1296         v->value = u;
1297         v->calendar_spec = c;
1298
1299         LIST_PREPEND(value, t->values, v);
1300
1301         return 0;
1302 }
1303
1304 int config_parse_trigger_unit(
1305                 const char *unit,
1306                 const char *filename,
1307                 unsigned line,
1308                 const char *section,
1309                 unsigned section_line,
1310                 const char *lvalue,
1311                 int ltype,
1312                 const char *rvalue,
1313                 void *data,
1314                 void *userdata) {
1315
1316         _cleanup_free_ char *p = NULL;
1317         Unit *u = data;
1318         UnitType type;
1319         int r;
1320
1321         assert(filename);
1322         assert(lvalue);
1323         assert(rvalue);
1324         assert(data);
1325
1326         if (!set_isempty(u->dependencies[UNIT_TRIGGERS])) {
1327                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1328                            "Multiple units to trigger specified, ignoring: %s", rvalue);
1329                 return 0;
1330         }
1331
1332         r = unit_name_printf(u, rvalue, &p);
1333         if (r < 0)
1334                 log_syntax(unit, LOG_ERR, filename, line, -r,
1335                            "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1336
1337         type = unit_name_to_type(p ?: rvalue);
1338         if (type < 0) {
1339                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1340                            "Unit type not valid, ignoring: %s", rvalue);
1341                 return 0;
1342         }
1343
1344         if (type == u->type) {
1345                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1346                            "Trigger cannot be of same type, ignoring: %s", rvalue);
1347                 return 0;
1348         }
1349
1350         r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p ?: rvalue, NULL, true);
1351         if (r < 0) {
1352                 log_syntax(unit, LOG_ERR, filename, line, -r,
1353                            "Failed to add trigger on %s, ignoring: %s", p ?: rvalue, strerror(-r));
1354                 return 0;
1355         }
1356
1357         return 0;
1358 }
1359
1360 int config_parse_path_spec(const char *unit,
1361                            const char *filename,
1362                            unsigned line,
1363                            const char *section,
1364                            unsigned section_line,
1365                            const char *lvalue,
1366                            int ltype,
1367                            const char *rvalue,
1368                            void *data,
1369                            void *userdata) {
1370
1371         Path *p = data;
1372         PathSpec *s;
1373         PathType b;
1374         _cleanup_free_ char *k = NULL;
1375         int r;
1376
1377         assert(filename);
1378         assert(lvalue);
1379         assert(rvalue);
1380         assert(data);
1381
1382         if (isempty(rvalue)) {
1383                 /* Empty assignment clears list */
1384                 path_free_specs(p);
1385                 return 0;
1386         }
1387
1388         b = path_type_from_string(lvalue);
1389         if (b < 0) {
1390                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1391                            "Failed to parse path type, ignoring: %s", lvalue);
1392                 return 0;
1393         }
1394
1395         r = unit_full_printf(UNIT(p), rvalue, &k);
1396         if (r < 0) {
1397                 k = strdup(rvalue);
1398                 if (!k)
1399                         return log_oom();
1400                 else
1401                         log_syntax(unit, LOG_ERR, filename, line, -r,
1402                                    "Failed to resolve unit specifiers on %s. Ignoring.",
1403                                    rvalue);
1404         }
1405
1406         if (!path_is_absolute(k)) {
1407                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1408                            "Path is not absolute, ignoring: %s", k);
1409                 return 0;
1410         }
1411
1412         s = new0(PathSpec, 1);
1413         if (!s)
1414                 return log_oom();
1415
1416         s->unit = UNIT(p);
1417         s->path = path_kill_slashes(k);
1418         k = NULL;
1419         s->type = b;
1420         s->inotify_fd = -1;
1421
1422         LIST_PREPEND(spec, p->specs, s);
1423
1424         return 0;
1425 }
1426
1427 int config_parse_socket_service(const char *unit,
1428                                 const char *filename,
1429                                 unsigned line,
1430                                 const char *section,
1431                                 unsigned section_line,
1432                                 const char *lvalue,
1433                                 int ltype,
1434                                 const char *rvalue,
1435                                 void *data,
1436                                 void *userdata) {
1437
1438         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1439         Socket *s = data;
1440         int r;
1441         Unit *x;
1442         _cleanup_free_ char *p = NULL;
1443
1444         assert(filename);
1445         assert(lvalue);
1446         assert(rvalue);
1447         assert(data);
1448
1449         r = unit_name_printf(UNIT(s), rvalue, &p);
1450         if (r < 0) {
1451                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
1452                 return 0;
1453         }
1454
1455         if (!endswith(p, ".service")) {
1456                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type service, ignoring: %s", rvalue);
1457                 return 0;
1458         }
1459
1460         r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x);
1461         if (r < 0) {
1462                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
1463                 return 0;
1464         }
1465
1466         unit_ref_set(&s->service, x);
1467
1468         return 0;
1469 }
1470
1471 int config_parse_service_sockets(const char *unit,
1472                                  const char *filename,
1473                                  unsigned line,
1474                                  const char *section,
1475                                  unsigned section_line,
1476                                  const char *lvalue,
1477                                  int ltype,
1478                                  const char *rvalue,
1479                                  void *data,
1480                                  void *userdata) {
1481
1482         Service *s = data;
1483         int r;
1484         char *state, *w;
1485         size_t l;
1486
1487         assert(filename);
1488         assert(lvalue);
1489         assert(rvalue);
1490         assert(data);
1491
1492         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1493                 _cleanup_free_ char *t = NULL, *k = NULL;
1494
1495                 t = strndup(w, l);
1496                 if (!t)
1497                         return log_oom();
1498
1499                 r = unit_name_printf(UNIT(s), t, &k);
1500                 if (r < 0)
1501                         log_syntax(unit, LOG_ERR, filename, line, -r,
1502                                    "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1503
1504                 if (!endswith(k ?: t, ".socket")) {
1505                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1506                                    "Unit must be of type socket, ignoring: %s", k ?: t);
1507                         continue;
1508                 }
1509
1510                 r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k ?: t, NULL, true);
1511                 if (r < 0)
1512                         log_syntax(unit, LOG_ERR, filename, line, -r,
1513                                    "Failed to add dependency on %s, ignoring: %s",
1514                                    k ?: t, strerror(-r));
1515
1516                 r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k ?: t, NULL, true);
1517                 if (r < 0)
1518                         return r;
1519         }
1520
1521         return 0;
1522 }
1523
1524 int config_parse_service_timeout(const char *unit,
1525                                  const char *filename,
1526                                  unsigned line,
1527                                  const char *section,
1528                                  unsigned section_line,
1529                                  const char *lvalue,
1530                                  int ltype,
1531                                  const char *rvalue,
1532                                  void *data,
1533                                  void *userdata) {
1534
1535         Service *s = userdata;
1536         int r;
1537
1538         assert(filename);
1539         assert(lvalue);
1540         assert(rvalue);
1541         assert(s);
1542
1543         r = config_parse_sec(unit, filename, line, section, section_line, lvalue, ltype,
1544                              rvalue, data, userdata);
1545         if (r < 0)
1546                 return r;
1547
1548         if (streq(lvalue, "TimeoutSec")) {
1549                 s->start_timeout_defined = true;
1550                 s->timeout_stop_usec = s->timeout_start_usec;
1551         } else if (streq(lvalue, "TimeoutStartSec"))
1552                 s->start_timeout_defined = true;
1553
1554         return 0;
1555 }
1556
1557 int config_parse_busname_service(
1558                 const char *unit,
1559                 const char *filename,
1560                 unsigned line,
1561                 const char *section,
1562                 unsigned section_line,
1563                 const char *lvalue,
1564                 int ltype,
1565                 const char *rvalue,
1566                 void *data,
1567                 void *userdata) {
1568
1569         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1570         BusName *n = data;
1571         int r;
1572         Unit *x;
1573         _cleanup_free_ char *p = NULL;
1574
1575         assert(filename);
1576         assert(lvalue);
1577         assert(rvalue);
1578         assert(data);
1579
1580         r = unit_name_printf(UNIT(n), rvalue, &p);
1581         if (r < 0) {
1582                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
1583                 return 0;
1584         }
1585
1586         if (!endswith(p, ".service")) {
1587                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type service, ignoring: %s", rvalue);
1588                 return 0;
1589         }
1590
1591         r = manager_load_unit(UNIT(n)->manager, p, NULL, &error, &x);
1592         if (r < 0) {
1593                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
1594                 return 0;
1595         }
1596
1597         unit_ref_set(&n->service, x);
1598
1599         return 0;
1600 }
1601
1602 int config_parse_bus_policy(
1603                 const char *unit,
1604                 const char *filename,
1605                 unsigned line,
1606                 const char *section,
1607                 unsigned section_line,
1608                 const char *lvalue,
1609                 int ltype,
1610                 const char *rvalue,
1611                 void *data,
1612                 void *userdata) {
1613
1614         _cleanup_free_ BusNamePolicy *p = NULL;
1615         _cleanup_free_ char *id_str = NULL;
1616         BusName *busname = data;
1617         char *access_str;
1618         int r;
1619
1620         assert(filename);
1621         assert(lvalue);
1622         assert(rvalue);
1623         assert(data);
1624
1625         p = new0(BusNamePolicy, 1);
1626         if (!p)
1627                 return log_oom();
1628
1629         if (streq(lvalue, "AllowUser"))
1630                 p->type = BUSNAME_POLICY_TYPE_USER;
1631         else if (streq(lvalue, "AllowGroup"))
1632                 p->type = BUSNAME_POLICY_TYPE_GROUP;
1633         else if (streq(lvalue, "AllowWorld"))
1634                 p->type = BUSNAME_POLICY_TYPE_WORLD;
1635         else
1636                 assert_not_reached("Unknown lvalue");
1637
1638         id_str = strdup(rvalue);
1639         if (!id_str)
1640                 return log_oom();
1641
1642         if (p->type != BUSNAME_POLICY_TYPE_WORLD) {
1643                 access_str = strchr(id_str, ' ');
1644                 if (!access_str) {
1645                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid busname policy value '%s'", rvalue);
1646                         return 0;
1647                 }
1648
1649                 *access_str = '\0';
1650                 access_str++;
1651
1652                 if (p->type == BUSNAME_POLICY_TYPE_USER) {
1653                         const char *user = id_str;
1654
1655                         r = get_user_creds(&user, &p->uid, NULL, NULL, NULL);
1656                         if (r < 0) {
1657                                 log_syntax(unit, LOG_ERR, filename, line, r, "Unable to parse uid from '%s'", id_str);
1658                                 return 0;
1659                         }
1660                 } else {
1661                         const char *group = id_str;
1662
1663                         r = get_group_creds(&group, &p->gid);
1664                         if (r < 0) {
1665                                 log_syntax(unit, LOG_ERR, filename, line, -errno, "Unable to parse gid from '%s'", id_str);
1666                                 return 0;
1667                         }
1668                 }
1669         } else {
1670                 access_str = id_str;
1671         }
1672
1673         p->access = busname_policy_access_from_string(access_str);
1674         if (p->access < 0) {
1675                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid busname policy access type '%s'", access_str);
1676                 return 0;
1677         }
1678
1679         LIST_PREPEND(policy, busname->policy, p);
1680         p = NULL;
1681
1682         return 0;
1683 }
1684
1685 int config_parse_unit_env_file(const char *unit,
1686                                const char *filename,
1687                                unsigned line,
1688                                const char *section,
1689                                unsigned section_line,
1690                                const char *lvalue,
1691                                int ltype,
1692                                const char *rvalue,
1693                                void *data,
1694                                void *userdata) {
1695
1696         char ***env = data;
1697         Unit *u = userdata;
1698         _cleanup_free_ char *n = NULL;
1699         const char *s;
1700         int r;
1701
1702         assert(filename);
1703         assert(lvalue);
1704         assert(rvalue);
1705         assert(data);
1706
1707         if (isempty(rvalue)) {
1708                 /* Empty assignment frees the list */
1709                 strv_free(*env);
1710                 *env = NULL;
1711                 return 0;
1712         }
1713
1714         r = unit_full_printf(u, rvalue, &n);
1715         if (r < 0)
1716                 log_syntax(unit, LOG_ERR, filename, line, r,
1717                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1718
1719         s = n ?: rvalue;
1720         if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
1721                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1722                            "Path '%s' is not absolute, ignoring.", s);
1723                 return 0;
1724         }
1725
1726         r = strv_extend(env, s);
1727         if (r < 0)
1728                 return log_oom();
1729
1730         return 0;
1731 }
1732
1733 int config_parse_environ(const char *unit,
1734                          const char *filename,
1735                          unsigned line,
1736                          const char *section,
1737                          unsigned section_line,
1738                          const char *lvalue,
1739                          int ltype,
1740                          const char *rvalue,
1741                          void *data,
1742                          void *userdata) {
1743
1744         Unit *u = userdata;
1745         char*** env = data, *w, *state;
1746         size_t l;
1747         _cleanup_free_ char *k = NULL;
1748         int r;
1749
1750         assert(filename);
1751         assert(lvalue);
1752         assert(rvalue);
1753         assert(data);
1754
1755         if (isempty(rvalue)) {
1756                 /* Empty assignment resets the list */
1757                 strv_free(*env);
1758                 *env = NULL;
1759                 return 0;
1760         }
1761
1762         if (u) {
1763                 r = unit_full_printf(u, rvalue, &k);
1764                 if (r < 0)
1765                         log_syntax(unit, LOG_ERR, filename, line, -r,
1766                                    "Failed to resolve specifiers, ignoring: %s", rvalue);
1767         }
1768
1769         if (!k)
1770                 k = strdup(rvalue);
1771         if (!k)
1772                 return log_oom();
1773
1774         FOREACH_WORD_QUOTED(w, l, k, state) {
1775                 _cleanup_free_ char *n;
1776                 char **x;
1777
1778                 n = cunescape_length(w, l);
1779                 if (!n)
1780                         return log_oom();
1781
1782                 if (!env_assignment_is_valid(n)) {
1783                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1784                                    "Invalid environment assignment, ignoring: %s", rvalue);
1785                         continue;
1786                 }
1787
1788                 x = strv_env_set(*env, n);
1789                 if (!x)
1790                         return log_oom();
1791
1792                 strv_free(*env);
1793                 *env = x;
1794         }
1795
1796         return 0;
1797 }
1798
1799 int config_parse_ip_tos(const char *unit,
1800                         const char *filename,
1801                         unsigned line,
1802                         const char *section,
1803                         unsigned section_line,
1804                         const char *lvalue,
1805                         int ltype,
1806                         const char *rvalue,
1807                         void *data,
1808                         void *userdata) {
1809
1810         int *ip_tos = data, x;
1811
1812         assert(filename);
1813         assert(lvalue);
1814         assert(rvalue);
1815         assert(data);
1816
1817         x = ip_tos_from_string(rvalue);
1818         if (x < 0) {
1819                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1820                            "Failed to parse IP TOS value, ignoring: %s", rvalue);
1821                 return 0;
1822         }
1823
1824         *ip_tos = x;
1825         return 0;
1826 }
1827
1828 int config_parse_unit_condition_path(const char *unit,
1829                                      const char *filename,
1830                                      unsigned line,
1831                                      const char *section,
1832                                      unsigned section_line,
1833                                      const char *lvalue,
1834                                      int ltype,
1835                                      const char *rvalue,
1836                                      void *data,
1837                                      void *userdata) {
1838
1839         ConditionType cond = ltype;
1840         Unit *u = data;
1841         bool trigger, negate;
1842         Condition *c;
1843         _cleanup_free_ char *p = NULL;
1844         int r;
1845
1846         assert(filename);
1847         assert(lvalue);
1848         assert(rvalue);
1849         assert(data);
1850
1851         if (isempty(rvalue)) {
1852                 /* Empty assignment resets the list */
1853                 condition_free_list(u->conditions);
1854                 u->conditions = NULL;
1855                 return 0;
1856         }
1857
1858         trigger = rvalue[0] == '|';
1859         if (trigger)
1860                 rvalue++;
1861
1862         negate = rvalue[0] == '!';
1863         if (negate)
1864                 rvalue++;
1865
1866         r = unit_full_printf(u, rvalue, &p);
1867         if (r < 0)
1868                 log_syntax(unit, LOG_ERR, filename, line, -r,
1869                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1870         if (!p) {
1871                 p = strdup(rvalue);
1872                 if (!p)
1873                         return log_oom();
1874         }
1875
1876         if (!path_is_absolute(p)) {
1877                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1878                            "Path in condition not absolute, ignoring: %s", p);
1879                 return 0;
1880         }
1881
1882         c = condition_new(cond, p, trigger, negate);
1883         if (!c)
1884                 return log_oom();
1885
1886         LIST_PREPEND(conditions, u->conditions, c);
1887         return 0;
1888 }
1889
1890 int config_parse_unit_condition_string(const char *unit,
1891                                        const char *filename,
1892                                        unsigned line,
1893                                        const char *section,
1894                                        unsigned section_line,
1895                                        const char *lvalue,
1896                                        int ltype,
1897                                        const char *rvalue,
1898                                        void *data,
1899                                        void *userdata) {
1900
1901         ConditionType cond = ltype;
1902         Unit *u = data;
1903         bool trigger, negate;
1904         Condition *c;
1905         _cleanup_free_ char *s = NULL;
1906         int r;
1907
1908         assert(filename);
1909         assert(lvalue);
1910         assert(rvalue);
1911         assert(data);
1912
1913         if (isempty(rvalue)) {
1914                 /* Empty assignment resets the list */
1915                 condition_free_list(u->conditions);
1916                 u->conditions = NULL;
1917                 return 0;
1918         }
1919
1920         trigger = rvalue[0] == '|';
1921         if (trigger)
1922                 rvalue++;
1923
1924         negate = rvalue[0] == '!';
1925         if (negate)
1926                 rvalue++;
1927
1928         r = unit_full_printf(u, rvalue, &s);
1929         if (r < 0)
1930                 log_syntax(unit, LOG_ERR, filename, line, -r,
1931                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1932         if (!s) {
1933                 s = strdup(rvalue);
1934                 if (!s)
1935                         return log_oom();
1936         }
1937
1938         c = condition_new(cond, s, trigger, negate);
1939         if (!c)
1940                 return log_oom();
1941
1942         LIST_PREPEND(conditions, u->conditions, c);
1943         return 0;
1944 }
1945
1946 int config_parse_unit_condition_null(const char *unit,
1947                                      const char *filename,
1948                                      unsigned line,
1949                                      const char *section,
1950                                      unsigned section_line,
1951                                      const char *lvalue,
1952                                      int ltype,
1953                                      const char *rvalue,
1954                                      void *data,
1955                                      void *userdata) {
1956
1957         Unit *u = data;
1958         Condition *c;
1959         bool trigger, negate;
1960         int b;
1961
1962         assert(filename);
1963         assert(lvalue);
1964         assert(rvalue);
1965         assert(data);
1966
1967         if (isempty(rvalue)) {
1968                 /* Empty assignment resets the list */
1969                 condition_free_list(u->conditions);
1970                 u->conditions = NULL;
1971                 return 0;
1972         }
1973
1974         trigger = rvalue[0] == '|';
1975         if (trigger)
1976                 rvalue++;
1977
1978         negate = rvalue[0] == '!';
1979         if (negate)
1980                 rvalue++;
1981
1982         b = parse_boolean(rvalue);
1983         if (b < 0) {
1984                 log_syntax(unit, LOG_ERR, filename, line, -b,
1985                            "Failed to parse boolean value in condition, ignoring: %s",
1986                            rvalue);
1987                 return 0;
1988         }
1989
1990         if (!b)
1991                 negate = !negate;
1992
1993         c = condition_new(CONDITION_NULL, NULL, trigger, negate);
1994         if (!c)
1995                 return log_oom();
1996
1997         LIST_PREPEND(conditions, u->conditions, c);
1998         return 0;
1999 }
2000
2001 DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
2002 DEFINE_CONFIG_PARSE_ENUM(config_parse_failure_action, failure_action, FailureAction, "Failed to parse failure action specifier");
2003
2004 int config_parse_unit_requires_mounts_for(
2005                 const char *unit,
2006                 const char *filename,
2007                 unsigned line,
2008                 const char *section,
2009                 unsigned section_line,
2010                 const char *lvalue,
2011                 int ltype,
2012                 const char *rvalue,
2013                 void *data,
2014                 void *userdata) {
2015
2016         Unit *u = userdata;
2017         char *state;
2018         size_t l;
2019         char *w;
2020
2021         assert(filename);
2022         assert(lvalue);
2023         assert(rvalue);
2024         assert(data);
2025
2026         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2027                 int r;
2028                 _cleanup_free_ char *n;
2029
2030                 n = strndup(w, l);
2031                 if (!n)
2032                         return log_oom();
2033
2034                 if (!utf8_is_valid(n)) {
2035                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
2036                         continue;
2037                 }
2038
2039                 r = unit_require_mounts_for(u, n);
2040                 if (r < 0) {
2041                         log_syntax(unit, LOG_ERR, filename, line, r,
2042                                    "Failed to add required mount for, ignoring: %s", rvalue);
2043                         continue;
2044                 }
2045         }
2046
2047         return 0;
2048 }
2049
2050 int config_parse_documentation(const char *unit,
2051                                const char *filename,
2052                                unsigned line,
2053                                const char *section,
2054                                unsigned section_line,
2055                                const char *lvalue,
2056                                int ltype,
2057                                const char *rvalue,
2058                                void *data,
2059                                void *userdata) {
2060
2061         Unit *u = userdata;
2062         int r;
2063         char **a, **b;
2064
2065         assert(filename);
2066         assert(lvalue);
2067         assert(rvalue);
2068         assert(u);
2069
2070         if (isempty(rvalue)) {
2071                 /* Empty assignment resets the list */
2072                 strv_free(u->documentation);
2073                 u->documentation = NULL;
2074                 return 0;
2075         }
2076
2077         r = config_parse_unit_strv_printf(unit, filename, line, section, section_line, lvalue, ltype,
2078                                           rvalue, data, userdata);
2079         if (r < 0)
2080                 return r;
2081
2082         for (a = b = u->documentation; a && *a; a++) {
2083
2084                 if (is_valid_documentation_url(*a))
2085                         *(b++) = *a;
2086                 else {
2087                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2088                                    "Invalid URL, ignoring: %s", *a);
2089                         free(*a);
2090                 }
2091         }
2092         if (b)
2093                 *b = NULL;
2094
2095         return r;
2096 }
2097
2098 #ifdef HAVE_SECCOMP
2099 int config_parse_syscall_filter(
2100                 const char *unit,
2101                 const char *filename,
2102                 unsigned line,
2103                 const char *section,
2104                 unsigned section_line,
2105                 const char *lvalue,
2106                 int ltype,
2107                 const char *rvalue,
2108                 void *data,
2109                 void *userdata) {
2110
2111         static const char default_syscalls[] =
2112                 "execve\0"
2113                 "exit\0"
2114                 "exit_group\0"
2115                 "rt_sigreturn\0"
2116                 "sigreturn\0";
2117
2118         ExecContext *c = data;
2119         Unit *u = userdata;
2120         bool invert = false;
2121         char *w, *state;
2122         size_t l;
2123         int r;
2124
2125         assert(filename);
2126         assert(lvalue);
2127         assert(rvalue);
2128         assert(u);
2129
2130         if (isempty(rvalue)) {
2131                 /* Empty assignment resets the list */
2132                 set_free(c->syscall_filter);
2133                 c->syscall_filter = NULL;
2134                 c->syscall_whitelist = false;
2135                 return 0;
2136         }
2137
2138         if (rvalue[0] == '~') {
2139                 invert = true;
2140                 rvalue++;
2141         }
2142
2143         if (!c->syscall_filter) {
2144                 c->syscall_filter = set_new(trivial_hash_func, trivial_compare_func);
2145                 if (!c->syscall_filter)
2146                         return log_oom();
2147
2148                 if (invert)
2149                         /* Allow everything but the ones listed */
2150                         c->syscall_whitelist = false;
2151                 else {
2152                         const char *i;
2153
2154                         /* Allow nothing but the ones listed */
2155                         c->syscall_whitelist = true;
2156
2157                         /* Accept default syscalls if we are on a whitelist */
2158                         NULSTR_FOREACH(i, default_syscalls)  {
2159                                 int id;
2160
2161                                 id = seccomp_syscall_resolve_name(i);
2162                                 if (id < 0)
2163                                         continue;
2164
2165                                 r = set_put(c->syscall_filter, INT_TO_PTR(id + 1));
2166                                 if (r == -EEXIST)
2167                                         continue;
2168                                 if (r < 0)
2169                                         return log_oom();
2170                         }
2171                 }
2172         }
2173
2174         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2175                 _cleanup_free_ char *t = NULL;
2176                 int id;
2177
2178                 t = strndup(w, l);
2179                 if (!t)
2180                         return log_oom();
2181
2182                 id = seccomp_syscall_resolve_name(t);
2183                 if (id < 0)  {
2184                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse system call, ignoring: %s", t);
2185                         continue;
2186                 }
2187
2188                 /* If we previously wanted to forbid a syscall and now
2189                  * we want to allow it, then remove it from the list
2190                  */
2191                 if (!invert == c->syscall_whitelist)  {
2192                         r = set_put(c->syscall_filter, INT_TO_PTR(id + 1));
2193                         if (r == -EEXIST)
2194                                 continue;
2195                         if (r < 0)
2196                                 return log_oom();
2197                 } else
2198                         set_remove(c->syscall_filter, INT_TO_PTR(id + 1));
2199         }
2200
2201         /* Turn on NNP, but only if it wasn't configured explicitly
2202          * before, and only if we are in user mode. */
2203         if (!c->no_new_privileges_set && u->manager->running_as == SYSTEMD_USER)
2204                 c->no_new_privileges = true;
2205
2206         return 0;
2207 }
2208
2209 int config_parse_syscall_archs(
2210                 const char *unit,
2211                 const char *filename,
2212                 unsigned line,
2213                 const char *section,
2214                 unsigned section_line,
2215                 const char *lvalue,
2216                 int ltype,
2217                 const char *rvalue,
2218                 void *data,
2219                 void *userdata) {
2220
2221         Set **archs = data;
2222         char *w, *state;
2223         size_t l;
2224         int r;
2225
2226         if (isempty(rvalue)) {
2227                 set_free(*archs);
2228                 *archs = NULL;
2229                 return 0;
2230         }
2231
2232         r = set_ensure_allocated(archs, trivial_hash_func, trivial_compare_func);
2233         if (r < 0)
2234                 return log_oom();
2235
2236         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2237                 _cleanup_free_ char *t = NULL;
2238                 uint32_t a;
2239
2240                 t = strndup(w, l);
2241                 if (!t)
2242                         return log_oom();
2243
2244                 r = seccomp_arch_from_string(t, &a);
2245                 if (r < 0) {
2246                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse system call architecture, ignoring: %s", t);
2247                         continue;
2248                 }
2249
2250                 r = set_put(*archs, UINT32_TO_PTR(a + 1));
2251                 if (r == -EEXIST)
2252                         continue;
2253                 if (r < 0)
2254                         return log_oom();
2255         }
2256
2257         return 0;
2258 }
2259
2260 int config_parse_syscall_errno(
2261                 const char *unit,
2262                 const char *filename,
2263                 unsigned line,
2264                 const char *section,
2265                 unsigned section_line,
2266                 const char *lvalue,
2267                 int ltype,
2268                 const char *rvalue,
2269                 void *data,
2270                 void *userdata) {
2271
2272         ExecContext *c = data;
2273         int e;
2274
2275         assert(filename);
2276         assert(lvalue);
2277         assert(rvalue);
2278
2279         if (isempty(rvalue)) {
2280                 /* Empty assignment resets to KILL */
2281                 c->syscall_errno = 0;
2282                 return 0;
2283         }
2284
2285         e = errno_from_name(rvalue);
2286         if (e < 0) {
2287                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse error number, ignoring: %s", rvalue);
2288                 return 0;
2289         }
2290
2291         c->syscall_errno = e;
2292         return 0;
2293 }
2294
2295 int config_parse_address_families(
2296                 const char *unit,
2297                 const char *filename,
2298                 unsigned line,
2299                 const char *section,
2300                 unsigned section_line,
2301                 const char *lvalue,
2302                 int ltype,
2303                 const char *rvalue,
2304                 void *data,
2305                 void *userdata) {
2306
2307         ExecContext *c = data;
2308         Unit *u = userdata;
2309         bool invert = false;
2310         char *w, *state;
2311         size_t l;
2312         int r;
2313
2314         assert(filename);
2315         assert(lvalue);
2316         assert(rvalue);
2317         assert(u);
2318
2319         if (isempty(rvalue)) {
2320                 /* Empty assignment resets the list */
2321                 set_free(c->address_families);
2322                 c->address_families = NULL;
2323                 c->address_families_whitelist = false;
2324                 return 0;
2325         }
2326
2327         if (rvalue[0] == '~') {
2328                 invert = true;
2329                 rvalue++;
2330         }
2331
2332         if (!c->address_families) {
2333                 c->address_families = set_new(trivial_hash_func, trivial_compare_func);
2334                 if (!c->address_families)
2335                         return log_oom();
2336
2337                 c->address_families_whitelist = !invert;
2338         }
2339
2340         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2341                 _cleanup_free_ char *t = NULL;
2342                 int af;
2343
2344                 t = strndup(w, l);
2345                 if (!t)
2346                         return log_oom();
2347
2348                 af = af_from_name(t);
2349                 if (af <= 0)  {
2350                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse address family, ignoring: %s", t);
2351                         continue;
2352                 }
2353
2354                 /* If we previously wanted to forbid an address family and now
2355                  * we want to allow it, then remove it from the list
2356                  */
2357                 if (!invert == c->address_families_whitelist)  {
2358                         r = set_put(c->address_families, INT_TO_PTR(af));
2359                         if (r == -EEXIST)
2360                                 continue;
2361                         if (r < 0)
2362                                 return log_oom();
2363                 } else
2364                         set_remove(c->address_families, INT_TO_PTR(af));
2365         }
2366
2367         return 0;
2368 }
2369 #endif
2370
2371 int config_parse_unit_slice(
2372                 const char *unit,
2373                 const char *filename,
2374                 unsigned line,
2375                 const char *section,
2376                 unsigned section_line,
2377                 const char *lvalue,
2378                 int ltype,
2379                 const char *rvalue,
2380                 void *data,
2381                 void *userdata) {
2382
2383         _cleanup_free_ char *k = NULL;
2384         Unit *u = userdata, *slice;
2385         int r;
2386
2387         assert(filename);
2388         assert(lvalue);
2389         assert(rvalue);
2390         assert(u);
2391
2392         r = unit_name_printf(u, rvalue, &k);
2393         if (r < 0)
2394                 log_syntax(unit, LOG_ERR, filename, line, -r,
2395                            "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
2396         if (!k) {
2397                 k = strdup(rvalue);
2398                 if (!k)
2399                         return log_oom();
2400         }
2401
2402         r = manager_load_unit(u->manager, k, NULL, NULL, &slice);
2403         if (r < 0) {
2404                 log_syntax(unit, LOG_ERR, filename, line, -r,
2405                            "Failed to load slice unit %s. Ignoring.", k);
2406                 return 0;
2407         }
2408
2409         if (slice->type != UNIT_SLICE) {
2410                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2411                            "Slice unit %s is not a slice. Ignoring.", k);
2412                 return 0;
2413         }
2414
2415         unit_ref_set(&u->slice, slice);
2416         return 0;
2417 }
2418
2419 DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy");
2420
2421 int config_parse_cpu_shares(
2422                 const char *unit,
2423                 const char *filename,
2424                 unsigned line,
2425                 const char *section,
2426                 unsigned section_line,
2427                 const char *lvalue,
2428                 int ltype,
2429                 const char *rvalue,
2430                 void *data,
2431                 void *userdata) {
2432
2433         CGroupContext *c = data;
2434         unsigned long lu;
2435         int r;
2436
2437         assert(filename);
2438         assert(lvalue);
2439         assert(rvalue);
2440
2441         if (isempty(rvalue)) {
2442                 c->cpu_shares = 1024;
2443                 return 0;
2444         }
2445
2446         r = safe_atolu(rvalue, &lu);
2447         if (r < 0 || lu <= 0) {
2448                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2449                            "CPU shares '%s' invalid. Ignoring.", rvalue);
2450                 return 0;
2451         }
2452
2453         c->cpu_shares = lu;
2454         return 0;
2455 }
2456
2457 int config_parse_cpu_quota(
2458                 const char *unit,
2459                 const char *filename,
2460                 unsigned line,
2461                 const char *section,
2462                 unsigned section_line,
2463                 const char *lvalue,
2464                 int ltype,
2465                 const char *rvalue,
2466                 void *data,
2467                 void *userdata) {
2468
2469         CGroupContext *c = data;
2470         int r;
2471
2472         assert(filename);
2473         assert(lvalue);
2474         assert(rvalue);
2475
2476         if (isempty(rvalue)) {
2477                 c->cpu_quota_per_sec_usec = (usec_t) -1;
2478                 c->cpu_quota_usec = (usec_t) -1;
2479                 return 0;
2480         }
2481
2482         if (endswith(rvalue, "%")) {
2483                 double percent;
2484
2485                 if (sscanf(rvalue, "%lf%%", &percent) != 1 || percent <= 0) {
2486                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "CPU quota '%s' invalid. Ignoring.", rvalue);
2487                         return 0;
2488                 }
2489
2490                 c->cpu_quota_per_sec_usec = (usec_t) (percent * USEC_PER_SEC / 100);
2491                 c->cpu_quota_usec = (usec_t) -1;
2492         } else {
2493                 r = parse_sec(rvalue, &c->cpu_quota_usec);
2494                 if (r < 0) {
2495                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "CPU quota '%s' invalid. Ignoring.", rvalue);
2496                         return 0;
2497                 }
2498
2499                 c->cpu_quota_per_sec_usec = (usec_t) -1;
2500         }
2501
2502         return 0;
2503 }
2504
2505 int config_parse_memory_limit(
2506                 const char *unit,
2507                 const char *filename,
2508                 unsigned line,
2509                 const char *section,
2510                 unsigned section_line,
2511                 const char *lvalue,
2512                 int ltype,
2513                 const char *rvalue,
2514                 void *data,
2515                 void *userdata) {
2516
2517         CGroupContext *c = data;
2518         off_t bytes;
2519         int r;
2520
2521         if (isempty(rvalue)) {
2522                 c->memory_limit = (uint64_t) -1;
2523                 return 0;
2524         }
2525
2526         assert_cc(sizeof(uint64_t) == sizeof(off_t));
2527
2528         r = parse_size(rvalue, 1024, &bytes);
2529         if (r < 0) {
2530                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Memory limit '%s' invalid. Ignoring.", rvalue);
2531                 return 0;
2532         }
2533
2534         c->memory_limit = (uint64_t) bytes;
2535         return 0;
2536 }
2537
2538 int config_parse_device_allow(
2539                 const char *unit,
2540                 const char *filename,
2541                 unsigned line,
2542                 const char *section,
2543                 unsigned section_line,
2544                 const char *lvalue,
2545                 int ltype,
2546                 const char *rvalue,
2547                 void *data,
2548                 void *userdata) {
2549
2550         _cleanup_free_ char *path = NULL;
2551         CGroupContext *c = data;
2552         CGroupDeviceAllow *a;
2553         const char *m;
2554         size_t n;
2555
2556         if (isempty(rvalue)) {
2557                 while (c->device_allow)
2558                         cgroup_context_free_device_allow(c, c->device_allow);
2559
2560                 return 0;
2561         }
2562
2563         n = strcspn(rvalue, WHITESPACE);
2564         path = strndup(rvalue, n);
2565         if (!path)
2566                 return log_oom();
2567
2568         if (!startswith(path, "/dev/") &&
2569             !startswith(path, "block-") &&
2570             !startswith(path, "char-")) {
2571                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid device node path '%s'. Ignoring.", path);
2572                 return 0;
2573         }
2574
2575         m = rvalue + n + strspn(rvalue + n, WHITESPACE);
2576         if (isempty(m))
2577                 m = "rwm";
2578
2579         if (!in_charset(m, "rwm")) {
2580                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid device rights '%s'. Ignoring.", m);
2581                 return 0;
2582         }
2583
2584         a = new0(CGroupDeviceAllow, 1);
2585         if (!a)
2586                 return log_oom();
2587
2588         a->path = path;
2589         path = NULL;
2590         a->r = !!strchr(m, 'r');
2591         a->w = !!strchr(m, 'w');
2592         a->m = !!strchr(m, 'm');
2593
2594         LIST_PREPEND(device_allow, c->device_allow, a);
2595         return 0;
2596 }
2597
2598 int config_parse_blockio_weight(
2599                 const char *unit,
2600                 const char *filename,
2601                 unsigned line,
2602                 const char *section,
2603                 unsigned section_line,
2604                 const char *lvalue,
2605                 int ltype,
2606                 const char *rvalue,
2607                 void *data,
2608                 void *userdata) {
2609
2610         CGroupContext *c = data;
2611         unsigned long lu;
2612         int r;
2613
2614         assert(filename);
2615         assert(lvalue);
2616         assert(rvalue);
2617
2618         if (isempty(rvalue)) {
2619                 c->blockio_weight = 1000;
2620                 return 0;
2621         }
2622
2623         r = safe_atolu(rvalue, &lu);
2624         if (r < 0 || lu < 10 || lu > 1000) {
2625                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2626                            "Block IO weight '%s' invalid. Ignoring.", rvalue);
2627                 return 0;
2628         }
2629
2630         c->blockio_weight = lu;
2631
2632         return 0;
2633 }
2634
2635 int config_parse_blockio_device_weight(
2636                 const char *unit,
2637                 const char *filename,
2638                 unsigned line,
2639                 const char *section,
2640                 unsigned section_line,
2641                 const char *lvalue,
2642                 int ltype,
2643                 const char *rvalue,
2644                 void *data,
2645                 void *userdata) {
2646
2647         _cleanup_free_ char *path = NULL;
2648         CGroupBlockIODeviceWeight *w;
2649         CGroupContext *c = data;
2650         unsigned long lu;
2651         const char *weight;
2652         size_t n;
2653         int r;
2654
2655         assert(filename);
2656         assert(lvalue);
2657         assert(rvalue);
2658
2659         if (isempty(rvalue)) {
2660                 while (c->blockio_device_weights)
2661                         cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
2662
2663                 return 0;
2664         }
2665
2666         n = strcspn(rvalue, WHITESPACE);
2667         weight = rvalue + n;
2668         if (!*weight) {
2669                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2670                            "Expected block device and device weight. Ignoring.");
2671                 return 0;
2672         }
2673
2674         path = strndup(rvalue, n);
2675         if (!path)
2676                 return log_oom();
2677
2678         if (!path_startswith(path, "/dev")) {
2679                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2680                            "Invalid device node path '%s'. Ignoring.", path);
2681                 return 0;
2682         }
2683
2684         weight += strspn(weight, WHITESPACE);
2685         r = safe_atolu(weight, &lu);
2686         if (r < 0 || lu < 10 || lu > 1000) {
2687                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2688                            "Block IO weight '%s' invalid. Ignoring.", rvalue);
2689                 return 0;
2690         }
2691
2692
2693         w = new0(CGroupBlockIODeviceWeight, 1);
2694         if (!w)
2695                 return log_oom();
2696
2697         w->path = path;
2698         path = NULL;
2699
2700         w->weight = lu;
2701
2702         LIST_PREPEND(device_weights, c->blockio_device_weights, w);
2703         return 0;
2704 }
2705
2706 int config_parse_blockio_bandwidth(
2707                 const char *unit,
2708                 const char *filename,
2709                 unsigned line,
2710                 const char *section,
2711                 unsigned section_line,
2712                 const char *lvalue,
2713                 int ltype,
2714                 const char *rvalue,
2715                 void *data,
2716                 void *userdata) {
2717
2718         _cleanup_free_ char *path = NULL;
2719         CGroupBlockIODeviceBandwidth *b;
2720         CGroupContext *c = data;
2721         const char *bandwidth;
2722         off_t bytes;
2723         bool read;
2724         size_t n;
2725         int r;
2726
2727         assert(filename);
2728         assert(lvalue);
2729         assert(rvalue);
2730
2731         read = streq("BlockIOReadBandwidth", lvalue);
2732
2733         if (isempty(rvalue)) {
2734                 CGroupBlockIODeviceBandwidth *next;
2735
2736                 LIST_FOREACH_SAFE (device_bandwidths, b, next, c->blockio_device_bandwidths)
2737                         if (b->read == read)
2738                                 cgroup_context_free_blockio_device_bandwidth(c, b);
2739
2740                 return 0;
2741         }
2742
2743         n = strcspn(rvalue, WHITESPACE);
2744         bandwidth = rvalue + n;
2745         bandwidth += strspn(bandwidth, WHITESPACE);
2746
2747         if (!*bandwidth) {
2748                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2749                            "Expected space separated pair of device node and bandwidth. Ignoring.");
2750                 return 0;
2751         }
2752
2753         path = strndup(rvalue, n);
2754         if (!path)
2755                 return log_oom();
2756
2757         if (!path_startswith(path, "/dev")) {
2758                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2759                            "Invalid device node path '%s'. Ignoring.", path);
2760                 return 0;
2761         }
2762
2763         r = parse_size(bandwidth, 1000, &bytes);
2764         if (r < 0 || bytes <= 0) {
2765                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue);
2766                 return 0;
2767         }
2768
2769         b = new0(CGroupBlockIODeviceBandwidth, 1);
2770         if (!b)
2771                 return log_oom();
2772
2773         b->path = path;
2774         path = NULL;
2775         b->bandwidth = (uint64_t) bytes;
2776         b->read = read;
2777
2778         LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, b);
2779
2780         return 0;
2781 }
2782
2783 DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode");
2784
2785 int config_parse_job_mode_isolate(
2786                 const char *unit,
2787                 const char *filename,
2788                 unsigned line,
2789                 const char *section,
2790                 unsigned section_line,
2791                 const char *lvalue,
2792                 int ltype,
2793                 const char *rvalue,
2794                 void *data,
2795                 void *userdata) {
2796
2797         JobMode *m = data;
2798         int r;
2799
2800         assert(filename);
2801         assert(lvalue);
2802         assert(rvalue);
2803
2804         r = parse_boolean(rvalue);
2805         if (r < 0) {
2806                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse boolean, ignoring: %s", rvalue);
2807                 return 0;
2808         }
2809
2810         *m = r ? JOB_ISOLATE : JOB_REPLACE;
2811         return 0;
2812 }
2813
2814 int config_parse_personality(
2815                 const char *unit,
2816                 const char *filename,
2817                 unsigned line,
2818                 const char *section,
2819                 unsigned section_line,
2820                 const char *lvalue,
2821                 int ltype,
2822                 const char *rvalue,
2823                 void *data,
2824                 void *userdata) {
2825
2826         unsigned long *personality = data, p;
2827
2828         assert(filename);
2829         assert(lvalue);
2830         assert(rvalue);
2831         assert(personality);
2832
2833         p = personality_from_string(rvalue);
2834         if (p == 0xffffffffUL) {
2835                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2836                            "Failed to parse personality, ignoring: %s", rvalue);
2837                 return 0;
2838         }
2839
2840         *personality = p;
2841         return 0;
2842 }
2843
2844 int config_parse_runtime_directory(
2845                 const char *unit,
2846                 const char *filename,
2847                 unsigned line,
2848                 const char *section,
2849                 unsigned section_line,
2850                 const char *lvalue,
2851                 int ltype,
2852                 const char *rvalue,
2853                 void *data,
2854                 void *userdata) {
2855
2856         char***rt = data, *w, *state;
2857         size_t l;
2858         int r;
2859
2860         assert(filename);
2861         assert(lvalue);
2862         assert(rvalue);
2863         assert(data);
2864
2865         if (isempty(rvalue)) {
2866                 /* Empty assignment resets the list */
2867                 strv_free(*rt);
2868                 *rt = NULL;
2869                 return 0;
2870         }
2871
2872         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2873                 _cleanup_free_ char *n;
2874
2875                 n = strndup(w, l);
2876                 if (!n)
2877                         return log_oom();
2878
2879                 if (!filename_is_safe(n)) {
2880                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Runtime directory is not valid, ignoring assignment: %s", rvalue);
2881                         continue;
2882                 }
2883
2884                 r = strv_push(rt, n);
2885                 if (r < 0)
2886                         return log_oom();
2887
2888                 n = NULL;
2889         }
2890
2891         return 0;
2892 }
2893
2894 int config_parse_set_status(
2895                 const char *unit,
2896                 const char *filename,
2897                 unsigned line,
2898                 const char *section,
2899                 unsigned section_line,
2900                 const char *lvalue,
2901                 int ltype,
2902                 const char *rvalue,
2903                 void *data,
2904                 void *userdata) {
2905
2906         char *w;
2907         size_t l;
2908         char *state;
2909         int r;
2910         ExitStatusSet *status_set = data;
2911
2912         assert(filename);
2913         assert(lvalue);
2914         assert(rvalue);
2915         assert(data);
2916
2917         if (isempty(rvalue)) {
2918                 /* Empty assignment resets the list */
2919
2920                 set_free(status_set->signal);
2921                 set_free(status_set->code);
2922
2923                 status_set->signal = status_set->code = NULL;
2924                 return 0;
2925         }
2926
2927         FOREACH_WORD(w, l, rvalue, state) {
2928                 _cleanup_free_ char *temp;
2929                 int val;
2930
2931                 temp = strndup(w, l);
2932                 if (!temp)
2933                         return log_oom();
2934
2935                 r = safe_atoi(temp, &val);
2936                 if (r < 0) {
2937                         val = signal_from_string_try_harder(temp);
2938
2939                         if (val > 0) {
2940                                 r = set_ensure_allocated(&status_set->signal, trivial_hash_func, trivial_compare_func);
2941                                 if (r < 0)
2942                                         return log_oom();
2943
2944                                 r = set_put(status_set->signal, INT_TO_PTR(val));
2945                                 if (r < 0) {
2946                                         log_syntax(unit, LOG_ERR, filename, line, -r, "Unable to store: %s", w);
2947                                         return r;
2948                                 }
2949                         } else {
2950                                 log_syntax(unit, LOG_ERR, filename, line, -val, "Failed to parse value, ignoring: %s", w);
2951                                 return 0;
2952                         }
2953                 } else {
2954                         if (val < 0 || val > 255)
2955                                 log_syntax(unit, LOG_ERR, filename, line, ERANGE, "Value %d is outside range 0-255, ignoring", val);
2956                         else {
2957                                 r = set_ensure_allocated(&status_set->code, trivial_hash_func, trivial_compare_func);
2958                                 if (r < 0)
2959                                         return log_oom();
2960
2961                                 r = set_put(status_set->code, INT_TO_PTR(val));
2962                                 if (r < 0) {
2963                                         log_syntax(unit, LOG_ERR, filename, line, -r, "Unable to store: %s", w);
2964                                         return r;
2965                                 }
2966                         }
2967                 }
2968         }
2969
2970         return 0;
2971 }
2972
2973 int config_parse_namespace_path_strv(
2974                 const char *unit,
2975                 const char *filename,
2976                 unsigned line,
2977                 const char *section,
2978                 unsigned section_line,
2979                 const char *lvalue,
2980                 int ltype,
2981                 const char *rvalue,
2982                 void *data,
2983                 void *userdata) {
2984
2985         char*** sv = data, *w, *state;
2986         size_t l;
2987         int r;
2988
2989         assert(filename);
2990         assert(lvalue);
2991         assert(rvalue);
2992         assert(data);
2993
2994         if (isempty(rvalue)) {
2995                 /* Empty assignment resets the list */
2996                 strv_free(*sv);
2997                 *sv = NULL;
2998                 return 0;
2999         }
3000
3001         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
3002                 _cleanup_free_ char *n;
3003                 int offset;
3004
3005                 n = strndup(w, l);
3006                 if (!n)
3007                         return log_oom();
3008
3009                 if (!utf8_is_valid(n)) {
3010                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
3011                         continue;
3012                 }
3013
3014                 offset = n[0] == '-';
3015                 if (!path_is_absolute(n + offset)) {
3016                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Not an absolute path, ignoring: %s", rvalue);
3017                         continue;
3018                 }
3019
3020                 path_kill_slashes(n);
3021
3022                 r = strv_push(sv, n);
3023                 if (r < 0)
3024                         return log_oom();
3025
3026                 n = NULL;
3027         }
3028
3029         return 0;
3030 }
3031
3032 int config_parse_no_new_privileges(
3033                 const char* unit,
3034                 const char *filename,
3035                 unsigned line,
3036                 const char *section,
3037                 unsigned section_line,
3038                 const char *lvalue,
3039                 int ltype,
3040                 const char *rvalue,
3041                 void *data,
3042                 void *userdata) {
3043
3044         ExecContext *c = data;
3045         int k;
3046
3047         assert(filename);
3048         assert(lvalue);
3049         assert(rvalue);
3050         assert(data);
3051
3052         k = parse_boolean(rvalue);
3053         if (k < 0) {
3054                 log_syntax(unit, LOG_ERR, filename, line, -k, "Failed to parse boolean value, ignoring: %s", rvalue);
3055                 return 0;
3056         }
3057
3058         c->no_new_privileges = !!k;
3059         c->no_new_privileges_set = true;
3060
3061         return 0;
3062 }
3063
3064 #define FOLLOW_MAX 8
3065
3066 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
3067         unsigned c = 0;
3068         int fd, r;
3069         FILE *f;
3070         char *id = NULL;
3071
3072         assert(filename);
3073         assert(*filename);
3074         assert(_f);
3075         assert(names);
3076
3077         /* This will update the filename pointer if the loaded file is
3078          * reached by a symlink. The old string will be freed. */
3079
3080         for (;;) {
3081                 char *target, *name;
3082
3083                 if (c++ >= FOLLOW_MAX)
3084                         return -ELOOP;
3085
3086                 path_kill_slashes(*filename);
3087
3088                 /* Add the file name we are currently looking at to
3089                  * the names of this unit, but only if it is a valid
3090                  * unit name. */
3091                 name = basename(*filename);
3092
3093                 if (unit_name_is_valid(name, TEMPLATE_VALID)) {
3094
3095                         id = set_get(names, name);
3096                         if (!id) {
3097                                 id = strdup(name);
3098                                 if (!id)
3099                                         return -ENOMEM;
3100
3101                                 r = set_consume(names, id);
3102                                 if (r < 0)
3103                                         return r;
3104                         }
3105                 }
3106
3107                 /* Try to open the file name, but don't if its a symlink */
3108                 fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
3109                 if (fd >= 0)
3110                         break;
3111
3112                 if (errno != ELOOP)
3113                         return -errno;
3114
3115                 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
3116                 r = readlink_and_make_absolute(*filename, &target);
3117                 if (r < 0)
3118                         return r;
3119
3120                 free(*filename);
3121                 *filename = target;
3122         }
3123
3124         f = fdopen(fd, "re");
3125         if (!f) {
3126                 r = -errno;
3127                 safe_close(fd);
3128                 return r;
3129         }
3130
3131         *_f = f;
3132         *_final = id;
3133         return 0;
3134 }
3135
3136 static int merge_by_names(Unit **u, Set *names, const char *id) {
3137         char *k;
3138         int r;
3139
3140         assert(u);
3141         assert(*u);
3142         assert(names);
3143
3144         /* Let's try to add in all symlink names we found */
3145         while ((k = set_steal_first(names))) {
3146