packages feed

landlock-0.1.0.0: internal/System/Landlock/Rules.hsc

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE StandaloneDeriving #-}

module System.Landlock.Rules (
      Rule
    , RuleType(..)
    , ruleType
    , pathBeneath
    , AccessFsFlag(..)
    ) where

#include <linux/landlock.h>
#include <sys/types.h>

import Data.Int (Int32)
import Data.Word (Word32, Word64)
import Foreign.Storable (Storable(..))
import System.Posix.Types (Fd)

import System.Landlock.Flags (AccessFsFlag(..), accessFsFlagToBit, fromBits, toBits)

-- | Kind of 'Rule's.
data RuleType = PathBeneath

-- | A rule enforced by Landlock, to be registered using 'System.Landlock.addRule'.
--
-- 'Rule's can be constructed using the relevant functions, like 'pathBeneath'.
data Rule (a :: RuleType) where
    PathBeneathRule :: [AccessFsFlag] -> Fd -> Rule 'PathBeneath

deriving instance Show (Rule a)
deriving instance Eq (Rule a)

-- | Retrieve the @enum landlock_rule_type@ value of a given 'Rule'.
ruleType :: Rule a -> #{type enum landlock_rule_type}
ruleType = \case
    PathBeneathRule{} -> #{const LANDLOCK_RULE_PATH_BENEATH}

instance Storable (Rule 'PathBeneath) where
    sizeOf _ = #{size struct landlock_path_beneath_attr}
    alignment _ = #{alignment struct landlock_path_beneath_attr}
    peek ptr = do
        allowedAccess <- #{peek struct landlock_path_beneath_attr, allowed_access} ptr :: IO #{type __u64}
        parentFd <- #{peek struct landlock_path_beneath_attr, parent_fd} ptr :: IO #{type __s32}
        return $ PathBeneathRule (fromBits allowedAccess accessFsFlagToBit) (fromIntegral parentFd)
    poke ptr (PathBeneathRule flags fd) = do
        let allowedAccess = toBits flags accessFsFlagToBit :: #{type __u64}
            parentFd = fromIntegral fd :: #{type __s32}
        #{poke struct landlock_path_beneath_attr, allowed_access} ptr allowedAccess
        #{poke struct landlock_path_beneath_attr, parent_fd} ptr parentFd

-- | Construct a path hierarchy rule definition.
--
-- This corresponds to a rule of type @LANDLOCK_RULE_PATH_BENEATH@, with
-- attributes defined in a @struct landlock_path_beneath_attr@.
pathBeneath :: Fd  -- ^ File descriptor, preferably opened with @O_PATH@, which
                   --   identifies the parent directory of a file hierarchy, or
                   --   just a file.
            -> [AccessFsFlag]  -- ^ Allowed actions for this file hierarchy
                               --   (cf. 'AccessFsFlag').
            -> Rule 'PathBeneath
pathBeneath fd flags = PathBeneathRule flags fd