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:
parent
2384fa6e4d
commit
9dbae34c3d
23
lib/path.c
23
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)
|
ssize_t ul_path_readlink(struct path_cxt *pc, char *buf, size_t bufsiz, const char *path)
|
||||||
{
|
{
|
||||||
int dirfd;
|
int dirfd;
|
||||||
|
ssize_t ssz;
|
||||||
|
|
||||||
if (!path) {
|
if (!path) {
|
||||||
const char *p = get_absdir(pc);
|
const char *p = get_absdir(pc);
|
||||||
if (!p)
|
if (!p)
|
||||||
return -errno;
|
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 (ssz >= 0)
|
||||||
if (dirfd < 0)
|
buf[ssz] = '\0';
|
||||||
return dirfd;
|
return ssz;
|
||||||
|
|
||||||
if (*path == '/')
|
|
||||||
path++;
|
|
||||||
|
|
||||||
return readlinkat(dirfd, path, buf, bufsiz);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
11
lib/sysfs.c
11
lib/sysfs.c
|
@ -182,10 +182,9 @@ char *sysfs_blkdev_get_name(struct path_cxt *pc, char *buf, size_t bufsiz)
|
||||||
ssize_t sz;
|
ssize_t sz;
|
||||||
|
|
||||||
/* read /sys/dev/block/<maj:min> link */
|
/* 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)
|
if (sz < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
link[sz] = '\0';
|
|
||||||
|
|
||||||
name = strrchr(link, '/');
|
name = strrchr(link, '/');
|
||||||
if (!name)
|
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)
|
if (sz <= 0 || sz + sizeof(_PATH_SYS_DEVBLOCK "/") > bufsz)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
buf[sz++] = '\0';
|
sz++;
|
||||||
prefix = ul_path_get_prefix(pc);
|
prefix = ul_path_get_prefix(pc);
|
||||||
if (prefix)
|
if (prefix)
|
||||||
psz = strlen(prefix);
|
psz = strlen(prefix);
|
||||||
|
@ -567,10 +566,9 @@ int sysfs_blkdev_get_wholedisk( struct path_cxt *pc,
|
||||||
char *name;
|
char *name;
|
||||||
ssize_t linklen;
|
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)
|
if (linklen < 0)
|
||||||
goto err;
|
goto err;
|
||||||
linkpath[linklen] = '\0';
|
|
||||||
|
|
||||||
stripoff_last_component(linkpath); /* dirname */
|
stripoff_last_component(linkpath); /* dirname */
|
||||||
name = stripoff_last_component(linkpath); /* basename */
|
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;
|
goto done;
|
||||||
|
|
||||||
blk->hctl_error = 1;
|
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)
|
if (len < 0)
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
buf[len] = '\0';
|
|
||||||
hctl = strrchr(buf, '/');
|
hctl = strrchr(buf, '/');
|
||||||
if (!hctl)
|
if (!hctl)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Reference in New Issue