Linux File Permissions

Linux file permissions are based upon three actions:

  • Read – read a file, on directories grants permission to read names of files in the directory (but not find any additional information size owner etc..)
  • Write – modify, delete rename a file, on directories it gives permission to modify entries inside the directory including create, delete and rename files
  • Execute – execute a file, on directories is grants permission to go into the directory and subdirectories it goes not grant read access to the directory

Linux also supports three additional permissions:

  • SUID – Set user ID – when a file with this bit is set and it is executable it will be executed with the effective permissions of the owner.
  • SGID – Set group ID – when a file with this bit is set and it is executable it will be executed with the effective permissions of the group, directories with the SGID new files and directories created under the original directory will inhert it’s group from the SGID group.
  • sticky –  when a file with this bit is set and it is executable it encourages the kernel to  retain the resulting process beyond termination, when set upon a directory it prevents users who are not the owner from renaming, deleting or moving files or subdirectories.

Each file can be owned by a single user, group and everyone else.     Other is everyone who is not the user or a member of the group.  All directories are really just files in linux.   Linux filenames can be up to 256 characters long.  Linux permissions are not inherited except SGID and SUID.  Since the 2.6 Kernel linux also support acl based file permissions giving you better control on your file system.  You can see the permission user and group on a file by performing a long listing of a file:

ls -al

drwxr-xr-x  3 root       root  4096 Nov 10 21:25 .
drwx—— 46 root       root  4096 Nov 10 21:12 ..
drwxr-xr-x  2 jgriffiths users 4096 Nov 10 21:25 cheese
-rw-r–r–  1 root       root     0 Nov 10 21:12 donkey.doc
-rw-r–r–  1 jgriffiths video    0 Nov 10 21:12 myfile.txt

This listing displays hidden files because we issued ls with the -a command line switch.   The sections are divided as follows:

Sample Field Description
drwxr_xr_x Permissions Permissions on the directory or file
2 Directories Amount of links (files and directories) inside the directory including itself
jgriffiths User Owner of this files username
users Group Group this file is owner by
4096 Size Size of file in k-bytes
Nov 10 21:25 Modification time Time of last change
cheese Name Name of directory or file

The permissions field is 11 characters broken down into four sections: type, owner permissions, group permissions and other permissions.

Characters #’s
Section Description
1 type This defines a directory vs a file or special type
2-4 owner permissions This defines users permissions
5-7 group permissions This defines group permissions
8-11 other permissions This defines world permissions

There can be the following types:

Type Description
d Directory
l Symbolic link
s Socket
p Named pipe
Normal file
c Character device or special file
b Block device or special file

Each of the user, group and other permissions files contain either a r,w,x or an -.  They are always displayed in the order of rwx.

Type Description
Not set not allowed to take action
r Read permission
w Write permission
x Execute permission

For example the following listing:

drwxr-xr-x  2 root       root  4096 Nov 10 21:25 cheese

Is a directory (d) with owner (root) read (r), write (w), execute (x), group (root) read (r), no-write (-), execute (x), other, read (r), no-write (-),  and execute (x).

Additional Permissions

The additional permissions show up by replacing the execute bit with a character:

Permission Class Non-Executable Executable
setuid User S s
setgid Group S s
Sticky bit Others T t

Changing Permissions

In Linux you use the chmod command to change permissions of a file or directory.  chmod can be used with an octal set of permissions or individually using characters to represent user (u), group (g), other (o), and an add (+), subtract (-).  I will cover Octal permissions using numbers to represent combination permissions.  When using octal permissions you seperate out permission in the following order user:group:other.  Each permission type adds an amount to zero:

  • Read – Adds 4 to the total
  • Write – Adds 2 to the total
  • Execute – Adds 1 to the total

So permission 744 would be User: read,write, execute; Group read; Other read.  The command to set a file to 744 would be:

chmod 744 filename

Changing Additional Permissions

Additional permissions take the first bit a hidden bit of the permissions:

  • The setuid bit adds 4 to the total.
  • The setgid bit adds 2 to the total.
  • The sticky bit adds 1 to the total.

If I wanted to set the permissions to 744 with the sticky bit set I would run this command:

chmod 1744 filename

Default Permissions – Umask

The umask defines the default permissions assigned to any file created by a user or system.   You can assign your umask at any time by executing:

