In addition to standard Unix file permissions, FreeBSD offers an additional layer of file-level security that applies to non-directory files, known as “file flags.”

File flags can be used even to prevent the root user account from altering or deleting files — something that POSIX compliant Unix file permissions cannot do. To check the flags set for a given flag, use the -lo options for ls:

  > ls -lo foobar.pdf

-rwxrwxr-- 1 bob bob - 0 Nov 19 12:47 foobar.pdf

That dash shows that there are no file flags set for the file foobar.pdf. Flags can be set using the chflags utility:

  > chflags sunlink foobar.pdf

> ls -lo foobar.pdf

-rwxrwxr-- 1 ren ren sunlnk 0 Nov 19 12:47 foobar.pdf

In the case of each flag, a flag that has been set can be cleared by attaching “no” to the beginning of the flag name:

  > chflags nosunlink foobar.pdf

> ls -lo foobar.pdf

-rwxrwxr-- 1 ren ren - 0 Nov 19 12:47 foobar.pdf

A set of octal values may be used to set and unset file flags, using numeric codes rather than longer names. The most useful of these is probably 0, which clears all file flag settings. The chflags manpage for FreeBSD provides a complete listing of the octal codes.

Normally, an article like this could point out a few cases where a given set of commands might be useful and direct the reader to the manpage for the relevant utility — in this case, the chflags utility. In this case, however, the manpage is especially cryptic about what the various flags actually do. It says of them:

arch, archived

set the archived flag (super-user only)

opaque set the opaque flag (owner or super-user only)

nodump set the nodump flag (owner or super-user only)

sappnd, sappend

set the system append-only flag (super-user only)

schg, schange, simmutable

set the system immutable flag (super-user only)

sunlnk, sunlink

set the system undeletable flag (super-user only)

uappnd, uappend

set the user append-only flag (owner or super-user only)

uchg, uchange, uimmutable

set the user immutable flag (owner or super-user only)

uunlnk, uunlink

set the user undeletable flag (owner or super-user only)

The following explains in slightly more detail what each flag does:

  • archivedThe archived flag is not used by FreeBSD’s standard UFS filesystem, and is only relevant to legacy filesystems.
  • opaqueThe opaque flag ensures that when unionfs is used to mount another directory over the top of the flagged directory, the contents of the flagged directory will not show.
  • nodumpThe nodump flag is of particular use for people using the standard dump utility to make backups of the system. If a particular file should not be backed up by the dump utility, setting the nodump flag will ensure that it is ignored by dump. Unfortunately, an additional step must be taken to get the dump command to completely honor the nodump flag: the -h option must be used with dump. This will see to it that the flagged file is omitted from incredmental dumps, but not from full dumps. To omit the file from even full dumps, use the -h 0 option with dump.
  • sappendThe sappend flag ensures that the flagged file cannot be truncated, and cannot be written to at any point other than at the end of the file. In other words, the only changes that are allowed for that file are changes that are appended to it. This applies to all users, including the root user, without taking the system to single-user mode or reducing the securelevel to 0 or less.
  • schangeThe schange flag makes a file “system immutable,” so that nothing about the file can be altered at all, including metadata. Be very careful setting this flag; even root cannot remove this flag without either taking the system to single-user mode or reducing the securelevel to 0 or less, as with the sappend flag.
  • sunlinkThe sunlink flag prevents everyone, including the root user, from deleting (unlinking) the flagged file. This overrides any Unix filesystem permissions that otherwise might allow file deletion.
  • uappendThe uappend flag is similar to the sappend flag, but it can be set and unset by both the root user and the file’s owner without limitation.
  • uchangeThe uchange flag makes a file “user immutable”, just as the schange flag makes a file “system immutable”. As with uappend, the “user” version of the “change” flag can be set or unset by both the root user and the file’s owner without limitation.
  • uunlinkThe uunlink flag is similar to the sunlink flag, but it only prevents the user account that “owns” the file (and those with lesser permissions for the file) from deleting it. The root user account will not be prohibited from deleting the file, unless the root user is the owner of the file — in which case the root user is then prevented from deleting the file.

Some use cases for FreeBSD servers are more suitable to use of file flags, and desktop systems are somewhat less than perfectly suitable to use of file flags. Because the X Window System and certain other pieces of software do not work properly at any securelevel greater than 0, it is unlikely that such systems would be run at a higher securelevel. Because at securelevel 0 and below the root user can change any file flags on the system, anyone who can achieve root level access to the system can change any file flags, thus circumventing the security value of those flags.

There are ways to work around this problem in some cases. For instance, the X Window System can be started, then the securelevel increased from 0 to 1, but if you must restart X for some reason you will then have to restart the system to get the securelevel back to 0.

Under the right circumstances, however, FreeBSD’s file flags can provide a significant improvement to security, particularly for public-facing servers. For instance, it may be appropriate in some cases to run a Webserver at securelevel 1 and use the schange flag to protect static files that do not ever need to be altered to protect against alteration by malicious security crackers. In fact, in some cases, you may not need anything but your logfiles to be mutable on a public-facing server — and there are even ways around that when logging to another system on the local network, sometimes.