40 41#include <vm/vm.h> 42#include <vm/vm_kern.h> 43 44extern struct sysentvec aout_sysvec; 45 46int 47exec_gzip_imgact(iparams) 48 struct image_params *iparams; 49{ 50 int error,error2=0; 51 u_char *p = (u_char *) iparams->image_header; 52 struct gzip *gz; 53 struct gz_global gz_glbl; 54 55 /* If these four are not OK, it isn't a gzip file */ 56 if (p[0] != 0x1f) return -1; /* 0 Simply magic */ 57 if (p[1] != 0x8b) return -1; /* 1 Simply magic */ 58 if (p[2] != 0x08) return -1; /* 2 Compression method */ 59 if (p[9] != 0x03) return -1; /* 9 OS compressed on */ 60 61 /* If this one contains anything but a comment or a filename 62 * marker, we don't want to chew on it 63 */ 64 if (p[3] & ~(0x18)) return ENOEXEC; /* 3 Flags */ 65 66 /* These are of no use to us */ 67 /* 4-7 Timestamp */ 68 /* 8 Extra flags */ 69 70 gz = malloc(sizeof *gz,M_GZIP,M_NOWAIT); 71 if (!gz) 72 return ENOMEM; 73 bzero(gz,sizeof *gz); /* waste of time ? */ 74 75 gz->gz_slide = malloc(WSIZE,M_TEMP,M_NOWAIT); 76 if (!gz->gz_slide) { 77 free(gz,M_GZIP); 78 return ENOMEM; 79 } 80 81 gz->ip = iparams; 82 gz->error = ENOEXEC; 83 gz->idx = 10; 84 85 if (p[3] & 0x08) { /* skip a filename */ 86 while (p[gz->idx++]) 87 if (gz->idx >= PAGE_SIZE) 88 goto done; 89 } 90 91 if (p[3] & 0x10) { /* skip a comment */ 92 while (p[gz->idx++]) 93 if (gz->idx >= PAGE_SIZE) 94 goto done; 95 } 96 97 gz->len = gz->ip->attr->va_size; 98 99 gz->error = 0; 100 101 error = inflate(gz, &gz_glbl); 102 103 if (gz->inbuf) { 104 error2 = 105 vm_deallocate(kernel_map, (vm_offset_t)gz->inbuf, PAGE_SIZE); 106 } 107 108 if (gz->error || error || error2) { 109 printf("Output=%lu ",gz->output); 110 printf("Inflate_error=%d gz->error=%d error2=%d where=%d\n", 111 error,gz->error,error2,gz->where); 112 if (gz->error) 113 goto done; 114 if (error) { 115 gz->error = ENOEXEC; 116 goto done; 117 } 118 if (error2) { 119 gz->error = error2; 120 goto done; 121 } 122 } 123 124 done: 125 error = gz->error; 126 free(gz->gz_slide,M_TEMP); 127 free(gz,M_GZIP); 128 return error; 129} 130 131int 132do_aout_hdr(struct gzip *gz) 133{ 134 int error; 135 struct vmspace *vmspace = gz->ip->proc->p_vmspace; 136 u_long vmaddr; 137 138 /* 139 * Set file/virtual offset based on a.out variant. 140 * We do two cases: host byte order and network byte order 141 * (for NetBSD compatibility) 142 */ 143 switch ((int)(gz->a_out.a_magic & 0xffff)) { 144 case ZMAGIC: 145 gz->virtual_offset = 0; 146 if (gz->a_out.a_text) { 147 gz->file_offset = NBPG; 148 } else { 149 /* Bill's "screwball mode" */ 150 gz->file_offset = 0; 151 } 152 break; 153 case QMAGIC: 154 gz->virtual_offset = NBPG; 155 gz->file_offset = 0; 156 break; 157 default: 158 /* NetBSD compatibility */ 159 switch ((int)(ntohl(gz->a_out.a_magic) & 0xffff)) { 160 case ZMAGIC: 161 case QMAGIC: 162 gz->virtual_offset = NBPG; 163 gz->file_offset = 0; 164 break; 165 default: 166 gz->where = __LINE__; 167 return (-1); 168 } 169 } 170 171 gz->bss_size = roundup(gz->a_out.a_bss, NBPG); 172 173 /* 174 * Check various fields in header for validity/bounds. 175 */ 176 if (/* entry point must lay with text region */ 177 gz->a_out.a_entry < gz->virtual_offset || 178 gz->a_out.a_entry >= gz->virtual_offset + gz->a_out.a_text || 179 180 /* text and data size must each be page rounded */ 181 gz->a_out.a_text % NBPG || 182 gz->a_out.a_data % NBPG) { 183 gz->where = __LINE__; 184 return (-1); 185 } 186 187 /* 188 * text/data/bss must not exceed limits 189 */ 190 if (/* text can't exceed maximum text size */ 191 gz->a_out.a_text > MAXTSIZ || 192 193 /* data + bss can't exceed maximum data size */ 194 gz->a_out.a_data + gz->bss_size > MAXDSIZ || 195 196 /* data + bss can't exceed rlimit */ 197 gz->a_out.a_data + gz->bss_size > 198 gz->ip->proc->p_rlimit[RLIMIT_DATA].rlim_cur) { 199 gz->where = __LINE__; 200 return (ENOMEM); 201 } 202 203 /* Find out how far we should go */ 204 gz->file_end = gz->file_offset + gz->a_out.a_text + gz->a_out.a_data; 205 206 /* copy in arguments and/or environment from old process */ 207 error = exec_extract_strings(gz->ip); 208 if (error) { 209 gz->where = __LINE__; 210 return (error); 211 } 212 213 /* 214 * Destroy old process VM and create a new one (with a new stack) 215 */ 216 exec_new_vmspace(gz->ip); 217 218 vmaddr = gz->virtual_offset; 219 220 error = vm_mmap(&vmspace->vm_map, /* map */ 221 &vmaddr, /* address */ 222 gz->a_out.a_text, /* size */ 223 VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_WRITE, /* protection */ 224 VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_WRITE, 225 MAP_ANON | MAP_FIXED, /* flags */ 226 0, /* vnode */ 227 0); /* offset */ 228 229 if (error) { 230 gz->where = __LINE__; 231 return (error); 232 } 233 234 vmaddr = gz->virtual_offset + gz->a_out.a_text; 235 236 /* 237 * Map data read/write (if text is 0, assume text is in data area 238 * [Bill's screwball mode]) 239 */ 240 241 error = vm_mmap(&vmspace->vm_map, 242 &vmaddr, 243 gz->a_out.a_data, 244 VM_PROT_READ | VM_PROT_WRITE | (gz->a_out.a_text ? 0 : VM_PROT_EXECUTE), 245 VM_PROT_ALL, MAP_ANON | MAP_FIXED, 246 0, 247 0); 248 249 if (error) { 250 gz->where = __LINE__; 251 return (error); 252 } 253 254 /* 255 * Allocate demand-zeroed area for uninitialized data 256 * "bss" = 'block started by symbol' - named after the IBM 7090 257 * instruction of the same name. 258 */ 259 vmaddr = gz->virtual_offset + gz->a_out.a_text + gz->a_out.a_data; 260 error = vm_allocate(&vmspace->vm_map, &vmaddr, gz->bss_size, FALSE); 261 if (error) { 262 gz->where = __LINE__; 263 return (error); 264 } 265 266 /* Fill in process VM information */ 267 vmspace->vm_tsize = gz->a_out.a_text >> PAGE_SHIFT; 268 vmspace->vm_dsize = (gz->a_out.a_data + gz->bss_size) >> PAGE_SHIFT; 269 vmspace->vm_taddr = (caddr_t) gz->virtual_offset; 270 vmspace->vm_daddr = (caddr_t) gz->virtual_offset + gz->a_out.a_text; 271 272 /* Fill in image_params */ 273 gz->ip->interpreted = 0; 274 gz->ip->entry_addr = gz->a_out.a_entry; 275 276 gz->ip->proc->p_sysent = &aout_sysvec; 277 278 return 0; 279} 280 281/* 282 * Tell kern_execve.c about it, with a little help from the linker. 283 * Since `const' objects end up in the text segment, TEXT_SET is the 284 * correct directive to use. 285 */ 286static const struct execsw gzip_execsw = { exec_gzip_imgact, "gzip" }; 287TEXT_SET(execsw_set, gzip_execsw); 288
| 42 43#include <vm/vm.h> 44#include <vm/vm_kern.h> 45 46extern struct sysentvec aout_sysvec; 47 48int 49exec_gzip_imgact(iparams) 50 struct image_params *iparams; 51{ 52 int error,error2=0; 53 u_char *p = (u_char *) iparams->image_header; 54 struct gzip *gz; 55 struct gz_global gz_glbl; 56 57 /* If these four are not OK, it isn't a gzip file */ 58 if (p[0] != 0x1f) return -1; /* 0 Simply magic */ 59 if (p[1] != 0x8b) return -1; /* 1 Simply magic */ 60 if (p[2] != 0x08) return -1; /* 2 Compression method */ 61 if (p[9] != 0x03) return -1; /* 9 OS compressed on */ 62 63 /* If this one contains anything but a comment or a filename 64 * marker, we don't want to chew on it 65 */ 66 if (p[3] & ~(0x18)) return ENOEXEC; /* 3 Flags */ 67 68 /* These are of no use to us */ 69 /* 4-7 Timestamp */ 70 /* 8 Extra flags */ 71 72 gz = malloc(sizeof *gz,M_GZIP,M_NOWAIT); 73 if (!gz) 74 return ENOMEM; 75 bzero(gz,sizeof *gz); /* waste of time ? */ 76 77 gz->gz_slide = malloc(WSIZE,M_TEMP,M_NOWAIT); 78 if (!gz->gz_slide) { 79 free(gz,M_GZIP); 80 return ENOMEM; 81 } 82 83 gz->ip = iparams; 84 gz->error = ENOEXEC; 85 gz->idx = 10; 86 87 if (p[3] & 0x08) { /* skip a filename */ 88 while (p[gz->idx++]) 89 if (gz->idx >= PAGE_SIZE) 90 goto done; 91 } 92 93 if (p[3] & 0x10) { /* skip a comment */ 94 while (p[gz->idx++]) 95 if (gz->idx >= PAGE_SIZE) 96 goto done; 97 } 98 99 gz->len = gz->ip->attr->va_size; 100 101 gz->error = 0; 102 103 error = inflate(gz, &gz_glbl); 104 105 if (gz->inbuf) { 106 error2 = 107 vm_deallocate(kernel_map, (vm_offset_t)gz->inbuf, PAGE_SIZE); 108 } 109 110 if (gz->error || error || error2) { 111 printf("Output=%lu ",gz->output); 112 printf("Inflate_error=%d gz->error=%d error2=%d where=%d\n", 113 error,gz->error,error2,gz->where); 114 if (gz->error) 115 goto done; 116 if (error) { 117 gz->error = ENOEXEC; 118 goto done; 119 } 120 if (error2) { 121 gz->error = error2; 122 goto done; 123 } 124 } 125 126 done: 127 error = gz->error; 128 free(gz->gz_slide,M_TEMP); 129 free(gz,M_GZIP); 130 return error; 131} 132 133int 134do_aout_hdr(struct gzip *gz) 135{ 136 int error; 137 struct vmspace *vmspace = gz->ip->proc->p_vmspace; 138 u_long vmaddr; 139 140 /* 141 * Set file/virtual offset based on a.out variant. 142 * We do two cases: host byte order and network byte order 143 * (for NetBSD compatibility) 144 */ 145 switch ((int)(gz->a_out.a_magic & 0xffff)) { 146 case ZMAGIC: 147 gz->virtual_offset = 0; 148 if (gz->a_out.a_text) { 149 gz->file_offset = NBPG; 150 } else { 151 /* Bill's "screwball mode" */ 152 gz->file_offset = 0; 153 } 154 break; 155 case QMAGIC: 156 gz->virtual_offset = NBPG; 157 gz->file_offset = 0; 158 break; 159 default: 160 /* NetBSD compatibility */ 161 switch ((int)(ntohl(gz->a_out.a_magic) & 0xffff)) { 162 case ZMAGIC: 163 case QMAGIC: 164 gz->virtual_offset = NBPG; 165 gz->file_offset = 0; 166 break; 167 default: 168 gz->where = __LINE__; 169 return (-1); 170 } 171 } 172 173 gz->bss_size = roundup(gz->a_out.a_bss, NBPG); 174 175 /* 176 * Check various fields in header for validity/bounds. 177 */ 178 if (/* entry point must lay with text region */ 179 gz->a_out.a_entry < gz->virtual_offset || 180 gz->a_out.a_entry >= gz->virtual_offset + gz->a_out.a_text || 181 182 /* text and data size must each be page rounded */ 183 gz->a_out.a_text % NBPG || 184 gz->a_out.a_data % NBPG) { 185 gz->where = __LINE__; 186 return (-1); 187 } 188 189 /* 190 * text/data/bss must not exceed limits 191 */ 192 if (/* text can't exceed maximum text size */ 193 gz->a_out.a_text > MAXTSIZ || 194 195 /* data + bss can't exceed maximum data size */ 196 gz->a_out.a_data + gz->bss_size > MAXDSIZ || 197 198 /* data + bss can't exceed rlimit */ 199 gz->a_out.a_data + gz->bss_size > 200 gz->ip->proc->p_rlimit[RLIMIT_DATA].rlim_cur) { 201 gz->where = __LINE__; 202 return (ENOMEM); 203 } 204 205 /* Find out how far we should go */ 206 gz->file_end = gz->file_offset + gz->a_out.a_text + gz->a_out.a_data; 207 208 /* copy in arguments and/or environment from old process */ 209 error = exec_extract_strings(gz->ip); 210 if (error) { 211 gz->where = __LINE__; 212 return (error); 213 } 214 215 /* 216 * Destroy old process VM and create a new one (with a new stack) 217 */ 218 exec_new_vmspace(gz->ip); 219 220 vmaddr = gz->virtual_offset; 221 222 error = vm_mmap(&vmspace->vm_map, /* map */ 223 &vmaddr, /* address */ 224 gz->a_out.a_text, /* size */ 225 VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_WRITE, /* protection */ 226 VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_WRITE, 227 MAP_ANON | MAP_FIXED, /* flags */ 228 0, /* vnode */ 229 0); /* offset */ 230 231 if (error) { 232 gz->where = __LINE__; 233 return (error); 234 } 235 236 vmaddr = gz->virtual_offset + gz->a_out.a_text; 237 238 /* 239 * Map data read/write (if text is 0, assume text is in data area 240 * [Bill's screwball mode]) 241 */ 242 243 error = vm_mmap(&vmspace->vm_map, 244 &vmaddr, 245 gz->a_out.a_data, 246 VM_PROT_READ | VM_PROT_WRITE | (gz->a_out.a_text ? 0 : VM_PROT_EXECUTE), 247 VM_PROT_ALL, MAP_ANON | MAP_FIXED, 248 0, 249 0); 250 251 if (error) { 252 gz->where = __LINE__; 253 return (error); 254 } 255 256 /* 257 * Allocate demand-zeroed area for uninitialized data 258 * "bss" = 'block started by symbol' - named after the IBM 7090 259 * instruction of the same name. 260 */ 261 vmaddr = gz->virtual_offset + gz->a_out.a_text + gz->a_out.a_data; 262 error = vm_allocate(&vmspace->vm_map, &vmaddr, gz->bss_size, FALSE); 263 if (error) { 264 gz->where = __LINE__; 265 return (error); 266 } 267 268 /* Fill in process VM information */ 269 vmspace->vm_tsize = gz->a_out.a_text >> PAGE_SHIFT; 270 vmspace->vm_dsize = (gz->a_out.a_data + gz->bss_size) >> PAGE_SHIFT; 271 vmspace->vm_taddr = (caddr_t) gz->virtual_offset; 272 vmspace->vm_daddr = (caddr_t) gz->virtual_offset + gz->a_out.a_text; 273 274 /* Fill in image_params */ 275 gz->ip->interpreted = 0; 276 gz->ip->entry_addr = gz->a_out.a_entry; 277 278 gz->ip->proc->p_sysent = &aout_sysvec; 279 280 return 0; 281} 282 283/* 284 * Tell kern_execve.c about it, with a little help from the linker. 285 * Since `const' objects end up in the text segment, TEXT_SET is the 286 * correct directive to use. 287 */ 288static const struct execsw gzip_execsw = { exec_gzip_imgact, "gzip" }; 289TEXT_SET(execsw_set, gzip_execsw); 290
|