memory.c 5.4 KB

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