safe_open man page on Tru64

Man page or keyword search:  
man Server   12896 pages
apropos Keyword Search (all sections)
Output format
Tru64 logo
[printable version]

safe_open(3)							  safe_open(3)

NAME
       safe_open  - Open a file for I/O with comprehensive or customized secu‐
       rity checks

SYNOPSIS
       #include <safe_open.h>

       int safe_open(
	       char const *pathname,
	       int oflags,
	       ulong_t sflags,
	       ...  );

LIBRARY
       Standard C Library (libc)

PARAMETERS
       Identifies the file or other file system object being opened.  Includes
       the flags (such as O_RDONLY, O_CREAT, or O_APPEND) that one would spec‐
       ify to an open() call. The flags	 actually  passed  by  safe_open()  to
       open()  may  vary  from	these;	see DESCRIPTION for details.  Includes
       flags that can relax 20 of the restrictions that	 safe_open()  enforces
       by default. You can specify one or more of the following flags, each of
       which tells safe_open() not to enforce a particular restriction: Accept
       the  risk  of blocking for off-line modems or named pipes (fifos). This
       flag is often appropriate when intending to  write  to  a  named	 pipe,
       since  a non-blocking open of a named pipe for writing fails when there
       is no reader.  Allow opening file system objects under /dev/fd (or  any
       other  file  system  mounted  as type fdfs).  Allow opening file system
       objects that are the targets of	file-on-file  mounts.	Allow  opening
       file  system  objects  under /proc (or any other file system mounted as
       type procfs).  Allow opening files on non-local file systems. Not  set‐
       ting  this  flag excludes (at least) NFS and DCE file systems. For sup‐
       port of dataless client configurations, the /, /usr, /usr/var, and /var
       file systems are always accepted, even when this flag is not specified.

	      Local  file  systems  are currently defined as MFS, CFS, and any
	      others that set the M_LOCAL bit in the m_flags  field  of	 their
	      mount  structures. (At the time this reference page was written,
	      the full list of local file systems included AdvFS,  CDFS,  CFS,
	      DVDFS,  MFS,  and	 UFS.)	 Allow	relative paths in the pathname
	      parameter.  When creating a new file, do not check for a	possi‐
	      bly-inappropriate	 default  access control list (ACL) on the new
	      file. If this flag is omitted, newly-created files  are  checked
	      to  see  whether they have inherited a default ACL from the con‐
	      taining directory. If so, and if the owner of that directory  is
	      neither  UID  0 nor the effective UID of the process, an attempt
	      is made to delete the ACL from the file. If any other readers or
	      writers  of  the	file  are detected after removing the ACL, the
	      file is closed and safe_open() fails, setting errno to [EMLINK].
	      When  resolving  the  pathname  parameter, accept symbolic links
	      that have the same UID as the directory in which they are found.
	      If this flag is omitted, only symbolic links owned by the effec‐
	      tive UID of the process or by UID 0 will be  accepted.   Do  not
	      check for other links to the same file. If this flag is omitted,
	      named pipes and regular files with link counts greater than  one
	      will  be rejected, causing safe_open() to fail with errno set to
	      [EMLINK].	 Limit “writable directory” checks to making sure that
	      directories  do not have world write permission. If this flag is
	      omitted, safe_open() makes sure that  directories	 have  neither
	      world  write nor group write permission.	Limit “writable direc‐
	      tory” checking to the immediate  parent  directory  of  pathname
	      (and  of any symbolic links traversed to the final symbolic link
	      target, when relevant). If this  flag  is	 omitted,  safe_open()
	      will  also  traverse upward from the immediate parent directory,
	      checking each directory until reaching (and  testing)  the  root
	      directory,  as  well  as	checking  each	directory traversed to
	      resolve any symbolic links.  Skip	 “writable  directory”	checks
	      for  the	starting  directory  of	 the  pathname	parameter. See
	      RESTRICTIONS for a limited number of cases  when	this  flag  is
	      ignored.	 Skip “writable directory” checks for directories with
	      the “sticky bit” (S_ISVTX) set in their  mode  bits.   Skip  the
	      checks  for  symbolic link ownership.  Allow block-special files
	      to be opened.   Allow  character-special	files  to  be  opened.
	      Allow  directories  to be opened for reading.  Allow named pipes
	      (fifos) to be opened.  Allow symbolic links to  be  followed  if
	      all  other  constraints  are  met.  Even with this flag set, the
	      object type of the symbolic link's target must be acceptable. On
	      systems  where  the  open()  call	 supports the O_NOFOLLOW flag,
	      including	 O_NOFOLLOW  in	 oflags	 overrides  the	 inclusion  of
	      OPN_TYPE_SYMLINK in sflags.  Allow files not owned by the effec‐
	      tive UID to be opened.  Reserved for future expansion.

