A memory disclosure vulnerability exists in FUSE versions below 2.3.0.
1617e02791e8e6f8f643c263484eb5e3ba6de5bf570af2a803a1c4ed05c3e96a
Advisory: FUSE: Filesystem in Userspace - Information Disclosure
Update: Correction of affected versions and os.
Product: FUSE: Filesystem in Userspace
Affected Version: 2.2, 2.2.1, 2.3-pre* and 2.3-rc1
Immune Version: < 2.2, 2.3.0
OS affected: Linux 2.4.*, 2.6.*
Security-Risk: high
Remote-Exploit: no
Date: 03.06.2005
Author: Sven Tantau - https://www.sven-tantau.de/
Vendor-URL: https://sourceforge.net/projects/fuse
Vendor-Status: informed, vendor released a fixed version
Advisory-URL:
https://www.sven-tantau.de/public_files/fuse/fuse_20050603.txt
Exploit-URL: https://www.sven-tantau.de/public_files/fuse/memfs.c
Product
=======
> From fuse/README
FUSE (Filesystem in Userspace) is a simple interface for userspace
programs to export a virtual filesystem to the linux kernel. FUSE
also aims to provide a secure method for non privileged users to
create and mount their own filesystem implementations.
You can download the source code releases from
https://sourceforge.net/projects/fuse
Details
=======
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;
....
}
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);
}
....
}
Pages will not be zeroed if nbytes==0 which leads to
information disclosure of previous page content. As those can contain
sensitive data of other users (including root), risk is rated high.
A proof of concept file system is available at:
https://www.sven-tantau.de/public_files/fuse/memfs.c
Workaround
==========
rmmod fuse
Install the patch or update to fuse-2.3.0.
Patch
=====
Vendor (Miklos Szeredi) provided fix:
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)
History
=======
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
2005-06-06 Update of this advisory (affected versions mixup)
--
Sven Tantau
https://www.sven-tantau.de/ *** https://www.beastiebytes.de/
https://twe.sven-tantau.de/ *** https://www.bewiso.de/