1/*- 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 5 * can do whatever you want with this stuff. If we meet some day, and you think 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7 * ---------------------------------------------------------------------------- 8 */ 9 10/* 11 * This module handles execution of a.out files which have been run through 12 * "gzip". This saves diskspace, but wastes cpu-cycles and VM. 13 * 14 * TODO: 15 * text-segments should be made R/O after being filled 16 * is the vm-stuff safe ? 17 * should handle the entire header of gzip'ed stuff. 18 * inflate isn't quite reentrant yet... 19 * error-handling is a mess... 20 * so is the rest... 21 * tidy up unnecesary includes 22 */ 23 24#include <sys/cdefs.h>
| 1/*- 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 5 * can do whatever you want with this stuff. If we meet some day, and you think 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7 * ---------------------------------------------------------------------------- 8 */ 9 10/* 11 * This module handles execution of a.out files which have been run through 12 * "gzip". This saves diskspace, but wastes cpu-cycles and VM. 13 * 14 * TODO: 15 * text-segments should be made R/O after being filled 16 * is the vm-stuff safe ? 17 * should handle the entire header of gzip'ed stuff. 18 * inflate isn't quite reentrant yet... 19 * error-handling is a mess... 20 * so is the rest... 21 * tidy up unnecesary includes 22 */ 23 24#include <sys/cdefs.h>
|
25__FBSDID("$FreeBSD: head/sys/kern/imgact_gzip.c 220373 2011-04-05 20:23:59Z trasz $");
| 25__FBSDID("$FreeBSD: head/sys/kern/imgact_gzip.c 231885 2012-02-17 23:47:16Z kib $");
|
26 27#include <sys/param.h> 28#include <sys/exec.h> 29#include <sys/imgact.h> 30#include <sys/imgact_aout.h> 31#include <sys/kernel.h> 32#include <sys/lock.h> 33#include <sys/mman.h> 34#include <sys/mutex.h> 35#include <sys/proc.h> 36#include <sys/racct.h> 37#include <sys/resourcevar.h> 38#include <sys/sysent.h> 39#include <sys/systm.h> 40#include <sys/vnode.h> 41#include <sys/inflate.h> 42 43#include <vm/vm.h> 44#include <vm/vm_param.h> 45#include <vm/pmap.h> 46#include <vm/vm_map.h> 47#include <vm/vm_kern.h> 48#include <vm/vm_extern.h> 49 50struct imgact_gzip { 51 struct image_params *ip; 52 struct exec a_out; 53 int error; 54 int gotheader; 55 int where; 56 u_char *inbuf; 57 u_long offset; 58 u_long output; 59 u_long len; 60 int idx; 61 u_long virtual_offset, file_offset, file_end, bss_size; 62}; 63 64static int exec_gzip_imgact(struct image_params *imgp); 65static int NextByte(void *vp); 66static int do_aout_hdr(struct imgact_gzip *); 67static int Flush(void *vp, u_char *, u_long siz); 68 69static int 70exec_gzip_imgact(imgp) 71 struct image_params *imgp; 72{
| 26 27#include <sys/param.h> 28#include <sys/exec.h> 29#include <sys/imgact.h> 30#include <sys/imgact_aout.h> 31#include <sys/kernel.h> 32#include <sys/lock.h> 33#include <sys/mman.h> 34#include <sys/mutex.h> 35#include <sys/proc.h> 36#include <sys/racct.h> 37#include <sys/resourcevar.h> 38#include <sys/sysent.h> 39#include <sys/systm.h> 40#include <sys/vnode.h> 41#include <sys/inflate.h> 42 43#include <vm/vm.h> 44#include <vm/vm_param.h> 45#include <vm/pmap.h> 46#include <vm/vm_map.h> 47#include <vm/vm_kern.h> 48#include <vm/vm_extern.h> 49 50struct imgact_gzip { 51 struct image_params *ip; 52 struct exec a_out; 53 int error; 54 int gotheader; 55 int where; 56 u_char *inbuf; 57 u_long offset; 58 u_long output; 59 u_long len; 60 int idx; 61 u_long virtual_offset, file_offset, file_end, bss_size; 62}; 63 64static int exec_gzip_imgact(struct image_params *imgp); 65static int NextByte(void *vp); 66static int do_aout_hdr(struct imgact_gzip *); 67static int Flush(void *vp, u_char *, u_long siz); 68 69static int 70exec_gzip_imgact(imgp) 71 struct image_params *imgp; 72{
|
73 int error, error2 = 0;
| 73 int error;
|
74 const u_char *p = (const u_char *) imgp->image_header; 75 struct imgact_gzip igz; 76 struct inflate infl; 77 struct vmspace *vmspace; 78 79 /* If these four are not OK, it isn't a gzip file */ 80 if (p[0] != 0x1f) 81 return -1; /* 0 Simply magic */ 82 if (p[1] != 0x8b) 83 return -1; /* 1 Simply magic */ 84 if (p[2] != 0x08) 85 return -1; /* 2 Compression method */ 86 if (p[9] != 0x03) 87 return -1; /* 9 OS compressed on */ 88 89 /* 90 * If this one contains anything but a comment or a filename marker, 91 * we don't want to chew on it 92 */ 93 if (p[3] & ~(0x18)) 94 return ENOEXEC; /* 3 Flags */ 95 96 /* These are of no use to us */ 97 /* 4-7 Timestamp */ 98 /* 8 Extra flags */ 99 100 bzero(&igz, sizeof igz); 101 bzero(&infl, sizeof infl); 102 infl.gz_private = (void *) &igz; 103 infl.gz_input = NextByte; 104 infl.gz_output = Flush; 105 106 igz.ip = imgp; 107 igz.idx = 10; 108 109 if (p[3] & 0x08) { /* skip a filename */ 110 while (p[igz.idx++]) 111 if (igz.idx >= PAGE_SIZE) 112 return ENOEXEC; 113 } 114 if (p[3] & 0x10) { /* skip a comment */ 115 while (p[igz.idx++]) 116 if (igz.idx >= PAGE_SIZE) 117 return ENOEXEC; 118 } 119 igz.len = imgp->attr->va_size; 120 121 error = inflate(&infl); 122 123 /* 124 * The unzipped file may not even have been long enough to contain 125 * a header giving Flush() a chance to return error. Check for this. 126 */ 127 if ( !igz.gotheader ) 128 return ENOEXEC; 129 130 if ( !error ) { 131 vmspace = imgp->proc->p_vmspace; 132 error = vm_map_protect(&vmspace->vm_map, 133 (vm_offset_t) vmspace->vm_taddr, 134 (vm_offset_t) (vmspace->vm_taddr + 135 (vmspace->vm_tsize << PAGE_SHIFT)) , 136 VM_PROT_READ|VM_PROT_EXECUTE,0); 137 } 138
| 74 const u_char *p = (const u_char *) imgp->image_header; 75 struct imgact_gzip igz; 76 struct inflate infl; 77 struct vmspace *vmspace; 78 79 /* If these four are not OK, it isn't a gzip file */ 80 if (p[0] != 0x1f) 81 return -1; /* 0 Simply magic */ 82 if (p[1] != 0x8b) 83 return -1; /* 1 Simply magic */ 84 if (p[2] != 0x08) 85 return -1; /* 2 Compression method */ 86 if (p[9] != 0x03) 87 return -1; /* 9 OS compressed on */ 88 89 /* 90 * If this one contains anything but a comment or a filename marker, 91 * we don't want to chew on it 92 */ 93 if (p[3] & ~(0x18)) 94 return ENOEXEC; /* 3 Flags */ 95 96 /* These are of no use to us */ 97 /* 4-7 Timestamp */ 98 /* 8 Extra flags */ 99 100 bzero(&igz, sizeof igz); 101 bzero(&infl, sizeof infl); 102 infl.gz_private = (void *) &igz; 103 infl.gz_input = NextByte; 104 infl.gz_output = Flush; 105 106 igz.ip = imgp; 107 igz.idx = 10; 108 109 if (p[3] & 0x08) { /* skip a filename */ 110 while (p[igz.idx++]) 111 if (igz.idx >= PAGE_SIZE) 112 return ENOEXEC; 113 } 114 if (p[3] & 0x10) { /* skip a comment */ 115 while (p[igz.idx++]) 116 if (igz.idx >= PAGE_SIZE) 117 return ENOEXEC; 118 } 119 igz.len = imgp->attr->va_size; 120 121 error = inflate(&infl); 122 123 /* 124 * The unzipped file may not even have been long enough to contain 125 * a header giving Flush() a chance to return error. Check for this. 126 */ 127 if ( !igz.gotheader ) 128 return ENOEXEC; 129 130 if ( !error ) { 131 vmspace = imgp->proc->p_vmspace; 132 error = vm_map_protect(&vmspace->vm_map, 133 (vm_offset_t) vmspace->vm_taddr, 134 (vm_offset_t) (vmspace->vm_taddr + 135 (vmspace->vm_tsize << PAGE_SHIFT)) , 136 VM_PROT_READ|VM_PROT_EXECUTE,0); 137 } 138
|
139 if (igz.inbuf) { 140 error2 = 141 vm_map_remove(kernel_map, (vm_offset_t) igz.inbuf, 142 (vm_offset_t) igz.inbuf + PAGE_SIZE); 143 } 144 if (igz.error || error || error2) {
| 139 if (igz.inbuf) 140 kmem_free_wakeup(exec_map, (vm_offset_t)igz.inbuf, PAGE_SIZE); 141 if (igz.error || error) {
|
145 printf("Output=%lu ", igz.output);
| 142 printf("Output=%lu ", igz.output);
|
146 printf("Inflate_error=%d igz.error=%d error2=%d where=%d\n", 147 error, igz.error, error2, igz.where);
| 143 printf("Inflate_error=%d igz.error=%d where=%d\n", 144 error, igz.error, igz.where);
|
148 } 149 if (igz.error) 150 return igz.error; 151 if (error) 152 return ENOEXEC;
| 145 } 146 if (igz.error) 147 return igz.error; 148 if (error) 149 return ENOEXEC;
|
153 if (error2) 154 return error2;
| |
155 return 0; 156} 157 158static int 159do_aout_hdr(struct imgact_gzip * gz) 160{ 161 int error; 162 struct vmspace *vmspace; 163 vm_offset_t vmaddr; 164 165 /* 166 * Set file/virtual offset based on a.out variant. We do two cases: 167 * host byte order and network byte order (for NetBSD compatibility) 168 */ 169 switch ((int) (gz->a_out.a_magic & 0xffff)) { 170 case ZMAGIC: 171 gz->virtual_offset = 0; 172 if (gz->a_out.a_text) { 173 gz->file_offset = PAGE_SIZE; 174 } else { 175 /* Bill's "screwball mode" */ 176 gz->file_offset = 0; 177 } 178 break; 179 case QMAGIC: 180 gz->virtual_offset = PAGE_SIZE; 181 gz->file_offset = 0; 182 break; 183 default: 184 /* NetBSD compatibility */ 185 switch ((int) (ntohl(gz->a_out.a_magic) & 0xffff)) { 186 case ZMAGIC: 187 case QMAGIC: 188 gz->virtual_offset = PAGE_SIZE; 189 gz->file_offset = 0; 190 break; 191 default: 192 gz->where = __LINE__; 193 return (-1); 194 } 195 } 196 197 gz->bss_size = roundup(gz->a_out.a_bss, PAGE_SIZE); 198 199 /* 200 * Check various fields in header for validity/bounds. 201 */ 202 if ( /* entry point must lay with text region */ 203 gz->a_out.a_entry < gz->virtual_offset || 204 gz->a_out.a_entry >= gz->virtual_offset + gz->a_out.a_text || 205 206 /* text and data size must each be page rounded */ 207 gz->a_out.a_text & PAGE_MASK || gz->a_out.a_data & PAGE_MASK) { 208 gz->where = __LINE__; 209 return (-1); 210 } 211 /* 212 * text/data/bss must not exceed limits 213 */ 214 PROC_LOCK(gz->ip->proc); 215 if ( /* text can't exceed maximum text size */ 216 gz->a_out.a_text > maxtsiz || 217 218 /* data + bss can't exceed rlimit */ 219 gz->a_out.a_data + gz->bss_size > 220 lim_cur(gz->ip->proc, RLIMIT_DATA) || 221 racct_set(gz->ip->proc, RACCT_DATA, 222 gz->a_out.a_data + gz->bss_size) != 0) { 223 PROC_UNLOCK(gz->ip->proc); 224 gz->where = __LINE__; 225 return (ENOMEM); 226 } 227 PROC_UNLOCK(gz->ip->proc); 228 /* Find out how far we should go */ 229 gz->file_end = gz->file_offset + gz->a_out.a_text + gz->a_out.a_data; 230 231 /* 232 * Avoid a possible deadlock if the current address space is destroyed 233 * and that address space maps the locked vnode. In the common case, 234 * the locked vnode's v_usecount is decremented but remains greater 235 * than zero. Consequently, the vnode lock is not needed by vrele(). 236 * However, in cases where the vnode lock is external, such as nullfs, 237 * v_usecount may become zero. 238 */ 239 VOP_UNLOCK(gz->ip->vp, 0); 240 241 /* 242 * Destroy old process VM and create a new one (with a new stack) 243 */ 244 error = exec_new_vmspace(gz->ip, &aout_sysvec); 245 246 vn_lock(gz->ip->vp, LK_EXCLUSIVE | LK_RETRY); 247 if (error) { 248 gz->where = __LINE__; 249 return (error); 250 } 251 252 vmspace = gz->ip->proc->p_vmspace; 253 254 vmaddr = gz->virtual_offset; 255 256 error = vm_mmap(&vmspace->vm_map, 257 &vmaddr, 258 gz->a_out.a_text + gz->a_out.a_data, 259 VM_PROT_ALL, VM_PROT_ALL, MAP_ANON | MAP_FIXED, 260 OBJT_DEFAULT, 261 NULL, 262 0); 263 264 if (error) { 265 gz->where = __LINE__; 266 return (error); 267 } 268 269 if (gz->bss_size != 0) { 270 /* 271 * Allocate demand-zeroed area for uninitialized data. 272 * "bss" = 'block started by symbol' - named after the 273 * IBM 7090 instruction of the same name. 274 */ 275 vmaddr = gz->virtual_offset + gz->a_out.a_text + 276 gz->a_out.a_data; 277 error = vm_map_find(&vmspace->vm_map, 278 NULL, 279 0, 280 &vmaddr, 281 gz->bss_size, 282 FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); 283 if (error) { 284 gz->where = __LINE__; 285 return (error); 286 } 287 } 288 /* Fill in process VM information */ 289 vmspace->vm_tsize = gz->a_out.a_text >> PAGE_SHIFT; 290 vmspace->vm_dsize = (gz->a_out.a_data + gz->bss_size) >> PAGE_SHIFT; 291 vmspace->vm_taddr = (caddr_t) (uintptr_t) gz->virtual_offset; 292 vmspace->vm_daddr = (caddr_t) (uintptr_t) 293 (gz->virtual_offset + gz->a_out.a_text); 294 295 /* Fill in image_params */ 296 gz->ip->interpreted = 0; 297 gz->ip->entry_addr = gz->a_out.a_entry; 298 299 gz->ip->proc->p_sysent = &aout_sysvec; 300 301 return 0; 302} 303 304static int 305NextByte(void *vp) 306{ 307 int error; 308 struct imgact_gzip *igz = (struct imgact_gzip *) vp; 309 310 if (igz->idx >= igz->len) { 311 igz->where = __LINE__; 312 return GZ_EOF; 313 } 314 if (igz->inbuf && igz->idx < (igz->offset + PAGE_SIZE)) { 315 return igz->inbuf[(igz->idx++) - igz->offset]; 316 }
| 150 return 0; 151} 152 153static int 154do_aout_hdr(struct imgact_gzip * gz) 155{ 156 int error; 157 struct vmspace *vmspace; 158 vm_offset_t vmaddr; 159 160 /* 161 * Set file/virtual offset based on a.out variant. We do two cases: 162 * host byte order and network byte order (for NetBSD compatibility) 163 */ 164 switch ((int) (gz->a_out.a_magic & 0xffff)) { 165 case ZMAGIC: 166 gz->virtual_offset = 0; 167 if (gz->a_out.a_text) { 168 gz->file_offset = PAGE_SIZE; 169 } else { 170 /* Bill's "screwball mode" */ 171 gz->file_offset = 0; 172 } 173 break; 174 case QMAGIC: 175 gz->virtual_offset = PAGE_SIZE; 176 gz->file_offset = 0; 177 break; 178 default: 179 /* NetBSD compatibility */ 180 switch ((int) (ntohl(gz->a_out.a_magic) & 0xffff)) { 181 case ZMAGIC: 182 case QMAGIC: 183 gz->virtual_offset = PAGE_SIZE; 184 gz->file_offset = 0; 185 break; 186 default: 187 gz->where = __LINE__; 188 return (-1); 189 } 190 } 191 192 gz->bss_size = roundup(gz->a_out.a_bss, PAGE_SIZE); 193 194 /* 195 * Check various fields in header for validity/bounds. 196 */ 197 if ( /* entry point must lay with text region */ 198 gz->a_out.a_entry < gz->virtual_offset || 199 gz->a_out.a_entry >= gz->virtual_offset + gz->a_out.a_text || 200 201 /* text and data size must each be page rounded */ 202 gz->a_out.a_text & PAGE_MASK || gz->a_out.a_data & PAGE_MASK) { 203 gz->where = __LINE__; 204 return (-1); 205 } 206 /* 207 * text/data/bss must not exceed limits 208 */ 209 PROC_LOCK(gz->ip->proc); 210 if ( /* text can't exceed maximum text size */ 211 gz->a_out.a_text > maxtsiz || 212 213 /* data + bss can't exceed rlimit */ 214 gz->a_out.a_data + gz->bss_size > 215 lim_cur(gz->ip->proc, RLIMIT_DATA) || 216 racct_set(gz->ip->proc, RACCT_DATA, 217 gz->a_out.a_data + gz->bss_size) != 0) { 218 PROC_UNLOCK(gz->ip->proc); 219 gz->where = __LINE__; 220 return (ENOMEM); 221 } 222 PROC_UNLOCK(gz->ip->proc); 223 /* Find out how far we should go */ 224 gz->file_end = gz->file_offset + gz->a_out.a_text + gz->a_out.a_data; 225 226 /* 227 * Avoid a possible deadlock if the current address space is destroyed 228 * and that address space maps the locked vnode. In the common case, 229 * the locked vnode's v_usecount is decremented but remains greater 230 * than zero. Consequently, the vnode lock is not needed by vrele(). 231 * However, in cases where the vnode lock is external, such as nullfs, 232 * v_usecount may become zero. 233 */ 234 VOP_UNLOCK(gz->ip->vp, 0); 235 236 /* 237 * Destroy old process VM and create a new one (with a new stack) 238 */ 239 error = exec_new_vmspace(gz->ip, &aout_sysvec); 240 241 vn_lock(gz->ip->vp, LK_EXCLUSIVE | LK_RETRY); 242 if (error) { 243 gz->where = __LINE__; 244 return (error); 245 } 246 247 vmspace = gz->ip->proc->p_vmspace; 248 249 vmaddr = gz->virtual_offset; 250 251 error = vm_mmap(&vmspace->vm_map, 252 &vmaddr, 253 gz->a_out.a_text + gz->a_out.a_data, 254 VM_PROT_ALL, VM_PROT_ALL, MAP_ANON | MAP_FIXED, 255 OBJT_DEFAULT, 256 NULL, 257 0); 258 259 if (error) { 260 gz->where = __LINE__; 261 return (error); 262 } 263 264 if (gz->bss_size != 0) { 265 /* 266 * Allocate demand-zeroed area for uninitialized data. 267 * "bss" = 'block started by symbol' - named after the 268 * IBM 7090 instruction of the same name. 269 */ 270 vmaddr = gz->virtual_offset + gz->a_out.a_text + 271 gz->a_out.a_data; 272 error = vm_map_find(&vmspace->vm_map, 273 NULL, 274 0, 275 &vmaddr, 276 gz->bss_size, 277 FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); 278 if (error) { 279 gz->where = __LINE__; 280 return (error); 281 } 282 } 283 /* Fill in process VM information */ 284 vmspace->vm_tsize = gz->a_out.a_text >> PAGE_SHIFT; 285 vmspace->vm_dsize = (gz->a_out.a_data + gz->bss_size) >> PAGE_SHIFT; 286 vmspace->vm_taddr = (caddr_t) (uintptr_t) gz->virtual_offset; 287 vmspace->vm_daddr = (caddr_t) (uintptr_t) 288 (gz->virtual_offset + gz->a_out.a_text); 289 290 /* Fill in image_params */ 291 gz->ip->interpreted = 0; 292 gz->ip->entry_addr = gz->a_out.a_entry; 293 294 gz->ip->proc->p_sysent = &aout_sysvec; 295 296 return 0; 297} 298 299static int 300NextByte(void *vp) 301{ 302 int error; 303 struct imgact_gzip *igz = (struct imgact_gzip *) vp; 304 305 if (igz->idx >= igz->len) { 306 igz->where = __LINE__; 307 return GZ_EOF; 308 } 309 if (igz->inbuf && igz->idx < (igz->offset + PAGE_SIZE)) { 310 return igz->inbuf[(igz->idx++) - igz->offset]; 311 }
|
317 if (igz->inbuf) { 318 error = vm_map_remove(kernel_map, (vm_offset_t) igz->inbuf, 319 (vm_offset_t) igz->inbuf + PAGE_SIZE); 320 if (error) { 321 igz->where = __LINE__; 322 igz->error = error; 323 return GZ_EOF; 324 } 325 }
| 312 if (igz->inbuf) 313 kmem_free_wakeup(exec_map, (vm_offset_t)igz->inbuf, PAGE_SIZE);
|
326 igz->offset = igz->idx & ~PAGE_MASK; 327
| 314 igz->offset = igz->idx & ~PAGE_MASK; 315
|
328 error = vm_mmap(kernel_map, /* map */
| 316 error = vm_mmap(exec_map, /* map */
|
329 (vm_offset_t *) & igz->inbuf, /* address */ 330 PAGE_SIZE, /* size */ 331 VM_PROT_READ, /* protection */ 332 VM_PROT_READ, /* max protection */ 333 0, /* flags */ 334 OBJT_VNODE, /* handle type */ 335 igz->ip->vp, /* vnode */ 336 igz->offset); /* offset */ 337 if (error) { 338 igz->where = __LINE__; 339 igz->error = error; 340 return GZ_EOF; 341 } 342 return igz->inbuf[(igz->idx++) - igz->offset]; 343} 344 345static int 346Flush(void *vp, u_char * ptr, u_long siz) 347{ 348 struct imgact_gzip *gz = (struct imgact_gzip *) vp; 349 u_char *p = ptr, *q; 350 int i; 351 352 /* First, find an a.out-header. */ 353 if (gz->output < sizeof gz->a_out) { 354 q = (u_char *) & gz->a_out; 355 i = min(siz, sizeof gz->a_out - gz->output); 356 bcopy(p, q + gz->output, i); 357 gz->output += i; 358 p += i; 359 siz -= i; 360 if (gz->output == sizeof gz->a_out) { 361 gz->gotheader = 1; 362 i = do_aout_hdr(gz); 363 if (i == -1) { 364 if (!gz->where) 365 gz->where = __LINE__; 366 gz->error = ENOEXEC; 367 return ENOEXEC; 368 } else if (i) { 369 gz->where = __LINE__; 370 gz->error = i; 371 return ENOEXEC; 372 } 373 if (gz->file_offset == 0) { 374 q = (u_char *) (uintptr_t) gz->virtual_offset; 375 copyout(&gz->a_out, q, sizeof gz->a_out); 376 } 377 } 378 } 379 /* Skip over zero-padded first PAGE if needed */ 380 if (gz->output < gz->file_offset && 381 gz->output + siz > gz->file_offset) { 382 i = min(siz, gz->file_offset - gz->output); 383 gz->output += i; 384 p += i; 385 siz -= i; 386 } 387 if (gz->output >= gz->file_offset && gz->output < gz->file_end) { 388 i = min(siz, gz->file_end - gz->output); 389 q = (u_char *) (uintptr_t) 390 (gz->virtual_offset + gz->output - gz->file_offset); 391 copyout(p, q, i); 392 gz->output += i; 393 p += i; 394 siz -= i; 395 } 396 gz->output += siz; 397 return 0; 398} 399 400 401/* 402 * Tell kern_execve.c about it, with a little help from the linker. 403 */ 404static struct execsw gzip_execsw = {exec_gzip_imgact, "gzip"}; 405EXEC_SET(execgzip, gzip_execsw);
| 317 (vm_offset_t *) & igz->inbuf, /* address */ 318 PAGE_SIZE, /* size */ 319 VM_PROT_READ, /* protection */ 320 VM_PROT_READ, /* max protection */ 321 0, /* flags */ 322 OBJT_VNODE, /* handle type */ 323 igz->ip->vp, /* vnode */ 324 igz->offset); /* offset */ 325 if (error) { 326 igz->where = __LINE__; 327 igz->error = error; 328 return GZ_EOF; 329 } 330 return igz->inbuf[(igz->idx++) - igz->offset]; 331} 332 333static int 334Flush(void *vp, u_char * ptr, u_long siz) 335{ 336 struct imgact_gzip *gz = (struct imgact_gzip *) vp; 337 u_char *p = ptr, *q; 338 int i; 339 340 /* First, find an a.out-header. */ 341 if (gz->output < sizeof gz->a_out) { 342 q = (u_char *) & gz->a_out; 343 i = min(siz, sizeof gz->a_out - gz->output); 344 bcopy(p, q + gz->output, i); 345 gz->output += i; 346 p += i; 347 siz -= i; 348 if (gz->output == sizeof gz->a_out) { 349 gz->gotheader = 1; 350 i = do_aout_hdr(gz); 351 if (i == -1) { 352 if (!gz->where) 353 gz->where = __LINE__; 354 gz->error = ENOEXEC; 355 return ENOEXEC; 356 } else if (i) { 357 gz->where = __LINE__; 358 gz->error = i; 359 return ENOEXEC; 360 } 361 if (gz->file_offset == 0) { 362 q = (u_char *) (uintptr_t) gz->virtual_offset; 363 copyout(&gz->a_out, q, sizeof gz->a_out); 364 } 365 } 366 } 367 /* Skip over zero-padded first PAGE if needed */ 368 if (gz->output < gz->file_offset && 369 gz->output + siz > gz->file_offset) { 370 i = min(siz, gz->file_offset - gz->output); 371 gz->output += i; 372 p += i; 373 siz -= i; 374 } 375 if (gz->output >= gz->file_offset && gz->output < gz->file_end) { 376 i = min(siz, gz->file_end - gz->output); 377 q = (u_char *) (uintptr_t) 378 (gz->virtual_offset + gz->output - gz->file_offset); 379 copyout(p, q, i); 380 gz->output += i; 381 p += i; 382 siz -= i; 383 } 384 gz->output += siz; 385 return 0; 386} 387 388 389/* 390 * Tell kern_execve.c about it, with a little help from the linker. 391 */ 392static struct execsw gzip_execsw = {exec_gzip_imgact, "gzip"}; 393EXEC_SET(execgzip, gzip_execsw);
|