forked from aniani/vim
patch 8.0.1300: file permissions may end up wrong when writing
Problem: File permissions may end up wrong when writing. Solution: Use fchmod() instead of chmod() when possible. Don't truncate until we know we can change the file.
This commit is contained in:
parent
a42ad57e48
commit
cd142e3369
4
src/auto/configure
vendored
4
src/auto/configure
vendored
@ -12090,13 +12090,13 @@ if test "x$vim_cv_getcwd_broken" = "xyes" ; then
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for ac_func in fchdir fchown fsync getcwd getpseudotty \
|
for ac_func in fchdir fchown fchmod fsync getcwd getpseudotty \
|
||||||
getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat \
|
getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat \
|
||||||
memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
|
memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
|
||||||
getpgid setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
|
getpgid setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
|
||||||
sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
|
sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
|
||||||
strnicmp strpbrk strtol tgetent towlower towupper iswupper \
|
strnicmp strpbrk strtol tgetent towlower towupper iswupper \
|
||||||
usleep utime utimes mblen
|
usleep utime utimes mblen ftruncate
|
||||||
do :
|
do :
|
||||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||||
|
@ -156,9 +156,11 @@
|
|||||||
/* Define if you the function: */
|
/* Define if you the function: */
|
||||||
#undef HAVE_FCHDIR
|
#undef HAVE_FCHDIR
|
||||||
#undef HAVE_FCHOWN
|
#undef HAVE_FCHOWN
|
||||||
|
#undef HAVE_FCHMOD
|
||||||
|
#undef HAVE_FLOAT_FUNCS
|
||||||
#undef HAVE_FSEEKO
|
#undef HAVE_FSEEKO
|
||||||
#undef HAVE_FSYNC
|
#undef HAVE_FSYNC
|
||||||
#undef HAVE_FLOAT_FUNCS
|
#undef HAVE_FTRUNCATE
|
||||||
#undef HAVE_GETCWD
|
#undef HAVE_GETCWD
|
||||||
#undef HAVE_GETPGID
|
#undef HAVE_GETPGID
|
||||||
#undef HAVE_GETPSEUDOTTY
|
#undef HAVE_GETPSEUDOTTY
|
||||||
|
@ -3655,13 +3655,13 @@ fi
|
|||||||
|
|
||||||
dnl Check for functions in one big call, to reduce the size of configure.
|
dnl Check for functions in one big call, to reduce the size of configure.
|
||||||
dnl Can only be used for functions that do not require any include.
|
dnl Can only be used for functions that do not require any include.
|
||||||
AC_CHECK_FUNCS(fchdir fchown fsync getcwd getpseudotty \
|
AC_CHECK_FUNCS(fchdir fchown fchmod fsync getcwd getpseudotty \
|
||||||
getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat \
|
getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat \
|
||||||
memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
|
memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
|
||||||
getpgid setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
|
getpgid setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
|
||||||
sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
|
sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
|
||||||
strnicmp strpbrk strtol tgetent towlower towupper iswupper \
|
strnicmp strpbrk strtol tgetent towlower towupper iswupper \
|
||||||
usleep utime utimes mblen)
|
usleep utime utimes mblen ftruncate)
|
||||||
AC_FUNC_FSEEKO
|
AC_FUNC_FSEEKO
|
||||||
|
|
||||||
dnl define _LARGE_FILES, _FILE_OFFSET_BITS and _LARGEFILE_SOURCE when
|
dnl define _LARGE_FILES, _FILE_OFFSET_BITS and _LARGEFILE_SOURCE when
|
||||||
|
80
src/fileio.c
80
src/fileio.c
@ -3863,6 +3863,7 @@ buf_write(
|
|||||||
char_u *rootname;
|
char_u *rootname;
|
||||||
#if defined(UNIX)
|
#if defined(UNIX)
|
||||||
int did_set_shortname;
|
int did_set_shortname;
|
||||||
|
mode_t umask_save;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
copybuf = alloc(BUFSIZE + 1);
|
copybuf = alloc(BUFSIZE + 1);
|
||||||
@ -3994,10 +3995,17 @@ buf_write(
|
|||||||
/* remove old backup, if present */
|
/* remove old backup, if present */
|
||||||
mch_remove(backup);
|
mch_remove(backup);
|
||||||
/* Open with O_EXCL to avoid the file being created while
|
/* Open with O_EXCL to avoid the file being created while
|
||||||
* we were sleeping (symlink hacker attack?) */
|
* we were sleeping (symlink hacker attack?). Reset umask
|
||||||
|
* if possible to avoid mch_setperm() below. */
|
||||||
|
#ifdef UNIX
|
||||||
|
umask_save = umask(0);
|
||||||
|
#endif
|
||||||
bfd = mch_open((char *)backup,
|
bfd = mch_open((char *)backup,
|
||||||
O_WRONLY|O_CREAT|O_EXTRA|O_EXCL|O_NOFOLLOW,
|
O_WRONLY|O_CREAT|O_EXTRA|O_EXCL|O_NOFOLLOW,
|
||||||
perm & 0777);
|
perm & 0777);
|
||||||
|
#ifdef UNIX
|
||||||
|
(void)umask(umask_save);
|
||||||
|
#endif
|
||||||
if (bfd < 0)
|
if (bfd < 0)
|
||||||
{
|
{
|
||||||
vim_free(backup);
|
vim_free(backup);
|
||||||
@ -4005,11 +4013,12 @@ buf_write(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* set file protection same as original file, but
|
/* Set file protection same as original file, but
|
||||||
* strip s-bit */
|
* strip s-bit. Only needed if umask() wasn't used
|
||||||
|
* above. */
|
||||||
|
#ifndef UNIX
|
||||||
(void)mch_setperm(backup, perm & 0777);
|
(void)mch_setperm(backup, perm & 0777);
|
||||||
|
#else
|
||||||
#ifdef UNIX
|
|
||||||
/*
|
/*
|
||||||
* Try to set the group of the backup same as the
|
* Try to set the group of the backup same as the
|
||||||
* original file. If this fails, set the protection
|
* original file. If this fails, set the protection
|
||||||
@ -4377,6 +4386,11 @@ buf_write(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_FTRUNCATE
|
||||||
|
# define TRUNC_ON_OPEN 0
|
||||||
|
#else
|
||||||
|
# define TRUNC_ON_OPEN O_TRUNC
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* Open the file "wfname" for writing.
|
* Open the file "wfname" for writing.
|
||||||
* We may try to open the file twice: If we can't write to the file
|
* We may try to open the file twice: If we can't write to the file
|
||||||
@ -4389,7 +4403,7 @@ buf_write(
|
|||||||
*/
|
*/
|
||||||
while ((fd = mch_open((char *)wfname, O_WRONLY | O_EXTRA | (append
|
while ((fd = mch_open((char *)wfname, O_WRONLY | O_EXTRA | (append
|
||||||
? (forceit ? (O_APPEND | O_CREAT) : O_APPEND)
|
? (forceit ? (O_APPEND | O_CREAT) : O_APPEND)
|
||||||
: (O_CREAT | O_TRUNC))
|
: (O_CREAT | TRUNC_ON_OPEN))
|
||||||
, perm < 0 ? 0666 : (perm & 0777))) < 0)
|
, perm < 0 ? 0666 : (perm & 0777))) < 0)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -4482,6 +4496,30 @@ restore_backup:
|
|||||||
}
|
}
|
||||||
write_info.bw_fd = fd;
|
write_info.bw_fd = fd;
|
||||||
|
|
||||||
|
#if defined(UNIX)
|
||||||
|
{
|
||||||
|
stat_T st;
|
||||||
|
|
||||||
|
/* Double check we are writing the intended file before making
|
||||||
|
* any changes. */
|
||||||
|
if (overwriting
|
||||||
|
&& (!dobackup || backup_copy)
|
||||||
|
&& fname == wfname
|
||||||
|
&& perm >= 0
|
||||||
|
&& mch_fstat(fd, &st) == 0
|
||||||
|
&& st.st_ino != st_old.st_ino)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
errmsg = (char_u *)_("E949: File changed while writing");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FTRUNCATE
|
||||||
|
if (!append)
|
||||||
|
ftruncate(fd, (off_t)0);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(WIN3264)
|
#if defined(WIN3264)
|
||||||
if (backup != NULL && overwriting && !append)
|
if (backup != NULL && overwriting && !append)
|
||||||
{
|
{
|
||||||
@ -4752,15 +4790,17 @@ restore_backup:
|
|||||||
# ifdef HAVE_FCHOWN
|
# ifdef HAVE_FCHOWN
|
||||||
stat_T st;
|
stat_T st;
|
||||||
|
|
||||||
/* don't change the owner when it's already OK, some systems remove
|
/* Don't change the owner when it's already OK, some systems remove
|
||||||
* permission or ACL stuff */
|
* permission or ACL stuff. */
|
||||||
if (mch_stat((char *)wfname, &st) < 0
|
if (mch_stat((char *)wfname, &st) < 0
|
||||||
|| st.st_uid != st_old.st_uid
|
|| st.st_uid != st_old.st_uid
|
||||||
|| st.st_gid != st_old.st_gid)
|
|| st.st_gid != st_old.st_gid)
|
||||||
{
|
{
|
||||||
ignored = fchown(fd, st_old.st_uid, st_old.st_gid);
|
/* changing owner might not be possible */
|
||||||
if (perm >= 0) /* set permission again, may have changed */
|
ignored = fchown(fd, st_old.st_uid, -1);
|
||||||
(void)mch_setperm(wfname, perm);
|
/* if changing group fails clear the group permissions */
|
||||||
|
if (fchown(fd, -1, st_old.st_gid) == -1 && perm > 0)
|
||||||
|
perm &= ~070;
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
buf_setino(buf);
|
buf_setino(buf);
|
||||||
@ -4770,18 +4810,26 @@ restore_backup:
|
|||||||
buf_setino(buf);
|
buf_setino(buf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
|
if (made_writable)
|
||||||
|
perm &= ~0200; /* reset 'w' bit for security reasons */
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FCHMOD
|
||||||
|
/* set permission of new file same as old file */
|
||||||
|
if (perm >= 0)
|
||||||
|
(void)mch_fsetperm(fd, perm);
|
||||||
|
#endif
|
||||||
if (close(fd) != 0)
|
if (close(fd) != 0)
|
||||||
{
|
{
|
||||||
errmsg = (char_u *)_("E512: Close failed");
|
errmsg = (char_u *)_("E512: Close failed");
|
||||||
end = 0;
|
end = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef UNIX
|
#ifndef HAVE_FCHMOD
|
||||||
if (made_writable)
|
/* set permission of new file same as old file */
|
||||||
perm &= ~0200; /* reset 'w' bit for security reasons */
|
if (perm >= 0)
|
||||||
#endif
|
|
||||||
if (perm >= 0) /* set perm. of new file same as old file */
|
|
||||||
(void)mch_setperm(wfname, perm);
|
(void)mch_setperm(wfname, perm);
|
||||||
|
#endif
|
||||||
#ifdef HAVE_ACL
|
#ifdef HAVE_ACL
|
||||||
/*
|
/*
|
||||||
* Probably need to set the ACL before changing the user (can't set the
|
* Probably need to set the ACL before changing the user (can't set the
|
||||||
|
@ -2725,9 +2725,8 @@ mch_getperm(char_u *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set file permission for 'name' to 'perm'
|
* Set file permission for "name" to "perm".
|
||||||
*
|
* Return FAIL for failure, OK otherwise.
|
||||||
* return FAIL for failure, OK otherwise
|
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
mch_setperm(char_u *name, long perm)
|
mch_setperm(char_u *name, long perm)
|
||||||
@ -2741,6 +2740,18 @@ mch_setperm(char_u *name, long perm)
|
|||||||
(mode_t)perm) == 0 ? OK : FAIL);
|
(mode_t)perm) == 0 ? OK : FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_FCHMOD) || defined(PROTO)
|
||||||
|
/*
|
||||||
|
* Set file permission for open file "fd" to "perm".
|
||||||
|
* Return FAIL for failure, OK otherwise.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
mch_fsetperm(int fd, long perm)
|
||||||
|
{
|
||||||
|
return (fchmod(fd, (mode_t)perm) == 0 ? OK : FAIL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_ACL) || defined(PROTO)
|
#if defined(HAVE_ACL) || defined(PROTO)
|
||||||
# ifdef HAVE_SYS_ACL_H
|
# ifdef HAVE_SYS_ACL_H
|
||||||
# include <sys/acl.h>
|
# include <sys/acl.h>
|
||||||
|
@ -36,6 +36,7 @@ int mch_isFullName(char_u *fname);
|
|||||||
void fname_case(char_u *name, int len);
|
void fname_case(char_u *name, int len);
|
||||||
long mch_getperm(char_u *name);
|
long mch_getperm(char_u *name);
|
||||||
int mch_setperm(char_u *name, long perm);
|
int mch_setperm(char_u *name, long perm);
|
||||||
|
int mch_fsetperm(int fd, long perm);
|
||||||
void mch_copy_sec(char_u *from_file, char_u *to_file);
|
void mch_copy_sec(char_u *from_file, char_u *to_file);
|
||||||
vim_acl_T mch_get_acl(char_u *fname);
|
vim_acl_T mch_get_acl(char_u *fname);
|
||||||
void mch_set_acl(char_u *fname, vim_acl_T aclent);
|
void mch_set_acl(char_u *fname, vim_acl_T aclent);
|
||||||
|
@ -766,6 +766,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1300,
|
||||||
/**/
|
/**/
|
||||||
1299,
|
1299,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user