summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2020-05-20 18:14:38 +0100
committerRoy Marples <roy@marples.name>2020-05-20 18:14:38 +0100
commit57b2db8ffc9e88d303e2c140e07be79aa45a35ce (patch)
treed54c187e7337494e883a7ceb3381933dd0039a42
parentce1f59bef3420015ae06ff8f7c04c8f56c320c90 (diff)
downloaddhcpcd-57b2db8ffc9e88d303e2c140e07be79aa45a35ce.tar.xz
privsep: Filter ioctls to a known list.
In-case the master process is broken into.
-rw-r--r--src/privsep-bsd.c47
-rw-r--r--src/privsep-root.c21
2 files changed, 68 insertions, 0 deletions
diff --git a/src/privsep-bsd.c b/src/privsep-bsd.c
index d714eee4..e73984e4 100644
--- a/src/privsep-bsd.c
+++ b/src/privsep-bsd.c
@@ -28,6 +28,12 @@
#include <sys/ioctl.h>
+/* Need these for filtering the ioctls */
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
+
#include <errno.h>
#include <string.h>
#include <unistd.h>
@@ -41,6 +47,38 @@ ps_root_doioctldom(int domain, unsigned long req, void *data, size_t len)
{
int s, err;
+ /* Only allow these ioctls */
+ switch(req) {
+#ifdef SIOCIFAFATTACH
+ case SIOCIFAFATTACH: /* FALLTHROUGH */
+#endif
+#ifdef SIOCSIFXFLAGS
+ case SIOCSIFXFLAGS: /* FALLTHROUGH */
+#endif
+#ifdef SIOCSIFINFO_FLAGS
+ case SIOCSIFINFO_FLAGS: /* FALLTHROUGH */
+#endif
+#ifdef SIOCSRTRFLUSH_IN6
+ case SIOCSRTRFLUSH_IN6: /* FALLTHROUGH */
+ case SIOCSPFXFLUSH_IN6: /* FALLTHROUGH */
+#endif
+#if defined(SIOCALIFADDR) && defined(IFLR_ACTIVE)
+ case SIOCALIFADDR: /* FALLTHROUGH */
+ case SIOCDLIFADDR: /* FALLTHROUGH */
+#else
+ case SIOCSIFLLADDR: /* FALLTHROUGH */
+#endif
+#ifdef SIOCSIFINFO_IN6
+ case SIOCSIFINFO_IN6: /* FALLTHROUGH */
+#endif
+ case SIOCAIFADDR_IN6: /* FALLTHROUGH */
+ case SIOCDIFADDR_IN6: /* FALLTHROUGH */
+ break;
+ default:
+ errno = EPERM;
+ return -1;
+ }
+
s = socket(domain, SOCK_DGRAM, 0);
if (s == -1)
return -1;
@@ -73,6 +111,15 @@ ps_root_doindirectioctl(unsigned long req, void *data, size_t len)
struct ifreq ifr = { .ifr_flags = 0 };
ssize_t err;
+ switch(req) {
+ case SIOCG80211NWID: /* FALLTHROUGH */
+ case SIOCGETVLAN:
+ break;
+ default:
+ errno = EPERM;
+ return -1;
+ }
+
if (len < IFNAMSIZ) {
errno = EINVAL;
return -1;
diff --git a/src/privsep-root.c b/src/privsep-root.c
index f511a43f..8232a532 100644
--- a/src/privsep-root.c
+++ b/src/privsep-root.c
@@ -215,6 +215,27 @@ ps_root_doioctl(unsigned long req, void *data, size_t len)
{
int s, err;
+ /* Only allow these ioctls */
+ switch(req) {
+#ifdef SIOCAIFADDR
+ case SIOCAIFADDR: /* FALLTHROUGH */
+ case SIOCDIFADDR: /* FALLTHROUGH */
+#endif
+#ifdef SIOCSIFHWADDR
+ case SIOCSIFHWADDR: /* FALLTHROUGH */
+#endif
+#ifdef SIOCGIFPRIORITY
+ case SIOCGIFPRIORITY: /* FALLTHROUGH */
+#endif
+ case SIOCSIFFLAGS: /* FALLTHROUGH */
+ case SIOCGIFMTU: /* FALLTHROUGH */
+ case SIOCSIFMTU:
+ break;
+ default:
+ errno = EPERM;
+ return -1;
+ }
+
s = socket(PF_INET, SOCK_DGRAM, 0);
if (s != -1)
#ifdef IOCTL_REQUEST_TYPE