DESCRIPTION
       The safe_open() function attempts to open the file system object	 iden‐
       tified  by  its	pathname  parameter and makes validity checks, as con‐
       trolled by the oflags and sflags parameters. The validity checking that
       this  function  performs	 helps to protect against some common security
       vulnerabilities, such as “time of check, time  of  use”	(TOCTOU)  race
       conditions, that can be created when programs manipulate arbitrary file
       system objects.

       If successful, safe_open() returns a file descriptor.  On failure,  the
       function returns -1 and sets errno to indicate the error.

       For many applications that want to protect against security vulnerabil‐
       ities when opening files, the safe_open() function will	be  a  drop-in
       replacement  for an open() call, after selecting a suitable set of val‐
       ues for the sflags parameter.  However, the  oflags  parameter  is  not
       necessarily passed to the open() call or passed exactly as specified in
       order to protect	 against  security  vulnerabilities.  The  safe_open()
       function differs from the open() function with respect to oflags values
       in the  following  ways:	 The  safe_open()  function  never  implements
       O_CREAT without an implicit O_EXCL.

	      When   called   with  only  O_CREAT  in  its  oflags  parameter,
	      safe_open() always passes 0600 to open() as  a  mode  parameter.
	      Therefore,  applications	that  need  to use an oflags parameter
	      that specifies O_CREAT without O_EXCL  will  need	 to  add  some
	      retry logic in addition to the safe_open() call. (See EXAMPLES.)
	      If the pathname parameter is a symbolic link,  safe_open()  will
	      never  create  a	file,  even  when  O_CREAT  is specified.  The
	      safe_open() function never passes O_TRUNC to open().

	      When called with O_TRUNC in its  oflags  parameter,  safe_open()
	      simulates	 the O_TRUNC operation by using a call to ftruncate().
	      The safe_open() function always adds both O_NONBLOCK and	O_NDE‐
	      LAY to any open() calls (even if O_CREAT is specified in oflags)
	      unless OPN_BLOCKING is included in sflags.

       This function makes the following checks before opening	the  specified
       pathname	 parameter whether or not a new or existing file system object
       is being opened. There is no guaranteed order in which these checks are
       made.  If  a  file system or the target object fails any of the checks,
       the function will return failure (unless otherwise noted).  Because  of
       the  potential for race conditions, some of the checks may be made more
       than once.  Validate the type of the target file system,	 depending  on
       the OPN_FSTYPE_* flags that are provided for sflags. If no OPN_FSTYPE_*
       flags are set, only local file systems (as defined in  the  description
       of  the OPN_FSTYPE_REMOTE flag) are permitted and they cannot be one of
       the “pseudo” local file systems (FDFS, FFM, or PROCFS).	 Validate  the
       type  of the file system object, depending on the OPN_TYPE_* flags that
       are provided for sflags. If no OPN_TYPE_* flags are set, only a regular
       file  may  be  opened.	Confirm that the target file does not exist if
       O_CREAT and O_EXCL are included in oflags Validate that no component of
       the  resolved  pathname	parameter  is  in  an untrustworthy (world- or
       group-writable) directory, depending on the OPN_TRUST_* flags that  are
       provided	 for  sflags. Regardless of whether OPN_TRUST_* flags are set,
       safe_open() always subjects any symbolic link component found in	 path‐
       name  to	 the  writable-directory check. Other directory components are
       checked, depending on whether  OPN_TRUST_PARENT_DIRS,  OPN_TRUST_START‐
       ING_DIRS,  or  both  are set. Symbolic links are also subject to proper
       ownership checking,  as	controlled  by	the  OPN_TRUST_DIR_OWNERS  and
       OPN_TRUST_SYMLINK_OWNERS flags.

	      If  no  OPN_TRUST_*  flags  are  present: All directories in the
	      absolute pathname of the file system object being opened will be
	      checked  None  of	 those	directories  may  be group-writable or
	      world-writable All symbolic links found during pathname  traver‐
	      sal  must	 be owned by UID 0 or the effective UID of the calling
	      process If the pathname parameter identifies a symbolic link and
	      OPN_TYPE_SYMLINK	is specified, the link's target must also pass
	      the object type validation, depending on	any  other  OPN_TYPE_*
	      flags that are included.

       To  open the file system object, safe_open() may use the resolved path‐
       name that was obtained during the per-component,	 access-checking  tra‐
       versal  of  pathname.  (This  is	 always	 done  on  file	 creation.) If
       OPN_BLOCKING was not included in sflags, the open is always done	 as  a
       non-blocking open and fcntl() is called to clear the non-blocking bits.
       If an existing file was opened, safe_open() makes additional checks  as
       follows:	 Verify	 that  pathname	 was  successfully opened and that the
       opened file system object is what was expected  based  on  the  earlier
       checks  on the type or types of file system objects that are allowed to
       be opened.  Check to make sure that the call to	fcntl()	 succeeded  if
       OPN_BLOCKING  was  not specified in sflags, and O_NONBLOCK and O_NDELAY
       were not both specified in oflags.  Verify that the call to ftruncate()
       succeeded  if  O_TRUNC  was specified in oflags.	 (This step is skipped
       for named pipes and objects opened through file systems of type	FDFS.)
       Confirm that the object being opened does not have a link count greater
       than one if OPN_TRUST_NLINKS was not specified in sflags, and the  file
       system object being opened is a named pipe or a regular file.

       For a newly created file, assuming OPN_TRUST_DEFAULT_ACLS was not spec‐
       ified in sflags, safe_open() makes sure that at least one of  the  fol‐
       lowing  additional conditions applies: The file was created in a direc‐
       tory owned by UID 0 or the effective UID of  the	 calling  process  The
       file did not inherit a default ACL from its directory

	      For  more	 information,  see  the	 “ACL  Inheritance” section in
	      acl(4).  Deleting the default ACL on the new file and  resetting
	      its mode to 0600 must succeed and, after doing so, there must be
	      no other processes accessing the file.

       On  failure  of	any  check  after  a  file  descriptor	is   obtained,
       safe_open() closes the file descriptor before returning failure status.

NOTES
       HP  reserves  the  right	 to  revise  the safe_open() implementation to
       address additional security vulnerabilities in the future. It is possi‐
       ble  that  these	 future additional checks might cause application code
       that is	designed to use the current implementation and that has a pre‐
       viously-undetected vulnerability to fail under circumstances that exer‐
       cise that vulnerability.	 This is appropriate for  privileged  programs
       that must maintain the highest level of safe operation. For the benefit
       of applications with looser security requirements, the validity	check‐
       ing  on	the  sflags  mask  only rejects bits in the range reserved for
       future expansion of the argument list. The start of that reserved range
       of  bit	numbers	 is identified by the OPN_first_reserved symbol. Those
       bits that are currently unassigned, but which may be  assigned  in  the
       future  to  disable new checks, are accepted by the current implementa‐
       tion. The start of the unassigned range of bit numbers is identified by
       the  OPN_num_flags symbol.  The full mask of acceptable unassigned bits
       can thus be obtained by the following expression:

       ((1UL<<OPN_first_reserved) - (1UL<<OPN_num_flags))

RESTRICTIONS
       Even if OPN_TRUST_STARTING_DIRS is included in sflags, it  is  possible
       that  the  starting directory of the pathname parameter will be subject
       to “writable directory” testing. This happens if the  pathname  resolu‐
       tion  process  encounters a sequence like subdir/../file. This behavior
       is considered a restriction rather than a bug due to the possibility of
       races  with  other processes in the handling of pathnames and directory
       modes.

       For similar reasons, the target of a symbolic link is always subject to
       the “writable directory” checks, even when it is the same as the start‐
       ing directory.

RETURN VALUES
       Success. The returned value is the file descriptor of the  file	system
       object  that  was opened.  Failure. In this case, errno is set to indi‐
       cate the condition that caused the failure.

