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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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