[prev in list] [next in list] [prev in thread] [next in thread]
List: openbsd-tech
Subject: Re: dhcpd(8): Parse lease database after dropping privileges
From: Stephen Fox <stephen.j.fox.jr () gmail ! com>
Date: 2023-10-25 21:48:19
Message-ID: CAFLgvu0KNwcGGB7we4bjWpAmLquxkC8k_AXvo5znKinjtRa2mQ () mail ! gmail ! com
[Download RAW message or body]
Hello,
I just wanted to double check if there is any additional feedback on the patch.
I am happy to make changes or discuss alternative approaches.
Thank you,
Stephen
On Tue, Oct 3, 2023 at 11:33 PM Stephen Fox <stephen.j.fox.jr@gmail.com> wrote:
>
> Hello,
>
> I received feedback from deraadt that the first two unveil(2) calls were
> unnecessary because pledge(2) automatically unveils "/usr/share/zoneinfo".
>
> This updated patch removes the unneeded unveil(2) calls.
>
> Best regards,
> Stephen
> ---
> usr.sbin/dhcpd/confpars.c | 41 ++++++++++++++++++++++++++-------------
> usr.sbin/dhcpd/db.c | 19 ++++++++++++++++++
> usr.sbin/dhcpd/dhcpd.c | 30 ++++++++++++++++++++++++++--
> usr.sbin/dhcpd/dhcpd.h | 2 ++
> 4 files changed, 76 insertions(+), 16 deletions(-)
>
> diff --git usr.sbin/dhcpd/confpars.c usr.sbin/dhcpd/confpars.c
> index 1bdffb38842..bb245fc663e 100644
> --- usr.sbin/dhcpd/confpars.c
> +++ usr.sbin/dhcpd/confpars.c
> @@ -57,6 +57,8 @@
> #include "dhctoken.h"
> #include "log.h"
>
> +FILE *db_file_ro;
> +
> int parse_cidr(FILE *, unsigned char *, unsigned char *);
>
> /*
> @@ -106,18 +108,11 @@ readconf(void)
> }
>
> /*
> - * lease-file :== lease-declarations EOF
> - * lease-statments :== <nil>
> - * | lease-declaration
> - * | lease-declarations lease-declaration
> + * Open and retain a read-only file descriptor to the lease database file.
> */
> void
> -read_leases(void)
> +open_leases(void)
> {
> - FILE *cfile;
> - char *val;
> - int token;
> -
> new_parse(path_dhcpd_db);
>
> /*
> @@ -131,23 +126,40 @@ read_leases(void)
> * thinking that no leases have been assigned to anybody, which
> * could create severe network chaos.
> */
> - if ((cfile = fopen(path_dhcpd_db, "r")) == NULL) {
> + if ((db_file_ro = fopen(path_dhcpd_db, "r")) == NULL) {
> log_warn("Can't open lease database (%s)", path_dhcpd_db);
> log_warnx("check for failed database rewrite attempt!");
> log_warnx("Please read the dhcpd.leases manual page if you");
> fatalx("don't know what to do about this.");
> }
> +}
> +
> +/*
> + * lease-file :== lease-declarations EOF
> + * lease-statments :== <nil>
> + * | lease-declaration
> + * | lease-declarations lease-declaration
> + */
> +void
> +read_leases(void)
> +{
> + char *val;
> + int token;
> +
> + if (!db_file_ro) {
> + fatalx("db_file_ro is NULL");
> + }
>
> do {
> - token = next_token(&val, cfile);
> + token = next_token(&val, db_file_ro);
> if (token == EOF)
> break;
> if (token != TOK_LEASE) {
> log_warnx("Corrupt lease file - possible data loss!");
> - skip_to_semi(cfile);
> + skip_to_semi(db_file_ro);
> } else {
> struct lease *lease;
> - lease = parse_lease_declaration(cfile);
> + lease = parse_lease_declaration(db_file_ro);
> if (lease)
> enter_lease(lease);
> else
> @@ -155,7 +167,8 @@ read_leases(void)
> }
>
> } while (1);
> - fclose(cfile);
> + fclose(db_file_ro);
> + db_file_ro = NULL;
> }
>
> /*
> diff --git usr.sbin/dhcpd/db.c usr.sbin/dhcpd/db.c
> index 295e522b1ce..634ec8a593a 100644
> --- usr.sbin/dhcpd/db.c
> +++ usr.sbin/dhcpd/db.c
> @@ -190,6 +190,16 @@ commit_leases(void)
> return (1);
> }
>
> +/*
> + * Open and retain two file descriptors to the lease database file:
> + *
> + * - A read-only fd for learning existing leases
> + * - A write-only fd for writing new leases
> + *
> + * Reading and parsing data from the read-only fd is done separately.
> + * This allows privilege drop to happen *before* parsing untrusted
> + * client data from the lease database file.
> + */
> void
> db_startup(void)
> {
> @@ -202,6 +212,15 @@ db_startup(void)
> if ((db_file = fdopen(db_fd, "w")) == NULL)
> fatalx("Can't fdopen new lease file!");
>
> + open_leases();
> +}
> +
> +/*
> + * Read and parse the existing leases from the lease database file.
> + */
> +void
> +db_parse(void)
> +{
> /* Read in the existing lease file... */
> read_leases();
> time(&write_time);
> diff --git usr.sbin/dhcpd/dhcpd.c usr.sbin/dhcpd/dhcpd.c
> index b3562dce34f..7759f7839e0 100644
> --- usr.sbin/dhcpd/dhcpd.c
> +++ usr.sbin/dhcpd/dhcpd.c
> @@ -244,8 +244,6 @@ main(int argc, char *argv[])
>
> icmp_startup(1, lease_pinged);
>
> - if (chroot(pw->pw_dir) == -1)
> - fatal("chroot %s", pw->pw_dir);
> if (chdir("/") == -1)
> fatal("chdir(\"/\")");
> if (setgroups(1, &pw->pw_gid) ||
> @@ -253,6 +251,34 @@ main(int argc, char *argv[])
> setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
> fatal("can't drop privileges");
>
> + /*
> + * The lease database parsing logic needs the zoneinfo files
> + * for the lease begin / end date strings. These files are
> + * automatically unveiled by pledge(2). It also opens the
> + * /etc/ethers file using ether_hostton(3).
> + */
> + if (unveil("/etc/ethers", "r") == -1)
> + err(1, "unveil /etc/ethers");
> + if (unveil(NULL, NULL) == -1)
> + err(1, "unveil");
> +
> + /*
> + * Apply initial pledge(2) promises - we will drop "rpath" after
> + * parsing the lease database (we need it for ether_hostton(3)).
> + */
> + if (udpsockmode) {
> + if (pledge("rpath stdio inet route sendfd", NULL) == -1)
> + err(1, "pledge init");
> + } else {
> + if (pledge("rpath stdio inet sendfd", NULL) == -1)
> + err(1, "pledge init");
> + }
> +
> + db_parse();
> +
> + /*
> + * Drop the "rpath" promise.
> + */
> if (udpsockmode) {
> if (pledge("stdio inet route sendfd", NULL) == -1)
> err(1, "pledge");
> diff --git usr.sbin/dhcpd/dhcpd.h usr.sbin/dhcpd/dhcpd.h
> index 0903c244ddd..8c52b6603fc 100644
> --- usr.sbin/dhcpd/dhcpd.h
> +++ usr.sbin/dhcpd/dhcpd.h
> @@ -343,6 +343,7 @@ int peek_token(char **, FILE *);
>
> /* confpars.c */
> int readconf(void);
> +void open_leases(void);
> void read_leases(void);
> int parse_statement(FILE *, struct group *, int, struct host_decl *, int);
> void parse_allow_deny(FILE *, struct group *, int);
> @@ -489,6 +490,7 @@ char *piaddr(struct iaddr);
> int write_lease(struct lease *);
> int commit_leases(void);
> void db_startup(void);
> +void db_parse(void);
> void new_lease_file(void);
>
> /* packet.c */
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic