From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933527AbeAYDhf (ORCPT ); Wed, 24 Jan 2018 22:37:35 -0500 Received: from alln-iport-6.cisco.com ([173.37.142.93]:21061 "EHLO alln-iport-6.cisco.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933490AbeAYDhc (ORCPT ); Wed, 24 Jan 2018 22:37:32 -0500 X-IronPort-AV: E=Sophos;i="5.46,409,1511827200"; d="scan'208";a="60773962" From: Taras Kondratiuk To: "H. Peter Anvin" , Al Viro , Arnd Bergmann , Rob Landley , Mimi Zohar , Jonathan Corbet , James McMechan Cc: initramfs@vger.kernel.org, Victor Kamensky , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org, xe-linux-external@cisco.com Subject: [PATCH v2 08/15] initramfs: add newcx format Date: Thu, 25 Jan 2018 03:27:48 +0000 Message-Id: <1516850875-25066-9-git-send-email-takondra@cisco.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1516850875-25066-1-git-send-email-takondra@cisco.com> References: <1516850875-25066-1-git-send-email-takondra@cisco.com> X-Auto-Response-Suppress: DR, OOF, AutoReply X-Authenticated-User: takondra@cisco.com Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add 'newcx' format that adds extended attributes and increased size of c_mtime and c_filesize fields. Refer to Documentation/early-userspace/buffer-format.txt for detailed format description. Signed-off-by: Taras Kondratiuk --- init/initramfs.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 10 deletions(-) diff --git a/init/initramfs.c b/init/initramfs.c index 7f0bbfde94e3..3d0f46c28459 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -54,6 +54,7 @@ static void __init error(char *x) /* link hash */ #define N_ALIGN(len) ((((len) + 1) & ~3) + 2) +#define X_ALIGN(len) ((len + 3) & ~3) static __initdata struct hash { int ino, minor, major; @@ -154,7 +155,8 @@ static void __init dir_utime(void) static __initdata time64_t mtime; static __initdata u32 ino, major, minor, nlink, rmajor, rminor; static __initdata umode_t mode; -static __initdata u32 body_len, name_len; +static __initdata u32 name_len, xattr_len; +static __initdata u64 body_len, mtime_u64; static __initdata uid_t uid; static __initdata gid_t gid; static __initdata u32 mode_u32; @@ -167,6 +169,12 @@ struct cpio_hdr_field { const char *name; }; +static __initdata enum cpio_format { + CPIO_NO_MAGIC, + CPIO_NEWC, + CPIO_NEWCX, +} cpio_format; + #define HDR_FIELD(type, field, variable) \ { .offset = offsetof(type, field) + \ BUILD_BUG_ON_ZERO(sizeof(*(variable))*2 < FIELD_SIZEOF(type, field)),\ @@ -177,9 +185,11 @@ struct cpio_hdr_field { #define NEWC_FIELD(field, variable) \ HDR_FIELD(struct cpio_newc_header, field, variable) +#define NEWCX_FIELD(field, variable) \ + HDR_FIELD(struct cpio_newcx_header, field, variable) -#define CPIO_MAX_HEADER_SIZE sizeof(struct cpio_newc_header) -#define CPIO_MAX_FIELD_SIZE 8 +#define CPIO_MAX_HEADER_SIZE sizeof(struct cpio_newcx_header) +#define CPIO_MAX_FIELD_SIZE 16 #define CPIO_MAGIC_SIZE 6 struct cpio_newc_header { @@ -214,10 +224,44 @@ static struct cpio_hdr_field cpio_newc_header_info[] __initdata = { { 0 }, }; +struct cpio_newcx_header { + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[16]; + char c_filesize[16]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_xattrsize[8]; +}; + +static struct cpio_hdr_field cpio_newcx_header_info[] __initdata = { + NEWCX_FIELD(c_ino, &ino), + NEWCX_FIELD(c_mode, &mode_u32), + NEWCX_FIELD(c_uid, &uid), + NEWCX_FIELD(c_gid, &gid), + NEWCX_FIELD(c_nlink, &nlink), + NEWCX_FIELD(c_mtime, &mtime_u64), + NEWCX_FIELD(c_filesize, &body_len), + NEWCX_FIELD(c_devmajor, &major), + NEWCX_FIELD(c_devminor, &minor), + NEWCX_FIELD(c_rdevmajor, &rmajor), + NEWCX_FIELD(c_rdevminor, &rminor), + NEWCX_FIELD(c_namesize, &name_len), + NEWCX_FIELD(c_xattrsize, &xattr_len), + { 0 }, +}; + static void __init parse_header(char *s) { char buf[CPIO_MAX_FIELD_SIZE + 1]; - struct cpio_hdr_field *field = cpio_newc_header_info; + struct cpio_hdr_field *field = (cpio_format == CPIO_NEWC) ? + cpio_newc_header_info : cpio_newcx_header_info; while (field->size) { int ret = 0; @@ -243,7 +287,15 @@ static void __init parse_header(char *s) pr_err("invalid cpio header field (%d)", ret); field++; } + mode = mode_u32; + if (cpio_format == CPIO_NEWCX) { + /* Microseconds are ignored for now */ + do_div(mtime_u64, USEC_PER_SEC); + mtime = mtime_u64; + } else { + xattr_len = 0; + } } /* FSM */ @@ -254,6 +306,7 @@ static int __init do_format(void); static int __init do_header(void); static int __init do_skip(void); static int __init do_name(void); +static int __init do_xattrs(void); static int __init do_create(void); static int __init do_copy(void); static int __init do_symlink(void); @@ -291,7 +344,7 @@ static void __init read_into(char *buf, unsigned size, fsm_state_t next) } } -static __initdata char *header_buf, *symlink_buf, *name_buf; +static __initdata char *header_buf, *symlink_buf, *name_buf, *xattr_buf; static int __init do_start(void) { @@ -315,22 +368,34 @@ static int __init do_collect(void) static int __init do_format(void) { - if (memcmp(collected, "070707", CPIO_MAGIC_SIZE) == 0) { + int header_size = 0; + + cpio_format = CPIO_NO_MAGIC; + + if (!memcmp(collected, "070707", CPIO_MAGIC_SIZE)) { error("incorrect cpio method used: use -H newc option"); return 1; + } else if (!memcmp(collected, "070701", CPIO_MAGIC_SIZE)) { + cpio_format = CPIO_NEWC; + header_size = sizeof(struct cpio_newc_header); + } else if (!memcmp(collected, "070703", CPIO_MAGIC_SIZE)) { + cpio_format = CPIO_NEWCX; + header_size = sizeof(struct cpio_newcx_header); } - if (memcmp(collected, "070701", CPIO_MAGIC_SIZE)) { + + if (cpio_format == CPIO_NO_MAGIC) { error("no cpio magic"); return 1; } - read_into(header_buf, sizeof(struct cpio_newc_header), do_header); + read_into(header_buf, header_size, do_header); return 0; } static int __init do_header(void) { parse_header(collected); - next_header = this_header + N_ALIGN(name_len) + body_len; + next_header = this_header + N_ALIGN(name_len) + X_ALIGN(xattr_len) + + body_len; next_header = (next_header + 3) & ~3; state = do_skip; if (name_len <= 0 || name_len > PATH_MAX) @@ -400,9 +465,17 @@ static int __init do_name(void) } memcpy_optional(name_buf, collected, N_ALIGN(name_len)); state = do_create; + if (xattr_len > 0) + read_into(xattr_buf, X_ALIGN(xattr_len), do_xattrs); return 0; } +static int __init do_xattrs(void) +{ + /* Do nothing for now */ + state = do_create; + return 0; +} static __initdata int wfd; @@ -529,8 +602,9 @@ static char * __init unpack_to_rootfs(char *buf, unsigned long len) header_buf = kmalloc(CPIO_MAX_HEADER_SIZE, GFP_KERNEL); symlink_buf = kmalloc(PATH_MAX + 1, GFP_KERNEL); name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL); + xattr_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!header_buf || !symlink_buf || !name_buf) + if (!header_buf || !symlink_buf || !name_buf || !xattr_buf) panic("can't allocate buffers"); state = do_start; @@ -575,6 +649,7 @@ static char * __init unpack_to_rootfs(char *buf, unsigned long len) len -= my_inptr; } dir_utime(); + kfree(xattr_buf); kfree(name_buf); kfree(symlink_buf); kfree(header_buf); -- 2.10.3.dirty