📄 exec.c
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/mm/exec.c
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
17100 /* This file handles the EXEC system call. It performs the work as follows:
17101 * - see if the permissions allow the file to be executed
17102 * - read the header and extract the sizes
17103 * - fetch the initial args and environment from the user space
17104 * - allocate the memory for the new process
17105 * - copy the initial stack from MM to the process
17106 * - read in the text and data segments and copy to the process
17107 * - take care of setuid and setgid bits
17108 * - fix up 'mproc' table
17109 * - tell kernel about EXEC
17110 * - save offset to initial argc (for ps)
17111 *
17112 * The entry points into this file are:
17113 * do_exec: perform the EXEC system call
17114 * find_share: find a process whose text segment can be shared
17115 */
17116
17117 #include "mm.h"
17118 #include <sys/stat.h>
17119 #include <minix/callnr.h>
17120 #include <a.out.h>
17121 #include <signal.h>
17122 #include <string.h>
17123 #include "mproc.h"
17124 #include "param.h"
17125
17126 FORWARD _PROTOTYPE( void load_seg, (int fd, int seg, vir_bytes seg_bytes) );
17127 FORWARD _PROTOTYPE( int new_mem, (struct mproc *sh_mp, vir_bytes text_bytes,
17128 vir_bytes data_bytes, vir_bytes bss_bytes,
17129 vir_bytes stk_bytes, phys_bytes tot_bytes) );
17130 FORWARD _PROTOTYPE( void patch_ptr, (char stack [ARG_MAX ], vir_bytes base) );
17131 FORWARD _PROTOTYPE( int read_header, (int fd, int *ft, vir_bytes *text_bytes,
17132 vir_bytes *data_bytes, vir_bytes *bss_bytes,
17133 phys_bytes *tot_bytes, long *sym_bytes, vir_clicks sc,
17134 vir_bytes *pc) );
17135
17136
17137 /*===========================================================================*
17138 * do_exec *
17139 *===========================================================================*/
17140 PUBLIC int do_exec()
17141 {
17142 /* Perform the execve(name, argv, envp) call. The user library builds a
17143 * complete stack image, including pointers, args, environ, etc. The stack
17144 * is copied to a buffer inside MM, and then to the new core image.
17145 */
17146
17147 register struct mproc *rmp;
17148 struct mproc *sh_mp;
17149 int m, r, fd, ft, sn;
17150 static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */
17151 static char name_buf[PATH_MAX]; /* the name of the file to exec */
17152 char *new_sp, *basename;
17153 vir_bytes src, dst, text_bytes, data_bytes, bss_bytes, stk_bytes, vsp;
17154 phys_bytes tot_bytes; /* total space for program, including gap */
17155 long sym_bytes;
17156 vir_clicks sc;
17157 struct stat s_buf;
17158 vir_bytes pc;
17159
17160 /* Do some validity checks. */
17161 rmp = mp;
17162 stk_bytes = (vir_bytes) stack_bytes;
17163 if (stk_bytes > ARG_MAX) return(ENOMEM); /* stack too big */
17164 if (exec_len <= 0 || exec_len > PATH_MAX) return(EINVAL);
17165
17166 /* Get the exec file name and see if the file is executable. */
17167 src = (vir_bytes) exec_name;
17168 dst = (vir_bytes) name_buf;
17169 r = sys_copy(who, D, (phys_bytes) src,
17170 MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes) exec_len);
17171 if (r != OK) return(r); /* file name not in user data segment */
17172 tell_fs(CHDIR, who, FALSE, 0); /* switch to the user's FS environ. */
17173 fd = allowed(name_buf, &s_buf, X_BIT); /* is file executable? */
17174 if (fd < 0) return(fd); /* file was not executable */
17175
17176 /* Read the file header and extract the segment sizes. */
17177 sc = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
17178 m = read_header(fd, &ft, &text_bytes, &data_bytes, &bss_bytes,
17179 &tot_bytes, &sym_bytes, sc, &pc);
17180 if (m < 0) {
17181 close(fd); /* something wrong with header */
17182 return(ENOEXEC);
17183 }
17184
17185 /* Fetch the stack from the user before destroying the old core image. */
17186 src = (vir_bytes) stack_ptr;
17187 dst = (vir_bytes) mbuf;
17188 r = sys_copy(who, D, (phys_bytes) src,
17189 MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes)stk_bytes);
17190 if (r != OK) {
17191 close(fd); /* can't fetch stack (e.g. bad virtual addr) */
17192 return(EACCES);
17193 }
17194
17195 /* Can the process' text be shared with that of one already running? */
17196 sh_mp = find_share(rmp, s_buf.st_ino, s_buf.st_dev, s_buf.st_ctime);
17197
17198 /* Allocate new memory and release old memory. Fix map and tell kernel. */
17199 r = new_mem(sh_mp, text_bytes, data_bytes, bss_bytes, stk_bytes, tot_bytes);
17200 if (r != OK) {
17201 close(fd); /* insufficient core or program too big */
17202 return(r);
17203 }
17204
17205 /* Save file identification to allow it to be shared. */
17206 rmp->mp_ino = s_buf.st_ino;
17207 rmp->mp_dev = s_buf.st_dev;
17208 rmp->mp_ctime = s_buf.st_ctime;
17209
17210 /* Patch up stack and copy it from MM to new core image. */
17211 vsp = (vir_bytes) rmp->mp_seg[S].mem_vir << CLICK_SHIFT;
17212 vsp += (vir_bytes) rmp->mp_seg[S].mem_len << CLICK_SHIFT;
17213 vsp -= stk_bytes;
17214 patch_ptr(mbuf, vsp);
17215 src = (vir_bytes) mbuf;
17216 r = sys_copy(MM_PROC_NR, D, (phys_bytes) src,
17217 who, D, (phys_bytes) vsp, (phys_bytes)stk_bytes);
17218 if (r != OK) panic("do_exec stack copy err", NO_NUM);
17219
17220 /* Read in text and data segments. */
17221 if (sh_mp != NULL) {
17222 lseek(fd, (off_t) text_bytes, SEEK_CUR); /* shared: skip text */
17223 } else {
17224 load_seg(fd, T, text_bytes);
17225 }
17226 load_seg(fd, D, data_bytes);
17227
17228
17229 close(fd); /* don't need exec file any more */
17230
17231 /* Take care of setuid/setgid bits. */
17232 if ((rmp->mp_flags & TRACED) == 0) { /* suppress if tracing */
17233 if (s_buf.st_mode & I_SET_UID_BIT) {
17234 rmp->mp_effuid = s_buf.st_uid;
17235 tell_fs(SETUID,who, (int)rmp->mp_realuid, (int)rmp->mp_effuid);
17236 }
17237 if (s_buf.st_mode & I_SET_GID_BIT) {
17238 rmp->mp_effgid = s_buf.st_gid;
17239 tell_fs(SETGID,who, (int)rmp->mp_realgid, (int)rmp->mp_effgid);
17240 }
17241 }
17242
17243 /* Save offset to initial argc (for ps) */
17244 rmp->mp_procargs = vsp;
17245
17246 /* Fix 'mproc' fields, tell kernel that exec is done, reset caught sigs. */
17247 for (sn = 1; sn <= _NSIG; sn++) {
17248 if (sigismember(&rmp->mp_catch, sn)) {
17249 sigdelset(&rmp->mp_catch, sn);
17250 rmp->mp_sigact[sn].sa_handler = SIG_DFL;
17251 sigemptyset(&rmp->mp_sigact[sn].sa_mask);
17252 }
17253 }
17254
17255 rmp->mp_flags &= ~SEPARATE; /* turn off SEPARATE bit */
17256 rmp->mp_flags |= ft; /* turn it on for separate I & D files */
17257 new_sp = (char *) vsp;
17258
17259 tell_fs(EXEC, who, 0, 0); /* allow FS to handle FD_CLOEXEC files */
17260
17261 /* System will save command line for debugging, ps(1) output, etc. */
17262 basename = strrchr(name_buf, '/');
17263 if (basename == NULL) basename = name_buf; else basename++;
17264 sys_exec(who, new_sp, rmp->mp_flags & TRACED, basename, pc);
17265 return(OK);
17266 }
17269 /*===========================================================================*
17270 * read_header *
17271 *===========================================================================*/
17272 PRIVATE int read_header(fd, ft, text_bytes, data_bytes, bss_bytes,
17273 tot_bytes, sym_bytes, sc, pc)
17274 int fd; /* file descriptor for reading exec file */
17275 int *ft; /* place to return ft number */
17276 vir_bytes *text_bytes; /* place to return text size */
17277 vir_bytes *data_bytes; /* place to return initialized data size */
17278 vir_bytes *bss_bytes; /* place to return bss size */
17279 phys_bytes *tot_bytes; /* place to return total size */
17280 long *sym_bytes; /* place to return symbol table size */
17281 vir_clicks sc; /* stack size in clicks */
17282 vir_bytes *pc; /* program entry point (initial PC) */
17283 {
17284 /* Read the header and extract the text, data, bss and total sizes from it. */
17285
17286 int m, ct;
17287 vir_clicks tc, dc, s_vir, dvir;
17288 phys_clicks totc;
17289 struct exec hdr; /* a.out header is read in here */
17290
17291 /* Read the header and check the magic number. The standard MINIX header
17292 * is defined in <a.out.h>. It consists of 8 chars followed by 6 longs.
17293 * Then come 4 more longs that are not used here.
17294 * Byte 0: magic number 0x01
17295 * Byte 1: magic number 0x03
17296 * Byte 2: normal = 0x10 (not checked, 0 is OK), separate I/D = 0x20
17297 * Byte 3: CPU type, Intel 16 bit = 0x04, Intel 32 bit = 0x10,
17298 * Motorola = 0x0B, Sun SPARC = 0x17
17299 * Byte 4: Header length = 0x20
17300 * Bytes 5-7 are not used.
17301 *
17302 * Now come the 6 longs
17303 * Bytes 8-11: size of text segments in bytes
17304 * Bytes 12-15: size of initialized data segment in bytes
17305 * Bytes 16-19: size of bss in bytes
17306 * Bytes 20-23: program entry point
17307 * Bytes 24-27: total memory allocated to program (text, data + stack)
17308 * Bytes 28-31: size of symbol table in bytes
17309 * The longs are represented in a machine dependent order,
17310 * little-endian on the 8088, big-endian on the 68000.
17311 * The header is followed directly by the text and data segments, and the
17312 * symbol table (if any). The sizes are given in the header. Only the
17313 * text and data segments are copied into memory by exec. The header is
17314 * used here only. The symbol table is for the benefit of a debugger and
17315 * is ignored here.
17316 */
17317
17318 if (read(fd, (char *) &hdr, A_MINHDR) != A_MINHDR) return(ENOEXEC);
17319
17320 /* Check magic number, cpu type, and flags. */
17321 if (BADMAG(hdr)) return(ENOEXEC);
17322 #if (CHIP == INTEL && _WORD_SIZE == 2)
17323 if (hdr.a_cpu != A_I8086) return(ENOEXEC);
17324 #endif
17325 #if (CHIP == INTEL && _WORD_SIZE == 4)
17326 if (hdr.a_cpu != A_I80386) return(ENOEXEC);
17327 #endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -