Hi tech@,
The Patch 1 below tighten pledge(2) promises to stdio, after the
freopen(3) call, and replaces an exit(3) call to return, so the
stack protector could be used.
I verify that after pledge stdio, there are only calls to:
getline(3), memcmp(3), regexec(3), printf(3), fwrite(3), fputs(3),
ferror(3), free(3), and err(3). All this functions do not need
the rpath promise.
The Patch 2, includes Patch 1 and uses unveil(2) when the user supply
a file. A prior version of this patch used unveil("/dev/null", "r")
after the first pledge call, to forbid any filesystem access, except
the file supplied. But it seemed like a hack.
Comments?
Regards,
Rafael Neves
Patch 1 (just pledge):
Index: usr.bin/nl/nl.c
===================================================================
RCS file: /cvs/src/usr.bin/nl/nl.c,v
retrieving revision 1.6
diff -u -p -r1.6 nl.c
--- usr.bin/nl/nl.c 9 Oct 2015 01:37:08 -0000 1.6
+++ usr.bin/nl/nl.c 20 Apr 2019 21:27:39 -0000
@@ -218,6 +218,9 @@ main(int argc, char *argv[])
/* NOTREACHED */
}
+ if (pledge("stdio", NULL) == -1)
+ err(1, "pledge");
+
/* Generate the delimiter sequence */
memcpy(delim, delim1, delim1len);
memcpy(delim + delim1len, delim2, delim2len);
@@ -226,7 +229,7 @@ main(int argc, char *argv[])
/* Do the work. */
filter();
- exit(EXIT_SUCCESS);
+ return(EXIT_SUCCESS);
}
void
Pledge 2 (pledge and unveil):
Index: usr.bin/nl/nl.c
===================================================================
RCS file: /cvs/src/usr.bin/nl/nl.c,v
retrieving revision 1.6
diff -u -p -r1.6 nl.c
--- usr.bin/nl/nl.c 9 Oct 2015 01:37:08 -0000 1.6
+++ usr.bin/nl/nl.c 20 Apr 2019 21:28:44 -0000
@@ -118,7 +118,7 @@ main(int argc, char *argv[])
(void)setlocale(LC_ALL, "");
- if (pledge("stdio rpath", NULL) == -1)
+ if (pledge("stdio unveil rpath", NULL) == -1)
err(1, "pledge");
while ((c = getopt(argc, argv, "pb:d:f:h:i:l:n:s:v:w:")) != -1) {
@@ -209,8 +209,14 @@ main(int argc, char *argv[])
case 0:
break;
case 1:
- if (strcmp(argv[0], "-") != 0 &&
- freopen(argv[0], "r", stdin) == NULL)
+ if (strcmp(argv[0], "-") == 0)
+ break;
+
+ /* Let freopen(3) check deal with permission problems. */
+ if (unveil(argv[0], "r") == -1 && errno != ENOENT)
+ err(1, "unveil");
+
+ if (freopen(argv[0], "r", stdin) == NULL)
err(EXIT_FAILURE, "%s", argv[0]);
break;
default:
@@ -218,6 +224,9 @@ main(int argc, char *argv[])
/* NOTREACHED */
}
+ if (pledge("stdio", NULL) == -1)
+ err(1, "pledge");
+
/* Generate the delimiter sequence */
memcpy(delim, delim1, delim1len);
memcpy(delim + delim1len, delim2, delim2len);
@@ -226,7 +235,7 @@ main(int argc, char *argv[])
/* Do the work. */
filter();
- exit(EXIT_SUCCESS);
+ return(EXIT_SUCCESS);
}
void