]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
fsck.cramfs: check directory entry names
authorSamanta Navarro <ferivoz@riseup.net>
Thu, 26 Jan 2023 11:56:42 +0000 (11:56 +0000)
committerKarel Zak <kzak@redhat.com>
Thu, 26 Jan 2023 15:58:32 +0000 (16:58 +0100)
Do not accept slashes in names or the special entries "." and ".." in
directories while extracting files.

[kzak@redhat.com: - add errx_path() to report the path]

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
Signed-off-by: Karel Zak <kzak@redhat.com>
disk-utils/fsck.cramfs.c

index 7503fae2fbb137c90bd06e61886eef8f56719eb8..943f52e43f23bb14239e5daf34aa191c2dee2c72 100644 (file)
@@ -442,6 +442,23 @@ static void change_file_status(char *path, struct cramfs_inode *i)
                err(FSCK_EX_ERROR, _("utimes failed: %s"), path);
 }
 
+static int is_dangerous_filename(char *name, int len)
+{
+       return (len == 1 && name[0] == '.') ||
+              (len == 2 && name[0] == '.' && name[1] == '.');
+}
+
+static void __attribute__((__noreturn__))
+       errx_path(const char *mesg, const char *name, size_t namelen)
+{
+       char buf[PATH_MAX] = { 0 };
+
+       namelen = min(namelen, sizeof(buf) - 1);
+       memcpy(buf, name, namelen);
+
+       errx(FSCK_EX_UNCORRECTED, "%s: %s", mesg, buf);
+}
+
 static void do_directory(char *path, struct cramfs_inode *i)
 {
        int pathlen = strlen(path);
@@ -471,6 +488,7 @@ static void do_directory(char *path, struct cramfs_inode *i)
        }
        while (count > 0) {
                struct cramfs_inode *child = iget(offset);
+               char *name;
                int size;
                int newlen = child->namelen << 2;
 
@@ -478,8 +496,13 @@ static void do_directory(char *path, struct cramfs_inode *i)
                count -= size;
 
                offset += sizeof(struct cramfs_inode);
+               name = romfs_read(offset);
 
-               memcpy(newpath + pathlen, romfs_read(offset), newlen);
+               if (memchr(name, '/', newlen) != NULL)
+                       errx_path(_("illegal filename"), name, newlen);
+               if (*extract_dir != '\0' && is_dangerous_filename(name, newlen))
+                       errx_path(_("dangerous filename"), name, newlen);
+               memcpy(newpath + pathlen, name, newlen);
                newpath[pathlen + newlen] = 0;
                if (newlen == 0)
                        errx(FSCK_EX_UNCORRECTED, _("filename length is zero"));