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 - http://www.sven-tantau.de/ Vendor-URL: http://sourceforge.net/projects/fuse Vendor-Status: informed, vendor released a fixed version Advisory-URL: http://www.sven-tantau.de/public_files/fuse/fuse_20050603.txt Exploit-URL: http://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 http://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: http://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 http://www.sven-tantau.de/ *** http://www.beastiebytes.de/ http://twe.sven-tantau.de/ *** http://www.bewiso.de/ _______________________________________________ Full-Disclosure - We believe in it. Charter: http://lists.grok.org.uk/full-disclosure-charter.html Hosted and sponsored by Secunia - http://secunia.com/