|
|
|
|
|
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
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
|
To generate random numbers for security or cryptography, use the
getrandom() function, which is available starting with Oracle Solaris 11.3, or /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
|
wordexp()
|
int wordexp(const char *restrict words, wordexp_t *restrict pwordexp, int
flags)
|
USE WITH CAUTION
|
wordexp() passes the input string to a shell for expansion.
Input provided by untrusted sources may attempt to use shell injection attacks to run
additional commands.
|
If only wildcard expansion is required, use the glob()
function.
|