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 <jpazdziora@redhat.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2021-06-17 13:28:32 +02:00
parent 2384fa6e4d
commit 9dbae34c3d
2 changed files with 18 additions and 16 deletions

View File

@ -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;
}
/*

View File

@ -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/<maj:min> 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;