pkubat / rpms / cpio

Forked from rpms/cpio 4 years ago
Clone
501abeb
--- cpio-2.6/src/copyin.c.chmodRaceC	2005-07-01 14:23:04.000000000 +0200
501abeb
+++ cpio-2.6/src/copyin.c	2005-07-01 14:46:34.000000000 +0200
501abeb
@@ -184,11 +184,12 @@
501abeb
 
501abeb
 static int
501abeb
 try_existing_file(struct new_cpio_header* file_hdr, int in_file_des,
501abeb
-		  int *existing_dir)
501abeb
+		  int *existing_dir, mode_t *existing_mode)
501abeb
 {
501abeb
   struct stat file_stat;
501abeb
 
501abeb
   *existing_dir = false;
501abeb
+  *existing_mode = 0;
501abeb
   if (lstat (file_hdr->c_name, &file_stat) == 0)
501abeb
     {
501abeb
       if (S_ISDIR (file_stat.st_mode)
501abeb
@@ -198,6 +199,7 @@
501abeb
 	     we are trying to create, don't complain about
501abeb
 	     it.  */
501abeb
 	  *existing_dir = true;
501abeb
+	  *existing_mode = file_stat.st_mode;
501abeb
 	  return 0;
501abeb
 	}
501abeb
       else if (!unconditional_flag
501abeb
@@ -389,19 +391,20 @@
0005073
 	  continue;
0005073
 	}
0005073
 
0005073
-      if (close (out_file_des) < 0)
0005073
-	error (0, errno, "%s", d->header.c_name);
0005073
-
0005073
       /* File is now copied; set attributes.  */
0005073
       if (!no_chown_flag)
0005073
-	if ((chown (d->header.c_name,
0005073
+	if ((fchown (out_file_des,
0005073
 		    set_owner_flag ? set_owner : d->header.c_uid,
0005073
 	       set_group_flag ? set_group : d->header.c_gid) < 0)
0005073
 	    && errno != EPERM)
0005073
 	  error (0, errno, "%s", d->header.c_name);
0005073
       /* chown may have turned off some permissions we wanted. */
0005073
-      if (chmod (d->header.c_name, (int) d->header.c_mode) < 0)
0005073
+      if (fchmod (out_file_des, (int) d->header.c_mode) < 0)
501abeb
 	error (0, errno, "%s", d->header.c_name);
0005073
+
0005073
+      if (close (out_file_des) < 0)
501abeb
+	error (0, errno, "%s", d->header.c_name);
0005073
+
0005073
       if (retain_time_flag)
0005073
 	{
0005073
 	  times.actime = times.modtime = d->header.c_mtime;
501abeb
@@ -557,6 +560,19 @@
0005073
       write (out_file_des, "", 1);
0005073
       delayed_seek_count = 0;
0005073
     }
0005073
+    
0005073
+  /* File is now copied; set attributes.  */
0005073
+  if (!no_chown_flag)
0005073
+    if ((fchown (out_file_des,
0005073
+		set_owner_flag ? set_owner : file_hdr->c_uid,
0005073
+	   set_group_flag ? set_group : file_hdr->c_gid) < 0)
0005073
+	&& errno != EPERM)
0005073
+      error (0, errno, "%s", file_hdr->c_name);
0005073
+  
0005073
+  /* chown may have turned off some permissions we wanted. */
0005073
+  if (fchmod (out_file_des, (int) file_hdr->c_mode) < 0)
0005073
+    error (0, errno, "%s", file_hdr->c_name);
0005073
+     
0005073
   if (close (out_file_des) < 0)
0005073
     error (0, errno, "%s", file_hdr->c_name);
0005073
 
501abeb
@@ -567,18 +583,6 @@
0005073
 	       file_hdr->c_name, crc, file_hdr->c_chksum);
0005073
     }
0005073
 
0005073
-  /* File is now copied; set attributes.  */
0005073
-  if (!no_chown_flag)
0005073
-    if ((chown (file_hdr->c_name,
0005073
-		set_owner_flag ? set_owner : file_hdr->c_uid,
0005073
-	   set_group_flag ? set_group : file_hdr->c_gid) < 0)
0005073
-	&& errno != EPERM)
0005073
-      error (0, errno, "%s", file_hdr->c_name);
0005073
-  
0005073
-  /* chown may have turned off some permissions we wanted. */
0005073
-  if (chmod (file_hdr->c_name, (int) file_hdr->c_mode) < 0)
0005073
-    error (0, errno, "%s", file_hdr->c_name);
0005073
-  
0005073
   if (retain_time_flag)
0005073
     {
0005073
       struct utimbuf times;		/* For setting file times.  */
501abeb
@@ -589,7 +593,7 @@
0005073
       if (utime (file_hdr->c_name, &times) < 0)
0005073
 	error (0, errno, "%s", file_hdr->c_name);
0005073
     }
0005073
-  
0005073
+    
0005073
   tape_skip_padding (in_file_des, file_hdr->c_filesize);
0005073
   if (file_hdr->c_nlink > 1
0005073
       && (archive_format == arf_newascii || archive_format == arf_crcascii) )
501abeb
@@ -603,7 +607,7 @@
501abeb
 }
501abeb
 
501abeb
 static void
501abeb
-copyin_directory(struct new_cpio_header* file_hdr, int existing_dir)
501abeb
+copyin_directory(struct new_cpio_header* file_hdr, int existing_dir, mode_t existing_mode)
501abeb
 {
501abeb
   int res;			/* Result of various function calls.  */
501abeb
 #ifdef HPUX_CDF
501abeb
@@ -646,14 +650,23 @@
501abeb
 	  cdf_flag = 1;
501abeb
 	}
501abeb
 #endif
501abeb
-      res = mkdir (file_hdr->c_name, file_hdr->c_mode);
501abeb
+      res = mkdir (file_hdr->c_name, file_hdr->c_mode & ~077);
501abeb
     }
501abeb
-  else
501abeb
-    res = 0;
501abeb
+  else 
501abeb
+    {
501abeb
+      if (!no_chown_flag && (existing_mode & 077) != 0
501abeb
+         && chmod (file_hdr->c_name, existing_mode & 07700) < 0)
501abeb
+       {
501abeb
+         error (0, errno, "%s: chmod", file_hdr->c_name);
501abeb
+         return;
501abeb
+       }
501abeb
+      res = 0;
501abeb
+    }
501abeb
+
501abeb
   if (res < 0 && create_dir_flag)
501abeb
     {
501abeb
       create_all_directories (file_hdr->c_name);
501abeb
-      res = mkdir (file_hdr->c_name, file_hdr->c_mode);
501abeb
+      res = mkdir (file_hdr->c_name, file_hdr->c_mode & ~077);
501abeb
     }
501abeb
   if (res < 0)
501abeb
     {
501abeb
@@ -742,12 +755,12 @@
501abeb
       return;
501abeb
     }
501abeb
   
501abeb
-  res = mknod (file_hdr->c_name, file_hdr->c_mode,
501abeb
+  res = mknod (file_hdr->c_name, file_hdr->c_mode & ~077,
501abeb
 	    makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min));
501abeb
   if (res < 0 && create_dir_flag)
501abeb
     {
501abeb
       create_all_directories (file_hdr->c_name);
501abeb
-      res = mknod (file_hdr->c_name, file_hdr->c_mode,
501abeb
+      res = mknod (file_hdr->c_name, file_hdr->c_mode & ~077,
501abeb
 	    makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min));
501abeb
     }
501abeb
   if (res < 0)
501abeb
@@ -826,9 +839,10 @@
501abeb
 copyin_file (struct new_cpio_header* file_hdr, int in_file_des)
501abeb
 {
501abeb
   int existing_dir;
501abeb
+  mode_t existing_mode;
501abeb
 
501abeb
   if (!to_stdout_option
501abeb
-      && try_existing_file (file_hdr, in_file_des, &existing_dir) < 0)
501abeb
+      && try_existing_file (file_hdr, in_file_des, &existing_dir, &existing_mode) < 0)
501abeb
     return;
501abeb
 
501abeb
   /* Do the real copy or link.  */
501abeb
@@ -839,7 +853,7 @@
501abeb
       break;
501abeb
 
501abeb
     case CP_IFDIR:
501abeb
-      copyin_directory(file_hdr, existing_dir);
501abeb
+      copyin_directory(file_hdr, existing_dir, existing_mode);
501abeb
       break;
501abeb
 
501abeb
     case CP_IFCHR:
0005073
--- cpio-2.6/src/copypass.c.chmodRaceC	2004-09-06 14:09:04.000000000 +0200
501abeb
+++ cpio-2.6/src/copypass.c	2005-07-01 14:50:46.000000000 +0200
0005073
@@ -181,19 +181,25 @@
0005073
 		}
