1 /* This file handles the EXEC system call. It performs the work as follows:
2 * - see if the permissions allow the file to be executed
3 * - read the header and extract the sizes
4 * - fetch the initial args and environment from the user space
5 * - allocate the memory for the new process
6 * - copy the initial stack from PM to the process
7 * - read in the text and data segments and copy to the process
8 * - take care of setuid and setgid bits
9 * - fix up 'mproc' table
10 * - tell kernel about EXEC
11 * - save offset to initial argc (for ps)
13 * The entry points into this file are:
14 * pm_exec: perform the EXEC system call
19 #include <minix/callnr.h>
20 #include <minix/endpoint.h>
21 #include <minix/com.h>
22 #include <minix/u64.h>
28 #include <sys/param.h>
33 #include <minix/vfsif.h>
34 #include <machine/vmparam.h>
38 #define _KERNEL /* for ELF_AUX_ENTRIES */
41 /* fields only used by elf and in VFS */
42 struct vfs_exec_info
{
43 struct exec_info args
; /* libexec exec args */
44 struct vnode
*vp
; /* Exec file's vnode */
45 struct vmnt
*vmp
; /* Exec file's vmnt */
46 struct stat sb
; /* Exec file's stat structure */
47 int userflags
; /* exec() flags from userland */
48 int is_dyn
; /* Dynamically linked executable */
49 int elf_main_fd
; /* Dyn: FD of main program execuatble */
50 char execname
[PATH_MAX
]; /* Full executable invocation */
53 static void lock_exec(void);
54 static void unlock_exec(void);
55 static int patch_stack(struct vnode
*vp
, char stack
[ARG_MAX
],
56 size_t *stk_bytes
, char path
[PATH_MAX
]);
57 static int is_script(struct vfs_exec_info
*execi
);
58 static int insert_arg(char stack
[ARG_MAX
], size_t *stk_bytes
, char *arg
,
60 static void clo_exec(struct fproc
*rfp
);
61 static int stack_prepare_elf(struct vfs_exec_info
*execi
,
62 char *curstack
, size_t *frame_len
, vir_bytes
*vsp
, int *extrabase
);
63 static int map_header(struct vfs_exec_info
*execi
);
64 static int read_seg(struct exec_info
*execi
, off_t off
, off_t seg_addr
, size_t seg_bytes
);
66 #define PTRSIZE sizeof(char *) /* Size of pointers in argv[] and envp[]. */
68 /* Array of loaders for different object file formats */
69 typedef int (*exechook_t
)(struct vfs_exec_info
*execpackage
);
70 typedef int (*stackhook_t
)(struct vfs_exec_info
*execi
, char *curstack
,
71 size_t *frame_len
, vir_bytes
*, int *extrabase
);
73 libexec_exec_loadfunc_t load_object
; /* load executable into memory */
74 stackhook_t setup_stack
; /* prepare stack before argc and argv push */
77 static const struct exec_loaders exec_loaders
[] = {
78 { libexec_load_elf
, stack_prepare_elf
},
82 /*===========================================================================*
84 *===========================================================================*/
85 static void lock_exec(void)
88 struct worker_thread
*org_self
;
90 /* First try to get it right off the bat */
91 if (mutex_trylock(&exec_lock
) == 0)
97 if (mutex_lock(&exec_lock
) != 0)
98 panic("Could not obtain lock on exec");
104 /*===========================================================================*
106 *===========================================================================*/
107 static void unlock_exec(void)
109 if (mutex_unlock(&exec_lock
) != 0)
110 panic("Could not release lock on exec");
113 /*===========================================================================*
115 *===========================================================================*/
116 static int get_read_vp(struct vfs_exec_info
*execi
,
117 char *fullpath
, int copyprogname
, int sugid
, struct lookup
*resolve
, struct fproc
*fp
)
119 /* Make the executable that we want to exec() into the binary pointed
120 * to by 'fullpath.' This function fills in necessary details in the execi
121 * structure, such as opened vnode. It unlocks and releases the vnode if
122 * it was already there. This makes it easy to change the executable
123 * during the exec(), which is often necessary, by calling this function
124 * more than once. This is specifically necessary when we discover the
125 * executable is actually a script or a dynamically linked executable.
129 /* Caller wants to switch vp to the file in 'fullpath.'
130 * unlock and put it first if there is any there.
133 unlock_vnode(execi
->vp
);
134 put_vnode(execi
->vp
);
138 /* Remember/overwrite the executable name if requested. */
140 char *cp
= strrchr(fullpath
, '/');
143 strlcpy(execi
->args
.progname
, cp
, sizeof(execi
->args
.progname
));
144 execi
->args
.progname
[sizeof(execi
->args
.progname
)-1] = '\0';
147 /* Open executable */
148 if ((execi
->vp
= eat_path(resolve
, fp
)) == NULL
)
151 unlock_vmnt(execi
->vmp
);
153 if (!S_ISREG(execi
->vp
->v_mode
))
155 else if ((r
= forbidden(fp
, execi
->vp
, X_BIT
)) != OK
)
158 r
= req_stat(execi
->vp
->v_fs_e
, execi
->vp
->v_inode_nr
,
159 VFS_PROC_NR
, (vir_bytes
) &(execi
->sb
), 0);
161 if (r
!= OK
) return r
;
163 /* If caller wants us to, honour suid/guid mode bits. */
165 /* Deal with setuid/setgid executables */
166 if (execi
->vp
->v_mode
& I_SET_UID_BIT
) {
167 execi
->args
.new_uid
= execi
->vp
->v_uid
;
168 execi
->args
.allow_setuid
= 1;
170 if (execi
->vp
->v_mode
& I_SET_GID_BIT
) {
171 execi
->args
.new_gid
= execi
->vp
->v_gid
;
172 execi
->args
.allow_setuid
= 1;
176 /* Read in first chunk of file. */
177 if((r
=map_header(execi
)) != OK
)
183 #define FAILCHECK(expr) if((r=(expr)) != OK) { goto pm_execfinal; } while(0)
184 #define Get_read_vp(e,f,p,s,rs,fp) do { \
185 r=get_read_vp(&e,f,p,s,rs,fp); if(r != OK) { FAILCHECK(r); } \
188 /*===========================================================================*
190 *===========================================================================*/
191 int pm_exec(endpoint_t proc_e
, vir_bytes path
, size_t path_len
,
192 vir_bytes frame
, size_t frame_len
, vir_bytes
*pc
,
193 vir_bytes
*newsp
, int user_exec_flags
)
195 /* Perform the execve(name, argv, envp) call. The user library builds a
196 * complete stack image, including pointers, args, environ, etc. The stack
197 * is copied to a buffer inside VFS, and then to the new core image.
203 static char mbuf
[ARG_MAX
]; /* buffer for stack and zeroes */
204 struct vfs_exec_info execi
;
206 static char fullpath
[PATH_MAX
],
207 elf_interpreter
[PATH_MAX
],
209 struct lookup resolve
;
210 stackhook_t makestack
= NULL
;
214 /* unset execi values are 0. */
215 memset(&execi
, 0, sizeof(execi
));
217 /* passed from exec() libc code */
218 execi
.userflags
= user_exec_flags
;
219 execi
.args
.stack_high
= kinfo
.user_sp
;
220 execi
.args
.stack_size
= DEFAULT_STACK_LIMIT
;
222 okendpt(proc_e
, &slot
);
223 rfp
= fp
= &fproc
[slot
];
225 lookup_init(&resolve
, fullpath
, PATH_NOFLAGS
, &execi
.vmp
, &execi
.vp
);
226 resolve
.l_vmnt_lock
= VMNT_READ
;
227 resolve
.l_vnode_lock
= VNODE_READ
;
229 /* Fetch the stack from the user before destroying the old core image. */
230 if (frame_len
> ARG_MAX
)
231 FAILCHECK(ENOMEM
); /* stack too big */
233 r
= sys_datacopy(proc_e
, (vir_bytes
) frame
, SELF
, (vir_bytes
) mbuf
,
235 if (r
!= OK
) { /* can't fetch stack (e.g. bad virtual addr) */
236 printf("VFS: pm_exec: sys_datacopy failed\n");
240 /* The default is to keep the original user and group IDs */
241 execi
.args
.new_uid
= rfp
->fp_effuid
;
242 execi
.args
.new_gid
= rfp
->fp_effgid
;
244 /* Get the exec file name. */
245 FAILCHECK(fetch_name(path
, path_len
, fullpath
));
246 strlcpy(finalexec
, fullpath
, PATH_MAX
);
248 /* Get_read_vp will return an opened vn in execi.
249 * if necessary it releases the existing vp so we can
250 * switch after we find out what's inside the file.
251 * It reads the start of the file.
253 Get_read_vp(execi
, fullpath
, 1, 1, &resolve
, fp
);
255 /* If this is a script (i.e. has a #!/interpreter line),
256 * retrieve the name of the interpreter and open that
257 * executable instead.
259 if(is_script(&execi
)) {
260 /* patch_stack will add interpreter name and
261 * args to stack and retrieve the new binary
262 * name into fullpath.
264 FAILCHECK(fetch_name(path
, path_len
, fullpath
));
265 FAILCHECK(patch_stack(execi
.vp
, mbuf
, &frame_len
, fullpath
));
266 strlcpy(finalexec
, fullpath
, PATH_MAX
);
267 Get_read_vp(execi
, fullpath
, 1, 0, &resolve
, fp
);
270 /* If this is a dynamically linked executable, retrieve
271 * the name of that interpreter in elf_interpreter and open that
272 * executable instead. But open the current executable in an
273 * fd for the current process.
275 if(elf_has_interpreter(execi
.args
.hdr
, execi
.args
.hdr_len
,
276 elf_interpreter
, sizeof(elf_interpreter
))) {
277 /* Switch the executable vnode to the interpreter */
280 /* The interpreter (loader) needs an fd to the main program,
281 * which is currently in finalexec
283 if((r
= execi
.elf_main_fd
= common_open(finalexec
, O_RDONLY
, 0)) < 0) {
284 printf("VFS: exec: dynamic: open main exec failed %s (%d)\n",
289 /* ld.so is linked at 0, but it can relocate itself; we
290 * want it higher to trap NULL pointer dereferences.
292 execi
.args
.load_offset
= 0x10000;
295 strlcpy(execi
.execname
, finalexec
, PATH_MAX
);
297 /* The executable we need to execute first (loader)
298 * is in elf_interpreter, and has to be in fullpath to
301 strlcpy(fullpath
, elf_interpreter
, PATH_MAX
);
302 Get_read_vp(execi
, fullpath
, 0, 0, &resolve
, fp
);
305 /* callback functions and data */
306 execi
.args
.copymem
= read_seg
;
307 execi
.args
.clearproc
= libexec_clearproc_vm_procctl
;
308 execi
.args
.clearmem
= libexec_clear_sys_memset
;
309 execi
.args
.allocmem_prealloc
= libexec_alloc_mmap_prealloc
;
310 execi
.args
.allocmem_ondemand
= libexec_alloc_mmap_ondemand
;
311 execi
.args
.opaque
= &execi
;
313 execi
.args
.proc_e
= proc_e
;
314 execi
.args
.frame_len
= frame_len
;
316 for (i
= 0; exec_loaders
[i
].load_object
!= NULL
; i
++) {
317 r
= (*exec_loaders
[i
].load_object
)(&execi
.args
);
318 /* Loaded successfully, so no need to try other loaders */
319 if (r
== OK
) { makestack
= exec_loaders
[i
].setup_stack
; break; }
325 FAILCHECK(libexec_pm_newexec(proc_e
, &execi
.args
));
330 /* call a stack-setup function if this executable type wants it */
331 vsp
= execi
.args
.stack_high
- frame_len
;
332 if(makestack
) FAILCHECK(makestack(&execi
, mbuf
, &frame_len
, &vsp
, &extrabase
));
334 /* Patch up stack and copy it from VFS to new core image. */
335 libexec_patch_ptr(mbuf
, vsp
+ extrabase
);
336 FAILCHECK(sys_datacopy(SELF
, (vir_bytes
) mbuf
, proc_e
, (vir_bytes
) vsp
,
337 (phys_bytes
)frame_len
));
339 /* Return new stack pointer to caller */
344 if (execi
.args
.allow_setuid
) {
345 /* If after loading the image we're still allowed to run with
346 * setuid or setgid, change credentials now */
347 rfp
->fp_effuid
= execi
.args
.new_uid
;
348 rfp
->fp_effgid
= execi
.args
.new_gid
;
351 /* Remember the new name of the process */
352 strlcpy(rfp
->fp_name
, execi
.args
.progname
, PROC_NAME_LEN
);
355 if (execi
.vp
!= NULL
) {
356 unlock_vnode(execi
.vp
);
363 static int stack_prepare_elf(struct vfs_exec_info
*execi
, char *frame
, size_t *framelen
,
364 vir_bytes
*newsp
, int *extrabase
)
367 Elf_Ehdr
*elf_header
;
369 char **mysp
= (char **) frame
,
370 **mysp_end
= (char **) ((char *)frame
+ *framelen
);
375 assert(execi
->args
.hdr_len
>= sizeof(*elf_header
));
376 elf_header
= (Elf_Ehdr
*) execi
->args
.hdr
;
378 /* exec() promises stack space. Now find it. */
379 mysp
++; /* skip argc */
381 /* find a terminating NULL entry twice: one for argv[], one for envp[]. */
382 for(nulls
= 0; nulls
< 2; nulls
++) {
383 assert(mysp
< mysp_end
);
384 while(*mysp
&& mysp
< mysp_end
) mysp
++; /* find terminating NULL */
385 if(mysp
>= mysp_end
) {
386 printf("VFS: malformed stack for exec()\n");
393 /* Userland provides a fully filled stack frame, with argc, argv, envp
394 * and then all the argv and envp strings; consistent with ELF ABI, except
395 * for a list of Aux vectors that should be between envp points and the
396 * start of the strings.
398 * It would take some very unpleasant hackery to insert the aux vectors before
399 * the strings, and correct all the pointers, so the exec code in libc makes
400 * space for us first and indicates the fact it did this with this flag.
402 if(!(execi
->userflags
& PMEF_AUXVECTORSPACE
)) {
403 char *f
= (char *) mysp
;
405 vir_bytes extrabytes
= sizeof(*a
) * PMEF_AUXVECTORS
;
407 /* Create extrabytes more space */
408 remain
= *framelen
- (int)(f
- frame
);
409 if(*framelen
+ extrabytes
>= ARG_MAX
)
411 *framelen
+= extrabytes
;
412 *newsp
-= extrabytes
;
413 *extrabase
+= extrabytes
;
414 memmove(f
+extrabytes
, f
, remain
);
415 memset(f
, 0, extrabytes
);
418 /* Ok, what mysp points to now we can use for the aux vectors. */
419 a
= (AuxInfo
*) mysp
;
420 #define AUXINFO(type, value) \
421 { assert((char *) a < (char *) mysp_end); a->a_type = type; a->a_v = value; a++; }
423 AUXINFO(AT_PHENT
, elf_header
->e_phentsize
);
424 AUXINFO(AT_PHNUM
, elf_header
->e_phnum
);
426 AUXINFO(AT_BASE
, execi
->args
.load_base
);
427 AUXINFO(AT_ENTRY
, execi
->args
.pc
);
428 AUXINFO(AT_PAGESZ
, PAGE_SIZE
);
429 AUXINFO(AT_EXECFD
, execi
->elf_main_fd
);
431 /* This is where we add the AT_NULL */
434 /* Always terminate with AT_NULL */
437 /* Empty space starts here, if any. */
438 if((execi
->userflags
& PMEF_EXECNAMESPACE1
)
439 && strlen(execi
->execname
) < PMEF_EXECNAMELEN1
) {
443 /* Make space for the real closing AT_NULL entry. */
446 /* Empty space starts here; we can put the name here. */
447 spacestart
= (char *) a
;
448 strlcpy(spacestart
, execi
->execname
, PATH_MAX
);
450 /* What will the address of the string for the user be */
451 userp
= *newsp
+ (spacestart
-frame
);
453 /* Move back to where the AT_NULL is */
455 AUXINFO(AT_SUN_EXECNAME
, userp
);
462 /*===========================================================================*
464 *===========================================================================*/
465 static int is_script(struct vfs_exec_info
*execi
)
467 /* Is Interpreted script? */
468 assert(execi
->args
.hdr
!= NULL
);
470 return(execi
->args
.hdr
[0] == '#' && execi
->args
.hdr
[1] == '!'
471 && execi
->args
.hdr_len
>= 2);
474 /*===========================================================================*
476 *===========================================================================*/
477 static int patch_stack(vp
, stack
, stk_bytes
, path
)
478 struct vnode
*vp
; /* pointer for open script file */
479 char stack
[ARG_MAX
]; /* pointer to stack image within VFS */
480 size_t *stk_bytes
; /* size of initial stack */
481 char path
[PATH_MAX
]; /* path to script file */
483 /* Patch the argument vector to include the path name of the script to be
484 * interpreted, and all strings on the #! line. Returns the path name of
487 enum { INSERT
=FALSE
, REPLACE
=TRUE
};
490 char *sp
, *interp
= NULL
;
493 char buf
[_MAX_BLOCK_SIZE
];
495 /* Make 'path' the new argv[0]. */
496 if (!insert_arg(stack
, stk_bytes
, path
, REPLACE
)) return(ENOMEM
);
498 pos
= 0; /* Read from the start of the file */
501 r
= req_readwrite(vp
->v_fs_e
, vp
->v_inode_nr
, cvul64(pos
), READING
,
502 VFS_PROC_NR
, buf
, _MAX_BLOCK_SIZE
, &new_pos
, &cum_io
);
503 if (r
!= OK
) return(r
);
506 if (n
> _MAX_BLOCK_SIZE
)
508 if (n
< 2) return ENOEXEC
;
510 sp
= &(buf
[2]); /* just behind the #! */
512 if (n
> PATH_MAX
) n
= PATH_MAX
;
514 /* Use the 'path' variable for temporary storage */
517 if ((sp
= memchr(path
, '\n', n
)) == NULL
) /* must be a proper line */
520 /* Move sp backwards through script[], prepending each string to stack. */
522 /* skip spaces behind argument. */
523 while (sp
> path
&& (*--sp
== ' ' || *sp
== '\t')) {}
524 if (sp
== path
) break;
527 /* Move to the start of the argument. */
528 while (sp
> path
&& sp
[-1] != ' ' && sp
[-1] != '\t') --sp
;
531 if (!insert_arg(stack
, stk_bytes
, sp
, INSERT
)) {
532 printf("VFS: patch_stack: insert_arg failed\n");
540 /* Round *stk_bytes up to the size of a pointer for alignment contraints. */
541 *stk_bytes
= ((*stk_bytes
+ PTRSIZE
- 1) / PTRSIZE
) * PTRSIZE
;
544 memmove(path
, interp
, strlen(interp
)+1);
548 /*===========================================================================*
550 *===========================================================================*/
551 static int insert_arg(
552 char stack
[ARG_MAX
], /* pointer to stack image within PM */
553 size_t *stk_bytes
, /* size of initial stack */
554 char *arg
, /* argument to prepend/replace as new argv[0] */
558 /* Patch the stack so that arg will become argv[0]. Be careful, the stack may
559 * be filled with garbage, although it normally looks like this:
560 * nargs argv[0] ... argv[nargs-1] NULL envp[0] ... NULL
561 * followed by the strings "pointed" to by the argv[i] and the envp[i]. The
562 * pointers are really offsets from the start of stack.
563 * Return true iff the operation succeeded.
567 size_t old_bytes
= *stk_bytes
;
569 /* Prepending arg adds at least one string and a zero byte. */
570 offset
= strlen(arg
) + 1;
572 a0
= (int) ((char **) stack
)[1]; /* argv[0] */
573 if (a0
< 4 * PTRSIZE
|| a0
>= old_bytes
) return(FALSE
);
575 a1
= a0
; /* a1 will point to the strings to be moved */
577 /* Move a1 to the end of argv[0][] (argv[1] if nargs > 1). */
579 if (a1
== old_bytes
) return(FALSE
);
581 } while (stack
[a1
++] != 0);
583 offset
+= PTRSIZE
; /* new argv[0] needs new pointer in argv[] */
584 a0
+= PTRSIZE
; /* location of new argv[0][]. */
587 /* stack will grow by offset bytes (or shrink by -offset bytes) */
588 if ((*stk_bytes
+= offset
) > ARG_MAX
) return(FALSE
);
590 /* Reposition the strings by offset bytes */
591 memmove(stack
+ a1
+ offset
, stack
+ a1
, old_bytes
- a1
);
593 strlcpy(stack
+ a0
, arg
, PATH_MAX
); /* Put arg in the new space. */
596 /* Make space for a new argv[0]. */
597 memmove(stack
+ 2 * PTRSIZE
, stack
+ 1 * PTRSIZE
, a0
- 2 * PTRSIZE
);
599 ((char **) stack
)[0]++; /* nargs++; */
601 /* Now patch up argv[] and envp[] by offset. */
602 libexec_patch_ptr(stack
, (vir_bytes
) offset
);
603 ((char **) stack
)[1] = (char *) a0
; /* set argv[0] correctly */
607 /*===========================================================================*
609 *===========================================================================*/
610 static int read_seg(struct exec_info
*execi
, off_t off
, off_t seg_addr
, size_t seg_bytes
)
613 * The byte count on read is usually smaller than the segment count, because
614 * a segment is padded out to a click multiple, and the data segment is only
615 * partially initialized.
620 struct vnode
*vp
= ((struct vfs_exec_info
*) execi
->opaque
)->vp
;
622 /* Make sure that the file is big enough */
623 if (off
+ seg_bytes
> LONG_MAX
) return(EIO
);
624 if ((unsigned long) vp
->v_size
< off
+seg_bytes
) return(EIO
);
626 if ((r
= req_readwrite(vp
->v_fs_e
, vp
->v_inode_nr
, cvul64(off
), READING
,
627 execi
->proc_e
, (char*)seg_addr
, seg_bytes
,
628 &new_pos
, &cum_io
)) != OK
) {
629 printf("VFS: read_seg: req_readwrite failed (data)\n");
633 if (r
== OK
&& cum_io
!= seg_bytes
)
634 printf("VFS: read_seg segment has not been read properly\n");
640 /*===========================================================================*
642 *===========================================================================*/
643 static void clo_exec(struct fproc
*rfp
)
645 /* Files can be marked with the FD_CLOEXEC bit (in fp->fp_cloexec).
649 /* Check the file desriptors one by one for presence of FD_CLOEXEC. */
650 for (i
= 0; i
< OPEN_MAX
; i
++)
651 if ( FD_ISSET(i
, &rfp
->fp_cloexec_set
))
652 (void) close_fd(rfp
, i
);
655 /*===========================================================================*
657 *===========================================================================*/
658 static int map_header(struct vfs_exec_info
*execi
)
664 static char hdr
[PAGE_SIZE
]; /* Assume that header is not larger than a page */
666 pos
= 0; /* Read from the start of the file */
668 /* How much is sensible to read */
669 execi
->args
.hdr_len
= MIN(execi
->vp
->v_size
, sizeof(hdr
));
670 execi
->args
.hdr
= hdr
;
672 r
= req_readwrite(execi
->vp
->v_fs_e
, execi
->vp
->v_inode_nr
,
673 cvul64(pos
), READING
, VFS_PROC_NR
, hdr
,
674 execi
->args
.hdr_len
, &new_pos
, &cum_io
);
676 printf("VFS: exec: map_header: req_readwrite failed\n");