umask permissions

The permissions on umasks can be tricky.  You need to take the permissions of 777 and subtract the umask.  For example a user has the umask of 022 when he / she creates a file the default permissions are: 644.

Finding Files with Special Permissions

Since special permissions break the authentication method for Linux they can be very dangerous.  There are some simple ways to locate suid and sgid files.

Find all SetGID files on your system:

find / -xdev -type f -perm +g=s -print’

Find all SetUID files on your system:

find / -xdev -type f -perm +u=s -print

Find all world writable files on a system:

find / -xdev -perm +o=w ! \( -type d -perm +o=t \) ! -type l -printtype f -perm +u=s -print

ACL File Permissions on 2.6 Kernel

The 2.6 Linux kernel added ACL’s to file permissions (access control lists)  it allows you to have unlimited number of users with individual permissions on a file.  It also adds a level of complexity to your file system.  Before you can work with ACL’s you need to enable them on a mount point basis.  Enabling ACL’s requires adding the option acl to the /etc/fstab and remounting the mount point.  For example take a look at this root partition:

/dev/hda5            /                    ext3       acl,user_xattr        1 1

This shows acl’s enabled and ready to work.  ACL can only be used on the following file systems: ext2/3, XFS, JFS and ReiserFS.  The primary method for manipulating acl’s is using the getfacl and setfacl commands. getfact allows you to display acl lists on a file or directory.  setfacl allows you to set the current acl on a file or directory.  In order to explain acl’s lets assume that I have a unix system with four users jack,jill,bob and myself (jgriffiths).   I want to create a file called test.txt and give jack and jill read and write permission to this file while bob can only read the file.  I created the file and started with the following permissions:

ls -al test.txt
-rw——- 1 jgriffiths users 0 2007-11-16 23:37 test.txt

The permissions are clearly set to allow jgriffiths as the only person who can manipulate this file in anyway.  setfacl allows you to set permissions for more than one user at a time.  To create my acl permissions I would use the following command:

setfacl -m u:bob:r–,u:jack,jill:rw- tester.txt

I can use the getfacl to view the current effective permissions on the file:

getfacl test.txt
# file: test.txt
# owner: jgriffiths
# group: users
user:jill:rw-
user:jack:rwx

user:bob:r–
group::—
mask::r-x
other::—

So jack and jill can read and write while bob can only read.  Everyone else but jgriffiths cannot do anything with this file.  You will also notice an entry called mask.  The mask sets the effective permissions for all acl groups and users.  This allows you to limit acl’s control maxium on a file or directory.  Assume my mask looks like this in the above entry:  mask::r–  then no one would be able to do more than read this file unless they are the owner.  You can set the mask using:

setfacl -m mask::rw- tester.txt

Viewing the rights of our file now produces an effective rights listing:

getfacl tester.txt
# file: tester.txt
# owner: jgriffiths
# group: users
user::rw-
user:jack:rw-                 #effective:r–
user:bob:r–
group::—
mask::r–
other::—

If we perform an ls -al on the file it produces the following confusing results:

-rw-rw—-+ 1 jgriffiths users 0 2007-11-17 00:01 test.txt

As you can see it seems the users group has read and write access to test.txt when in reality they do not.  Also linux has added a + to the permission list to help us know there is a acl on this file.

ACL’s can be added based upon Linux groups using the same setfacl command:

setfacl -m g:groupname:rw-,g:groupname_two:r test.txt

Removing acl based permission can be done using the -x command line parameter:

setfacl -x u:bob,u:jack tester.txt

Now only Jill can access the tester.txt file.  Or we can removal all acl’s on a file with the –remove-all:

setfacl –remove-all tester.txt

If you would like to recursively assign an acl to a directory and all files add an -R to the command use the following command:

setfacl -R -m g:users:r-x /data/webroot

ACL’s viewed by the getfacl command can be piped into a file and used to generate the same acl on any other file using the setfacl command:

# getfacl -omit tester.txt
# setfacl -M myacl test*
# getfacl -omit test.txt
user:jill:rw-
user:jack:r-x
user:bob:r–
group::—
mask::r-x
other::—

You can also use gid’s and uid’s instead of names as long as you provide the -numeric switch to setfacl.

