From: Karel Zak Date: Fri, 30 Oct 2015 10:08:32 +0000 (+0100) Subject: lib/sysfs: make sysfs_get_devname()/blkid_devno_to_wholedisk() more robust X-Git-Tag: v2.27.1~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4bee4ece7393b43159b38e80173bcbf3c781c2e8;p=thirdparty%2Futil-linux.git lib/sysfs: make sysfs_get_devname()/blkid_devno_to_wholedisk() more robust Now the function uses result buffer for internal stuff (readlink), so it requires that the buffer is large enough. This is unexpected as caller assumes that the buffer has to be large enough for devname only. References: http://www.spinics.net/lists/util-linux-ng/msg12015.html Reported-by: Tom Yan Signed-off-by: Karel Zak --- diff --git a/lib/sysfs.c b/lib/sysfs.c index d2146d5fb9..51ec2bfe23 100644 --- a/lib/sysfs.c +++ b/lib/sysfs.c @@ -125,9 +125,6 @@ dev_t sysfs_devname_to_devno(const char *name, const char *parent) /* * Returns devname (e.g. "/dev/sda1") for the given devno. * - * Note that the @buf has to be large enough to store /sys/dev/block/ - * symlinks. - * * Please, use more robust blkid_devno_to_devname() in your applications. */ char *sysfs_devno_to_devpath(dev_t devno, char *buf, size_t bufsiz) @@ -544,28 +541,28 @@ err: return NULL; } -/* - * Note that the @buf has to be large enough to store /sys/dev/block/ - * symlinks. - */ char *sysfs_get_devname(struct sysfs_cxt *cxt, char *buf, size_t bufsiz) { - char *name = NULL; - ssize_t sz; + char linkpath[PATH_MAX]; + char *name; + ssize_t sz; - sz = sysfs_readlink(cxt, NULL, buf, bufsiz - 1); + sz = sysfs_readlink(cxt, NULL, linkpath, sizeof(linkpath) - 1); if (sz < 0) return NULL; + linkpath[sz] = '\0'; - buf[sz] = '\0'; - name = strrchr(buf, '/'); + name = strrchr(linkpath, '/'); if (!name) return NULL; name++; sz = strlen(name); - memmove(buf, name, sz + 1); + if ((size_t) sz + 1 > bufsiz) + return NULL; + + memcpy(buf, name, sz + 1); sysfs_devname_sys_to_dev(buf); return buf; @@ -1024,8 +1021,9 @@ int main(int argc, char *argv[]) { struct sysfs_cxt cxt = UL_SYSFSCXT_EMPTY; char *devname; - dev_t devno; + dev_t devno, disk_devno; char path[PATH_MAX], *sub, *chain; + char diskname[32]; int i, is_part; uint64_t u64; ssize_t len; @@ -1039,16 +1037,24 @@ int main(int argc, char *argv[]) if (!devno) err(EXIT_FAILURE, "failed to read devno"); - is_part = sysfs_devno_has_attribute(devno, "partition"); + if (sysfs_init(&cxt, devno, NULL)) + return EXIT_FAILURE; printf("NAME: %s\n", devname); - printf("DEVNO: %u (%d:%d)\n", (unsigned int) devno, major(devno), minor(devno)); - printf("DEVNOPATH: %s\n", sysfs_devno_path(devno, path, sizeof(path))); + printf("DEVNAME: %s\n", sysfs_get_devname(&cxt, path, sizeof(path))); printf("DEVPATH: %s\n", sysfs_devno_to_devpath(devno, path, sizeof(path))); + printf("DEVNO: %u (%d:%d)\n", (unsigned int) devno, major(devno), minor(devno)); + printf("DEVNO-PATH: %s\n", sysfs_devno_path(devno, path, sizeof(path))); + + sysfs_devno_to_wholedisk(devno, diskname, sizeof(diskname), &disk_devno); + printf("WHOLEDISK-DEVNO: %u (%d:%d)\n", (unsigned int) disk_devno, major(disk_devno), minor(disk_devno)); + printf("WHOLEDISK-DEVNAME: %s\n", diskname); + + is_part = sysfs_devno_has_attribute(devno, "partition"); printf("PARTITION: %s\n", is_part ? "YES" : "NOT"); - if (sysfs_init(&cxt, devno, NULL)) - return EXIT_FAILURE; + printf("HOTPLUG: %s\n", sysfs_is_hotpluggable(&cxt) ? "yes" : "no"); + printf("SLAVES: %d\n", sysfs_count_dirents(&cxt, "slaves")); len = sysfs_readlink(&cxt, NULL, path, sizeof(path) - 1); if (len > 0) { @@ -1065,8 +1071,6 @@ int main(int argc, char *argv[]) } } - printf("SLAVES: %d\n", sysfs_count_dirents(&cxt, "slaves")); - if (sysfs_read_u64(&cxt, "size", &u64)) printf("read SIZE failed\n"); else @@ -1077,8 +1081,6 @@ int main(int argc, char *argv[]) else printf("SECTOR: %d\n", i); - printf("DEVNAME: %s\n", sysfs_get_devname(&cxt, path, sizeof(path))); - printf("HOTPLUG: %s\n", sysfs_is_hotpluggable(&cxt) ? "yes" : "no"); chain = sysfs_get_devchain(&cxt, path, sizeof(path)); printf("SUBSUSTEMS:\n");