Hi, Here is a new version of the unveil patch. Some notable changes: - Dillo will exit if 'save_dir' is set to $HOME (only with unveil) - dUnveil() function moved to dlib - New 'enable_unveil' pref for dillorc - New dGetsavedir() function to parse 'save_dir' - New dGetenableunveil() function to parse 'enable_unveil' enable_unveil is not used by the prefs parser, but rather dGetenableunveil(). I still need to fix it so that we don't get this warning on the console: prefs: {enable_unveil} is not a recognized token. To-Do: - Localize wget and $AUTHORITY - ... As always, feedback is welcome. Regards, Alex diff -upr a/configure.ac b/configure.ac --- a/configure.ac Wed Aug 7 20:50:53 2024 +++ b/configure.ac Thu Aug 8 20:06:15 2024 @@ -36,6 +36,11 @@ AC_ARG_ENABLE([insure], [enable_insure=$enableval], [enable_insure=no]) +AC_ARG_ENABLE([unveil], + [AS_HELP_STRING([--enable-unveil], [Build with support for unveil])], + [enable_unveil=$enableval], + [enable_unveil=no]) + AC_ARG_ENABLE([ipv6], [AS_HELP_STRING([--enable-ipv6], [Build with support for IPv6])], [enable_ipv6=$enableval], @@ -619,6 +624,9 @@ if test "x$enable_insure" = "xyes" ; then CC="insure -Zoi \"compiler $CC\"" LIBS="$LIBS -lstdc++-2-libc6.1-1-2.9.0" fi +if test "x$enable_unveil" = "xyes" ; then + AC_DEFINE([ENABLE_UNVEIL], [1], [Enable unveil]) +fi if test "x$enable_threaded_dns" = "xyes" ; then CFLAGS="$CFLAGS -DD_DNS_THREADED" fi @@ -726,4 +734,5 @@ _AS_ECHO([ GIF enabled : ${enable_gif}]) _AS_ECHO([ SVG enabled : ${enable_svg}]) _AS_ECHO([]) _AS_ECHO([ HTML tests : ${html_tests_ok}]) +_AS_ECHO([ unveil enabled : ${enable_unveil}]) _AS_ECHO([]) diff -upr a/dlib/dlib.c b/dlib/dlib.c --- a/dlib/dlib.c Wed Aug 7 20:50:53 2024 +++ b/dlib/dlib.c Thu Aug 8 20:07:28 2024 @@ -922,6 +922,99 @@ char *dGethomedir (void) } /** + * Return the save directory in a static string + */ +char *dGetsavedir () +{ + static char *dillorc = NULL; + dillorc = dStrconcat(dGethomedir(), "/", ".dillo/dillorc", NULL); + FILE *In; + int len; + char *rcline = NULL, *value = NULL, *p; + if ((In = fopen(dillorc, "r")) == NULL) { + DLIB_MSG("dGetsavedir: unable to open dillorc.\n"); + return (NULL); + } + while ((rcline = dGetline(In)) != NULL) { + if (strncmp(rcline, "save_dir", 8) == 0) + break; + dFree(rcline); + } + fclose(In); + if (!rcline) { + value = NULL; + DLIB_MSG("dGetsavedir: no 'save_dir' in dillorc..\n"); + } else { + len = (int) strlen(rcline); + if (len && rcline[len - 1] == '\n') + rcline[len - 1] = 0; + if ((p = strchr(rcline, '='))) { + while (*++p == ' '); + value = dStrdup(p); + } else { + value = NULL; + DLIB_MSG("dGetsavedir: error parsing value in dillorc.\n"); + } + } + dFree(rcline); + return (value); +} + +/** + * Return the enable_unveil value in a static string + */ +char *dGetenableunveil () +{ + static char *dillorc = NULL; + dillorc = dStrconcat(dGethomedir(), "/", ".dillo/dillorc", NULL); + FILE *In; + int len; + char *rcline = NULL, *value = NULL, *p; + if ((In = fopen(dillorc, "r")) == NULL) { + DLIB_MSG("dGetenableunveil: unable to open dillorc.\n"); + return (NULL); + } + while ((rcline = dGetline(In)) != NULL) { + if (strncmp(rcline, "enable_unveil", 13) == 0) + break; + dFree(rcline); + } + fclose(In); + if (!rcline) { + value = NULL; + DLIB_MSG("dGetenableunveil: no 'enable_unveil' in dillorc.\n"); + } else { + len = (int) strlen(rcline); + if (len && rcline[len - 1] == '\n') + rcline[len - 1] = 0; + if ((p = strchr(rcline, '='))) { + while (*++p == ' '); + value = dStrdup(p); + } else { + value = NULL; + DLIB_MSG("dGetenableunveil: error parsing value in dillorc.\n"); + } + } + dFree(rcline); + return (value); +} + +/** + * Use unveil on OpenBSD + */ +void *dUnveil(const char *path, const char *perm) +{ + #ifdef ENABLE_UNVEIL + #ifdef __OpenBSD__ + if (unveil(path, perm) == -1) { + DLIB_MSG("unveil(%s, %s) failed: %s\n", path, perm, strerror(errno)); + exit(1); + } + #endif + #endif +} + +/** * Get a line from a FILE stream. * Return value: read line on success, NULL on EOF. */ diff -upr a/dlib/dlib.h b/dlib/dlib.h --- a/dlib/dlib.h Wed Aug 7 20:50:53 2024 +++ b/dlib/dlib.h Thu Aug 8 20:07:26 2024 @@ -175,6 +175,9 @@ void dLib_show_messages(bool_t show); */ char *dGetcwd(void); char *dGethomedir(void); +char *dGetsavedir(); +char *dGetenableunveil(); +void *dUnveil(const char *path, const char *perm); char *dGetline(FILE *stream); int dClose(int fd); int dUsleep(unsigned long us); diff -upr a/dpi/bookmarks.c b/dpi/bookmarks.c --- a/dpi/bookmarks.c Wed Aug 7 20:50:53 2024 +++ b/dpi/bookmarks.c Thu Aug 8 20:08:40 2024 @@ -37,6 +37,7 @@ #include <signal.h> #include "../dpip/dpip.h" #include "dpiutil.h" +#include "../dlib/dlib.h" /* @@ -1606,7 +1607,6 @@ static void termination_handler(int signum) exit(signum); } - /* * -- MAIN ------------------------------------------------------------------- */ @@ -1616,6 +1616,18 @@ int main(void) { socklen_t address_size; char *tok; Dsh *sh; + + /* Use unveil on OpenBSD */ + if (dGetenableunveil() != NULL) { + if (strncmp(dGetenableunveil(), "YES", 3) == 0) { + #ifdef ENABLE_UNVEIL + char *dil_bm = dStrconcat(dGethomedir(), "/.dillo/bm.txt", NULL); + dUnveil(dil_bm, "rwc"); + dFree(dil_bm); + unveil(NULL, NULL); + #endif + } + } /* Arrange the cleanup function for terminations via exit() */ atexit(cleanup); diff -upr a/dpi/cookies.c b/dpi/cookies.c --- a/dpi/cookies.c Wed Aug 7 20:50:53 2024 +++ b/dpi/cookies.c Thu Aug 8 20:08:40 2024 @@ -50,6 +50,7 @@ int main(void) #include <signal.h> #include "dpiutil.h" #include "../dpip/dpip.h" +#include "../dlib/dlib.h" /* @@ -1632,7 +1633,6 @@ static void termination_handler(int signum) exit(signum); } - /* * -- MAIN ------------------------------------------------------------------- */ @@ -1643,7 +1643,19 @@ int main(void) { int sock_fd, code; char *buf; Dsh *sh; - + + /* Use unveil on OpenBSD */ + if (dGetenableunveil() != NULL) { + if (strncmp(dGetenableunveil(), "YES", 3) == 0) { + #ifdef ENABLE_UNVEIL + char *dil_loc = dStrconcat(dGethomedir(), "/.dillo", NULL); + dUnveil(dil_loc, "rwc"); + dFree(dil_loc); + unveil(NULL, NULL); + #endif + } + } + /* Arrange the cleanup function for terminations via exit() */ atexit(cleanup); diff -upr a/dpi/datauri.c b/dpi/datauri.c --- a/dpi/datauri.c Wed Aug 7 20:50:53 2024 +++ b/dpi/datauri.c Thu Aug 8 20:08:40 2024 @@ -21,6 +21,7 @@ #include "../dpip/dpip.h" #include "dpiutil.h" #include "../src/misc.h" +#include "../dlib/dlib.h" /* * Debugging macros @@ -290,6 +291,19 @@ int main(void) unsigned char *data; int rc; size_t data_size = 0; + + /* Use unveil on OpenBSD */ + if (dGetenableunveil() != NULL) { + if (strncmp(dGetenableunveil(), "YES", 3) == 0) { + #ifdef ENABLE_UNVEIL + dUnveil("/tmp", "rwc"); + char *dil_loc = dStrconcat(dGethomedir(), "/.dillo", NULL); + dUnveil(dil_loc, "rwc"); + dFree(dil_loc); + unveil(NULL, NULL); + #endif + } + } /* Initialize the SockHandler */ sh = a_Dpip_dsh_new(STDIN_FILENO, STDOUT_FILENO, 8*1024); diff -upr a/dpi/downloads.cc b/dpi/downloads.cc --- a/dpi/downloads.cc Wed Aug 7 20:50:53 2024 +++ b/dpi/downloads.cc Thu Aug 8 20:08:40 2024 @@ -45,6 +45,7 @@ #include "config.h" #include "dpiutil.h" #include "../dpip/dpip.h" +#include "../dlib/dlib.h" /* * Debugging macros @@ -206,7 +207,6 @@ static char *escape_tooltip(const char *buf, ssize_t l return ret; } - /* * Global variables */ @@ -1098,13 +1098,30 @@ static void custLabelMeasure(const Fl_Label* o, int& W fl_measure(o->value, W, H, interpret_symbols); } - - //int main(int argc, char **argv) int main() { int ww = 420, wh = 85; - + + /* Use unveil on OpenBSD */ + if (dGetenableunveil() != NULL) { + if (strncmp(dGetenableunveil(), "YES", 3) == 0) { + #ifdef ENABLE_UNVEIL + dUnveil("/tmp", "rwc"); + dUnveil("/etc/fonts", "r"); + dUnveil("/usr/local/bin/wget", "x"); + char *xauth_loc = dStrconcat(dGethomedir(), "/.Xauthority", NULL); + dUnveil(xauth_loc, "r"); + dFree(xauth_loc); + dUnveil("/usr/local/share/fonts", "r"); + char *dil_loc = dStrconcat(dGethomedir(), "/.dillo", NULL); + dUnveil(dil_loc, "rwc"); + dFree(dil_loc); + dUnveil(NULL, NULL); + #endif + } + } + Fl::lock(); // Disable '@' and '&' interpretation in normal labels. diff -upr a/dpi/file.c b/dpi/file.c --- a/dpi/file.c Wed Aug 7 20:50:53 2024 +++ b/dpi/file.c Thu Aug 8 20:08:40 2024 @@ -37,6 +37,7 @@ #include "../dpip/dpip.h" #include "dpiutil.h" #include "d_size.h" +#include "../dlib/dlib.h" /* * Debugging macros @@ -1063,12 +1064,24 @@ static int File_check_fds(uint_t seconds) return st; } - int main(void) { struct sockaddr_in sin; socklen_t sin_sz; int sock_fd, c_st, st = 1; + + /* Use unveil on OpenBSD */ + if (dGetenableunveil() != NULL) { + if (strncmp(dGetenableunveil(), "YES", 3) == 0) { + #ifdef ENABLE_UNVEIL + dUnveil(dGetsavedir(), "rw"); + dUnveil("/tmp", "rw"); + char *dil_loc = dStrconcat(dGethomedir(), "/.dillo", NULL); + dUnveil(dil_loc, "rwc"); + unveil(NULL, NULL); + #endif + } + } /* Arrange the cleanup function for abnormal terminations */ if (signal (SIGINT, termination_handler) == SIG_IGN) diff -upr a/dpi/ftp.c b/dpi/ftp.c --- a/dpi/ftp.c Wed Aug 7 20:50:53 2024 +++ b/dpi/ftp.c Thu Aug 8 20:08:40 2024 @@ -44,6 +44,7 @@ #include "../dpip/dpip.h" #include "dpiutil.h" #include "d_size.h" +#include "../dlib/dlib.h" /* * Debugging macros @@ -282,6 +283,21 @@ int main(int argc, char **argv) int st, rc; char *p, *d_cmd; + /* Use unveil on OpenBSD */ + if (dGetenableunveil() != NULL) { + if (strncmp(dGetenableunveil(), "YES", 3) == 0) { + #ifdef ENABLE_UNVEIL + dUnveil("/tmp", "rwc"); + dUnveil("/usr/local/bin/wget", "x"); + char *dil_loc = dStrconcat(dGethomedir(), "/.dillo", NULL); + dUnveil(dil_loc, "rwc"); + dFree(dil_loc); + dUnveil(dGetsavedir(), "rwc"); + unveil(NULL, NULL); + #endif + } + } + /* wget may need to write a temporary file... */ rc = chdir("/tmp"); if (rc == -1) { diff -upr a/dpi/vsource.c b/dpi/vsource.c --- a/dpi/vsource.c Wed Aug 7 20:50:53 2024 +++ b/dpi/vsource.c Thu Aug 8 20:08:40 2024 @@ -21,6 +21,7 @@ #include <errno.h> #include "../dpip/dpip.h" #include "dpiutil.h" +#include "../dlib/dlib.h" /* * Debugging macros @@ -188,6 +189,18 @@ int main(void) char *dpip_tag, *cmd = NULL, *cmd2 = NULL, *url = NULL, *size_str = NULL; char *d_cmd; + /* Use unveil on OpenBSD */ + if (dGetenableunveil() != NULL) { + if (strncmp(dGetenableunveil(), "YES", 3) == 0) { + #ifdef ENABLE_UNVEIL + char *dil_loc = dStrconcat(dGethomedir(), "/.dillo", NULL); + dUnveil(dil_loc, "r"); + dFree(dil_loc); + unveil(NULL, NULL); + #endif + } + } + _MSG("starting...\n"); //sleep(20); diff -upr a/dpid/main.c b/dpid/main.c --- a/dpid/main.c Wed Aug 7 20:50:53 2024 +++ b/dpid/main.c Thu Aug 8 20:07:44 2024 @@ -236,6 +236,19 @@ int main(void) //daemon(0,0); /* Use 0,1 for feedback */ /* TODO: call setsid() ?? */ + /* Use unveil on OpenBSD */ + if (dGetenableunveil() != NULL) { + if (strncmp(dGetenableunveil(), "YES", 3) == 0) { + #ifdef ENABLE_UNVEIL + dUnveil("/usr/local/lib/dillo", "rx"); + dUnveil("/usr/local/etc/dillo", "r"); + char *dil_loc = dStrconcat(dGethomedir(), "/.dillo", NULL); + dUnveil(dil_loc, "rwc"); + unveil(NULL, NULL); + #endif + } + } + /* Allow read and write access, but only for the user. * TODO: can this cause trouble with umount? */ umask(0077); diff -upr a/src/dillo.cc b/src/dillo.cc --- a/src/dillo.cc Wed Aug 7 20:50:53 2024 +++ b/src/dillo.cc Thu Aug 8 20:08:54 2024 @@ -463,7 +463,47 @@ int main(int argc, char **argv) fclose(fp); } dLib_show_messages(prefs.show_msg); - + + // Use unveil + if (dGetenableunveil() != NULL) { + if (strncmp(dGetenableunveil(), "YES", 3) == 0) { + #ifdef ENABLE_UNVEIL + const char *home = dGethomedir(); + const char *save = prefs.save_dir; + int nsave = strlen(save); + int nhome = strlen(home); + if (nsave <= nhome) { + /* Prevent save_dir="/home" and save_dir=$HOME */ + if (strncmp(save, home, nsave) == 0) { + MSG("save_dir cannot contain home\n"); + exit(1); + } + } + dUnveil("/usr/local/share/fonts", "r"); + dUnveil("/usr/local/share/icons", "r"); + dUnveil("/usr/X11R6/share/X11/locale", "r"); + dUnveil("/usr/X11R6/lib/X11/fonts", "r"); + dUnveil("/usr/local/etc/dillo", "r"); + dUnveil("/tmp", "rwc"); + dUnveil("/usr/local/bin/dpid", "x"); + dUnveil("/etc/fonts", "r"); + dUnveil("/etc/resolv.conf", "r"); + dUnveil("/etc/ssl/cert.pem", "r"); + dUnveil(prefs.save_dir, "rwc"); + char *dil_loc = dStrconcat(dGethomedir(), "/.dillo", NULL); + dUnveil(dil_loc, "rwc"); + dFree(dil_loc); + char *icons_loc = dStrconcat(dGethomedir(), "/.icons", NULL); + dUnveil(icons_loc, "r"); + dFree(icons_loc); + char *xauth_loc = dStrconcat(dGethomedir(), "/.Xauthority", NULL); + dUnveil(xauth_loc, "r"); + dFree(xauth_loc); + dUnveil(NULL, NULL); + #endif + } + } + // initialize internal modules a_Dpi_init(); a_Dns_init();