module Mueval.Resources (limitResources) where

import Control.Monad (when)
import System.Posix.Process (nice)
import System.Posix.Resource -- (Resource(..), ResourceLimits, setResourceLimit)

-- | Pull together several methods of reducing priority and easy access to resources:
--  'nice', and the rlimit bindings,
--  If called with False, 'limitResources' will not use POSIX rlimits.
limitResources :: Bool -> IO ()
limitResources :: Bool -> IO ()
limitResources rlimit :: Bool
rlimit = do Int -> IO ()
nice 20 -- Set our process priority way down
                           Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
rlimit (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ ((Resource, ResourceLimits) -> IO ())
-> [(Resource, ResourceLimits)] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ((Resource -> ResourceLimits -> IO ())
-> (Resource, ResourceLimits) -> IO ()
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Resource -> ResourceLimits -> IO ()
setResourceLimit) [(Resource, ResourceLimits)]
limits

-- | Set all the available rlimits.
--   These values have been determined through trial-and-error
stackSizeLimitSoft, stackSizeLimitHard, totalMemoryLimitSoft, totalMemoryLimitHard,
 dataSizeLimitSoft, openFilesLimitSoft, openFilesLimitHard, fileSizeLimitSoft, fileSizeLimitHard,
 dataSizeLimitHard, cpuTimeLimitSoft, cpuTimeLimitHard, coreSizeLimitSoft, coreSizeLimitHard, zero :: ResourceLimit
totalMemoryLimitSoft :: ResourceLimit
totalMemoryLimitSoft = ResourceLimit
dataSizeLimitSoft
totalMemoryLimitHard :: ResourceLimit
totalMemoryLimitHard = ResourceLimit
dataSizeLimitHard
-- These limits seem to be useless?
stackSizeLimitSoft :: ResourceLimit
stackSizeLimitSoft = ResourceLimit
zero
stackSizeLimitHard :: ResourceLimit
stackSizeLimitHard = ResourceLimit
zero
-- We allow a few files to be opened, such as package.conf, because they are necessary. This
-- doesn't seem to be security problem because it'll be opened at the module
-- stage, before code ever evaluates. I hope.
openFilesLimitSoft :: ResourceLimit
openFilesLimitSoft = ResourceLimit
openFilesLimitHard
openFilesLimitHard :: ResourceLimit
openFilesLimitHard = Integer -> ResourceLimit
ResourceLimit 7
-- TODO: It would be nice to set these to zero, but right now Hint gets around the
-- insecurity of the GHC API by writing stuff out to a file in /tmp, so we need
-- to allow our compiled binary to do file I/O... :( But at least we can still limit
-- how much we write out!
fileSizeLimitSoft :: ResourceLimit
fileSizeLimitSoft = ResourceLimit
fileSizeLimitHard
fileSizeLimitHard :: ResourceLimit
fileSizeLimitHard = Integer -> ResourceLimit
ResourceLimit 10800
dataSizeLimitSoft :: ResourceLimit
dataSizeLimitSoft = ResourceLimit
dataSizeLimitHard
dataSizeLimitHard :: ResourceLimit
dataSizeLimitHard = Integer -> ResourceLimit
ResourceLimit (Integer -> ResourceLimit) -> Integer -> ResourceLimit
forall a b. (a -> b) -> a -> b
$ 6Integer -> Int -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^(12::Int)
-- These should not be identical, to give the XCPU handler time to trigger
cpuTimeLimitSoft :: ResourceLimit
cpuTimeLimitSoft = Integer -> ResourceLimit
ResourceLimit 4
cpuTimeLimitHard :: ResourceLimit
cpuTimeLimitHard = Integer -> ResourceLimit
ResourceLimit 5
coreSizeLimitSoft :: ResourceLimit
coreSizeLimitSoft = ResourceLimit
coreSizeLimitHard
coreSizeLimitHard :: ResourceLimit
coreSizeLimitHard = ResourceLimit
zero

-- convenience
zero :: ResourceLimit
zero = Integer -> ResourceLimit
ResourceLimit 0

limits :: [(Resource, ResourceLimits)]
limits :: [(Resource, ResourceLimits)]
limits = [ (Resource
ResourceStackSize,    ResourceLimit -> ResourceLimit -> ResourceLimits
ResourceLimits ResourceLimit
stackSizeLimitSoft ResourceLimit
stackSizeLimitHard)
         , (Resource
ResourceTotalMemory,  ResourceLimit -> ResourceLimit -> ResourceLimits
ResourceLimits ResourceLimit
totalMemoryLimitSoft ResourceLimit
totalMemoryLimitHard)
         , (Resource
ResourceOpenFiles,    ResourceLimit -> ResourceLimit -> ResourceLimits
ResourceLimits ResourceLimit
openFilesLimitSoft ResourceLimit
openFilesLimitHard)
         , (Resource
ResourceFileSize,     ResourceLimit -> ResourceLimit -> ResourceLimits
ResourceLimits ResourceLimit
fileSizeLimitSoft ResourceLimit
fileSizeLimitHard)
         , (Resource
ResourceDataSize,     ResourceLimit -> ResourceLimit -> ResourceLimits
ResourceLimits ResourceLimit
dataSizeLimitSoft ResourceLimit
dataSizeLimitHard)
         , (Resource
ResourceCoreFileSize, ResourceLimit -> ResourceLimit -> ResourceLimits
ResourceLimits ResourceLimit
coreSizeLimitSoft ResourceLimit
coreSizeLimitHard)
         , (Resource
ResourceCPUTime,      ResourceLimit -> ResourceLimit -> ResourceLimits
ResourceLimits ResourceLimit
cpuTimeLimitSoft ResourceLimit
cpuTimeLimitHard)]