GT.M Security Philosophy and Implementation

GT.M V5.3-003 Release

Legal Notice

December 30, 2008

Revision History
Revision 1.0December 30, 2008



                                            GT.M Group

                                            Fidelity National Information Services, Inc.

                                            2 West Liberty Boulevard, Suite 300

                                            Malvern, PA 19355

                                            United States of America

                                        



                                            GT.M Support: +1 (610) 578-4226

                                            Switchboard: +1 (610) 296-8877

                                            Fax: +1 (484) 595-5101

                                            Website: http://fis-gtm.com

                                            Email: gtmsupport@fnis.com

                                        

Table of Contents

Conventions
Philosophy
Normal User and Group Id Rule
Exceptions
Shared Memory Exception for BG
gtmsecshr Exception
Recommendations
Appendix: gtmsecshr commands

Return to top

Conventions

Except where otherwise noted, UNIX refers to all supported POSIX platforms: AIX, GNU/Linux, HP-UX, Solaris and Tru64 UNIX.

Return to top

Philosophy

The general GT.M philosophy is to use the security of the underlying operating system, and to neither subvert it nor extend it. The purpose of this document is to discuss the implications of, exceptions to, and limitations of this philosophy (the “security model”). This document reflects GT.M as of V5.3-003.

[Note]

GT.M is not intended to operate robustly on a machine that is potentially subject to direct attack, such as a firewall, or a machine operating in a “DMZ.”

Return to top

Normal User and Group Id Rule

GT.M processes run with normal UNIX user and group id. GT.M has no database daemon that needs to run with elevated privileges. Process code written in M will be able to read a database file if and only if the process has read permission for that database file, and to update that database file if and only if the process has read/write permission for that database file. [1]

Return to top

Exceptions

Exceptions to the Normal User and Group Id rule exist for:

  • Shared Memory when the Buffered Global (BG) access method is used, and

  • gtmsecshr

Shared Memory Exception for BG

With the BG access method, each open database file has a shared memory segment associated with it. This shared memory contains a pool of disk blocks (the global buffers) as well as associated control structures (for example, for concurrency control). Even a process that has read-only permission to the database file requires read-write access to the associated shared memory in order to use the control structures. It is therefore possible for a cached disk block in shared memory to be modified by one process and for the actual write of that dirty block to disk to be performed by another. Thus, a “rogue” process with read-only access to the database file but read-write access to shared memory can modify the cached copy of a disk block and effect a permanent change to the database when that block is written to disk by another process that has read-write access to the database file.

Comments on the Shared Memory Exception for BG:

  • This only applies if a mumps process contains non-M code. If a mumps processes has only M code, the GT.M run-time environment will not allow a process to modify a database for which it lacks write permission.

  • This only applies if a database file has mixed read-only and read-write access – that is, some mumps processes have read-only access and others have read-write access. If all processes have read-only access, although the database may appear to be temporarily modified when copies of blocks in shared memory are modified, the database file on disk cannot be permanently modified because no process will have the required permission to flush dirty blocks to disk.

  • Where processes that contain C code and have read-only database access must co-exist with processes that have read-write access, GT.M will only “keep honest processes honest.” [See below for recommendations where read-only access is required by processes that cannot be considered trustworthy.]

gtmsecshr Exception

Processes with normal user and group ids do not have adequate permissions to effect necessary GT.M interprocess communication and cleanup after abnormal process termination. A process called gtmsecshr runs as root in order to effect the following functionality:

  • Interprocess communication, including sending SIGALARM and SIGCONT between processes where normal UNIX permissions do not permit such signals to be sent.

  • Cleanup after processes that terminate abnormally, including removing semaphores, shared memory segments, and flushing database file headers (but not database blocks) from shared memory segments to disk.

Whenever a GT.M process lacks adequate permissions to effect any of the above operations, it automatically invokes gtmsecshr if it is not already running. A complete list of gtmsecshr functionality appears in the appendix.

