~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/akari/memory.c

Version: ~ [ linux-5.5-rc7 ] ~ [ linux-5.4.13 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.97 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.166 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.210 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.210 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.81 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * security/ccsecurity/memory.c
  3  *
  4  * Copyright (C) 2005-2012  NTT DATA CORPORATION
  5  *
  6  * Version: 1.8.5   2015/11/11
  7  */
  8 
  9 #include "internal.h"
 10 
 11 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
 12 /* Use functions in lsm.c */
 13 #undef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
 14 #endif
 15 
 16 /***** SECTION1: Constants definition *****/
 17 
 18 /***** SECTION2: Structure definition *****/
 19 
 20 /***** SECTION3: Prototype definition section *****/
 21 
 22 bool ccs_memory_ok(const void *ptr, const unsigned int size);
 23 const struct ccs_path_info *ccs_get_name(const char *name);
 24 #ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
 25 struct ccs_security *ccs_find_task_security(const struct task_struct *task);
 26 #endif
 27 void *ccs_commit_ok(void *data, const unsigned int size);
 28 void __init ccs_mm_init(void);
 29 void ccs_warn_oom(const char *function);
 30 
 31 #ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
 32 static int __ccs_alloc_task_security(const struct task_struct *task);
 33 static void __ccs_free_task_security(const struct task_struct *task);
 34 static void ccs_add_task_security(struct ccs_security *ptr,
 35                                   struct list_head *list);
 36 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
 37 static void ccs_rcu_free(struct rcu_head *rcu);
 38 #else
 39 static void ccs_rcu_free(void *arg);
 40 #endif
 41 #endif
 42 
 43 /***** SECTION4: Standalone functions section *****/
 44 
 45 /***** SECTION5: Variables definition section *****/
 46 
 47 /* Memoy currently used by policy/audit log/query. */
 48 unsigned int ccs_memory_used[CCS_MAX_MEMORY_STAT];
 49 
 50 /* Memory quota for "policy"/"audit log"/"query". */
 51 unsigned int ccs_memory_quota[CCS_MAX_MEMORY_STAT];
 52 
 53 /* The list for "struct ccs_name". */
 54 struct list_head ccs_name_list[CCS_MAX_HASH];
 55 
 56 #ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
 57 
 58 /* Dummy security context for avoiding NULL pointer dereference. */
 59 struct ccs_security ccs_oom_security = {
 60         .ccs_domain_info = &ccs_kernel_domain
 61 };
 62 
 63 /* Dummy security context for avoiding NULL pointer dereference. */
 64 struct ccs_security ccs_default_security = {
 65         .ccs_domain_info = &ccs_kernel_domain
 66 };
 67 
 68 /* List of "struct ccs_security". */
 69 struct list_head ccs_task_security_list[CCS_MAX_TASK_SECURITY_HASH];
 70 /* Lock for protecting ccs_task_security_list[]. */
 71 static DEFINE_SPINLOCK(ccs_task_security_list_lock);
 72 
 73 #endif
 74 
 75 /***** SECTION6: Dependent functions section *****/
 76 
 77 /**
 78  * ccs_warn_oom - Print out of memory warning message.
 79  *
 80  * @function: Function's name.
 81  *
 82  * Returns nothing.
 83  */
 84 void ccs_warn_oom(const char *function)
 85 {
 86         /* Reduce error messages. */
 87         static pid_t ccs_last_pid;
 88         const pid_t pid = current->pid;
 89         if (ccs_last_pid != pid) {
 90                 printk(KERN_WARNING "ERROR: Out of memory at %s.\n",
 91                        function);
 92                 ccs_last_pid = pid;
 93         }
 94         if (!ccs_policy_loaded)
 95                 panic("MAC Initialization failed.\n");
 96 }
 97 
 98 /**
 99  * ccs_memory_ok - Check memory quota.
100  *
101  * @ptr:  Pointer to allocated memory. Maybe NULL.
102  * @size: Size in byte. Not used if @ptr is NULL.
103  *
104  * Returns true if @ptr is not NULL and quota not exceeded, false otherwise.
105  *
106  * Caller holds ccs_policy_lock mutex.
107  */
108 bool ccs_memory_ok(const void *ptr, const unsigned int size)
109 {
110         if (ptr) {
111                 const size_t s = ccs_round2(size);
112                 ccs_memory_used[CCS_MEMORY_POLICY] += s;
113                 if (!ccs_memory_quota[CCS_MEMORY_POLICY] ||
114                     ccs_memory_used[CCS_MEMORY_POLICY] <=
115                     ccs_memory_quota[CCS_MEMORY_POLICY])
116                         return true;
117                 ccs_memory_used[CCS_MEMORY_POLICY] -= s;
118         }
119         ccs_warn_oom(__func__);
120         return false;
121 }
122 
123 /**
124  * ccs_commit_ok - Allocate memory and check memory quota.
125  *
126  * @data: Data to copy from.
127  * @size: Size in byte.
128  *
129  * Returns pointer to allocated memory on success, NULL otherwise.
130  * @data is zero-cleared on success.
131  *
132  * Caller holds ccs_policy_lock mutex.
133  */
134 void *ccs_commit_ok(void *data, const unsigned int size)
135 {
136         void *ptr = kmalloc(size, CCS_GFP_FLAGS);
137         if (ccs_memory_ok(ptr, size)) {
138                 memmove(ptr, data, size);
139                 memset(data, 0, size);
140                 return ptr;
141         }
142         kfree(ptr);
143         return NULL;
144 }
145 
146 /**
147  * ccs_get_name - Allocate memory for string data.
148  *
149  * @name: The string to store into the permernent memory.
150  *
151  * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
152  */
153 const struct ccs_path_info *ccs_get_name(const char *name)
154 {
155         struct ccs_name *ptr;
156         unsigned int hash;
157         int len;
158         int allocated_len;
159         struct list_head *head;
160 
161         if (!name)
162                 return NULL;
163         len = strlen(name) + 1;
164         hash = full_name_hash((const unsigned char *) name, len - 1);
165 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) || defined(RHEL_MAJOR)
166         head = &ccs_name_list[hash_long(hash, CCS_HASH_BITS)];
167 #else
168         head = &ccs_name_list[hash % CCS_MAX_HASH];
169 #endif
170         if (mutex_lock_interruptible(&ccs_policy_lock))
171                 return NULL;
172         list_for_each_entry(ptr, head, head.list) {
173                 if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name) ||
174                     atomic_read(&ptr->head.users) == CCS_GC_IN_PROGRESS)
175                         continue;
176                 atomic_inc(&ptr->head.users);
177                 goto out;
178         }
179         allocated_len = sizeof(*ptr) + len;
180         ptr = kzalloc(allocated_len, CCS_GFP_FLAGS);
181         if (ccs_memory_ok(ptr, allocated_len)) {
182                 ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
183                 memmove((char *) ptr->entry.name, name, len);
184                 atomic_set(&ptr->head.users, 1);
185                 ccs_fill_path_info(&ptr->entry);
186                 ptr->size = allocated_len;
187                 list_add_tail(&ptr->head.list, head);
188         } else {
189                 kfree(ptr);
190                 ptr = NULL;
191         }
192 out:
193         mutex_unlock(&ccs_policy_lock);
194         return ptr ? &ptr->entry : NULL;
195 }
196 
197 #ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
198 
199 /**
200  * ccs_add_task_security - Add "struct ccs_security" to list.
201  *
202  * @ptr:  Pointer to "struct ccs_security".
203  * @list: Pointer to "struct list_head".
204  *
205  * Returns nothing.
206  */
207 static void ccs_add_task_security(struct ccs_security *ptr,
208                                   struct list_head *list)
209 {
210         unsigned long flags;
211         spin_lock_irqsave(&ccs_task_security_list_lock, flags);
212         list_add_rcu(&ptr->list, list);
213         spin_unlock_irqrestore(&ccs_task_security_list_lock, flags);
214 }
215 
216 /**
217  * __ccs_alloc_task_security - Allocate memory for new tasks.
218  *
219  * @task: Pointer to "struct task_struct".
220  *
221  * Returns 0 on success, negative value otherwise.
222  */
223 static int __ccs_alloc_task_security(const struct task_struct *task)
224 {
225         struct ccs_security *old_security = ccs_current_security();
226         struct ccs_security *new_security = kzalloc(sizeof(*new_security),
227                                                     GFP_KERNEL);
228         struct list_head *list = &ccs_task_security_list
229                 [hash_ptr((void *) task, CCS_TASK_SECURITY_HASH_BITS)];
230         if (!new_security)
231                 return -ENOMEM;
232         new_security->task = task;
233         new_security->ccs_domain_info = old_security->ccs_domain_info;
234         new_security->ccs_flags = old_security->ccs_flags;
235         ccs_add_task_security(new_security, list);
236         return 0;
237 }
238 
239 /**
240  * ccs_find_task_security - Find "struct ccs_security" for given task.
241  *
242  * @task: Pointer to "struct task_struct".
243  *
244  * Returns pointer to "struct ccs_security" on success, &ccs_oom_security on
245  * out of memory, &ccs_default_security otherwise.
246  *
247  * If @task is current thread and "struct ccs_security" for current thread was
248  * not found, I try to allocate it. But if allocation failed, current thread
249  * will be killed by SIGKILL. Note that if current->pid == 1, sending SIGKILL
250  * won't work.
251  */
252 struct ccs_security *ccs_find_task_security(const struct task_struct *task)
253 {
254         struct ccs_security *ptr;
255         struct list_head *list = &ccs_task_security_list
256                 [hash_ptr((void *) task, CCS_TASK_SECURITY_HASH_BITS)];
257         /* Make sure INIT_LIST_HEAD() in ccs_mm_init() takes effect. */
258         while (!list->next);
259         rcu_read_lock();
260         list_for_each_entry_rcu(ptr, list, list) {
261                 if (ptr->task != task)
262                         continue;
263                 rcu_read_unlock();
264                 return ptr;
265         }
266         rcu_read_unlock();
267         if (task != current)
268                 return &ccs_default_security;
269         /* Use GFP_ATOMIC because caller may have called rcu_read_lock(). */
270         ptr = kzalloc(sizeof(*ptr), GFP_ATOMIC);
271         if (!ptr) {
272                 printk(KERN_WARNING "Unable to allocate memory for pid=%u\n",
273                        task->pid);
274                 send_sig(SIGKILL, current, 0);
275                 return &ccs_oom_security;
276         }
277         *ptr = ccs_default_security;
278         ptr->task = task;
279         ccs_add_task_security(ptr, list);
280         return ptr;
281 }
282 
283 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
284 
285 /**
286  * ccs_rcu_free - RCU callback for releasing "struct ccs_security".
287  *
288  * @rcu: Pointer to "struct rcu_head".
289  *
290  * Returns nothing.
291  */
292 static void ccs_rcu_free(struct rcu_head *rcu)
293 {
294         struct ccs_security *ptr = container_of(rcu, typeof(*ptr), rcu);
295         kfree(ptr);
296 }
297 
298 #else
299 
300 /**
301  * ccs_rcu_free - RCU callback for releasing "struct ccs_security".
302  *
303  * @arg: Pointer to "void".
304  *
305  * Returns nothing.
306  */
307 static void ccs_rcu_free(void *arg)
308 {
309         struct ccs_security *ptr = arg;
310         kfree(ptr);
311 }
312 
313 #endif
314 
315 /**
316  * __ccs_free_task_security - Release memory associated with "struct task_struct".
317  *
318  * @task: Pointer to "struct task_struct".
319  *
320  * Returns nothing.
321  */
322 static void __ccs_free_task_security(const struct task_struct *task)
323 {
324         unsigned long flags;
325         struct ccs_security *ptr = ccs_find_task_security(task);
326         if (ptr == &ccs_default_security || ptr == &ccs_oom_security)
327                 return;
328         spin_lock_irqsave(&ccs_task_security_list_lock, flags);
329         list_del_rcu(&ptr->list);
330         spin_unlock_irqrestore(&ccs_task_security_list_lock, flags);
331 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
332         call_rcu(&ptr->rcu, ccs_rcu_free);
333 #else
334         call_rcu(&ptr->rcu, ccs_rcu_free, ptr);
335 #endif
336 }
337 
338 #endif
339 
340 /**
341  * ccs_mm_init - Initialize mm related code.
342  *
343  * Returns nothing.
344  */
345 void __init ccs_mm_init(void)
346 {
347         int idx;
348         for (idx = 0; idx < CCS_MAX_HASH; idx++)
349                 INIT_LIST_HEAD(&ccs_name_list[idx]);
350 #ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
351         for (idx = 0; idx < CCS_MAX_TASK_SECURITY_HASH; idx++)
352                 INIT_LIST_HEAD(&ccs_task_security_list[idx]);
353 #endif
354         smp_wmb(); /* Avoid out of order execution. */
355 #ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
356         ccsecurity_ops.alloc_task_security = __ccs_alloc_task_security;
357         ccsecurity_ops.free_task_security = __ccs_free_task_security;
358 #endif
359         ccs_kernel_domain.domainname = ccs_get_name("<kernel>");
360         list_add_tail_rcu(&ccs_kernel_domain.list, &ccs_domain_list);
361 }
362 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp