Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Privilege Separation for dhcpcd
      3  * SPDX-License-Identifier: BSD-2-Clause
      4  * Copyright (c) 2006-2025 Roy Marples <roy (at) marples.name>
      5  * All rights reserved
      6 
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #ifndef PRIVSEP_H
     30 #define PRIVSEP_H
     31 
     32 // #define PRIVSEP_DEBUG
     33 
     34 /* Start flags */
     35 #define PSF_DROPPRIVS 0x01
     36 #define PSF_ELOOP     0x02
     37 
     38 /* Protocols */
     39 #define PS_BOOTP     0x0001
     40 #define PS_ND	     0x0002
     41 #define PS_DHCP6     0x0003
     42 #define PS_BPF_BOOTP 0x0004
     43 #define PS_BPF_ARP   0x0005
     44 
     45 /* Generic commands */
     46 #define PS_IOCTL	0x0010
     47 #define PS_ROUTE	0x0011 /* Also used for NETLINK */
     48 #define PS_SCRIPT	0x0012
     49 #define PS_UNLINK	0x0013
     50 #define PS_READFILE	0x0014
     51 #define PS_WRITEFILE	0x0015
     52 #define PS_FILEMTIME	0x0016
     53 #define PS_AUTH_MONORDM 0x0017
     54 #define PS_CTL		0x0018
     55 #define PS_CTL_CONTROL	0x0019
     56 #define PS_CTL_READ	0x0020
     57 #define PS_LOGREOPEN	0x0021
     58 #define PS_STOPPROCS	0x0022
     59 #define PS_DAEMONISED	0x0023
     60 #define PS_USER_INGROUP 0x0024
     61 
     62 /* Domains */
     63 #define PS_ROOT	   0x0101
     64 #define PS_INET	   0x0102
     65 #define PS_CONTROL 0x0103
     66 
     67 /* BSD Commands */
     68 #define PS_IOCTLLINK	 0x0201
     69 #define PS_IOCTL6	 0x0202
     70 #define PS_IOCTLINDIRECT 0x0203
     71 #define PS_IP6FORWARDING 0x0204
     72 #define PS_GETIFADDRS	 0x0205
     73 #define PS_IFIGNOREGRP	 0x0206
     74 #define PS_SYSCTL	 0x0207
     75 #define PS_GETHOSTNAME	 0x0208
     76 
     77 /* Dev Commands */
     78 #define PS_DEV_LISTENING 0x1001
     79 #define PS_DEV_INITTED	 0x1002
     80 #define PS_DEV_IFCMD	 0x1003
     81 
     82 /* Dev Interface Commands (via flags) */
     83 #define PS_DEV_IFADDED	 0x0001
     84 #define PS_DEV_IFREMOVED 0x0002
     85 #define PS_DEV_IFUPDATED 0x0003
     86 
     87 /* Sysctl Needs (via flags) */
     88 #define PS_SYSCTL_OLEN	0x0001
     89 #define PS_SYSCTL_ODATA 0x0002
     90 
     91 /* Process commands */
     92 #define PS_START     0x4000
     93 #define PS_STOP	     0x8000
     94 
     95 #define PSP_NAMESIZE 16 + INET_MAX_ADDRSTRLEN
     96 
     97 /* Handy macro to work out if in the privsep engine or not. */
     98 #define IN_PRIVSEP(ctx) ((ctx)->options & DHCPCD_PRIVSEP)
     99 #define IN_PRIVSEP_SE(ctx) \
    100 	(((ctx)->options & (DHCPCD_PRIVSEP | DHCPCD_FORKED)) == DHCPCD_PRIVSEP)
    101 
    102 #define PS_PROCESS_TIMEOUT 5 /* seconds to stop all processes */
    103 
    104 #ifdef PRIVSEP
    105 #ifdef HAVE_CAPSICUM
    106 #define PRIVSEP_RIGHTS
    107 #endif
    108 /* Pledge and Capsicum deny nearly all sysctls.
    109  * Linux needs directory access to sysctls. */
    110 #if defined(HAVE_CAPSICUM) || defined(HAVE_PLEDGE) || defined(__linux__)
    111 #define PRIVSEP_SYSCTL
    112 #endif
    113 #endif
    114 
    115 #define PS_ROOT_FD(ctx) ((ctx)->ps_root ? (ctx)->ps_root->psp_fd : -1)
    116 
    117 #if !defined(DISABLE_SECCOMP) && defined(__linux__)
    118 #include <linux/version.h>
    119 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
    120 #define HAVE_SECCOMP
    121 #endif
    122 #endif
    123 
    124 #include "config.h"
    125 #include "arp.h"
    126 #include "dhcp.h"
    127 #include "dhcpcd.h"
    128 
    129 struct ps_addr {
    130 	sa_family_t psa_family;
    131 	uint8_t psa_pad[4 - sizeof(sa_family_t)];
    132 	union {
    133 		struct in_addr psau_in_addr;
    134 		struct in6_addr psau_in6_addr;
    135 	} psa_u;
    136 #define psa_in_addr  psa_u.psau_in_addr
    137 #define psa_in6_addr psa_u.psau_in6_addr
    138 };
    139 
    140 /* Uniquely identify a process */
    141 struct ps_id {
    142 	struct ps_addr psi_addr;
    143 	unsigned int psi_ifindex;
    144 	uint16_t psi_cmd;
    145 	uint8_t psi_pad[2];
    146 };
    147 
    148 struct ps_msghdr {
    149 	uint16_t ps_cmd;
    150 	uint8_t ps_pad[sizeof(unsigned long) - sizeof(uint16_t)];
    151 	unsigned long ps_flags;
    152 	struct ps_id ps_id;
    153 	socklen_t ps_namelen;
    154 	socklen_t ps_controllen;
    155 	uint8_t ps_pad2[sizeof(size_t) - sizeof(socklen_t)];
    156 	size_t ps_datalen;
    157 };
    158 
    159 struct bpf;
    160 
    161 struct ps_process {
    162 	TAILQ_ENTRY(ps_process) next;
    163 	struct dhcpcd_ctx *psp_ctx;
    164 	struct ps_id psp_id;
    165 	pid_t psp_pid;
    166 	int psp_fd;
    167 	int psp_work_fd;
    168 	unsigned int psp_ifindex;
    169 	char psp_ifname[IF_NAMESIZE];
    170 	char psp_name[PSP_NAMESIZE];
    171 	uint16_t psp_proto;
    172 	const char *psp_protostr;
    173 	bool psp_started;
    174 
    175 #ifdef INET
    176 	int (*psp_filter)(const struct bpf *, const struct in_addr *);
    177 	struct interface psp_ifp; /* Move BPF gubbins elsewhere */
    178 	struct bpf *psp_bpf;
    179 #endif
    180 
    181 #ifdef HAVE_CAPSICUM
    182 	int psp_pfd;
    183 #endif
    184 };
    185 TAILQ_HEAD(ps_process_head, ps_process);
    186 
    187 #include "privsep-control.h"
    188 #include "privsep-inet.h"
    189 #include "privsep-root.h"
    190 #ifdef INET
    191 #include "privsep-bpf.h"
    192 #endif
    193 
    194 int ps_bufalloc(struct dhcpcd_ctx *, size_t);
    195 int ps_init(struct dhcpcd_ctx *);
    196 int ps_start(struct dhcpcd_ctx *);
    197 int ps_stop(struct dhcpcd_ctx *);
    198 int ps_stopwait(struct dhcpcd_ctx *);
    199 int ps_entersandbox(const char *, const char **);
    200 int ps_managersandbox(struct dhcpcd_ctx *, const char *);
    201 ssize_t ps_daemonised(struct dhcpcd_ctx *);
    202 
    203 int ps_unrollmsg(struct msghdr *, struct ps_msghdr *, const void *, size_t);
    204 ssize_t ps_sendpsmmsg(struct dhcpcd_ctx *, int, struct ps_msghdr *,
    205     const struct msghdr *);
    206 ssize_t ps_sendpsmdata(struct dhcpcd_ctx *, int, struct ps_msghdr *,
    207     const void *, size_t);
    208 ssize_t ps_sendmsg(struct dhcpcd_ctx *, int, uint16_t, unsigned long,
    209     const struct msghdr *);
    210 ssize_t ps_sendcmd(struct dhcpcd_ctx *, int, uint16_t, unsigned long,
    211     const void *data, size_t len);
    212 ssize_t ps_sendcmdmsg(struct dhcpcd_ctx *, int fd, uint16_t cmd,
    213     unsigned long flags, const struct msghdr *msg);
    214 ssize_t ps_recvmsg(int, unsigned short, uint16_t, int);
    215 ssize_t ps_recvpsmsg(struct dhcpcd_ctx *, int, unsigned short,
    216     ssize_t (*callback)(void *, struct ps_msghdr *, struct msghdr *), void *);
    217 
    218 #ifdef PRIVSEP_RIGHTS
    219 int ps_rights_limit_ioctl(int);
    220 int ps_rights_limit_fd_getsockopt(int);
    221 int ps_rights_limit_fd_fctnl(int);
    222 int ps_rights_limit_fd_rdonly(int);
    223 int ps_rights_limit_fd_sockopt(int);
    224 int ps_rights_limit_fd(int);
    225 int ps_rights_limit_fdpair(int[]);
    226 #endif
    227 
    228 #ifdef HAVE_SECCOMP
    229 int ps_seccomp_enter(void);
    230 #endif
    231 
    232 pid_t ps_startprocess(struct ps_process *,
    233     void (*recv_msg)(void *, unsigned short),
    234     void (*recv_unpriv_msg)(void *, unsigned short),
    235     int (*callback)(struct ps_process *), unsigned int);
    236 int ps_stopprocess(struct ps_process *);
    237 struct ps_process *ps_findprocess(struct dhcpcd_ctx *, struct ps_id *);
    238 struct ps_process *ps_findprocesspid(struct dhcpcd_ctx *, pid_t);
    239 struct ps_process *ps_newprocess(struct dhcpcd_ctx *, struct ps_id *);
    240 bool ps_waitforprocs(struct dhcpcd_ctx *ctx);
    241 void ps_process_timeout(void *);
    242 void ps_freeprocess(struct ps_process *);
    243 void ps_freeprocesses(struct dhcpcd_ctx *, struct ps_process *);
    244 #endif
    245