Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20140712164156.GL179@brightrain.aerifal.cx>
Date: Sat, 12 Jul 2014 12:41:56 -0400
From: Rich Felker <dalias@...c.org>
To: musl@...ts.openwall.com
Subject: Locale path and security [Was: Status towards next release (1.1.4)]

On Sat, Jul 12, 2014 at 11:03:33AM -0400, Rich Felker wrote:
> On Sat, Jul 12, 2014 at 01:10:35AM -0400, Rich Felker wrote:
> > - The Big Bikeshed: where to find locale files? These will be somewhat
> >   musl-specific (to the extent that no other implementation uses the
> >   design I have in mind, though it would be easy for others to use
> >   it), so there's no existing practice to simply adopt. The files are
> >   not machine-specific (we'll support either endianness .mo file) so
> >   /usr/share (or other prefix variants) is the natural base location.
> 
> One idea for this: just don't accept anything except the built-in
> locales (C, C.UTF-8, POSIX) and absolute pathnames. For suid programs,
> the latter could be rejected completely (the safest and probably what
> we should do) or restricted to a set of reasonable paths where each
> path component is checked for permissions.
> 
> Another idea is pulling the search path from /etc/musl-locale.conf or
> similar. Obviously this is not the most friendly to Rune's usage case,
> but it would just be one more hard-coded path to override in the
> custom build, or if absolute pathnames were also accepted for locales
> the support for /etc/musl-locale.conf could just be stripped out.

>From a usability standpoint, I think it's desirable to have some sort
of search path, even if absolute pathnames are also supported.
Consider mixed environments where the user has something like
LANG=fr_FR.UTF-8 for glibc programs; assuming the corresponding locale
is also installed for musl, the reasonable user expectation is that
musl-linked programs also use French messages, time formatting,
collation, etc.

glibc honors the non-POSIX environment variable LOCPATH to control its
search for locales. While this is something of a consideration for
applications trying to avoid unwanted environment-influenced behavior
for security purposes or otherwise, it's not a big conformance problem
since setlocale already depends on the environment anyway (and thus
can't be called safely in parallel with modifications to the
environment, per POSIX). We could honor the same variable and just
append "/musl/" to the value (this would be nice from the standpoint
of not introducing another variable apps have to be aware of when they
want to filter it) but that's somewhat ugly since the glibc one is
intended to point to a "lib" (arch-specific) dir whereas musl's is
portable data. Using a separate variable might be preferable if we
even want to support an environment variable as a way to configure
this at runtime -- and I think doing so may be valuable since users
may want locales that are not installed by the system administrator.

In light of glibc CVE-2014-0475, which I'm not sure is even really a
proper "vulnerability" but rather just a complication of the standard
locale semantics that makes it hard to write secure programs without
filtering out locale vars from untrusted sources, a major goal I'd
like to pursue is minimizing the potential security impact of an
untrusted/malicious locale file. Obviously suid/AT_SECURE programs
should not even honor locale files except possibly from a hard-coded
trusted source, but ideally even programs without formally elevated
privilegs -- think gitolite type setups with ssh authorized_keys --
would not yield code execution or information leak when fed a
malicious locale file.

Here are the security aspects I have in mind:

- For libc itself (obviously we can't control application use of
  gettext), only translate literal strings, never printf/scanf format
  strings. For dlerror this requires some refactoring of the message
  strings but otherwise I think this property is easy to satisfy. The
  purpose of this property is to prevent format string injection via
  locales and limit the scope of bad messages to literal copying of
  those messages into the program output.

- Avoid loading as a locale any file which was not intended to be a
  locale. This entails checking the magic number, sanity-checking the
  headers, and also doing a single gettext-type string lookup for a
  key string associated with our locale file format (a specialization
  of general mo files). If the key is not found, the file can be
  rejected; it's probably a mo file but not one that satisfies the
  needs of libc for the requested locale category. The purpose of this
  check is to prevent disclosure of contents of files that were not
  intended to be locales.

- During gettext lookup (binary search), validate all offsets as lying
  within the address range of the mapping. The purpose of this check
  is to preclude information disclosure due to reading strings from
  locations outside the mapping.

Obviously as long as mmap is used, there is a possibility of DoS via
file truncation and SIGBUS. I don't think it's worth trying to work
around this since the scope is limited to crashing your own programs
(or allowing someone else to crash them if you use a locale file
writable by someone else). As previoysly discussed for zoneinfo, one
option would be to malloc, read, and validate (rather than mmap), but
IMO this is cost-prohibitive.

Rich

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.