|
@@ -49,6 +49,9 @@ const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
|
|
|
[TOMOYO_TYPE_CHGRP] = "chgrp",
|
|
|
};
|
|
|
|
|
|
+/*
|
|
|
+ * Mapping table from "enum tomoyo_path_acl_index" to "enum tomoyo_mac_index".
|
|
|
+ */
|
|
|
static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
|
|
|
[TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE,
|
|
|
[TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN,
|
|
@@ -63,17 +66,27 @@ static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
|
|
|
[TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT,
|
|
|
};
|
|
|
|
|
|
+/*
|
|
|
+ * Mapping table from "enum tomoyo_mkdev_acl_index" to "enum tomoyo_mac_index".
|
|
|
+ */
|
|
|
static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = {
|
|
|
[TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK,
|
|
|
[TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR,
|
|
|
};
|
|
|
|
|
|
+/*
|
|
|
+ * Mapping table from "enum tomoyo_path2_acl_index" to "enum tomoyo_mac_index".
|
|
|
+ */
|
|
|
static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = {
|
|
|
[TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK,
|
|
|
[TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME,
|
|
|
[TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT,
|
|
|
};
|
|
|
|
|
|
+/*
|
|
|
+ * Mapping table from "enum tomoyo_path_number_acl_index" to
|
|
|
+ * "enum tomoyo_mac_index".
|
|
|
+ */
|
|
|
static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
|
|
|
[TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE,
|
|
|
[TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR,
|
|
@@ -85,41 +98,76 @@ static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
|
|
|
[TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP,
|
|
|
};
|
|
|
|
|
|
+/**
|
|
|
+ * tomoyo_put_name_union - Drop reference on "struct tomoyo_name_union".
|
|
|
+ *
|
|
|
+ * @ptr: Pointer to "struct tomoyo_name_union".
|
|
|
+ *
|
|
|
+ * Returns nothing.
|
|
|
+ */
|
|
|
void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
|
|
|
{
|
|
|
- if (!ptr)
|
|
|
- return;
|
|
|
- if (ptr->is_group)
|
|
|
- tomoyo_put_group(ptr->group);
|
|
|
- else
|
|
|
- tomoyo_put_name(ptr->filename);
|
|
|
+ tomoyo_put_group(ptr->group);
|
|
|
+ tomoyo_put_name(ptr->filename);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * tomoyo_compare_name_union - Check whether a name matches "struct tomoyo_name_union" or not.
|
|
|
+ *
|
|
|
+ * @name: Pointer to "struct tomoyo_path_info".
|
|
|
+ * @ptr: Pointer to "struct tomoyo_name_union".
|
|
|
+ *
|
|
|
+ * Returns "struct tomoyo_path_info" if @name matches @ptr, NULL otherwise.
|
|
|
+ */
|
|
|
const struct tomoyo_path_info *
|
|
|
tomoyo_compare_name_union(const struct tomoyo_path_info *name,
|
|
|
const struct tomoyo_name_union *ptr)
|
|
|
{
|
|
|
- if (ptr->is_group)
|
|
|
+ if (ptr->group)
|
|
|
return tomoyo_path_matches_group(name, ptr->group);
|
|
|
if (tomoyo_path_matches_pattern(name, ptr->filename))
|
|
|
return ptr->filename;
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * tomoyo_put_number_union - Drop reference on "struct tomoyo_number_union".
|
|
|
+ *
|
|
|
+ * @ptr: Pointer to "struct tomoyo_number_union".
|
|
|
+ *
|
|
|
+ * Returns nothing.
|
|
|
+ */
|
|
|
void tomoyo_put_number_union(struct tomoyo_number_union *ptr)
|
|
|
{
|
|
|
- if (ptr && ptr->is_group)
|
|
|
- tomoyo_put_group(ptr->group);
|
|
|
+ tomoyo_put_group(ptr->group);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * tomoyo_compare_number_union - Check whether a value matches "struct tomoyo_number_union" or not.
|
|
|
+ *
|
|
|
+ * @value: Number to check.
|
|
|
+ * @ptr: Pointer to "struct tomoyo_number_union".
|
|
|
+ *
|
|
|
+ * Returns true if @value matches @ptr, false otherwise.
|
|
|
+ */
|
|
|
bool tomoyo_compare_number_union(const unsigned long value,
|
|
|
const struct tomoyo_number_union *ptr)
|
|
|
{
|
|
|
- if (ptr->is_group)
|
|
|
+ if (ptr->group)
|
|
|
return tomoyo_number_matches_group(value, value, ptr->group);
|
|
|
return value >= ptr->values[0] && value <= ptr->values[1];
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * tomoyo_add_slash - Add trailing '/' if needed.
|
|
|
+ *
|
|
|
+ * @buf: Pointer to "struct tomoyo_path_info".
|
|
|
+ *
|
|
|
+ * Returns nothing.
|
|
|
+ *
|
|
|
+ * @buf must be generated by tomoyo_encode() because this function does not
|
|
|
+ * allocate memory for adding '/'.
|
|
|
+ */
|
|
|
static void tomoyo_add_slash(struct tomoyo_path_info *buf)
|
|
|
{
|
|
|
if (buf->is_dir)
|
|
@@ -247,6 +295,18 @@ static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
|
|
|
filename->name, buffer);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * tomoyo_check_path_acl - Check permission for path operation.
|
|
|
+ *
|
|
|
+ * @r: Pointer to "struct tomoyo_request_info".
|
|
|
+ * @ptr: Pointer to "struct tomoyo_acl_info".
|
|
|
+ *
|
|
|
+ * Returns true if granted, false otherwise.
|
|
|
+ *
|
|
|
+ * To be able to use wildcard for domain transition, this function sets
|
|
|
+ * matching entry on success. Since the caller holds tomoyo_read_lock(),
|
|
|
+ * it is safe to set matching entry.
|
|
|
+ */
|
|
|
static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
|
|
|
const struct tomoyo_acl_info *ptr)
|
|
|
{
|
|
@@ -261,6 +321,14 @@ static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * tomoyo_check_path_number_acl - Check permission for path number operation.
|
|
|
+ *
|
|
|
+ * @r: Pointer to "struct tomoyo_request_info".
|
|
|
+ * @ptr: Pointer to "struct tomoyo_acl_info".
|
|
|
+ *
|
|
|
+ * Returns true if granted, false otherwise.
|
|
|
+ */
|
|
|
static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
|
|
|
const struct tomoyo_acl_info *ptr)
|
|
|
{
|
|
@@ -273,6 +341,14 @@ static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
|
|
|
&acl->name);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * tomoyo_check_path2_acl - Check permission for path path operation.
|
|
|
+ *
|
|
|
+ * @r: Pointer to "struct tomoyo_request_info".
|
|
|
+ * @ptr: Pointer to "struct tomoyo_acl_info".
|
|
|
+ *
|
|
|
+ * Returns true if granted, false otherwise.
|
|
|
+ */
|
|
|
static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
|
|
|
const struct tomoyo_acl_info *ptr)
|
|
|
{
|
|
@@ -284,8 +360,16 @@ static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
|
|
|
&acl->name2);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * tomoyo_check_mkdev_acl - Check permission for path number number number operation.
|
|
|
+ *
|
|
|
+ * @r: Pointer to "struct tomoyo_request_info".
|
|
|
+ * @ptr: Pointer to "struct tomoyo_acl_info".
|
|
|
+ *
|
|
|
+ * Returns true if granted, false otherwise.
|
|
|
+ */
|
|
|
static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
|
|
|
- const struct tomoyo_acl_info *ptr)
|
|
|
+ const struct tomoyo_acl_info *ptr)
|
|
|
{
|
|
|
const struct tomoyo_mkdev_acl *acl =
|
|
|
container_of(ptr, typeof(*acl), head);
|
|
@@ -300,13 +384,20 @@ static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
|
|
|
&acl->name);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * tomoyo_same_path_acl - Check for duplicated "struct tomoyo_path_acl" entry.
|
|
|
+ *
|
|
|
+ * @a: Pointer to "struct tomoyo_acl_info".
|
|
|
+ * @b: Pointer to "struct tomoyo_acl_info".
|
|
|
+ *
|
|
|
+ * Returns true if @a == @b except permission bits, false otherwise.
|
|
|
+ */
|
|
|
static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
|
|
|
const struct tomoyo_acl_info *b)
|
|
|
{
|
|
|
const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
|
|
|
const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
|
|
|
- return tomoyo_same_acl_head(&p1->head, &p2->head) &&
|
|
|
- tomoyo_same_name_union(&p1->name, &p2->name);
|
|
|
+ return tomoyo_same_name_union(&p1->name, &p2->name);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -364,23 +455,37 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename,
|
|
|
return error;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * tomoyo_same_mkdev_acl - Check for duplicated "struct tomoyo_mkdev_acl" entry.
|
|
|
+ *
|
|
|
+ * @a: Pointer to "struct tomoyo_acl_info".
|
|
|
+ * @b: Pointer to "struct tomoyo_acl_info".
|
|
|
+ *
|
|
|
+ * Returns true if @a == @b except permission bits, false otherwise.
|
|
|
+ */
|
|
|
static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a,
|
|
|
const struct tomoyo_acl_info *b)
|
|
|
{
|
|
|
- const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1),
|
|
|
- head);
|
|
|
- const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2),
|
|
|
- head);
|
|
|
- return tomoyo_same_acl_head(&p1->head, &p2->head)
|
|
|
- && tomoyo_same_name_union(&p1->name, &p2->name)
|
|
|
- && tomoyo_same_number_union(&p1->mode, &p2->mode)
|
|
|
- && tomoyo_same_number_union(&p1->major, &p2->major)
|
|
|
- && tomoyo_same_number_union(&p1->minor, &p2->minor);
|
|
|
+ const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head);
|
|
|
+ const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head);
|
|
|
+ return tomoyo_same_name_union(&p1->name, &p2->name) &&
|
|
|
+ tomoyo_same_number_union(&p1->mode, &p2->mode) &&
|
|
|
+ tomoyo_same_number_union(&p1->major, &p2->major) &&
|
|
|
+ tomoyo_same_number_union(&p1->minor, &p2->minor);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * tomoyo_merge_mkdev_acl - Merge duplicated "struct tomoyo_mkdev_acl" entry.
|
|
|
+ *
|
|
|
+ * @a: Pointer to "struct tomoyo_acl_info".
|
|
|
+ * @b: Pointer to "struct tomoyo_acl_info".
|
|
|
+ * @is_delete: True for @a &= ~@b, false for @a |= @b.
|
|
|
+ *
|
|
|
+ * Returns true if @a is empty, false otherwise.
|
|
|
+ */
|
|
|
static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
|
|
|
- struct tomoyo_acl_info *b,
|
|
|
- const bool is_delete)
|
|
|
+ struct tomoyo_acl_info *b,
|
|
|
+ const bool is_delete)
|
|
|
{
|
|
|
u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
|
|
|
head)->perm;
|
|
@@ -411,9 +516,9 @@ static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
|
|
|
* Caller holds tomoyo_read_lock().
|
|
|
*/
|
|
|
static int tomoyo_update_mkdev_acl(const u8 type, const char *filename,
|
|
|
- char *mode, char *major, char *minor,
|
|
|
- struct tomoyo_domain_info * const
|
|
|
- domain, const bool is_delete)
|
|
|
+ char *mode, char *major, char *minor,
|
|
|
+ struct tomoyo_domain_info * const domain,
|
|
|
+ const bool is_delete)
|
|
|
{
|
|
|
struct tomoyo_mkdev_acl e = {
|
|
|
.head.type = TOMOYO_TYPE_MKDEV_ACL,
|
|
@@ -436,16 +541,32 @@ static int tomoyo_update_mkdev_acl(const u8 type, const char *filename,
|
|
|
return error;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * tomoyo_same_path2_acl - Check for duplicated "struct tomoyo_path2_acl" entry.
|
|
|
+ *
|
|
|
+ * @a: Pointer to "struct tomoyo_acl_info".
|
|
|
+ * @b: Pointer to "struct tomoyo_acl_info".
|
|
|
+ *
|
|
|
+ * Returns true if @a == @b except permission bits, false otherwise.
|
|
|
+ */
|
|
|
static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
|
|
|
const struct tomoyo_acl_info *b)
|
|
|
{
|
|
|
const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
|
|
|
const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
|
|
|
- return tomoyo_same_acl_head(&p1->head, &p2->head)
|
|
|
- && tomoyo_same_name_union(&p1->name1, &p2->name1)
|
|
|
- && tomoyo_same_name_union(&p1->name2, &p2->name2);
|
|
|
+ return tomoyo_same_name_union(&p1->name1, &p2->name1) &&
|
|
|
+ tomoyo_same_name_union(&p1->name2, &p2->name2);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * tomoyo_merge_path2_acl - Merge duplicated "struct tomoyo_path2_acl" entry.
|
|
|
+ *
|
|
|
+ * @a: Pointer to "struct tomoyo_acl_info".
|
|
|
+ * @b: Pointer to "struct tomoyo_acl_info".
|
|
|
+ * @is_delete: True for @a &= ~@b, false for @a |= @b.
|
|
|
+ *
|
|
|
+ * Returns true if @a is empty, false otherwise.
|
|
|
+ */
|
|
|
static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
|
|
|
struct tomoyo_acl_info *b,
|
|
|
const bool is_delete)
|
|
@@ -532,6 +653,14 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
|
|
|
return error;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry.
|
|
|
+ *
|
|
|
+ * @a: Pointer to "struct tomoyo_acl_info".
|
|
|
+ * @b: Pointer to "struct tomoyo_acl_info".
|
|
|
+ *
|
|
|
+ * Returns true if @a == @b except permission bits, false otherwise.
|
|
|
+ */
|
|
|
static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
|
|
|
const struct tomoyo_acl_info *b)
|
|
|
{
|
|
@@ -539,11 +668,19 @@ static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
|
|
|
head);
|
|
|
const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
|
|
|
head);
|
|
|
- return tomoyo_same_acl_head(&p1->head, &p2->head)
|
|
|
- && tomoyo_same_name_union(&p1->name, &p2->name)
|
|
|
- && tomoyo_same_number_union(&p1->number, &p2->number);
|
|
|
+ return tomoyo_same_name_union(&p1->name, &p2->name) &&
|
|
|
+ tomoyo_same_number_union(&p1->number, &p2->number);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * tomoyo_merge_path_number_acl - Merge duplicated "struct tomoyo_path_number_acl" entry.
|
|
|
+ *
|
|
|
+ * @a: Pointer to "struct tomoyo_acl_info".
|
|
|
+ * @b: Pointer to "struct tomoyo_acl_info".
|
|
|
+ * @is_delete: True for @a &= ~@b, false for @a |= @b.
|
|
|
+ *
|
|
|
+ * Returns true if @a is empty, false otherwise.
|
|
|
+ */
|
|
|
static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
|
|
|
struct tomoyo_acl_info *b,
|
|
|
const bool is_delete)
|
|
@@ -575,8 +712,7 @@ static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
|
|
|
static int tomoyo_update_path_number_acl(const u8 type, const char *filename,
|
|
|
char *number,
|
|
|
struct tomoyo_domain_info * const
|
|
|
- domain,
|
|
|
- const bool is_delete)
|
|
|
+ domain, const bool is_delete)
|
|
|
{
|
|
|
struct tomoyo_path_number_acl e = {
|
|
|
.head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
|
|
@@ -737,7 +873,7 @@ int tomoyo_path_perm(const u8 operation, struct path *path)
|
|
|
* Returns 0 on success, negative value otherwise.
|
|
|
*/
|
|
|
int tomoyo_mkdev_perm(const u8 operation, struct path *path,
|
|
|
- const unsigned int mode, unsigned int dev)
|
|
|
+ const unsigned int mode, unsigned int dev)
|
|
|
{
|
|
|
struct tomoyo_request_info r;
|
|
|
int error = -ENOMEM;
|