]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lib/path: improve ul_path_readlink() to be more robust
authorKarel Zak <kzak@redhat.com>
Thu, 17 Jun 2021 11:28:32 +0000 (13:28 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 17 Jun 2021 11:28:32 +0000 (13:28 +0200)
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>
lib/path.c
lib/sysfs.c

index 058c143f40a6b9128a0e5104c6555f5c76e877a3..7576328d7cd230cc0073a46850a89a8746cee4b8 100644 (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;
 
-       dirfd = ul_path_get_dirfd(pc);
-       if (dirfd < 0)
-               return dirfd;
+               if (*path == '/')
+                       path++;
 
-       if (*path == '/')
-               path++;
+               ssz = readlinkat(dirfd, path, buf, bufsiz - 1);
+       }
 
-       return readlinkat(dirfd, path, buf, bufsiz);
+       if (ssz >= 0)
+               buf[ssz] = '\0';
+       return ssz;
 }
 
 /*
index 3b75a2398b4ed3a5bcbff11b067886e2e73a6f8c..bb718331931881d656e40071a04c7d8493743875 100644 (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;