chiark / gitweb /
core: priorize notification fd processing over notification fd process via sd-event...
[elogind.git] / src / core / dbus-execute.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
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <sys/prctl.h>
23
24 #include "bus-util.h"
25 #include "missing.h"
26 #include "ioprio.h"
27 #include "strv.h"
28 #include "syscall-list.h"
29 #include "fileio.h"
30 #include "execute.h"
31 #include "dbus-execute.h"
32
33 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
34
35 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
36
37 static int property_get_environment_files(
38                 sd_bus *bus,
39                 const char *path,
40                 const char *interface,
41                 const char *property,
42                 sd_bus_message *reply,
43                 void *userdata,
44                 sd_bus_error *error) {
45
46         ExecContext *c = userdata;
47         char **j;
48         int r;
49
50         assert(bus);
51         assert(reply);
52         assert(c);
53
54         r = sd_bus_message_open_container(reply, 'a', "(sb)");
55         if (r < 0)
56                 return r;
57
58         STRV_FOREACH(j, c->environment_files) {
59                 const char *fn = *j;
60
61                 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
62                 if (r < 0)
63                         return r;
64         }
65
66         return sd_bus_message_close_container(reply);
67 }
68
69 static int property_get_rlimit(
70                 sd_bus *bus,
71                 const char *path,
72                 const char *interface,
73                 const char *property,
74                 sd_bus_message *reply,
75                 void *userdata,
76                 sd_bus_error *error) {
77
78         struct rlimit *rl;
79         uint64_t u;
80
81         assert(bus);
82         assert(reply);
83         assert(userdata);
84
85         rl = *(struct rlimit**) userdata;
86         if (rl)
87                 u = (uint64_t) rl->rlim_max;
88         else {
89                 struct rlimit buf = {};
90                 int z;
91
92                 z = rlimit_from_string(property);
93                 assert(z >= 0);
94
95                 getrlimit(z, &buf);
96
97                 u = (uint64_t) buf.rlim_max;
98         }
99
100         return sd_bus_message_append(reply, "t", u);
101 }
102
103 static int property_get_oom_score_adjust(
104                 sd_bus *bus,
105                 const char *path,
106                 const char *interface,
107                 const char *property,
108                 sd_bus_message *reply,
109                 void *userdata,
110                 sd_bus_error *error) {
111
112
113         ExecContext *c = userdata;
114         int32_t n;
115
116         assert(bus);
117         assert(reply);
118         assert(c);
119
120         if (c->oom_score_adjust_set)
121                 n = c->oom_score_adjust;
122         else {
123                 _cleanup_free_ char *t = NULL;
124
125                 n = 0;
126                 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
127                         safe_atoi(t, &n);
128         }
129
130         return sd_bus_message_append(reply, "i", n);
131 }
132
133 static int property_get_nice(
134                 sd_bus *bus,
135                 const char *path,
136                 const char *interface,
137                 const char *property,
138                 sd_bus_message *reply,
139                 void *userdata,
140                 sd_bus_error *error) {
141
142
143         ExecContext *c = userdata;
144         int32_t n;
145
146         assert(bus);
147         assert(reply);
148         assert(c);
149
150         if (c->nice_set)
151                 n = c->nice;
152         else {
153                 errno = 0;
154                 n = getpriority(PRIO_PROCESS, 0);
155                 if (errno != 0)
156                         n = 0;
157         }
158
159         return sd_bus_message_append(reply, "i", n);
160 }
161
162 static int property_get_ioprio(
163                 sd_bus *bus,
164                 const char *path,
165                 const char *interface,
166                 const char *property,
167                 sd_bus_message *reply,
168                 void *userdata,
169                 sd_bus_error *error) {
170
171
172         ExecContext *c = userdata;
173         int32_t n;
174
175         assert(bus);
176         assert(reply);
177         assert(c);
178
179         if (c->ioprio_set)
180                 n = c->ioprio;
181         else {
182                 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
183                 if (n < 0)
184                         n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
185         }
186
187         return sd_bus_message_append(reply, "i", n);
188 }
189
190 static int property_get_cpu_sched_policy(
191                 sd_bus *bus,
192                 const char *path,
193                 const char *interface,
194                 const char *property,
195                 sd_bus_message *reply,
196                 void *userdata,
197                 sd_bus_error *error) {
198
199         ExecContext *c = userdata;
200         int32_t n;
201
202         assert(bus);
203         assert(reply);
204         assert(c);
205
206         if (c->cpu_sched_set)
207                 n = c->cpu_sched_policy;
208         else {
209                 n = sched_getscheduler(0);
210                 if (n < 0)
211                         n = SCHED_OTHER;
212         }
213
214         return sd_bus_message_append(reply, "i", n);
215 }
216
217 static int property_get_cpu_sched_priority(
218                 sd_bus *bus,
219                 const char *path,
220                 const char *interface,
221                 const char *property,
222                 sd_bus_message *reply,
223                 void *userdata,
224                 sd_bus_error *error) {
225
226         ExecContext *c = userdata;
227         int32_t n;
228
229         assert(bus);
230         assert(reply);
231         assert(c);
232
233         if (c->cpu_sched_set)
234                 n = c->cpu_sched_priority;
235         else {
236                 struct sched_param p = {};
237
238                 if (sched_getparam(0, &p) >= 0)
239                         n = p.sched_priority;
240                 else
241                         n = 0;
242         }
243
244         return sd_bus_message_append(reply, "i", n);
245 }
246
247 static int property_get_cpu_affinity(
248                 sd_bus *bus,
249                 const char *path,
250                 const char *interface,
251                 const char *property,
252                 sd_bus_message *reply,
253                 void *userdata,
254                 sd_bus_error *error) {
255
256         ExecContext *c = userdata;
257
258         assert(bus);
259         assert(reply);
260         assert(c);
261
262         if (c->cpuset)
263                 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
264         else
265                 return sd_bus_message_append_array(reply, 'y', NULL, 0);
266 }
267
268 static int property_get_timer_slack_nsec(
269                 sd_bus *bus,
270                 const char *path,
271                 const char *interface,
272                 const char *property,
273                 sd_bus_message *reply,
274                 void *userdata,
275                 sd_bus_error *error) {
276
277         ExecContext *c = userdata;
278         uint64_t u;
279
280         assert(bus);
281         assert(reply);
282         assert(c);
283
284         if (c->timer_slack_nsec != (nsec_t) -1)
285                 u = (uint64_t) c->timer_slack_nsec;
286         else
287                 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
288
289         return sd_bus_message_append(reply, "t", u);
290 }
291
292 static int property_get_capability_bounding_set(
293                 sd_bus *bus,
294                 const char *path,
295                 const char *interface,
296                 const char *property,
297                 sd_bus_message *reply,
298                 void *userdata,
299                 sd_bus_error *error) {
300
301         ExecContext *c = userdata;
302
303         assert(bus);
304         assert(reply);
305         assert(c);
306
307         /* We store this negated internally, to match the kernel, but
308          * we expose it normalized. */
309         return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
310 }
311
312 static int property_get_capabilities(
313                 sd_bus *bus,
314                 const char *path,
315                 const char *interface,
316                 const char *property,
317                 sd_bus_message *reply,
318                 void *userdata,
319                 sd_bus_error *error) {
320
321         ExecContext *c = userdata;
322         char *t = NULL;
323         const char *s;
324         int r;
325
326         assert(bus);
327         assert(reply);
328         assert(c);
329
330         if (c->capabilities)
331                 s = t = cap_to_text(c->capabilities, NULL);
332         else
333                 s = "";
334
335         if (!s)
336                 return -ENOMEM;
337
338         r = sd_bus_message_append(reply, "s", s);
339
340         if (t)
341                 cap_free(t);
342
343         return r;
344 }
345
346 static int property_get_syscall_filter(
347                 sd_bus *bus,
348                 const char *path,
349                 const char *interface,
350                 const char *property,
351                 sd_bus_message *reply,
352                 void *userdata,
353                 sd_bus_error *error) {
354
355         ExecContext *c = userdata;
356
357         assert(bus);
358         assert(reply);
359         assert(c);
360
361         if (c->syscall_filter)
362                 return sd_bus_message_append_array(reply, 'u', c->syscall_filter, (syscall_max() + 31) >> 4);
363         else
364                 return sd_bus_message_append_array(reply, 'u', NULL, 0);
365 }
366
367 const sd_bus_vtable bus_exec_vtable[] = {
368         SD_BUS_VTABLE_START(0),
369         SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), 0),
370         SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, 0),
371         SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), 0),
372         SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), 0),
373         SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), 0),
374         SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), 0),
375         SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), 0),
376         SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), 0),
377         SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), 0),
378         SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), 0),
379         SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), 0),
380         SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), 0),
381         SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), 0),
382         SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), 0),
383         SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), 0),
384         SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), 0),
385         SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), 0),
386         SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), 0),
387         SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), 0),
388         SD_BUS_PROPERTY("WorkingDirectory", "s", NULL, offsetof(ExecContext, working_directory), 0),
389         SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), 0),
390         SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, 0),
391         SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, 0),
392         SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, 0),
393         SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, 0),
394         SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, 0),
395         SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, 0),
396         SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, 0),
397         SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), 0),
398         SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), 0),
399         SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), 0),
400         SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), 0),
401         SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), 0),
402         SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), 0),
403         SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), 0),
404         SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), 0),
405         SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), 0),
406         SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), 0),
407         SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), 0),
408         SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), 0),
409         SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, 0),
410         SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), 0),
411         SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, 0),
412         SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), 0),
413         SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), 0),
414         SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), 0),
415         SD_BUS_PROPERTY("TCPWrapName", "s", NULL, offsetof(ExecContext, tcpwrap_name), 0),
416         SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), 0),
417         SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), 0),
418         SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), 0),
419         SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), 0),
420         SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), 0),
421         SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), 0),
422         SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), 0),
423         SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), 0),
424         SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), 0),
425         SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), 0),
426         SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), 0),
427         SD_BUS_PROPERTY("SystemCallFilter", "au", property_get_syscall_filter, 0, 0),
428         SD_BUS_VTABLE_END
429 };
430
431 static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
432         int r;
433
434         assert(reply);
435         assert(c);
436
437         if (!c->path)
438                 return 0;
439
440         r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
441         if (r < 0)
442                 return r;
443
444         r = sd_bus_message_append(reply, "s", c->path);
445         if (r < 0)
446                 return r;
447
448         r = sd_bus_message_append_strv(reply, c->argv);
449         if (r < 0)
450                 return r;
451
452         r = sd_bus_message_append(reply, "bttttuii",
453                                   c->ignore,
454                                   c->exec_status.start_timestamp.realtime,
455                                   c->exec_status.start_timestamp.monotonic,
456                                   c->exec_status.exit_timestamp.realtime,
457                                   c->exec_status.exit_timestamp.monotonic,
458                                   (uint32_t) c->exec_status.pid,
459                                   (int32_t) c->exec_status.code,
460                                   (int32_t) c->exec_status.status);
461         if (r < 0)
462                 return r;
463
464         return sd_bus_message_close_container(reply);
465 }
466
467 int bus_property_get_exec_command(
468                 sd_bus *bus,
469                 const char *path,
470                 const char *interface,
471                 const char *property,
472                 sd_bus_message *reply,
473                 void *userdata,
474                 sd_bus_error *ret_error) {
475
476         ExecCommand *c = (ExecCommand*) userdata;
477         int r;
478
479         assert(bus);
480         assert(reply);
481
482         r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
483         if (r < 0)
484                 return r;
485
486         r = append_exec_command(reply, c);
487         if (r < 0)
488                 return r;
489
490         return sd_bus_message_close_container(reply);
491 }
492
493 int bus_property_get_exec_command_list(
494                 sd_bus *bus,
495                 const char *path,
496                 const char *interface,
497                 const char *property,
498                 sd_bus_message *reply,
499                 void *userdata,
500                 sd_bus_error *ret_error) {
501
502         ExecCommand *c = *(ExecCommand**) userdata;
503         int r;
504
505         assert(bus);
506         assert(reply);
507
508         r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
509         if (r < 0)
510                 return r;
511
512         LIST_FOREACH(command, c, c) {
513                 r = append_exec_command(reply, c);
514                 if (r < 0)
515                         return r;
516         }
517
518         return sd_bus_message_close_container(reply);
519 }