Skip to content

Commit 97fdea6

Browse files
committedMar 12, 2015
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!) llvm-svn: 232049
1 parent 02e55ef commit 97fdea6

File tree

15 files changed

+104
-0
lines changed

15 files changed

+104
-0
lines changed
 

Diff for: ‎libcxx/CMakeLists.txt

+6
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ option(LIBCXX_ENABLE_PEDANTIC "Compile with pedantic enabled." ON)
5454
option(LIBCXX_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF)
5555
option(LIBCXX_ENABLE_CXX1Y "Enable -std=c++1y and use of c++1y language features if the compiler supports it." OFF)
5656
option(LIBCXX_ENABLE_SHARED "Build libc++ as a shared library." ON)
57+
option(LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE "Build libc++ with support for the global filesystem namespace." ON)
5758
option(LIBCXX_ENABLE_THREADS "Build libc++ with support for threads." ON)
5859
option(LIBCXX_BUILD_32_BITS "Build 32 bit libc++" OFF)
5960
option(LIBCXX_ENABLE_MONOTONIC_CLOCK
@@ -232,6 +233,11 @@ if (MSVC)
232233
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
233234
endif()
234235

236+
# LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE configuration
237+
if (NOT LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE)
238+
add_definitions(-D_LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE)
239+
endif()
240+
235241
# LIBCXX_ENABLE_THREADS configuration
236242
if (NOT LIBCXX_ENABLE_THREADS)
237243
add_definitions(-D_LIBCPP_HAS_NO_THREADS)

Diff for: ‎libcxx/include/__config

+8
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,14 @@ extern "C" void __sanitizer_annotate_contiguous_container(
724724
_LIBCPP_HAS_NO_THREADS is defined.
725725
#endif
726726

727+
// Systems that use capability-based security (FreeBSD with Capsicum,
728+
// Nuxi CloudABI) may only provide local filesystem access (using *at()).
729+
// Functions like open(), rename(), unlink() and stat() should not be
730+
// used, as they attempt to access the global filesystem namespace.
731+
#ifdef __CloudABI__
732+
#define _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
733+
#endif
734+
727735
#if defined(__ANDROID__)
728736
#define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
729737
#endif

Diff for: ‎libcxx/include/cstdio

+4
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,18 @@ using ::FILE;
144144
using ::fpos_t;
145145
using ::size_t;
146146

147+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
147148
using ::remove;
148149
using ::rename;
149150
using ::tmpfile;
150151
using ::tmpnam;
152+
#endif
151153
using ::fclose;
152154
using ::fflush;
155+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
153156
using ::fopen;
154157
using ::freopen;
158+
#endif
155159
using ::setbuf;
156160
using ::setvbuf;
157161
using ::fprintf;

Diff for: ‎libcxx/include/fstream

+26
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,10 @@ public:
206206

207207
// 27.9.1.4 Members:
208208
bool is_open() const;
209+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
209210
basic_filebuf* open(const char* __s, ios_base::openmode __mode);
210211
basic_filebuf* open(const string& __s, ios_base::openmode __mode);
212+
#endif
211213
basic_filebuf* close();
212214

213215
protected:
@@ -463,6 +465,7 @@ basic_filebuf<_CharT, _Traits>::is_open() const
463465
return __file_ != 0;
464466
}
465467

468+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
466469
template <class _CharT, class _Traits>
467470
basic_filebuf<_CharT, _Traits>*
468471
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
550553
{
551554
return open(__s.c_str(), __mode);
552555
}
556+
#endif
553557

554558
template <class _CharT, class _Traits>
555559
basic_filebuf<_CharT, _Traits>*
@@ -1005,8 +1009,10 @@ public:
10051009
typedef typename traits_type::off_type off_type;
10061010

10071011
basic_ifstream();
1012+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
10081013
explicit basic_ifstream(const char* __s, ios_base::openmode __mode = ios_base::in);
10091014
explicit basic_ifstream(const string& __s, ios_base::openmode __mode = ios_base::in);
1015+
#endif
10101016
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
10111017
basic_ifstream(basic_ifstream&& __rhs);
10121018
#endif
@@ -1018,8 +1024,10 @@ public:
10181024

10191025
basic_filebuf<char_type, traits_type>* rdbuf() const;
10201026
bool is_open() const;
1027+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
10211028
void open(const char* __s, ios_base::openmode __mode = ios_base::in);
10221029
void open(const string& __s, ios_base::openmode __mode = ios_base::in);
1030+
#endif
10231031
void close();
10241032

10251033
private:
@@ -1033,6 +1041,7 @@ basic_ifstream<_CharT, _Traits>::basic_ifstream()
10331041
{
10341042
}
10351043

1044+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
10361045
template <class _CharT, class _Traits>
10371046
inline _LIBCPP_INLINE_VISIBILITY
10381047
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
10501059
if (__sb_.open(__s, __mode | ios_base::in) == 0)
10511060
this->setstate(ios_base::failbit);
10521061
}
1062+
#endif
10531063

