Compare commits

..

11 Commits

Author SHA1 Message Date
Frantisek Sumsal a114ab6373 cifuzz: fuzz the master branch on push
Apart from running CIFuzz for each relevant PR, let's run it
unconditionally for each push to master to detect possible issues
(caused by ignored PRs, etc.).

Followup to 94f660a8fe.
2020-05-08 21:30:19 +03:00
Frantisek Sumsal 94f660a8fe cifuzz: run only for relevant PRs
Fuzz only PRs with relevant changes (source code and fuzzer corpora) to
save resources.
2020-05-08 20:58:11 +03:00
Zbigniew Jędrzejewski-Szmek f2a8372e37
Merge pull request #15703 from poettering/homed-tweak-default-storage
homed: avoid double encryption
2020-05-08 16:57:14 +02:00
Lennart Poettering 321330ecab update TODO 2020-05-07 23:37:35 +02:00
Lennart Poettering feb86ca90c man: document homed.conf 2020-05-07 23:37:30 +02:00
Lennart Poettering c76dd733af homed: make default storage/file system type configurable in homed.conf 2020-05-07 23:33:09 +02:00
Lennart Poettering c07bf7a4ed homed: move supported_fstype() to home-util.c
That way we can use it from other modules too. Just some shifting
around, no change in behaviour.
2020-05-07 23:33:04 +02:00
Lennart Poettering 1dfe5de095 homed: tweak logic for picking a default storage and file system
Let's make the logic a bit smarter: if we detect that /home is
encrypted, let's avoid double encryption and prefer plain
directory/subvolumes instead of our regular luks images.

Also, allow configuration go storage/file system via an env var passed
to homework. In a later commit, let's then change homed to initialize
that env var from a config file setting, when invoking homework.
2020-05-07 23:33:01 +02:00
Lennart Poettering 0d5e523461 home: when adding a binding for a user record, use common code for determining automatic image path
Make use of the new user_record_build_image_path() helper the previous
commit added to share some code.

Also, let's make sure we update all parsed-out fields with the new data
from the binding, so that the parsed-out fields are definitely
up-to-date.
2020-05-07 23:32:57 +02:00
Lennart Poettering a43eddbdf4 user-record: split out code that generates automatic image path for records
No change of behaviour, just some refactoring, so that we can use this
new helper function elswhere, too.
2020-05-07 23:32:41 +02:00
Lennart Poettering ed9c0851e5 fs-util: add helper path_is_encrypted() that checks if a file system is encrypted 2020-05-07 23:31:36 +02:00
26 changed files with 453 additions and 57 deletions

View File

@ -3,7 +3,18 @@
# See: https://google.github.io/oss-fuzz/getting-started/continuous-integration/ # See: https://google.github.io/oss-fuzz/getting-started/continuous-integration/
name: CIFuzz name: CIFuzz
on: [pull_request] on:
pull_request:
paths:
- '**/meson.build'
- '.github/workflows/**'
- 'meson_options.txt'
- 'src/**'
- 'test/fuzz/**'
- 'tools/oss-fuzz.sh'
push:
branches:
- master
jobs: jobs:
Fuzzing: Fuzzing:
runs-on: ubuntu-latest runs-on: ubuntu-latest

4
TODO
View File

@ -51,11 +51,11 @@ Features:
* homed: add a way to "adopt" a home directory, i.e. strip foreign signatures * homed: add a way to "adopt" a home directory, i.e. strip foreign signatures
and insert a local signature instead. and insert a local signature instead.
* Maybe expose path_is_encrypted() as a new ConditionPathIsEncrypted=?
* busctl: maybe expose a verb "ping" for pinging a dbus service to see if it * busctl: maybe expose a verb "ping" for pinging a dbus service to see if it
exists and responds. exists and responds.
* homed: add homed.conf setting DefaultStorage= or so
* homed: maybe pre-create ~/.cache as subvol so that it can have separate quota * homed: maybe pre-create ~/.cache as subvol so that it can have separate quota
easily? easily?

View File

@ -51,6 +51,15 @@
<variablelist id='efi-variables' /> <variablelist id='efi-variables' />
</refsect1> </refsect1>
<refsect1>
<title>Home Area/User Account directives</title>
<para>Directives for configuring home areas and user accounts via
<citerefentry><refentrytitle>systemd-homed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
<variablelist id='home-directives' />
</refsect1>
<refsect1> <refsect1>
<title>UDEV directives</title> <title>UDEV directives</title>

