Compare commits
6 Commits
ec34e7d1ab
...
9142bbd19c
Author | SHA1 | Date |
---|---|---|
Zbigniew Jędrzejewski-Szmek | 9142bbd19c | |
Zbigniew Jędrzejewski-Szmek | 68296b8b83 | |
Lennart Poettering | 6f0245b342 | |
Lennart Poettering | 7a77d2a41c | |
Lennart Poettering | 28937bcc6c | |
Lennart Poettering | 24a0b2c0ab |
|
@ -32,3 +32,8 @@
|
|||
#ifndef MQUEUE_MAGIC
|
||||
#define MQUEUE_MAGIC 0x19800202
|
||||
#endif
|
||||
|
||||
/* Not exposed yet (as of Linux 5.4). Defined in fs/xfs/libxfs/xfs_format.h */
|
||||
#ifndef XFS_SB_MAGIC
|
||||
#define XFS_SB_MAGIC 0x58465342
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
/* This is currently not exported in the public kernel headers, but the libxfs library code part of xfsprogs
|
||||
* defines it as public header */
|
||||
|
||||
#ifndef XFS_IOC_FSGEOMETRY
|
||||
#define XFS_IOC_FSGEOMETRY _IOR ('X', 124, struct xfs_fsop_geom)
|
||||
|
||||
typedef struct xfs_fsop_geom {
|
||||
uint32_t blocksize;
|
||||
uint32_t rtextsize;
|
||||
uint32_t agblocks;
|
||||
uint32_t agcount;
|
||||
uint32_t logblocks;
|
||||
uint32_t sectsize;
|
||||
uint32_t inodesize;
|
||||
uint32_t imaxpct;
|
||||
uint64_t datablocks;
|
||||
uint64_t rtblocks;
|
||||
uint64_t rtextents;
|
||||
uint64_t logstart;
|
||||
unsigned char uuid[16];
|
||||
uint32_t sunit;
|
||||
uint32_t swidth;
|
||||
int32_t version;
|
||||
uint32_t flags;
|
||||
uint32_t logsectsize;
|
||||
uint32_t rtsectsize;
|
||||
uint32_t dirblocksize;
|
||||
uint32_t logsunit;
|
||||
} xfs_fsop_geom_t;
|
||||
#endif
|
||||
|
||||
#ifndef XFS_IOC_FSGROWFSDATA
|
||||
#define XFS_IOC_FSGROWFSDATA _IOW ('X', 110, struct xfs_growfs_data)
|
||||
|
||||
typedef struct xfs_growfs_data {
|
||||
uint64_t newblocks;
|
||||
uint32_t imaxpct;
|
||||
} xfs_growfs_data_t;
|
||||
#endif
|
|
@ -685,6 +685,7 @@ global:
|
|||
|
||||
LIBSYSTEMD_245 {
|
||||
global:
|
||||
sd_bus_message_sensitive;
|
||||
sd_event_add_child_pidfd;
|
||||
sd_event_source_get_child_pidfd;
|
||||
sd_event_source_get_child_pidfd_own;
|
||||
|
|
|
@ -45,12 +45,24 @@ static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
|
|||
assert(m);
|
||||
assert(part);
|
||||
|
||||
if (part->memfd >= 0)
|
||||
if (part->memfd >= 0) {
|
||||
/* erase if requested, but ony if the memfd is not sealed yet, i.e. is writable */
|
||||
if (m->sensitive && !m->sealed)
|
||||
explicit_bzero_safe(part->data, part->size);
|
||||
|
||||
close_and_munmap(part->memfd, part->mmap_begin, part->mapped);
|
||||
else if (part->munmap_this)
|
||||
} else if (part->munmap_this)
|
||||
/* We don't erase sensitive data here, since the data is memory mapped from someone else, and
|
||||
* we just don't know if it's OK to write to it */
|
||||
munmap(part->mmap_begin, part->mapped);
|
||||
else if (part->free_this)
|
||||
else {
|
||||
/* Erase this if that is requested. Since this is regular memory we know we can write it. */
|
||||
if (m->sensitive)
|
||||
explicit_bzero_safe(part->data, part->size);
|
||||
|
||||
if (part->free_this)
|
||||
free(part->data);
|
||||
}
|
||||
|
||||
if (part != &m->body)
|
||||
free(part);
|
||||
|
@ -113,11 +125,11 @@ static void message_reset_containers(sd_bus_message *m) {
|
|||
static sd_bus_message* message_free(sd_bus_message *m) {
|
||||
assert(m);
|
||||
|
||||
message_reset_parts(m);
|
||||
|
||||
if (m->free_header)
|
||||
free(m->header);
|
||||
|
||||
message_reset_parts(m);
|
||||
|
||||
/* Note that we don't unref m->bus here. That's already done by sd_bus_message_unref() as each user
|
||||
* reference to the bus message also is considered a reference to the bus connection itself. */
|
||||
|
||||
|
@ -727,6 +739,12 @@ static int message_new_reply(
|
|||
t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
|
||||
t->enforced_reply_signature = call->enforced_reply_signature;
|
||||
|
||||
/* let's copy the sensitive flag over. Let's do that as a safety precaution to keep a transaction
|
||||
* wholly sensitive if already the incoming message was sensitive. This is particularly useful when a
|
||||
* vtable record sets the SD_BUS_VTABLE_SENSITIVE flag on a method call, since this means it applies
|
||||
* to both the message call and the reply. */
|
||||
t->sensitive = call->sensitive;
|
||||
|
||||
*m = TAKE_PTR(t);
|
||||
return 0;
|
||||
}
|
||||
|
@ -5919,3 +5937,10 @@ _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
|
|||
m->priority = priority;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_bus_message_sensitive(sd_bus_message *m) {
|
||||
assert_return(m, -EINVAL);
|
||||
|
||||
m->sensitive = true;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@ struct sd_bus_message {
|
|||
bool free_header:1;
|
||||
bool free_fds:1;
|
||||
bool poisoned:1;
|
||||
bool sensitive:1;
|
||||
|
||||
/* The first and last bytes of the message */
|
||||
struct bus_header *header;
|
||||
|
|
|
@ -353,6 +353,12 @@ static int method_callbacks_run(
|
|||
if (require_fallback && !c->parent->is_fallback)
|
||||
return 0;
|
||||
|
||||
if (FLAGS_SET(c->vtable->flags, SD_BUS_VTABLE_SENSITIVE)) {
|
||||
r = sd_bus_message_sensitive(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = check_access(bus, m, c, &error);
|
||||
if (r < 0)
|
||||
return bus_maybe_reply_error(m, r, &error);
|
||||
|
@ -577,6 +583,12 @@ static int property_get_set_callbacks_run(
|
|||
if (require_fallback && !c->parent->is_fallback)
|
||||
return 0;
|
||||
|
||||
if (FLAGS_SET(c->vtable->flags, SD_BUS_VTABLE_SENSITIVE)) {
|
||||
r = sd_bus_message_sensitive(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = vtable_property_get_userdata(bus, m->path, c, &u, &error);
|
||||
if (r <= 0)
|
||||
return bus_maybe_reply_error(m, r, &error);
|
||||
|
@ -591,6 +603,12 @@ static int property_get_set_callbacks_run(
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (FLAGS_SET(c->vtable->flags, SD_BUS_VTABLE_SENSITIVE)) {
|
||||
r = sd_bus_message_sensitive(reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (is_get) {
|
||||
/* Note that we do not protect against reexecution
|
||||
* here (using the last_iteration check, see below),
|
||||
|
@ -692,6 +710,12 @@ static int vtable_append_one_property(
|
|||
assert(c);
|
||||
assert(v);
|
||||
|
||||
if (FLAGS_SET(c->vtable->flags, SD_BUS_VTABLE_SENSITIVE)) {
|
||||
r = sd_bus_message_sensitive(reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'e', "sv");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -750,9 +774,18 @@ static int vtable_append_all_properties(
|
|||
if (v->flags & SD_BUS_VTABLE_HIDDEN)
|
||||
continue;
|
||||
|
||||
/* Let's not include properties marked as "explicit" in any message that contians a generic
|
||||
* dump of properties, but only in those generated as a response to an explicit request. */
|
||||
if (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)
|
||||
continue;
|
||||
|
||||
/* Let's not include properties marked only for invalidation on change (i.e. in contrast to
|
||||
* those whose new values are included in PropertiesChanges message) in any signals. This is
|
||||
* useful to ensure they aren't included in InterfacesAdded messages. */
|
||||
if (reply->header->type != SD_BUS_MESSAGE_METHOD_RETURN &&
|
||||
FLAGS_SET(v->flags, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION))
|
||||
continue;
|
||||
|
||||
r = vtable_append_one_property(bus, reply, path, c, v, userdata, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
|
|
@ -147,6 +147,8 @@ shared_sources = files('''
|
|||
ptyfwd.h
|
||||
reboot-util.c
|
||||
reboot-util.h
|
||||
resize-fs.c
|
||||
resize-fs.h
|
||||
resolve-util.c
|
||||
resolve-util.h
|
||||
seccomp-util.h
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include <linux/btrfs.h>
|
||||
#include <linux/magic.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/vfs.h>
|
||||
|
||||
#include "blockdev-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "missing_fs.h"
|
||||
#include "missing_magic.h"
|
||||
#include "missing_xfs.h"
|
||||
#include "resize-fs.h"
|
||||
#include "stat-util.h"
|
||||
|
||||
int resize_fs(int fd, uint64_t sz) {
|
||||
struct statfs sfs;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
/* Rounds down to next block size */
|
||||
|
||||
if (sz <= 0 || sz == UINT64_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
if (fstatfs(fd, &sfs) < 0)
|
||||
return -errno;
|
||||
|
||||
if (is_fs_type(&sfs, EXT4_SUPER_MAGIC)) {
|
||||
uint64_t u;
|
||||
|
||||
if (sz < EXT4_MINIMAL_SIZE)
|
||||
return -ERANGE;
|
||||
|
||||
u = sz / sfs.f_bsize;
|
||||
|
||||
if (ioctl(fd, EXT4_IOC_RESIZE_FS, &u) < 0)
|
||||
return -errno;
|
||||
|
||||
} else if (is_fs_type(&sfs, BTRFS_SUPER_MAGIC)) {
|
||||
struct btrfs_ioctl_vol_args args = {};
|
||||
|
||||
/* 256M is the minimize size enforced by the btrfs kernel code when resizing (which is
|
||||
* strange btw, as mkfs.btrfs is fine creating file systems > 109M). It will return EINVAL in
|
||||
* that case, let's catch this error beforehand though, and report a more explanatory
|
||||
* error. */
|
||||
|
||||
if (sz < BTRFS_MINIMAL_SIZE)
|
||||
return -ERANGE;
|
||||
|
||||
r = snprintf(args.name, sizeof(args.name), "%" PRIu64, sz);
|
||||
assert((size_t) r < sizeof(args.name));
|
||||
|
||||
if (ioctl(fd, BTRFS_IOC_RESIZE, &args) < 0)
|
||||
return -errno;
|
||||
|
||||
} else if (is_fs_type(&sfs, XFS_SB_MAGIC)) {
|
||||
xfs_fsop_geom_t geo;
|
||||
xfs_growfs_data_t d;
|
||||
|
||||
if (sz < XFS_MINIMAL_SIZE)
|
||||
return -ERANGE;
|
||||
|
||||
if (ioctl(fd, XFS_IOC_FSGEOMETRY, &geo) < 0)
|
||||
return -errno;
|
||||
|
||||
d = (xfs_growfs_data_t) {
|
||||
.imaxpct = geo.imaxpct,
|
||||
.newblocks = sz / geo.blocksize,
|
||||
};
|
||||
|
||||
if (ioctl(fd, XFS_IOC_FSGROWFSDATA, &d) < 0)
|
||||
return -errno;
|
||||
|
||||
} else
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t minimal_size_by_fs_magic(statfs_f_type_t magic) {
|
||||
|
||||
switch (magic) {
|
||||
|
||||
case (statfs_f_type_t) EXT4_SUPER_MAGIC:
|
||||
return EXT4_MINIMAL_SIZE;
|
||||
|
||||
case (statfs_f_type_t) XFS_SB_MAGIC:
|
||||
return XFS_MINIMAL_SIZE;
|
||||
|
||||
case (statfs_f_type_t) BTRFS_SUPER_MAGIC:
|
||||
return BTRFS_MINIMAL_SIZE;
|
||||
|
||||
default:
|
||||
return UINT64_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t minimal_size_by_fs_name(const char *name) {
|
||||
|
||||
if (streq_ptr(name, "ext4"))
|
||||
return EXT4_MINIMAL_SIZE;
|
||||
|
||||
if (streq_ptr(name, "xfs"))
|
||||
return XFS_MINIMAL_SIZE;
|
||||
|
||||
if (streq_ptr(name, "btrfs"))
|
||||
return BTRFS_MINIMAL_SIZE;
|
||||
|
||||
return UINT64_MAX;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "stat-util.h"
|
||||
|
||||
int resize_fs(int fd, uint64_t sz);
|
||||
|
||||
#define BTRFS_MINIMAL_SIZE (256U*1024U*1024U)
|
||||
#define XFS_MINIMAL_SIZE (14U*1024U*1024U)
|
||||
#define EXT4_MINIMAL_SIZE (1024U*1024U)
|
||||
|
||||
uint64_t minimal_size_by_fs_magic(statfs_f_type_t magic);
|
||||
uint64_t minimal_size_by_fs_name(const char *str);
|
|
@ -43,6 +43,7 @@ enum {
|
|||
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE = 1ULL << 5,
|
||||
SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION = 1ULL << 6,
|
||||
SD_BUS_VTABLE_PROPERTY_EXPLICIT = 1ULL << 7,
|
||||
SD_BUS_VTABLE_SENSITIVE = 1ULL << 8, /* covers both directions: method call + reply */
|
||||
_SD_BUS_VTABLE_CAPABILITY_MASK = 0xFFFFULL << 40
|
||||
};
|
||||
|
||||
|
|
|
@ -328,6 +328,7 @@ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **content
|
|||
int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents);
|
||||
int sd_bus_message_at_end(sd_bus_message *m, int complete);
|
||||
int sd_bus_message_rewind(sd_bus_message *m, int complete);
|
||||
int sd_bus_message_sensitive(sd_bus_message *m);
|
||||
|
||||
/* Bus management */
|
||||
|
||||
|
|
Loading…
Reference in New Issue