ACL’s and Directories the Default ACL

ACL’s created inherited permissions that allow subdirectories and file to get the permissions of their parent.  This type of inheritance is easy to manage but can be a security concern make sure to consider carefully how you set acl’s on directories because those same permissions will exist on the lower levels.

CD ISO’s in linux

Every so often I need to mount an ISO image on linux.

To mount an ISO you first have to create a mount point for example /mnt/iso then type the following command:

mount iso_name.iso /mnt/iso/ -t iso9660 -o loop=/dev/loop0

On some systems you need to avoid the loop= part of the command and issue:

mount -o loop -t iso9660 iso_name.iso /mnt/iso

To create an ISO from a directory use the following command consult the man page if any switches give you trouble.

mkisofs -rdlJ -allow-leading-dots -hide-rr-moved -dir-mode 555 -p “preparer”

-publisher “publisher” -A “Disc name” -V VOLNAME -o output.iso -b isolinux/isolinux.bin

-c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table /mnt/iso

Quick Search and Replace inside a file with perl

Almost every day I need to search and replace inside a file.   This is done very easily with vi but a little harder on multiple files.  Take this example I want to search all the files in the current directory ending in .conf and find the word jgriffiths.org and replace it with jgriffiths.com.    Perl to the rescue with this simple one line fix

perl -pi -e 's/jgriffiths.org/jgriffiths.com/g' *.conf

Yes it’s that simple.

HP spec’s for every machine on your desktop Quick Specs

A co-worker recently introduced me to HP quick specs a easy way to get information on HP servers and PC’s.  It provides all the information required to get part replacements or figure out what under the hood.   HP has done one thing better and provided a Windows application know as the product bulletin which updates all stats to your local PC and allows you to price items retail.   If you run HP hardware you should really look into this free download from HP.  You can download it here.

Check Pagesize in Linux

Recently my DBA’s were asking me what the page size was in linux.  A page size is a logical block of your physical, or virtual memory.  Each type of memory is divided into same size blocks or pages.  To find your system pagesize in linux type:

getconf PAGESIZE

or

getconf PAGE_SIZE

Brocade Zoning via scripting

Update: If you are looking for instructions for FOS 7 go here.

From time to time I have to handle some storage zoning.  I use mostly brocade fiber channel switches.  They are pretty easy to zone via scripts.  Which leaves you with your whole zone documented and rebuildable at a moments notice.  Before I get into the scripts I should mention that I do end to end zoning via WWID not port based zoning.   In other words I connect my Server HBA to my storage system.  Port based zoning means we zone the port that the HBA is on to the port that contains the storage system.  Port based requires that everything is plugged into the same port always and can be hard to rebuild quickly without the correct documentation.  Comments in brocade scripts are proceeded by an exclamation mark !

!!NOTE: This is fabric A
!! Make all the aliases for systems
alicreate "Storage_HBA1_A", "50:01:43:81:02:45:DE:45"
alicreate "Storgae_HBA2_A", "50:01:43:81:02:45:DE:47"
alicreate "Server_HBA1_A", "50:01:23:45:FE:34:52:12"
alicreate "Server2_HBA1_A", "50:01:23:45:FE:35:52:15"
alicreate "Server2_HBA1_A", "50:01:23:45:FE:35:52:17"

!! Make the zones

zonecreate "Z_server_to_Storage_HBA1_A", "Server_HBA1_A; Storage_HBA1_A"

zonecreate "Z_server_to_Storage_HBA2_A", "Server_HBA1_A; Storage_HBA2_A"

zonecreate "Z_server2_to_Storage_HBA1_A", "Server2_HBA1_A; Storage_HBA1_A"

zonecreate "Z_server2_to_Storage_HBA2_A", "Server2_HBA1_A; Storage_HBA2_A"

!!NOTE: effective config and zone members on SWITCHA_config Fabric
cfgcreate "SWITCHA_config", "Z_server_to_Storage_HBA1_A; Z_server_to_Storage_HBA2_A; Z_server2_to_Storage_HBA1_A; Z_server2_to_Storage_HBA2_A"

cfgsave
cfgenable "SWIT

Load it into your switch and your ready to go!

Scripting out vSwitches in VMware

Virtual switches are a fun topic in ESX,  They are unique on each ESX node and not shared across the cluster.  This problem was addressed in ESX 4.0 with distributed virtual switches (DVS) which allows you to create switches on vCenter and pass it to all nodes.  Unfortunately DVS is available only in the plus licenses which cost about $1000 more per processor.  For those of us without DVS are forced to script out vSwitches.   The process is pretty simple but has to be done in the right order from the service console:

  1. Create the vSwitch
  2. Create port groups
  3. Assign VLAN tags to port groups if required
  4. Apply security policy
  5. Link a nic to the switch
  6. Create a service console if required
  7. Assign ip addresses if required
  8. Enable vmotion if required
1.
# Create New vSwitches
# create a vSwitch with 56 ports for our service console
esxcfg-vswitch -a vSwitch0
# create a vSwitch with 56 ports for the vmkernel network
esxcfg-vswitch -a vSwitch1
# create a vSwitch with 1024 ports for VM's
esxcfg-vswitch -a vSwitch2:1024

2.
# Create Base port groups
# Service console port group
esxcfg-vswitch --add-pg="Service Console" vSwitch0
# Vmkernel port group
esxcfg-vswitch --add-pg="Vmkernel" vSwitch1
# Port group for FT
esxcfg-vswitch --add-pg="FT" vSwitch1
# Port group for VM's in VLAN 801
esxcfg-vswitch --add-pg="VM - 801" vSwitch2
# Port group for VM's in VLAN 802
esxcfg-vswitch --add-pg="VM - 802" vSwitch2
3.
# Assign VLAN's to port groups
esxcfg-vswitch -p "VM - 801" -v 801 vSwitch2
esxcfg-vswitch -p "VM - 802" -v 802 vSwitch2
4.
# Default setting on ESX allow for mac changing and sniffing fix this via these commands
vmware-vim-cmd hostsvc/net/vswitch_setpolicy --securepolicy-macchange=false vSwitch0
vmware-vim-cmd hostsvc/net/vswitch_setpolicy --securepolicy-promisc=false vSwitch0
vmware-vim-cmd hostsvc/net/vswitch_setpolicy --securepolicy-forgedxmit=false vSwitch0

vmware-vim-cmd hostsvc/net/vswitch_setpolicy --securepolicy-macchange=false vSwitch1
vmware-vim-cmd hostsvc/net/vswitch_setpolicy --securepolicy-promisc=false vSwitch1
vmware-vim-cmd hostsvc/net/vswitch_setpolicy --securepolicy-forgedxmit=false vSwitch1

vmware-vim-cmd hostsvc/net/vswitch_setpolicy --securepolicy-macchange=false vSwitch2
vmware-vim-cmd hostsvc/net/vswitch_setpolicy --securepolicy-promisc=false vSwitch2
vmware-vim-cmd hostsvc/net/vswitch_setpolicy --securepolicy-forgedxmit=false vSwitch2
5.
# Link primary nic to switch
esxcfg-vswitch --link=vmnic0 vSwitch0
esxcfg-vswitch --link=vmnic6 vSwitch1
esxcfg-vswitch --link=vmnic2 vSwitch1
#Link VMnetwork to vSwitch2
esxcfg-vswitch --link=vmnic1 vSwitch2
esxcfg-vswitch --link=vmnic3 vSwitch2
esxcfg-vswitch --link=vmnic5 vSwitch2
esxcfg-vswitch --link=vmnic7 vSwitch2

6.
esxcfg-vswif -a vswif0 -i192.168.10.45 -n 255.255.255.0 -p "Service Console"

7.
esxcfg-vmknic -a -i 192.168.20.10 -n 255.255.255.0 -p "Vmkernel" vmkernel
esxcfg-vmknic -a -i 192.168.20.40 -n 255.255.255.0 -p "FT"

8.

vmware-vim-cmd hostsvc/vmotion/vnic_set vmk0

The only thing I missed was setting a default order on the nic’s if you have multiple nic’s: For example my vSwitch1 has two port groups with 2 vnics I can choose to force a vnic for each group:

