This commit was generated by cvs2svn to compensate for changes in r86567,
which included commits to RCS files with non-trunk default branches.
This commit is contained in:
commit
5eca824ab0
497
sys/contrib/lomac/kernel_interface.c
Normal file
497
sys/contrib/lomac/kernel_interface.c
Normal file
@ -0,0 +1,497 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kernel_interface.c,v 1.25 2001/10/25 21:21:59 tfraser Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/pipe.h>
|
||||
#include <sys/socketvar.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_map.h>
|
||||
|
||||
#include "kernel_interface.h"
|
||||
#include "lomacfs.h"
|
||||
#include "kernel_log.h"
|
||||
|
||||
/*
|
||||
* Reuse the eflags field of proc.p_vmspace->vm_map.header (since it is
|
||||
* currently not used for anything but a placeholder, and won't change
|
||||
* generally...) as storage for our process-based information.
|
||||
*
|
||||
* This is the only really effective way to make thread-based MAC
|
||||
* easy.
|
||||
*/
|
||||
|
||||
#define p_eflags p_vmspace->vm_map.header.eflags
|
||||
#define EF_HIGHEST_LEVEL 0x00010000
|
||||
#define EF_LOWEST_LEVEL 0x00020000
|
||||
#define EF_LEVEL_MASK 0x00030000
|
||||
#define EF_ATTR_NONETDEMOTE 0x00040000
|
||||
#define EF_ATTR_NODEMOTE 0x00080000
|
||||
#define EF_ATTR_MASK 0x000c0000
|
||||
|
||||
static u_int
|
||||
level2subjectbits(level_t level) {
|
||||
|
||||
switch (level) {
|
||||
case LOMAC_HIGHEST_LEVEL:
|
||||
return (EF_HIGHEST_LEVEL);
|
||||
case LOMAC_LOWEST_LEVEL:
|
||||
return (EF_LOWEST_LEVEL);
|
||||
default:
|
||||
panic("level2subjectbits: invalid level %d\n", level);
|
||||
}
|
||||
}
|
||||
|
||||
static level_t
|
||||
subjectbits2level(u_int flags) {
|
||||
|
||||
switch (flags & EF_LEVEL_MASK) {
|
||||
case EF_HIGHEST_LEVEL:
|
||||
/*
|
||||
* During an execve(), the kernel's original execve() creates a
|
||||
* new vmspace and puts it into use before it has been initialized
|
||||
* by us to contain a subject level. Since this is the only case
|
||||
* when a subject may have a level not set, pretend that it
|
||||
* is just a high-level file, and allow the lomacfs_open() to then
|
||||
* succeed.
|
||||
*/
|
||||
case 0:
|
||||
return (LOMAC_HIGHEST_LEVEL);
|
||||
case EF_LOWEST_LEVEL:
|
||||
return (LOMAC_LOWEST_LEVEL);
|
||||
default:
|
||||
panic("subjectbits2level: invalid flags %#x\n", flags);
|
||||
}
|
||||
}
|
||||
|
||||
static u_int
|
||||
attr2subjectbits(u_int attr) {
|
||||
u_int bits = 0;
|
||||
|
||||
if (attr & LOMAC_ATTR_NONETDEMOTE)
|
||||
bits |= EF_ATTR_NONETDEMOTE;
|
||||
if (attr & LOMAC_ATTR_NODEMOTE)
|
||||
bits |= EF_ATTR_NODEMOTE;
|
||||
return (bits);
|
||||
}
|
||||
|
||||
static u_int
|
||||
subjectbits2attr(u_int bits) {
|
||||
u_int attr = 0;
|
||||
|
||||
if (bits & EF_ATTR_NONETDEMOTE)
|
||||
attr |= LOMAC_ATTR_NONETDEMOTE;
|
||||
if (bits & EF_ATTR_NODEMOTE)
|
||||
attr |= LOMAC_ATTR_NODEMOTE;
|
||||
return (attr);
|
||||
}
|
||||
|
||||
static int
|
||||
subject_lock(lomac_subject_t *p, int read) {
|
||||
#ifdef USES_LOCKMGR
|
||||
int hadlock;
|
||||
|
||||
hadlock = PROC_LOCKED(p);
|
||||
if (hadlock)
|
||||
PROC_UNLOCK(p);
|
||||
#endif
|
||||
if (read)
|
||||
vm_map_lock_read(&p->p_vmspace->vm_map);
|
||||
else
|
||||
vm_map_lock(&p->p_vmspace->vm_map);
|
||||
#ifdef USES_LOCKMGR
|
||||
return (hadlock);
|
||||
#else
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
subject_unlock(lomac_subject_t *p, int read, int hadlock) {
|
||||
|
||||
if (read)
|
||||
vm_map_unlock_read(&p->p_vmspace->vm_map);
|
||||
else
|
||||
vm_map_unlock(&p->p_vmspace->vm_map);
|
||||
#ifdef USES_LOCKMGR
|
||||
if (hadlock)
|
||||
PROC_LOCK(p);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
init_subject_lattr(lomac_subject_t *p, lattr_t *lattr) {
|
||||
int s;
|
||||
|
||||
s = subject_lock(p, 0);
|
||||
p->p_eflags = level2subjectbits(lattr->level) |
|
||||
attr2subjectbits(lattr->flags);
|
||||
subject_unlock(p, 0, s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set/get the subject level on a process. The process must not be able
|
||||
* to change, so either the process must be locked on entry or it must
|
||||
* be held in exclusivity otherwise (executing on behalf of via a syscall,
|
||||
* including as EITHER child or parent in a fork).
|
||||
*/
|
||||
void
|
||||
set_subject_lattr(lomac_subject_t *p, lattr_t lattr) {
|
||||
int s;
|
||||
|
||||
#ifdef INVARIANTS
|
||||
do {
|
||||
lattr_t oslattr;
|
||||
|
||||
get_subject_lattr(p, &oslattr);
|
||||
if (lomac_must_demote(&lattr, &oslattr))
|
||||
panic("raising subject level");
|
||||
} while (0);
|
||||
#endif /* !INVARIANTS */
|
||||
s = subject_lock(p, 0);
|
||||
p->p_eflags = (p->p_eflags & ~(EF_LEVEL_MASK | EF_ATTR_MASK)) |
|
||||
level2subjectbits(lattr.level) |
|
||||
attr2subjectbits(lattr.flags);
|
||||
subject_unlock(p, 0, s);
|
||||
kernel_vm_drop_perms(curthread, &lattr);
|
||||
}
|
||||
|
||||
void
|
||||
get_subject_lattr(lomac_subject_t *p, lattr_t *lattr) {
|
||||
int s;
|
||||
|
||||
s = subject_lock(p, 1);
|
||||
lattr->level = subjectbits2level(p->p_eflags);
|
||||
lattr->flags = subjectbits2attr(p->p_eflags);
|
||||
subject_unlock(p, 1, s);
|
||||
}
|
||||
|
||||
static __inline u_int
|
||||
level2lvnodebits(level_t level) {
|
||||
|
||||
switch (level) {
|
||||
case LOMAC_HIGHEST_LEVEL:
|
||||
return (LN_HIGHEST_LEVEL);
|
||||
case LOMAC_LOWEST_LEVEL:
|
||||
return (LN_LOWEST_LEVEL);
|
||||
default:
|
||||
panic("level2lvnodebits: invalid level %d\n", level);
|
||||
}
|
||||
}
|
||||
|
||||
static __inline level_t
|
||||
lvnodebits2level(u_int flags) {
|
||||
|
||||
switch (flags & LN_LEVEL_MASK) {
|
||||
case LN_HIGHEST_LEVEL:
|
||||
return (LOMAC_HIGHEST_LEVEL);
|
||||
case LN_LOWEST_LEVEL:
|
||||
return (LOMAC_LOWEST_LEVEL);
|
||||
default:
|
||||
panic("lvnodebits2level: invalid flags %#x\n", flags);
|
||||
}
|
||||
}
|
||||
|
||||
static __inline unsigned int
|
||||
attr2lvnodebits(unsigned int attr) {
|
||||
unsigned int bits = 0;
|
||||
|
||||
if (attr & LOMAC_ATTR_LOWWRITE)
|
||||
bits |= LN_ATTR_LOWWRITE;
|
||||
if (attr & LOMAC_ATTR_LOWNOOPEN)
|
||||
bits |= LN_ATTR_LOWNOOPEN;
|
||||
if (attr & LOMAC_ATTR_NONETDEMOTE)
|
||||
bits |= LN_ATTR_NONETDEMOTE;
|
||||
if (attr & LOMAC_ATTR_NODEMOTE)
|
||||
bits |= LN_ATTR_NODEMOTE;
|
||||
return (bits);
|
||||
}
|
||||
|
||||
static __inline unsigned int
|
||||
lvnodebits2attr(unsigned int bits) {
|
||||
unsigned int attr = 0;
|
||||
|
||||
if (bits & LN_ATTR_LOWWRITE)
|
||||
attr |= LOMAC_ATTR_LOWWRITE;
|
||||
if (bits & LN_ATTR_LOWNOOPEN)
|
||||
attr |= LOMAC_ATTR_LOWNOOPEN;
|
||||
if (bits & LN_ATTR_NONETDEMOTE)
|
||||
attr |= LOMAC_ATTR_NONETDEMOTE;
|
||||
if (bits & LN_ATTR_NODEMOTE)
|
||||
attr |= LOMAC_ATTR_NODEMOTE;
|
||||
return (attr);
|
||||
}
|
||||
|
||||
/*
|
||||
* These flags correspond to the same ones set in lomac_node{}s.
|
||||
*/
|
||||
#define UV_LEVEL_MASK 0x08000000
|
||||
#define UV_LOWEST_LEVEL 0x00000000
|
||||
#define UV_HIGHEST_LEVEL 0x08000000
|
||||
#define UV_ATTR_LOWWRITE 0x10000000
|
||||
#define UV_ATTR_LOWNOOPEN 0x20000000
|
||||
#define UV_ATTR_NONETDEMOTE 0x40000000
|
||||
#define UV_ATTR_NODEMOTE 0x80000000
|
||||
#define UV_ATTR_MASK 0xf0000000
|
||||
|
||||
static __inline u_int
|
||||
level2uvnodebits(level_t level) {
|
||||
|
||||
switch (level) {
|
||||
case LOMAC_HIGHEST_LEVEL:
|
||||
return (UV_HIGHEST_LEVEL);
|
||||
case LOMAC_LOWEST_LEVEL:
|
||||
return (UV_LOWEST_LEVEL);
|
||||
default:
|
||||
panic("level2uvnodebits: invalid level %d\n", level);
|
||||
}
|
||||
}
|
||||
|
||||
static __inline level_t
|
||||
uvnodebits2level(u_int flags) {
|
||||
|
||||
switch (flags & UV_LEVEL_MASK) {
|
||||
case UV_HIGHEST_LEVEL:
|
||||
return (LOMAC_HIGHEST_LEVEL);
|
||||
case UV_LOWEST_LEVEL:
|
||||
return (LOMAC_LOWEST_LEVEL);
|
||||
default:
|
||||
panic("uvnodebits2level: invalid flags %#x\n", flags);
|
||||
}
|
||||
}
|
||||
|
||||
static __inline u_int
|
||||
attr2uvnodebits(u_int attr) {
|
||||
unsigned int bits = 0;
|
||||
|
||||
if (attr & LOMAC_ATTR_LOWWRITE)
|
||||
bits |= UV_ATTR_LOWWRITE;
|
||||
if (attr & LOMAC_ATTR_LOWNOOPEN)
|
||||
bits |= UV_ATTR_LOWNOOPEN;
|
||||
if (attr & LOMAC_ATTR_NONETDEMOTE)
|
||||
bits |= UV_ATTR_NONETDEMOTE;
|
||||
if (attr & LOMAC_ATTR_NODEMOTE)
|
||||
bits |= UV_ATTR_NODEMOTE;
|
||||
return (bits);
|
||||
}
|
||||
|
||||
static __inline u_int
|
||||
uvnodebits2attr(u_int bits) {
|
||||
unsigned int attr = 0;
|
||||
|
||||
if (bits & UV_ATTR_LOWWRITE)
|
||||
attr |= LOMAC_ATTR_LOWWRITE;
|
||||
if (bits & UV_ATTR_LOWNOOPEN)
|
||||
attr |= LOMAC_ATTR_LOWNOOPEN;
|
||||
if (bits & UV_ATTR_NONETDEMOTE)
|
||||
attr |= LOMAC_ATTR_NONETDEMOTE;
|
||||
if (bits & UV_ATTR_NODEMOTE)
|
||||
attr |= LOMAC_ATTR_NODEMOTE;
|
||||
return (attr);
|
||||
}
|
||||
|
||||
#define OBJ_LOWEST_LEVEL 0x8000 /* the highest level is implicit */
|
||||
|
||||
/*
|
||||
* This code marks pipes with levels. We use a previously unnused bit
|
||||
* in the pipe_state field of struct pipe to store the level
|
||||
* information. Bit clear means LOMAC_HIGHEST_LEVEL, bit set means
|
||||
* LOMAC_LOWEST_LEVEL. Since new pipes have clear bits by default,
|
||||
* using clear bit as highest causes new pipes to start at the highest
|
||||
* level automatically.
|
||||
*/
|
||||
#define PIPE_LEVEL_LOWEST 0x10000000
|
||||
|
||||
/* This code marks sockets created by socketpair() with levels. It
|
||||
* uses a previouslt unused bit in the so_state field of struct socket
|
||||
* to store the level information. Bit clear means
|
||||
* LOMAC_HIGHEST_LEVEL, bit set means LOMAC_LOWEST_LEVEL. Since new
|
||||
* sockets have clear bits by default, using clear bit as highest
|
||||
* causes new sockets to start at the highest level automatically.
|
||||
*/
|
||||
#define SOCKET_LEVEL_LOWEST 0x4000
|
||||
|
||||
void
|
||||
set_object_lattr(lomac_object_t *obj, lattr_t lattr) {
|
||||
struct vnode *vp;
|
||||
struct lomac_node *ln;
|
||||
vm_object_t object;
|
||||
struct pipe *pipe;
|
||||
struct socket *socket;
|
||||
|
||||
switch (obj->lo_type) {
|
||||
case LO_TYPE_LVNODE:
|
||||
KASSERT(VISLOMAC(obj->lo_object.vnode),
|
||||
("not a LOMACFS vnode"));
|
||||
ln = VTOLOMAC(obj->lo_object.vnode);
|
||||
ln->ln_flags =
|
||||
(ln->ln_flags & ~(LN_LEVEL_MASK | LN_ATTR_MASK)) |
|
||||
level2lvnodebits(lattr.level) |
|
||||
attr2lvnodebits(lattr.flags);
|
||||
break;
|
||||
case LO_TYPE_UVNODE:
|
||||
vp = obj->lo_object.vnode;
|
||||
KASSERT(!VISLOMAC(vp), ("is a LOMACFS vnode"));
|
||||
VI_LOCK(vp);
|
||||
vp->v_flag = (vp->v_flag & ~(UV_LEVEL_MASK | UV_ATTR_MASK)) |
|
||||
level2uvnodebits(lattr.level) |
|
||||
attr2uvnodebits(lattr.flags);
|
||||
VI_UNLOCK(vp);
|
||||
break;
|
||||
case LO_TYPE_VM_OBJECT:
|
||||
object = obj->lo_object.vm_object;
|
||||
KASSERT(object->type != OBJT_VNODE, ("object has a vnode"));
|
||||
KASSERT(object->backing_object == NULL,
|
||||
("is a backing object"));
|
||||
if (lattr.level == LOMAC_HIGHEST_LEVEL)
|
||||
vm_object_clear_flag(object, OBJ_LOWEST_LEVEL);
|
||||
else
|
||||
vm_object_set_flag(object, OBJ_LOWEST_LEVEL);
|
||||
KASSERT(lattr.flags == 0,
|
||||
("cannot set attr on a vm_object"));
|
||||
break;
|
||||
case LO_TYPE_PIPE:
|
||||
pipe = obj->lo_object.pipe;
|
||||
KASSERT(pipe->pipe_peer == NULL ||
|
||||
(pipe->pipe_state & PIPE_LEVEL_LOWEST) ==
|
||||
(pipe->pipe_peer->pipe_state & PIPE_LEVEL_LOWEST),
|
||||
("pipe attrs unsynchronized"));
|
||||
if (lattr.level == LOMAC_HIGHEST_LEVEL)
|
||||
pipe->pipe_state &= ~PIPE_LEVEL_LOWEST;
|
||||
else
|
||||
pipe->pipe_state |= PIPE_LEVEL_LOWEST;
|
||||
pipe = pipe->pipe_peer;
|
||||
if (pipe != NULL) {
|
||||
if (lattr.level == LOMAC_HIGHEST_LEVEL)
|
||||
pipe->pipe_state &= ~PIPE_LEVEL_LOWEST;
|
||||
else
|
||||
pipe->pipe_state |= PIPE_LEVEL_LOWEST;
|
||||
}
|
||||
KASSERT(lattr.flags == 0, ("cannot set attr on a pipe"));
|
||||
break;
|
||||
case LO_TYPE_SOCKETPAIR:
|
||||
socket = obj->lo_object.socket;
|
||||
/* KASSERT that socket peer levels are synchronized */
|
||||
if (lattr.level == LOMAC_HIGHEST_LEVEL)
|
||||
socket->so_state &= ~SOCKET_LEVEL_LOWEST;
|
||||
else
|
||||
socket->so_state |= SOCKET_LEVEL_LOWEST;
|
||||
#ifdef NOT_YET
|
||||
pipe = pipe->pipe_peer;
|
||||
if (pipe != NULL) {
|
||||
if (lattr.level == LOMAC_HIGHEST_LEVEL)
|
||||
pipe->pipe_state &= ~PIPE_LEVEL_LOWEST;
|
||||
else
|
||||
pipe->pipe_state |= PIPE_LEVEL_LOWEST;
|
||||
}
|
||||
KASSERT(lattr.flags == 0, ("cannot set attr on a pipe"));
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
panic("set_object_lattr: invalid lo_type %d", obj->lo_type);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
get_object_lattr(const lomac_object_t *obj, lattr_t *lattr) {
|
||||
struct vnode *vp;
|
||||
struct lomac_node *ln;
|
||||
vm_object_t object;
|
||||
struct pipe *pipe;
|
||||
struct socket *socket;
|
||||
|
||||
switch (obj->lo_type) {
|
||||
case LO_TYPE_LVNODE:
|
||||
KASSERT(VISLOMAC(obj->lo_object.vnode),
|
||||
("not a LOMACFS vnode"));
|
||||
ln = VTOLOMAC(obj->lo_object.vnode);
|
||||
lattr->level = lvnodebits2level(ln->ln_flags);
|
||||
lattr->flags = lvnodebits2attr(ln->ln_flags);
|
||||
break;
|
||||
case LO_TYPE_UVNODE:
|
||||
vp = obj->lo_object.vnode;
|
||||
KASSERT(!VISLOMAC(vp), ("is a LOMACFS vnode"));
|
||||
VI_LOCK(vp);
|
||||
lattr->level = uvnodebits2level(vp->v_flag);
|
||||
lattr->flags = uvnodebits2attr(vp->v_flag);
|
||||
VI_UNLOCK(vp);
|
||||
break;
|
||||
case LO_TYPE_VM_OBJECT:
|
||||
object = obj->lo_object.vm_object;
|
||||
KASSERT(object->type != OBJT_VNODE, ("object has a vnode"));
|
||||
KASSERT(object->backing_object == NULL,
|
||||
("is a backing object"));
|
||||
lattr->level = (object->flags & OBJ_LOWEST_LEVEL) ?
|
||||
LOMAC_LOWEST_LEVEL : LOMAC_HIGHEST_LEVEL;
|
||||
lattr->flags = 0;
|
||||
break;
|
||||
case LO_TYPE_PIPE:
|
||||
pipe = obj->lo_object.pipe;
|
||||
lattr->level = (pipe->pipe_state & PIPE_LEVEL_LOWEST) ?
|
||||
LOMAC_LOWEST_LEVEL : LOMAC_HIGHEST_LEVEL;
|
||||
lattr->flags = 0;
|
||||
break;
|
||||
case LO_TYPE_SOCKETPAIR:
|
||||
socket = obj->lo_object.socket;
|
||||
lattr->level = (socket->so_state & SOCKET_LEVEL_LOWEST) ?
|
||||
LOMAC_LOWEST_LEVEL : LOMAC_HIGHEST_LEVEL;
|
||||
lattr->flags = 0;
|
||||
break;
|
||||
default:
|
||||
panic("get_object_level: invalid lo_type %d", obj->lo_type);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Flag certain procs, like init(8) and kthreads, as "invincible".
|
||||
*/
|
||||
int
|
||||
subject_do_not_demote(lomac_subject_t *subj) {
|
||||
int inv = 0;
|
||||
|
||||
if (subj->p_pid == 1) {
|
||||
inv = 1;
|
||||
} else {
|
||||
int had_lock = PROC_LOCKED(subj);
|
||||
|
||||
if (!had_lock)
|
||||
PROC_LOCK(subj);
|
||||
if (subj->p_flag & P_SYSTEM)
|
||||
inv = 1;
|
||||
if (!had_lock)
|
||||
PROC_UNLOCK(subj);
|
||||
}
|
||||
return (inv);
|
||||
}
|
91
sys/contrib/lomac/kernel_interface.h
Normal file
91
sys/contrib/lomac/kernel_interface.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kernel_interface.h,v 1.21 2001/10/15 17:58:32 bfeldman Exp $
|
||||
*/
|
||||
#ifndef KERNEL_INTERFACE_H
|
||||
#define KERNEL_INTERFACE_H
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_object.h>
|
||||
|
||||
#include "lomac.h"
|
||||
|
||||
|
||||
/*
|
||||
* We do not yet implement any categories. We use lattr_t's flags
|
||||
* field to implement the "LOMAC_ATTR_LOWWRITE" exception. When
|
||||
* this bit is set on a file, lowest-level processes can write to
|
||||
* the file, regardless of the file's level.
|
||||
*
|
||||
* There is also the LOMAC_ATTR_LOWNOOPEN flag, which prevents the
|
||||
* opening of a given object to subjects with a lower level than its
|
||||
* own.
|
||||
*
|
||||
* LOMAC_ATTR_NONETDEMOTE is set on subjects to prevent demotion on
|
||||
* network reads; LOMAC_ATTR_NODEMOTE is set on subjects to prevent
|
||||
* all demotion. Both of these will effectively set a high-level
|
||||
* subject as very trusted (and must be used sparingly).
|
||||
*/
|
||||
#define LOMAC_ATTR_LOWWRITE 0x00010000
|
||||
#define LOMAC_ATTR_LOWNOOPEN 0x00020000
|
||||
#define LOMAC_ATTR_NONETDEMOTE 0x00040000
|
||||
#define LOMAC_ATTR_NODEMOTE 0x00080000
|
||||
|
||||
typedef struct proc lomac_subject_t;
|
||||
typedef struct lomac_object {
|
||||
enum lomac_object_type {
|
||||
LO_TYPE_LVNODE, /* LOMAC vnode */
|
||||
LO_TYPE_UVNODE, /* underlying vnode */
|
||||
LO_TYPE_VM_OBJECT, /* VM object, not OBJT_VNODE */
|
||||
LO_TYPE_PIPE, /* pipe */
|
||||
LO_TYPE_SOCKETPAIR /* local-domain socket in socketpair */
|
||||
} lo_type;
|
||||
union {
|
||||
struct vnode *vnode;
|
||||
vm_object_t vm_object;
|
||||
struct pipe *pipe;
|
||||
struct socket *socket;
|
||||
} lo_object;
|
||||
} lomac_object_t;
|
||||
typedef struct sbuf lomac_log_t;
|
||||
|
||||
void init_subject_lattr(lomac_subject_t *, lattr_t *);
|
||||
void set_subject_lattr(lomac_subject_t *, lattr_t);
|
||||
void get_subject_lattr(lomac_subject_t *, lattr_t *);
|
||||
void set_object_lattr(lomac_object_t *, lattr_t);
|
||||
void get_object_lattr(const lomac_object_t *, lattr_t *);
|
||||
int subject_do_not_demote(lomac_subject_t *);
|
||||
#if 0
|
||||
void subject_propogate_lattr(lomac_subject_t *);
|
||||
#endif
|
||||
void kernel_vm_drop_perms(struct thread *, lattr_t *);
|
||||
|
||||
#endif /* KERNEL_INTERFACE_H */
|
279
sys/contrib/lomac/kernel_lkm.c
Normal file
279
sys/contrib/lomac/kernel_lkm.c
Normal file
@ -0,0 +1,279 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kernel_lkm.c,v 1.26 2001/11/14 16:30:17 bfeldman Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/linker.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include "kernel_interface.h"
|
||||
#include "kernel_mediate.h"
|
||||
#include "kernel_plm.h"
|
||||
#include "kernel_util.h"
|
||||
#include "kernel_pipe.h"
|
||||
#include "kernel_socket.h"
|
||||
#include "lomacfs.h"
|
||||
#include "lomacio.h"
|
||||
|
||||
static d_ioctl_t lomac_ioctl;
|
||||
|
||||
#define CDEV_MAJOR 207
|
||||
#define LOMAC_MINOR 0
|
||||
|
||||
static struct cdevsw lomac_cdevsw = {
|
||||
/* open */ (d_open_t *)nullop,
|
||||
/* close */ (d_open_t *)nullop,
|
||||
/* read */ noread,
|
||||
/* write */ nowrite,
|
||||
/* ioctl */ lomac_ioctl,
|
||||
/* poll */ nopoll,
|
||||
/* mmap */ nommap,
|
||||
/* strategy */ nostrategy,
|
||||
/* name */ "lomac",
|
||||
/* maj */ CDEV_MAJOR,
|
||||
/* dump */ nodump,
|
||||
/* psize */ nopsize,
|
||||
/* flags */ 0,
|
||||
};
|
||||
|
||||
static dev_t lomac_dev = NULL;
|
||||
|
||||
int
|
||||
lomac_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td) {
|
||||
struct nameidata nd;
|
||||
struct proc *p;
|
||||
struct proc *targp;
|
||||
struct lomac_fioctl *fio;
|
||||
lomac_object_t lobj;
|
||||
lattr_t lattr;
|
||||
int error;
|
||||
|
||||
p = td->td_proc;
|
||||
switch (cmd) {
|
||||
case LIOGETPLEVEL:
|
||||
targp = pfind(*(int *)data);
|
||||
if (targp == NULL)
|
||||
return (ESRCH);
|
||||
if (p_cansee(p, targp) != 0) {
|
||||
PROC_UNLOCK(targp);
|
||||
return (ESRCH);
|
||||
}
|
||||
get_subject_lattr(targp, &lattr);
|
||||
*(level_t *)data = lattr.level;
|
||||
PROC_UNLOCK(targp);
|
||||
return (0);
|
||||
case LIOGETFLEVEL:
|
||||
fio = (struct lomac_fioctl *)data;
|
||||
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_SYSSPACE,
|
||||
fio->path, td);
|
||||
if ((error = namei(&nd)) != 0)
|
||||
return (error);
|
||||
if (VISLOMAC(nd.ni_vp))
|
||||
lobj.lo_type = LO_TYPE_LVNODE;
|
||||
else
|
||||
lobj.lo_type = LO_TYPE_UVNODE;
|
||||
lobj.lo_object.vnode = nd.ni_vp;
|
||||
get_object_lattr(&lobj, &lattr);
|
||||
*(level_t *)&fio->level = lattr.level;
|
||||
NDFREE(&nd, NDF_ONLY_PNBUF);
|
||||
vput(nd.ni_vp);
|
||||
return (error);
|
||||
case LIOGETFLATTR:
|
||||
fio = (struct lomac_fioctl *)data;
|
||||
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_SYSSPACE,
|
||||
fio->path, td);
|
||||
if ((error = namei(&nd)) != 0)
|
||||
return (error);
|
||||
if (VISLOMAC(nd.ni_vp))
|
||||
lobj.lo_type = LO_TYPE_LVNODE;
|
||||
else
|
||||
lobj.lo_type = LO_TYPE_UVNODE;
|
||||
lobj.lo_object.vnode = nd.ni_vp;
|
||||
get_object_lattr(&lobj, (lattr_t *)&fio->level);
|
||||
NDFREE(&nd, NDF_ONLY_PNBUF);
|
||||
vput(nd.ni_vp);
|
||||
return (error);
|
||||
case LIOPMAKELOWLEVEL:
|
||||
lattr.level = LOMAC_LOWEST_LEVEL;
|
||||
lattr.flags = 0;
|
||||
set_subject_lattr(p, lattr);
|
||||
return (0);
|
||||
default:
|
||||
return (ENOTTY);
|
||||
}
|
||||
}
|
||||
|
||||
int (*old_execve)(struct proc *, void *);
|
||||
#ifdef __i386__
|
||||
int (*old_sysarch)(struct proc *, void *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is "borrowed" from kern_module.c and MUST be kept in synch!
|
||||
*/
|
||||
struct module {
|
||||
TAILQ_ENTRY(module) link; /* chain together all modules */
|
||||
TAILQ_ENTRY(module) flink; /* all modules in a file */
|
||||
struct linker_file* file; /* file which contains this module */
|
||||
int refs; /* reference count */
|
||||
int id; /* unique id number */
|
||||
char *name; /* module name */
|
||||
modeventhand_t handler; /* event handler */
|
||||
void *arg; /* argument for handler */
|
||||
modspecific_t data; /* module specific data */
|
||||
};
|
||||
|
||||
static int
|
||||
lomac_modevent(module_t module, int event, void *unused) {
|
||||
static int initialized_procs = 0;
|
||||
static int initialized_syscalls = 0;
|
||||
static int initialized_pipes = 0;
|
||||
static int initialized_sockets = 0;
|
||||
static int initialized_vm = 0;
|
||||
static linker_file_t kernlf;
|
||||
int error;
|
||||
|
||||
switch ((enum modeventtype)event) {
|
||||
case MOD_LOAD:
|
||||
if (!lomac_plm_initialized)
|
||||
return (EINVAL);
|
||||
kernlf = linker_kernel_file;
|
||||
old_execve =
|
||||
(int (*)(struct proc *, void *))linker_file_lookup_symbol(
|
||||
kernlf, "execve", 1);
|
||||
if (old_execve == NULL)
|
||||
return (ENOENT);
|
||||
#ifdef __i386__
|
||||
old_sysarch =
|
||||
(int (*)(struct proc *, void *))linker_file_lookup_symbol(
|
||||
kernlf, "sysarch", 1);
|
||||
if (old_sysarch == NULL)
|
||||
return (ENOENT);
|
||||
#endif
|
||||
error = lomac_initialize_procs();
|
||||
if (error)
|
||||
break;
|
||||
initialized_procs = 1;
|
||||
error = lomac_initialize_syscalls();
|
||||
if (error)
|
||||
break;
|
||||
initialized_syscalls = 1;
|
||||
error = lomac_initialize_pipes();
|
||||
if (error)
|
||||
break;
|
||||
initialized_pipes = 1;
|
||||
error = lomac_initialize_sockets();
|
||||
if (error)
|
||||
break;
|
||||
initialized_sockets = 1;
|
||||
lomac_dev = make_dev(&lomac_cdevsw, LOMAC_MINOR, UID_ROOT,
|
||||
GID_WHEEL, 0666, "lomac");
|
||||
linker_kernel_file = module->file;
|
||||
error = vfs_mount(curthread, "lomacfs", "/", 0, NULL);
|
||||
if (error)
|
||||
return (error);
|
||||
error = lomac_initialize_cwds();
|
||||
if (error)
|
||||
return (error);
|
||||
printf("LOMAC: Low-Watermark Mandatory Access Control v2.0.0\n");
|
||||
return (error);
|
||||
case MOD_UNLOAD:
|
||||
/*
|
||||
* It's always a bad idea to let a low-security process
|
||||
* unload the module providing security.
|
||||
*/
|
||||
if (initialized_procs &&
|
||||
!mediate_subject_at_level("kldunload", curthread->td_proc,
|
||||
LOMAC_HIGHEST_LEVEL))
|
||||
return (EPERM);
|
||||
/*
|
||||
* Unloading doesn't work well at the moment...
|
||||
*/
|
||||
return (EPERM);
|
||||
if (initialized_sockets) {
|
||||
error = lomac_uninitialize_sockets();
|
||||
if (error)
|
||||
break;
|
||||
initialized_sockets = 0;
|
||||
}
|
||||
if (initialized_pipes) {
|
||||
error = lomac_uninitialize_pipes();
|
||||
if (error)
|
||||
break;
|
||||
initialized_pipes = 0;
|
||||
}
|
||||
if (initialized_syscalls) {
|
||||
error = lomac_uninitialize_syscalls();
|
||||
if (error)
|
||||
break;
|
||||
initialized_syscalls = 0;
|
||||
}
|
||||
if (initialized_procs) {
|
||||
error = lomac_uninitialize_procs();
|
||||
if (error)
|
||||
break;
|
||||
initialized_procs = 0;
|
||||
}
|
||||
if (initialized_vm) {
|
||||
error = lomac_uninitialize_vm();
|
||||
if (error)
|
||||
break;
|
||||
initialized_vm = 0;
|
||||
}
|
||||
if (lomac_dev) {
|
||||
if (count_dev(lomac_dev) != 0)
|
||||
return (EBUSY);
|
||||
destroy_dev(lomac_dev);
|
||||
}
|
||||
printf("LOMAC: unloading\n");
|
||||
linker_kernel_file = kernlf;
|
||||
break;
|
||||
case MOD_SHUTDOWN:
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static moduledata_t lomac_moduledata = {
|
||||
"lomac",
|
||||
&lomac_modevent,
|
||||
NULL
|
||||
};
|
||||
DECLARE_MODULE(lomac, lomac_moduledata, SI_SUB_VFS, SI_ORDER_ANY);
|
||||
MODULE_VERSION(lomac, 1);
|
||||
MODULE_DEPEND(lomac, syscall_gate, 1, 1, 1);
|
||||
MODULE_DEPEND(lomac, lomacfs, 1, 1, 1);
|
||||
MODULE_DEPEND(lomac, lomac_plm, 1, 1, 1);
|
190
sys/contrib/lomac/kernel_log.c
Normal file
190
sys/contrib/lomac/kernel_log.c
Normal file
@ -0,0 +1,190 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kernel_log.c,v 1.12 2001/10/17 15:19:26 bfeldman Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/syslog.h>
|
||||
|
||||
#include "lomacfs.h"
|
||||
|
||||
#include "kernel_interface.h"
|
||||
|
||||
/* The following definition sets the global log verbosity level. */
|
||||
SYSCTL_NODE(_kern, OID_AUTO, lomac, CTLFLAG_RW, 0, "LOMAC");
|
||||
SYSCTL_NODE(_kern_lomac, OID_AUTO, verbose, CTLFLAG_RW, 0, "LOMAC verbosity");
|
||||
#define VERBOSITY_SETTING(level) \
|
||||
unsigned int lomac_verbose_##level## = 1; \
|
||||
SYSCTL_UINT(_kern_lomac_verbose, OID_AUTO, level, \
|
||||
CTLFLAG_RW, &lomac_verbose_##level##, 1, "")
|
||||
#include "kernel_log.h"
|
||||
|
||||
/* sbuf_start()
|
||||
*
|
||||
* in: nothing
|
||||
* out: nothing
|
||||
* return: struct sbuf * to pass to later callers
|
||||
*
|
||||
*/
|
||||
|
||||
lomac_log_t *
|
||||
log_start(void) {
|
||||
struct sbuf *s;
|
||||
|
||||
s = sbuf_new(NULL, NULL, PATH_MAX * 2, 0);
|
||||
KASSERT(s != NULL, ("sbuf uses M_WAITOK -- must not return NULL!"));
|
||||
return (s);
|
||||
} /* log_start() */
|
||||
|
||||
|
||||
/* log_append_string()
|
||||
*
|
||||
* in: s - a struct sbuf *
|
||||
* in: data_s - null-terminated string to append to log
|
||||
* out: nothing, see description for side-effects
|
||||
* return: nothing
|
||||
*
|
||||
* This function appends `data_s' to `log_s', being careful to ensure
|
||||
* that there is sufficient room in `log_s' for the data and a null
|
||||
* terminator. If there is insufficient room in `log_s' for the entire
|
||||
* `data_s' string, this function will append only the prefix of `data_s'
|
||||
* which fits.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
log_append_string(lomac_log_t *s, const char *data_s) {
|
||||
|
||||
(void)sbuf_cat(s, data_s);
|
||||
} /* log_append_string */
|
||||
|
||||
|
||||
/* log_append_int()
|
||||
*
|
||||
* in: data - integer value to append to log
|
||||
* out: nothing, see description for side-effects
|
||||
* return: nothing
|
||||
*
|
||||
* This function determines the ASCII representation of the integer
|
||||
* value in `data' and, if there is sufficient room, appends this
|
||||
* ASCII representation to `log_s'. If there is insufficient room,
|
||||
* this function behaves as log_append_string().
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
log_append_int(lomac_log_t *s, int data) {
|
||||
|
||||
(void)sbuf_printf(s, "%d", data);
|
||||
} /* log_append_int() */
|
||||
|
||||
|
||||
/* log_append_subject_id()
|
||||
*
|
||||
* in: p_subject - subject whose ID we want to append to the log message
|
||||
* out: nothing, see description for side-effects
|
||||
* return: nothing
|
||||
*
|
||||
* This function appends a string describing the identity of `p_subject'
|
||||
* to `log_s'. If there is insufficient room in `log_s' for the entire
|
||||
* ID string, only a (possibly empty) prefix of the ID string will be
|
||||
* appended.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
log_append_subject_id(lomac_log_t *s, const lomac_subject_t *p_subject) {
|
||||
|
||||
(void)sbuf_printf(s, "p%dg%du%d:%s", p_subject->p_pid,
|
||||
p_subject->p_pgrp->pg_id, p_subject->p_ucred->cr_uid,
|
||||
p_subject->p_comm);
|
||||
} /* log_append_subject_id() */
|
||||
|
||||
/* log_append_object_id()
|
||||
*
|
||||
* in: p_object - object whose ID we want to append to the log message
|
||||
* out: nothing, see description for side-effects
|
||||
* return: nothing
|
||||
*
|
||||
* This function appends a string describing the identity of `p_object'
|
||||
* to `log_s'. If there is insufficient room in `log_s' for the entire
|
||||
* ID string, only a (possibly empty) prefix of the ID string will be
|
||||
* appended.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
log_append_object_id(lomac_log_t *s, const lomac_object_t *p_object) {
|
||||
struct lomac_node *ln;
|
||||
|
||||
switch (p_object->lo_type) {
|
||||
case LO_TYPE_UVNODE:
|
||||
(void)sbuf_printf(s, "vp %p", p_object->lo_object.vnode);
|
||||
break;
|
||||
case LO_TYPE_LVNODE:
|
||||
ln = VTOLOMAC(p_object->lo_object.vnode);
|
||||
#ifdef LOMAC_DEBUG_INCNAME
|
||||
(void)sbuf_printf(s, "named \"%s\"", ln->ln_name);
|
||||
#else
|
||||
if (ln->ln_entry != NULL)
|
||||
(void)sbuf_printf(s, "named \"%s\"",
|
||||
ln->ln_entry->ln_path);
|
||||
else
|
||||
(void)sbuf_printf(s, "under \"%s\"",
|
||||
ln->ln_underpolicy->ln_path);
|
||||
#endif
|
||||
break;
|
||||
case LO_TYPE_PIPE:
|
||||
(void)sbuf_printf(s, "pipe %p", p_object->lo_object.pipe);
|
||||
break;
|
||||
case LO_TYPE_SOCKETPAIR:
|
||||
(void)sbuf_printf(s, "socket %p", p_object->lo_object.socket);
|
||||
break;
|
||||
default:
|
||||
panic("invalid LOMAC object type");
|
||||
}
|
||||
} /* log_append_object_id() */
|
||||
|
||||
/* log_print()
|
||||
*
|
||||
* in: nothing
|
||||
* out: nothing
|
||||
* return: nothing
|
||||
*
|
||||
* This function prints `log_s' to the system log.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
log_print(lomac_log_t *s) {
|
||||
|
||||
sbuf_finish(s);
|
||||
log(LOG_INFO, "%s", sbuf_data(s));
|
||||
sbuf_delete(s);
|
||||
} /* log_print() */
|
68
sys/contrib/lomac/kernel_log.h
Normal file
68
sys/contrib/lomac/kernel_log.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kernel_log.h,v 1.5 2001/09/20 21:29:21 tfraser Exp $
|
||||
*/
|
||||
|
||||
#ifndef _KERNEL_LOG_H_
|
||||
#define _KERNEL_LOG_H_
|
||||
|
||||
#include "kernel_interface.h"
|
||||
|
||||
/* Use this unsigned int and its constants to set the log output *
|
||||
* verbosity. Use of the log_* functions should be surrounded by *
|
||||
* if statements of the form "if( verbose & VERBOSE_FOO )" where *
|
||||
* VERBOSE_FOO is the constant below which corresponds to the *
|
||||
* type of event you're logging. */
|
||||
#define VERBOSE_NOLOG 0x00000000 /* no log output, please. */
|
||||
#define VERBOSE_DEMOTE_DENY 0x00000001 /* log demotions and access denials. */
|
||||
#define VERBOSE_PIPE 0x00000002 /* log changes to pipe "levels". */
|
||||
#define VERBOSE_LOG_SOCKETS 0x00000004 /* log UNIX domain socket setup. */
|
||||
#define VERBOSE_LOG_OBJECTS 0x00000008 /* log opening of objects. */
|
||||
#ifdef TRUST
|
||||
#define VERBOSE_TRUST 0x00000020 /* log when trust stops demotion. */
|
||||
#endif
|
||||
|
||||
#ifndef VERBOSITY_SETTING
|
||||
#define VERBOSITY_SETTING(level) extern unsigned int lomac_verbose_##level;
|
||||
#endif
|
||||
VERBOSITY_SETTING(demote_deny);
|
||||
VERBOSITY_SETTING(log_sockets);
|
||||
VERBOSITY_SETTING(log_objects);
|
||||
#ifdef LOMAC_DEBUG_PIPE
|
||||
VERBOSITY_SETTING(pipe);
|
||||
#endif
|
||||
#ifdef TRUST
|
||||
VERBOSITY_SETTING(trust);
|
||||
#endif
|
||||
|
||||
lomac_log_t *log_start( void );
|
||||
void log_append_string( lomac_log_t *s, const char *data_s );
|
||||
void log_append_int( lomac_log_t *s, int data );
|
||||
void log_append_subject_id( lomac_log_t *s, const lomac_subject_t *p_subject );
|
||||
void log_append_object_id( lomac_log_t *s, const lomac_object_t *p_object );
|
||||
void log_print( lomac_log_t *s );
|
||||
|
||||
#endif
|
280
sys/contrib/lomac/kernel_mediate.c
Normal file
280
sys/contrib/lomac/kernel_mediate.c
Normal file
@ -0,0 +1,280 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kernel_mediate.c,v 1.9 2001/10/17 15:19:40 bfeldman Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains functions that make access control decisions
|
||||
* concerning wether or not given system calls should be allowed
|
||||
* or denied. This activity is called "mediation". These functions
|
||||
* generally consider both the parameters passed to a system call
|
||||
* and the current internal state of LOMAC in the course of making
|
||||
* a decision. However, they do not modify these parameters or
|
||||
* LOMAC's internal state. Functions for modifying LOMAC's internal
|
||||
* state can be found in lomac_monitor.c.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kernel_interface.h"
|
||||
#include "kernel_mediate.h"
|
||||
#if 0
|
||||
#include "lomac_plm.h"
|
||||
#endif
|
||||
#include "kernel_log.h"
|
||||
|
||||
/* mediate_subject_level_subject()
|
||||
*
|
||||
* in: op_s - name of operation to mediate
|
||||
* p_subject_one - subject one (for informational purposes only)
|
||||
* level_one - already-known level of the first subject
|
||||
* p_subject_two - subject two
|
||||
* out: nothing
|
||||
* return: value condition
|
||||
* ----- ---------
|
||||
* 0 caller should deny operation
|
||||
* 1 caller should allow operation
|
||||
*
|
||||
* This function returns 1 if `p_subject_one's level is at least
|
||||
* as great as `p_subject_two's level. Otherwise, it logs a permission
|
||||
* failure on operation `op_s' and returns 0.
|
||||
*
|
||||
* This function is used to mediate pgrp changes.
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
mediate_subject_level_subject(const char *op_s,
|
||||
const lomac_subject_t *p_subject_one, level_t level_one,
|
||||
lomac_subject_t *p_subject_two) {
|
||||
|
||||
lattr_t lattr_two; /* lattr of `p_subject_two' */
|
||||
int ret_val; /* result to return to caller */
|
||||
|
||||
#ifdef NO_MEDIATION
|
||||
ret_val = 1; /* no denials, just logging */
|
||||
#else
|
||||
ret_val = 0; /* pessimistically assume deny */
|
||||
#endif
|
||||
|
||||
get_subject_lattr(p_subject_two, &lattr_two);
|
||||
|
||||
if (lattr_two.level <= level_one) {
|
||||
ret_val = 1; /* OK, allow */
|
||||
} else if (lomac_verbose_demote_deny) {
|
||||
lomac_log_t *logmsg = log_start();
|
||||
|
||||
log_append_string(logmsg, "LOMAC: denied level-");
|
||||
log_append_int(logmsg, level_one);
|
||||
log_append_string(logmsg, " proc ");
|
||||
log_append_subject_id(logmsg, p_subject_one);
|
||||
log_append_string(logmsg, " ");
|
||||
log_append_string(logmsg, op_s);
|
||||
log_append_string(logmsg, " to level-");
|
||||
log_append_int(logmsg, lattr_two.level);
|
||||
log_append_string(logmsg, " proc ");
|
||||
log_append_subject_id(logmsg, p_subject_two);
|
||||
log_print(logmsg);
|
||||
}
|
||||
return (ret_val);
|
||||
} /* mediate_subject_subject() */
|
||||
|
||||
/* mediate_subject_object()
|
||||
*
|
||||
* in: op_s - string describing operation, like "write" or "writev"
|
||||
* p_subject - subject trying to operate on `p_object'.
|
||||
* p_object - object that `p_subject' is trying to operate on.
|
||||
* out: nothing
|
||||
* return: value condition
|
||||
* ----- ---------
|
||||
* 0 Caller should prevent operation
|
||||
* 1 Caller should permit operation
|
||||
*
|
||||
* This function returns 1 if the level of `p_object' is less than or
|
||||
* equal to the level of `p_subject'. Otherwise, it returns 0 and
|
||||
* logs a permission denial on `op_s'.
|
||||
*
|
||||
* This function allows LOMAC to mediate write and writev system calls.
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
mediate_subject_object(const char *op_s, lomac_subject_t *p_subject,
|
||||
const lomac_object_t *p_object) {
|
||||
lattr_t subject_lattr; /* lattr of `p_subject' */
|
||||
lattr_t object_lattr; /* lattr of `p_object' */
|
||||
int ret_val; /* value to return to caller */
|
||||
|
||||
#ifdef NO_MEDIATION
|
||||
ret_val = 1; /* allow operation regardless of decision */
|
||||
#else
|
||||
ret_val = 0; /* pessimistically assume deny */
|
||||
#endif
|
||||
|
||||
/* Get the lattrs of `p_subject' and `p_object' so we can compare them. */
|
||||
get_subject_lattr(p_subject, &subject_lattr);
|
||||
get_object_lattr(p_object, &object_lattr);
|
||||
|
||||
/*
|
||||
* If `p_subject's level is less than `p_object's level,
|
||||
* we indicate that the operation must not be allowed.
|
||||
*/
|
||||
|
||||
if (!lomac_must_deny(&subject_lattr, &object_lattr) ||
|
||||
object_lattr.flags & LOMAC_ATTR_LOWWRITE) {
|
||||
ret_val = 1; /* allow operation */
|
||||
} else if (lomac_verbose_demote_deny) {
|
||||
lomac_log_t *logmsg = log_start();
|
||||
log_append_string(logmsg, "LOMAC: level-");
|
||||
log_append_int(logmsg, subject_lattr.level);
|
||||
log_append_string(logmsg, " proc ");
|
||||
log_append_subject_id(logmsg, p_subject);
|
||||
log_append_string(logmsg, " denied ");
|
||||
log_append_string(logmsg, op_s);
|
||||
log_append_string(logmsg, " to level-");
|
||||
log_append_int(logmsg, object_lattr.level);
|
||||
log_append_string(logmsg, " object ");
|
||||
log_append_object_id(logmsg, p_object);
|
||||
log_append_string(logmsg, "\n");
|
||||
log_print(logmsg);
|
||||
}
|
||||
return (ret_val);
|
||||
} /* mediate_subject_object() */
|
||||
|
||||
|
||||
/* mediate_subject_object_open()
|
||||
*
|
||||
* in: p_subject - subject trying to operate on `p_object'.
|
||||
* p_object - object that `p_subject' is trying to operate on.
|
||||
* out: nothing
|
||||
* return: value condition
|
||||
* ----- ---------
|
||||
* 0 Caller should prevent operation
|
||||
* 1 Caller should permit operation
|
||||
*
|
||||
* This function returns 1 if the level of `p_object' is less than or
|
||||
* equal to the level of `p_subject'. Otherwise, it returns 0 and
|
||||
* logs a permission denial on `op_s'.
|
||||
*
|
||||
* This function allows LOMAC to mediate open system calls.
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
mediate_subject_object_open(lomac_subject_t *p_subject,
|
||||
const lomac_object_t *p_object) {
|
||||
lattr_t subject_lattr; /* lattr of `p_subject' */
|
||||
lattr_t object_lattr; /* lattr of `p_object' */
|
||||
int ret_val; /* value to return to caller */
|
||||
|
||||
#ifdef NO_MEDIATION
|
||||
ret_val = 1; /* allow operation regardless of decision */
|
||||
#else
|
||||
ret_val = 0; /* pessimistically assume deny */
|
||||
#endif
|
||||
|
||||
/* Get the lattrs of `p_subject' and `p_object' so we can compare them. */
|
||||
get_subject_lattr(p_subject, &subject_lattr);
|
||||
get_object_lattr(p_object, &object_lattr);
|
||||
|
||||
/*
|
||||
* If `p_subject's level is less than `p_object's level,
|
||||
* we must indicate that the operation should not be allowed.
|
||||
*/
|
||||
if (lomac_must_deny(&subject_lattr, &object_lattr) &&
|
||||
object_lattr.flags & LOMAC_ATTR_LOWNOOPEN) {
|
||||
if (lomac_verbose_demote_deny) {
|
||||
lomac_log_t *logmsg = log_start();
|
||||
|
||||
log_append_string(logmsg, "LOMAC: level-");
|
||||
log_append_int(logmsg, subject_lattr.level);
|
||||
log_append_string(logmsg, " proc ");
|
||||
log_append_subject_id(logmsg, p_subject);
|
||||
log_append_string(logmsg, " denied open to level-");
|
||||
log_append_int(logmsg, object_lattr.level);
|
||||
log_append_string(logmsg, " object ");
|
||||
log_append_object_id(logmsg, p_object);
|
||||
log_append_string(logmsg, "\n");
|
||||
log_print(logmsg);
|
||||
}
|
||||
} else {
|
||||
ret_val = 1; /* allow operation */
|
||||
} /* if/else allow/deny */
|
||||
return (ret_val);
|
||||
} /* mediate_subject_object() */
|
||||
|
||||
|
||||
/* mediate_subject_at_level()
|
||||
*
|
||||
* in: op_s - name of operation being mediated
|
||||
* p_subject - subject whose level we want to check
|
||||
* target_level - level to compare to `p_subject's level
|
||||
*
|
||||
* out: nothing
|
||||
* return: value condition
|
||||
* ----- ---------
|
||||
* 0 `p_subject' is not at `target_level'
|
||||
* 1 `p_subject' is at `target_level'
|
||||
*
|
||||
* This function provides a predicate for determining whether or not
|
||||
* `p_subject' is at the level specified by `target_level'. This
|
||||
* function compares `p_subject's level to `target_level'. If the
|
||||
* levels match, it retruns 1. Otherwise, it logs a permission denial
|
||||
* on `op_s' and returns 0.
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
mediate_subject_at_level(const char *op_s, lomac_subject_t *p_subject,
|
||||
const level_t target_level) {
|
||||
lattr_t subject_lattr; /* lattr of `p_subject' */
|
||||
int ret_val; /* value returned to caller */
|
||||
|
||||
#ifdef NO_MEDIATION
|
||||
ret_val = 1; /* allow operation regardless of decision */
|
||||
#else
|
||||
ret_val = 0; /* pessimistically assume deny */
|
||||
#endif
|
||||
|
||||
/* Make `subject_lattr' the lattr of `p_subject'. */
|
||||
get_subject_lattr(p_subject, &subject_lattr);
|
||||
|
||||
/* compare with `target_lattr */
|
||||
if (subject_lattr.level == target_level) {
|
||||
ret_val = 1; /* allow operation */
|
||||
} else if (lomac_verbose_demote_deny) {
|
||||
lomac_log_t *logmsg = log_start();
|
||||
|
||||
log_append_string(logmsg, "LOMAC: denied level-");
|
||||
log_append_int(logmsg, subject_lattr.level);
|
||||
log_append_string(logmsg, " proc ");
|
||||
log_append_subject_id(logmsg, p_subject);
|
||||
log_append_string(logmsg, "'s ");
|
||||
log_append_string(logmsg, op_s);
|
||||
log_append_string(logmsg, ".\n");
|
||||
log_print(logmsg);
|
||||
}
|
||||
return (ret_val);
|
||||
} /* mediate_subject_at_level() */
|
59
sys/contrib/lomac/kernel_mediate.h
Normal file
59
sys/contrib/lomac/kernel_mediate.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kernel_mediate.h,v 1.5 2001/09/26 21:18:00 bfeldman Exp $
|
||||
*/
|
||||
|
||||
#ifndef _KERNEL_MEDIATE_H_
|
||||
#define _KERNEL_MEDIATE_H_
|
||||
|
||||
#include "kernel_interface.h"
|
||||
|
||||
int mediate_subject_level_subject( const char *op_s,
|
||||
const lomac_subject_t *p_subject_one,
|
||||
level_t level_one,
|
||||
lomac_subject_t *p_subject_two );
|
||||
int mediate_subject_object( const char *op_s, lomac_subject_t *p_subject,
|
||||
const lomac_object_t *p_object );
|
||||
int mediate_subject_object_open( lomac_subject_t *p_subject,
|
||||
const lomac_object_t *p_object );
|
||||
#if 0
|
||||
int mediate_subject_path( const char *op_s, const lomac_subject_t *p_subject,
|
||||
const char *path_s );
|
||||
int mediate_path_path( const char *op_s, const lomac_subject_t *p_subject,
|
||||
const char *canabsname_one_s,
|
||||
const char *canabsname_two_s );
|
||||
#endif
|
||||
int mediate_subject_at_level( const char *op_s,
|
||||
lomac_subject_t *p_subject,
|
||||
const level_t target_level );
|
||||
#if 0
|
||||
int mediate_object_at_level( const char *op_s,
|
||||
const lomac_subject_t *p_subject,
|
||||
const lomac_object_t *p_object,
|
||||
const level_t target_level );
|
||||
#endif
|
||||
|
||||
#endif
|
557
sys/contrib/lomac/kernel_mmap.c
Normal file
557
sys/contrib/lomac/kernel_mmap.c
Normal file
@ -0,0 +1,557 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* Copyright (c) 1988 University of Utah.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Systems Programming Group of the University of Utah Computer
|
||||
* Science Department.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$
|
||||
*
|
||||
* @(#)vm_mmap.c 8.4 (Berkeley) 1/12/94
|
||||
* $FreeBSD$
|
||||
* $Id: kernel_mmap.c,v 1.12 2001/10/17 15:34:29 bfeldman Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/filedesc.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_extern.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <vm/vm_object.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_pager.h>
|
||||
|
||||
#include "kernel_interface.h"
|
||||
#include "kernel_mediate.h"
|
||||
#include "kernel_monitor.h"
|
||||
#include "kernel_util.h"
|
||||
#include "lomacfs.h"
|
||||
|
||||
extern int max_proc_mmap;
|
||||
|
||||
int lomac_mmap(struct proc *, struct mmap_args *);
|
||||
|
||||
/*
|
||||
* Memory Map (mmap) system call. Note that the file offset
|
||||
* and address are allowed to be NOT page aligned, though if
|
||||
* the MAP_FIXED flag it set, both must have the same remainder
|
||||
* modulo the PAGE_SIZE (POSIX 1003.1b). If the address is not
|
||||
* page-aligned, the actual mapping starts at trunc_page(addr)
|
||||
* and the return value is adjusted up by the page offset.
|
||||
*
|
||||
* Generally speaking, only character devices which are themselves
|
||||
* memory-based, such as a video framebuffer, can be mmap'd. Otherwise
|
||||
* there would be no cache coherency between a descriptor and a VM mapping
|
||||
* both to the same character device.
|
||||
*
|
||||
* Block devices can be mmap'd no matter what they represent. Cache coherency
|
||||
* is maintained as long as you do not write directly to the underlying
|
||||
* character device.
|
||||
*/
|
||||
#ifndef _SYS_SYSPROTO_H_
|
||||
struct mmap_args {
|
||||
void *addr;
|
||||
size_t len;
|
||||
int prot;
|
||||
int flags;
|
||||
int fd;
|
||||
long pad;
|
||||
off_t pos;
|
||||
};
|
||||
#endif
|
||||
|
||||
int
|
||||
mmap(td, uap)
|
||||
struct thread *td;
|
||||
struct mmap_args *uap;
|
||||
{
|
||||
struct proc *p = td->td_proc;
|
||||
struct filedesc *fdp = p->p_fd;
|
||||
struct file *fp = NULL;
|
||||
struct vnode *vp, *origvp;
|
||||
vm_offset_t addr;
|
||||
vm_size_t size, pageoff;
|
||||
vm_prot_t prot, maxprot;
|
||||
void *handle;
|
||||
int flags, error;
|
||||
int disablexworkaround;
|
||||
off_t pos;
|
||||
struct vmspace *vms = p->p_vmspace;
|
||||
vm_object_t obj;
|
||||
lomac_object_t lobj;
|
||||
|
||||
addr = (vm_offset_t) uap->addr;
|
||||
size = uap->len;
|
||||
prot = uap->prot & VM_PROT_ALL;
|
||||
flags = uap->flags;
|
||||
pos = uap->pos;
|
||||
origvp = NULL;
|
||||
|
||||
/* make sure mapping fits into numeric range etc */
|
||||
if ((ssize_t) uap->len < 0 ||
|
||||
((flags & MAP_ANON) && uap->fd != -1))
|
||||
return (EINVAL);
|
||||
|
||||
if (flags & MAP_STACK) {
|
||||
if ((uap->fd != -1) ||
|
||||
((prot & (PROT_READ | PROT_WRITE)) != (PROT_READ | PROT_WRITE)))
|
||||
return (EINVAL);
|
||||
flags |= MAP_ANON;
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Align the file position to a page boundary,
|
||||
* and save its page offset component.
|
||||
*/
|
||||
pageoff = (pos & PAGE_MASK);
|
||||
pos -= pageoff;
|
||||
|
||||
/* Adjust size for rounding (on both ends). */
|
||||
size += pageoff; /* low end... */
|
||||
size = (vm_size_t) round_page(size); /* hi end */
|
||||
|
||||
/*
|
||||
* Check for illegal addresses. Watch out for address wrap... Note
|
||||
* that VM_*_ADDRESS are not constants due to casts (argh).
|
||||
*/
|
||||
if (flags & MAP_FIXED) {
|
||||
/*
|
||||
* The specified address must have the same remainder
|
||||
* as the file offset taken modulo PAGE_SIZE, so it
|
||||
* should be aligned after adjustment by pageoff.
|
||||
*/
|
||||
addr -= pageoff;
|
||||
if (addr & PAGE_MASK)
|
||||
return (EINVAL);
|
||||
/* Address range must be all in user VM space. */
|
||||
if (VM_MAXUSER_ADDRESS > 0 && addr + size > VM_MAXUSER_ADDRESS)
|
||||
return (EINVAL);
|
||||
#ifndef i386
|
||||
if (VM_MIN_ADDRESS > 0 && addr < VM_MIN_ADDRESS)
|
||||
return (EINVAL);
|
||||
#endif
|
||||
if (addr + size < addr)
|
||||
return (EINVAL);
|
||||
}
|
||||
/*
|
||||
* XXX for non-fixed mappings where no hint is provided or
|
||||
* the hint would fall in the potential heap space,
|
||||
* place it after the end of the largest possible heap.
|
||||
*
|
||||
* There should really be a pmap call to determine a reasonable
|
||||
* location.
|
||||
*/
|
||||
else if (addr == 0 ||
|
||||
(addr >= round_page((vm_offset_t)vms->vm_taddr) &&
|
||||
addr < round_page((vm_offset_t)vms->vm_daddr + MAXDSIZ)))
|
||||
addr = round_page((vm_offset_t)vms->vm_daddr + MAXDSIZ);
|
||||
|
||||
mtx_lock(&Giant); /* syscall marked mp-safe but isn't */
|
||||
if (flags & MAP_ANON) {
|
||||
/*
|
||||
* Mapping blank space is trivial.
|
||||
*/
|
||||
handle = NULL;
|
||||
maxprot = VM_PROT_ALL;
|
||||
pos = 0;
|
||||
} else {
|
||||
/*
|
||||
* Mapping file, get fp for validation. Obtain vnode and make
|
||||
* sure it is of appropriate type.
|
||||
*/
|
||||
if (((unsigned) uap->fd) >= fdp->fd_nfiles ||
|
||||
(fp = fdp->fd_ofiles[uap->fd]) == NULL) {
|
||||
mtx_unlock(&Giant);
|
||||
return (EBADF);
|
||||
}
|
||||
if (fp->f_type != DTYPE_VNODE) {
|
||||
mtx_unlock(&Giant);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* don't let the descriptor disappear on us if we block
|
||||
*/
|
||||
fhold(fp);
|
||||
|
||||
/*
|
||||
* POSIX shared-memory objects are defined to have
|
||||
* kernel persistence, and are not defined to support
|
||||
* read(2)/write(2) -- or even open(2). Thus, we can
|
||||
* use MAP_ASYNC to trade on-disk coherence for speed.
|
||||
* The shm_open(3) library routine turns on the FPOSIXSHM
|
||||
* flag to request this behavior.
|
||||
*/
|
||||
if (fp->f_flag & FPOSIXSHM)
|
||||
flags |= MAP_NOSYNC;
|
||||
vp = (struct vnode *) fp->f_data;
|
||||
if (vp->v_type != VREG && vp->v_type != VCHR) {
|
||||
error = EINVAL;
|
||||
goto done;
|
||||
}
|
||||
if (vp->v_type == VREG) {
|
||||
/*
|
||||
* Get the proper underlying object
|
||||
*/
|
||||
if (VOP_GETVOBJECT(vp, &obj) != 0) {
|
||||
error = EINVAL;
|
||||
goto done;
|
||||
}
|
||||
origvp = vp;
|
||||
vp = (struct vnode*)obj->handle;
|
||||
}
|
||||
/*
|
||||
* XXX hack to handle use of /dev/zero to map anon memory (ala
|
||||
* SunOS).
|
||||
*/
|
||||
if ((vp->v_type == VCHR) &&
|
||||
(vp->v_rdev->si_devsw->d_flags & D_MMAP_ANON)) {
|
||||
handle = NULL;
|
||||
maxprot = VM_PROT_ALL;
|
||||
flags |= MAP_ANON;
|
||||
pos = 0;
|
||||
} else {
|
||||
/*
|
||||
* cdevs does not provide private mappings of any kind.
|
||||
*/
|
||||
/*
|
||||
* However, for XIG X server to continue to work,
|
||||
* we should allow the superuser to do it anyway.
|
||||
* We only allow it at securelevel < 1.
|
||||
* (Because the XIG X server writes directly to video
|
||||
* memory via /dev/mem, it should never work at any
|
||||
* other securelevel.
|
||||
* XXX this will have to go
|
||||
*/
|
||||
if (securelevel >= 1)
|
||||
disablexworkaround = 1;
|
||||
else
|
||||
disablexworkaround = suser(p);
|
||||
if (vp->v_type == VCHR && disablexworkaround &&
|
||||
(flags & (MAP_PRIVATE|MAP_COPY))) {
|
||||
error = EINVAL;
|
||||
goto done;
|
||||
}
|
||||
/*
|
||||
* Ensure that file and memory protections are
|
||||
* compatible. Note that we only worry about
|
||||
* writability if mapping is shared; in this case,
|
||||
* current and max prot are dictated by the open file.
|
||||
* XXX use the vnode instead? Problem is: what
|
||||
* credentials do we use for determination? What if
|
||||
* proc does a setuid?
|
||||
*/
|
||||
maxprot = VM_PROT_EXECUTE; /* ??? */
|
||||
if (fp->f_flag & FREAD) {
|
||||
maxprot |= VM_PROT_READ;
|
||||
} else if (prot & PROT_READ) {
|
||||
error = EACCES;
|
||||
goto done;
|
||||
}
|
||||
/*
|
||||
* If we are sharing potential changes (either via
|
||||
* MAP_SHARED or via the implicit sharing of character
|
||||
* device mappings), and we are trying to get write
|
||||
* permission although we opened it without asking
|
||||
* for it, bail out. Check for superuser, only if
|
||||
* we're at securelevel < 1, to allow the XIG X server
|
||||
* to continue to work.
|
||||
*/
|
||||
|
||||
if ((flags & MAP_SHARED) != 0 ||
|
||||
(vp->v_type == VCHR && disablexworkaround)) {
|
||||
if ((fp->f_flag & FWRITE) != 0) {
|
||||
struct vattr va;
|
||||
if ((error =
|
||||
VOP_GETATTR(vp, &va,
|
||||
p->p_ucred, td))) {
|
||||
goto done;
|
||||
}
|
||||
if ((va.va_flags &
|
||||
(SF_SNAPSHOT|IMMUTABLE|APPEND)) == 0) {
|
||||
maxprot |= VM_PROT_WRITE;
|
||||
} else if (prot & PROT_WRITE) {
|
||||
error = EPERM;
|
||||
goto done;
|
||||
}
|
||||
} else if ((prot & PROT_WRITE) != 0) {
|
||||
error = EACCES;
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
maxprot |= VM_PROT_WRITE;
|
||||
}
|
||||
|
||||
handle = (void *)vp;
|
||||
origvp = vp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not allow more then a certain number of vm_map_entry structures
|
||||
* per process. Scale with the number of rforks sharing the map
|
||||
* to make the limit reasonable for threads.
|
||||
*/
|
||||
if (max_proc_mmap &&
|
||||
vms->vm_map.nentries >= max_proc_mmap * vms->vm_refcnt) {
|
||||
error = ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
mtx_unlock(&Giant);
|
||||
error = 0;
|
||||
if (handle != NULL && VISLOMAC(origvp)) {
|
||||
lobj.lo_type = LO_TYPE_LVNODE;
|
||||
lobj.lo_object.vnode = origvp;
|
||||
if (flags & MAP_SHARED && maxprot & VM_PROT_WRITE &&
|
||||
!mediate_subject_object("mmap", p, &lobj))
|
||||
error = EPERM;
|
||||
if (error == 0 && maxprot & VM_PROT_READ)
|
||||
error = monitor_read_object(p, &lobj);
|
||||
}
|
||||
if (error == 0)
|
||||
error = vm_mmap(&vms->vm_map, &addr, size, prot, maxprot,
|
||||
flags, handle, pos);
|
||||
if (error == 0)
|
||||
td->td_retval[0] = (register_t) (addr + pageoff);
|
||||
mtx_lock(&Giant);
|
||||
done:
|
||||
if (fp)
|
||||
fdrop(fp, td);
|
||||
mtx_unlock(&Giant);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
vm_drop_perms_recurse(struct thread *td, struct vm_map *map, lattr_t *lattr) {
|
||||
struct vm_map_entry *vme;
|
||||
|
||||
for (vme = map->header.next; vme != &map->header; vme = vme->next) {
|
||||
if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
|
||||
vm_map_lock_read(vme->object.sub_map);
|
||||
vm_drop_perms_recurse(td, vme->object.sub_map,
|
||||
lattr);
|
||||
vm_map_unlock_read(vme->object.sub_map);
|
||||
continue;
|
||||
}
|
||||
if ((vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC)) == 0 &&
|
||||
vme->max_protection & VM_PROT_WRITE) {
|
||||
vm_object_t object;
|
||||
vm_ooffset_t offset;
|
||||
lomac_object_t lobj;
|
||||
struct vnode *vp;
|
||||
lattr_t olattr;
|
||||
|
||||
offset = vme->offset;
|
||||
object = vme->object.vm_object;
|
||||
if (object == NULL)
|
||||
continue;
|
||||
while (object->backing_object) {
|
||||
object = object->backing_object;
|
||||
offset += object->backing_object_offset;
|
||||
}
|
||||
/*
|
||||
* Regular objects (swap, etc.) inherit from
|
||||
* their creator. Vnodes inherit from their
|
||||
* underlying on-disk object.
|
||||
*/
|
||||
if (object->type == OBJT_DEVICE)
|
||||
continue;
|
||||
if (object->type == OBJT_VNODE) {
|
||||
vp = lobj.lo_object.vnode = object->handle;
|
||||
/*
|
||||
* For the foreseeable future, an OBJT_VNODE
|
||||
* is always !VISLOMAC().
|
||||
*/
|
||||
lobj.lo_type = VISLOMAC(vp) ?
|
||||
LO_TYPE_LVNODE : LO_TYPE_UVNODE;
|
||||
} else {
|
||||
vp = NULL;
|
||||
lobj.lo_object.vm_object = object;
|
||||
lobj.lo_type = LO_TYPE_VM_OBJECT;
|
||||
}
|
||||
get_object_lattr(&lobj, &olattr);
|
||||
/*
|
||||
* Revoke write access only to files with a higher
|
||||
* level than the process or which have a possibly-
|
||||
* undeterminable level (interpreted as "lowest").
|
||||
*/
|
||||
if (lomac_must_deny(lattr, &olattr))
|
||||
continue;
|
||||
vm_map_lock_upgrade(map);
|
||||
/*
|
||||
* If it's a private, non-file-backed mapping and
|
||||
* not mapped anywhere else, we can just take it
|
||||
* down with us.
|
||||
*/
|
||||
if (vp == NULL && object->flags & OBJ_ONEMAPPING) {
|
||||
olattr.level = lattr->level;
|
||||
set_object_lattr(&lobj, olattr);
|
||||
goto downgrade;
|
||||
}
|
||||
if ((vme->protection & VM_PROT_WRITE) == 0)
|
||||
vme->max_protection &= ~VM_PROT_WRITE;
|
||||
else {
|
||||
vm_object_reference(object);
|
||||
if (vp != NULL)
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY,
|
||||
td);
|
||||
vm_object_page_clean(object,
|
||||
OFF_TO_IDX(offset),
|
||||
OFF_TO_IDX(offset + vme->end - vme->start +
|
||||
PAGE_MASK),
|
||||
OBJPC_SYNC);
|
||||
if (vp != NULL)
|
||||
VOP_UNLOCK(vp, 0, td);
|
||||
vm_object_deallocate(object);
|
||||
vme->eflags |= MAP_ENTRY_COW |
|
||||
MAP_ENTRY_NEEDS_COPY;
|
||||
pmap_protect(map->pmap, vme->start, vme->end,
|
||||
vme->protection & ~VM_PROT_WRITE);
|
||||
vm_map_simplify_entry(map, vme);
|
||||
}
|
||||
downgrade:
|
||||
vm_map_lock_downgrade(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
kernel_vm_drop_perms(struct thread *td, lattr_t *newlattr) {
|
||||
struct vm_map *map = &td->td_proc->p_vmspace->vm_map;
|
||||
|
||||
mtx_lock(&Giant);
|
||||
vm_map_lock_read(map);
|
||||
vm_drop_perms_recurse(td, map, newlattr);
|
||||
vm_map_unlock_read(map);
|
||||
mtx_unlock(&Giant);
|
||||
}
|
||||
|
||||
/*
|
||||
* Take the level of new vm_objects from the parent subject's level.
|
||||
*/
|
||||
static void
|
||||
vm_object_init_lattr(vm_object_t object) {
|
||||
lomac_object_t lobj;
|
||||
lattr_t lattr;
|
||||
|
||||
get_subject_lattr(curthread->td_proc, &lattr);
|
||||
lattr.flags = 0;
|
||||
lobj.lo_type = LO_TYPE_VM_OBJECT;
|
||||
lobj.lo_object.vm_object = object;
|
||||
set_object_lattr(&lobj, lattr);
|
||||
}
|
||||
|
||||
|
||||
#define PGO_ALLOC_REPLACEMENT(n) \
|
||||
static vm_object_t (*old_pgo_alloc_##n)(void *, vm_ooffset_t, \
|
||||
vm_prot_t, vm_ooffset_t); \
|
||||
\
|
||||
static vm_object_t \
|
||||
pgo_alloc_##n(void *handle, vm_ooffset_t size, vm_prot_t prot, \
|
||||
vm_ooffset_t off) { \
|
||||
vm_object_t newobj = NULL; \
|
||||
\
|
||||
newobj = old_pgo_alloc_##n(handle, size, prot, off); \
|
||||
if (newobj != NULL) \
|
||||
vm_object_init_lattr(newobj); \
|
||||
return (newobj); \
|
||||
}
|
||||
|
||||
#define PGO_ALLOC_REPLACE(n) \
|
||||
do { \
|
||||
old_pgo_alloc_##n = pagertab[n]->pgo_alloc; \
|
||||
if (pagertab[n]->pgo_alloc != NULL) \
|
||||
pagertab[n]->pgo_alloc = pgo_alloc_##n; \
|
||||
} while (0)
|
||||
|
||||
#define PGO_ALLOC_UNREPLACE(n) \
|
||||
do { \
|
||||
pagertab[n]->pgo_alloc = old_pgo_alloc_##n; \
|
||||
} while (0)
|
||||
|
||||
PGO_ALLOC_REPLACEMENT(0);
|
||||
PGO_ALLOC_REPLACEMENT(1);
|
||||
PGO_ALLOC_REPLACEMENT(2);
|
||||
PGO_ALLOC_REPLACEMENT(3);
|
||||
PGO_ALLOC_REPLACEMENT(4);
|
||||
PGO_ALLOC_REPLACEMENT(5);
|
||||
|
||||
extern int npagers;
|
||||
|
||||
int
|
||||
lomac_initialize_vm(void) {
|
||||
GIANT_REQUIRED;
|
||||
|
||||
if (npagers != 6) {
|
||||
printf("LOMAC: number of pagers %d not expected 6!\n", npagers);
|
||||
return (EDOM);
|
||||
}
|
||||
PGO_ALLOC_REPLACE(0);
|
||||
PGO_ALLOC_REPLACE(1);
|
||||
PGO_ALLOC_REPLACE(2);
|
||||
PGO_ALLOC_REPLACE(3);
|
||||
PGO_ALLOC_REPLACE(4);
|
||||
PGO_ALLOC_REPLACE(5);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
lomac_uninitialize_vm(void) {
|
||||
GIANT_REQUIRED;
|
||||
|
||||
PGO_ALLOC_UNREPLACE(0);
|
||||
PGO_ALLOC_UNREPLACE(1);
|
||||
PGO_ALLOC_UNREPLACE(2);
|
||||
PGO_ALLOC_UNREPLACE(3);
|
||||
PGO_ALLOC_UNREPLACE(4);
|
||||
PGO_ALLOC_UNREPLACE(5);
|
||||
return (0);
|
||||
}
|
197
sys/contrib/lomac/kernel_monitor.c
Normal file
197
sys/contrib/lomac/kernel_monitor.c
Normal file
@ -0,0 +1,197 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kernel_monitor.c,v 1.12 2001/10/16 15:25:02 bfeldman Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains functions which update LOMAC's internal
|
||||
* state in response to system events, such as successful
|
||||
* system calls. These updates allow LOMAC to keep an accurate
|
||||
* picture of the kernel's state, enabling LOMAC to make reasonable
|
||||
* decisions when it mediates processes' use of security-relevant
|
||||
* system calls. These functions perform no mediation themselves -
|
||||
* that is, they do not make access control decisions concerning
|
||||
* whether a given system call should be allowed or denied. This
|
||||
* mediation is handled by the functions in lomac_mediate.c.
|
||||
*/
|
||||
|
||||
#include "kernel_interface.h"
|
||||
#include "kernel_monitor.h"
|
||||
#include "kernel_log.h"
|
||||
|
||||
#include "kernel_util.h"
|
||||
|
||||
|
||||
/* monitor_read_object()
|
||||
*
|
||||
* in: p_subject - subject that read `p_object'.
|
||||
* p_object - object read by `p_subject'.
|
||||
* out: nothing
|
||||
* return: nothing
|
||||
*
|
||||
* This function examines the objects read by subjects. If a subject
|
||||
* reads from an object with a level lower than its own, this function
|
||||
* reduces the subject's level to match the object's. This lowering
|
||||
* is referred to as "demotion" in much of the LOMAC documentation.
|
||||
* This function performs no mediation.
|
||||
*
|
||||
* This function is for the following kinds of objects:
|
||||
* regular files and FIFOs.
|
||||
* It is also used to monitor reads on unnamed pipes. LOMAC does not
|
||||
* consider unnamed pipes to be objects, and treats them differently
|
||||
* from objects such as files. However, the differences are mostly
|
||||
* in the write-handling behavior. LOMAC's read-handling behavior is
|
||||
* the same both for objects and unnamed pipes, so this function
|
||||
* handles both cases.
|
||||
*/
|
||||
|
||||
int
|
||||
monitor_read_object(lomac_subject_t *p_subject, lomac_object_t *p_object) {
|
||||
lattr_t subject_lattr; /* lattr of `p_subject' */
|
||||
lattr_t object_lattr; /* lattr of `p_object' */
|
||||
|
||||
/* Get the lattrs of `p_subject' and `p_object' so we can compare them. */
|
||||
get_subject_lattr(p_subject, &subject_lattr);
|
||||
get_object_lattr(p_object, &object_lattr);
|
||||
|
||||
/*
|
||||
* If `p_object's level is less than `p_subject's level,
|
||||
* we must demote `p_subject'. The level may be 0 to indicate
|
||||
* existence before LOMAC started.
|
||||
*/
|
||||
if (object_lattr.level &&
|
||||
lomac_must_demote(&subject_lattr, &object_lattr) &&
|
||||
(subject_lattr.flags & LOMAC_ATTR_NODEMOTE) == 0) {
|
||||
if (subject_do_not_demote(p_subject))
|
||||
return (0);
|
||||
set_subject_lattr(p_subject, object_lattr); /* demote! */
|
||||
if (lomac_verbose_demote_deny) {
|
||||
lomac_log_t *s = log_start();
|
||||
|
||||
log_append_string(s, "LOMAC: level-");
|
||||
log_append_int(s, subject_lattr.level);
|
||||
log_append_string(s, " subject ");
|
||||
log_append_subject_id(s, p_subject);
|
||||
log_append_string(s, " demoted to level ");
|
||||
log_append_int(s, object_lattr.level);
|
||||
log_append_string(s, " after reading ");
|
||||
log_append_object_id(s, p_object);
|
||||
log_append_string(s, "\n");
|
||||
log_print(s);
|
||||
}
|
||||
} /* if we need to demote */
|
||||
return (0);
|
||||
} /* monitor_read_object() */
|
||||
|
||||
|
||||
/* monitor_pipe_write()
|
||||
*
|
||||
* in: p_subject - subject that just wrote to `p_pipe'.
|
||||
* p_pipe - pipe `p_subject' has written to.
|
||||
* out: p_pipe - pipe may have its level adjusted.
|
||||
* return: 0
|
||||
*
|
||||
* This function should be called after a successful write to
|
||||
* `p_pipe'. If the level of `p_subject' is less than the level of
|
||||
* `p_pipe', this function reduces `p_pipe's level to match
|
||||
* `current's.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
monitor_pipe_write(lomac_subject_t *p_subject, lomac_object_t *p_pipe) {
|
||||
lattr_t pipe_lattr; /* lattr of `p_pipe' */
|
||||
lattr_t subject_lattr; /* lattr of `p_subject' */
|
||||
|
||||
get_subject_lattr(p_subject, &subject_lattr);
|
||||
get_object_lattr(p_pipe, &pipe_lattr);
|
||||
if (lomac_must_demote(&pipe_lattr, &subject_lattr)) {
|
||||
subject_lattr.flags = 0;
|
||||
set_object_lattr(p_pipe, subject_lattr);
|
||||
#ifdef LOMAC_DEBUG_PIPE
|
||||
if (lomac_verbose_pipe) {
|
||||
lomac_log_t *s = log_start();
|
||||
|
||||
log_append_string(s, "LOMAC: level-");
|
||||
log_append_int(s, subject_lattr.level);
|
||||
log_append_string(s, " subject ");
|
||||
log_append_subject_id(s, p_subject);
|
||||
log_append_string(s, " contaminated level-");
|
||||
log_append_int(s, pipe_lattr.level);
|
||||
log_append_string(s, " ");
|
||||
log_append_object_id(s, p_pipe);
|
||||
log_append_string(s, "\n");
|
||||
log_print(s);
|
||||
}
|
||||
#endif /* LOMAC_DEBUG_PIPE */
|
||||
}
|
||||
return (0);
|
||||
} /* monitor_pipe_write() */
|
||||
|
||||
|
||||
/* monitor_read_net_socket()
|
||||
*
|
||||
* in: p_subject - subject that read from network socket.
|
||||
* out: nothing
|
||||
* return: 0
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
monitor_read_net_socket(lomac_subject_t *p_subject) {
|
||||
lattr_t subject_lattr; /* lattr of `p_subject' */
|
||||
lattr_t socket_lattr; /* lattr of socket (always lowest) */
|
||||
|
||||
socket_lattr.level = LOMAC_LOWEST_LEVEL;
|
||||
socket_lattr.flags = 0;
|
||||
get_subject_lattr(p_subject, &subject_lattr);
|
||||
|
||||
if (lomac_must_demote(&subject_lattr, &socket_lattr) &&
|
||||
(subject_lattr.flags &
|
||||
(LOMAC_ATTR_NODEMOTE | LOMAC_ATTR_NONETDEMOTE)) == 0) {
|
||||
|
||||
if (subject_do_not_demote(p_subject))
|
||||
return (0);
|
||||
socket_lattr.flags = subject_lattr.flags;
|
||||
set_subject_lattr(p_subject, socket_lattr); /* demote! */
|
||||
if (lomac_verbose_demote_deny) {
|
||||
lomac_log_t *s = log_start();
|
||||
|
||||
log_append_string(s, "LOMAC: level-");
|
||||
log_append_int(s, subject_lattr.level);
|
||||
log_append_string(s, " subject ");
|
||||
log_append_subject_id(s, p_subject);
|
||||
log_append_string(s, " demoted to level ");
|
||||
log_append_int(s, socket_lattr.level);
|
||||
log_append_string(s, " after reading from "
|
||||
"the network\n");
|
||||
log_print(s);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
53
sys/contrib/lomac/kernel_monitor.h
Normal file
53
sys/contrib/lomac/kernel_monitor.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kernel_monitor.h,v 1.5 2001/09/26 23:00:44 tfraser Exp $
|
||||
*/
|
||||
|
||||
#ifndef _LOMAC_MONITOR_H_
|
||||
#define _LOMAC_MONITOR_H_
|
||||
|
||||
int monitor_read_object( lomac_subject_t *, lomac_object_t * );
|
||||
int monitor_pipe_write( lomac_subject_t *, lomac_object_t * );
|
||||
int monitor_read_net_socket( lomac_subject_t *p_subject );
|
||||
|
||||
|
||||
#if 0
|
||||
void monitor_open( lomac_subject_t *p_subject, lomac_object_t *p_object );
|
||||
void monitor_pipe_create( lomac_subject_t *p_subject,
|
||||
lomac_object_t *p_pipe );
|
||||
void monitor_unix_socket_bind( lomac_subject_t *p_subject,
|
||||
lomac_object_t *p_socket,
|
||||
lomac_object_t *p_name );
|
||||
void monitor_unix_socket_abstract( lomac_subject_t *p_subject,
|
||||
lomac_object_t *p_socket );
|
||||
void monitor_unix_socketpair( lomac_subject_t *p_subject,
|
||||
lomac_object_t *p_socket1,
|
||||
lomac_object_t *p_socket2 );
|
||||
void monitor_unix_socket_accept_connect( lomac_subject_t *p_subject,
|
||||
lomac_object_t *p_old_socket,
|
||||
lomac_object_t *p_new_socket );
|
||||
#endif
|
||||
#endif
|
235
sys/contrib/lomac/kernel_pipe.c
Normal file
235
sys/contrib/lomac/kernel_pipe.c
Normal file
@ -0,0 +1,235 @@
|
||||
/*************************************************************************
|
||||
*
|
||||
* kernel_pipe.c
|
||||
*
|
||||
* LOMAC - Low Water-Mark Mandatory Access Control
|
||||
* Copyright (c) 1999-2001 Networks Associates, Inc. All rights reserved.
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of NAI Labs, Inc. nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
*
|
||||
* This file contains part of LOMAC's interface to the kernel. This
|
||||
* part allows LOMAC to monitor (unnamed) pipe read and write
|
||||
* operations by interposing control on the kernel's pipeops vector.
|
||||
*
|
||||
* The pipeops vector is defined in kern/sys_pipe.c.
|
||||
*
|
||||
* USAGE:
|
||||
*
|
||||
* The LOMAC LKM should call lomac_initialize_pipes() at LKM load time.
|
||||
* This function turns unnamed pipe interposition on by modifying
|
||||
* the function addresses in pipeops.
|
||||
*
|
||||
* Once the LOMAC LKM turns interposition on, all reads and writes
|
||||
* will pass through this file's monitoring functions.
|
||||
*
|
||||
* This file provides a lomac_uninitialize_pipes() function which
|
||||
* turns unnamed pipe interposition off by restoring pipeops to
|
||||
* its original unmodified state. Once the LOMAC LKM turns
|
||||
* interposition off, subsequent unnamed pipe reads and writes
|
||||
* will not pass through this file's monitoring functions.
|
||||
*
|
||||
* HOW LOMAC HANDLES PIPES:
|
||||
*
|
||||
* (This text describes how LOMAC handles (unnamed) pipes in terms of
|
||||
* abstract architecture-independent concepts.) LOMAC does not treat
|
||||
* pipes as objects, as it does files. When the kernel creates a new
|
||||
* pipe, LOMAC assigns it the highest level. Whenever a process
|
||||
* writes to the pipe, LOMAC reduces the pipe's level to match the
|
||||
* level of the writing process. Whenever a process reads from a
|
||||
* pipe, LOMAC reduces the level of the reading process to match the
|
||||
* pipe's level. As a result, if a high-level process reads the
|
||||
* output of a low-level process through a pipe, the reading process
|
||||
* will wind up at the low level.
|
||||
*
|
||||
* It takes two `struct pipe's to make a pipe. We set the level
|
||||
* information in both `struct pipes', and keep them synchronized.
|
||||
*
|
||||
* This code presently relies on the one-big-kernel-lock to
|
||||
* synchronize its access to the `pipe_state' field of each `struct
|
||||
* pipe'.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/selinfo.h>
|
||||
#include <sys/pipe.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include "lomac.h"
|
||||
#include "kernel_interface.h"
|
||||
#include "kernel_monitor.h"
|
||||
#include "kernel_pipe.h"
|
||||
|
||||
|
||||
/* `pipeops' is the kernel's pipe operations vector for the file *
|
||||
* structure. All reads and writes to pipes call through this vector. */
|
||||
extern struct fileops pipeops; /* defined in kern/sys_pipe.c */
|
||||
|
||||
|
||||
/* These vars store the original addresses of the pipeops read and *
|
||||
* write operations, so we can call them, and even restore them *
|
||||
* later if we want to. */
|
||||
static int (*pipe_read_orig)(struct file *, struct uio *, struct ucred *,
|
||||
int, struct thread *);
|
||||
static int (*pipe_write_orig)(struct file *, struct uio *, struct ucred *,
|
||||
int, struct thread *);
|
||||
|
||||
|
||||
/* declarations of functions private to this module: */
|
||||
static int lomac_pipe_read(struct file *, struct uio *, struct ucred *,
|
||||
int, struct thread *);
|
||||
static int lomac_pipe_write(struct file *, struct uio *, struct ucred *,
|
||||
int, struct thread *);
|
||||
|
||||
/* -------------------- public functions ---------------------------- */
|
||||
|
||||
/* lomac_initialize_pipes()
|
||||
*
|
||||
* in: nothing
|
||||
* out: nothing
|
||||
* return: 0
|
||||
*
|
||||
* Turns pipe interposition on by replacing the pipe_read() and pipe_write()
|
||||
* operations in the kernel's pipeops vector with lomac_pipe_read() and
|
||||
* lomac_pipe_write(). Saves the addresses of the original operations
|
||||
* so other functions can call them, and so pipe_interposition_off()
|
||||
* can restore the pipeops vector to its original unmodified state.
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
lomac_initialize_pipes(void) {
|
||||
|
||||
pipe_read_orig = pipeops.fo_read;
|
||||
pipeops.fo_read = lomac_pipe_read;
|
||||
pipe_write_orig = pipeops.fo_write;
|
||||
pipeops.fo_write = lomac_pipe_write;
|
||||
return (0);
|
||||
} /* lomac_initialize_pipes() */
|
||||
|
||||
|
||||
/* lomac_uninitialize_pipes()
|
||||
*
|
||||
* in: nothing
|
||||
* out: nothing
|
||||
* return: 0
|
||||
*
|
||||
* Turns pipe interposition off by restoring the pipeops vector to its
|
||||
* original unmodified state.
|
||||
*
|
||||
* See note at top of file regarding this function and unloading the
|
||||
* LOMAC LKM.
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
lomac_uninitialize_pipes(void) {
|
||||
|
||||
KASSERT(pipe_read_orig, ("LOMAC:pipe interpositon off before on"));
|
||||
KASSERT(pipe_write_orig, ("LOMAC:pipe interpositon off before on"));
|
||||
pipeops.fo_read = pipe_read_orig;
|
||||
pipeops.fo_write = pipe_write_orig;
|
||||
return (0);
|
||||
} /* lomac_uninitialize_pipes() */
|
||||
|
||||
|
||||
|
||||
/* ------------------- private functions --------------------------- */
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(lo, mac) ((lo) < (mac) ? (lo) : (mac))
|
||||
#endif
|
||||
|
||||
/* lomac_pipe_read()
|
||||
*
|
||||
* Passes the read operation down to pipe_read_orig(). If
|
||||
* pipe_read_orig() returns success, examines the level of the pipe
|
||||
* and the reading process. If the reading process has a higher
|
||||
* level, reduces the level of the process to equal the pipe's level.
|
||||
*
|
||||
*/
|
||||
|
||||
static int
|
||||
lomac_pipe_read(struct file *fp, struct uio *uio, struct ucred *cred,
|
||||
int flags, struct thread *td) {
|
||||
lomac_object_t read_pipe; /* attrs are in read end of pipe */
|
||||
struct uio kuio;
|
||||
struct iovec kiov;
|
||||
void *buf;
|
||||
int len;
|
||||
int ret_val; /* holds return values */
|
||||
|
||||
len = MIN(uio->uio_resid, BIG_PIPE_SIZE);
|
||||
kiov.iov_base = buf = malloc(len, M_TEMP, M_WAITOK);
|
||||
kiov.iov_len = len;
|
||||
kuio.uio_iov = &kiov;
|
||||
kuio.uio_iovcnt = 1;
|
||||
kuio.uio_offset = 0;
|
||||
kuio.uio_resid = len;
|
||||
kuio.uio_segflg = UIO_SYSSPACE;
|
||||
kuio.uio_rw = UIO_READ;
|
||||
kuio.uio_td = td;
|
||||
ret_val = pipe_read_orig(fp, &kuio, cred, flags, td);
|
||||
if (ret_val == 0) {
|
||||
read_pipe.lo_type = LO_TYPE_PIPE;
|
||||
read_pipe.lo_object.pipe = (struct pipe *)fp->f_data;
|
||||
(void)monitor_read_object(td->td_proc, &read_pipe);
|
||||
ret_val = uiomove(buf, len - kuio.uio_resid, uio);
|
||||
}
|
||||
free(buf, M_TEMP);
|
||||
return (ret_val);
|
||||
} /* lomac_pipe_read() */
|
||||
|
||||
|
||||
/* lomac_pipe_write()
|
||||
*
|
||||
* Passes the write operation down to pipe_write_orig(). If
|
||||
* pipe_write_orig() returns success, examines the level of the pipe
|
||||
* and the writing process. If the pipe has a higher level than the
|
||||
* writing process, this function reduces the pipe's level to equal
|
||||
* the level of the writing process.
|
||||
*
|
||||
*/
|
||||
|
||||
static int
|
||||
lomac_pipe_write(struct file *fp, struct uio *uio, struct ucred *cred,
|
||||
int flags, struct thread *td) {
|
||||
lomac_object_t pipe;
|
||||
int ret_val; /* holds return values */
|
||||
|
||||
pipe.lo_type = LO_TYPE_PIPE;
|
||||
pipe.lo_object.pipe = (struct pipe *)fp->f_data;
|
||||
ret_val = monitor_pipe_write(td->td_proc, &pipe);
|
||||
if (ret_val == 0)
|
||||
ret_val = pipe_write_orig(fp, uio, cred, flags, td);
|
||||
|
||||
return (ret_val);
|
||||
} /* lomac_pipe_write() */
|
45
sys/contrib/lomac/kernel_pipe.h
Normal file
45
sys/contrib/lomac/kernel_pipe.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef _KERNEL_PIPE_H_
|
||||
#define _KERNEL_PIPE_H_
|
||||
|
||||
/******************************************************************
|
||||
*
|
||||
* kernel_pipe.h
|
||||
*
|
||||
* LOMAC - Low Water-Mark Mandatory Access Control
|
||||
* Copyright (c) 1999-2001 Networks Associates, Inc. All rights reserved.
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of NAI Labs, Inc. nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kernel_pipe.h,v 1.1 2001/09/20 21:29:21 tfraser Exp $
|
||||
*
|
||||
* Public interface to kernel_pipe.c, the part of the LOMAC kernel
|
||||
* interface that takes control of operations on unnamed pipes.
|
||||
*
|
||||
*/
|
||||
|
||||
int lomac_initialize_pipes( void );
|
||||
int lomac_uninitialize_pipes( void );
|
||||
|
||||
|
||||
#endif /* _KERNEL_PIPE_H_ */
|
373
sys/contrib/lomac/kernel_plm.c
Normal file
373
sys/contrib/lomac/kernel_plm.c
Normal file
@ -0,0 +1,373 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kernel_plm.c,v 1.9 2001/10/17 15:20:09 bfeldman Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/namei.h>
|
||||
|
||||
#include "kernel_interface.h"
|
||||
#include "kernel_plm.h"
|
||||
#include "lomacfs.h"
|
||||
#include "policy_plm.h"
|
||||
|
||||
MALLOC_DEFINE(M_LOMACPLM, "LOMAC_PLM", "LOMAC PLM nodes and strings");
|
||||
char *strsep(register char **stringp, register const char *delim);
|
||||
|
||||
/*
|
||||
* Get next token from string *stringp, where tokens are possibly-empty
|
||||
* strings separated by characters from delim.
|
||||
*
|
||||
* Writes NULs into the string at *stringp to end tokens.
|
||||
* delim need not remain constant from call to call.
|
||||
* On return, *stringp points past the last NUL written (if there might
|
||||
* be further tokens), or is NULL (if there are definitely no more tokens).
|
||||
*
|
||||
* If *stringp is NULL, strsep returns NULL.
|
||||
*/
|
||||
char *
|
||||
strsep(stringp, delim)
|
||||
register char **stringp;
|
||||
register const char *delim;
|
||||
{
|
||||
register char *s;
|
||||
register const char *spanp;
|
||||
register int c, sc;
|
||||
char *tok;
|
||||
|
||||
if ((s = *stringp) == NULL)
|
||||
return (NULL);
|
||||
for (tok = s;;) {
|
||||
c = *s++;
|
||||
spanp = delim;
|
||||
do {
|
||||
if ((sc = *spanp++) == c) {
|
||||
if (c == 0)
|
||||
s = NULL;
|
||||
else
|
||||
s[-1] = 0;
|
||||
*stringp = s;
|
||||
return (tok);
|
||||
}
|
||||
} while (sc != 0);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
struct lomac_node_entry lomac_node_entry_root = {
|
||||
SLIST_HEAD_INITIALIZER(lomac_node_entry),
|
||||
{ NULL },
|
||||
LN_HIGHEST_LEVEL | LN_INHERIT_HIGH,
|
||||
"/"
|
||||
};
|
||||
|
||||
static struct lomac_node_entry *
|
||||
lomac_plm_subtree_find_cnp(struct lomac_node_entry *root,
|
||||
struct componentname *cnp) {
|
||||
char *nameptr = cnp->cn_nameptr;
|
||||
struct lomac_node_entry *lne;
|
||||
int len = cnp->cn_namelen;
|
||||
|
||||
SLIST_FOREACH(lne, &root->ln_children, ln_chain)
|
||||
if (strlen(lne->ln_name) == len &&
|
||||
bcmp(lne->ln_name, nameptr, len) == 0)
|
||||
break;
|
||||
|
||||
return (lne);
|
||||
}
|
||||
|
||||
static struct lomac_node_entry *
|
||||
lomac_plm_subtree_find(struct lomac_node_entry *root, const char *name) {
|
||||
struct lomac_node_entry *lne;
|
||||
|
||||
SLIST_FOREACH(lne, &root->ln_children, ln_chain)
|
||||
if (strcmp(name, lne->ln_name) == 0)
|
||||
break;
|
||||
|
||||
return (lne);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This is called from inside getnewvnode() before the vnode is in use.
|
||||
*/
|
||||
void
|
||||
lomac_plm_init_lomacfs_vnode(struct vnode *dvp, struct vnode *vp,
|
||||
struct componentname *cnp, lattr_t *subjlattr) {
|
||||
struct lomac_node *ln = VTOLOMAC(vp);
|
||||
struct lomac_node_entry *mlne = NULL;
|
||||
|
||||
/*
|
||||
* Only "/" has no parent, so inherit directly from our PLM root.
|
||||
*/
|
||||
if (dvp == NULL) {
|
||||
ln->ln_flags = lomac_node_entry_root.ln_flags;
|
||||
ln->ln_entry = ln->ln_underpolicy = &lomac_node_entry_root;
|
||||
} else {
|
||||
struct lomac_node *dln = VTOLOMAC(dvp);
|
||||
struct lomac_node_entry *dlne = dln->ln_entry;
|
||||
int fixup_inherit = 0;
|
||||
|
||||
/*
|
||||
* If we have no directory-specific entry, we inherit
|
||||
* directly from the lomac_node's previously-inherited
|
||||
* flags implicitly, otherwise we inherit explicitly
|
||||
* from the corresponding lomac_node_entry.
|
||||
*/
|
||||
if (dlne == NULL) {
|
||||
ln->ln_flags = dln->ln_flags & LN_INHERIT_MASK;
|
||||
fixup_inherit = 1;
|
||||
ln->ln_underpolicy = dln->ln_underpolicy;
|
||||
ln->ln_entry = NULL;
|
||||
} else if ((mlne = lomac_plm_subtree_find_cnp(dlne, cnp)) ==
|
||||
NULL) {
|
||||
ln->ln_flags = dlne->ln_flags & LN_INHERIT_MASK;
|
||||
fixup_inherit = 2;
|
||||
ln->ln_underpolicy = dlne;
|
||||
ln->ln_entry = NULL;
|
||||
} else {
|
||||
ln->ln_entry = ln->ln_underpolicy = mlne;
|
||||
}
|
||||
if (fixup_inherit) {
|
||||
switch (ln->ln_flags) {
|
||||
case LN_INHERIT_LOW:
|
||||
ln->ln_flags |= LN_LOWEST_LEVEL;
|
||||
break;
|
||||
case LN_INHERIT_SUBJ:
|
||||
if (subjlattr->level == LOMAC_HIGHEST_LEVEL)
|
||||
ln->ln_flags |= LN_HIGHEST_LEVEL;
|
||||
else {
|
||||
ln->ln_flags &= ~LN_INHERIT_MASK;
|
||||
ln->ln_flags |= LN_INHERIT_LOW |
|
||||
LN_LOWEST_LEVEL;
|
||||
}
|
||||
break;
|
||||
case LN_INHERIT_HIGH:
|
||||
ln->ln_flags |= LN_HIGHEST_LEVEL;
|
||||
break;
|
||||
}
|
||||
if (fixup_inherit == 2)
|
||||
ln->ln_flags |=
|
||||
(dlne->ln_flags & LN_CHILD_ATTR_MASK) >>
|
||||
LN_CHILD_ATTR_SHIFT;
|
||||
} else {
|
||||
/* this is the only case where mlne != NULL */
|
||||
ln->ln_flags &= ~(LN_INHERIT_MASK | LN_ATTR_MASK);
|
||||
ln->ln_flags |= mlne->ln_flags &
|
||||
(LN_INHERIT_MASK | LN_ATTR_MASK);
|
||||
if ((mlne->ln_flags & LN_LEVEL_MASK) ==
|
||||
LN_SUBJ_LEVEL) {
|
||||
if (subjlattr->level == LOMAC_HIGHEST_LEVEL)
|
||||
ln->ln_flags |= LN_HIGHEST_LEVEL;
|
||||
else
|
||||
ln->ln_flags |= LN_LOWEST_LEVEL;
|
||||
} else
|
||||
ln->ln_flags |= mlne->ln_flags & LN_LEVEL_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
KASSERT(ln->ln_flags & LN_LEVEL_MASK, ("lomac_node has no level"));
|
||||
KASSERT(ln->ln_flags & LN_INHERIT_MASK, ("lomac_node has no inherit"));
|
||||
#ifdef INVARIANTS
|
||||
if (mlne != NULL) {
|
||||
KASSERT(mlne->ln_flags & LN_LEVEL_MASK,
|
||||
("lomac_node_entry has no level"));
|
||||
KASSERT(mlne->ln_flags & LN_INHERIT_MASK,
|
||||
("lomac_node_entry has no inherit"));
|
||||
}
|
||||
#endif /* INVARIANTS */
|
||||
}
|
||||
|
||||
static struct lomac_node_entry *
|
||||
lomac_plm_subtree_new(struct lomac_node_entry *plne, char *name) {
|
||||
struct lomac_node_entry *lne;
|
||||
static struct lomac_node_entry_head head_init =
|
||||
SLIST_HEAD_INITIALIZER(lomac_node_entry);
|
||||
|
||||
lne = malloc(sizeof(*lne), M_LOMACPLM, M_WAITOK);
|
||||
bcopy(&head_init, &lne->ln_children, sizeof(head_init));
|
||||
lne->ln_name = name;
|
||||
lne->ln_flags = plne->ln_flags & LN_INHERIT_MASK;
|
||||
switch (lne->ln_flags) {
|
||||
case LN_INHERIT_LOW:
|
||||
lne->ln_flags |= LN_LOWEST_LEVEL;
|
||||
break;
|
||||
case LN_INHERIT_HIGH:
|
||||
lne->ln_flags |= LN_HIGHEST_LEVEL;
|
||||
break;
|
||||
case LN_INHERIT_SUBJ:
|
||||
lne->ln_flags |= LN_SUBJ_LEVEL;
|
||||
break;
|
||||
}
|
||||
SLIST_INSERT_HEAD(&plne->ln_children, lne, ln_chain);
|
||||
return (lne);
|
||||
}
|
||||
|
||||
static void
|
||||
lomac_plm_subtree_free(struct lomac_node_entry *lneself) {
|
||||
struct lomac_node_entry_head *head = &lneself->ln_children;
|
||||
struct lomac_node_entry *lne;
|
||||
|
||||
while (!SLIST_EMPTY(head)) {
|
||||
lne = SLIST_FIRST(head);
|
||||
SLIST_REMOVE_HEAD(head, ln_chain);
|
||||
lomac_plm_subtree_free(lne);
|
||||
}
|
||||
free(lneself, M_LOMACPLM);
|
||||
}
|
||||
|
||||
struct string_list {
|
||||
SLIST_ENTRY(string_list) entries;
|
||||
char string[1];
|
||||
};
|
||||
static SLIST_HEAD(, string_list) string_list_head =
|
||||
SLIST_HEAD_INITIALIZER(string_list);
|
||||
|
||||
static char *
|
||||
string_list_new(const char *s) {
|
||||
struct string_list *sl;
|
||||
|
||||
sl = malloc(sizeof(*sl) + strlen(s), M_LOMACPLM, M_WAITOK);
|
||||
strcpy(sl->string, s);
|
||||
SLIST_INSERT_HEAD(&string_list_head, sl, entries);
|
||||
|
||||
return (sl->string);
|
||||
}
|
||||
|
||||
static void
|
||||
lomac_plm_uninitialize(void) {
|
||||
struct lomac_node_entry_head *head = &lomac_node_entry_root.ln_children;
|
||||
struct lomac_node_entry *lne;
|
||||
struct string_list *sl;
|
||||
|
||||
while (!SLIST_EMPTY(head)) {
|
||||
lne = SLIST_FIRST(head);
|
||||
SLIST_REMOVE_HEAD(head, ln_chain);
|
||||
lomac_plm_subtree_free(lne);
|
||||
}
|
||||
while (!SLIST_EMPTY(&string_list_head)) {
|
||||
sl = SLIST_FIRST(&string_list_head);
|
||||
SLIST_REMOVE_HEAD(&string_list_head, entries);
|
||||
free(sl, M_LOMACPLM);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
lomac_plm_initialize(void) {
|
||||
struct lomac_node_entry *plne, *lne;
|
||||
plm_rule_t *pr;
|
||||
|
||||
for (pr = plm; pr->path != NULL; pr++) {
|
||||
char *path;
|
||||
char *comp;
|
||||
int depth;
|
||||
|
||||
if (*pr->path == '\0') {
|
||||
printf("lomac_plm: invalid path \"%s\"\n", pr->path);
|
||||
return (EINVAL);
|
||||
}
|
||||
path = string_list_new(pr->path);
|
||||
lne = &lomac_node_entry_root;
|
||||
depth = 0;
|
||||
for (;; depth++) {
|
||||
plne = lne;
|
||||
comp = strsep(&path, "/");
|
||||
if (comp == NULL)
|
||||
break;
|
||||
if (depth == 0) { /* special case: beginning / */
|
||||
if (*comp == '\0')
|
||||
continue;
|
||||
else {
|
||||
printf("lomac_plm: not absolute path "
|
||||
"\"%s\"\n", pr->path);
|
||||
return (EINVAL);
|
||||
}
|
||||
} else if (depth == 1) { /* special case: "/" */
|
||||
if (*comp == '\0' && strsep(&path, "/") == NULL)
|
||||
break;
|
||||
}
|
||||
if (*comp == '\0' ||
|
||||
strcmp(comp, ".") == 0 ||
|
||||
strcmp(comp, "..") == 0) {
|
||||
printf("lomac_plm: empty path component in "
|
||||
"\"%s\"\n", pr->path);
|
||||
return (EINVAL);
|
||||
}
|
||||
lne = lomac_plm_subtree_find(plne, comp);
|
||||
if (lne == NULL) {
|
||||
lne = lomac_plm_subtree_new(plne, comp);
|
||||
lne->ln_path = plne->ln_path;
|
||||
}
|
||||
}
|
||||
lne->ln_path = pr->path;
|
||||
if (pr->flags == PLM_NOFLAGS)
|
||||
lne->ln_flags &= ~LN_LEVEL_MASK;
|
||||
else
|
||||
lne->ln_flags &= ~LN_INHERIT_MASK;
|
||||
lne->ln_flags |=
|
||||
plm_levelflags_to_node_flags[pr->level][pr->flags];
|
||||
if (pr->flags == PLM_NOFLAGS)
|
||||
lne->ln_flags |= pr->attr;
|
||||
else
|
||||
lne->ln_flags |= (pr->attr & LN_ATTR_MASK)
|
||||
<< LN_CHILD_ATTR_SHIFT;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int lomac_plm_initialized = 0;
|
||||
|
||||
static int
|
||||
lomac_plm_modevent(module_t module, int event, void *unused) {
|
||||
int error = 0;
|
||||
|
||||
switch ((enum modeventtype)event) {
|
||||
case MOD_LOAD:
|
||||
error = lomac_plm_initialize();
|
||||
if (error == 0)
|
||||
lomac_plm_initialized = 1;
|
||||
break;
|
||||
case MOD_UNLOAD:
|
||||
lomac_plm_uninitialize();
|
||||
case MOD_SHUTDOWN:
|
||||
break;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
static moduledata_t lomac_plm_moduledata = {
|
||||
"lomac_plm",
|
||||
&lomac_plm_modevent,
|
||||
NULL
|
||||
};
|
||||
DECLARE_MODULE(lomac_plm, lomac_plm_moduledata, SI_SUB_VFS, SI_ORDER_ANY);
|
||||
MODULE_VERSION(lomac_plm, 1);
|
35
sys/contrib/lomac/kernel_plm.h
Normal file
35
sys/contrib/lomac/kernel_plm.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kernel_plm.h,v 1.4 2001/09/20 17:47:46 bfeldman Exp $
|
||||
*/
|
||||
#ifndef KERNEL_PLM_H
|
||||
#define KERNEL_PLM_H
|
||||
|
||||
extern int lomac_plm_initialized; /* set to 1 if successfully initialized */
|
||||
void lomac_plm_init_lomacfs_vnode(struct vnode *dvp, struct vnode *vp,
|
||||
struct componentname *cnp, lattr_t *subjlattr);
|
||||
|
||||
#endif /* KERNEL_PLM_H */
|
772
sys/contrib/lomac/kernel_socket.c
Normal file
772
sys/contrib/lomac/kernel_socket.c
Normal file
@ -0,0 +1,772 @@
|
||||
/*
|
||||
* LOMAC - Low Water-Mark Mandatory Access Control
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* Copyright (c) 1982, 1986, 1989, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kernel_socket.c,v 1.9 2001/11/05 20:57:41 tfraser Exp $
|
||||
*
|
||||
* This file implements LOMAC controls over socket operations. LOMAC
|
||||
* gains control of socket operations by interposing on the `struct
|
||||
* pr_usrreqs' operations vectors of each `struct protosw'. This code
|
||||
* replaces each `struct pr_usrreqs' with an instance of `struct
|
||||
* lomac_pr_usrreqs' containing LOMAC socket control functions. These
|
||||
* socket control functions implement LOMAC's socket controls, and then
|
||||
* call the corresponding socket operations from the original `struct
|
||||
* pr_usrreqs'. Each instance of `struct lomac_pr_usrreqs' ends with
|
||||
* a pointer to the `struct pr_usrreqs' it replaces. These pointers
|
||||
* allow the LOMAC socket control functions to find their corresponding
|
||||
* original `struct pr_usrreqs' functions.
|
||||
*
|
||||
* This file provides the function lomac_initialize_sockets() to turn
|
||||
* socket interposition on. Once socket iterposition is turned on,
|
||||
* the kernel will begin to call LOMAC's socket control functions.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/resourcevar.h>
|
||||
|
||||
#include <sys/domain.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/unpcb.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include "kernel_interface.h"
|
||||
#include "kernel_socket.h"
|
||||
#include "kernel_mediate.h"
|
||||
#include "kernel_monitor.h"
|
||||
#include "lomacfs.h"
|
||||
|
||||
MALLOC_DEFINE(M_LOMAC_USRREQS, "LOMAC-UR", "LOMAC usrreqs");
|
||||
|
||||
struct lomac_pr_usrreqs {
|
||||
struct pr_usrreqs lomac_pr_usrreqs; /* LOMAC socket control fxns */
|
||||
struct pr_usrreqs *orig_pr_usrreqs; /* original socket op vector */
|
||||
};
|
||||
|
||||
int lomac_local_accept(struct socket *, struct sockaddr **);
|
||||
int lomac_local_connect(struct socket *, struct sockaddr *, struct thread *);
|
||||
int lomac_local_connect2(struct socket *, struct socket *);
|
||||
int lomac_local_detach(struct socket *);
|
||||
int lomac_local_send( struct socket *, int, struct mbuf *, struct sockaddr *,
|
||||
struct mbuf *, struct thread * );
|
||||
int lomac_soreceive( struct socket *, struct sockaddr **, struct uio *,
|
||||
struct mbuf **, struct mbuf **, int * );
|
||||
int lomac_local_soreceive( struct socket *, struct sockaddr **, struct uio *,
|
||||
struct mbuf **, struct mbuf **, int * );
|
||||
static int monitored_soreceive( struct socket *, struct sockaddr **,
|
||||
struct uio *, struct mbuf **, struct mbuf **, int * );
|
||||
|
||||
/* This usrreqs structure implements LOMAC's controls on local sockets */
|
||||
struct pr_usrreqs lomac_local_usrreqs = {
|
||||
NULL,
|
||||
lomac_local_accept,
|
||||
NULL,
|
||||
NULL,
|
||||
lomac_local_connect,
|
||||
lomac_local_connect2,
|
||||
NULL,
|
||||
lomac_local_detach,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
lomac_local_send,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
lomac_local_soreceive,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* This usrreqs structure implements LOMAC's controls on network sockets */
|
||||
struct pr_usrreqs lomac_net_usrreqs = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
lomac_soreceive,
|
||||
NULL
|
||||
};
|
||||
|
||||
static __inline struct pr_usrreqs *
|
||||
orig_pr_usrreqs( struct socket *so ) {
|
||||
return (((struct lomac_pr_usrreqs *)(so->so_proto->pr_usrreqs))->
|
||||
orig_pr_usrreqs);
|
||||
}
|
||||
|
||||
int
|
||||
lomac_local_accept( struct socket *so, struct sockaddr **nam ) {
|
||||
struct vnode *vp;
|
||||
struct unpcb *unp;
|
||||
int ret_val; /* value to return to caller */
|
||||
|
||||
unp = sotounpcb(so);
|
||||
if (unp == NULL)
|
||||
return (EINVAL);
|
||||
if (unp->unp_conn != NULL) {
|
||||
vp = unp->unp_vnode = unp->unp_conn->unp_vnode;
|
||||
if (vp != NULL)
|
||||
vref(vp);
|
||||
}
|
||||
ret_val = (*orig_pr_usrreqs(so)->pru_accept)(so, nam);
|
||||
return (ret_val);
|
||||
}
|
||||
|
||||
int
|
||||
lomac_local_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
|
||||
{
|
||||
register struct sockaddr_un *soun = (struct sockaddr_un *)nam;
|
||||
register struct vnode *vp;
|
||||
register struct socket *so2, *so3;
|
||||
struct unpcb *unp, *unp2, *unp3;
|
||||
int error, len;
|
||||
struct nameidata nd;
|
||||
char buf[SOCK_MAXADDRLEN];
|
||||
|
||||
len = nam->sa_len - offsetof(struct sockaddr_un, sun_path);
|
||||
if (len <= 0)
|
||||
return EINVAL;
|
||||
strncpy(buf, soun->sun_path, len);
|
||||
buf[len] = 0;
|
||||
|
||||
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, buf, td);
|
||||
error = namei(&nd);
|
||||
if (error)
|
||||
goto bad2;
|
||||
vp = nd.ni_vp;
|
||||
NDFREE(&nd, NDF_ONLY_PNBUF);
|
||||
if (vp->v_type != VSOCK) {
|
||||
error = ENOTSOCK;
|
||||
goto bad;
|
||||
}
|
||||
error = VOP_ACCESS(vp, VWRITE, td->td_proc->p_ucred, td);
|
||||
if (error)
|
||||
goto bad;
|
||||
so2 = vp->v_socket;
|
||||
if (so2 == 0) {
|
||||
error = ECONNREFUSED;
|
||||
goto bad;
|
||||
}
|
||||
if (so->so_type != so2->so_type) {
|
||||
error = EPROTOTYPE;
|
||||
goto bad;
|
||||
}
|
||||
if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
|
||||
if ((so2->so_options & SO_ACCEPTCONN) == 0 ||
|
||||
(so3 = sonewconn3(so2, 0, td)) == 0) {
|
||||
error = ECONNREFUSED;
|
||||
goto bad;
|
||||
}
|
||||
unp = sotounpcb(so);
|
||||
unp2 = sotounpcb(so2);
|
||||
unp3 = sotounpcb(so3);
|
||||
if (unp2->unp_addr)
|
||||
unp3->unp_addr = (struct sockaddr_un *)
|
||||
dup_sockaddr((struct sockaddr *)
|
||||
unp2->unp_addr, 1);
|
||||
|
||||
/*
|
||||
* unp_peercred management:
|
||||
*
|
||||
* The connecter's (client's) credentials are copied
|
||||
* from its process structure at the time of connect()
|
||||
* (which is now).
|
||||
*/
|
||||
memset(&unp3->unp_peercred, '\0', sizeof(unp3->unp_peercred));
|
||||
unp3->unp_peercred.cr_uid = td->td_proc->p_ucred->cr_uid;
|
||||
unp3->unp_peercred.cr_ngroups = td->td_proc->p_ucred->cr_ngroups;
|
||||
memcpy(unp3->unp_peercred.cr_groups, td->td_proc->p_ucred->cr_groups,
|
||||
sizeof(unp3->unp_peercred.cr_groups));
|
||||
unp3->unp_flags |= UNP_HAVEPC;
|
||||
/*
|
||||
* The receiver's (server's) credentials are copied
|
||||
* from the unp_peercred member of socket on which the
|
||||
* former called listen(); unp_listen() cached that
|
||||
* process's credentials at that time so we can use
|
||||
* them now.
|
||||
*/
|
||||
KASSERT(unp2->unp_flags & UNP_HAVEPCCACHED,
|
||||
("unp_connect: listener without cached peercred"));
|
||||
memcpy(&unp->unp_peercred, &unp2->unp_peercred,
|
||||
sizeof(unp->unp_peercred));
|
||||
unp->unp_flags |= UNP_HAVEPC;
|
||||
|
||||
so2 = so3;
|
||||
}
|
||||
error = lomac_local_connect2(so, so2);
|
||||
bad:
|
||||
vput(vp);
|
||||
bad2:
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
lomac_local_connect2( struct socket *so1, struct socket *so2 ) {
|
||||
struct vnode *vp;
|
||||
int ret_val; /* value to return to caller */
|
||||
|
||||
if (so2->so_head != NULL) {
|
||||
vp = sotounpcb(so2->so_head)->unp_vnode;
|
||||
if (vp != NULL) {
|
||||
sotounpcb(so1)->unp_vnode = vp;
|
||||
vref(vp);
|
||||
}
|
||||
}
|
||||
ret_val = (*orig_pr_usrreqs(so1)->pru_connect2)(so1, so2);
|
||||
return (ret_val);
|
||||
}
|
||||
|
||||
int
|
||||
lomac_local_detach( struct socket *so ) {
|
||||
int ret_val; /* value to return to caller */
|
||||
struct unpcb *unp = sotounpcb(so);
|
||||
|
||||
if (unp == NULL)
|
||||
return (EINVAL);
|
||||
if (unp->unp_vnode != NULL && unp->unp_vnode->v_socket != so) {
|
||||
vrele(unp->unp_vnode);
|
||||
unp->unp_vnode = NULL;
|
||||
}
|
||||
ret_val = (*orig_pr_usrreqs(so)->pru_detach)(so);
|
||||
return (ret_val);
|
||||
}
|
||||
|
||||
int
|
||||
lomac_local_send( struct socket *so, int flags, struct mbuf *m,
|
||||
struct sockaddr *addr, struct mbuf *control, struct thread *td ) {
|
||||
struct vnode *vp;
|
||||
struct unpcb *unp = sotounpcb(so);
|
||||
int error;
|
||||
|
||||
/* printf( "pid %d local send\n", p->p_pid ); */
|
||||
if (unp == NULL) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (so->so_type == SOCK_DGRAM) {
|
||||
if (addr != NULL) {
|
||||
if (unp->unp_conn != NULL) {
|
||||
error = EISCONN;
|
||||
goto out;
|
||||
}
|
||||
error = lomac_local_connect(so, addr, td);
|
||||
if (error)
|
||||
goto out;
|
||||
} else if (unp->unp_conn == NULL) {
|
||||
error = ENOTCONN;
|
||||
goto out;
|
||||
}
|
||||
} else if ((so->so_state & SS_ISCONNECTED) == 0) {
|
||||
if (addr != NULL) {
|
||||
error = lomac_local_connect(so, addr, td);
|
||||
if (error)
|
||||
goto out; /* XXX */
|
||||
} else {
|
||||
error = ENOTCONN;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
vp = unp->unp_vnode;
|
||||
if (vp != NULL) {
|
||||
lomac_object_t lobj;
|
||||
|
||||
lobj.lo_type = VISLOMAC(vp) ? LO_TYPE_LVNODE : LO_TYPE_UVNODE;
|
||||
lobj.lo_object.vnode = vp;
|
||||
if (!mediate_subject_object("send", td->td_proc, &lobj)) {
|
||||
error = EPERM;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* This is a send to a socket in a socketpair() pair.
|
||||
* Mark both sockets in pair with the appropriate level.
|
||||
*/
|
||||
lomac_object_t lobj1, lobj2;
|
||||
lattr_t lattr;
|
||||
|
||||
lobj1.lo_type = LO_TYPE_SOCKETPAIR;
|
||||
lobj1.lo_object.socket = so;
|
||||
if ((error = monitor_pipe_write(td->td_proc, &lobj1)) != 0)
|
||||
goto out;
|
||||
lobj2.lo_type = LO_TYPE_SOCKETPAIR;
|
||||
lobj2.lo_object.socket = unp->unp_conn->unp_socket;
|
||||
get_object_lattr(&lobj1, &lattr);
|
||||
set_object_lattr(&lobj2, lattr);
|
||||
}
|
||||
error = (*orig_pr_usrreqs(so)->pru_send)( so, flags, m, NULL,
|
||||
control, td );
|
||||
if (addr != NULL && so->so_type == SOCK_DGRAM)
|
||||
(*orig_pr_usrreqs(so)->pru_disconnect)(so);
|
||||
out:
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
lomac_local_soreceive(struct socket *so, struct sockaddr **paddr,
|
||||
struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp) {
|
||||
lomac_object_t lobj;
|
||||
struct vnode *vp;
|
||||
struct unpcb *unp = sotounpcb(so);
|
||||
int ret_val; /* value to return to caller */
|
||||
|
||||
if (unp == NULL)
|
||||
return (EINVAL);
|
||||
vp = unp->unp_vnode;
|
||||
if (vp != NULL) {
|
||||
lobj.lo_type = VISLOMAC(vp) ? LO_TYPE_LVNODE : LO_TYPE_UVNODE;
|
||||
lobj.lo_object.vnode = vp;
|
||||
ret_val = monitor_read_object(uio->uio_td->td_proc, &lobj);
|
||||
if (ret_val == 0)
|
||||
ret_val = (*orig_pr_usrreqs(so)->pru_soreceive)(so,
|
||||
paddr, uio, mp0, controlp, flagsp);
|
||||
} else {
|
||||
/*
|
||||
* This is a receive from a socket in a pair created by
|
||||
* socketpair(). Monitor it as we would a pipe read,
|
||||
* except for allowing for arbitrary numbers of sleeps.
|
||||
*/
|
||||
ret_val = monitored_soreceive(so, paddr, uio, mp0, controlp,
|
||||
flagsp);
|
||||
}
|
||||
return (ret_val);
|
||||
}
|
||||
|
||||
int
|
||||
lomac_soreceive(struct socket *so, struct sockaddr **paddr, struct uio *uio,
|
||||
struct mbuf **mp0, struct mbuf **controlp, int *flagsp) {
|
||||
int ret_val; /* value to return to caller */
|
||||
|
||||
(void)monitor_read_net_socket(uio->uio_td->td_proc);
|
||||
ret_val = (*orig_pr_usrreqs(so)->pru_soreceive)(so, paddr, uio, mp0,
|
||||
controlp, flagsp);
|
||||
return (ret_val);
|
||||
}
|
||||
|
||||
int
|
||||
lomac_initialize_sockets(void) {
|
||||
struct domain *dp; /* used to traverse global `domains' list */
|
||||
struct protosw *pr; /* used to traverse each domain's protosw list */
|
||||
struct lomac_pr_usrreqs *lomac_pr_usrreqs; /* lomac usrreqs vectors */
|
||||
void (**lfuncp)(void), (**funcp)(void);
|
||||
int n, nreq;
|
||||
|
||||
nreq = sizeof(struct pr_usrreqs) / sizeof(void (*)(void));
|
||||
for (dp = domains; dp; dp = dp->dom_next) {
|
||||
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
|
||||
|
||||
lomac_pr_usrreqs = (struct lomac_pr_usrreqs *)malloc(
|
||||
sizeof(struct lomac_pr_usrreqs), M_LOMAC_USRREQS,
|
||||
M_WAITOK);
|
||||
|
||||
if (dp->dom_family == AF_LOCAL)
|
||||
memcpy(lomac_pr_usrreqs, &lomac_local_usrreqs,
|
||||
sizeof(struct pr_usrreqs));
|
||||
else
|
||||
memcpy(lomac_pr_usrreqs, &lomac_net_usrreqs,
|
||||
sizeof(struct pr_usrreqs));
|
||||
/*
|
||||
* Do sparse allocation of user requests and only
|
||||
* override the ones we need to (to reduce overhead).
|
||||
*/
|
||||
lfuncp = (void (**)(void))lomac_pr_usrreqs;
|
||||
funcp = (void (**)(void))pr->pr_usrreqs;
|
||||
for (n = 0; n < nreq; n++) {
|
||||
if (lfuncp[n] == NULL)
|
||||
lfuncp[n] = funcp[n];
|
||||
}
|
||||
lomac_pr_usrreqs->orig_pr_usrreqs = pr->pr_usrreqs;
|
||||
pr->pr_usrreqs = (struct pr_usrreqs *)lomac_pr_usrreqs;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
lomac_uninitialize_sockets(void) {
|
||||
struct domain *dp; /* used to traverse global `domains' list */
|
||||
struct protosw *pr; /* used to traverse each domain's protosw list */
|
||||
struct lomac_pr_usrreqs *lomac_pr_usrreqs; /* lomac usrreqs vectors */
|
||||
|
||||
for (dp = domains; dp; dp = dp->dom_next) {
|
||||
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
|
||||
lomac_pr_usrreqs = (struct lomac_pr_usrreqs *)
|
||||
pr->pr_usrreqs;
|
||||
pr->pr_usrreqs = lomac_pr_usrreqs->orig_pr_usrreqs;
|
||||
free(lomac_pr_usrreqs, M_LOMAC_USRREQS);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define SBLOCKWAIT(f) (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK)
|
||||
/*
|
||||
* Implement receive operations on a socket.
|
||||
* We depend on the way that records are added to the sockbuf
|
||||
* by sbappend*. In particular, each record (mbufs linked through m_next)
|
||||
* must begin with an address if the protocol so specifies,
|
||||
* followed by an optional mbuf or mbufs containing ancillary data,
|
||||
* and then zero or more mbufs of data.
|
||||
* In order to avoid blocking network interrupts for the entire time here,
|
||||
* we splx() while doing the actual copy to user space.
|
||||
* Although the sockbuf is locked, new data may still be appended,
|
||||
* and thus we must maintain consistency of the sockbuf during that time.
|
||||
*
|
||||
* The caller may receive the data as a single mbuf chain by supplying
|
||||
* an mbuf **mp0 for use in returning the chain. The uio is then used
|
||||
* only for the count in uio_resid.
|
||||
*/
|
||||
static int
|
||||
monitored_soreceive(so, psa, uio, mp0, controlp, flagsp)
|
||||
register struct socket *so;
|
||||
struct sockaddr **psa;
|
||||
struct uio *uio;
|
||||
struct mbuf **mp0;
|
||||
struct mbuf **controlp;
|
||||
int *flagsp;
|
||||
{
|
||||
lomac_object_t lobj;
|
||||
register struct mbuf *m, **mp;
|
||||
register int flags, len, error, s, offset;
|
||||
struct protosw *pr = so->so_proto;
|
||||
struct mbuf *nextrecord;
|
||||
struct proc *p;
|
||||
int moff, type = 0;
|
||||
int orig_resid = uio->uio_resid;
|
||||
|
||||
mp = mp0;
|
||||
if (psa)
|
||||
*psa = 0;
|
||||
if (controlp)
|
||||
*controlp = 0;
|
||||
if (flagsp)
|
||||
flags = *flagsp &~ MSG_EOR;
|
||||
else
|
||||
flags = 0;
|
||||
lobj.lo_type = LO_TYPE_SOCKETPAIR;
|
||||
lobj.lo_object.socket = so;
|
||||
if (uio->uio_td != NULL) /* XXX */
|
||||
p = uio->uio_td->td_proc;
|
||||
else
|
||||
p = curthread->td_proc;
|
||||
if (flags & MSG_OOB) {
|
||||
m = m_get(M_TRYWAIT, MT_DATA);
|
||||
if (m == NULL)
|
||||
return (ENOBUFS);
|
||||
error = (*pr->pr_usrreqs->pru_rcvoob)(so, m, flags & MSG_PEEK);
|
||||
if (error)
|
||||
goto bad;
|
||||
do {
|
||||
monitor_read_object(p, &lobj);
|
||||
error = uiomove(mtod(m, caddr_t),
|
||||
(int) min(uio->uio_resid, m->m_len), uio);
|
||||
m = m_free(m);
|
||||
} while (uio->uio_resid && error == 0 && m);
|
||||
bad:
|
||||
if (m)
|
||||
m_freem(m);
|
||||
return (error);
|
||||
}
|
||||
if (mp)
|
||||
*mp = (struct mbuf *)0;
|
||||
if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
|
||||
(*pr->pr_usrreqs->pru_rcvd)(so, 0);
|
||||
|
||||
restart:
|
||||
error = sblock(&so->so_rcv, SBLOCKWAIT(flags));
|
||||
if (error)
|
||||
return (error);
|
||||
s = splnet();
|
||||
|
||||
m = so->so_rcv.sb_mb;
|
||||
/*
|
||||
* If we have less data than requested, block awaiting more
|
||||
* (subject to any timeout) if:
|
||||
* 1. the current count is less than the low water mark, or
|
||||
* 2. MSG_WAITALL is set, and it is possible to do the entire
|
||||
* receive operation at once if we block (resid <= hiwat).
|
||||
* 3. MSG_DONTWAIT is not set
|
||||
* If MSG_WAITALL is set but resid is larger than the receive buffer,
|
||||
* we have to do the receive in sections, and thus risk returning
|
||||
* a short count if a timeout or signal occurs after we start.
|
||||
*/
|
||||
if (m == 0 || (((flags & MSG_DONTWAIT) == 0 &&
|
||||
so->so_rcv.sb_cc < uio->uio_resid) &&
|
||||
(so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
|
||||
((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) &&
|
||||
m->m_nextpkt == 0 && (pr->pr_flags & PR_ATOMIC) == 0)) {
|
||||
KASSERT(m != 0 || !so->so_rcv.sb_cc,
|
||||
("receive: m == %p so->so_rcv.sb_cc == %lu",
|
||||
m, so->so_rcv.sb_cc));
|
||||
if (so->so_error) {
|
||||
if (m)
|
||||
goto dontblock;
|
||||
error = so->so_error;
|
||||
if ((flags & MSG_PEEK) == 0)
|
||||
so->so_error = 0;
|
||||
goto release;
|
||||
}
|
||||
if (so->so_state & SS_CANTRCVMORE) {
|
||||
if (m)
|
||||
goto dontblock;
|
||||
else
|
||||
goto release;
|
||||
}
|
||||
for (; m; m = m->m_next)
|
||||
if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) {
|
||||
m = so->so_rcv.sb_mb;
|
||||
goto dontblock;
|
||||
}
|
||||
if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
|
||||
(so->so_proto->pr_flags & PR_CONNREQUIRED)) {
|
||||
error = ENOTCONN;
|
||||
goto release;
|
||||
}
|
||||
if (uio->uio_resid == 0)
|
||||
goto release;
|
||||
if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) {
|
||||
error = EWOULDBLOCK;
|
||||
goto release;
|
||||
}
|
||||
sbunlock(&so->so_rcv);
|
||||
error = sbwait(&so->so_rcv);
|
||||
splx(s);
|
||||
if (error)
|
||||
return (error);
|
||||
goto restart;
|
||||
}
|
||||
dontblock:
|
||||
if (uio->uio_td)
|
||||
p->p_stats->p_ru.ru_msgrcv++;
|
||||
nextrecord = m->m_nextpkt;
|
||||
if (pr->pr_flags & PR_ADDR) {
|
||||
KASSERT(m->m_type == MT_SONAME, ("receive 1a"));
|
||||
orig_resid = 0;
|
||||
if (psa)
|
||||
*psa = dup_sockaddr(mtod(m, struct sockaddr *),
|
||||
mp0 == 0);
|
||||
if (flags & MSG_PEEK) {
|
||||
m = m->m_next;
|
||||
} else {
|
||||
sbfree(&so->so_rcv, m);
|
||||
MFREE(m, so->so_rcv.sb_mb);
|
||||
m = so->so_rcv.sb_mb;
|
||||
}
|
||||
}
|
||||
while (m && m->m_type == MT_CONTROL && error == 0) {
|
||||
if (flags & MSG_PEEK) {
|
||||
if (controlp)
|
||||
*controlp = m_copy(m, 0, m->m_len);
|
||||
m = m->m_next;
|
||||
} else {
|
||||
sbfree(&so->so_rcv, m);
|
||||
so->so_rcv.sb_mb = m->m_next;
|
||||
m->m_next = NULL;
|
||||
if (pr->pr_domain->dom_externalize)
|
||||
error =
|
||||
(*pr->pr_domain->dom_externalize)(m, controlp);
|
||||
else if (controlp)
|
||||
*controlp = m;
|
||||
else
|
||||
m_freem(m);
|
||||
m = so->so_rcv.sb_mb;
|
||||
}
|
||||
if (controlp) {
|
||||
orig_resid = 0;
|
||||
do
|
||||
controlp = &(*controlp)->m_next;
|
||||
while (*controlp != NULL);
|
||||
}
|
||||
}
|
||||
if (m) {
|
||||
if ((flags & MSG_PEEK) == 0)
|
||||
m->m_nextpkt = nextrecord;
|
||||
type = m->m_type;
|
||||
if (type == MT_OOBDATA)
|
||||
flags |= MSG_OOB;
|
||||
}
|
||||
moff = 0;
|
||||
offset = 0;
|
||||
while (m && uio->uio_resid > 0 && error == 0) {
|
||||
if (m->m_type == MT_OOBDATA) {
|
||||
if (type != MT_OOBDATA)
|
||||
break;
|
||||
} else if (type == MT_OOBDATA)
|
||||
break;
|
||||
else
|
||||
KASSERT(m->m_type == MT_DATA || m->m_type == MT_HEADER,
|
||||
("receive 3"));
|
||||
so->so_state &= ~SS_RCVATMARK;
|
||||
len = uio->uio_resid;
|
||||
if (so->so_oobmark && len > so->so_oobmark - offset)
|
||||
len = so->so_oobmark - offset;
|
||||
if (len > m->m_len - moff)
|
||||
len = m->m_len - moff;
|
||||
/*
|
||||
* If mp is set, just pass back the mbufs.
|
||||
* Otherwise copy them out via the uio, then free.
|
||||
* Sockbuf must be consistent here (points to current mbuf,
|
||||
* it points to next record) when we drop priority;
|
||||
* we must note any additions to the sockbuf when we
|
||||
* block interrupts again.
|
||||
*/
|
||||
if (mp == 0) {
|
||||
splx(s);
|
||||
monitor_read_object(p, &lobj);
|
||||
error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio);
|
||||
s = splnet();
|
||||
if (error)
|
||||
goto release;
|
||||
} else
|
||||
uio->uio_resid -= len;
|
||||
if (len == m->m_len - moff) {
|
||||
if (m->m_flags & M_EOR)
|
||||
flags |= MSG_EOR;
|
||||
if (flags & MSG_PEEK) {
|
||||
m = m->m_next;
|
||||
moff = 0;
|
||||
} else {
|
||||
nextrecord = m->m_nextpkt;
|
||||
sbfree(&so->so_rcv, m);
|
||||
if (mp) {
|
||||
*mp = m;
|
||||
mp = &m->m_next;
|
||||
so->so_rcv.sb_mb = m = m->m_next;
|
||||
*mp = (struct mbuf *)0;
|
||||
} else {
|
||||
MFREE(m, so->so_rcv.sb_mb);
|
||||
m = so->so_rcv.sb_mb;
|
||||
}
|
||||
if (m)
|
||||
m->m_nextpkt = nextrecord;
|
||||
}
|
||||
} else {
|
||||
if (flags & MSG_PEEK)
|
||||
moff += len;
|
||||
else {
|
||||
if (mp)
|
||||
*mp = m_copym(m, 0, len, M_TRYWAIT);
|
||||
m->m_data += len;
|
||||
m->m_len -= len;
|
||||
so->so_rcv.sb_cc -= len;
|
||||
}
|
||||
}
|
||||
if (so->so_oobmark) {
|
||||
if ((flags & MSG_PEEK) == 0) {
|
||||
so->so_oobmark -= len;
|
||||
if (so->so_oobmark == 0) {
|
||||
so->so_state |= SS_RCVATMARK;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
offset += len;
|
||||
if (offset == so->so_oobmark)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flags & MSG_EOR)
|
||||
break;
|
||||
/*
|
||||
* If the MSG_WAITALL flag is set (for non-atomic socket),
|
||||
* we must not quit until "uio->uio_resid == 0" or an error
|
||||
* termination. If a signal/timeout occurs, return
|
||||
* with a short count but without error.
|
||||
* Keep sockbuf locked against other readers.
|
||||
*/
|
||||
while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 &&
|
||||
!sosendallatonce(so) && !nextrecord) {
|
||||
if (so->so_error || so->so_state & SS_CANTRCVMORE)
|
||||
break;
|
||||
/*
|
||||
* Notify the protocol that some data has been
|
||||
* drained before blocking.
|
||||
*/
|
||||
if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
|
||||
(*pr->pr_usrreqs->pru_rcvd)(so, flags);
|
||||
error = sbwait(&so->so_rcv);
|
||||
if (error) {
|
||||
sbunlock(&so->so_rcv);
|
||||
splx(s);
|
||||
return (0);
|
||||
}
|
||||
m = so->so_rcv.sb_mb;
|
||||
if (m)
|
||||
nextrecord = m->m_nextpkt;
|
||||
}
|
||||
}
|
||||
|
||||
if (m && pr->pr_flags & PR_ATOMIC) {
|
||||
flags |= MSG_TRUNC;
|
||||
if ((flags & MSG_PEEK) == 0)
|
||||
(void) sbdroprecord(&so->so_rcv);
|
||||
}
|
||||
if ((flags & MSG_PEEK) == 0) {
|
||||
if (m == 0)
|
||||
so->so_rcv.sb_mb = nextrecord;
|
||||
if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
|
||||
(*pr->pr_usrreqs->pru_rcvd)(so, flags);
|
||||
}
|
||||
if (orig_resid == uio->uio_resid && orig_resid &&
|
||||
(flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
|
||||
sbunlock(&so->so_rcv);
|
||||
splx(s);
|
||||
goto restart;
|
||||
}
|
||||
|
||||
if (flagsp)
|
||||
*flagsp |= flags;
|
||||
release:
|
||||
sbunlock(&so->so_rcv);
|
||||
splx(s);
|
||||
return (error);
|
||||
}
|
35
sys/contrib/lomac/kernel_socket.h
Normal file
35
sys/contrib/lomac/kernel_socket.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* LOMAC - Low Water-Mark Mandatory Access Control
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kernel_socket.h,v 1.1 2001/09/26 23:00:44 tfraser Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _KERNEL_SOCKET_H_
|
||||
#define _KERNEL_SOCKET_H_
|
||||
|
||||
int lomac_initialize_sockets( void );
|
||||
int lomac_uninitialize_sockets( void );
|
||||
|
||||
#endif /* _KERNEL_SOCKET_H_ */
|
||||
|
687
sys/contrib/lomac/kernel_util.c
Normal file
687
sys/contrib/lomac/kernel_util.c
Normal file
@ -0,0 +1,687 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1982, 1986, 1989, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* (c) UNIX System Laboratories, Inc.
|
||||
* All or some portions of this file are derived from material licensed
|
||||
* to the University of California by American Telephone and Telegraph
|
||||
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
||||
* the permission of UNIX System Laboratories, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kernel_util.c,v 1.22 2001/11/15 20:51:13 bfeldman Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/sx.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/linker.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/dirent.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/unistd.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_extern.h>
|
||||
#include <vm/vm_kern.h>
|
||||
|
||||
#include "kernel_interface.h"
|
||||
#include "kernel_util.h"
|
||||
#include "kernel_mediate.h"
|
||||
#include "kernel_monitor.h"
|
||||
#include "lomacfs.h"
|
||||
|
||||
#include "syscall_gate/syscall_gate.h"
|
||||
|
||||
#define AS(name) (sizeof(struct name) / sizeof(register_t))
|
||||
|
||||
int
|
||||
each_proc(int (*iter)(struct proc *p)) {
|
||||
struct proc *p;
|
||||
int error = 0;
|
||||
|
||||
sx_slock(&allproc_lock);
|
||||
LIST_FOREACH(p, &allproc, p_list) {
|
||||
error = (*iter)(p);
|
||||
if (error)
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
sx_sunlock(&allproc_lock);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
initialize_proc(struct proc *p) {
|
||||
lattr_t lattr = { LOMAC_HIGHEST_LEVEL, 0 };
|
||||
|
||||
init_subject_lattr(p, &lattr);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
lomac_at_fork(struct proc *parent, struct proc *p, int flags) {
|
||||
|
||||
if ((flags & RFMEM) == 0) {
|
||||
lattr_t parent_lattr;
|
||||
|
||||
get_subject_lattr(parent, &parent_lattr);
|
||||
init_subject_lattr(p, &parent_lattr);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
lomac_proc_candebug(struct proc *p1, struct proc *p2) {
|
||||
lattr_t lattr;
|
||||
|
||||
get_subject_lattr(p1, &lattr);
|
||||
if (mediate_subject_level_subject("debug", p1, lattr.level, p2))
|
||||
return (0);
|
||||
else
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
static int
|
||||
lomac_proc_cansched(struct proc *p1, struct proc *p2) {
|
||||
lattr_t lattr;
|
||||
|
||||
get_subject_lattr(p1, &lattr);
|
||||
if (mediate_subject_level_subject("sched", p1, lattr.level, p2))
|
||||
return (0);
|
||||
else
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
static int
|
||||
lomac_proc_cansignal(struct proc *p1, struct proc *p2, int signum) {
|
||||
lattr_t lattr;
|
||||
|
||||
get_subject_lattr(p1, &lattr);
|
||||
/*
|
||||
* Always allow signals to init(8) (necessary to shut down).
|
||||
*/
|
||||
if (p2->p_pid == 1 ||
|
||||
mediate_subject_level_subject("signal", p1, lattr.level, p2))
|
||||
return (0);
|
||||
else
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
lomac_initialize_procs(void) {
|
||||
int error;
|
||||
|
||||
#ifdef P_CAN_HOOKS
|
||||
can_hooks_lock();
|
||||
(void)p_candebug_hook(lomac_proc_candebug);
|
||||
(void)p_cansignal_hook(lomac_proc_cansignal);
|
||||
(void)p_cansched_hook(lomac_proc_cansched);
|
||||
can_hooks_unlock();
|
||||
#endif
|
||||
error = at_fork(lomac_at_fork);
|
||||
if (error)
|
||||
return (error);
|
||||
return (each_proc(&initialize_proc));
|
||||
}
|
||||
|
||||
int
|
||||
lomac_uninitialize_procs(void) {
|
||||
|
||||
rm_at_fork(lomac_at_fork);
|
||||
return (0);
|
||||
}
|
||||
|
||||
extern int (*old_execve)(struct thread *, struct execve_args *);
|
||||
|
||||
int
|
||||
execve(struct thread *td, struct execve_args *uap) {
|
||||
lattr_t lattr, textattr;
|
||||
struct vmspace *oldvmspace;
|
||||
struct proc *p;
|
||||
int error;
|
||||
|
||||
p = td->td_proc;
|
||||
get_subject_lattr(p, &lattr);
|
||||
oldvmspace = p->p_vmspace;
|
||||
error = old_execve(td, uap);
|
||||
if (error == 0) {
|
||||
lomac_object_t lobj;
|
||||
|
||||
lobj.lo_type = VISLOMAC(p->p_textvp) ? LO_TYPE_LVNODE :
|
||||
LO_TYPE_UVNODE;
|
||||
lobj.lo_object.vnode = p->p_textvp;
|
||||
get_object_lattr(&lobj, &textattr);
|
||||
/*
|
||||
* Install the executable's relevant attributes into the
|
||||
* process.
|
||||
*/
|
||||
lattr.flags |= textattr.flags &
|
||||
(LOMAC_ATTR_NODEMOTE | LOMAC_ATTR_NONETDEMOTE);
|
||||
if (p->p_vmspace != oldvmspace)
|
||||
init_subject_lattr(p, &lattr);
|
||||
else
|
||||
set_subject_lattr(p, lattr);
|
||||
mtx_lock(&Giant);
|
||||
(void)monitor_read_object(p, &lobj);
|
||||
mtx_unlock(&Giant);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
const char *linker_basename(const char* path);
|
||||
int linker_load_module(const char *kldname, const char *modname,
|
||||
struct linker_file *parent, struct mod_depend *verinfo,
|
||||
struct linker_file **lfpp);
|
||||
|
||||
MALLOC_DECLARE(M_LINKER);
|
||||
|
||||
/*
|
||||
* MPSAFE
|
||||
*/
|
||||
int
|
||||
kldload(struct thread* td, struct kldload_args* uap)
|
||||
{
|
||||
char *kldname, *modname;
|
||||
char *pathname = NULL;
|
||||
linker_file_t lf;
|
||||
int error = 0;
|
||||
|
||||
td->td_retval[0] = -1;
|
||||
|
||||
if (securelevel > 0) /* redundant, but that's OK */
|
||||
return EPERM;
|
||||
|
||||
mtx_lock(&Giant);
|
||||
|
||||
if ((error = suser_td(td)) != 0)
|
||||
goto out;
|
||||
|
||||
pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
|
||||
if ((error = copyinstr(SCARG(uap, file), pathname, MAXPATHLEN, NULL)) != 0)
|
||||
goto out;
|
||||
if (!mediate_subject_at_level("kldload", td->td_proc,
|
||||
LOMAC_HIGHEST_LEVEL)) {
|
||||
error = EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* If path do not contain qualified name or any dot in it (kldname.ko, or
|
||||
* kldname.ver.ko) treat it as interface name.
|
||||
*/
|
||||
if (index(pathname, '/') || index(pathname, '.')) {
|
||||
kldname = pathname;
|
||||
modname = NULL;
|
||||
} else {
|
||||
kldname = NULL;
|
||||
modname = pathname;
|
||||
}
|
||||
error = linker_load_module(kldname, modname, NULL, NULL, &lf);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
lf->userrefs++;
|
||||
td->td_retval[0] = lf->id;
|
||||
|
||||
out:
|
||||
if (pathname)
|
||||
free(pathname, M_TEMP);
|
||||
mtx_unlock(&Giant);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __i386__
|
||||
#include <machine/sysarch.h>
|
||||
|
||||
extern int (*old_sysarch)(struct thread *, void *);
|
||||
|
||||
int
|
||||
sysarch(struct thread *td, struct sysarch_args *uap) {
|
||||
switch (uap->op) {
|
||||
case I386_SET_IOPERM:
|
||||
if (!mediate_subject_at_level("ioperm", td->td_proc,
|
||||
LOMAC_HIGHEST_LEVEL))
|
||||
return (EPERM);
|
||||
default:
|
||||
return (old_sysarch(td, uap));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
extern int lomac_mmap(struct proc *, struct mmap_args *);
|
||||
|
||||
/*
|
||||
* Mount a file system.
|
||||
*/
|
||||
#ifndef _SYS_SYSPROTO_H_
|
||||
struct mount_args {
|
||||
char *type;
|
||||
char *path;
|
||||
int flags;
|
||||
caddr_t data;
|
||||
};
|
||||
#endif
|
||||
/* ARGSUSED */
|
||||
int
|
||||
mount(td, uap)
|
||||
struct thread *td;
|
||||
struct mount_args /* {
|
||||
syscallarg(char *) type;
|
||||
syscallarg(char *) path;
|
||||
syscallarg(int) flags;
|
||||
syscallarg(caddr_t) data;
|
||||
} */ *uap;
|
||||
{
|
||||
char *fstype;
|
||||
char *fspath;
|
||||
int error;
|
||||
|
||||
fstype = malloc(MFSNAMELEN, M_TEMP, M_WAITOK | M_ZERO);
|
||||
fspath = malloc(MNAMELEN, M_TEMP, M_WAITOK | M_ZERO);
|
||||
|
||||
/*
|
||||
* vfs_mount() actually takes a kernel string for `type' and
|
||||
* `path' now, so extract them.
|
||||
*/
|
||||
error = copyinstr(SCARG(uap, type), fstype, MFSNAMELEN, NULL);
|
||||
if (error)
|
||||
goto finish;
|
||||
error = copyinstr(SCARG(uap, path), fspath, MNAMELEN, NULL);
|
||||
if (error)
|
||||
goto finish;
|
||||
if (!mediate_subject_at_level("mount", td->td_proc,
|
||||
LOMAC_HIGHEST_LEVEL)) {
|
||||
error = EPERM;
|
||||
goto finish;
|
||||
}
|
||||
error = vfs_mount(td, fstype, fspath, SCARG(uap, flags),
|
||||
SCARG(uap, data));
|
||||
finish:
|
||||
free(fstype, M_TEMP);
|
||||
free(fspath, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unmount a file system.
|
||||
*
|
||||
* Note: unmount takes a path to the vnode mounted on as argument,
|
||||
* not special file (as before).
|
||||
*/
|
||||
#ifndef _SYS_SYSPROTO_H_
|
||||
struct unmount_args {
|
||||
char *path;
|
||||
int flags;
|
||||
};
|
||||
#endif
|
||||
/* ARGSUSED */
|
||||
int
|
||||
unmount(td, uap)
|
||||
struct thread *td;
|
||||
register struct unmount_args /* {
|
||||
syscallarg(char *) path;
|
||||
syscallarg(int) flags;
|
||||
} */ *uap;
|
||||
{
|
||||
register struct vnode *vp;
|
||||
struct mount *mp;
|
||||
int error;
|
||||
struct nameidata nd;
|
||||
|
||||
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
|
||||
SCARG(uap, path), td);
|
||||
if ((error = namei(&nd)) != 0)
|
||||
return (error);
|
||||
vp = nd.ni_vp;
|
||||
NDFREE(&nd, NDF_ONLY_PNBUF);
|
||||
mp = vp->v_mount;
|
||||
|
||||
/*
|
||||
* Only root, or the user that did the original mount is
|
||||
* permitted to unmount this filesystem.
|
||||
*/
|
||||
if (!mediate_subject_at_level("unmount", td->td_proc,
|
||||
LOMAC_HIGHEST_LEVEL) ||
|
||||
((mp->mnt_stat.f_owner != td->td_proc->p_ucred->cr_uid) &&
|
||||
(error = suser_td(td)))) {
|
||||
vput(vp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't allow unmounting the root file system.
|
||||
*/
|
||||
if (mp->mnt_flag & MNT_ROOTFS) {
|
||||
vput(vp);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Must be the root of the filesystem
|
||||
*/
|
||||
if ((vp->v_flag & VROOT) == 0) {
|
||||
vput(vp);
|
||||
return (EINVAL);
|
||||
}
|
||||
vput(vp);
|
||||
return (dounmount(mp, SCARG(uap, flags), td));
|
||||
}
|
||||
|
||||
static struct syscall_override {
|
||||
int offset;
|
||||
sy_call_t *call;
|
||||
int narg;
|
||||
int mpsafe;
|
||||
} syscall_overrides[] = {
|
||||
{ SYS_mmap, (sy_call_t *)mmap, AS(mmap_args), 1 },
|
||||
{ SYS_execve, (sy_call_t *)execve, AS(execve_args), 1 },
|
||||
{ SYS_kldload, (sy_call_t *)kldload, AS(kldload_args), 1 },
|
||||
{ SYS_mount, (sy_call_t *)mount, AS(mount_args), 0 },
|
||||
{ SYS_unmount, (sy_call_t *)unmount, AS(unmount_args), 0 },
|
||||
#ifdef __i386__
|
||||
{ SYS_sysarch, (sy_call_t *)sysarch, AS(sysarch_args), 1 }
|
||||
#endif
|
||||
};
|
||||
|
||||
int
|
||||
lomac_initialize_syscalls(void) {
|
||||
int error, i;
|
||||
|
||||
for (i = 0;
|
||||
i < sizeof(syscall_overrides) / sizeof(syscall_overrides[0]); i++) {
|
||||
struct syscall_override *so = &syscall_overrides[i];
|
||||
|
||||
error = syscall_gate_register(so->offset, so->call, so->narg,
|
||||
so->mpsafe);
|
||||
if (error) {
|
||||
while (--i >= 0)
|
||||
syscall_gate_deregister(
|
||||
syscall_overrides[i].offset);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
lomac_uninitialize_syscalls(void) {
|
||||
int i;
|
||||
|
||||
for (i = 0;
|
||||
i < sizeof(syscall_overrides) / sizeof(syscall_overrides[0]); i++)
|
||||
syscall_gate_deregister(syscall_overrides[i].offset);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* This memory is shared by all lomac_do_recwd() calls, in sequence. */
|
||||
static char *pathmem;
|
||||
#define DIRENTMEM_SIZE (64 << 10) /* 64KB is good, I guess! */
|
||||
static char *direntmem;
|
||||
|
||||
static int
|
||||
lomac_dirents_searchbyid(struct vnode *dvp, struct dirent *dp,
|
||||
struct dirent *enddp, const struct vattr *vap, struct dirent **retdp)
|
||||
{
|
||||
struct vattr pvattr;
|
||||
struct componentname cnp;
|
||||
struct thread *td = curthread;
|
||||
struct ucred *ucred = td->td_ucred;
|
||||
struct vnode *vp;
|
||||
int error;
|
||||
|
||||
*retdp = NULL;
|
||||
for (; dp != enddp; dp = (struct dirent *)((char *)dp + dp->d_reclen)) {
|
||||
cnp.cn_nameiop = LOOKUP;
|
||||
cnp.cn_flags = LOCKPARENT | ISLASTCN | NOFOLLOW;
|
||||
cnp.cn_thread = td;
|
||||
cnp.cn_cred = ucred;
|
||||
cnp.cn_nameptr = dp->d_name;
|
||||
cnp.cn_namelen = dp->d_namlen;
|
||||
|
||||
error = VOP_LOOKUP(dvp, &vp, &cnp);
|
||||
if (error)
|
||||
return (error);
|
||||
error = VOP_GETATTR(vp, &pvattr, ucred, td);
|
||||
if (vp != dvp)
|
||||
(void)vput(vp);
|
||||
else
|
||||
vrele(vp); /* if looking up "." */
|
||||
if (error)
|
||||
return (error);
|
||||
if (pvattr.va_fsid == vap->va_fsid &&
|
||||
pvattr.va_fileid == vap->va_fileid) {
|
||||
*retdp = dp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
lomac_getcwd(
|
||||
struct thread *td,
|
||||
char *buf,
|
||||
size_t buflen,
|
||||
char **bufret
|
||||
) {
|
||||
struct vattr cvattr;
|
||||
char *bp;
|
||||
int error, i, slash_prefixed;
|
||||
struct filedesc *fdp;
|
||||
struct vnode *vp, *startvp, *dvp;
|
||||
|
||||
if (buflen < 2)
|
||||
return (EINVAL);
|
||||
if (buflen > MAXPATHLEN)
|
||||
buflen = MAXPATHLEN;
|
||||
bp = buf;
|
||||
bp += buflen - 1;
|
||||
*bp = '\0';
|
||||
fdp = td->td_proc->p_fd;
|
||||
slash_prefixed = 0;
|
||||
#if defined(LOMAC_DEBUG_RECWD)
|
||||
printf("lomac_getcwd for %d:\n", td->td_proc->p_pid);
|
||||
#endif
|
||||
startvp = fdp->fd_cdir;
|
||||
vref(startvp);
|
||||
for (vp = startvp; vp != rootvnode; vp = dvp) {
|
||||
struct iovec diov = {
|
||||
direntmem,
|
||||
DIRENTMEM_SIZE
|
||||
};
|
||||
struct uio duio = {
|
||||
&diov,
|
||||
1,
|
||||
0,
|
||||
DIRENTMEM_SIZE,
|
||||
UIO_SYSSPACE,
|
||||
UIO_READ,
|
||||
curthread
|
||||
};
|
||||
struct dirent *dp;
|
||||
int direof;
|
||||
|
||||
if (vp->v_flag & VROOT) {
|
||||
if (vp->v_mount == NULL) /* forced unmount */
|
||||
return (EBADF);
|
||||
dvp = vp->v_mount->mnt_vnodecovered;
|
||||
continue;
|
||||
}
|
||||
dvp = vp->v_dd;
|
||||
if (vp == dvp)
|
||||
break;
|
||||
/*
|
||||
* Utilize POSIX requirement of files having same
|
||||
* st_dev and st_ino to be the same file, in our
|
||||
* case with vattr.va_fsid and vattr.va_fileid.
|
||||
*/
|
||||
error = vget(vp, LK_EXCLUSIVE, curthread);
|
||||
if (error)
|
||||
goto out2;
|
||||
error = VOP_GETATTR(vp, &cvattr, curthread->td_ucred,
|
||||
curthread);
|
||||
if (error)
|
||||
goto out2;
|
||||
(void)vput(vp);
|
||||
error = vget(dvp, LK_EXCLUSIVE, curthread);
|
||||
if (error)
|
||||
goto out2;
|
||||
for (direof = 0; !direof;) {
|
||||
error = VOP_READDIR(dvp, &duio,
|
||||
curthread->td_ucred, &direof, NULL, NULL);
|
||||
if (error)
|
||||
break;
|
||||
error = lomac_dirents_searchbyid(dvp,
|
||||
(struct dirent *)direntmem,
|
||||
(struct dirent *)(direntmem +
|
||||
DIRENTMEM_SIZE - duio.uio_resid),
|
||||
&cvattr,
|
||||
&dp);
|
||||
if (error)
|
||||
break;
|
||||
if (dp != NULL) {
|
||||
(void)vput(dvp);
|
||||
#if defined(LOMAC_DEBUG_RECWD)
|
||||
printf("\tdirent component: \"%.*s\"\n",
|
||||
dp->d_namlen, dp->d_name);
|
||||
#endif
|
||||
for (i = dp->d_namlen - 1; i >= 0; i--)
|
||||
if (bp == buf)
|
||||
return (ENOMEM);
|
||||
else
|
||||
*--bp = dp->d_name[i];
|
||||
goto nextcomp;
|
||||
}
|
||||
diov.iov_base = direntmem;
|
||||
diov.iov_len = DIRENTMEM_SIZE;
|
||||
duio.uio_resid = DIRENTMEM_SIZE;
|
||||
}
|
||||
if (direof)
|
||||
error = ENOENT;
|
||||
(void)vput(dvp);
|
||||
out2:
|
||||
#if defined(LOMAC_DEBUG_RECWD)
|
||||
printf("backup dirent lookup problem: %d\n", error);
|
||||
#endif
|
||||
goto out;
|
||||
nextcomp:
|
||||
if (bp == buf)
|
||||
return (ENOMEM);
|
||||
*--bp = '/';
|
||||
slash_prefixed = 1;
|
||||
}
|
||||
if (!slash_prefixed) {
|
||||
if (bp == buf)
|
||||
return (ENOMEM);
|
||||
*--bp = '/';
|
||||
}
|
||||
error = 0;
|
||||
*bufret = bp;
|
||||
out:
|
||||
vrele(startvp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
lomac_do_recwd(struct proc *p) {
|
||||
struct nameidata nd;
|
||||
struct filedesc *fdp = curthread->td_proc->p_fd;
|
||||
struct thread *td = &p->p_thread;
|
||||
char *nbuf;
|
||||
struct vnode *cdir, *rdir, *vp;
|
||||
int error;
|
||||
|
||||
if (p == curthread->td_proc)
|
||||
return (0);
|
||||
PROC_LOCK(p);
|
||||
if (p->p_flag & P_SYSTEM) {
|
||||
PROC_UNLOCK(p);
|
||||
return (0);
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
error = lomac_getcwd(td, pathmem, MAXPATHLEN, &nbuf);
|
||||
if (error) {
|
||||
#if defined(LOMAC_DEBUG_RECWD)
|
||||
printf("lomac: recwd() failure, lomac_getcwd() == %d\n",
|
||||
error);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
rdir = fdp->fd_rdir;
|
||||
fdp->fd_rdir = rootvnode;
|
||||
vref(fdp->fd_rdir);
|
||||
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
|
||||
nbuf, curthread);
|
||||
error = namei(&nd);
|
||||
vrele(fdp->fd_rdir);
|
||||
fdp->fd_rdir = rdir;
|
||||
if (error == 0) {
|
||||
vp = nd.ni_vp;
|
||||
if (vp->v_type != VDIR)
|
||||
error = ENOTDIR;
|
||||
else
|
||||
error = VOP_ACCESS(vp, VEXEC, td->td_proc->p_ucred,
|
||||
curthread);
|
||||
if (error)
|
||||
vput(vp);
|
||||
else {
|
||||
NDFREE(&nd, NDF_ONLY_PNBUF);
|
||||
fdp = p->p_fd;
|
||||
cdir = fdp->fd_cdir;
|
||||
fdp->fd_cdir = vp;
|
||||
vrele(cdir);
|
||||
VOP_UNLOCK(vp, 0, curthread);
|
||||
}
|
||||
}
|
||||
#if defined(LOMAC_DEBUG_RECWD)
|
||||
printf("\trecwd() to \"%.*s\" == %d\n",
|
||||
MAXPATHLEN, nbuf, error);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
lomac_initialize_cwds(void) {
|
||||
int error;
|
||||
|
||||
pathmem = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
|
||||
direntmem = malloc(DIRENTMEM_SIZE, M_TEMP, M_WAITOK);
|
||||
mtx_lock(&Giant);
|
||||
error = each_proc(lomac_do_recwd);
|
||||
mtx_unlock(&Giant);
|
||||
free(pathmem, M_TEMP);
|
||||
free(direntmem, M_TEMP);
|
||||
return (error);
|
||||
}
|
54
sys/contrib/lomac/kernel_util.h
Normal file
54
sys/contrib/lomac/kernel_util.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kernel_util.h,v 1.4 2001/11/14 16:30:17 bfeldman Exp $
|
||||
*/
|
||||
#ifndef KERNEL_UTIL_H
|
||||
#define KERNEL_UTIL_H
|
||||
|
||||
/*
|
||||
* Iterate through each proc, locking it and calling iter.
|
||||
* Short-circuit and return an error if the iterator ever returns one.
|
||||
*/
|
||||
int each_proc(int (*iter)(struct proc *p));
|
||||
|
||||
/*
|
||||
* Set the initial level on each proc, register at_fork().
|
||||
*/
|
||||
int lomac_initialize_procs(void);
|
||||
|
||||
/*
|
||||
* Unregister at_fork().
|
||||
*/
|
||||
int lomac_uninitialize_procs(void);
|
||||
|
||||
int lomac_initialize_cwds(void);
|
||||
|
||||
int lomac_initialize_syscalls(void);
|
||||
int lomac_uninitialize_syscalls(void);
|
||||
|
||||
int lomac_initialize_vm(void);
|
||||
int lomac_uninitialize_vm(void);
|
||||
#endif /* KERNEL_UTIL_H */
|
193
sys/contrib/lomac/lomac.h
Normal file
193
sys/contrib/lomac/lomac.h
Normal file
@ -0,0 +1,193 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: lomacfs.h,v 1.20 2001/10/17 15:34:29 bfeldman Exp $
|
||||
*/
|
||||
|
||||
#ifndef _LOMAC_H_
|
||||
#define _LOMAC_H_
|
||||
|
||||
/*
|
||||
* This file defines the `lattr_t' type, which represents
|
||||
* the architecture-independent notion of LOMAC attributes.
|
||||
*
|
||||
* Each architecture must associate LOMAC attributes with subjects and
|
||||
* objects. This association can be implemented in an architecture-
|
||||
* specific way. However, when it comes time to make a decision by
|
||||
* comparing two LOMAC attributes, the architecture-specific code should
|
||||
* construct two instances of the architecture-independent lattr_t type
|
||||
* and compare them using the lomac_must_demote() and lomac_must_deny()
|
||||
* functions.
|
||||
*
|
||||
* The following two examples demonstrate how architecture-specific code
|
||||
* might do this construction and comparison:
|
||||
*
|
||||
* EXAMPLE USAGE:
|
||||
*
|
||||
* Example 1: subject x reads object y.
|
||||
* (1) a = LOMAC attributes of subject x
|
||||
* (2) b = LOMAC attributes of object y
|
||||
* (3) demote_result = lomac_must_demote( a, b );
|
||||
* (4) IF demote_result THEN
|
||||
* (5) IF subject x is running in "deny read instead of demote" mode THEN
|
||||
* (6) RETURN read denied
|
||||
* (7) ENDIF
|
||||
* (8) IF subject x is not running in "never demote" mode THEN
|
||||
* (9) demote subject x
|
||||
* (10) ENDIF
|
||||
* (11) ENDIF
|
||||
* (12) perform read on object y
|
||||
*
|
||||
*
|
||||
* Example 2: subject x writes object y.
|
||||
* (50) a = LOMAC attributes of subject x
|
||||
* (51) b = LOMAC attributes of object y
|
||||
* (52) IF lomac_must_deny( a, b ) THEN
|
||||
* (53) return write denied
|
||||
* (54) ELSE
|
||||
* (55) perform write operation on object y
|
||||
* (56) ENDIF
|
||||
*
|
||||
* Lines 1, 2, 50, and 51 show the architecture-specific code
|
||||
* constructing instances of lattr_t.
|
||||
*
|
||||
* Lines 5 and 8 ask "is the subject running in some mode?" (See note
|
||||
* on modes, below.) The architecture-specific code must use these
|
||||
* modes to determine when to call lomac_must_demote/deny() and when not
|
||||
* to.
|
||||
*
|
||||
* Lines 6, 9, 53 and 55 show the architecture-specific code
|
||||
* taking different actions depending on the results of calls to
|
||||
* lomac_must_demote/deny(). The architecture-specific code is responsible
|
||||
* for calling lomac_must_demote/deny() in the proper places, and carrying
|
||||
* out the appropriate demotions and denials depending on the result.
|
||||
*
|
||||
*
|
||||
* A NOTE ON LEVELS:
|
||||
*
|
||||
* LOMAC presently supports only two levels: 1 and 2. Future versions
|
||||
* of LOMAC may support more levels. Architecture-specific code may
|
||||
* assume that the LOWEST and HIGHEST constants defined below will
|
||||
* always refer to the lowest and highest levels in the range. They
|
||||
* may also provide support for only two levels for the time being.
|
||||
* However, architecture-specific code should try to minimize any other
|
||||
* assumptions about levels, in order to make it easier to increase
|
||||
* the level range in the future.
|
||||
*
|
||||
*
|
||||
* A NOTE ON CATEGORIES:
|
||||
*
|
||||
* The lattr_t structure's `flags' field is intended to be a bitfield
|
||||
* which architecture-specific code can use to implement categories.
|
||||
* The lomac_must_deny() function interprets the bits in the flags field
|
||||
* as categories. A clear flags field means no categories.
|
||||
*
|
||||
* A NOTE ON MODES:
|
||||
*
|
||||
* LOMAC allows subjects to run in many modes, such as "never demote"
|
||||
* or "no demote on IPC reads". Support for these modes is entirely
|
||||
* the responsibility of the architecture-specific code, because the
|
||||
* architecture-independent code doesn't know about operations like
|
||||
* "read" or "read on an IPC object".
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
typedef enum {
|
||||
LOMAC_LOWEST_LEVEL = 1,
|
||||
LOMAC_HIGHEST_LEVEL = 2
|
||||
} level_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
level_t level; /* level (an integer range) */
|
||||
unsigned int flags; /* category flags */
|
||||
} lattr_t; /* lomac attribute structure type */
|
||||
|
||||
|
||||
/* lomac_must_demote()
|
||||
*
|
||||
* in: actor - attributes of a subject that has or will perform an
|
||||
* operation that may require LOMAC to demote it.
|
||||
* target - attributes of the object that is or was the operand.
|
||||
* out: nothing
|
||||
* return: value condition
|
||||
* ----- ---------
|
||||
* 0 LOMAC should not demote the subject
|
||||
* 1 LOMAC should demote the subject
|
||||
*
|
||||
* This function is a predicate which decides whether or not LOMAC should
|
||||
* demote the subject with attributes `actor' after it performs an operation
|
||||
* (probably some kind of a read operation) on the object with attributes
|
||||
* `target'.
|
||||
*
|
||||
*/
|
||||
|
||||
static __inline int lomac_must_demote( const lattr_t *actor,
|
||||
const lattr_t *target ) {
|
||||
return( ( actor->level > target->level ) );
|
||||
}
|
||||
|
||||
|
||||
/* lomac_must_deny()
|
||||
*
|
||||
* in: actor - attributes of a subject that wants to perform some
|
||||
* operation that requires LOMAC to make an allow/deny
|
||||
* decision.
|
||||
* target - attributes of the subject or object the above subject
|
||||
* will operate upon.
|
||||
* out: nothing
|
||||
* return: value condition
|
||||
* ----- ---------
|
||||
* 0 LOMAC should allow the operation
|
||||
* 1 LOMAC should deny the operation
|
||||
*
|
||||
* This function is a predicate which decides whether or not LOMAC should
|
||||
* allow the subject with attributes `actor' to perform some operation
|
||||
* (probably some kind of write or kill operation) on the subject or object
|
||||
* with attributes `target'.
|
||||
*
|
||||
* The flags are two words: the low word is to be used for categories,
|
||||
* and the high word is meant to hold implementation-dependent flags that
|
||||
* are not category-related.
|
||||
*
|
||||
*/
|
||||
|
||||
static __inline int lomac_must_deny( const lattr_t *actor,
|
||||
const lattr_t *target ) {
|
||||
|
||||
if( actor->level >= target->level ) {
|
||||
return 0; /* allow */
|
||||
}
|
||||
if( target->flags & 0xffff ) {
|
||||
if( ( actor->flags & target->flags & 0xffff ) ==
|
||||
( target->flags & 0xffff ) ) {
|
||||
return 0; /* allow */
|
||||
}
|
||||
}
|
||||
|
||||
return 1; /* deny */
|
||||
}
|
||||
|
||||
#endif /* lomac.h */
|
106
sys/contrib/lomac/lomacfs.h
Normal file
106
sys/contrib/lomac/lomacfs.h
Normal file
@ -0,0 +1,106 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: lomacfs.h,v 1.20 2001/10/17 15:34:29 bfeldman Exp $
|
||||
*/
|
||||
|
||||
#ifndef LOMACFS_H
|
||||
#define LOMACFS_H
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include "kernel_interface.h"
|
||||
|
||||
struct lomac_mount {
|
||||
struct vnode *lm_rootvp; /* singly-ref'd root after mount() */
|
||||
#define LM_TOOKROOT 0x0001
|
||||
unsigned int lm_flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the structure associated with v_data on all LOMACFS vnodes.
|
||||
*/
|
||||
struct lomac_node {
|
||||
struct vnode *ln_vp; /* vnode back-pointer */
|
||||
struct vnode *ln_lowervp; /* shadowed vnode (ref'd or NULL) */
|
||||
#define LN_LEVEL_MASK 0x0003
|
||||
#define LN_LOWEST_LEVEL 0x0001
|
||||
#define LN_SUBJ_LEVEL 0x0002 /* placeholder before inheriting */
|
||||
#define LN_HIGHEST_LEVEL 0x0003
|
||||
#define LN_INHERIT_MASK 0x001c
|
||||
#define LN_INHERIT_LOW 0x0004 /* children start with a low level */
|
||||
#define LN_INHERIT_HIGH 0x0008 /* children start with a high level */
|
||||
#define LN_INHERIT_SUBJ 0x0010 /* children inherit subject's level */
|
||||
#define LN_ATTR_MASK 0x01e0
|
||||
#define LN_ATTR_LOWWRITE 0x0020 /* lower levels may write to */
|
||||
#define LN_ATTR_LOWNOOPEN 0x0040 /* lower levels may not open */
|
||||
#define LN_ATTR_NONETDEMOTE 0x0080 /* will not demote on net read */
|
||||
#define LN_ATTR_NODEMOTE 0x0100 /* subject won't demote on other read */
|
||||
u_int ln_flags;
|
||||
/* What's the last node explicitly specifying policy for this? */
|
||||
struct lomac_node_entry *ln_underpolicy;
|
||||
/* If non-NULL, this corresponds 1:1 to a specific PLM node entry. */
|
||||
struct lomac_node_entry *ln_entry;
|
||||
#if defined(LOMAC_DEBUG_INCNAME)
|
||||
char ln_name[MAXPATHLEN]; /* final component name */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the "placeholder" structure initialized from the PLM that
|
||||
* holds the level information for all named objects.
|
||||
*/
|
||||
struct lomac_node_entry {
|
||||
SLIST_HEAD(lomac_node_entry_head, lomac_node_entry) ln_children;
|
||||
SLIST_ENTRY(lomac_node_entry) ln_chain; /* chain of current level */
|
||||
/* continuing with the LN_* flags above */
|
||||
#define LN_CHILD_ATTR_SHIFT 4 /* lshift from attr -> child attr */
|
||||
#define LN_CHILD_ATTR_MASK 0x1e00
|
||||
#define LN_CHILD_ATTR_LOWWRITE 0x0200 /* lower levels may write to */
|
||||
#define LN_CHILD_ATTR_LOWNOOPEN 0x0400 /* lower levels may not open */
|
||||
#define LN_CHILD_ATTR_NONETDEMOTE 0x0800 /* will not demote on net read */
|
||||
#define LN_CHILD_ATTR_NODEMOTE 0x1000 /* subject won't demote on other read */
|
||||
u_int ln_flags;
|
||||
char *ln_name; /* last component name (to search) */
|
||||
const char *ln_path; /* in "stable" storage */
|
||||
};
|
||||
|
||||
#define VTOLOMAC(vp) ((struct lomac_node *)(vp)->v_data)
|
||||
#define VTOLVP(vp) VTOLOMAC(vp)->ln_lowervp
|
||||
#define VFSTOLOMAC(mp) ((struct lomac_mount *)mp->mnt_data)
|
||||
#define VISLOMAC(vp) (vp->v_op == lomacfs_vnodeop_p)
|
||||
|
||||
int lomacfs_node_alloc(struct mount *mp, struct componentname *cnp,
|
||||
struct vnode *dvp, struct vnode *lowervp, struct vnode **vpp);
|
||||
|
||||
MALLOC_DECLARE(M_LOMACFS);
|
||||
extern vop_t **lomacfs_vnodeop_p;
|
||||
extern struct lomac_node_entry lomac_node_entry_root;
|
||||
|
||||
#endif /* LOMACFS_H */
|
118
sys/contrib/lomac/lomacfs_subr.c
Normal file
118
sys/contrib/lomac/lomacfs_subr.c
Normal file
@ -0,0 +1,118 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: lomacfs_subr.c,v 1.24 2001/11/05 20:57:41 tfraser Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/namei.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_extern.h>
|
||||
|
||||
#include "lomacfs.h"
|
||||
#include "kernel_plm.h"
|
||||
|
||||
int
|
||||
lomacfs_node_alloc(struct mount *mp, struct componentname *cnp,
|
||||
struct vnode *dvp, struct vnode *lowervp, struct vnode **vpp) {
|
||||
lomac_object_t lobj;
|
||||
struct thread *td = curthread;
|
||||
struct vnode *vp;
|
||||
struct lomac_node *lp;
|
||||
lattr_t subjlattr, objlattr;
|
||||
int error;
|
||||
|
||||
KASSERT((cnp == NULL) == (dvp == NULL),
|
||||
("lomacfs_node_alloc: dvp and cnp do not match"));
|
||||
lp = malloc(sizeof(*lp), M_LOMACFS, M_WAITOK);
|
||||
if (dvp != NULL) {
|
||||
error = cache_lookup(dvp, vpp, cnp);
|
||||
if (error == -1) { /* lost the race; return EEXIST and the vp */
|
||||
vput(lowervp);
|
||||
error = vget(*vpp, LK_EXCLUSIVE, td);
|
||||
free(lp, M_LOMACFS);
|
||||
if (error) {
|
||||
*vpp = NULL;
|
||||
return (error);
|
||||
} else
|
||||
return (EEXIST);
|
||||
}
|
||||
}
|
||||
error = getnewvnode(VT_NULL, mp, lomacfs_vnodeop_p, vpp);
|
||||
if (error) {
|
||||
vput(lowervp);
|
||||
free(lp, M_LOMACFS);
|
||||
return (error);
|
||||
}
|
||||
vp = *vpp;
|
||||
|
||||
vp->v_type = lowervp != NULL ? lowervp->v_type : VBAD;
|
||||
if (vp->v_type == VCHR)
|
||||
vp->v_rdev = lowervp->v_rdev;
|
||||
vp->v_data = lp;
|
||||
lp->ln_vp = vp;
|
||||
lp->ln_lowervp = lowervp;
|
||||
if (lowervp != NULL)
|
||||
vhold(lowervp);
|
||||
get_subject_lattr(curthread->td_proc, &subjlattr);
|
||||
lp->ln_flags = 0;
|
||||
lomac_plm_init_lomacfs_vnode(dvp, vp, cnp, &subjlattr);
|
||||
/* retrieve the just-initialized attributes */
|
||||
lobj.lo_type = LO_TYPE_LVNODE;
|
||||
lobj.lo_object.vnode = vp;
|
||||
get_object_lattr(&lobj, &objlattr);
|
||||
/* propogate the lattr to the underlying vnode */
|
||||
lobj.lo_type = LO_TYPE_UVNODE;
|
||||
lobj.lo_object.vnode = lowervp;
|
||||
set_object_lattr(&lobj, objlattr);
|
||||
#if defined(LOMAC_DEBUG_INCNAME)
|
||||
if (cnp == NULL)
|
||||
strncpy(lp->ln_name, "/", sizeof(lp->ln_name));
|
||||
else {
|
||||
strncpy(lp->ln_name, cnp->cn_nameptr, cnp->cn_namelen);
|
||||
lp->ln_name[cnp->cn_namelen] = '\0';
|
||||
}
|
||||
#endif
|
||||
error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_THISLAYER, td);
|
||||
if (error)
|
||||
panic("lomacfs_node_alloc: can't lock new vnode\n");
|
||||
if (cnp == NULL)
|
||||
vp->v_flag |= VROOT;
|
||||
else if (cnp->cn_flags & MAKEENTRY)
|
||||
cache_enter(dvp, vp, cnp);
|
||||
|
||||
#if defined(LOMAC_DEBUG_NODE_ALLOC)
|
||||
printf("lomacfs: made vp %p for lvp %p \"%.*s\" in dvp %p from %s\n",
|
||||
vp, lowervp, cnp ? (int)cnp->cn_namelen : 0,
|
||||
cnp ? cnp->cn_nameptr : "", dvp,
|
||||
lowervp != NULL ? lowervp->v_mount->mnt_stat.f_mntonname : "");
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
190
sys/contrib/lomac/lomacfs_vfsops.c
Normal file
190
sys/contrib/lomac/lomacfs_vfsops.c
Normal file
@ -0,0 +1,190 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: lomacfs_vfsops.c,v 1.16 2001/10/17 19:36:39 bfeldman Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include "lomacfs.h"
|
||||
#include "kernel_mediate.h"
|
||||
|
||||
MALLOC_DEFINE(M_LOMACFS, "LOMACFS", "LOMAC filesystem objects");
|
||||
|
||||
static int lomacfs_mount(struct mount *mp, char *path, caddr_t data,
|
||||
struct nameidata *ndp, struct thread *td);
|
||||
static int lomacfs_statfs(struct mount *mp, struct statfs *sbp,
|
||||
struct thread *td);
|
||||
static int lomacfs_unmount(struct mount *mp, int mntflags, struct thread *td);
|
||||
|
||||
static int
|
||||
lomacfs_mount(struct mount *mp, char *path, caddr_t data,
|
||||
struct nameidata *ndp, struct thread *td) {
|
||||
|
||||
if (mp->mnt_flag & MNT_UPDATE || VISLOMAC(mp->mnt_vnodecovered))
|
||||
return (EOPNOTSUPP);
|
||||
|
||||
mp->mnt_flag |= MNT_LOCAL;
|
||||
mp->mnt_flag &= ~MNT_RDONLY;
|
||||
mp->mnt_data = malloc(sizeof(struct lomac_mount), M_LOMACFS,
|
||||
M_WAITOK | M_ZERO);
|
||||
vfs_getnewfsid(mp);
|
||||
|
||||
strncpy(mp->mnt_stat.f_mntfromname, "lomacfs", MNAMELEN);
|
||||
(void)lomacfs_statfs(mp, &mp->mnt_stat, td);
|
||||
|
||||
/*
|
||||
* Keep around an extra ref for dounmount() to vrele() after the
|
||||
* VFS_UNMOUNT()... (who knows...)
|
||||
*/
|
||||
vref(mp->mnt_vnodecovered);
|
||||
if (VOP_ISLOCKED(mp->mnt_vnodecovered, NULL))
|
||||
VOP_UNLOCK(mp->mnt_vnodecovered, 0, td);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
lomacfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td) {
|
||||
struct statfs tmpstat;
|
||||
int error;
|
||||
|
||||
bzero(&tmpstat, sizeof(tmpstat));
|
||||
|
||||
error = VFS_STATFS(mp->mnt_vnodecovered->v_mount, &tmpstat, td);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
sbp->f_type = tmpstat.f_type;
|
||||
sbp->f_flags = tmpstat.f_flags;
|
||||
sbp->f_bsize = tmpstat.f_bsize;
|
||||
sbp->f_iosize = tmpstat.f_iosize;
|
||||
sbp->f_blocks = tmpstat.f_blocks;
|
||||
sbp->f_bfree = tmpstat.f_bfree;
|
||||
sbp->f_bavail = tmpstat.f_bavail;
|
||||
sbp->f_files = tmpstat.f_files;
|
||||
sbp->f_ffree = tmpstat.f_ffree;
|
||||
if (sbp != &mp->mnt_stat) {
|
||||
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
|
||||
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
|
||||
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
lomacfs_unmount(struct mount *mp, int mntflags, struct thread *td) {
|
||||
struct vnode *crootvp = VFSTOLOMAC(mp)->lm_rootvp;
|
||||
int error;
|
||||
int flags = 0;
|
||||
|
||||
if (mntflags & MNT_FORCE)
|
||||
flags |= FORCECLOSE;
|
||||
|
||||
if (VFSTOLOMAC(mp)->lm_flags & LM_TOOKROOT) {
|
||||
mtx_lock(&crootvp->v_interlock);
|
||||
crootvp->v_flag |= VROOT;
|
||||
mtx_unlock(&crootvp->v_interlock);
|
||||
}
|
||||
|
||||
error = vflush(mp, 1, flags); /* have an extra root ref */
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
free(VFSTOLOMAC(mp), M_LOMACFS);
|
||||
|
||||
/* bye, lomacfs. */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
lomacfs_root(struct mount *mp, struct vnode **vpp) {
|
||||
int error;
|
||||
|
||||
if (VFSTOLOMAC(mp)->lm_rootvp == NULL) {
|
||||
struct vnode *rootvp, *crootvp;
|
||||
|
||||
crootvp = mp->mnt_vnodecovered;
|
||||
error = lomacfs_node_alloc(mp, NULL, NULL, crootvp, &rootvp);
|
||||
if (error)
|
||||
return (error);
|
||||
/*
|
||||
* Reference twice to match the rest of the lomacfs vnodes.
|
||||
*/
|
||||
vref(crootvp);
|
||||
vref(crootvp);
|
||||
VFSTOLOMAC(mp)->lm_rootvp = rootvp;
|
||||
/*
|
||||
* This releases the lock on root, but it doesn't release
|
||||
* the reference so that root won't "disappear" until
|
||||
* unmount.
|
||||
*/
|
||||
error = VOP_UNLOCK(rootvp, 0, curthread);
|
||||
if (error)
|
||||
return (error);
|
||||
/*
|
||||
* This is some strange magic here... I need to pretend
|
||||
* that the mounted-on directory isn't a root vnode if I
|
||||
* want things like __getcwd() to just fail and not crash.
|
||||
*/
|
||||
mtx_lock(&crootvp->v_interlock);
|
||||
if (crootvp->v_flag & VROOT && crootvp == rootvnode) {
|
||||
crootvp->v_flag &= ~VROOT;
|
||||
VFSTOLOMAC(mp)->lm_flags |= LM_TOOKROOT;
|
||||
}
|
||||
mtx_unlock(&crootvp->v_interlock);
|
||||
}
|
||||
*vpp = VFSTOLOMAC(mp)->lm_rootvp;
|
||||
return (vget(*vpp, LK_EXCLUSIVE, curthread));
|
||||
}
|
||||
|
||||
static struct vfsops lomacfs_vfsops = {
|
||||
lomacfs_mount,
|
||||
vfs_stdstart,
|
||||
lomacfs_unmount,
|
||||
lomacfs_root,
|
||||
vfs_stdquotactl,
|
||||
lomacfs_statfs,
|
||||
vfs_stdsync,
|
||||
vfs_stdvget,
|
||||
vfs_stdfhtovp,
|
||||
vfs_stdcheckexp,
|
||||
vfs_stdvptofh,
|
||||
vfs_stdinit,
|
||||
vfs_stduninit,
|
||||
vfs_stdextattrctl
|
||||
};
|
||||
VFS_SET(lomacfs_vfsops, lomacfs, VFCF_LOOPBACK);
|
||||
MODULE_VERSION(lomacfs, 1);
|
||||
MODULE_DEPEND(lomacfs, lomac_plm, 1, 1, 1);
|
1141
sys/contrib/lomac/lomacfs_vnops.c
Normal file
1141
sys/contrib/lomac/lomacfs_vnops.c
Normal file
File diff suppressed because it is too large
Load Diff
49
sys/contrib/lomac/lomacio.h
Normal file
49
sys/contrib/lomac/lomacio.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: lomacio.h,v 1.4 2001/09/26 21:18:00 bfeldman Exp $
|
||||
*/
|
||||
#ifndef LOMACIO_H
|
||||
#define LOMACIO_H
|
||||
|
||||
#include <sys/ioccom.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
struct lomac_fioctl {
|
||||
char path[MAXPATHLEN];
|
||||
int level; /* LOMAC security level */
|
||||
};
|
||||
|
||||
struct lomac_fioctl2 {
|
||||
char path[MAXPATHLEN];
|
||||
int level; /* LOMAC security level */
|
||||
int flags;
|
||||
};
|
||||
|
||||
#define LIOGETPLEVEL _IOWR('L', 0, int) /* get process level */
|
||||
#define LIOGETFLEVEL _IOWR('L', 1, struct lomac_fioctl) /* get file level */
|
||||
#define LIOGETFLATTR _IOWR('L', 3, struct lomac_fioctl2) /* get file level */
|
||||
#define LIOPMAKELOWLEVEL _IO('L', 2) /* lower proc's level */
|
||||
#endif /* LOMACIO_H */
|
110
sys/contrib/lomac/policy_plm.h
Normal file
110
sys/contrib/lomac/policy_plm.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: policy_plm.h,v 1.20 2001/11/15 20:55:05 bfeldman Exp $
|
||||
*/
|
||||
|
||||
#ifndef LOMAC_PLM_H
|
||||
#define LOMAC_PLM_H
|
||||
|
||||
enum plm_level {
|
||||
LOW,
|
||||
SUBJ,
|
||||
HIGH
|
||||
};
|
||||
enum plm_flags {
|
||||
PLM_NOFLAGS, /* rule applies to this node and its children */
|
||||
PLM_CHILDOF /* rule applies to node's children, not the node */
|
||||
};
|
||||
#define LOWWRITE LN_ATTR_LOWWRITE
|
||||
#define LOWNOOPEN LN_ATTR_LOWNOOPEN
|
||||
#define NONETDEMOTE LN_ATTR_NONETDEMOTE
|
||||
#define NODEMOTE LN_ATTR_NODEMOTE
|
||||
|
||||
static u_int plm_levelflags_to_node_flags[3][2] = {
|
||||
{ LN_LOWEST_LEVEL, LN_INHERIT_LOW },
|
||||
{ LN_SUBJ_LEVEL, LN_INHERIT_SUBJ },
|
||||
{ LN_HIGHEST_LEVEL, LN_INHERIT_HIGH }
|
||||
};
|
||||
|
||||
typedef struct plm_rule {
|
||||
enum plm_level level; /* LOMAC level */
|
||||
enum plm_flags flags; /* flags for PLM evaluation */
|
||||
unsigned int attr; /* LN_ATTR_MASK of flags */
|
||||
const char *path; /* absolute path for this PLM rule */
|
||||
} plm_rule_t;
|
||||
|
||||
/* The `plm' array maps levels onto all of the files in the filesystem */
|
||||
static plm_rule_t plm[] = {
|
||||
{ HIGH, PLM_NOFLAGS, 0, "/" }, /* everything initially inherits high level */
|
||||
{ HIGH, PLM_CHILDOF, 0, "/" },
|
||||
{ HIGH, PLM_NOFLAGS, NONETDEMOTE, "/sbin/dhclient" },
|
||||
{ HIGH, PLM_CHILDOF, 0, "/var" },
|
||||
{ HIGH, PLM_CHILDOF, LOWWRITE, "/dev" },
|
||||
{ HIGH, PLM_NOFLAGS, LOWNOOPEN, "/dev/mdctl" },
|
||||
{ HIGH, PLM_NOFLAGS, LOWNOOPEN, "/dev/pci" },
|
||||
{ HIGH, PLM_NOFLAGS, LOWNOOPEN, "/dev/kmem" },
|
||||
{ HIGH, PLM_NOFLAGS, LOWNOOPEN, "/dev/mem" },
|
||||
{ HIGH, PLM_NOFLAGS, LOWNOOPEN, "/dev/io" },
|
||||
{ HIGH, PLM_CHILDOF, 0, "/etc" },
|
||||
{ HIGH, PLM_NOFLAGS, LOWWRITE, "/tmp" },
|
||||
{ SUBJ, PLM_CHILDOF, 0, "/tmp" },
|
||||
{ HIGH, PLM_NOFLAGS, 0, "/tmp/.X11-unix" },
|
||||
{ HIGH, PLM_CHILDOF, LOWWRITE, "/tmp/.X11-unix" },
|
||||
{ SUBJ, PLM_CHILDOF, 0, "/proc" },
|
||||
{ LOW, PLM_CHILDOF, 0, "/mnt" }, /* all nfs mounts are low */
|
||||
{ LOW, PLM_CHILDOF, 0, "/home" },
|
||||
{ HIGH, PLM_NOFLAGS, NONETDEMOTE, "/usr/bin/env-nonetdemote" },
|
||||
{ HIGH, PLM_NOFLAGS, NODEMOTE, "/usr/bin/env-nodemote" },
|
||||
{ LOW, PLM_CHILDOF, 0, "/usr/home" },
|
||||
{ LOW, PLM_CHILDOF, 0, "/var/lib" },
|
||||
{ HIGH, PLM_NOFLAGS, LOWWRITE, "/var/tmp" },
|
||||
{ SUBJ, PLM_CHILDOF, 0, "/var/tmp" },
|
||||
{ LOW, PLM_NOFLAGS, 0, "/var/tmp/vi.recover" },
|
||||
{ SUBJ, PLM_CHILDOF, 0, "/var/tmp/vi.recover" },
|
||||
{ HIGH, PLM_NOFLAGS, LOWWRITE, "/usr/tmp" },
|
||||
{ SUBJ, PLM_CHILDOF, 0, "/usr/tmp" },
|
||||
{ HIGH, PLM_NOFLAGS, 0, "/usr/tmp/.X11-unix" },
|
||||
{ HIGH, PLM_CHILDOF, LOWWRITE, "/usr/tmp/.X11-unix" },
|
||||
{ LOW, PLM_NOFLAGS, 0, "/var/mail" },
|
||||
{ LOW, PLM_CHILDOF, 0, "/var/mail" },
|
||||
{ LOW, PLM_NOFLAGS, 0, "/var/spool/mqueue" },
|
||||
{ LOW, PLM_CHILDOF, 0, "/var/spool/mqueue" },
|
||||
{ LOW, PLM_NOFLAGS, 0, "/dev/log" },
|
||||
{ HIGH, PLM_NOFLAGS, 0, "/home/ftp" },
|
||||
{ HIGH, PLM_NOFLAGS, 0, "/usr/home/ftp" },
|
||||
{ HIGH, PLM_NOFLAGS, 0, "/mnt/cdrom" }, /* cdrom is high */
|
||||
{ HIGH, PLM_NOFLAGS, 0, "/home/samba" },
|
||||
{ HIGH, PLM_NOFLAGS, 0, "/usr/home/samba" },
|
||||
{ LOW, PLM_NOFLAGS, 0, "/dev/printer" },
|
||||
{ HIGH, PLM_CHILDOF, 0, "/var/log" },
|
||||
{ LOW, PLM_NOFLAGS, 0, "/var/log/sendmail.st" },
|
||||
{ HIGH, PLM_NOFLAGS, LOWWRITE, "/var/run/utmp" },
|
||||
{ HIGH, PLM_NOFLAGS, LOWWRITE, "/var/log/lastlog" },
|
||||
{ HIGH, PLM_NOFLAGS, LOWWRITE, "/var/log/wtmp" },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
#endif /* LOMAC_PLM_H */
|
116
sys/contrib/lomac/syscall_gate.c
Normal file
116
sys/contrib/lomac/syscall_gate.c
Normal file
@ -0,0 +1,116 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: syscall_gate.c,v 1.4 2001/11/05 21:23:12 bfeldman Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sysent.h>
|
||||
|
||||
#include <machine/frame.h>
|
||||
|
||||
#include "syscall_gate.h"
|
||||
void syscall_gate_init(void);
|
||||
int syscall_gate(struct thread *td, caddr_t params);
|
||||
|
||||
static struct syscall_gate sg;
|
||||
|
||||
void
|
||||
syscall_gate_init(void) {
|
||||
|
||||
sg.sg_table = curthread->td_proc->p_sysent->sv_table;
|
||||
bzero(sg.sg_oldsyscalls, sizeof(sg.sg_oldsyscalls));
|
||||
}
|
||||
|
||||
int
|
||||
syscall_gate_register(int offset, sy_call_t *call, int narg, int mpsafe) {
|
||||
struct sysent *se;
|
||||
int error = 0;
|
||||
|
||||
if (offset <= 0 || offset >= SYS_MAXSYSCALL) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (sg.sg_oldsyscalls[offset].sy_call != NULL) {
|
||||
error = EEXIST;
|
||||
goto out;
|
||||
}
|
||||
se = &sg.sg_table[offset];
|
||||
sg.sg_oldsyscalls[offset] = *se;
|
||||
se->sy_call = (sy_call_t *)call;
|
||||
se->sy_narg = narg | (mpsafe ? SYF_MPSAFE : 0);
|
||||
out:
|
||||
return (error);
|
||||
}
|
||||
|
||||
void
|
||||
syscall_gate_deregister(int offset) {
|
||||
KASSERT(offset > 0 && offset < SYS_MAXSYSCALL, ("syscall offset %d out of range",
|
||||
offset));
|
||||
KASSERT(sg.sg_oldsyscalls[offset].sy_call != NULL, ("deregistering nonexistant syscall %d",
|
||||
offset));
|
||||
sg.sg_table[offset] = sg.sg_oldsyscalls[offset];
|
||||
sg.sg_oldsyscalls[offset].sy_call = NULL;
|
||||
sg.sg_oldsyscalls[offset].sy_narg = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
syscall_gate_modevent(module_t module, int event, void *unused) {
|
||||
int i;
|
||||
|
||||
switch ((enum modeventtype)event) {
|
||||
case MOD_LOAD:
|
||||
syscall_gate_init();
|
||||
break;
|
||||
case MOD_UNLOAD:
|
||||
for (i = 1; i < SYS_MAXSYSCALL; i++) {
|
||||
struct sysent *se;
|
||||
|
||||
se = &sg.sg_oldsyscalls[i];
|
||||
if (se->sy_call != NULL)
|
||||
sg.sg_table[i] = *se;
|
||||
}
|
||||
break;
|
||||
case MOD_SHUTDOWN:
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static moduledata_t syscall_gate_moduledata = {
|
||||
"syscall_gate",
|
||||
&syscall_gate_modevent,
|
||||
NULL
|
||||
};
|
||||
DECLARE_MODULE(syscall_gate, syscall_gate_moduledata, SI_SUB_DRIVERS, SI_ORDER_ANY);
|
||||
MODULE_VERSION(syscall_gate, 1);
|
47
sys/contrib/lomac/syscall_gate.h
Normal file
47
sys/contrib/lomac/syscall_gate.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: syscall_gate.h,v 1.2 2001/09/20 17:47:46 bfeldman Exp $
|
||||
*/
|
||||
|
||||
#ifndef SYSCALL_GATE_H
|
||||
#define SYSCALL_GATE_H
|
||||
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/sx.h>
|
||||
#include <sys/sysent.h>
|
||||
|
||||
#ifdef _KERNEL
|
||||
struct syscall_gate {
|
||||
struct sx sg_lock; /* syscalls entered into the kernel */
|
||||
struct sysent *sg_table;
|
||||
struct sysent sg_oldsyscalls[SYS_MAXSYSCALL];
|
||||
struct sysent sg_newsyscalls[SYS_MAXSYSCALL];
|
||||
};
|
||||
#endif /* _KERNEL */
|
||||
|
||||
int syscall_gate_register(int offset, sy_call_t *func, int nargs, int mpsafe);
|
||||
void syscall_gate_deregister(int offset);
|
||||
#endif /* SYSCALL_GATE_H */
|
Loading…
Reference in New Issue
Block a user