The readlink() function reads where a link points to. It is unusual, as makes no effort to null terminate its second argument, buffer
. Instead, it just returns the number of characters it has written.
Non-Compliant Coding Example
If len
is equal to sizeof(buf)
, the null terminator will be written one byte past the end of buf
.
char buf[256]; ssize_t len = readlink("/usr/bin/perl", buf, sizeof(buf)); buf[len] = '\0';
A simple (but incorrect) solution to this problem is to try to make buf
large enough that it can always hold the result:
Unknown macro: {code bgColor=#ffcccc}
char buf[PATH_MAX+1];
ssize_t len = readlink("/usr/bin/perl", buf, sizeof(buf));
buf[len] = '\0';
This "fix" 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 so the off-by-one buffer overflow risk is still present. An additional issue is that {{readlink()}} can return {{-1}} if it fails, causing an off-by-one underflow. h2. Compliant Solution {code:bgColor=#ccccff} char buf[256]; ssizet_t len; if ((len = readlink("/usr/bin/perl", buf, sizeof(buf)-1)) != -1) buf[len] = '\0'; else { /* handle error condition */ }
Risk Analysis
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
POS30-C |
1 (low) |
2 (probable) |
2 (medium) |
P4 |
L3 |
References
[[ilja 06]]
[[Open Group 97]]
[[Open Group 04]]