0005073
 	      if (close (in_file_des) < 0)
0005073
 		error (0, errno, "%s", input_name.ds_string);
0005073
-	      if (close (out_file_des) < 0)
0005073
-		error (0, errno, "%s", output_name.ds_string);
0005073
-
0005073
+	      /*
0005073
+	       *  Avoid race condition.
0005073
+	       *  Set chown and chmod before closing the file desc.
0005073
+	       *  pvrabec@redhat.com
0005073
+	       */
0005073
 	      /* Set the attributes of the new file.  */
0005073
 	      if (!no_chown_flag)
0005073
-		if ((chown (output_name.ds_string,
0005073
+		if ((fchown (out_file_des,
0005073
 			    set_owner_flag ? set_owner : in_file_stat.st_uid,
0005073
 		      set_group_flag ? set_group : in_file_stat.st_gid) < 0)
0005073
 		    && errno != EPERM)
0005073
 		  error (0, errno, "%s", output_name.ds_string);
0005073
 	      /* chown may have turned off some permissions we wanted. */
0005073
-	      if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
0005073
+	      if (fchmod (out_file_des, in_file_stat.st_mode) < 0)
501abeb
 		error (0, errno, "%s", output_name.ds_string);
0005073
+		
0005073
+	      if (close (out_file_des) < 0)
501abeb
+		error (0, errno, "%s", output_name.ds_string);
0005073
+
0005073
 	      if (reset_time_flag)
0005073
 		{
0005073
 		  times.actime = in_file_stat.st_atime;
501abeb
@@ -240,15 +246,24 @@
501abeb
 		  cdf_flag = 1;
501abeb
 		}
501abeb
 #endif
501abeb
-	      res = mkdir (output_name.ds_string, in_file_stat.st_mode);
501abeb
+	      res = mkdir (output_name.ds_string, in_file_stat.st_mode & ~077);
501abeb
 
501abeb
 	    }
501abeb
 	  else
501abeb
-	    res = 0;
501abeb
+            {
501abeb
+              if (!no_chown_flag && (out_file_stat.st_mode & 077) != 0
501abeb
+                  && chmod (output_name.ds_string, out_file_stat.st_mode & 07700) < 0)
501abeb
+                {
501abeb
+                  error (0, errno, "%s: chmod", output_name.ds_string);
501abeb
+                  continue;
501abeb
+                }
501abeb
+              res = 0;
501abeb
+            }
501abeb
+
501abeb
 	  if (res < 0 && create_dir_flag)
501abeb
 	    {
501abeb
 	      create_all_directories (output_name.ds_string);
501abeb
-	      res = mkdir (output_name.ds_string, in_file_stat.st_mode);
501abeb
+	      res = mkdir (output_name.ds_string, in_file_stat.st_mode & ~077);
501abeb
 	    }
501abeb
 	  if (res < 0)
501abeb
 	    {
501abeb
@@ -311,12 +326,12 @@
501abeb
 
501abeb
 	  if (link_res < 0)
501abeb
 	    {
501abeb
-	      res = mknod (output_name.ds_string, in_file_stat.st_mode,
501abeb
+	      res = mknod (output_name.ds_string, in_file_stat.st_mode & ~077,
501abeb
 			   in_file_stat.st_rdev);
501abeb
 	      if (res < 0 && create_dir_flag)
501abeb
 		{
501abeb
 		  create_all_directories (output_name.ds_string);
501abeb
-		  res = mknod (output_name.ds_string, in_file_stat.st_mode,
501abeb
+		  res = mknod (output_name.ds_string, in_file_stat.st_mode & ~077,
501abeb
 			       in_file_stat.st_rdev);
501abeb
 		}
501abeb
 	      if (res < 0)