Table of C Library Functions

 The table below explains the necessary security considerations when using various C library functions. Each function is classified in one of the following categories.

UNRESTRICTED
This is the default for functions
USE WITH CAUTION
Allowed for use, but special care is needed when using these functions
AVOID
Use should be avoided as these functions are difficult to use securely
UNSAFE
These functions cannot be used securely so they should not to be used under any circumstances

gets

char *gets(char *s)
Category
UNSAFE
Note
This function does not check for bounds while storing the input. This function can't be used securely.
Alternative
fgets(buf, sizeof (buf), stdin)

cftime

int cftime(char *s, char *format, const time_t *clock)
int ascftime(char *s, const char *format, const struct tm *timeptr)
Category
UNSAFE
Note
These routines do on bounds checking on the output buffer and may import user-data through the environment variable CFTIME.
Alternative
strftime(buf, sizeof (buf), fmt, &tm)

strcat

char *strcat(char *s1, const char *s2)
char *strcpy(char *s1, const char *s2)
Category
AVOID
Note
It is not possible to limit these functions to a maximum buffer size. Although one can calculate the amount of space needed before calling strcat or strcpy, the use of these functions will always force reviewers to follow the logic, and prevent automated scanning of source code for vulnerabilities.
Alternative
strlcat(dst, src, dstsize)
 strlcpy(dst, src, dstsize)

strncat

char *strncat(char *s1, const char *s2, size_t n)
char *strncpy(char *s1, const char *s2, size_t n)
Category
USE WITH CAUTION
Note
strncpy() is not guaranteed to null-terminate the destination buffer. strncat() is hard to use as it requires the proper size of the destination buffer to be calculated.
Note
The fact that strncpy() does not null- terminate on insufficient space, together with the side effect that it will add NUL bytes if there is space left makes it a useful function for updating structures that reside on disk, for example wtmpx, which are often generated with write(fd, w, sizeof (*w));
Alternative
strlcpy(dst, src, dstsize)
strlcat(dst, src, dstsize)

strlcpy

size_t strlcpy(char *dst, const char *src, size_t dstsize)
size_t strlcat(char *dst, const char *src, size_t dstsize)
Category
UNRESTRICTED
Note
Preferred alternative to strcpy/strcat functions. Available in Solaris 8 and later. Should be used with constant and not computed size arguments to facilitate code review.

open

int open(const char *path, int oflag, /* mode_t mode */...)
int creat(const char *path, mode_t mode)
Category
USE WITH CAUTION
Note
 When opening for reading from a privileged program, make sure that you open the file as the 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 chown() the file.
Note
 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.

fopen

FILE *fopen(const char *path, const char *mode)
FILE *freopen(const char *path, const char *mode, FILE *stream)
Category
USE WITH CAUTION
Note
It's not possible to safely create files using fopen(). However, once a pathname is verified to exist, e.g., after mkstemp(), it can be used to open those pathnames. In other cases, a safe invocation of open() followed by fdopen() should be used.
Alternative
open() followed by fdopen(), e.g.:
FILE *fp; int fd; fd = open(path, O_CREAT|O_EXCL|O_WRONLY, 0600); if (fd < 0) { ... } fp = fdopen(fd, "w");

fdopen

FILE *fdopen(int filedes, const char *mode)
Category
UNRESTRICTED
Note
Alternative for fopen()

access

int access(const char *path, in mode)
Category
AVOID
Note
This function is useless because the information it provides is outdated by the time you get to use it. Using access() followed by open() has a race condition that can't be solved.
Alternative
open() the file with the permissions of the intended user.

lstat

int lstat(const char *path, struct stat *buf)
int stat(const char *path, struct stat *buf)
Category
USE WITH CAUTION
Note
Neither of these functions is suitable to check for the existence or absence of a file. lstat()/stat() followed by open() has an inherent race condition that can't be solved.
Alternative
;
If the purpose is to create the file if it doesn't 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, &stat);
 If the pathname can't be trusted, add O_NONBLOCK to the open-flags. This prevents the application from hanging upon opening a device.

