diff options
48 files changed, 413 insertions, 764 deletions
diff --git a/.gitignore b/.gitignore index 1e704a872b..99f361d555 100644 --- a/.gitignore +++ b/.gitignore @@ -26,7 +26,6 @@ /GRTAGS /GSYMS /GTAGS -/accelerometer /ata_id /bootctl /build-aux diff --git a/Makefile-man.am b/Makefile-man.am index 734a923799..74a1f4cb43 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -23,7 +23,6 @@ MANPAGES += \ man/localtime.5 \ man/machine-id.5 \ man/machine-info.5 \ - man/networkctl.1 \ man/os-release.5 \ man/sd-daemon.3 \ man/sd-id128.3 \ @@ -144,7 +143,6 @@ MANPAGES += \ man/systemd.time.7 \ man/systemd.timer.5 \ man/systemd.unit.5 \ - man/sysusers.d.5 \ man/telinit.8 \ man/tmpfiles.d.5 \ man/udev.7 \ @@ -1538,6 +1536,7 @@ endif if ENABLE_NETWORKD MANPAGES += \ + man/networkctl.1 \ man/systemd-networkd-wait-online.service.8 \ man/systemd-networkd.service.8 \ man/systemd.netdev.5 \ @@ -1605,6 +1604,15 @@ man/systemd-rfkill.html: man/systemd-rfkill@.service.html endif +if ENABLE_SYSUSERS +MANPAGES += \ + man/sysusers.d.5 +MANPAGES_ALIAS += \ + # + + +endif + if ENABLE_TIMEDATED MANPAGES += \ man/systemd-timedated.service.8 \ diff --git a/Makefile.am b/Makefile.am index d6e0b4ce39..0fa4cf4824 100644 --- a/Makefile.am +++ b/Makefile.am @@ -708,10 +708,14 @@ noinst_DATA += \ CLEANFILES += \ man/index.html +XML_GLOB = $(wildcard $(top_srcdir)/man/*.xml) NON_INDEX_XML_FILES = $(filter-out man/systemd.index.xml,$(XML_FILES)) SOURCE_XML_FILES = ${patsubst %,$(top_srcdir)/%,$(filter-out man/systemd.directives.xml,$(NON_INDEX_XML_FILES))} -update-man-list: $(top_srcdir)/tools/make-man-rules.py $(SOURCE_XML_FILES) +# This target should only be run manually. It recreates Makefile-man.am +# file in the source directory based on all man/*.xml files. Run it after +# adding, removing, or changing the conditional in a man page. +update-man-list: $(top_srcdir)/tools/make-man-rules.py $(XML_GLOB) $(AM_V_GEN)$(PYTHON) $^ > $(top_srcdir)/Makefile-man.tmp $(AM_V_at)mv $(top_srcdir)/Makefile-man.tmp $(top_srcdir)/Makefile-man.am @echo "Makefile-man.am has been regenerated" @@ -3486,7 +3490,6 @@ dist_network_DATA = \ network/80-container-ve.network dist_udevrules_DATA += \ - rules/42-usb-hid-pm.rules \ rules/50-udev-default.rules \ rules/60-block.rules \ rules/60-drm.rules \ @@ -3498,7 +3501,6 @@ dist_udevrules_DATA += \ rules/60-serial.rules \ rules/64-btrfs.rules \ rules/70-mouse.rules \ - rules/70-touchpad.rules \ rules/75-net-description.rules \ rules/78-sound-card.rules \ rules/80-net-setup-link.rules @@ -3667,8 +3669,7 @@ dist_udevhwdb_DATA = \ hwdb/60-evdev.hwdb \ hwdb/60-keyboard.hwdb \ hwdb/70-mouse.hwdb \ - hwdb/70-pointingstick.hwdb \ - hwdb/70-touchpad.hwdb + hwdb/70-pointingstick.hwdb SYSINIT_TARGET_WANTS += \ systemd-hwdb-update.service @@ -3804,19 +3805,6 @@ dist_udevrules_DATA += \ rules/60-persistent-v4l.rules # ------------------------------------------------------------------------------ -accelerometer_SOURCES = \ - src/udev/accelerometer/accelerometer.c - -accelerometer_LDADD = \ - libshared.la - -udevlibexec_PROGRAMS += \ - accelerometer - -dist_udevrules_DATA += \ - rules/61-accelerometer.rules - -# ------------------------------------------------------------------------------ mtd_probe_SOURCES = \ src/udev/mtd_probe/mtd_probe.c \ src/udev/mtd_probe/mtd_probe.h \ diff --git a/docs/.gitignore b/docs/.gitignore deleted file mode 100644 index ac7af2e80e..0000000000 --- a/docs/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/html/ diff --git a/hwdb/70-touchpad.hwdb b/hwdb/70-touchpad.hwdb deleted file mode 100644 index 8a324466b3..0000000000 --- a/hwdb/70-touchpad.hwdb +++ /dev/null @@ -1,43 +0,0 @@ -# This file is part of systemd. -# -# The lookup keys are composed in: -# 70-touchpad.rules -# -# Note: The format of the "touchpad:" prefix match key is a -# contract between the rules file and the hardware data, it might -# change in later revisions to support more or better matches, it -# is not necessarily expected to be a stable ABI. -# -# Match string format: -# touchpad:pnpid:<pnpid>: -# -# To add local entries, create a new file -# /etc/udev/hwdb.d/71-touchpad-local.hwdb -# and add your rules there. To load the new rules execute (as root): -# udevadm hwdb --update -# udevadm trigger /dev/input/eventXX -# where /dev/input/eventXX is the touchpad in question. If in -# doubt, simply use /dev/input/event* to reload all input rules. -# -# If your changes are generally applicable, open a bug report on -# http://bugs.freedesktop.org/enter_bug.cgi?product=systemd -# and include your new rules, a description of the device, and the -# output of -# udevadm info /dev/input/eventXX -# (or /dev/input/event*). -# -# Allowed properties are: -# TOUCHPAD_HAS_TRACKPOINT_BUTTONS=1 -# -# If the TOUCHPAD_HAS_TRACKPOINT_BUTTONS property is set, this -# device has # the trackpoint buttons wired up to the touchpad as -# BTN_0, BTN_1 and BTN_2. This affects the Lenovo X1 Carbon 3rd -# and the *50 series (T450, T550, etc.) - -# Lenovo X1 Carbon 3rd -touchpad:pnpid:*LEN0048*: -# Lenovo W541 -touchpad:pnpid:*LEN004a*: -# Lenovo T450s -touchpad:pnpid:*LEN200f*: - TOUCHPAD_HAS_TRACKPOINT_BUTTONS=1 diff --git a/man/journalctl.xml b/man/journalctl.xml index 08de0ff068..ca933645a9 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -111,9 +111,9 @@ <para>All users are granted access to their private per-user journals. However, by default, only root and users who are members of a few special groups are granted access to the system - journal and the journals of other users. Members of the the + journal and the journals of other users. Members of the groups <literal>systemd-journal</literal>, <literal>adm</literal>, and - <literal>wheel</literal> groups can read all journal files. Note + <literal>wheel</literal> can read all journal files. Note that the two latter groups traditionally have additional privileges specified by the distribution. Members of the <literal>wheel</literal> group can often perform administrative diff --git a/man/machinectl.xml b/man/machinectl.xml index cf17349a6c..4b87870853 100644 --- a/man/machinectl.xml +++ b/man/machinectl.xml @@ -628,7 +628,7 @@ <para>Image verification is identical for raw and tar images (see above).</para> - <para>If the the downloaded image is in + <para>If the downloaded image is in <filename>.qcow2</filename> format it is converted into a raw image file before it is made available.</para> diff --git a/man/networkctl.xml b/man/networkctl.xml index 884d2005c4..388afbed93 100644 --- a/man/networkctl.xml +++ b/man/networkctl.xml @@ -64,7 +64,7 @@ state of the network links as seen by <command>systemd-networkd</command>. Please refer to <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> - for an introduction to the the basic concepts, functionality, and + for an introduction to the basic concepts, functionality, and configuration syntax.</para> </refsect1> diff --git a/man/sd_notify.xml b/man/sd_notify.xml index 87e59c9cc2..14030f56b1 100644 --- a/man/sd_notify.xml +++ b/man/sd_notify.xml @@ -197,7 +197,7 @@ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry> for information how to enable this functionality and <citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry> - for the details of how the service can check if the the + for the details of how the service can check whether the watchdog is enabled. </para></listitem> </varlistentry> diff --git a/man/systemctl.xml b/man/systemctl.xml index 409b6f0895..e18ef6f898 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -1181,9 +1181,9 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service <replaceable>NAME</replaceable>...</command></term> <listitem> - <para>Adds <literal>Wants=</literal> resp. <literal>Requires=</literal> - dependency to the specified <replaceable>TARGET</replaceable> for - one or more units. </para> + <para>Adds <literal>Wants=</literal> or <literal>Requires=</literal> + dependency, respectively, to the specified + <replaceable>TARGET</replaceable> for one or more units. </para> <para>This command honors <option>--system</option>, <option>--user</option>, <option>--runtime</option> and diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 64877720bc..45a4422dc3 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -858,9 +858,10 @@ <listitem><para>Takes a boolean argument or <literal>read-only</literal>. If true, the directories - <filename>/home</filename> and <filename>/run/user</filename> + <filename>/home</filename>, <filename>/root</filename> and + <filename>/run/user</filename> are made inaccessible and empty for processes invoked by this - unit. If set to <literal>read-only</literal>, the two + unit. If set to <literal>read-only</literal>, the three directories are made read-only instead. It is recommended to enable this setting for all long-running services (in particular network-facing ones), to ensure they cannot get diff --git a/man/systemd.service.xml b/man/systemd.service.xml index 1e949f0c52..4368ca8a19 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -226,7 +226,10 @@ services where <varname>Type=</varname> is set to <option>forking</option>. systemd will read the PID of the main process of the daemon after start-up of the service. - systemd will not write to the file configured here.</para> + systemd will not write to the file configured here, although + it will remove the file after the service has shut down if it + still exists. + </para> </listitem> </varlistentry> diff --git a/man/systemd.time.xml b/man/systemd.time.xml index da0729725d..64358351d5 100644 --- a/man/systemd.time.xml +++ b/man/systemd.time.xml @@ -125,7 +125,7 @@ (<literal>Wednesday</literal>) English language form (case does not matter), and is not subject to the locale choice of the user. Either the date, or the time part may be omitted, in which case - the current date or 00:00:00, resp., is assumed. The seconds + the current date or 00:00:00, respectively, is assumed. The seconds component of the time may also be omitted, in which case ":00" is assumed. Year numbers may be specified in full or may be abbreviated (omitting the century).</para> diff --git a/man/udev.xml b/man/udev.xml index 4c2e13ee7b..2e1655bf55 100644 --- a/man/udev.xml +++ b/man/udev.xml @@ -522,15 +522,6 @@ </varlistentry> <varlistentry> - <term><varname>WAIT_FOR</varname></term> - <listitem> - <para>Wait for a file to become available or until a timeout of - 10 seconds expires. The path is relative to the sysfs device; - if no path is specified, this waits for an attribute to appear.</para> - </listitem> - </varlistentry> - - <varlistentry> <term><varname>OPTIONS</varname></term> <listitem> <para>Rule and device options:</para> diff --git a/rules/42-usb-hid-pm.rules b/rules/42-usb-hid-pm.rules deleted file mode 100644 index 3721219098..0000000000 --- a/rules/42-usb-hid-pm.rules +++ /dev/null @@ -1,36 +0,0 @@ -# do not edit this file, it will be overwritten on update -# -# Enable autosuspend for qemu emulated usb hid devices - -# Note that there are buggy qemu versions (0.13 & older) which -# advertise remote wakeup support but don't actually implement -# it correctly. This is the reason why we need a match for the -# serial number here. Old, broken versions have serial "1". -# It has been changed to "42" after fixing the bug to indicate -# remote wakeup is working. -ACTION=="add", SUBSYSTEM=="usb", ATTR{product}=="QEMU USB Mouse", ATTR{serial}!="1", TEST=="power/control", ATTR{power/control}="auto" -ACTION=="add", SUBSYSTEM=="usb", ATTR{product}=="QEMU USB Tablet", ATTR{serial}!="1", TEST=="power/control", ATTR{power/control}="auto" -ACTION=="add", SUBSYSTEM=="usb", ATTR{product}=="QEMU USB Keyboard", ATTR{serial}!="1", TEST=="power/control", ATTR{power/control}="auto" - -# Dell DRAC 4 -ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="413c", ATTR{idProduct}=="2500", TEST=="power/control", ATTR{power/control}="auto" - -# Dell DRAC 5 -ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="413c", ATTR{idProduct}=="0000", TEST=="power/control", ATTR{power/control}="auto" - -# IBM remote access -ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="04b3", ATTR{idProduct}=="4001", TEST=="power/control", ATTR{power/control}="auto" -ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="04b3", ATTR{idProduct}=="4002", TEST=="power/control", ATTR{power/control}="auto" -ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="04b3", ATTR{idProduct}=="4012", TEST=="power/control", ATTR{power/control}="auto" - -# Raritan Computer, Inc KVM. -ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="14dd", ATTR{idProduct}=="0002", TEST=="power/control", ATTR{power/control}="auto" - -# USB HID devices that are internal to the machine should also be safe to autosuspend - -ACTION=="add", SUBSYSTEM=="usb", SUBSYSTEMS=="usb", ATTR{../removable}=="removable", GOTO="usb_hid_pm_end" -ACTION=="add", SUBSYSTEM=="usb", SUBSYSTEMS=="usb", ATTR{../removable}=="unknown", GOTO="usb_hid_pm_end" - -ACTION=="add", SUBSYSTEM=="usb", ATTR{bInterfaceClass}=="03", ATTR{../removable}=="fixed", TEST=="../power/control", ATTR{../power/control}="auto" - -LABEL="usb_hid_pm_end" diff --git a/rules/60-persistent-storage.rules b/rules/60-persistent-storage.rules index 71b8e46ae8..90b62cc490 100644 --- a/rules/60-persistent-storage.rules +++ b/rules/60-persistent-storage.rules @@ -6,7 +6,7 @@ ACTION=="remove", GOTO="persistent_storage_end" SUBSYSTEM!="block", GOTO="persistent_storage_end" -KERNEL!="loop*|mmcblk*[0-9]|msblk*[0-9]|mspblk*[0-9]|nvme*|sd*|sr*|vd*|xvd*|bcache*", GOTO="persistent_storage_end" +KERNEL!="loop*|mmcblk*[0-9]|msblk*[0-9]|mspblk*[0-9]|nvme*|sd*|sr*|vd*|xvd*|bcache*|cciss*", GOTO="persistent_storage_end" # ignore partitions that span the entire disk TEST=="whole_disk", GOTO="persistent_storage_end" diff --git a/rules/61-accelerometer.rules b/rules/61-accelerometer.rules deleted file mode 100644 index a6a2bfd088..0000000000 --- a/rules/61-accelerometer.rules +++ /dev/null @@ -1,3 +0,0 @@ -# do not edit this file, it will be overwritten on update - -SUBSYSTEM=="input", ACTION!="remove", ENV{ID_INPUT_ACCELEROMETER}=="1", IMPORT{program}="accelerometer %p" diff --git a/rules/70-touchpad.rules b/rules/70-touchpad.rules deleted file mode 100644 index 88e6fd2f25..0000000000 --- a/rules/70-touchpad.rules +++ /dev/null @@ -1,12 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION=="remove", GOTO="touchpad_end" -KERNEL!="event*", GOTO="touchpad_end" -ENV{ID_INPUT_TOUCHPAD}=="", GOTO="touchpad_end" - -# touchpad:pnpid:<pnpid>:* -KERNELS=="serio1", \ - IMPORT{builtin}="hwdb 'touchpad:pnpid:$attr{firmware_id}:'", \ - GOTO="touchpad_end" - -LABEL="touchpad_end" diff --git a/src/basic/socket-label.c b/src/basic/socket-label.c index cbe3ff216e..144e6fd86e 100644 --- a/src/basic/socket-label.c +++ b/src/basic/socket-label.c @@ -38,6 +38,7 @@ int socket_address_listen( int backlog, SocketAddressBindIPv6Only only, const char *bind_to_device, + bool reuse_port, bool free_bind, bool transparent, mode_t directory_mode, @@ -83,6 +84,12 @@ int socket_address_listen( if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, bind_to_device, strlen(bind_to_device)+1) < 0) return -errno; + if (reuse_port) { + one = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) < 0) + log_warning_errno(errno, "SO_REUSEPORT failed: %m"); + } + if (free_bind) { one = 1; if (setsockopt(fd, IPPROTO_IP, IP_FREEBIND, &one, sizeof(one)) < 0) @@ -146,7 +153,7 @@ int make_socket_fd(int log_level, const char* address, int flags) { } fd = socket_address_listen(&a, flags, SOMAXCONN, SOCKET_ADDRESS_DEFAULT, - NULL, false, false, 0755, 0644, NULL); + NULL, false, false, false, 0755, 0644, NULL); if (fd < 0 || log_get_max_level() >= log_level) { _cleanup_free_ char *p = NULL; diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 538cf59174..6b0ce7836f 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -80,6 +80,7 @@ int socket_address_listen( int backlog, SocketAddressBindIPv6Only only, const char *bind_to_device, + bool reuse_port, bool free_bind, bool transparent, mode_t directory_mode, diff --git a/src/basic/util.c b/src/basic/util.c index 727be56f58..906e4abad6 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -3627,7 +3627,7 @@ bool string_is_safe(const char *p) { if (*t > 0 && *t < ' ') return false; - if (strchr("\\\"\'\0x7f", *t)) + if (strchr("\\\"\'\x7f", *t)) return false; } diff --git a/src/bootchart/store.c b/src/bootchart/store.c index f159cbafe2..caa97b97fc 100644 --- a/src/bootchart/store.c +++ b/src/bootchart/store.c @@ -37,6 +37,7 @@ #include "store.h" #include "bootchart.h" #include "cgroup-util.h" +#include "fileio.h" /* * Alloc a static 4k buffer for stdio - primarily used to increase @@ -97,13 +98,14 @@ int log_sample(DIR *proc, int *cpus) { static int vmstat = -1; - static int schedstat = -1; + _cleanup_free_ char *buf_schedstat = NULL; char buf[4096]; char key[256]; char val[256]; char rt[256]; char wt[256]; char *m; + int r; int c; int p; int mod; @@ -115,6 +117,7 @@ int log_sample(DIR *proc, struct list_sample_data *sampledata; struct ps_sched_struct *ps_prev = NULL; int procfd; + int taskfd = -1; sampledata = *ptr; @@ -155,27 +158,13 @@ vmstat_next: break; } - if (schedstat < 0) { - /* overall CPU utilization */ - schedstat = openat(procfd, "schedstat", O_RDONLY|O_CLOEXEC); - if (schedstat < 0) - return log_error_errno(errno, "Failed to open /proc/schedstat (requires CONFIG_SCHEDSTATS=y in kernel config): %m"); - } - - n = pread(schedstat, buf, sizeof(buf) - 1, 0); - if (n <= 0) { - schedstat = safe_close(schedstat); - if (n < 0) - return -errno; - return -ENODATA; - } + /* Parse "/proc/schedstat" for overall CPU utilization */ + r = read_full_file("/proc/schedstat", &buf_schedstat, NULL); + if (r < 0) + return log_error_errno(r, "Unable to read schedstat: %m"); - buf[n] = '\0'; - - m = buf; + m = buf_schedstat; while (m) { - int r; - if (sscanf(m, "%s %*s %*s %*s %*s %*s %*s %s %s", key, rt, wt) < 3) goto schedstat_next; @@ -237,7 +226,6 @@ schedstat_next: _cleanup_fclose_ FILE *st = NULL; char t[32]; struct ps_struct *parent; - int r; ps->next_ps = new0(struct ps_struct, 1); if (!ps->next_ps) @@ -409,6 +397,62 @@ schedstat_next: ps->total = (ps->last->runtime - ps->first->runtime) / 1000000000.0; + /* Take into account CPU runtime/waittime spent in non-main threads of the process + * by parsing "/proc/[pid]/task/[tid]/schedstat" for all [tid] != [pid] + * See https://github.com/systemd/systemd/issues/139 + */ + + /* Browse directory "/proc/[pid]/task" to know the thread ids of process [pid] */ + snprintf(filename, sizeof(filename), PID_FMT "/task", pid); + taskfd = openat(procfd, filename, O_RDONLY|O_DIRECTORY|O_CLOEXEC); + if (taskfd >= 0) { + _cleanup_closedir_ DIR *taskdir = NULL; + + taskdir = fdopendir(taskfd); + if (!taskdir) { + safe_close(taskfd); + return -errno; + } + FOREACH_DIRENT(ent, taskdir, break) { + int tid = -1; + _cleanup_close_ int tid_schedstat = -1; + long long delta_rt; + long long delta_wt; + + if ((ent->d_name[0] < '0') || (ent->d_name[0] > '9')) + continue; + + /* Skip main thread as it was already accounted */ + r = safe_atoi(ent->d_name, &tid); + if (r < 0 || tid == pid) + continue; + + /* Parse "/proc/[pid]/task/[tid]/schedstat" */ + snprintf(filename, sizeof(filename), PID_FMT "/schedstat", tid); + tid_schedstat = openat(taskfd, filename, O_RDONLY|O_CLOEXEC); + + if (tid_schedstat == -1) + continue; + + s = pread(tid_schedstat, buf, sizeof(buf) - 1, 0); + if (s <= 0) + continue; + buf[s] = '\0'; + + if (!sscanf(buf, "%s %s %*s", rt, wt)) + continue; + + r = safe_atolli(rt, &delta_rt); + if (r < 0) + continue; + r = safe_atolli(rt, &delta_wt); + if (r < 0) + continue; + ps->sample->runtime += delta_rt; + ps->sample->waittime += delta_wt; + } + } + if (!arg_pss) goto catch_rename; diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c index f442200b66..a7ef653d5d 100644 --- a/src/bootchart/svg.c +++ b/src/bootchart/svg.c @@ -76,8 +76,6 @@ static void svg_header(FILE *of, struct list_sample_data *head, double graph_sta assert(head); - sampledata = head; - LIST_FIND_TAIL(link, sampledata, head); sampledata_last = head; LIST_FOREACH_BEFORE(link, sampledata, head) { sampledata_last = sampledata; @@ -174,7 +172,7 @@ static int svg_title(FILE *of, const char *build, int pscount, double log_start, r = read_one_line_file(filename, &model); if (r < 0) - log_warning("Error reading disk model for %s: %m\n", rootbdev); + log_info("Error reading disk model for %s: %m\n", rootbdev); } /* various utsname parameters */ @@ -210,7 +208,8 @@ static int svg_title(FILE *of, const char *build, int pscount, double log_start, fprintf(of, "<text class=\"t2\" x=\"20\" y=\"50\">System: %s %s %s %s</text>\n", uts.sysname, uts.release, uts.version, uts.machine); fprintf(of, "<text class=\"t2\" x=\"20\" y=\"65\">CPU: %s</text>\n", cpu); - fprintf(of, "<text class=\"t2\" x=\"20\" y=\"80\">Disk: %s</text>\n", model); + if (model) + fprintf(of, "<text class=\"t2\" x=\"20\" y=\"80\">Disk: %s</text>\n", model); fprintf(of, "<text class=\"t2\" x=\"20\" y=\"95\">Boot options: %s</text>\n", cmdline); fprintf(of, "<text class=\"t2\" x=\"20\" y=\"110\">Build: %s</text>\n", build); fprintf(of, "<text class=\"t2\" x=\"20\" y=\"125\">Log start time: %.03fs</text>\n", log_start); @@ -1296,6 +1295,8 @@ int svg_do(FILE *of, double offset = 7; int r, c; + sampledata = head; + LIST_FIND_TAIL(link, sampledata, head); ps = ps_first; /* count initcall thread count first */ diff --git a/src/bus-proxyd/proxy.c b/src/bus-proxyd/proxy.c index 28ab1c97fc..1dc55171e7 100644 --- a/src/bus-proxyd/proxy.c +++ b/src/bus-proxyd/proxy.c @@ -494,7 +494,16 @@ static int process_policy_unlocked(sd_bus *from, sd_bus *to, sd_bus_message *m, } /* First check if we (the sender) can send to this name */ - if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, destination_names, m->path, m->interface, m->member, true, &n)) { + if (sd_bus_message_is_signal(m, NULL, NULL)) { + /* If we forward a signal from dbus-1 to kdbus, we have + * no idea who the recipient is. Therefore, we cannot + * apply any dbus-1 policies that match on receiver + * credentials. We know sd-bus always sets + * KDBUS_MSG_SIGNAL, so the kernel applies policies to + * the message. Therefore, skip policy checks in this + * case. */ + return 0; + } else if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, destination_names, m->path, m->interface, m->member, true, &n)) { if (n) { /* If we made a receiver decision, then remember which * name's policy we used, and to which unique ID it @@ -512,19 +521,8 @@ static int process_policy_unlocked(sd_bus *from, sd_bus *to, sd_bus_message *m, return r; } - if (sd_bus_message_is_signal(m, NULL, NULL)) { - /* If we forward a signal from dbus-1 to kdbus, - * we have no idea who the recipient is. - * Therefore, we cannot apply any dbus-1 - * receiver policies that match on receiver - * credentials. We know sd-bus always sets - * KDBUS_MSG_SIGNAL, so the kernel applies - * receiver policies to the message. Therefore, - * skip policy checks in this case. */ - return 0; - } else if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, true)) { + if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, true)) return 0; - } } /* Return an error back to the caller */ diff --git a/src/core/kmod-setup.c b/src/core/kmod-setup.c index e7a6bdc8c4..fc6d2f4acb 100644 --- a/src/core/kmod-setup.c +++ b/src/core/kmod-setup.c @@ -116,7 +116,7 @@ int kmod_setup(void) { else if (r == KMOD_PROBE_APPLY_BLACKLIST) log_info("Module '%s' is blacklisted", kmod_module_get_name(mod)); else { - bool print_warning = kmod_table[i].warn_if_unavailable || (r < 0 && r != -ENOSYS); + bool print_warning = kmod_table[i].warn_if_unavailable || (r < 0 && r != -ENOENT); log_full_errno(print_warning ? LOG_WARNING : LOG_DEBUG, r, "Failed to insert module '%s': %m", kmod_module_get_name(mod)); diff --git a/src/core/main.c b/src/core/main.c index 332453a0ea..523f0ce020 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1995,6 +1995,10 @@ finish: command_line[pos++] = "kmsg"; break; + case LOG_TARGET_NULL: + command_line[pos++] = "null"; + break; + case LOG_TARGET_CONSOLE: default: command_line[pos++] = "console"; diff --git a/src/core/socket.c b/src/core/socket.c index d3178e642b..693cbc6080 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -922,12 +922,6 @@ static void socket_apply_socket_options(Socket *s, int fd) { if (setsockopt(fd, SOL_TCP, TCP_CONGESTION, s->tcp_congestion, strlen(s->tcp_congestion)+1) < 0) log_unit_warning_errno(UNIT(s), errno, "TCP_CONGESTION failed: %m"); - if (s->reuse_port) { - int b = s->reuse_port; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &b, sizeof(b)) < 0) - log_unit_warning_errno(UNIT(s), errno, "SO_REUSEPORT failed: %m"); - } - if (s->smack_ip_in) { r = mac_smack_apply_ip_in_fd(fd, s->smack_ip_in); if (r < 0) @@ -1183,6 +1177,7 @@ static int socket_open_fds(Socket *s) { s->backlog, s->bind_ipv6_only, s->bind_to_device, + s->reuse_port, s->free_bind, s->transparent, s->directory_mode, diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index f08db2da89..e3fac01f92 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -1385,15 +1385,16 @@ int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) { r = 0; } - } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL) + if (r <= 0) + close_kdbus_msg(bus, k); + } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL) { r = bus_kernel_translate_message(bus, k); - else { + close_kdbus_msg(bus, k); + } else { log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type); r = 0; - } - - if (r <= 0) close_kdbus_msg(bus, k); + } return r < 0 ? r : 1; } diff --git a/src/libsystemd/sd-netlink/netlink-internal.h b/src/libsystemd/sd-netlink/netlink-internal.h index 7290f4e875..b8a3668bfc 100644 --- a/src/libsystemd/sd-netlink/netlink-internal.h +++ b/src/libsystemd/sd-netlink/netlink-internal.h @@ -92,18 +92,25 @@ struct sd_netlink { sd_event *event; }; +struct netlink_attribute { + size_t offset; /* offset from hdr to attirubte */ +}; + +struct netlink_container { + const struct NLTypeSystem *type_system; /* the type system of the container */ + size_t offset; /* offset from hdr to the start of the container */ + struct netlink_attribute *attributes; + unsigned short n_attributes; /* number of attributes in container */ +}; + struct sd_netlink_message { RefCount n_ref; sd_netlink *rtnl; struct nlmsghdr *hdr; - const struct NLTypeSystem *(container_type_system[RTNL_CONTAINER_DEPTH]); /* the type of the container and all its parents */ - size_t container_offsets[RTNL_CONTAINER_DEPTH]; /* offset from hdr to each container's start */ + struct netlink_container containers[RTNL_CONTAINER_DEPTH]; unsigned n_containers; /* number of containers */ - size_t next_rta_offset; /* offset from hdr to next rta */ - size_t *rta_offset_tb[RTNL_CONTAINER_DEPTH]; - unsigned short rta_tb_size[RTNL_CONTAINER_DEPTH]; bool sealed:1; bool broadcast:1; @@ -122,14 +129,6 @@ int socket_read_message(sd_netlink *nl); int rtnl_rqueue_make_room(sd_netlink *rtnl); int rtnl_rqueue_partial_make_room(sd_netlink *rtnl); -int rtnl_message_read_internal(sd_netlink_message *m, unsigned short type, void **data); -int rtnl_message_parse(sd_netlink_message *m, - size_t **rta_offset_tb, - unsigned short *rta_tb_size, - int max, - struct rtattr *rta, - unsigned int rt_len); - /* Make sure callbacks don't destroy the rtnl connection */ #define RTNL_DONT_DESTROY(rtnl) \ _cleanup_netlink_unref_ _unused_ sd_netlink *_dont_destroy_##rtnl = sd_netlink_ref(rtnl) diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c index a935b821f6..13573dcea8 100644 --- a/src/libsystemd/sd-netlink/netlink-message.c +++ b/src/libsystemd/sd-netlink/netlink-message.c @@ -34,7 +34,7 @@ #include "netlink-internal.h" #include "netlink-types.h" -#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL) +#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset) : NULL) #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr; #define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK) @@ -88,7 +88,7 @@ int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) { m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - type_get_type_system(nl_type, &m->container_type_system[0]); + type_get_type_system(nl_type, &m->containers[0].type_system); m->hdr->nlmsg_len = size; m->hdr->nlmsg_type = type; @@ -129,7 +129,7 @@ sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m) { free(m->hdr); for (i = 0; i <= m->n_containers; i++) - free(m->rta_offset_tb[i]); + free(m->containers[i].attributes); sd_netlink_message_unref(m->next); @@ -223,7 +223,7 @@ static int message_attribute_has_type(sd_netlink_message *m, size_t *out_size, u assert(m); - r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type); + r = type_system_get_type(m->containers[m->n_containers].type_system, &type, attribute_type); if (r < 0) return r; @@ -406,18 +406,18 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type if (r < 0) return r; - r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type); + r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type); if (r < 0) return r; r = type_system_union_protocol_get_type_system(type_system_union, - &m->container_type_system[m->n_containers + 1], + &m->containers[m->n_containers + 1].type_system, family); if (r < 0) return r; } else { - r = type_system_get_type_system(m->container_type_system[m->n_containers], - &m->container_type_system[m->n_containers + 1], + r = type_system_get_type_system(m->containers[m->n_containers].type_system, + &m->containers[m->n_containers + 1].type_system, type); if (r < 0) return r; @@ -427,7 +427,7 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type if (r < 0) return r; - m->container_offsets[m->n_containers ++] = r; + m->containers[m->n_containers ++].offset = r; return 0; } @@ -439,12 +439,12 @@ int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned shor assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); - r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type); + r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type); if (r < 0) return r; r = type_system_union_get_type_system(type_system_union, - &m->container_type_system[m->n_containers + 1], + &m->containers[m->n_containers + 1].type_system, key); if (r < 0) return r; @@ -454,11 +454,11 @@ int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned shor return r; /* do we evere need non-null size */ - r = add_rtattr(m, type, NULL, 0); + r = add_rtattr(m, type | NLA_F_NESTED, NULL, 0); if (r < 0) return r; - m->container_offsets[m->n_containers ++] = r; + m->containers[m->n_containers ++].offset = r; return 0; } @@ -469,26 +469,29 @@ int sd_netlink_message_close_container(sd_netlink_message *m) { assert_return(!m->sealed, -EPERM); assert_return(m->n_containers > 0, -EINVAL); - m->container_type_system[m->n_containers] = NULL; + m->containers[m->n_containers].type_system = NULL; m->n_containers --; return 0; } -int rtnl_message_read_internal(sd_netlink_message *m, unsigned short type, void **data) { +static int netlink_message_read_internal(sd_netlink_message *m, unsigned short type, void **data) { + struct netlink_attribute *attribute; struct rtattr *rta; assert_return(m, -EINVAL); assert_return(m->sealed, -EPERM); assert_return(data, -EINVAL); assert(m->n_containers <= RTNL_CONTAINER_DEPTH); - assert(m->rta_offset_tb[m->n_containers]); - assert(type < m->rta_tb_size[m->n_containers]); + assert(m->containers[m->n_containers].attributes); + assert(type < m->containers[m->n_containers].n_attributes); - if(!m->rta_offset_tb[m->n_containers][type]) + attribute = &m->containers[m->n_containers].attributes[type]; + + if(!attribute->offset) return -ENODATA; - rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]); + rta = (struct rtattr*)((uint8_t *) m->hdr + attribute->offset); *data = RTA_DATA(rta); @@ -505,7 +508,7 @@ int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, c if (r < 0) return r; - r = rtnl_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data); if (r < 0) return r; else if (strnlen(attr_data, r) >= (size_t) r) @@ -527,7 +530,7 @@ int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8 if (r < 0) return r; - r = rtnl_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data); if (r < 0) return r; else if ((size_t) r < sizeof(uint8_t)) @@ -549,7 +552,7 @@ int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint if (r < 0) return r; - r = rtnl_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data); if (r < 0) return r; else if ((size_t) r < sizeof(uint16_t)) @@ -571,7 +574,7 @@ int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint if (r < 0) return r; - r = rtnl_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data); if (r < 0) return r; else if ((size_t)r < sizeof(uint32_t)) @@ -593,7 +596,7 @@ int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short typ if (r < 0) return r; - r = rtnl_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data); if (r < 0) return r; else if ((size_t)r < sizeof(struct ether_addr)) @@ -615,7 +618,7 @@ int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short typ if (r < 0) return r; - r = rtnl_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data); if (r < 0) return r; else if ((size_t)r < sizeof(struct ifa_cacheinfo)) @@ -637,7 +640,7 @@ int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, if (r < 0) return r; - r = rtnl_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data); if (r < 0) return r; else if ((size_t)r < sizeof(struct in_addr)) @@ -659,7 +662,7 @@ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, if (r < 0) return r; - r = rtnl_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data); if (r < 0) return r; else if ((size_t)r < sizeof(struct in6_addr)) @@ -671,6 +674,40 @@ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, return 0; } +static int netlink_container_parse(sd_netlink_message *m, + struct netlink_container *container, + int count, + struct rtattr *rta, + unsigned int rt_len) { + _cleanup_free_ struct netlink_attribute *attributes = NULL; + + attributes = new0(struct netlink_attribute, count); + if(!attributes) + return -ENOMEM; + + for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) { + unsigned short type; + + type = RTA_TYPE(rta); + + /* if the kernel is newer than the headers we used + when building, we ignore out-of-range attributes */ + if (type >= count) + continue; + + if (attributes[type].offset) + log_debug("rtnl: message parse - overwriting repeated attribute"); + + attributes[type].offset = (uint8_t *) rta - (uint8_t *) m->hdr; + } + + container->attributes = attributes; + attributes = NULL; + container->n_attributes = count; + + return 0; +} + int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type_id) { const NLType *nl_type; const NLTypeSystem *type_system; @@ -682,7 +719,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ assert_return(m, -EINVAL); assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL); - r = type_system_get_type(m->container_type_system[m->n_containers], + r = type_system_get_type(m->containers[m->n_containers].type_system, &nl_type, type_id); if (r < 0) @@ -691,7 +728,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ type = type_get_type(nl_type); if (type == NETLINK_TYPE_NESTED) { - r = type_system_get_type_system(m->container_type_system[m->n_containers], + r = type_system_get_type_system(m->containers[m->n_containers].type_system, &type_system, type_id); if (r < 0) @@ -699,7 +736,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ } else if (type == NETLINK_TYPE_UNION) { const NLTypeSystemUnion *type_system_union; - r = type_system_get_type_system_union(m->container_type_system[m->n_containers], + r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type_id); if (r < 0) @@ -744,7 +781,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ } else return -EINVAL; - r = rtnl_message_read_internal(m, type_id, &container); + r = netlink_message_read_internal(m, type_id, &container); if (r < 0) return r; else @@ -752,18 +789,17 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ m->n_containers ++; - r = rtnl_message_parse(m, - &m->rta_offset_tb[m->n_containers], - &m->rta_tb_size[m->n_containers], - type_system_get_count(type_system), - container, - size); + r = netlink_container_parse(m, + &m->containers[m->n_containers], + type_system_get_count(type_system), + container, + size); if (r < 0) { m->n_containers --; return r; } - m->container_type_system[m->n_containers] = type_system; + m->containers[m->n_containers].type_system = type_system; return 0; } @@ -773,9 +809,9 @@ int sd_netlink_message_exit_container(sd_netlink_message *m) { assert_return(m->sealed, -EINVAL); assert_return(m->n_containers > 0, -EINVAL); - free(m->rta_offset_tb[m->n_containers]); - m->rta_offset_tb[m->n_containers] = NULL; - m->container_type_system[m->n_containers] = NULL; + free(m->containers[m->n_containers].attributes); + m->containers[m->n_containers].attributes = NULL; + m->containers[m->n_containers].type_system = NULL; m->n_containers --; @@ -810,41 +846,6 @@ int sd_netlink_message_get_errno(sd_netlink_message *m) { return err->error; } -int rtnl_message_parse(sd_netlink_message *m, - size_t **rta_offset_tb, - unsigned short *rta_tb_size, - int count, - struct rtattr *rta, - unsigned int rt_len) { - unsigned short type; - size_t *tb; - - tb = new0(size_t, count); - if(!tb) - return -ENOMEM; - - *rta_tb_size = count; - - for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) { - type = RTA_TYPE(rta); - - /* if the kernel is newer than the headers we used - when building, we ignore out-of-range attributes - */ - if (type >= count) - continue; - - if (tb[type]) - log_debug("rtnl: message parse - overwriting repeated attribute"); - - tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr; - } - - *rta_offset_tb = tb; - - return 0; -} - int sd_netlink_message_rewind(sd_netlink_message *m) { const NLType *nl_type; uint16_t type; @@ -859,15 +860,13 @@ int sd_netlink_message_rewind(sd_netlink_message *m) { rtnl_message_seal(m); for (i = 1; i <= m->n_containers; i++) { - free(m->rta_offset_tb[i]); - m->rta_offset_tb[i] = NULL; - m->rta_tb_size[i] = 0; - m->container_type_system[i] = NULL; + free(m->containers[i].attributes); + m->containers[i].attributes = NULL; } m->n_containers = 0; - if (m->rta_offset_tb[0]) { + if (m->containers[0].attributes) { /* top-level attributes have already been parsed */ return 0; } @@ -886,14 +885,13 @@ int sd_netlink_message_rewind(sd_netlink_message *m) { type_get_type_system(nl_type, &type_system); - m->container_type_system[0] = type_system; + m->containers[0].type_system = type_system; - r = rtnl_message_parse(m, - &m->rta_offset_tb[m->n_containers], - &m->rta_tb_size[m->n_containers], - type_system_get_count(type_system), - (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)), - NLMSG_PAYLOAD(m->hdr, size)); + r = netlink_container_parse(m, + &m->containers[m->n_containers], + type_system_get_count(type_system), + (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)), + NLMSG_PAYLOAD(m->hdr, size)); if (r < 0) return r; } diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 8ebcd3f5ca..659ce18a48 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -690,6 +690,8 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus } manager_get_session_by_pid(m, leader, &session); + if (!session && vtnr > 0) + session = (vtnr < m->seat0->position_count) ? m->seat0->positions[vtnr] : NULL; if (session) { _cleanup_free_ char *path = NULL; _cleanup_close_ int fifo_fd = -1; @@ -1486,18 +1488,13 @@ static int execute_shutdown_or_sleep( return 0; } -static int manager_inhibit_timeout_handler( - sd_event_source *s, - uint64_t usec, - void *userdata) { +int manager_dispatch_delayed(Manager *manager, bool timeout) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; Inhibitor *offending = NULL; - Manager *manager = userdata; int r; assert(manager); - assert(manager->inhibit_timeout_source == s); if (manager->action_what == 0 || manager->action_job) return 0; @@ -1505,6 +1502,9 @@ static int manager_inhibit_timeout_handler( if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) { _cleanup_free_ char *comm = NULL, *u = NULL; + if (!timeout) + return 0; + (void) get_process_comm(offending->pid, &comm); u = uid_to_name(offending->uid); @@ -1520,9 +1520,25 @@ static int manager_inhibit_timeout_handler( manager->action_unit = NULL; manager->action_what = 0; + return r; } - return 0; + return 1; +} + +static int manager_inhibit_timeout_handler( + sd_event_source *s, + uint64_t usec, + void *userdata) { + + Manager *manager = userdata; + int r; + + assert(manager); + assert(manager->inhibit_timeout_source == s); + + r = manager_dispatch_delayed(manager, true); + return (r < 0) ? r : 0; } static int delay_shutdown_or_sleep( diff --git a/src/login/logind.c b/src/login/logind.c index 01f7cd9ee0..e2fb496289 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -1109,6 +1109,12 @@ static int manager_run(Manager *m) { manager_gc(m, true); + r = manager_dispatch_delayed(m, false); + if (r < 0) + return r; + if (r > 0) + continue; + r = sd_event_run(m->event, (uint64_t) -1); if (r < 0) return r; diff --git a/src/login/logind.h b/src/login/logind.h index feb381d0b1..ad437b72cb 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -194,3 +194,5 @@ int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char int manager_setup_wall_message_timer(Manager *m); bool logind_wall_tty_filter(const char *tty, void *userdata); + +int manager_dispatch_delayed(Manager *manager, bool timeout); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 16243a5352..dff81a5cf0 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1360,8 +1360,7 @@ static int link_joined(Link *link) { return link_enter_set_addresses(link); } -static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, - void *userdata) { +static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c index ece9ecc251..6949b403c8 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -92,10 +92,11 @@ static void netdev_cancel_callbacks(NetDev *netdev) { assert(netdev->manager); assert(netdev->manager->rtnl); - callback->callback(netdev->manager->rtnl, m, link); + callback->callback(netdev->manager->rtnl, m, callback->link); } LIST_REMOVE(callbacks, netdev->callbacks, callback); + link_unref(callback->link); free(callback); } } @@ -177,6 +178,8 @@ int netdev_get(Manager *manager, const char *name, NetDev **ret) { static int netdev_enter_failed(NetDev *netdev) { netdev->state = NETDEV_STATE_FAILED; + netdev_cancel_callbacks(netdev); + return 0; } @@ -266,12 +269,20 @@ int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t call int r; assert(netdev); + assert(netdev->manager); + assert(netdev->manager->rtnl); assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND)); if (netdev->state == NETDEV_STATE_READY) { r = netdev_enslave_ready(netdev, link, callback); if (r < 0) return r; + } else if (IN_SET(netdev->state, NETDEV_STATE_LINGER, NETDEV_STATE_FAILED)) { + _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL; + + r = rtnl_message_new_synthetic_error(-ENODEV, 0, &m); + if (r >= 0) + callback(netdev->manager->rtnl, m, link); } else { /* the netdev is not yet read, save this request for when it is */ netdev_join_callback *cb; diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 4cf2d14ae2..7fa098bea8 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1074,18 +1074,18 @@ static int mount_all(const char *dest, bool userns) { } MountPoint; static const MountPoint mount_table[] = { - { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true, true }, - { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, true, true }, /* Bind mount first */ - { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, true, true }, /* Then, make it r/o */ - { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false }, - { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, true, false }, - { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true, false }, - { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false }, - { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false }, - { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_STRICTATIME, true, false }, + { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true, true }, + { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, true, true }, /* Bind mount first */ + { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, true, true }, /* Then, make it r/o */ + { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false }, + { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, true, false }, + { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true, false }, + { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false }, + { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false }, + { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_STRICTATIME, true, false }, #ifdef HAVE_SELINUX - { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, false, false }, /* Bind mount first */ - { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, false, false }, /* Then, make it r/o */ + { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, false, false }, /* Bind mount first */ + { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, false, false }, /* Then, make it r/o */ #endif }; @@ -4313,10 +4313,6 @@ static int outer_child( if (r < 0) return r; - r = determine_uid_shift(directory); - if (r < 0) - return r; - /* Turn directory into bind mount */ if (mount(directory, directory, NULL, MS_BIND|MS_REC, NULL) < 0) return log_error_errno(errno, "Failed to make bind mount: %m"); @@ -4495,6 +4491,10 @@ int main(int argc, char *argv[]) { if (r < 0) goto finish; + r = determine_uid_shift(arg_directory); + if (r < 0) + return r; + if (geteuid() != 0) { log_error("Need to be root."); r = -EPERM; diff --git a/src/shared/install.c b/src/shared/install.c index 559fda211d..c37cf1948a 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -2263,7 +2263,7 @@ int unit_file_get_list( } } - return r; + return 0; } static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = { diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c index 9ae518ac4a..45b119362c 100644 --- a/src/sysv-generator/sysv-generator.c +++ b/src/sysv-generator/sysv-generator.c @@ -240,20 +240,21 @@ static bool usage_contains_reload(const char *line) { } static char *sysv_translate_name(const char *name) { - char *r; + _cleanup_free_ char *c = NULL; + char *res; - r = new(char, strlen(name) + strlen(".service") + 1); - if (!r) + c = strdup(name); + if (!c) return NULL; - if (endswith(name, ".sh")) - /* Drop .sh suffix */ - strcpy(stpcpy(r, name) - 3, ".service"); - else - /* Normal init script name */ - strcpy(stpcpy(r, name), ".service"); + res = endswith(c, ".sh"); + if (res) + *res = 0; - return r; + if (unit_name_mangle(c, UNIT_NAME_NOGLOB, &res) < 0) + return NULL; + + return res; } static int sysv_translate_facility(const char *name, const char *filename, char **_r) { @@ -340,6 +341,7 @@ static int handle_provides(SysvStub *s, unsigned line, const char *full_text, co FOREACH_WORD_QUOTED(word, z, text, state_) { _cleanup_free_ char *n = NULL, *m = NULL; + UnitType t; n = strndup(word, z); if (!n) @@ -351,12 +353,13 @@ static int handle_provides(SysvStub *s, unsigned line, const char *full_text, co if (r == 0) continue; - if (unit_name_to_type(m) == UNIT_SERVICE) { + t = unit_name_to_type(m); + if (t == UNIT_SERVICE) { log_debug("Adding Provides: alias '%s' for '%s'", m, s->name); r = add_alias(s->name, m); if (r < 0) log_warning_errno(r, "[%s:%u] Failed to add LSB Provides name %s, ignoring: %m", s->path, line, m); - } else { + } else if (t == UNIT_TARGET) { /* NB: SysV targets which are provided by a * service are pulled in by the services, as * an indication that the generic service is @@ -373,7 +376,10 @@ static int handle_provides(SysvStub *s, unsigned line, const char *full_text, co if (r < 0) return log_oom(); } - } + } else if (t == _UNIT_TYPE_INVALID) + log_warning("Unit name '%s' is invalid", m); + else + log_warning("Unknown unit type for unit '%s'", m); } if (!isempty(state_)) log_error("[%s:%u] Trailing garbage in Provides, ignoring.", s->path, line); diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c index 195d5f3892..25c25952aa 100644 --- a/src/timedate/timedatectl.c +++ b/src/timedate/timedatectl.c @@ -154,11 +154,12 @@ static void print_status_info(const StatusInfo *i) { if (i->rtc_local) fputs("\n" ANSI_HIGHLIGHT_ON - "Warning: The system is configured to read the RTC time in the local time zone. This\n" - " mode can not be fully supported. It will create various problems with time\n" - " zone changes and daylight saving time adjustments. The RTC time is never updated,\n" - " it relies on external facilities to maintain it. If at all possible, use\n" - " RTC in UTC by calling 'timedatectl set-local-rtc 0'" ANSI_HIGHLIGHT_OFF ".\n", stdout); + "Warning: The system is configured to read the RTC time in the local time zone.\n" + " This mode can not be fully supported. It will create various problems\n" + " with time zone changes and daylight saving time adjustments. The RTC\n" + " time is never updated, it relies on external facilities to maintain it.\n" + " If at all possible, use RTC in UTC by calling\n" + " 'timedatectl set-local-rtc 0'" ANSI_HIGHLIGHT_OFF ".\n", stdout); } static int show_status(sd_bus *bus, char **args, unsigned n) { diff --git a/src/udev/accelerometer/Makefile b/src/udev/accelerometer/Makefile deleted file mode 120000 index d0b0e8e008..0000000000 --- a/src/udev/accelerometer/Makefile +++ /dev/null @@ -1 +0,0 @@ -../Makefile
\ No newline at end of file diff --git a/src/udev/accelerometer/accelerometer.c b/src/udev/accelerometer/accelerometer.c deleted file mode 100644 index 9e2c590c15..0000000000 --- a/src/udev/accelerometer/accelerometer.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * accelerometer - exports device orientation through property - * - * When an "change" event is received on an accelerometer, - * open its device node, and from the value, as well as the previous - * value of the property, calculate the device's new orientation, - * and export it as ID_INPUT_ACCELEROMETER_ORIENTATION. - * - * Possible values are: - * undefined - * * normal - * * bottom-up - * * left-up - * * right-up - * - * The property will be persistent across sessions, and the new - * orientations can be deducted from the previous one (it allows - * for a threshold for switching between opposite ends of the - * orientation). - * - * Copyright (C) 2011 Red Hat, Inc. - * Author: - * Bastien Nocera <hadess@hadess.net> - * - * orientation_calc() from the sensorfw package - * Copyright (C) 2009-2010 Nokia Corporation - * Authors: - * Üstün Ergenoglu <ext-ustun.ergenoglu@nokia.com> - * Timo Rongas <ext-timo.2.rongas@nokia.com> - * Lihan Guo <lihan.guo@digia.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include <stdio.h> -#include <string.h> -#include <math.h> -#include <stdlib.h> -#include <getopt.h> -#include <limits.h> -#include <linux/input.h> - -#include "libudev.h" -#include "libudev-private.h" - -/* we must use this kernel-compatible implementation */ -#define BITS_PER_LONG (sizeof(unsigned long) * 8) -#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) -#define OFF(x) ((x)%BITS_PER_LONG) -#define BIT(x) (1UL<<OFF(x)) -#define LONG(x) ((x)/BITS_PER_LONG) -#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1) - -typedef enum { - ORIENTATION_UNDEFINED, - ORIENTATION_NORMAL, - ORIENTATION_BOTTOM_UP, - ORIENTATION_LEFT_UP, - ORIENTATION_RIGHT_UP -} OrientationUp; - -static const char *orientations[] = { - "undefined", - "normal", - "bottom-up", - "left-up", - "right-up", - NULL -}; - -#define ORIENTATION_UP_UP ORIENTATION_NORMAL - -#define DEFAULT_THRESHOLD 250 -#define RADIANS_TO_DEGREES 180.0/M_PI -#define SAME_AXIS_LIMIT 5 - -#define THRESHOLD_LANDSCAPE 25 -#define THRESHOLD_PORTRAIT 20 - -static const char * -orientation_to_string (OrientationUp o) -{ - return orientations[o]; -} - -static OrientationUp -string_to_orientation (const char *orientation) -{ - int i; - - if (orientation == NULL) - return ORIENTATION_UNDEFINED; - for (i = 0; orientations[i] != NULL; i++) { - if (streq (orientation, orientations[i])) - return i; - } - return ORIENTATION_UNDEFINED; -} - -static OrientationUp -orientation_calc (OrientationUp prev, - int x, int y, int z) -{ - int rotation; - OrientationUp ret = prev; - - /* Portrait check */ - rotation = round(atan((double) x / sqrt(y * y + z * z)) * RADIANS_TO_DEGREES); - - if (abs(rotation) > THRESHOLD_PORTRAIT) { - ret = (rotation < 0) ? ORIENTATION_LEFT_UP : ORIENTATION_RIGHT_UP; - - /* Some threshold to switching between portrait modes */ - if (prev == ORIENTATION_LEFT_UP || prev == ORIENTATION_RIGHT_UP) { - if (abs(rotation) < SAME_AXIS_LIMIT) { - ret = prev; - } - } - - } else { - /* Landscape check */ - rotation = round(atan((double) y / sqrt(x * x + z * z)) * RADIANS_TO_DEGREES); - - if (abs(rotation) > THRESHOLD_LANDSCAPE) { - ret = (rotation < 0) ? ORIENTATION_BOTTOM_UP : ORIENTATION_NORMAL; - - /* Some threshold to switching between landscape modes */ - if (prev == ORIENTATION_BOTTOM_UP || prev == ORIENTATION_NORMAL) { - if (abs(rotation) < SAME_AXIS_LIMIT) { - ret = prev; - } - } - } - } - - return ret; -} - -static OrientationUp -get_prev_orientation(struct udev_device *dev) -{ - const char *value; - - value = udev_device_get_property_value(dev, "ID_INPUT_ACCELEROMETER_ORIENTATION"); - if (value == NULL) - return ORIENTATION_UNDEFINED; - return string_to_orientation(value); -} - -#define READ_AXIS(axis, var) { memzero(&abs_info, sizeof(abs_info)); r = ioctl(fd, EVIOCGABS(axis), &abs_info); if (r < 0) return; var = abs_info.value; } - -/* accelerometers */ -static void test_orientation(struct udev *udev, - struct udev_device *dev, - const char *devpath) -{ - OrientationUp old, new; - _cleanup_close_ int fd = -1; - struct input_absinfo abs_info; - int x = 0, y = 0, z = 0; - int r; - char text[64]; - - old = get_prev_orientation(dev); - - fd = open(devpath, O_RDONLY|O_CLOEXEC); - if (fd < 0) - return; - - READ_AXIS(ABS_X, x); - READ_AXIS(ABS_Y, y); - READ_AXIS(ABS_Z, z); - - new = orientation_calc(old, x, y, z); - snprintf(text, sizeof(text), - "ID_INPUT_ACCELEROMETER_ORIENTATION=%s", orientation_to_string(new)); - puts(text); -} - -static void help(void) { - - printf("%s [options] <device path>\n\n" - "Accelerometer device identification.\n\n" - " -h --help Print this message\n" - " -d --debug Debug to stderr\n" - , program_invocation_short_name); -} - -int main (int argc, char** argv) -{ - struct udev *udev; - struct udev_device *dev; - - static const struct option options[] = { - { "debug", no_argument, NULL, 'd' }, - { "help", no_argument, NULL, 'h' }, - {} - }; - - char devpath[PATH_MAX]; - char *devnode; - struct udev_enumerate *enumerate; - struct udev_list_entry *list_entry; - - log_parse_environment(); - log_open(); - - udev = udev_new(); - if (udev == NULL) - return 1; - - /* CLI argument parsing */ - while (1) { - int option; - - option = getopt_long(argc, argv, "dh", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'd': - log_set_target(LOG_TARGET_CONSOLE); - log_set_max_level(LOG_DEBUG); - log_open(); - break; - case 'h': - help(); - exit(0); - default: - exit(1); - } - } - - if (argv[optind] == NULL) { - help(); - exit(1); - } - - /* get the device */ - snprintf(devpath, sizeof(devpath), "/sys/%s", argv[optind]); - dev = udev_device_new_from_syspath(udev, devpath); - if (dev == NULL) { - fprintf(stderr, "unable to access '%s'\n", devpath); - return 1; - } - - /* Get the children devices and find the devnode */ - devnode = NULL; - enumerate = udev_enumerate_new(udev); - udev_enumerate_add_match_parent(enumerate, dev); - udev_enumerate_scan_devices(enumerate); - udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) { - struct udev_device *device; - const char *node; - - device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate), - udev_list_entry_get_name(list_entry)); - if (device == NULL) - continue; - /* Already found it */ - if (devnode != NULL) { - udev_device_unref(device); - continue; - } - - node = udev_device_get_devnode(device); - if (node == NULL) { - udev_device_unref(device); - continue; - } - /* Use the event sub-device */ - if (strstr(node, "/event") == NULL) { - udev_device_unref(device); - continue; - } - - devnode = strdup(node); - udev_device_unref(device); - } - - if (devnode == NULL) { - fprintf(stderr, "unable to get device node for '%s'\n", devpath); - return 0; - } - - log_debug("opening accelerometer device %s", devnode); - test_orientation(udev, dev, devnode); - free(devnode); - log_close(); - return 0; -} diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index 1092071e26..4761222786 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -721,19 +721,13 @@ int udev_event_spawn(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, bool accept_failure, - const char *cmd, char **envp, + const char *cmd, char *result, size_t ressize) { int outpipe[2] = {-1, -1}; int errpipe[2] = {-1, -1}; pid_t pid; - char arg[UTIL_PATH_SIZE]; - char *argv[128]; - char program[UTIL_PATH_SIZE]; int err = 0; - strscpy(arg, sizeof(arg), cmd); - udev_build_argv(event->udev, arg, NULL, argv); - /* pipes from child to parent */ if (result != NULL || log_get_max_level() >= LOG_INFO) { if (pipe2(outpipe, O_NONBLOCK) != 0) { @@ -750,15 +744,14 @@ int udev_event_spawn(struct udev_event *event, } } - /* allow programs in /usr/lib/udev/ to be called without the path */ - if (argv[0][0] != '/') { - strscpyl(program, sizeof(program), UDEVLIBEXECDIR "/", argv[0], NULL); - argv[0] = program; - } - pid = fork(); switch(pid) { case 0: + { + char arg[UTIL_PATH_SIZE]; + char *argv[128]; + char program[UTIL_PATH_SIZE]; + /* child closes parent's ends of pipes */ if (outpipe[READ_END] >= 0) { close(outpipe[READ_END]); @@ -769,12 +762,22 @@ int udev_event_spawn(struct udev_event *event, errpipe[READ_END] = -1; } + strscpy(arg, sizeof(arg), cmd); + udev_build_argv(event->udev, arg, NULL, argv); + + /* allow programs in /usr/lib/udev/ to be called without the path */ + if (argv[0][0] != '/') { + strscpyl(program, sizeof(program), UDEVLIBEXECDIR "/", argv[0], NULL); + argv[0] = program; + } + log_debug("starting '%s'", cmd); - spawn_exec(event, cmd, argv, envp, + spawn_exec(event, cmd, argv, udev_device_get_properties_envp(event->dev), outpipe[WRITE_END], errpipe[WRITE_END]); - _exit(2 ); + _exit(2); + } case -1: log_error_errno(errno, "fork of '%s' failed: %m", cmd); err = -1; @@ -934,26 +937,21 @@ void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_ struct udev_list_entry *list_entry; udev_list_entry_foreach(list_entry, udev_list_get_entry(&event->run_list)) { + char command[UTIL_PATH_SIZE]; const char *cmd = udev_list_entry_get_name(list_entry); enum udev_builtin_cmd builtin_cmd = udev_list_entry_get_num(list_entry); - if (builtin_cmd < UDEV_BUILTIN_MAX) { - char command[UTIL_PATH_SIZE]; + udev_event_apply_format(event, cmd, command, sizeof(command)); - udev_event_apply_format(event, cmd, command, sizeof(command)); + if (builtin_cmd < UDEV_BUILTIN_MAX) udev_builtin_run(event->dev, builtin_cmd, command, false); - } else { - char program[UTIL_PATH_SIZE]; - char **envp; - + else { if (event->exec_delay > 0) { - log_debug("delay execution of '%s'", program); + log_debug("delay execution of '%s'", command); sleep(event->exec_delay); } - udev_event_apply_format(event, cmd, program, sizeof(program)); - envp = udev_device_get_properties_envp(event->dev); - udev_event_spawn(event, timeout_usec, timeout_warn_usec, false, program, envp, NULL, 0); + udev_event_spawn(event, timeout_usec, timeout_warn_usec, false, command, NULL, 0); } } } diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 8ebc061eb1..d00f90afa6 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -634,14 +634,11 @@ static int import_program_into_properties(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, const char *program) { - struct udev_device *dev = event->dev; - char **envp; char result[UTIL_LINE_SIZE]; char *line; int err; - envp = udev_device_get_properties_envp(dev); - err = udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, envp, result, sizeof(result)); + err = udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, result, sizeof(result)); if (err < 0) return err; @@ -654,7 +651,7 @@ static int import_program_into_properties(struct udev_event *event, pos[0] = '\0'; pos = &pos[1]; } - import_property_from_string(dev, line); + import_property_from_string(event->dev, line); line = pos; } return 0; @@ -682,41 +679,6 @@ static int import_parent_into_properties(struct udev_device *dev, const char *fi return 0; } -#define WAIT_LOOP_PER_SECOND 50 -static int wait_for_file(struct udev_device *dev, const char *file, int timeout) { - char filepath[UTIL_PATH_SIZE]; - char devicepath[UTIL_PATH_SIZE]; - struct stat stats; - int loop = timeout * WAIT_LOOP_PER_SECOND; - - /* a relative path is a device attribute */ - devicepath[0] = '\0'; - if (file[0] != '/') { - strscpyl(devicepath, sizeof(devicepath), udev_device_get_syspath(dev), NULL); - strscpyl(filepath, sizeof(filepath), devicepath, "/", file, NULL); - file = filepath; - } - - while (--loop) { - const struct timespec duration = { 0, 1000 * 1000 * 1000 / WAIT_LOOP_PER_SECOND }; - - /* lookup file */ - if (stat(file, &stats) == 0) { - log_debug("file '%s' appeared after %i loops", file, (timeout * WAIT_LOOP_PER_SECOND) - loop-1); - return 0; - } - /* make sure, the device did not disappear in the meantime */ - if (devicepath[0] != '\0' && stat(devicepath, &stats) != 0) { - log_debug("device disappeared while waiting for '%s'", file); - return -2; - } - log_debug("wait for '%s' for %i mseconds", file, 1000 / WAIT_LOOP_PER_SECOND); - nanosleep(&duration, NULL); - } - log_debug("waiting for '%s' failed", file); - return -1; -} - static int attr_subst_subdir(char *attr, size_t len) { bool found = false; @@ -1397,15 +1359,6 @@ static int add_rule(struct udev_rules *rules, char *line, continue; } - if (streq(key, "WAIT_FOR") || streq(key, "WAIT_FOR_SYSFS")) { - if (op == OP_REMOVE) { - log_error("invalid WAIT_FOR/WAIT_FOR_SYSFS operation"); - goto invalid; - } - rule_add_key(&rule_tmp, TK_M_WAITFOR, 0, value, NULL); - continue; - } - if (streq(key, "LABEL")) { if (op == OP_REMOVE) { log_error("invalid LABEL operation"); @@ -1999,16 +1952,6 @@ int udev_rules_apply_to_event(struct udev_rules *rules, if (match_key(rules, cur, udev_device_get_driver(event->dev)) != 0) goto nomatch; break; - case TK_M_WAITFOR: { - char filename[UTIL_PATH_SIZE]; - int found; - - udev_event_apply_format(event, rules_str(rules, cur->key.value_off), filename, sizeof(filename)); - found = (wait_for_file(event->dev, filename, 10) == 0); - if (!found && (cur->key.op != OP_NOMATCH)) - goto nomatch; - break; - } case TK_M_ATTR: if (match_attr(rules, event->dev, event, cur) != 0) goto nomatch; @@ -2119,19 +2062,17 @@ int udev_rules_apply_to_event(struct udev_rules *rules, } case TK_M_PROGRAM: { char program[UTIL_PATH_SIZE]; - char **envp; char result[UTIL_LINE_SIZE]; free(event->program_result); event->program_result = NULL; udev_event_apply_format(event, rules_str(rules, cur->key.value_off), program, sizeof(program)); - envp = udev_device_get_properties_envp(event->dev); log_debug("PROGRAM '%s' %s:%u", program, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); - if (udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, envp, result, sizeof(result)) < 0) { + if (udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, result, sizeof(result)) < 0) { if (cur->key.op != OP_NOMATCH) goto nomatch; } else { diff --git a/src/udev/udev.h b/src/udev/udev.h index 3dca72e499..d17fc8c1ea 100644 --- a/src/udev/udev.h +++ b/src/udev/udev.h @@ -85,8 +85,7 @@ int udev_event_spawn(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, bool accept_failure, - const char *cmd, char **envp, - char *result, size_t ressize); + const char *cmd, char *result, size_t ressize); void udev_event_execute_rules(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, struct udev_list *properties_list, diff --git a/src/udev/udevd.c b/src/udev/udevd.c index cf15ddf641..e27fb1fd9e 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -1608,8 +1608,42 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg return 0; } -int main(int argc, char *argv[]) { +static int run(int fd_ctrl, int fd_uevent, const char *cgroup) { _cleanup_(manager_freep) Manager *manager = NULL; + int r; + + r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup); + if (r < 0) { + r = log_error_errno(r, "failed to allocate manager object: %m"); + goto exit; + } + + r = udev_rules_apply_static_dev_perms(manager->rules); + if (r < 0) + log_error_errno(r, "failed to apply permissions on static device nodes: %m"); + + (void) sd_notify(false, + "READY=1\n" + "STATUS=Processing..."); + + r = sd_event_loop(manager->event); + if (r < 0) { + log_error_errno(r, "event loop failed: %m"); + goto exit; + } + + sd_event_get_exit_code(manager->event, &r); + +exit: + sd_notify(false, + "STOPPING=1\n" + "STATUS=Shutting down..."); + if (manager) + udev_ctrl_cleanup(manager->ctrl); + return r; +} + +int main(int argc, char *argv[]) { _cleanup_free_ char *cgroup = NULL; int r, fd_ctrl, fd_uevent; @@ -1625,8 +1659,10 @@ int main(int argc, char *argv[]) { if (r < 0) log_warning_errno(r, "failed to parse kernel command line, ignoring: %m"); - if (arg_debug) + if (arg_debug) { + log_set_target(LOG_TARGET_CONSOLE); log_set_max_level(LOG_DEBUG); + } if (getuid() != 0) { r = log_error_errno(EPERM, "root privileges required"); @@ -1714,35 +1750,9 @@ int main(int argc, char *argv[]) { write_string_file("/proc/self/oom_score_adj", "-1000"); } - r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup); - if (r < 0) { - r = log_error_errno(r, "failed to allocate manager object: %m"); - goto exit; - } - - r = udev_rules_apply_static_dev_perms(manager->rules); - if (r < 0) - log_error_errno(r, "failed to apply permissions on static device nodes: %m"); - - (void) sd_notify(false, - "READY=1\n" - "STATUS=Processing..."); - - r = sd_event_loop(manager->event); - if (r < 0) { - log_error_errno(r, "event loop failed: %m"); - goto exit; - } - - sd_event_get_exit_code(manager->event, &r); + r = run(fd_ctrl, fd_uevent, cgroup); exit: - sd_notify(false, - "STOPPING=1\n" - "STATUS=Shutting down..."); - - if (manager) - udev_ctrl_cleanup(manager->ctrl); mac_selinux_finish(); log_close(); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; diff --git a/test/rule-syntax-check.py b/test/rule-syntax-check.py index 80bbe65bea..e43a3daeb3 100644 --- a/test/rule-syntax-check.py +++ b/test/rule-syntax-check.py @@ -35,7 +35,7 @@ else: no_args_tests = re.compile('(ACTION|DEVPATH|KERNELS?|NAME|SYMLINK|SUBSYSTEMS?|DRIVERS?|TAG|RESULT|TEST)\s*(?:=|!)=\s*"([^"]*)"$') args_tests = re.compile('(ATTRS?|ENV|TEST){([a-zA-Z0-9/_.*%-]+)}\s*(?:=|!)=\s*"([^"]*)"$') -no_args_assign = re.compile('(NAME|SYMLINK|OWNER|GROUP|MODE|TAG|PROGRAM|RUN|LABEL|GOTO|WAIT_FOR|OPTIONS|IMPORT)\s*(?:\+=|:=|=)\s*"([^"]*)"$') +no_args_assign = re.compile('(NAME|SYMLINK|OWNER|GROUP|MODE|TAG|PROGRAM|RUN|LABEL|GOTO|OPTIONS|IMPORT)\s*(?:\+=|:=|=)\s*"([^"]*)"$') args_assign = re.compile('(ATTR|ENV|IMPORT|RUN){([a-zA-Z0-9/_.*%-]+)}\s*(=|\+=)\s*"([^"]*)"$') result = 0 diff --git a/test/sysv-generator-test.py b/test/sysv-generator-test.py index af0493b9a8..721e53a4ee 100644 --- a/test/sysv-generator-test.py +++ b/test/sysv-generator-test.py @@ -190,6 +190,15 @@ class SysvGeneratorTest(unittest.TestCase): self.assert_enabled('foo.service', ['multi-user', 'graphical']) self.assertNotIn('Overwriting', err) + def test_simple_escaped(self): + '''simple service without dependencies, that requires escaping the name''' + + self.add_sysv('foo+', {}) + self.add_sysv('foo-admin', {}) + err, results = self.run_generator() + self.assertEqual(set(results), {'foo-admin.service', 'foo\\x2b.service'}) + self.assertNotIn('Overwriting', err) + def test_simple_enabled_some(self): '''simple service without dependencies, enabled in some runlevels''' @@ -276,6 +285,16 @@ class SysvGeneratorTest(unittest.TestCase): 'foo.service') self.assertNotIn('Overwriting', err) + def test_provides_escaped(self): + '''a script that Provides: a name that requires escaping''' + + self.add_sysv('foo', {'Provides': 'foo foo+'}) + err, results = self.run_generator() + self.assertEqual(list(results), ['foo.service']) + self.assertEqual(os.readlink(os.path.join(self.out_dir, 'foo\\x2b.service')), + 'foo.service') + self.assertNotIn('Overwriting', err) + def test_same_provides_in_multiple_scripts(self): '''multiple init.d scripts provide the same name''' diff --git a/tools/make-man-rules.py b/tools/make-man-rules.py index e75bfffba1..5e61917d60 100644 --- a/tools/make-man-rules.py +++ b/tools/make-man-rules.py @@ -62,7 +62,7 @@ FOOTER = '''\ # Really, do not edit this file. EXTRA_DIST += \\ - {files} + {dist_files} ''' def man(page, number): @@ -106,7 +106,7 @@ def create_rules(xml_files): def mjoin(files): return ' \\\n\t'.join(sorted(files) or '#') -def make_makefile(rules, files): +def make_makefile(rules, dist_files): return HEADER + '\n'.join( (CONDITIONAL if conditional else SECTION).format( manpages=mjoin(set(rulegroup.values())), @@ -119,9 +119,11 @@ def make_makefile(rules, files): if k != v), conditional=conditional) for conditional,rulegroup in sorted(rules.items()) - ) + FOOTER.format(files=mjoin(sorted(files))) + ) + FOOTER.format(dist_files=mjoin(sorted(dist_files))) if __name__ == '__main__': rules = create_rules(sys.argv[1:]) - files = (xml(file) for file in sys.argv[1:]) - print(make_makefile(rules, files), end='') + dist_files = (xml(file) for file in sys.argv[1:] + if not file.endswith(".directives.xml") and + not file.endswith(".index.xml")) + print(make_makefile(rules, dist_files), end='') |