Add option to disable access to the global filesystem namespace.
Systems like FreeBSD's Capsicum and Nuxi CloudABI apply the concept of capability-based security on the way processes can interact with the filesystem API. It is no longer possible to interact with the VFS through calls like open(), unlink(), rename(), etc. Instead, processes are only allowed to interact with files and directories to which they have been granted access. The *at() functions can be used for this purpose. This change adds a new config switch called _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE. If set, all functionality that requires the global filesystem namespace will be disabled. More concretely: - fstream's open() function will be removed. - cstdio will no longer pull in fopen(), rename(), etc. - The test suite's get_temp_file_name() will be removed. This will cause all tests that use the global filesystem namespace to break, but will at least make all the other tests run (as get_temp_file_name will not build anyway). It is important to mention that this change will make fstream rather useless on those systems for now. Still, I'd rather not have fstream disabled entirely, as it is of course possible to come up with an extension for fstream that would allow access to local filesystem namespaces (e.g., by adding an openat() member function). Differential revision: http://reviews.llvm.org/D8194 Reviewed by: jroelofs (thanks!) git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@232049 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6fb33ea8fb
commit
b33ae5ba7d
@ -54,6 +54,7 @@ option(LIBCXX_ENABLE_PEDANTIC "Compile with pedantic enabled." ON)
|
||||
option(LIBCXX_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF)
|
||||
option(LIBCXX_ENABLE_CXX1Y "Enable -std=c++1y and use of c++1y language features if the compiler supports it." OFF)
|
||||
option(LIBCXX_ENABLE_SHARED "Build libc++ as a shared library." ON)
|
||||
option(LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE "Build libc++ with support for the global filesystem namespace." ON)
|
||||
option(LIBCXX_ENABLE_THREADS "Build libc++ with support for threads." ON)
|
||||
option(LIBCXX_BUILD_32_BITS "Build 32 bit libc++" OFF)
|
||||
option(LIBCXX_ENABLE_MONOTONIC_CLOCK
|
||||
@ -232,6 +233,11 @@ if (MSVC)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
# LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE configuration
|
||||
if (NOT LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE)
|
||||
add_definitions(-D_LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE)
|
||||
endif()
|
||||
|
||||
# LIBCXX_ENABLE_THREADS configuration
|
||||
if (NOT LIBCXX_ENABLE_THREADS)
|
||||
add_definitions(-D_LIBCPP_HAS_NO_THREADS)
|
||||
|
@ -724,6 +724,14 @@ extern "C" void __sanitizer_annotate_contiguous_container(
|
||||
_LIBCPP_HAS_NO_THREADS is defined.
|
||||
#endif
|
||||
|
||||
// Systems that use capability-based security (FreeBSD with Capsicum,
|
||||
// Nuxi CloudABI) may only provide local filesystem access (using *at()).
|
||||
// Functions like open(), rename(), unlink() and stat() should not be
|
||||
// used, as they attempt to access the global filesystem namespace.
|
||||
#ifdef __CloudABI__
|
||||
#define _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
|
||||
#endif
|
||||
|
@ -144,14 +144,18 @@ using ::FILE;
|
||||
using ::fpos_t;
|
||||
using ::size_t;
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
using ::remove;
|
||||
using ::rename;
|
||||
using ::tmpfile;
|
||||
using ::tmpnam;
|
||||
#endif
|
||||
using ::fclose;
|
||||
using ::fflush;
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
using ::fopen;
|
||||
using ::freopen;
|
||||
#endif
|
||||
using ::setbuf;
|
||||
using ::setvbuf;
|
||||
using ::fprintf;
|
||||
|
@ -206,8 +206,10 @@ public:
|
||||
|
||||
// 27.9.1.4 Members:
|
||||
bool is_open() const;
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
basic_filebuf* open(const char* __s, ios_base::openmode __mode);
|
||||
basic_filebuf* open(const string& __s, ios_base::openmode __mode);
|
||||
#endif
|
||||
basic_filebuf* close();
|
||||
|
||||
protected:
|
||||
@ -463,6 +465,7 @@ basic_filebuf<_CharT, _Traits>::is_open() const
|
||||
return __file_ != 0;
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
template <class _CharT, class _Traits>
|
||||
basic_filebuf<_CharT, _Traits>*
|
||||
basic_filebuf<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode)
|
||||
@ -550,6 +553,7 @@ basic_filebuf<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mod
|
||||
{
|
||||
return open(__s.c_str(), __mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class _CharT, class _Traits>
|
||||
basic_filebuf<_CharT, _Traits>*
|
||||
@ -1005,8 +1009,10 @@ public:
|
||||
typedef typename traits_type::off_type off_type;
|
||||
|
||||
basic_ifstream();
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
explicit basic_ifstream(const char* __s, ios_base::openmode __mode = ios_base::in);
|
||||
explicit basic_ifstream(const string& __s, ios_base::openmode __mode = ios_base::in);
|
||||
#endif
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
basic_ifstream(basic_ifstream&& __rhs);
|
||||
#endif
|
||||
@ -1018,8 +1024,10 @@ public:
|
||||
|
||||
basic_filebuf<char_type, traits_type>* rdbuf() const;
|
||||
bool is_open() const;
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
void open(const char* __s, ios_base::openmode __mode = ios_base::in);
|
||||
void open(const string& __s, ios_base::openmode __mode = ios_base::in);
|
||||
#endif
|
||||
void close();
|
||||
|
||||
private:
|
||||
@ -1033,6 +1041,7 @@ basic_ifstream<_CharT, _Traits>::basic_ifstream()
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
template <class _CharT, class _Traits>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_ifstream<_CharT, _Traits>::basic_ifstream(const char* __s, ios_base::openmode __mode)
|
||||
@ -1050,6 +1059,7 @@ basic_ifstream<_CharT, _Traits>::basic_ifstream(const string& __s, ios_base::ope
|
||||
if (__sb_.open(__s, __mode | ios_base::in) == 0)
|
||||
this->setstate(ios_base::failbit);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
|
||||
@ -1107,6 +1117,7 @@ basic_ifstream<_CharT, _Traits>::is_open() const
|
||||
return __sb_.is_open();
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
template <class _CharT, class _Traits>
|
||||
void
|
||||
basic_ifstream<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode)
|
||||
@ -1126,6 +1137,7 @@ basic_ifstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mo
|
||||
else
|
||||
this->setstate(ios_base::failbit);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class _CharT, class _Traits>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
@ -1163,8 +1175,10 @@ public:
|
||||
|
||||
basic_filebuf<char_type, traits_type>* rdbuf() const;
|
||||
bool is_open() const;
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
void open(const char* __s, ios_base::openmode __mode = ios_base::out);
|
||||
void open(const string& __s, ios_base::openmode __mode = ios_base::out);
|
||||
#endif
|
||||
void close();
|
||||
|
||||
private:
|
||||
@ -1178,6 +1192,7 @@ basic_ofstream<_CharT, _Traits>::basic_ofstream()
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
template <class _CharT, class _Traits>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_ofstream<_CharT, _Traits>::basic_ofstream(const char* __s, ios_base::openmode __mode)
|
||||
@ -1195,6 +1210,7 @@ basic_ofstream<_CharT, _Traits>::basic_ofstream(const string& __s, ios_base::ope
|
||||
if (__sb_.open(__s, __mode | ios_base::out) == 0)
|
||||
this->setstate(ios_base::failbit);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
|
||||
@ -1252,6 +1268,7 @@ basic_ofstream<_CharT, _Traits>::is_open() const
|
||||
return __sb_.is_open();
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
template <class _CharT, class _Traits>
|
||||
void
|
||||
basic_ofstream<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode)
|
||||
@ -1271,6 +1288,7 @@ basic_ofstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mo
|
||||
else
|
||||
this->setstate(ios_base::failbit);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class _CharT, class _Traits>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
@ -1295,8 +1313,10 @@ public:
|
||||
typedef typename traits_type::off_type off_type;
|
||||
|
||||
basic_fstream();
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
explicit basic_fstream(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
|
||||
explicit basic_fstream(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
|
||||
#endif
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
basic_fstream(basic_fstream&& __rhs);
|
||||
#endif
|
||||
@ -1308,8 +1328,10 @@ public:
|
||||
|
||||
basic_filebuf<char_type, traits_type>* rdbuf() const;
|
||||
bool is_open() const;
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
void open(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
|
||||
void open(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
|
||||
#endif
|
||||
void close();
|
||||
|
||||
private:
|
||||
@ -1323,6 +1345,7 @@ basic_fstream<_CharT, _Traits>::basic_fstream()
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
template <class _CharT, class _Traits>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_fstream<_CharT, _Traits>::basic_fstream(const char* __s, ios_base::openmode __mode)
|
||||
@ -1340,6 +1363,7 @@ basic_fstream<_CharT, _Traits>::basic_fstream(const string& __s, ios_base::openm
|
||||
if (__sb_.open(__s, __mode) == 0)
|
||||
this->setstate(ios_base::failbit);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
|
||||
@ -1397,6 +1421,7 @@ basic_fstream<_CharT, _Traits>::is_open() const
|
||||
return __sb_.is_open();
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
template <class _CharT, class _Traits>
|
||||
void
|
||||
basic_fstream<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode)
|
||||
@ -1416,6 +1441,7 @@ basic_fstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mod
|
||||
else
|
||||
this->setstate(ios_base::failbit);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class _CharT, class _Traits>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
|
@ -42,6 +42,7 @@ if (LIT_EXECUTABLE)
|
||||
pythonize_bool(LIBCXX_ENABLE_RTTI)
|
||||
pythonize_bool(LIBCXX_ENABLE_SHARED)
|
||||
pythonize_bool(LIBCXX_BUILD_32_BITS)
|
||||
pythonize_bool(LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE)
|
||||
pythonize_bool(LIBCXX_ENABLE_THREADS)
|
||||
pythonize_bool(LIBCXX_ENABLE_MONOTONIC_CLOCK)
|
||||
# The tests shouldn't link to any ABI library when it has been linked into
|
||||
|
@ -347,6 +347,7 @@ class Configuration(object):
|
||||
# Configure feature flags.
|
||||
self.configure_compile_flags_exceptions()
|
||||
self.configure_compile_flags_rtti()
|
||||
self.configure_compile_flags_no_global_filesystem_namespace()
|
||||
enable_32bit = self.get_lit_bool('enable_32bit', False)
|
||||
if enable_32bit:
|
||||
self.cxx.flags += ['-m32']
|
||||
@ -395,6 +396,15 @@ class Configuration(object):
|
||||
self.config.available_features.add('libcpp-no-rtti')
|
||||
self.cxx.compile_flags += ['-fno-rtti', '-D_LIBCPP_NO_RTTI']
|
||||
|
||||
def configure_compile_flags_no_global_filesystem_namespace(self):
|
||||
enable_global_filesystem_namespace = self.get_lit_bool(
|
||||
'enable_global_filesystem_namespace', True)
|
||||
if not enable_global_filesystem_namespace:
|
||||
self.config.available_features.add(
|
||||
'libcpp-has-no-global-filesystem-namespace')
|
||||
self.cxx.compile_flags += [
|
||||
'-D_LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE']
|
||||
|
||||
def configure_compile_flags_no_threads(self):
|
||||
self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_THREADS']
|
||||
self.config.available_features.add('libcpp-has-no-threads')
|
||||
|
@ -60,6 +60,10 @@ class LibcxxTestFormat(object):
|
||||
is_pass_test = name.endswith('.pass.cpp')
|
||||
is_fail_test = name.endswith('.fail.cpp')
|
||||
|
||||
if test.config.unsupported:
|
||||
return (lit.Test.UNSUPPORTED,
|
||||
"A lit.local.cfg marked this unsupported")
|
||||
|
||||
res = lit.TestRunner.parseIntegratedTestScript(
|
||||
test, require_script=is_sh_test)
|
||||
# Check if a result for the test was returned. If so return that
|
||||
|
@ -8,6 +8,7 @@ config.enable_exceptions = "@LIBCXX_ENABLE_EXCEPTIONS@"
|
||||
config.enable_rtti = "@LIBCXX_ENABLE_RTTI@"
|
||||
config.enable_shared = "@LIBCXX_ENABLE_SHARED@"
|
||||
config.enable_32bit = "@LIBCXX_BUILD_32_BITS@"
|
||||
config.enable_global_filesystem_namespace = "@LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE@"
|
||||
config.enable_threads = "@LIBCXX_ENABLE_THREADS@"
|
||||
config.enable_monotonic_clock = "@LIBCXX_ENABLE_MONOTONIC_CLOCK@"
|
||||
config.cxx_abi = "@LIBCXX_CXX_ABI_LIBNAME@"
|
||||
|
@ -88,14 +88,18 @@ int main()
|
||||
std::size_t s = 0;
|
||||
char* cp = 0;
|
||||
std::va_list va;
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
static_assert((std::is_same<decltype(std::remove("")), int>::value), "");
|
||||
static_assert((std::is_same<decltype(std::rename("","")), int>::value), "");
|
||||
static_assert((std::is_same<decltype(std::tmpfile()), std::FILE*>::value), "");
|
||||
static_assert((std::is_same<decltype(std::tmpnam(cp)), char*>::value), "");
|
||||
#endif
|
||||
static_assert((std::is_same<decltype(std::fclose(fp)), int>::value), "");
|
||||
static_assert((std::is_same<decltype(std::fflush(fp)), int>::value), "");
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
static_assert((std::is_same<decltype(std::fopen("", "")), std::FILE*>::value), "");
|
||||
static_assert((std::is_same<decltype(std::freopen("", "", fp)), std::FILE*>::value), "");
|
||||
#endif
|
||||
static_assert((std::is_same<decltype(std::setbuf(fp,cp)), void>::value), "");
|
||||
static_assert((std::is_same<decltype(std::vfprintf(fp,"",va)), int>::value), "");
|
||||
static_assert((std::is_same<decltype(std::fprintf(fp," ")), int>::value), "");
|
||||
|
@ -0,0 +1,15 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
int main() {
|
||||
// fopen is not available on systems without a global filesystem namespace.
|
||||
std::fopen("", "");
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
if 'libcpp-has-no-global-filesystem-namespace' not in config.available_features:
|
||||
config.unsupported = True
|
@ -0,0 +1,15 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
int main() {
|
||||
// rename is not available on systems without a global filesystem namespace.
|
||||
std::rename("", "");
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
if 'libcpp-has-no-global-filesystem-namespace' in config.available_features:
|
||||
config.unsupported = True
|
@ -0,0 +1,2 @@
|
||||
if 'libcpp-has-no-global-filesystem-namespace' in config.available_features:
|
||||
config.unsupported = True
|
@ -15,6 +15,8 @@
|
||||
#ifndef PLATFORM_SUPPORT_H
|
||||
#define PLATFORM_SUPPORT_H
|
||||
|
||||
#include <__config>
|
||||
|
||||
// locale names
|
||||
#ifdef _WIN32
|
||||
// WARNING: Windows does not support UTF-8 codepages.
|
||||
@ -65,6 +67,7 @@ extern "C" {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
inline
|
||||
std::string
|
||||
get_temp_file_name()
|
||||
@ -90,5 +93,6 @@ get_temp_file_name()
|
||||
return Name;
|
||||
#endif
|
||||
}
|
||||
#endif // _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
|
||||
#endif // PLATFORM_SUPPORT_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user