tar: fix 1.23 Solaris regression related to PRIV_SYS_LINKDIR
The idea was suggested by Petr Sumbera in the thread starting here: http://lists.gnu.org/archive/html/bug-tar/2010-08/msg00000.html * src/extract.c (set_mode): Save the errno of the chmod that failed, for the benefit of chmod_error_details. Do not bother retrying chmod unless the mode suggests setuid is the issue. (extract_archive): Remove redundant call to priv_set_remove_linkdir. * src/system.c: Include priv-set.h. (sys_spawn_shell, sys_child_open_for_compress): (sys_child_open_for_uncompress, sys_exec_command): (sys_exec_info_script, sys_exec_checkpoint_script): Invoke priv_set_restore_linkdir before execv or execlp, so that the subprocess has the same privileges that tar originally did.
This commit is contained in:
@@ -144,7 +144,7 @@ set_mode (char const *file_name,
|
||||
char typeflag)
|
||||
{
|
||||
mode_t mode;
|
||||
bool failed;
|
||||
int chmod_errno;
|
||||
|
||||
if (0 < same_permissions_option
|
||||
&& permstatus != INTERDIR_PERMSTATUS)
|
||||
@@ -187,18 +187,24 @@ set_mode (char const *file_name,
|
||||
mode = cur_info->st_mode ^ invert_permissions;
|
||||
}
|
||||
|
||||
failed = chmod (file_name, mode) != 0;
|
||||
if (failed && errno == EPERM)
|
||||
chmod_errno = chmod (file_name, mode) == 0 ? 0 : errno;
|
||||
if (chmod_errno == EPERM && (mode & S_ISUID) != 0)
|
||||
{
|
||||
/* On Solaris, chmod may fail if we don't have PRIV_ALL. */
|
||||
/* On Solaris, chmod may fail if we don't have PRIV_ALL, because
|
||||
setuid-root files would otherwise be a backdoor. See
|
||||
http://opensolaris.org/jive/thread.jspa?threadID=95826
|
||||
(2009-09-03). */
|
||||
if (priv_set_restore_linkdir () == 0)
|
||||
{
|
||||
failed = chmod (file_name, mode) != 0;
|
||||
chmod_errno = chmod (file_name, mode) == 0 ? 0 : errno;
|
||||
priv_set_remove_linkdir ();
|
||||
}
|
||||
}
|
||||
if (failed)
|
||||
chmod_error_details (file_name, mode);
|
||||
if (chmod_errno)
|
||||
{
|
||||
errno = chmod_errno;
|
||||
chmod_error_details (file_name, mode);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check time after successfully setting FILE_NAME's time stamp to T. */
|
||||
@@ -1271,9 +1277,6 @@ extract_archive (void)
|
||||
|
||||
fatal_exit_hook = extract_finish;
|
||||
|
||||
/* Try to disable the ability to unlink a directory. */
|
||||
priv_set_remove_linkdir ();
|
||||
|
||||
set_next_block_after (current_header);
|
||||
|
||||
if (!current_stat_info.file_name[0]
|
||||
|
||||
11
src/system.c
11
src/system.c
@@ -1,7 +1,7 @@
|
||||
/* System-dependent calls for tar.
|
||||
|
||||
Copyright (C) 2003, 2004, 2005, 2006, 2007,
|
||||
2008 Free Software Foundation, Inc.
|
||||
2008, 2010 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <system.h>
|
||||
|
||||
#include "common.h"
|
||||
#include <priv-set.h>
|
||||
#include <rmt.h>
|
||||
#include <signal.h>
|
||||
|
||||
@@ -192,6 +193,7 @@ sys_spawn_shell (void)
|
||||
child = xfork ();
|
||||
if (child == 0)
|
||||
{
|
||||
priv_set_restore_linkdir ();
|
||||
execlp (shell, "-sh", "-i", (char *) 0);
|
||||
exec_fatal (shell);
|
||||
}
|
||||
@@ -362,6 +364,7 @@ sys_child_open_for_compress (void)
|
||||
}
|
||||
xdup2 (archive, STDOUT_FILENO);
|
||||
}
|
||||
priv_set_restore_linkdir ();
|
||||
execlp (use_compress_program_option, use_compress_program_option, NULL);
|
||||
exec_fatal (use_compress_program_option);
|
||||
}
|
||||
@@ -379,6 +382,7 @@ sys_child_open_for_compress (void)
|
||||
|
||||
xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
|
||||
xclose (child_pipe[PREAD]);
|
||||
priv_set_restore_linkdir ();
|
||||
execlp (use_compress_program_option, use_compress_program_option,
|
||||
(char *) 0);
|
||||
exec_fatal (use_compress_program_option);
|
||||
@@ -496,6 +500,7 @@ sys_child_open_for_uncompress (void)
|
||||
if (archive < 0)
|
||||
open_fatal (archive_name_array[0]);
|
||||
xdup2 (archive, STDIN_FILENO);
|
||||
priv_set_restore_linkdir ();
|
||||
execlp (use_compress_program_option, use_compress_program_option,
|
||||
"-d", (char *) 0);
|
||||
exec_fatal (use_compress_program_option);
|
||||
@@ -514,6 +519,7 @@ sys_child_open_for_uncompress (void)
|
||||
|
||||
xdup2 (child_pipe[PREAD], STDIN_FILENO);
|
||||
xclose (child_pipe[PWRITE]);
|
||||
priv_set_restore_linkdir ();
|
||||
execlp (use_compress_program_option, use_compress_program_option,
|
||||
"-d", (char *) 0);
|
||||
exec_fatal (use_compress_program_option);
|
||||
@@ -702,6 +708,7 @@ sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st)
|
||||
argv[2] = to_command_option;
|
||||
argv[3] = NULL;
|
||||
|
||||
priv_set_restore_linkdir ();
|
||||
execv ("/bin/sh", argv);
|
||||
|
||||
exec_fatal (file_name);
|
||||
@@ -816,6 +823,7 @@ sys_exec_info_script (const char **archive_name, int volume_number)
|
||||
argv[2] = (char *) info_script_option;
|
||||
argv[3] = NULL;
|
||||
|
||||
priv_set_restore_linkdir ();
|
||||
execv (argv[0], argv);
|
||||
|
||||
exec_fatal (info_script_option);
|
||||
@@ -863,6 +871,7 @@ sys_exec_checkpoint_script (const char *script_name,
|
||||
argv[2] = (char *) script_name;
|
||||
argv[3] = NULL;
|
||||
|
||||
priv_set_restore_linkdir ();
|
||||
execv (argv[0], argv);
|
||||
|
||||
exec_fatal (script_name);
|
||||
|
||||
Reference in New Issue
Block a user