Skip to content

Commit

Permalink
storage: Don't allow mounting over other mounted filesystems
Browse files Browse the repository at this point in the history
  • Loading branch information
mvollmer committed Sep 28, 2023
1 parent 515b6bc commit 0731117
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 169 deletions.
39 changes: 3 additions & 36 deletions pkg/storaged/content-views.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
init_active_usage_processes
} from "./dialog.jsx";
import * as utils from "./utils.js";
import { set_crypto_auto_option } from "./utils.js";

import React from "react";
import { Card, CardBody, CardHeader, CardTitle } from '@patternfly/react-core/dist/esm/components/Card/index.js';
Expand All @@ -38,13 +39,11 @@ import { ListingTable } from "cockpit-components-table.jsx";
import { ListingPanel } from 'cockpit-components-listing-panel.jsx';
import { StorageButton, StorageBarMenu, StorageMenuItem, StorageUsageBar } from "./storage-controls.jsx";
import * as PK from "packagekit.js";
import {
format_dialog, parse_options, extract_option, unparse_options
} from "./format-dialog.jsx";
import { format_dialog } from "./format-dialog.jsx";
import { job_progress_wrapper } from "./jobs-panel.jsx";

import { FilesystemTab, is_mounted, mounting_dialog, get_fstab_config } from "./fsys-tab.jsx";
import { CryptoTab, edit_config } from "./crypto-tab.jsx";
import { CryptoTab } from "./crypto-tab.jsx";
import { get_existing_passphrase, unlock_with_type } from "./crypto-keyslots.jsx";
import { BlockVolTab, PoolVolTab, VDOPoolTab } from "./lvol-tabs.jsx";
import { PartitionTab } from "./part-tab.jsx";
Expand Down Expand Up @@ -75,38 +74,6 @@ function next_default_logical_volume_name(client, vgroup, prefix) {
return name;
}

export function set_crypto_options(block, readonly, auto, nofail, netdev) {
return edit_config(block, (config, commit) => {
const opts = config.options ? parse_options(utils.decode_filename(config.options.v)) : [];
if (readonly !== null) {
extract_option(opts, "readonly");
if (readonly)
opts.push("readonly");
}
if (auto !== null) {
extract_option(opts, "noauto");
if (!auto)
opts.push("noauto");
}
if (nofail !== null) {
extract_option(opts, "nofail");
if (nofail)
opts.push("nofail");
}
if (netdev !== null) {
extract_option(opts, "_netdev");
if (netdev)
opts.push("_netdev");
}
config.options = { t: 'ay', v: utils.encode_filename(unparse_options(opts)) };
return commit();
});
}

export function set_crypto_auto_option(block, flag) {
return set_crypto_options(block, null, flag, null, null);
}

