diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libspl/os/linux/zone.c | 2 | ||||
-rw-r--r-- | lib/libzfs/os/freebsd/libzfs_compat.c | 2 | ||||
-rw-r--r-- | lib/libzpool/kernel.c | 29 |
3 files changed, 31 insertions, 2 deletions
diff --git a/lib/libspl/os/linux/zone.c b/lib/libspl/os/linux/zone.c index e37b34975..622d04cbc 100644 --- a/lib/libspl/os/linux/zone.c +++ b/lib/libspl/os/linux/zone.c @@ -41,7 +41,7 @@ getzoneid(void) int c = snprintf(path, sizeof (path), "/proc/self/ns/user"); /* This API doesn't have any error checking... */ - if (c < 0) + if (c < 0 || c >= sizeof (path)) return (0); ssize_t r = readlink(path, buf, sizeof (buf) - 1); diff --git a/lib/libzfs/os/freebsd/libzfs_compat.c b/lib/libzfs/os/freebsd/libzfs_compat.c index f4900943c..5e280cbae 100644 --- a/lib/libzfs/os/freebsd/libzfs_compat.c +++ b/lib/libzfs/os/freebsd/libzfs_compat.c @@ -202,7 +202,7 @@ libzfs_error_init(int error) size_t msglen = sizeof (errbuf); if (modfind("zfs") < 0) { - size_t len = snprintf(msg, msglen, dgettext(TEXT_DOMAIN, + size_t len = kmem_scnprintf(msg, msglen, dgettext(TEXT_DOMAIN, "Failed to load %s module: "), ZFS_KMOD); msg += len; msglen -= len; diff --git a/lib/libzpool/kernel.c b/lib/libzpool/kernel.c index 1f58acb04..1d4647094 100644 --- a/lib/libzpool/kernel.c +++ b/lib/libzpool/kernel.c @@ -956,6 +956,35 @@ kmem_asprintf(const char *fmt, ...) return (buf); } +/* + * kmem_scnprintf() will return the number of characters that it would have + * printed whenever it is limited by value of the size variable, rather than + * the number of characters that it did print. This can cause misbehavior on + * subsequent uses of the return value, so we define a safe version that will + * return the number of characters actually printed, minus the NULL format + * character. Subsequent use of this by the safe string functions is safe + * whether it is snprintf(), strlcat() or strlcpy(). + */ +int +kmem_scnprintf(char *restrict str, size_t size, const char *restrict fmt, ...) +{ + int n; + va_list ap; + + /* Make the 0 case a no-op so that we do not return -1 */ + if (size == 0) + return (0); + + va_start(ap, fmt); + n = vsnprintf(str, size, fmt, ap); + va_end(ap); + + if (n >= size) + n = size - 1; + + return (n); +} + zfs_file_t * zfs_onexit_fd_hold(int fd, minor_t *minorp) { |