Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144385338
D19824.id55822.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D19824.id55822.diff
View Options
Index: head/sbin/fsck_msdosfs/dir.c
===================================================================
--- head/sbin/fsck_msdosfs/dir.c
+++ head/sbin/fsck_msdosfs/dir.c
@@ -444,7 +444,78 @@
return FSOK;
}
+static const u_char dot_name[] = {
+ '.', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ' };
+static const u_char dotdot_name[] = {
+ '.', '.',' ',' ',' ',' ',' ',' ',' ',' ',' ' };
+
/*
+ * Basic sanity check if the subdirectory have good '.' and '..' entries,
+ * and they are directory entries. Further sanity checks are performed
+ * when we traverse into it.
+ */
+static int
+check_subdirectory(int f, struct bootblock *boot, struct dosDirEntry *dir)
+{
+ u_char *buf, *cp;
+ off_t off;
+ cl_t cl;
+ int retval = FSOK;
+
+ cl = dir->head;
+ if (dir->parent && (cl < CLUST_FIRST || cl >= boot->NumClusters)) {
+ return FSERROR;
+ }
+
+ if (!(boot->flags & FAT32) && !dir->parent) {
+ off = boot->bpbResSectors + boot->bpbFATs *
+ boot->FATsecs;
+ } else {
+ off = cl * boot->bpbSecPerClust + boot->ClusterOffset;
+ }
+
+ /*
+ * We only need to check the first two entries of the directory,
+ * which is found in the first sector of the directory entry,
+ * so read in only the first sector.
+ */
+ buf = malloc(boot->bpbBytesPerSec);
+ if (buf == NULL) {
+ perr("No space for directory buffer (%u)",
+ boot->bpbBytesPerSec);
+ return FSFATAL;
+ }
+
+ off *= boot->bpbBytesPerSec;
+ if (lseek(f, off, SEEK_SET) != off ||
+ read(f, buf, boot->bpbBytesPerSec) != boot->bpbBytesPerSec) {
+ perr("Unable to read directory");
+ free(buf);
+ return FSFATAL;
+ }
+
+ /*
+ * Both `.' and `..' must be present and be the first two entries
+ * and be ATTR_DIRECTORY of a valid subdirectory.
+ */
+ cp = buf;
+ if (memcmp(cp, dot_name, sizeof(dot_name)) != 0 ||
+ (cp[11] & ATTR_DIRECTORY) != ATTR_DIRECTORY) {
+ pwarn("%s: Incorrect `.' for %s.\n", __func__, dir->name);
+ retval |= FSERROR;
+ }
+ cp += 32;
+ if (memcmp(cp, dotdot_name, sizeof(dotdot_name)) != 0 ||
+ (cp[11] & ATTR_DIRECTORY) != ATTR_DIRECTORY) {
+ pwarn("%s: Incorrect `..' for %s. \n", __func__, dir->name);
+ retval |= FSERROR;
+ }
+
+ free(buf);
+ return retval;
+}
+
+/*
* Read a directory and
* - resolve long name records
* - enter file and directory records into the parent's list
@@ -491,9 +562,6 @@
return FSFATAL;
}
last /= 32;
- /*
- * Check `.' and `..' entries here? XXX
- */
for (p = buffer, i = 0; i < last; i++, p += 32) {
if (dir->fsckflags & DIREMPWARN) {
*p = SLOT_EMPTY;
@@ -830,6 +898,36 @@
}
}
continue;
+ } else {
+ /*
+ * Only one directory entry can point
+ * to dir->head, it's '.'.
+ */
+ if (dirent.head == dir->head) {
+ pwarn("%s entry in %s has incorrect start cluster\n",
+ dirent.name, fullpath(dir));
+ if (ask(1, "Remove")) {
+ *p = SLOT_DELETED;
+ mod |= THISMOD|FSDIRMOD;
+ } else
+ mod |= FSERROR;
+ continue;
+ } else if ((check_subdirectory(f, boot,
+ &dirent) & FSERROR) == FSERROR) {
+ /*
+ * A subdirectory should have
+ * a dot (.) entry and a dot-dot
+ * (..) entry of ATTR_DIRECTORY,
+ * we will inspect further when
+ * traversing into it.
+ */
+ if (ask(1, "Remove")) {
+ *p = SLOT_DELETED;
+ mod |= THISMOD|FSDIRMOD;
+ } else
+ mod |= FSERROR;
+ continue;
+ }
}
/* create directory tree node */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 9, 4:23 AM (22 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28536471
Default Alt Text
D19824.id55822.diff (3 KB)
Attached To
Mode
D19824: Implement checking of `.' and `..' entries of subdirectory.
Attached
Detach File
Event Timeline
Log In to Comment