Received: by 10.223.176.46 with SMTP id f43csp1569877wra; Wed, 24 Jan 2018 19:39:25 -0800 (PST) X-Google-Smtp-Source: AH8x225K6+fGP2PHJYxcQ/9mU8oMccGrvHmDyXAV5JOTjtenLvaxvAqn6H0vMovO1kQVYzN6rxnZ X-Received: by 2002:a17:902:9a43:: with SMTP id x3-v6mr10164001plv.45.1516851565843; Wed, 24 Jan 2018 19:39:25 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516851565; cv=none; d=google.com; s=arc-20160816; b=axzPl4AP0fMtQBguIC9kIA2+ytQmhZILLYBEH8+dhWj5NPaawbsXXyVi8YJOWalEug EhidPAGx5TQEhnW0YZcy/rvNZx0V/oXdVtM++3nuVXPU4axZgu+F0HaHI+Xr1zId6IMx UjLOWdRgOPpSIn5SFRMFdUY9fsEX1Y8yEqpBRexL/h2BKncm5YokE4Wa8g4J6TkfzJq/ 7ugOmikPSmmz/3Q5JjlLYpz09R6Och5ESvNeltzMo7p6Yb2Q/gPGt1HuGZK0VgJ10hxx 5Z2UUIQhux1QO6sf5QhYA/H6HJZz0svHkG3cOwAuyoizWr3L1/4tLao0OLDSid/b41rO HBFQ== 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=gpHmBYK5G4fNy7DIIAcsM0i80MqvDIVNxwyv2bEv3Sw=; b=VS75lLqnvVKvxNALCPILCi7ZAmhvHwgjYio2YWl4ayOQ0W87NoqUrx6P3+cCsO5Xkb kFmuGevYg1x03Pp/BX4QJEajZSBQAR7E688Hc5qpmpdRHw30dUALG7hUo0Z8xNUFG6OO ZDwuZefrv7+ERCAEzOivofw4+cDBp2qyhs91rWOlcwFS36t+mEchsDgZUMYZpdoEDF4a h0uM+fg16NBT/KzKjZMzEAr1lHd/Nlk4EY0Y1K4Xmc/tPp4voVCsuQ1VmihEo1u1gkCt n53jM7UiChONMDWz2LjUGWF2kb87haSKdLVFCXnVIiw+efTxnbx4F/noYundGcOSy66r ULXg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cisco.com header.s=iport header.b=VOHVhbUl; 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 o3-v6si757582pld.605.2018.01.24.19.39.11; Wed, 24 Jan 2018 19:39:25 -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=VOHVhbUl; 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 S933680AbeAYDiU (ORCPT + 99 others); Wed, 24 Jan 2018 22:38:20 -0500 Received: from alln-iport-8.cisco.com ([173.37.142.95]:46561 "EHLO alln-iport-8.cisco.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933532AbeAYDhj (ORCPT ); Wed, 24 Jan 2018 22:37:39 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cisco.com; i=@cisco.com; l=7364; q=dns/txt; s=iport; t=1516851459; x=1518061059; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=v2Sd9j87sSK0OjBSOsZOw/6kuLjd0UEt3c0PeADIO3w=; b=VOHVhbUlT0L5y3fwUHDSeaV3ZKMijebAjBR0bNJAhgln+5I0jfC73mLv T2DDPVXhfK10iKWWci1DLlqXwUZX6BEZxbpF2rUz4gNC+VM5N1cDhDfSk 61nkKVgfzE4LigaXwI8s6OZjmR35WzxQoBDCbeV+NqncB0QCRFqxlUdMw w=; X-IronPort-AV: E=Sophos;i="5.46,409,1511827200"; d="scan'208";a="60787414" Received: from rcdn-core-6.cisco.com ([173.37.93.157]) by alln-iport-8.cisco.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 25 Jan 2018 03:28:08 +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 w0P3Ruj3007601 (version=TLSv1/SSLv3 cipher=AES128-SHA256 bits=128 verify=NO); Thu, 25 Jan 2018 03:28:07 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 v2 12/15] gen_init_cpio: set extended attributes for newcx format Date: Thu, 25 Jan 2018 03:27:52 +0000 Message-Id: <1516850875-25066-13-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 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org gen_init_cpio creates CPIO archive according to cpio_list manifest file that contains list of archive entries (one per line). To be able to store extended attributes in newcx CPIO format we need to pass them via cpio_list file. One way of doing it would be to append xattrs to each entry line, but "file" lines have a variable number of elements because of hardlinks. It is not obvious how to mark end of hardlinks and start of xattrs in this case. This patch introduces a new entry type: "xattr". Each "xattr" line specify one name=value pair. xattr values are applied to the next non-xattr line. There can be multiple "xattr" lines before non-xattr line. It may be more logical to have xattr lines after corresponding file entry, but it makes parsing a bit more complex and needs more intrusive changes. Xattr value is hex-encoded (see getfattr(1)). Plain string variant would be easier to read, but special symbols have to be escaped. Hex encoding is much simpler. Signed-off-by: Taras Kondratiuk --- usr/gen_init_cpio.c | 142 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 119 insertions(+), 23 deletions(-) diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c index 78a47a5bdcb1..e356f9e532a2 100644 --- a/usr/gen_init_cpio.c +++ b/usr/gen_init_cpio.c @@ -10,6 +10,7 @@ #include #include #include +#include #include /* @@ -50,21 +51,10 @@ static void push_pad (void) } } -static void push_rest(const char *name) +static void push_string_padded(const char *name) { - unsigned int name_len = strlen(name) + 1; - unsigned int tmp_ofs; - - fputs(name, stdout); - putchar(0); - offset += name_len; - - tmp_ofs = name_len + cpio_hdr_size; - while (tmp_ofs & 3) { - putchar(0); - offset++; - tmp_ofs++; - } + push_string(name); + push_pad(); } struct cpio_header { @@ -137,7 +127,7 @@ static void cpio_trailer(void) }; push_hdr(&hdr); - push_rest(name); + push_string_padded(name); while (offset % 512) { putchar(0); @@ -145,6 +135,96 @@ static void cpio_trailer(void) } } +struct xattr_hdr { + char c_size[8]; /* total size including c_size field */ + char c_data[]; +}; +static unsigned int xattr_buflen; +static char xattr_buf[4096]; + +static void push_xattrs(void) +{ + if (!newcx || !xattr_buflen) + return; + + if (fwrite(xattr_buf, xattr_buflen, 1, stdout) != 1) + fprintf(stderr, "writing xattrs failed\n"); + offset += xattr_buflen; + xattr_buflen = 0; + + push_pad(); +} + +static int convert_hex_string(const char *hex_str, char *out, size_t out_size) +{ + char buf[3]; + size_t str_len = strlen(hex_str); + + if (str_len % 2 != 0 || str_len / 2 > out_size) + return 0; + + buf[2] = '\0'; + while (*hex_str != '\0') { + buf[0] = *hex_str++; + buf[1] = *hex_str++; + *out++ = (char)strtol(buf, NULL, 16); + } + + return str_len / 2; +} + +static int collect_xattr(const char *line) +{ + const char *name, *value; + size_t name_len, value_len; + char *buf = xattr_buf + xattr_buflen; + struct xattr_hdr *hdr = (struct xattr_hdr *)buf; + char *bufend = xattr_buf + sizeof(xattr_buf); + char *value_buf; + size_t xattr_entry_size; + char size_str[sizeof(hdr->c_size) + 1]; + + if (!newcx) + return 0; + + name = line; + value = strchr(line, '='); + if (!value) { + fprintf(stderr, "Unrecognized xattr format '%s'", line); + return -1; + } + name_len = value - name; + value++; + + /* + * For now we support only hex encoded values. + * String or base64 can be added later. + */ + if (strncmp(value, "0x", 2)) { + fprintf(stderr, + "Only hex encoded xattr value is supported '%s'", + value); + return -1; + } + + value += 2; + value_buf = buf + sizeof(struct xattr_hdr) + name_len + 1; + value_len = convert_hex_string(value, value_buf, bufend - value_buf); + if (value_len == 0) { + fprintf(stderr, "Failed to parse xattr value '%s'", line); + return -1; + } + xattr_entry_size = sizeof(struct xattr_hdr) + name_len + 1 + value_len; + + sprintf(size_str, "%08X", (unsigned int)xattr_entry_size); + memcpy(hdr->c_size, size_str, sizeof(hdr->c_size)); + memcpy(hdr->c_data, name, name_len); + hdr->c_data[name_len] = '\0'; + xattr_buflen += xattr_entry_size; + + return 0; +} + static int cpio_mkslink(const char *name, const char *target, unsigned int mode, uid_t uid, gid_t gid) { @@ -161,12 +241,12 @@ static int cpio_mkslink(const char *name, const char *target, .devmajor = 3, .devminor = 1, .namesize = strlen(name)+1, + .xattrsize = xattr_buflen, }; push_hdr(&hdr); - push_string(name); - push_pad(); - push_string(target); - push_pad(); + push_string_padded(name); + push_xattrs(); + push_string_padded(target); return 0; } @@ -203,9 +283,11 @@ static int cpio_mkgeneric(const char *name, unsigned int mode, .devmajor = 3, .devminor = 1, .namesize = strlen(name)+1, + .xattrsize = xattr_buflen, }; push_hdr(&hdr); - push_rest(name); + push_string_padded(name); + push_xattrs(); return 0; } @@ -292,9 +374,11 @@ static int cpio_mknod(const char *name, unsigned int mode, .rdevmajor = maj, .rdevminor = min, .namesize = strlen(name)+1, + .xattrsize = xattr_buflen, }; push_hdr(&hdr); - push_rest(name); + push_string_padded(name); + push_xattrs(); return 0; } @@ -377,10 +461,13 @@ static int cpio_mkfile(const char *name, const char *location, .devmajor = 3, .devminor = 1, .namesize = namesize, + /* xattrs go on last link */ + .xattrsize = (i == nlinks) ? xattr_buflen : 0, }; push_hdr(&hdr); - push_string(name); - push_pad(); + push_string_padded(name); + if (hdr.xattrsize) + push_xattrs(); if (size) { if (fwrite(filebuf, size, 1, stdout) != 1) { @@ -486,6 +573,8 @@ static void usage(const char *prog) "slink \n" "pipe \n" "sock \n" + "# xattr line is applied to the next non-xattr entry\n" + "xattr =\n" "\n" " name of the file/dir/nod/etc in the archive\n" " location of the file in the current filesystem\n" @@ -498,12 +587,16 @@ static void usage(const char *prog) " major number of nod\n" " minor number of nod\n" " space separated list of other links to file\n" + " extended attribute name\n" + " hex-encoded extended attribute value\n" "\n" "example:\n" "# A simple initramfs\n" "dir /dev 0755 0 0\n" "nod /dev/console 0600 0 0 c 5 1\n" "dir /root 0700 0 0\n" + "# set SELinux label 'system_u:object_r:bin_t:s0' for /sbin directory\n" + "xattr security.selinux=0x73797374656d5f753a6f626a6563745f723a62696e5f743a733000\n" "dir /sbin 0755 0 0\n" "file /sbin/kinit /usr/src/klibc/kinit/kinit 0755 0 0\n" "\n" @@ -533,6 +626,9 @@ struct file_handler file_handler_table[] = { .type = "sock", .handler = cpio_mksock_line, }, { + .type = "xattr", + .handler = collect_xattr, + }, { .type = NULL, .handler = NULL, } -- 2.10.3.dirty