]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fileio: beef up READ_FULL_FILE_CONNECT_SOCKET to allow setting sender socket name
authorLennart Poettering <lennart@poettering.net>
Mon, 2 Nov 2020 11:07:51 +0000 (12:07 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 3 Nov 2020 08:48:04 +0000 (09:48 +0100)
This beefs up the READ_FULL_FILE_CONNECT_SOCKET logic of
read_full_file_full() a bit: when used a sender socket name may be
specified. If specified as NULL behaviour is as before: the client
socket name is picked by the kernel. But if specified as non-NULL the
client can pick a socket name to use when connecting. This is useful to
communicate a minimal amount of metainformation from client to server,
outside of the transport payload.

Specifically, these beefs up the service credential logic to pass an
abstract AF_UNIX socket name as client socket name when connecting via
READ_FULL_FILE_CONNECT_SOCKET, that includes the requesting unit name
and the eventual credential name. This allows servers implementing the
trivial credential socket logic to distinguish clients: via a simple
getpeername() it can be determined which unit is requesting a
credential, and which credential specifically.

Example: with this patch in place, in a unit file "waldo.service" a
configuration line like the following:

    LoadCredential=foo:/run/quux/creds.sock

will result in a connection to the AF_UNIX socket /run/quux/creds.sock,
originating from an abstract namespace AF_UNIX socket:

    @$RANDOM/unit/waldo.service/foo

(The $RANDOM is replaced by some randomized string. This is included in
the socket name order to avoid namespace squatting issues: the abstract
socket namespace is open to unprivileged users after all, and care needs
to be taken not to use guessable names)

The services listening on the /run/quux/creds.sock socket may thus
easily retrieve the name of the unit the credential is requested for
plus the credential name, via a simpler getpeername(), discarding the
random preifx and the /unit/ string.

This logic uses "/" as separator between the fields, since both unit
names and credential names appear in the file system, and thus are
designed to use "/" as outer separators. Given that it's a good safe
choice to use as separators here, too avoid any conflicts.

This is a minimal patch only: the new logic is used only for the unit
file credential logic. For other places where we use
READ_FULL_FILE_CONNECT_SOCKET it is probably a good idea to use this
scheme too, but this should be done carefully in later patches, since
the socket names become API that way, and we should determine the right
amount of info to pass over.

14 files changed:
man/systemd.exec.xml
src/basic/fileio.c
src/basic/fileio.h
src/core/execute.c
src/journal-remote/journal-gatewayd.c
src/journal-remote/journal-remote-main.c
src/network/netdev/macsec.c
src/network/netdev/wireguard.c
src/nspawn/nspawn.c
src/partition/repart.c
src/shared/dissect-image.c
src/shared/json.c
src/test/test-fileio.c
src/veritysetup/veritysetup.c

index 5c18fffbc82226a0b7450f5863a6a55ef94ea7d3..69a79a18721065feaaa91769bbc481b905f8a8ca 100644 (file)
@@ -2706,15 +2706,16 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
         credential plus a file system path. The ID must be a short ASCII string suitable as filename in the
         filesystem, and may be chosen freely by the user. If the specified path is absolute it is opened as
         regular file and the credential data is read from it. If the absolute path refers to an
-        <constant>AF_UNIX</constant> stream socket in the file system a connection is made to it and the
-        credential data read from the connection, providing an easy IPC integration point for dynamically
-        providing credentials from other services. If the specified path is not absolute and itself qualifies
-        as valid credential identifier it is understood to refer to a credential that the service manager
-        itself received via the <varname>$CREDENTIALS_DIRECTORY</varname> environment variable, which may be
-        used to propagate credentials from an invoking environment (e.g. a container manager that invoked the
-        service manager) into a service. The contents of the file/socket may be arbitrary binary or textual
-        data, including newline characters and NUL bytes. This option may be used multiple times, each time
-        defining an additional credential to pass to the unit.</para>
+        <constant>AF_UNIX</constant> stream socket in the file system a connection is made to it (only once
+        at unit start-up) and the credential data read from the connection, providing an easy IPC integration
+        point for dynamically providing credentials from other services. If the specified path is not
+        absolute and itself qualifies as valid credential identifier it is understood to refer to a
+        credential that the service manager itself received via the <varname>$CREDENTIALS_DIRECTORY</varname>
+        environment variable, which may be used to propagate credentials from an invoking environment (e.g. a
+        container manager that invoked the service manager) into a service. The contents of the file/socket
+        may be arbitrary binary or textual data, including newline characters and <constant>NUL</constant>
+        bytes. This option may be used multiple times, each time defining an additional credential to pass to
+        the unit.</para>
 
         <para>The credential files/IPC sockets must be accessible to the service manager, but don't have to
         be directly accessible to the unit's processes: the credential data is read and copied into separate,
@@ -2728,7 +2729,22 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
         e.g. <literal>ExecStart=cat ${CREDENTIALS_DIRECTORY}/mycred</literal>.</para>
 
         <para>Currently, an accumulated credential size limit of 1M bytes per unit is
-        enforced.</para></listitem>
+        enforced.</para>
+
+        <para>If referencing an <constant>AF_UNIX</constant> stream socket to connect to, the connection will
+        originate from an abstract namespace socket, that includes information about the unit and the
+        credential ID in its socket name. Use <citerefentry
+        project='man-pages'><refentrytitle>getpeername</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+        to query this information. The returned socket name is formatted as <constant>NUL</constant>
+        <replaceable>RANDOM</replaceable> <literal>/unit/</literal> <replaceable>UNIT</replaceable>
+        <literal>/</literal> <replaceable>ID</replaceable>, i.e. a <constant>NUL</constant> byte (as required
+        for abstract namespace socket names), followed by a random string (consisting of alphadecimal
+        characters), followed by the literal string <literal>/unit/</literal>, followed by the requesting
+        unit name, followed by the literal character <literal>/</literal>, followed by the textual credential
+        ID requested. Example: <literal>\0adf9d86b6eda275e/unit/foobar.service/credx</literal> in case the
+        credential <literal>credx</literal> is requested for a unit <literal>foobar.service</literal>. This
+        functionality is useful for using a single listening socket to serve credentials to multiple
+        consumers.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 050c8709f81f563870776378c751c915776110bf..e53e826b728ad2f95168edb1e8426e816749c3bc 100644 (file)
@@ -602,7 +602,13 @@ finalize:
         return r;
 }
 
