Trusted Solaris Developer's Guide

Chapter 7 Multilevel Directories

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.

Directory Structure

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.

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.

Figure 7-1 Multilevel Directories

Graphic

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:

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

Temporary Directory

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

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.

Adorned Names

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.


% ls /.MLD.tmp

% ls /.MLD.tmp/.SLD.3

Privileged Operations

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:

Data Types, Header Files, and Libraries

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

Sensitivity Label

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.

Status

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. 

nlink_t 

st_nlink

Number of hard links. 

uid_t 

st_uid

User ID of owner. 

gid_t 

st_gid

Group Id of owner. 

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 

Programming Interface Declarations

The following programming interfaces are available for getting information on MLDs and SLDs.

System Calls

System calls are available to get the SLD name, get MLD adornment, and get SLD or MLD file attribute information.

Get SLD Name

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);

Get MLD Adornment

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]);

Get Attribute Information for SLD or MLD

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);

Get MLD Attribute Flags

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

Library routines are available to get the pathname of the current working directory and display a pathname with adornments.

Get Current Working Directory

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);

Get Adorned Name

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);

Find the Real Path 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);

Query MLD and SLD Name

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:


Note -

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

Using Path Names with Adornments

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.

Open a File

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

Create a file

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