In order to run as root, and to be invoked by a process that has normal user and group ids, the invocation chain for gtmsecshr requires an executable image that is owned by root and which has the setuid bit turned on in its file permissions.

Once started and running, gtmsecshr records information in a log file gtm_secshr_log (in a directory specified by $gtm_log), creating it if it does not exist. $gtm_log is inherited from the environment of the GT.M process (mumps, mupip or dse) that first invokes the gtmsecshr process. If the environment variable $gtm_log is undefined, if its value is longer than GT.M can handle, or if it is defined to a value that is not an absolute pathname (starting with a /), $gtm_log is assumed to be the directory /tmp (AIX, GNU/Linux, Tru64 UNIX) or /var/tmp (HP-UX, Solaris). Communication between GT.M processes and gtmsecshr uses socket files in $gtm_tmp, which is also inherited from the GT.M process that first invokes gtmsecshr. If the environment variable $gtm_tmp is undefined, if its value is longer than GT.M can handle, or if it is defined to a value that is not an absolute pathname (starting with a /), $gtm_tmp is assumed to be the directory /tmp (AIX, GNU/Linux, Tru64 UNIX) or /var/tmpemphasis> (HP-UX, Solaris).

The gtmsecshr process receives messages via a socket file owned by root with a name of the form gtm_secshrnnnnnnnn, the nnnnnnnn being replaced by the hexadecimal ftok value of the gtmsecshr executable file. This value is reported by the GT.M ftok utility on the gtmsecshr file, for example, $gtm_dist/ftok $gtm_dist/gtmsecshr

GT.M processes receive responses from gtmsecshr via socket files owned by the userid of the process with names of the form gtm_secshrnnnnnnnn, where nnnnnnnn is a hexadecimal version of the client's process id, padded with leading zeroes. When a client process terminates abnormally, or is killed before it cleans up its socket file, it is possible for a subsequent client with the same process id but a different userid to be unable to delete the leftover socket file. In this case, it tries to send a message to gtmsecshr using a slightly modified client socket file of the form gtm_secshrnnnnnnnnx where x starts with“a” whose corresponding socket file does not already exist or is removable by the current client process (if all suffixes “a” through “z” are unavailable, the client process errors out with a “Too many leftover client socket files” message). gtmsecshr recognizes this special modified socket file name, and as part of servicing the client's request deletes the gtm_secshrnnnnnnnn socket file and all gtm_secshrnnnnnnnnx files that exist. The client process expects this file removal and creates a new gtm_secshrnnnnnnnn file for subsequent communications with gtmsecshr.

  • When there is no gtmsecshr process running, by starting one up with incorrect values of $gtm_log and $gtm_tmp, a gtmsecshr process can be made to create a file called gtm_secshr_log in any directory. Having incorrect values can also interfere with normal GT.M operations until the incorrect gtmsecshr process times out and terminates, because GT.M processes and gtmsecshr will be unable to communicate with one another.

  • gtmsecshr can be made to delete client socket files by a rogue process. If a socket file is deleted under a running GT.M process, gtmsecshr will be unable to reply to the process. It will timeout, create another and proceed. Thus, while GT.M performance of a single process may temporarily be slowed, system operation will not be disrupted.

Return to top

Recommendations

