Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hidden coreos-rootfs seal command #1911

Merged
merged 1 commit into from
Oct 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile-rpm-ostree.am
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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().
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And yeah, this turned out to be a lot more code in Rust than it would have been in C particularly if we just copy-pasted the libostree code but I doggedly kept at it 😉

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")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kebab-case is best 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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
45 changes: 45 additions & 0 deletions src/app/rpmostree-builtin-coreos-rootfs.c
Original file line number Diff line number Diff line change
@@ -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);
}
1 change: 1 addition & 0 deletions src/app/rpmostree-builtins.h
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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 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"
Expand Down