-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathThreadedScenario.hs
68 lines (50 loc) · 2.12 KB
/
ThreadedScenario.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
module ThreadedScenario (scenario) where
import Control.Concurrent.Async (Async, wait)
import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
import Control.Exception.Base (handleJust)
import System.IO (IOMode(ReadMode), withFile)
import System.IO.Error (isPermissionError)
import System.Posix.Types (CPid(..))
import Test.Tasty (TestTree)
import Test.Tasty.HUnit (assertFailure, testCaseSteps)
import System.Landlock (AccessFsFlag(..), RulesetAttr(..), unsafeLandlock)
foreign import ccall unsafe "unistd.h gettid"
gettid :: IO CPid
scenario :: (IO () -> (Async () -> IO ()) -> IO ()) -> TestTree
scenario fn = testCaseSteps "Multithreaded Scenario" (scenario' fn)
scenario' :: (IO () -> (Async () -> IO ()) -> IO ()) -> (String -> IO ()) -> IO ()
scenario' withAsync step = do
step "Starting scenario"
mainTid <- gettid
step $ "Main TID = " ++ show mainTid
tidMVar <- newEmptyMVar
continueMVar <- newEmptyMVar
step "Launching thread"
withAsync (thread tidMVar continueMVar) $ \child -> do
_ <- takeMVar tidMVar
step "Setting up Landlock sandbox"
let flags = [AccessFsReadFile]
unsafeLandlock (RulesetAttr flags) [] [] $ \_ -> return ()
step "Assert file not readable from main thread"
assertFileNotReadable "main"
step "Success"
step "Letting thread continue"
putMVar continueMVar ()
step "Waiting for thread to exit"
wait child
where
thread tidMVar continueMVar = do
step "Running in thread"
tid <- gettid
step $ "Thread TID = " ++ show tid
putMVar tidMVar tid
step "Waiting for the signal..."
() <- takeMVar continueMVar
step "Received signal, continuing"
step "Assert file not readable from thread"
assertFileNotReadable "thread"
step "Success"
file = "/etc/resolv.conf"
assertFileNotReadable env = handleJust permissionError return $ withFile file ReadMode $ \_ ->
assertFailure $ "Still able to open file " ++ file ++ " in " ++ env
permissionError exc = if isPermissionError exc then Just () else Nothing