ext2: Fix permission of the root directory

When a source directory path is given to the ext2 logic, its metadata
such as mode should be copied to the disk.

Before this patch, some unit tests that dump files in the created file
system with `debugfs` failed to clean up these files after completion
because the top directory permission is not set properly.

BUG=b:351994509
TEST=CQ

Change-Id: I9315d8cae45a738e8abcda1a4313a89d5fa7bd16
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/5687140
Reviewed-by: Takaya Saeki <takayas@chromium.org>
Commit-Queue: Keiichi Watanabe <keiichiw@chromium.org>
This commit is contained in:
Keiichi Watanabe 2024-07-09 20:07:41 +09:00 committed by crosvm LUCI
parent 18c8261043
commit 046a6acc64
3 changed files with 43 additions and 14 deletions

View file

@ -716,6 +716,20 @@ impl<'a> Ext2<'a> {
/// Walks through `src_dir` and copies directories and files to the new file system.
fn copy_dirtree<P: AsRef<Path>>(&mut self, arena: &'a Arena<'a>, src_dir: P) -> Result<()> {
// Update the root directory's metadata with the metadata of `src_dir`.
let root_inode_num = InodeNum::new(2).expect("2 is a valid inode number");
let group_id = self.group_num_for_inode(root_inode_num);
let gm = &mut self.group_metadata[group_id];
let inode: &mut &mut Inode = gm
.inode_table
.get_mut(&root_inode_num)
.expect("root dir is not stored");
let metadata = src_dir
.as_ref()
.metadata()
.with_context(|| format!("failed to get metadata of {:?}", src_dir.as_ref()))?;
inode.update_metadata(&metadata);
self.copy_dirtree_rec(arena, InodeNum(2), src_dir)
}

View file

@ -173,13 +173,13 @@ impl InodeBlock {
#[derive(Default, Debug, Copy, Clone, FromZeroes, FromBytes, AsBytes)]
pub(crate) struct Inode {
mode: u16,
_uid: u16,
uid: u16,
pub size: u32,
atime: u32,
ctime: u32,
mtime: u32,
_dtime: u32,
_gid: u16,
gid: u16,
pub links_count: u16,
pub blocks: InodeBlocksCount,
_flags: u32,
@ -192,8 +192,8 @@ pub(crate) struct Inode {
_fragment_num: u8,
_fragment_size: u8,
_reserved1: u16,
_uid_high: u16,
_gid_high: u16,
uid_high: u16,
gid_high: u16,
_reserved2: u32,
}
@ -278,10 +278,10 @@ impl Inode {
atime: now,
ctime: now,
mtime: now,
_uid: uid_low,
_gid: gid_low,
_uid_high: uid_high,
_gid_high: gid_high,
uid: uid_low,
gid: gid_low,
uid_high,
gid_high,
..Default::default()
};
Ok(inode)
@ -319,8 +319,8 @@ impl Inode {
*inode = Inode {
mode,
_uid: uid_low,
_gid: gid_low,
uid: uid_low,
gid: gid_low,
size,
atime,
ctime,
@ -328,16 +328,29 @@ impl Inode {
links_count,
blocks,
block,
_uid_high: uid_high,
_gid_high: gid_high,
uid_high,
gid_high,
..Default::default()
};
Ok(inode)
}
pub fn update_metadata(&mut self, m: &std::fs::Metadata) {
self.mode = m.mode() as u16;
let uid: u32 = m.uid();
self.uid_high = (uid >> 16) as u16;
self.uid = uid as u16;
let gid = m.gid();
self.gid_high = (gid >> 16) as u16;
self.gid = gid as u16;
self.atime = m.atime() as u32;
self.ctime = m.ctime() as u32;
self.mtime = m.mtime() as u32;
}
pub fn typ(&self) -> Option<InodeType> {
InodeType::n((self.mode >> 12) as u8)
}

View file

@ -236,6 +236,8 @@ fn test_simple_dir() {
);
assert_eq_dirs(&td, &dir, &disk);
td.close().unwrap(); // make sure that tempdir is properly deleted.
}
#[test]