Limit rights on process descriptors.

On CloudABI, the rights bits returned by cap_rights_get() match up with
the operations that you can actually perform on the file descriptor.

Limiting the rights is good, because it makes it easier to get uniform
behaviour across different operating systems. If process descriptors on
FreeBSD would suddenly gain support for any new file operation, this
wouldn't become exposed to CloudABI processes without first extending
the rights.

Extend fork1() to gain a 'struct filecaps' argument that allows you to
construct process descriptors with custom rights. Use this in
cloudabi_sys_proc_fork() to limit the rights to just fstat() and
pdwait().

Obtained from:	https://github.com/NuxiNL/freebsd
This commit is contained in:
Ed Schouten 2015-07-31 10:21:58 +00:00
parent a2b3dfad08
commit 367a13f905
6 changed files with 21 additions and 14 deletions

View File

@ -27,6 +27,8 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/capsicum.h>
#include <sys/filedesc.h>
#include <sys/imgact.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@ -67,10 +69,12 @@ int
cloudabi_sys_proc_fork(struct thread *td,
struct cloudabi_sys_proc_fork_args *uap)
{
struct filecaps fcaps = {};
struct proc *p2;
int error, fd;
error = fork1(td, RFFDG | RFPROC | RFPROCDESC, 0, &p2, &fd, 0);
cap_rights_init(&fcaps.fc_rights, CAP_FSTAT, CAP_PDWAIT);
error = fork1(td, RFFDG | RFPROC | RFPROCDESC, 0, &p2, &fd, 0, &fcaps);
if (error != 0)
return (error);
/* Return the file descriptor to the parent process. */

View File

@ -73,8 +73,8 @@ linux_fork(struct thread *td, struct linux_fork_args *args)
printf(ARGS(fork, ""));
#endif
if ((error = fork1(td, RFFDG | RFPROC | RFSTOPPED, 0, &p2, NULL, 0))
!= 0)
if ((error = fork1(td, RFFDG | RFPROC | RFSTOPPED, 0, &p2, NULL, 0,
NULL)) != 0)
return (error);
td2 = FIRST_THREAD_IN_PROC(p2);
@ -108,7 +108,7 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args)
/* Exclude RFPPWAIT */
if ((error = fork1(td, RFFDG | RFPROC | RFMEM | RFSTOPPED, 0, &p2,
NULL, 0)) != 0)
NULL, 0, NULL)) != 0)
return (error);
@ -179,7 +179,7 @@ linux_clone_proc(struct thread *td, struct linux_clone_args *args)
if (args->parent_tidptr == NULL)
return (EINVAL);
error = fork1(td, ff, 0, &p2, NULL, 0);
error = fork1(td, ff, 0, &p2, NULL, 0, NULL);
if (error)
return (error);

View File

@ -831,7 +831,7 @@ create_init(const void *udata __unused)
int error;
error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, 0, &initproc,
NULL, 0);
NULL, 0, NULL);
if (error)
panic("cannot fork init: %d\n", error);
KASSERT(initproc->p_pid == 1, ("create_init: initproc->p_pid != 1"));

View File

@ -104,7 +104,7 @@ sys_fork(struct thread *td, struct fork_args *uap)
int error;
struct proc *p2;
error = fork1(td, RFFDG | RFPROC, 0, &p2, NULL, 0);
error = fork1(td, RFFDG | RFPROC, 0, &p2, NULL, 0, NULL);
if (error == 0) {
td->td_retval[0] = p2->p_pid;
td->td_retval[1] = 0;
@ -127,7 +127,7 @@ sys_pdfork(td, uap)
* itself from the parent using the return value.
*/
error = fork1(td, RFFDG | RFPROC | RFPROCDESC, 0, &p2,
&fd, uap->flags);
&fd, uap->flags, NULL);
if (error == 0) {
td->td_retval[0] = p2->p_pid;
td->td_retval[1] = 0;
@ -144,7 +144,7 @@ sys_vfork(struct thread *td, struct vfork_args *uap)
struct proc *p2;
flags = RFFDG | RFPROC | RFPPWAIT | RFMEM;
error = fork1(td, flags, 0, &p2, NULL, 0);
error = fork1(td, flags, 0, &p2, NULL, 0, NULL);
if (error == 0) {
td->td_retval[0] = p2->p_pid;
td->td_retval[1] = 0;
@ -163,7 +163,7 @@ sys_rfork(struct thread *td, struct rfork_args *uap)
return (EINVAL);
AUDIT_ARG_FFLAGS(uap->flags);
error = fork1(td, uap->flags, 0, &p2, NULL, 0);
error = fork1(td, uap->flags, 0, &p2, NULL, 0, NULL);
if (error == 0) {
td->td_retval[0] = p2 ? p2->p_pid : 0;
td->td_retval[1] = 0;
@ -768,7 +768,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
int
fork1(struct thread *td, int flags, int pages, struct proc **procp,
int *procdescp, int pdflags)
int *procdescp, int pdflags, struct filecaps *fcaps)
{
struct proc *p1;
struct proc *newproc;
@ -824,7 +824,8 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
* later.
*/
if (flags & RFPROCDESC) {
error = falloc(td, &fp_procdesc, procdescp, 0);
error = falloc_caps(td, &fp_procdesc, procdescp, 0,
fcaps);
if (error != 0)
return (error);
}

View File

@ -89,7 +89,7 @@ kproc_create(void (*func)(void *), void *arg,
panic("kproc_create called too soon");
error = fork1(&thread0, RFMEM | RFFDG | RFPROC | RFSTOPPED | flags,
pages, &p2, NULL, 0);
pages, &p2, NULL, 0, NULL);
if (error)
return error;

View File

@ -161,6 +161,7 @@ struct pargs {
* for write access.
*/
struct cpuset;
struct filecaps;
struct kaioinfo;
struct kaudit_record;
struct kdtrace_proc;
@ -916,7 +917,8 @@ int enterpgrp(struct proc *p, pid_t pgid, struct pgrp *pgrp,
int enterthispgrp(struct proc *p, struct pgrp *pgrp);
void faultin(struct proc *p);
void fixjobc(struct proc *p, struct pgrp *pgrp, int entering);
int fork1(struct thread *, int, int, struct proc **, int *, int);
int fork1(struct thread *, int, int, struct proc **, int *, int,
struct filecaps *);
void fork_exit(void (*)(void *, struct trapframe *), void *,
struct trapframe *);
void fork_return(struct thread *, struct trapframe *);