Add hidden coreos-rootfs seal
command
All this does is put the immutable bit on the target directory.
The intention is to replace this bit to start:
8b205bfbb9/src/create_disk.sh (L229)
However, the real goal here is to add code in this file
to handle redeploying the rootfs for Fedora CoreOS which
combines OSTree+Ignition:
https://github.com/coreos/fedora-coreos-tracker/issues/94
Basically doing this in proper Rust is going to be a lot
nicer than shell script in dracut modules. Among other
details, coreutils `mv` doesn't seem to do the right thing
for SELinux labels when policy isn't loaded.
This commit is contained in:
parent
68750b6894
commit
c8113bde32
@ -39,6 +39,7 @@ rpm_ostree_SOURCES = src/app/main.c \
|
||||
src/app/rpmostree-pkg-builtins.c \
|
||||
src/app/rpmostree-builtin-status.c \
|
||||
src/app/rpmostree-builtin-ex.c \
|
||||
src/app/rpmostree-builtin-coreos-rootfs.c \
|
||||
src/app/rpmostree-builtin-container.c \
|
||||
src/app/rpmostree-ex-builtin-commit2rojig.c \
|
||||
src/app/rpmostree-ex-builtin-rojig2commit.c \
|
||||
|
38
rust/Cargo.lock
generated
38
rust/Cargo.lock
generated
@ -309,6 +309,14 @@ dependencies = [
|
||||
"pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indicatif"
|
||||
version = "0.11.0"
|
||||
@ -650,6 +658,7 @@ dependencies = [
|
||||
"serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"systemd 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -756,6 +765,26 @@ name = "strsim"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "structopt"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "structopt-derive"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.15.44"
|
||||
@ -836,6 +865,11 @@ dependencies = [
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.6"
|
||||
@ -943,6 +977,7 @@ dependencies = [
|
||||
"checksum glib 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e8fdc159c196a5dfa53a92929ac4c10c8a6637ffb43951f3fff89c2cd2365"
|
||||
"checksum glib-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5bda542f3caee39a027638e9644ff89204101ad916fd7370b585ad2c5fc97e61"
|
||||
"checksum gobject-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23e05a14290d3dc255223cba51db4b0f3da438d5250657996fa99b2a30faf43e"
|
||||
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||
"checksum indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c60da1c9abea75996b70a931bba6c750730399005b61ccd853cee50ef3d0d0c"
|
||||
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
|
||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
@ -996,6 +1031,8 @@ dependencies = [
|
||||
"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
|
||||
"checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85"
|
||||
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
|
||||
"checksum structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "16c2cdbf9cc375f15d1b4141bc48aeef444806655cd0e904207edc8d68d86ed7"
|
||||
"checksum structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "53010261a84b37689f9ed7d395165029f9cc7abb9f56bbfe86bee2597ed25107"
|
||||
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
||||
"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
|
||||
"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
|
||||
@ -1004,6 +1041,7 @@ dependencies = [
|
||||
"checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625"
|
||||
"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
|
||||
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
|
||||
"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9"
|
||||
"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
|
||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
|
@ -17,6 +17,7 @@ gio-sys = "0.8.0"
|
||||
glib = "0.7.1"
|
||||
tempfile = "3.0.3"
|
||||
clap = "~2.32"
|
||||
structopt = "0.2"
|
||||
openat = "0.1.15"
|
||||
openat-ext = "0.1.0"
|
||||
curl = "0.4.14"
|
||||
|
119
rust/src/coreos_rootfs.rs
Normal file
119
rust/src/coreos_rootfs.rs
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Red Hat, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
//! # Code for CoreOS rootfs
|
||||
//!
|
||||
//! This backs the `rpm-ostree coreos-rootfs` CLI, which is intended as
|
||||
//! a hidden implmentation detail of CoreOS style systems. The code
|
||||
//! is here in rpm-ostree as a convenience.
|
||||
|
||||
use std::os::unix::prelude::*;
|
||||
use failure::{Fallible, ResultExt};
|
||||
use structopt::StructOpt;
|
||||
use openat;
|
||||
use nix;
|
||||
use libc;
|
||||
|
||||
/// A reference to a *directory* file descriptor. Unfortunately,
|
||||
/// the openat crate always uses O_PATH which doesn't support ioctl().
|
||||
pub struct RawDirFd(RawFd);
|
||||
|
||||
impl AsRawFd for RawDirFd {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for RawDirFd {
|
||||
#[inline]
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> RawDirFd {
|
||||
RawDirFd(fd)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for RawDirFd {
|
||||
fn drop(&mut self) {
|
||||
let fd = self.0;
|
||||
unsafe {
|
||||
libc::close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* From /usr/include/ext2fs/ext2_fs.h */
|
||||
const EXT2_IMMUTABLE_FL : libc::c_long = 0x00000010; /* Immutable file */
|
||||
|
||||
nix::ioctl_read!(ext2_get_flags, b'f', 1, libc::c_long);
|
||||
nix::ioctl_write_ptr!(ext2_set_flags, b'f', 2, libc::c_long);
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
struct SealOpts {
|
||||
/// Path to rootfs
|
||||
sysroot: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
#[structopt(name = "coreos-rootfs")]
|
||||
#[structopt(rename_all = "kebab-case")]
|
||||
enum Opt {
|
||||
/// Final step after changing a sysroot
|
||||
Seal(SealOpts),
|
||||
}
|
||||
|
||||
// taken from openat code
|
||||
fn to_cstr<P: openat::AsPath>(path: P) -> std::io::Result<P::Buffer> {
|
||||
path.to_path()
|
||||
.ok_or_else(|| {
|
||||
std::io::Error::new(std::io::ErrorKind::InvalidInput,
|
||||
"nul byte in file name")
|
||||
})
|
||||
}
|
||||
|
||||
/// Set the immutable bit
|
||||
fn seal(opts: &SealOpts) -> Fallible<()> {
|
||||
let fd = unsafe {
|
||||
let fd = libc::open(to_cstr(opts.sysroot.as_str())?.as_ref().as_ptr(), libc::O_CLOEXEC | libc::O_DIRECTORY);
|
||||
if fd < 0 {
|
||||
Err(std::io::Error::last_os_error())?
|
||||
} else {
|
||||
RawDirFd::from_raw_fd(fd)
|
||||
}
|
||||
};
|
||||
|
||||
let mut flags : libc::c_long = 0;
|
||||
unsafe { ext2_get_flags(fd.as_raw_fd(), &mut flags as *mut libc::c_long)? };
|
||||
if flags & EXT2_IMMUTABLE_FL == 0 {
|
||||
flags |= EXT2_IMMUTABLE_FL;
|
||||
unsafe { ext2_set_flags(fd.as_raw_fd(), &flags as *const libc::c_long)? };
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Main entrypoint
|
||||
fn coreos_rootfs_main(args: &Vec<String>) -> Fallible<()> {
|
||||
let opt = Opt::from_iter(args.iter());
|
||||
match opt {
|
||||
Opt::Seal(ref opts) => seal(opts).with_context(|e| format!("Sealing: {}", e.to_string()))?,
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
mod ffi {
|
||||
use super::*;
|
||||
use glib_sys;
|
||||
use libc;
|
||||
|
||||
use crate::ffiutil::*;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ror_coreos_rootfs_entrypoint(argv: *mut *mut libc::c_char,
|
||||
gerror: *mut *mut glib_sys::GError) -> libc::c_int {
|
||||
let v: Vec<String> = unsafe { glib::translate::FromGlibPtrContainer::from_glib_none(argv) };
|
||||
int_glib_error(coreos_rootfs_main(&v), gerror)
|
||||
}
|
||||
}
|
||||
pub use self::ffi::*;
|
@ -12,6 +12,8 @@ mod composepost;
|
||||
pub use self::composepost::*;
|
||||
mod history;
|
||||
pub use self::history::*;
|
||||
mod coreos_rootfs;
|
||||
pub use self::coreos_rootfs::*;
|
||||
mod journal;
|
||||
pub use self::journal::*;
|
||||
mod progress;
|
||||
|
@ -115,6 +115,10 @@ static RpmOstreeCommand commands[] = {
|
||||
RPM_OSTREE_BUILTIN_FLAG_HIDDEN,
|
||||
"Experimental commands that may change or be removed in the future",
|
||||
rpmostree_builtin_ex },
|
||||
{ "coreos-rootfs", RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD |
|
||||
RPM_OSTREE_BUILTIN_FLAG_REQUIRES_ROOT |
|
||||
RPM_OSTREE_BUILTIN_FLAG_HIDDEN,
|
||||
NULL, rpmostree_builtin_coreos_rootfs },
|
||||
{ "start-daemon", RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD |
|
||||
RPM_OSTREE_BUILTIN_FLAG_REQUIRES_ROOT |
|
||||
RPM_OSTREE_BUILTIN_FLAG_HIDDEN,
|
||||
|
45
src/app/rpmostree-builtin-coreos-rootfs.c
Normal file
45
src/app/rpmostree-builtin-coreos-rootfs.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2019 Red Hat, Inc.
|
||||
*
|
||||
* This program 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 of the licence or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <glib-unix.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "rpmostree-builtins.h"
|
||||
#include "rpmostree-libbuiltin.h"
|
||||
#include "rpmostree-rust.h"
|
||||
|
||||
#include <libglnx.h>
|
||||
|
||||
gboolean
|
||||
rpmostree_builtin_coreos_rootfs (int argc,
|
||||
char **argv,
|
||||
RpmOstreeCommandInvocation *invocation,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GPtrArray) args = g_ptr_array_new ();
|
||||
for (int i = 0; i < argc; i++)
|
||||
g_ptr_array_add (args, argv[i]);
|
||||
g_ptr_array_add (args, NULL);
|
||||
return ror_coreos_rootfs_entrypoint ((char**)args->pdata, error);
|
||||
}
|
@ -51,6 +51,7 @@ BUILTINPROTO(override);
|
||||
BUILTINPROTO(kargs);
|
||||
BUILTINPROTO(reset);
|
||||
BUILTINPROTO(start_daemon);
|
||||
BUILTINPROTO(coreos_rootfs);
|
||||
BUILTINPROTO(ex);
|
||||
BUILTINPROTO(finalize_deployment);
|
||||
|
||||
|
@ -102,6 +102,15 @@ fi
|
||||
assert_file_has_content err.txt 'ReloadConfig not allowed for user'
|
||||
echo "ok auth"
|
||||
|
||||
# Test coreos-rootfs
|
||||
vm_shell_inline << EOF
|
||||
mkdir /var/tmp/coreos-rootfs
|
||||
rpm-ostree coreos-rootfs seal /var/tmp/coreos-rootfs
|
||||
lsattr -d /var/tmp/coreos-rootfs
|
||||
rpm-ostree coreos-rootfs seal /var/tmp/coreos-rootfs
|
||||
EOF > coreos-rootfs.txt
|
||||
assert_file_has_content_literal coreos-rootfs.txt '----i-------------- /var/tmp/coreos-rootfs'
|
||||
|
||||
# Assert that we can do status as non-root
|
||||
vm_cmd_as testuser rpm-ostree status
|
||||
echo "ok status doesn't require root"
|
||||
|
Loading…
Reference in New Issue
Block a user