From owner-p4-projects@FreeBSD.ORG Fri Oct 10 19:04:00 2003 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 3D87F16A4C0; Fri, 10 Oct 2003 19:04:00 -0700 (PDT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id F3DFB16A4B3 for ; Fri, 10 Oct 2003 19:03:59 -0700 (PDT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 679FE43FDD for ; Fri, 10 Oct 2003 19:03:58 -0700 (PDT) (envelope-from cvance@nailabs.com) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.9/8.12.9) with ESMTP id h9B23wXJ049173 for ; Fri, 10 Oct 2003 19:03:58 -0700 (PDT) (envelope-from cvance@nailabs.com) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.9/8.12.9/Submit) id h9B23v9r049170 for perforce@freebsd.org; Fri, 10 Oct 2003 19:03:57 -0700 (PDT) (envelope-from cvance@nailabs.com) Date: Fri, 10 Oct 2003 19:03:57 -0700 (PDT) Message-Id: <200310110203.h9B23v9r049170@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to cvance@nailabs.com using -f From: Chris Vance To: Perforce Change Reviews Subject: PERFORCE change 39487 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 11 Oct 2003 02:04:00 -0000 http://perforce.freebsd.org/chv.cgi?CH=39487 Change 39487 by cvance@cvance_osx_laptop on 2003/10/10 19:03:16 Copy from sebsd branch, initial import Affected files ... .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/Makefile#2 edit .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/avc/av_inherit.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/avc/av_perm_to_string.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/avc/av_permissions.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/avc/avc.c#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/avc/avc.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/avc/avc_ss.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/avc/class_to_string.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/avc/common_perm_to_string.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/avc/initial_sid_to_string.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/flask.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/flask/Makefile#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/flask/README#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/flask/access_vectors#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/flask/initial_sids#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/flask/mkaccess_vector.sh#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/flask/mkflask.sh#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/flask/security_classes#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/flask_types.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/linux-compat.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/sebsd.c#2 edit .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/sebsd.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/sebsd_labels.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/sebsd_syscall.c#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/sebsd_syscalls.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/sebsd_sysctl.c#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/avtab.c#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/avtab.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/constraint.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/context.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/ebitmap.c#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/ebitmap.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/fileutils.c#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/fileutils.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/global.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/hashtab.c#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/hashtab.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/init.c#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/mls.c#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/mls.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/mls_types.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/policydb.c#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/policydb.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/queue.c#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/queue.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/security.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/services.c#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/services.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/services_private.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/sidtab.c#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/sidtab.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/symtab.c#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/ss/symtab.h#1 add Differences ... ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/Makefile#2 (text+ko) ==== @@ -7,22 +7,29 @@ include $(MakeInc_cmd) include $(MakeInc_def) -INSTINC_SUBDIRS = +EXPORT_ONLY_FILES = \ + sebsd.h \ + flask.h \ + flask_types.h \ + linux-compat.h + +INSTINC_SUBDIRS = avc ss INSTINC_SUBDIRS_PPC = ${INSTINC_SUBDIRS} INSTINC_SUBDIRS_I386 = ${INSTINC_SUBDIRS} -EXPINC_SUBDIRS = +EXPINC_SUBDIRS = avc ss EXPINC_SUBDIRS_PPC = ${EXPINC_SUBDIRS} EXPINC_SUBDIRS_I386 = ${EXPINC_SUBDIRS} INSTALL_MI_LIST = -INSTALL_MI_DIR = +INSTALL_MI_DIR = sebsd -EXPORT_MI_LIST = +EXPORT_MI_LIST = ${EXPORT_ONLY_FILES} -EXPORT_MI_DIR = +EXPORT_MI_DIR = sebsd +INCFLAGS_MAKEFILE= -I.. include $(MakeInc_rule) include $(MakeInc_dir) ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/security/sebsd/sebsd.c#2 (text+ko) ==== @@ -1,1 +1,2151 @@ -char *sebsd_id = "SEBSD Module"; +/*- + * Copyright (c) 2002, 2003 Networks Associates Technology, Inc. + * All rights reserved. + * + * This software was developed for the FreeBSD Project by NAI Labs, the + * Security Research Division of Network Associates, Inc. under + * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA + * CHATS research program. + * + * 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. The names of the authors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * 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. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include + +int sebsd_verbose = 0; + +static int slot; +#define SLOT(l) ((void *)LABEL_TO_SLOT((l), slot).l_ptr) + +MALLOC_DEFINE(M_SEBSD, "sebsd", "Security Enhanced BSD"); + +extern int ss_initialized; +static __inline int ss_precondition(void) +{ + return ss_initialized; +} + +static void +sebsd_init(struct mac_policy_conf *mpc) +{ + printf("sebsd:: init\n"); + avc_init(); + if (security_init()) { + panic("SEBSD: couldn't read policy file"); + } +} + +static void +sebsd_destroy(struct mac_policy_conf *mpc) +{ + + printf("sebsd:: destroy\n"); +} + +/* + * Check whether a task is allowed to use a capability. + */ +static int +cred_has_capability(struct ucred *cred, cap_value_t cap) +{ + struct task_security_struct *task; + struct avc_audit_data ad; + + task = SLOT(&cred->cr_label); + + AVC_AUDIT_DATA_INIT(&ad, CAP); + ad.u.cap = cap; + + return avc_has_perm_audit(task->sid, task->sid, + SECCLASS_CAPABILITY, cap, &ad); +} + +static int +cred_has_perm(struct ucred *cred, struct proc *proc, access_vector_t perm) +{ + struct task_security_struct *task, *target; + + task = SLOT(&cred->cr_label); + target = SLOT(&proc->p_ucred->cr_label); + + return (avc_has_perm_ref(task->sid, target->sid, SECCLASS_PROCESS, + perm, &target->avcr)); +} + +static int +mount_has_perm(struct ucred *cred, struct mount *mp, access_vector_t perm, + struct avc_audit_data *ad) +{ + struct mount_security_struct *sbsec; + struct task_security_struct *task; + + task = SLOT(&cred->cr_label); + sbsec = SLOT(&mp->mnt_mntlabel); + + return (avc_has_perm_audit(task->sid, sbsec->sid, SECCLASS_FILESYSTEM, + perm, ad)); +} + +static int +cred_has_system(struct ucred *cred, access_vector_t perm) +{ + struct task_security_struct *task; + + task = SLOT(&cred->cr_label); + + return (avc_has_perm(task->sid, SECINITSID_KERNEL, + SECCLASS_SYSTEM, perm, NULL, NULL)); +} + +static int +cred_has_security(struct ucred *cred, access_vector_t perm) +{ + struct task_security_struct *task; + + task = SLOT(&cred->cr_label); + + return (avc_has_perm(task->sid, SECINITSID_SECURITY, + SECCLASS_SECURITY, perm, NULL, NULL)); +} + +int +thread_has_system(struct thread *td, access_vector_t perm) +{ + + return (cred_has_system(td->td_proc->p_ucred, perm)); +} + +int +thread_has_security(struct thread *td, access_vector_t perm) +{ + + return (cred_has_security(td->td_proc->p_ucred, perm)); +} + +static __inline security_class_t +vnode_type_to_security_class(enum vtype vt) +{ + switch (vt) { + case VREG: + return SECCLASS_FILE; + case VDIR: + return SECCLASS_DIR; + case VBLK: + return SECCLASS_BLK_FILE; + case VCHR: + return SECCLASS_CHR_FILE; + case VLNK: + return SECCLASS_LNK_FILE; + case VSOCK: + return SECCLASS_SOCK_FILE; + case VFIFO: + return SECCLASS_FIFO_FILE; + case VNON: + case VBAD: + return SECCLASS_FILE; + } + + return SECCLASS_FILE; +} + +static __inline security_class_t +dirent_type_to_security_class(__uint8_t type) +{ + switch (type) { + case DT_REG: + return SECCLASS_FILE; + case DT_DIR: + return SECCLASS_DIR; + case DT_BLK: + return SECCLASS_BLK_FILE; + case DT_CHR: + return SECCLASS_CHR_FILE; + case DT_LNK: + return SECCLASS_LNK_FILE; + case DT_SOCK: + return SECCLASS_SOCK_FILE; + case DT_FIFO: + return SECCLASS_FIFO_FILE; + case DT_UNKNOWN: + case DT_WHT: + return SECCLASS_FILE; + } + + return SECCLASS_FILE; +} + +static __inline access_vector_t +file_mask_to_av(enum vtype vt, int mask) +{ + access_vector_t av = 0; + + if (vt != VDIR) { + if (mask & VEXEC) + av |= FILE__EXECUTE; + if (mask & VREAD) + av |= FILE__READ; + + if (mask & VAPPEND) + av |= FILE__APPEND; + else if (mask & VWRITE) + av |= FILE__WRITE; + + } else { + if (mask & VEXEC) + av |= DIR__SEARCH; + if (mask & VWRITE) + av |= DIR__WRITE; + if (mask & VREAD) + av |= DIR__READ; + } + + return av; +} + +static int +vnode_has_perm(struct ucred *cred, struct vnode *vp, access_vector_t perm, + struct avc_entry_ref *aeref) +{ + struct task_security_struct *task; + struct vnode_security_struct *file; + struct avc_audit_data ad; + + task = SLOT(&cred->cr_label); + file = SLOT(&vp->v_label); + + AVC_AUDIT_DATA_INIT(&ad, FS); + ad.u.fs.vp = vp; + + if (file->sclass == 0) { + struct vattr va; + VOP_GETATTR(vp, &va, curthread->td_ucred, curthread); + printf("vnode_has_perm:: ERROR, sid=%d, sclass=0, v_type=%d," + " inode=%ld, fsid=%d\n", + file->sid, vp->v_type, va.va_fileid, va.va_fsid); + file->sclass = vnode_type_to_security_class(vp->v_type); + if (file->sclass == 0) { + printf("vnode_has_perm:: Giving up\n"); + return 1; /* TBD: debugging */ + } + } + return avc_has_perm_ref_audit(task->sid, file->sid, file->sclass, + perm, aeref ? aeref : &file->avcr, &ad); +} + +static int +pipe_has_perm(struct ucred *cred, struct pipe *pipe, access_vector_t perm) +{ + struct task_security_struct *task; + struct vnode_security_struct *file; + + task = SLOT(&cred->cr_label); + file = SLOT(pipe->pipe_label); + + /* + * TBD: No audit information yet + */ + + return(avc_has_perm_ref(task->sid, file->sid, file->sclass, + perm, &file->avcr)); +} + +static void +sebsd_init_cred_label(struct label *label) +{ + struct task_security_struct *new_tsec; + + new_tsec = malloc(sizeof(*new_tsec), M_SEBSD, M_ZERO | M_WAITOK); + new_tsec->osid = new_tsec->sid = SECINITSID_UNLABELED; + SLOT(label) = new_tsec; +} + +static void +sebsd_init_file_label(struct label *label) +{ + struct file_security_struct *new_fsec; + + new_fsec = malloc(sizeof(*new_fsec), M_SEBSD, M_ZERO | M_WAITOK); + new_fsec->sid = new_fsec->sid = SECINITSID_UNLABELED; + SLOT(label) = new_fsec; +} + +static void +sebsd_init_mount_label(struct label *label) +{ + struct mount_security_struct *sbsec; + + sbsec = malloc(sizeof(*sbsec), M_SEBSD, M_ZERO | M_WAITOK); + sbsec->sid = SECINITSID_UNLABELED; + SLOT(label) = sbsec; +} + +static void +sebsd_init_mount_fs_label(struct label *label) +{ + struct mount_fs_security_struct *sbsec; + + sbsec = malloc(sizeof(*sbsec), M_SEBSD, M_ZERO | M_WAITOK); + sbsec->sid = SECINITSID_UNLABELED; + SLOT(label) = sbsec; +} + +static void +sebsd_init_network_label(struct label *label) +{ + struct network_security_struct *new; + + new = malloc(sizeof(*new), M_SEBSD, M_ZERO | M_WAITOK); + new->sid = new->task_sid = SECINITSID_UNLABELED; + SLOT(label) = new; +} + +static int +sebsd_init_network_label_waitcheck(struct label *label, int flag) +{ + struct network_security_struct *new; + + new = malloc(sizeof(*new), M_SEBSD, M_ZERO | flag); + if (new == NULL) { + SLOT(label) = NULL; + return (ENOMEM); + } + + new->sid = new->task_sid = SECINITSID_UNLABELED; + SLOT(label) = new; + + return (0); +} + +static void +sebsd_init_vnode_label(struct label *label) +{ + struct vnode_security_struct *vsec; + + vsec = malloc(sizeof(*vsec), M_SEBSD, M_ZERO | M_WAITOK); + vsec->sid = SECINITSID_UNLABELED; + vsec->task_sid = SECINITSID_UNLABELED; + SLOT(label) = vsec; +} + +static void +sebsd_destroy_label(struct label *label) +{ + + free(SLOT(label), M_SEBSD); + SLOT(label) = NULL; +} + +static void +sebsd_relabel_cred(struct ucred *cred, struct label *newlabel) +{ + + printf("sebsd_relabel_cred:: This does nothing\n"); +} + +static void +sebsd_associate_vnode_devfs(struct mount *mp, struct label *fslabel, + struct devfs_dirent *de, struct label *delabel, struct vnode *vp, + struct label *vlabel) +{ + struct vnode_security_struct *vsec, *dsec; + + dsec = SLOT(delabel); + vsec = SLOT(vlabel); + + vsec->sid = dsec->sid; + vsec->task_sid = dsec->task_sid; + vsec->sclass = dsec->sclass; + + /* + * This is a no-op for now, but when devfs_dirents do contain + * labels, they should be copied to the vp here as per how + * sebsd_update_vnode_from_extattr() functions. They will be + * kept synchronized from here on automatically with the vnode + * relabel calls. + */ +} + +static int +sebsd_associate_vnode_extattr(struct mount *mp, struct label *fslabel, + struct vnode *vp, struct label *vlabel) +{ + struct vnode_security_struct *vsec; + /* TBD: Need to limit size of contexts used in extattr labels */ + char context[128]; + u_int32_t context_len; + int error; + + vsec = SLOT(vlabel); + + context_len = sizeof(context); /* TBD: bad fixed length */ + error = vn_extattr_get(vp, IO_NODELOCKED, + SEBSD_MAC_EXTATTR_NAMESPACE, + SEBSD_MAC_EXTATTR_NAME, + &context_len, context, curthread); + if (error == ENOATTR || error == EOPNOTSUPP) { + vsec->sid = SECINITSID_UNLABELED; /* Use the default label */ + + /* + struct vattr va; + + (void)VOP_GETATTR(vp, &va, curthread->td_ucred, curthread); + printf("sebsd_update_vnode_from_extattr: no label for " + "inode=%ld, fsid=%d\n", va.va_fileid, va.va_fsid); + */ + goto dosclass; + } + if (error) { + printf("sebsd_update_vnode_from_extattr: ERROR %d returned " + " by vn_extattr_get()\n", error); + return (error); /* Fail closed */ + } + if (sebsd_verbose > 1) { + struct vattr va; + + VOP_GETATTR(vp, &va, curthread->td_ucred, curthread); + printf("sebsd_vnode_from_extattr: len=%d: context=%.*s " + "inode=%ld, fsid=%d\n", context_len, context_len, + context, va.va_fileid, va.va_fsid); + } + + error = security_context_to_sid(context, context_len, &vsec->sid); + if (error) { + printf("sebsd_update_vnode_from_extattr: ERROR mapping " + "context to sid: %.*s\n", context_len, context); + return (0); /* TBD bad, bad, bad */ + } + +dosclass: + /* TBD: */ + vsec->sclass = vnode_type_to_security_class(vp->v_type); + if (vsec->sclass == 0) { + printf("sebsd_update_vnode_from_extattr:: sclass is 0\n"); + } + + return (0); +} + +static void +sebsd_associate_vnode_singlelabel(struct mount *mp, struct label *fslabel, + struct vnode *vp, struct label *vlabel) +{ + struct mount_fs_security_struct *sbsec; + struct vnode_security_struct *vsec; + + sbsec = SLOT(fslabel); + vsec = SLOT(vlabel); + vsec->sid = sbsec->sid; + vsec->sclass = vnode_type_to_security_class(vp->v_type); +} + +static void +sebsd_create_cred(struct ucred *cred_parent, struct ucred *cred_child) +{ + int rc; + struct task_security_struct *parent, *task; + + rc = ss_precondition(); + if (rc <= 0) + return; + + parent = SLOT(&cred_parent->cr_label); + task = SLOT(&cred_child->cr_label); + + /* Default to using the attributes from the parent process */ + task->osid = parent->osid; + task->sid = parent->sid; + + return; +} + +static void +sebsd_create_file(struct ucred *cred, struct file *fp, struct label *label) +{ + struct task_security_struct *tsec; + struct file_security_struct *fsec; + + tsec = SLOT(&cred->cr_label); + fsec = SLOT(label); + + fsec->sid = tsec->sid; +} + +static void +sebsd_create_devfs_device(struct ucred *cr, struct mount *mp, dev_t dev, + struct devfs_dirent *devfs_dirent, struct label *label, + const char *fullpath) +{ + char *path; + int rc; + security_id_t newsid; + struct mount_security_struct *sbsec; + struct vnode_security_struct *dirent; + + dirent = SLOT(label); + sbsec = SLOT(&mp->mnt_mntlabel); + + /* Default to the filesystem SID. */ + dirent->sid = sbsec->sid; + dirent->task_sid = SECINITSID_KERNEL; + dirent->sclass = + dirent_type_to_security_class(devfs_dirent->de_dirent->d_type); + + /* Obtain a SID based on the fstype, path, and class. */ + path = malloc(strlen(fullpath) + 2, M_SEBSD, M_ZERO | M_WAITOK); + path[0] = '/'; + strcpy(&path[1], fullpath); + rc = security_genfs_sid(mp->mnt_vfc->vfc_name, path, dirent->sclass, + &newsid); + + if (rc == 0) + dirent->sid = newsid; + + /* If there was a creating process (currently only for /dev/pty*), + try a type_transition rule. */ + if (cr != NULL) { + struct task_security_struct *task = SLOT(&cr->cr_label); + + /* XXX: uses the type specified by genfs instead of the parent directory + like it should! */ + int error = security_transition_sid(task->sid, dirent->sid, dirent->sclass, + &newsid); + if (error == 0) + dirent->sid = newsid; + } + + /* TBD: debugging */ + if (sebsd_verbose > 1) { + printf("sebsd_create_devfs_device(%s): sbsid=%d, " + "mountpoint=%s, rc=%d, sclass=%d, computedsid=%d, " + "dirent=%d\n", path, sbsec->sid, mp->mnt_stat.f_mntonname, + rc, dirent->sclass, newsid, dirent->sid); + } + free(path, M_SEBSD); +} + +static void +sebsd_create_devfs_directory(struct mount *mp, char *dirname, + int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label, + const char *fullpath) +{ + char *path; + int rc; + security_id_t newsid; + struct mount_security_struct *sbsec; + struct vnode_security_struct *dirent; + + dirent = SLOT(label); + sbsec = SLOT(&mp->mnt_mntlabel); + + /* Default to the filesystem SID. */ + dirent->sid = sbsec->sid; + dirent->task_sid = SECINITSID_KERNEL; + dirent->sclass = SECCLASS_DIR; + + /* Obtain a SID based on the fstype, path, and class. */ + path = malloc(strlen(fullpath) + 2, M_SEBSD, M_ZERO | M_WAITOK); + path[0] = '/'; + strcpy(&path[1], fullpath); + rc = security_genfs_sid(mp->mnt_vfc->vfc_name, path, dirent->sclass, + &newsid); + if (rc == 0) + dirent->sid = newsid; + + /* TBD: debugging */ + if (sebsd_verbose > 1) { + printf("%s(%s): sbsid=%d, mountpoint=%s, " + "rc=%d, sclass=%d, computedsid=%d, dirent=%d\n", + __func__, path, sbsec->sid, mp->mnt_stat.f_mntonname, rc, + dirent->sclass, newsid, dirent->sid); + } + free(path, M_SEBSD); +} + +static void +sebsd_create_devfs_symlink(struct ucred *cred, struct mount *mp, + struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de, + struct label *delabel, const char *fullpath) +{ + + char *path; + int rc; + security_id_t newsid; + struct vnode_security_struct *lnksec; + struct vnode_security_struct *dirsec; + struct mount_security_struct *sbsec; + + /* TBD: Should probably be checking MAY_LINK/MAY_CREATE perms here */ + + dirsec = SLOT(ddlabel); + lnksec = SLOT(delabel); + sbsec = SLOT(&mp->mnt_mntlabel); + + /* Default to the filesystem SID. */ + lnksec->sid = dirsec->sid; + lnksec->task_sid = SECINITSID_KERNEL; + lnksec->sclass = SECCLASS_LNK_FILE; + + /* Obtain a SID based on the fstype, path, and class. */ + path = malloc(strlen(fullpath) + 2, M_SEBSD, M_ZERO | M_WAITOK); + path[0] = '/'; + strcpy(&path[1], fullpath); + rc = security_genfs_sid(mp->mnt_vfc->vfc_name, path, lnksec->sclass, + &newsid); + if (rc == 0) + lnksec->sid = newsid; + + if (sebsd_verbose > 1) { + printf("%s(%s): sbsid=%d, mountpoint=%s, rc=%d, sclass=%d, " + "computedsid=%d, dirent=%d\n", __func__, path, + sbsec->sid, mp->mnt_stat.f_mntonname, rc, + lnksec->sclass, newsid, lnksec->sid); + } + free(path, M_SEBSD); +} + +/* + * Use the allocating task SID to label pipes. On Linux, pipes reside + * in a pseudo filesystem. + */ +static void +sebsd_create_pipe(struct ucred *cred, struct pipe *pipe, + struct label *pipelabel) +{ + struct task_security_struct *tsec; + struct vnode_security_struct *vsec; + + tsec = SLOT(&cred->cr_label); + vsec = SLOT(pipelabel); + + vsec->sid = vsec->task_sid = tsec->sid; + vsec->sclass = SECCLASS_FIFO_FILE; +} + +static void +sebsd_create_proc0(struct ucred *cred) +{ + struct task_security_struct *task; + + task = SLOT(&cred->cr_label); + task->osid = task->sid = SECINITSID_KERNEL; + printf("sebsd_create_proc0:: using SECINITSID_KERNEL = %d\n", + SECINITSID_KERNEL); +} + +static void +sebsd_create_proc1(struct ucred *cred) +{ + struct task_security_struct *task; + + task = SLOT(&cred->cr_label); + task->osid = SECINITSID_KERNEL; + task->sid = SECINITSID_INIT; + printf("sebsd_create_proc1:: using SICINITSID_INIT = %d\n", + SECINITSID_INIT); +} + +static void +sebsd_create_mount(struct ucred *cred, struct mount *mp, + struct label *mntlabel, struct label *fslabel, struct label *mount_arg_label) +{ + struct mount_security_struct *sbsec, *mntsec; + struct mount_fs_security_struct *sbfssec; + int behavior, rc; + + sbsec = SLOT(mntlabel); + sbfssec = SLOT(fslabel); + /* TBD TBD TBD */ + /* + * Make the label for the filesystem the same as the singlelabel + * which the filesystem will use if not a "multilabel" type. + */ + rc = security_fs_use(mp->mnt_vfc->vfc_name, &behavior, &sbsec->sid); + if (rc) { + printf("sebsd_create_mount: security_fs_use(%s) returned %d\n", + mp->mnt_vfc->vfc_name, rc); + behavior = SECURITY_FS_USE_NONE; + } else { + sbfssec->sid = sbsec->sid; + /* TBD: debugging only */ + printf("sebsd_create_mount: security_fs_use(%s) behavior %d, sid %d\n", + mp->mnt_vfc->vfc_name, behavior, sbsec->sid); + } + + switch (behavior) { + case SECURITY_FS_USE_XATTR: + /* PSIDs only work for persistent file systems with + unique and persistent inode numbers. */ + sbsec->uses_psids = 1; + + /* + * TBD: need to correctly label mountpoint with persistent + * label at this point (currently vnode is unavailable) + */ + + break; + case SECURITY_FS_USE_TRANS: + /* Transition SIDs are used for pseudo filesystems like + devpts and tmpfs where you want the SID to be derived + from the SID of the creating process and the SID of + the filesystem. */ + sbsec->uses_trans = 1; + break; + case SECURITY_FS_USE_TASK: + /* Task SIDs are used for pseudo filesystems like pipefs + and sockfs where you want the objects to be labeled + with the SID of the creating process. */ + sbsec->uses_task = 1; + break; + case SECURITY_FS_USE_GENFS: + /* genfs_contexts handles everything else, like devfs, + usbdevfs, driverfs, and portions of proc. */ + sbsec->uses_genfs = 1; + break; + case SECURITY_FS_USE_NONE: + /* No labeling support configured for this filesystem type. + Don't appear to require labeling for binfmt_misc, bdev, + or rootfs. */ + break; + default: + printf("%s: security_fs_use(%s) returned unrecognized " + "behavior %d\n", __FUNCTION__, mp->mnt_vfc->vfc_name, + behavior); + behavior = SECURITY_FS_USE_NONE; + break; + } + + if (mount_arg_label) { + mntsec = SLOT(mount_arg_label); + sbsec->sid = mntsec->sid; + } +} + +/* + * Initialize the SEBSD security server after the root partition has + * been mounted; policy is located on root partition. + */ +static void +sebsd_create_root_mount(struct ucred *cred, struct mount *mp, + struct label *mntlabel, struct label *fslabel) +{ + struct vnode *vp, *nvp; + + /* + * Go through all open vnodes and reload their labels. + */ + mtx_lock(&mntvnode_mtx); + vp = TAILQ_FIRST(&mp->mnt_nvnodelist); + do { + nvp = TAILQ_NEXT(vp, v_nmntvnodes); + VI_LOCK(vp); + mtx_unlock(&mntvnode_mtx); + vn_lock(vp, LK_INTERLOCK | LK_EXCLUSIVE | LK_RETRY, curthread); + (void)sebsd_associate_vnode_extattr(mp, fslabel, vp, + &vp->v_label); + VOP_UNLOCK(vp, 0, curthread); + mtx_lock(&mntvnode_mtx); + vp = nvp; + } while (vp != NULL); + mtx_unlock(&mntvnode_mtx); +} + +static int +sebsd_create_vnode_extattr(struct ucred *cred, struct mount *mp, + struct label *fslabel, struct vnode *parent, struct label *parentlabel, + struct vnode *child, struct label *childlabel, struct componentname *cnp) +{ + struct vnode_security_struct *dir, *vsec; + struct task_security_struct *task; + security_context_t context; + u_int32_t context_len; + security_id_t newsid; + int error; + int tclass; + + task = SLOT(&cred->cr_label); + dir = SLOT(parentlabel); + vsec = SLOT(childlabel); + tclass = vnode_type_to_security_class (child->v_type); + + error = security_transition_sid(task->sid, dir->sid, tclass, + &newsid); + if (error) + return (error); + + vsec->sid = newsid; + vsec->task_sid = task->sid; + vsec->sclass = tclass; + + /* store label in vnode */ + error = security_sid_to_context(vsec->sid, &context, + &context_len); + if (error) + return (error); + + error = vn_extattr_set(child, IO_NODELOCKED, + SEBSD_MAC_EXTATTR_NAMESPACE, + SEBSD_MAC_EXTATTR_NAME, + context_len, context, curthread); + + security_free_context(context); + return (error); +} + +static int +sebsd_check_cap (struct ucred *cred, cap_value_t capv) +{ + return cred_has_capability (cred, capv); +} + +/* + * SEBSD does not support the relabeling of processes without + * transitioning. + */ +static int +sebsd_check_cred_relabel(struct ucred *cred, struct label *newlabel) +{ + struct task_security_struct *nsec, *tsec; + + nsec = SLOT(newlabel); + tsec = SLOT(&cred->cr_label); + if (nsec != NULL && nsec->sid != tsec->sid) + return EPERM; + return 0; +} + +static int +sebsd_check_mount (struct ucred *cred, struct vnode *vp, struct label *vl, + const char *vfc_name, struct label *mntlabel) +{ + int rc; + security_id_t sid; + int behavior; + struct vnode_security_struct *vsec; + struct task_security_struct *task; + struct mount_security_struct *sbsec; + + vsec = SLOT(vl); + task = SLOT(&cred->cr_label); + + rc = vnode_has_perm (cred, vp, FILE__MOUNTON, NULL); + if (rc) + return rc; + + if (mntlabel) { + sbsec = SLOT(mntlabel); + sid = sbsec->sid; + + rc = avc_has_perm_ref_audit (task->sid, sid, SECCLASS_FILE, + COMMON_FILE__RELABELTO, NULL, NULL); + if (rc) + return rc; + } + else { + rc = security_fs_use (vfc_name, &behavior, &sid); + if (rc) + return rc; >>> TRUNCATED FOR MAIL (1000 lines) <<<