Compare commits

...

16 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek c13f4643f4 Merge pull request #15579 from DaanDeMeyer/sd-bus-get-name/owner-creds-docs 2020-04-24 08:29:41 +02:00
Zbigniew Jędrzejewski-Szmek e2697253c8
Merge pull request #15564 from poettering/tmpfiles-no-proc
util-lib: check for /proc being mounted in some really basic fs operations
2020-04-24 08:16:22 +02:00
Daan De Meyer 425d5cecbe sd-bus: Add sd_bus_get_name/owner_creds docs 2020-04-24 08:15:05 +02:00
Zbigniew Jędrzejewski-Szmek 11f9379866
Merge pull request #15570 from poettering/cmsg-find
CMSG_FIND_DATA() and cmsg_find() work
2020-04-24 07:45:07 +02:00
Lennart Poettering 41ab8c67eb tree-wide: use structured initialization at various places 2020-04-24 07:44:42 +02:00
Lennart Poettering 2efa5bc6fa dhcp-server: port to recvmsg_safe()
Split out of #15457, let's see if this is the culprit of the CI failure.
2020-04-24 07:43:42 +02:00
Lennart Poettering 2adfd1bda1 icmp6-util: port to recvmsg_safe()
Split out of #15457, let's see if this is the culprit of the CI failure.
2020-04-24 07:41:32 +02:00
Lennart Poettering 84b5d3e532 dhcp-client: port to recvmsg_safe()
Split out of #15457, let's see if this is the culprit of the CI failure.

(also setting green label here, since @keszybz already greenlit it in that other PR)
2020-04-24 07:40:32 +02:00
Frantisek Sumsal a8af7f6a5c fuzzit: make the submit phase a bit more robust
The submit phase of the Fuzzit Travis job has been spuriously failing
for some time with various (and usually pretty hidden) errors, like:

```
./fuzzit create job --type regression ...
2020/04/23 17:02:12 please set env variable FUZZIT_API_KEY or pass --api-key. API Key for you account: ...
```

```
./fuzzit create job --type regression ...
2020/04/23 11:36:53 Creating job...
2020/04/23 11:36:54 Uploading fuzzer...
2020/04/23 11:36:54 Job created successfully
2020/04/23 11:36:54 Get https://...&action=create: read tcp x.x.x.x:39674->x.x.x.x:443: read: connection reset by peer
```

```
./fuzzit create job --type regression ...
2020/04/22 18:09:15 Creating job...
2020/04/22 18:09:16 Uploading fuzzer...
2020/04/22 18:09:37 Job created successfully
2020/04/22 18:09:37 500 Internal Server Error
```

etc.

Let's retry each submit job up to three times to (hopefully) mitigate this.
2020-04-24 01:58:37 +03:00
Lennart Poettering 371d72e05b socket-util: introduce type-safe, dereferencing wrapper CMSG_FIND_DATA around cmsg_find()
let's take this once step further, and add type-safety to cmsg_find(),
and imply the CMSG_DATA() macro for finding the cmsg payload.
2020-04-23 19:41:15 +02:00
Lennart Poettering dac556fa7b tree-wide: use cmsg_find() helper at various places where appropriate 2020-04-23 19:41:15 +02:00
Lennart Poettering f8606626ed tmpfiles: if we get ENOENT when opening /proc/self/fd/, check if /proc is mounted
let's return ENOSYS in that case, to make things a bit less confusng.

Previously we'd just propagate ENOENT, which people might mistake as
applying to the object being modified rather than /proc/ just not being
there.

Let's return ENOSYS instead, i.e. an error clearly indicating that some
kernel API is not available. This hopefully should put people on a
better track.

Note that we only do the procfs check in the error path, which hopefully
means it's the less likely path.

We probably can add similar bits to more suitable codepaths dealing with
/proc/self/fd, but for now, let's pick to the ones noticed in #14745.

