From acc629abb0d7a26f692f99e5a9cf8c8401bc6a86 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 10 Feb 2022 20:08:11 +0100 Subject: [PATCH] fix(cpio): correct dev_t -> rmajor/rminor mapping dev_t -> major/minor number mapping is more complicated than the incorrect major=(dev_t >> 8) minor=(dev_t & 0xff) mapping that we currently perform. Fix mapping to match Linux / glibc behaviour. Fixes: https://github.com/dracutdevs/dracut/issues/1695 Reported-by: Ethan Wu Signed-off-by: David Disseldorp --- src/dracut-cpio/src/main.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/dracut-cpio/src/main.rs b/src/dracut-cpio/src/main.rs index a1994b96..816fc510 100644 --- a/src/dracut-cpio/src/main.rs +++ b/src/dracut-cpio/src/main.rs @@ -361,9 +361,12 @@ fn archive_path( // no zero terminator for symlink target path } + // Linux kernel uses 32-bit dev_t, encoded as mmmM MMmm. glibc uses 64-bit + // MMMM Mmmm mmmM MMmm, which is compatible with the former. if ftype.is_block_device() || ftype.is_char_device() { - rmajor = (md.rdev() >> 8) as u32; - rminor = (md.rdev() & 0xff) as u32; + let rd = md.rdev(); + rmajor = (((rd >> 32) & 0xfffff000) | ((rd >> 8) & 0x00000fff)) as u32; + rminor = (((rd >> 12) & 0xffffff00) | (rd & 0x000000ff)) as u32; } if ftype.is_file() {