linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/15] extend initramfs archive format to support xattrs
@ 2018-01-25  3:27 Taras Kondratiuk
  2018-01-25  3:27 ` [PATCH v2 01/15] Documentation: add newcx initramfs format description Taras Kondratiuk
                   ` (14 more replies)
  0 siblings, 15 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25  3:27 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

Many of the Linux security/integrity features are dependent on file
metadata, stored as extended attributes (xattrs), for making decisions.
These features need to be initialized during initcall and enabled as
early as possible for complete security coverage. 

Initramfs (tmpfs) supports xattrs, but newc CPIO archive format does not
support including them into the archive.

There are several ways to include xattrs for initramfs:

- Add TAR support. Complicated format and big headers looks like too
  much overhead.

- Include a file manifest containing the xattrs in the CPIO. Should be
  easy for initramfs because we can set xattrs at the end when all files
  are extracted, but extracting such archive in userspace will be more
  complicated. For example it may be necessary to set SELinux labels for
  directories before extracting files into them, so manifest has to be
  extracted first and then searched during each file extraction.

- Extend CPIO header to support xattrs. This seem to be the most
  straight forward way. It also allows to do other useful changes
  to CPIO format at the same time. E.g. increase filesize field to
  support files >4GB.

This patch set extends the existing newc CPIO archive format to include
xattrs in the initramfs.

The series is based on v4.15-rc8. cpio_xattr branch is available here:
https://github.com/kontar/linux/commits/cpio_xattr

=== Patch summary ===

Documentation:
[PATCH 01/15] Documentation: add newcx initramfs format description

Refactoring to simplify adding the new format:
[PATCH 02/15] initramfs: replace states with function pointers
[PATCH 03/15] initramfs: store file name in name_buf
[PATCH 04/15] initramfs: remove unnecessary symlinks processing shortcut
[PATCH 05/15] initramfs: move files creation into separate state
[PATCH 06/15] initramfs: separate reading cpio method from header
[PATCH 07/15] initramfs: split header layout information from parsing
function

Parse newxc format:
[PATCH 08/15] initramfs: add newcx format
[PATCH 09/15] initramfs: set extended attributes

Generate newcx cpio archive:
[PATCH 10/15] gen_init_cpio: move header formatting into function
[PATCH 11/15] gen_init_cpio: add newcx format
[PATCH 12/15] gen_init_cpio: set extended attributes for newcx
[PATCH 13/15] gen_initramfs_list.sh: add -x option to enable newcx

SELinux patches used for testing. They will be sent to SELinux
maintainers separately.
[PATCH 14/15] selinux: allow setxattr on rootfs so initramfs code can
set them
[PATCH 15/15] selinux: delay sid population for rootfs till init is
complete

=== Testing ===

gen_initramfs_list.sh can be used to generate newcx CPIO archive: if
CONFIG_INITRAMFS_NEWCX is enabled CONFIG_INITRAMFS_SOURCE will be packed
into newcx archive. It is enough for basic testing, but it is not
convenient for more complex setup.

Victor have prepared a test setup with SELinux-labeled initramfs based
on Poky(Yocto) with meta-selinux layer.

Repo manifest and build instructions:
https://github.com/victorkamensky/initramfs-xattrs-manifest

Reference cpio utility patch to support newcx format could be
found as part of poky/meta-selinux testing environment at

https://raw.githubusercontent.com/victorkamensky/initramfs-xattrs-poky/rocko/meta/recipes-extended/cpio/cpio-2.12/cpio-xattrs.patch

=== History ===

The patch set is based on Mimi's series from Jan 2015:
https://www.mail-archive.com/initramfs@vger.kernel.org/msg03971.html
Latest discussion I was able to find is from Dec 2015:
https://www.mail-archive.com/initramfs@vger.kernel.org/msg04198.html

Format changes:
- increased size of filesize to 64 bits to support files >4GB.
- increased mtime field size to 64 bits to get usec precision
  and more than 32 bits of seconds. Rob mentioned nsec, but that
  will leave only 34 bits for seconds. If nsec precision is needed
  then we can add a separate 32 bit nsec field (it will match statx).
- Checksum field is replased by xattrs_size field.

Other fields are left unchanged. See patch format description in the
patch #1.

James suggested to add many other changes, but that will bloat header
and make this new format very similar to tar. To keep format simple no
other fields were added.

v2 changes:
- added documentation
- made format more consistent. In previous version a sequence of fields
  in newcx header was different for symlinks and regular files (for
  symlinks data field was before xattrs). It was caused by a flow
  shortcut during symlink entry parsing.
- removed unused checksum field in newcx header
- removed redundant xattrcount at the beginning of xattr section
  (xattrs_size is enough to determine the end of section).
- size of xattr entry in xattr section includes both name and value.
  This makes format more consistent and allows to jump over an entry
  without scanning for the end of name string first.
- streamlined the state machine to address the previous issue and make
  it easier to add the new format
- made header parsing data-driven to remove magic numbers and make it
  easier to add the new format
- eliminated unnecessary buffer allocation for every file name
- pass xattrs to gen_init_cpio via cpio_list file instead of reading
  them from files during packaging. This allows to set xattrs in CPIO
  even if they can't be set on a build machine.
- incorporated several bug fixes from Victor Kamensky for v1 series

Mimi Zohar (3):
  initramfs: separate reading cpio method from header
  initramfs: set extended attributes
  gen_initramfs_list.sh: add -x option to enable newcx format

Taras Kondratiuk (10):
  Documentation: add newcx initramfs format description
  initramfs: replace states with function pointers
  initramfs: store file name in name_buf
  initramfs: remove unnecessary symlinks processing shortcut
  initramfs: move files creation into separate state
  initramfs: split header layout information from parsing function
  initramfs: add newcx format
  gen_init_cpio: move header formatting into function
  gen_init_cpio: add newcx format
  gen_init_cpio: set extended attributes for newcx format

Victor Kamensky (2):
  selinux: allow setxattr on rootfs so initramfs code can set them
  selinux: delay sid population for rootfs till init is complete

 Documentation/early-userspace/buffer-format.txt |  46 ++-
 init/initramfs.c                                | 401 ++++++++++++++++++------
 scripts/gen_initramfs_list.sh                   |  13 +-
 security/selinux/hooks.c                        |  19 ++
 security/selinux/include/security.h             |   1 +
 usr/Kconfig                                     |  11 +
 usr/Makefile                                    |   3 +-
 usr/gen_init_cpio.c                             | 364 ++++++++++++++-------
 8 files changed, 626 insertions(+), 232 deletions(-)

-- 
2.10.3.dirty

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH v2 01/15] Documentation: add newcx initramfs format description
  2018-01-25  3:27 [PATCH v2 00/15] extend initramfs archive format to support xattrs Taras Kondratiuk
@ 2018-01-25  3:27 ` Taras Kondratiuk
  2018-01-25  9:29   ` Arnd Bergmann
  2018-01-26  2:40   ` Rob Landley
  2018-01-25  3:27 ` [PATCH v2 02/15] initramfs: replace states with function pointers Taras Kondratiuk
                   ` (13 subsequent siblings)
  14 siblings, 2 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25  3:27 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

Many of the Linux security/integrity features are dependent on file
metadata, stored as extended attributes (xattrs), for making decisions.
These features need to be initialized during initcall and enabled as
early as possible for complete security coverage.

Initramfs (tmpfs) supports xattrs, but newc CPIO archive format does not
support including them into the archive.

This patch describes "extended" newc format (newcx) that is based on
newc and has following changes:
- extended attributes support
- increased size of filesize to support files >4GB.
- increased mtime field size to have usec precision and more than
  32-bit of seconds.
- removed unused checksum field.

Signed-off-by: Taras Kondratiuk <takondra@cisco.com>
Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Signed-off-by: Victor Kamensky <kamensky@cisco.com>
---
 Documentation/early-userspace/buffer-format.txt | 46 ++++++++++++++++++++++---
 1 file changed, 41 insertions(+), 5 deletions(-)

diff --git a/Documentation/early-userspace/buffer-format.txt b/Documentation/early-userspace/buffer-format.txt
index e1fd7f9dad16..d818df4f72dc 100644
--- a/Documentation/early-userspace/buffer-format.txt
+++ b/Documentation/early-userspace/buffer-format.txt
@@ -24,6 +24,7 @@ grammar, where:
 	+	indicates concatenation
 	GZIP()	indicates the gzip(1) of the operand
 	ALGN(n)	means padding with null bytes to an n-byte boundary
+	[n]	means size of field is n bytes
 
 	initramfs  := ("\0" | cpio_archive | cpio_gzip_archive)*
 
@@ -31,20 +32,29 @@ grammar, where:
 
 	cpio_archive := cpio_file* + (<nothing> | cpio_trailer)
 
-	cpio_file := ALGN(4) + cpio_header + filename + "\0" + ALGN(4) + data
+	cpio_file := (cpio_newc_file | cpio_newcx_file)
+
+	cpio_newc_file := ALGN(4) + cpio_newc_header + filename + "\0" + \
+			  ALGN(4) + data
+
+	cpio_newcx_file := ALGN(4) + cpio_newcx_header + filename + "\0" + \
+			   ALGN(4) + xattrs + ALGN(4) + data
+
+	xattrs := xattr_entry*
+
+	xattr_entry := xattr_size[8] + xattr_name + "\0" + xattr_value
 
 	cpio_trailer := ALGN(4) + cpio_header + "TRAILER!!!\0" + ALGN(4)
 
 
 In human terms, the initramfs buffer contains a collection of
-compressed and/or uncompressed cpio archives (in the "newc" or "crc"
-formats); arbitrary amounts zero bytes (for padding) can be added
-between members.
+compressed and/or uncompressed cpio archives; arbitrary amounts
+zero bytes (for padding) can be added between members.
 
 The cpio "TRAILER!!!" entry (cpio end-of-archive) is optional, but is
 not ignored; see "handling of hard links" below.
 
-The structure of the cpio_header is as follows (all fields contain
+The structure of the cpio_newc_header is as follows (all fields contain
 hexadecimal ASCII numbers fully padded with '0' on the left to the
 full width of the field, for example, the integer 4780 is represented
 by the ASCII string "000012ac"):
@@ -81,6 +91,32 @@ algorithm used.
 If the filename is "TRAILER!!!" this is actually an end-of-archive
 marker; the c_filesize for an end-of-archive marker must be zero.
 
+"Extended" newc format (newcx)
+"newcx" cpio format extends "newc" by increasing size of some fields
+and adding extended attributes support. cpio_newcx_header structure:
+
+Field name    Field size	 Meaning
+c_magic	       6 bytes		 The string "070703"
+c_ino	       8 bytes		 File inode number
+c_mode	       8 bytes		 File mode and permissions
+c_uid	       8 bytes		 File uid
+c_gid	       8 bytes		 File gid
+c_nlink	       8 bytes		 Number of links
+c_mtime	      16 bytes		 Modification time (microseconds)
+c_filesize    16 bytes		 Size of data field
+c_maj	       8 bytes		 Major part of file device number
+c_min	       8 bytes		 Minor part of file device number
+c_rmaj	       8 bytes		 Major part of device node reference
+c_rmin	       8 bytes		 Minor part of device node reference
+c_namesize     8 bytes		 Length of filename, including final \0
+c_xattrs_size  8 bytes		 Size of xattrs field
+
+Most of the fields match cpio_newc_header except c_mtime that contains
+microseconds. c_chksum field is dropped.
+
+xattr_size is a total size of xattr_entry including 8 bytes of
+xattr_size. xattr_size has the same hexadecimal ASCII encoding as other
+fields of cpio header.
 
 *** Handling of hard links
 
-- 
2.10.3.dirty

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v2 02/15] initramfs: replace states with function pointers
  2018-01-25  3:27 [PATCH v2 00/15] extend initramfs archive format to support xattrs Taras Kondratiuk
  2018-01-25  3:27 ` [PATCH v2 01/15] Documentation: add newcx initramfs format description Taras Kondratiuk
@ 2018-01-25  3:27 ` Taras Kondratiuk
  2018-01-25  3:27 ` [PATCH v2 03/15] initramfs: store file name in name_buf Taras Kondratiuk
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25  3:27 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

Currently the FSM states are mapped directly to function pointers. Extra
level of intirection is not needed and makes navigation over the code
harder. One can't jump between states directly when browsing code (e.g.
with cscope). Need to go through actions[] array each time.

Replace states with their action function pointers. No behaviour change.

Signed-off-by: Taras Kondratiuk <takondra@cisco.com>
---
 init/initramfs.c | 73 +++++++++++++++++++++++++-------------------------------
 1 file changed, 32 insertions(+), 41 deletions(-)

diff --git a/init/initramfs.c b/init/initramfs.c
index 7e99a0038942..49cd2681a26f 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -187,16 +187,17 @@ static void __init parse_header(char *s)
 
 /* FSM */
 
-static __initdata enum state {
-	Start,
-	Collect,
-	GotHeader,
-	SkipIt,
-	GotName,
-	CopyFile,
-	GotSymlink,
-	Reset
-} state, next_state;
+static int __init do_start(void);
+static int __init do_collect(void);
+static int __init do_header(void);
+static int __init do_skip(void);
+static int __init do_name(void);
+static int __init do_copy(void);
+static int __init do_symlink(void);
+static int __init do_reset(void);
+
+typedef int (*fsm_state_t)(void);
+static __initdata fsm_state_t state, next_state;
 
 static __initdata char *victim;
 static unsigned long byte_count __initdata;
@@ -214,7 +215,7 @@ static __initdata char *collected;
 static long remains __initdata;
 static __initdata char *collect;
 
-static void __init read_into(char *buf, unsigned size, enum state next)
+static void __init read_into(char *buf, unsigned size, fsm_state_t next)
 {
 	if (byte_count >= size) {
 		collected = victim;
@@ -224,7 +225,7 @@ static void __init read_into(char *buf, unsigned size, enum state next)
 		collect = collected = buf;
 		remains = size;
 		next_state = next;
-		state = Collect;
+		state = do_collect;
 	}
 }
 
@@ -232,7 +233,7 @@ static __initdata char *header_buf, *symlink_buf, *name_buf;
 
 static int __init do_start(void)
 {
-	read_into(header_buf, 110, GotHeader);
+	read_into(header_buf, 110, do_header);
 	return 0;
 }
 
@@ -263,7 +264,7 @@ static int __init do_header(void)
 	parse_header(collected);
 	next_header = this_header + N_ALIGN(name_len) + body_len;
 	next_header = (next_header + 3) & ~3;
-	state = SkipIt;
+	state = do_skip;
 	if (name_len <= 0 || name_len > PATH_MAX)
 		return 0;
 	if (S_ISLNK(mode)) {
@@ -271,12 +272,12 @@ static int __init do_header(void)
 			return 0;
 		collect = collected = symlink_buf;
 		remains = N_ALIGN(name_len) + body_len;
-		next_state = GotSymlink;
-		state = Collect;
+		next_state = do_symlink;
+		state = do_collect;
 		return 0;
 	}
 	if (S_ISREG(mode) || !body_len)
-		read_into(name_buf, N_ALIGN(name_len), GotName);
+		read_into(name_buf, N_ALIGN(name_len), do_name);
 	return 0;
 }
 
@@ -327,8 +328,8 @@ static __initdata int wfd;
 
 static int __init do_name(void)
 {
-	state = SkipIt;
-	next_state = Reset;
+	state = do_skip;
+	next_state = do_reset;
 	if (strcmp(collected, "TRAILER!!!") == 0) {
 		free_hash();
 		return 0;
@@ -348,7 +349,7 @@ static int __init do_name(void)
 				if (body_len)
 					sys_ftruncate(wfd, body_len);
 				vcollected = kstrdup(collected, GFP_KERNEL);
-				state = CopyFile;
+				state = do_copy;
 			}
 		}
 	} else if (S_ISDIR(mode)) {
@@ -377,7 +378,7 @@ static int __init do_copy(void)
 		do_utime(vcollected, mtime);
 		kfree(vcollected);
 		eat(body_len);
-		state = SkipIt;
+		state = do_skip;
 		return 0;
 	} else {
 		if (xwrite(wfd, victim, byte_count) != byte_count)
@@ -395,29 +396,19 @@ static int __init do_symlink(void)
 	sys_symlink(collected + N_ALIGN(name_len), collected);
 	sys_lchown(collected, uid, gid);
 	do_utime(collected, mtime);
-	state = SkipIt;
-	next_state = Reset;
+	state = do_skip;
+	next_state = do_reset;
 	return 0;
 }
 
-static __initdata int (*actions[])(void) = {
-	[Start]		= do_start,
-	[Collect]	= do_collect,
-	[GotHeader]	= do_header,
-	[SkipIt]	= do_skip,
-	[GotName]	= do_name,
-	[CopyFile]	= do_copy,
-	[GotSymlink]	= do_symlink,
-	[Reset]		= do_reset,
-};
-
 static long __init write_buffer(char *buf, unsigned long len)
 {
 	byte_count = len;
 	victim = buf;
 
-	while (!actions[state]())
-		;
+	do
+		pr_debug("state: %pf\n", state);
+	while (!state());
 	return len - byte_count;
 }
 
@@ -433,11 +424,11 @@ static long __init flush_buffer(void *bufv, unsigned long len)
 		if (c == '0') {
 			buf += written;
 			len -= written;
-			state = Start;
+			state = do_start;
 		} else if (c == 0) {
 			buf += written;
 			len -= written;
-			state = Reset;
+			state = do_reset;
 		} else
 			error("junk in compressed archive");
 	}
@@ -462,13 +453,13 @@ static char * __init unpack_to_rootfs(char *buf, unsigned long len)
 	if (!header_buf || !symlink_buf || !name_buf)
 		panic("can't allocate buffers");
 
-	state = Start;
+	state = do_start;
 	this_header = 0;
 	message = NULL;
 	while (!message && len) {
 		loff_t saved_offset = this_header;
 		if (*buf == '0' && !(this_header & 3)) {
-			state = Start;
+			state = do_start;
 			written = write_buffer(buf, len);
 			buf += written;
 			len -= written;
@@ -497,7 +488,7 @@ static char * __init unpack_to_rootfs(char *buf, unsigned long len)
 			}
 		} else
 			error("junk in compressed archive");
-		if (state != Reset)
+		if (state != do_reset)
 			error("junk in compressed archive");
 		this_header = saved_offset + my_inptr;
 		buf += my_inptr;
-- 
2.10.3.dirty

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v2 03/15] initramfs: store file name in name_buf
  2018-01-25  3:27 [PATCH v2 00/15] extend initramfs archive format to support xattrs Taras Kondratiuk
  2018-01-25  3:27 ` [PATCH v2 01/15] Documentation: add newcx initramfs format description Taras Kondratiuk
  2018-01-25  3:27 ` [PATCH v2 02/15] initramfs: replace states with function pointers Taras Kondratiuk
@ 2018-01-25  3:27 ` Taras Kondratiuk
  2018-01-25  3:27 ` [PATCH v2 04/15] initramfs: remove unnecessary symlinks processing shortcut Taras Kondratiuk
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25  3:27 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

There is already name_buf buffer pre-allocated for a file name. No need
to allocate vcollected for every file. More over a name can be already
stored in name_buf by read_info() function.

Add memcpy_optional() function to handle such case.

Signed-off-by: Taras Kondratiuk <takondra@cisco.com>
---
 init/initramfs.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/init/initramfs.c b/init/initramfs.c
index 49cd2681a26f..b6ee675e5cdb 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -210,7 +210,6 @@ static inline void __init eat(unsigned n)
 	byte_count -= n;
 }
 
-static __initdata char *vcollected;
 static __initdata char *collected;
 static long remains __initdata;
 static __initdata char *collect;
@@ -324,6 +323,13 @@ static void __init clean_path(char *path, umode_t fmode)
 	}
 }
 
+static void *memcpy_optional(void *dest, const void *src, size_t n)
+{
+	if (dest != src)
+		return memcpy(dest, src, n);
+	return dest;
+}
+
 static __initdata int wfd;
 
 static int __init do_name(void)
@@ -348,7 +354,8 @@ static int __init do_name(void)
 				sys_fchmod(wfd, mode);
 				if (body_len)
 					sys_ftruncate(wfd, body_len);
-				vcollected = kstrdup(collected, GFP_KERNEL);
+				memcpy_optional(name_buf, collected,
+						N_ALIGN(name_len));
 				state = do_copy;
 			}
 		}
@@ -375,8 +382,7 @@ static int __init do_copy(void)
 		if (xwrite(wfd, victim, body_len) != body_len)
 			error("write error");
 		sys_close(wfd);
-		do_utime(vcollected, mtime);
-		kfree(vcollected);
+		do_utime(name_buf, mtime);
 		eat(body_len);
 		state = do_skip;
 		return 0;
-- 
2.10.3.dirty

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v2 04/15] initramfs: remove unnecessary symlinks processing shortcut
  2018-01-25  3:27 [PATCH v2 00/15] extend initramfs archive format to support xattrs Taras Kondratiuk
                   ` (2 preceding siblings ...)
  2018-01-25  3:27 ` [PATCH v2 03/15] initramfs: store file name in name_buf Taras Kondratiuk
@ 2018-01-25  3:27 ` Taras Kondratiuk
  2018-01-25  3:27 ` [PATCH v2 05/15] initramfs: move files creation into separate state Taras Kondratiuk
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25  3:27 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

Special handling of symlinks in do_header() assumes that name and body
entries are sequential and reads them together. This shortcut has no
real performance benefits, but it complicates changes to the state
machine.

Make handling of symlinks more similar to a regular files. Store name
in name_buf and destination in symlink_buf.

Signed-off-by: Taras Kondratiuk <takondra@cisco.com>
---
 init/initramfs.c | 29 +++++++++++++----------------
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/init/initramfs.c b/init/initramfs.c
index b6ee675e5cdb..d0ab7ad6ac05 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -266,16 +266,7 @@ static int __init do_header(void)
 	state = do_skip;
 	if (name_len <= 0 || name_len > PATH_MAX)
 		return 0;
-	if (S_ISLNK(mode)) {
-		if (body_len > PATH_MAX)
-			return 0;
-		collect = collected = symlink_buf;
-		remains = N_ALIGN(name_len) + body_len;
-		next_state = do_symlink;
-		state = do_collect;
-		return 0;
-	}
-	if (S_ISREG(mode) || !body_len)
+	if (S_ISREG(mode) || S_ISLNK(mode) || !body_len)
 		read_into(name_buf, N_ALIGN(name_len), do_name);
 	return 0;
 }
@@ -372,6 +363,11 @@ static int __init do_name(void)
 			sys_chmod(collected, mode);
 			do_utime(collected, mtime);
 		}
+	} else if (S_ISLNK(mode)) {
+		if (body_len > PATH_MAX)
+			return 0;
+		memcpy_optional(name_buf, collected, N_ALIGN(name_len));
+		read_into(symlink_buf, body_len, do_symlink);
 	}
 	return 0;
 }