-int read_full_file_full(int dir_fd, const char *filename, ReadFullFileFlags flags, char **contents, size_t *size) {
+int read_full_file_full(
+                int dir_fd,
+                const char *filename,
+                ReadFullFileFlags flags,
+                const char *bind_name,
+                char **contents, size_t *size) {
+
         _cleanup_fclose_ FILE *f = NULL;
         int r;
 
@@ -645,6 +651,20 @@ int read_full_file_full(int dir_fd, const char *filename, ReadFullFileFlags flag
                 if (sk < 0)
                         return -errno;
 
+                if (bind_name) {
+                        /* If the caller specified a socket name to bind to, do so before connecting. This is
+                         * useful to communicate some minor, short meta-information token from the client to
+                         * the server. */
+                        union sockaddr_union bsa;
+
+                        r = sockaddr_un_set_path(&bsa.un, bind_name);
+                        if (r < 0)
+                                return r;
+
+                        if (bind(sk, &bsa.sa, r) < 0)
+                                return r;
+                }
+
                 if (connect(sk, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0)
                         return errno == ENOTSOCK ? -ENXIO : -errno; /* propagate original error if this is
                                                                      * not a socket after all */
index 963d7d08fc869913a99fb49a7c5277d7b082dafe..d2901cdb611dbb417afc3ea9642e3f25e098e438 100644 (file)
@@ -60,9 +60,9 @@ static inline int write_string_file(const char *fn, const char *line, WriteStrin
 int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *format, ...) _printf_(3, 4);
 
 int read_one_line_file(const char *filename, char **line);
-int read_full_file_full(int dir_fd, const char *filename, ReadFullFileFlags flags, char **contents, size_t *size);
+int read_full_file_full(int dir_fd, const char *filename, ReadFullFileFlags flags, const char *bind_name, char **contents, size_t *size);
 static inline int read_full_file(const char *filename, char **contents, size_t *size) {
-        return read_full_file_full(AT_FDCWD, filename, 0, contents, size);
+        return read_full_file_full(AT_FDCWD, filename, 0, NULL, contents, size);
 }
 int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size);
 int read_full_stream_full(FILE *f, const char *filename, ReadFullFileFlags flags, char **contents, size_t *size);
index 98e54acf77efa03ef08b71354cb4c5dfe7828c09..e0062eed40855435c6f8e24b4396ac56aeb0f900 100644 (file)
@@ -73,6 +73,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
+#include "random-util.h"
 #include "rlimit-util.h"
 #include "rm-rf.h"
 #if HAVE_SECCOMP
@@ -2509,6 +2510,7 @@ static int write_credential(
 static int acquire_credentials(
                 const ExecContext *context,
                 const ExecParameters *params,
+                const char *unit,
                 const char *p,
                 uid_t uid,
                 bool ownership_ok) {
@@ -2546,7 +2548,7 @@ static int acquire_credentials(
         STRV_FOREACH_PAIR(id, fn, context->load_credentials) {
                 ReadFullFileFlags flags = READ_FULL_FILE_SECURE;
                 _cleanup_(erase_and_freep) char *data = NULL;
-                _cleanup_free_ char *j = NULL;
+                _cleanup_free_ char *j = NULL, *bindname = NULL;
                 const char *source;
                 size_t size, add;
 
@@ -2554,6 +2556,12 @@ static int acquire_credentials(
                         /* If this is an absolute path, read the data directly from it, and support AF_UNIX sockets */
                         source = *fn;
                         flags |= READ_FULL_FILE_CONNECT_SOCKET;
+
+                        /* Pass some minimal info about the unit and the credential name we are looking to acquire
+                         * via the source socket address in case we read off an AF_UNIX socket. */
+                        if (asprintf(&bindname, "@%" PRIx64"/unit/%s/%s", random_u64(), unit, *id) < 0)
+                                return -ENOMEM;
+
                 } else if (params->received_credentials) {
                         /* If this is a relative path, take it relative to the credentials we received
                          * ourselves. We don't support the AF_UNIX stuff in this mode, since we are operating
@@ -2566,8 +2574,9 @@ static int acquire_credentials(
                 } else
                         source = NULL;
 
+
                 if (source)
-                        r = read_full_file_full(AT_FDCWD, source, flags, &data, &size);
+                        r = read_full_file_full(AT_FDCWD, source, flags, bindname, &data, &size);
                 else
                         r = -ENOENT;
                 if (r == -ENOENT &&
@@ -2613,6 +2622,7 @@ static int acquire_credentials(
 static int setup_credentials_internal(
                 const ExecContext *context,
                 const ExecParameters *params,
+                const char *unit,
                 const char *final,        /* This is where the credential store shall eventually end up at */
                 const char *workspace,    /* This is where we can prepare it before moving it to the final place */
                 bool reuse_workspace,     /* Whether to reuse any existing workspace mount if it already is a mount */
@@ -2724,7 +2734,7 @@ static int setup_credentials_internal(
         assert(!must_mount || workspace_mounted > 0);
         where = workspace_mounted ? workspace : final;
 
-        r = acquire_credentials(context, params, where, uid, workspace_mounted);
+        r = acquire_credentials(context, params, unit, where, uid, workspace_mounted);
         if (r < 0)
                 return r;
 
@@ -2824,6 +2834,7 @@ static int setup_credentials(
                 r = setup_credentials_internal(
                                 context,
                                 params,
+                                unit,
                                 p,       /* final mount point */
                                 u,       /* temporary workspace to overmount */
                                 true,    /* reuse the workspace if it is already a mount */
@@ -2861,6 +2872,7 @@ static int setup_credentials(
                 r = setup_credentials_internal(
                                 context,
                                 params,
+                                unit,
                                 p,           /* final mount point */
                                 "/dev/shm",  /* temporary workspace to overmount */
                                 false,       /* do not reuse /dev/shm if it is already a mount, under no circumstances */
index c4d45020803d6a425d21d4d106d7a32128985714..a0de0fa9b5f6e2608f5c2568e7f03d5689a493e7 100644 (file)
@@ -896,7 +896,7 @@ static int parse_argv(int argc, char *argv[]) {
                         if (arg_key_pem)
                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                        "Key file specified twice");
-                        r = read_full_file_full(AT_FDCWD, optarg, READ_FULL_FILE_CONNECT_SOCKET, &arg_key_pem, NULL);
+                        r = read_full_file_full(AT_FDCWD, optarg, READ_FULL_FILE_CONNECT_SOCKET, NULL, &arg_key_pem, NULL);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to read key file: %m");
                         assert(arg_key_pem);
@@ -906,7 +906,7 @@ static int parse_argv(int argc, char *argv[]) {
                         if (arg_cert_pem)
                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                        "Certificate file specified twice");
-                        r = read_full_file_full(AT_FDCWD, optarg, READ_FULL_FILE_CONNECT_SOCKET, &arg_cert_pem, NULL);
+                        r = read_full_file_full(AT_FDCWD, optarg, READ_FULL_FILE_CONNECT_SOCKET, NULL, &arg_cert_pem, NULL);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to read certificate file: %m");
                         assert(arg_cert_pem);
@@ -917,7 +917,7 @@ static int parse_argv(int argc, char *argv[]) {
                         if (arg_trust_pem)
                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                        "CA certificate file specified twice");
-                        r = read_full_file_full(AT_FDCWD, optarg, READ_FULL_FILE_CONNECT_SOCKET, &arg_trust_pem, NULL);
+                        r = read_full_file_full(AT_FDCWD, optarg, READ_FULL_FILE_CONNECT_SOCKET, NULL, &arg_trust_pem, NULL);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to read CA certificate file: %m");
                         assert(arg_trust_pem);
index 0e028a9e4a7a51ca0c4c13e8a51b9c07d7926494..6eea8acb05e7c68df864226d67dd91bed279cfd9 100644 (file)
@@ -1077,12 +1077,12 @@ static int parse_argv(int argc, char *argv[]) {
 static int load_certificates(char **key, char **cert, char **trust) {
         int r;
 
-        r = read_full_file_full(AT_FDCWD, arg_key ?: PRIV_KEY_FILE, READ_FULL_FILE_CONNECT_SOCKET, key, NULL);
+        r = read_full_file_full(AT_FDCWD, arg_key ?: PRIV_KEY_FILE, READ_FULL_FILE_CONNECT_SOCKET, NULL, key, NULL);
         if (r < 0)
                 return log_error_errno(r, "Failed to read key from file '%s': %m",
                                        arg_key ?: PRIV_KEY_FILE);
 
-        r = read_full_file_full(AT_FDCWD, arg_cert ?: CERT_FILE, READ_FULL_FILE_CONNECT_SOCKET, cert, NULL);
+        r = read_full_file_full(AT_FDCWD, arg_cert ?: CERT_FILE, READ_FULL_FILE_CONNECT_SOCKET, NULL, cert, NULL);
         if (r < 0)
                 return log_error_errno(r, "Failed to read certificate from file '%s': %m",
                                        arg_cert ?: CERT_FILE);
@@ -1090,7 +1090,7 @@ static int load_certificates(char **key, char **cert, char **trust) {
         if (arg_trust_all)
                 log_info("Certificate checking disabled.");
         else {
-                r = read_full_file_full(AT_FDCWD, arg_trust ?: TRUST_FILE, READ_FULL_FILE_CONNECT_SOCKET, trust, NULL);
+                r = read_full_file_full(AT_FDCWD, arg_trust ?: TRUST_FILE, READ_FULL_FILE_CONNECT_SOCKET, NULL, trust, NULL);
                 if (r < 0)
                         return log_error_errno(r, "Failed to read CA certificate file '%s': %m",
                                                arg_trust ?: TRUST_FILE);
index 9f0e6f25c1e51739fc889fd33394b102d48a33b7..e84a18ffae20da83558fc28bf48768dbe9d15049 100644 (file)
@@ -989,7 +989,7 @@ static int macsec_read_key_file(NetDev *netdev, SecurityAssociation *sa) {
         r = read_full_file_full(
                         AT_FDCWD, sa->key_file,
                         READ_FULL_FILE_SECURE | READ_FULL_FILE_UNHEX | READ_FULL_FILE_WARN_WORLD_READABLE | READ_FULL_FILE_CONNECT_SOCKET,
-                        (char **) &key, &key_len);
+                        NULL, (char **) &key, &key_len);
         if (r < 0)
                 return log_netdev_error_errno(netdev, r,
                                               "Failed to read key from '%s', ignoring: %m",
index f1de5d41de827d9cc66ce525fa20015f10699ae5..e7683892a5b1b6b88bc1d13ffe82cd4a697d1a86 100644 (file)
@@ -871,7 +871,7 @@ static int wireguard_read_key_file(const char *filename, uint8_t dest[static WG_
         r = read_full_file_full(
                         AT_FDCWD, filename,
                         READ_FULL_FILE_SECURE | READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_WARN_WORLD_READABLE | READ_FULL_FILE_CONNECT_SOCKET,
-                        &key, &key_len);
+                        NULL, &key, &key_len);
         if (r < 0)
                 return r;
 
index 5db08cb5b3a65c8fd4cb950fe73ceece1ef61bef..e59237e2275a698db767f8917eee64845417c216 100644 (file)
@@ -1589,7 +1589,7 @@ static int parse_argv(int argc, char *argv[]) {
                                         return log_oom();
                         }
 
-                        r = read_full_file_full(AT_FDCWD, j ?: p, flags, &data, &size);
+                        r = read_full_file_full(AT_FDCWD, j ?: p, flags, NULL, &data, &size);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to read credential '%s': %m", j ?: p);
 
index 4cf6a5fe3a69e447557b028c7f2fcf57c48d9fda..0f3d3b3c75dcaf4bf5cda4218daaabf9ce84d8a6 100644 (file)
@@ -3630,7 +3630,7 @@ static int parse_argv(int argc, char *argv[]) {
                         _cleanup_(erase_and_freep) char *k = NULL;
                         size_t n = 0;
 
-                        r = read_full_file_full(AT_FDCWD, optarg, READ_FULL_FILE_SECURE|READ_FULL_FILE_CONNECT_SOCKET, &k, &n);
+                        r = read_full_file_full(AT_FDCWD, optarg, READ_FULL_FILE_SECURE|READ_FULL_FILE_CONNECT_SOCKET, NULL, &k, &n);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to read key file '%s': %m", optarg);
 
index 1820b81e11b2794a9a571c9b0fd434c9bbf345ce..394692093c151370a26321969e1219c8fb89b6aa 100644 (file)
@@ -2115,7 +2115,7 @@ int verity_settings_load(
 
         if (verity->root_hash && !verity->root_hash_sig) {
                 if (root_hash_sig_path) {
-                        r = read_full_file_full(AT_FDCWD, root_hash_sig_path, 0, (char**) &root_hash_sig, &root_hash_sig_size);
+                        r = read_full_file_full(AT_FDCWD, root_hash_sig_path, 0, NULL, (char**) &root_hash_sig, &root_hash_sig_size);
                         if (r < 0 && r != -ENOENT)
                                 return r;
 
@@ -2131,7 +2131,7 @@ int verity_settings_load(
                                 if (!p)
                                         return -ENOMEM;
 
-                                r = read_full_file_full(AT_FDCWD, p, 0, (char**) &root_hash_sig, &root_hash_sig_size);
+                                r = read_full_file_full(AT_FDCWD, p, 0, NULL, (char**) &root_hash_sig, &root_hash_sig_size);
                                 if (r < 0 && r != -ENOENT)
                                         return r;
                                 if (r >= 0)
@@ -2145,7 +2145,7 @@ int verity_settings_load(
                                 if (!p)
                                         return -ENOMEM;
 
-                                r = read_full_file_full(AT_FDCWD, p, 0, (char**) &root_hash_sig, &root_hash_sig_size);
+                                r = read_full_file_full(AT_FDCWD, p, 0, NULL, (char**) &root_hash_sig, &root_hash_sig_size);
                                 if (r < 0 && r != -ENOENT)
                                         return r;
                                 if (r >= 0)
index 1d2cbc8aed980f4431b70bfac3388c99f07df1c0..dc06dcb6b8eb8e23b57dd4203a26634afd8c07d7 100644 (file)
@@ -3195,7 +3195,7 @@ int json_parse_file_at(FILE *f, int dir_fd, const char *path, JsonParseFlags fla
         if (f)
                 r = read_full_stream(f, &text, NULL);
         else if (path)
-                r = read_full_file_full(dir_fd, path, 0, &text, NULL);
+                r = read_full_file_full(dir_fd, path, 0, NULL, &text, NULL);
         else
                 return -EINVAL;
         if (r < 0)
index ce5af43db5796d5cd3fc08fea6facc9ef84af99b..fcc2bc2a8b351706d19eaf525ccafc0e396d5506 100644 (file)
@@ -15,6 +15,7 @@
 #include "io-util.h"
 #include "parse-util.h"
 #include "process-util.h"
+#include "random-util.h"
 #include "rm-rf.h"
 #include "socket-util.h"
 #include "string-util.h"
@@ -863,7 +864,7 @@ static void test_read_nul_string(void) {
 static void test_read_full_file_socket(void) {
         _cleanup_(rm_rf_physical_and_freep) char *z = NULL;
         _cleanup_close_ int listener = -1;
-        _cleanup_free_ char *data = NULL;
+        _cleanup_free_ char *data = NULL, *clientname = NULL;
         union sockaddr_union sa;
         const char *j;
         size_t size;
@@ -883,23 +884,35 @@ static void test_read_full_file_socket(void) {
         assert_se(bind(listener, &sa.sa, SOCKADDR_UN_LEN(sa.un)) >= 0);
         assert_se(listen(listener, 1) >= 0);
 
+        /* Bind the *client* socket to some randomized name, to verify that this works correctly. */
+        assert_se(asprintf(&clientname, "@%" PRIx64 "/test-bindname", random_u64()) >= 0);
+
         r = safe_fork("(server)", FORK_DEATHSIG|FORK_LOG, &pid);
         assert_se(r >= 0);
         if (r == 0) {
+                union sockaddr_union peer = {};
+                socklen_t peerlen = sizeof(peer);
                 _cleanup_close_ int rfd = -1;
                 /* child */
 
                 rfd = accept4(listener, NULL, 0, SOCK_CLOEXEC);
                 assert_se(rfd >= 0);
 
+                assert_se(getpeername(rfd, &peer.sa, &peerlen) >= 0);
+
+                assert_se(peer.un.sun_family == AF_UNIX);
+                assert_se(peerlen > offsetof(struct sockaddr_un, sun_path));
+                assert_se(peer.un.sun_path[0] == 0);
+                assert_se(streq(peer.un.sun_path + 1, clientname + 1));
+
 #define TEST_STR "This is a test\nreally."
 
                 assert_se(write(rfd, TEST_STR, strlen(TEST_STR)) == strlen(TEST_STR));
                 _exit(EXIT_SUCCESS);
         }
 
-        assert_se(read_full_file_full(AT_FDCWD, j, 0, &data, &size) == -ENXIO);
-        assert_se(read_full_file_full(AT_FDCWD, j, READ_FULL_FILE_CONNECT_SOCKET, &data, &size) >= 0);
+        assert_se(read_full_file_full(AT_FDCWD, j, 0, NULL, &data, &size) == -ENXIO);
+        assert_se(read_full_file_full(AT_FDCWD, j, READ_FULL_FILE_CONNECT_SOCKET, clientname, &data, &size) >= 0);
         assert_se(size == strlen(TEST_STR));
         assert_se(streq(data, TEST_STR));
 
index 829495175924895602823a88dd8a15fa8bc1da68..7ea9eae796348cb9f9fca14a73e823c04e3afa95 100644 (file)
@@ -100,7 +100,7 @@ static int run(int argc, char *argv[]) {
                                 if (r < 0)
                                         return log_error_errno(r, "Failed to parse root hash signature '%s': %m", argv[6]);
                         } else {
-                                r = read_full_file_full(AT_FDCWD, argv[6], READ_FULL_FILE_CONNECT_SOCKET, &hash_sig, &hash_sig_size);
+                                r = read_full_file_full(AT_FDCWD, argv[6], READ_FULL_FILE_CONNECT_SOCKET, NULL, &hash_sig, &hash_sig_size);
                                 if (r < 0)
                                         return log_error_errno(r, "Failed to read root hash signature: %m");
                         }