ERRORS
       Except for a few cases, error conditions documented in  this  reference
       page are specific to the safe_open() function. However, the safe_open()
       function can also set errno in response to failure conditions  returned
       by  any	of  the	 following calls: acl_get_fd(), acl_set_fd(), fcntl(),
       fstat(), ftruncate(), fuser(), lstat(), open(), readlink(), realpath(),
       stat(),	and  statfs().	Refer to SEE ALSO find the reference pages for
       these functions.	 The oflags parameter had O_TRUNC set, but the	access
       portion	of that parameter was O_RDONLY. (This error is propagated from
       an ftruncate() call.)  The type of the file system object was  rejected
       based on the OPN_TYPE_* values omitted from sflags, or the type of file
       system type in which the object was to be opened was rejected, based on
       the  OPN_FSTYPE_*  values  omitted from sflags.	The pathname parameter
       was NULL or did not start with a / character and the  sflags  parameter
       did  not	 include  OPN_RELATIVE,	 or the sflags parameter included bits
       that are reserved for future argument expansion.	 One of the  following
       conditions  was	encountered: OPN_TRUST_NLINKS flag was not included in
       sflags, an existing file system object was  found  that	was  either  a
       named  pipe or a regular file, and its link count was greater than one.
       OPN_TRUST_DEFAULT_ACLS was not included in sflags, a newly-created file
       was found to have inherited a default access control list from a direc‐
       tory owned by an inappropriate UID, and other processes were  found  to
       be  accessing the new file after resetting its ACL.  One of the follow‐
       ing conditions was encountered: The pathname  parameter	was  an	 empty
       string.	 The pathname parameter had at least one trailing / character.
       If the intent was to specify a directory, it should be done by  append‐
       ing  a  dot  (.)	 character.   O_CREAT  was specified without O_EXCL in
       oflags and a file system object associated with the pathname  parameter
       existed	at the start of the call but no longer existed when an attempt
       was made to open the existing file. The safe_open() routine  will  have
       retried this sequence of operations at least once before returning this
       error.  One of the following conditions was encountered: Some directory
       permissions  found  were	 overly	 permissive (given the constraints not
       relaxed by the OPN_TRUST_* flags).  An attempt was made to create a new
       file  by	 traversing  a symbolic link.  One of the following conditions
       was encountered: OPN_UNOWNED was not included in sflags, and  the  file
       found   was   not   owned   by	the  effective	UID  of	 the  process.
       OPN_TRUST_SYMLINK_OWNERS was not included in  sflags,  and  a  symbolic
       link  was  found	 that failed the symbolic link ownership checks during
       resolution of pathname.	Either some check on the pathname parameter or
       on  symbolic  links  that  needed  to  be  resolved  for that parameter
       returned inconsistent results, or the file originally tested (by	 means
       of the pathname parameter) did not match the file object returned by an
       internal call to open().