@@ -397,11 +393,12 @@ static int __init do_copy(void)
 
 static int __init do_symlink(void)
 {
-	collected[N_ALIGN(name_len) + body_len] = '\0';
-	clean_path(collected, 0);
-	sys_symlink(collected + N_ALIGN(name_len), collected);
-	sys_lchown(collected, uid, gid);
-	do_utime(collected, mtime);
+	memcpy_optional(symlink_buf, collected, body_len);
+	symlink_buf[body_len] = '\0';
+	clean_path(name_buf, 0);
+	sys_symlink(symlink_buf, name_buf);
+	sys_lchown(name_buf, uid, gid);
+	do_utime(name_buf, mtime);
 	state = do_skip;
 	next_state = do_reset;
 	return 0;
@@ -453,7 +450,7 @@ static char * __init unpack_to_rootfs(char *buf, unsigned long len)
 	static __initdata char msg_buf[64];
 
 	header_buf = kmalloc(110, GFP_KERNEL);
-	symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL);
+	symlink_buf = kmalloc(PATH_MAX + 1, GFP_KERNEL);
 	name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL);
 
 	if (!header_buf || !symlink_buf || !name_buf)
-- 
2.10.3.dirty

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v2 05/15] initramfs: move files creation into separate state
  2018-01-25  3:27 [PATCH v2 00/15] extend initramfs archive format to support xattrs Taras Kondratiuk
                   ` (3 preceding siblings ...)
  2018-01-25  3:27 ` [PATCH v2 04/15] initramfs: remove unnecessary symlinks processing shortcut Taras Kondratiuk
@ 2018-01-25  3:27 ` Taras Kondratiuk
  2018-01-25  3:27 ` [PATCH v2 06/15] initramfs: separate reading cpio method from header Taras Kondratiuk
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25  3:27 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

Move most of the file creation logic into a separate state. This splits
collection of data stage from data processing and makes it easier to add
additional states for a new archive format.

Signed-off-by: Taras Kondratiuk <takondra@cisco.com>
---
 init/initramfs.c | 52 ++++++++++++++++++++++++++++++----------------------
 1 file changed, 30 insertions(+), 22 deletions(-)

diff --git a/init/initramfs.c b/init/initramfs.c
index d0ab7ad6ac05..2d5920c094e0 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -192,6 +192,7 @@ static int __init do_collect(void);
 static int __init do_header(void);
 static int __init do_skip(void);
 static int __init do_name(void);
+static int __init do_create(void);
 static int __init do_copy(void);
 static int __init do_symlink(void);
 static int __init do_reset(void);
@@ -292,12 +293,12 @@ static int __init do_reset(void)
 	return 1;
 }
 
-static int __init maybe_link(void)
+static int __init maybe_link(char *name)
 {
 	if (nlink >= 2) {
-		char *old = find_link(major, minor, ino, mode, collected);
+		char *old = find_link(major, minor, ino, mode, name);
 		if (old)
-			return (sys_link(old, collected) < 0) ? -1 : 1;
+			return (sys_link(old, name) < 0) ? -1 : 1;
 	}
 	return 0;
 }
@@ -321,52 +322,59 @@ static void *memcpy_optional(void *dest, const void *src, size_t n)
 	return dest;
 }
 
-static __initdata int wfd;
-
 static int __init do_name(void)
 {
-	state = do_skip;
-	next_state = do_reset;
 	if (strcmp(collected, "TRAILER!!!") == 0) {
+		state = do_skip;
+		next_state = do_reset;
 		free_hash();
 		return 0;
 	}
-	clean_path(collected, mode);
+	memcpy_optional(name_buf, collected, N_ALIGN(name_len));
+	state = do_create;
+	return 0;
+}
+
+
+static __initdata int wfd;
+
+static int __init do_create(void)
+{
+	state = do_skip;
+	next_state = do_reset;
+	clean_path(name_buf, mode);
 	if (S_ISREG(mode)) {
-		int ml = maybe_link();
+		int ml = maybe_link(name_buf);
 		if (ml >= 0) {
 			int openflags = O_WRONLY|O_CREAT;
 			if (ml != 1)
 				openflags |= O_TRUNC;
-			wfd = sys_open(collected, openflags, mode);
+			wfd = sys_open(name_buf, openflags, mode);
 
 			if (wfd >= 0) {
 				sys_fchown(wfd, uid, gid);
 				sys_fchmod(wfd, mode);
 				if (body_len)
 					sys_ftruncate(wfd, body_len);
-				memcpy_optional(name_buf, collected,
-						N_ALIGN(name_len));
 				state = do_copy;
 			}
 		}
 	} else if (S_ISDIR(mode)) {
-		sys_mkdir(collected, mode);
-		sys_chown(collected, uid, gid);
-		sys_chmod(collected, mode);
-		dir_add(collected, mtime);
+		sys_mkdir(name_buf, mode);
+		sys_chown(name_buf, uid, gid);
+		sys_chmod(name_buf, mode);
+		dir_add(name_buf, mtime);
 	} else if (S_ISBLK(mode) || S_ISCHR(mode) ||
 		   S_ISFIFO(mode) || S_ISSOCK(mode)) {
-		if (maybe_link() == 0) {
-			sys_mknod(collected, mode, rdev);
-			sys_chown(collected, uid, gid);
-			sys_chmod(collected, mode);
-			do_utime(collected, mtime);
+		if (maybe_link(name_buf) == 0) {
+			sys_mknod(name_buf, mode, rdev);
+			sys_chown(name_buf, uid, gid);
+			sys_chmod(name_buf, mode);
+			do_utime(name_buf, mtime);
 		}
 	} else if (S_ISLNK(mode)) {
 		if (body_len > PATH_MAX)
 			return 0;
-		memcpy_optional(name_buf, collected, N_ALIGN(name_len));
 		read_into(symlink_buf, body_len, do_symlink);
 	}
 	return 0;
-- 
2.10.3.dirty

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v2 06/15] initramfs: separate reading cpio method from header
  2018-01-25  3:27 [PATCH v2 00/15] extend initramfs archive format to support xattrs Taras Kondratiuk
                   ` (4 preceding siblings ...)
  2018-01-25  3:27 ` [PATCH v2 05/15] initramfs: move files creation into separate state Taras Kondratiuk
@ 2018-01-25  3:27 ` Taras Kondratiuk
  2018-01-25  3:27 ` [PATCH v2 07/15] initramfs: split header layout information from parsing function Taras Kondratiuk
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25  3:27 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

From: Mimi Zohar <zohar@linux.vnet.ibm.com>

In preparation for adding xattr support, read the CPIO method
separately from the rest of the header.

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Signed-off-by: Taras Kondratiuk <takondra@cisco.com>
---
 init/initramfs.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/init/initramfs.c b/init/initramfs.c
index 2d5920c094e0..b3d39c8793be 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -168,7 +168,7 @@ static void __init parse_header(char *s)
 	int i;
 
 	buf[8] = '\0';
-	for (i = 0, s += 6; i < 12; i++, s += 8) {
+	for (i = 0; i < 12; i++, s += 8) {
 		memcpy(buf, s, 8);
 		parsed[i] = simple_strtoul(buf, NULL, 16);
 	}
@@ -189,6 +189,7 @@ static void __init parse_header(char *s)
 
 static int __init do_start(void);
 static int __init do_collect(void);
+static int __init do_format(void);
 static int __init do_header(void);
 static int __init do_skip(void);
 static int __init do_name(void);
@@ -233,7 +234,7 @@ static __initdata char *header_buf, *symlink_buf, *name_buf;
 
 static int __init do_start(void)
 {
-	read_into(header_buf, 110, do_header);
+	read_into(header_buf, 6, do_format);
 	return 0;
 }
 
@@ -251,7 +252,7 @@ static int __init do_collect(void)
 	return 0;
 }
 
-static int __init do_header(void)
+static int __init do_format(void)
 {
 	if (memcmp(collected, "070707", 6)==0) {
 		error("incorrect cpio method used: use -H newc option");
@@ -261,6 +262,12 @@ static int __init do_header(void)
 		error("no cpio magic");
 		return 1;
 	}
+	read_into(header_buf, 104, 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 = (next_header + 3) & ~3;
@@ -457,7 +464,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(110, GFP_KERNEL);
+	header_buf = kmalloc(104, GFP_KERNEL);
 	symlink_buf = kmalloc(PATH_MAX + 1, GFP_KERNEL);
 	name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL);
 
-- 
2.10.3.dirty

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v2 07/15] initramfs: split header layout information from parsing function
  2018-01-25  3:27 [PATCH v2 00/15] extend initramfs archive format to support xattrs Taras Kondratiuk
                   ` (5 preceding siblings ...)
  2018-01-25  3:27 ` [PATCH v2 06/15] initramfs: separate reading cpio method from header Taras Kondratiuk
@ 2018-01-25  3:27 ` Taras Kondratiuk
  2018-01-25  3:27 ` [PATCH v2 08/15] initramfs: add newcx format Taras Kondratiuk
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25  3:27 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

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 <takondra@cisco.com>
---
 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

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v2 08/15] initramfs: add newcx format
  2018-01-25  3:27 [PATCH v2 00/15] extend initramfs archive format to support xattrs Taras Kondratiuk
                   ` (6 preceding siblings ...)
  2018-01-25  3:27 ` [PATCH v2 07/15] initramfs: split header layout information from parsing function Taras Kondratiuk
@ 2018-01-25  3:27 ` Taras Kondratiuk
  2018-01-25  3:27 ` [PATCH v2 09/15] initramfs: set extended attributes Taras Kondratiuk
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25  3:27 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

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 <takondra@cisco.com>
---
 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

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v2 09/15] initramfs: set extended attributes
  2018-01-25  3:27 [PATCH v2 00/15] extend initramfs archive format to support xattrs Taras Kondratiuk
                   ` (7 preceding siblings ...)
  2018-01-25  3:27 ` [PATCH v2 08/15] initramfs: add newcx format Taras Kondratiuk
@ 2018-01-25  3:27 ` Taras Kondratiuk
  2018-01-25  3:27 ` [PATCH v2 10/15] gen_init_cpio: move header formatting into function Taras Kondratiuk
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25  3:27 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

From: Mimi Zohar <zohar@linux.vnet.ibm.com>

This patch writes out the extended attributes included in the cpio file.
As the "security.ima" xattr needs to be written after the file data.
this patch separates extracting and setting the xattrs by defining new
do_setxattrs state.

[kamensky: fixed restoring of xattrs for symbolic links by using
           sys_lsetxattr() instead of sys_setxattr()]

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Signed-off-by: Victor Kamensky <kamensky@cisco.com>
Signed-off-by: Taras Kondratiuk <takondra@cisco.com>
---
 init/initramfs.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 52 insertions(+), 5 deletions(-)

diff --git a/init/initramfs.c b/init/initramfs.c
index 3d0f46c28459..040e26cf451a 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -310,6 +310,7 @@ static int __init do_xattrs(void);
 static int __init do_create(void);
 static int __init do_copy(void);
 static int __init do_symlink(void);
+static int __init do_setxattrs(void);
 static int __init do_reset(void);
 
 typedef int (*fsm_state_t)(void);
@@ -472,7 +473,7 @@ static int __init do_name(void)
 
 static int __init do_xattrs(void)
 {
-	/* Do nothing for now */
+	memcpy_optional(xattr_buf, collected, xattr_len);
 	state = do_create;
 	return 0;
 }
