LLVM Builtins for CHERI

A list of builtins

// file:
//  sys/cheri/cheric.h

/*
 * Programmer-friendly macros for CHERI-aware C code -- requires use of
 * CHERI-aware Clang/LLVM, and full capability context switching.
 */
#define cheri_getlen(x)         __builtin_cheri_length_get((x))
#define cheri_getbase(x)        __builtin_cheri_base_get((x))
#define cheri_getoffset(x)      __builtin_cheri_offset_get((x))
#define cheri_getaddress(x)     __builtin_cheri_address_get((x))
#define cheri_getperm(x)        __builtin_cheri_perms_get((x))
#define cheri_getsealed(x)      __builtin_cheri_sealed_get((x))
#define cheri_gettag(x)         __builtin_cheri_tag_get((x))
#define cheri_gettype(x)        __builtin_cheri_type_get((x))

#define cheri_andperm(x, y)     __builtin_cheri_perms_and((x), (y))
#define cheri_clearperm(x, y)   __builtin_cheri_perms_and((x), ~(y))
#define cheri_cleartag(x)       __builtin_cheri_tag_clear((x))
#define cheri_incoffset(x, y)   __builtin_cheri_offset_increment((x), (y))
#define cheri_setoffset(x, y)   __builtin_cheri_offset_set((x), (y))
#define cheri_setaddress(x, y)  __builtin_cheri_address_set((x), (y))

#define cheri_seal(x, y)        __builtin_cheri_seal((x), (y))
#define cheri_unseal(x, y)      __builtin_cheri_unseal((x), (y))

#define cheri_getcause()        __builtin_mips_cheri_get_cause()
#define cheri_setcause(x)       __builtin_mips_cheri_set_cause(x)

#define cheri_ccheckperm(c, p)  __builtin_cheri_perms_check((c), (p))
#define cheri_cchecktype(c, t)  __builtin_cheri_type_check((c), (t))

#define cheri_getdefault()      __builtin_cheri_global_data_get()
#define cheri_getidc()          __builtin_mips_cheri_get_invoke_data_cap()
#define cheri_getkr1c()         __builtin_mips_cheri_get_kernel_cap1()
#define cheri_getkr2c()         __builtin_mips_cheri_get_kernel_cap2()
#define cheri_getkcc()          __builtin_mips_cheri_get_kernel_code_cap()
#define cheri_getkdc()          __builtin_mips_cheri_get_kernel_data_cap()
#define cheri_getepcc()         __builtin_mips_cheri_get_exception_program_counter_cap()
#define cheri_getpcc()          __builtin_cheri_program_counter_get()
#define cheri_getstack()        __builtin_cheri_stack_get()

#define cheri_local(c)          cheri_andperm((c), ~CHERI_PERM_GLOBAL)

#define cheri_csetbounds(x, y)  __builtin_cheri_bounds_set((x), (y))
#define cheri_csetboundsexact(x, y)     __builtin_cheri_bounds_set_exact((x), (y))
/* XXXAR: shouldn't this be the default and we add cheri_csetbounds_untyped? */
#define cheri_csetbounds_changetype(type, x, y) \
        (type)cheri_csetbounds((x), (y)))
#define cheri_csetbounds_sametype(x, y) \
        ((__typeof__(x))cheri_csetbounds((x), (y)))

/* Create an untagged capability from an integer */
#define cheri_fromint(x)        cheri_incoffset(NULL, x)

Tracking __builtin_cheri_perms_and

cheri_andperm

// file: sys/cheri/cheric.h

#define	cheri_andperm(x, y)	__builtin_cheri_perms_and((x), (y))

__builtin_cheri_perms_and is compiler built in function to emit ??? instruction:

// file:
//   clang/include/clang/Basic/Builtins.def

BUILTIN(__builtin_cheri_perms_and, "v*mvC*mz", "nc")

LLM: What does this mean ???????????

// file: 
//  clang/lib/CodeGen/CGBuiltin.cpp: L3624 in CodeGenFunction::EmitBuiltinExpr(..)

switch (BuiltinID){
  ...
  case Builtin::BI__builtin_cheri_perms_and:
    return RValue::get(Builder.CreateCall(
        CGM.getIntrinsic(llvm::Intrinsic::cheri_cap_perms_and, SizeTy),
        {EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1))}));
  ...

}

// file: 
//  clang/lib/CodeGen/CGBuiltin.cpp:L12248 in *CodeGenFunction::EmitMIPSBuiltinExpr()
switch (BuiltinID) {
  ...
  case Mips::BI__builtin_mips_cheri_and_cap_perms:
    return Builder.CreateCall(
        CGM.getIntrinsic(llvm::Intrinsic::cheri_cap_perms_and, SizeTy),
        {EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1))});
  ...
}

Tracking intrinsic cheri_cap_perms_and

cheri_cap_perms_and is an llvm intrinsic defined as:

// file:
//  llvm/include/llvm/IR/IntrinsicsCHERICap.td

def int_cheri_cap_perms_and :
  Intrinsic<[llvm_fatptr_ty],
            [llvm_fatptr_ty, llvm_anyint_ty],
            [IntrNoMem]>;

// LLM: ????????????????
// file:
//   llvm/lib/Target/Mips/CheriPureCapABI.cpp


// file: 
//   llvm/lib/Target/Mips/MipsISelLowering.cpp: LowerCall()

if (ABI.IsCheriPureCap()) {
    if (FirstOffset != -1) {
      SDValue PtrOff = DAG.getPointerAdd(DL, StackPtr, FirstOffset);
      PtrOff = setBounds(DAG, PtrOff, LastOffset, /*CSetBoundsStatsLogged=*/true);
      PtrOff = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, CapType,
          DAG.getConstant(Intrinsic::cheri_cap_perms_and, DL, MVT::i64), PtrOff,
          DAG.getIntPtrConstant(0xFFD7, DL));
      RegsToPass.push_back(std::make_pair(Mips::C13, PtrOff));
      if (cheri::ShouldCollectCSetBoundsStats) {
        StringRef Name = "<unknown function>";
        if (ES) {
          Name = ES->getSymbol();
        } else if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
          Name = G->getGlobal()->getName();
        }
        cheri::CSetBoundsStats->add(
            1, LastOffset, "variadic call lowering",
            cheri::SetBoundsPointerSource::Stack,
            StringRef("setting varargs bounds for call to ") + Name,
            cheri::inferSourceLocation(DL.getDebugLoc(),
                                       DAG.getMachineFunction().getName()));
      }
    } else {
      // ...
    }
    // ...
 }
Created Aug 25, 2019 // Last Updated Sep 5, 2019

If you could revise
the fundmental principles of
computer system design
to improve security...

... what would you change?