veriexec: Additional functionality for MAC/veriexec
Ensure veriexec opens the file before doing any read operations. When the MAC_VERIEXEC_CHECK_PATH_SYSCALL syscall is requested, veriexec needs to open the file before calling mac_veriexec_check_vp. This is to ensure any set up is done by the file system. Most file systems do not explicitly need an open, but some (e.g. virtfs) require initialization of access tokens (file identifiers, etc.) before doing any read or write operations. The evaluate_fingerprint() function needs to ensure it has an open file for reading in order to evaluate the fingerprint. The ideal solution is to have a hook after the VOP_OPEN call in vn_open. For now, we open the file for reading, envaluate the fingerprint, and close the file. While this leaves a potential hole that could possibly be taken advantage of by a dedicated aversary, this code path is not typically visited often in our use cases, as we primarily encounter verified mounts and not individual files. This should be considered a temporary workaround until discussions about the post-open hook have concluded and the hook becomes available. Add MAC_VERIEXEC_GET_PARAMS_PATH_SYSCALL and MAC_VERIEXEC_GET_PARAMS_PID_SYSCALL to mac_veriexec_syscall so we can fetch and check label contents in an unconstrained manner. Add a check for PRIV_VERIEXEC_CONTROL to do ioctl on /dev/veriexec Make it clear that trusted process cannot be debugged. Attempts to debug a trusted process already fail, but the failure path is very obscure. Add an explicit check for VERIEXEC_TRUSTED in mac_veriexec_proc_check_debug. We need mac_veriexec_priv_check to not block PRIV_KMEM_WRITE if mac_priv_gant() says it is ok. Reviewed by: sjg Obtained from: Juniper Networks, Inc.
This commit is contained in:
parent
4654ba28fb
commit
8512d82ea0
@ -8,7 +8,9 @@ INCS= libveriexec.h
|
|||||||
|
|
||||||
WARNS?= 2
|
WARNS?= 2
|
||||||
|
|
||||||
SRCS= veriexec_check.c
|
SRCS= \
|
||||||
|
veriexec_check.c \
|
||||||
|
veriexec_get.c
|
||||||
|
|
||||||
.include <bsd.lib.mk>
|
.include <bsd.lib.mk>
|
||||||
|
|
||||||
|
@ -29,9 +29,17 @@
|
|||||||
#ifndef __LIBVERIEXEC_H__
|
#ifndef __LIBVERIEXEC_H__
|
||||||
#define __LIBVERIEXEC_H__
|
#define __LIBVERIEXEC_H__
|
||||||
|
|
||||||
|
struct mac_veriexec_syscall_params;
|
||||||
|
|
||||||
int veriexec_check_fd_mode(int, unsigned int);
|
int veriexec_check_fd_mode(int, unsigned int);
|
||||||
int veriexec_check_path_mode(const char *, unsigned int);
|
int veriexec_check_path_mode(const char *, unsigned int);
|
||||||
int veriexec_check_fd(int);
|
int veriexec_check_fd(int);
|
||||||
int veriexec_check_path(const char *);
|
int veriexec_check_path(const char *);
|
||||||
|
int veriexec_get_pid_params(pid_t, struct mac_veriexec_syscall_params *);
|
||||||
|
int veriexec_get_path_params(const char *,
|
||||||
|
struct mac_veriexec_syscall_params *);
|
||||||
|
int veriexec_check_pid_label(pid_t, const char *);
|
||||||
|
|
||||||
|
#define HAVE_VERIEXEC_CHECK_PID_LABEL 1
|
||||||
|
|
||||||
#endif /* __LIBVERIEXEC_H__ */
|
#endif /* __LIBVERIEXEC_H__ */
|
||||||
|
184
lib/libveriexec/veriexec_get.c
Normal file
184
lib/libveriexec/veriexec_get.c
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
/*-
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021-2023, Juniper Networks, 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 ``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 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <sys/mac.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <security/mac_veriexec/mac_veriexec.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get veriexec params for a process
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @li 0 if successful
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
veriexec_get_pid_params(pid_t pid,
|
||||||
|
struct mac_veriexec_syscall_params *params)
|
||||||
|
{
|
||||||
|
struct mac_veriexec_syscall_params_args args;
|
||||||
|
|
||||||
|
if (params == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
args.u.pid = pid;
|
||||||
|
args.params = params;
|
||||||
|
return mac_syscall(MAC_VERIEXEC_NAME,
|
||||||
|
MAC_VERIEXEC_GET_PARAMS_PID_SYSCALL, &args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get veriexec params for a process
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @li 0 if successful
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
veriexec_get_path_params(const char *file,
|
||||||
|
struct mac_veriexec_syscall_params *params)
|
||||||
|
{
|
||||||
|
struct mac_veriexec_syscall_params_args args;
|
||||||
|
|
||||||
|
if (file == NULL || params == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
args.u.filename = file;
|
||||||
|
args.params = params;
|
||||||
|
return mac_syscall(MAC_VERIEXEC_NAME,
|
||||||
|
MAC_VERIEXEC_GET_PARAMS_PATH_SYSCALL, &args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief check if label contains what we want
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @li 0 if no
|
||||||
|
* @li 1 if yes
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
veriexec_check_pid_label(pid_t pid, const char *want)
|
||||||
|
{
|
||||||
|
struct mac_veriexec_syscall_params params;
|
||||||
|
char *cp;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
if (want != NULL &&
|
||||||
|
veriexec_get_pid_params(pid, ¶ms) == 0) {
|
||||||
|
/* Does label contain [,]<want>[,] ? */
|
||||||
|
if (params.labellen > 0 &&
|
||||||
|
(cp = strstr(params.label, want)) != NULL) {
|
||||||
|
if (cp == params.label || cp[-1] == ',') {
|
||||||
|
n = strlen(want);
|
||||||
|
if (cp[n] == '\0' || cp[n] == ',')
|
||||||
|
return 1; /* yes */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0; /* no */
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef UNIT_TEST
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <err.h>
|
||||||
|
|
||||||
|
static char *
|
||||||
|
hash2hex(char *type, unsigned char *digest)
|
||||||
|
{
|
||||||
|
static char buf[2*MAXFINGERPRINTLEN+1];
|
||||||
|
size_t n;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (strcmp(type, "SHA1") == 0) {
|
||||||
|
n = 20;
|
||||||
|
} else if (strcmp(type, "SHA256") == 0) {
|
||||||
|
n = 32;
|
||||||
|
} else if (strcmp(type, "SHA384") == 0) {
|
||||||
|
n = 48;
|
||||||
|
}
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
sprintf(&buf[2*i], "%02x", (unsigned)digest[i]);
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct mac_veriexec_syscall_params params;
|
||||||
|
pid_t pid;
|
||||||
|
char *want = NULL;
|
||||||
|
int pflag = 0;
|
||||||
|
int error;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
while ((c = getopt(argc, argv, "pw:")) != -1) {
|
||||||
|
switch (c) {
|
||||||
|
case 'p':
|
||||||
|
pflag = 1;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
want = optarg;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (; optind < argc; optind++) {
|
||||||
|
|
||||||
|
if (pflag) {
|
||||||
|
pid = atoi(argv[optind]);
|
||||||
|
if (want) {
|
||||||
|
error = veriexec_check_pid_label(pid, want);
|
||||||
|
printf("pid=%d want='%s': %d\n",
|
||||||
|
pid, want, error);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
error = veriexec_get_pid_params(pid, ¶ms);
|
||||||
|
} else {
|
||||||
|
error = veriexec_get_path_params(argv[optind], ¶ms);
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
err(2, "%s, error=%d", argv[optind], error);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("arg=%s, type=%s, flags=%u, label='%s', fingerprint='%s'\n",
|
||||||
|
argv[optind], params.fp_type, (unsigned)params.flags,
|
||||||
|
params.label,
|
||||||
|
hash2hex(params.fp_type, params.fingerprint));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* $FreeBSD$
|
* $FreeBSD$
|
||||||
*
|
*
|
||||||
* Copyright (c) 2011-2013, 2015, 2019, Juniper Networks, Inc.
|
* Copyright (c) 2011-2023, Juniper Networks, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -34,11 +34,8 @@
|
|||||||
#ifndef _DEV_VERIEXEC_VERIEXEC_IOCTL_H
|
#ifndef _DEV_VERIEXEC_VERIEXEC_IOCTL_H
|
||||||
#define _DEV_VERIEXEC_VERIEXEC_IOCTL_H
|
#define _DEV_VERIEXEC_VERIEXEC_IOCTL_H
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <security/mac_veriexec/mac_veriexec.h>
|
#include <security/mac_veriexec/mac_veriexec.h>
|
||||||
|
|
||||||
#define VERIEXEC_FPTYPELEN 16
|
|
||||||
|
|
||||||
struct verified_exec_params {
|
struct verified_exec_params {
|
||||||
unsigned char flags;
|
unsigned char flags;
|
||||||
char fp_type[VERIEXEC_FPTYPELEN]; /* type of fingerprint */
|
char fp_type[VERIEXEC_FPTYPELEN]; /* type of fingerprint */
|
||||||
|
@ -99,7 +99,7 @@ verifiedexecioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
|
|||||||
*
|
*
|
||||||
* MAC/veriexec will grant kmem write privs to "trusted" processes.
|
* MAC/veriexec will grant kmem write privs to "trusted" processes.
|
||||||
*/
|
*/
|
||||||
error = priv_check(td, PRIV_KMEM_WRITE);
|
error = priv_check(td, PRIV_VERIEXEC_CONTROL);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*-
|
/*-
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*
|
*
|
||||||
* Copyright (c) 2011, 2012, 2013, 2015, 2016, 2019 Juniper Networks, Inc.
|
* Copyright (c) 2011-2023 Juniper Networks, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -330,7 +330,10 @@ mac_veriexec_proc_check_debug(struct ucred *cred, struct proc *p)
|
|||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
return ((flags & VERIEXEC_NOTRACE) ? EACCES : 0);
|
error = (flags & (VERIEXEC_NOTRACE|VERIEXEC_TRUSTED)) ? EACCES : 0;
|
||||||
|
MAC_VERIEXEC_DBG(4, "%s flags=%#x error=%d", __func__, flags, error);
|
||||||
|
|
||||||
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -406,6 +409,9 @@ mac_veriexec_kld_check_load(struct ucred *cred, struct vnode *vp,
|
|||||||
* - PRIV_KMEM_WRITE\n
|
* - PRIV_KMEM_WRITE\n
|
||||||
* Check if writes to /dev/mem and /dev/kmem are allowed\n
|
* Check if writes to /dev/mem and /dev/kmem are allowed\n
|
||||||
* (Only trusted processes are allowed)
|
* (Only trusted processes are allowed)
|
||||||
|
* - PRIV_VERIEXEC_CONTROL\n
|
||||||
|
* Check if manipulating veriexec is allowed\n
|
||||||
|
* (only trusted processes are allowed)
|
||||||
*
|
*
|
||||||
* @param cred credentials to use
|
* @param cred credentials to use
|
||||||
* @param priv privilege to check
|
* @param priv privilege to check
|
||||||
@ -415,20 +421,30 @@ mac_veriexec_kld_check_load(struct ucred *cred, struct vnode *vp,
|
|||||||
static int
|
static int
|
||||||
mac_veriexec_priv_check(struct ucred *cred, int priv)
|
mac_veriexec_priv_check(struct ucred *cred, int priv)
|
||||||
{
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
/* If we are not enforcing veriexec, nothing for us to check */
|
/* If we are not enforcing veriexec, nothing for us to check */
|
||||||
if ((mac_veriexec_state & VERIEXEC_STATE_ENFORCE) == 0)
|
if ((mac_veriexec_state & VERIEXEC_STATE_ENFORCE) == 0)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
error = 0;
|
||||||
switch (priv) {
|
switch (priv) {
|
||||||
case PRIV_KMEM_WRITE:
|
case PRIV_KMEM_WRITE:
|
||||||
if (!mac_veriexec_proc_is_trusted(cred, curproc))
|
case PRIV_VERIEXEC_CONTROL:
|
||||||
return (EPERM);
|
/*
|
||||||
|
* Do not allow writing to memory or manipulating veriexec,
|
||||||
|
* unless trusted
|
||||||
|
*/
|
||||||
|
if (mac_veriexec_proc_is_trusted(cred, curproc) == 0 &&
|
||||||
|
mac_priv_grant(cred, priv) != 0)
|
||||||
|
error = EPERM;
|
||||||
|
MAC_VERIEXEC_DBG(4, "%s priv=%d error=%d", __func__, priv,
|
||||||
|
error);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return (0);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -812,7 +828,24 @@ mac_veriexec_syscall(struct thread *td, int call, void *arg)
|
|||||||
cap_rights_t rights;
|
cap_rights_t rights;
|
||||||
struct vattr va;
|
struct vattr va;
|
||||||
struct file *fp;
|
struct file *fp;
|
||||||
int error;
|
struct mac_veriexec_syscall_params_args pargs;
|
||||||
|
struct mac_veriexec_syscall_params result;
|
||||||
|
struct mac_veriexec_file_info *ip;
|
||||||
|
struct proc *proc;
|
||||||
|
struct vnode *textvp;
|
||||||
|
int error, flags, proc_locked;
|
||||||
|
|
||||||
|
nd.ni_vp = NULL;
|
||||||
|
proc_locked = 0;
|
||||||
|
textvp = NULL;
|
||||||
|
switch (call) {
|
||||||
|
case MAC_VERIEXEC_GET_PARAMS_PID_SYSCALL:
|
||||||
|
case MAC_VERIEXEC_GET_PARAMS_PATH_SYSCALL:
|
||||||
|
error = copyin(arg, &pargs, sizeof(pargs));
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (call) {
|
switch (call) {
|
||||||
case MAC_VERIEXEC_CHECK_FD_SYSCALL:
|
case MAC_VERIEXEC_CHECK_FD_SYSCALL:
|
||||||
@ -863,18 +896,69 @@ mac_veriexec_syscall(struct thread *td, int call, void *arg)
|
|||||||
NDINIT(&nd, LOOKUP,
|
NDINIT(&nd, LOOKUP,
|
||||||
FOLLOW | LOCKLEAF | LOCKSHARED | AUDITVNODE1,
|
FOLLOW | LOCKLEAF | LOCKSHARED | AUDITVNODE1,
|
||||||
UIO_USERSPACE, arg);
|
UIO_USERSPACE, arg);
|
||||||
error = namei(&nd);
|
flags = FREAD;
|
||||||
|
error = vn_open(&nd, &flags, 0, NULL);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
break;
|
break;
|
||||||
NDFREE_PNBUF(&nd);
|
NDFREE_PNBUF(&nd);
|
||||||
|
|
||||||
/* Check the fingerprint status of the vnode */
|
/* Check the fingerprint status of the vnode */
|
||||||
error = mac_veriexec_check_vp(td->td_ucred, nd.ni_vp, VVERIFY);
|
error = mac_veriexec_check_vp(td->td_ucred, nd.ni_vp, VVERIFY);
|
||||||
vput(nd.ni_vp);
|
/* nd.ni_vp cleaned up below */
|
||||||
|
break;
|
||||||
|
case MAC_VERIEXEC_GET_PARAMS_PID_SYSCALL:
|
||||||
|
if (pargs.u.pid == 0 || pargs.u.pid == curproc->p_pid) {
|
||||||
|
proc = curproc;
|
||||||
|
} else {
|
||||||
|
proc = pfind(pargs.u.pid);
|
||||||
|
if (proc == NULL)
|
||||||
|
return (EINVAL);
|
||||||
|
proc_locked = 1;
|
||||||
|
}
|
||||||
|
textvp = proc->p_textvp;
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
case MAC_VERIEXEC_GET_PARAMS_PATH_SYSCALL:
|
||||||
|
if (textvp == NULL) {
|
||||||
|
/* Look up the path to get the vnode */
|
||||||
|
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1,
|
||||||
|
UIO_USERSPACE, pargs.u.filename);
|
||||||
|
flags = FREAD;
|
||||||
|
error = vn_open(&nd, &flags, 0, NULL);
|
||||||
|
if (error != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
NDFREE_PNBUF(&nd);
|
||||||
|
textvp = nd.ni_vp;
|
||||||
|
}
|
||||||
|
error = VOP_GETATTR(textvp, &va, curproc->p_ucred);
|
||||||
|
if (proc_locked)
|
||||||
|
PROC_UNLOCK(proc);
|
||||||
|
if (error != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
error = mac_veriexec_metadata_get_file_info(va.va_fsid,
|
||||||
|
va.va_fileid, va.va_gen, NULL, &ip, FALSE);
|
||||||
|
if (error != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
result.flags = ip->flags;
|
||||||
|
strlcpy(result.fp_type, ip->ops->type, sizeof(result.fp_type));
|
||||||
|
result.labellen = ip->labellen;
|
||||||
|
if (ip->labellen > 0)
|
||||||
|
strlcpy(result.label, ip->label, sizeof(result.label));
|
||||||
|
result.label[result.labellen] = '\0';
|
||||||
|
memcpy(result.fingerprint, ip->fingerprint,
|
||||||
|
ip->ops->digest_len);
|
||||||
|
|
||||||
|
error = copyout(&result, pargs.params, sizeof(result));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error = EOPNOTSUPP;
|
error = EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
if (nd.ni_vp != NULL) {
|
||||||
|
VOP_UNLOCK(nd.ni_vp);
|
||||||
|
vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
|
||||||
|
}
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
#ifndef _SECURITY_MAC_VERIEXEC_H
|
#ifndef _SECURITY_MAC_VERIEXEC_H
|
||||||
#define _SECURITY_MAC_VERIEXEC_H
|
#define _SECURITY_MAC_VERIEXEC_H
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
#ifdef _KERNEL
|
#ifdef _KERNEL
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
@ -44,6 +46,10 @@
|
|||||||
/* MAC/veriexec syscalls */
|
/* MAC/veriexec syscalls */
|
||||||
#define MAC_VERIEXEC_CHECK_FD_SYSCALL 1
|
#define MAC_VERIEXEC_CHECK_FD_SYSCALL 1
|
||||||
#define MAC_VERIEXEC_CHECK_PATH_SYSCALL 2
|
#define MAC_VERIEXEC_CHECK_PATH_SYSCALL 2
|
||||||
|
#define MAC_VERIEXEC_GET_PARAMS_PID_SYSCALL 3
|
||||||
|
#define MAC_VERIEXEC_GET_PARAMS_PATH_SYSCALL 4
|
||||||
|
|
||||||
|
#define VERIEXEC_FPTYPELEN 16 /* hash name */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enough room for the largest signature...
|
* Enough room for the largest signature...
|
||||||
@ -68,6 +74,23 @@
|
|||||||
match signature */
|
match signature */
|
||||||
#define VERIEXEC_STATE_LOCKED (1<<3) /**< Do not allow further changes */
|
#define VERIEXEC_STATE_LOCKED (1<<3) /**< Do not allow further changes */
|
||||||
|
|
||||||
|
/* for MAC_VERIEXEC_GET_PARAMS_*_SYSCALL */
|
||||||
|
struct mac_veriexec_syscall_params {
|
||||||
|
char fp_type[VERIEXEC_FPTYPELEN];
|
||||||
|
unsigned char fingerprint[MAXFINGERPRINTLEN];
|
||||||
|
char label[MAXLABELLEN];
|
||||||
|
size_t labellen;
|
||||||
|
unsigned char flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mac_veriexec_syscall_params_args {
|
||||||
|
union {
|
||||||
|
pid_t pid;
|
||||||
|
const char *filename;
|
||||||
|
} u; /* input only */
|
||||||
|
struct mac_veriexec_syscall_params *params; /* result */
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef _KERNEL
|
#ifdef _KERNEL
|
||||||
/**
|
/**
|
||||||
* Version of the MAC/veriexec module
|
* Version of the MAC/veriexec module
|
||||||
|
@ -78,9 +78,9 @@ int mac_veriexec_metadata_get_executable_flags(struct ucred *cred,
|
|||||||
struct proc *p, int *flags, int check_files);
|
struct proc *p, int *flags, int check_files);
|
||||||
int mac_veriexec_metadata_get_file_flags(dev_t fsid, long fileid,
|
int mac_veriexec_metadata_get_file_flags(dev_t fsid, long fileid,
|
||||||
unsigned long gen, int *flags, int check_files);
|
unsigned long gen, int *flags, int check_files);
|
||||||
struct mac_veriexec_file_info *
|
int mac_veriexec_metadata_get_file_info(dev_t fsid, long fileid,
|
||||||
mac_veriexec_metadata_get_file_info(dev_t fsid, long fileid,
|
unsigned long gen, int *found_dev,
|
||||||
unsigned long gen, int *found_dev, int check_files);
|
struct mac_veriexec_file_info **ipp, int check_files);
|
||||||
void mac_veriexec_metadata_init(void);
|
void mac_veriexec_metadata_init(void);
|
||||||
void mac_veriexec_metadata_print_db(struct sbuf *sbp);
|
void mac_veriexec_metadata_print_db(struct sbuf *sbp);
|
||||||
int mac_veriexec_metadata_unmounted(dev_t fsid, struct thread *td);
|
int mac_veriexec_metadata_unmounted(dev_t fsid, struct thread *td);
|
||||||
|
@ -231,7 +231,7 @@ mac_veriexec_metadata_has_file(dev_t fsid, long fileid, unsigned long gen)
|
|||||||
{
|
{
|
||||||
|
|
||||||
return (mac_veriexec_metadata_get_file_info(fsid, fileid, gen, NULL,
|
return (mac_veriexec_metadata_get_file_info(fsid, fileid, gen, NULL,
|
||||||
VERIEXEC_FILES_FIRST) != NULL);
|
NULL, VERIEXEC_FILES_FIRST) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -438,12 +438,12 @@ mac_veriexec_metadata_get_file_flags(dev_t fsid, long fileid, unsigned long gen,
|
|||||||
int *flags, int check_files)
|
int *flags, int check_files)
|
||||||
{
|
{
|
||||||
struct mac_veriexec_file_info *ip;
|
struct mac_veriexec_file_info *ip;
|
||||||
int found_dev;
|
int error;
|
||||||
|
|
||||||
ip = mac_veriexec_metadata_get_file_info(fsid, fileid, gen, &found_dev,
|
error = mac_veriexec_metadata_get_file_info(fsid, fileid, gen, NULL,
|
||||||
check_files);
|
&ip, check_files);
|
||||||
if (ip == NULL)
|
if (error != 0)
|
||||||
return (ENOENT);
|
return (error);
|
||||||
|
|
||||||
*flags = ip->flags;
|
*flags = ip->flags;
|
||||||
return (0);
|
return (0);
|
||||||
@ -513,9 +513,9 @@ mac_veriexec_metadata_fetch_fingerprint_status(struct vnode *vp,
|
|||||||
status = mac_veriexec_get_fingerprint_status(vp);
|
status = mac_veriexec_get_fingerprint_status(vp);
|
||||||
if (status == FINGERPRINT_INVALID || status == FINGERPRINT_NODEV) {
|
if (status == FINGERPRINT_INVALID || status == FINGERPRINT_NODEV) {
|
||||||
found_dev = 0;
|
found_dev = 0;
|
||||||
ip = mac_veriexec_metadata_get_file_info(vap->va_fsid,
|
error = mac_veriexec_metadata_get_file_info(vap->va_fsid,
|
||||||
vap->va_fileid, vap->va_gen, &found_dev, check_files);
|
vap->va_fileid, vap->va_gen, &found_dev, &ip, check_files);
|
||||||
if (ip == NULL) {
|
if (error != 0) {
|
||||||
status = (found_dev) ? FINGERPRINT_NOENTRY :
|
status = (found_dev) ? FINGERPRINT_NOENTRY :
|
||||||
FINGERPRINT_NODEV;
|
FINGERPRINT_NODEV;
|
||||||
VERIEXEC_DEBUG(3,
|
VERIEXEC_DEBUG(3,
|
||||||
@ -739,15 +739,16 @@ mac_veriexec_metadata_add_file(int file_dev, dev_t fsid, long fileid,
|
|||||||
* @param fileid file to look for
|
* @param fileid file to look for
|
||||||
* @param gen generation of file
|
* @param gen generation of file
|
||||||
* @param found_dev indicator that an entry for the file system was found
|
* @param found_dev indicator that an entry for the file system was found
|
||||||
|
* @param ipp pointer to location to store the info pointer
|
||||||
* @param check_files if 1, check the files list first, otherwise check the
|
* @param check_files if 1, check the files list first, otherwise check the
|
||||||
* exectuables list first
|
* exectuables list first
|
||||||
*
|
*
|
||||||
* @return A pointer to the meta-data inforation if meta-data exists for
|
* @return A pointer to the meta-data inforation if meta-data exists for
|
||||||
* the specified file identifier, otherwise @c NULL
|
* the specified file identifier, otherwise @c NULL
|
||||||
*/
|
*/
|
||||||
struct mac_veriexec_file_info *
|
int
|
||||||
mac_veriexec_metadata_get_file_info(dev_t fsid, long fileid, unsigned long gen,
|
mac_veriexec_metadata_get_file_info(dev_t fsid, long fileid, unsigned long gen,
|
||||||
int *found_dev, int check_files)
|
int *found_dev, struct mac_veriexec_file_info **ipp, int check_files)
|
||||||
{
|
{
|
||||||
struct veriexec_devhead *search[3];
|
struct veriexec_devhead *search[3];
|
||||||
struct mac_veriexec_file_info *ip;
|
struct mac_veriexec_file_info *ip;
|
||||||
@ -763,14 +764,18 @@ mac_veriexec_metadata_get_file_info(dev_t fsid, long fileid, unsigned long gen,
|
|||||||
}
|
}
|
||||||
search[2] = NULL;
|
search[2] = NULL;
|
||||||
|
|
||||||
VERIEXEC_DEBUG(3, ("%s: searching for dev %ju, file %lu\n",
|
VERIEXEC_DEBUG(3, ("%s: searching for dev %#jx, file %lu.%lu\n",
|
||||||
__func__, (uintmax_t)fsid, fileid));
|
__func__, (uintmax_t)fsid, fileid, gen));
|
||||||
|
|
||||||
/* Search for the specified file */
|
/* Search for the specified file */
|
||||||
for (ip = NULL, x = 0; ip == NULL && search[x]; x++)
|
for (ip = NULL, x = 0; ip == NULL && search[x]; x++)
|
||||||
ip = get_veriexec_file(search[x], fsid, fileid, gen, found_dev);
|
ip = get_veriexec_file(search[x], fsid, fileid, gen, found_dev);
|
||||||
|
|
||||||
return (ip);
|
if (ipp != NULL)
|
||||||
|
*ipp = ip;
|
||||||
|
if (ip == NULL)
|
||||||
|
return (ENOENT);
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -525,11 +525,12 @@
|
|||||||
*/
|
*/
|
||||||
#define PRIV_VERIEXEC_DIRECT 700 /* Can override 'indirect' */
|
#define PRIV_VERIEXEC_DIRECT 700 /* Can override 'indirect' */
|
||||||
#define PRIV_VERIEXEC_NOVERIFY 701 /* Can override O_VERIFY */
|
#define PRIV_VERIEXEC_NOVERIFY 701 /* Can override O_VERIFY */
|
||||||
|
#define PRIV_VERIEXEC_CONTROL 702 /* Can configure veriexec */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Track end of privilege list.
|
* Track end of privilege list.
|
||||||
*/
|
*/
|
||||||
#define _PRIV_HIGHEST 702
|
#define _PRIV_HIGHEST 703
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Validate that a named privilege is known by the privilege system. Invalid
|
* Validate that a named privilege is known by the privilege system. Invalid
|
||||||
|
Loading…
Reference in New Issue
Block a user