# Force Vmkernel to use vmnic6 unless it's unavailable
vmware-vim-cmd /hostsvc/net/portgroup_set -–nicorderpolicy-active=vmnic6 vSwitch1 “Vmkernel”
vmware-vim-cmd /hostsvc/net/portgroup_set -–nicorderpolicy-standby=vmnic2 vSwitch1 “Vmkernel”
vmware-vim-cmd /hostsvc/net/portgroup_set -–nicorderpolicy-active=vmnic2 vSwitch1 “FT”
vmware-vim-cmd /hostsvc/net/portgroup_set -–nicorderpolicy-standby=vmnic6 vSwitch1 “FT”

VLAN Tagging in Linux

Recently I have been doing some reworking on networking at work. One of the new requirements is that everything be network connection be a tagged VLAN. This is a pretty simple process in Red Hat Linux with multiple paths. Test files are my favorite way to make these changes so lets assume that I want the VLAN to be 455 with the nic eth0.

  • Navigate to your networking scripts:  /etc/sysconfig/network-scripts
  • Copy your current eth0 configuration cp ifcfg-eth0 ifcfg-eth0.455
  • Open the file:
DEVICE=eth0
IPADDR=192.168.10.10
NETMASK=255.255.255.0
BOOTPROTO=static
HWADDR=00:e0:4c:87:e2:36
MTU=1500
ONBOOT=yes
BROADCAST=192.168.10.255
NETWORK=192.168.10.0
DNS1=192.168.10.1
  • Modify the device name to read eth0.455
  • Add the line VLAN=yes to the end of the file
  • Save and exit
  • Shutdown the old interface (make sure your on console)
  • ifdown eth0
  • Bring up new VLAN
  • ifup eth0.455
  • Delete old interface rm ifcfg-eth0

That’s all you have to do and your Operating system will be tagging all outbound traffic with VLAN 455 and only reading traffic from 455.

Mounting via labels in fstab

An issue I have run into on Solaris is the dreaded device rename during a reboot. This can wreak havoc on your system during booting making it unable to boot. This problem was addressed in multiple ways in Linux. One of the most common methods is via labels. This allows you to write a string name to the disk and mount the disk via the string name. I find this particularly useful when using hot swappable drives in my PC. To see the current label on a disk:

[root@linuxmonkey ~]# e2label /dev/sda1
/boot

so the label on disk /dev/sda1 is /boot

To set a label type
[root@linuxmonkey ~]# e2label /dev/sda1 label_name

In order to mount via label instead of the traditional /dev/sda1 in fstab use a

LABEL=/boot

And you have a mount that is not effected by reboots.

Logical Volume Management

Logical Volume Management provides a great deal of flexibility allowing you to dynamically re-allocate blocks of space to different file systems.  Traditional volume manage relies upon strict partition boundaries separating and containerizing each mount point.  Logical Volume Management in linux takes control of the whole drive carving it out into equal chunks called physical extents (PE).  Each PE is addressed by it’s logical extent (LE) address.  Groups of LE’s are grouped together to form logical volumes (LV) that are used to mount as file systems.   Then LV’s are grouped into volume groups (VG) for management purposes.

Creating a Physical Volume

Use the pvcreate command to create a PV.  To create a PV on an empty disk (/dev/sda)  use this command:

pvcreate /dev/sda

You can also setup PV’s on current empty partitions.  Use fdisk to change to system ID of the partition to hex 8e then use the pvcreate command on the partition.  Any data on that partition will be lost.

Create a Volume Group

Once you have one or more PV’s you can create a LV.   LV’s can cross multiple partitions or disks.  To create the initial VG called bob use the following command:

vgcreate bob /dev/sda1 /dev/sda3

If you would like to add space to bob use the following command:

vgextend bob /dev/hda1

If you want to reduce space you can use the following command:

vgreduce bob /dev/hda1


Creating the logical volume

Now that you have one or more PV’s grouped together in VG’s your ready for a logical volume and file systems.   In order to create a mountable file system it would be best to know the size of each PE.  This will allow you to define the correct size for each mount point.   You display a lot of information on vg’s with the following command:

vgdisplay bob

Then you can create an LV of the correct size with the lvcreate command:

lvcreate -l num_of_PEs bob -n name_of_LV

This will create a LV inside the location /dev/bob/name_of_LV.  Then you can use standard disk tools on the logical volume to lay down a file system.  If you want to extend the size of the LV you use the lvextend command for example to add 150Mb’s:

lvextend -L150M /dev/bob/name_of_LV