@@ -481,8 +482,7 @@ static __initdata int wfd;
 
 static int __init do_create(void)
 {
-	state = do_skip;
-	next_state = do_reset;
+	state = do_setxattrs;
 	clean_path(name_buf, mode);
 	if (S_ISREG(mode)) {
 		int ml = maybe_link(name_buf);
@@ -515,8 +515,11 @@ static int __init do_create(void)
 			do_utime(name_buf, mtime);
 		}
 	} else if (S_ISLNK(mode)) {
-		if (body_len > PATH_MAX)
+		if (body_len > PATH_MAX) {
+			state = do_skip;
+			next_state = do_reset;
 			return 0;
+		}
 		read_into(symlink_buf, body_len, do_symlink);
 	}
 	return 0;
@@ -530,7 +533,7 @@ static int __init do_copy(void)
 		sys_close(wfd);
 		do_utime(name_buf, mtime);
 		eat(body_len);
-		state = do_skip;
+		state = do_setxattrs;
 		return 0;
 	} else {
 		if (xwrite(wfd, victim, byte_count) != byte_count)
@@ -549,8 +552,52 @@ static int __init do_symlink(void)
 	sys_symlink(symlink_buf, name_buf);
 	sys_lchown(name_buf, uid, gid);
 	do_utime(name_buf, mtime);
+	state = do_setxattrs;
+	return 0;
+}
+
+struct xattr_hdr {
+	char c_size[8]; /* total size including c_size field */
+	char c_data[];  /* <name>\0<value> */
+};
+
+static int __init do_setxattrs(void)
+{
+	char *buf = xattr_buf;
+	char *bufend = buf + xattr_len;
+	struct xattr_hdr *hdr;
+	char str[sizeof(hdr->c_size) + 1];
+
 	state = do_skip;
 	next_state = do_reset;
+	if (!xattr_len)
+		return 0;
+
+	str[sizeof(hdr->c_size)] = 0;
+
+	while (buf < bufend) {
+		char *xattr_name, *xattr_value;
+		unsigned long xattr_entry_size, xattr_value_size;
+		int ret;
+
+		hdr = (struct xattr_hdr *)buf;
+		memcpy(str, hdr->c_size, sizeof(hdr->c_size));
+		ret = kstrtoul(str, 16, &xattr_entry_size);
+		buf += xattr_entry_size;
+		if (ret || buf > bufend) {
+			error("malformed xattrs");
+			break;
+		}
+
+		xattr_name = hdr->c_data;
+		xattr_value = xattr_name + strlen(xattr_name) + 1;
+		xattr_value_size = buf - xattr_value;
+
+		ret = sys_lsetxattr(name_buf, xattr_name, xattr_value,
+				xattr_value_size, 0);
+		pr_debug("%s: %s size: %lu val: %s (ret: %d)\n", name_buf,
+				xattr_name, xattr_value_size, xattr_value, ret);
+	}
 	return 0;
 }
 
-- 
2.10.3.dirty

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v2 10/15] gen_init_cpio: move header formatting into function
  2018-01-25  3:27 [PATCH v2 00/15] extend initramfs archive format to support xattrs Taras Kondratiuk
                   ` (8 preceding siblings ...)
  2018-01-25  3:27 ` [PATCH v2 09/15] initramfs: set extended attributes Taras Kondratiuk
@ 2018-01-25  3:27 ` Taras Kondratiuk
  2018-01-25  3:27 ` [PATCH v2 11/15] gen_init_cpio: add newcx format Taras Kondratiuk
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25  3:27 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

CPIO header is generated in multiple places with the same sprintf()
format string. Move formatting into a single function in preparation
to adding a new cpio format.

Signed-off-by: Taras Kondratiuk <takondra@cisco.com>
---
 usr/gen_init_cpio.c | 186 ++++++++++++++++++++++++++--------------------------
 1 file changed, 92 insertions(+), 94 deletions(-)

diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c
index 03b21189d58b..7a2a6d85345d 100644
--- a/usr/gen_init_cpio.c
+++ b/usr/gen_init_cpio.c
@@ -64,34 +64,55 @@ static void push_rest(const char *name)
 	}
 }
 
-static void push_hdr(const char *s)
+struct cpio_header {
+	unsigned int ino;
+	unsigned int mode;
+	uid_t uid;
+	gid_t gid;
+	unsigned int nlink;
+	time_t mtime;
+	size_t filesize;
+	int devmajor;
+	int devminor;
+	int rdevmajor;
+	int rdevminor;
+	size_t namesize;
+	unsigned int check;
+};
+
+static void push_hdr(const struct cpio_header *hdr)
 {
+	char s[256];
+
+	sprintf(s, "%s%08X%08X%08lX%08lX%08X%08lX"
+		   "%08X%08X%08X%08X%08X%08X%08X",
+		"070701",
+		hdr->ino,
+		hdr->mode,
+		(long)hdr->uid,
+		(long)hdr->gid,
+		hdr->nlink,
+		(long)hdr->mtime,
+		(unsigned int)hdr->filesize,
+		hdr->devmajor,
+		hdr->devminor,
+		hdr->rdevmajor,
+		hdr->rdevminor,
+		(unsigned int)hdr->namesize,
+		hdr->check);
 	fputs(s, stdout);
 	offset += 110;
 }
 
 static void cpio_trailer(void)
 {
-	char s[256];
 	const char name[] = "TRAILER!!!";
+	struct cpio_header hdr = {
+		.nlink = 1,
+		.namesize = strlen(name)+1,
+	};
 
-	sprintf(s, "%s%08X%08X%08lX%08lX%08X%08lX"
-	       "%08X%08X%08X%08X%08X%08X%08X",
-		"070701",		/* magic */
-		0,			/* ino */
-		0,			/* mode */
-		(long) 0,		/* uid */
-		(long) 0,		/* gid */
-		1,			/* nlink */
-		(long) 0,		/* mtime */
-		0,			/* filesize */
-		0,			/* major */
-		0,			/* minor */
-		0,			/* rmajor */
-		0,			/* rminor */
-		(unsigned)strlen(name)+1, /* namesize */
-		0);			/* chksum */
-	push_hdr(s);
+	push_hdr(&hdr);
 	push_rest(name);
 
 	while (offset % 512) {
@@ -103,27 +124,21 @@ static void cpio_trailer(void)
 static int cpio_mkslink(const char *name, const char *target,
 			 unsigned int mode, uid_t uid, gid_t gid)
 {
-	char s[256];
-
 	if (name[0] == '/')
 		name++;
-	sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
-	       "%08X%08X%08X%08X%08X%08X%08X",
-		"070701",		/* magic */
-		ino++,			/* ino */
-		S_IFLNK | mode,		/* mode */
-		(long) uid,		/* uid */
-		(long) gid,		/* gid */
-		1,			/* nlink */
-		(long) default_mtime,	/* mtime */
-		(unsigned)strlen(target)+1, /* filesize */
-		3,			/* major */
-		1,			/* minor */
-		0,			/* rmajor */
-		0,			/* rminor */
-		(unsigned)strlen(name) + 1,/* namesize */
-		0);			/* chksum */
-	push_hdr(s);
+	struct cpio_header hdr = {
+		.ino = ino++,
+		.mode = S_IFLNK | mode,
+		.uid = uid,
+		.gid = gid,
+		.nlink = 1,
+		.mtime = default_mtime,
+		.filesize = strlen(target)+1,
+		.devmajor = 3,
+		.devminor = 1,
+		.namesize = strlen(name)+1,
+	};
+	push_hdr(&hdr);
 	push_string(name);
 	push_pad();
 	push_string(target);
@@ -152,27 +167,20 @@ static int cpio_mkslink_line(const char *line)
 static int cpio_mkgeneric(const char *name, unsigned int mode,
 		       uid_t uid, gid_t gid)
 {
-	char s[256];
-
 	if (name[0] == '/')
 		name++;
-	sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
-	       "%08X%08X%08X%08X%08X%08X%08X",
-		"070701",		/* magic */
-		ino++,			/* ino */
-		mode,			/* mode */
-		(long) uid,		/* uid */
-		(long) gid,		/* gid */
-		2,			/* nlink */
-		(long) default_mtime,	/* mtime */
-		0,			/* filesize */
-		3,			/* major */
-		1,			/* minor */
-		0,			/* rmajor */
-		0,			/* rminor */
-		(unsigned)strlen(name) + 1,/* namesize */
-		0);			/* chksum */
-	push_hdr(s);
+	struct cpio_header hdr = {
+		.ino = ino++,
+		.mode = mode,
+		.uid = uid,
+		.gid = gid,
+		.nlink = 2,
+		.mtime = default_mtime,
+		.devmajor = 3,
+		.devminor = 1,
+		.namesize = strlen(name)+1,
+	};
+	push_hdr(&hdr);
 	push_rest(name);
 	return 0;
 }
@@ -241,8 +249,6 @@ static int cpio_mknod(const char *name, unsigned int mode,
 		       uid_t uid, gid_t gid, char dev_type,
 		       unsigned int maj, unsigned int min)
 {
-	char s[256];
-
 	if (dev_type == 'b')
 		mode |= S_IFBLK;
 	else
@@ -250,23 +256,20 @@ static int cpio_mknod(const char *name, unsigned int mode,
 
 	if (name[0] == '/')
 		name++;
-	sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
-	       "%08X%08X%08X%08X%08X%08X%08X",
-		"070701",		/* magic */
-		ino++,			/* ino */
-		mode,			/* mode */
-		(long) uid,		/* uid */
-		(long) gid,		/* gid */
-		1,			/* nlink */
-		(long) default_mtime,	/* mtime */
-		0,			/* filesize */
-		3,			/* major */
-		1,			/* minor */
-		maj,			/* rmajor */
-		min,			/* rminor */
-		(unsigned)strlen(name) + 1,/* namesize */
-		0);			/* chksum */
-	push_hdr(s);
+	struct cpio_header hdr = {
+		.ino = ino++,
+		.mode = mode,
+		.uid = uid,
+		.gid = gid,
+		.nlink = 1,
+		.mtime = default_mtime,
+		.devmajor = 3,
+		.devminor = 1,
+		.rdevmajor = maj,
+		.rdevminor = min,
+		.namesize = strlen(name)+1,
+	};
+	push_hdr(&hdr);
 	push_rest(name);
 	return 0;
 }
@@ -296,7 +299,6 @@ static int cpio_mkfile(const char *name, const char *location,
 			unsigned int mode, uid_t uid, gid_t gid,
 			unsigned int nlinks)
 {
-	char s[256];
 	char *filebuf = NULL;
 	struct stat buf;
 	long size;
@@ -340,23 +342,19 @@ static int cpio_mkfile(const char *name, const char *location,
 		if (name[0] == '/')
 			name++;
 		namesize = strlen(name) + 1;
-		sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
-		       "%08lX%08X%08X%08X%08X%08X%08X",
-			"070701",		/* magic */
-			ino,			/* ino */
-			mode,			/* mode */
-			(long) uid,		/* uid */
-			(long) gid,		/* gid */
-			nlinks,			/* nlink */
-			(long) buf.st_mtime,	/* mtime */
-			size,			/* filesize */
-			3,			/* major */
-			1,			/* minor */
-			0,			/* rmajor */
-			0,			/* rminor */
-			namesize,		/* namesize */
-			0);			/* chksum */
-		push_hdr(s);
+		struct cpio_header hdr = {
+			.ino = ino,
+			.mode = mode,
+			.uid = uid,
+			.gid = gid,
+			.nlink = nlinks,
+			.mtime = buf.st_mtime,
+			.filesize = size,
+			.devmajor = 3,
+			.devminor = 1,
+			.namesize = namesize,
+		};
+		push_hdr(&hdr);
 		push_string(name);
 		push_pad();
 
-- 
2.10.3.dirty

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v2 11/15] gen_init_cpio: add newcx format
  2018-01-25  3:27 [PATCH v2 00/15] extend initramfs archive format to support xattrs Taras Kondratiuk
                   ` (9 preceding siblings ...)
  2018-01-25  3:27 ` [PATCH v2 10/15] gen_init_cpio: move header formatting into function Taras Kondratiuk
@ 2018-01-25  3:27 ` Taras Kondratiuk
  2018-01-26  2:40   ` Rob Landley
  2018-01-25  3:27 ` [PATCH v2 12/15] gen_init_cpio: set extended attributes for " Taras Kondratiuk
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25  3:27 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

Add "newcx" format that supports extended attributes and has increased
size of c_mtime and c_filesize fields.

Added -x option to select "newcx" format. Default is "newc".

Refer to Documentation/early-userspace/buffer-format.txt for detailed
format description.

Signed-off-by: Taras Kondratiuk <takondra@cisco.com>
---
 usr/gen_init_cpio.c | 70 +++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 49 insertions(+), 21 deletions(-)

diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c
index 7a2a6d85345d..78a47a5bdcb1 100644
--- a/usr/gen_init_cpio.c
+++ b/usr/gen_init_cpio.c
@@ -10,6 +10,7 @@
 #include <errno.h>
 #include <ctype.h>
 #include <limits.h>
+#include <assert.h>
 
 /*
  * Original work by Jeff Garzik
@@ -21,6 +22,8 @@
 #define xstr(s) #s
 #define str(s) xstr(s)
 
+static int newcx;
+static unsigned int cpio_hdr_size;
 static unsigned int offset;
 static unsigned int ino = 721;
 static time_t default_mtime;
@@ -56,7 +59,7 @@ static void push_rest(const char *name)
 	putchar(0);
 	offset += name_len;
 
-	tmp_ofs = name_len + 110;
+	tmp_ofs = name_len + cpio_hdr_size;
 	while (tmp_ofs & 3) {
 		putchar(0);
 		offset++;
@@ -77,6 +80,7 @@ struct cpio_header {
 	int rdevmajor;
 	int rdevminor;
 	size_t namesize;
+	size_t xattrsize;
 	unsigned int check;
 };
 
@@ -84,24 +88,44 @@ static void push_hdr(const struct cpio_header *hdr)
 {
 	char s[256];
 
-	sprintf(s, "%s%08X%08X%08lX%08lX%08X%08lX"
-		   "%08X%08X%08X%08X%08X%08X%08X",
-		"070701",
-		hdr->ino,
-		hdr->mode,
-		(long)hdr->uid,
-		(long)hdr->gid,
-		hdr->nlink,
-		(long)hdr->mtime,
-		(unsigned int)hdr->filesize,
-		hdr->devmajor,
-		hdr->devminor,
-		hdr->rdevmajor,
-		hdr->rdevminor,
-		(unsigned int)hdr->namesize,
-		hdr->check);
+	if (newcx) {
+		sprintf(s, "%s%08X%08X%08lX%08lX%08X%016llX"
+			   "%016llX%08X%08X%08X%08X%08X%08X",
+			"070703",
+			hdr->ino,
+			hdr->mode,
+			(long)hdr->uid,
+			(long)hdr->gid,
+			hdr->nlink,
+			hdr->mtime * 1000000ULL,
+			(long long)hdr->filesize,
+			hdr->devmajor,
+			hdr->devminor,
+			hdr->rdevmajor,
+			hdr->rdevminor,
+			(unsigned int)hdr->namesize,
+			(unsigned int)hdr->xattrsize);
+	} else {
+		sprintf(s, "%s%08X%08X%08lX%08lX%08X%08lX"
+			   "%08X%08X%08X%08X%08X%08X%08X",
+			"070701",
+			hdr->ino,
+			hdr->mode,
+			(long)hdr->uid,
+			(long)hdr->gid,
+			hdr->nlink,
+			(long)hdr->mtime,
+			(unsigned int)hdr->filesize,
+			hdr->devmajor,
+			hdr->devminor,
+			hdr->rdevmajor,
+			hdr->rdevminor,
+			(unsigned int)hdr->namesize,
+			hdr->check);
+	}
 	fputs(s, stdout);
-	offset += 110;
+	assert((offset & 3) == 0);
+	offset += cpio_hdr_size;
 }
 
 static void cpio_trailer(void)
@@ -301,7 +325,7 @@ static int cpio_mkfile(const char *name, const char *location,
 {
 	char *filebuf = NULL;
 	struct stat buf;
-	long size;
+	size_t size;
 	int file = -1;
 	int retval;
 	int rc = -1;
@@ -450,7 +474,7 @@ static int cpio_mkfile_line(const char *line)
 static void usage(const char *prog)
 {
 	fprintf(stderr, "Usage:\n"
-		"\t%s [-t <timestamp>] <cpio_list>\n"
+		"\t%s [-t <timestamp>] [-x] <cpio_list>\n"
 		"\n"
 		"<cpio_list> is a file containing newline separated entries that\n"
 		"describe the files to be included in the initramfs archive:\n"
@@ -527,7 +551,7 @@ int main (int argc, char *argv[])
 
 	default_mtime = time(NULL);
 	while (1) {
-		int opt = getopt(argc, argv, "t:h");
+		int opt = getopt(argc, argv, "t:h:x");
 		char *invalid;
 
 		if (opt == -1)
@@ -542,12 +566,16 @@ int main (int argc, char *argv[])
 				exit(1);
 			}
 			break;
+		case 'x':
+			newcx = 1;
+			break;
 		case 'h':
 		case '?':
 			usage(argv[0]);
 			exit(opt == 'h' ? 0 : 1);
 		}
 	}
+	cpio_hdr_size = newcx ? 134 : 110;
 
 	if (argc - optind != 1) {
 		usage(argv[0]);
-- 
2.10.3.dirty

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v2 12/15] gen_init_cpio: set extended attributes for newcx format
  2018-01-25  3:27 [PATCH v2 00/15] extend initramfs archive format to support xattrs Taras Kondratiuk
                   ` (10 preceding siblings ...)
  2018-01-25  3:27 ` [PATCH v2 11/15] gen_init_cpio: add newcx format Taras Kondratiuk
@ 2018-01-25  3:27 ` Taras Kondratiuk
  2018-01-25  3:27 ` [PATCH v2 13/15] gen_initramfs_list.sh: add -x option to enable " Taras Kondratiuk
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25  3:27 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

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 <takondra@cisco.com>
---
 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 <errno.h>
 #include <ctype.h>
 #include <limits.h>
+#include <sys/xattr.h>
 #include <assert.h>
 
 /*
@@ -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 <name> <target> <mode> <uid> <gid>\n"
 		"pipe <name> <mode> <uid> <gid>\n"
 		"sock <name> <mode> <uid> <gid>\n"
+		"# xattr line is applied to the next non-xattr entry\n"
+		"xattr <xattr_name>=<xattr_val>\n"
 		"\n"
 		"<name>       name of the file/dir/nod/etc in the archive\n"
 		"<location>   location of the file in the current filesystem\n"
@@ -498,12 +587,16 @@ static void usage(const char *prog)
 		"<maj>        major number of nod\n"
 		"<min>        minor number of nod\n"
 		"<hard links> space separated list of other links to file\n"
+		"<xattr_name> extended attribute name\n"
+		"<xattr_val>  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

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v2 13/15] gen_initramfs_list.sh: add -x option to enable newcx format
  2018-01-25  3:27 [PATCH v2 00/15] extend initramfs archive format to support xattrs Taras Kondratiuk
                   ` (11 preceding siblings ...)
  2018-01-25  3:27 ` [PATCH v2 12/15] gen_init_cpio: set extended attributes for " Taras Kondratiuk
@ 2018-01-25  3:27 ` Taras Kondratiuk
  2018-01-25  3:27 ` [PATCH v2 14/15] selinux: allow setxattr on rootfs so initramfs code can set them Taras Kondratiuk
  2018-01-25  3:27 ` [PATCH v2 15/15] selinux: delay sid population for rootfs till init is complete Taras Kondratiuk
  14 siblings, 0 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25  3:27 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

From: Mimi Zohar <zohar@linux.vnet.ibm.com>

-x option populates extended attributes in cpio_list file passed to
get_init_cpio and selects newcx CPIO format.

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Signed-off-by: Taras Kondratiuk <takondra@cisco.com>
---
 scripts/gen_initramfs_list.sh | 13 ++++++++++++-
 usr/Kconfig                   | 11 +++++++++++
 usr/Makefile                  |  3 ++-
 3 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
index 86a3c0e5cfbc..cddb82f093d9 100755
--- a/scripts/gen_initramfs_list.sh
+++ b/scripts/gen_initramfs_list.sh
@@ -24,6 +24,7 @@ $0 [-o <file>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ...
 	-g <gid>       Group ID to map to group ID 0 (root).
 		       <gid> is only meaningful if <cpio_source> is a
 		       directory.  "squash" forces all files to gid 0.
+	-x             include file extended attributes in cpio archive.
 	<cpio_source>  File list or directory for cpio archive.
 		       If <cpio_source> is a .cpio file it will be used
 		       as direct input to initramfs.
@@ -146,6 +147,9 @@ parse() {
 			;;
 	esac
 
+	$include_xattrs && \
+		getfattr -h -d -m - -e hex --absolute-names ${location} | \
+		sed -e '/^#/d' -e '/^$/d' -e 's/^/xattr /' >> ${output}
 	echo "${str}" >> ${output}
 
 	return 0
@@ -226,6 +230,8 @@ root_gid=0
 dep_list=
 cpio_file=
 cpio_list=
+cpio_opts=
+include_xattrs=false
 output="/dev/stdout"
 output_file=""
 is_cpio_compressed=
@@ -283,6 +289,10 @@ while [ $# -gt 0 ]; do
 			default_list="$arg"
 			${dep_list}default_initramfs
 			;;
+		"-x")   # include extended attributers
+			cpio_opts="-x"
+			include_xattrs=true
+			;;
 		"-h")
 			usage
 			exit 0
@@ -312,7 +322,8 @@ if [ ! -z ${output_file} ]; then
 			fi
 		fi
 		cpio_tfile="$(mktemp ${TMPDIR:-/tmp}/cpiofile.XXXXXX)"
-		usr/gen_init_cpio $timestamp ${cpio_list} > ${cpio_tfile}
+		usr/gen_init_cpio $timestamp ${cpio_opts} ${cpio_list} \
+			> ${cpio_tfile}
 	else
 		cpio_tfile=${cpio_file}
 	fi
diff --git a/usr/Kconfig b/usr/Kconfig
index 43658b8a975e..0cc03bc4614c 100644
--- a/usr/Kconfig
+++ b/usr/Kconfig
@@ -52,6 +52,17 @@ config INITRAMFS_ROOT_GID
 
 	  If you are not sure, leave it set to "0".
 
+config INITRAMFS_NEWCX
+	bool "Use newcx CPIO format for initramfs"
+	depends on INITRAMFS_SOURCE!=""
+	default n
+	help
+	  If selected "usr/gen_init_cpio" will generate newcx CPIO archive
+	  format that supports extended attributes.
+
+	  See <file:Documentation/early-userspace/buffer-format.txt> for
+	  more details.
+
 config RD_GZIP
 	bool "Support initial ramdisk/ramfs compressed using gzip"
 	depends on BLK_DEV_INITRD
diff --git a/usr/Makefile b/usr/Makefile
index 237a028693ce..1106bfd61475 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -29,7 +29,8 @@ ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)), \
 			$(shell echo $(CONFIG_INITRAMFS_SOURCE)),-d)
 ramfs-args  := \
         $(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \
-        $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID))
+        $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) \
+        $(if $(CONFIG_INITRAMFS_NEWCX), -x)
 
 # $(datafile_d_y) is used to identify all files included
 # in initramfs and to detect if any files are added/removed.
