DF-0134 / setlabel.c
/* * DF-0134 contrast — read the crafted (out-of-slice) disklabel64 from the * image file (already CRC-correct, written by craft_label) and attempt * DIOCSDINFO64 (the write/set path, which DOES validate via l64_setdisklabel). * It must be rejected with EINVAL, proving the read/set asymmetry. * * Build: cc -o setlabel setlabel.c * Run: ./setlabel <image> /dev/vnXs0 */ #include <stdio.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/disklabel64.h> int main(int argc, char **argv) { struct disklabel64 *lp; char buf[sizeof(struct disklabel64)]; int imgfd, devfd, rc; if (argc < 3) { fprintf(stderr, "usage: %s <image> /dev/vnXs0\n", argv[0]); return 2; } imgfd = open(argv[1], O_RDONLY); if (imgfd < 0) { perror("open image"); return 1; } if (read(imgfd, buf, sizeof(buf)) != (ssize_t)sizeof(buf)) { perror("read image"); close(imgfd); return 1; } close(imgfd); lp = (struct disklabel64 *)buf; printf("[*] loaded crafted label from %s: part[1] end=%llu " "(d_total_size=%llu)\n", argv[1], (unsigned long long)(lp->d_partitions[1].p_boffset + lp->d_partitions[1].p_bsize), (unsigned long long)lp->d_total_size); devfd = open(argv[2], O_RDWR); if (devfd < 0) { perror("open device"); return 1; } printf("[*] attempting DIOCSDINFO64 (set path, which validates)...\n"); rc = ioctl(devfd, DIOCSDINFO64, lp); printf(" DIOCSDINFO64 rc=%d errno=%d (%s)\n", rc, errno, rc ? strerror(errno) : "success"); if (rc && errno == EINVAL) printf("[*] SET path REJECTED the out-of-slice label (EINVAL) — " "confirms read path (readdisklabel) lacks the validation " "that set path (setdisklabel) has\n"); close(devfd); return (rc && errno == EINVAL) ? 0 : 1; } |