changeset 5249:a8c2969955f9 draft

privsep: Only allow file IO to specific paths In the same vein as filtering ioctls.
author Roy Marples <roy@marples.name>
date Thu, 21 May 2020 12:54:58 +0100
parents af220d1d4c92
children 698ca745f939
files src/privsep-root.c
diffstat 1 files changed, 30 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/privsep-root.c	Wed May 20 21:43:20 2020 +0100
+++ b/src/privsep-root.c	Thu May 21 12:54:58 2020 +0100
@@ -304,8 +304,25 @@
 	return status;
 }
 
+static bool
+ps_root_validpath(const struct dhcpcd_ctx *ctx, uint16_t cmd, const char *path)
+{
+
+	if (cmd == PS_READFILE) {
+		if (strcmp(ctx->cffile, path) == 0)
+			return true;
+	}
+	if (strncmp(DBDIR, path, strlen(DBDIR)) == 0)
+		return true;
+	if (strncmp(RUNDIR, path, strlen(RUNDIR)) == 0)
+		return true;
+	errno = EPERM;
+	return false;
+}
+
 static ssize_t
-ps_root_dowritefile(mode_t mode, void *data, size_t len)
+ps_root_dowritefile(const struct dhcpcd_ctx *ctx,
+    mode_t mode, void *data, size_t len)
 {
 	char *file = data, *nc;
 
@@ -314,6 +331,8 @@
 		errno = EINVAL;
 		return -1;
 	}
+	if (!ps_root_validpath(ctx, PS_WRITEFILE, file))
+		return -1;
 	nc++;
 	return writefile(file, mode, nc, len - (size_t)(nc - file));
 }
@@ -480,9 +499,17 @@
 		err = ps_root_run_script(ctx, data, len);
 		break;
 	case PS_UNLINK:
+		if (!ps_root_validpath(ctx, psm->ps_cmd, data)) {
+			err = -1;
+			break;
+		}
 		err = unlink(data);
 		break;
 	case PS_READFILE:
+		if (!ps_root_validpath(ctx, psm->ps_cmd, data)) {
+			err = -1;
+			break;
+		}
 		err = readfile(data, buf, sizeof(buf));
 		if (err != -1) {
 			rdata = buf;
@@ -490,7 +517,8 @@
 		}
 		break;
 	case PS_WRITEFILE:
-		err = ps_root_dowritefile((mode_t)psm->ps_flags, data, len);
+		err = ps_root_dowritefile(ctx, (mode_t)psm->ps_flags,
+		    data, len);
 		break;
 	case PS_FILEMTIME:
 		err = filemtime(data, &mtime);