1 /* $NetBSD: verified_exec.c,v 1.4.2.1 2005/06/11 12:31:41 tron Exp $ */
2
3 /*-
4 * Copyright (c) 1998-1999 Brett Lymn
5 * (blymn@baea.com.au, brett_lymn@yahoo.com.au)
6 * All rights reserved.
7 *
8 * This code has been donated to The NetBSD Foundation by the Author.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. The name of the author may not be used to endorse or promote products
16 * derived from this software withough specific prior written permission
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 *
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: verified_exec.c,v 1.4.2.1 2005/06/11 12:31:41 tron Exp $");
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/proc.h>
38 #include <sys/errno.h>
39 #include <sys/verified_exec.h>
40 #include <sys/buf.h>
41 #include <sys/malloc.h>
42 #include <sys/ioctl.h>
43 #include <sys/device.h>
44 #include <sys/conf.h>
45 #include <sys/lock.h>
46 #include <sys/queue.h>
47 #include <sys/vnode.h>
48 #include <sys/fcntl.h>
49 #include <sys/namei.h>
50
51 struct verified_exec_softc {
52 struct device veriexec_dev;
53 };
54
55 const struct cdevsw verifiedexec_cdevsw = {
56 verifiedexecopen, verifiedexecclose, noread, nowrite,
57 verifiedexecioctl, nostop, notty, nopoll, nommap, nokqfilter,
58 };
59
60 /* internal structures */
61 LIST_HEAD(veriexec_devhead, veriexec_dev_list) veriexec_dev_head;
62 /*LIST_HEAD(veriexec_file_devhead, veriexec_dev_list) veriexec_file_dev_head;*/
63 struct veriexec_devhead veriexec_file_dev_head;
64
65 /* Autoconfiguration glue */
66 void verifiedexecattach(struct device *parent, struct device *self,
67 void *aux);
68 int verifiedexecopen(dev_t dev, int flags, int fmt, struct proc *p);
69 int verifiedexecclose(dev_t dev, int flags, int fmt, struct proc *p);
70 int verifiedexecioctl(dev_t dev, u_long cmd, caddr_t data, int flags,
71 struct proc *p);
72 void add_veriexec_inode(struct veriexec_dev_list *list, unsigned long inode,
73 unsigned char fingerprint[MAXFINGERPRINTLEN],
74 unsigned char type, unsigned char fp_type);
75 struct veriexec_dev_list *find_veriexec_dev(unsigned long dev,
76 struct veriexec_devhead *head);
77
78 /*
79 * Attach for autoconfig to find. Initialise the lists and return...
80 */
81 void
82 verifiedexecattach(struct device *parent, struct device *self, void *aux)
83 {
84 LIST_INIT(&veriexec_dev_head);
85 LIST_INIT(&veriexec_file_dev_head);
86 }
87
88 int
89 verifiedexecopen(dev_t dev, int flags, int fmt, struct proc *p)
90 {
91 return 0;
92 }
93
94 int
95 verifiedexecclose(dev_t dev, int flags, int fmt, struct proc *p)
96 {
97 #ifdef VERIFIED_EXEC_DEBUG_VERBOSE
98 struct veriexec_dev_list *lp;
99 struct veriexec_inode_list *ip;
100
101 printf("Loaded exec fingerprint list is:\n");
102 for (lp = LIST_FIRST(&veriexec_dev_head); lp != NULL;
103 lp = LIST_NEXT(lp, entries)) {
104 for (ip = LIST_FIRST(&(lp->inode_head)); ip != NULL;
105 ip = LIST_NEXT(ip, entries)) {
106 printf("Got loaded fingerprint for dev %lu, inode %lu\n",
107 lp->id, ip->inode);
108 }
109 }
110
111 printf("\n\nLoaded file fingerprint list is:\n");
112 for (lp = LIST_FIRST(&veriexec_file_dev_head); lp != NULL;
113 lp = LIST_NEXT(lp, entries)) {
114 for (ip = LIST_FIRST(&(lp->inode_head)); ip != NULL;
115 ip = LIST_NEXT(ip, entries)) {
116 printf("Got loaded fingerprint for dev %lu, inode %lu\n",
117 lp->id, ip->inode);
118 }
119 }
120 #endif
121 return 0;
122 }
123
124 /*
125 * Search the list of devices looking for the one given. If it is not
126 * in the list then add it.
127 */
128 struct veriexec_dev_list *
129 find_veriexec_dev(unsigned long dev, struct veriexec_devhead *head)
130 {
131 struct veriexec_dev_list *lp;
132
133 for (lp = LIST_FIRST(head); lp != NULL;
134 lp = LIST_NEXT(lp, entries))
135 if (lp->id == dev) break;
136
137 if (lp == NULL) {
138 /* if pointer is null then entry not there, add a new one */
139 MALLOC(lp, struct veriexec_dev_list *,
140 sizeof(struct veriexec_dev_list), M_TEMP, M_WAITOK);
141 LIST_INIT(&(lp->inode_head));
142 lp->id = dev;
143 LIST_INSERT_HEAD(head, lp, entries);
144 }
145
146 return lp;
147 }
148
149 /*
150 * Add a file's inode and fingerprint to the list of inodes attached
151 * to the device id. Only add the entry if it is not already on the
152 * list.
153 */
154 void
155 add_veriexec_inode(struct veriexec_dev_list *list, unsigned long inode,
156 unsigned char fingerprint[MAXFINGERPRINTLEN],
157 unsigned char type, unsigned char fp_type)
158 {
159 struct veriexec_inode_list *ip;
160
161 for (ip = LIST_FIRST(&(list->inode_head)); ip != NULL;
162 ip = LIST_NEXT(ip, entries))
163 /* check for a dupe inode in the list, skip if an entry
164 * exists for this inode except for when the type is
165 * VERIEXEC_INDIRECT, always set the type when it is so
166 * we don't get a hole caused by conflicting types on
167 * hardlinked files. XXX maybe we should validate
168 * fingerprint is same and complain if it is not...
169 */
170 if (ip->inode == inode) {
171 if (type == VERIEXEC_INDIRECT)
172 ip->type = type;
173 return;
174 }
175
176
177 MALLOC(ip, struct veriexec_inode_list *, sizeof(struct veriexec_inode_list),
178 M_TEMP, M_WAITOK);
179 ip->type = type;
180 ip->fp_type = fp_type;
181 ip->inode = inode;
182 memcpy(ip->fingerprint, fingerprint, sizeof(ip->fingerprint));
183 LIST_INSERT_HEAD(&(list->inode_head), ip, entries);
184 }
185
186 /*
187 * Handle the ioctl for the device
188 */
189 int
190 verifiedexecioctl(dev_t dev, u_long cmd, caddr_t data, int flags,
191 struct proc *p)
192 {
193 int error = 0;
194 struct verified_exec_params *params = (struct verified_exec_params *)data;
195 struct nameidata nid;
196 struct vattr vattr;
197 struct veriexec_dev_list *dlp;
198
199 #ifdef VERIFIED_EXEC_DEBUG
200 printf("veriexec_ioctl: got cmd 0x%lx for file %s\n", cmd, params->file);
201 #endif
202
203 switch (cmd) {
204 case VERIEXECLOAD:
205 if (securelevel > 0) {
206 /* don't allow updates when secure */
207 error = EPERM;
208 } else {
209 /*
210 * Get the attributes for the file name passed
211 * stash the file's device id and inode number
212 * along with it's fingerprint in a list for
213 * exec to use later.
214 */
215 NDINIT(&nid, LOOKUP, FOLLOW, UIO_SYSSPACE,
216 params->file, p);
217 if ((error = vn_open(&nid, FREAD, 0)) != 0) {
218 return(error);
219 }
220 error = VOP_GETATTR(nid.ni_vp, &vattr, p->p_ucred, p);
221 if (error) {
222 nid.ni_vp->fp_status = FINGERPRINT_INVALID;
223 VOP_UNLOCK(nid.ni_vp, 0);
224 (void) vn_close(nid.ni_vp, FREAD,
225 p->p_ucred, p);
226 return(error);
227 }
228 /* invalidate the node fingerprint status
229 * which will have been set in the vn_open
230 * and would always be FINGERPRINT_NOTFOUND
231 */
232 nid.ni_vp->fp_status = FINGERPRINT_INVALID;
233 VOP_UNLOCK(nid.ni_vp, 0);
234 (void) vn_close(nid.ni_vp, FREAD, p->p_ucred, p);
235 /* vattr.va_fsid = dev, vattr.va_fileid = inode */
236 if (params->type == VERIEXEC_FILE) {
237 dlp = find_veriexec_dev(vattr.va_fsid,
238 &veriexec_file_dev_head);
239 } else {
240 dlp = find_veriexec_dev(vattr.va_fsid,
241 &veriexec_dev_head);
242 }
243
244 add_veriexec_inode(dlp, vattr.va_fileid,
245 params->fingerprint, params->type,
246 params->fp_type);
247 }
248 break;
249
250 default:
251 error = ENODEV;
252 }
253
254 return (error);
255 }
256
Cache object: 58c772fd58f0c4faa35ba2842805a1e6
|