LCOV - code coverage report
Current view: top level - source3/lib - per_thread_cwd.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 24 27 88.9 %
Date: 2024-01-11 09:59:51 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/Netbios implementation.
       3             : 
       4             :    Copyright (C) Ralph Boehme 2019
       5             :    Copyright (C) Stefan Metzmacher 2019
       6             : 
       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.
      11             : 
      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.
      16             : 
      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/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "system/filesys.h"
      23             : #include "system/threads.h"
      24             : #ifdef HAVE_UNSHARE_CLONE_FS
      25             : #include <sched.h>
      26             : #endif /* HAVE_UNSHARE_CLONE_FS */
      27             : 
      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 */
      34             : 
      35             : /*
      36             :  * This is the first function to be called!
      37             :  * Typically in the main() function before
      38             :  * any threads are created.
      39             :  *
      40             :  * This can be called multiple times
      41             :  * as the result is cached the first time.
      42             :  */
      43          12 : void per_thread_cwd_check(void)
      44             : {
      45          12 :         if (_per_thread_cwd_checked) {
      46           0 :                 return;
      47             :         }
      48             : 
      49             : #ifdef HAVE_UNSHARE_CLONE_FS
      50             :         /*
      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.
      55             :          *
      56             :          * It's possible that the whole unshare()
      57             :          * is blocked in order to disallow nested
      58             :          * containers.
      59             :          *
      60             :          * That's why we sadly need a runtime check
      61             :          * for this.
      62             :          */
      63             :         {
      64           0 :                 int res;
      65             : 
      66          12 :                 res = unshare(CLONE_FS);
      67          12 :                 if (res == 0) {
      68          12 :                         _per_thread_cwd_supported = true;
      69             :                 }
      70             :         }
      71             : 
      72             :         /*
      73             :          * We're in the main thread, so we should disallow
      74             :          * per_thread_cwd_activate() here.
      75             :          */
      76          12 :         _per_thread_cwd_disabled = true;
      77             : #endif /* HAVE_UNSHARE_CLONE_FS */
      78             : 
      79          12 :         _per_thread_cwd_checked = true;
      80             : }
      81             : 
      82             : /*
      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!
      86             :  */
      87       10116 : bool per_thread_cwd_supported(void)
      88             : {
      89       10116 :         SMB_ASSERT(_per_thread_cwd_checked);
      90       10116 :         return _per_thread_cwd_supported;
      91             : }
      92             : 
      93             : /*
      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().
      98             :  *
      99             :  * This can be called without calling
     100             :  * per_thread_cwd_check() first.
     101             :  *
     102             :  * And it can't be called after calling
     103             :  * per_thread_cwd_activate()!
     104             :  * Otherwise an assert will be triggered!
     105             :  *
     106             :  * This can be called multiple times
     107             :  * as the result is cached the first time.
     108             :  */
     109       31312 : void per_thread_cwd_disable(void)
     110             : {
     111             : #ifdef HAVE_UNSHARE_CLONE_FS
     112       31312 :         SMB_ASSERT(!_per_thread_cwd_activated);
     113       31312 :         if (_per_thread_cwd_disabled) {
     114       30237 :                 return;
     115             :         }
     116         233 :         _per_thread_cwd_disabled = true;
     117             : #endif /* HAVE_UNSHARE_CLONE_FS */
     118             : }
     119             : 
     120             : /*
     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!
     124             :  *
     125             :  * This MUST only be called within helper threads!
     126             :  *
     127             :  * That means it can't be called after calling
     128             :  * per_thread_cwd_disable()!
     129             :  * Otherwise an assert will be triggered!
     130             :  *
     131             :  * This can be called multiple times
     132             :  * as the result is cached the first time.
     133             :  */
     134       10078 : void per_thread_cwd_activate(void)
     135             : {
     136       10078 :         SMB_ASSERT(_per_thread_cwd_checked);
     137       10078 :         SMB_ASSERT(_per_thread_cwd_supported);
     138             : 
     139             : #ifdef HAVE_UNSHARE_CLONE_FS
     140       10078 :         if (_per_thread_cwd_activated) {
     141       10059 :                 return;
     142             :         }
     143             : 
     144          19 :         SMB_ASSERT(!_per_thread_cwd_disabled);
     145             : 
     146             :         {
     147           0 :                 int ret;
     148          19 :                 ret = unshare(CLONE_FS);
     149          19 :                 SMB_ASSERT(ret == 0);
     150             :         }
     151             : 
     152          19 :         _per_thread_cwd_activated = true;
     153             : #else /* not HAVE_UNSHARE_CLONE_FS */
     154             :         smb_panic(__location__);
     155             : #endif /* not HAVE_UNSHARE_CLONE_FS */
     156             : }

Generated by: LCOV version 1.14