mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-11 05:17:44 +03:00
Merge pull request #25734 from yuwata/sd-id128
sd-id128: several followups
This commit is contained in:
commit
30a3181504
@ -94,10 +94,20 @@
|
||||
has properties similar to the machine ID during that time.</para>
|
||||
|
||||
<para><function>sd_id128_get_invocation()</function> returns the invocation ID of the currently executed
|
||||
service. In its current implementation, this reads and parses the <varname>$INVOCATION_ID</varname> environment
|
||||
variable that the service manager sets when activating a service, see
|
||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for details. The
|
||||
ID is cached internally. In future a different mechanism to determine the invocation ID may be added.</para>
|
||||
service. In its current implementation, this tries to read and parse the following:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>The <varname>$INVOCATION_ID</varname> environment variable that the service manager sets when
|
||||
activating a service.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>An entry in the kernel keyring that the system service manager sets when activating a service.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
See <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details. The ID is cached internally. In future a different mechanism to determine the invocation ID
|
||||
may be added.</para>
|
||||
|
||||
<para>Note that <function>sd_id128_get_machine_app_specific()</function>,
|
||||
<function>sd_id128_get_boot()</function>, <function>sd_id128_get_boot_app_specific()</function>, and
|
||||
@ -139,7 +149,8 @@
|
||||
|
||||
<listitem><para>Returned by <function>sd_id128_get_machine()</function> and
|
||||
<function>sd_id128_get_machine_app_specific()</function> when <filename>/etc/machine-id</filename>
|
||||
is empty or all zeros.</para></listitem>
|
||||
is empty or all zeros. Also returned by <function>sd_id128_get_invocation()</function> when the
|
||||
invocation ID is all zeros.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@ -166,7 +177,7 @@
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>-EIO</constant></term>
|
||||
<term><constant>-EUCLEAN</constant></term>
|
||||
|
||||
<listitem><para>Returned by any of the functions described here when the configured value has
|
||||
invalid format.</para></listitem>
|
||||
|
@ -43,6 +43,7 @@ bool id128_is_valid(const char *s) {
|
||||
int id128_read_fd(int fd, Id128FormatFlag f, sd_id128_t *ret) {
|
||||
char buffer[SD_ID128_UUID_STRING_MAX + 1]; /* +1 is for trailing newline */
|
||||
ssize_t l;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
@ -54,7 +55,7 @@ int id128_read_fd(int fd, Id128FormatFlag f, sd_id128_t *ret) {
|
||||
* This returns the following:
|
||||
* -ENOMEDIUM: an empty string,
|
||||
* -ENOPKG: "uninitialized" or "uninitialized\n",
|
||||
* -EINVAL: other invalid strings. */
|
||||
* -EUCLEAN: other invalid strings. */
|
||||
|
||||
l = loop_read(fd, buffer, sizeof(buffer), false); /* we expect a short read of either 32/33 or 36/37 chars */
|
||||
if (l < 0)
|
||||
@ -70,33 +71,34 @@ int id128_read_fd(int fd, Id128FormatFlag f, sd_id128_t *ret) {
|
||||
|
||||
case SD_ID128_STRING_MAX: /* plain UUID with trailing newline */
|
||||
if (buffer[SD_ID128_STRING_MAX-1] != '\n')
|
||||
return -EINVAL;
|
||||
return -EUCLEAN;
|
||||
|
||||
_fallthrough_;
|
||||
case SD_ID128_STRING_MAX-1: /* plain UUID without trailing newline */
|
||||
if (!FLAGS_SET(f, ID128_FORMAT_PLAIN))
|
||||
return -EINVAL;
|
||||
return -EUCLEAN;
|
||||
|
||||
buffer[SD_ID128_STRING_MAX-1] = 0;
|
||||
break;
|
||||
|
||||
case SD_ID128_UUID_STRING_MAX: /* RFC UUID with trailing newline */
|
||||
if (buffer[SD_ID128_UUID_STRING_MAX-1] != '\n')
|
||||
return -EINVAL;
|
||||
return -EUCLEAN;
|
||||
|
||||
_fallthrough_;
|
||||
case SD_ID128_UUID_STRING_MAX-1: /* RFC UUID without trailing newline */
|
||||
if (!FLAGS_SET(f, ID128_FORMAT_UUID))
|
||||
return -EINVAL;
|
||||
return -EUCLEAN;
|
||||
|
||||
buffer[SD_ID128_UUID_STRING_MAX-1] = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
return -EUCLEAN;
|
||||
}
|
||||
|
||||
return sd_id128_from_string(buffer, ret);
|
||||
r = sd_id128_from_string(buffer, ret);
|
||||
return r == -EINVAL ? -EUCLEAN : r;
|
||||
}
|
||||
|
||||
int id128_read(const char *p, Id128FormatFlag f, sd_id128_t *ret) {
|
||||
|
@ -124,8 +124,6 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) {
|
||||
static thread_local sd_id128_t saved_machine_id = {};
|
||||
int r;
|
||||
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
if (sd_id128_is_null(saved_machine_id)) {
|
||||
r = id128_read("/etc/machine-id", ID128_FORMAT_PLAIN, &saved_machine_id);
|
||||
if (r < 0)
|
||||
@ -135,7 +133,8 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) {
|
||||
return -ENOMEDIUM;
|
||||
}
|
||||
|
||||
*ret = saved_machine_id;
|
||||
if (ret)
|
||||
*ret = saved_machine_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -143,8 +142,6 @@ _public_ int sd_id128_get_boot(sd_id128_t *ret) {
|
||||
static thread_local sd_id128_t saved_boot_id = {};
|
||||
int r;
|
||||
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
if (sd_id128_is_null(saved_boot_id)) {
|
||||
r = id128_read("/proc/sys/kernel/random/boot_id", ID128_FORMAT_UUID, &saved_boot_id);
|
||||
if (r == -ENOENT && proc_mounted() == 0)
|
||||
@ -156,7 +153,8 @@ _public_ int sd_id128_get_boot(sd_id128_t *ret) {
|
||||
return -ENOMEDIUM;
|
||||
}
|
||||
|
||||
*ret = saved_boot_id;
|
||||
if (ret)
|
||||
*ret = saved_boot_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -206,22 +204,22 @@ static int get_invocation_from_keyring(sd_id128_t *ret) {
|
||||
/* Chop off the final description string */
|
||||
d = strrchr(description, ';');
|
||||
if (!d)
|
||||
return -EIO;
|
||||
return -EUCLEAN;
|
||||
*d = 0;
|
||||
|
||||
/* Look for the permissions */
|
||||
p = strrchr(description, ';');
|
||||
if (!p)
|
||||
return -EIO;
|
||||
return -EUCLEAN;
|
||||
|
||||
errno = 0;
|
||||
perms = strtoul(p + 1, &e, 16);
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
if (e == p + 1) /* Read at least one character */
|
||||
return -EIO;
|
||||
return -EUCLEAN;
|
||||
if (e != d) /* Must reached the end */
|
||||
return -EIO;
|
||||
return -EUCLEAN;
|
||||
|
||||
if ((perms & ~MAX_PERMS) != 0)
|
||||
return -EPERM;
|
||||
@ -231,7 +229,7 @@ static int get_invocation_from_keyring(sd_id128_t *ret) {
|
||||
/* Look for the group ID */
|
||||
g = strrchr(description, ';');
|
||||
if (!g)
|
||||
return -EIO;
|
||||
return -EUCLEAN;
|
||||
r = parse_gid(g + 1, &gid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -242,7 +240,7 @@ static int get_invocation_from_keyring(sd_id128_t *ret) {
|
||||
/* Look for the user ID */
|
||||
u = strrchr(description, ';');
|
||||
if (!u)
|
||||
return -EIO;
|
||||
return -EUCLEAN;
|
||||
r = parse_uid(u + 1, &uid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -253,13 +251,14 @@ static int get_invocation_from_keyring(sd_id128_t *ret) {
|
||||
if (c < 0)
|
||||
return -errno;
|
||||
if (c != sizeof(sd_id128_t))
|
||||
return -EIO;
|
||||
return -EUCLEAN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_invocation_from_environment(sd_id128_t *ret) {
|
||||
const char *e;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
@ -267,33 +266,31 @@ static int get_invocation_from_environment(sd_id128_t *ret) {
|
||||
if (!e)
|
||||
return -ENXIO;
|
||||
|
||||
return sd_id128_from_string(e, ret);
|
||||
r = sd_id128_from_string(e, ret);
|
||||
return r == -EINVAL ? -EUCLEAN : r;
|
||||
}
|
||||
|
||||
_public_ int sd_id128_get_invocation(sd_id128_t *ret) {
|
||||
static thread_local sd_id128_t saved_invocation_id = {};
|
||||
int r;
|
||||
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
if (sd_id128_is_null(saved_invocation_id)) {
|
||||
/* We first check the environment. The environment variable is primarily relevant for user
|
||||
* services, and sufficiently safe as long as no privilege boundary is involved. */
|
||||
r = get_invocation_from_environment(&saved_invocation_id);
|
||||
if (r >= 0) {
|
||||
*ret = saved_invocation_id;
|
||||
return 0;
|
||||
} else if (r != -ENXIO)
|
||||
return r;
|
||||
|
||||
/* The kernel keyring is relevant for system services (as for user services we don't store
|
||||
* the invocation ID in the keyring, as there'd be no trust benefit in that). */
|
||||
r = get_invocation_from_keyring(&saved_invocation_id);
|
||||
if (r == -ENXIO)
|
||||
/* The kernel keyring is relevant for system services (as for user services we don't
|
||||
* store the invocation ID in the keyring, as there'd be no trust benefit in that). */
|
||||
r = get_invocation_from_keyring(&saved_invocation_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (sd_id128_is_null(saved_invocation_id))
|
||||
return -ENOMEDIUM;
|
||||
}
|
||||
|
||||
*ret = saved_invocation_id;
|
||||
if (ret)
|
||||
*ret = saved_invocation_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ TEST(id128) {
|
||||
assert_se(id128_write_fd(fd, ID128_FORMAT_UUID, id) >= 0);
|
||||
|
||||
assert_se(lseek(fd, 0, SEEK_SET) == 0);
|
||||
assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) == -EINVAL);
|
||||
assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) == -EUCLEAN);
|
||||
|
||||
assert_se(lseek(fd, 0, SEEK_SET) == 0);
|
||||
assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) >= 0);
|
||||
@ -107,7 +107,7 @@ TEST(id128) {
|
||||
assert_se(id128_write_fd(fd, ID128_FORMAT_PLAIN, id) >= 0);
|
||||
|
||||
assert_se(lseek(fd, 0, SEEK_SET) == 0);
|
||||
assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) == -EINVAL);
|
||||
assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) == -EUCLEAN);
|
||||
|
||||
assert_se(lseek(fd, 0, SEEK_SET) == 0);
|
||||
assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) >= 0);
|
||||
@ -125,7 +125,7 @@ TEST(id128) {
|
||||
assert_se(write(fd, sd_id128_to_string(id, t), 32) == 32);
|
||||
|
||||
assert_se(lseek(fd, 0, SEEK_SET) == 0);
|
||||
assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) == -EINVAL);
|
||||
assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) == -EUCLEAN);
|
||||
|
||||
assert_se(lseek(fd, 0, SEEK_SET) == 0);
|
||||
assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) >= 0);
|
||||
@ -139,7 +139,7 @@ TEST(id128) {
|
||||
assert_se(write(fd, sd_id128_to_uuid_string(id, q), 36) == 36);
|
||||
|
||||
assert_se(lseek(fd, 0, SEEK_SET) == 0);
|
||||
assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) == -EINVAL);
|
||||
assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) == -EUCLEAN);
|
||||
|
||||
assert_se(lseek(fd, 0, SEEK_SET) == 0);
|
||||
assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) >= 0);
|
||||
@ -162,13 +162,13 @@ TEST(id128) {
|
||||
assert_se(ftruncate(fd, 0) >= 0);
|
||||
assert_se(write(fd, "uninitialized\nfoo", STRLEN("uninitialized\nfoo")) == STRLEN("uninitialized\nfoo"));
|
||||
assert_se(lseek(fd, 0, SEEK_SET) == 0);
|
||||
assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -EINVAL);
|
||||
assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -EUCLEAN);
|
||||
|
||||
assert_se(lseek(fd, 0, SEEK_SET) == 0);
|
||||
assert_se(ftruncate(fd, 0) >= 0);
|
||||
assert_se(write(fd, "uninit", STRLEN("uninit")) == STRLEN("uninit"));
|
||||
assert_se(lseek(fd, 0, SEEK_SET) == 0);
|
||||
assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -EINVAL);
|
||||
assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -EUCLEAN);
|
||||
|
||||
if (sd_booted() > 0 && access("/etc/machine-id", F_OK) >= 0) {
|
||||
assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id) >= 0);
|
||||
|
Loading…
Reference in New Issue
Block a user