Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/1.7.x/ccs-patch/security/ccsecurity/memory.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4783 - (show annotations) (download) (as text)
Thu Mar 31 03:04:18 2011 UTC (2 years, 1 month ago) by kumaneko
File MIME type: text/x-csrc
File size: 7419 byte(s)
1 /*
2 * security/ccsecurity/memory.c
3 *
4 * Copyright (C) 2005-2011 NTT DATA CORPORATION
5 *
6 * Version: 1.7.3+ 2011/04/01
7 *
8 * This file is applicable to both 2.4.30 and 2.6.11 and later.
9 * See README.ccs for ChangeLog.
10 *
11 */
12
13 #include "internal.h"
14 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) || defined(RHEL_MAJOR)
15 #include <linux/hash.h>
16 #endif
17
18 /**
19 * ccs_warn_oom - Print out of memory warning message.
20 *
21 * @function: Function's name.
22 */
23 void ccs_warn_oom(const char *function)
24 {
25 /* Reduce error messages. */
26 static pid_t ccs_last_pid;
27 const pid_t pid = current->pid;
28 if (ccs_last_pid != pid) {
29 printk(KERN_WARNING "ERROR: Out of memory at %s.\n",
30 function);
31 ccs_last_pid = pid;
32 }
33 if (!ccs_policy_loaded)
34 panic("MAC Initialization failed.\n");
35 }
36
37 /* Memory allocated for policy. */
38 static atomic_t ccs_policy_memory_size;
39 /* Quota for holding policy. */
40 static unsigned int ccs_quota_for_policy;
41
42 /**
43 * ccs_memory_ok - Check memory quota.
44 *
45 * @ptr: Pointer to allocated memory.
46 * @size: Size in byte.
47 *
48 * Returns true if @ptr is not NULL and quota not exceeded, false otherwise.
49 */
50 bool ccs_memory_ok(const void *ptr, const unsigned int size)
51 {
52 size_t s = ccs_round2(size);
53 atomic_add(s, &ccs_policy_memory_size);
54 if (ptr && (!ccs_quota_for_policy ||
55 atomic_read(&ccs_policy_memory_size)
56 <= ccs_quota_for_policy))
57 return true;
58 atomic_sub(s, &ccs_policy_memory_size);
59 ccs_warn_oom(__func__);
60 return false;
61 }
62
63 /**
64 * ccs_commit_ok - Allocate memory and check memory quota.
65 *
66 * @data: Data to copy from.
67 * @size: Size in byte.
68 *
69 * Returns pointer to allocated memory on success, NULL otherwise.
70 * @data is zero-cleared on success.
71 */
72 void *ccs_commit_ok(void *data, const unsigned int size)
73 {
74 void *ptr = kmalloc(size, CCS_GFP_FLAGS);
75 if (ccs_memory_ok(ptr, size)) {
76 memmove(ptr, data, size);
77 memset(data, 0, size);
78 return ptr;
79 }
80 kfree(ptr);
81 return NULL;
82 }
83
84 /**
85 * ccs_memory_free - Free memory for elements.
86 *
87 * @ptr: Pointer to allocated memory.
88 * @size: Size in byte.
89 */
90 void ccs_memory_free(const void *ptr, size_t size)
91 {
92 atomic_sub(ccs_round2(size), &ccs_policy_memory_size);
93 kfree(ptr);
94 }
95
96 /* List of IPv6 address. */
97 LIST_HEAD(ccs_address_list);
98
99 /**
100 * ccs_get_ipv6_address - Keep the given IPv6 address on the RAM.
101 *
102 * @addr: Pointer to "struct in6_addr".
103 *
104 * Returns pointer to "struct in6_addr" on success, NULL otherwise.
105 *
106 * The RAM is shared, so NEVER try to modify or kfree() the returned address.
107 */
108 const struct in6_addr *ccs_get_ipv6_address(const struct in6_addr *addr)
109 {
110 struct ccs_ipv6addr_entry *entry;
111 struct ccs_ipv6addr_entry *ptr = NULL;
112 int error = -ENOMEM;
113 if (!addr)
114 return NULL;
115 entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);
116 if (mutex_lock_interruptible(&ccs_policy_lock))
117 goto out;
118 list_for_each_entry(ptr, &ccs_address_list, list) {
119 if (memcmp(&ptr->addr, addr, sizeof(*addr)))
120 continue;
121 atomic_inc(&ptr->users);
122 error = 0;
123 break;
124 }
125 if (error && ccs_memory_ok(entry, sizeof(*entry))) {
126 ptr = entry;
127 ptr->addr = *addr;
128 atomic_set(&ptr->users, 1);
129 list_add_tail(&ptr->list, &ccs_address_list);
130 entry = NULL;
131 error = 0;
132 }
133 mutex_unlock(&ccs_policy_lock);
134 out:
135 kfree(entry);
136 return !error ? &ptr->addr : NULL;
137 }
138
139 /* The list for "struct ccs_name_entry". */
140 struct list_head ccs_name_list[CCS_MAX_HASH];
141
142 /**
143 * ccs_get_name - Allocate memory for string data.
144 *
145 * @name: The string to store into the permernent memory.
146 *
147 * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
148 */
149 const struct ccs_path_info *ccs_get_name(const char *name)
150 {
151 struct ccs_name_entry *ptr;
152 unsigned int hash;
153 int len;
154 int allocated_len;
155 struct list_head *head;
156
157 if (!name)
158 return NULL;
159 len = strlen(name) + 1;
160 hash = full_name_hash((const unsigned char *) name, len - 1);
161 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) || defined(RHEL_MAJOR)
162 head = &ccs_name_list[hash_long(hash, CCS_HASH_BITS)];
163 #else
164 head = &ccs_name_list[hash % CCS_MAX_HASH];
165 #endif
166 if (mutex_lock_interruptible(&ccs_policy_lock))
167 return NULL;
168 list_for_each_entry(ptr, head, list) {
169 if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
170 continue;
171 atomic_inc(&ptr->users);
172 goto out;
173 }
174 allocated_len = ccs_round2(sizeof(*ptr) + len);
175 ptr = kzalloc(allocated_len, CCS_GFP_FLAGS);
176 if (!ptr || (ccs_quota_for_policy &&
177 atomic_read(&ccs_policy_memory_size) + allocated_len
178 > ccs_quota_for_policy)) {
179 kfree(ptr);
180 ptr = NULL;
181 ccs_warn_oom(__func__);
182 goto out;
183 }
184 atomic_add(allocated_len, &ccs_policy_memory_size);
185 ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
186 memmove((char *) ptr->entry.name, name, len);
187 atomic_set(&ptr->users, 1);
188 ccs_fill_path_info(&ptr->entry);
189 ptr->size = allocated_len;
190 list_add_tail(&ptr->list, head);
191 out:
192 mutex_unlock(&ccs_policy_lock);
193 return ptr ? &ptr->entry : NULL;
194 }
195
196 /**
197 * ccs_mm_init - Initialize mm related code.
198 */
199 void __init ccs_mm_init(void)
200 {
201 int idx;
202 for (idx = 0; idx < CCS_MAX_HASH; idx++)
203 INIT_LIST_HEAD(&ccs_name_list[idx]);
204 INIT_LIST_HEAD(&ccs_kernel_domain.acl_info_list);
205 ccs_kernel_domain.domainname = ccs_get_name(ROOT_NAME);
206 list_add_tail_rcu(&ccs_kernel_domain.list, &ccs_domain_list);
207 idx = ccs_read_lock();
208 if (ccs_find_domain(ROOT_NAME) != &ccs_kernel_domain)
209 panic("Can't register ccs_kernel_domain");
210 {
211 /* Load built-in policy. */
212 static char ccs_builtin_initializers[] __initdata
213 = CONFIG_CCSECURITY_BUILTIN_INITIALIZERS;
214 char *cp = ccs_builtin_initializers;
215 ccs_normalize_line(cp);
216 while (cp && *cp) {
217 char *cp2 = strchr(cp, ' ');
218 if (cp2)
219 *cp2++ = '\0';
220 ccs_write_domain_initializer_policy(cp, false, false);
221 cp = cp2;
222 }
223 }
224 ccs_read_unlock(idx);
225 }
226
227 /* Memory allocated for audit logs. */
228 unsigned int ccs_audit_log_memory_size;
229 /* Quota for holding audit logs. */
230 unsigned int ccs_quota_for_audit_log;
231
232 /* Memory allocated for query lists. */
233 unsigned int ccs_query_memory_size;
234 /* Quota for holding query lists. */
235 unsigned int ccs_quota_for_query;
236
237 /**
238 * ccs_read_memory_counter - Check for memory usage.
239 *
240 * @head: Pointer to "struct ccs_io_buffer".
241 */
242 void ccs_read_memory_counter(struct ccs_io_buffer *head)
243 {
244 const unsigned int usage[3] = {
245 atomic_read(&ccs_policy_memory_size),
246 ccs_audit_log_memory_size,
247 ccs_query_memory_size
248 };
249 const unsigned int quota[3] = {
250 ccs_quota_for_policy,
251 ccs_quota_for_audit_log,
252 ccs_quota_for_query
253 };
254 static const char *header[4] = {
255 "Policy: ",
256 "Audit logs: ",
257 "Query lists:",
258 "Total: "
259 };
260 unsigned int total = 0;
261 int i;
262 if (head->read_eof)
263 return;
264 for (i = 0; i < 3; i++) {
265 total += usage[i];
266 ccs_io_printf(head, "%s %10u", header[i], usage[i]);
267 if (quota[i])
268 ccs_io_printf(head, " (Quota: %10u)", quota[i]);
269 ccs_io_printf(head, "\n");
270 }
271 ccs_io_printf(head, "%s %10u\n", header[3], total);
272 head->read_eof = true;
273 }
274
275 /**
276 * ccs_write_memory_quota - Set memory quota.
277 *
278 * @head: Pointer to "struct ccs_io_buffer".
279 *
280 * Returns 0.
281 */
282 int ccs_write_memory_quota(struct ccs_io_buffer *head)
283 {
284 char *data = head->write_buf;
285 unsigned int size;
286 if (sscanf(data, "Policy: %u", &size) == 1)
287 ccs_quota_for_policy = size;
288 else if (sscanf(data, "Audit logs: %u", &size) == 1)
289 ccs_quota_for_audit_log = size;
290 else if (sscanf(data, "Query lists: %u", &size) == 1)
291 ccs_quota_for_query = size;
292 return 0;
293 }

SourceForge.JP is a Japanese version of SourceForge.net. For developments that are not related to Japan, we recommend you to use SourceForge.net.