5aad5f6178
This commit improves DST handling significantly in the following ways: firstly is_dst () is overhauled to correctly process DST sequences that would be accepted given the ELF gABI. This means that we actually now accept slightly more sequences than before. Now we accept $ORIGIN$ORIGIN, but in the past we accepted only $ORIGIN\0 or $ORIGIN/..., but this kind of behaviour results in unexpected and uninterpreted DST sequences being used as literal search paths leading to security defects. Therefore the first step in correcting this defect is making is_dst () properly account for all DSTs and making the function context free in the sense that it counts DSTs without knowledge of path, or AT_SECURE. Next, _dl_dst_count () is also simplified to count all DSTs regardless of context. Then in _dl_dst_substitute () we reintroduce context-dependent processing for such things as AT_SECURE handling. At the level of _dl_dst_substitute we can have access to things like the true start of the string sequence to validate $ORIGIN-based paths rooted in trusted directories. Lastly, we tighten up the accepted sequences in AT_SECURE, and avoid leaving known unexpanded DSTs, this is noted in the NEWS entry. Verified with a sequence of 68 tests on x86_64 that cover non-AT_SECURE and AT_SECURE testing using a sysroot (requires root to run). The tests cover cases for bug 23102, bug 21942, bug 18018, and bug 23259. These tests are not yet appropriate for the glibc regression testsuite, but with the upcoming test-in-container testing framework it should be possible to include these tests upstream soon. See the mailing list for the tests: https://www.sourceware.org/ml/libc-alpha/2018-06/msg00251.html
62 lines
2.4 KiB
C
62 lines
2.4 KiB
C
/* Handling of dynamic sring tokens.
|
|
Copyright (C) 1999-2018 Free Software Foundation, Inc.
|
|
This file is part of the GNU C Library.
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with the GNU C Library; if not, see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#include "trusted-dirs.h"
|
|
|
|
#ifdef SHARED
|
|
# define IS_RTLD(l) (l) == &GL(dl_rtld_map)
|
|
#else
|
|
# define IS_RTLD(l) 0
|
|
#endif
|
|
/* Guess from the number of DSTs the length of the result string. */
|
|
#define DL_DST_REQUIRED(l, name, len, cnt) \
|
|
({ \
|
|
size_t __len = (len); \
|
|
size_t __cnt = (cnt); \
|
|
\
|
|
if (__cnt > 0) \
|
|
{ \
|
|
size_t dst_len; \
|
|
/* Now we make a guess how many extra characters on top of the \
|
|
length of S we need to represent the result. We know that \
|
|
we have CNT replacements. Each at most can use \
|
|
MAX (MAX (strlen (ORIGIN), strlen (_dl_platform)), \
|
|
strlen (DL_DST_LIB)) \
|
|
minus 4 (which is the length of "$LIB"). \
|
|
\
|
|
First get the origin string if it is not available yet. \
|
|
This can only happen for the map of the executable or, when \
|
|
auditing, in ld.so. */ \
|
|
if ((l)->l_origin == NULL) \
|
|
{ \
|
|
assert ((l)->l_name[0] == '\0' || IS_RTLD (l)); \
|
|
(l)->l_origin = _dl_get_origin (); \
|
|
dst_len = ((l)->l_origin && (l)->l_origin != (char *) -1 \
|
|
? strlen ((l)->l_origin) : 0); \
|
|
} \
|
|
else \
|
|
dst_len = (l)->l_origin == (char *) -1 \
|
|
? 0 : strlen ((l)->l_origin); \
|
|
dst_len = MAX (MAX (dst_len, GLRO(dl_platformlen)), \
|
|
strlen (DL_DST_LIB)); \
|
|
if (dst_len > 4) \
|
|
__len += __cnt * (dst_len - 4); \
|
|
} \
|
|
\
|
|
__len; })
|