Fixes: #14745
2020-04-23 14:52:10 +02:00
Lennart Poettering 883fff25f4 stat-util: add simpler helper for checking if /proc/ is mounted 2020-04-23 14:51:08 +02:00
Lennart Poettering 6d965610bd stat-util: no need to open a file to check fs type 2020-04-23 14:50:53 +02:00
Lennart Poettering 0f7e4b2888 sysusers,tmpfiles: always mention error when failing to replace specifiers 2020-04-23 14:50:07 +02:00
Lennart Poettering 2230e8f29d sysusers: add accidentally forgotten 'return' 2020-04-23 14:49:14 +02:00
29 changed files with 312 additions and 186 deletions

View File

@ -262,6 +262,7 @@ manpages = [
['sd_bus_get_events', 'sd_bus_get_timeout', 'sd_bus_set_fd'],
''],
['sd_bus_get_n_queued_read', '3', ['sd_bus_get_n_queued_write'], ''],
['sd_bus_get_name_creds', '3', ['sd_bus_get_owner_creds'], ''],
['sd_bus_get_name_machine_id', '3', [], ''],
['sd_bus_is_open', '3', ['sd_bus_is_ready'], ''],
['sd_bus_list_names', '3', [], ''],

View File

@ -83,6 +83,8 @@
<citerefentry><refentrytitle>sd_bus_get_method_call_timeout</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_n_queued_read</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_name_machine_id</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_name_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_owner_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_scope</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_tid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_unique_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,

View File

