Commit 4c504f5d authored by Ruslan Kuprieiev's avatar Ruslan Kuprieiev Committed by Pavel Emelyanov

dump: Don't dump if children's uids are not equal to client's uid

This is for security -- service is run from root, but serves requests from non-root
processes. Thus, we shouldn't allow for anyone to dump suid programs that a run from
under unpriviledged processes.
Signed-off-by: 's avatarRuslan Kuprieiev <kupruser@gmail.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent d74073a5
...@@ -64,6 +64,7 @@ ...@@ -64,6 +64,7 @@
#include "vdso.h" #include "vdso.h"
#include "page-pipe.h" #include "page-pipe.h"
#include "vdso.h" #include "vdso.h"
#include "cr-service.h"
#include "asm/dump.h" #include "asm/dump.h"
...@@ -393,39 +394,35 @@ err: ...@@ -393,39 +394,35 @@ err:
return ret; return ret;
} }
static int dump_task_creds(struct parasite_ctl *ctl, const struct cr_fdset *fds) static int dump_task_creds(struct parasite_ctl *ctl,
const struct cr_fdset *fds,
struct proc_status_creds *cr)
{ {
int ret;
struct proc_status_creds cr;
CredsEntry ce = CREDS_ENTRY__INIT; CredsEntry ce = CREDS_ENTRY__INIT;
pr_info("\n"); pr_info("\n");
pr_info("Dumping creds for %d)\n", ctl->pid.real); pr_info("Dumping creds for %d)\n", ctl->pid.real);
pr_info("----------------------------------------\n"); pr_info("----------------------------------------\n");
ret = parse_pid_status(ctl->pid.real, &cr); ce.uid = cr->uids[0];
if (ret < 0) ce.gid = cr->gids[0];
return ret; ce.euid = cr->uids[1];
ce.egid = cr->gids[1];
ce.uid = cr.uids[0]; ce.suid = cr->uids[2];
ce.gid = cr.gids[0]; ce.sgid = cr->gids[2];
ce.euid = cr.uids[1]; ce.fsuid = cr->uids[3];
ce.egid = cr.gids[1]; ce.fsgid = cr->gids[3];
ce.suid = cr.uids[2];
ce.sgid = cr.gids[2];
ce.fsuid = cr.uids[3];
ce.fsgid = cr.gids[3];
BUILD_BUG_ON(CR_CAP_SIZE != PROC_CAP_SIZE); BUILD_BUG_ON(CR_CAP_SIZE != PROC_CAP_SIZE);
ce.n_cap_inh = CR_CAP_SIZE; ce.n_cap_inh = CR_CAP_SIZE;
ce.cap_inh = cr.cap_inh; ce.cap_inh = cr->cap_inh;
ce.n_cap_prm = CR_CAP_SIZE; ce.n_cap_prm = CR_CAP_SIZE;
ce.cap_prm = cr.cap_prm; ce.cap_prm = cr->cap_prm;
ce.n_cap_eff = CR_CAP_SIZE; ce.n_cap_eff = CR_CAP_SIZE;
ce.cap_eff = cr.cap_eff; ce.cap_eff = cr->cap_eff;
ce.n_cap_bnd = CR_CAP_SIZE; ce.n_cap_bnd = CR_CAP_SIZE;
ce.cap_bnd = cr.cap_bnd; ce.cap_bnd = cr->cap_bnd;
if (parasite_dump_creds(ctl, &ce) < 0) if (parasite_dump_creds(ctl, &ce) < 0)
return -1; return -1;
...@@ -1373,6 +1370,19 @@ err_cure: ...@@ -1373,6 +1370,19 @@ err_cure:
goto err_free; goto err_free;
} }
static int check_uid(uid)
{
if (cr_service_client)
if ((cr_service_client->uid != uid) &&
(cr_service_client->uid != 0)) {
pr_err("UID (%d) != client's UID(%d)\n",
uid, cr_service_client->uid);
return -1;
}
return 0;
}
static int dump_one_task(struct pstree_item *item) static int dump_one_task(struct pstree_item *item)
{ {
pid_t pid = item->pid.real; pid_t pid = item->pid.real;
...@@ -1383,6 +1393,7 @@ static int dump_one_task(struct pstree_item *item) ...@@ -1383,6 +1393,7 @@ static int dump_one_task(struct pstree_item *item)
struct cr_fdset *cr_fdset = NULL; struct cr_fdset *cr_fdset = NULL;
struct parasite_drain_fd *dfds; struct parasite_drain_fd *dfds;
struct proc_posix_timers_stat proc_args; struct proc_posix_timers_stat proc_args;
struct proc_status_creds cr;
pr_info("========================================\n"); pr_info("========================================\n");
pr_info("Dumping task (pid: %d)\n", pid); pr_info("Dumping task (pid: %d)\n", pid);
...@@ -1405,6 +1416,16 @@ static int dump_one_task(struct pstree_item *item) ...@@ -1405,6 +1416,16 @@ static int dump_one_task(struct pstree_item *item)
if (ret < 0) if (ret < 0)
goto err; goto err;
ret = parse_pid_status(pid, &cr);
if (ret)
goto err;
ret = check_uid(cr.uids[0]);
if (ret) {
pr_err("Check uid (pid: %d) failed\n", pid);
goto err;
}
ret = collect_mappings(pid, &vmas); ret = collect_mappings(pid, &vmas);
if (ret) { if (ret) {
pr_err("Collect mappings (pid: %d) failed with %d\n", pid, ret); pr_err("Collect mappings (pid: %d) failed with %d\n", pid, ret);
...@@ -1532,7 +1553,7 @@ static int dump_one_task(struct pstree_item *item) ...@@ -1532,7 +1553,7 @@ static int dump_one_task(struct pstree_item *item)
goto err_cure; goto err_cure;
} }
ret = dump_task_creds(parasite_ctl, cr_fdset); ret = dump_task_creds(parasite_ctl, cr_fdset, &cr);
if (ret) { if (ret) {
pr_err("Dump creds (pid: %d) failed with %d\n", pid, ret); pr_err("Dump creds (pid: %d) failed with %d\n", pid, ret);
goto err; goto err;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment