Re: cpio 2.9: sets unexpected (wrong?) file owner UID

View: New views
1 Messages — Rating Filter:   Alert me  

Re: cpio 2.9: sets unexpected (wrong?) file owner UID

by Radek Brich :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

forwarding to the list...

----------  Forwarded Message  ----------

Subject: Re: [Bug-cpio] cpio 2.9: sets unexpected (wrong?) file owner UID
Date: Ășt 26. Ășnora 2008
From: Radek Brich <rbrich@...>
To: "Sergey Poznyakoff" <gray@...>

On Tuesday 26 of February 2008 12:05:05 you wrote:

> Radek Brich <rbrich@...> ha escrit:
> > On Tue 30. of October 2007 12:27:11 Alexey Stratonnikov wrote:
> > > When cpio archive is created as "find . -depth |cpio -o" and extracted
> > > as "cpio -i --make-directories" under root user, I get all directories
> > > owned by UID=0 no matter who was the owner of the directory when acrive
> > > was created.
> > >
> > > This may be shown as:
>
> [...]
>
> This test case works with the latest alpha version
> (ftp://alpha.gnu.org/gnu/cpio/cpio-2.9.90.tar.gz).
>
> Regards,
> Sergey
Hi Sergey,

I'm attaching few reproducers here -- only the 'no-depth' one works with
cpio-2.9.90. I think the problem is in the delayed_set_stat. It remembers
permissions of implicitly created directories and overwrites the permissions
from archive with those when apply_delayed_set_stat() is called.

$ sudo ./cpio-dir-perm-depth ~/tmp/cpio-2.9.90/src/cpio
* Original permissions:
drwx------ 2 bin bin 4096 2008-02-26 13:33 a
* Extracted permissions:
drwxr-xr-x 2 root root 4096 2008-02-26 13:33 a

I wrote a patch for the 'find . -depth | cpio -o' case, so I'm attaching it
too, though it's not exactly clean to be included...

--
Radek Brich
Base OS/core services
Red Hat, Brno, Czech Rep.

-------------------------------------------------------




[cpio-2.9-dir_perm.patch]

diff -up cpio-2.9/src/extern.h.orig cpio-2.9/src/extern.h
--- cpio-2.9/src/extern.h.orig 2007-06-28 14:59:38.000000000 +0200
+++ cpio-2.9/src/extern.h 2008-02-13 15:24:37.000000000 +0100
@@ -211,7 +211,7 @@ uintmax_t from_ascii (char const *where,
     
 void delay_set_stat (char const *file_name, struct stat *st,
      mode_t invert_permissions);
-void repair_delayed_set_stat (char const *dir,
+int repair_delayed_set_stat (char const *dir,
       struct stat *dir_stat_info);
 void apply_delayed_set_stat (void);
     
diff -up cpio-2.9/src/copyin.c.orig cpio-2.9/src/copyin.c
--- cpio-2.9/src/copyin.c.orig 2007-06-28 12:51:09.000000000 +0200
+++ cpio-2.9/src/copyin.c 2008-02-14 10:28:33.000000000 +0100
@@ -570,6 +570,7 @@ static void
 copyin_directory (struct cpio_file_stat *file_hdr, int existing_dir)
 {
   int res; /* Result of various function calls.  */
+  struct stat file_stat;
 #ifdef HPUX_CDF
   int cdf_flag;                 /* True if file is a CDF.  */
   int cdf_char;                 /* Index of `+' char indicating a CDF.  */
@@ -626,7 +627,6 @@ copyin_directory (struct cpio_file_stat
  create_all_directories(), so the mkdir will fail
  because the directory exists.  If that's the case,
  don't complain about it.  */
-      struct stat file_stat;
       if (errno != EEXIST)
  {
   mkdir_error (file_hdr->c_name);
@@ -645,7 +645,11 @@ copyin_directory (struct cpio_file_stat
  }
     }
 
-  set_perms (-1, file_hdr);
+  /* if the directory is queued for delayed_set_stat,
+     fix permissions in the queue, otherwise set the permissions now */
+  cpio_to_stat(file_hdr, &file_stat);
+  if (repair_delayed_set_stat(file_hdr->c_name, &file_stat))
+    set_perms (-1, file_hdr);
 }
 
 static void
diff -up cpio-2.9/src/makepath.c.orig cpio-2.9/src/makepath.c
diff -up cpio-2.9/src/util.c.orig cpio-2.9/src/util.c
--- cpio-2.9/src/util.c.orig 2007-06-28 15:04:51.000000000 +0200
+++ cpio-2.9/src/util.c 2008-02-14 13:24:37.000000000 +0100
@@ -1265,6 +1265,16 @@ stat_to_cpio (struct cpio_file_stat *hdr
   hdr->c_tar_linkname = NULL;
 }
 
+void
+cpio_to_stat (struct cpio_file_stat *hdr, struct stat *st)
+{
+  stat (hdr->c_name, st);
+  st->st_mode = hdr->c_mode;
+  st->st_uid = CPIO_UID(hdr->c_uid);
+  st->st_gid = CPIO_GID(hdr->c_gid);
+  st->st_mtime = hdr->c_mtime;
+}
+
 #ifndef HAVE_FCHOWN
 # define fchown(fd, uid, gid) (-1)
 #endif
@@ -1389,7 +1399,7 @@ delay_set_stat (char const *file_name, s
    created within the file name of DIR.  The intermediate directory turned
    out to be the same as this directory, e.g. due to ".." or symbolic
    links.  *DIR_STAT_INFO is the status of the directory.  */
-void
+int
 repair_delayed_set_stat (char const *dir,
  struct stat *dir_stat_info)
 {
@@ -1400,22 +1410,19 @@ repair_delayed_set_stat (char const *dir
       if (stat (data->stat.c_name, &st) != 0)
  {
   stat_error (data->stat.c_name);
-  return;
+  return 0;
  }
 
       if (st.st_dev == dir_stat_info->st_dev
   && st.st_ino == dir_stat_info->st_ino)
  {
   stat_to_cpio (&data->stat, dir_stat_info);
-  data->invert_permissions =
-    ((dir_stat_info->st_mode ^ st.st_mode)
-     & MODE_RWX & ~ newdir_umask);
-  return;
+  data->invert_permissions = 0;
+  return 0;
  }
     }
 
-  ERROR ((0, 0, _("%s: Unexpected inconsistency when making directory"),
-  quotearg_colon (dir)));
+  return -1;
 }
 
 void


_______________________________________________
Bug-cpio mailing list
Bug-cpio@...
http://lists.gnu.org/mailman/listinfo/bug-cpio

cpio-dir-perm-depth (501 bytes) Download Attachment
cpio-dir-perm-passthrough (495 bytes) Download Attachment
cpio-dir-perm-no-depth (494 bytes) Download Attachment