2 Unix SMB/Netbios implementation.
4 Copyright (C) Ralph Boehme 2019
5 Copyright (C) Stefan Metzmacher 2019
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/filesys.h"
23 #include "system/threads.h"
24 #ifdef HAVE_UNSHARE_CLONE_FS
26 #endif /* HAVE_UNSHARE_CLONE_FS */
28 static bool _per_thread_cwd_checked
;
29 static bool _per_thread_cwd_supported
;
30 #ifdef HAVE_UNSHARE_CLONE_FS
31 static __thread
bool _per_thread_cwd_disabled
;
32 static __thread
bool _per_thread_cwd_activated
;
33 #endif /* HAVE_UNSHARE_CLONE_FS */
36 * This is the first function to be called!
37 * Typically in the main() function before
38 * any threads are created.
40 * This can be called multiple times
41 * as the result is cached the first time.
43 void per_thread_cwd_check(void)
45 if (_per_thread_cwd_checked
) {
49 #ifdef HAVE_UNSHARE_CLONE_FS
51 * While unshare(CLONE_FS) is available on
52 * Linux for ages, unshare() is also
53 * used to implement containers with various
54 * per container namespaces.
56 * It's possible that the whole unshare()
57 * is blocked in order to disallow nested
60 * That's why we sadly need a runtime check
66 res
= unshare(CLONE_FS
);
68 _per_thread_cwd_supported
= true;
73 * We're in the main thread, so we should disallow
74 * per_thread_cwd_activate() here.
76 _per_thread_cwd_disabled
= true;
77 #endif /* HAVE_UNSHARE_CLONE_FS */
79 _per_thread_cwd_checked
= true;
83 * In order to use per_thread_cwd_supported()
84 * per_thread_cwd_check() needs to be called first!
85 * Otherwise an assert will be triggered!
87 bool per_thread_cwd_supported(void)
89 SMB_ASSERT(_per_thread_cwd_checked
);
90 return _per_thread_cwd_supported
;
94 * In order to use per_thread_cwd_disable()
95 * should be called after any fork() in order
96 * to mark the main thread of the process,
97 * which should disallow per_thread_cwd_activate().
99 * This can be called without calling
100 * per_thread_cwd_check() first.
102 * And it can't be called after calling
103 * per_thread_cwd_activate()!
104 * Otherwise an assert will be triggered!
106 * This can be called multiple times
107 * as the result is cached the first time.
109 void per_thread_cwd_disable(void)
111 #ifdef HAVE_UNSHARE_CLONE_FS
112 SMB_ASSERT(!_per_thread_cwd_activated
);
113 if (_per_thread_cwd_disabled
) {
116 _per_thread_cwd_disabled
= true;
117 #endif /* HAVE_UNSHARE_CLONE_FS */
121 * In order to use per_thread_cwd_activate()
122 * per_thread_cwd_supported() needs to be checked first!
123 * Otherwise an assert will be triggered!
125 * This MUST only be called within helper threads!
127 * That means it can't be called after calling
128 * per_thread_cwd_disable()!
129 * Otherwise an assert will be triggered!
131 * This can be called multiple times
132 * as the result is cached the first time.
134 void per_thread_cwd_activate(void)
136 SMB_ASSERT(_per_thread_cwd_checked
);
137 SMB_ASSERT(_per_thread_cwd_supported
);
139 #ifdef HAVE_UNSHARE_CLONE_FS
140 if (_per_thread_cwd_activated
) {
144 SMB_ASSERT(!_per_thread_cwd_disabled
);
148 ret
= unshare(CLONE_FS
);
149 SMB_ASSERT(ret
== 0);
152 _per_thread_cwd_activated
= true;
153 #else /* not HAVE_UNSHARE_CLONE_FS */
154 smb_panic(__location__
);
155 #endif /* not HAVE_UNSHARE_CLONE_FS */