The branch main has been updated by jhb:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=e01fe14c9aac95b1daec877af1729545b6d1b147

commit e01fe14c9aac95b1daec877af1729545b6d1b147
Author:     John Baldwin <j...@freebsd.org>
AuthorDate: 2025-08-04 19:38:06 +0000
Commit:     John Baldwin <j...@freebsd.org>
CommitDate: 2025-08-04 19:38:06 +0000

    ctld: Make config file parsing exception safe
    
    Split parse_conf in half keeping yyparse_conf as C-only function in
    parse.y.  parse_conf uses freebsd::FILE_up to ensure that the config
    file is always closed.
    
    Both parse_conf and uclparse_conf catch any exceptions thrown during
    parsing.  This is in preparation for using C++ objects allocated with
    new for various data structures.
    
    Note that this treats memory allocation failures from new as parsing
    errors rather than ctld exiting entirely as it currently does if
    malloc or calloc fail.
    
    Sponsored by:   Chelsio Communications
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/1794
---
 usr.sbin/ctld/Makefile    |  1 +
 usr.sbin/ctld/conf.cc     | 25 +++++++++++++++++++++++++
 usr.sbin/ctld/conf.h      |  2 +-
 usr.sbin/ctld/ctld.hh     |  1 +
 usr.sbin/ctld/parse.y     | 10 ++--------
 usr.sbin/ctld/uclparse.cc | 12 +++++++++++-
 6 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/usr.sbin/ctld/Makefile b/usr.sbin/ctld/Makefile
index 314554a99b56..67f89dca2757 100644
--- a/usr.sbin/ctld/Makefile
+++ b/usr.sbin/ctld/Makefile
@@ -12,6 +12,7 @@ CFLAGS+=      -I${SRCTOP}/sys
 CFLAGS+=       -I${SRCTOP}/sys/cam/ctl
 CFLAGS+=       -I${SRCTOP}/sys/dev/iscsi
 CFLAGS+=       -I${SRCTOP}/lib/libiscsiutil
+CFLAGS+=       -I${SRCTOP}/lib/libutil++
 #CFLAGS+=      -DICL_KERNEL_PROXY
 NO_WCAST_ALIGN=
 CXXWARNFLAGS.gcc= -Wno-shadow
diff --git a/usr.sbin/ctld/conf.cc b/usr.sbin/ctld/conf.cc
index 1750f7ab96c6..c9e1a2fb9968 100644
--- a/usr.sbin/ctld/conf.cc
+++ b/usr.sbin/ctld/conf.cc
@@ -39,6 +39,8 @@
 #include <string.h>
 #include <cam/scsi/scsi_all.h>
 
+#include <libutil++.hh>
+
 #include "conf.h"
 #include "ctld.hh"
 
@@ -757,3 +759,26 @@ target_start_lun(u_int id)
        lun = new_lun;
        return (true);
 }
+
+bool
+parse_conf(const char *path)
+{
+       freebsd::FILE_up fp(fopen(path, "r"));
+       if (fp == nullptr) {
+               log_warn("unable to open configuration file %s", path);
+               return (false);
+       }
+
+       bool parsed;
+       try {
+               parsed = yyparse_conf(fp.get());
+       } catch (std::bad_alloc) {
+               log_warnx("failed to allocate memory parsing %s", path);
+               return (false);
+       } catch (...) {
+               log_warnx("unknown exception parsing %s", path);
+               return (false);
+       }
+
+       return (parsed);
+}
diff --git a/usr.sbin/ctld/conf.h b/usr.sbin/ctld/conf.h
index 6e287ce70436..b13fd80e9fe5 100644
--- a/usr.sbin/ctld/conf.h
+++ b/usr.sbin/ctld/conf.h
@@ -97,7 +97,7 @@ bool  lun_set_path(const char *value);
 bool   lun_set_serial(const char *value);
 bool   lun_set_size(uint64_t value);
 
-bool   parse_conf(const char *path);
+bool   yyparse_conf(FILE *fp);
 
 __END_DECLS
 
diff --git a/usr.sbin/ctld/ctld.hh b/usr.sbin/ctld/ctld.hh
index b1757f98ac81..61e453d8dc23 100644
--- a/usr.sbin/ctld/ctld.hh
+++ b/usr.sbin/ctld/ctld.hh
@@ -247,6 +247,7 @@ struct ctld_connection {
 
 extern int ctl_fd;
 
+bool                   parse_conf(const char *path);
 bool                   uclparse_conf(const char *path);
 
 struct conf            *conf_new(void);
diff --git a/usr.sbin/ctld/parse.y b/usr.sbin/ctld/parse.y
index c0146262e895..432183ed794c 100644
--- a/usr.sbin/ctld/parse.y
+++ b/usr.sbin/ctld/parse.y
@@ -890,20 +890,14 @@ yyerror(const char *str)
 }
 
 bool
-parse_conf(const char *path)
+yyparse_conf(FILE *fp)
 {
        int error;
 
-       yyin = fopen(path, "r");
-       if (yyin == NULL) {
-               log_warn("unable to open configuration file %s", path);
-               return (false);
-       }
-
+       yyin = fp;
        lineno = 1;
        yyrestart(yyin);
        error = yyparse();
-       fclose(yyin);
 
        return (error == 0);
 }
diff --git a/usr.sbin/ctld/uclparse.cc b/usr.sbin/ctld/uclparse.cc
index 8788e1cbb981..4c7bbb43d75d 100644
--- a/usr.sbin/ctld/uclparse.cc
+++ b/usr.sbin/ctld/uclparse.cc
@@ -41,6 +41,8 @@
 #include <netinet/in.h>
 #include <netinet/ip.h>
 
+#include <memory>
+
 #include "conf.h"
 #include "ctld.hh"
 
@@ -1113,7 +1115,15 @@ uclparse_conf(const char *path)
        }
 
        top = ucl_parser_get_object(parser);
-       parsed = uclparse_toplevel(top);
+       try {
+               parsed = uclparse_toplevel(top);
+       } catch (std::bad_alloc) {
+               log_warnx("failed to allocate memory parsing %s", path);
+               parsed = false;
+       } catch (...) {
+               log_warnx("unknown exception parsing %s", path);
+               parsed = false;
+       }
        ucl_object_unref(top);
        ucl_parser_free(parser);
 

Reply via email to