Based on the security model, the following are recommended best practices for securing GT.M:

  1. Secure the machine on which GT.M operates behind layers of defenses that permit only legitimate accesses.

  2. Restrict access to a system on which GT.M runs to those who legitimately need it.

  3. If not all users who have access to a system require the ability to run GT.M, limit access to GT.M to a group to which all users who need access belong, and remove world access to GT.M. If such a group is called gtmusers, and GT.M was initially installed with world access, the following command executed as root will accomplish this restriction: chgrp -R gtmusers $gtm_dist ; chmod -R o-rwx $gtm_dist

  4. Ensure that database file ownership (user and group), UNIX user and group ids, and permissions at the UNIX level match the intended access. If finer grained access controls than those provided by user and group id and permissions are needed, consider using Access Control Lists (ACLs) where they are available.

  5. By default, since any user may need to switch journal files,[2] GT.M journal files have world access permissions. To restrict access to journal files, locate them in directories whose user and group ids and permissions provide the correct level of access, and consider using ACLs.

  6. The Mapped Memory (MM) access method does not use a shared memory segment for a buffer pool for database blocks – shared memory is used only for control structures. Therefore, consider using MM if there are processes that are are not considered trustworthy but which need read-only access to database file [3]

  7. If MM cannot be used, and processes that are not considered trustworthy need read-only access to database files, run those processes on a secondary instance specifically set up for that purpose.

  8. If a database file does not change during normal operation (for example, it contains configuration parameters), make its permissions read only for everyone. On rare occasions when they need to be changed, shut down the application to get stand-along access, temporarily make it read-write, make the changes, and then make it read-only once more.

  9. If processes that startup gtmsecshr cannot be trusted to have the correct values of $gtm_log & $gtm_tmp, replace gtmsecshr with a root-owned setuid wrapper that sets the values and then calls the distributed gtmsecshr executable (which should be protected so that it is impossible for any non-root process to execute it directly)[4]

  10. Consider implementing layered security software if it exists for your platform, for example, SELinux, Trusted Solaris, Trusted AIX.

Return to top

Appendix: gtmsecshr commands

Commands

Action

Comments

WAKE_MESSAGE

Sends SIGALRM to specified process.

Used to inform receiving process that a resource (such as a critical section) it awaits has become available.

CONTINUE_PROCESS

Sends SIGCONT to specified process.

Used to awake a process that has been suspended while holding a resource.[a]

REMOVE_SEM

Remove a specified POSIX semaphore.

Used to remove an abandoned semaphore (for example, if the last attached process terminated abnormally).

REMOVE_SHMMEM

Remove a specified shared memory segment.

Used to remove an abandoned shared memory segment.  Before removing the segment, gtmsecshr checks that there are no processes attached to it.

REMOVE_FILE

Remove a specified file.

Used to remove an abandoned socket file (for example, as a result of abnormal process termination) used for interprocess communication on platforms that do not support memory semaphores (msems); unused on other platforms. Before removing, gtmsecshr verifies that the file is a socket file, in directory $gtm_tmp, and its name matches GT.M socket file naming conventions.

FLUSH_DB_IPCS_INFO

Writes file header of specified database file to disk.

The ipc resources (shared memory and semaphore) created for a database file are stored in the database file header.  The first process opening a database file initializes these fields while the last process to use the database clears them. If neither of them has read-write access permissions to the database file, they set/reset these fields in shared memory and gtmsecshr will write the database file header from shared memory to disk on their behalf.

[a] GT.M processes are never supposed to be suspended.  However, in the event GT.M finds a process suspended while holding a resource, it is sent a SIGCONT.

Table 1. 




[1] The concept of write-only access to a database file is not meaningful for GT.M.

[2] Consider a case where Process P1 with user id U1 and primary group G1 and Process P2 with user id U2 and primary group G2 both access a database file with group G3, which is a secondary group for both U1 and U2. If process P1 switches the journal file, it will have owner U1 and group G1, and be unusable by process P2 unless it has world read-write permission. The solution is to place the journal files in a directory whose group is G3.

[3] Even with MM, processes that have read-only access to the database file still have read-write access to the control structures (for example, for M locks).It is conceivable that a rogue process with read-only access may somehow place information in the control structures (for example, bad M lock information) to induce a normal process with read-write access to record inconsistent information in the database.

[4] GT.M by default uses a wrapper for gtmsecshr. Source code for the wrapper is published. You can modify the source code to set $gtm_log and $gtm_tmp to required values, recompile and reinstall your modified wrapper.

For more information, see the GT.M web site.