]> Zhao Yanbai Git Server - minix.git/commitdiff
VFS: prevent buffer overflow
authorThomas Veerman <thomas@minix3.org>
Tue, 17 Jul 2012 08:47:51 +0000 (08:47 +0000)
committerThomas Veerman <thomas@minix3.org>
Tue, 17 Jul 2012 08:49:41 +0000 (08:49 +0000)
If an FS returns faulty struct dirent data, VFS could overflow
a buffer that holds this data.

servers/vfs/path.c

index b3baf5815dc0629094a5fd652c6ab77307b66f85..bb9db3a2ce39dde08f4113549f8402513de893ae 100644 (file)
 #include <minix/keymap.h>
 #include <minix/const.h>
 #include <minix/endpoint.h>
+#include <stddef.h>
 #include <unistd.h>
 #include <assert.h>
 #include <minix/vfsif.h>
+#include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/un.h>
 #include <dirent.h>
@@ -545,9 +547,11 @@ struct vnode *dirp;
 struct vnode *entry;
 char ename[NAME_MAX + 1];
 {
+#define DIR_ENTRIES 8
+#define DIR_ENTRY_SIZE (sizeof(struct dirent) + NAME_MAX)
   u64_t pos, new_pos;
-  int r, consumed, totalbytes;
-  char buf[(sizeof(struct dirent) + NAME_MAX) * 8];
+  int r, consumed, totalbytes, name_len;
+  char buf[DIR_ENTRY_SIZE * DIR_ENTRIES];
   struct dirent *cur;
 
   pos = make64(0, 0);
@@ -569,9 +573,14 @@ char ename[NAME_MAX + 1];
 
        do {
                cur = (struct dirent *) (buf + consumed);
+               name_len = cur->d_reclen - offsetof(struct dirent, d_name) - 1;
+
+               if(cur->d_name + name_len >= &buf[DIR_ENTRIES * DIR_ENTRY_SIZE])
+                       return(EINVAL); /* Rubbish in dir entry */
                if (entry->v_inode_nr == cur->d_ino) {
                        /* found the entry we were looking for */
-                       strlcpy(ename, cur->d_name, NAME_MAX+1);
+                       strlcpy(ename, cur->d_name,
+                               MIN(name_len + 1, NAME_MAX + 1));
                        ename[NAME_MAX] = '\0';
                        return(OK);
                }