From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BF5B5C072A4 for ; Mon, 20 May 2019 08:47:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9FA8520856 for ; Mon, 20 May 2019 08:47:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730433AbfETIrb (ORCPT ); Mon, 20 May 2019 04:47:31 -0400 Received: from lhrrgout.huawei.com ([185.176.76.210]:32955 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727499AbfETIrb (ORCPT ); Mon, 20 May 2019 04:47:31 -0400 Received: from LHREML714-CAH.china.huawei.com (unknown [172.18.7.107]) by Forcepoint Email with ESMTP id 4BE9A91FD6E0516857B2; Mon, 20 May 2019 09:47:29 +0100 (IST) Received: from [10.220.96.108] (10.220.96.108) by smtpsuk.huawei.com (10.201.108.37) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 20 May 2019 09:47:21 +0100 Subject: Re: [PATCH v3 2/2] initramfs: introduce do_readxattrs() To: , CC: , , , , , , , , , , , , , , References: <20190517165519.11507-1-roberto.sassu@huawei.com> <20190517165519.11507-3-roberto.sassu@huawei.com> From: Roberto Sassu Message-ID: <2fbe55dc-2f4a-e476-79d0-06931b4f1dee@huawei.com> Date: Mon, 20 May 2019 10:47:27 +0200 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.3.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset="utf-8"; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-Originating-IP: [10.220.96.108] X-CFilter-Loop: Reflected Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org On 5/17/2019 10:18 PM, hpa@zytor.com wrote: > On May 17, 2019 9:55:19 AM PDT, Roberto Sassu wrote: >> This patch adds support for an alternative method to add xattrs to >> files in >> the rootfs filesystem. Instead of extracting them directly from the ram >> disk image, they are extracted from a regular file called .xattr-list, >> that >> can be added by any ram disk generator available today. The file format >> is: >> >> \0 >> \0 >> >> .xattr-list can be generated by executing: >> >> $ getfattr --absolute-names -d -h -R -e hex -m - \ >> | xattr.awk -b > ${initdir}/.xattr-list >> >> where the content of the xattr.awk script is: >> >> #! /usr/bin/awk -f >> { >> if (!length($0)) { >> printf("%.10x%s\0", len, file); >> for (x in xattr) { >> printf("%.8x%s\0", xattr_len[x], x); >> for (i = 0; i < length(xattr[x]) / 2; i++) { >> printf("%c", strtonum("0x"substr(xattr[x], i * 2 + 1, 2))); >> } >> } >> i = 0; >> delete xattr; >> delete xattr_len; >> next; >> }; >> if (i == 0) { >> file=$3; >> len=length(file) + 8 + 1; >> } >> if (i > 0) { >> split($0, a, "="); >> xattr[a[1]]=substr(a[2], 3); >> xattr_len[a[1]]=length(a[1]) + 1 + 8 + length(xattr[a[1]]) / 2; >> len+=xattr_len[a[1]]; >> }; >> i++; >> } >> >> Signed-off-by: Roberto Sassu >> --- >> init/initramfs.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 99 insertions(+) >> >> diff --git a/init/initramfs.c b/init/initramfs.c >> index 0c6dd1d5d3f6..6ec018c6279a 100644 >> --- a/init/initramfs.c >> +++ b/init/initramfs.c >> @@ -13,6 +13,8 @@ >> #include >> #include >> >> +#define XATTR_LIST_FILENAME ".xattr-list" >> + >> static ssize_t __init xwrite(int fd, const char *p, size_t count) >> { >> ssize_t out = 0; >> @@ -382,6 +384,97 @@ static int __init __maybe_unused do_setxattrs(char >> *pathname) >> return 0; >> } >> >> +struct path_hdr { >> + char p_size[10]; /* total size including p_size field */ >> + char p_data[]; /* \0 */ >> +}; >> + >> +static int __init do_readxattrs(void) >> +{ >> + struct path_hdr hdr; >> + char *path = NULL; >> + char str[sizeof(hdr.p_size) + 1]; >> + unsigned long file_entry_size; >> + size_t size, path_size, total_size; >> + struct kstat st; >> + struct file *file; >> + loff_t pos; >> + int ret; >> + >> + ret = vfs_lstat(XATTR_LIST_FILENAME, &st); >> + if (ret < 0) >> + return ret; >> + >> + total_size = st.size; >> + >> + file = filp_open(XATTR_LIST_FILENAME, O_RDONLY, 0); >> + if (IS_ERR(file)) >> + return PTR_ERR(file); >> + >> + pos = file->f_pos; >> + >> + while (total_size) { >> + size = kernel_read(file, (char *)&hdr, sizeof(hdr), &pos); >> + if (size != sizeof(hdr)) { >> + ret = -EIO; >> + goto out; >> + } >> + >> + total_size -= size; >> + >> + str[sizeof(hdr.p_size)] = 0; >> + memcpy(str, hdr.p_size, sizeof(hdr.p_size)); >> + ret = kstrtoul(str, 16, &file_entry_size); >> + if (ret < 0) >> + goto out; >> + >> + file_entry_size -= sizeof(sizeof(hdr.p_size)); >> + if (file_entry_size > total_size) { >> + ret = -EINVAL; >> + goto out; >> + } >> + >> + path = vmalloc(file_entry_size); >> + if (!path) { >> + ret = -ENOMEM; >> + goto out; >> + } >> + >> + size = kernel_read(file, path, file_entry_size, &pos); >> + if (size != file_entry_size) { >> + ret = -EIO; >> + goto out_free; >> + } >> + >> + total_size -= size; >> + >> + path_size = strnlen(path, file_entry_size); >> + if (path_size == file_entry_size) { >> + ret = -EINVAL; >> + goto out_free; >> + } >> + >> + xattr_buf = path + path_size + 1; >> + xattr_len = file_entry_size - path_size - 1; >> + >> + ret = do_setxattrs(path); >> + vfree(path); >> + path = NULL; >> + >> + if (ret < 0) >> + break; >> + } >> +out_free: >> + vfree(path); >> +out: >> + fput(file); >> + >> + if (ret < 0) >> + error("Unable to parse xattrs"); >> + >> + return ret; >> +} >> + >> static __initdata int wfd; >> >> static int __init do_name(void) >> @@ -391,6 +484,11 @@ static int __init do_name(void) >> if (strcmp(collected, "TRAILER!!!") == 0) { >> free_hash(); >> return 0; >> + } else if (strcmp(collected, XATTR_LIST_FILENAME) == 0) { >> + struct kstat st; >> + >> + if (!vfs_lstat(collected, &st)) >> + do_readxattrs(); >> } >> clean_path(collected, mode); >> if (S_ISREG(mode)) { >> @@ -562,6 +660,7 @@ static char * __init unpack_to_rootfs(char *buf, >> unsigned long len) >> buf += my_inptr; >> len -= my_inptr; >> } >> + do_readxattrs(); >> dir_utime(); >> kfree(name_buf); >> kfree(symlink_buf); > > Ok... I just realized this does not work for a modular initramfs, composed at load time from multiple files, which is a very real problem. Should be easy enough to deal with: instead of one large file, use one companion file per source file, perhaps something like filename..xattrs (suggesting double dots to make it less likely to conflict with a "real" file.) No leading dot, as it makes it more likely that archivers will sort them before the file proper. Version 1 of the patch set worked exactly in this way. However, Rob pointed out that this would be a problem if file names plus the suffix exceed 255 characters. Roberto -- HUAWEI TECHNOLOGIES Duesseldorf GmbH, HRB 56063 Managing Director: Bo PENG, Jian LI, Yanli SHI