Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4c3e9e2d authored by Tetsuo Handa's avatar Tetsuo Handa Committed by James Morris
Browse files

TOMOYO: Add numeric values grouping support.



This patch adds numeric values grouping support, which is useful for grouping
numeric values such as file's UID, DAC's mode, ioctl()'s cmd number.

Signed-off-by: default avatarTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent babcd378
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o path_group.o
obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o path_group.o number_group.o
+161 −0
Original line number Diff line number Diff line
@@ -118,6 +118,159 @@ static bool tomoyo_print_name_union(struct tomoyo_io_buffer *head,
	return tomoyo_io_printf(head, " %s", ptr->filename->name);
}

/**
 * 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.
 */
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_print_number_union - Print a tomoyo_number_union.
 *
 * @head:       Pointer to "struct tomoyo_io_buffer".
 * @ptr:        Pointer to "struct tomoyo_number_union".
 *
 * Returns true on success, false otherwise.
 */
bool tomoyo_print_number_union(struct tomoyo_io_buffer *head,
			       const struct tomoyo_number_union *ptr)
{
	unsigned long min;
	unsigned long max;
	u8 min_type;
	u8 max_type;
	if (!tomoyo_io_printf(head, " "))
		return false;
	if (ptr->is_group)
		return tomoyo_io_printf(head, "@%s",
					ptr->group->group_name->name);
	min_type = ptr->min_type;
	max_type = ptr->max_type;
	min = ptr->values[0];
	max = ptr->values[1];
	switch (min_type) {
	case TOMOYO_VALUE_TYPE_HEXADECIMAL:
		if (!tomoyo_io_printf(head, "0x%lX", min))
			return false;
		break;
	case TOMOYO_VALUE_TYPE_OCTAL:
		if (!tomoyo_io_printf(head, "0%lo", min))
			return false;
		break;
	default:
		if (!tomoyo_io_printf(head, "%lu", min))
			return false;
		break;
	}
	if (min == max && min_type == max_type)
		return true;
	switch (max_type) {
	case TOMOYO_VALUE_TYPE_HEXADECIMAL:
		return tomoyo_io_printf(head, "-0x%lX", max);
	case TOMOYO_VALUE_TYPE_OCTAL:
		return tomoyo_io_printf(head, "-0%lo", max);
	default:
		return tomoyo_io_printf(head, "-%lu", max);
	}
}

/**
 * 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_is_correct_path(data, 0, 0, 0))
			return false;
		num->group = tomoyo_get_number_group(data + 1);
		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_is_byte_range - Check whether the string isa \ooo style octal value.
 *
@@ -1750,6 +1903,8 @@ static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head)
		return tomoyo_write_no_rewrite_policy(data, is_delete);
	if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_PATH_GROUP))
		return tomoyo_write_path_group_policy(data, is_delete);
	if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NUMBER_GROUP))
		return tomoyo_write_number_group_policy(data, is_delete);
	return -EINVAL;
}

@@ -1812,6 +1967,12 @@ static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head)
			head->read_var2 = NULL;
			head->read_step = 10;
		case 10:
			if (!tomoyo_read_number_group_policy(head))
				break;
			head->read_var1 = NULL;
			head->read_var2 = NULL;
			head->read_step = 11;
		case 11:
			head->read_eof = true;
			break;
		default:
+61 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ struct linux_binprm;
#define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN      "no_initialize_domain "
#define TOMOYO_KEYWORD_NO_KEEP_DOMAIN            "no_keep_domain "
#define TOMOYO_KEYWORD_PATH_GROUP                "path_group "
#define TOMOYO_KEYWORD_NUMBER_GROUP              "number_group "
#define TOMOYO_KEYWORD_SELECT                    "select "
#define TOMOYO_KEYWORD_USE_PROFILE               "use_profile "
#define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ  "ignore_global_allow_read"
@@ -62,6 +63,12 @@ struct linux_binprm;
#define TOMOYO_ROOT_NAME                         "<kernel>"
#define TOMOYO_ROOT_NAME_LEN                     (sizeof(TOMOYO_ROOT_NAME) - 1)

/* Value type definition. */
#define TOMOYO_VALUE_TYPE_INVALID     0
#define TOMOYO_VALUE_TYPE_DECIMAL     1
#define TOMOYO_VALUE_TYPE_OCTAL       2
#define TOMOYO_VALUE_TYPE_HEXADECIMAL 3

/* Index numbers for Access Controls. */
enum tomoyo_mac_index {
	TOMOYO_MAC_FOR_FILE,  /* domain_policy.conf */
@@ -211,6 +218,14 @@ struct tomoyo_name_union {
	u8 is_group;
};

struct tomoyo_number_union {
	unsigned long values[2];
	struct tomoyo_number_group *group;
	u8 min_type;
	u8 max_type;
	u8 is_group;
};

/* Structure for "path_group" directive. */
struct tomoyo_path_group {
	struct list_head list;
@@ -219,6 +234,14 @@ struct tomoyo_path_group {
	atomic_t users;
};

/* Structure for "number_group" directive. */
struct tomoyo_number_group {
	struct list_head list;
	const struct tomoyo_path_info *group_name;
	struct list_head member_list;
	atomic_t users;
};

/* Structure for "path_group" directive. */
struct tomoyo_path_group_member {
	struct list_head list;
@@ -226,6 +249,13 @@ struct tomoyo_path_group_member {
	const struct tomoyo_path_info *member_name;
};

/* Structure for "number_group" directive. */
struct tomoyo_number_group_member {
	struct list_head list;
	bool is_deleted;
	struct tomoyo_number_union number;
};

/*
 * tomoyo_acl_info is a structure which is used for holding
 *
@@ -554,9 +584,18 @@ bool tomoyo_parse_name_union(const char *filename,
bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
			       const struct tomoyo_path_group *group,
			       const bool may_use_pattern);
/* Check whether the given value matches the given number_group. */
bool tomoyo_number_matches_group(const unsigned long min,
				 const unsigned long max,
				 const struct tomoyo_number_group *group);
/* Check whether the given filename matches the given pattern. */
bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
				 const struct tomoyo_path_info *pattern);

bool tomoyo_print_number_union(struct tomoyo_io_buffer *head,
			       const struct tomoyo_number_union *ptr);
bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num);

/* Read "alias" entry in exception policy. */
bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head);
/*
@@ -570,6 +609,8 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head);
bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head);
/* Read "path_group" entry in exception policy. */
bool tomoyo_read_path_group_policy(struct tomoyo_io_buffer *head);
/* Read "number_group" entry in exception policy. */
bool tomoyo_read_number_group_policy(struct tomoyo_io_buffer *head);
/* Read "allow_read" entry in exception policy. */
bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head);
/* Read "deny_rewrite" entry in exception policy. */
@@ -614,6 +655,8 @@ int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete);
int tomoyo_write_pattern_policy(char *data, const bool is_delete);
/* Create "path_group" entry in exception policy. */
int tomoyo_write_path_group_policy(char *data, const bool is_delete);
/* Create "number_group" entry in exception policy. */
int tomoyo_write_number_group_policy(char *data, const bool is_delete);
/* Find a domain by the given name. */
struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname);
/* Find or create a domain by the given name. */
@@ -623,6 +666,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *

/* Allocate memory for "struct tomoyo_path_group". */
struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name);
struct tomoyo_number_group *tomoyo_get_number_group(const char *group_name);

/* Check mode for specified functionality. */
unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
@@ -632,6 +676,8 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
/* Run policy loader when /sbin/init starts. */
void tomoyo_load_policy(const char *filename);

void tomoyo_put_number_union(struct tomoyo_number_union *ptr);

/* Convert binary string to ascii string. */
int tomoyo_encode(char *buffer, int buflen, const char *str);

@@ -697,6 +743,7 @@ extern struct srcu_struct tomoyo_ss;
extern struct list_head tomoyo_domain_list;

extern struct list_head tomoyo_path_group_list;
extern struct list_head tomoyo_number_group_list;
extern struct list_head tomoyo_domain_initializer_list;
extern struct list_head tomoyo_domain_keeper_list;
extern struct list_head tomoyo_alias_list;
@@ -773,6 +820,12 @@ static inline void tomoyo_put_path_group(struct tomoyo_path_group *group)
		atomic_dec(&group->users);
}

static inline void tomoyo_put_number_group(struct tomoyo_number_group *group)
{
	if (group)
		atomic_dec(&group->users);
}

static inline struct tomoyo_domain_info *tomoyo_domain(void)
{
	return current_cred()->security;
@@ -797,6 +850,14 @@ static inline bool tomoyo_is_same_name_union
		p1->is_group == p2->is_group;
}

static inline bool tomoyo_is_same_number_union
(const struct tomoyo_number_union *p1, const struct tomoyo_number_union *p2)
{
	return p1->values[0] == p2->values[0] && p1->values[1] == p2->values[1]
		&& p1->group == p2->group && p1->min_type == p2->min_type &&
		p1->max_type == p2->max_type && p1->is_group == p2->is_group;
}

static inline bool tomoyo_is_same_path_acl(const struct tomoyo_path_acl *p1,
					   const struct tomoyo_path_acl *p2)
{
+14 −0
Original line number Diff line number Diff line
@@ -76,6 +76,20 @@ static bool tomoyo_compare_name_union_pattern(const struct tomoyo_path_info
	return false;
}

void tomoyo_put_number_union(struct tomoyo_number_union *ptr)
{
	if (ptr && ptr->is_group)
		tomoyo_put_number_group(ptr->group);
}

bool tomoyo_compare_number_union(const unsigned long value,
				 const struct tomoyo_number_union *ptr)
{
	if (ptr->is_group)
		return tomoyo_number_matches_group(value, value, ptr->group);
	return value >= ptr->values[0] && value <= ptr->values[1];
}

/**
 * tomoyo_path2keyword - Get the name of single path operation.
 *
+41 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
enum tomoyo_gc_id {
	TOMOYO_ID_PATH_GROUP,
	TOMOYO_ID_PATH_GROUP_MEMBER,
	TOMOYO_ID_NUMBER_GROUP,
	TOMOYO_ID_NUMBER_GROUP_MEMBER,
	TOMOYO_ID_DOMAIN_INITIALIZER,
	TOMOYO_ID_DOMAIN_KEEPER,
	TOMOYO_ID_ALIAS,
@@ -162,6 +164,16 @@ static void tomoyo_del_path_group(struct tomoyo_path_group *group)
	tomoyo_put_name(group->group_name);
}

static void tomoyo_del_number_group_member(struct tomoyo_number_group_member
					   *member)
{
}

static void tomoyo_del_number_group(struct tomoyo_number_group *group)
{
	tomoyo_put_name(group->group_name);
}

static void tomoyo_collect_entry(void)
{
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
@@ -329,6 +341,29 @@ static void tomoyo_collect_entry(void)
				break;
		}
	}
	{
		struct tomoyo_number_group *group;
		list_for_each_entry_rcu(group, &tomoyo_number_group_list, list) {
			struct tomoyo_number_group_member *member;
			list_for_each_entry_rcu(member, &group->member_list,
						list) {
				if (!member->is_deleted)
					continue;
				if (tomoyo_add_to_gc(TOMOYO_ID_NUMBER_GROUP_MEMBER,
						     member))
					list_del_rcu(&member->list);
				else
					break;
			}
			if (!list_empty(&group->member_list) ||
			    atomic_read(&group->users))
				continue;
			if (tomoyo_add_to_gc(TOMOYO_ID_NUMBER_GROUP, group))
				list_del_rcu(&group->list);
			else
				break;
		}
	}
	mutex_unlock(&tomoyo_policy_lock);
}

@@ -376,6 +411,12 @@ static void tomoyo_kfree_entry(void)
		case TOMOYO_ID_PATH_GROUP:
			tomoyo_del_path_group(p->element);
			break;
		case TOMOYO_ID_NUMBER_GROUP_MEMBER:
			tomoyo_del_number_group_member(p->element);
			break;
		case TOMOYO_ID_NUMBER_GROUP:
			tomoyo_del_number_group(p->element);
			break;
		default:
			printk(KERN_WARNING "Unknown type\n");
			break;
Loading