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

typedef unsigned long size_t;
typedef long ssize_t;
typedef _Bool bool;

#include "morello.h"

int sprintf(char *dst, const char *fmt, ...);
char *strcpy(char *dst, const char *src);

#define NULL ((void *)0)
#define TEST(x, f) (((x) & (f)) == (f))

static const char permnames[] = {
    'G',
    'r', 'R', 'M',
    'w', 'W', 'L',
    'x', 'E', 'S',
    's', 'u',
    'I',
    'C',
    'V',
    '1', '2', '3',
    0
};

static size_t permbits[] = {
    PERM_GLOBAL,
    PERM_LOAD, PERM_LOAD_CAP, PERM_MUTABLE_LOAD,
    PERM_STORE, PERM_STORE_CAP, PERM_STORE_LOCAL_CAP,
    PERM_EXECUTE, PERM_EXECUTIVE, PERM_SYS_REG,
    PERM_SEAL, PERM_UNSEAL,
    PERM_CAP_INVOKE,
    PERM_CMPT_ID,
    PERM_VMEM,
    PERM_USER_1, PERM_USER_2, PERM_USER_3,
    0ul
};

static char buf[128];

const char *cap_perms_to_str(char *dst, const void * __capability cap)
{
    if (dst == NULL) {
        dst = buf;
    }
    const char *res = dst;
    size_t perms = cheri_perms_get(cap);
    const size_t *p = permbits;
    const char *n = permnames;
    for(; *p && *n; n++, p++, dst++) {
        *dst = TEST(perms, *p) ? *n : '-';
    }
    *dst = '\0';
    return res;
}

const char *cap_seal_to_str(char *dst, const void * __capability cap)
{
    if (dst == NULL) {
        dst = buf;
    }
    const char *res = dst;
    unsigned int otype = cheri_type_get(cap) & 0x7fffu;
    switch (otype) {
        case 0:
            strcpy(dst, "none");
            break;
        case 1:
            strcpy(dst, "rb");
            break;
        case 2:
            strcpy(dst, "lpb");
            break;
        case 3:
            strcpy(dst, "lb");
            break;
        default:
            sprintf(dst, "%04x", otype);
    }
    return res;
}

/**
 * Prints detailed information about capability to string.
 */
const char *cap_to_str(char *dst, const void * __capability cap)
{
    if (dst == NULL) {
        dst = buf;
    }
    size_t tag = cheri_tag_get(cap);
    size_t addr = cheri_address_get(cap);
    size_t base = cheri_base_get(cap);
    size_t len = cheri_length_get(cap);
    size_t lim = base + len;
    ssize_t offset = (ssize_t)cheri_offset_get(cap);

    char perm[19];
    char seal[5];
    sprintf(dst, "%016lx %c [%016lx:%016lx) %s %-4s %ld of %lu",
        addr, tag ? '1' : '0', base, lim, cap_perms_to_str(perm, cap),
        cap_seal_to_str(seal, cap), offset, len);
    return dst;
}