Skip to content

Commit

Permalink
WIP - compute crypto options from children
Browse files Browse the repository at this point in the history
  • Loading branch information
mvollmer committed Feb 29, 2024
1 parent dc33b9c commit f9df53c
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 45 deletions.
15 changes: 6 additions & 9 deletions pkg/storaged/btrfs/subvolume.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ function get_mount_point_in_parent(volume, subvol) {
return null;
}

function set_mount_options(subvol, block, vals) {
async function set_mount_options(subvol, block, vals) {
const mount_options = [];
const mount_now = vals.variant != "nomount";

Expand Down Expand Up @@ -115,14 +115,11 @@ function set_mount_options(subvol, block, vals) {
}
];

return block.AddConfigurationItem(config, {})
.then(reload_systemd)
.then(() => {
if (mount_now) {
return client.mount_at(block, mount_point);
} else
return Promise.resolve();
});
await block.AddConfigurationItem(config, {});
await reload_systemd();
if (mount_now)
await client.mount_at(block, mount_point);
await maybe_update_crypto_options(block);
}

function subvolume_create(volume, subvol, parent_dir) {
Expand Down
43 changes: 42 additions & 1 deletion pkg/storaged/crypto/utils.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
* along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
*/

import client from "../client.js";

import { encode_filename, decode_filename, parse_options, extract_option, unparse_options } from "../utils.js";

export function edit_crypto_config(block, modify) {
Expand Down Expand Up @@ -46,7 +48,7 @@ export function edit_crypto_config(block, modify) {
});
}

