Hacking Linux Exposed

About
Authors
Contents
Reviews
Foreword
Purchase

Articles
Books
Sourcecode
Tools
Errata

Home

 


previous article
index
next article
Linux file locking mechanisms - Mandatory Locking
By Bri Hatch.

Summary: Mandatory Locking can enforce file locks at the kernel level.

Last week I described three locking functions - flock, lockf, and fcntl. These functions, while managed by the Linux kernel, are known as advisory locking mechanisms. Any program which doesn't bother checking to see if a lock is in place will never know. The kernel won't stop it from reading or writing the file.

This can be a problem when some programs correctly wait for an exclusive lock on a file, but other programs out of your control access the same files simultaneously without lock checks. If you don't have the code, it may be difficult or impossible to wrap some sort of external locking mechanism around the closed source program.

In these cases, you can enforce locking at the kernel level with mandatory locks. Mandatory locking is implemented on a file-by-file basis. When a program attempts to lock a file with lockf or fcntl that has mandatory locking set, the kernel will prevent all other programs from accessing the file.[1] Processes which use flock will not trigger a mandatory lock.

To enable mandatory locking, you must first mount the filesystem with the mand mount option:

  # mount | grep /data
  /dev/hda7 on /data type ext3 (rw,noatime)

  # mount -oremount,mand /data
  
  # mount | grep /data
  /dev/hda7 on /data type ext3 (rw,mand,noatime)

Here I remounted the /data directory with the mand option. (I should add mand to the appropriate /etc/fstab entry to have this setting survive reboots as well.)

To prevent mandatory locking from taking over the entire filesystem, only specifically tagged files will exhibit mandatory locks. The way you define a file to be governed by mandatory locks is to set the sgid (setgroupid) bit, but not the group execute bit. This combination doesn't make any sense normally,[2] which is why it was chosen for this purpose.

So, say we needed to enforce mandatory locking on the files d_* in a directory, we'd do the following:

  $ cd /data
  $ ls -l
  -rw-r--r--    1 dbrand   stuff       82756 May 28 14:07 a_5772.dat
  -rw-r--r--    1 dbrand   stuff        7788 May 28 14:07 a_9298.dat
  -rw-r--r--    1 dbrand   stuff        3325 May 28 14:07 d_0283.dat
  -rw-r--r--    1 dbrand   stuff       19288 May 28 14:07 d_5755.dat
  -rw-r--r--    1 dbrand   stuff        1224 May 28 14:07 d_5758.dat
  
  $ chmod g+s,g-x d*
  $ ls -l
  -rw-r--r--    1 dbrand   stuff       82756 May 28 14:07 a_5772.dat
  -rw-r--r--    1 dbrand   stuff        7788 May 28 14:07 a_9298.dat
  -rw-r-Sr--    1 dbrand   stuff        3325 May 28 14:07 d_0283.dat
  -rw-r-Sr--    1 dbrand   stuff       19288 May 28 14:07 d_5755.dat
  -rw-r-Sr--    1 dbrand   stuff        1224 May 28 14:07 d_5758.dat

Henceforth, the d_* files will exhibit mandatory locking. The capital "S" in the output signifies that the sgid bit is set, but there is no underlying execute ("x") bit, which is what we need.

Mandatory locks should only be used where you have problem software you cannot modify to use locks correctly. Even with mandatory locks, you can still have conflicts. If program A reads in a file, program B locks, edits, and unlocks the file, and program A then writes out what it originally read, you're still in a pickle. However in many cases, mandatory locking can help prevent corruption of your data.

The other potential problem with mandatory locks is that nothing, not even root-owned processes, can override the lock. The best root could do would be to kill the process that has the lock on the file. This could be particularly nasty if the mandatory-locked file is available via NFS or other remotely-accessible filesystem, as the entire fileserver process itself will block until the lock is released.

NOTES:

[1] To be exact, if a program has a read or shared lock on a file, no other program can write to it. If a program has a write or exclusive lock on a file, no other programs can read or write to it.

[2] The sgid bit is put on programs that should run with different group permissions than the invoking user. When a program doesn't have the group execute bit set, this situation is rather meaningless


Bri Hatch is Chief Hacker at Onsight, Inc and author of Hacking Linux Exposed and Building Linux VPNs. He likes to periodically delete /etc/passwd and /etc/shadow and reboot as the ultimate Linux locking system. Bri can be reached at bri@hackinglinuxexposed.com.


Copyright Bri Hatch, 2003


This is the June 23, 2003 issue of the Linux Security: Tips, Tricks, and Hackery newsletter. If you wish to subscribe, visit http://lists.onsight.com/ or send email to Linux_Security-request@lists.onsight.com.

previous article
index
next article