Content-type: text/html
Manpage of SAFE_IS_PATH_TRUSTED_FORK
SAFE_IS_PATH_TRUSTED_FORK
Section: (3)
Updated: 2011-08-12
Index
Return to Main Contents
NAME
safe_is_path_trusted_fork - check the trust of a path
SYNOPSIS
#include safe_is_path_trusted.h
int safe_is_path_trusted_fork(const char *pathname, struct safe_id_range_list *trusted_uids, struct safe_id_range_list *trusted_gids);
DESCRIPTION
safe_is_path_trusted_r(3)
should be used in most cases instead of
safe_is_path_trusted_fork.
safe_is_path_trusted_fork
checks if the path name given by
pathname
can only be modified by the list of trusted users and groups.
The type of modifications include the file system object itself, and which
file system object the path refers.
The check is done by forking a process, the child process calling
safe_is_path_trusted(3),
and returning the result to the parent. This function is called internally by
safe_is_path_trusted_r(3)
as needed, and the results are identical.
The function returns the type of trust that the path provides based on the
trusted users and groups. The specific types of trust for a path are detailed
in the return value section.
An error of
EINVAL
is returned if any of the parameters are
NULL.
Parameters
- pathname
-
The path name to verify.
- trusted_uids
-
The set of user ids that are considered trusted. The
root
(0) user account is implicitly trusted.
- trusted_gids
-
The set of group ids that are considered trusted. No groups are implicitly
trusted.
Algorithm
safe_is_path_trusted_fork
works by walking the path from the first directory entry in the path to the
last. Each directory entry is checked to verified to make sure that only the
trusted users and groups and modify (write) the file system object referred
to by the directory entry.
If a directory entry is not trusted
SAFE_PATH_UNTRUSTED
is immediately returned. If an error occurs
SAFE_PATH_ERROR
is returned.
The trust of the entire path is the trust level of the last component of the
path if all the prior directory components are trusted and without error.
Relative paths, symbolic links, directories with the sticky bit set and the
determination of a path being confidential are described below.
Relative Paths
If the
pathname
is a relative path, the trust of all the directories from the
current working directory up to the root directory are checked to verify that
each directory is trusted. If any of the directories are not trusted
SAFE_PATH_UNTRUSTED
is returned.
This is done because the process must use a set of paths to arrive at the
current working directory. If one of the directories from the current working
directory to the root is not trusted, then their is no path the process could
use that is trusted to get to the current working directory, so any path
relative to the current working directory cannot be trusted.
Sticky Bit Directories
Sticky bit directories (see
chmod(2))
are treated specially. If a directory is not otherwise trusted, but has the
sticky bit set, has an owner that is in the set of trusted users, then the
directory is sticky dir trusted. The value
SAFE_PATH_TRUSTED_STICKY_DIR
is returned if the last component is sticky dir trusted.
If the parent directory of a directory entry is sticky dir trusted, and the
directory entry type is not a directory, then the path is not trusted. This
includes symbolic links and regular files in a sticky dir trusted directory.
This is because an untrusted user can create a hard link in the sticky bit
directory to make a file appear as if a trusted user created the file.
Symbolic Links
If a symbolic link is encountered while checking the directory components,
the referent of the symbolic link is read and the trust of the referent is
recursively checked. If the depth of a recursion exceeds
SYMLOOP_MAX
(or 32 if not defined),
ELOOP
is returned as do all system calls that take a path parameter.
Confidential Trust
The value
SAFE_PATH_TRUSTED_CONFIDENTIAL
is returned if in addition to the path being trusted, the final directory
entry has permissions such that only the trusted users and groups can read
the file system object.
For directories, both the ability to read the directory entries (read
permission) and to access the directory entries (execute permission) are
allowed by only trusted users and groups.
Path Exceeds PATH_MAX
This function can handle paths of arbitrary length directly.
Thread Safety
This function is thread safe.
RETURN VALUE
The function returns the type of trust for the given path. The types of trust
form a hierarchy. If a type of trust is needed, then a path with a higher
level of trust will also be suitable for the same purpose, while any path
with a lower trust will not be suitable.
The constant for each trust level is given with the numeric value given
in parenthesis.
- SAFE_PATH_ERROR (-1)
-
An error has occurred while checking the path.
errno
will be set to the type of error.
- SAFE_PATH_UNTRUSTED (0)
-
The path can be modified by a user or group that is not in the set
of trusted users and groups.
- SAFE_PATH_TRUSTED_STICKY_DIR (1)
-
The path is trusted up to the final component of the path. The final
component of the path is directory owned by a trusted user, allows
untrusted user and groups to create entries in the directory, and
has the stick bit set. This type of directory is typically used for
the /tmp directory.
This type of directory is safe to use for two types of operations:
(1) create a secure directory, or (2) create a temporary file (one that
has secure permissions and is only accessed through the file descriptor
returned from the create function).
- SAFE_PATH_TRUSTED (2)
-
The path can only be modified (written) by trusted users or groups.
- SAFE_PATH_TRUSTED_CONFIDENTIAL (3)
-
The path can only be modified (written) and accessed (read) by trusted
users and groups. The confidentiality property is only based on the
last component of the path. An alternative would be to treat anything
contained in a directory that is confidential to be confidential, but
hard links could subvert this, so the conservative approach was chosen.
ERRORS
The value of
errno
can be set to any values that the following functions set:
open(2),
close(2),
pipe(2),
read(2),
write(2),
fstat(2),
lstat(2),
fchdir(2),
readlink(2),
strdup(3),
malloc(3),
sigfillset(3),
sigprocmask(2),
sigaddset(3),
fork(2),
and
waitpid(2).
In addition
errno
can be set to the following errors:
- EAGAIN
-
If when processing a symbolic link along the path, the symbolic link is
repeatedly replaced with a new symbolic link whose referents are longer than
the previous referent. This should be a very rare event and can only occur if
a trusted user or group is constantly replacing a symbolic link with a new
symbolic link (if a symbolic link can be replaced by an untrusted user or group
the function will return that the path is untrusted before reading the referent
of the symbolic link). Retrying the call may succeed.
- EINVAL
-
One of the parameters was NULL.
EXAMPLES
The following example provides a command line interface to
safe_is_path_trusted_fork.
The typical usage pattern of
safe_is_path_trusted_fork
would be to use
>=
to test if a path is trusted enough for an operation or to use
<
to test is a path is not trusted enough.
-
#include "safe_id_range_list.h"
#include "safe_is_path_trusted.h"
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char *path;
int status;
struct safe_id_range_list safe_uids;
struct safe_id_range_list safe_gids;
if (argc != 2) {
fprintf(stderr, "Usage: %s <path>\n", argv[0]);
exit(1);
}
/* init id list structs */
if (safe_init_id_range_list(&safe_uids) == -1) {
perror("safe_init_id_range_list(&safe_uids): ");
exit(2);
}
if (safe_init_id_range_list(&safe_gids) == -1) {
perror("safe_init_id_range_list(&safe_gids): ");
exit(3);
}
/* add current user's uid and gid to safe lists */
if (safe_add_id_to_list(&safe_uids, getuid()) == -1) {
perror("safe_add_id_to_list(&safe_uids, getuid()): ");
exit(4);
}
if (safe_add_id_to_list(&safe_gids, getgid()) == -1) {
perror("safe_add_id_to_list(&safe_gids, getgid()): ");
exit(5);
}
path = argv[1];
status = safe_is_path_trusted_fork(path, &safe_uids, &safe_gids);
safe_destroy_id_range_list(&safe_uids);
safe_destroy_id_range_list(&safe_gids);
/* print exact type of trust */
switch (status) {
case SAFE_PATH_ERROR:
perror("ERROR: safe_is_path_trusted_fork: ");
exit(6);
case SAFE_PATH_UNTRUSTED:
printf("%s is not trusted.\n", path);
exit(7);
case SAFE_PATH_TRUSTED_STICKY_DIR:
printf("%s is a trusted sticky-bit directory.\n", path);
break;
case SAFE_PATH_TRUSTED:
printf("%s is trusted.\n", path);
break;
case SAFE_PATH_TRUSTED_CONFIDENTIAL:
printf("%s is trusted and confidential.\n", path);
break;
default:
printf("ERROR: unknown status: %d\n", status);
exit(8);
}
printf("\nPermissable operations are:\n");
if (status >= SAFE_PATH_TRUSTED_STICKY_DIR) {
printf("\n");
printf(" - Create a trusted directory in this directory.\n");
printf("\n");
printf(" - Create a true temporary storage file, using\n");
printf(" mkstemp() followed by unlink() (the path can\n");
printf(" only be used by these two functions).\n");
}
if (status >= SAFE_PATH_TRUSTED) {
printf("\n");
printf(" - Assume the file can not be modified, or directory\n");
printf(" entries can not be be created by untrusted\n");
printf(" users or groups.\n");
printf("\n");
printf(" - Create files (or non-directory objects) in this\n");
printf(" directory, that can be trusted.\n");
printf("\n");
printf(" - Use the path repeatedly without the possibility\n");
printf(" of an untrusted users or groups creating an\n");
printf(" exploitable race condition.\n");
}
if (status >= SAFE_PATH_TRUSTED_CONFIDENTIAL) {
printf("\n");
printf(" - Assume the file's contents or directory's entries\n");
printf(" can not be read by untrusted users or groups.\n");
}
return 0;
}
AUTHOR
James A. Kupsch
SEE ALSO
safe_is_path_trusted_r(3)
safe_is_path_trusted(3)
safe_init_id_range_list(3)
safe_destroy_id_range_list(3)
safe_parse_uid_list(3)
safe_parse_gid_list(3)
"How to Open a File and Not Get Hacked",
2008 Third International Conference on Availability, Reliability and
Security (ARES),"
Barcelona, Spain, March 2008,
http://research.cs.wisc.edu/mist/safefile
Index
- NAME
-
- SYNOPSIS
-
- DESCRIPTION
-
- Parameters
-
- Algorithm
-
- Relative Paths
-
- Sticky Bit Directories
-
- Symbolic Links
-
- Confidential Trust
-
- Path Exceeds PATH_MAX
-
- Thread Safety
-
- RETURN VALUE
-
- ERRORS
-
- EXAMPLES
-
- AUTHOR
-
- SEE ALSO
-
This document was created by
man2html,
using the manual pages.
Time: 15:16:58 GMT, August 12, 2011