From 9dbae34c3da7667319df2191b4b0fee6552dd0e3 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 17 Jun 2021 13:28:32 +0200 Subject: [PATCH] lib/path: improve ul_path_readlink() to be more robust According to POSIX, readlink() makes no effort to null-terminate buffer with the result. It seems better to hide this disadvantage in the ul_path_...() API rather than assume buf[sz] = '\0' everywhere. Reported-by: Reported-by: Jan Pazdziora Signed-off-by: Karel Zak --- lib/path.c | 23 ++++++++++++++--------- lib/sysfs.c | 11 ++++------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/path.c b/lib/path.c index 058c143f4..7576328d7 100644 --- a/lib/path.c +++ b/lib/path.c @@ -542,22 +542,27 @@ DIR *ul_path_opendirf(struct path_cxt *pc, const char *path, ...) ssize_t ul_path_readlink(struct path_cxt *pc, char *buf, size_t bufsiz, const char *path) { int dirfd; + ssize_t ssz; if (!path) { const char *p = get_absdir(pc); if (!p) return -errno; - return readlink(p, buf, bufsiz); + ssz = readlink(p, buf, bufsiz - 1); + } else { + dirfd = ul_path_get_dirfd(pc); + if (dirfd < 0) + return dirfd; + + if (*path == '/') + path++; + + ssz = readlinkat(dirfd, path, buf, bufsiz - 1); } - dirfd = ul_path_get_dirfd(pc); - if (dirfd < 0) - return dirfd; - - if (*path == '/') - path++; - - return readlinkat(dirfd, path, buf, bufsiz); + if (ssz >= 0) + buf[ssz] = '\0'; + return ssz; } /* diff --git a/lib/sysfs.c b/lib/sysfs.c index 3b75a2398..bb7183319 100644 --- a/lib/sysfs.c +++ b/lib/sysfs.c @@ -182,10 +182,9 @@ char *sysfs_blkdev_get_name(struct path_cxt *pc, char *buf, size_t bufsiz) ssize_t sz; /* read /sys/dev/block/ link */ - sz = ul_path_readlink(pc, link, sizeof(link) - 1, NULL); + sz = ul_path_readlink(pc, link, sizeof(link), NULL); if (sz < 0) return NULL; - link[sz] = '\0'; name = strrchr(link, '/'); if (!name) @@ -393,7 +392,7 @@ char *sysfs_blkdev_get_devchain(struct path_cxt *pc, char *buf, size_t bufsz) if (sz <= 0 || sz + sizeof(_PATH_SYS_DEVBLOCK "/") > bufsz) return NULL; - buf[sz++] = '\0'; + sz++; prefix = ul_path_get_prefix(pc); if (prefix) psz = strlen(prefix); @@ -567,10 +566,9 @@ int sysfs_blkdev_get_wholedisk( struct path_cxt *pc, char *name; ssize_t linklen; - linklen = ul_path_readlink(pc, linkpath, sizeof(linkpath) - 1, NULL); + linklen = ul_path_readlink(pc, linkpath, sizeof(linkpath), NULL); if (linklen < 0) goto err; - linkpath[linklen] = '\0'; stripoff_last_component(linkpath); /* dirname */ name = stripoff_last_component(linkpath); /* basename */ @@ -678,11 +676,10 @@ int sysfs_blkdev_scsi_get_hctl(struct path_cxt *pc, int *h, int *c, int *t, int goto done; blk->hctl_error = 1; - len = ul_path_readlink(pc, buf, sizeof(buf) - 1, "device"); + len = ul_path_readlink(pc, buf, sizeof(buf), "device"); if (len < 0) return len; - buf[len] = '\0'; hctl = strrchr(buf, '/'); if (!hctl) return -1;