cheri-security / MorelloLinux / exampleCode / src / util / morello.h
morello.h
Raw
/*
 * Copyright (c) 2023 Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#pragma once

#include <cheriintrin.h>
#include "perms.h"

/**
 * Returns length of a capability:
 * length = limit - base
 * Length of a NULL capability is returned as 0.
 */
size_t cheri_length_get_zero(const void * __capability cap);
/**
 * Returns limit of the capability as a pointer.
 * Note that limit for a NULL pointer is returned as NULL.
 */
const void * __capability cheri_get_limit(const void * __capability cap);

/**
 * Returns difference between the address and the limit
 * of a capability: tail = limit - (base + offset) if this
 * capability is in bounds, otherwise, returns NULL.
 */
size_t cheri_get_tail(const void * __capability cap);

/**
 * Returns true if capability is in bounds.
 */
bool cheri_in_bounds(const void * __capability cap);

/**
 * Returns true if a capability is dereferenceable:
 * capability's tag is set, it is not sealed and it
 * is in bounds.
 */
bool cheri_is_deref(const void * __capability cap);

/**
 * Returns true if capability is local.
 */
bool cheri_is_local(const void * __capability cap);

/**
 * Convert capability into string representation.
 * If dst is NULL, a pointer to a static object is returned.
 * Using it may be unsafe.
 */
const char *cap_to_str(char *dst, const void * __capability cap);
const char *cap_perms_to_str(char *dst, const void * __capability cap);
const char *cap_seal_to_str(char *dst, const void * __capability cap);

#if defined(__GNUC__) && !defined(__clang__) && defined(__CHERI__)
// GCC does not provide this builtin.
inline static void * __capability __builtin_cheri_stack_get()
{
    void * __capability ret;
    __asm__ volatile ("mov %0, csp" : "=C"(ret));
    return ret;
}
#endif

#ifndef cheri_csp_get
#define cheri_csp_get() __builtin_cheri_stack_get()
#endif

/**
 * Access CID register.
 */
inline static void * __capability __builtin_cheri_cid_get()
{
    void * __capability ret;
    __asm__ volatile ("mrs %0, CID_EL0" : "=C"(ret));
    return ret;
}

#ifndef cheri_cid_get
#define cheri_cid_get() __builtin_cheri_cid_get()
#endif

/**
 * Create LPB-sealed sentry.
 */
inline static void * __capability morello_lpb_sentry_create(void *cap)
{
    void * __capability ret;
    __asm__ ("seal %0, %1, lpb" : "=C"(ret) : "C"(cap));
    return ret;
}

/**
 * Create LB-sealed sentry.
 */
inline static void * __capability morello_lb_sentry_create(void *cap)
{
    void * __capability ret;
    __asm__ ("seal %0, %1, lb" : "=C"(ret) : "C"(cap));
    return ret;
}

/**
 * Checks if given permissions are present in the capability.
 */
inline static bool cheri_check_perms(const void * __capability cap, size_t perms)
{
    return (cheri_perms_get(cap) | ~perms) == ~0;
}

#ifndef cheri_copy_from_high
#define cheri_copy_from_high(cap) __builtin_cheri_copy_from_high(cap)
#endif