/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
* cramfsck - check a cramfs file system
*
* Copyright (C) 2000-2002 Transmeta Corporation
fputs(_(" -b, --blocksize <size> use this blocksize, defaults to page size\n"), out);
fputs(_(" --extract[=<dir>] test uncompression, optionally extract into <dir>\n"), out);
fputs(USAGE_SEPARATOR, out);
- printf(USAGE_HELP_OPTIONS(26));
+ fprintf(out, USAGE_HELP_OPTIONS(26));
- printf(USAGE_MAN_TAIL("fsck.cramfs(8)"));
+ fprintf(out, USAGE_MAN_TAIL("fsck.cramfs(8)"));
exit(FSCK_EX_OK);
}
if (S_ISLNK(i->mode))
return;
if (((S_ISUID | S_ISGID) & i->mode) && chmod(path, i->mode) < 0)
- err(FSCK_EX_ERROR, _("chown failed: %s"), path);
+ err(FSCK_EX_ERROR, _("chmod failed: %s"), path);
}
if (S_ISLNK(i->mode))
return;
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);
}
while (count > 0) {
struct cramfs_inode *child = iget(offset);
+ char *name;
int size;
int newlen = child->namelen << 2;
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"));