1 Star 0 Fork 49

happy_orange/systemd

forked from src-anolis-os/systemd 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
10026-fileio-beef-up-READ_FULL_FILE_CONNECT_SOCKET-to-all.patch 8.12 KB
一键复制 编辑 原始数据 按行查看 历史
From 0717de25e6508b10ea034fa1b96675f18100ac01 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 2 Nov 2020 12:07:51 +0100
Subject: [PATCH] fileio: beef up READ_FULL_FILE_CONNECT_SOCKET to allow
setting sender socket name
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.
(cherry picked from commit 142e9756c98c69cdd5d03df4028700acb5739f72)
Signed-off-by: Guorui Yu <GuoRui.Yu@linux.alibaba.com>
---
src/basic/fileio.c | 22 +++++++++++++++++++++-
src/basic/fileio.h | 4 ++--
src/test/test-fileio.c | 19 ++++++++++++++++---
3 files changed, 39 insertions(+), 6 deletions(-)
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index 9cb0a2bd28..35eaa3c1c7 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -574,7 +574,13 @@ static int xfopenat(int dir_fd, const char *path, const char *mode, int flags, F
return 0;
}
-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;
@@ -617,6 +623,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 */
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
index 1a16e0fd13..82897e209c 100644
--- a/src/basic/fileio.h
+++ b/src/basic/fileio.h
@@ -44,9 +44,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_stream_full(FILE *f, const char *filename, ReadFullFileFlags flags, char **contents, size_t *size);
static inline int read_full_stream(FILE *f, char **contents, size_t *size) {
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index 82b7cb1242..5ec70eec14 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -14,6 +14,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"
@@ -714,7 +715,7 @@ static void test_read_line3(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;
@@ -734,23 +735,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));
--
2.39.1
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/happy_orange/systemd.git
git@gitee.com:happy_orange/systemd.git
happy_orange
systemd
systemd
a8

搜索帮助

0d507c66 1850385 C8b1a773 1850385