Received: by 10.223.185.116 with SMTP id b49csp1110245wrg; Fri, 16 Feb 2018 12:39:24 -0800 (PST) X-Google-Smtp-Source: AH8x225fqi42A075TyqjFVvqZ5YJ+YUTdJdRE2SqGWAC9Vq866m5TctJWqt7335Qb77qbnP9+LyK X-Received: by 10.167.129.24 with SMTP id b24mr1415170pfi.183.1518813564305; Fri, 16 Feb 2018 12:39:24 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518813564; cv=none; d=google.com; s=arc-20160816; b=l7wC7acpaFIT5MPFx8Q1b2Adg/Yzt8bHzRu6+Bm3WVPrBQAn08QqDxhuwfJBsSMy9Z EwqMS0hLUazJakuoDvJLF2UwFdcvHmqceSdnatS6AhnUOIKD5dW/g5q51vXiyPqMZw7o ibJ2yM1iaPEjTgXPwSUL4MnnQIKcxUwT2QAABVhs2A0tyNNzAUXzhxzhTf7l0bKdYTu/ BjAF7HBWLBnvguSs/2BXI3z82kbaqBZnETqC2rHKpby4RPeuaZ2Ow4DX/z+tZxsVVsd2 7VeKnbExMmv9IayRqsuFbXb6CgcKxnQs6mwyFLfCt6/uXerIKSGgNDza4eAI+AZ4pBX5 IPtA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=M5dVv2Tq/uSVnSCULg8aiAxBjKzAljCxGc0/2Ba0O2U=; b=MWarii99WU6UyrB4Le19qWkoyBJMeWmZpUywnufhlrFcoPea6UuPgSzMzMpCy2s90Q d4e4YBQcDjSJFt4ai7dM0ta1ilhjRqyFe5xsVzguZFoBC55nnmOzD1Vo1KQZVMYVsDPS u0ylw64Mh5nDD3di6gKWjTxn3oklHtYW5O878foZ0t5VbbIx1sravX6h3csDGv+NN+QC 8xt74zmWW0Kogtfd7z9dzJ3dSivTrdaIbBzoKS6IfK9p7cr8d9icPENEwunh6e2Rho9z CyMW7cVLEfkBYBIX9+QptH0Sso1oH4r9wCLIESqgYhB6qRtFyq1eSoWvXdWxYmRJGY1c i1mg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cisco.com header.s=iport header.b=Zv1JpMhq; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=cisco.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id j4si2009719pfe.324.2018.02.16.12.39.09; Fri, 16 Feb 2018 12:39:24 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@cisco.com header.s=iport header.b=Zv1JpMhq; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=cisco.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751223AbeBPUhr (ORCPT + 99 others); Fri, 16 Feb 2018 15:37:47 -0500 Received: from rcdn-iport-9.cisco.com ([173.37.86.80]:17582 "EHLO rcdn-iport-9.cisco.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750951AbeBPUeC (ORCPT ); Fri, 16 Feb 2018 15:34:02 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cisco.com; i=@cisco.com; l=5503; q=dns/txt; s=iport; t=1518813242; x=1520022842; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=7fdyqsS+k1XeqW14jyS/DXDdkMe9brBhAMIxsTBxYH8=; b=Zv1JpMhqz5nil4TCYfd2LC7KQiGgkYOUmZFOPn8sX/s0DsHgFz3e26os Jw1nVisyJIJxMB5kPUuVT8d0dahzwqQOTAIFTdNP5BA6yT0T0aO8sOwI8 YBNRTVZJVdt0vw91+oNHFgEeuUV90DZX5l23qsI3MOQQiDvTAvXw155x7 4=; X-IronPort-AV: E=Sophos;i="5.46,520,1511827200"; d="scan'208";a="350021939" Received: from rcdn-core-6.cisco.com ([173.37.93.157]) by rcdn-iport-9.cisco.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Feb 2018 20:34:01 +0000 Received: from sjc-ads-7132.cisco.com (sjc-ads-7132.cisco.com [10.30.217.207]) (authenticated bits=0) by rcdn-core-6.cisco.com (8.14.5/8.14.5) with ESMTP id w1GKXsMW015412 (version=TLSv1/SSLv3 cipher=AES128-SHA256 bits=128 verify=NO); Fri, 16 Feb 2018 20:34:00 GMT 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 v3 07/15] initramfs: split header layout information from parsing function Date: Fri, 16 Feb 2018 20:33:43 +0000 Message-Id: <1518813234-5874-8-git-send-email-takondra@cisco.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1518813234-5874-1-git-send-email-takondra@cisco.com> References: <1518813234-5874-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 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Header parsing has hardcoded assumption about header field size and layout. It is hard to modify the function to parse a new format. Move information about size and layout into a data structure to make parsing code more generic and simplify adding a new format. This also removes some magic numbers. Signed-off-by: Taras Kondratiuk --- init/initramfs.c | 122 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 92 insertions(+), 30 deletions(-) diff --git a/init/initramfs.c b/init/initramfs.c index b3d39c8793be..7f0bbfde94e3 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -150,39 +150,100 @@ static void __init dir_utime(void) } } -static __initdata time64_t mtime; - /* cpio header parsing */ - -static __initdata unsigned long ino, major, minor, nlink; +static __initdata time64_t mtime; +static __initdata u32 ino, major, minor, nlink, rmajor, rminor; static __initdata umode_t mode; -static __initdata unsigned long body_len, name_len; +static __initdata u32 body_len, name_len; static __initdata uid_t uid; static __initdata gid_t gid; -static __initdata unsigned rdev; +static __initdata u32 mode_u32; + +struct cpio_hdr_field { + size_t offset; + size_t size; + void *out; + size_t out_size; + const char *name; +}; + +#define HDR_FIELD(type, field, variable) \ + { .offset = offsetof(type, field) + \ + BUILD_BUG_ON_ZERO(sizeof(*(variable))*2 < FIELD_SIZEOF(type, field)),\ + .size = FIELD_SIZEOF(type, field), \ + .out = variable, \ + .out_size = sizeof(*(variable)), \ + .name = #field } + +#define NEWC_FIELD(field, variable) \ + HDR_FIELD(struct cpio_newc_header, field, variable) + +#define CPIO_MAX_HEADER_SIZE sizeof(struct cpio_newc_header) +#define CPIO_MAX_FIELD_SIZE 8 +#define CPIO_MAGIC_SIZE 6 + +struct cpio_newc_header { + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +}; + +static struct cpio_hdr_field cpio_newc_header_info[] __initdata = { + NEWC_FIELD(c_ino, &ino), + NEWC_FIELD(c_mode, &mode_u32), + NEWC_FIELD(c_uid, &uid), + NEWC_FIELD(c_gid, &gid), + NEWC_FIELD(c_nlink, &nlink), + NEWC_FIELD(c_mtime, &mtime), + NEWC_FIELD(c_filesize, &body_len), + NEWC_FIELD(c_devmajor, &major), + NEWC_FIELD(c_devminor, &minor), + NEWC_FIELD(c_rdevmajor, &rmajor), + NEWC_FIELD(c_rdevminor, &rminor), + NEWC_FIELD(c_namesize, &name_len), + { 0 }, +}; static void __init parse_header(char *s) { - unsigned long parsed[12]; - char buf[9]; - int i; - - buf[8] = '\0'; - for (i = 0; i < 12; i++, s += 8) { - memcpy(buf, s, 8); - parsed[i] = simple_strtoul(buf, NULL, 16); + char buf[CPIO_MAX_FIELD_SIZE + 1]; + struct cpio_hdr_field *field = cpio_newc_header_info; + + while (field->size) { + int ret = 0; + + memcpy(buf, s + field->offset, field->size); + buf[field->size] = '\0'; + switch (field->out_size) { + case sizeof(u32): + ret = kstrtou32(buf, 16, field->out); + pr_debug("cpio field %s: %u, buf: %s\n", + field->name, *(u32 *)field->out, buf); + break; + case sizeof(u64): + ret = kstrtou64(buf, 16, field->out); + pr_debug("cpio field %s: %llu, buf: %s\n", + field->name, *(u64 *)field->out, buf); + break; + default: + BUG_ON(1); + } + + if (ret) + pr_err("invalid cpio header field (%d)", ret); + field++; } - ino = parsed[0]; - mode = parsed[1]; - uid = parsed[2]; - gid = parsed[3]; - nlink = parsed[4]; - mtime = parsed[5]; /* breaks in y2106 */ - body_len = parsed[6]; - major = parsed[7]; - minor = parsed[8]; - rdev = new_encode_dev(MKDEV(parsed[9], parsed[10])); - name_len = parsed[11]; + mode = mode_u32; } /* FSM */ @@ -234,7 +295,7 @@ static __initdata char *header_buf, *symlink_buf, *name_buf; static int __init do_start(void) { - read_into(header_buf, 6, do_format); + read_into(header_buf, CPIO_MAGIC_SIZE, do_format); return 0; } @@ -254,15 +315,15 @@ static int __init do_collect(void) static int __init do_format(void) { - if (memcmp(collected, "070707", 6)==0) { + if (memcmp(collected, "070707", CPIO_MAGIC_SIZE) == 0) { error("incorrect cpio method used: use -H newc option"); return 1; } - if (memcmp(collected, "070701", 6)) { + if (memcmp(collected, "070701", CPIO_MAGIC_SIZE)) { error("no cpio magic"); return 1; } - read_into(header_buf, 104, do_header); + read_into(header_buf, sizeof(struct cpio_newc_header), do_header); return 0; } @@ -374,6 +435,7 @@ static int __init do_create(void) } else if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { if (maybe_link(name_buf) == 0) { + u32 rdev = new_encode_dev(MKDEV(rmajor, rminor)); sys_mknod(name_buf, mode, rdev); sys_chown(name_buf, uid, gid); sys_chmod(name_buf, mode); @@ -464,7 +526,7 @@ static char * __init unpack_to_rootfs(char *buf, unsigned long len) const char *compress_name; static __initdata char msg_buf[64]; - header_buf = kmalloc(104, GFP_KERNEL); + 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); -- 2.10.3.dirty