xorl %eax, %eax

CVE-2008-5025: hfs_cat_find_brec() Local Buffer Overflow

leave a comment »

This vulnerability is present in 2.6 Linux kernel releases up to 2.6.28-rc1 which is not vulnerable. The provided code will be from Linux kernel 2.6.27.5. The flawed function
was written by Paul H. Hargrove of Ardis Technologies and it is located at fs/hfs/catalog.c line 174. The vulnerable function is:

174 int hfs_cat_find_brec(struct super_block *sb, u32 cnid,
175                      struct hfs_find_data *fd)
176 {
177        hfs_cat_rec rec;
178        int res, len, type;
179

And is being used to get a catalog entry for the given ID received by varible cnid. Its first argument is the standard super block structure provided by linux/fs.h and its third
is pointer to an HFS’ structure defined at fs/hfsplus/hfsplus_fs.h which keeps track of a binary tree structure used for more efficient search on the file system. Next, at line 177 is
a declaration of hfs_cat_rec variable, this data type is defined at fs/hfs/hfs.h as a union which is being used to describe a catalog tree record.

180        hfs_cat_build_key(sb, fd->search_key, cnid, NULL);
181        res = hfs_brec_read(fd, &rec, sizeof(rec));
182        if (res)
183                return res;
184

The call to hfs_cat_build_key() provides fd->search_key with the catalog name on success, else it sets it sets it to zero. The following call to hfs_brec_read() uses the given hfs_find_data pointer (first argument) to find the record in the binary tree. If this does not success, it returns a non-zero value, else it checks its length to be less than its third argument, reads it and returns zero. That is, the above snippet locates the requested record
and initializes rec to this entry. Next,

185        type = rec.type;
186        if (type != HFS_CDR_THD && type != HFS_CDR_FTH) {
187                printk(KERN_ERR "hfs: found bad thread record in catalog\n");
188                return -EIO;
189        }
190

Integer type has now the type of the requested record and if it is neither a directory (HFS_CDR_THD) nor a file thread (HFS_CDR_FTH) an error is being printed and the function terminates with error on Input/Ouput operation. Lastly,

191        fd->search_key->cat.ParID = rec.thread.ParID;
192        len = fd->search_key->cat.CName.len = rec.thread.CName.len;

The search key’s binary tree structure parent ID is being replaced with the requsted entry’s one and at line 192 the length field of this new catalog name is also updated with the requested one. Finally,

193        memcpy(fd->search_key->cat.CName.name, rec.thread.CName.name, len);
194        return hfs_brec_find(fd);
195 }

The requested catalog name is copied to the binary tree search structure’s field using memcpy() and a size limit of the source string. At last, it calls hfs_brec_find() to find the requsted record which is now stored on the hfs_find_data structure. This is a classic overflow case since the user controls both the requsted catalog name, its length and the search_key‘s buffer which is only 31 bytes as defined at fs/hfs/hfs.h

#define HFS_NAMELEN             31     /* maximum length of an HFS filename */

Attackers have complete control over the copied data at line 193 using the memcpy library call. This means that a malicious user could construct a filename that when parsed by the HFS will be inserted in the binary tree it could lead to buffer overflow in the kernel space. To do this an attacker could construct a malicious HFS image with tools like mkisofs(8).

Strangely enough, various vulnerability databases identify this vulnerability as a denial of service attack. Memory corruption bugs should never be treated as DoS, since in most cases can lead to code execution one way or another.

Written by xorl

January 1, 2009 at 11:48

Posted in bugs, linux

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s