Compare commits

..

6 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek 9142bbd19c
Merge pull request #14209 from poettering/sd-bus-sensitive
sd-bus bits from homed PR
2019-12-05 10:22:01 +01:00
Zbigniew Jędrzejewski-Szmek 68296b8b83
Merge pull request #14221 from poettering/homed-preparatory-resizefs
preparatory fs resizing support split out of homed PR
2019-12-05 10:17:10 +01:00
Lennart Poettering 6f0245b342 sd-bus: don't include properties maked as "emit-invalidation" in InterfacesAdded signals
Properties marked this way really shouldn't be sent around willy-nilly,
that's what the flag is about, hence exclude it from InterfacesAdded
signals (and in fact anything that is a signal).
2019-12-04 13:46:23 +01:00
Lennart Poettering 7a77d2a41c sd-bus: add new call sd_bus_message_sensitive() and SD_BUS_VTABLE_SENSITIVE
This allows marking messages that contain "sensitive" data with a flag.
If it's set then the messages are erased from memory when the message is
freed.

Similar, a flag may be set on vtable entries: incoming/outgoing message
matching the entry will then automatically be flagged this way.

This is supposed to be an easy method to mark messages containing
potentially sensitive data (such as passwords) for proper destruction.

(Note that this of course is only is as safe as the broker in between is
doing something similar. But let's at least not be the ones at fault
here.)
2019-12-04 13:46:23 +01:00
Lennart Poettering 28937bcc6c shared: add new wrapper for online fs resizing ioctls 2019-12-04 11:02:14 +01:00
Lennart Poettering 24a0b2c0ab missing: add XFS magic 2019-12-04 11:01:31 +01:00
11 changed files with 244 additions and 6 deletions

View File

@ -32,3 +32,8 @@
#ifndef MQUEUE_MAGIC #ifndef MQUEUE_MAGIC
#define MQUEUE_MAGIC 0x19800202 #define MQUEUE_MAGIC 0x19800202
#endif #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

42
src/basic/missing_xfs.h Normal file
View File

@ -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

View File

@ -685,6 +685,7 @@ global:
LIBSYSTEMD_245 { LIBSYSTEMD_245 {
global: global:
sd_bus_message_sensitive;
sd_event_add_child_pidfd; sd_event_add_child_pidfd;
sd_event_source_get_child_pidfd; sd_event_source_get_child_pidfd;
sd_event_source_get_child_pidfd_own; sd_event_source_get_child_pidfd_own;

View File

@ -45,12 +45,24 @@ static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
assert(m); assert(m);
assert(part); 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); 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); 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); free(part->data);
}
if (part != &m->body) if (part != &m->body)
free(part); 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) { static sd_bus_message* message_free(sd_bus_message *m) {
assert(m); assert(m);
message_reset_parts(m);
if (m->free_header) if (m->free_header)
free(m->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 /* 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. */ * 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->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
t->enforced_reply_signature = call->enforced_reply_signature; 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); *m = TAKE_PTR(t);
return 0; return 0;
} }
@ -5919,3 +5937,10 @@ _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
m->priority = priority; m->priority = priority;
return 0; return 0;
} }
_public_ int sd_bus_message_sensitive(sd_bus_message *m) {
assert_return(m, -EINVAL);
m->sensitive = true;
return 0;
}

View File

@ -85,6 +85,7 @@ struct sd_bus_message {
bool free_header:1; bool free_header:1;
bool free_fds:1; bool free_fds:1;
bool poisoned:1; bool poisoned:1;
bool sensitive:1;
/* The first and last bytes of the message */ /* The first and last bytes of the message */
struct bus_header *header; struct bus_header *header;

View File

@ -353,6 +353,12 @@ static int method_callbacks_run(
if (require_fallback && !c->parent->is_fallback) if (require_fallback && !c->parent->is_fallback)
return 0; 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); r = check_access(bus, m, c, &error);
if (r < 0) if (r < 0)
return bus_maybe_reply_error(m, r, &error); 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) if (require_fallback && !c->parent->is_fallback)
return 0; 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); r = vtable_property_get_userdata(bus, m->path, c, &u, &error);
if (r <= 0) if (r <= 0)
return bus_maybe_reply_error(m, r, &error); return bus_maybe_reply_error(m, r, &error);
@ -591,6 +603,12 @@ static int property_get_set_callbacks_run(
if (r < 0) if (r < 0)
return r; 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) { if (is_get) {
/* Note that we do not protect against reexecution /* Note that we do not protect against reexecution
* here (using the last_iteration check, see below), * here (using the last_iteration check, see below),
@ -692,6 +710,12 @@ static int vtable_append_one_property(
assert(c); assert(c);
assert(v); 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"); r = sd_bus_message_open_container(reply, 'e', "sv");
if (r < 0) if (r < 0)
return r; return r;
@ -750,9 +774,18 @@ static int vtable_append_all_properties(
if (v->flags & SD_BUS_VTABLE_HIDDEN) if (v->flags & SD_BUS_VTABLE_HIDDEN)
continue; 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) if (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)
continue; 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); r = vtable_append_one_property(bus, reply, path, c, v, userdata, error);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -147,6 +147,8 @@ shared_sources = files('''
ptyfwd.h ptyfwd.h
reboot-util.c reboot-util.c
reboot-util.h reboot-util.h
resize-fs.c
resize-fs.h
resolve-util.c resolve-util.c
resolve-util.h resolve-util.h
seccomp-util.h seccomp-util.h

112
src/shared/resize-fs.c Normal file
View File

@ -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;
}

15
src/shared/resize-fs.h Normal file
View File

@ -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);

View File

@ -43,6 +43,7 @@ enum {
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE = 1ULL << 5, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE = 1ULL << 5,
SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION = 1ULL << 6, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION = 1ULL << 6,
SD_BUS_VTABLE_PROPERTY_EXPLICIT = 1ULL << 7, 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 _SD_BUS_VTABLE_CAPABILITY_MASK = 0xFFFFULL << 40
}; };

View File

@ -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_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_at_end(sd_bus_message *m, int complete);
int sd_bus_message_rewind(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 */ /* Bus management */