The readlabel() function in disklabel() does two things: it reads the
disklabel from the device using a ioctl() and then parses it into some
strings. We can't pledge beforehand since we have no way of knowing the
file we process is actually a disk device. However, once the ioctl()
succeeds, we know that we deal with a disk and we can do all further
processing of the untrusted data under pledge.
Thus, split up readlabel() into two functions, and pledge between the
two function calls. This seems cleaner than moving some of the pledging
into readlabel, because this would make the different pledge regimes
harder to discern.
I tested the diff with make release on amd64.
Index: disklabel.c
===================================================================
RCS file: /var/cvs/src/sbin/disklabel/disklabel.c,v
retrieving revision 1.219
diff -u -p -r1.219 disklabel.c
--- disklabel.c 29 May 2016 17:02:21 -0000 1.219
+++ disklabel.c 29 May 2016 20:41:50 -0000
@@ -206,20 +206,26 @@ main(int argc, char *argv[])
if (f < 0)
err(4, "%s", specname);
- if (op != WRITE || aflag || dflag)
+ if (op != WRITE || aflag || dflag) {
readlabel(f);
- else if (argc == 2 || argc == 3)
+
+ if (op == EDIT || op == EDITOR || aflag) {
+ if (pledge("stdio rpath wpath cpath disklabel proc "
+ "exec", NULL) == -1)
+ err(1, "pledge");
+ } else {
+ if (pledge("stdio rpath wpath disklabel", NULL) == -1)
+ err(1, "pledge");
+ }
+
+ parselabel();
+ } else if (argc == 2 || argc == 3) {
makelabel(argv[1], argc == 3 ? argv[2] : NULL, &lab);
- else
- usage();
- if (op == EDIT || op == EDITOR || aflag) {
- if (pledge("stdio rpath wpath cpath disklabel proc exec", NULL)
== -1)
- err(1, "pledge");
- } else {
if (pledge("stdio rpath wpath disklabel", NULL) == -1)
err(1, "pledge");
- }
+ } else
+ usage();
if (autotable != NULL)
parse_autotable(autotable);
@@ -353,9 +359,6 @@ l_perror(char *s)
void
readlabel(int f)
{
- char *partname, *partduid;
- struct fstab *fsent;
- int i;
if (cflag && ioctl(f, DIOCRLDINFO) < 0)
err(4, "ioctl DIOCRLDINFO");
@@ -367,6 +370,14 @@ readlabel(int f)
if (ioctl(f, DIOCGDINFO, &lab) < 0)
err(4, "ioctl DIOCGDINFO");
}
+}
+
+void
+parselabel(void)
+{
+ char *partname, *partduid;
+ struct fstab *fsent;
+ int i;
i = asprintf(&partname, "/dev/%s%c", dkname, 'a');
if (i == -1)
Index: extern.h
===================================================================
RCS file: /var/cvs/src/sbin/disklabel/extern.h,v
retrieving revision 1.27
diff -u -p -r1.27 extern.h
--- extern.h 17 Oct 2015 13:27:08 -0000 1.27
+++ extern.h 29 May 2016 20:40:30 -0000
@@ -28,6 +28,7 @@ void display_partition(FILE *, struct di
int duid_parse(struct disklabel *, char *);
void readlabel(int);
+void parselabel(void);
struct disklabel *makebootarea(char *, struct disklabel *);
int editor(int);
void editor_allocspace(struct disklabel *);