|
|
|
|
|
access()
|
int access(const char *path, in mode)
|
AVOID
|
The information this function provides is outdated by the time you receive it. Using the access() function
followed by the open() function causes a race condition that cannot be solved.
|
Open the file with the permissions of the intended user.
|
bcopy()
|
void bcopy(const void *s1, void *s2, size_t n) void *memcpy(void *s1,
const void *s2, size_t n)
|
USE WITH CAUTION
|
Should not be used for copying strings, even though the length is
known. Instead, use the strlcpy() function.
|
NA
|
catopen()
|
nl_catd catopen(const char *name, int oflag)
|
USE WITH CAUTION
|
Libraries and programs should not call the catopen() function on user-supplied
pathnames. User-supplied message catalogues can be leveraged to break
privileged code easily.
|
NA
|
cftime()
|
int cftime(char *s, char *format, const time_t *clock)
int ascftime(char *s, const char *format, const struct tm
*timeptr)
|
UNSAFE
|
These functions do not check for bounds on the output buffer and might
import the userdata through the CFTIME environment variable.
|
strftime(buf, sizeof (buf), fmt, &tm)
|
chdir()
|
int chdir(const char *path)
|
USE WITH CAUTION
|
Prone to pathname race conditions. Do not use in multithreaded
programs.
|
To avoid the race condition, use the fchdir() function after the
directory has been opened and the properties have been checked using
the fstat() function). Oracle Solaris 11 has added the POSIX 2008 *at() versions of
the system calls that operate on files such as openat(), linkat(), mkdirat(),
mkfifoat(), readlinkat(), and symlinkat(). These calls take the file
descriptor of a directory as the first argument to use as the working
directory for relative paths. These methods avoid the race condition when one
thread calls chdir() while another is calling open(), unlink() and the like.
|
chmod()
|
int chmod(const char *path, mode_t mode)
int fchmodat(int fd, const char *path, mode_t mode, int flag)
int chown(const char *path, uid_t owner, gid_t group)
int lchown(const char *path, uid_t owner, gid_t group)
|
AVOID
|
These functions operate on pathnames and are prone to race conditions.
Normally, programs need not call chown() or chmod(), but honor the
current UID (switch back to it before opening files) and umask. Note
that chmod() always follows symbolic links.
|
If the attributes of a file must be changed, open the file safely
and use the the fchown() or the fchmod() functions on the resulting
file descriptor.
|
chroot()
|
int chroot(const char *path)
|
USE WITH CAUTION
|
After the chroot() function is called, the environment in which it is called
offers little protection. Programs can easily escape. Do not run
privileged programs in such a environment and that you change the directory to a
point below the new root after the chroot() function.
|
Run in a non-global zone.
|
copylist()
|
char *copylist(const char *filenm, off_t *szptr)
DBM *dbm_open(const char *file, int open_flags, mode_t file_mode)
int dbminit(char *file)
|
USE WITH CAUTION
|
Used to open files and should only be used to open pathnames
known to be safe.
|
NA
|
dlopen()
|
void *dlopen(const char *pathname, int mode)
|
USE WITH CAUTION
|
Parameters passed to the dlopen() function should only be unqualified
pathnames which are then found using the runtime linker's path, or full
pathnames not in any way derived from user input (including from argv[0]
). There is no way to safely open a user-supplied shared object. The
object's _init() function is executed before dlopen() returns.
|
NA
|
drand48()
|
double drand48(void)
double erand48(unsigned short xi[3])
long lrand48(void)long mrand48(void)
long jrand48(unsigned short xi[3])
long nrand48(unsigned short xi[3])
void srand48(long seedval)
int rand(void)
int rand_r(unsigned int *seed)
void srand(unsigned int seed)
long random(void)
|
AVOID
|
These weak random number generators are not useful for
increasing security. To generate random numbers for security,
use /dev/urandom, which is available starting with Solaris 9.
|
NA
|
dup()
|
int dup(int fildes)
int dup2(int fildes, int fildes2)
|
USE WITH CAUTION
|
Both the dup() and the dup2() functions return file descriptors with
the FD_CLOEXEC cleared and therefore they might leak when a program calls
exec(). Older code made fcntl() calls shortly after these functions
returned to set that flag. But in multithreaded code (including
programs that only run one thread themselves but may be linked with
libraries that run additional threads), that leaves a window open for a
race with another thread. The F_DUPFD_CLOEXEC and F_DUP2FD_CLOEXE
calls to fcntl (available in Oracle Solaris 11 and later releases)
combine the duplication and flag setting into an atomic operation so
there is no race.
|
fcntl(fildes, F_DUPFD_CLOEXEC, 0)
fcntl(fildes, F_DUP2FD_CLOEXEC, fildes2)
|
execl()
|
int execl(const char *path, const char *arg0, ..., const char *argn,
NULL)
int execv(const char *path, char *const argv[])
int execve(const char *path, char *const argv[], char *const
envp[])
|
USE WITH CAUTION
|
Make sure that the environment is sanitized and non-essential file
descriptors are closed before executing a new program.
|
NA
|
execvp()
|
int execvp(const char *file, const char *argv[])
int execlp(const char *file, const char *arg0, ..., const char *argn,
NULL)
|
AVOID
|
Too dangerous to use in libraries or privileged commands and
daemons because they find the executable by searching the directories in
the PATH environment variable, which is under the complete control of
the user. They should be avoided for most other programs.
|
Use the execl(), execv(), or execve() functions.
|
fattach()
|
int fattach(int filedes, const char *path)
|
USE WITH CAUTION
|
Check the file descriptor after the open() function (using fstat()), and not the
pathname before the open() function.
|
NA
|
fchmod()
|
int fchmod(int filedes, mode_t mode)
int fchown(int filedes, uid_t owner, gid_t group)
|
UNRESTRICTED
|
Preferred alternative to chmod() and chown() functions.
|
NA
|
fdopen()
|
FILE *fdopen(int filedes, const char *mode)
|
UNRESTRICTED
|
Alternative for fopen()
|
NA
|
fopen()
|
FILE *fopen(const char *path, const char *mode)
FILE *freopen(const char *path, const char *mode, FILE *stream)
|
USE WITH CAUTION
|
It is not possible to safely create files by using fopen(). However, once
a pathname is verified to exist, that is, after calling the mkstemp() function, it can be used
to open those pathnames. In other cases, a safe invocation of open()
followed by fdopen() should be used.
|
Use open() followed by fdopen(), For example:
FILE *fp; int fd;
fd = open(path,
O_CREAT|O_EXCL|O_WRONLY,
0600);
if (fd < 0){
...... }
fp = fdopen(fd, "w");
|
fstat()
|
int fstat(int filedes, struct stat *buf)
|
UNRESTRICTED
|
Useful to check whether the file that is opened is the file you expected to
open.
|
NA
|
ftw()
|
int ftw(const char *path, int (*fn)(), int depth)
int nftw(const char *path, int (*fn)(), int depth, int flags)
|
USE WITH CAUTION
|
Follows symbolic links and crosses mount points.
|
Use nftw with the appropriate flags set (a combination of FTW_PHYS and
FTW_MOUNT).
|
getenv()
|
char *getenv(const char *name)
|
USE WITH CAUTION
|
The environment is completely user-specified. If possible, avoid the
use of getenv() in libraries. Strings returned by getenv() can be up to
NCARGS bytes long (currently 1MB for 32-bit environments).
Pathnames derived from environment variables should not be trusted. They
should not be used as input for any of the *open() functions (including
catopen() and dlopen()).
|
NA
|
getlogin()
|
char *getlogin(void)
|
AVOID
|
The value returned by getlogin() is not reliable. It is only a hint
for the user name.
|
NA
|
getpass()
|
char *getpass(const char *prompt)
|
AVOID
|
Only the first 8 bytes of input are used. Avoid using it in new
code.
|
Use the getpassphrase() function.
|
gets()
|
char *gets(char *s)
|
UNSAFE
|
This function does not check for bounds when storing the input. This
function cannot be used securely.
|
Use fgets(buf, sizeof (buf), stdin) OR
getline(buf, bufsize, stdin).
The getline(buf, bufsize, stdin) function is new
in Oracle Solaris 11.
|
kvm_open()
|
kvm_t *kvm_open(char *namelist, char *corefile, char *swapfile, int
flag, char *errstr)
int nlist(const char *filename, struct nlist *nl)
|
AVOID
|
Write a proper kstat or other interface if you need information from
the kernel. If you accept a user-specified namelist argument, make sure
you revoke privileges before using it. Otherwise, a specifically constructed
namelist can be used to read random parts of the kernel, revealing
possibly sensitive data.
|
NA
|
lstat()
|
int lstat(const char *path, struct stat *buf)
int stat(const char *path, struct stat *buf)
int fstatat(int fildes, const char *path, struct stat *buf, int
flag)
|
USE WITH CAUTION
|
Do not use these functions to check for the existence or
absence of a file. The lstat(), stat(), or fstatat() functions followed
by open() have an inherent race condition.
|
If the purpose is to create the file that does not exist, use
open(file, O_CREAT|O_EXCL, mode)
If the purpose is to read the file, open it for reading. If the
purpose is to make sure the file attributes are correct before reading
from it, use
fd = open(file, O_RDONLY); fstat(fd, &statbuf);
If the pathname can't be trusted, add O_NONBLOCK to the open flags.
This prevents the application from hanging upon opening a device.
|
mkdir()
|
int mkdir(const char *path, mode_t mode)
int mkdirat(int fd, const char *path, mode_t mode)
int mknod(const char *path, mode_t mode, dev_t dev)
int mknodat(int fd, const char *path, mode_t mode, dev_t dev)
|
USE WITH CAUTION
|
Be careful about the path used. These functions will not follow
symbolic links for the last component and hence they are relatively safe.
|
NA
|
mkstemp()
|
int mkstemp(char *template)
|
UNRESTRICTED
|
Safe temporary file creation function.
|
NA
|
mktemp()
|
char *mktemp(char *template)
|
AVOID
|
Generates a temporary filename but the use of the generated pathname is
not guaranteed safe because there is a race condition between the checks
in mktemp() and the subsequent call to open() by the application.
|
Use mkstemp() to create a file and mkdtemp() to create a
directory.
|
open()
|
int open(const char *path, int oflag, /* mode_t mode */...)
int creat(const char *path, mode_t mode)
|
USE WITH CAUTION
|
When opening for reading from a privileged program, make sure
that you open the file as a user by dropping privileges or setting the
effective UID to the real UID. Under no circumstances should programs
implement their own access control based on file ownership and modes.
Similarly, when creating files, do not open and then use chown() on the
file.
When opening for writing, the program can be tricked into opening the
wrong file by following symbolic or hard links. To avoid this problem,
either use the O_NOFOLLOW and O_NOLINKS flags, or use O_CREAT|O_EXCL to
ensure that a new file is created instead of opening an existing
file.
When opening a file, consider whether the file descriptor should be
kept open across an exec() call. In Oracle Solaris 11, you can specify
O_CLOEXEC in the open flags to atomically mark the file descriptor to be
closed by exec system calls. In older releases, you must use the
fcntl() function with the FD_CLOEXEC flag, which allows a race condition
in multithreaded programs, if another thread forks and execute between the
open() and fcntl() calls.
|
NA
|
popen()
|
FILE *popen(const char *command, const char *mode)
int p2open(const char *cmd, FILE *fp[2])
int system(const char *string)
|
AVOID
|
These three library calls always involve the shell which involves
PATH, IFS, other environment variables and interpretation of special
characters. Refer CERT C Coding Recommendation
ENV04-C for more details.
|
Use posix_spawn() to execute other programs, with waitpid() or pipe()
as necessary.
|
printf()
|
int printf(const char *format, ...)
int vprintf(const char *format, va_list ap)
int fprintf(FILE *stream, const char *format, ...)
int vfprintf(FILE *stream, const char *format, va_list ap)
int snprintf(char *s, size_t n, const char *format, ...)
int vsnprintf(char *s, size_t n, const char *format, va_list ap)
int wprintf(const wchar_t *format, ...)
int vwprintf(const wchar_t format, va_list arg)
int fwprintf(FILE *stream, const wchar_t *format, ...)
int vfwprintf(FILE *stream, const wchar_t *format, va_list arg)
int swprintf(wchar_t *s, size_t n, const wchar_t *format, ...)
int vswprintf(wchar_t *s, size_t n, const wchar_t *format, va_list
arg)
int asprintf(char **ret, const char *format, ...)
|
USE WITH CAUTION
|
At risk from user-specified format strings. If the format string comes
from a message catalog, verify your NLSPATH manipulations and catopen()
or catget() uses. The C library tries to be safe by ignoring NLSPATH
settings for set-uid and set-gid applications.
|
The snprintf() and vsnprintf() functions return the number of
characters that would have been written to the buffer if it were large
enough. You cannot use this value in constructs like, p += snprintf(p,
lenp, "...") because p might point beyond p+lenp
afterwards.
|
scanf()
|
int scanf(const char *format, ...)
int vscanf(const char *format, va_list arg)
int fscanf(FILE *stream, const char *format, ...)
int vfscanf(FILE *stream, const char *format, va_list arg)
int sscanf(const char *s, const char *format, ...)
int vsscanf(const char *s, const char *format, va_list arg)
|
USE WITH CAUTION
|
When scanning strings, make sure the format specified includes maximum
buffer lengths. Use scanf("%10s", p) to limit scanf() to read 10
characters at most. Note that the corresponding buffer must be at least
eleven bytes to allow space for the terminating NULL character.
|
NA
|
sprintf()
|
int sprintf(char *s, const char *fmt, ...)
int vsprintf(char *s, const char *fmt, va_list ap)
|
AVOID
|
Typically cause buffer overflow. If you must use these functions, make
sure that the fmt argument cannot be user-controlled and that you can
trust the parameters not to overflow the destination buffer.
|
Use snprintf(), vsnprintf() or asprintf(). The asprintf() function is
new in Oracle Solaris 11.
|
strcat()
|
char *strcat(char *s1, const char *s2)
char *strcpy(char *s1, const char *s2)
|
AVOID
|
It is not possible to limit these functions to a maximum buffer size.
However, you can calculate the amount of space required before calling
strcat or strcpy. Use of these functions always forces reviewers to
follow the logic, and prevent automated scanning of source code for
vulnerabilities.
|
strlcat(dst, src, dstsize)
strlcpy(dst, src, dstsize)
|
strccpy()
|
char *strccpy(char *output, const char *input)
char *strcadd(char *output, const char *input)
char *streadd(char *output, const char *input)
char *strecpy(char *output, const char *input, const char
*exceptions)
char *strtrns(const char *string, const char *old, const char *new,
char *result)
|
USE WITH CAUTION
|
Similar problems as with strcpy(). See the strcpy and strccpy man pages for proper
use.
|
NA
|
strlcpy()
|
size_t strlcpy(char *dst, const char *src, size_t dstsize)
size_t strlcat(char *dst, const char *src, size_t dstsize)
|
UNRESTRICTED
|
Preferred alternative to the strcpy() and the strcat() functions.
Available in Solaris 8 and later. Should be used with constant and not
computed size arguments to facilitate code review.
|
NA
|
strncat()
|
char *strncat(char *s1, const char *s2, size_t n)
char *strncpy(char *s1, const char *s2, size_t n)
|
USE WITH CAUTION
|
The strncpy() function is not guaranteed to null-terminate the
destination buffer. The strncat() function is hard to use as it requires
the proper size of the destination buffer to be calculated.
The fact that the strncpy() function does not null- terminate on
insufficient space, together with the side effect that it will add NULL
bytes if there is space left, makes it a useful function for updating
structures that reside on disk. For example the wtmpx files, are often
generated with write(fd, w, sizeof (*w));
|
strlcpy(dst, src, dstsize)
strlcat(dst, src, dstsize)
|
syslog()
|
void syslog(int priority, const char *message, ...)
void vsyslog(int priority, const char *message, va_list ap)
|
USE WITH CAUTION
|
At risk from user-specified format strings. Verify your NLSPAT
manipulations and catopen() or catget() uses.
|
NA
|
tempnam()
|
char *tempnam(const char *dir, const char *pfx)
char *tmpnam(char *s)
char *tmpnam_r(char *s)
|
AVOID
|
These functions are not suitable for generating unpredictable
filenames. There is a race condition between the generation of the
filename and its use, for example, open().
|
mkstem()
|
tmpfile()
|
FILE *tmpfile(void)
|
USE WITH CAUTION
|
Uses mkstemp(), so it is safe to use.
However, because this function changes the umask, it is not multithread
safe.
|
NA
|
truncate()
|
int truncate(const char *path, off_t length)
|
AVOID
|
This function is prone to pathname race conditions.
|
Use ftruncate() after a safe open().
|
umask()
|
mode_t umask(mode_t cmask)
|
USE WITH CAUTION
|
Should not be used in libraries or applications; the user's
umask should be used. Also it is not multithread safe.
|
NA
|
utmpname()
|
int utmpname(const char *file) int utmpxname(const char *file)
|
AVOID
|
Use the default utmp and utmpx files.
|
NA
|