mirror of
https://https.git.savannah.gnu.org/git/gettext.git
synced 2026-01-26 15:39:11 +00:00
Avoid symlink attack in localcharset module. Use fcntl_h.m4 from gnulib.
This commit is contained in:
parent
e487ecf4c9
commit
8c4ff981d5
@ -1,3 +1,8 @@
|
||||
2009-10-18 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
* Makefile.am (distcheck-hook): Compare fcntl_h.m4.
|
||||
* PACKAGING: Mention also fcntl_h.m4.
|
||||
|
||||
2009-09-27 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
* NEWS: Mention configure options --without-cvs and --with-git.
|
||||
|
||||
@ -43,6 +43,7 @@ distcheck-hook:
|
||||
cmp -s gettext-runtime/po/remove-potcdate.sin gettext-tools/po/remove-potcdate.sin
|
||||
cmp -s gettext-runtime/po/remove-potcdate.sin gettext-tools/examples/po/remove-potcdate.sin
|
||||
cmp -s gettext-runtime/m4/codeset.m4 gettext-tools/gnulib-m4/codeset.m4
|
||||
cmp -s gettext-runtime/m4/fcntl_h.m4 gettext-tools/gnulib-m4/fcntl_h.m4
|
||||
cmp -s gettext-runtime/m4/gettext.m4 gettext-tools/gnulib-m4/gettext.m4
|
||||
cmp -s gettext-runtime/m4/glibc2.m4 gettext-tools/gnulib-m4/glibc2.m4
|
||||
cmp -s gettext-runtime/m4/glibc21.m4 gettext-tools/gnulib-m4/glibc21.m4
|
||||
|
||||
@ -117,6 +117,7 @@ following file list.
|
||||
$prefix/share/gettext/archive.git.tar.gz (only installed if --with-git specified)
|
||||
$prefix/share/gettext/archive.dir.tar.gz (only installed if --without-cvs specified)
|
||||
$prefix/share/aclocal/codeset.m4
|
||||
$prefix/share/aclocal/fcntl_h.m4
|
||||
$prefix/share/aclocal/gettext.m4
|
||||
$prefix/share/aclocal/glibc2.m4
|
||||
$prefix/share/aclocal/glibc21.m4
|
||||
|
||||
@ -1,3 +1,11 @@
|
||||
2009-10-18 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
Avoid symlink attack in localcharset module.
|
||||
* localcharset.c: Include <fcntl.h>, <unistd.h>.
|
||||
(O_NOFOLLOW): Define fallback.
|
||||
(get_charset_aliases): Don't open the file if it is a symbolic link.
|
||||
Reported by Fergal Glynn <fglynn@veracode.com>.
|
||||
|
||||
2009-08-20 Eric Blake <ebb9@byu.net>
|
||||
|
||||
* vasnprintf.c (decimal_point_char): Avoid warning on old-style
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
/* Specification. */
|
||||
#include "localcharset.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -45,6 +46,7 @@
|
||||
#endif
|
||||
|
||||
#if !defined WIN32_NATIVE
|
||||
# include <unistd.h>
|
||||
# if HAVE_LANGINFO_CODESET
|
||||
# include <langinfo.h>
|
||||
# else
|
||||
@ -76,6 +78,11 @@
|
||||
# include "configmake.h"
|
||||
#endif
|
||||
|
||||
/* Define O_NOFOLLOW to 0 on platforms where it does not exist. */
|
||||
#ifndef O_NOFOLLOW
|
||||
# define O_NOFOLLOW 0
|
||||
#endif
|
||||
|
||||
#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
|
||||
/* Win32, Cygwin, OS/2, DOS */
|
||||
# define ISSLASH(C) ((C) == '/' || (C) == '\\')
|
||||
@ -118,7 +125,6 @@ get_charset_aliases (void)
|
||||
if (cp == NULL)
|
||||
{
|
||||
#if !(defined DARWIN7 || defined VMS || defined WIN32_NATIVE || defined __CYGWIN__)
|
||||
FILE *fp;
|
||||
const char *dir;
|
||||
const char *base = "charset.alias";
|
||||
char *file_name;
|
||||
@ -144,77 +150,105 @@ get_charset_aliases (void)
|
||||
}
|
||||
}
|
||||
|
||||
if (file_name == NULL || (fp = fopen (file_name, "r")) == NULL)
|
||||
/* Out of memory or file not found, treat it as empty. */
|
||||
if (file_name == NULL)
|
||||
/* Out of memory. Treat the file as empty. */
|
||||
cp = "";
|
||||
else
|
||||
{
|
||||
/* Parse the file's contents. */
|
||||
char *res_ptr = NULL;
|
||||
size_t res_size = 0;
|
||||
int fd;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int c;
|
||||
char buf1[50+1];
|
||||
char buf2[50+1];
|
||||
size_t l1, l2;
|
||||
char *old_res_ptr;
|
||||
|
||||
c = getc (fp);
|
||||
if (c == EOF)
|
||||
break;
|
||||
if (c == '\n' || c == ' ' || c == '\t')
|
||||
continue;
|
||||
if (c == '#')
|
||||
{
|
||||
/* Skip comment, to end of line. */
|
||||
do
|
||||
c = getc (fp);
|
||||
while (!(c == EOF || c == '\n'));
|
||||
if (c == EOF)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
ungetc (c, fp);
|
||||
if (fscanf (fp, "%50s %50s", buf1, buf2) < 2)
|
||||
break;
|
||||
l1 = strlen (buf1);
|
||||
l2 = strlen (buf2);
|
||||
old_res_ptr = res_ptr;
|
||||
if (res_size == 0)
|
||||
{
|
||||
res_size = l1 + 1 + l2 + 1;
|
||||
res_ptr = (char *) malloc (res_size + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
res_size += l1 + 1 + l2 + 1;
|
||||
res_ptr = (char *) realloc (res_ptr, res_size + 1);
|
||||
}
|
||||
if (res_ptr == NULL)
|
||||
{
|
||||
/* Out of memory. */
|
||||
res_size = 0;
|
||||
if (old_res_ptr != NULL)
|
||||
free (old_res_ptr);
|
||||
break;
|
||||
}
|
||||
strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1);
|
||||
strcpy (res_ptr + res_size - (l2 + 1), buf2);
|
||||
}
|
||||
fclose (fp);
|
||||
if (res_size == 0)
|
||||
/* Open the file. Reject symbolic links on platforms that support
|
||||
O_NOFOLLOW. This is a security feature. Without it, an attacker
|
||||
could retrieve parts of the contents (namely, the tail of the
|
||||
first line that starts with "* ") of an arbitrary file by placing
|
||||
a symbolic link to that file under the name "charset.alias" in
|
||||
some writable directory and defining the environment variable
|
||||
CHARSETALIASDIR to point to that directory. */
|
||||
fd = open (file_name,
|
||||
O_RDONLY | (HAVE_WORKING_O_NOFOLLOW ? O_NOFOLLOW : 0));
|
||||
if (fd < 0)
|
||||
/* File not found. Treat it as empty. */
|
||||
cp = "";
|
||||
else
|
||||
{
|
||||
*(res_ptr + res_size) = '\0';
|
||||
cp = res_ptr;
|
||||
}
|
||||
}
|
||||
FILE *fp;
|
||||
|
||||
if (file_name != NULL)
|
||||
free (file_name);
|
||||
fp = fdopen (fd, "r");
|
||||
if (fp == NULL)
|
||||
{
|
||||
/* Out of memory. Treat the file as empty. */
|
||||
close (fd);
|
||||
cp = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Parse the file's contents. */
|
||||
char *res_ptr = NULL;
|
||||
size_t res_size = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int c;
|
||||
char buf1[50+1];
|
||||
char buf2[50+1];
|
||||
size_t l1, l2;
|
||||
char *old_res_ptr;
|
||||
|
||||
c = getc (fp);
|
||||
if (c == EOF)
|
||||
break;
|
||||
if (c == '\n' || c == ' ' || c == '\t')
|
||||
continue;
|
||||
if (c == '#')
|
||||
{
|
||||
/* Skip comment, to end of line. */
|
||||
do
|
||||
c = getc (fp);
|
||||
while (!(c == EOF || c == '\n'));
|
||||
if (c == EOF)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
ungetc (c, fp);
|
||||
if (fscanf (fp, "%50s %50s", buf1, buf2) < 2)
|
||||
break;
|
||||
l1 = strlen (buf1);
|
||||
l2 = strlen (buf2);
|
||||
old_res_ptr = res_ptr;
|
||||
if (res_size == 0)
|
||||
{
|
||||
res_size = l1 + 1 + l2 + 1;
|
||||
res_ptr = (char *) malloc (res_size + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
res_size += l1 + 1 + l2 + 1;
|
||||
res_ptr = (char *) realloc (res_ptr, res_size + 1);
|
||||
}
|
||||
if (res_ptr == NULL)
|
||||
{
|
||||
/* Out of memory. */
|
||||
res_size = 0;
|
||||
if (old_res_ptr != NULL)
|
||||
free (old_res_ptr);
|
||||
break;
|
||||
}
|
||||
strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1);
|
||||
strcpy (res_ptr + res_size - (l2 + 1), buf2);
|
||||
}
|
||||
fclose (fp);
|
||||
if (res_size == 0)
|
||||
cp = "";
|
||||
else
|
||||
{
|
||||
*(res_ptr + res_size) = '\0';
|
||||
cp = res_ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free (file_name);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
||||
@ -1,3 +1,9 @@
|
||||
2009-10-18 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
* fcntl_h.m4: New file, from gnulib.
|
||||
* intl.m4 (AM_INTL_SUBDIR): Require gl_FCNTL_O_FLAGS.
|
||||
* Makefile.am (EXTRA_DIST): Add fcntl_h.m4.
|
||||
|
||||
2009-08-14 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
* eoverflow.m4: Remove file. Obsoleted by gnulib's 'errno' module.
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
EXTRA_DIST = README \
|
||||
ansi-c++.m4 \
|
||||
codeset.m4 \
|
||||
fcntl_h.m4 \
|
||||
gettext.m4 \
|
||||
glibc2.m4 \
|
||||
glibc21.m4 \
|
||||
|
||||
108
gettext-runtime/m4/fcntl_h.m4
Normal file
108
gettext-runtime/m4/fcntl_h.m4
Normal file
@ -0,0 +1,108 @@
|
||||
# serial 6
|
||||
# Configure fcntl.h.
|
||||
dnl Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
dnl Written by Paul Eggert.
|
||||
|
||||
AC_DEFUN([gl_FCNTL_H],
|
||||
[
|
||||
AC_REQUIRE([gl_FCNTL_H_DEFAULTS])
|
||||
AC_REQUIRE([gl_FCNTL_O_FLAGS])
|
||||
gl_CHECK_NEXT_HEADERS([fcntl.h])
|
||||
FCNTL_H='fcntl.h'
|
||||
AC_SUBST([FCNTL_H])
|
||||
])
|
||||
|
||||
# Test whether the flags O_NOATIME and O_NOFOLLOW actually work.
|
||||
# Define HAVE_WORKING_O_NOATIME to 1 if O_NOATIME works, or to 0 otherwise.
|
||||
# Define HAVE_WORKING_O_NOFOLLOW to 1 if O_NOFOLLOW works, or to 0 otherwise.
|
||||
AC_DEFUN([gl_FCNTL_O_FLAGS],
|
||||
[
|
||||
dnl Persuade glibc <fcntl.h> to define O_NOATIME and O_NOFOLLOW.
|
||||
AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
|
||||
AC_CACHE_CHECK([for working fcntl.h], [gl_cv_header_working_fcntl_h],
|
||||
[AC_RUN_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#ifndef O_NOATIME
|
||||
#define O_NOATIME 0
|
||||
#endif
|
||||
#ifndef O_NOFOLLOW
|
||||
#define O_NOFOLLOW 0
|
||||
#endif
|
||||
static int const constants[] =
|
||||
{
|
||||
O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC, O_APPEND,
|
||||
O_NONBLOCK, O_SYNC, O_ACCMODE, O_RDONLY, O_RDWR, O_WRONLY
|
||||
};
|
||||
]],
|
||||
[[
|
||||
int status = !constants;
|
||||
{
|
||||
static char const sym[] = "conftest.sym";
|
||||
if (symlink (".", sym) != 0
|
||||
|| close (open (sym, O_RDONLY | O_NOFOLLOW)) == 0)
|
||||
status |= 32;
|
||||
unlink (sym);
|
||||
}
|
||||
{
|
||||
static char const file[] = "confdefs.h";
|
||||
int fd = open (file, O_RDONLY | O_NOATIME);
|
||||
char c;
|
||||
struct stat st0, st1;
|
||||
if (fd < 0
|
||||
|| fstat (fd, &st0) != 0
|
||||
|| sleep (1) != 0
|
||||
|| read (fd, &c, 1) != 1
|
||||
|| close (fd) != 0
|
||||
|| stat (file, &st1) != 0
|
||||
|| st0.st_atime != st1.st_atime)
|
||||
status |= 64;
|
||||
}
|
||||
return status;]])],
|
||||
[gl_cv_header_working_fcntl_h=yes],
|
||||
[case $? in #(
|
||||
32) gl_cv_header_working_fcntl_h='no (bad O_NOFOLLOW)';; #(
|
||||
64) gl_cv_header_working_fcntl_h='no (bad O_NOATIME)';; #(
|
||||
96) gl_cv_header_working_fcntl_h='no (bad O_NOATIME, O_NOFOLLOW)';; #(
|
||||
*) gl_cv_header_working_fcntl_h='no';;
|
||||
esac],
|
||||
[gl_cv_header_working_fcntl_h=cross-compiling])])
|
||||
|
||||
case $gl_cv_header_working_fcntl_h in #(
|
||||
*O_NOATIME* | no | cross-compiling) ac_val=0;; #(
|
||||
*) ac_val=1;;
|
||||
esac
|
||||
AC_DEFINE_UNQUOTED([HAVE_WORKING_O_NOATIME], [$ac_val],
|
||||
[Define to 1 if O_NOATIME works.])
|
||||
|
||||
case $gl_cv_header_working_fcntl_h in #(
|
||||
*O_NOFOLLOW* | no | cross-compiling) ac_val=0;; #(
|
||||
*) ac_val=1;;
|
||||
esac
|
||||
AC_DEFINE_UNQUOTED([HAVE_WORKING_O_NOFOLLOW], [$ac_val],
|
||||
[Define to 1 if O_NOFOLLOW works.])
|
||||
])
|
||||
|
||||
AC_DEFUN([gl_FCNTL_MODULE_INDICATOR],
|
||||
[
|
||||
dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
|
||||
AC_REQUIRE([gl_FCNTL_H_DEFAULTS])
|
||||
GNULIB_[]m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./-],[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])=1
|
||||
])
|
||||
|
||||
AC_DEFUN([gl_FCNTL_H_DEFAULTS],
|
||||
[
|
||||
GNULIB_OPEN=0; AC_SUBST([GNULIB_OPEN])
|
||||
GNULIB_OPENAT=0; AC_SUBST([GNULIB_OPENAT])
|
||||
dnl Assume proper GNU behavior unless another module says otherwise.
|
||||
HAVE_OPENAT=1; AC_SUBST([HAVE_OPENAT])
|
||||
REPLACE_OPEN=0; AC_SUBST([REPLACE_OPEN])
|
||||
REPLACE_OPENAT=0; AC_SUBST([REPLACE_OPENAT])
|
||||
])
|
||||
@ -1,4 +1,4 @@
|
||||
# intl.m4 serial 13 (gettext-0.18)
|
||||
# intl.m4 serial 14 (gettext-0.18)
|
||||
dnl Copyright (C) 1995-2009 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
@ -40,6 +40,7 @@ AC_DEFUN([AM_INTL_SUBDIR],
|
||||
AC_REQUIRE([gt_PRINTF_POSIX])
|
||||
AC_REQUIRE([gl_GLIBC21])dnl
|
||||
AC_REQUIRE([gl_XSIZE])dnl
|
||||
AC_REQUIRE([gl_FCNTL_O_FLAGS])dnl
|
||||
AC_REQUIRE([gt_INTL_MACOSX])dnl
|
||||
|
||||
dnl Support for automake's --enable-silent-rules.
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
2009-10-18 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
* gettext.texi (aclocal): Add fcntl_h.m4 to the file list.
|
||||
|
||||
2009-09-20 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
* gettext.texi (src/Makefile): Update recommendations for autoconf
|
||||
|
||||
@ -7934,7 +7934,7 @@ automake 1.9.
|
||||
@cindex @file{aclocal.m4} file
|
||||
|
||||
If you do not have an @file{aclocal.m4} file in your distribution,
|
||||
the simplest is to concatenate the files @file{codeset.m4},
|
||||
the simplest is to concatenate the files @file{codeset.m4}, @file{fcntl_h.m4},
|
||||
@file{gettext.m4}, @file{glibc2.m4}, @file{glibc21.m4}, @file{iconv.m4},
|
||||
@file{intdiv0.m4}, @file{intl.m4}, @file{intldir.m4}, @file{intlmacosx.m4},
|
||||
@file{intmax.m4}, @file{inttypes_h.m4}, @file{inttypes-pri.m4},
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
2009-10-18 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
* Makefile.am (aclocal_DATA): Add fcntl_h.m4.
|
||||
|
||||
2009-08-15 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
Stop using gnulib module 'strdup'.
|
||||
|
||||
@ -8,6 +8,7 @@ aclocal_DATA = \
|
||||
../../autoconf-lib-link/m4/lib-link.m4 \
|
||||
../../autoconf-lib-link/m4/lib-prefix.m4 \
|
||||
../../gettext-runtime/m4/codeset.m4 \
|
||||
../../gettext-runtime/m4/fcntl_h.m4 \
|
||||
../../gettext-runtime/m4/gettext.m4 \
|
||||
../../gettext-runtime/m4/glibc2.m4 \
|
||||
../../gettext-runtime/m4/glibc21.m4 \
|
||||
|
||||
@ -1,3 +1,8 @@
|
||||
2009-10-18 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
* gettextize.in (m4filelist): Add fcntl_h.m4 to the list.
|
||||
(func_version): Bump copyright year.
|
||||
|
||||
2009-09-27 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
* add-to-archive: Pass option -fPIC to gcc. Clean up cvsuser.so.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# Copyright (C) 1995-1998, 2000-2008 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1995-1998, 2000-2009 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
|
||||
@ -174,7 +174,7 @@ Report bugs to <bug-gnu-gettext@gnu.org>."
|
||||
func_version ()
|
||||
{
|
||||
echo "$progname (GNU $package) $version"
|
||||
echo "Copyright (C) 1995-1998, 2000-2008 Free Software Foundation, Inc.
|
||||
echo "Copyright (C) 1995-1998, 2000-2009 Free Software Foundation, Inc.
|
||||
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
||||
This is free software: you are free to change and redistribute it.
|
||||
There is NO WARRANTY, to the extent permitted by law."
|
||||
@ -768,8 +768,8 @@ m4filelist='gettext.m4 iconv.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 nls.m4
|
||||
min_automake_version=1.9
|
||||
if test -n "$intldir" || test -z "$have_automake19"; then
|
||||
# Add intldir.m4, intl.m4 and its dependencies.
|
||||
m4filelist=$m4filelist' codeset.m4 glibc2.m4 glibc21.m4 intdiv0.m4 intl.m4
|
||||
intldir.m4 intlmacosx.m4 intmax.m4 inttypes_h.m4 inttypes-pri.m4
|
||||
m4filelist=$m4filelist' codeset.m4 fcntl_h.m4 glibc2.m4 glibc21.m4 intdiv0.m4
|
||||
intl.m4 intldir.m4 intlmacosx.m4 intmax.m4 inttypes_h.m4 inttypes-pri.m4
|
||||
lcmessage.m4 lock.m4 longlong.m4 printf-posix.m4 size_max.m4 stdint_h.m4
|
||||
threadlib.m4 uintmax_t.m4 visibility.m4 wchar_t.m4 wint_t.m4 xsize.m4'
|
||||
min_automake_version=1.8
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user