export function set_crypto_options(block, readonly, auto, nofail, netdev) {
function set_crypto_options(block, readonly, auto, nofail, netdev) {
return edit_crypto_config(block, (config, commit) => {
const opts = config.options ? parse_options(decode_filename(config.options.v)) : [];
if (readonly !== null) {
Expand Down Expand Up @@ -77,3 +79,42 @@ export function set_crypto_options(block, readonly, auto, nofail, netdev) {
export function set_crypto_auto_option(block, flag) {
return set_crypto_options(block, null, flag, null, null);
}

async function update_crypto_options_for_children(block) {
// This sets the readonly, noauto, nofail, and _netdev options as
// required by the content of this block device.

const block_crypto = client.blocks_crypto[block.path];
console.log("UPDATE", block_crypto.path);

let readonly = true;
let noauto = true;
let nofail = true;
let netdev = true;

for (const c of block_crypto.ChildConfiguration) {
if (c[0] == "fstab") {
const opts = parse_options(decode_filename(c[1].opts.v));
console.log(" ", opts);
if (opts.indexOf("ro") < 0)
readonly = false;
if (opts.indexOf("noauto") < 0)
noauto = false;
if (opts.indexOf("nofail") < 0)
nofail = false;
if (opts.indexOf("_netdev") < 0)
netdev = false;
}
}

console.log("=", { readonly, noauto, nofail, netdev });
await set_crypto_options(block, readonly, !noauto, nofail, netdev);
}

export async function maybe_update_crypto_options(block) {
// XXX - don't do this for btrfs volumes with multiple devices
if (client.blocks_crypto[block.path])
await update_crypto_options_for_children(block);
else if (client.blocks_crypto[block.CryptoBackingDevice])
await update_crypto_options_for_children(client.blocks[block.CryptoBackingDevice]);
}
59 changes: 24 additions & 35 deletions pkg/storaged/filesystem/mounting-dialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
} from "../dialog.jsx";
import { init_existing_passphrase, unlock_with_type } from "../crypto/keyslots.jsx";
import { initial_tab_options, mount_explanation } from "../block/format-dialog.jsx";
import { set_crypto_options } from "../crypto/utils.jsx";
import { maybe_update_crypto_options } from "../crypto/utils.jsx";

import {
is_mounted, get_fstab_config,
Expand Down Expand Up @@ -195,17 +195,6 @@ export function mounting_dialog(client, block, mode, forced_options, subvol) {
return Promise.resolve();
}

function maybe_lock() {
if (mode == "unmount" && !subvol) {
const crypto_backing = client.blocks[block.CryptoBackingDevice];
const crypto_backing_crypto = crypto_backing && client.blocks_crypto[crypto_backing.path];
if (crypto_backing_crypto) {
return crypto_backing_crypto.Lock({});
} else
return Promise.resolve();
}
}

// We need to reload systemd twice: Once at the beginning so
// that it is up to date with whatever is currently in fstab,
// and once at the end to make it see our changes. Otherwise
Expand All @@ -227,7 +216,6 @@ export function mounting_dialog(client, block, mode, forced_options, subvol) {
else if (new_config && !is_mounted(client, block))
return maybe_mount();
})
.then(maybe_lock)
.then(reload_systemd));
}

Expand Down Expand Up @@ -280,7 +268,18 @@ export function mounting_dialog(client, block, mode, forced_options, subvol) {
update: _("Save")
};

function do_unmount() {
function maybe_lock() {
const block_fsys = client.blocks_fsys[block.path];
const crypto_backing = client.blocks[block.CryptoBackingDevice];
const crypto_backing_crypto = crypto_backing && client.blocks_crypto[crypto_backing.path];
console.log("LOCK?", block_fsys?.MountPoints.length == 0);
if (crypto_backing_crypto && block_fsys && block_fsys.MountPoints.length == 0) {
return crypto_backing_crypto.Lock({});
} else
return Promise.resolve();
}

async function do_unmount() {
let opts = [];
opts.push("noauto");
if (opt_ro)
Expand All @@ -295,21 +294,14 @@ export function mounting_dialog(client, block, mode, forced_options, subvol) {
opts = opts.concat(forced_options);
if (extra_options)
opts = opts.concat(extra_options);
return (maybe_set_crypto_options(null, false, null, null)
.then(() => maybe_update_config(old_dir, unparse_options(opts))));

await maybe_update_config(old_dir, unparse_options(opts));
await maybe_update_crypto_options(block);
await maybe_lock(block);
}

let passphrase_type;

function maybe_set_crypto_options(readonly, auto, nofail, netdev) {
if (client.blocks_crypto[block.path]) {
return set_crypto_options(block, readonly, auto, nofail, netdev);
} else if (client.blocks_crypto[block.CryptoBackingDevice]) {
return set_crypto_options(client.blocks[block.CryptoBackingDevice], readonly, auto, nofail, netdev);
} else
return Promise.resolve();
}

const usage = get_active_usage(client, block.path, null, null, false, subvol);

const dlg = dialog_open({
Expand All @@ -323,9 +315,9 @@ export function mounting_dialog(client, block, mode, forced_options, subvol) {
Action: {
Title: mode_action[mode],
disable_on_error: usage.Teardown,
action: function (vals) {
action: async function (vals) {
if (mode == "unmount") {
return do_unmount();
await do_unmount();
} else if (mode == "mount" || mode == "update") {
let opts = [];
if ((mode == "update" && !is_filesystem_mounted) || vals.at_boot == "never")
Expand All @@ -342,14 +334,11 @@ export function mounting_dialog(client, block, mode, forced_options, subvol) {
opts = opts.concat(forced_options);
if (vals.mount_options?.extra)
opts = opts.concat(parse_options(vals.mount_options.extra));
return (maybe_update_config(client.add_mount_point_prefix(vals.mount_point),
unparse_options(opts),
vals.passphrase,
passphrase_type)
.then(() => maybe_set_crypto_options(vals.mount_options?.ro,
opts.indexOf("noauto") == -1,
vals.at_boot == "nofail",
vals.at_boot == "netdev")));
await maybe_update_config(client.add_mount_point_prefix(vals.mount_point),
unparse_options(opts),
vals.passphrase,
passphrase_type);
await maybe_update_crypto_options(block);
}
}
},
Expand Down

0 comments on commit f9df53c

Please sign in to comment.