57int 58exec_gzip_imgact(iparams) 59 struct image_params *iparams; 60{ 61 int error, error2 = 0; 62 u_char *p = (u_char *) iparams->image_header; 63 struct imgact_gzip igz; 64 struct inflate infl; 65 66 /* If these four are not OK, it isn't a gzip file */ 67 if (p[0] != 0x1f) 68 return -1; /* 0 Simply magic */ 69 if (p[1] != 0x8b) 70 return -1; /* 1 Simply magic */ 71 if (p[2] != 0x08) 72 return -1; /* 2 Compression method */ 73 if (p[9] != 0x03) 74 return -1; /* 9 OS compressed on */ 75 76 /* 77 * If this one contains anything but a comment or a filename marker, 78 * we don't want to chew on it 79 */ 80 if (p[3] & ~(0x18)) 81 return ENOEXEC; /* 3 Flags */ 82 83 /* These are of no use to us */ 84 /* 4-7 Timestamp */ 85 /* 8 Extra flags */ 86 87 bzero(&igz, sizeof igz); 88 bzero(&infl, sizeof infl); 89 infl.gz_private = (void *) &igz; 90 infl.gz_input = NextByte; 91 infl.gz_output = Flush; 92 93 igz.ip = iparams; 94 igz.idx = 10; 95 96 if (p[3] & 0x08) { /* skip a filename */ 97 while (p[igz.idx++]) 98 if (igz.idx >= PAGE_SIZE) 99 return ENOEXEC; 100 } 101 if (p[3] & 0x10) { /* skip a comment */ 102 while (p[igz.idx++]) 103 if (igz.idx >= PAGE_SIZE) 104 return ENOEXEC; 105 } 106 igz.len = igz.ip->attr->va_size; 107 108 error = inflate(&infl); 109 110 if (igz.inbuf) { 111 error2 = 112 vm_map_remove(kernel_map, (vm_offset_t) igz.inbuf, 113 (vm_offset_t) igz.inbuf + PAGE_SIZE); 114 } 115 if (igz.error || error || error2) { 116 printf("Output=%lu ", igz.output); 117 printf("Inflate_error=%d igz.error=%d error2=%d where=%d\n", 118 error, igz.error, error2, igz.where); 119 } 120 if (igz.error) 121 return igz.error; 122 if (error) 123 return ENOEXEC; 124 if (error2) 125 return error2; 126 return 0; 127} 128 129static int 130do_aout_hdr(struct imgact_gzip * gz) 131{ 132 int error; 133 struct vmspace *vmspace = gz->ip->proc->p_vmspace; 134 u_long vmaddr; 135 136 /* 137 * Set file/virtual offset based on a.out variant. We do two cases: 138 * host byte order and network byte order (for NetBSD compatibility) 139 */ 140 switch ((int) (gz->a_out.a_magic & 0xffff)) { 141 case ZMAGIC: 142 gz->virtual_offset = 0; 143 if (gz->a_out.a_text) { 144 gz->file_offset = NBPG; 145 } else { 146 /* Bill's "screwball mode" */ 147 gz->file_offset = 0; 148 } 149 break; 150 case QMAGIC: 151 gz->virtual_offset = NBPG; 152 gz->file_offset = 0; 153 break; 154 default: 155 /* NetBSD compatibility */ 156 switch ((int) (ntohl(gz->a_out.a_magic) & 0xffff)) { 157 case ZMAGIC: 158 case QMAGIC: 159 gz->virtual_offset = NBPG; 160 gz->file_offset = 0; 161 break; 162 default: 163 gz->where = __LINE__; 164 return (-1); 165 } 166 } 167 168 gz->bss_size = roundup(gz->a_out.a_bss, NBPG); 169 170 /* 171 * Check various fields in header for validity/bounds. 172 */ 173 if ( /* entry point must lay with text region */ 174 gz->a_out.a_entry < gz->virtual_offset || 175 gz->a_out.a_entry >= gz->virtual_offset + gz->a_out.a_text || 176 177 /* text and data size must each be page rounded */ 178 gz->a_out.a_text % NBPG || 179 gz->a_out.a_data % NBPG) { 180 gz->where = __LINE__; 181 return (-1); 182 } 183 /* 184 * text/data/bss must not exceed limits 185 */ 186 if ( /* text can't exceed maximum text size */ 187 gz->a_out.a_text > MAXTSIZ || 188 189 /* data + bss can't exceed maximum data size */ 190 gz->a_out.a_data + gz->bss_size > MAXDSIZ || 191 192 /* data + bss can't exceed rlimit */ 193 gz->a_out.a_data + gz->bss_size > 194 gz->ip->proc->p_rlimit[RLIMIT_DATA].rlim_cur) { 195 gz->where = __LINE__; 196 return (ENOMEM); 197 } 198 /* Find out how far we should go */ 199 gz->file_end = gz->file_offset + gz->a_out.a_text + gz->a_out.a_data; 200 201 /* copy in arguments and/or environment from old process */ 202 error = exec_extract_strings(gz->ip); 203 if (error) { 204 gz->where = __LINE__; 205 return (error); 206 } 207 /* 208 * Destroy old process VM and create a new one (with a new stack) 209 */ 210 exec_new_vmspace(gz->ip); 211 212 vmaddr = gz->virtual_offset; 213 214 error = vm_mmap(&vmspace->vm_map, /* map */ 215 &vmaddr,/* address */ 216 gz->a_out.a_text, /* size */ 217 VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_WRITE, /* protection */ 218 VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_WRITE, 219 MAP_ANON | MAP_FIXED, /* flags */ 220 0, /* vnode */ 221 0); /* offset */ 222 223 if (error) { 224 gz->where = __LINE__; 225 return (error); 226 } 227 vmaddr = gz->virtual_offset + gz->a_out.a_text; 228 229 /* 230 * Map data read/write (if text is 0, assume text is in data area 231 * [Bill's screwball mode]) 232 */ 233 234 error = vm_mmap(&vmspace->vm_map, 235 &vmaddr, 236 gz->a_out.a_data, 237 VM_PROT_READ | VM_PROT_WRITE | (gz->a_out.a_text ? 0 : VM_PROT_EXECUTE), 238 VM_PROT_ALL, MAP_ANON | MAP_FIXED, 239 0, 240 0); 241 242 if (error) { 243 gz->where = __LINE__; 244 return (error); 245 } 246 if (gz->bss_size != 0) { 247 /* 248 * Allocate demand-zeroed area for uninitialized data "bss" = 'block 249 * started by symbol' - named after the IBM 7090 instruction of the 250 * same name. 251 */ 252 vmaddr = gz->virtual_offset + gz->a_out.a_text + gz->a_out.a_data; 253 error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, gz->bss_size, FALSE); 254 if (error) { 255 gz->where = __LINE__; 256 return (error); 257 } 258 } 259 /* Fill in process VM information */ 260 vmspace->vm_tsize = gz->a_out.a_text >> PAGE_SHIFT; 261 vmspace->vm_dsize = (gz->a_out.a_data + gz->bss_size) >> PAGE_SHIFT; 262 vmspace->vm_taddr = (caddr_t) gz->virtual_offset; 263 vmspace->vm_daddr = (caddr_t) gz->virtual_offset + gz->a_out.a_text; 264 265 /* Fill in image_params */ 266 gz->ip->interpreted = 0; 267 gz->ip->entry_addr = gz->a_out.a_entry; 268 269 gz->ip->proc->p_sysent = &aout_sysvec; 270 271 return 0; 272} 273 274static int 275NextByte(void *vp) 276{ 277 int error; 278 struct imgact_gzip *igz = (struct imgact_gzip *) vp; 279 280 if (igz->idx >= igz->len) { 281 igz->where = __LINE__; 282 return GZ_EOF; 283 } 284 if (igz->inbuf && igz->idx < (igz->offset + PAGE_SIZE)) { 285 return igz->inbuf[(igz->idx++) - igz->offset]; 286 } 287 if (igz->inbuf) { 288 error = vm_map_remove(kernel_map, (vm_offset_t) igz->inbuf, 289 (vm_offset_t) igz->inbuf + PAGE_SIZE); 290 if (error) { 291 igz->where = __LINE__; 292 igz->error = error; 293 return GZ_EOF; 294 } 295 } 296 igz->offset = igz->idx & ~PAGE_MASK; 297 298 error = vm_mmap(kernel_map, /* map */ 299 (vm_offset_t *) & igz->inbuf, /* address */ 300 PAGE_SIZE, /* size */ 301 VM_PROT_READ, /* protection */ 302 VM_PROT_READ, /* max protection */ 303 0, /* flags */ 304 (caddr_t) igz->ip->vnodep, /* vnode */ 305 igz->offset); /* offset */ 306 if (error) { 307 igz->where = __LINE__; 308 igz->error = error; 309 return GZ_EOF; 310 } 311 return igz->inbuf[(igz->idx++) - igz->offset]; 312} 313 314static int 315Flush(void *vp, u_char * ptr, u_long siz) 316{ 317 struct imgact_gzip *gz = (struct imgact_gzip *) vp; 318 u_char *p = ptr, *q; 319 int i; 320 321 /* First, find a a.out-header */ 322 if (gz->output < sizeof gz->a_out) { 323 q = (u_char *) & gz->a_out; 324 i = min(siz, sizeof gz->a_out - gz->output); 325 bcopy(p, q + gz->output, i); 326 gz->output += i; 327 p += i; 328 siz -= i; 329 if (gz->output == sizeof gz->a_out) { 330 i = do_aout_hdr(gz); 331 if (i == -1) { 332 if (!gz->where) 333 gz->where = __LINE__; 334 gz->error = ENOEXEC; 335 return ENOEXEC; 336 } else if (i) { 337 gz->where = __LINE__; 338 gz->error = i; 339 return ENOEXEC; 340 } 341 if (gz->file_offset < sizeof gz->a_out) { 342 q = (u_char *) gz->virtual_offset + gz->output - gz->file_offset; 343 bcopy(&gz->a_out, q, sizeof gz->a_out - gz->file_offset); 344 } 345 } 346 } 347 /* Skip over zero-padded first PAGE if needed */ 348 if (gz->output < gz->file_offset && (gz->output + siz) > gz->file_offset) { 349 i = min(siz, gz->file_offset - gz->output); 350 gz->output += i; 351 p += i; 352 siz -= i; 353 } 354 if (gz->output >= gz->file_offset && gz->output < gz->file_end) { 355 i = min(siz, gz->file_end - gz->output); 356 q = (u_char *) gz->virtual_offset + gz->output - gz->file_offset; 357 bcopy(p, q, i); 358 gz->output += i; 359 p += i; 360 siz -= i; 361 } 362 gz->output += siz; 363 return 0; 364} 365 366 367/* 368 * Tell kern_execve.c about it, with a little help from the linker. 369 * Since `const' objects end up in the text segment, TEXT_SET is the 370 * correct directive to use. 371 */ 372 373static const struct execsw gzip_execsw = {exec_gzip_imgact, "gzip"}; 374TEXT_SET(execsw_set, gzip_execsw);
| 55int 56exec_gzip_imgact(iparams) 57 struct image_params *iparams; 58{ 59 int error, error2 = 0; 60 u_char *p = (u_char *) iparams->image_header; 61 struct imgact_gzip igz; 62 struct inflate infl; 63 64 /* If these four are not OK, it isn't a gzip file */ 65 if (p[0] != 0x1f) 66 return -1; /* 0 Simply magic */ 67 if (p[1] != 0x8b) 68 return -1; /* 1 Simply magic */ 69 if (p[2] != 0x08) 70 return -1; /* 2 Compression method */ 71 if (p[9] != 0x03) 72 return -1; /* 9 OS compressed on */ 73 74 /* 75 * If this one contains anything but a comment or a filename marker, 76 * we don't want to chew on it 77 */ 78 if (p[3] & ~(0x18)) 79 return ENOEXEC; /* 3 Flags */ 80 81 /* These are of no use to us */ 82 /* 4-7 Timestamp */ 83 /* 8 Extra flags */ 84 85 bzero(&igz, sizeof igz); 86 bzero(&infl, sizeof infl); 87 infl.gz_private = (void *) &igz; 88 infl.gz_input = NextByte; 89 infl.gz_output = Flush; 90 91 igz.ip = iparams; 92 igz.idx = 10; 93 94 if (p[3] & 0x08) { /* skip a filename */ 95 while (p[igz.idx++]) 96 if (igz.idx >= PAGE_SIZE) 97 return ENOEXEC; 98 } 99 if (p[3] & 0x10) { /* skip a comment */ 100 while (p[igz.idx++]) 101 if (igz.idx >= PAGE_SIZE) 102 return ENOEXEC; 103 } 104 igz.len = igz.ip->attr->va_size; 105 106 error = inflate(&infl); 107 108 if (igz.inbuf) { 109 error2 = 110 vm_map_remove(kernel_map, (vm_offset_t) igz.inbuf, 111 (vm_offset_t) igz.inbuf + PAGE_SIZE); 112 } 113 if (igz.error || error || error2) { 114 printf("Output=%lu ", igz.output); 115 printf("Inflate_error=%d igz.error=%d error2=%d where=%d\n", 116 error, igz.error, error2, igz.where); 117 } 118 if (igz.error) 119 return igz.error; 120 if (error) 121 return ENOEXEC; 122 if (error2) 123 return error2; 124 return 0; 125} 126 127static int 128do_aout_hdr(struct imgact_gzip * gz) 129{ 130 int error; 131 struct vmspace *vmspace = gz->ip->proc->p_vmspace; 132 u_long vmaddr; 133 134 /* 135 * Set file/virtual offset based on a.out variant. We do two cases: 136 * host byte order and network byte order (for NetBSD compatibility) 137 */ 138 switch ((int) (gz->a_out.a_magic & 0xffff)) { 139 case ZMAGIC: 140 gz->virtual_offset = 0; 141 if (gz->a_out.a_text) { 142 gz->file_offset = NBPG; 143 } else { 144 /* Bill's "screwball mode" */ 145 gz->file_offset = 0; 146 } 147 break; 148 case QMAGIC: 149 gz->virtual_offset = NBPG; 150 gz->file_offset = 0; 151 break; 152 default: 153 /* NetBSD compatibility */ 154 switch ((int) (ntohl(gz->a_out.a_magic) & 0xffff)) { 155 case ZMAGIC: 156 case QMAGIC: 157 gz->virtual_offset = NBPG; 158 gz->file_offset = 0; 159 break; 160 default: 161 gz->where = __LINE__; 162 return (-1); 163 } 164 } 165 166 gz->bss_size = roundup(gz->a_out.a_bss, NBPG); 167 168 /* 169 * Check various fields in header for validity/bounds. 170 */ 171 if ( /* entry point must lay with text region */ 172 gz->a_out.a_entry < gz->virtual_offset || 173 gz->a_out.a_entry >= gz->virtual_offset + gz->a_out.a_text || 174 175 /* text and data size must each be page rounded */ 176 gz->a_out.a_text % NBPG || 177 gz->a_out.a_data % NBPG) { 178 gz->where = __LINE__; 179 return (-1); 180 } 181 /* 182 * text/data/bss must not exceed limits 183 */ 184 if ( /* text can't exceed maximum text size */ 185 gz->a_out.a_text > MAXTSIZ || 186 187 /* data + bss can't exceed maximum data size */ 188 gz->a_out.a_data + gz->bss_size > MAXDSIZ || 189 190 /* data + bss can't exceed rlimit */ 191 gz->a_out.a_data + gz->bss_size > 192 gz->ip->proc->p_rlimit[RLIMIT_DATA].rlim_cur) { 193 gz->where = __LINE__; 194 return (ENOMEM); 195 } 196 /* Find out how far we should go */ 197 gz->file_end = gz->file_offset + gz->a_out.a_text + gz->a_out.a_data; 198 199 /* copy in arguments and/or environment from old process */ 200 error = exec_extract_strings(gz->ip); 201 if (error) { 202 gz->where = __LINE__; 203 return (error); 204 } 205 /* 206 * Destroy old process VM and create a new one (with a new stack) 207 */ 208 exec_new_vmspace(gz->ip); 209 210 vmaddr = gz->virtual_offset; 211 212 error = vm_mmap(&vmspace->vm_map, /* map */ 213 &vmaddr,/* address */ 214 gz->a_out.a_text, /* size */ 215 VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_WRITE, /* protection */ 216 VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_WRITE, 217 MAP_ANON | MAP_FIXED, /* flags */ 218 0, /* vnode */ 219 0); /* offset */ 220 221 if (error) { 222 gz->where = __LINE__; 223 return (error); 224 } 225 vmaddr = gz->virtual_offset + gz->a_out.a_text; 226 227 /* 228 * Map data read/write (if text is 0, assume text is in data area 229 * [Bill's screwball mode]) 230 */ 231 232 error = vm_mmap(&vmspace->vm_map, 233 &vmaddr, 234 gz->a_out.a_data, 235 VM_PROT_READ | VM_PROT_WRITE | (gz->a_out.a_text ? 0 : VM_PROT_EXECUTE), 236 VM_PROT_ALL, MAP_ANON | MAP_FIXED, 237 0, 238 0); 239 240 if (error) { 241 gz->where = __LINE__; 242 return (error); 243 } 244 if (gz->bss_size != 0) { 245 /* 246 * Allocate demand-zeroed area for uninitialized data "bss" = 'block 247 * started by symbol' - named after the IBM 7090 instruction of the 248 * same name. 249 */ 250 vmaddr = gz->virtual_offset + gz->a_out.a_text + gz->a_out.a_data; 251 error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, gz->bss_size, FALSE); 252 if (error) { 253 gz->where = __LINE__; 254 return (error); 255 } 256 } 257 /* Fill in process VM information */ 258 vmspace->vm_tsize = gz->a_out.a_text >> PAGE_SHIFT; 259 vmspace->vm_dsize = (gz->a_out.a_data + gz->bss_size) >> PAGE_SHIFT; 260 vmspace->vm_taddr = (caddr_t) gz->virtual_offset; 261 vmspace->vm_daddr = (caddr_t) gz->virtual_offset + gz->a_out.a_text; 262 263 /* Fill in image_params */ 264 gz->ip->interpreted = 0; 265 gz->ip->entry_addr = gz->a_out.a_entry; 266 267 gz->ip->proc->p_sysent = &aout_sysvec; 268 269 return 0; 270} 271 272static int 273NextByte(void *vp) 274{ 275 int error; 276 struct imgact_gzip *igz = (struct imgact_gzip *) vp; 277 278 if (igz->idx >= igz->len) { 279 igz->where = __LINE__; 280 return GZ_EOF; 281 } 282 if (igz->inbuf && igz->idx < (igz->offset + PAGE_SIZE)) { 283 return igz->inbuf[(igz->idx++) - igz->offset]; 284 } 285 if (igz->inbuf) { 286 error = vm_map_remove(kernel_map, (vm_offset_t) igz->inbuf, 287 (vm_offset_t) igz->inbuf + PAGE_SIZE); 288 if (error) { 289 igz->where = __LINE__; 290 igz->error = error; 291 return GZ_EOF; 292 } 293 } 294 igz->offset = igz->idx & ~PAGE_MASK; 295 296 error = vm_mmap(kernel_map, /* map */ 297 (vm_offset_t *) & igz->inbuf, /* address */ 298 PAGE_SIZE, /* size */ 299 VM_PROT_READ, /* protection */ 300 VM_PROT_READ, /* max protection */ 301 0, /* flags */ 302 (caddr_t) igz->ip->vnodep, /* vnode */ 303 igz->offset); /* offset */ 304 if (error) { 305 igz->where = __LINE__; 306 igz->error = error; 307 return GZ_EOF; 308 } 309 return igz->inbuf[(igz->idx++) - igz->offset]; 310} 311 312static int 313Flush(void *vp, u_char * ptr, u_long siz) 314{ 315 struct imgact_gzip *gz = (struct imgact_gzip *) vp; 316 u_char *p = ptr, *q; 317 int i; 318 319 /* First, find a a.out-header */ 320 if (gz->output < sizeof gz->a_out) { 321 q = (u_char *) & gz->a_out; 322 i = min(siz, sizeof gz->a_out - gz->output); 323 bcopy(p, q + gz->output, i); 324 gz->output += i; 325 p += i; 326 siz -= i; 327 if (gz->output == sizeof gz->a_out) { 328 i = do_aout_hdr(gz); 329 if (i == -1) { 330 if (!gz->where) 331 gz->where = __LINE__; 332 gz->error = ENOEXEC; 333 return ENOEXEC; 334 } else if (i) { 335 gz->where = __LINE__; 336 gz->error = i; 337 return ENOEXEC; 338 } 339 if (gz->file_offset < sizeof gz->a_out) { 340 q = (u_char *) gz->virtual_offset + gz->output - gz->file_offset; 341 bcopy(&gz->a_out, q, sizeof gz->a_out - gz->file_offset); 342 } 343 } 344 } 345 /* Skip over zero-padded first PAGE if needed */ 346 if (gz->output < gz->file_offset && (gz->output + siz) > gz->file_offset) { 347 i = min(siz, gz->file_offset - gz->output); 348 gz->output += i; 349 p += i; 350 siz -= i; 351 } 352 if (gz->output >= gz->file_offset && gz->output < gz->file_end) { 353 i = min(siz, gz->file_end - gz->output); 354 q = (u_char *) gz->virtual_offset + gz->output - gz->file_offset; 355 bcopy(p, q, i); 356 gz->output += i; 357 p += i; 358 siz -= i; 359 } 360 gz->output += siz; 361 return 0; 362} 363 364 365/* 366 * Tell kern_execve.c about it, with a little help from the linker. 367 * Since `const' objects end up in the text segment, TEXT_SET is the 368 * correct directive to use. 369 */ 370 371static const struct execsw gzip_execsw = {exec_gzip_imgact, "gzip"}; 372TEXT_SET(execsw_set, gzip_execsw);
|