10541064
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
10551065

@@ -1107,6 +1117,7 @@ basic_ifstream<_CharT, _Traits>::is_open() const
11071117
return __sb_.is_open();
11081118
}
11091119

1120+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
11101121
template <class _CharT, class _Traits>
11111122
void
11121123
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
11261137
else
11271138
this->setstate(ios_base::failbit);
11281139
}
1140+
#endif
11291141

11301142
template <class _CharT, class _Traits>
11311143
inline _LIBCPP_INLINE_VISIBILITY
@@ -1163,8 +1175,10 @@ public:
11631175

11641176
basic_filebuf<char_type, traits_type>* rdbuf() const;
11651177
bool is_open() const;
1178+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
11661179
void open(const char* __s, ios_base::openmode __mode = ios_base::out);
11671180
void open(const string& __s, ios_base::openmode __mode = ios_base::out);
1181+
#endif
11681182
void close();
11691183

11701184
private:
@@ -1178,6 +1192,7 @@ basic_ofstream<_CharT, _Traits>::basic_ofstream()
11781192
{
11791193
}
11801194

1195+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
11811196
template <class _CharT, class _Traits>
11821197
inline _LIBCPP_INLINE_VISIBILITY
11831198
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
11951210
if (__sb_.open(__s, __mode | ios_base::out) == 0)
11961211
this->setstate(ios_base::failbit);
11971212
}
1213+
#endif
11981214

11991215
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
12001216

@@ -1252,6 +1268,7 @@ basic_ofstream<_CharT, _Traits>::is_open() const
12521268
return __sb_.is_open();
12531269
}
12541270

1271+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
12551272
template <class _CharT, class _Traits>
12561273
void
12571274
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
12711288
else
12721289
this->setstate(ios_base::failbit);
12731290
}
1291+
#endif
12741292

12751293
template <class _CharT, class _Traits>
12761294
inline _LIBCPP_INLINE_VISIBILITY
@@ -1295,8 +1313,10 @@ public:
12951313
typedef typename traits_type::off_type off_type;
12961314

