util/nvmutil: extreme pledge/unveil hardening

call pledge *much* earlier, and and lock everything down
much sooner. the point of pledge/unveil is precisely that
your program must operate under the most restrictive set
of conditions possible, and still function.

Signed-off-by: Leah Rowe <leah@libreboot.org>
master
Leah Rowe 2025-01-24 17:58:42 +00:00
parent deb307eaf6
commit a6c18734e7
1 changed files with 27 additions and 16 deletions

View File

@ -71,6 +71,11 @@ void (*cmd)(void) = NULL;
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
#ifdef __OpenBSD__
/* OpenBSD pledge (sandboxing): https://man.openbsd.org/pledge.2 */
err_if(pledge("stdio rpath wpath unveil", NULL) == -1);
#endif
if (argc < 3) { /* TODO: manpage! */ if (argc < 3) { /* TODO: manpage! */
fprintf(stderr, "Modify Intel GbE NVM images e.g. set MAC\n"); fprintf(stderr, "Modify Intel GbE NVM images e.g. set MAC\n");
fprintf(stderr, "USAGE:\n"); fprintf(stderr, "USAGE:\n");
@ -84,29 +89,35 @@ main(int argc, char *argv[])
} }
filename = argv[1]; filename = argv[1];
if (strcmp(COMMAND, "dump") == 0)
flags = O_RDONLY; /* write not needed for dump cmd */
else
flags = O_RDWR;
/* Err if files are actually directories; this also if (strcmp(COMMAND, "dump") == 0) {
prevents unveil allowing directory accesses, which flags = O_RDONLY; /* write not needed for dump cmd */
is critical because we only want *file* accesses. */ #ifdef __OpenBSD__
/* writes not needed for the dump command */
err_if(pledge("stdio rpath unveil", NULL) == -1);
#endif
} else {
flags = O_RDWR;
}
/* check for dir first, to prevent unveil from
permitting directory access on OpenBSD */
checkdir("/dev/urandom"); checkdir("/dev/urandom");
checkdir(filename); /* Must be a file, not a directory */ checkdir(filename); /* Must be a file, not a directory */
#ifdef __OpenBSD__ #ifdef __OpenBSD__
/* OpenBSD sandboxing: https://man.openbsd.org/pledge.2 */ /* OpenBSD unveil: https://man.openbsd.org/unveil.2 */
/* Also: https://man.openbsd.org/unveil.2 */
err_if(unveil("/dev/urandom", "r") == -1); err_if(unveil("/dev/urandom", "r") == -1);
if (flags == O_RDONLY) { /* write not needed for dump command */ /* Only allow access to /dev/urandom and the gbe file */
err_if(unveil(filename, "r") == -1); if (flags == O_RDONLY) { /* dump command */
err_if(pledge("stdio rpath", NULL) == -1); err_if(unveil(filename, "r") == -1); /* write not needed */
} else { /* not dump command, so pledge read-write instead */ err_if(unveil(NULL, NULL) == -1); /* lock unveil */
err_if(pledge("stdio rpath", NULL) == -1); /* lock unveil */
} else { /* other commands need read-write */
err_if(unveil(filename, "rw") == -1); err_if(unveil(filename, "rw") == -1);
err_if(pledge("stdio rpath wpath", NULL) == -1); err_if(unveil(NULL, NULL) == -1); /* lock unveil */
err_if(pledge("stdio rpath wpath", NULL) == -1); /* no unveil */
} }
#endif #endif
@ -119,7 +130,7 @@ main(int argc, char *argv[])
for (int i = 0; i < 6; i++) /* detect user-supplied command */ for (int i = 0; i < 6; i++) /* detect user-supplied command */
if (strcmp(COMMAND, op[i].str) == 0) if (strcmp(COMMAND, op[i].str) == 0)
if ((cmd = argc >= op[i].args ? op[i].cmd : NULL)) if ((cmd = argc >= op[i].args ? op[i].cmd : NULL))
break; /* function ptr set, as per user cmd */ break;
if (cmd == cmd_setmac) { if (cmd == cmd_setmac) {
strMac = strRMac; /* random MAC */ strMac = strRMac; /* random MAC */