Skip to content

Commit

Permalink
Add hidden coreos-rootfs seal command
Browse files Browse the repository at this point in the history
All this does is put the immutable bit on the target directory.
The intention is to replace this bit to start:
https://github.com/coreos/coreos-assembler/blob/8b205bfbb971707382ace76bbb39e46ed3fc560d/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:
coreos/fedora-coreos-tracker#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.
  • Loading branch information
cgwalters committed Sep 25, 2019
1 parent ccace4c commit 319874f
Show file tree
Hide file tree
Showing 9 changed files with 222 additions and 0 deletions.
1 change: 1 addition & 0 deletions Makefile-rpm-ostree.am
Expand Up @@ -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 \
Expand Down
38 changes: 38 additions & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rust/Cargo.toml
Expand Up @@ -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"
Expand Down
119 changes: 119 additions & 0 deletions rust/src/coreos_rootfs.rs
@@ -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::*;
2 changes: 2 additions & 0 deletions rust/src/lib.rs
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions src/app/main.c
Expand Up @@ -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,
Expand Down
47 changes: 47 additions & 0 deletions src/app/rpmostree-builtin-coreos-rootfs.c
@@ -0,0 +1,47 @@
/* -*- 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(GOptionContext) context = g_option_context_new ("");
g_autoptr(GPtrArray) args = g_ptr_array_new ();
g_ptr_array_add (args, "rpm-ostree");
for (int i = 1; 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);
}
1 change: 1 addition & 0 deletions src/app/rpmostree-builtins.h
Expand Up @@ -51,6 +51,7 @@ BUILTINPROTO(override);
BUILTINPROTO(kargs);
BUILTINPROTO(reset);
BUILTINPROTO(start_daemon);
BUILTINPROTO(coreos_rootfs);
BUILTINPROTO(ex);
BUILTINPROTO(finalize_deployment);

Expand Down
9 changes: 9 additions & 0 deletions tests/vmcheck/test-misc-1.sh
Expand Up @@ -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 /var/tmp/coreos-rootfs
lsattr -d /var/tmp/coreos-rootfs
rpm-ostree coreos-rootfs /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"
Expand Down

0 comments on commit 319874f

Please sign in to comment.