diff options
| author | Roy Marples <roy@marples.name> | 2020-05-21 12:54:58 +0100 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2020-05-21 12:54:58 +0100 |
| commit | 8179a69d03a2939ed5c795f94dca74bb2d0e6b6c (patch) | |
| tree | 34dc0e64218f43fb93bbdb6362f7e79f1129525a /src/privsep-root.c | |
| parent | 9121c5c67a7ad7127c9434ec00662b4bf0aedd0d (diff) | |
| download | dhcpcd-8179a69d03a2939ed5c795f94dca74bb2d0e6b6c.tar.xz | |
privsep: Only allow file IO to specific paths
In the same vein as filtering ioctls.
Diffstat (limited to 'src/privsep-root.c')
| -rw-r--r-- | src/privsep-root.c | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/src/privsep-root.c b/src/privsep-root.c index 8232a532..d58d282f 100644 --- a/src/privsep-root.c +++ b/src/privsep-root.c @@ -304,8 +304,25 @@ ps_root_run_script(struct dhcpcd_ctx *ctx, const void *data, size_t len) 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 @@ ps_root_dowritefile(mode_t mode, void *data, size_t len) 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 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg) 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 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg) } 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); |