-- 
2.10.3.dirty

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v2 14/15] selinux: allow setxattr on rootfs so initramfs code can set them
  2018-01-25  3:27 [PATCH v2 00/15] extend initramfs archive format to support xattrs Taras Kondratiuk
                   ` (12 preceding siblings ...)
  2018-01-25  3:27 ` [PATCH v2 13/15] gen_initramfs_list.sh: add -x option to enable " Taras Kondratiuk
@ 2018-01-25  3:27 ` Taras Kondratiuk
  2018-01-25  3:27 ` [PATCH v2 15/15] selinux: delay sid population for rootfs till init is complete Taras Kondratiuk
  14 siblings, 0 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25  3:27 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

From: Victor Kamensky <kamensky@cisco.com>

initramfs code supporting extended cpio format have ability to
fill extended attributes from cpio archive, but if SELinux enabled
and security server is not initialized yet, selinux callback would
refuse setxattr made by initramfs code.

Solution enable SBLABEL_MNT on rootfs even if secrurity server is
not initialized yet.

Signed-off-by: Victor Kamensky <kamensky@cisco.com>
---
 security/selinux/hooks.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8644d864e3c1..f3fe65589f02 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -706,6 +706,18 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 
 	if (!ss_initialized) {
 		if (!num_opts) {
+			/*
+			 * Special handling for rootfs. Is genfs but supports
+			 * setting SELinux context on in-core inodes.
+			 *
+			 * Chicken and egg problem: policy may reside in rootfs
+			 * but for initramfs code to fill in attributes, it
+			 * needs selinux to allow that.
+			 */
+			if (!strncmp(sb->s_type->name, "rootfs",
+				     sizeof("rootfs")))
+				sbsec->flags |= SBLABEL_MNT;
+
 			/* Defer initialization until selinux_complete_init,
 			   after the initial policy is loaded and the security
 			   server is ready to handle calls. */
-- 
2.10.3.dirty

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v2 15/15] selinux: delay sid population for rootfs till init is complete
  2018-01-25  3:27 [PATCH v2 00/15] extend initramfs archive format to support xattrs Taras Kondratiuk
                   ` (13 preceding siblings ...)
  2018-01-25  3:27 ` [PATCH v2 14/15] selinux: allow setxattr on rootfs so initramfs code can set them Taras Kondratiuk
@ 2018-01-25  3:27 ` Taras Kondratiuk
  14 siblings, 0 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25  3:27 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

From: Victor Kamensky <kamensky@cisco.com>

With initramfs cpio format that supports extended attributes
we need to skip sid population on sys_lsetxattr call from
initramfs for rootfs if security server is not initialized yet.

Otherwise callback in selinux_inode_post_setxattr will try to
translate give security.selinux label into sid context and since
security server is not available yet inode will receive default
sid (typically kernel_t). Note that in the same time proper
label will be stored in inode xattrs. Later, since inode sid
would be already populated system will never look back at
actual xattrs. But if we skip sid population for rootfs and
we have policy that direct use of xattrs for rootfs, proper
sid will be filled in from extended attributes one node is
accessed and server is initialized.

Note new DELAYAFTERINIT_MNT super block flag is introduced
to only mark rootfs for such behavior. For other types of
tmpfs original logic is still used.

Signed-off-by: Victor Kamensky <kamensky@cisco.com>
---
 security/selinux/hooks.c            | 9 ++++++++-
 security/selinux/include/security.h | 1 +
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index f3fe65589f02..bb25268f734e 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -716,7 +716,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 			 */
 			if (!strncmp(sb->s_type->name, "rootfs",
 				     sizeof("rootfs")))
-				sbsec->flags |= SBLABEL_MNT;
+				sbsec->flags |= SBLABEL_MNT|DELAYAFTERINIT_MNT;
 
 			/* Defer initialization until selinux_complete_init,
 			   after the initial policy is loaded and the security
@@ -3253,6 +3253,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
 {
 	struct inode *inode = d_backing_inode(dentry);
 	struct inode_security_struct *isec;
+	struct superblock_security_struct *sbsec;
 	u32 newsid;
 	int rc;
 
@@ -3261,6 +3262,12 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
 		return;
 	}
 
+	if (!ss_initialized) {
+		sbsec = inode->i_sb->s_security;
+		if (sbsec->flags & DELAYAFTERINIT_MNT)
+			return;
+	}
+
 	rc = security_context_to_sid_force(value, size, &newsid);
 	if (rc) {
 		printk(KERN_ERR "SELinux:  unable to map context to SID"
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 02f0412d42f2..585acfd6cbcf 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -52,6 +52,7 @@
 #define ROOTCONTEXT_MNT	0x04
 #define DEFCONTEXT_MNT	0x08
 #define SBLABEL_MNT	0x10
+#define DELAYAFTERINIT_MNT 0x20
 /* Non-mount related flags */
 #define SE_SBINITIALIZED	0x0100
 #define SE_SBPROC		0x0200
-- 
2.10.3.dirty

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 01/15] Documentation: add newcx initramfs format description
  2018-01-25  3:27 ` [PATCH v2 01/15] Documentation: add newcx initramfs format description Taras Kondratiuk
@ 2018-01-25  9:29   ` Arnd Bergmann
  2018-01-25 20:26     ` Taras Kondratiuk
  2018-01-26  2:39     ` Rob Landley
  2018-01-26  2:40   ` Rob Landley
  1 sibling, 2 replies; 29+ messages in thread
From: Arnd Bergmann @ 2018-01-25  9:29 UTC (permalink / raw)
  To: Taras Kondratiuk
  Cc: H. Peter Anvin, Al Viro, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan, initramfs, Victor Kamensky,
	linux-doc, Linux Kernel Mailing List, LSM List,
	xe-linux-external

On Thu, Jan 25, 2018 at 4:27 AM, Taras Kondratiuk <takondra@cisco.com> wrote:
> Many of the Linux security/integrity features are dependent on file
> metadata, stored as extended attributes (xattrs), for making decisions.
> These features need to be initialized during initcall and enabled as
> early as possible for complete security coverage.
>
> Initramfs (tmpfs) supports xattrs, but newc CPIO archive format does not
> support including them into the archive.
>
> This patch describes "extended" newc format (newcx) that is based on
> newc and has following changes:
> - extended attributes support
> - increased size of filesize to support files >4GB.
> - increased mtime field size to have usec precision and more than
>   32-bit of seconds.
> - removed unused checksum field.
>
> Signed-off-by: Taras Kondratiuk <takondra@cisco.com>
> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
> Signed-off-by: Victor Kamensky <kamensky@cisco.com>

Ah nice, I like the extension of the time handling, that certainly
addresses one of the issues with y2038 that we have previously
hacked around in an ugly way (interpreting the 32-bit
number as unsigned).

However, if this is to become a generally supported format
for cpio files, could we make it use nanosecond resolution
instead? The issue that I see with microseconds is that
storing a file in an archive and extracting it again would
otherwise keep the mtime stamp /almost/ identical on file
systems that have nanosecond resolution, but most of
the time a comparison would indicate that the files are
not the same.

Unfortunately, the range of a 64-bit nanoseconds counter
is still a bit limited (584 years, or half of that if we make it
signed). While this is clearly enough for the uses in
initramfs, it still has a similar problem: someone creating
a fake timestamp a long time in the past or future on
a file system would lose information after going though
cpio.

         Arnd

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 01/15] Documentation: add newcx initramfs format description
  2018-01-25  9:29   ` Arnd Bergmann
@ 2018-01-25 20:26     ` Taras Kondratiuk
  2018-01-25 21:02       ` Arnd Bergmann
  2018-01-26  2:39     ` Rob Landley
  1 sibling, 1 reply; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25 20:26 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: H. Peter Anvin, Al Viro, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan, initramfs, Victor Kamensky,
	linux-doc, Linux Kernel Mailing List, LSM List,
	xe-linux-external

Quoting Arnd Bergmann (2018-01-25 01:29:12)
> On Thu, Jan 25, 2018 at 4:27 AM, Taras Kondratiuk <takondra@cisco.com> wrote:
> > Many of the Linux security/integrity features are dependent on file
> > metadata, stored as extended attributes (xattrs), for making decisions.
> > These features need to be initialized during initcall and enabled as
> > early as possible for complete security coverage.
> >
> > Initramfs (tmpfs) supports xattrs, but newc CPIO archive format does not
> > support including them into the archive.
> >
> > This patch describes "extended" newc format (newcx) that is based on
> > newc and has following changes:
> > - extended attributes support
> > - increased size of filesize to support files >4GB.
> > - increased mtime field size to have usec precision and more than
> >   32-bit of seconds.
> > - removed unused checksum field.
> >
> > Signed-off-by: Taras Kondratiuk <takondra@cisco.com>
> > Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
> > Signed-off-by: Victor Kamensky <kamensky@cisco.com>
> 
> Ah nice, I like the extension of the time handling, that certainly
> addresses one of the issues with y2038 that we have previously
> hacked around in an ugly way (interpreting the 32-bit
> number as unsigned).
> 
> However, if this is to become a generally supported format
> for cpio files, could we make it use nanosecond resolution
> instead? The issue that I see with microseconds is that
> storing a file in an archive and extracting it again would
> otherwise keep the mtime stamp /almost/ identical on file
> systems that have nanosecond resolution, but most of
> the time a comparison would indicate that the files are
> not the same.
> 
> Unfortunately, the range of a 64-bit nanoseconds counter
> is still a bit limited (584 years, or half of that if we make it
> signed). While this is clearly enough for the uses in
> initramfs, it still has a similar problem: someone creating
> a fake timestamp a long time in the past or future on
> a file system would lose information after going though
> cpio.

We can match statx(2) by having 64 bits for seconds plus 32 bits for
nanoseconds. For initramfs nanoseconds field can be ignored during
unpacking.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 01/15] Documentation: add newcx initramfs format description
  2018-01-25 20:26     ` Taras Kondratiuk
@ 2018-01-25 21:02       ` Arnd Bergmann
  2018-01-25 22:13         ` Taras Kondratiuk
  0 siblings, 1 reply; 29+ messages in thread
From: Arnd Bergmann @ 2018-01-25 21:02 UTC (permalink / raw)
  To: Taras Kondratiuk
  Cc: H. Peter Anvin, Al Viro, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan, initramfs, Victor Kamensky,
	linux-doc, Linux Kernel Mailing List, LSM List,
	xe-linux-external

On Thu, Jan 25, 2018 at 9:26 PM, Taras Kondratiuk <takondra@cisco.com> wrote:
> Quoting Arnd Bergmann (2018-01-25 01:29:12)
>> On Thu, Jan 25, 2018 at 4:27 AM, Taras Kondratiuk <takondra@cisco.com> wrote:
>
> We can match statx(2) by having 64 bits for seconds plus 32 bits for
> nanoseconds.

Ok.

> For initramfs nanoseconds field can be ignored during
> unpacking.

That sounds like a pointless microoptimization. Most likely we won't ever
need the nanoseconds in the initramfs, but it's trivial to just copy them
into the right field, and not adding that one source line would probably
involve adding a one-line source comment to explain the omission ;-)

      Arnd

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 01/15] Documentation: add newcx initramfs format description
  2018-01-25 21:02       ` Arnd Bergmann
