- Avoid pollution of struct vnode. Save the fingerprint evaluation status
in the veriexec table entry; the lookups are very cheap now. Suggested by Chuq. - Handle non-regular (!VREG) files correctly). - Remove (no longer needed) FINGERPRINT_NOENTRY.
This commit is contained in:
parent
3d0edb52b9
commit
c3caa55d4d
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: verified_exec.c,v 1.15 2005/06/17 17:46:18 elad Exp $ */
|
||||
/* $NetBSD: verified_exec.c,v 1.16 2005/06/19 18:22:36 elad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright 2005 Elad Efrat <elad@bsd.org.il>
|
||||
@ -31,9 +31,9 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(__NetBSD__)
|
||||
__KERNEL_RCSID(0, "$NetBSD: verified_exec.c,v 1.15 2005/06/17 17:46:18 elad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: verified_exec.c,v 1.16 2005/06/19 18:22:36 elad Exp $");
|
||||
#else
|
||||
__RCSID("$Id: verified_exec.c,v 1.15 2005/06/17 17:46:18 elad Exp $\n$NetBSD: verified_exec.c,v 1.15 2005/06/17 17:46:18 elad Exp $");
|
||||
__RCSID("$Id: verified_exec.c,v 1.16 2005/06/19 18:22:36 elad Exp $\n$NetBSD: verified_exec.c,v 1.16 2005/06/19 18:22:36 elad Exp $");
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -215,8 +215,6 @@ veriexecioctl(dev_t dev __unused, u_long cmd, caddr_t data,
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
nid.ni_vp->fp_status = FINGERPRINT_NOTEVAL;
|
||||
|
||||
/* Get attributes for device and inode. */
|
||||
error = VOP_GETATTR(nid.ni_vp, &va, p->p_ucred, p);
|
||||
if (error)
|
||||
@ -267,6 +265,7 @@ veriexecioctl(dev_t dev __unused, u_long cmd, caddr_t data,
|
||||
e = malloc(sizeof(*e), M_TEMP, M_WAITOK);
|
||||
e->inode = va.va_fileid;
|
||||
e->type = params->type;
|
||||
e->status = FINGERPRINT_NOTEVAL;
|
||||
if ((e->ops = veriexec_find_ops(params->fp_type)) == NULL) {
|
||||
free(e, M_TEMP);
|
||||
printf("Veriexec: veriexecioctl: Invalid or unknown "
|
||||
@ -276,14 +275,14 @@ veriexecioctl(dev_t dev __unused, u_long cmd, caddr_t data,
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Just a bit of a sanity check - require the size of
|
||||
* the fp to be passed in, check this against the expected
|
||||
* size. Of course userland could lie deliberately, this
|
||||
* really only protects against the obvious fumble of
|
||||
* changing the fp type but not updating the fingerprint
|
||||
* string.
|
||||
*/
|
||||
/*
|
||||
* Just a bit of a sanity check - require the size of
|
||||
* the fp to be passed in, check this against the expected
|
||||
* size. Of course userland could lie deliberately, this
|
||||
* really only protects against the obvious fumble of
|
||||
* changing the fp type but not updating the fingerprint
|
||||
* string.
|
||||
*/
|
||||
if (e->ops->hash_len != params->size) {
|
||||
printf("Veriexec: veriexecioctl: Inconsistent "
|
||||
"fingerprint size for type \"%s\" for file "
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: kern_verifiedexec.c,v 1.27 2005/06/17 22:39:08 elad Exp $ */
|
||||
/* $NetBSD: kern_verifiedexec.c,v 1.28 2005/06/19 18:22:36 elad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright 2005 Elad Efrat <elad@bsd.org.il>
|
||||
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_verifiedexec.c,v 1.27 2005/06/17 22:39:08 elad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_verifiedexec.c,v 1.28 2005/06/19 18:22:36 elad Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
@ -351,47 +351,46 @@ veriexec_hashadd(struct veriexec_hashtbl *tbl, struct veriexec_hash_entry *e)
|
||||
*/
|
||||
int
|
||||
veriexec_verify(struct proc *p, struct vnode *vp, struct vattr *va,
|
||||
const u_char *name, int flag)
|
||||
const u_char *name, int flag, struct veriexec_hash_entry **ret)
|
||||
{
|
||||
u_char *digest;
|
||||
struct veriexec_hash_entry *vhe = NULL;
|
||||
u_char *digest = NULL;
|
||||
int error = 0;
|
||||
|
||||
/* Evaluate fingerprint if needed and set the status on the vp. */
|
||||
if (vp->fp_status == FINGERPRINT_NOTEVAL) {
|
||||
if ((vp->v_type != VREG) || (vp->vhe =
|
||||
veriexec_lookup(va->va_fsid, va->va_fileid)) == NULL) {
|
||||
vp->fp_status = FINGERPRINT_NOENTRY;
|
||||
goto out;
|
||||
}
|
||||
/* XXXEE Ignore non-VREG files. */
|
||||
if (vp->v_type != VREG)
|
||||
return (0);
|
||||
|
||||
veriexec_dprintf(("veriexec: veriexec_verify: Got entry for "
|
||||
"%s. (dev=%d, inode=%u)\n", name,
|
||||
va->va_fsid, va->va_fileid));
|
||||
/* Lookup veriexec table entry, save pointer if requested. */
|
||||
vhe = veriexec_lookup(va->va_fsid, va->va_fileid);
|
||||
if (ret != NULL)
|
||||
*ret = vhe;
|
||||
if (vhe == NULL)
|
||||
goto out;
|
||||
|
||||
digest = (u_char *) malloc(vp->vhe->ops->hash_len, M_TEMP,
|
||||
/* Evaluate fingerprint if needed. */
|
||||
if (vhe->status == FINGERPRINT_NOTEVAL) {
|
||||
/* Calculate fingerprint for on-disk file. */
|
||||
digest = (u_char *) malloc(vhe->ops->hash_len, M_TEMP,
|
||||
M_WAITOK);
|
||||
error = veriexec_fp_calc(p, vp, vp->vhe, va->va_size, digest);
|
||||
|
||||
error = veriexec_fp_calc(p, vp, vhe, va->va_size, digest);
|
||||
if (error) {
|
||||
veriexec_dprintf(("veriexec: veriexec_verify: "
|
||||
"Calculation error.\n"));
|
||||
/* XXXEE verbose+ printf here */
|
||||
free(digest, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (veriexec_fp_cmp(vp->vhe->ops, vp->vhe->fp, digest) == 0) {
|
||||
vp->fp_status = FINGERPRINT_VALID;
|
||||
/* Compare fingerprint with loaded data. */
|
||||
if (veriexec_fp_cmp(vhe->ops, vhe->fp, digest) == 0) {
|
||||
vhe->status = FINGERPRINT_VALID;
|
||||
} else {
|
||||
vp->fp_status = FINGERPRINT_NOMATCH;
|
||||
vhe->status = FINGERPRINT_NOMATCH;
|
||||
}
|
||||
|
||||
free(digest, M_TEMP);
|
||||
}
|
||||
|
||||
if (vp->vhe == NULL)
|
||||
goto out;
|
||||
|
||||
if (flag != vp->vhe->type) {
|
||||
if (flag != vhe->type) {
|
||||
veriexec_report("Incorrect access type.", name, va, p,
|
||||
REPORT_NOVERBOSE, REPORT_ALARM,
|
||||
REPORT_NOPANIC);
|
||||
@ -402,7 +401,19 @@ veriexec_verify(struct proc *p, struct vnode *vp, struct vattr *va,
|
||||
}
|
||||
|
||||
out:
|
||||
switch (vp->fp_status) {
|
||||
/* No entry in the veriexec tables. */
|
||||
if (vhe == NULL) {
|
||||
veriexec_report("veriexec_verify: No entry.", name, va,
|
||||
p, REPORT_VERBOSE, REPORT_NOALARM, REPORT_NOPANIC);
|
||||
|
||||
/* Lockdown mode: Deny access to non-monitored files. */
|
||||
if (veriexec_strict >= 3)
|
||||
return (EPERM);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
switch (vhe->status) {
|
||||
case FINGERPRINT_NOTEVAL:
|
||||
/* Should not happen. */
|
||||
veriexec_report("veriexec_verify: Not-evaluated status "
|
||||
@ -427,17 +438,6 @@ out:
|
||||
|
||||
break;
|
||||
|
||||
case FINGERPRINT_NOENTRY:
|
||||
/* No entry in the list. */
|
||||
veriexec_report("veriexec_verify: No entry.", name, va,
|
||||
p, REPORT_VERBOSE, REPORT_NOALARM, REPORT_NOPANIC);
|
||||
|
||||
/* Lockdown mode: Deny access to non-monitored files. */
|
||||
if (veriexec_strict >= 3)
|
||||
error = EPERM;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* Should never happen.
|
||||
@ -494,8 +494,6 @@ veriexec_removechk(struct proc *p, struct vnode *vp, const char *pathbuf)
|
||||
free(vhe->fp, M_TEMP);
|
||||
free(vhe, M_TEMP);
|
||||
tbl->hash_count--;
|
||||
vp->fp_status = FINGERPRINT_NOENTRY;
|
||||
vp->vhe = NULL;
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vfs_subr.c,v 1.249 2005/06/15 16:59:27 elad Exp $ */
|
||||
/* $NetBSD: vfs_subr.c,v 1.250 2005/06/19 18:22:36 elad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998, 2004, 2005 The NetBSD Foundation, Inc.
|
||||
@ -80,7 +80,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.249 2005/06/15 16:59:27 elad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.250 2005/06/19 18:22:36 elad Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ddb.h"
|
||||
@ -587,10 +587,6 @@ getnewvnode(enum vtagtype tag, struct mount *mp, int (**vops)(void *),
|
||||
vp->v_usecount = 1;
|
||||
vp->v_flag = 0;
|
||||
vp->v_socket = NULL;
|
||||
#ifdef VERIFIED_EXEC
|
||||
vp->fp_status = FINGERPRINT_NOTEVAL;
|
||||
vp->vhe = NULL;
|
||||
#endif
|
||||
}
|
||||
vp->v_type = VNON;
|
||||
vp->v_vnlock = &vp->v_lock;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vfs_vnops.c,v 1.91 2005/06/17 17:46:18 elad Exp $ */
|
||||
/* $NetBSD: vfs_vnops.c,v 1.92 2005/06/19 18:22:36 elad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.91 2005/06/17 17:46:18 elad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.92 2005/06/19 18:22:36 elad Exp $");
|
||||
|
||||
#include "fs_union.h"
|
||||
|
||||
@ -100,15 +100,9 @@ vn_open(struct nameidata *ndp, int fmode, int cmode)
|
||||
struct ucred *cred = p->p_ucred;
|
||||
struct vattr va;
|
||||
int error;
|
||||
#ifdef NEVER /* for the moment I am not convinced this is needed since NDINIT should do this lookup...XXXX blymn */
|
||||
char pathbuf[MAXPATHLEN];
|
||||
unsigned pathlen;
|
||||
|
||||
if (ndp->ni_segflg == UIO_SYSSPACE)
|
||||
error = copystr(pathbuf, ndp->ni_dirp, MAXPATHLEN, &pathlen);
|
||||
else
|
||||
error = copyinstr(pathbuf, ndp->ni_dirp,MAXPATHLEN, &pathlen);
|
||||
#endif
|
||||
#ifdef VERIFIED_EXEC
|
||||
struct veriexec_hash_entry *vhe = NULL;
|
||||
#endif /* VERIFIED_EXEC */
|
||||
|
||||
restart:
|
||||
if (fmode & O_CREAT) {
|
||||
@ -196,7 +190,7 @@ restart:
|
||||
#ifdef VERIFIED_EXEC
|
||||
/* XXX may need pathbuf instead */
|
||||
if ((error = veriexec_verify(p, vp, &va, ndp->ni_dirp,
|
||||
VERIEXEC_FILE)) != 0)
|
||||
VERIEXEC_FILE, &vhe)) != 0)
|
||||
goto bad;
|
||||
#endif
|
||||
|
||||
@ -214,7 +208,7 @@ restart:
|
||||
(error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0)
|
||||
goto bad;
|
||||
#ifdef VERIFIED_EXEC
|
||||
if (vp->fp_status != FINGERPRINT_NOENTRY) {
|
||||
if (vhe != NULL) {
|
||||
veriexec_report("Write access request.",
|
||||
ndp->ni_dirp, &va, p,
|
||||
REPORT_NOVERBOSE,
|
||||
@ -226,7 +220,7 @@ restart:
|
||||
error = EPERM;
|
||||
goto bad;
|
||||
} else {
|
||||
vp->fp_status = FINGERPRINT_NOTEVAL;
|
||||
vhe->status = FINGERPRINT_NOTEVAL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: verified_exec.h,v 1.12 2005/05/29 16:07:10 elad Exp $ */
|
||||
/* $NetBSD: verified_exec.h,v 1.13 2005/06/19 18:22:37 elad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright 2005 Elad Efrat <elad@bsd.org.il>
|
||||
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: verified_exec.h,v 1.12 2005/05/29 16:07:10 elad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: verified_exec.h,v 1.13 2005/06/19 18:22:37 elad Exp $");
|
||||
|
||||
/*
|
||||
*
|
||||
@ -119,11 +119,17 @@ struct veriexec_fp_ops {
|
||||
struct veriexec_hash_entry {
|
||||
ino_t inode; /* Inode number. */
|
||||
unsigned char type; /* Entry type. */
|
||||
unsigned char status; /* Evaluation status. */
|
||||
unsigned char *fp; /* Fingerprint. */
|
||||
struct veriexec_fp_ops *ops; /* Fingerprint ops vector*/
|
||||
LIST_ENTRY(veriexec_hash_entry) entries; /* List pointer. */
|
||||
};
|
||||
|
||||
/* Valid status field values. */
|
||||
#define FINGERPRINT_NOTEVAL 0 /* fingerprint has not been evaluated */
|
||||
#define FINGERPRINT_VALID 1 /* fingerprint evaluated and matches list */
|
||||
#define FINGERPRINT_NOMATCH 2 /* fingerprint evaluated but does not match */
|
||||
|
||||
LIST_HEAD(veriexec_hashhead, veriexec_hash_entry) *hash_tbl;
|
||||
|
||||
/* Veriexec hash table information. */
|
||||
@ -175,13 +181,11 @@ struct veriexec_fp_ops *veriexec_find_ops(u_char *name);
|
||||
int veriexec_fp_calc(struct proc *, struct vnode *,
|
||||
struct veriexec_hash_entry *, uint64_t, u_char *);
|
||||
int veriexec_fp_cmp(struct veriexec_fp_ops *, u_char *, u_char *);
|
||||
|
||||
struct veriexec_hashtbl *veriexec_tblfind(dev_t);
|
||||
struct veriexec_hash_entry *veriexec_lookup(dev_t, ino_t);
|
||||
int veriexec_hashadd(struct veriexec_hashtbl *, struct veriexec_hash_entry *);
|
||||
|
||||
int veriexec_verify(struct proc *, struct vnode *, struct vattr *,
|
||||
const u_char *, int);
|
||||
const u_char *, int, struct veriexec_hash_entry **);
|
||||
int veriexec_removechk(struct proc *, struct vnode *, const char *);
|
||||
void veriexec_init_fp_ops(void);
|
||||
void veriexec_report(const u_char *, const u_char *, struct vattr *,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vnode.h,v 1.139 2005/06/17 17:46:18 elad Exp $ */
|
||||
/* $NetBSD: vnode.h,v 1.140 2005/06/19 18:22:37 elad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
@ -121,15 +121,12 @@ struct vnode {
|
||||
struct lock *v_vnlock; /* pointer to lock */
|
||||
void *v_data; /* private data for fs */
|
||||
struct klist v_klist; /* knotes attached to vnode */
|
||||
#ifdef VERIFIED_EXEC
|
||||
u_char fp_status; /* fingerprint status */
|
||||
struct veriexec_hash_entry *vhe; /* veriexec table entry */
|
||||
#endif
|
||||
};
|
||||
#define v_mountedhere v_un.vu_mountedhere
|
||||
#define v_socket v_un.vu_socket
|
||||
#define v_specinfo v_un.vu_specinfo
|
||||
#define v_fifoinfo v_un.vu_fifoinfo
|
||||
|
||||
/*
|
||||
* All vnode locking operations should use vp->v_vnlock. For leaf filesystems
|
||||
* (such as ffs, lfs, msdosfs, etc), vp->v_vnlock = &vp->v_lock. For
|
||||
@ -181,16 +178,6 @@ extern struct simplelock global_v_numoutput_slock;
|
||||
simple_unlock(&global_v_numoutput_slock); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
/*
|
||||
* Valid states for the fingerprint flag - if signed exec is being used
|
||||
*/
|
||||
#ifdef VERIFIED_EXEC
|
||||
#define FINGERPRINT_NOTEVAL 0 /* fingerprint has not been evaluated */
|
||||
#define FINGERPRINT_VALID 1 /* fingerprint evaluated and matches list */
|
||||
#define FINGERPRINT_NOMATCH 2 /* fingerprint evaluated but does not match */
|
||||
#define FINGERPRINT_NOENTRY 3 /* fingerprint evaluated but no list entry */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Vnode attributes. A field value of VNOVAL represents a field whose value
|
||||
* is unavailable (getattr) or which is not to be changed (setattr).
|
||||
|
Loading…
Reference in New Issue
Block a user