Blame view

fs/binfmt_flat.c 27 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  /****************************************************************************/
  /*
   *  linux/fs/binfmt_flat.c
   *
   *	Copyright (C) 2000-2003 David McCullough <davidm@snapgear.com>
   *	Copyright (C) 2002 Greg Ungerer <gerg@snapgear.com>
   *	Copyright (C) 2002 SnapGear, by Paul Dale <pauli@snapgear.com>
   *	Copyright (C) 2000, 2001 Lineo, by David McCullough <davidm@lineo.com>
   *  based heavily on:
   *
   *  linux/fs/binfmt_aout.c:
   *      Copyright (C) 1991, 1992, 1996  Linus Torvalds
   *  linux/fs/binfmt_flat.c for 2.0 kernel
   *	    Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>
   *	JAN/99 -- coded full program relocation (gerg@snapgear.com)
   */
  
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
22
  #include <linux/kernel.h>
  #include <linux/sched.h>
  #include <linux/mm.h>
  #include <linux/mman.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
26
27
28
29
30
31
32
33
34
35
36
  #include <linux/errno.h>
  #include <linux/signal.h>
  #include <linux/string.h>
  #include <linux/fs.h>
  #include <linux/file.h>
  #include <linux/stat.h>
  #include <linux/fcntl.h>
  #include <linux/ptrace.h>
  #include <linux/user.h>
  #include <linux/slab.h>
  #include <linux/binfmts.h>
  #include <linux/personality.h>
  #include <linux/init.h>
  #include <linux/flat.h>
1ad3dcc09   Luke Yang   [PATCH] flat bina...
37
  #include <linux/syscalls.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
40
41
42
43
  
  #include <asm/byteorder.h>
  #include <asm/system.h>
  #include <asm/uaccess.h>
  #include <asm/unaligned.h>
  #include <asm/cacheflush.h>
c3dc5bec0   Oskar Schirmer   flat: fix data se...
44
  #include <asm/page.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
48
49
50
51
52
53
54
55
56
  
  /****************************************************************************/
  
  #if 0
  #define DEBUG 1
  #endif
  
  #ifdef DEBUG
  #define	DBG_FLT(a...)	printk(a)
  #else
  #define	DBG_FLT(a...)
  #endif
c3dc5bec0   Oskar Schirmer   flat: fix data se...
57
  /*
2e94de8ac   Mike Frysinger   fs/binfmt_flat.c:...
58
59
60
61
62
63
64
65
66
67
68
   * User data (data section and bss) needs to be aligned.
   * We pick 0x20 here because it is the max value elf2flt has always
   * used in producing FLAT files, and because it seems to be large
   * enough to make all the gcc alignment related tests happy.
   */
  #define FLAT_DATA_ALIGN	(0x20)
  
  /*
   * User data (stack) also needs to be aligned.
   * Here we can be a bit looser than the data sections since this
   * needs to only meet arch ABI requirements.
c3dc5bec0   Oskar Schirmer   flat: fix data se...
69
   */
2952095c6   Mike Frysinger   flat: tweak defau...
70
  #define FLAT_STACK_ALIGN	max_t(unsigned long, sizeof(void *), ARCH_SLAB_MINALIGN)
c3dc5bec0   Oskar Schirmer   flat: fix data se...
71

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  #define RELOC_FAILED 0xff00ff01		/* Relocation incorrect somewhere */
  #define UNLOADED_LIB 0x7ff000ff		/* Placeholder for unused library */
  
  struct lib_info {
  	struct {
  		unsigned long start_code;		/* Start of text segment */
  		unsigned long start_data;		/* Start of data segment */
  		unsigned long start_brk;		/* End of data segment */
  		unsigned long text_len;			/* Length of text segment */
  		unsigned long entry;			/* Start address for this module */
  		unsigned long build_date;		/* When this one was compiled */
  		short loaded;				/* Has this library been loaded? */
  	} lib_list[MAX_SHARED_LIBS];
  };
  
  #ifdef CONFIG_BINFMT_SHARED_FLAT
  static int load_flat_shared_library(int id, struct lib_info *p);
  #endif
  
  static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