@ 2018-01-25 22:13         ` Taras Kondratiuk
  0 siblings, 0 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-25 22:13 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: H. Peter Anvin, Al Viro, Rob Landley, Mimi Zohar,
	Jonathan Corbet, James McMechan, initramfs, Victor Kamensky,
	linux-doc, Linux Kernel Mailing List, LSM List,
	xe-linux-external

Quoting Arnd Bergmann (2018-01-25 13:02:49)
> On Thu, Jan 25, 2018 at 9:26 PM, Taras Kondratiuk <takondra@cisco.com> wrote:
> 
> > For initramfs nanoseconds field can be ignored during
> > unpacking.
> 
> That sounds like a pointless microoptimization. Most likely we won't ever
> need the nanoseconds in the initramfs, but it's trivial to just copy them
> into the right field, and not adding that one source line would probably
> involve adding a one-line source comment to explain the omission ;-)

Agree.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 01/15] Documentation: add newcx initramfs format description
  2018-01-25  9:29   ` Arnd Bergmann
  2018-01-25 20:26     ` Taras Kondratiuk
@ 2018-01-26  2:39     ` Rob Landley
  2018-01-26  9:04       ` Arnd Bergmann
  2018-01-26 10:31       ` Henrique de Moraes Holschuh
  1 sibling, 2 replies; 29+ messages in thread
From: Rob Landley @ 2018-01-26  2:39 UTC (permalink / raw)
  To: Arnd Bergmann, Taras Kondratiuk
  Cc: H. Peter Anvin, Al Viro, Mimi Zohar, Jonathan Corbet,
	James McMechan, initramfs, Victor Kamensky, linux-doc,
	Linux Kernel Mailing List, LSM List, xe-linux-external

On 01/25/2018 03:29 AM, Arnd Bergmann wrote:
> On Thu, Jan 25, 2018 at 4:27 AM, Taras Kondratiuk <takondra@cisco.com> wrote:
>> Many of the Linux security/integrity features are dependent on file
>> metadata, stored as extended attributes (xattrs), for making decisions.
>> These features need to be initialized during initcall and enabled as
>> early as possible for complete security coverage.
>>
>> Initramfs (tmpfs) supports xattrs, but newc CPIO archive format does not
>> support including them into the archive.
>>
>> This patch describes "extended" newc format (newcx) that is based on
>> newc and has following changes:
>> - extended attributes support
>> - increased size of filesize to support files >4GB.
>> - increased mtime field size to have usec precision and more than
>>   32-bit of seconds.
>> - removed unused checksum field.
>>
>> Signed-off-by: Taras Kondratiuk <takondra@cisco.com>
>> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
>> Signed-off-by: Victor Kamensky <kamensky@cisco.com>
> 
> Ah nice, I like the extension of the time handling, that certainly
> addresses one of the issues with y2038 that we have previously
> hacked around in an ugly way (interpreting the 32-bit
> number as unsigned).

Taras and I exchanged email like a year ago working out format stuff, so
I don't have any real complaints. My feedback's already worked in, and I
can make toybox cpio support -h newcx as soon as the format's finalized
and I get a free weekend.

That said, I don't think -h newcx should emit (or recognize) the
"TRAILER!!!1!" entry. That's kinda silly in-band signaling for 2018:
files have a length, pipes provide EOF, and each cpiox entry starts with
6 bytes of c_magic anyway. (I stopped toybox from producing the TRAILER
entry back in june, toybox commit 32550751997d, and the kernel consumes
the resulting cpio just fine. All the trailer does is prevent you from
concatenating cpio files, which is a feature multiple people asked me for.)

> However, if this is to become a generally supported format
> for cpio files,

After Joerg Schilling dies (or admits solaris has) it might even make it
into posix.

> could we make it use nanosecond resolution
> instead? The issue that I see with microseconds is that
> storing a file in an archive and extracting it again would
> otherwise keep the mtime stamp /almost/ identical on file
> systems that have nanosecond resolution, but most of
> the time a comparison would indicate that the files are
> not the same.

I have no strong opinion on this? The tmpfs is still going to track
nanoseconds, this is just rounding when it populates them.

> Unfortunately, the range of a 64-bit nanoseconds counter
> is still a bit limited (584 years, or half of that if we make it
> signed). While this is clearly enough for the uses in
> initramfs, it still has a similar problem: someone creating
> a fake timestamp a long time in the past or future on
> a file system would lose information after going though
> cpio.

Hence microseconds. This came up in email when we were talking about
this (like a year ago) and I decided I didn't care. :)

64 bits of microseconds is +- 584 centuries, while being accurate
enough[1] that making a getpid() syscall probably takes longer than that
on our highest end boxen, let alone doing a dentry lookup in the vfs
(even if it's hot in cache).

Rob

[1] Is future proofing an issue here? The s-curve of moore's law started
bending down around y2k back when Intel had to recall its 1.13ghz
pentium III for having overclocked its own chip at the factory, and it's
pretty darn flat these days. Clock speeds first hit 4ghz 15 years ago
and haven't been back, most of the work since 2005 has been about
parallelism, and recent performance improvements are once again going to
pentium 4 pipeline length levels of absurdity, as meltdown/spectre
demonstrates (140 instructions of prefetch!??!?). Maybe intel will make
9 nanometer manufacturing work, but atomic limits are already an issue.

The problem with 1 second timestamps was you honestly could confuse
"make" about which file was newer once an exec() could complete in the
same second having done real work. That was the motivating issue causing
the change, going to nanoseconds was just the big hammer of "this is
large enough it won't matter again in our lifetimes". But nanosecond
time stamps are recording more jitter than useful information, and that
seems unlikely to change this century?

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 11/15] gen_init_cpio: add newcx format
  2018-01-25  3:27 ` [PATCH v2 11/15] gen_init_cpio: add newcx format Taras Kondratiuk
@ 2018-01-26  2:40   ` Rob Landley
  2018-01-26 20:37     ` Taras Kondratiuk
  0 siblings, 1 reply; 29+ messages in thread
From: Rob Landley @ 2018-01-26  2:40 UTC (permalink / raw)
  To: Taras Kondratiuk, H. Peter Anvin, Al Viro, Arnd Bergmann,
	Mimi Zohar, Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

On 01/24/2018 09:27 PM, Taras Kondratiuk wrote:
> diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c
> index 7a2a6d85345d..78a47a5bdcb1 100644
> --- a/usr/gen_init_cpio.c
> +++ b/usr/gen_init_cpio.c
> @@ -10,6 +10,7 @@
>  #include <errno.h>
>  #include <ctype.h>
>  #include <limits.h>
> +#include <assert.h>

You're adding an assert? Really?

>  	fputs(s, stdout);
> -	offset += 110;
> +	assert((offset & 3) == 0);
> +	offset += cpio_hdr_size;

Why?

Rob

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 01/15] Documentation: add newcx initramfs format description
  2018-01-25  3:27 ` [PATCH v2 01/15] Documentation: add newcx initramfs format description Taras Kondratiuk
  2018-01-25  9:29   ` Arnd Bergmann
@ 2018-01-26  2:40   ` Rob Landley
  2018-01-26 21:02     ` Taras Kondratiuk
  1 sibling, 1 reply; 29+ messages in thread
From: Rob Landley @ 2018-01-26  2:40 UTC (permalink / raw)
  To: Taras Kondratiuk, H. Peter Anvin, Al Viro, Arnd Bergmann,
	Mimi Zohar, Jonathan Corbet, James McMechan
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

On 01/24/2018 09:27 PM, Taras Kondratiuk wrote:
> diff --git a/Documentation/early-userspace/buffer-format.txt b/Documentation/early-userspace/buffer-format.txt
> index e1fd7f9dad16..d818df4f72dc 100644
> --- a/Documentation/early-userspace/buffer-format.txt
> +++ b/Documentation/early-userspace/buffer-format.txt

> +compressed and/or uncompressed cpio archives; arbitrary amounts
> +zero bytes (for padding) can be added between members.

Missing "of" between amounts and zero. (Yeah it was in the original, but
if you're touching it anyway...)

> +c_xattrs_size  8 bytes		 Size of xattrs field
> +
> +Most of the fields match cpio_newc_header except c_mtime that contains
> +microseconds. c_chksum field is dropped.
> +
> +xattr_size is a total size of xattr_entry including 8 bytes of
> +xattr_size. xattr_size has the same hexadecimal ASCII encoding as other
> +fields of cpio header.

xattrs_size or xattr_size?

Total nitpicks, I know. :)

Rob

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 01/15] Documentation: add newcx initramfs format description
  2018-01-26  2:39     ` Rob Landley
@ 2018-01-26  9:04       ` Arnd Bergmann
  2018-01-26 10:31       ` Henrique de Moraes Holschuh
  1 sibling, 0 replies; 29+ messages in thread
From: Arnd Bergmann @ 2018-01-26  9:04 UTC (permalink / raw)
  To: Rob Landley
  Cc: Taras Kondratiuk, H. Peter Anvin, Al Viro, Mimi Zohar,
	Jonathan Corbet, James McMechan, initramfs, Victor Kamensky,
	linux-doc, Linux Kernel Mailing List, LSM List,
	xe-linux-external

On Fri, Jan 26, 2018 at 3:39 AM, Rob Landley <rob@landley.net> wrote:

> The problem with 1 second timestamps was you honestly could confuse
> "make" about which file was newer once an exec() could complete in the
> same second having done real work. That was the motivating issue causing
> the change, going to nanoseconds was just the big hammer of "this is
> large enough it won't matter again in our lifetimes". But nanosecond
> time stamps are recording more jitter than useful information, and that
> seems unlikely to change this century?

Sure, the only thing we really need the nanosecond timestamp for is
to keep them identical. E.g. if you use cpio to make an exact copy
of a file system, using microseconds timestamps will round all mtime
values. If you then use 'rsync' to compare/update the two copies
without passing a --modify-window= or --size-only, it will have
to read all files in rather then skipping those with identical size and
mtime.

Side note: the default behavior for file systems is actually to only use
the coarse timestamps of the last timer tick, so you actually do get
identical timestamps in practice, plus six digits of nonsense:

(on tmpfs)
 $ for i in {000..999} ; do > $i ; done; stat --format="%y" *  | uniq -c
     86 2018-01-26 10:01:48.811135084 +0100
    469 2018-01-26 10:01:48.815135143 +0100
    445 2018-01-26 10:01:48.819135201 +0100

         Arnd

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 01/15] Documentation: add newcx initramfs format description
  2018-01-26  2:39     ` Rob Landley
  2018-01-26  9:04       ` Arnd Bergmann
@ 2018-01-26 10:31       ` Henrique de Moraes Holschuh
  2018-01-26 15:51         ` Victor Kamensky
  1 sibling, 1 reply; 29+ messages in thread
From: Henrique de Moraes Holschuh @ 2018-01-26 10:31 UTC (permalink / raw)
  To: Rob Landley
  Cc: Arnd Bergmann, Taras Kondratiuk, H. Peter Anvin, Al Viro,
	Mimi Zohar, Jonathan Corbet, James McMechan, initramfs,
	Victor Kamensky, linux-doc, Linux Kernel Mailing List, LSM List,
	xe-linux-external