chmod

int chmod(const char *path, mode_t mode)
int chown(const char *path, uid_t owner, gid_t group)
int lchown(const char *path, uid_t owner, gid_t group)
Category
AVOID
Note
These functions operate on pathnames and are prone to race conditions. Normally, programs shouldn't need to call chown/chmod but honor the current uid (switch back to it before opening files.) and umask. Note that chmod() always follows symbolic links.
Alternative
If a file's attributes need to be changed, the best way to do this is to safely open the file and use fchown/fchmod on the resulting file descriptor.

fchmod

int fchmod(int filedes, mode_t mode)
int fchown(int filedes, uid_t owner, gid_t group)
Category
UNRESTRICTED
Note
Preferred alternative to chmod and chown.

fstat

int fstat(int filedes, struct stat *buf)
Category
UNRESTRICTED
Note
Useful for checking that the file you've just opened is the file you expected to open.

bcopy

void bcopy(const void *s1, void *s2, size_t n)
void *memcpy(void *s1, const void *s2, size_t n)
Category
USE WITH CAUTION
Note
Should not be used for copying strings, even though the length may be known. Use strlcpy() in those cases instead.

catopen

nl_catd catopen(const char *name, int oflag)
Category
USE WITH CAUTION
Note
Libraries and programs should not call catopen() on user supplied pathnames. User supplied message catalogues can be leveraged to break privileged code easily.

chdir

int chdir(const char *path)
Category
USE WITH CAUTION
Note
This function is open to pathname race conditions. Do not use in multi-threaded programs.
Alternative
To avoid the race condition, use fchdir() after the directory has been open()-ed and the properties have been checked using fstat()).

chroot

int chroot(const char *path)
Category
USE WITH CAUTION
Note
chroot'ed environments offer little protection; programs can easily escape. Make sure you run no privileged programs in a chroot()'ed environment and that you chdir() to a point below the new root after the chroot().

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)
Category
USE WITH CAUTION
Note
These functions open files and should only be used to open known-safe pathnames.

dlopen

void *dlopen(const char *pathname, int mode)
Category
USE WITH CAUTION
Note
Parameters passed to dlopen 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.

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)
Category
AVOID
Note
These are weak random number generators; they are not useful for increasing security. If you need random numbers for security, it's better to use /dev/urandom, which is available starting with Solaris 9.

execvp

int execvp(const char *file, const char *argv[])
int execlp(const char *file, const char *arg0, ..., const char *argn, NULL)
Category
AVOID
Note
These functions are 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.
Alternative
Carefully use one of the exec* functions defined below.

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[])
Category
USE WITH CAUTION
Note
Make sure that the environment is sanitized and unneeded file descriptors are closed before executing a new program.

fattach

int fattach(int filedes, const char *path)
Category
USE WITH CAUTION
Note
Check the file descriptor after open (using fstat()), not the pathname before the open.

sprintf

int sprintf(char *s, const char *fmt, ...)
int vsprintf(char *s, const char *fmt, va_list ap)
Category
AVOID
Note
sprintf() and vsprintf() are typical buffer overflow causes. If, for whatever reason, you must use these functions, make sure that the fmt argument can't be user-controlled and that you can trust the parameters not to overflow the destination buffer.
Alternative
snprintf()/vsnprintf()

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, ...)
Category
USE WITH CAUTION
Note
At risk from user-specified format strings. If the format string comes from a message catalog, verify your NLSPATH manipulations and catopen()/catget() uses. (The C library tries to be safe by ignoring NLSPATH settings for set-uid and set-gid applications.)
Note
snprintf() and vsnprintf() return the number of characters that would have been written to the buffer if it were large enough. You can't use this value in constructs like:
p += snprintf(p, lenp, "...");
 since p might point beyond p+lenp afterwards.

syslog

