Fixed buffer overflow in mserver; fixed type of checkinfo () 2nd parameter; memory
[ZeXOS.git] / kernel / core / mm / usermem.c
blobfee846805aee982e632ac8f8cc8f91afb7ffe47f
1 /*
2 * ZeX/OS
3 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2010 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <system.h>
22 #include <string.h>
23 #include <build.h>
24 #include <config.h>
25 #include <mutex.h>
26 #include <errno.h>
28 #define UMEM_HEAP_ADDR 0x800000 // MEMORY HEAP is placed at 8MB address
29 #define UMEM_MALLOC_MAGIC 0xebc9 // MALLOC STRUCTURE signature
31 #define UMEM_MALLOC_STATE_FREE 0xaa // MEMORY is FREE at moment
32 #define UMEM_MALLOC_STATE_USED 0xcc // MEMORY is USED at moment
34 typedef struct {
35 unsigned short magic;
36 unsigned char state;
37 void *next;
38 proc_t *proc;
39 } __attribute__ ((__packed__)) malloc_t;
41 typedef struct {
42 void *addr; /* heap structure is covered by own heap structure address */
43 void *first; /* first malloc structure */
44 void *last; /* last malloc structure - usefully for calculate memory usage */
45 void *curr; /* current malloc structure */
46 } __attribute__ ((__packed__)) heap_t;
48 static heap_t *heap; /* heap structure of memory */
49 static MUTEX_CREATE (mutex_umalloc);
50 static MUTEX_CREATE (mutex_ufree);
52 void *umalloc (proc_t *proc, size_t size)
54 if (!size)
55 return 0;
57 mutex_lock (&mutex_umalloc);
59 unsigned malloc_len = sizeof (malloc_t); /* check malloc structure size */
60 unsigned need_alloc = 0;
62 /* let's find new or free malloc structure in memory */
63 malloc_t *malloc = (malloc_t *) heap->first;
65 while (1) {
66 //DPRINT (DBG_MM | DBG_UMEM, "malloc: 0x%x\n", malloc);
68 if (!malloc) {
69 DPRINT (DBG_MM | DBG_UMEM, "!malloc");
70 need_alloc = 1;
71 break;
74 if (malloc->magic != UMEM_MALLOC_MAGIC) {
75 DPRINT (DBG_MM | DBG_UMEM, "malloc->magic != UMEM_MALLOC_MAGIC");
76 need_alloc = 1;
77 break;
80 if (malloc->state == UMEM_MALLOC_STATE_USED) { /* It's OK */
81 DPRINT (DBG_MM | DBG_UMEM, "malloc->state == UMEM_MALLOC_STATE_USED");
82 //need_alloc = 1;
83 malloc = (malloc_t *) malloc->next;
84 continue;
87 /* we've found FREE memory block, at moment it is not used */
88 if (malloc->state == UMEM_MALLOC_STATE_FREE) {
89 /* read next malloc structure, right behind free block */
90 malloc_t *next = (malloc_t *) malloc;
92 DPRINT (DBG_MM | DBG_UMEM, "malloc->state == UMEM_MALLOC_STATE_FREE");
94 for (;;) {
95 next = (malloc_t *) next->next;
97 if (next->magic != UMEM_MALLOC_MAGIC) {
98 DPRINT (DBG_MM | DBG_UMEM, "2: next->magic != UMEM_MALLOC_MAGIC");
99 break;
102 if ((unsigned) ((void *) malloc + malloc_len + size) <= (unsigned) next) {
103 //kprintf ("Je mensi\n");
104 break;
105 } else {
106 if (next->state == UMEM_MALLOC_STATE_USED)
107 need_alloc = 1;
109 if (next->state == UMEM_MALLOC_STATE_USED)
110 break;
112 if (next->state != UMEM_MALLOC_STATE_FREE)
113 break;
116 /*if (need_alloc)
117 break;
119 unsigned diff = (unsigned) ((void *) next - (void *) malloc);
121 DPRINT (DBG_MM | DBG_UMEM, "diff: %d", diff);
123 if (diff < size) {
124 malloc = (malloc_t *) malloc->next;
125 continue;
128 break;
131 malloc = (malloc_t *) malloc->next;
134 if (need_alloc) {
135 /* when old malloc structures are full, let's grab new block of memory */
136 malloc = heap->curr;
138 malloc->magic = UMEM_MALLOC_MAGIC;
140 malloc->next = (void *) ((void *) malloc + malloc_len + size);
142 heap->curr = malloc->next;
145 malloc->state = UMEM_MALLOC_STATE_USED;
147 malloc->proc = proc;
149 /* calculate size of process image (binary file) */
150 unsigned p = (unsigned) palign ((void *) (proc->end - proc->start));
152 /* save last malloc structure pointer to heap */
153 if ((unsigned) heap->curr > (unsigned) heap->last)
154 heap->last = heap->curr;
156 unsigned l;
157 unsigned s = proc->heap;
158 for (l = s; l < (unsigned) ((char *) malloc + malloc_len + size); l += 0x1000) {
159 #ifdef ARCH_i386
160 page_mmap (proc->task->page_cover, (void *) proc->heap+p, (void *) proc->heap+p + 0x1000, 0, 1);
161 #endif
162 //kprintf ("OD: 0x%x DO: 0x%x | 0x%x | 0x%x\n", (void *) proc->heap + p, (void *) proc->heap + 0x1000 + p, s, size);
163 proc->heap += 0x1000;
166 mutex_unlock (&mutex_umalloc);
168 return (void *) ((void *) malloc + malloc_len + p);
171 void ufree (proc_t *proc, void *ptr)
173 if (!ptr || !proc)
174 return;
176 mutex_lock (&mutex_ufree);
178 /* calculate size of process image (binary file) */
179 unsigned p = (unsigned) palign ((void *) (proc->end - proc->start));
181 /* we need find malloc structure - it could be risk working with lower memory address */
182 malloc_t *malloc = (void *) ((void *) ptr - sizeof (malloc_t) - p);
184 /* check malloc signature, when not agree, ptr pointing to wrong memory address */
185 if (malloc->magic != UMEM_MALLOC_MAGIC) {
186 kprintf ("free: malloc->magic != UMEM_MALLOC_MAGIC\n");
187 goto end;
190 /* is this memory block our ? */
191 if (malloc->proc != proc) {
192 kprintf ("free: malloc->proc != proc\n");
193 goto end;
196 if (malloc->state == UMEM_MALLOC_STATE_FREE) {
197 kprintf ("kfree () - memory is FREE - double free !\n");
198 goto end;
201 if (malloc->state != UMEM_MALLOC_STATE_USED) {
202 kprintf ("malloc->state != UMEM_MALLOC_STATE_USED\n");
203 goto end;
206 /* match malloc as FREE */
207 malloc->state = UMEM_MALLOC_STATE_FREE;
209 end:
210 mutex_unlock (&mutex_ufree);
213 void *urealloc (proc_t *proc, void *ptr, size_t size)
215 if (!proc)
216 return 0;
218 if (!ptr)
219 return umalloc (proc, size);
221 if (!size) {
222 ufree (proc, ptr);
223 return 0;
226 /* calculate size of process image (binary file) */
227 unsigned p = (unsigned) palign ((void *) (proc->end - proc->start));
229 /* we need find malloc structure - it could be risk working with lower memory address */
230 malloc_t *malloc = (void *) ((char *) ptr - sizeof (malloc_t) - p);
232 /* check malloc signature, when not agree, ptr pointing to wrong memory address */
233 if (malloc->magic != UMEM_MALLOC_MAGIC) {
234 kprintf ("urealloc: malloc->magic != UMEM_MALLOC_MAGIC\n");
235 return 0;
238 int s = (int) (malloc->next - ptr) + p;
239 printf ("s: %d : %d\n", s, size);
240 if (s >= size)
241 return 0;
243 char *ptr_new = umalloc (proc, size);
244 printf ("s: ptr_new: 0x%x\n", ptr_new);
245 if (!ptr_new) {
246 ufree (proc, ptr);
247 errno_set (ENOMEM);
248 return 0;
251 /* copy old memory block to new one (-p because ptr and ptr_new got virtual mapped address) */
252 memcpy (ptr_new - p, ptr - p, s);
254 ufree (proc, ptr);
256 return ptr_new;
259 /* free all memory blocks allocated by process */
260 unsigned ufree_proc (proc_t *proc)
262 #ifndef ARCH_arm
263 paging_disable ();
264 #endif
265 unsigned used = 0;
266 malloc_t *malloc;
268 for (malloc = (malloc_t *) heap->first; malloc->magic == UMEM_MALLOC_MAGIC; malloc = (malloc_t *) malloc->next)
269 if (malloc->proc == proc)
270 if (malloc->state == UMEM_MALLOC_STATE_USED)
271 malloc->state = UMEM_MALLOC_STATE_FREE;
272 #ifndef ARCH_arm
273 paging_enable ();
274 #endif
275 return used;
278 /* calculate used memory by process */
279 unsigned umem_used_proc (proc_t *proc)
281 #ifndef ARCH_arm
282 paging_disable ();
283 #endif
284 unsigned used = 0;
285 malloc_t *malloc;
287 for (malloc = (malloc_t *) heap->first; malloc->magic == UMEM_MALLOC_MAGIC; malloc = (malloc_t *) malloc->next)
288 if (malloc->proc == proc)
289 if (malloc->state == UMEM_MALLOC_STATE_USED)
290 used += (int) ((unsigned) malloc->next - (unsigned) malloc);
291 #ifndef ARCH_arm
292 paging_enable ();
293 #endif
294 return used;
297 /* calculate used memory from all apps */
298 unsigned umem_used ()
300 #ifndef ARCH_arm
301 paging_disable ();
302 #endif
303 unsigned used = 0;
304 malloc_t *malloc;
306 for (malloc = (malloc_t *) heap->first; malloc->magic == UMEM_MALLOC_MAGIC; malloc = (malloc_t *) malloc->next)
307 if (malloc->state == UMEM_MALLOC_STATE_USED)
308 used += (int) ((unsigned) malloc->next - (unsigned) malloc);
309 #ifndef ARCH_arm
310 paging_enable ();
311 #endif
312 return used;
315 unsigned umem_init ()
317 heap = (heap_t *) UMEM_HEAP_ADDR;
319 /* we rather clear heap structure */
320 heap->addr = (void *) heap;
321 heap->first = (void *) ((void *) heap + sizeof (heap_t)); /* first malloc structure should be right behind heap structure */
322 heap->last = heap->first; /* last malloc structure - it is first at init */
323 heap->curr = heap->first; /* point to first malloc structure - well, it is clear and not used yet */
325 return 1;