function create_tabs(client, target, options) {
function endsWith(str, suffix) {
return str.indexOf(suffix, str.length - suffix.length) !== -1;
Expand Down
6 changes: 2 additions & 4 deletions pkg/storaged/crypto-keyslots.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,9 @@ import {
dialog_open,
SelectOneRadio, TextInput, PassInput, Skip
} from "./dialog.jsx";
import { decode_filename, encode_filename, get_block_mntopts, block_name, for_each_async, get_children } from "./utils.js";
import { decode_filename, encode_filename, get_block_mntopts, block_name, for_each_async, get_children, parse_options, unparse_options, edit_crypto_config } from "./utils.js";
import { fmt_to_fragments } from "utils.jsx";
import { StorageButton } from "./storage-controls.jsx";
import { parse_options, unparse_options } from "./format-dialog.jsx";
import { edit_config } from "./crypto-tab.jsx";

import clevis_luks_passphrase_sh from "./clevis-luks-passphrase.sh";

Expand Down Expand Up @@ -384,7 +382,7 @@ function ensure_crypto_option(steps, progress, client, block, option) {

const new_crypto_options = crypto_options.concat([option]);
progress(cockpit.format(_("Adding \"$0\" to encryption options"), option), null);
return edit_config(block, (config, commit) => {
return edit_crypto_config(block, (config, commit) => {
config.options = { t: 'ay', v: encode_filename(unparse_options(new_crypto_options)) };
return commit();
});
Expand Down
34 changes: 3 additions & 31 deletions pkg/storaged/crypto-tab.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ import { DescriptionList, DescriptionListDescription, DescriptionListGroup, Desc
import { Flex, FlexItem } from "@patternfly/react-core/dist/esm/layouts/Flex/index.js";
import cockpit from "cockpit";
import { dialog_open, TextInput, PassInput } from "./dialog.jsx";
import { encode_filename, decode_filename, block_name } from "./utils.js";
import { parse_options, unparse_options, extract_option } from "./format-dialog.jsx";
import { encode_filename, decode_filename, block_name, parse_options, unparse_options, extract_option, edit_crypto_config } from "./utils.js";
import { is_mounted } from "./fsys-tab.jsx";

import React from "react";
Expand Down Expand Up @@ -50,33 +49,6 @@ function parse_tag_mtime(tag) {
return null;
}

export function edit_config(block, modify) {
let old_config, new_config;

function commit() {
new_config[1]["track-parents"] = { t: 'b', v: true };
if (old_config)
return block.UpdateConfigurationItem(old_config, new_config, { });
else
return block.AddConfigurationItem(new_config, { });
}

return block.GetSecretConfiguration({}).then(
function (items) {
old_config = items.find(c => c[0] == "crypttab");
new_config = ["crypttab", old_config ? Object.assign({ }, old_config[1]) : { }];

// UDisks insists on always having a "passphrase-contents" field when
// adding a crypttab entry, but doesn't include one itself when returning
// an entry without a stored passphrase.
//
if (!new_config[1]['passphrase-contents'])
new_config[1]['passphrase-contents'] = { t: 'ay', v: encode_filename("") };

return modify(new_config[1], commit);
});
}

export class CryptoTab extends React.Component {
constructor() {
super();
Expand Down Expand Up @@ -141,7 +113,7 @@ export class CryptoTab extends React.Component {
this.monitor_slots(block);

function edit_stored_passphrase() {
edit_config(block, function (config, commit) {
edit_crypto_config(block, function (config, commit) {
dialog_open({
Title: _("Stored passphrase"),
Fields: [
Expand Down Expand Up @@ -188,7 +160,7 @@ export class CryptoTab extends React.Component {
const content_block = client.blocks_cleartext[block.path];
const is_fsys = fsys_config || (content_block && content_block.IdUsage == "filesystem");

edit_config(block, function (config, commit) {
edit_crypto_config(block, function (config, commit) {
dialog_open({
Title: _("Encryption options"),
Fields: [
Expand Down
13 changes: 10 additions & 3 deletions pkg/storaged/dialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -1140,10 +1140,14 @@ const UsersPopover = ({ users }) => {
</Popover>);
};

export const TeardownMessage = (usage) => {
export const TeardownMessage = (usage, expect_single_unmount) => {
if (usage.length == 0)
return null;

if (expect_single_unmount && usage.length == 1 &&
usage[0].usage == "mounted" && usage[0].location == expect_single_unmount)
return <StopProcessesMessage mount_point={expect_single_unmount} users={usage[0].users} />;

const rows = [];
usage.forEach((use, index) => {
if (use.block) {
Expand Down Expand Up @@ -1178,7 +1182,7 @@ export const TeardownMessage = (usage) => {
</div>);
};

export function init_active_usage_processes(client, usage) {
export function init_active_usage_processes(client, usage, expect_single_unmount) {
return {
title: _("Checking related processes"),
func: dlg => {
Expand All @@ -1191,7 +1195,7 @@ export function init_active_usage_processes(client, usage) {
} else
return Promise.resolve();
}).then(() => {
dlg.set_attribute("Teardown", TeardownMessage(usage));
dlg.set_attribute("Teardown", TeardownMessage(usage, expect_single_unmount));
const usage_with_users = usage.filter(u => u.users);
const n_processes = usage_with_users.reduce((sum, u) => sum + u.users.filter(u => u.pid).length, 0);
const n_services = usage_with_users.reduce((sum, u) => sum + u.users.filter(u => u.unit).length, 0);
Expand All @@ -1207,6 +1211,9 @@ export function init_active_usage_processes(client, usage) {
}

export const StopProcessesMessage = ({ mount_point, users }) => {
if (!users || users.length == 0)
return null;

const process_rows = users.filter(u => u.pid).map(u => {
return {
columns: [
Expand Down
35 changes: 6 additions & 29 deletions pkg/storaged/format-dialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import cockpit from "cockpit";
import * as utils from "./utils.js";
import { edit_crypto_config, parse_options, unparse_options, extract_option } from "./utils.js";

import React from "react";
import { FormHelperText } from "@patternfly/react-core/dist/esm/components/Form/index.js";
Expand All @@ -33,35 +34,11 @@ import {
} from "./dialog.jsx";

import { get_fstab_config, is_valid_mount_point } from "./fsys-tab.jsx";
import { edit_config } from "./crypto-tab.jsx";
import { init_existing_passphrase, unlock_with_type } from "./crypto-keyslots.jsx";
import { job_progress_wrapper } from "./jobs-panel.jsx";

const _ = cockpit.gettext;

export function parse_options(options) {
if (options)
return (options.split(",")
.map(function (s) { return s.trim() })
.filter(function (s) { return s != "" }));
else
return [];
}

export function unparse_options(split) {
return split.join(",");
}

export function extract_option(split, opt) {
const index = split.indexOf(opt);
if (index >= 0) {
split.splice(index, 1);
return true;
} else {
return false;
}
}

export function initial_tab_options(client, block, for_fstab) {
const options = { };

Expand Down Expand Up @@ -530,11 +507,11 @@ function format_dialog_internal(client, path, start, size, enable_dos_extended,
return block_ptable.CreatePartitionAndFormat(start, vals.size, "", "", { },
vals.type, options);
} else if (keep_keys) {
return (edit_config(block,
(config, commit) => {
config.options = new_crypto_options;
return commit();
})
return (edit_crypto_config(block,
(config, commit) => {
config.options = new_crypto_options;
return commit();
})
.then(() => maybe_unlock())
.then(content_block => {
return content_block.Format(vals.type, options);
Expand Down
Loading

0 comments on commit 0731117

Please sign in to comment.