12971315
basic_fstream();
1316+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
12981317
explicit basic_fstream(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
12991318
explicit basic_fstream(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
1319+
#endif
13001320
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
13011321
basic_fstream(basic_fstream&& __rhs);
13021322
#endif
@@ -1308,8 +1328,10 @@ public:
13081328

13091329
basic_filebuf<char_type, traits_type>* rdbuf() const;
13101330
bool is_open() const;
1331+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
13111332
void open(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
13121333
void open(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
1334+
#endif
13131335
void close();
13141336

13151337
private:
@@ -1323,6 +1345,7 @@ basic_fstream<_CharT, _Traits>::basic_fstream()
13231345
{
13241346
}
13251347

1348+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
13261349
template <class _CharT, class _Traits>
13271350
inline _LIBCPP_INLINE_VISIBILITY
13281351
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
13401363
if (__sb_.open(__s, __mode) == 0)
13411364
this->setstate(ios_base::failbit);
13421365
}
1366+
#endif
13431367

13441368
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
13451369

@@ -1397,6 +1421,7 @@ basic_fstream<_CharT, _Traits>::is_open() const
13971421
return __sb_.is_open();
13981422
}
13991423

1424+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
14001425
template <class _CharT, class _Traits>
14011426
void
14021427
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
14161441
else
14171442
this->setstate(ios_base::failbit);
14181443
}
1444+
#endif
14191445

14201446
template <class _CharT, class _Traits>
14211447
inline _LIBCPP_INLINE_VISIBILITY

Diff for: ‎libcxx/test/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ if (LIT_EXECUTABLE)
4242
pythonize_bool(LIBCXX_ENABLE_RTTI)
4343
pythonize_bool(LIBCXX_ENABLE_SHARED)
4444
pythonize_bool(LIBCXX_BUILD_32_BITS)
45+
pythonize_bool(LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE)
4546
pythonize_bool(LIBCXX_ENABLE_THREADS)
4647
pythonize_bool(LIBCXX_ENABLE_MONOTONIC_CLOCK)
4748
# The tests shouldn't link to any ABI library when it has been linked into

Diff for: ‎libcxx/test/libcxx/test/config.py

+10
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ def configure_default_compile_flags(self):
347347
# Configure feature flags.
348348
self.configure_compile_flags_exceptions()
349349
self.configure_compile_flags_rtti()
350+
self.configure_compile_flags_no_global_filesystem_namespace()
350351
enable_32bit = self.get_lit_bool('enable_32bit', False)
351352
if enable_32bit:
352353
self.cxx.flags += ['-m32']
@@ -395,6 +396,15 @@ def configure_compile_flags_rtti(self):
395396
self.config.available_features.add('libcpp-no-rtti')
396397
self.cxx.compile_flags += ['-fno-rtti', '-D_LIBCPP_NO_RTTI']
397398

399+
def configure_compile_flags_no_global_filesystem_namespace(self):
400+
enable_global_filesystem_namespace = self.get_lit_bool(
401+
'enable_global_filesystem_namespace', True)
402+
if not enable_global_filesystem_namespace:
403+
self.config.available_features.add(
404+
'libcpp-has-no-global-filesystem-namespace')
405+
self.cxx.compile_flags += [
406+
'-D_LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE']
407+
398408
def configure_compile_flags_no_threads(self):
399409
self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_THREADS']
400410
self.config.available_features.add('libcpp-has-no-threads')

Diff for: ‎libcxx/test/libcxx/test/format.py

+4
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ def _execute(self, test, lit_config):
6060
is_pass_test = name.endswith('.pass.cpp')
6161
is_fail_test = name.endswith('.fail.cpp')
6262

63+
if test.config.unsupported:
64+
return (lit.Test.UNSUPPORTED,
65+
"A lit.local.cfg marked this unsupported")
66+
6367
res = lit.TestRunner.parseIntegratedTestScript(
6468
test, require_script=is_sh_test)
6569
# Check if a result for the test was returned. If so return that

Diff for: ‎libcxx/test/lit.site.cfg.in

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ config.enable_exceptions = "@LIBCXX_ENABLE_EXCEPTIONS@"
88
config.enable_rtti = "@LIBCXX_ENABLE_RTTI@"
99
config.enable_shared = "@LIBCXX_ENABLE_SHARED@"
1010
config.enable_32bit = "@LIBCXX_BUILD_32_BITS@"
11+
config.enable_global_filesystem_namespace = "@LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE@"
1112
config.enable_threads = "@LIBCXX_ENABLE_THREADS@"
1213
config.enable_monotonic_clock = "@LIBCXX_ENABLE_MONOTONIC_CLOCK@"
1314
config.cxx_abi = "@LIBCXX_CXX_ABI_LIBNAME@"

Diff for: ‎libcxx/test/std/input.output/file.streams/c.files/cstdio.pass.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,18 @@ int main()
8888
std::size_t s = 0;
8989
char* cp = 0;
9090
std::va_list va;
91+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
9192
static_assert((std::is_same<decltype(std::remove("")), int>::value), "");
9293
static_assert((std::is_same<decltype(std::rename("","")), int>::value), "");
9394
static_assert((std::is_same<decltype(std::tmpfile()), std::FILE*>::value), "");
9495
static_assert((std::is_same<decltype(std::tmpnam(cp)), char*>::value), "");
96+
#endif
9597
static_assert((std::is_same<decltype(std::fclose(fp)), int>::value), "");
9698
static_assert((std::is_same<decltype(std::fflush(fp)), int>::value), "");
99+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
97100
static_assert((std::is_same<decltype(std::fopen("", "")), std::FILE*>::value), "");
98101
static_assert((std::is_same<decltype(std::freopen("", "", fp)), std::FILE*>::value), "");
102+
#endif
99103
static_assert((std::is_same<decltype(std::setbuf(fp,cp)), void>::value), "");
100104
static_assert((std::is_same<decltype(std::vfprintf(fp,"",va)), int>::value), "");
101105
static_assert((std::is_same<decltype(std::fprintf(fp," ")), int>::value), "");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is dual licensed under the MIT and the University of Illinois Open
6+
// Source Licenses. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include <cstdio>
11+
12+
int main() {
13+
// fopen is not available on systems without a global filesystem namespace.
14+
std::fopen("", "");
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
if 'libcpp-has-no-global-filesystem-namespace' not in config.available_features:
2+
config.unsupported = True
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is dual licensed under the MIT and the University of Illinois Open
6+
// Source Licenses. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include <cstdio>
11+
12+
int main() {
13+
// rename is not available on systems without a global filesystem namespace.
14+
std::rename("", "");
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
if 'libcpp-has-no-global-filesystem-namespace' in config.available_features:
2+
config.unsupported = True
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
if 'libcpp-has-no-global-filesystem-namespace' in config.available_features:
2+
config.unsupported = True

Diff for: ‎libcxx/test/support/platform_support.h

+4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#ifndef PLATFORM_SUPPORT_H
1616
#define PLATFORM_SUPPORT_H
1717

18+
#include <__config>
19+
1820
// locale names
1921
#ifdef _WIN32
2022
// WARNING: Windows does not support UTF-8 codepages.
@@ -65,6 +67,7 @@ extern "C" {
6567
}
6668
#endif
6769

70+
#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
6871
inline
6972
std::string
7073
get_temp_file_name()
@@ -90,5 +93,6 @@ get_temp_file_name()
9093
return Name;
9194
#endif
9295
}
96+
#endif // _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
9397

9498
#endif // PLATFORM_SUPPORT_H

0 commit comments

Comments
 (0)
Please sign in to comment.