@ -0,0 +1,120 @@
<?xml version='1.0'?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1+ -->
<refentry id="sd_bus_get_name_creds" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_get_name_creds</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>sd_bus_get_name_creds</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>sd_bus_get_name_creds</refname>
<refname>sd_bus_get_owner_creds</refname>
<refpurpose>Query bus client credentials</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_bus_get_name_creds</function></funcdef>
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
<paramdef>const char *<parameter>name</parameter></paramdef>
<paramdef>uint64_t <parameter>mask</parameter></paramdef>
<paramdef>sd_bus_creds **<parameter>creds</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_bus_get_owner_creds</function></funcdef>
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
<paramdef>uint64_t <parameter>mask</parameter></paramdef>
<paramdef>sd_bus_creds **<parameter>creds</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><function>sd_bus_get_name_creds()</function> queries the credentials of the bus client
identified by <parameter>name</parameter>. The <parameter>mask</parameter> parameter is a combo of
<constant index='false'>SD_BUS_CREDS_*</constant> flags that indicate which credential info the caller is
interested in. See
<citerefentry><refentrytitle>sd_bus_creds_new_from_pid</refentrytitle><manvolnum>3</manvolnum></citerefentry>
for a list of possible flags. On success, <parameter>creds</parameter> contains a new
<structname>sd_bus_creds</structname> instance with the requested information. Ownership of this instance
belongs to the caller and it should be freed once no longer needed by calling
<function>sd_bus_creds_unref()</function>.</para>
<para><function>sd_bus_get_owner_creds()</function> queries the credentials of the creator of the given
bus. The <parameter>mask</parameter> and <parameter>creds</parameter> parameters behave the same as in
<function>sd_bus_get_name_creds()</function>.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
<para>On success, these functions return a non-negative integer. On failure, they return a negative
errno-style error code.</para>
<refsect2>
<title>Errors</title>
<para>Returned errors may indicate the following problems:</para>
<variablelist>
<varlistentry>
<term><constant>-EINVAL</constant></term>
<listitem><para>An argument is invalid.</para></listitem>
</varlistentry>
<varlistentry>
<term><constant>-ENOPKG</constant></term>
<listitem><para>The bus cannot be resolved.</para></listitem>
</varlistentry>
<varlistentry>
<term><constant>-EPERM</constant></term>
<listitem><para>The bus has already been started.</para></listitem>
</varlistentry>
<varlistentry>
<term><constant>-ECHILD</constant></term>
<listitem><para>The bus was created in a different process.</para></listitem>
</varlistentry>
<varlistentry>
<term><constant>-ENOMEM</constant></term>
<listitem><para>Memory allocation failed.</para></listitem>
</varlistentry>
</variablelist>
</refsect2>
</refsect1>
<xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -1149,7 +1149,6 @@ static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol
FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
_cleanup_free_ char *p = NULL;
const struct btrfs_root_ref *ref;
struct btrfs_ioctl_ino_lookup_args ino_args;
btrfs_ioctl_search_args_set(&args, sh);
@ -1164,9 +1163,10 @@ static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol
if (!p)
return -ENOMEM;
zero(ino_args);
ino_args.treeid = subvol_id;
ino_args.objectid = htole64(ref->dirid);
struct btrfs_ioctl_ino_lookup_args ino_args = {
.treeid = subvol_id,
.objectid = htole64(ref->dirid),
};
if (ioctl(fd, BTRFS_IOC_INO_LOOKUP, &ino_args) < 0)
return -errno;
@ -1504,7 +1504,6 @@ static int subvol_snapshot_children(
FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
_cleanup_free_ char *p = NULL, *c = NULL, *np = NULL;
struct btrfs_ioctl_ino_lookup_args ino_args;
const struct btrfs_root_ref *ref;
_cleanup_close_ int old_child_fd = -1, new_child_fd = -1;
@ -1528,9 +1527,10 @@ static int subvol_snapshot_children(
if (!p)
return -ENOMEM;
zero(ino_args);
ino_args.treeid = old_subvol_id;
ino_args.objectid = htole64(ref->dirid);
struct btrfs_ioctl_ino_lookup_args ino_args = {
.treeid = old_subvol_id,
.objectid = htole64(ref->dirid),
};
if (ioctl(old_fd, BTRFS_IOC_INO_LOOKUP, &ino_args) < 0)
return -errno;

View File

@ -21,9 +21,10 @@
#include "path-util.h"
#include "process-util.h"
#include "socket-util.h"
#include "stat-util.h"
#include "stdio-util.h"
#include "util.h"
#include "tmpfile-util.h"
#include "util.h"
/* The maximum number of iterations in the loop to close descriptors in the fallback case
* when /proc/self/fd/ is inaccessible. */
@ -939,8 +940,15 @@ int fd_reopen(int fd, int flags) {
xsprintf(procfs_path, "/proc/self/fd/%i", fd);
new_fd = open(procfs_path, flags);
if (new_fd < 0)
return -errno;
if (new_fd < 0) {
if (errno != ENOENT)
return -errno;
if (proc_mounted() == 0)
return -ENOSYS; /* if we have no /proc/, the concept is not implementable */
return -ENOENT;
}
return new_fd;
}

View File

@ -337,8 +337,15 @@ int fchmod_opath(int fd, mode_t m) {
* fchownat() does. */
xsprintf(procfs_path, "/proc/self/fd/%i", fd);
if (chmod(procfs_path, m) < 0)
return -errno;
if (chmod(procfs_path, m) < 0) {
if (errno != ENOENT)
return -errno;
if (proc_mounted() == 0)
return -ENOSYS; /* if we have no /proc/, the concept is not implementable */
return -ENOENT;
}
return 0;
}

View File

@ -887,7 +887,7 @@ ssize_t receive_one_fd_iov(
.msg_iov = iov,
.msg_iovlen = iovlen,
};
struct cmsghdr *cmsg, *found = NULL;
struct cmsghdr *found;
ssize_t k;
assert(transport_fd >= 0);
@ -905,16 +905,7 @@ ssize_t receive_one_fd_iov(
if (k < 0)
return k;
CMSG_FOREACH(cmsg, &mh) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
assert(!found);
found = cmsg;
break;
}
}
found = cmsg_find(&mh, SOL_SOCKET, SCM_RIGHTS, CMSG_LEN(sizeof(int)));
if (!found) {
cmsg_close_all(&mh);

View File

@ -158,6 +158,14 @@ int flush_accept(int fd);
struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length);
/* Type-safe, dereferencing version of cmsg_find() */
#define CMSG_FIND_DATA(mh, level, type, ctype) \
({ \
struct cmsghdr *_found; \
_found = cmsg_find(mh, level, type, CMSG_LEN(sizeof(ctype))); \
(ctype*) (_found ? CMSG_DATA(_found) : NULL); \
})
/*
* Certain hardware address types (e.g Infiniband) do not fit into sll_addr
* (8 bytes) and run over the structure. This macro returns the correct size that

View File

@ -178,13 +178,12 @@ int fd_is_fs_type(int fd, statfs_f_type_t magic_value) {
}
int path_is_fs_type(const char *path, statfs_f_type_t magic_value) {
_cleanup_close_ int fd = -1;
struct statfs s;
fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
if (fd < 0)
if (statfs(path, &s) < 0)
return -errno;
return fd_is_fs_type(fd, magic_value);
return is_fs_type(&s, magic_value);
}
bool is_temporary_fs(const struct statfs *s) {
@ -377,3 +376,15 @@ int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret
return 0;
}
int proc_mounted(void) {
int r;
/* A quick check of procfs is properly mounted */
r = path_is_fs_type("/proc/", PROC_SUPER_MAGIC);
if (r == -ENOENT) /* not mounted at all */
return false;
return r;
}