View File

@ -504,9 +504,9 @@
<listitem><para>Selects the storage mechanism to use for this home directory. Takes one of <listitem><para>Selects the storage mechanism to use for this home directory. Takes one of
<literal>luks</literal>, <literal>fscrypt</literal>, <literal>directory</literal>, <literal>luks</literal>, <literal>fscrypt</literal>, <literal>directory</literal>,
<literal>subvolume</literal>, <literal>cifs</literal>. For details about these mechanisms, see <literal>subvolume</literal>, <literal>cifs</literal>. For details about these mechanisms, see
above. If a new home directory is created and the storage type is not specifically specified defaults above. If a new home directory is created and the storage type is not specifically specified,
to <literal>luks</literal> if supported, <literal>subvolume</literal> as first fallback if supported, <citerefentry><refentrytitle>homed.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
and <literal>directory</literal> if not.</para></listitem> defines which default storage to use.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
@ -525,9 +525,10 @@
<listitem><para>When LUKS2 storage is used configures the file system type to use inside the home <listitem><para>When LUKS2 storage is used configures the file system type to use inside the home
directory LUKS2 container. One of <literal>ext4</literal>, <literal>xfs</literal>, directory LUKS2 container. One of <literal>ext4</literal>, <literal>xfs</literal>,
<literal>btrfs</literal>. If not specified defaults to <literal>ext4</literal>. Note that <literal>btrfs</literal>. If not specified
<literal>xfs</literal> is not recommended as its support for file system resizing is too <citerefentry><refentrytitle>homed.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
limited.</para></listitem> defines which default file system type to use. Note that <literal>xfs</literal> is not recommended as
its support for file system resizing is too limited.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
@ -837,6 +838,7 @@ homectl update lafcadio --pkcs11-token-uri=…</programlisting>
<para> <para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-homed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd-homed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>homed.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>userdbctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>userdbctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>useradd</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>useradd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry> <citerefentry project='man-pages'><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>

84
man/homed.conf.xml Normal file
View File