void syslog(int priority, const char *message, ...)
void vsyslog(int priority, const char *message, va_list ap)
Category
USE WITH CAUTION
Note
At risk from user-specified format strings. Verify your NLSPATH manipulations and catopen()/catget() uses.

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)
Category
USE WITH CAUTION
Note
When scanning strings, make sure the format specified includes maximum buffer lengths, thus use
scanf("%10s", p);
 to limit scanf() to reading 10 characters at most. Note that the corresponding buffer must be at least eleven bytes to allow space for the terminating NUL character.

ftw

int ftw(const char *path, int (*fn)(), int depth)
int nftw(const char *path, int (*fn)(), int depth, int flags)
Category
USE WITH CAUTION
Note
ftw follows symbolic links and crosses mount points.
Alternative
use nftw with the appropriate flags set (a combination of FTW_PHYS and FTW_MOUNT).

getenv

char *getenv(const char *name)
Category
USE WITH CAUTION
Note
The environment is completely user-specified. When possible, use of getenv() should be avoided in libraries. Strings returned by getenv() can be up to NCARGS bytes long (that's 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()).

getlogin

char *getlogin(void)
Category
AVOID
Note
The value returned by getlogin() is not reliable; it is a mere hint as to the user name.

getpass

char *getpass(const char *prompt)
Category
AVOID
Note
Only the first 8 bytes of input are used. Avoid using it in new code.
Alternative
getpassphrase().

kvm_open

kvm_t *kvm_open(char *namelist, char *corefile, char *swapfile, int flag, char *errstr)
int nlist(const char *filename, struct nlist *nl)
Category
AVOID
Note
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. If you don't, a specifically constructed namelist can be used to read random parts of the kernel, revealing possibly sensitive data.

mkdir

int mkdir(const char *path, mode_t mode)
int mknod(const char *path, mode_t mode, dev_t dev)
Category
USE WITH CAUTION
Note
Be careful about the path used. mkdir() and mknod() will not follow symlinks for the last component, so they are relatively safe.

mkstemp

int mkstemp(char *template)
Category
UNRESTRICTED
Note
Safe temporary file creation function.

mktemp

char *mktemp(char *template)
Category
AVOID
Note
Generates temporary filename, but the use of the generated pathname is not guaranteed safe since there is a race condition between the checks in mktemp() and the subsequent open() by the application.
Alternative
Use mkstemp().

popen

FILE *popen(const char *command, const char *mode)
int p2open(const char *cmd, FILE *fp[2])
int system(const char *string)
Category
AVOID
Note
These three library calls always involve the shell which involves PATH, IFS, other environment variables and interpretation of special characters.

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)
Category
USE WITH CAUTION
Note
Similar problems as with strcpy(). See the manual pages on proper use.

tempnam

char *tempnam(const char *dir, const char *pfx)
char *tmpnam(char *s)
char *tmpnam_r(char *s)
Category
AVOID
Note
These functions are not suitable for generating unpredictable filenames. There is a race condition between the generation of the filename and its use in, e.g., open()
Alternative
mkstemp()

tmpfile

FILE *tmpfile(void)
Category
USE WITH CAUTION
Note
Uses mkstemp() since Solaris 2.6 or thereabouts, so is safe to use. However: since this function changes the umask, it is not multi-thread safe.

truncate

int truncate(const char *path, off_t length)
Category
AVOID
Note
This function is prone to pathname race conditions.
Alternative
Use ftruncate() after a safe open().

umask

mode_t umask(mode_t cmask)
Category
USE WITH CAUTION
Note
Shouldn't be used in libraries or applications; the user knows best and his umask should be used. Also not multi-thread safe.

utmpname

int utmpname(const char *file)
int utmpxname(const char *file)
Category
AVOID
Note
Use the default utmp and utmpx files.
last modified by admin on 2009/11/11 10:54
Collectives
Project


© Sun Microsystems Inc. 2009
XWiki Enterprise 1.8.2.19075 - Documentation
Terms Of Use | Privacy | Trademarks | Copyright Policy | Site Guidelines | Site map | Help
Your use of this web site or any of its content or software indicates your agreement to be bound by these Terms of Use.