[klibc] [PATCH] initramfs: CPIO unpacking fix

H. Peter Anvin hpa at zytor.com
Fri Apr 7 10:33:20 PDT 2006


Unlink files, symlinks, FIFOs, devices etc. (except directories) before
writing them when extracting CPIOs.  This stops weird behaviour like:
  1) writing through symlinks created in earlier CPIOs. eg foo->bar in
     the first CPIO.  Having foo as a non-link in a subsequent CPIO,
     results in bar being written and foo remaining as a symlink.
  2) if the first version of file foo is larger than foo in a
     subsequent CPIO, we end up with a mix of the two.  ie. neither
     the first or second version of /foo.
  3) special files like devices, fifo etc. can't be overwritten in
     subsequent CPIOS.

With this, the kernel will more closely replicate
   for i in *.cpio; do cpio --extract --unconditional < $i ; done

This is a change but it's regarded as fixing broken functionality.

Signed-off-by: Michael Neuling <mikey at neuling.org>
Signed-off-by: H. Peter Anvin <hpa at zytor.com>

  init/initramfs.c |    3 +++
  1 files changed, 3 insertions(+)

Index: linux-2.6.15/init/initramfs.c
===================================================================
--- linux-2.6.15.orig/init/initramfs.c
+++ linux-2.6.15/init/initramfs.c
@@ -249,6 +249,7 @@ static int __init do_name(void)
  	if (dry_run)
  		return 0;
  	if (S_ISREG(mode)) {
+		sys_unlink(collected);
  		if (maybe_link() >= 0) {
  			wfd = sys_open(collected, O_WRONLY|O_CREAT, mode);
  			if (wfd >= 0) {
@@ -263,6 +264,7 @@ static int __init do_name(void)
  		sys_chmod(collected, mode);
  	} else if (S_ISBLK(mode) || S_ISCHR(mode) ||
  		   S_ISFIFO(mode) || S_ISSOCK(mode)) {
+		sys_unlink(collected);
  		if (maybe_link() == 0) {
  			sys_mknod(collected, mode, rdev);
  			sys_chown(collected, uid, gid);
@@ -291,6 +293,7 @@ static int __init do_copy(void)
  static int __init do_symlink(void)
  {
  	collected[N_ALIGN(name_len) + body_len] = '\0';
+	sys_unlink(collected);
  	sys_symlink(collected + N_ALIGN(name_len), collected);
  	sys_lchown(collected, uid, gid);
  	state = SkipIt;



More information about the klibc mailing list