f6151dfea   Masami Hiramatsu   mm: introduce cor...
92
  static int flat_core_dump(struct coredump_params *cprm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
97
98
99
100
101
102
103
104
105
  static struct linux_binfmt flat_format = {
  	.module		= THIS_MODULE,
  	.load_binary	= load_flat_binary,
  	.core_dump	= flat_core_dump,
  	.min_coredump	= PAGE_SIZE
  };
  
  /****************************************************************************/
  /*
   * Routine writes a core dump image in the current directory.
   * Currently only a stub-function.
   */
f6151dfea   Masami Hiramatsu   mm: introduce cor...
106
  static int flat_core_dump(struct coredump_params *cprm)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
109
  {
  	printk("Process %s:%d received signr %d and should have core dumped
  ",
f6151dfea   Masami Hiramatsu   mm: introduce cor...
110
  			current->comm, current->pid, (int) cprm->signr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  	return(1);
  }
  
  /****************************************************************************/
  /*
   * create_flat_tables() parses the env- and arg-strings in new user
   * memory and creates the pointer tables from them, and puts their
   * addresses on the "stack", returning the new stack pointer value.
   */
  
  static unsigned long create_flat_tables(
  	unsigned long pp,
  	struct linux_binprm * bprm)
  {
  	unsigned long *argv,*envp;
  	unsigned long * sp;
  	char * p = (char*)pp;
  	int argc = bprm->argc;
  	int envc = bprm->envc;
0e647c04f   Andrew Morton   binfmt_flat: warn...
130
  	char uninitialized_var(dummy);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131

c3dc5bec0   Oskar Schirmer   flat: fix data se...
132
133
  	sp = (unsigned long *)p;
  	sp -= (envc + argc + 2) + 1 + (flat_argvp_envp_on_stack() ? 2 : 0);
2e94de8ac   Mike Frysinger   fs/binfmt_flat.c:...
134
  	sp = (unsigned long *) ((unsigned long)sp & -FLAT_STACK_ALIGN);
c3dc5bec0   Oskar Schirmer   flat: fix data se...
135
136
  	argv = sp + 1 + (flat_argvp_envp_on_stack() ? 2 : 0);
  	envp = argv + (argc + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
  	if (flat_argvp_envp_on_stack()) {
c3dc5bec0   Oskar Schirmer   flat: fix data se...
139
140
  		put_user((unsigned long) envp, sp + 2);
  		put_user((unsigned long) argv, sp + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  	}
c3dc5bec0   Oskar Schirmer   flat: fix data se...
142
  	put_user(argc, sp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
  	current->mm->arg_start = (unsigned long) p;
  	while (argc-->0) {
  		put_user((unsigned long) p, argv++);
  		do {
  			get_user(dummy, p); p++;
  		} while (dummy);
  	}
  	put_user((unsigned long) NULL, argv);
  	current->mm->arg_end = current->mm->env_start = (unsigned long) p;
  	while (envc-->0) {
  		put_user((unsigned long)p, envp); envp++;
  		do {
  			get_user(dummy, p); p++;
  		} while (dummy);
  	}
  	put_user((unsigned long) NULL, envp);
  	current->mm->env_end = (unsigned long) p;
  	return (unsigned long)sp;
  }
  
  /****************************************************************************/
  
  #ifdef CONFIG_BINFMT_ZFLAT
  
  #include <linux/zlib.h>
  
  #define LBUFSIZE	4000
  
  /* gzip flag byte */
  #define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
  #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
  #define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
  #define ORIG_NAME    0x08 /* bit 3 set: original file name present */
  #define COMMENT      0x10 /* bit 4 set: file comment present */
  #define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
  #define RESERVED     0xC0 /* bit 6,7:   reserved */
  
  static int decompress_exec(
  	struct linux_binprm *bprm,
  	unsigned long offset,
  	char *dst,
  	long len,
  	int fd)
  {
  	unsigned char *buf;
  	z_stream strm;
  	loff_t fpos;
  	int ret, retval;
  
  	DBG_FLT("decompress_exec(offset=%x,buf=%x,len=%x)
  ",(int)offset, (int)dst, (int)len);
  
  	memset(&strm, 0, sizeof(strm));
  	strm.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
  	if (strm.workspace == NULL) {
  		DBG_FLT("binfmt_flat: no memory for decompress workspace
  ");
  		return -ENOMEM;
  	}
  	buf = kmalloc(LBUFSIZE, GFP_KERNEL);
  	if (buf == NULL) {
  		DBG_FLT("binfmt_flat: no memory for read buffer
  ");
  		retval = -ENOMEM;
  		goto out_free;
  	}
  
  	/* Read in first chunk of data and parse gzip header. */
  	fpos = offset;
  	ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos);
  
  	strm.next_in = buf;
  	strm.avail_in = ret;
  	strm.total_in = 0;
  
  	retval = -ENOEXEC;
  
  	/* Check minimum size -- gzip header */
  	if (ret < 10) {
  		DBG_FLT("binfmt_flat: file too small?
  ");
  		goto out_free_buf;
  	}
  
  	/* Check gzip magic number */
  	if ((buf[0] != 037) || ((buf[1] != 0213) && (buf[1] != 0236))) {
  		DBG_FLT("binfmt_flat: unknown compression magic?
  ");
  		goto out_free_buf;
  	}
  
  	/* Check gzip method */
  	if (buf[2] != 8) {
  		DBG_FLT("binfmt_flat: unknown compression method?
  ");
  		goto out_free_buf;
  	}
  	/* Check gzip flags */
  	if ((buf[3] & ENCRYPTED) || (buf[3] & CONTINUATION) ||
  	    (buf[3] & RESERVED)) {
  		DBG_FLT("binfmt_flat: unknown flags?
  ");
  		goto out_free_buf;
  	}
  
  	ret = 10;
  	if (buf[3] & EXTRA_FIELD) {
  		ret += 2 + buf[10] + (buf[11] << 8);
f4cfb18d7   Volodymyr G. Lukiianyk   uclinux: fix gzip...
251
  		if (unlikely(LBUFSIZE <= ret)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
253
254
255
256
257
  			DBG_FLT("binfmt_flat: buffer overflow (EXTRA)?
  ");
  			goto out_free_buf;
  		}
  	}
  	if (buf[3] & ORIG_NAME) {
f4cfb18d7   Volodymyr G. Lukiianyk   uclinux: fix gzip...
258
  		while (ret < LBUFSIZE && buf[ret++] != 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
260
261
262
263
264
265
266
  			;
  		if (unlikely(LBUFSIZE == ret)) {
  			DBG_FLT("binfmt_flat: buffer overflow (ORIG_NAME)?
  ");
  			goto out_free_buf;
  		}
  	}
  	if (buf[3] & COMMENT) {
f4cfb18d7   Volodymyr G. Lukiianyk   uclinux: fix gzip...
267
  		while (ret < LBUFSIZE && buf[ret++] != 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
  			;
  		if (unlikely(LBUFSIZE == ret)) {
  			DBG_FLT("binfmt_flat: buffer overflow (COMMENT)?
  ");
  			goto out_free_buf;
  		}
  	}
  
  	strm.next_in += ret;
  	strm.avail_in -= ret;
  
  	strm.next_out = dst;
  	strm.avail_out = len;
  	strm.total_out = 0;
  
  	if (zlib_inflateInit2(&strm, -MAX_WBITS) != Z_OK) {
  		DBG_FLT("binfmt_flat: zlib init failed?
  ");
  		goto out_free_buf;
  	}
  
  	while ((ret = zlib_inflate(&strm, Z_NO_FLUSH)) == Z_OK) {
  		ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos);
  		if (ret <= 0)
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
  		len -= ret;
  
  		strm.next_in = buf;
  		strm.avail_in = ret;
  		strm.total_in = 0;
  	}
  
  	if (ret < 0) {
  		DBG_FLT("binfmt_flat: decompression failed (%d), %s
  ",
  			ret, strm.msg);
  		goto out_zlib;
  	}
  
  	retval = 0;
  out_zlib:
  	zlib_inflateEnd(&strm);
  out_free_buf:
  	kfree(buf);
  out_free:
  	kfree(strm.workspace);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
  	return retval;
  }
  
  #endif /* CONFIG_BINFMT_ZFLAT */
  
  /****************************************************************************/
  
  static unsigned long
  calc_reloc(unsigned long r, struct lib_info *p, int curid, int internalp)
  {
  	unsigned long addr;
  	int id;
  	unsigned long start_brk;
  	unsigned long start_data;
  	unsigned long text_len;
  	unsigned long start_code;
  
  #ifdef CONFIG_BINFMT_SHARED_FLAT
  	if (r == 0)
  		id = curid;	/* Relocs of 0 are always self referring */
  	else {
  		id = (r >> 24) & 0xff;	/* Find ID for this reloc */
  		r &= 0x00ffffff;	/* Trim ID off here */
  	}
  	if (id >= MAX_SHARED_LIBS) {
  		printk("BINFMT_FLAT: reference 0x%x to shared library %d",
  				(unsigned) r, id);
  		goto failed;
  	}
  	if (curid != id) {
  		if (internalp) {
  			printk("BINFMT_FLAT: reloc address 0x%x not in same module "
  					"(%d != %d)", (unsigned) r, curid, id);
  			goto failed;
  		} else if ( ! p->lib_list[id].loaded &&
0b8c78f2b   Mike Frysinger   flat: use IS_ERR_...
349
  				IS_ERR_VALUE(load_flat_shared_library(id, p))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
  			printk("BINFMT_FLAT: failed to load library %d", id);
  			goto failed;
  		}
  		/* Check versioning information (i.e. time stamps) */
  		if (p->lib_list[id].build_date && p->lib_list[curid].build_date &&
  				p->lib_list[curid].build_date < p->lib_list[id].build_date) {
  			printk("BINFMT_FLAT: library %d is younger than %d", id, curid);
  			goto failed;
  		}
  	}
  #else
  	id = 0;
  #endif
  
  	start_brk = p->lib_list[id].start_brk;
  	start_data = p->lib_list[id].start_data;
  	start_code = p->lib_list[id].start_code;
  	text_len = p->lib_list[id].text_len;
  
  	if (!flat_reloc_valid(r, start_brk - start_data + text_len)) {
  		printk("BINFMT_FLAT: reloc outside program 0x%x (0 - 0x%x/0x%x)",
d7dfee3f5   Jun Sun   uclinux: error me...
371
  		       (int) r,(int)(start_brk-start_data+text_len),(int)text_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
  		goto failed;
  	}
  
  	if (r < text_len)			/* In text segment */
  		addr = r + start_code;
  	else					/* In data segment */
  		addr = r - text_len + start_data;
  
  	/* Range checked already above so doing the range tests is redundant...*/
  	return(addr);
  
  failed:
  	printk(", killing %s!
  ", current->comm);
  	send_sig(SIGSEGV, current, 0);
  
  	return RELOC_FAILED;
  }
  
  /****************************************************************************/
  
  void old_reloc(unsigned long rl)
  {
  #ifdef DEBUG
  	char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
  #endif
  	flat_v2_reloc_t	r;
  	unsigned long *ptr;
  	
  	r.value = rl;
  #if defined(CONFIG_COLDFIRE)
  	ptr = (unsigned long *) (current->mm->start_code + r.reloc.offset);
  #else
  	ptr = (unsigned long *) (current->mm->start_data + r.reloc.offset);
  #endif
  
  #ifdef DEBUG
  	printk("Relocation of variable at DATASEG+%x "
  		"(address %p, currently %x) into segment %s
  ",
  		r.reloc.offset, ptr, (int)*ptr, segment[r.reloc.type]);
  #endif
  	
  	switch (r.reloc.type) {
  	case OLD_FLAT_RELOC_TYPE_TEXT:
  		*ptr += current->mm->start_code;
  		break;
  	case OLD_FLAT_RELOC_TYPE_DATA:
  		*ptr += current->mm->start_data;
  		break;
  	case OLD_FLAT_RELOC_TYPE_BSS:
  		*ptr += current->mm->end_data;
  		break;
  	default:
  		printk("BINFMT_FLAT: Unknown relocation type=%x
  ", r.reloc.type);
  		break;
  	}
  
  #ifdef DEBUG
  	printk("Relocation became %x
  ", (int)*ptr);
  #endif
  }		
  
  /****************************************************************************/
  
  static int load_flat_file(struct linux_binprm * bprm,
  		struct lib_info *libinfo, int id, unsigned long *extra_stack)
  {
  	struct flat_hdr * hdr;
  	unsigned long textpos = 0, datapos = 0, result;
  	unsigned long realdatastart = 0;
  	unsigned long text_len, data_len, bss_len, stack_len, flags;
0f3e442a4   David Howells   FLAT: Don't attem...
446
447
  	unsigned long len, memp = 0;
  	unsigned long memp_size, extra, rlim;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
450
451
452
  	unsigned long *reloc = 0, *rp;
  	struct inode *inode;
  	int i, rev, relocs = 0;
  	loff_t fpos;
  	unsigned long start_code, end_code;
1ad3dcc09   Luke Yang   [PATCH] flat bina...
453
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
455
  
  	hdr = ((struct flat_hdr *) bprm->buf);		/* exec-header */
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
456
  	inode = bprm->file->f_path.dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
458
459
460
461
462
463
464
465
466
467
468
  
  	text_len  = ntohl(hdr->data_start);
  	data_len  = ntohl(hdr->data_end) - ntohl(hdr->data_start);
  	bss_len   = ntohl(hdr->bss_end) - ntohl(hdr->data_end);
  	stack_len = ntohl(hdr->stack_size);
  	if (extra_stack) {
  		stack_len += *extra_stack;
  		*extra_stack = stack_len;
  	}
  	relocs    = ntohl(hdr->reloc_count);
  	flags     = ntohl(hdr->flags);
  	rev       = ntohl(hdr->rev);
845884d33   Greg Ungerer   [PATCH] uclinux: ...
469
  	if (strncmp(hdr->magic, "bFLT", 4)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
  		/*
e2a366dc5   Mike Frysinger   FLAT binaries: dr...
471
472
473
474
  		 * Previously, here was a printk to tell people
  		 *   "BINFMT_FLAT: bad header magic".
  		 * But for the kernel which also use ELF FD-PIC format, this
  		 * error message is confusing.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
  		 * because a lot of people do not manage to produce good
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
  		 */
1ad3dcc09   Luke Yang   [PATCH] flat bina...
477
478
  		ret = -ENOEXEC;
  		goto err;
845884d33   Greg Ungerer   [PATCH] uclinux: ...
479
480
481
482
483
484
485
  	}
  
  	if (flags & FLAT_FLAG_KTRACE)
  		printk("BINFMT_FLAT: Loading file: %s
  ", bprm->filename);
  
  	if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) {
0e647c04f   Andrew Morton   binfmt_flat: warn...
486
487
488
489
  		printk("BINFMT_FLAT: bad flat file version 0x%x (supported "
  			"0x%lx and 0x%lx)
  ",
  			rev, FLAT_VERSION, OLD_FLAT_VERSION);
1ad3dcc09   Luke Yang   [PATCH] flat bina...
490
491
  		ret = -ENOEXEC;
  		goto err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
493
494
495
496
497
498
  	}
  	
  	/* Don't allow old format executables to use shared libraries */
  	if (rev == OLD_FLAT_VERSION && id != 0) {
  		printk("BINFMT_FLAT: shared libraries are not available before rev 0x%x
  ",
  				(int) FLAT_VERSION);
1ad3dcc09   Luke Yang   [PATCH] flat bina...
499
500
  		ret = -ENOEXEC;
  		goto err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
502
503
504
505
506
507
508
509
510
511
512
513
  	}
  
  	/*
  	 * fix up the flags for the older format,  there were all kinds
  	 * of endian hacks,  this only works for the simple cases
  	 */
  	if (rev == OLD_FLAT_VERSION && flat_old_ram_flag(flags))
  		flags = FLAT_FLAG_RAM;
  
  #ifndef CONFIG_BINFMT_ZFLAT
  	if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) {
  		printk("Support for ZFLAT executables is not enabled.
  ");
1ad3dcc09   Luke Yang   [PATCH] flat bina...
514
515
  		ret = -ENOEXEC;
  		goto err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
518
519
520
521
522
523
  	}
  #endif
  
  	/*
  	 * Check initial limits. This avoids letting people circumvent
  	 * size limits imposed on them by creating programs with large
  	 * arrays in the data or bss.
  	 */
d554ed895   Jiri Slaby   fs: use rlimit he...
524
  	rlim = rlimit(RLIMIT_DATA);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
526
  	if (rlim >= RLIM_INFINITY)
  		rlim = ~0;
1ad3dcc09   Luke Yang   [PATCH] flat bina...
527
528
529
530
  	if (data_len + bss_len > rlim) {
  		ret = -ENOMEM;
  		goto err;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
532
533
  	/* Flush all traces of the currently running executable */
  	if (id == 0) {
  		result = flush_old_exec(bprm);
1ad3dcc09   Luke Yang   [PATCH] flat bina...
534
535
  		if (result) {
  			ret = result;
df88912a2   Andrew Morton   [PATCH] binfmt_fl...
536
  			goto err;
1ad3dcc09   Luke Yang   [PATCH] flat bina...
537
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538
539
  
  		/* OK, This is the point of no return */
fcc18e83e   Malcolm Parsons   [PATCH] uclinux: ...
540
  		set_personality(PER_LINUX_32BIT);
221af7f87   Linus Torvalds   Split 'flush_old_...
541
  		setup_new_exec(bprm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542
543
544
545
546
  	}
  
  	/*
  	 * calculate the extra space we need to map in
  	 */
0e647c04f   Andrew Morton   binfmt_flat: warn...
547
548
  	extra = max_t(unsigned long, bss_len + stack_len,
  			relocs * sizeof(unsigned long));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
  
  	/*
  	 * there are a couple of cases here,  the separate code/data
  	 * case,  and then the fully copied to RAM case which lumps
  	 * it all together.
  	 */
  	if ((flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP)) == 0) {
  		/*
  		 * this should give us a ROM ptr,  but if it doesn't we don't
  		 * really care
  		 */
  		DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)
  ");
  
  		down_write(&current->mm->mmap_sem);
925d1c401   Matt Helsley   procfs task exe s...
564
565
  		textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
  				  MAP_PRIVATE|MAP_EXECUTABLE, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566
  		up_write(&current->mm->mmap_sem);
0b8c78f2b   Mike Frysinger   flat: use IS_ERR_...
567
  		if (!textpos || IS_ERR_VALUE(textpos)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
569
570
571
  			if (!textpos)
  				textpos = (unsigned long) -ENOMEM;
  			printk("Unable to mmap process text, errno %d
  ", (int)-textpos);
1ad3dcc09   Luke Yang   [PATCH] flat bina...
572
  			ret = textpos;
df88912a2   Andrew Morton   [PATCH] binfmt_fl...
573
  			goto err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
  		}
72613e5f4   Greg Ungerer   [PATCH] uclinux: ...
575
  		len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
0f3e442a4   David Howells   FLAT: Don't attem...
576
  		len = PAGE_ALIGN(len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
  		down_write(&current->mm->mmap_sem);
72613e5f4   Greg Ungerer   [PATCH] uclinux: ...
578
579
  		realdatastart = do_mmap(0, 0, len,
  			PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
  		up_write(&current->mm->mmap_sem);
0b8c78f2b   Mike Frysinger   flat: use IS_ERR_...
581
  		if (realdatastart == 0 || IS_ERR_VALUE(realdatastart)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
583
584
585
  			if (!realdatastart)
  				realdatastart = (unsigned long) -ENOMEM;
  			printk("Unable to allocate RAM for process data, errno %d
  ",
c287ef1ff   Greg Ungerer   nommu: report cor...
586
  					(int)-realdatastart);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
587
  			do_munmap(current->mm, textpos, text_len);
1ad3dcc09   Luke Yang   [PATCH] flat bina...
588
  			ret = realdatastart;
df88912a2   Andrew Morton   [PATCH] binfmt_fl...
589
  			goto err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590
  		}
c3dc5bec0   Oskar Schirmer   flat: fix data se...
591
592
593
  		datapos = ALIGN(realdatastart +
  				MAX_SHARED_LIBS * sizeof(unsigned long),
  				FLAT_DATA_ALIGN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
  
  		DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x
  ",
  				(int)(data_len + bss_len + stack_len), (int)datapos);
  
  		fpos = ntohl(hdr->data_start);
  #ifdef CONFIG_BINFMT_ZFLAT
  		if (flags & FLAT_FLAG_GZDATA) {
  			result = decompress_exec(bprm, fpos, (char *) datapos, 
  						 data_len + (relocs * sizeof(unsigned long)), 0);
  		} else
  #endif
  		{
  			result = bprm->file->f_op->read(bprm->file, (char *) datapos,
  					data_len + (relocs * sizeof(unsigned long)), &fpos);
  		}
0b8c78f2b   Mike Frysinger   flat: use IS_ERR_...
610
  		if (IS_ERR_VALUE(result)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
611
612
613
  			printk("Unable to read data+bss, errno %d
  ", (int)-result);
  			do_munmap(current->mm, textpos, text_len);
1da083c9b   Mike Frysinger   flat: fix unmap l...
614
  			do_munmap(current->mm, realdatastart, len);
1ad3dcc09   Luke Yang   [PATCH] flat bina...
615
  			ret = result;
df88912a2   Andrew Morton   [PATCH] binfmt_fl...
616
  			goto err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
618
619
620
  		}
  
  		reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len));
  		memp = realdatastart;
0f3e442a4   David Howells   FLAT: Don't attem...
621
  		memp_size = len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
  	} else {
72613e5f4   Greg Ungerer   [PATCH] uclinux: ...
623
  		len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
0f3e442a4   David Howells   FLAT: Don't attem...
624
  		len = PAGE_ALIGN(len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
  		down_write(&current->mm->mmap_sem);
72613e5f4   Greg Ungerer   [PATCH] uclinux: ...
626
627
  		textpos = do_mmap(0, 0, len,
  			PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
628
  		up_write(&current->mm->mmap_sem);
72613e5f4   Greg Ungerer   [PATCH] uclinux: ...
629

0b8c78f2b   Mike Frysinger   flat: use IS_ERR_...
630
  		if (!textpos || IS_ERR_VALUE(textpos)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
631
632
633
634
635
  			if (!textpos)
  				textpos = (unsigned long) -ENOMEM;
  			printk("Unable to allocate RAM for process text/data, errno %d
  ",
  					(int)-textpos);
1ad3dcc09   Luke Yang   [PATCH] flat bina...
636
  			ret = textpos;
df88912a2   Andrew Morton   [PATCH] binfmt_fl...
637
  			goto err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
639
640
  		}
  
  		realdatastart = textpos + ntohl(hdr->data_start);
c3dc5bec0   Oskar Schirmer   flat: fix data se...
641
642
643
644
645
646
  		datapos = ALIGN(realdatastart +
  				MAX_SHARED_LIBS * sizeof(unsigned long),
  				FLAT_DATA_ALIGN);
  
  		reloc = (unsigned long *)
  			(datapos + (ntohl(hdr->reloc_start) - text_len));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
  		memp = textpos;
0f3e442a4   David Howells   FLAT: Don't attem...
648
  		memp_size = len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
  #ifdef CONFIG_BINFMT_ZFLAT
  		/*
  		 * load it all in and treat it like a RAM load from now on
  		 */
  		if (flags & FLAT_FLAG_GZIP) {
  			result = decompress_exec(bprm, sizeof (struct flat_hdr),
  					 (((char *) textpos) + sizeof (struct flat_hdr)),
  					 (text_len + data_len + (relocs * sizeof(unsigned long))
  						  - sizeof (struct flat_hdr)),
  					 0);
  			memmove((void *) datapos, (void *) realdatastart,
  					data_len + (relocs * sizeof(unsigned long)));
  		} else if (flags & FLAT_FLAG_GZDATA) {
  			fpos = 0;
  			result = bprm->file->f_op->read(bprm->file,
  					(char *) textpos, text_len, &fpos);
0b8c78f2b   Mike Frysinger   flat: use IS_ERR_...
665
  			if (!IS_ERR_VALUE(result))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
668
669
670
671
672
673
674
  				result = decompress_exec(bprm, text_len, (char *) datapos,
  						 data_len + (relocs * sizeof(unsigned long)), 0);
  		}
  		else
  #endif
  		{
  			fpos = 0;
  			result = bprm->file->f_op->read(bprm->file,
  					(char *) textpos, text_len, &fpos);
0b8c78f2b   Mike Frysinger   flat: use IS_ERR_...
675
  			if (!IS_ERR_VALUE(result)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
677
678
679
680
  				fpos = ntohl(hdr->data_start);
  				result = bprm->file->f_op->read(bprm->file, (char *) datapos,
  					data_len + (relocs * sizeof(unsigned long)), &fpos);
  			}
  		}
0b8c78f2b   Mike Frysinger   flat: use IS_ERR_...
681
  		if (IS_ERR_VALUE(result)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682
683
684
685
  			printk("Unable to read code+data+bss, errno %d
  ",(int)-result);
  			do_munmap(current->mm, textpos, text_len + data_len + extra +
  				MAX_SHARED_LIBS * sizeof(unsigned long));
1ad3dcc09   Luke Yang   [PATCH] flat bina...
686
  			ret = result;
df88912a2   Andrew Morton   [PATCH] binfmt_fl...
687
  			goto err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
  		}
  	}
  
  	if (flags & FLAT_FLAG_KTRACE)
  		printk("Mapping is %x, Entry point is %x, data_start is %x
  ",
  			(int)textpos, 0x00ffffff&ntohl(hdr->entry), ntohl(hdr->data_start));
  
  	/* The main program needs a little extra setup in the task structure */
  	start_code = textpos + sizeof (struct flat_hdr);
  	end_code = textpos + text_len;
  	if (id == 0) {
  		current->mm->start_code = start_code;
  		current->mm->end_code = end_code;
  		current->mm->start_data = datapos;
  		current->mm->end_data = datapos + data_len;
  		/*
  		 * set up the brk stuff, uses any slack left in data/bss/stack
  		 * allocation.  We put the brk after the bss (between the bss
  		 * and stack) like other platforms.
0f3e442a4   David Howells   FLAT: Don't attem...
708
709
  		 * Userspace code relies on the stack pointer starting out at
  		 * an address right at the end of a page.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
711
712
  		 */
  		current->mm->start_brk = datapos + data_len + bss_len;
  		current->mm->brk = (current->mm->start_brk + 3) & ~3;
0f3e442a4   David Howells   FLAT: Don't attem...
713
  		current->mm->context.end_brk = memp + memp_size - stack_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
  	}
  
  	if (flags & FLAT_FLAG_KTRACE)
  		printk("%s %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x
  ",
  			id ? "Lib" : "Load", bprm->filename,
  			(int) start_code, (int) end_code,
  			(int) datapos,
  			(int) (datapos + data_len),
  			(int) (datapos + data_len),
  			(int) (((datapos + data_len + bss_len) + 3) & ~3));
  
  	text_len -= sizeof(struct flat_hdr); /* the real code len */
  
  	/* Store the current module values into the global library structure */
  	libinfo->lib_list[id].start_code = start_code;
  	libinfo->lib_list[id].start_data = datapos;
  	libinfo->lib_list[id].start_brk = datapos + data_len + bss_len;
  	libinfo->lib_list[id].text_len = text_len;
  	libinfo->lib_list[id].loaded = 1;
  	libinfo->lib_list[id].entry = (0x00ffffff & ntohl(hdr->entry)) + textpos;
  	libinfo->lib_list[id].build_date = ntohl(hdr->build_date);
  	
  	/*
  	 * We just load the allocations into some temporary memory to
  	 * help simplify all this mumbo jumbo
  	 *
  	 * We've got two different sections of relocation entries.
25985edce   Lucas De Marchi   Fix common misspe...
742
  	 * The first is the GOT which resides at the beginning of the data segment
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
744
745
746
747
748
749
750
751
752
753
  	 * and is terminated with a -1.  This one can be relocated in place.
  	 * The second is the extra relocation entries tacked after the image's
  	 * data segment. These require a little more processing as the entry is
  	 * really an offset into the image which contains an offset into the
  	 * image.
  	 */
  	if (flags & FLAT_FLAG_GOTPIC) {
  		for (rp = (unsigned long *)datapos; *rp != 0xffffffff; rp++) {
  			unsigned long addr;
  			if (*rp) {
  				addr = calc_reloc(*rp, libinfo, id, 0);
1ad3dcc09   Luke Yang   [PATCH] flat bina...
754
755
  				if (addr == RELOC_FAILED) {
  					ret = -ENOEXEC;
df88912a2   Andrew Morton   [PATCH] binfmt_fl...
756
  					goto err;
1ad3dcc09   Luke Yang   [PATCH] flat bina...
757
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
  				*rp = addr;
  			}
  		}
  	}
  
  	/*
  	 * Now run through the relocation entries.
  	 * We've got to be careful here as C++ produces relocatable zero
  	 * entries in the constructor and destructor tables which are then
  	 * tested for being not zero (which will always occur unless we're
  	 * based from address zero).  This causes an endless loop as __start
  	 * is at zero.  The solution used is to not relocate zero addresses.
  	 * This has the negative side effect of not allowing a global data
  	 * reference to be statically initialised to _stext (I've moved
  	 * __start to address 4 so that is okay).
  	 */
  	if (rev > OLD_FLAT_VERSION) {
f9720205d   Bernd Schmidt   Binfmt_flat: Add ...
775
  		unsigned long persistent = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
776
777
778
779
780
781
782
  		for (i=0; i < relocs; i++) {
  			unsigned long addr, relval;
  
  			/* Get the address of the pointer to be
  			   relocated (of course, the address has to be
  			   relocated first).  */
  			relval = ntohl(reloc[i]);
f9720205d   Bernd Schmidt   Binfmt_flat: Add ...
783
784
  			if (flat_set_persistent (relval, &persistent))
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
786
  			addr = flat_get_relocate_addr(relval);
  			rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1);
1ad3dcc09   Luke Yang   [PATCH] flat bina...
787
788
  			if (rp == (unsigned long *)RELOC_FAILED) {
  				ret = -ENOEXEC;
df88912a2   Andrew Morton   [PATCH] binfmt_fl...
789
  				goto err;
1ad3dcc09   Luke Yang   [PATCH] flat bina...
790
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791
792
  
  			/* Get the pointer's value.  */
576bb9ced   Andrew Morton   binfmt_flat: chec...
793
794
  			addr = flat_get_addr_from_rp(rp, relval, flags,
  							&persistent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
795
796
797
798
799
800
801
802
  			if (addr != 0) {
  				/*
  				 * Do the relocation.  PIC relocs in the data section are
  				 * already in target order
  				 */
  				if ((flags & FLAT_FLAG_GOTPIC) == 0)
  					addr = ntohl(addr);
  				addr = calc_reloc(addr, libinfo, id, 0);
1ad3dcc09   Luke Yang   [PATCH] flat bina...
803
804
  				if (addr == RELOC_FAILED) {
  					ret = -ENOEXEC;
df88912a2   Andrew Morton   [PATCH] binfmt_fl...
805
  					goto err;
1ad3dcc09   Luke Yang   [PATCH] flat bina...
806
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
808
809
810
811
812
813
814
815
816
817
818
819
820
  
  				/* Write back the relocated pointer.  */
  				flat_put_addr_at_rp(rp, addr, relval);
  			}
  		}
  	} else {
  		for (i=0; i < relocs; i++)
  			old_reloc(ntohl(reloc[i]));
  	}
  	
  	flush_icache_range(start_code, end_code);
  
  	/* zero the BSS,  BRK and stack areas */
  	memset((void*)(datapos + data_len), 0, bss_len + 
0f3e442a4   David Howells   FLAT: Don't attem...
821
822
  			(memp + memp_size - stack_len -		/* end brk */
  			libinfo->lib_list[id].start_brk) +	/* start brk */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823
824
825
  			stack_len);
  
  	return 0;
1ad3dcc09   Luke Yang   [PATCH] flat bina...
826
827
  err:
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
  }
  
  
  /****************************************************************************/
  #ifdef CONFIG_BINFMT_SHARED_FLAT
  
  /*
   * Load a shared library into memory.  The library gets its own data
   * segment (including bss) but not argv/argc/environ.
   */
  
  static int load_flat_shared_library(int id, struct lib_info *libs)
  {
  	struct linux_binprm bprm;
  	int res;
  	char buf[16];
3a852d3bd   David Howells   CRED: Fix load_fl...
844
  	memset(&bprm, 0, sizeof(bprm));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845
846
847
848
849
850
851
852
853
  	/* Create the file name */
  	sprintf(buf, "/lib/lib%d.so", id);
  
  	/* Open the file up */
  	bprm.filename = buf;
  	bprm.file = open_exec(bprm.filename);
  	res = PTR_ERR(bprm.file);
  	if (IS_ERR(bprm.file))
  		return res;
3440625d7   Linus Torvalds   flat: fix uniniti...
854
855
856
857
  	bprm.cred = prepare_exec_creds();
  	res = -ENOMEM;
  	if (!bprm.cred)
  		goto out;
3a852d3bd   David Howells   CRED: Fix load_fl...
858
859
860
861
862
  	/* We don't really care about recalculating credentials at this point
  	 * as we're past the point of no return and are dealing with shared
  	 * libraries.
  	 */
  	bprm.cred_prepared = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863
  	res = prepare_binprm(&bprm);
0b8c78f2b   Mike Frysinger   flat: use IS_ERR_...
864
  	if (!IS_ERR_VALUE(res))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
865
  		res = load_flat_file(&bprm, libs, id, NULL);
3440625d7   Linus Torvalds   flat: fix uniniti...
866
867
868
869
870
871
  
  	abort_creds(bprm.cred);
  
  out:
  	allow_write_access(bprm.file);
  	fput(bprm.file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
  	return(res);
  }
  
  #endif /* CONFIG_BINFMT_SHARED_FLAT */
  /****************************************************************************/
  
  /*
   * These are the functions used to load flat style executables and shared
   * libraries.  There is no binary dependent code anywhere else.
   */
  
  static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
  {
  	struct lib_info libinfo;
  	unsigned long p = bprm->p;
  	unsigned long stack_len;
  	unsigned long start_addr;
  	unsigned long *sp;
  	int res;
  	int i, j;
  
  	memset(&libinfo, 0, sizeof(libinfo));
  	/*
  	 * We have to add the size of our arguments to our stack size
  	 * otherwise it's too easy for users to create stack overflows
  	 * by passing in a huge argument list.  And yes,  we have to be
  	 * pedantic and include space for the argv/envp array as it may have
  	 * a lot of entries.
  	 */
  #define TOP_OF_ARGS (PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *))
  	stack_len = TOP_OF_ARGS - bprm->p;             /* the strings */
  	stack_len += (bprm->argc + 1) * sizeof(char *); /* the argv array */
  	stack_len += (bprm->envc + 1) * sizeof(char *); /* the envp array */
2e94de8ac   Mike Frysinger   fs/binfmt_flat.c:...
905
  	stack_len += FLAT_STACK_ALIGN - 1;  /* reserve for upcoming alignment */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
906
907
  	
  	res = load_flat_file(bprm, &libinfo, 0, &stack_len);
0b8c78f2b   Mike Frysinger   flat: use IS_ERR_...
908
  	if (IS_ERR_VALUE(res))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
909
910
911
912
913
914
915
916
917
  		return res;
  	
  	/* Update data segment pointers for all libraries */
  	for (i=0; i<MAX_SHARED_LIBS; i++)
  		if (libinfo.lib_list[i].loaded)
  			for (j=0; j<MAX_SHARED_LIBS; j++)
  				(-(j+1))[(unsigned long *)(libinfo.lib_list[i].start_data)] =
  					(libinfo.lib_list[j].loaded)?
  						libinfo.lib_list[j].start_data:UNLOADED_LIB;
a6f76f23d   David Howells   CRED: Make execve...
918
  	install_exec_creds(bprm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
   	current->flags &= ~PF_FORKNOEXEC;
  
  	set_binfmt(&flat_format);
  
  	p = ((current->mm->context.end_brk + stack_len + 3) & ~3) - 4;
  	DBG_FLT("p=%x
  ", (int)p);
  
  	/* copy the arg pages onto the stack, this could be more efficient :-) */
  	for (i = TOP_OF_ARGS - 1; i >= bprm->p; i--)
  		* (char *) --p =
  			((char *) page_address(bprm->page[i/PAGE_SIZE]))[i % PAGE_SIZE];
  
  	sp = (unsigned long *) create_flat_tables(p, bprm);
  	
  	/* Fake some return addresses to ensure the call chain will
  	 * initialise library in order for us.  We are required to call
  	 * lib 1 first, then 2, ... and finally the main program (id 0).
  	 */
  	start_addr = libinfo.lib_list[0].entry;
  
  #ifdef CONFIG_BINFMT_SHARED_FLAT
  	for (i = MAX_SHARED_LIBS-1; i>0; i--) {
  		if (libinfo.lib_list[i].loaded) {
  			/* Push previos first to call address */
  			--sp;	put_user(start_addr, sp);
  			start_addr = libinfo.lib_list[i].entry;
  		}
  	}
  #endif
  	
  	/* Stash our initial stack pointer into the mm structure */
  	current->mm->start_stack = (unsigned long )sp;
74c27c43e   Takashi YOSHII   binfmt_flat: Stub...
952
953
954
  #ifdef FLAT_PLAT_INIT
  	FLAT_PLAT_INIT(regs);
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
955
956
957
958
959
  	DBG_FLT("start_thread(regs=0x%x, entry=0x%x, start_stack=0x%x)
  ",
  		(int)regs, (int)start_addr, (int)current->mm->start_stack);
  	
  	start_thread(regs, start_addr, current->mm->start_stack);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
960
961
962
963
964
965
966
967
968
  	return 0;
  }
  
  /****************************************************************************/
  
  static int __init init_flat_binfmt(void)
  {
  	return register_binfmt(&flat_format);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
969
970
971
  /****************************************************************************/
  
  core_initcall(init_flat_binfmt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
972
973
  
  /****************************************************************************/