Nucleus
Barry Fixed resource leak in VFS c4a1ba4 (3 years, 2 months ago)
diff --git a/drivers/video/bga.c b/drivers/video/bga.c
index 3354d01..061409a 100644
--- a/drivers/video/bga.c
+++ b/drivers/video/bga.c
@@ -10,9 +10,11 @@
#include <sys/stat.h>
#include <sys/fb.h>
#include <fcntl.h>
+#include <errno.h>
#include <io.h>
#include <nucleus/driver.h>
-#include <nucleus/panic.h>
+#include <nucleus/kernel.h>
+#include <nucleus/memory.h>
#include <nucleus/pci.h>
#include <nucleus/vfs.h>
@@ -108,22 +110,33 @@ bga_dev_ioctl(File *file, unsigned long request, uintptr_t argp)
FBVarInfo *vinfo;
FBFixInfo *finfo;
+ if (!argp)
+ return -EFAULT;
+
switch (request) {
case FBIOGET_VSCREENINFO:
vinfo = (void *) argp;
+ if (!verify_access(vinfo, sizeof(FBVarInfo), PROT_WRITE))
+ return -EFAULT;
vinfo->xres = bgaDev.width;
vinfo->yres = bgaDev.height;
vinfo->bpp = bgaDev.bpp;
return 0;
case FBIOPUT_VSCREENINFO:
vinfo = (void *) argp;
+ if (!verify_access(vinfo, sizeof(FBVarInfo), PROT_WRITE))
+ return -EFAULT;
bga_set_mode(vinfo->xres, vinfo->yres, vinfo->bpp);
return 0;
case FBIOGET_FSCREENINFO:
finfo = (void *) argp;
+ if (!verify_access(finfo, sizeof(FBFixInfo), PROT_WRITE))
+ return -EFAULT;
finfo->fbmem = bgaDev.lfb;
finfo->fbmemLen = bgaDev.memSize;
return 0;
+ default:
+ return -EINVAL;
}
}
diff --git a/include/nucleus/object.h b/include/nucleus/object.h
index b86a86f..139f7ca 100644
--- a/include/nucleus/object.h
+++ b/include/nucleus/object.h
@@ -51,6 +51,7 @@ enum ListMode {
LIST_ORDERED,
};
+int check(void *addr);
void *get(void *addr);
void put(void *addr);
void *new(ObjectType *type);
@@ -58,6 +59,7 @@ void *copy(void *addr);
refcount_t usage(void *addr);
void lock(void *addr);
void unlock(void *addr);
+#define swap_ref(v,o) ({ if (o) get(o); if (v) put(v); v = o; })
ObjectList *create_list(ObjectType *type, enum ListMode mode, ...);
void destroy_list(ObjectList *list);
diff --git a/memory/heap.c b/memory/heap.c
index a61149c..0e0dbed 100644
--- a/memory/heap.c
+++ b/memory/heap.c
@@ -8,7 +8,7 @@
#include <stdint.h>
#include <stddef.h>
#include <string.h>
-#include <nucleus/panic.h>
+#include <nucleus/kernel.h>
#define KHEAP_START 0x200000 /* 2MB */
#define KHEAP_END 0x800000 /* 2MB */
diff --git a/object/list.c b/object/list.c
index 01f6aef..6745f28 100644
--- a/object/list.c
+++ b/object/list.c
@@ -7,9 +7,9 @@
*/
#include <stdarg.h>
+#include <nucleus/kernel.h>
#include <nucleus/object.h>
#include <nucleus/memory.h>
-#include <nucleus/panic.h>
/* Structure for a List Entry */
struct ListEntry {
@@ -144,7 +144,8 @@ remove(ObjectList *list, void *addr)
entry->next->prev = entry->prev;
/* Release resources */
- put(obj);
+ if (__builtin_expect(!!(obj->usage), 1))
+ put(obj);
list->entries--;
kfree(entry);
release(&list->lock);
diff --git a/object/manager.c b/object/manager.c
index a274408..7e6da04 100644
--- a/object/manager.c
+++ b/object/manager.c
@@ -6,14 +6,22 @@
* controls their instantiation and deletion.
*/
-#include <nucleus/object.h>
+#include <nucleus/kernel.h>
#include <nucleus/memory.h>
-#include <nucleus/panic.h>
+#include <nucleus/object.h>
void init_lock(Spinlock *lock);
void acquire(Spinlock *lock);
void release(Spinlock *lock);
+/* Check the magic of an object */
+int
+check(void *addr)
+{
+ Object *obj = addr;
+ return (obj && obj->magic == OBJECT_MAGIC);
+}
+
/* Obtain a reference to an object */
void *
get(void *addr)
@@ -37,6 +45,7 @@ put(void *addr)
if (obj->type->delete)
obj->type->delete(obj);
remove(obj->type->objects, obj);
+ obj->magic = 0;
if (obj->type->free)
obj->type->free(obj);
else
diff --git a/vfs/inode.c b/vfs/inode.c
index 8197127..903efd1 100644
--- a/vfs/inode.c
+++ b/vfs/inode.c
@@ -134,8 +134,10 @@ inode_lookup(Inode *inode, const char *name)
/* The file doesn't exist */
if (!child) {
- if (entry)
+ if (entry) {
remove(inode->dirEntries, entry);
+ put(entry);
+ }
entry = NULL;
goto end;
}
diff --git a/vfs/open.c b/vfs/open.c
index cac1512..cbc4bac 100644
--- a/vfs/open.c
+++ b/vfs/open.c
@@ -25,16 +25,16 @@ lookup(const char *path, ObjectList *newcustody)
char buf[PATH_MAX], *p = buf;
strncpy(buf, path, PATH_MAX);
Inode *inode;
- DirEntry *entry;
+ DirEntry *entry = NULL;
ObjectList *custody;
/* Resolve to absolute/relative root */
if (*p == '/') {
- inode = current->fs->root;
+ inode = get(current->fs->root);
while (*++p == '/');
custody = create_list(&dirEntryType, LIST_NORMAL);
} else {
- inode = current->fs->cwd;
+ inode = get(current->fs->cwd);
custody = copy_list(current->fs->cwdPath);
}
@@ -53,22 +53,21 @@ lookup(const char *path, ObjectList *newcustody)
if (inode != current->fs->root) {
entry = pop_from_end(custody);
if (!entry)
- inode = current->fs->root;
+ swap_ref(inode, current->fs->root);
else
put(entry);
}
} else {
entry = inode_lookup(inode, prev);
if (!entry) {
- inode = NULL;
+ swap_ref(inode, NULL);
goto end;
}
add(custody, entry);
put(entry);
}
-
if (entry)
- inode = entry->inode;
+ swap_ref(inode, entry->inode);
while (*++curr == '/');
prev = curr;
@@ -77,14 +76,14 @@ lookup(const char *path, ObjectList *newcustody)
/* Base name */
if (!strcmp(prev, ".") || !strcmp(prev, "")) {
if (!S_ISDIR(inode->mode)) {
- inode = NULL;
- entry = NULL;
+ swap_ref(inode, NULL);
+ swap_ref(entry, NULL);
}
} else if (!strcmp(prev, "..")) {
if (inode != current->fs->root) {
entry = pop_from_end(custody);
if (!entry)
- inode = current->fs->root;
+ swap_ref(inode, current->fs->root);
else
put(entry);
}
@@ -98,11 +97,8 @@ lookup(const char *path, ObjectList *newcustody)
add(custody, entry);
put(entry);
}
- if (entry) {
- inode = entry->inode;
- if (inode)
- get(inode);
- }
+ if (entry)
+ swap_ref(inode, entry->inode);
/* Copy path */
if (newcustody)