The Trusted Solaris environment supports regular UNIX directories and multilevel directories (MLDs). MLDs enable a program that runs at different sensitivity labels to use a common directory and access files at the sensitivity label at which the program is currently running. An MLD contains only single-level directories (SLDs), and each SLD stores files at the sensitivity label of the SLD. Within one MLD, several files with the same name can be stored in different SLDs. Each instance of the same file contains data appropriate to the sensitivity label of the SLD where it is stored. This is called polyinstantiation of directories and files.
The tmp directory and all home directories are automatically MLDs at ADMIN_LOW when set up for users in the User Manager by the system administrator. Additionally, mkdir(1) has an option for creating an MLD. Figure 7-1 shows the directory structure of Zelda's home directory where the MLD is ADMIN_LOW with three SLDs at Top Secret, Secret, and Confidential.
An MLD cannot contain another MLD.
An SLD cannot contain an MLD or an SLD.
An SLD can contain regular UNIX directories and all types of files.
SLDs are created as needed during pathname lookup, and by the getsldname(2) and fgetsldname(2) system calls. The SLD sensitivity label is always a valid sensitivity label for the system.
An application running at Secret dominates the ADMIN_LOW directory path /home/export/.MLD.zelda, dominates the SLDs at Secret and Confidential, but does not dominate the SLD at Top Secret. Without privilege and with discretionary access, a process running at Secret has the following access:
Read, Write, and Create access to the Secret SLD.
The ability to read down to the Confidential SLD using the fully adorned name /export/home/.MLD.zelda/.SLD.1. See "Adorned Names" and "Using Path Names with Adornments".
The ability to write up to the Top Secret SLD using the fully adorned name /export/home/.MLD.zelda/.SLD.3 if the process clearance dominates the Top Secret SLD. See "Adorned Names" and "Using Path Names with Adornments".
A process running at Confidential would have access to the following files assuming the directory structure in Figure 7-1.
.login conf_proj |
A process running at Secret would have access to the following files assuming the directory structure in Figure 7-1.
.login secret_proj1 secret_proj2 |
A process running at Top Secret would have access to the following files assuming the directory structure in Figure 7-1.
.login ts_proj |
Many applications create files in the /tmp directory. If /tmp is a regular UNIX directory at some sensitivity label, unprivileged processes running at other sensitivity labels cannot create files in /tmp. The Trusted Solaris environment makes /tmp an MLD so applications can create files in the SLD that corresponds to the sensitivity label of the process.
Symbolic links can be used in combination with MLDs. For example, a symbolic link whose target path name is in an MLD points to a different target file at each sensitivity label. Symbolic links in an SLD can point to a target path name in a regular directory to have a path name in an MLD refer to the same file when referenced at different sensitivity labels.
When a process refers to an MLD in a pathname, the system transparently extends the reference to include the SLD that corresponds to the process sensitivity label. This operation is called pathname translation. If a process running at Confidential references /export/home/zelda, it accesses the SLD in /export/home/zelda at Confidential. Because pathname translation is transparent, the process does not explicitly reference the SLD.
All MLDs have an adornment. The adornment is .MLD. unless it was changed by the system administrator. The adornment lets a process refer directly to the MLD rather than transparently to the SLD that has the same sensitivity label as the process. A process would use the ls(1) command to reference the adorned name to do the following.
List the SLDs within an MLD. Without the adornment, the contents of the SLD with the same he sensitivity label as the process are listed instead.
% ls /.MLD.tmp |
Refer explicitly to an SLD by using the adorned MLD name.
% ls /.MLD.tmp/.SLD.3 |
Mandatory and discretionary access is required to get information on an MLD or SLD, and to access objects within an SLD with the fully adorned path name.
When considering the mandatory and discretionary access rules presented in Chapter 1, Introduction to the API and Security Policy, the SLD is a component in the path name leading to the final file system object. The calling process needs mandatory and discretionary search access to the SLD and the appropriate access to the final object. Privileges may be required if access is denied.
To get the SLD name for a specified sensitivity label within an MLD, the calling process needs the following privileges in the following situations:
The calling process needs the file_upgrade_sl privilege in its effective set if the process sensitivity label is strictly dominated by the SLD sensitivity label.
The calling process needs the file_downgrade_sl privilege in its effective set if the SLD sensitivity label dominates the process's sensitivity label.
To use the programming interfaces described in this chapter, you need the following header file.
#include <tsol/mld.h> |
The examples in this chapter compile with the following library:
-ltsol |
The bslabel_t type definition represents the sensitivity label portion of a binary CMW label. The getsldname(2) system call accepts a variable of type bslabel_t.
The stat structure contains information on a specified MLD, SLD, or symbolic link. The structure is returned by the mldstat(3TSOL) and mldlstat(3TSOL) system calls.
Type |
Field |
Description |
Default |
---|---|---|---|
mode_t |
st_mode |
File type and permissions. |
0 |
nlink_t |
st_nlink |
Number of hard links. |
1 |
uid_t |
st_uid |
User ID of owner. |
0 |
gid_t |
st_gid |
Group Id of owner. |
0 |
time_t |
st_atime |
Last access time in seconds. |
Current time |
time_t |
st_mtime |
Last modify time in seconds. |
Current time |
time_t |
st_ctime |
Last inode change time in seconds. |
Current time |
The following programming interfaces are available for getting information on MLDs and SLDs.
System calls are available to get the SLD name, get MLD adornment, and get SLD or MLD file attribute information.
The getsldname(2) system call gets the SLD name for path_name at the specified slabel. Refer to the getsldname(2) man page. The fgetsldname(2) system call uses a file descriptor.
int getsldname(const char *path_name, const bslabel_t *slabel, char *name_buf, const int len); int fgetsldname(const int fd, const bslabel_t *slabel_p, char *name_buf, const int len);
The getmldadorn(2) system call gets the fully adorned path name for path_name. The fgetmldadorn(2) system call uses a file descriptor. Refer to the getmldadorn(2) man page.
int getmldadorn(const char *path_name, char *adorn_buf[MLD_ADORN_MAX]); int fgetmldadorn(const int fd, char adorn_buf[MLD_ADORN_MAX]);
The mldstat(3TSOL) system call returns file attribute information on the MLD specified by path_name. The mldlstat(3TSOL) system call returns information on the MLD symbolic link.
int mldstat(const char *path_name, struct stat *stat_buf); int mldlstat(const char *path_name, struct stat *stat_buf);
These system calls are described in "Get and Set File System Security Attribute Flags" in Chapter 2, Getting Started. Also, refer to the getfattrflag(2) man page.
int mldgetfattrflag(const char *path, secflgs_t *flags); int mldsetfattrflag(const char * path, secflgs_t which, secflgs_t flags);
Library routines are available to get the pathname of the current working directory and display a pathname with adornments.
This routine gets the fully adorned path name for the current working directory. Refer to the mldgetcwd(3TSOL) man page.
char* mldgetcwd(char *buf, size_t size);
This routine gets the adorned name for the MLD specified in path_name. Refer to the adornfc(3TSOL) man page.
int adornfc(const char *path_name, char *adorned_name);
These routines take the path name supplied in path_name, expand all symbolic links, resolve dot references to the current directory and dot-dot references to the parent directory, remove extra slash characters, add the correct MLD and SLD adornments, and store the final result in resolved_path. The result is for the SLD at which the process is running, or at the specified SLD. Refer to the mldrealpath(3TSOL) man page.
char* mldrealpath(const char *path_name, char *resolved_path); char *mldrealpathl(const char *path_name, char *resolved_path, const bslabel_t *senslabel);
The following code queries the MLD adornment with the getmldadorn(2) system call and queries the SLD name for the Top Secret SLD with the getsldname(2) system call. In this example, the Top Secret SLD does not already exist, so the call to getsldname(2) will create it.
The process is running at Confidential with a clearance of Top Secret. The process needs the sys_trans_label privilege to translate the Top Secret label, the file_upgrade_sl privilege to create the Top Secret SLD, and the file_mac_search and file_mac_read privileges to access the Top Secret SLD information.
#include <tsol/label.h> main() { int retval, error, length; bslabel_t label; char *buffer[1025], *buf[1025], *string = "TOP SECRET"; char *file = "/export/home/zelda"; retval = getmldadorn(file, buffer); printf("MLD adornment = %s\n", buffer); /* Turn sys_trans_label on in the effective set */ retval = stobsl(string, &label, NEW_LABEL, &error); /* Turn sys_trans_label off */ length = sizeof(buf); /* Turn file_upgrade_sl, file_mac_search, and file_mac_read on */ retval = getsldname(file, &label, buf, length); /* Turn file_upgrade_sl, file_mac_search, and file_mac_read off*/ printf("SLD name = %s\n", buf); }
The printf(1) statements print the following:
MLD adornment = .MLD. SLD name = .SLD.3 |
This example queries the current working directory (MLD plus current SLD) with the mldgetcwd(3TSOL) routine, gets the adorned name for the MLD with the adornfc(1) routine, and finds the real path with the mldrealpath(1) routine by removing the extra slash in the path name stored in resolvefile. The process is running at Confidential.
#include <tsol/label.h> #include <sys/types.h> main() { int retval; char *buffer[1025]; char *file = "/export/home/zelda"; char *string2, *name[1025], *string3, *resolved[1025]; size_t size; /* Character string with errors to be resolved */ char *resolvefile = "./"; size = sizeof(buffer); string2 = (char *)mldgetcwd(buffer, size); printf("Current working directory = %s\n", buffer); retval = adornfc(file, name); printf("Adorned name = %s\n", name); string3 = (char *)mldrealpath(resolvefile, resolved); printf("Real path = %s\n", resolved); }
The printf statements print the following:
If the SLD name is included in the file parameter to the adornfc(1) routine, the adorned name is returned with the SLD appended in the form /export/home/zelda/.MLD..SLD.1.
Current working directory = /export/home/.MLD.zelda/.SLD.2 Adorned name = /export/home/.MLD.zelda Real path = /export/home/.MLD.zelda/.SLD.2 |
This example gets attribute information for the /export/home/zelda MLD. In the printf(1) statements, the stat(2) system call macros test whether the MLD is a directory or regular file, and the time returned in seconds is converted to a human-readable time with the ctime(3C) routine.
#include <tsol/label.h> #include <sys/stat.h> main() { int retval; struct stat statbuf; char *file = "/export/home/zelda"; retval = mldstat(file, &statbuf); printf("Is file system object a directory? = %d\n", S_ISDIR(statbuf.st_mode)); printf("Is file system object a regular file? = %d\n", S_ISREG(statbuf.st_mode)); printf("Number of links = %d\n", statbuf.st_nlink); printf("Owner's user ID = %d\n", statbuf.st_uid); printf("Owner's group Id = %d\n", statbuf.st_gid); printf("Last access time = %s\n", ctime(&statbuf.st_atime)); printf("Last modify time = %s\n", ctime(&statbuf.st_mtime)); printf("Last status change = %s\n", ctime(&statbuf.st_ctime)); }
The printf statements print the following:
Is file system object a directory? = 1 Is file system object a regular file? = 0 Number of links = 6 Owner's user ID = 29378 Owner's group Id = 10 Last access time = Wed May 28 10:58:25 1999 Last modify time = Wed May 28 09:39:18 1999 Last status change = Wed May 28 09:39:18 1999 |
UNIX system calls that accept a path name such as open(2) and creat(2) go to the SLD at the same sensitivity label as the process unless the fully adorned path name is passed instead of a regular path name. The fully adorned path name includes the MLD adornment and the SLD directory name as shown in the code example. Note that a process cannot create files or directories in either an MLD or SLD with the mkdir(1) system call.
The mandatory access and discretionary access controls described in "Security Policy" apply.
In this example, the process is running at Confidential with a clearance of Top Secret. The Confidential process needs the file_mac_search privilege in its effective set to access the SLD at Top Secret. Because the file is opened for writing and a write-up is allowed by the security policy, no other privileges are needed assuming the operation passes all discretionary access checks.
#include <tsol/label.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> main() { int filedes; /* Open a file in the SLD at which the process is running */ filedes = open("/export/home/zelda/afile", O_WRONLY); printf("File descriptor for regular path = %d\n", filedes); /* Open a file in the Top Secret SLD */ /* Turn file_mac_search on in the effective set */ filedes = open("/export/home/.MLD.zelda/.SLD.3/afile", O_WRONLY); /* Turn file_mac_search off */ printf("File descriptor for adorned path = %d\n", filedes); }
The printf statements print the following.
File descriptor for regular path = 3 File descriptor for adorned path = 4 |
In this example, the process is running at Confidential with a clearance of Top Secret. The Confidential process needs the file_mac_search privilege in its effective set to access the SLD at Top Secret. If afile does not already exist in the Top Secret SLD, the process needs the file_mac_write privilege because the process sensitivity label does not equal the SLD sensitivity label. If afile already exists, the file_mac_write privilege is not needed.
#include <tsol/label.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> main() { int filedes; /* Create a file in the SLD at which the process is running */ filedes = creat("/export/home/zelda/afile", 660); printf("File descriptor for regular path = %d\n", filedes); /* Create a file in the Top Secret SLD */ /* Turn file_mac_search on in the effective set */ filedes = creat("/export/home/.MLD.zelda/.SLD.3/afile", 660); /* Turn file_mac_search off */ printf("File descriptor for adorned path = %d\n", filedes); }
The printf statements print the following.
File descriptor for regular path = 3 File descriptor for adorned path = 4 |