Add kern_shm_open().

This allows you to specify the capabilities that the new file descriptor
should have. This allows us to create shared memory objects that only
have the rights we're interested in.

The idea behind restricting the rights is that it makes it a lot easier
for CloudABI to get consistent behaviour across different operating
systems. We only need to make sure that a shared memory implementation
consistently implements the operations that are whitelisted.

Approved by:	kib
Obtained from:	https://github.com/NuxiNL/freebsd
This commit is contained in:
Ed Schouten 2015-08-01 07:21:14 +00:00
parent fc9ce3812d
commit 7ee1b208c3
2 changed files with 27 additions and 18 deletions

View File

@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$");
#include <sys/resourcevar.h>
#include <sys/rwlock.h>
#include <sys/stat.h>
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/sysproto.h>
#include <sys/systm.h>
@ -683,9 +684,9 @@ shm_remove(char *path, Fnv32_t fnv, struct ucred *ucred)
return (ENOENT);
}
/* System calls. */
int
sys_shm_open(struct thread *td, struct shm_open_args *uap)
kern_shm_open(struct thread *td, const char *userpath, int flags, mode_t mode,
struct filecaps *fcaps)
{
struct filedesc *fdp;
struct shmfd *shmfd;
@ -699,28 +700,27 @@ sys_shm_open(struct thread *td, struct shm_open_args *uap)
/*
* shm_open(2) is only allowed for anonymous objects.
*/
if (IN_CAPABILITY_MODE(td) && (uap->path != SHM_ANON))
if (IN_CAPABILITY_MODE(td) && (userpath != SHM_ANON))
return (ECAPMODE);
#endif
if ((uap->flags & O_ACCMODE) != O_RDONLY &&
(uap->flags & O_ACCMODE) != O_RDWR)
if ((flags & O_ACCMODE) != O_RDONLY && (flags & O_ACCMODE) != O_RDWR)
return (EINVAL);
if ((uap->flags & ~(O_ACCMODE | O_CREAT | O_EXCL | O_TRUNC | O_CLOEXEC)) != 0)
if ((flags & ~(O_ACCMODE | O_CREAT | O_EXCL | O_TRUNC | O_CLOEXEC)) != 0)
return (EINVAL);
fdp = td->td_proc->p_fd;
cmode = (uap->mode & ~fdp->fd_cmask) & ACCESSPERMS;
cmode = (mode & ~fdp->fd_cmask) & ACCESSPERMS;
error = falloc(td, &fp, &fd, O_CLOEXEC);
error = falloc_caps(td, &fp, &fd, O_CLOEXEC, fcaps);
if (error)
return (error);
/* A SHM_ANON path pointer creates an anonymous object. */
if (uap->path == SHM_ANON) {
if (userpath == SHM_ANON) {
/* A read-only anonymous object is pointless. */
if ((uap->flags & O_ACCMODE) == O_RDONLY) {
if ((flags & O_ACCMODE) == O_RDONLY) {
fdclose(td, fp, fd);
fdrop(fp, td);
return (EINVAL);
@ -728,7 +728,7 @@ sys_shm_open(struct thread *td, struct shm_open_args *uap)
shmfd = shm_alloc(td->td_ucred, cmode);
} else {
path = malloc(MAXPATHLEN, M_SHMFD, M_WAITOK);
error = copyinstr(uap->path, path, MAXPATHLEN, NULL);
error = copyinstr(userpath, path, MAXPATHLEN, NULL);
#ifdef KTRACE
if (error == 0 && KTRPOINT(curthread, KTR_NAMEI))
ktrnamei(path);
@ -748,7 +748,7 @@ sys_shm_open(struct thread *td, struct shm_open_args *uap)
shmfd = shm_lookup(path, fnv);
if (shmfd == NULL) {
/* Object does not yet exist, create it if requested. */
if (uap->flags & O_CREAT) {
if (flags & O_CREAT) {
#ifdef MAC
error = mac_posixshm_check_create(td->td_ucred,
path);
@ -769,17 +769,16 @@ sys_shm_open(struct thread *td, struct shm_open_args *uap)
* reference if requested and permitted.
*/
free(path, M_SHMFD);
if ((uap->flags & (O_CREAT | O_EXCL)) ==
(O_CREAT | O_EXCL))
if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
error = EEXIST;
else {
#ifdef MAC
error = mac_posixshm_check_open(td->td_ucred,
shmfd, FFLAGS(uap->flags & O_ACCMODE));
shmfd, FFLAGS(flags & O_ACCMODE));
if (error == 0)
#endif
error = shm_access(shmfd, td->td_ucred,
FFLAGS(uap->flags & O_ACCMODE));
FFLAGS(flags & O_ACCMODE));
}
/*
@ -788,7 +787,7 @@ sys_shm_open(struct thread *td, struct shm_open_args *uap)
* opened with read/write.
*/
if (error == 0 &&
(uap->flags & (O_ACCMODE | O_TRUNC)) ==
(flags & (O_ACCMODE | O_TRUNC)) ==
(O_RDWR | O_TRUNC)) {
#ifdef MAC
error = mac_posixshm_check_truncate(
@ -809,7 +808,7 @@ sys_shm_open(struct thread *td, struct shm_open_args *uap)
}
}
finit(fp, FFLAGS(uap->flags & O_ACCMODE), DTYPE_SHM, shmfd, &shm_ops);
finit(fp, FFLAGS(flags & O_ACCMODE), DTYPE_SHM, shmfd, &shm_ops);
td->td_retval[0] = fd;
fdrop(fp, td);
@ -817,6 +816,14 @@ sys_shm_open(struct thread *td, struct shm_open_args *uap)
return (0);
}
/* System calls. */
int
sys_shm_open(struct thread *td, struct shm_open_args *uap)
{
return (kern_shm_open(td, uap->path, uap->flags, uap->mode, NULL));
}
int
sys_shm_unlink(struct thread *td, struct shm_unlink_args *uap)
{

View File

@ -204,6 +204,8 @@ int kern_setsockopt(struct thread *td, int s, int level, int name,
void *optval, enum uio_seg valseg, socklen_t valsize);
int kern_settimeofday(struct thread *td, struct timeval *tv,
struct timezone *tzp);
int kern_shm_open(struct thread *td, const char *userpath, int flags,
mode_t mode, struct filecaps *fcaps);
int kern_shmat(struct thread *td, int shmid, const void *shmaddr,
int shmflg);
int kern_shmctl(struct thread *td, int shmid, int cmd, void *buf,