memory.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * security/tomoyo/memory.c
  4. *
  5. * Copyright (C) 2005-2011 NTT DATA CORPORATION
  6. */
  7. #include <linux/hash.h>
  8. #include <linux/slab.h>
  9. #include "common.h"
  10. /**
  11. * tomoyo_warn_oom - Print out of memory warning message.
  12. *
  13. * @function: Function's name.
  14. */
  15. void tomoyo_warn_oom(const char *function)
  16. {
  17. /* Reduce error messages. */
  18. static pid_t tomoyo_last_pid;
  19. const pid_t pid = current->pid;
  20. if (tomoyo_last_pid != pid) {
  21. pr_warn("ERROR: Out of memory at %s.\n", function);
  22. tomoyo_last_pid = pid;
  23. }
  24. if (!tomoyo_policy_loaded)
  25. panic("MAC Initialization failed.\n");
  26. }
  27. /* Memoy currently used by policy/audit log/query. */
  28. unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT];
  29. /* Memory quota for "policy"/"audit log"/"query". */
  30. unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT];
  31. /**
  32. * tomoyo_memory_ok - Check memory quota.
  33. *
  34. * @ptr: Pointer to allocated memory.
  35. *
  36. * Returns true on success, false otherwise.
  37. *
  38. * Returns true if @ptr is not NULL and quota not exceeded, false otherwise.
  39. *
  40. * Caller holds tomoyo_policy_lock mutex.
  41. */
  42. bool tomoyo_memory_ok(void *ptr)
  43. {
  44. if (ptr) {
  45. const size_t s = ksize(ptr);
  46. tomoyo_memory_used[TOMOYO_MEMORY_POLICY] += s;
  47. if (!tomoyo_memory_quota[TOMOYO_MEMORY_POLICY] ||
  48. tomoyo_memory_used[TOMOYO_MEMORY_POLICY] <=
  49. tomoyo_memory_quota[TOMOYO_MEMORY_POLICY])
  50. return true;
  51. tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= s;
  52. }
  53. tomoyo_warn_oom(__func__);
  54. return false;
  55. }
  56. /**
  57. * tomoyo_commit_ok - Check memory quota.
  58. *
  59. * @data: Data to copy from.
  60. * @size: Size in byte.
  61. *
  62. * Returns pointer to allocated memory on success, NULL otherwise.
  63. * @data is zero-cleared on success.
  64. *
  65. * Caller holds tomoyo_policy_lock mutex.
  66. */
  67. void *tomoyo_commit_ok(void *data, const unsigned int size)
  68. {
  69. void *ptr = kzalloc(size, GFP_NOFS);
  70. if (tomoyo_memory_ok(ptr)) {
  71. memmove(ptr, data, size);
  72. memset(data, 0, size);
  73. return ptr;
  74. }
  75. kfree(ptr);
  76. return NULL;
  77. }
  78. /**
  79. * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group".
  80. *
  81. * @param: Pointer to "struct tomoyo_acl_param".
  82. * @idx: Index number.
  83. *
  84. * Returns pointer to "struct tomoyo_group" on success, NULL otherwise.
  85. */
  86. struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param,
  87. const u8 idx)
  88. {
  89. struct tomoyo_group e = { };
  90. struct tomoyo_group *group = NULL;
  91. struct list_head *list;
  92. const char *group_name = tomoyo_read_token(param);
  93. bool found = false;
  94. if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP)
  95. return NULL;
  96. e.group_name = tomoyo_get_name(group_name);
  97. if (!e.group_name)
  98. return NULL;
  99. if (mutex_lock_interruptible(&tomoyo_policy_lock))
  100. goto out;
  101. list = &param->ns->group_list[idx];
  102. list_for_each_entry(group, list, head.list) {
  103. if (e.group_name != group->group_name ||
  104. atomic_read(&group->head.users) == TOMOYO_GC_IN_PROGRESS)
  105. continue;
  106. atomic_inc(&group->head.users);
  107. found = true;
  108. break;
  109. }
  110. if (!found) {
  111. struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e));
  112. if (entry) {
  113. INIT_LIST_HEAD(&entry->member_list);
  114. atomic_set(&entry->head.users, 1);
  115. list_add_tail_rcu(&entry->head.list, list);
  116. group = entry;
  117. found = true;
  118. }
  119. }
  120. mutex_unlock(&tomoyo_policy_lock);
  121. out:
  122. tomoyo_put_name(e.group_name);
  123. return found ? group : NULL;
  124. }
  125. /*
  126. * tomoyo_name_list is used for holding string data used by TOMOYO.
  127. * Since same string data is likely used for multiple times (e.g.
  128. * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of
  129. * "const struct tomoyo_path_info *".
  130. */
  131. struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
  132. /**
  133. * tomoyo_get_name - Allocate permanent memory for string data.
  134. *
  135. * @name: The string to store into the permernent memory.
  136. *
  137. * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
  138. */
  139. const struct tomoyo_path_info *tomoyo_get_name(const char *name)
  140. {
  141. struct tomoyo_name *ptr;
  142. unsigned int hash;
  143. int len;
  144. struct list_head *head;
  145. if (!name)
  146. return NULL;
  147. len = strlen(name) + 1;
  148. hash = full_name_hash(NULL, (const unsigned char *) name, len - 1);
  149. head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
  150. if (mutex_lock_interruptible(&tomoyo_policy_lock))
  151. return NULL;
  152. list_for_each_entry(ptr, head, head.list) {
  153. if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name) ||
  154. atomic_read(&ptr->head.users) == TOMOYO_GC_IN_PROGRESS)
  155. continue;
  156. atomic_inc(&ptr->head.users);
  157. goto out;
  158. }
  159. ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS);
  160. if (tomoyo_memory_ok(ptr)) {
  161. ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
  162. memmove((char *) ptr->entry.name, name, len);
  163. atomic_set(&ptr->head.users, 1);
  164. tomoyo_fill_path_info(&ptr->entry);
  165. list_add_tail(&ptr->head.list, head);
  166. } else {
  167. kfree(ptr);
  168. ptr = NULL;
  169. }
  170. out:
  171. mutex_unlock(&tomoyo_policy_lock);
  172. return ptr ? &ptr->entry : NULL;
  173. }
  174. /* Initial namespace.*/
  175. struct tomoyo_policy_namespace tomoyo_kernel_namespace;
  176. /**
  177. * tomoyo_mm_init - Initialize mm related code.
  178. */
  179. void __init tomoyo_mm_init(void)
  180. {
  181. int idx;
  182. for (idx = 0; idx < TOMOYO_MAX_HASH; idx++)
  183. INIT_LIST_HEAD(&tomoyo_name_list[idx]);
  184. tomoyo_kernel_namespace.name = "<kernel>";
  185. tomoyo_init_policy_namespace(&tomoyo_kernel_namespace);
  186. tomoyo_kernel_domain.ns = &tomoyo_kernel_namespace;
  187. INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
  188. tomoyo_kernel_domain.domainname = tomoyo_get_name("<kernel>");
  189. list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
  190. }