View File

@ -87,3 +87,5 @@ int fd_verify_directory(int fd);
int device_path_make_major_minor(mode_t mode, dev_t devno, char **ret);
int device_path_make_canonical(mode_t mode, dev_t devno, char **ret);
int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno);
int proc_mounted(void);

View File

@ -921,19 +921,11 @@ static int process_socket(int fd) {
/* The final zero-length datagram carries the file descriptor and tells us
* that we're done. */
if (n == 0) {
struct cmsghdr *cmsg, *found = NULL;
struct cmsghdr *found;
free(iovec.iov_base);
CMSG_FOREACH(cmsg, &mh) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
assert(!found);
found = cmsg;
}
}
found = cmsg_find(&mh, SOL_SOCKET, SCM_RIGHTS, CMSG_LEN(sizeof(int)));
if (!found) {
cmsg_close_all(&mh);
r = log_error_errno(SYNTHETIC_ERRNO(EBADMSG),

View File

@ -557,9 +557,8 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
.msg_control = &control,
.msg_controllen = sizeof(control),
};
struct ucred *ucred = NULL;
struct ucred *ucred;
Manager *m = userdata;
struct cmsghdr *cmsg;
char *p, *e;
Transfer *t;
Iterator i;
@ -574,17 +573,12 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
cmsg_close_all(&msghdr);
CMSG_FOREACH(cmsg, &msghdr)
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_CREDENTIALS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
ucred = (struct ucred*) CMSG_DATA(cmsg);
if (msghdr.msg_flags & MSG_TRUNC) {
log_warning("Got overly long notification datagram, ignoring.");
return 0;
}
ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
if (!ucred || ucred->pid <= 0) {
log_warning("Got notification datagram lacking credential information, ignoring.");
return 0;

View File

@ -246,9 +246,10 @@ static int server_init(Server *s, unsigned n_sockets) {
assert(s);
assert(n_sockets > 0);
zero(*s);
*s = (struct Server) {
.epoll_fd = epoll_create1(EPOLL_CLOEXEC),
};
s->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
if (s->epoll_fd < 0) {
r = log_error_errno(errno,
"Failed to create epoll object: %m");
@ -256,7 +257,6 @@ static int server_init(Server *s, unsigned n_sockets) {
}
for (i = 0; i < n_sockets; i++) {
struct epoll_event ev;
Fifo *f;
int fd;
@ -283,9 +283,11 @@ static int server_init(Server *s, unsigned n_sockets) {
f->fd = -1;
zero(ev);
ev.events = EPOLLIN;
ev.data.ptr = f;
struct epoll_event ev = {
.events = EPOLLIN,
.data.ptr = f,
};
if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
r = -errno;
fifo_free(f);

View File

@ -1783,7 +1783,6 @@ static int setup_keys(void) {
int fd = -1, r;
sd_id128_t machine, boot;
char *p = NULL, *k = NULL;
struct FSSHeader h;
uint64_t n;
struct stat st;
@ -1873,15 +1872,17 @@ static int setup_keys(void) {
if (r < 0)
log_warning_errno(r, "Failed to set file attributes: %m");
zero(h);
struct FSSHeader h = {
.machine_id = machine,
.boot_id = boot,
.header_size = htole64(sizeof(h)),
.start_usec = htole64(n * arg_interval),
.interval_usec = htole64(arg_interval),
.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR),
.fsprg_state_size = htole64(state_size),
};
memcpy(h.signature, "KSHHRHLP", 8);
h.machine_id = machine;
h.boot_id = boot;
h.header_size = htole64(sizeof(h));
h.start_usec = htole64(n * arg_interval);
h.interval_usec = htole64(arg_interval);
h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
h.fsprg_state_size = htole64(state_size);
r = loop_write(fd, &h, sizeof(h), false);
if (r < 0) {

View File

@ -491,8 +491,7 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
StdoutStream *s = userdata;
struct ucred *ucred = NULL;
struct cmsghdr *cmsg;
struct ucred *ucred;
struct iovec iovec;
size_t limit;
ssize_t l;
@ -541,25 +540,14 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
goto terminate;
}
CMSG_FOREACH(cmsg, &msghdr)
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_CREDENTIALS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
assert(!ucred);
ucred = (struct ucred *)CMSG_DATA(cmsg);
break;
}
/* Invalidate the context if the pid of the sender changed.
* This happens when a forked process inherits stdout / stderr
* from a parent. In this case getpeercred returns the ucred
* of the parent, which can be invalid if the parent has exited
* in the meantime.
/* Invalidate the context if the pid of the sender changed. This happens when a forked process
* inherits stdout / stderr from a parent. In this case getpeercred returns the ucred of the parent,
* which can be invalid if the parent has exited in the meantime.
*/
ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
if (ucred && ucred->pid != s->ucred.pid) {
/* force out any previously half-written lines from a
* different process, before we switch to the new ucred
* structure for everything we just added */
/* force out any previously half-written lines from a different process, before we switch to
* the new ucred structure for everything we just added */
r = stdout_stream_scan(s, true);
if (r < 0)
goto terminate;

View File

@ -162,7 +162,7 @@ static Window *window_add(MMapCache *m, MMapFileDescriptor *f, int prot, bool ke
if (!m->last_unused || m->n_windows <= WINDOWS_MIN) {
/* Allocate a new window */
w = new0(Window, 1);
w = new(Window, 1);
if (!w)
return NULL;
m->n_windows++;
@ -171,16 +171,17 @@ static Window *window_add(MMapCache *m, MMapFileDescriptor *f, int prot, bool ke
/* Reuse an existing one */
w = m->last_unused;
window_unlink(w);
zero(*w);
}
w->cache = m;
w->fd = f;
w->prot = prot;
w->keep_always = keep_always;
w->offset = offset;
w->size = size;
w->ptr = ptr;
*w = (Window) {
.cache = m,
.fd = f,
.prot = prot,
.keep_always = keep_always,
.offset = offset,
.size = size,
.ptr = ptr,
};
LIST_PREPEND(by_fd, f->windows, w);

View File

@ -167,9 +167,9 @@ int icmp6_receive(int fd, void *buffer, size_t size, struct in6_addr *dst,
iov = IOVEC_MAKE(buffer, size);
len = recvmsg(fd, &msg, MSG_DONTWAIT);
len = recvmsg_safe(fd, &msg, MSG_DONTWAIT);
if (len < 0)
return -errno;
return (int) len;
if ((size_t) len != size)
return -EINVAL;

View File

@ -1927,25 +1927,21 @@ static int client_receive_message_raw(
iov = IOVEC_MAKE(packet, buflen);
len = recvmsg(fd, &msg, 0);
if (len < 0) {
if (IN_SET(errno, EAGAIN, EINTR, ENETDOWN))
return 0;
return log_dhcp_client_errno(client, errno,
len = recvmsg_safe(fd, &msg, 0);
if (IN_SET(len, -EAGAIN, -EINTR, -ENETDOWN))
return 0;
if (len < 0)
return log_dhcp_client_errno(client, len,
"Could not receive message from raw socket: %m");
} else if ((size_t)len < sizeof(DHCPPacket))
if ((size_t) len < sizeof(DHCPPacket))
return 0;
CMSG_FOREACH(cmsg, &msg)
if (cmsg->cmsg_level == SOL_PACKET &&
cmsg->cmsg_type == PACKET_AUXDATA &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);
checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
break;
}
cmsg = cmsg_find(&msg, SOL_PACKET, PACKET_AUXDATA, CMSG_LEN(sizeof(struct tpacket_auxdata)));
if (cmsg) {
struct tpacket_auxdata *aux = (struct tpacket_auxdata*) CMSG_DATA(cmsg);
checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
}
r = dhcp_packet_verify_headers(packet, len, checksum, client->port);
if (r < 0)

View File

@ -995,14 +995,12 @@ static int server_receive_message(sd_event_source *s, int fd,
iov = IOVEC_MAKE(message, buflen);
len = recvmsg(fd, &msg, 0);
if (len < 0) {
if (IN_SET(errno, EAGAIN, EINTR))
return 0;
return -errno;
}
if ((size_t)len < sizeof(DHCPMessage))
len = recvmsg_safe(fd, &msg, 0);
if (IN_SET(len, -EAGAIN, -EINTR))
return 0;
if (len < 0)
return len;
if ((size_t) len < sizeof(DHCPMessage))
return 0;
CMSG_FOREACH(cmsg, &msg) {

View File

@ -13,8 +13,9 @@
int introspect_begin(struct introspect *i, bool trusted) {
assert(i);
zero(*i);
i->trusted = trusted;
*i = (struct introspect) {
.trusted = trusted,
};
i->f = open_memstream_unlocked(&i->introspection, &i->size);
if (!i->f)

View File

@ -136,11 +136,10 @@ static int bus_socket_write_auth(sd_bus *b) {
if (b->prefer_writev)
k = writev(b->output_fd, b->auth_iovec + b->auth_index, ELEMENTSOF(b->auth_iovec) - b->auth_index);
else {
struct msghdr mh;
zero(mh);
mh.msg_iov = b->auth_iovec + b->auth_index;
mh.msg_iovlen = ELEMENTSOF(b->auth_iovec) - b->auth_index;
struct msghdr mh = {
.msg_iov = b->auth_iovec + b->auth_index,
.msg_iovlen = ELEMENTSOF(b->auth_iovec) - b->auth_index,
};
k = sendmsg(b->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
if (k < 0 && errno == ENOTSOCK) {
@ -551,11 +550,12 @@ static int bus_socket_read_auth(sd_bus *b) {
if (b->prefer_readv)
k = readv(b->input_fd, &iov, 1);
else {
zero(mh);
mh.msg_iov = &iov;
mh.msg_iovlen = 1;
mh.msg_control = &control;
mh.msg_controllen = sizeof(control);
mh = (struct msghdr) {
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = &control,
.msg_controllen = sizeof(control),
};
k = recvmsg_safe(b->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (k == -ENOTSOCK) {
@ -1194,11 +1194,12 @@ int bus_socket_read_message(sd_bus *bus) {
if (bus->prefer_readv)
k = readv(bus->input_fd, &iov, 1);
else {
zero(mh);
mh.msg_iov = &iov;
mh.msg_iovlen = 1;
mh.msg_control = &control;
mh.msg_controllen = sizeof(control);
mh = (struct msghdr) {
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = &control,
.msg_controllen = sizeof(control),
};
k = recvmsg_safe(bus->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (k == -ENOTSOCK) {

View File

@ -238,7 +238,7 @@ int socket_write_message(sd_netlink *nl, sd_netlink_message *m) {
return k;
}
static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
static int socket_recv_message(int fd, struct iovec *iov, uint32_t *ret_mcast_group, bool peek) {
union sockaddr_union sender;
uint8_t cmsg_buffer[CMSG_SPACE(sizeof(struct nl_pktinfo))];
struct msghdr msg = {
@ -249,8 +249,6 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool
.msg_control = cmsg_buffer,
.msg_controllen = sizeof(cmsg_buffer),
};
struct cmsghdr *cmsg;
uint32_t group = 0;
ssize_t n;
assert(fd >= 0);
@ -281,20 +279,16 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool
return 0;
}
CMSG_FOREACH(cmsg, &msg) {
if (cmsg->cmsg_level == SOL_NETLINK &&
cmsg->cmsg_type == NETLINK_PKTINFO &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
if (ret_mcast_group) {
struct cmsghdr *cmsg;
/* multi-cast group */
group = pktinfo->group;
}
cmsg = cmsg_find(&msg, SOL_NETLINK, NETLINK_PKTINFO, CMSG_LEN(sizeof(struct nl_pktinfo)));
if (ret_mcast_group)
*ret_mcast_group = ((struct nl_pktinfo*) CMSG_DATA(cmsg))->group;
else
*ret_mcast_group = 0;
}
if (_group)
*_group = group;
return (int) n;
}

View File

@ -3698,8 +3698,7 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r
.msg_control = &control,
.msg_controllen = sizeof(control),
};
struct cmsghdr *cmsg;
struct ucred *ucred = NULL;
struct ucred *ucred;
ssize_t n;
pid_t inner_child_pid;
_cleanup_strv_free_ char **tags = NULL;
@ -3721,15 +3720,7 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r
cmsg_close_all(&msghdr);
CMSG_FOREACH(cmsg, &msghdr) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_CREDENTIALS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
ucred = (struct ucred*) CMSG_DATA(cmsg);
}
}
ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
if (!ucred || ucred->pid != inner_child_pid) {
log_debug("Received notify message without valid credentials. Ignoring.");
return 0;

View File

@ -860,7 +860,6 @@ int ask_password_agent(
for (;;) {
char passphrase[LINE_MAX+1];
struct msghdr msghdr;
struct iovec iovec;
struct ucred *ucred;
union {
@ -919,11 +918,12 @@ int ask_password_agent(
iovec = IOVEC_MAKE(passphrase, sizeof(passphrase));
zero(control);
zero(msghdr);
msghdr.msg_iov = &iovec;
msghdr.msg_iovlen = 1;
msghdr.msg_control = &control;
msghdr.msg_controllen = sizeof(control);
struct msghdr msghdr = {
.msg_iov = &iovec,
.msg_iovlen = 1,
.msg_control = &control,
.msg_controllen = sizeof(control),
};
n = recvmsg_safe(socket_fd, &msghdr, 0);
if (IN_SET(n, -EAGAIN, -EINTR))
@ -940,15 +940,12 @@ int ask_password_agent(
continue;
}
if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
control.cmsghdr.cmsg_level != SOL_SOCKET ||
control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) {
ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
if (!ucred) {
log_debug("Received message without credentials. Ignoring.");
continue;
}
ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
if (ucred->uid != 0) {
log_debug("Got request from unprivileged user. Ignoring.");
continue;

View File

@ -243,8 +243,9 @@ int socket_address_parse_netlink(SocketAddress *a, const char *s) {
assert(a);
assert(s);
zero(*a);
a->type = SOCK_RAW;
*a = (SocketAddress) {
.type = SOCK_RAW,
};
r = extract_first_word(&s, &word, NULL, 0);
if (r < 0)

View File

@ -1443,7 +1443,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
if (name) {
r = specifier_printf(name, specifier_table, NULL, &resolved_name);
if (r < 0)
log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", fname, line, name);
return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", fname, line, name);
if (!valid_user_group_name(resolved_name, 0))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
@ -1458,7 +1458,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
if (id) {
r = specifier_printf(id, specifier_table, NULL, &resolved_id);
if (r < 0)
return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s",
return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m",
fname, line, name);
}
@ -1469,7 +1469,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
if (description) {
r = specifier_printf(description, specifier_table, NULL, &resolved_description);
if (r < 0)
return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s",
return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m",
fname, line, description);
if (!valid_gecos(resolved_description))
@ -1485,7 +1485,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
if (home) {
r = specifier_printf(home, specifier_table, NULL, &resolved_home);
if (r < 0)
return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s",
return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m",
fname, line, home);
if (!valid_home(resolved_home))
@ -1501,7 +1501,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
if (shell) {
r = specifier_printf(shell, specifier_table, NULL, &resolved_shell);
if (r < 0)
return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s",
return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m",
fname, line, shell);
if (!valid_shell(resolved_shell))

View File

@ -1078,6 +1078,11 @@ static int fd_set_acls(Item *item, int fd, const char *path, const struct stat *
if (r > 0)
return -r; /* already warned */
/* The above procfs paths don't work if /proc is not mounted. */
if (r == -ENOENT && proc_mounted() == 0)
r = -ENOSYS;
if (r == -EOPNOTSUPP) {
log_debug_errno(r, "ACLs not supported by file system at %s", path);
return 0;
@ -2556,7 +2561,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer, bool
if (r < 0) {
if (IN_SET(r, -EINVAL, -EBADSLT))
*invalid_config = true;
return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", fname, line, path);
return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", fname, line, path);
}
r = patch_var_run(fname, line, &i.path);

View File

@ -916,9 +916,8 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat
.msg_control = &control,
.msg_controllen = sizeof(control),
};
struct cmsghdr *cmsg;
ssize_t size;
struct ucred *ucred = NULL;
struct ucred *ucred;
struct worker *worker;
size = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT);
@ -937,12 +936,7 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat
continue;
}
CMSG_FOREACH(cmsg, &msghdr)
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_CREDENTIALS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
ucred = (struct ucred*) CMSG_DATA(cmsg);
ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
if (!ucred || ucred->pid <= 0) {
log_warning("Ignoring worker message without valid PID");
continue;

View File

@ -48,10 +48,30 @@ FUZZIT_ARGS="--type ${FUZZING_TYPE} --branch ${FUZZIT_BRANCH} --revision ${TRAVI
wget -O fuzzit https://github.com/fuzzitdev/fuzzit/releases/latest/download/fuzzit_Linux_x86_64
chmod +x fuzzit
find out/ -maxdepth 1 -name 'fuzz-*' -executable -type f -exec basename '{}' \; | xargs --verbose -n1 -I%FUZZER% ./fuzzit create job ${FUZZIT_ARGS} %FUZZER%-asan-ubsan out/%FUZZER% ${FUZZIT_ADDITIONAL_FILES}
# Simple wrapper which retries given command up to three times if it fails
_retry() {
local EC=1
for _ in {0..2}; do
if "$@"; then
EC=0
break
fi
sleep 1
done
return $EC
}
find out/ -maxdepth 1 -name 'fuzz-*' -executable -type f -exec basename '{}' \; | while read -r fuzzer; do
_retry ./fuzzit create job ${FUZZIT_ARGS} ${fuzzer}-asan-ubsan out/${fuzzer} ${FUZZIT_ADDITIONAL_FILES}
done
export SANITIZER="memory -fsanitize-memory-track-origins"
FUZZIT_ARGS="--type ${FUZZING_TYPE} --branch ${FUZZIT_BRANCH} --revision ${TRAVIS_COMMIT}"
tools/oss-fuzz.sh
find out/ -maxdepth 1 -name 'fuzz-*' -executable -type f -exec basename '{}' \; | xargs --verbose -n1 -I%FUZZER% ./fuzzit create job ${FUZZIT_ARGS} %FUZZER%-msan out/%FUZZER% ${FUZZIT_ADDITIONAL_FILES}
find out/ -maxdepth 1 -name 'fuzz-*' -executable -type f -exec basename '{}' \; | while read -r fuzzer; do
_retry ./fuzzit create job ${FUZZIT_ARGS} ${fuzzer}-msan out/${fuzzer} ${FUZZIT_ADDITIONAL_FILES}
done