On Thu, 25 Jan 2018, Rob Landley wrote:
> That said, I don't think -h newcx should emit (or recognize) the
> "TRAILER!!!1!" entry. That's kinda silly in-band signaling for 2018:
> files have a length, pipes provide EOF, and each cpiox entry starts with
> 6 bytes of c_magic anyway. (I stopped toybox from producing the TRAILER
> entry back in june, toybox commit 32550751997d, and the kernel consumes
> the resulting cpio just fine. All the trailer does is prevent you from
> concatenating cpio files, which is a feature multiple people asked me for.)

Not in the kernel.  What TRAILER does in the kernel is to act as a
barrier for the hardlink creation state, which IS a good thing.  You
could just specify it as such for "newcx".

The kernel will continue reading for more entries after TRAILER, so
concatenation is not broken by TRAILER.  It is also insensitive to
NUL-padding length (as long as it is 4-byte aligned), which is another
nice feature you could specify for "newcx".

Also, the kernel does something nothing in userspace ever tried to,
AFAIK: it detects compression signatures along with the CPIO header
signatures, and thus it can take several compressed and uncompressed
archives concatenater together (and the compressor doesn't need to be
the same, either).

-- 
  Henrique Holschuh

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 01/15] Documentation: add newcx initramfs format description
  2018-01-26 10:31       ` Henrique de Moraes Holschuh
@ 2018-01-26 15:51         ` Victor Kamensky
  2018-01-26 18:15           ` Henrique de Moraes Holschuh
  0 siblings, 1 reply; 29+ messages in thread
From: Victor Kamensky @ 2018-01-26 15:51 UTC (permalink / raw)
  To: Henrique de Moraes Holschuh, Rob Landley
  Cc: Arnd Bergmann, Taras Kondratiuk, H. Peter Anvin, Al Viro,
	Mimi Zohar, Jonathan Corbet, James McMechan, initramfs,
	linux-doc, Linux Kernel Mailing List, LSM List,
	xe-linux-external



On Fri, 26 Jan 2018, Henrique de Moraes Holschuh wrote:

> On Thu, 25 Jan 2018, Rob Landley wrote:
>> That said, I don't think -h newcx should emit (or recognize) the
>> "TRAILER!!!1!" entry. That's kinda silly in-band signaling for 2018:
>> files have a length, pipes provide EOF, and each cpiox entry starts with
>> 6 bytes of c_magic anyway.

My understanding that TRAILER is really used on tape devices,
there is no notion of file end in this case, it is just a stream of bytes
from char device.

Thanks,
Victor

>> (I stopped toybox from producing the TRAILER
>> entry back in june, toybox commit 32550751997d, and the kernel consumes
>> the resulting cpio just fine. All the trailer does is prevent you from
>> concatenating cpio files, which is a feature multiple people asked me for.)
>
> Not in the kernel.  What TRAILER does in the kernel is to act as a
> barrier for the hardlink creation state, which IS a good thing.  You
> could just specify it as such for "newcx".
>
> The kernel will continue reading for more entries after TRAILER, so
> concatenation is not broken by TRAILER.  It is also insensitive to
> NUL-padding length (as long as it is 4-byte aligned), which is another
> nice feature you could specify for "newcx".
>
> Also, the kernel does something nothing in userspace ever tried to,
> AFAIK: it detects compression signatures along with the CPIO header
> signatures, and thus it can take several compressed and uncompressed
> archives concatenater together (and the compressor doesn't need to be
> the same, either).
> --
>  Henrique Holschuh
>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 01/15] Documentation: add newcx initramfs format description
  2018-01-26 15:51         ` Victor Kamensky
@ 2018-01-26 18:15           ` Henrique de Moraes Holschuh
  0 siblings, 0 replies; 29+ messages in thread
From: Henrique de Moraes Holschuh @ 2018-01-26 18:15 UTC (permalink / raw)
  To: Victor Kamensky
  Cc: Rob Landley, Arnd Bergmann, Taras Kondratiuk, H. Peter Anvin,
	Al Viro, Mimi Zohar, Jonathan Corbet, James McMechan, initramfs,
	linux-doc, Linux Kernel Mailing List, LSM List,
	xe-linux-external


On Fri, 26 Jan 2018, Victor Kamensky wrote:
> On Fri, 26 Jan 2018, Henrique de Moraes Holschuh wrote:
> > On Thu, 25 Jan 2018, Rob Landley wrote:
> > > That said, I don't think -h newcx should emit (or recognize) the
> > > "TRAILER!!!1!" entry. That's kinda silly in-band signaling for 2018:
> > > files have a length, pipes provide EOF, and each cpiox entry starts with
> > > 6 bytes of c_magic anyway.
> 
> My understanding that TRAILER is really used on tape devices,
> there is no notion of file end in this case, it is just a stream of bytes
> from char device.

TRAILER is really used anywhere you can have several cpio archives
concatenated, which is the exact case of a Linux initramfs, not just
tape.

The initramfs format takes *one or more* cpio archives, concatenated.
Each archive may be independently compressed (using whatever supported
compression method), or uncompressed[1].  EOF or size information can
only tell you where the entire concatenated archive ends, not where each
"segment" (independent cpio archive that was concatenated into the
whole) ends.

TRAILER is the only decent way to know the concatenation points.
Knowing where these points are is necessary for the kernel, due to the
way hardlink encoding is done on cpio archives: one has to reset the
state of the hardlink-tracking table between cpio archives that were
concatenated, for safety (and sysadmin sanity) reasons.

[1] for the special case when one includes an "early initramfs" section
for firmware (microcode, etc) updates, the archive(s) containing the
firmware data must be uncompressed, and these archives must come before
compressed archives in the concatenation.

-- 
  Henrique Holschuh

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 11/15] gen_init_cpio: add newcx format
  2018-01-26  2:40   ` Rob Landley
@ 2018-01-26 20:37     ` Taras Kondratiuk
  0 siblings, 0 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-26 20:37 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, James McMechan,
	Jonathan Corbet, Mimi Zohar, Rob Landley
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

Quoting Rob Landley (2018-01-25 18:40:25)
> On 01/24/2018 09:27 PM, Taras Kondratiuk wrote:
> > diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c
> > index 7a2a6d85345d..78a47a5bdcb1 100644
> > --- a/usr/gen_init_cpio.c
> > +++ b/usr/gen_init_cpio.c
> > @@ -10,6 +10,7 @@
> >  #include <errno.h>
> >  #include <ctype.h>
> >  #include <limits.h>
> > +#include <assert.h>
> 
> You're adding an assert? Really?
> 
> >       fputs(s, stdout);
> > -     offset += 110;
> > +     assert((offset & 3) == 0);
> > +     offset += cpio_hdr_size;
> 
> Why?

Current code assumes that previous file entry in cpio is padded to 4
byte boundary. The assert just captures this assumption. It should be
true unless there is a bug in the code and some padding is missing.

Actually this assert should be a part of the next patch (#12) that
modifies padding code.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 01/15] Documentation: add newcx initramfs format description
  2018-01-26  2:40   ` Rob Landley
@ 2018-01-26 21:02     ` Taras Kondratiuk
  0 siblings, 0 replies; 29+ messages in thread
From: Taras Kondratiuk @ 2018-01-26 21:02 UTC (permalink / raw)
  To: H. Peter Anvin, Al Viro, Arnd Bergmann, James McMechan,
	Jonathan Corbet, Mimi Zohar, Rob Landley
  Cc: initramfs, Victor Kamensky, linux-doc, linux-kernel,
	linux-security-module, xe-linux-external

Quoting Rob Landley (2018-01-25 18:40:54)
> On 01/24/2018 09:27 PM, Taras Kondratiuk wrote:
> > diff --git a/Documentation/early-userspace/buffer-format.txt b/Documentation/early-userspace/buffer-format.txt
> > index e1fd7f9dad16..d818df4f72dc 100644
> > --- a/Documentation/early-userspace/buffer-format.txt
> > +++ b/Documentation/early-userspace/buffer-format.txt
> 
> > +compressed and/or uncompressed cpio archives; arbitrary amounts
> > +zero bytes (for padding) can be added between members.
> 
> Missing "of" between amounts and zero. (Yeah it was in the original, but
> if you're touching it anyway...)
> 
> > +c_xattrs_size  8 bytes                Size of xattrs field
> > +
> > +Most of the fields match cpio_newc_header except c_mtime that contains
> > +microseconds. c_chksum field is dropped.
> > +
> > +xattr_size is a total size of xattr_entry including 8 bytes of
> > +xattr_size. xattr_size has the same hexadecimal ASCII encoding as other
> > +fields of cpio header.
> 
> xattrs_size or xattr_size?
> 
> Total nitpicks, I know. :)

xattr_size here refers to size of each xattr_entry:
xattr_entry := xattr_size[8] + xattr_name + "\0" + xattr_value

I'll move this paragraph closer to that line.

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2018-01-26 21:03 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-25  3:27 [PATCH v2 00/15] extend initramfs archive format to support xattrs Taras Kondratiuk
2018-01-25  3:27 ` [PATCH v2 01/15] Documentation: add newcx initramfs format description Taras Kondratiuk
2018-01-25  9:29   ` Arnd Bergmann
2018-01-25 20:26     ` Taras Kondratiuk
2018-01-25 21:02       ` Arnd Bergmann
2018-01-25 22:13         ` Taras Kondratiuk
2018-01-26  2:39     ` Rob Landley
2018-01-26  9:04       ` Arnd Bergmann
2018-01-26 10:31       ` Henrique de Moraes Holschuh
2018-01-26 15:51         ` Victor Kamensky
2018-01-26 18:15           ` Henrique de Moraes Holschuh
2018-01-26  2:40   ` Rob Landley
2018-01-26 21:02     ` Taras Kondratiuk
2018-01-25  3:27 ` [PATCH v2 02/15] initramfs: replace states with function pointers Taras Kondratiuk
2018-01-25  3:27 ` [PATCH v2 03/15] initramfs: store file name in name_buf Taras Kondratiuk
2018-01-25  3:27 ` [PATCH v2 04/15] initramfs: remove unnecessary symlinks processing shortcut Taras Kondratiuk
2018-01-25  3:27 ` [PATCH v2 05/15] initramfs: move files creation into separate state Taras Kondratiuk
2018-01-25  3:27 ` [PATCH v2 06/15] initramfs: separate reading cpio method from header Taras Kondratiuk
2018-01-25  3:27 ` [PATCH v2 07/15] initramfs: split header layout information from parsing function Taras Kondratiuk
2018-01-25  3:27 ` [PATCH v2 08/15] initramfs: add newcx format Taras Kondratiuk
2018-01-25  3:27 ` [PATCH v2 09/15] initramfs: set extended attributes Taras Kondratiuk
2018-01-25  3:27 ` [PATCH v2 10/15] gen_init_cpio: move header formatting into function Taras Kondratiuk
2018-01-25  3:27 ` [PATCH v2 11/15] gen_init_cpio: add newcx format Taras Kondratiuk
2018-01-26  2:40   ` Rob Landley
2018-01-26 20:37     ` Taras Kondratiuk
2018-01-25  3:27 ` [PATCH v2 12/15] gen_init_cpio: set extended attributes for " Taras Kondratiuk
2018-01-25  3:27 ` [PATCH v2 13/15] gen_initramfs_list.sh: add -x option to enable " Taras Kondratiuk
2018-01-25  3:27 ` [PATCH v2 14/15] selinux: allow setxattr on rootfs so initramfs code can set them Taras Kondratiuk
2018-01-25  3:27 ` [PATCH v2 15/15] selinux: delay sid population for rootfs till init is complete Taras Kondratiuk

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).