In libcasper, prefer to send a function index or service name over the IPC
channel to a zygote process, rather than sending a function pointer or service pointer. This avoids transfering pointers between address spaces, which while robust in this case (due to the zygote being forked() from the parent) is not generally a good idea, especially in the presence of increasingly popular control-flow integrity and pointer protection mitigation schemes. With this change, ping(8) and other sandboxed tools using libcasper for DNS resolution now work on architectures with tagged memory again. Reviewed by: oshogbo MFC after: 1 week Sponsored by: DARPA, AFRL
This commit is contained in:
parent
63254ceea6
commit
a78ff3f4f3
@ -1,11 +1,16 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 The FreeBSD Foundation
|
||||
* Copyright (c) 2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
|
||||
* Copyright (c) 2017 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by Pawel Jakub Dawidek under sponsorship from
|
||||
* the FreeBSD Foundation.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
@ -130,18 +135,25 @@ casper_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
service_execute(int chanfd)
|
||||
{
|
||||
struct casper_service *casserv;
|
||||
struct service *service;
|
||||
const char *servname;
|
||||
nvlist_t *nvl;
|
||||
int procfd;
|
||||
|
||||
nvl = nvlist_recv(chanfd, 0);
|
||||
if (nvl == NULL)
|
||||
exit(1);
|
||||
service = (struct service *)(uintptr_t)nvlist_take_number(nvl,
|
||||
"service");
|
||||
if (!nvlist_exists_string(nvl, "service"))
|
||||
exit(1);
|
||||
servname = nvlist_get_string(nvl, "service");
|
||||
casserv = service_find(servname);
|
||||
if (casserv == NULL)
|
||||
exit(1);
|
||||
service = casserv->cs_service;
|
||||
procfd = nvlist_take_descriptor(nvl, "procfd");
|
||||
nvlist_destroy(nvl);
|
||||
|
||||
@ -172,12 +184,11 @@ casper_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin,
|
||||
if (!casper_allowed_service(limits, servname))
|
||||
return (ENOTCAPABLE);
|
||||
|
||||
if (zygote_clone(service_execute, &chanfd, &procfd) == -1)
|
||||
if (zygote_clone_service_execute(&chanfd, &procfd) == -1)
|
||||
return (errno);
|
||||
|
||||
nvl = nvlist_create(0);
|
||||
nvlist_add_number(nvl, "service",
|
||||
(uint64_t)(uintptr_t)casserv->cs_service);
|
||||
nvlist_add_string(nvl, "service", servname);
|
||||
nvlist_move_descriptor(nvl, "procfd", procfd);
|
||||
if (nvlist_send(chanfd, nvl) == -1) {
|
||||
error = errno;
|
||||
|
@ -1,11 +1,16 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 The FreeBSD Foundation
|
||||
* Copyright (c) 2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2017 Robert N. M. Watson
|
||||
*
|
||||
* This software was developed by Pawel Jakub Dawidek under sponsorship from
|
||||
* the FreeBSD Foundation.
|
||||
*
|
||||
* All rights reserved.
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
@ -50,8 +55,10 @@ __FBSDID("$FreeBSD$");
|
||||
/* Zygote info. */
|
||||
static int zygote_sock = -1;
|
||||
|
||||
#define ZYGOTE_SERVICE_EXECUTE 1
|
||||
|
||||
int
|
||||
zygote_clone(zygote_func_t *func, int *chanfdp, int *procfdp)
|
||||
zygote_clone(uint64_t funcidx, int *chanfdp, int *procfdp)
|
||||
{
|
||||
nvlist_t *nvl;
|
||||
int error;
|
||||
@ -63,7 +70,7 @@ zygote_clone(zygote_func_t *func, int *chanfdp, int *procfdp)
|
||||
}
|
||||
|
||||
nvl = nvlist_create(0);
|
||||
nvlist_add_number(nvl, "func", (uint64_t)(uintptr_t)func);
|
||||
nvlist_add_number(nvl, "funcidx", funcidx);
|
||||
nvl = nvlist_xfer(zygote_sock, nvl, 0);
|
||||
if (nvl == NULL)
|
||||
return (-1);
|
||||
@ -81,6 +88,13 @@ zygote_clone(zygote_func_t *func, int *chanfdp, int *procfdp)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
zygote_clone_service_execute(int *chanfdp, int *procfdp)
|
||||
{
|
||||
|
||||
return (zygote_clone(ZYGOTE_SERVICE_EXECUTE, chanfdp, procfdp));
|
||||
}
|
||||
|
||||
/*
|
||||
* This function creates sandboxes on-demand whoever has access to it via
|
||||
* 'sock' socket. Function sends two descriptors to the caller: process
|
||||
@ -93,6 +107,7 @@ zygote_main(int sock)
|
||||
int error, procfd;
|
||||
int chanfd[2];
|
||||
nvlist_t *nvlin, *nvlout;
|
||||
uint64_t funcidx;
|
||||
zygote_func_t *func;
|
||||
pid_t pid;
|
||||
|
||||
@ -109,10 +124,17 @@ zygote_main(int sock)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
func = (zygote_func_t *)(uintptr_t)nvlist_get_number(nvlin,
|
||||
"func");
|
||||
funcidx = nvlist_get_number(nvlin, "funcidx");
|
||||
nvlist_destroy(nvlin);
|
||||
|
||||
switch (funcidx) {
|
||||
case ZYGOTE_SERVICE_EXECUTE:
|
||||
func = service_execute;
|
||||
break;
|
||||
default:
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Someone is requesting a new process, create one.
|
||||
*/
|
||||
|
@ -36,6 +36,12 @@
|
||||
typedef void zygote_func_t(int);
|
||||
|
||||
int zygote_init(void);
|
||||
int zygote_clone(zygote_func_t *func, int *chanfdp, int *procfdp);
|
||||
int zygote_clone(uint64_t funcidx, int *chanfdp, int *procfdp);
|
||||
int zygote_clone_service_execute(int *chanfdp, int *procfdp);
|
||||
|
||||
/*
|
||||
* Functions reachable via zygote_clone().
|
||||
*/
|
||||
zygote_func_t service_execute;
|
||||
|
||||
#endif /* !_ZYGOTE_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user