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:
parent
e9882e57f5
commit
2de72bfe34
|
@ -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 "
|
||||
|
|
|
@ -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--;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue