• Linux workswith many types of filesystems both native filesystems like ext2, ext3 and ext4, and it has the ability to work with filesystems which are being brought from other operating systems such as XFS, JFS, etc., or VFAT, etc.


  • Journaling filesystems which all modern file systems are, have extended capabilities and can recover far more quickly in case of some kind of disaster.


  • Types of Files There are a limited number of basic file types, each of which are displayed in the following directory listing:


  •  	
    $ ls -lF
    total 8
    brw-r--r-- 1 coop coop 200, 0 Mar  9 15:07 a_block_device_node
    crw-r--r-- 1 coop coop 200, 0 Mar  9 15:06 a_character_device_node
    drwxrwxr-x 2 coop coop   4096 Mar  9 15:05 a_directory/
    prw-rw-r-- 1 coop coop      0 Mar  9 15:04 a_fifo|
    -rw-rw-r-- 1 coop coop   1601 Mar  9 15:04 a_file
    lrwxrwxrwx 1 coop coop      4 Mar  9 15:06 a_symbolic_link_to_directory -> /usr/
    lrwxrwxrwx 1 coop coop      6 Mar  9 15:10 a_symbolic_link_to_a_file -> a_file
    srwxrwxr-x 1 coop coop      0 Mar  9 15:09 mysock=
    
    
  • The first character in the listing shows the type of file:


  • Character Type
    - Normal File
    d Directory
    l Symbolic link
    p Named pipe (FIFO)
    s Unix domain socket
    b Block device node
    c Character device node
     	
    file *
    
    acpitool:             ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV),
                              for GNU/Linux 2.6.9, dynamically linked
                              (uses shared libs), for GNU/Linux 2.6.9, not stripped
    atob:                 C shell script text executable
    awkit.sh:             Bourne-Again shell script text executable
    blank:                JPEG image data, JFIF standard 1.01
    cdc.ORIG3:            Bourne-Again shell script text executable
    copy_configs.sh:      ASCII text
    gtk-recordMyDesktop:  python script text executable
    gztobz2:              Bourne-Again shell script text executable
    html2ps:              shell archive or script for antique kernel text
    
    
  • When you do an "ls -l", you get ten characters at the beginning in the description of a file.


  • The first one, indicates the type of file, whether it's a normal file, a directory, a socket, a symbolic link, etc.


  • The next nine are three groups of three for "owner", "group", and "world", where "world" is everybody who doesn't belong to the "owner"'s' group, and the "owner" is the user that generally creates and owns the file.


  • You see that each of these three groups of permissions has three possibilities, "r", "w", and "x" for "read", "write", and "execute".


  • If you don't have that permission, then you see a dash ("-") instead of the "r", the "w", or the "x".


  • This permission model is sometimes called direct access control, it's not unique to Linux. It'ss standard in all Unix-like operating systems.


  • Changing file permissions is done with chmod, while changing file ownership is done with chown, and changing the group is done with chgrp.


  • There are a number of different ways to use chmod. For instance, to give the owner and world execute permission, and remove the group write permission:


  •  	
    $ ls -l a_file
    -rw-rw-r-- 1 coop coop 1601 Mar  9 15:04 a_file
    $ chmod uo+x,g-w a_file
    $ ls -l a_file
    -rwxr--r-x 1 coop coop 1601 Mar  9 15:04 a_file
    
    
  • where u stands for user (owner), o stands for other (world), and g stands for group.


  • This kind of syntax can be difficult to type and remember, so one often uses a shorthand which lets you set all the permissions in one step. This is done with a simple algorithm, and a single digit suffices to specify all three permission bits for each entity. This digit is the sum of:


    1. 4 if read permission is desired


    2. 2 if write permission is desired


    3. 1 if execute permission is desired.


  • Thus, 7 means read/write/execute, 6 means read/write, and 5 means read/execute.


  • When you apply this when using chmod, you have to give three digits for each degree of freedom, such as in:


  •  	
    $ chmod 755 a_file
    $ ls -l a_file
    -rwxr-xr-x 1 coop coop 1601 Mar  9 15:04 a_file
    
    
  • Changing the group ownership of the file is as simple as doing:


  •  	
    $ chgrp aproject a_file
    
    
  • and changing the ownership is as simple as:


  •  	
    $ chown coop a_file
    
    
  • You can change both at the same time with:


  •  	
    $ chown coop.aproject a_file
    
    
  • where you separate the owner and the group with a period. All three of these commands can take an -R option, which stands for recursive. For example:


  •  	
    $ chown -R coop.aproject .
    $ chown -R coop.aproject subdir
    
    
  • will change the owner and group of all files in the current directory and all its subdirectories in the first command, and in subdir and all its subdirectories in the second command.


  • These commands can only do what you already have the right to do. You cannot change the permissions on a file you do not own, for example, or switch to a group you are not a member of. To do such changes, you must be root, prefixing sudo to most of the above commands.


  • if we didn't have a "mask" set when we created a file, it would be created with "666" permission. So, that is read-write permission for user, group, and other, or world.


  • Create an empty file with:


  •  	
    $ touch afile
    $ ls -l afile
    -rw-rw-r-- 1 coop coop 0 Jul 26 12:43 afile
    
    
  • which shows it is created by default with read/write permissions for owner and group, and read for world.


  • In fact, the default permissions given when creating a file is actually read/write for owner, group and world (0666); it has been modified by the current umask.


  • If you just type umask you get the current value:


  •  	
    $ umask 
    0002
    
    
  • which is the most conventional value set by system administrators for users. This value is combined with the file creation permissions to get the actual result; i.e.:


  •  	
    0666 & ~002 = 0664; i.e., rw-rw-r--
    
    
  • Try modifying the umask and creating new files and see the resulting permissions as in:


  •  	
    $ umask 0022
    $ touch afile2
    $ umask 0666
    $ touch afile3
    $ ls -l afile*
    
    
  • While we have shown you how to use chmod using the octal digit method of specifying permissions, it is usually preferable to use the symbolic methods that we will show here.


  • It is possible to either give the permissions directly, or add or subtract permissions. The syntax is pretty obvious. Some examples


  •  	
    $ chmod u=r,g=w,o=x afile
    $ chmod u=+w,g=-w,o=+rw afile
    $ chmod ug=rwx,o=-rw afile
    
    
  • After each step do:


  •  	
    $ ls -l afile
    
    
  • to see how the permissions took, and try some variations.


  • Normally, programs are run with the privileges of the user who is executing the program. Occasionally, it may make sense to have normal users have expanded capabilities they would not normally have, such as the ability to start or stop a network interface, or edit a file owned by the superuser.


  • By setting the setuid (set user ID) flag on an executable file, you modify this normal behavior by giving the program the access rights of the owner rather than the user of the program.


  • We should emphasize that this is generally a bad idea and is to be avoided in most circumstances. It is often better to write a daemon program with lesser privileges for this kind of use.


  • Suppose we have the following C program (writeit.c, provided to save typing for download with the solution below) which attempts to overwrite a file in the current directory, afile:


  •  
    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/stat.h>
         
    int main(int argc, char *argv[])
    {
            int fd, rc;
            char *buffer = "TESTING A WRITE";
            
            fd = open("./afile", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
            rc = write(fd, buffer, strlen(buffer));
            printf("wrote %d bytes\n", rc);
            close(fd);
            exit(EXIT_SUCCESS);
    }
    
    
  • which can be compiled simply by doing:


  •  
    $ make writeit
    
    
  • or


  •  
    $ gcc -o writeit writeit.c
    
    
  • If you try to run this program on a file owned by root, you will get the following sequence of events:


  •  
    $ sudo touch afile
    $ ./writeit afile
    wrote -1 bytes
    $ sudo ./writeit afile
    wrote 15 bytes
    
    
  • Thus, the root user was able to overwrite the file it owned, but a normal user could not.


  • Note that changing the owner of writeit to root will not help:


  • By setting the setuid bit you can make any normal user able to do this:


  •  
    $ sudo chown root.root writeit
    $ ./writeit
    wrote -1 bytes
    
    
  • You may be asking why we did not just write a script to do such an operation, rather than to write and compile an executable program?


  •  
    $ sudo chmod +s writeit
    $ ./writeit
    wrote 15 bytes
    
    
  • The reason is that under Linux if you change the setuid bit on such an executable, it will not do anything unless you actually change the setuid bit on the shell.