Ported changes from 1.4.

This commit is contained in:
Werner Koch 2009-04-01 13:23:27 +00:00
parent f8b4cd7650
commit 0b99639624
8 changed files with 153 additions and 36 deletions

View File

@ -1,3 +1,7 @@
2009-04-01 Werner Koch <wk@g10code.com>
* configure.ac: Test for fsync.
2009-03-18 Werner Koch <wk@g10code.com>
* configure.ac: Test for getrlimit.

View File

@ -50,7 +50,7 @@ struct try_unprotect_arg_s
/* Write an S-expression formatted key to our key storage. With FORCE
pased as true an existing key with the given GRIP will get
passed as true an existing key with the given GRIP will get
overwritten. */
int
agent_write_private_key (const unsigned char *grip,

View File

@ -1,5 +1,14 @@
2009-04-01 Werner Koch <wk@g10code.com>
* iobuf.c: Port David's changes from 1.4:
(fd_cache_invalidate): Pass return code from close back.
(direct_open, iobuf_ioctl): Check that eturn value.
(fd_cache_synchronize): New.
(iobuf_ioctl): Add new sub command 4 (fsync).
* iobuf.c (fd_cache_strcmp): New. Taken from 1.4.
(fd_cache_invalidate, fd_cache_close, fd_cache_open): Use it.
* exechelp.c (gnupg_spawn_process): Implement new flag bit 6.
* sysutils.c (gnupg_allow_set_foregound_window): Allow the use of
ASFW_ANY.

View File

@ -1,6 +1,6 @@
/* iobuf.c - File Handling for OpenPGP.
* Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2006,
* 2007, 2008 Free Software Foundation, Inc.
* 2007, 2008, 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -48,7 +48,8 @@
test "armored_key_8192" in armor.test! */
#define IOBUF_BUFFER_SIZE 8192
/* We don't want to use the STDIO based backend. */
/* We don't want to use the STDIO based backend. If you change this
be aware that there is no fsync support for the stdio backend. */
#undef FILE_FILTER_USES_STDIO
/*-- End configurable part. --*/
@ -187,13 +188,32 @@ static int translate_file_handle (int fd, int for_write);
#ifndef FILE_FILTER_USES_STDIO
/* This is a replacement for strcmp. Under W32 it does not
distinguish between backslash and slash. */
static int
fd_cache_strcmp (const char *a, const char *b)
{
#ifdef HAVE_DOSISH_SYSTEM
for (; *a && *b; a++, b++)
{
if (*a != *b && !((*a == '/' && *b == '\\')
|| (*a == '\\' && *b == '/')) )
break;
}
return *(const unsigned char *)a - *(const unsigned char *)b;
#else
return strcmp (a, b);
#endif
}
/*
* Invalidate (i.e. close) a cached iobuf
*/
static void
static int
fd_cache_invalidate (const char *fname)
{
close_cache_t cc;
int rc = 0;
assert (fname);
if (DBG_IOBUF)
@ -201,18 +221,52 @@ fd_cache_invalidate (const char *fname)
for (cc = close_cache; cc; cc = cc->next)
{
if (cc->fp != INVALID_FP && !strcmp (cc->fname, fname))
if (cc->fp != INVALID_FP && !fd_cache_strcmp (cc->fname, fname))
{
if (DBG_IOBUF)
log_debug (" did (%s)\n", cc->fname);
#ifdef HAVE_W32_SYSTEM
CloseHandle (cc->fp);
if (!CloseHandle (cc->fp))
rc = -1;
#else
close (cc->fp);
rc = close (cc->fp);
#endif
cc->fp = INVALID_FP;
}
}
return rc;
}
/* Try to sync changes to the disk. This is to avoid data loss during
a system crash in write/close/rename cycle on some file
systems. */
static int
fd_cache_synchronize (const char *fname)
{
int err = 0;
#ifdef HAVE_FSYNC
close_cache_t cc;
if (DBG_IOBUF)
log_debug ("fd_cache_synchronize (%s)\n", fname);
for (cc=close_cache; cc; cc = cc->next )
{
if (cc->fp != INVALID_FP && !fd_cache_strcmp (cc->fname, fname))
{
if (DBG_IOBUF)
log_debug (" did (%s)\n", cc->fname);
err = fsync (cc->fp);
}
}
#else
(void)fname;
#endif /*HAVE_FSYNC*/
return err;
}
@ -226,19 +280,21 @@ direct_open (const char *fname, const char *mode)
/* Note, that we do not handle all mode combinations */
/* According to the ReactOS source it seems that open() of the
* standard MSW32 crt does open the file in share mode which is
* standard MSW32 crt does open the file in shared mode which is
* something new for MS applications ;-)
*/
if (strchr (mode, '+'))
{
fd_cache_invalidate (fname);
if (fd_cache_invalidate (fname))
return INVALID_FP;
da = GENERIC_READ | GENERIC_WRITE;
cd = OPEN_EXISTING;
sm = FILE_SHARE_READ | FILE_SHARE_WRITE;
}
else if (strchr (mode, 'w'))
{
fd_cache_invalidate (fname);
if (fd_cache_invalidate (fname))
return INVALID_FP;
da = GENERIC_WRITE;
cd = CREATE_ALWAYS;
sm = FILE_SHARE_WRITE;
@ -259,12 +315,14 @@ direct_open (const char *fname, const char *mode)
/* Note, that we do not handle all mode combinations */
if (strchr (mode, '+'))
{
fd_cache_invalidate (fname);
if (fd_cache_invalidate (fname))
return INVALID_FP;
oflag = O_RDWR;
}
else if (strchr (mode, 'w'))
{
fd_cache_invalidate (fname);
if (fd_cache_invalidate (fname))
return INVALID_FP;
oflag = O_WRONLY | O_CREAT | O_TRUNC;
}
else
@ -318,7 +376,7 @@ fd_cache_close (const char *fname, fp_or_fd_t fp)
/* try to reuse a slot */
for (cc = close_cache; cc; cc = cc->next)
{
if (cc->fp == INVALID_FP && !strcmp (cc->fname, fname))
if (cc->fp == INVALID_FP && !fd_cache_strcmp (cc->fname, fname))
{
cc->fp = fp;
if (DBG_IOBUF)
@ -347,7 +405,7 @@ fd_cache_open (const char *fname, const char *mode)
assert (fname);
for (cc = close_cache; cc; cc = cc->next)
{
if (cc->fp != INVALID_FP && !strcmp (cc->fname, fname))
if (cc->fp != INVALID_FP && !fd_cache_strcmp (cc->fname, fname))
{
fp_or_fd_t fp = cc->fp;
cc->fp = INVALID_FP;
@ -1449,7 +1507,8 @@ iobuf_ioctl (iobuf_t a, int cmd, int intval, void *ptrval)
if (!a && !intval && ptrval)
{
#ifndef FILE_FILTER_USES_STDIO
fd_cache_invalidate (ptrval);
if (fd_cache_invalidate (ptrval))
return -1;
#endif
return 0;
}
@ -1477,6 +1536,24 @@ iobuf_ioctl (iobuf_t a, int cmd, int intval, void *ptrval)
}
#endif
}
else if (cmd == 4)
{
/* Do a fsync on the open fd and return any errors to the caller
of iobuf_ioctl. Note that we work on a file name here. */
if (DBG_IOBUF)
log_debug ("iobuf-*.*: ioctl `%s' fsync\n",
ptrval? (const char*)ptrval:"<null>");
if (!a && !intval && ptrval)
{
#ifndef FILE_FILTER_USES_STDIO
return fd_cache_synchronize (ptrval);
#else
return 0;
#endif
}
}
return -1;
}
@ -2310,7 +2387,6 @@ iobuf_get_fname (iobuf_t a)
file_filter_ctx_t *b = a->filter_ov;
return b->fname;
}
return NULL;
}

View File

@ -1062,7 +1062,7 @@ AC_CHECK_FUNCS([unsetenv getpwnam getpwuid fcntl ftruncate])
AC_CHECK_FUNCS([gettimeofday getrusage getrlimit setrlimit clock_gettime])
AC_CHECK_FUNCS([atexit raise getpagesize strftime nl_langinfo setlocale])
AC_CHECK_FUNCS([waitpid wait4 sigaction sigprocmask pipe stat getaddrinfo])
AC_CHECK_FUNCS([ttyname rand ftello])
AC_CHECK_FUNCS([ttyname rand ftello fsync])
AC_CHECK_TYPES([struct sigaction, sigset_t],,,[#include <signal.h>])

View File

@ -1,3 +1,16 @@
2009-04-01 Werner Koch <wk@g10code.com>
* gpg.c (main): Properly handle UTF8 usernames with --sign-key and
--lsign-key. From 1.4, David 2008-12-21.
2009-03-20 David Shaw <dshaw@jabberwocky.com> (wk)
* keyring.c (rename_tmp_file): Force a fsync (via iobuf_ioctl) on
secret keyring files to be extra safe on filesystems that may not
sync data and metadata together (ext4). Also check return code
from the cache invalidation to make sure we're safe over NFS and
similar.
2009-03-31 Werner Koch <wk@g10code.com>
* passphrase.c (ask_passphrase): Use percent_plus_unescape.

View File

@ -3562,7 +3562,7 @@ main (int argc, char **argv)
append_to_strlist( &sl, "save" );
username = make_username( fname );
keyedit_menu(fname, locusr, sl, 0, 0 );
keyedit_menu (username, locusr, sl, 0, 0 );
xfree(username);
free_strlist(sl);
break;

View File

@ -1,5 +1,5 @@
/* keyring.c - keyring file handling
* Copyright (C) 2001, 2004 Free Software Foundation, Inc.
* Copyright (C) 2001, 2004, 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -1219,10 +1219,23 @@ static int
rename_tmp_file (const char *bakfname, const char *tmpfname,
const char *fname, int secret )
{
int rc=0;
int rc = 0;
/* invalidate close caches*/
iobuf_ioctl (NULL, 2, 0, (char*)tmpfname );
/* It's a secret keyring, so let's force a fsync just to be safe on
filesystems that may not sync data and metadata together
(e.g. ext4). */
if (secret && iobuf_ioctl (NULL, 4, 0, (char*)tmpfname))
{
rc = gpg_error_from_syserror ();
goto fail;
}
/* Invalidate close caches. */
if (iobuf_ioctl (NULL, 2, 0, (char*)tmpfname ))
{
rc = gpg_error_from_syserror ();
goto fail;
}
iobuf_ioctl (NULL, 2, 0, (char*)bakfname );
iobuf_ioctl (NULL, 2, 0, (char*)fname );
@ -1253,15 +1266,7 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
log_error (_("renaming `%s' to `%s' failed: %s\n"),
tmpfname, fname, strerror(errno) );
register_secured_file (fname);
if (secret)
{
log_info(_("WARNING: 2 files with confidential"
" information exists.\n"));
log_info(_("%s is the unchanged one\n"), fname );
log_info(_("%s is the new one\n"), tmpfname );
log_info(_("Please fix this possible security flaw\n"));
}
return rc;
goto fail;
}
/* Now make sure the file has the same permissions as the original */
@ -1272,17 +1277,27 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
statbuf.st_mode=S_IRUSR | S_IWUSR;
if(((secret && !opt.preserve_permissions) ||
(stat(bakfname,&statbuf)==0)) &&
(chmod(fname,statbuf.st_mode)==0))
if (((secret && !opt.preserve_permissions)
|| !stat (bakfname,&statbuf))
&& !chmod (fname,statbuf.st_mode))
;
else
log_error("WARNING: unable to restore permissions to `%s': %s",
fname,strerror(errno));
log_error ("WARNING: unable to restore permissions to `%s': %s",
fname, strerror(errno));
}
#endif
return 0;
fail:
if (secret)
{
log_info(_("WARNING: 2 files with confidential information exists.\n"));
log_info(_("%s is the unchanged one\n"), fname );
log_info(_("%s is the new one\n"), tmpfname );
log_info(_("Please fix this possible security flaw\n"));
}
return rc;
}