/*
* security/tomoyo/util.c
*
* Utility functions for TOMOYO.
*
* Copyright (C) 2005-2010 NTT DATA CORPORATION
*/
#include <linux/slab.h>
#include "common.h"
/* Lock for protecting policy. */
DEFINE_MUTEX(tomoyo_policy_lock);
/* Has /sbin/init started? */
bool tomoyo_policy_loaded;
/**
* tomoyo_parse_ulong - Parse an "unsigned long" value.
*
* @result: Pointer to "unsigned long".
* @str: Pointer to string to parse.
*
* Returns value type on success, 0 otherwise.
*
* The @src is updated to point the first character after the value
* on success.
*/
static u8 tomoyo_parse_ulong(unsigned long *result, char **str)
{
const char *cp = *str;
char *ep;
int base = 10;
if (*cp == '0') {
char c = *(cp + 1);
if (c == 'x' || c == 'X') {
base = 16;
cp += 2;
} else if (c >= '0' && c <= '7') {
base = 8;
cp++;
}
}
*result = simple_strtoul(cp, &ep, base);
if (cp == ep)
return 0;
*str = ep;
switch (base) {
case 16:
return TOMOYO_VALUE_TYPE_HEXADECIMAL;
case 8:
return TOMOYO_VALUE_TYPE_OCTAL;
default:
return TOMOYO_VALUE_TYPE_DECIMAL;
}
}
/**
* tomoyo_print_ulong - Print an "unsigned long" value.
*
* @buffer: Pointer to buffer.
* @buffer_len: Size of @buffer.
* @value: An "unsigned long" value.
* @type: Type of @value.
*
* Returns nothing.
*/
void tomoyo_print_ulong(char *buffer, const int buffer_len,
const unsigned long value, const u8 type)
{
if (type == TOMOYO_VALUE_TYPE_DECIMAL)
snprintf(buffer, buffer_len, "%lu", value);
else if (type == TOMOYO_VALUE_TYPE_OCTAL)
snprintf(buffer, buffer_len, "0%lo", value);
else if (type == TOMOYO_VALUE_TYPE_HEXADECIMAL)
snprintf(buffer, buffer_len, "0x%lX", value);
else
snprintf(buffer, buffer_len, "type(%u)", type);
}
/**
* tomoyo_parse_name_union - Parse a tomoyo_name_union.
*
* @filename: Name or name group.
* @ptr: Pointer to "struct tomoyo_name_union".
*
* Returns true on success, false otherwise.
*/
bool tomoyo_parse_name_union(const char *filename,
struct tomoyo_name_union *ptr)
{
if (!tomoyo_correct_word(filename))
return false;
if (filename[0] == '@') {
ptr->group = tomoyo_get_group(filename + 1, TOMOYO_PATH_GROUP);
ptr->is_group = true;
return ptr->group != NULL;
}
ptr->filename = tomoyo_get_name(filename);
ptr->is_group = false;
return ptr->filename != NULL;
}
/**
* tomoyo_parse_number_union - Parse a tomoyo_number_union.
*
* @data: Number or number range or number group.
* @ptr: Pointer to "struct tomoyo_number_union".
*
* Returns true on success, false otherwise.
*/
bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num)
{
u8 type;
unsigned long v;
memset(num, 0, sizeof(*num));
if (data[0] == '@') {
if (!tomoyo_correct_word(data))
return false;
num->group = tomoyo_get_group(data + 1, TOMOYO_NUMBER_GROUP);
num->is_group = true;
return num->group != NULL;
}
type = tomoyo_parse_ulong(&v, &data);
if (!type)
return false;
num->values[0] = v;
num->min_type = type;
if (!*data) {
num->values[1] = v;
num->max_type = type;
return true;
}
if (*data++ != '-')
return false;
type = tomoyo_parse_ulong(&v, &data);
if (!type || *data)
return false;
num->values[1] = v;
num->max_type = type;
return true;
}
/**
* tomoyo_byte_range - Check whether the string is a \ooo style octal value.
*
* @str: Pointer to the string.
*
* Returns true if @str is a \ooo style octal value, false otherwise.
*
* TOMOYO uses \ooo style representation for 0x01 - 0x20 and 0x7F - 0xFF.
* This function verifies that \ooo is in valid range.
*/
static inline bool tomoyo_byte_range(const char *str)
{
return *str >= '0' && *str++ <= '3' &&
*str >= '0' && *str++ <= '7' &&
*str >= '0'