Various fixes from blymn@ and myself.

Also, put genfs changes under #if 0, and don't do per-page fingerprints
until this is properly discussed, as requested by yamt@.
This commit is contained in:
elad 2005-10-07 18:07:46 +00:00
parent e9882e57f5
commit 2de72bfe34
4 changed files with 68 additions and 63 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: verified_exec.c,v 1.24 2005/10/05 13:48:48 elad Exp $ */
/* $NetBSD: verified_exec.c,v 1.25 2005/10/07 18:07:46 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.24 2005/10/05 13:48:48 elad Exp $");
__KERNEL_RCSID(0, "$NetBSD: verified_exec.c,v 1.25 2005/10/07 18:07:46 elad Exp $");
#else
__RCSID("$Id: verified_exec.c,v 1.24 2005/10/05 13:48:48 elad Exp $\n$NetBSD: verified_exec.c,v 1.24 2005/10/05 13:48:48 elad Exp $");
__RCSID("$Id: verified_exec.c,v 1.25 2005/10/07 18:07:46 elad Exp $\n$NetBSD: verified_exec.c,v 1.25 2005/10/07 18:07:46 elad Exp $");
#endif
#include <sys/param.h>
@ -272,7 +272,8 @@ veriexecioctl(dev_t dev __unused, u_long cmd, caddr_t data,
e->status = FINGERPRINT_NOTEVAL;
e->page_fp = NULL;
e->page_fp_status = PAGE_FP_NONE;
e->last_page = 0;
e->npages = 0;
e->last_page_size = 0;
if ((e->ops = veriexec_find_ops(params->fp_type)) == NULL) {
free(e, M_TEMP);
printf("Veriexec: veriexecioctl: Invalid or unknown "

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_verifiedexec.c,v 1.41 2005/10/05 16:21:46 elad Exp $ */
/* $NetBSD: kern_verifiedexec.c,v 1.42 2005/10/07 18:07:46 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.41 2005/10/05 16:21:46 elad Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_verifiedexec.c,v 1.42 2005/10/07 18:07:46 elad Exp $");
#include "opt_verified_exec.h"
@ -209,26 +209,34 @@ veriexec_fp_calc(struct proc *p, struct vnode *vp,
{
void *ctx = NULL, *page_ctx = NULL;
u_char *buf = NULL, *page_fp = NULL;
off_t offset, len;
off_t offset, len = 0;
size_t resid, npages = 0;
int error = 0;
int error = 0, do_perpage = 0;
/* XXX: This should not happen. Print more details? */
if (vhe->ops == NULL) {
panic("veriexec: Operations vector is NULL");
}
#if 0
/*
* XXX Until we have a better way to do per-page fingerprints,
* XXX avoid using them.
*/
if ((vhe->type & VERIEXEC_UNTRUSTED) &&
(vhe->page_fp_status == PAGE_FP_NONE))
do_perpage = 1;
#endif
memset(fp, 0, vhe->ops->hash_len);
ctx = (void *) malloc(vhe->ops->context_size, M_TEMP, M_WAITOK);
buf = (u_char *) malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
if (vhe->type & VERIEXEC_UNTRUSTED) {
if (do_perpage) {
npages = (size >> PAGE_SHIFT) + 1;
vhe->page_fp = (u_char *) malloc(vhe->ops->hash_len * npages,
page_fp = (u_char *) malloc(vhe->ops->hash_len * npages,
M_TEMP, M_WAITOK|M_ZERO);
page_fp = vhe->page_fp;
vhe->last_page = size % PAGE_SIZE;
vhe->page_fp = page_fp;
page_ctx = (void *) malloc(vhe->ops->context_size, M_TEMP,
M_WAITOK);
}
@ -241,7 +249,7 @@ veriexec_fp_calc(struct proc *p, struct vnode *vp,
*/
for (offset = 0; offset < size; offset += PAGE_SIZE) {
len = ((size - offset) < PAGE_SIZE) ? (size - offset)
: PAGE_SIZE;
: PAGE_SIZE;
error = vn_rdwr(UIO_READ, vp, buf, len, offset,
UIO_SYSSPACE,
@ -253,7 +261,7 @@ veriexec_fp_calc(struct proc *p, struct vnode *vp,
p->p_ucred, &resid, NULL);
if (error) {
if (vhe->page_fp) {
if (do_perpage) {
free(vhe->page_fp, M_TEMP);
vhe->page_fp = NULL;
}
@ -265,16 +273,13 @@ veriexec_fp_calc(struct proc *p, struct vnode *vp,
(vhe->ops->update)(ctx, buf, (unsigned int) len);
/* calculate per-page fingerprint if needed */
if (vhe->type & VERIEXEC_UNTRUSTED) {
memset(page_ctx, 0, vhe->ops->context_size);
if (do_perpage) {
(vhe->ops->init)(page_ctx);
(vhe->ops->update)(page_ctx, buf, (unsigned int) len);
(vhe->ops->update)(page_ctx, buf, (unsigned int)len);
(vhe->ops->final)(page_fp, page_ctx);
page_fp += vhe->ops->hash_len;
}
/* XXXEE: don't overflow offset */
if (len != PAGE_SIZE)
break;
}
@ -282,11 +287,14 @@ veriexec_fp_calc(struct proc *p, struct vnode *vp,
/* finalise the fingerprint calculation */
(vhe->ops->final)(fp, ctx);
if (vhe->type & VERIEXEC_UNTRUSTED)
vhe->page_fp_status = PAGE_FP_READY;
if (do_perpage) {
vhe->last_page_size = len;
vhe->page_fp_status = PAGE_FP_READY;
vhe->npages = npages;
}
bad:
if (page_ctx)
if (do_perpage)
free(page_ctx, M_TEMP);
free(ctx, M_TEMP);
free(buf, M_TEMP);
@ -405,7 +413,8 @@ veriexec_verify(struct proc *p, struct vnode *vp, struct vattr *va,
goto out;
/* Evaluate fingerprint if needed. */
if (vhe->status == FINGERPRINT_NOTEVAL) {
if ((vhe->status == FINGERPRINT_NOTEVAL) ||
(vhe->type & VERIEXEC_UNTRUSTED)) {
/* Calculate fingerprint for on-disk file. */
digest = (u_char *) malloc(vhe->ops->hash_len, M_TEMP,
M_WAITOK);
@ -474,12 +483,6 @@ out:
if (veriexec_strict >= 1)
error = EPERM;
if (vhe->page_fp != NULL) {
free(vhe->page_fp, M_TEMP);
vhe->page_fp = NULL;
vhe->page_fp_status = PAGE_FP_FAIL;
}
break;
default:
@ -500,28 +503,23 @@ out:
*/
int
veriexec_page_verify(struct veriexec_hash_entry *vhe, struct vattr *va,
struct vm_page *pg, u_int is_last_page)
struct vm_page *pg, size_t idx)
{
void *ctx;
u_char *fp;
u_char *page_fp;
int error;
size_t pagen;
vaddr_t kva;
vaddr_t kva = 0;
if (vhe->page_fp_status == PAGE_FP_NONE) {
if (vhe->page_fp_status == PAGE_FP_NONE)
return (0);
}
if (vhe->page_fp_status == PAGE_FP_FAIL) {
if (vhe->page_fp_status == PAGE_FP_FAIL)
return (EPERM);
}
ctx = (void *) malloc(vhe->ops->context_size, M_TEMP, M_WAITOK);
fp = (u_char *) malloc(vhe->ops->hash_len, M_TEMP, M_WAITOK);
pagen = pg->offset >> PAGE_SHIFT;
error = uvm_map(kernel_map, &kva, PAGE_SIZE, NULL,
UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(UVM_PROT_READ,
UVM_PROT_READ, UVM_INH_NONE, UVM_ADV_NORMAL,
@ -531,12 +529,12 @@ veriexec_page_verify(struct veriexec_hash_entry *vhe, struct vattr *va,
pmap_kenter_pa(kva, pg->phys_addr, VM_PROT_READ);
page_fp = (u_char *) vhe->page_fp + pagen;
page_fp = (u_char *) vhe->page_fp + (vhe->ops->hash_len * idx);
memset(ctx, 0, vhe->ops->context_size);
(vhe->ops->init)(ctx);
(vhe->ops->update)(ctx, (void *) &kva, is_last_page ? vhe->last_page :
PAGE_SIZE);
(vhe->ops->update)(ctx, (void *) kva,
((vhe->npages - 1) == idx) ? vhe->last_page_size
: PAGE_SIZE);
(vhe->ops->final)(fp, ctx);
pmap_kremove(kva, PAGE_SIZE);
@ -562,7 +560,7 @@ veriexec_page_verify(struct veriexec_hash_entry *vhe, struct vattr *va,
KSI_INIT(&ksi);
ksi.ksi_signo = SIGKILL;
ksi.ksi_code = SI_NOINFO; /* XXXEE */
ksi.ksi_code = SI_NOINFO;
ksi.ksi_pid = p->p_pid;
ksi.ksi_uid = 0;
@ -571,12 +569,8 @@ veriexec_page_verify(struct veriexec_hash_entry *vhe, struct vattr *va,
}
bad:
if (error || is_last_page) {
free(ctx, M_TEMP);
ctx = NULL;
free(fp, M_TEMP);
fp = NULL;
}
free(ctx, M_TEMP);
free(fp, M_TEMP);
return (error);
}
@ -622,8 +616,12 @@ veriexec_removechk(struct proc *p, struct vnode *vp, const char *pathbuf)
LIST_REMOVE(vhe, entries);
free(vhe->fp, M_TEMP);
if (vhe->page_fp)
if (vhe->page_fp) {
vhe->page_fp_status = PAGE_FP_NONE;
free(vhe->page_fp, M_TEMP);
vhe->page_fp = NULL;
vhe->npages = 0;
}
free(vhe, M_TEMP);
tbl->hash_count--;

View File

@ -1,4 +1,4 @@
/* $NetBSD: genfs_vnops.c,v 1.105 2005/10/05 13:48:48 elad Exp $ */
/* $NetBSD: genfs_vnops.c,v 1.106 2005/10/07 18:07:46 elad Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.105 2005/10/05 13:48:48 elad Exp $");
__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.106 2005/10/07 18:07:46 elad Exp $");
#if defined(_KERNEL_OPT)
#include "opt_nfsserver.h"
@ -904,12 +904,18 @@ loopdone:
uvm_pagermapout(kva, npages);
raoffset = startoffset + totalbytes;
#if 0
/*
* XXX This should not be here. We can't rely on all
* XXX filesystems to use genfs_getpages(), even though at the
* XXX moment that's the most common case (with the exception
* XXX of smbfs).
*/
#ifdef VERIFIED_EXEC
if (!error && !sawhole && !write) {
struct proc *veriexec_p = curlwp->l_proc;
struct vattr veriexec_va;
struct veriexec_hash_entry *vhe;
size_t last_page;
/* XXXEE: try to eliminate this. */
error = VOP_GETATTR(vp, &veriexec_va, veriexec_p->p_ucred,
@ -921,20 +927,19 @@ loopdone:
veriexec_va.va_fileid);
if (vhe == NULL || vhe->page_fp == NULL)
goto skip_veriexec;
last_page = (ridx + npages - 1);
pidx = origoffset >> PAGE_SHIFT;
for (i = ridx; i < ridx + npages; i++) {
error = veriexec_page_verify(vhe, &veriexec_va,
pgs[i],
((i == last_page) ? 1
: 0));
error = veriexec_page_verify(vhe, &veriexec_va, pgs[i],
pidx + i);
if (error)
break;
}
}
skip_veriexec:
#endif /* VERIFIED_EXEC */
#endif /* 0 */
/*
* if this we encountered a hole then we have to do a little more work.

View File

@ -1,4 +1,4 @@
/* $NetBSD: verified_exec.h,v 1.20 2005/10/05 13:48:48 elad Exp $ */
/* $NetBSD: verified_exec.h,v 1.21 2005/10/07 18:07:46 elad Exp $ */
/*-
* Copyright 2005 Elad Efrat <elad@bsd.org.il>
@ -125,7 +125,8 @@ struct veriexec_hash_entry {
unsigned char page_fp_status; /* Per-page FP status. */
unsigned char *fp; /* Fingerprint. */
void *page_fp; /* Per-page fingerprints */
size_t last_page; /* Index of last page. */
size_t npages; /* Number of pages. */
size_t last_page_size;
struct veriexec_fp_ops *ops; /* Fingerprint ops vector*/
LIST_ENTRY(veriexec_hash_entry) entries; /* List pointer. */
};
@ -198,7 +199,7 @@ int veriexec_hashadd(struct veriexec_hashtbl *, struct veriexec_hash_entry *);
int veriexec_verify(struct proc *, struct vnode *, struct vattr *,
const u_char *, int, struct veriexec_hash_entry **);
int veriexec_page_verify(struct veriexec_hash_entry *, struct vattr *,
struct vm_page *, u_int);
struct vm_page *, size_t);
int veriexec_removechk(struct proc *, struct vnode *, const char *);
int veriexec_renamechk(struct vnode *, const char *, const char *);
void veriexec_init_fp_ops(void);