オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Annotation of /trunk/1.8.x/ccs-patch/security/ccsecurity/memory.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6407 - (hide annotations) (download) (as text)
Tue Apr 21 08:15:55 2015 UTC (9 years, 1 month ago) by kumaneko
File MIME type: text/x-csrc
File size: 9825 byte(s)


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

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26