From: Jan Kiszka <jan.kis...@siemens.com> This fixes buffer overflows when large number of heaps are registered.
Signed-off-by: Jan Kiszka <jan.kis...@siemens.com> --- ksrc/nucleus/heap.c | 121 +++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 98 insertions(+), 23 deletions(-) diff --git a/ksrc/nucleus/heap.c b/ksrc/nucleus/heap.c index e5dfef0..3891cd3 100644 --- a/ksrc/nucleus/heap.c +++ b/ksrc/nucleus/heap.c @@ -1409,16 +1409,69 @@ void xnheap_destroy_mapped(xnheap_t *heap, #ifdef CONFIG_PROC_FS -#include <linux/proc_fs.h> +#include <linux/seq_file.h> + +struct heap_seq_iterator { + int nentries; + struct heap_seq_info { + u_long usable_mem; + u_long used_mem; + u_long page_size; + char label[XNOBJECT_NAME_LEN]; + } heap_info[1]; +}; + +static void *heap_seq_start(struct seq_file *seq, loff_t *pos) +{ + struct heap_seq_iterator *iter = seq->private; + + if (*pos >= iter->nentries) + return NULL; + + return iter->heap_info + *pos; +} + +static void *heap_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct heap_seq_iterator *iter = seq->private; + + ++*pos; -static int heap_read_proc(char *page, - char **start, - off_t off, int count, int *eof, void *data) + if (*pos >= iter->nentries) + return NULL; + + return iter->heap_info + *pos; +} + +static void heap_seq_stop(struct seq_file *seq, void *v) +{ +} + +static int heap_seq_show(struct seq_file *seq, void *v) { + struct heap_seq_info *p = v; + + seq_printf(seq, "size=%lu:used=%lu:pagesz=%lu (%s)\n", + p->usable_mem, p->used_mem, p->page_size, p->label); + return 0; +} + +static const struct seq_operations heap_op = { + .start = heap_seq_start, + .next = heap_seq_next, + .stop = heap_seq_stop, + .show = heap_seq_show +}; + +static int heap_seq_open(struct inode *inode, struct file *file) +{ + struct heap_seq_iterator *iter = NULL; + struct heap_seq_info *heap_info; + struct seq_file *seq; unsigned long rev; xnholder_t *entry; xnheap_t *heap; - int len; + int count, err; spl_t s; if (!xnpod_active_p()) @@ -1427,17 +1480,38 @@ static int heap_read_proc(char *page, xnlock_get_irqsave(&nklock, s); restart: - len = 0; + count = countq(&heapq); /* Cannot be empty (system heap) */ + rev = heapq_rev; + + xnlock_put_irqrestore(&nklock, s); + + kfree(iter); + iter = kmalloc(sizeof(*iter) + + (count - 1) * sizeof(struct heap_seq_info), + GFP_KERNEL); + if (!iter) + return -ENOMEM; + + err = seq_open(file, &heap_op); + if (err) { + kfree(iter); + return err; + } + + iter->nentries = 0; + + xnlock_get_irqsave(&nklock, s); entry = getheadq(&heapq); while (entry) { heap = container_of(entry, xnheap_t, stat_link); - len += sprintf(page + len, - "size=%lu:used=%lu:pagesz=%lu (%s)\n", - xnheap_usable_mem(heap), - xnheap_used_mem(heap), - xnheap_page_size(heap), - heap->label); + heap_info = &iter->heap_info[iter->nentries++]; + + heap_info->usable_mem = xnheap_usable_mem(heap); + heap_info->used_mem = xnheap_used_mem(heap); + heap_info->page_size = xnheap_page_size(heap); + memcpy(heap_info->label, heap->label, + sizeof(heap_info->label)); rev = heapq_rev; @@ -1451,22 +1525,23 @@ restart: xnlock_put_irqrestore(&nklock, s); - len -= off; - if (len <= off + count) - *eof = 1; - *start = page + off; - if (len > count) - len = count; - if (len < 0) - len = 0; + seq = file->private_data; + seq->private = iter; - return len; + return 0; } +static const struct file_operations heap_operations = { + .owner = THIS_MODULE, + .open = heap_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + void xnheap_init_proc(void) { - rthal_add_proc_leaf("heap", &heap_read_proc, NULL, NULL, - rthal_proc_root); + rthal_add_proc_seq("heap", &heap_operations, 0, rthal_proc_root); } void xnheap_cleanup_proc(void) -- 1.6.0.2 _______________________________________________ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core