@ -0,0 +1,84 @@
<?xml version='1.0'?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1+ -->
<refentry id="homed.conf" conditional='ENABLE_RESOLVE'
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>homed.conf</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>homed.conf</refentrytitle>
<manvolnum>5</manvolnum>
</refmeta>
<refnamediv>
<refname>homed.conf</refname>
<refname>homed.conf.d</refname>
<refpurpose>Home area/user account manager configuration files</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>/etc/systemd/homed.conf</filename></para>
<para><filename>/etc/systemd/homed.conf.d/*.conf</filename></para>
<para><filename>/run/systemd/homed.conf.d/*.conf</filename></para>
<para><filename>/usr/lib/systemd/homed.conf.d/*.conf</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>These configuration files control default parameters for home areas/user accounts created and
managed by
<citerefentry><refentrytitle>systemd-homed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</refsect1>
<xi:include href="standard-conf.xml" xpointer="main-conf" />
<refsect1>
<title>Options</title>
<para>The following options are available in the <literal>[Home]</literal> section:</para>
<variablelist class='home-directives'>
<varlistentry>
<term><varname>DefaultStorage=</varname></term>
<listitem><para>The default storage to use for home areas. Takes one of <literal>luks</literal>,
<literal>fscrypt</literal>, <literal>directory</literal>, <literal>subvolume</literal>,
<literal>cifs</literal>. For details about these options, see
<citerefentry><refentrytitle>homectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>. If not
configured or assigned the empty string, the default storage is automatically determined: if not
running in a container enviroment and <filename>/home/</filename> is not itself encrypted, defaults
to <literal>luks</literal>. Otherwise defaults to <literal>subvolume</literal> if
<filename>/home/</filename> is on a btrfs file system, and <literal>directory</literal>
otherwise. Note that the storage selected on the <command>homectl</command> command line always takes
precedence.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>DefaultFileSystemType=</varname></term>
<listitem><para>When using <literal>luks</literal> as storage (see above), selects the default file
system to use inside the user's LUKS volume. Takes one of <literal>ext4</literal>,
<literal>xfs</literal> or <literal>btrfs</literal>. If not specified defaults to
<literal>ext4</literal>. This setting has no effect if a different storage mechanism is used. The
file system type selected on the <command>homectl</command> command line always takes
precedence.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-homed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -18,6 +18,7 @@ manpages = [
['file-hierarchy', '7', [], ''], ['file-hierarchy', '7', [], ''],
['halt', '8', ['poweroff', 'reboot'], ''], ['halt', '8', ['poweroff', 'reboot'], ''],
['homectl', '1', [], 'ENABLE_HOMED'], ['homectl', '1', [], 'ENABLE_HOMED'],
['homed.conf', '5', ['homed.conf.d'], 'ENABLE_RESOLVE'],
['hostname', '5', [], ''], ['hostname', '5', [], ''],
['hostnamectl', '1', [], 'ENABLE_HOSTNAMED'], ['hostnamectl', '1', [], 'ENABLE_HOSTNAMED'],
['hwdb', '7', [], 'ENABLE_HWDB'], ['hwdb', '7', [], 'ENABLE_HWDB'],

View File

@ -100,6 +100,7 @@
<title>See Also</title> <title>See Also</title>
<para> <para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>homed.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>homectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>homectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>pam_systemd_home</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry><refentrytitle>pam_systemd_home</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>userdbctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> <citerefentry><refentrytitle>userdbctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>

View File

@ -1492,6 +1492,7 @@ meson_apply_m4 = find_program('tools/meson-apply-m4.sh')
includes = include_directories('src/basic', includes = include_directories('src/basic',
'src/boot', 'src/boot',
'src/home',
'src/shared', 'src/shared',
'src/systemd', 'src/systemd',
'src/journal', 'src/journal',

View File

@ -8,8 +8,10 @@
#include <unistd.h> #include <unistd.h>
#include "alloc-util.h" #include "alloc-util.h"
#include "blockdev-util.h"
#include "dirent-util.h" #include "dirent-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h"
#include "fs-util.h" #include "fs-util.h"
#include "locale-util.h" #include "locale-util.h"
#include "log.h" #include "log.h"
@ -1488,3 +1490,26 @@ int open_parent(const char *path, int flags, mode_t mode) {
return fd; return fd;
} }
int path_is_encrypted(const char *path) {
_cleanup_free_ char *uuids = NULL;
char p[SYS_BLOCK_PATH_MAX("/dm/uuid")];
dev_t devt;
int r;
r = get_block_device(path, &devt);
if (r < 0)
return r;
if (r == 0) /* doesn't have a block device */
return false;
xsprintf_sys_block_path(p, "/dm/uuid", devt);
r = read_one_line_file(p, &uuids);
if (r == -ENOENT)
return false;
if (r < 0)
return r;
/* The DM device's uuid attribute is prefixed with "CRYPT-" if this is a dm-crypt device. */
return !!startswith(uuids, "CRYPT-");
}

View File

@ -122,3 +122,5 @@ int fsync_path_at(int at_fd, const char *path);
int syncfs_path(int atfd, const char *path); int syncfs_path(int atfd, const char *path);
int open_parent(const char *path, int flags, mode_t mode); int open_parent(const char *path, int flags, mode_t mode);
int path_is_encrypted(const char *path);

View File

@ -64,6 +64,12 @@ int suitable_image_path(const char *path) {
path_is_absolute(path); path_is_absolute(path);
} }
bool supported_fstype(const char *fstype) {
/* Limit the set of supported file systems a bit, as protection against little tested kernel file
* systems. Also, we only support the resize ioctls for these file systems. */
return STR_IN_SET(fstype, "ext4", "btrfs", "xfs");
}
int split_user_name_realm(const char *t, char **ret_user_name, char **ret_realm) { int split_user_name_realm(const char *t, char **ret_user_name, char **ret_realm) {
_cleanup_free_ char *user_name = NULL, *realm = NULL; _cleanup_free_ char *user_name = NULL, *realm = NULL;
const char *c; const char *c;

View File

@ -12,6 +12,8 @@ bool suitable_user_name(const char *name);
int suitable_realm(const char *realm); int suitable_realm(const char *realm);
int suitable_image_path(const char *path); int suitable_image_path(const char *path);
bool supported_fstype(const char *fstype);
int split_user_name_realm(const char *t, char **ret_user_name, char **ret_realm); int split_user_name_realm(const char *t, char **ret_user_name, char **ret_realm);
int bus_message_append_secret(sd_bus_message *m, UserRecord *secret); int bus_message_append_secret(sd_bus_message *m, UserRecord *secret);

51
src/home/homed-conf.c Normal file
View File

@ -0,0 +1,51 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "conf-parser.h"
#include "def.h"
#include "home-util.h"
#include "homed-conf.h"
int manager_parse_config_file(Manager *m) {
int r;
assert(m);
r = config_parse_many_nulstr(PKGSYSCONFDIR "/homed.conf",
CONF_PATHS_NULSTR("systemd/homed.conf.d"),
"Home\0",
config_item_perf_lookup, homed_gperf_lookup,
CONFIG_PARSE_WARN, m);
if (r < 0)
return r;
return 0;
}
DEFINE_CONFIG_PARSE_ENUM(config_parse_default_storage, user_storage, UserStorage, "Failed to parse default storage setting");
int config_parse_default_file_system_type(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
char **s = data;
assert(rvalue);
assert(s);
if (!isempty(rvalue) && !supported_fstype(rvalue)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Unsupported file system, ignoring: %s", rvalue);
return 0;
}
return free_and_strdup_warn(s, empty_to_null(rvalue));
}

12
src/home/homed-conf.h Normal file
View File

@ -0,0 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include "conf-parser.h"
#include "homed-manager.h"
int manager_parse_config_file(Manager *m);
const struct ConfigPerfItem* homed_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
CONFIG_PARSER_PROTOTYPE(config_parse_default_storage);
CONFIG_PARSER_PROTOTYPE(config_parse_default_file_system_type);

View File

@ -0,0 +1,21 @@
%{
#if __GNUC__ >= 7
_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#endif
#include <stddef.h>
#include "conf-parser.h"
#include "homed-conf.h"
%}
struct ConfigPerfItem;
%null_strings
%language=ANSI-C
%define slot-name section_and_lvalue
%define hash-function-name homed_gperf_hash
%define lookup-function-name homed_gperf_lookup
%readonly-tables
%omit-struct-type
%struct-type
%includes
%%
Home.DefaultStorage, config_parse_default_storage, 0, offsetof(Manager, default_storage)
Home.DefaultFileSystemType, config_parse_default_file_system_type, 0, offsetof(Manager, default_file_system_type)

View File

@ -1011,6 +1011,18 @@ static int home_start_work(Home *h, const char *verb, UserRecord *hr, UserRecord
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} }
if (h->manager->default_storage >= 0)
if (setenv("SYSTEMD_HOME_DEFAULT_STORAGE", user_storage_to_string(h->manager->default_storage), 1) < 0) {
log_error_errno(errno, "Failed to set $SYSTEMD_HOME_DEFAULT_STORAGE: %m");
_exit(EXIT_FAILURE);
}
if (h->manager->default_file_system_type)
if (setenv("SYSTEMD_HOME_DEFAULT_FILE_SYSTEM_TYPE", h->manager->default_file_system_type, 1) < 0) {
log_error_errno(errno, "Failed to set $SYSTEMD_HOME_DEFAULT_FILE_SYSTEM_TYPE: %m");
_exit(EXIT_FAILURE);
}
r = rearrange_stdio(stdin_fd, stdout_fd, STDERR_FILENO); r = rearrange_stdio(stdin_fd, stdout_fd, STDERR_FILENO);
if (r < 0) { if (r < 0) {
log_error_errno(r, "Failed to rearrange stdin/stdout/stderr: %m"); log_error_errno(r, "Failed to rearrange stdin/stdout/stderr: %m");

View File

@ -24,6 +24,7 @@
#include "fs-util.h" #include "fs-util.h"
#include "gpt.h" #include "gpt.h"
#include "home-util.h" #include "home-util.h"
#include "homed-conf.h"
#include "homed-home-bus.h" #include "homed-home-bus.h"
#include "homed-home.h" #include "homed-home.h"
#include "homed-manager-bus.h" #include "homed-manager-bus.h"
@ -184,10 +185,18 @@ int manager_new(Manager **ret) {
assert(ret); assert(ret);
m = new0(Manager, 1); m = new(Manager, 1);
if (!m) if (!m)
return -ENOMEM; return -ENOMEM;
*m = (Manager) {
.default_storage = _USER_STORAGE_INVALID,
};
r = manager_parse_config_file(m);
if (r < 0)
return r;
r = sd_event_default(&m->event); r = sd_event_default(&m->event);
if (r < 0) if (r < 0)
return r; return r;
@ -251,6 +260,8 @@ Manager* manager_free(Manager *m) {
varlink_server_unref(m->varlink_server); varlink_server_unref(m->varlink_server);
free(m->default_file_system_type);
return mfree(m); return mfree(m);
} }

View File

@ -28,6 +28,8 @@ struct Manager {
Hashmap *homes_by_sysfs; Hashmap *homes_by_sysfs;
bool scan_slash_home; bool scan_slash_home;
UserStorage default_storage;
char *default_file_system_type;
sd_event_source *inotify_event_source; sd_event_source *inotify_event_source;

16
src/home/homed.conf Normal file
View File

@ -0,0 +1,16 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# Entries in this file show the compile time defaults.
# You can change settings by editing this file.
# Defaults can be restored by simply deleting this file.
#
# See homed.conf(5) for details
[Resolve]
#DefaultStorage=
#DefaultFileSystemType=ext4

View File

@ -16,6 +16,7 @@
#include "fileio.h" #include "fileio.h"
#include "fs-util.h" #include "fs-util.h"
#include "fsck-util.h" #include "fsck-util.h"
#include "home-util.h"
#include "homework-luks.h" #include "homework-luks.h"
#include "homework-mount.h" #include "homework-mount.h"
#include "id128-util.h" #include "id128-util.h"
@ -39,12 +40,6 @@
* strictly round disk sizes down to the next 1K boundary.*/ * strictly round disk sizes down to the next 1K boundary.*/
#define DISK_SIZE_ROUND_DOWN(x) ((x) & ~UINT64_C(1023)) #define DISK_SIZE_ROUND_DOWN(x) ((x) & ~UINT64_C(1023))
static bool supported_fstype(const char *fstype) {
/* Limit the set of supported file systems a bit, as protection against little tested kernel file
* systems. Also, we only support the resize ioctls for these file systems. */
return STR_IN_SET(fstype, "ext4", "btrfs", "xfs");
}
static int probe_file_system_by_fd( static int probe_file_system_by_fd(
int fd, int fd,
char **ret_fstype, char **ret_fstype,

View File

@ -7,6 +7,7 @@
#include "copy.h" #include "copy.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "fs-util.h"
#include "home-util.h" #include "home-util.h"
#include "homework-cifs.h" #include "homework-cifs.h"
#include "homework-directory.h" #include "homework-directory.h"
@ -862,9 +863,68 @@ static int user_record_compile_effective_passwords(
return 0; return 0;
} }
static int determine_default_storage(UserStorage *ret) {
UserStorage storage = _USER_STORAGE_INVALID;
const char *e;
int r;
assert(ret);
/* homed tells us via an environment variable which default storage to use */
e = getenv("SYSTEMD_HOME_DEFAULT_STORAGE");
if (e) {
storage = user_storage_from_string(e);
if (storage < 0)
log_warning("$SYSTEMD_HOME_DEFAULT_STORAGE set to invalid storage type, ignoring: %s", e);
else {
log_info("Using configured default storage '%s'.", user_storage_to_string(storage));
*ret = storage;
return 0;
}
}
/* When neither user nor admin specified the storage type to use, fix it to be LUKS — unless we run
* in a container where loopback devices and LUKS/DM are not available. Also, if /home is encrypted
* anyway, let's avoid duplicate encryption. Note that we typically default to the assumption of
* "classic" storage for most operations. However, if we create a new home, then let's user LUKS if
* nothing is specified. */
r = detect_container();
if (r < 0)
return log_error_errno(r, "Failed to determine whether we are in a container: %m");
if (r == 0) {
r = path_is_encrypted("/home");
if (r < 0)
log_warning_errno(r, "Failed to determine if /home is encrypted, ignoring: %m");
if (r <= 0) {
log_info("Using automatic default storage of '%s'.", user_storage_to_string(USER_LUKS));
*ret = USER_LUKS;
return 0;
}
log_info("/home is encrypted, not using '%s' storage, in order to avoid double encryption.", user_storage_to_string(USER_LUKS));
} else
log_info("Running in container, not using '%s' storage.", user_storage_to_string(USER_LUKS));
r = path_is_fs_type("/home", BTRFS_SUPER_MAGIC);
if (r < 0)
log_warning_errno(r, "Failed to determine file system of /home, ignoring: %m");
if (r > 0) {
log_info("/home is on btrfs, using '%s' as storage.", user_storage_to_string(USER_SUBVOLUME));
*ret = USER_SUBVOLUME;
} else {
log_info("/home is on simple file system, using '%s' as storage.", user_storage_to_string(USER_DIRECTORY));
*ret = USER_DIRECTORY;
}
return 0;
}
static int home_create(UserRecord *h, UserRecord **ret_home) { static int home_create(UserRecord *h, UserRecord **ret_home) {
_cleanup_(strv_free_erasep) char **effective_passwords = NULL, **pkcs11_decrypted_passwords = NULL; _cleanup_(strv_free_erasep) char **effective_passwords = NULL, **pkcs11_decrypted_passwords = NULL;
_cleanup_(user_record_unrefp) UserRecord *new_home = NULL; _cleanup_(user_record_unrefp) UserRecord *new_home = NULL;
UserStorage new_storage = _USER_STORAGE_INVALID;
const char *new_fs = NULL;
int r; int r;
assert(h); assert(h);
@ -884,27 +944,18 @@ static int home_create(UserRecord *h, UserRecord **ret_home) {
if (r != USER_TEST_ABSENT) if (r != USER_TEST_ABSENT)
return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Home directory %s already exists, refusing.", user_record_home_directory(h)); return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Home directory %s already exists, refusing.", user_record_home_directory(h));
/* When the user didn't specify the storage type to use, fix it to be LUKS -- unless we run in a
* container where loopback devices and LUKS/DM are not available. Note that we typically default to
* the assumption of "classic" storage for most operations. However, if we create a new home, then
* let's user LUKS if nothing is specified. */
if (h->storage < 0) { if (h->storage < 0) {
UserStorage new_storage; r = determine_default_storage(&new_storage);
r = detect_container();
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to determine whether we are in a container: %m"); return r;
if (r > 0) { }
new_storage = USER_DIRECTORY;
r = path_is_fs_type("/home", BTRFS_SUPER_MAGIC); if ((h->storage == USER_LUKS ||
if (r < 0) (h->storage < 0 && new_storage == USER_LUKS)) &&
log_debug_errno(r, "Failed to determine file system of /home, ignoring: %m"); !h->file_system_type)
new_fs = getenv("SYSTEMD_HOME_DEFAULT_FILE_SYSTEM_TYPE");
new_storage = r > 0 ? USER_SUBVOLUME : USER_DIRECTORY;
} else
new_storage = USER_LUKS;
if (new_storage >= 0 || new_fs) {
r = user_record_add_binding( r = user_record_add_binding(
h, h,
new_storage, new_storage,
@ -915,18 +966,12 @@ static int home_create(UserRecord *h, UserRecord **ret_home) {
NULL, NULL,
NULL, NULL,
UINT64_MAX, UINT64_MAX,
NULL, new_fs,
NULL, NULL,
UID_INVALID, UID_INVALID,
GID_INVALID); GID_INVALID);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to change storage type to LUKS: %m"); return log_error_errno(r, "Failed to change storage type to LUKS: %m");
if (!h->image_path_auto) {
h->image_path_auto = strjoin("/home/", user_record_user_name_and_realm(h), new_storage == USER_LUKS ? ".home" : ".homedir");
if (!h->image_path_auto)
return log_oom();
}
} }
r = user_record_test_image_path_and_warn(h); r = user_record_test_image_path_and_warn(h);

View File

@ -31,6 +31,8 @@ systemd_homed_sources = files('''
home-util.h home-util.h
homed-bus.c homed-bus.c
homed-bus.h homed-bus.h
homed-conf.c
homed-conf.h
homed-home-bus.c homed-home-bus.c
homed-home-bus.h homed-home-bus.h
homed-home.c homed-home.c
@ -52,6 +54,14 @@ systemd_homed_sources = files('''
user-record-util.h user-record-util.h
'''.split()) '''.split())
homed_gperf_c = custom_target(
'homed_gperf.c',
input : 'homed-gperf.gperf',
output : 'homed-gperf.c',
command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
systemd_homed_sources += [homed_gperf_c]
homectl_sources = files(''' homectl_sources = files('''
home-util.c home-util.c
home-util.h home-util.h
@ -78,4 +88,7 @@ if conf.get('ENABLE_HOMED') == 1
install_dir : dbussystemservicedir) install_dir : dbussystemservicedir)
install_data('org.freedesktop.home1.policy', install_data('org.freedesktop.home1.policy',
install_dir : polkitpolicydir) install_dir : polkitpolicydir)
install_data('homed.conf',
install_dir : pkgsysconfdir)
endif endif

View File

@ -276,7 +276,7 @@ int user_record_add_binding(
_cleanup_(json_variant_unrefp) JsonVariant *new_binding_entry = NULL, *binding = NULL; _cleanup_(json_variant_unrefp) JsonVariant *new_binding_entry = NULL, *binding = NULL;
char smid[SD_ID128_STRING_MAX], partition_uuids[37], luks_uuids[37], fs_uuids[37]; char smid[SD_ID128_STRING_MAX], partition_uuids[37], luks_uuids[37], fs_uuids[37];
_cleanup_free_ char *ip = NULL, *hd = NULL; _cleanup_free_ char *ip = NULL, *hd = NULL, *ip_auto = NULL, *lc = NULL, *lcm = NULL, *fst = NULL;
sd_id128_t mid; sd_id128_t mid;
int r; int r;
@ -294,6 +294,10 @@ int user_record_add_binding(
ip = strdup(image_path); ip = strdup(image_path);
if (!ip) if (!ip)
return -ENOMEM; return -ENOMEM;
} else if (!h->image_path && storage >= 0) {
r = user_record_build_image_path(storage, user_record_user_name_and_realm(h), &ip_auto);
if (r < 0)
return r;
} }
if (home_directory) { if (home_directory) {
@ -302,6 +306,24 @@ int user_record_add_binding(
return -ENOMEM; return -ENOMEM;
} }
if (file_system_type) {
fst = strdup(file_system_type);
if (!fst)
return -ENOMEM;
}
if (luks_cipher) {
lc = strdup(luks_cipher);
if (!lc)
return -ENOMEM;
}
if (luks_cipher_mode) {
lcm = strdup(luks_cipher_mode);
if (!lcm)
return -ENOMEM;
}
r = json_build(&new_binding_entry, r = json_build(&new_binding_entry,
JSON_BUILD_OBJECT( JSON_BUILD_OBJECT(
JSON_BUILD_PAIR_CONDITION(!!image_path, "imagePath", JSON_BUILD_STRING(image_path)), JSON_BUILD_PAIR_CONDITION(!!image_path, "imagePath", JSON_BUILD_STRING(image_path)),
@ -348,6 +370,8 @@ int user_record_add_binding(
if (ip) if (ip)
free_and_replace(h->image_path, ip); free_and_replace(h->image_path, ip);
if (ip_auto)
free_and_replace(h->image_path_auto, ip_auto);
if (!sd_id128_is_null(partition_uuid)) if (!sd_id128_is_null(partition_uuid))
h->partition_uuid = partition_uuid; h->partition_uuid = partition_uuid;
@ -358,11 +382,22 @@ int user_record_add_binding(
if (!sd_id128_is_null(fs_uuid)) if (!sd_id128_is_null(fs_uuid))
h->file_system_uuid = fs_uuid; h->file_system_uuid = fs_uuid;
if (lc)
free_and_replace(h->luks_cipher, lc);
if (lcm)
free_and_replace(h->luks_cipher_mode, lcm);
if (luks_volume_key_size != UINT64_MAX)
h->luks_volume_key_size = luks_volume_key_size;
if (fst)
free_and_replace(h->file_system_type, fst);
if (hd) if (hd)
free_and_replace(h->home_directory, hd); free_and_replace(h->home_directory, hd);
if (uid_is_valid(uid)) if (uid_is_valid(uid))
h->uid = uid; h->uid = uid;
if (gid_is_valid(gid))
h->gid = gid;
h->mask |= USER_RECORD_BINDING; h->mask |= USER_RECORD_BINDING;
return 1; return 1;

View File

@ -1059,7 +1059,34 @@ static int dispatch_status(const char *name, JsonVariant *variant, JsonDispatchF
return json_dispatch(m, status_dispatch_table, NULL, flags, userdata); return json_dispatch(m, status_dispatch_table, NULL, flags, userdata);
} }
int user_record_build_image_path(UserStorage storage, const char *user_name_and_realm, char **ret) {
const char *suffix;
char *z;
assert(storage >= 0);
assert(user_name_and_realm);
assert(ret);
if (storage == USER_LUKS)
suffix = ".home";
else if (IN_SET(storage, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT))
suffix = ".homedir";
else {
*ret = NULL;
return 0;
}
z = strjoin("/home/", user_name_and_realm, suffix);
if (!z)
return -ENOMEM;
*ret = z;
return 1;
}
static int user_record_augment(UserRecord *h, JsonDispatchFlags json_flags) { static int user_record_augment(UserRecord *h, JsonDispatchFlags json_flags) {
int r;
assert(h); assert(h);
if (!FLAGS_SET(h->mask, USER_RECORD_REGULAR)) if (!FLAGS_SET(h->mask, USER_RECORD_REGULAR))
@ -1084,22 +1111,9 @@ static int user_record_augment(UserRecord *h, JsonDispatchFlags json_flags) {
} }
if (!h->image_path && !h->image_path_auto) { if (!h->image_path && !h->image_path_auto) {
const char *suffix; r = user_record_build_image_path(user_record_storage(h), user_record_user_name_and_realm(h), &h->image_path_auto);
UserStorage storage; if (r < 0)
return json_log(h->json, json_flags, r, "Failed to determine default image path: %m");
storage = user_record_storage(h);
if (storage == USER_LUKS)
suffix = ".home";
else if (IN_SET(storage, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT))
suffix = ".homedir";
else
suffix = NULL;
if (suffix) {
h->image_path_auto = strjoin("/home/", user_record_user_name_and_realm(h), suffix);
if (!h->image_path_auto)
return json_log_oom(h->json, json_flags);
}
} }
return 0; return 0;

View File

@ -349,6 +349,8 @@ usec_t user_record_ratelimit_interval_usec(UserRecord *h);
uint64_t user_record_ratelimit_burst(UserRecord *h); uint64_t user_record_ratelimit_burst(UserRecord *h);
bool user_record_can_authenticate(UserRecord *h); bool user_record_can_authenticate(UserRecord *h);
int user_record_build_image_path(UserStorage storage, const char *user_name_and_realm, char **ret);
bool user_record_equal(UserRecord *a, UserRecord *b); bool user_record_equal(UserRecord *a, UserRecord *b);
bool user_record_compatible(UserRecord *a, UserRecord *b); bool user_record_compatible(UserRecord *a, UserRecord *b);
int user_record_compare_last_change(UserRecord *a, UserRecord *b); int user_record_compare_last_change(UserRecord *a, UserRecord *b);

View File

@ -846,6 +846,28 @@ static void test_chmod_and_chown_unsafe(void) {
assert_se(S_ISLNK(st.st_mode)); assert_se(S_ISLNK(st.st_mode));
} }
static void test_path_is_encrypted_one(const char *p, int expect) {
int r;
r = path_is_encrypted(p);
assert_se(r >= 0);
printf("%s encrypted: %s\n", p, yes_no(r));
assert_se(expect < 0 || ((r > 0) == (expect > 0)));
}
static void test_path_is_encrypted(void) {
log_info("/* %s */", __func__);
test_path_is_encrypted_one("/home", -1);
test_path_is_encrypted_one("/var", -1);
test_path_is_encrypted_one("/", -1);
test_path_is_encrypted_one("/proc", false);
test_path_is_encrypted_one("/sys", false);
test_path_is_encrypted_one("/dev", false);
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
test_setup_logging(LOG_INFO); test_setup_logging(LOG_INFO);
@ -864,6 +886,7 @@ int main(int argc, char *argv[]) {
test_rename_noreplace(); test_rename_noreplace();
test_chmod_and_chown(); test_chmod_and_chown();
test_chmod_and_chown_unsafe(); test_chmod_and_chown_unsafe();
test_path_is_encrypted();
return 0; return 0;
} }