Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The readlink() function reads where a link points to. It makes no effort to null-terminate its second argument, buffer. Instead, it just returns the number of characters it has written.

...

Noncompliant Code Example

If len is equal to sizeof(buf), the null terminator will be written one is written 1 byte past the end of buf.:

Code Block
bgColor#FFcccc
langc

char buf[2561024];
ssize_t len = readlink("/usr/bin/perl", buf, sizeof(buf));
buf[len] = '\0';

A simple (but An incorrect ) solution to this problem is to try to make buf large enough that it can always hold the result:

Code Block
bgColor#ffcccc
langc
long symlink_max;
size_t bufsize;
char buf[PATH_MAX+1];
ssize_t *buf;
ssize_t len;

errno = 0;
symlink_max = pathconf("/usr/bin/", _PC_SYMLINK_MAX);
if (symlink_max == -1) {
  if (errno != 0) {
    /* handle error condition */
  }
  bufsize = 10000;
}
else {
  bufsize = symlink_max+1;
}

buf = (char *)malloc(bufsize);
if (buf == NULL) {
  /* handle error condition */
}

len = readlink("/usr/bin/perl", buf, sizeof(bufbufsize));
buf[len] = '\0';

This "fix" modification incorrectly assumes that PATH_MAX represents the longest possible path for a file in the filesystem. (PATH_MAX only bounds the longest possible relative path that can be passed to the kernel in a single call.) On most Unix and Linux systems, there is no easily-determined maximum length for a file path, and the symbolic link cannot be longer than the value of SYMLINK_MAX returned by pathconf(). However, the value returned by pathconf() is out of date by the time readlink() is called, so the off-by-one buffer-overflow risk is still present because, between the two calls, the location of /usr/bin/perl can change to a file system with a larger SYMLINK_MAX value. Also, if SYMLINK_MAX is indeterminate (that is, if pathconf() returned -1 without setting errno), the code uses an arbitrary large buffer size (10,000) that it hopes will be sufficient, but there is a small chance that readlink() can return exactly this size.

An additional issue is that readlink() can return -1 if it fails, causing an off-by-one underflow.

Compliant Solution

This example compliant solution ensures there will be is no overflow by only reading in only sizeof(buf)-1 characters. It also properly checks to see if an error has occurred.:

Code Block
bgColor#ccccff
langc
enum { BUFFERSIZE = 1024 };
char buf[256BUFFERSIZE];
ssizetssize_t len;

if ((len = readlink("/usr/bin/perl", buf, sizeof(buf)-1));

if (len != -1) {
    buf[len] = '\0';
}
else {
   /* handle error condition */
}

Risk

...

Assessment

Failing to properly null-terminate the result of readlink() can result in abnormal program termination and buffer-overflow vulnerabilities.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

POS30-C

high

probable

medium

P12

L1

Automated Detection

Tool

Version

Checker

Description

Astrée
Include Page
Astrée_V
Astrée_V


Supported: Can be checked with appropriate analysis stubs.
Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC-POS30
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

LANG.MEM.BO
LANG.MEM.TBA
MISC.MEM.NTERM.CSTRING

Buffer Overrun
Tainted Buffer Access
Unterminated C String

Compass/ROSE




Coverity
Include Page
Coverity_V
Coverity_V

READLINK

Implemented
Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C5033
Klocwork

Include Page
Klocwork_V
Klocwork_V

ABV.GENERAL
ABV.GENERAL.MULTIDIMENSION


Parasoft C/C++test
Include Page
Parasoft_V
Parasoft_V

CERT_C-POS30-a
CERT_C-POS30-b
CERT_C-POS30-c

Avoid overflow due to reading a not zero terminated string
The values returned by functions 'read' and 'readlink' shall be used
Use of possibly not null-terminated string with functions expecting null-terminated string

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rule POS30-C

1 (low)

2 (probable)

2 (medium)

P4

L3

References

Checks for misuse of readlink() (rule partially covered)

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Related Guidelines

Key here (explains table format and definitions)

Taxonomy

Taxonomy item

Relationship

CWE 2.11CWE-170, Improper null termination2017-06-13: CERT: Rule subset of CWE

CERT-CWE Mapping Notes

Key here for mapping notes

CWE-170 and POS30-C

CWE-170 = Union( POS30-C, list) where list =


  • Non-null terminated strings fed to functions other than POSIX readlink()


Bibliography


...

Image AddedImage AddedImage Added Wiki Markup\[[ilja 06|AA. C References#ilja 06]\] \[[Open Group 97|AA. C References#Open Group 97]\] \[[Open Group 04|AA. C References#Open Group 04]\]