z/OS UNIX System Services File Security
Introduction
In my previous article “UNIX File System Security”, I discussed file system security, concentrating on security controls available at the file system aggregate level. In this article, I discuss file security. That is, security controls around individual file and directory access and logging. Because it gets tedious to constantly type (and to read) “file and directory” security, I will shorten this to “file” security throughout this article, unless I need to specifically discuss directories (and I will). If it makes you feel better, however, a directory is a just a special type of file that contains the names of the objects within it along with a reference to their location (called an inode).
Files have various pieces of meta-data, including the security attributes, that are considered part of the file, and are stored with it in the file system. We will now discuss the security attributes.
Ownership and permission bits
UNIX file access control is nothing like protecting resources with RACF profiles. But you knew that. Basic access is controlled by a set of non-hierarchical permissions bits for read, write, and execute access. Another new concept for RACF admins is that a file has a group owner along with a user owner. There are three sets of rwx permission bits associated with a file: those for the user owner, those for the group owner, and those for everybody else.
The user owner bits are fairly straightforward. They apply only to the owner of the file. If the owner does not have the requested access via these bits, then the owner does not have access, regardless of the other two bit sets.
The group bits are similarly applied to any (non-owner) user connected to that group. It need not be their default group or current connect group (assuming you have list-of-groups processing active in RACF, and you do). If you are not the file owner, but are connected to the owning group, and the group bits do not allow the requested access, then you do not have access, regardless of the other bits.
The “everyone else” bits are often referred to as the “other” bits, or “world” bits, and you can think of them as analogous to the universal access (UACC) of a RACF profile. If you are not the file owner, and not connected to the owning group, then these bits determine your access. By default, the other bits are honored for users with the RESTRICTED attribute in RACF, and this is probably not what you want. If you want the other bits to be treated like UACC is for RESTRICTED users, then define the RESTRICTED.FILESYS.ACCESS profile in the UNIXPRIV class.
The owning user and owning group are numeric values that identify a user or group to a UNIX operating system. They are assigned to users and groups using the OMVS(UID(n)) and OMVS(GID(n)) keywords of the RACF ADDUSER/ALTUSER and ADDGROUP/ALTGROUP commands, respectively. UNIX commands will accept and display RACF user IDs in these contexts, with the kernel and the security product automatically performing the mapping for your convenience.
I should mention that a UNIX superuser gets any access to any file (almost) regardless of the permission bits. The UNIX superuser, and a description of its super-powers, is an entire discussion in and of itself. Am I hearing a topic for another article? For now, we can define a superuser as one with the special UID value of 0. As a z/OS-unique extension to the definition, a TRUSTED or PRIVILEGED started task is also treated as a superuser.
These concepts are determined by open standards, and z/OS UNIX adheres to them. However, the standard can be expanded upon, as demonstrated immediately above with the definition of superuser. We will see more extensions below.
Permission bit initialization and the umask
So where do the initial bit settings come from, anyway? The answer is, as always, “it depends”. There is an API called open() that is used to create a file, and its parameters include the initial permission bits. So, you might see anything ranging from all bits being on, as specified by the mkdir command, to only the user owner bits being on, as specified by the oedit command. In general, the z/OS-specific ways to create a file tend to be more restrictive than the POSIX standard ways, because security is in our DNA on z.
The UNIX standard does provide a defense against applications creating overly permissive defaults. This is the umask command. It specifies the bits that should be masked off when a file is created. For example, the following commands both result in the group and other write bits being masked off for new objects:
umask rwxr-xr-x
umask 022
When using the symbolic notation, you specify the permissions that are allowed to be set. When using the octal notation, you specify the bits that are not allowed to be set. It is important to understand that the umask doesn’t specify initial settings; it just indicates which ones are going to be nullified. There is no administrative mechanism by which to define starting permissions for file system objects.
Octal notation is one of those things you just have to get used to. But if you think of the permissions in terms of a binary number, where execute bit is in the ones position, the write bit is in the twos position, and the read bit is in the fours position, and you add the values together for the bits that are on, you get the octal number for that bit combination. Settings of r-x mean 4(r)+0(w)+1(x)=5. Octal values of 755 (rwxr-xr-x), 750 (rwxr-x---), and 700 (rwx------) are common patterns.
If you enter the umask command without any operands, it will display the current setting in octal notation (unless you specify the -S option). You might be curious why four digits are displayed rather than 3. Save your curiosity for the discussion of the file mode a little bit later in this article.
In practice, an administrator will put a umask command into the /etc/profile script. This gets run for every user who enters the shell. Further, each user can have a file named ‘.profile’ in their home directory, and the shell runs it after running /etc/profile. For you z/VM enthusiasts, I like to draw an analogy with SYSPROF EXEC on the system S disk, and PROFILE EXEC on a user’s A-disk.
Note that not all UNIX applications are run within a shell environment, and thus aren’t affected by a umask command either issued by the shell itself, or by /etc/profile running in the shell. Use the UMASK statement in SYS1.PARMLIB(BPXPRMxx) to set a value for such applications.
Finally, it’s important to understand that the umask is completely at the discretion of the user. I can put a ‘umask 0’ command in my .profile to immediately undermine the umask command in /etc/profile, and there’s nothing you can do about it. If you want to have a policy of, for example, no other bits being on, or no other write bits being on, then you will have to look for them and warn your users accordingly. In the previous article “UNIX File System Security”, I discussed the find command and the irrhfsu download as ways to query your file security attributes.
Changing ownership and permission bits
A file’s user and group ownership can be changed with the chown command. The chgrp command can change the group owner. For example:
chown bruce thisfile
chown bruce:racfgrp thisfile
chown :racfgrp thisfile
chgrp racfgrp thisfile
A file’s permission bits are modified using the chmod command. Chmod accepts several formats in which permission bits can be expressed (symbolic, relative, octal), but for simplicity, we’ll specify every bit symbolically. For example, to specify that the owner has all permissions, the group has read and execute, and nobody else has any permission:
chmod rwxr-x--- thisfile
Displaying security attributes of a file
The shell ‘ls’ command is used to display the names of files within a directory. The long form of the output shows the security attributes.
ls -l /u/bruce
-rw-r--r-- 1 BRUCE SYS1 0 Jun 8 12:59 file1
-rw-r--r-- 2 BRUCE SYS1 9 Jun 8 13:02 file2
drwxr-xr-x 2 BRUCE SYS1 8192 Jun 8 12:56 sdir1
drwxr-xr-x 2 BRUCE SYS1 8192 Jun 8 12:56 sdir2
The very first character indicates the file type. A regular file is indicated by a dash, and a directory is indicated by a “d”. Other types are possible.
Then the permission bits are displayed. The remaining columns display the link count, the user owner, the group owner, the file size, the date and time of last modification, and, finally, the file name.
Access control lists
The three sets of permission bits do not always provide enough granularity of control in the z/OS environment, where a diverse array of applications, workloads, and job roles coexist. So, access control lists (acls) can be applied to individual files, providing essentially the same level of granularity available when using RACF profiles to protect traditional z/OS resources. In fact, as with RACF profiles, acls may be created before their use is activated, which is done by activating the FSSEC class. Acls are an extension to the POSIX standard, and the implementation incorporates the standard permission bits when determining a user’s access.
The access algorithm is completely documented in Appendix E of the z/OS RACF Security Administrator’s Guide, but in a nutshell:
1. The user owner bits are applied to the file owner, exactly as described above, and the acl is not considered
2. When the user is not the owner, user acl entries are searched for a match on the user’s UID. If an entry is found, it determines access, with no continuation
3. The user’s groups are compared against the group bits and all group acl entries until a single entry grants the requested access.
4. If there was no group match, the other bits determine access
In the previous article “UNIX File System Security”, I described FSACCESS protection as a control point on a directory to prevent access to its contents. This can only be applied at a mount point. However, you might have a subdirectory within a given aggregate on which you would like to apply similar protection. This can be accomplished using what I like to call a ‘gateway acl’. You create it on a directory, permitting only the users and groups you wish to allow into the directory by granting them execute access. Execute access on a directory is often called ‘search’ access. It allows you to pass through the directory while working your way down a path name. By blocking search access, you make every object under that directory inaccessible, regardless of their ownership, permissions bits, or acls. Make sure the ‘other’ bits do not grant any undesirable access. This technique works like FSACCESS protection except:
· You must use the shell ‘setfacl’ command to establish and maintain the protection.
· It does not prevent superuser access
For example, assume I have a directory with none of the execute permissions bits set. To put a gateway acl on my projectX directory, I could issue:
setfacl -m g:racfgrp:--x /u/bruce/projectX
Now, only members of the RACFGRP group can get into the projectX directory. Once in, the standard rules apply to objects within the directory. If I want stricter security on individual objects, I can apply additional acls as required.
The setfacl command does not have a recursive option like several of the other security-related shell commands do. So, when you want to apply acls to all objects within a directory, or down an entire subtree, you use the various shell techniques at your disposal. For example, you use shell substitution to apply a setfacl command to all objects returned by the find command. In this example, find returns all the objects under /u/ibmuser:
setfacl -m u:tsousr1:r-x $(find /u/ibmuser)
Now you have the acl consistently applied across a set of objects in a subtree, but you might also want this protection applied to objects that get created in the future. Acls support inheritance through the use of ‘model’ acls that you establish on a directory. There are separate model acls for files and directories. When a file or subdirectory gets created, the contents of the appropriate model acl are set on the object as its access acl.
After having established the acls on the current objects, and having established model acls to apply to future objects, you must take care to keep the protection consistent going forward. For example, if you want to change a user’s or group’s permissions, or add or delete a user or group entry, you should apply the change recursively to all acls, including model acls, using shell techniques.
When an acl exists for a file, the output of ls -l will contain a plus sign after the permission bits to indicate the existence of an acl. The getfacl command can then be used to display it.
#ls -l /u/bruce/projectX
drwxr-xr-x+ 2 BRUCE SYS1 8192 Jun 9 10:48 projectX
#getfacl /u/bruce/project
#file: projectX/
#owner: BRUCE
#group: SYS1
user::rwx
group::r-x
other::r-x
group:RACFGRP:--x
As you can see, getfacl also displays the owners and permission bits to give you a fuller picture of the protection in place. You could even get in the habit of starting with getfacl instead of waiting to be cued by the plus sign displayed by ls -l.
The getfacl command uses the default of the (unspecified) -a option, to display only the “access acl” (i.e. the one actually controlling access to the file). You would need to explicitly specify -d or -f to see directory model acl and file model acl entries for a directory. Or, you might simply get into the habit of issuing:
getfacl -adf /u/bruce/projectX
to see all possible types.
Logging of access attempts
UNIX file access can be logged in a conceptually similar manner to RACF-protected resources, although once again, a shell command (chaudit) is used to establish the settings. Audit bits are another extension on top of the UNIX standard.
RACF has several UNIX-related classes that control logging. These are described in the Auditor’s Guide. DIRACC covers directory access, DIRSRCH covers directory searches, and FSOBJ covers file access. All RACF classes start in the LOGOPTIONS "DEFAULT" CLASSES list as reported by SETROPTS LIST. The definition of “default” means to honor the settings at the profile level, which the RACF RDEFINE and ADDSD commands initialize to log all failed access. This is why you get ICH408I violation messages and an SMF ‘access’ failure record automatically for RACF-protected resources.
In a similar manner, UNIX file creation defaults the audit bits to log failed accesses. Thus, you automatically get ICH408I messages and an SMF Type 80 failure record (Event Type x’1C’ for directory searches, x’1D’ for directory access, and x’1E’ for file access).
Use the chaudit command to change the audit bits for a file. Let’s say you have a sensitive file for which you want to log successful reads and writes.
chaudit rw+s file1
The -W option of the ls command displays the audit bits:
#ls -W /u/bruce
-rw-r--r--+ fff--- 1 BRUCE SYS1 0 Jun 8 12:59 file1
-rw-r--r--+ aaf--- 1 BRUCE SYS1 9 Jun 8 13:02 file2
drwxr-xr-x+ fff--- 2 BRUCE SYS1 8192 Jun 8 12:56 sdir1
drwxr-xr-x+ fff--- 2 BRUCE SYS1 8192 Jun 8 12:56 sdir2
In the second column, each character position corresponds to a permission bit (rwx). The “f” indicates that type of access is logged for failures only. You can see these default settings for r, w, and x failures that I described above. However, for file2, we added successes, so “a” indicates “all” (both failures and successes).
“What are the three dashes after the audit settings?”, you ask. Excellent question! A RACF profile has two sets of audit options: one that the profile owner can set using the AUDIT keyword of RALTER, and another that only a user with the RACF AUDITOR attribute can set using the GLOBALAUDIT keyword. The auditor bits can be used to prevent a profile owner from messing with your logging policy.
This second set of bits are the auditor options for a UNIX file. As with a RACF profile, they are initialized to not specify any logging. To set those, an auditor uses the -a option:
chaudit -a rw+s file1
#ls -W /u/bruce/file1
-rw-r--r--+ fffss- 1 BRUCE SYS1 0 Jun 8 12:59 file1
Now you can see that “s” indicates success logging only in the auditor bits. As with a RACF profile, the owner and auditor bits are ORed to determine if logging should occur.
Logging of security attribute changes
You likely are using SETROPTS AUDIT(class) to log changes made to RACF profiles in class. So, would you want the analogous thing to happen for UNIX file security changes? If the answer is “yes”, then you should know that this is not happening by default. FSSEC is the class used to log security changes, and, though it also starts out in the LOGOPTIONS "DEFAULT" CLASSES list, there are no ‘administration’ audit bits in the file to which to defer. Those only apply to file access, not file administration.
To start logging security updates, issue:
SETROPTS LOGOPTIONS(ALWAYS(FSSEC))
This results in SMF 80 records with various Event Codes, each of which corresponds to a different shell command/security setting. For the commands we have seen thus far, there is a separate Event Code for chaudit (x’1F), chmod (x’21’), chown (x’22’), setfacl (x’4B), and deletion of an acl (x’4C’, accomplished using the -D option of setfacl). Further, the setfacl command results in a separate SMF record for each modified entry, containing both the old and new permissions where appropriate.
The file mode
The permission bits are contained in a 4-byte construct known as the file mode. But the mode contains three additional bits that are also changed using the chmod command. In the previous article “UNIX File System Security”, I described two of them: the set-user-ID bit and the set-group-ID bit. These cause an executable file to run under the identity of the file owner and/or group. What I did not mention last time is that the set-group-ID bit has an additional meaning when set on a directory. When the RACF profile named FILE.GROUPOWNER.SETGID exists in the UNIXPRIV class, then the set-group-ID bit for a directory determines how the group owner is initialized for new objects created within the directory:
• If the set-gid bit is on, then the owning GID is set to that of the directory.
• If the set-gid bit is off, then the owning GID is set to the effective GID of the process.
The remaining bit is called the “sticky bit”. For a file, the sticky bit causes a search for the program in the user's STEPLIB, the link pack area, or link list concatenation. For a directory, the sticky bit allows files in a directory or subdirectories to be deleted or renamed only by the owner of the file, by the owner of the directory, or by a superuser (but not by a user with write access to the directory).
To turn on these bits:
chmod u+s mypgm
chmod g+s mypgn
chmod +t mypgm
ls -l mypgm
-rwsrwS--T 1 IBMUSER SYS1 0 Jun 9 16:28 mypgm
This output needs some unpacking. The ls command has overloaded the execute bit positions in its output. The owner execute bit is used to convey the set-user-ID value by displaying a lowercase “s”. But that’s odd, the group execute bit is displayed as an uppercase “S”. What gives? The lowercase s means that the set-user-ID bit is on, and so is the user execute bit. The uppercase S means that the set-user-ID bit is on, but the underlying execute bit is off. The sticky bit overloads the other execute bit, and the lowercase or uppercase “t” likewise indicates the status of the underlying execute bit.
If we turn off these bits, we can confirm that the underlying execute bits are set (or not) as I described:
# chmod -t,u-s,g-s mypgm
# ls -l mypgm
-rwxrw---- 1 IBMUSER SYS1 0 Jun 9 16:28 mypgm
Now that we’ve described these additional bits, we can loop back to the discussion about umask. While umask allows me to specify 4 digits, implying I can use it to mask off set-user-ID, set-group-ID, and sticky bits with a command such as:
umask 7022
displaying the value indicates that my first digit was ignored.
# umask
0022
The documentation is silent on this matter.
Extended attributes
Another security extension to the standard are the extended attributes. The two of most importance to RACF administrators are the APF and the program-controlled bits. These apply to executable programs.
The APF bit means that the system should treat the program as if it were fetched from an Authorized Program Facility library. This allows to the program to switch into supervisor state or a system storage key.
The program bit means that the system should treat the program as if it were defined to RACF program control (the PROGRAM) class. This allows the program to be executed in an environment that needs to remain clean, such as when a daemon with access to BPX.DAEMON performs identity switches.
These bits are changed using the shell extattr command. For example, to set the APF bit on, and the program bit off:
extattr +a mypgm
extattr -p mypgm
The bits can be displayed using the -E option of ls:
# ls -E mypgm
-rwxrw---x a-s- 1 IBMUSER SYS1 0 Jun 9 16:28 mypgm
The “a” indicates that the APF bit is on, and the dash immediately after it is the program position, and that bit of off.
What are the other two bits? The “s” bit is the “_BPX_SHAREAS bit”. It’s performance related and means that the _BPX_SHAREAS environment variable should be honored. This variable controls whether the shell runs foreground processes in the same address space as the shell is running in, which saves overhead. The “s” bit is always initialized on.
The ‘shared library’ bit indicates that the program , when loaded, is put in the shared library region for system-wide sharing. When on, a lowercase “l” is displayed in the fourth position.
The authority to set these bits is controlled by RACF profiles in the FACILITY class, which are checked by UNIX itself:
- BPX.FILEATTR.APF
- BPX.FILEATTR.PROGCTL
- BPX.FILEATTR. SHARELIB
There is no profile that protects the _BPX_SHAREAS bit. However, all bits have the additional requirement that the user issuing extattr must have write access to the file or be a superuser.
There isn’t a specific Type 80 SMF record for extattr. Rather, you would log successes/failures to the FACILITY profile itself. However, this won’t contain the path name of the affected file. Fortunately, UNIX creates its own Type 92 record for extended attribute changes, and this does contain the file name.
Security labels
z/OS UNIX supports multilevel security (MLS) through the assignment of security labels (SECLABELs) to UNIX files and directories. Depending on the system-wide options in effect, SECLABELs may be assigned automatically to zFS aggregate file systems, and to objects within the file system as they are created.
The shell chlabel command can be used to assign a SECLABEL to objects that existed prior to implementing MLS. The issuer must have the RACF SPECIAL attribute. The -M option of the ls command displays the security label:
# chlabel secret99 file1
# ls -M file1
SECRET99 file1
Once a SECLABEL is assigned, it cannot be changed or deleted. When a SECLABEL exists on a file, a user attempting to access the file must have the correct authority to the security label in order to access the file.
Shell game
That’s it in a very large nutshell, folks. There are several different commands used to modify UNIX file security attributes, and several options of the ls command to view the various pieces. This can be a bit overwhelming for the traditional RACF administrator. However, I consider it well worth your while to familiarize yourself with the more commonly issued commands and shell techniques. With the standard commands in particular (ls, find, chown, chmod, umask) you will find an abundance of information on the internet, as long as you remain vigilant there could be subtle differences between the various UNIX/Linux operating systems and shells.
But if you really, really wish you could administer UNIX security using the RACF commands you know and love, then I have just the thing for you! After hearing this stated desire for over two decades, I conducted a thought experiment about what RACF commands would look like if we pretended that UNIX files were protected by RACF profiles. I then coded some REXX execs to externalize RACFish keywords and use z/OS UNIX REXX syscall support to extract and modify file security attributes. I then made these execs available on the RACF downloads site:
https://github.com/IBM/IBM-Z-zOS/tree/main/zOS-RACF/Downloads/RacfUnixCommands
I named the “commands” ORLIST, ORALTER, and OPERMIT, though you can call them whatever you wish.
A single ORLIST command can return all the attributes in one fell swoop, along with information about how the containing file system is mounted, and whether the aggregate is protected by an FSACCESS or FSEXEC profile.
A single ORALTER command can be used to change the various security attributes using existing RALTER keywords where possible, and inventing new ones, with a RACF/TSO command look and feel, where necessary.
The “PERMIT” command allows you to manage access lists using most of the same keywords and behaviors implemented by the real PERMIT command.
All commands sport a RECURSIVE keyword, which is particularly helpful with OPERMIT when managing model acls and inheritance.
ORLIST can both write its output to the display and to an output file. OPERMIT and ORLIST create a script containing the shell commands that will effect the desired changes. The script can be viewed and edited as necessary prior to running it, and the file can be saved and used as a change-record. You never have to leave the TSO command line to do any of this.
Here are some examples to whet your appetite:
oralter /u/bruce/file1 nosetuid audit(all(rw)) group(racfgrp) perms(rwxr-x---)
opermit /u/bruce id(racfdevs) access(r--) recursive
orlist /u/bruce/file1
CLASS NAME
----- ----
FSSEC /u/bruce/file1
FILE SYSTEM CONTAINER ATTRIBUTES
--------------------------------
NAME = ZOS25.ROOT.ZFS TYPE = ZFS
MOUNT POINT = /
Mount mode = READ/WRITE
Not protected by an FSEXEC class profile
FILE TYPE
----------------------
Regular file
OWNER GROUP OWNER UNIVERSAL ACCESS YOUR ACCESS
---------- ----------- ---------------- -----------
BRUCE RACFGRP --- rwx
SECLABEL
--------
SECRET99
AUDITING
--------
ALL(READ),ALL(UPDATE),FAILURES(EXECUTE)
GLOBALAUDIT
-----------
SUCCESSES(READ),SUCCESSES(UPDATE),NONE(EXECUTE)
CREATION DATE LAST REFERENCE DATE LAST STATUS CHANGE DATE
------------- ------------------- -----------------------
2021-06-08 2021-06-09 2021-06-11
EXTENDED ATTRIBUTES
-------------------
SHAREAS
FILE MODE BITS
--------------
Sticky bit is: 0
Set-uid bit is: 0
Set-gid bit is: 0
FILE PERMISSIONS
----------------
OWNER GROUP OTHER
----- ----- -----
rwx r-x --- (750 in octal notation)
ID TYPE ACCESS
-- ---- ------
RACFDEVS GROUP R--
Conclusion
We have seen the various and sundry security attributes associated with UNIX files, and have demonstrated how to change and display them using UNIX shell commands.
What are some things you can do, right now, to get a handle on your UNIX file security?
- Activate logging of UNIX security changes with SETROPTS LOGOPTIONS(ALWAYS(FSSEC)). Familiarize yourself with the SMF 80 records that get generated. They are fully supported by the SMF Unload utility!
- See if you have a system-wide umask in effect, both in /etc/profile and in BPXPRMxx. If not, implement one to mask off (at least) world write bits.
- Define the RESTRICTED.FILESYS.ACCESS profile in the UNIXPRIV class so that RESTRICTED users don’t gain file access via the ‘other’ bits.
- Use the find command or the irrhfsu download to search for occurrences of world write access and remediate them as necessary.
- Implement gateway acls on important subdirectories that are not mount points, and thus cannot exploit FSACCESS protection.
- Play with the RACF UNIX commands download as a teaching tool. Generate “RACF” commands to make changes and see what shell commands get generated (out of the box, the REXX execs just generate the script, but do not execute the commands. They will also display the generated commands on the screen.). You can use these to practice your octal notation also.
Brought to you by Bruce Wells
Bruce Wells is the RACF Product Owner, and has been a RACF design and developer on both the z/VM and z/OS versions for over 30 years.