EXAMPLES
       The following replacement example  shows	 how  file  opening  might  be
       updated	for  an application that intends to display a notice file to a
       user.  This example assumes that the application	 is  not  in  complete
       control	of  the	 pathname to be displayed, but that it is running with
       the user's own UID, and that the application displays  a	 regular  file
       (however it was found).

	      Original code:

	      int fd = open(pathname, O_RDONLY);

	      Replacement code:

	      const ulong_t soflags = (OPN_UNOWNED | OPN_TRUST_STICKY_BIT |
				       OPN_TRUST_NLINKS | OPN_TYPE_SYMLINK |
				       OPN_RELATIVE  | OPN_FSTYPE_REMOTE); int
	      fd  =  safe_open(pathname,  O_RDONLY,  soflags);	The  following
	      replacement  example  shows  how adding data to a user-specified
	      pathname can be done more safely. This example assumes that  the
	      application  has no control over the user-provided pathname, but
	      that it is running  with	the  user's  credentials.  It  further
	      assumes  that  the  application  is  running as a daemon, so the
	      practice	of  accepting  relative	 pathnames   is	  inadvisable.
	      Finally,	it  assumes  that the expected location for the user's
	      file  is	in  either  /tmp  or  /var/tmp,	 so  the  use  of  the
	      OPN_TRUST_STICKY_BIT is appropriate.

	      Original code:

	      int fd = open(pathname, O_CREAT|O_APPEND|O_WRONLY, 0644);

	      Replacement code:

	      The  replacement	code  is  complicated  slightly by the need to
	      retry file creation attempts and to reset the file's mode if  it
	      was newly created.

	      const ulong_t soflags = (OPN_TRUST_STICKY_BIT); int loop_limit =
	      3, fd; do {
		  fd = safe_open(pathname, O_CREAT|O_APPEND|O_WRONLY,soflags);
	      } while (-1 == fd && ENOENT == errno && --loop_limit); if (fd >=
	      0)
		  (void) fchmod(fd, 0644);

	      (The retry for [ENOENT] errors is	 only  needed  for  robustness
	      because  safe_open() does its own retry in this case.)  The fol‐
	      lowing replacement example shows how an operation similar to the
	      >>  redirection of the shells can be made safer against inadver‐
	      tent file substitution, while still allowing the user  to	 write
	      to a hardcopy terminal, a magnetic tape, a named pipe, a file in
	      /tmp, or a file in the user's (possibly NFS-mounted) home direc‐
	      tory.

	      Original code:

	      int  fd  = open(pathname, O_CREAT|O_EXCL|O_WRONLY, 0666); if (-1
	      == fd && EEXIST == errno)
		  fd = open(pathname, O_APPEND|O_WRONLY);

	      Replacement code:

	      The replacement code uses the process umask setting  to  (possi‐
	      bly)  open up the permissions on a newly-created file beyond the
	      0600 mode always applied by the safe_open() routine.  This  code
	      also  deliberately  excludes  block-special devices because they
	      are not suitable for text output.

	      const   ulong_t	soflags_append	 =   (OPN_TRUST_STICKY_BIT   |
	      OPN_UNOWNED |
					      OPN_TRUST_NLINKS	| OPN_RELATIVE
	      |
					      OPN_FSTYPE_REMOTE | OPN_TYPE_CHR
	      |
					      OPN_TYPE_FIFO | OPN_TYPE_SYMLINK
	      |
					      OPN_BLOCKING);   const   ulong_t
	      soflags_create = (OPN_TRUST_STICKY_BIT | OPN_RELATIVE |
					      OPN_FSTYPE_REMOTE | OPN_BLOCKING
	      |
					      OPN_TRUST_DEFAULT_ACLS); int  fd
	      =	 safe_open(pathname, O_CREAT|O_EXCL|O_WRONLY, soflags_create);
	      if (fd >= 0) {
		  mode_t cmask = umask(077);  /* Get prevailing umask. */
		  (void) umask(cmask);	      /* Restore it. */
		  (void) fchmod(fd, 0666 & ~cmask); /* Apply it. */ } else
		  fd = safe_open(pathname, O_APPEND|O_WRONLY, soflags_append);

	      (It should be noted that this method of  obtaining  the  process
	      umask  value, while simple, is not thread safe. A multi-threaded
	      application should use the TBL_UAREA  function  of  the  table()
	      system  call, and examine the u_cmask structure member to obtain
	      the umask value.)

SEE ALSO
       Functions:  fcntl(2),  ftruncate(2),  fuser(2),	open(2),  readlink(2),
       stat(2),	 statfs(2),  table(2), umask(2), acl_get_fd(3), acl_set_fd(3),
       fdopen(3), realpath(3)

       Files: acl(4), fd(4), ffm(4), proc(4)

								  safe_open(3)
[top]
                             _         _         _ 
                            | |       | |       | |     
                            | |       | |       | |     
                         __ | | __ __ | | __ __ | | __  
                         \ \| |/ / \ \| |/ / \ \| |/ /  
                          \ \ / /   \ \ / /   \ \ / /   
                           \   /     \   /     \   /    
                            \_/       \_/       \_/ 
More information is available in HTML format for server Tru64

List of man pages available for Tru64

Copyright (c) for man pages and the logo by the respective OS vendor.

For those who want to learn more, the polarhome community provides shell access and support.

[legal] [privacy] [GNU] [policy] [cookies] [netiquette] [sponsors] [FAQ]
Tweet
Polarhome, production since 1999.
Member of Polarhome portal.
Based on Fawad Halim's script.
....................................................................
Vote for polarhome
Free Shell Accounts :: the biggest list on the net