00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "fs.h"
00018 #include <sys/stat.h>
00019 #include <minix/callnr.h>
00020 #include <minix/endpoint.h>
00021 #include <minix/com.h>
00022 #include <minix/u64.h>
00023 #include <a.out.h>
00024 #include <signal.h>
00025 #include <string.h>
00026 #include <dirent.h>
00027 #include "fproc.h"
00028 #include "param.h"
00029 #include "vnode.h"
00030 #include "vmnt.h"
00031 #include <minix/vfsif.h>
00032
00033 FORWARD _PROTOTYPE( int exec_newmem, (int proc_e, vir_bytes text_bytes,
00034 vir_bytes data_bytes, vir_bytes bss_bytes, vir_bytes tot_bytes,
00035 vir_bytes frame_len, int sep_id,
00036 Dev_t st_dev, ino_t st_ino, time_t st_ctime, char *progname,
00037 int new_uid, int new_gid,
00038 vir_bytes *stack_topp, int *load_textp, int *allow_setuidp) );
00039 FORWARD _PROTOTYPE( int read_header, (struct vnode *vp, int *sep_id,
00040 vir_bytes *text_bytes, vir_bytes *data_bytes,
00041 vir_bytes *bss_bytes, phys_bytes *tot_bytes, vir_bytes *pc,
00042 int *hdrlenp) );
00043 FORWARD _PROTOTYPE( int patch_stack, (struct vnode *vp,
00044 char stack[ARG_MAX], vir_bytes *stk_bytes) );
00045 FORWARD _PROTOTYPE( int insert_arg, (char stack[ARG_MAX],
00046 vir_bytes *stk_bytes, char *arg, int replace) );
00047 FORWARD _PROTOTYPE( void patch_ptr, (char stack[ARG_MAX],
00048 vir_bytes base) );
00049 FORWARD _PROTOTYPE( int read_seg, (struct vnode *vp, off_t off,
00050 int proc_e, int seg, phys_bytes seg_bytes) );
00051 FORWARD _PROTOTYPE( void clo_exec, (struct fproc *rfp) );
00052
00053 #define ESCRIPT (-2000)
00054 #define PTRSIZE sizeof(char *)
00055
00056
00057
00058
00059 PUBLIC int pm_exec(proc_e, path, path_len, frame, frame_len)
00060 int proc_e;
00061 char *path;
00062 vir_bytes path_len;
00063 char *frame;
00064 vir_bytes frame_len;
00065 {
00066
00067
00068
00069
00070 int r, r1, sep_id, round, proc_s, hdrlen, load_text, allow_setuid;
00071 vir_bytes text_bytes, data_bytes, bss_bytes, pc;
00072 phys_bytes tot_bytes;
00073 vir_bytes stack_top, vsp;
00074 off_t off;
00075 uid_t new_uid;
00076 gid_t new_gid;
00077 struct fproc *rfp;
00078 struct vnode *vp;
00079 time_t v_ctime;
00080 char *cp;
00081 struct stat sb;
00082 char progname[PROC_NAME_LEN];
00083 static char mbuf[ARG_MAX];
00084
00085 okendpt(proc_e, &proc_s);
00086 rfp = fp = &fproc[proc_s];
00087 who_e = proc_e;
00088 who_p = proc_s;
00089 super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE);
00090
00091
00092 if ((r = fetch_name(path, path_len, 0)) != OK) return(r);
00093
00094
00095 if (frame_len > ARG_MAX) return(ENOMEM);
00096 r = sys_datacopy(proc_e, (vir_bytes) frame, SELF, (vir_bytes) mbuf,
00097 (phys_bytes) frame_len);
00098 if (r != OK) {
00099 printf("pm_exec: sys_datacopy failed\n");
00100 return(r);
00101 }
00102
00103
00104 new_uid = rfp->fp_effuid;
00105 new_gid = rfp->fp_effgid;
00106
00107 for (round= 0; round < 2; round++) {
00108
00109
00110
00111 (cp= strrchr(user_fullpath, '/')) ? cp++ : (cp= user_fullpath);
00112
00113 strncpy(progname, cp, PROC_NAME_LEN-1);
00114 progname[PROC_NAME_LEN-1] = '\0';
00115
00116
00117 if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);
00118
00119 if ((vp->v_mode & I_TYPE) != I_REGULAR)
00120 r = ENOEXEC;
00121 else if ((r1 = forbidden(vp, X_BIT)) != OK)
00122 r = r1;
00123 else
00124 r = req_stat(vp->v_fs_e, vp->v_inode_nr, FS_PROC_NR,
00125 (char *) &sb, 0);
00126 if (r != OK) {
00127 put_vnode(vp);
00128 return(r);
00129 }
00130
00131 v_ctime = sb.st_ctime;
00132 if (round == 0) {
00133
00134 if (vp->v_mode & I_SET_UID_BIT) new_uid = vp->v_uid;
00135 if (vp->v_mode & I_SET_GID_BIT) new_gid = vp->v_gid;
00136 }
00137
00138
00139 r = read_header(vp, &sep_id, &text_bytes, &data_bytes, &bss_bytes,
00140 &tot_bytes, &pc, &hdrlen);
00141 if (r != ESCRIPT || round != 0)
00142 break;
00143
00144
00145 if ((r = fetch_name(path, path_len, 0)) != OK)
00146 printf("VFS pm_exec: 2nd fetch_name failed\n");
00147 else if ((r = patch_stack(vp, mbuf, &frame_len)) != OK)
00148 printf("VFS pm_exec: patch_stack failed\n");
00149 put_vnode(vp);
00150 if (r != OK) return(r);
00151 }
00152
00153 if (r != OK) {
00154 put_vnode(vp);
00155 return(ENOEXEC);
00156 }
00157
00158 r = exec_newmem(proc_e, text_bytes, data_bytes, bss_bytes, tot_bytes,
00159 frame_len, sep_id, vp->v_dev, vp->v_inode_nr, v_ctime,
00160 progname, new_uid, new_gid, &stack_top, &load_text,
00161 &allow_setuid);
00162 if (r != OK) {
00163 printf("VFS: pm_exec: exec_newmem failed: %d\n", r);
00164 put_vnode(vp);
00165 return(r);
00166 }
00167
00168
00169 vsp = stack_top;
00170 vsp -= frame_len;
00171 patch_ptr(mbuf, vsp);
00172 if ((r = sys_datacopy(SELF, (vir_bytes) mbuf, proc_e, (vir_bytes) vsp,
00173 (phys_bytes)frame_len)) != OK) {
00174 printf("VFS: datacopy failed (%d) trying to copy to %p\n", r, vsp);
00175 return(r);
00176 }
00177
00178 off = hdrlen;
00179
00180
00181 if (load_text) r = read_seg(vp, off, proc_e, T, text_bytes);
00182 off += text_bytes;
00183 if (r == OK) r = read_seg(vp, off, proc_e, D, data_bytes);
00184 put_vnode(vp);
00185 if (r != OK) return(r);
00186 clo_exec(rfp);
00187
00188 if (allow_setuid) {
00189 rfp->fp_effuid = new_uid;
00190 rfp->fp_effgid = new_gid;
00191 }
00192
00193
00194 rfp->fp_execced = 1;
00195
00196
00197 dmap_endpt_up(rfp->fp_endpoint);
00198
00199 return(OK);
00200 }
00201
00202
00203
00204
00205
00206 PRIVATE int exec_newmem(proc_e, text_bytes, data_bytes, bss_bytes, tot_bytes,
00207 frame_len, sep_id, st_dev, st_ino, st_ctime, progname,
00208 new_uid, new_gid, stack_topp, load_textp, allow_setuidp)
00209 int proc_e;
00210 vir_bytes text_bytes;
00211 vir_bytes data_bytes;
00212 vir_bytes bss_bytes;
00213 vir_bytes tot_bytes;
00214 vir_bytes frame_len;
00215 int sep_id;
00216 dev_t st_dev;
00217 ino_t st_ino;
00218 time_t st_ctime;
00219 int new_uid;
00220 int new_gid;
00221 char *progname;
00222 vir_bytes *stack_topp;
00223 int *load_textp;
00224 int *allow_setuidp;
00225 {
00226 int r;
00227 struct exec_newmem e;
00228 message m;
00229
00230 e.text_bytes = text_bytes;
00231 e.data_bytes = data_bytes;
00232 e.bss_bytes = bss_bytes;
00233 e.tot_bytes = tot_bytes;
00234 e.args_bytes = frame_len;
00235 e.sep_id = sep_id;
00236 e.st_dev = st_dev;
00237 e.st_ino = st_ino;
00238 e.st_ctime = st_ctime;
00239 e.new_uid = new_uid;
00240 e.new_gid = new_gid;
00241 strncpy(e.progname, progname, sizeof(e.progname)-1);
00242 e.progname[sizeof(e.progname)-1] = '\0';
00243
00244 m.m_type = EXEC_NEWMEM;
00245 m.EXC_NM_PROC = proc_e;
00246 m.EXC_NM_PTR = (char *)&e;
00247 if ((r = sendrec(PM_PROC_NR, &m)) != OK) return(r);
00248
00249 *stack_topp = m.m1_i1;
00250 *load_textp = !!(m.m1_i2 & EXC_NM_RF_LOAD_TEXT);
00251 *allow_setuidp = !!(m.m1_i2 & EXC_NM_RF_ALLOW_SETUID);
00252
00253 return(m.m_type);
00254 }
00255
00256
00257
00258
00259
00260 PRIVATE int read_header(vp, sep_id, text_bytes, data_bytes, bss_bytes,
00261 tot_bytes, pc, hdrlenp)
00262 struct vnode *vp;
00263 int *sep_id;
00264 vir_bytes *text_bytes;
00265 vir_bytes *data_bytes;
00266 vir_bytes *bss_bytes;
00267 phys_bytes *tot_bytes;
00268 vir_bytes *pc;
00269 int *hdrlenp;
00270 {
00271
00272 off_t pos;
00273 int r;
00274 u64_t new_pos;
00275 unsigned int cum_io;
00276 struct exec hdr;
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 pos= 0;
00306
00307
00308 r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(pos), READING,
00309 FS_PROC_NR, (char*)&hdr, sizeof(hdr), &new_pos, &cum_io);
00310 if (r != OK) return r;
00311
00312
00313 if (((char*)&hdr)[0] == '#' && ((char*)&hdr)[1] == '!' && vp->v_size >= 2)
00314 return(ESCRIPT);
00315
00316 if (vp->v_size < A_MINHDR) return(ENOEXEC);
00317
00318
00319 if (BADMAG(hdr)) return(ENOEXEC);
00320 #if (CHIP == INTEL && _WORD_SIZE == 2)
00321 if (hdr.a_cpu != A_I8086) return(ENOEXEC);
00322 #endif
00323 #if (CHIP == INTEL && _WORD_SIZE == 4)
00324 if (hdr.a_cpu != A_I80386) return(ENOEXEC);
00325 #endif
00326 if ((hdr.a_flags & ~(A_NSYM | A_EXEC | A_SEP)) != 0) return(ENOEXEC);
00327
00328 *sep_id = !!(hdr.a_flags & A_SEP);
00329
00330
00331 *text_bytes = (vir_bytes) hdr.a_text;
00332 *data_bytes = (vir_bytes) hdr.a_data;
00333 *bss_bytes = (vir_bytes) hdr.a_bss;
00334 *tot_bytes = hdr.a_total;
00335 if (*tot_bytes == 0) return(ENOEXEC);
00336
00337 if (!*sep_id) {
00338
00339 *data_bytes += *text_bytes;
00340 *text_bytes = 0;
00341 }
00342 *pc = hdr.a_entry;
00343 *hdrlenp = hdr.a_hdrlen & BYTE;
00344
00345 return(OK);
00346 }
00347
00348
00349
00350
00351
00352 PRIVATE int patch_stack(vp, stack, stk_bytes)
00353 struct vnode *vp;
00354 char stack[ARG_MAX];
00355 vir_bytes *stk_bytes;
00356 {
00357
00358
00359
00360
00361 enum { INSERT=FALSE, REPLACE=TRUE };
00362 int n, r;
00363 off_t pos;
00364 char *sp, *interp = NULL;
00365 u64_t new_pos;
00366 unsigned int cum_io;
00367 char buf[_MAX_BLOCK_SIZE];
00368
00369
00370 if (!insert_arg(stack, stk_bytes, user_fullpath, REPLACE)) return(ENOMEM);
00371
00372 pos = 0;
00373
00374
00375 r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(pos), READING,
00376 FS_PROC_NR, buf, _MAX_BLOCK_SIZE, &new_pos, &cum_io);
00377 if (r != OK) return(r);
00378
00379 n = vp->v_size;
00380 if (n > _MAX_BLOCK_SIZE)
00381 n = _MAX_BLOCK_SIZE;
00382 if (n < 2) return ENOEXEC;
00383
00384 sp = &(buf[2]);
00385 n -= 2;
00386 if (n > PATH_MAX) n = PATH_MAX;
00387
00388
00389 memcpy(user_fullpath, sp, n);
00390
00391 if ((sp = memchr(user_fullpath, '\n', n)) == NULL)
00392 return(ENOEXEC);
00393
00394
00395 for (;;) {
00396
00397 while (sp > user_fullpath && (*--sp == ' ' || *sp == '\t')) {}
00398 if (sp == user_fullpath) break;
00399
00400 sp[1] = 0;
00401
00402 while (sp > user_fullpath && sp[-1] != ' ' && sp[-1] != '\t') --sp;
00403
00404 interp = sp;
00405 if (!insert_arg(stack, stk_bytes, sp, INSERT)) return(ENOMEM);
00406 }
00407
00408
00409 *stk_bytes= ((*stk_bytes + PTRSIZE - 1) / PTRSIZE) * PTRSIZE;
00410
00411 if (interp != user_fullpath)
00412 memmove(user_fullpath, interp, strlen(interp)+1);
00413 return(OK);
00414 }
00415
00416
00417
00418
00419 PRIVATE int insert_arg(stack, stk_bytes, arg, replace)
00420 char stack[ARG_MAX];
00421 vir_bytes *stk_bytes;
00422 char *arg;
00423 int replace;
00424 {
00425
00426
00427
00428
00429
00430
00431
00432 int offset, a0, a1, old_bytes = *stk_bytes;
00433
00434
00435 offset = strlen(arg) + 1;
00436
00437 a0 = (int) ((char **) stack)[1];
00438 if (a0 < 4 * PTRSIZE || a0 >= old_bytes) return(FALSE);
00439
00440 a1 = a0;
00441 if (replace) {
00442
00443 do {
00444 if (a1 == old_bytes) return(FALSE);
00445 --offset;
00446 } while (stack[a1++] != 0);
00447 } else {
00448 offset += PTRSIZE;
00449 a0 += PTRSIZE;
00450 }
00451
00452
00453 if ((*stk_bytes += offset) > ARG_MAX) return(FALSE);
00454
00455
00456 memmove(stack + a1 + offset, stack + a1, old_bytes - a1);
00457
00458 strcpy(stack + a0, arg);
00459
00460 if (!replace) {
00461
00462 memmove(stack + 2 * PTRSIZE, stack + 1 * PTRSIZE, a0 - 2 * PTRSIZE);
00463
00464 ((char **) stack)[0]++;
00465 }
00466
00467 patch_ptr(stack, (vir_bytes) offset);
00468 ((char **) stack)[1] = (char *) a0;
00469 return(TRUE);
00470 }
00471
00472
00473
00474
00475
00476 PRIVATE void patch_ptr(stack, base)
00477 char stack[ARG_MAX];
00478 vir_bytes base;
00479 {
00480
00481
00482
00483
00484
00485
00486 char **ap, flag;
00487 vir_bytes v;
00488
00489 flag = 0;
00490 ap = (char **) stack;
00491 ap++;
00492 while (flag < 2) {
00493 if (ap >= (char **) &stack[ARG_MAX]) return;
00494 if (*ap != NULL) {
00495 v = (vir_bytes) *ap;
00496 v += base;
00497 *ap = (char *) v;
00498 } else {
00499 flag++;
00500 }
00501 ap++;
00502 }
00503 }
00504
00505
00506
00507
00508
00509 PRIVATE int read_seg(vp, off, proc_e, seg, seg_bytes)
00510 struct vnode *vp;
00511 off_t off;
00512 int proc_e;
00513 int seg;
00514 phys_bytes seg_bytes;
00515 {
00516
00517
00518
00519
00520
00521 int r;
00522 unsigned n, o;
00523 u64_t new_pos;
00524 unsigned int cum_io;
00525 char buf[1024];
00526
00527
00528 if (vp->v_size < off+seg_bytes) return(EIO);
00529
00530 if (seg != D) {
00531
00532 o = 0;
00533 while (o < seg_bytes) {
00534 n = seg_bytes - o;
00535 if (n > sizeof(buf))
00536 n = sizeof(buf);
00537
00538 if ((r = req_readwrite(vp->v_fs_e,vp->v_inode_nr,cvul64(off+o), READING, FS_PROC_NR, buf,
00539 n, &new_pos, &cum_io)) != OK) {
00540 printf("VFS: read_seg: req_readwrite failed (text)\n");
00541 return(r);
00542 }
00543
00544 if (cum_io != n) {
00545 printf(
00546 "VFSread_seg segment has not been read properly by exec() \n");
00547 return(EIO);
00548 }
00549
00550 if ((r = sys_vircopy(FS_PROC_NR, D, (vir_bytes)buf, proc_e,
00551 seg, o, n)) != OK) {
00552 printf("VFS: read_seg: copy failed (text)\n");
00553 return(r);
00554 }
00555
00556 o += n;
00557 }
00558 return(OK);
00559 }
00560
00561 if ((r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(off), READING,
00562 proc_e, 0, seg_bytes, &new_pos, &cum_io)) != OK) {
00563 printf("VFS: read_seg: req_readwrite failed (data)\n");
00564 return(r);
00565 }
00566
00567 if (r == OK && cum_io != seg_bytes)
00568 printf("VFSread_seg segment has not been read properly by exec()\n");
00569
00570 return(r);
00571 }
00572
00573
00574
00575
00576
00577 PRIVATE void clo_exec(rfp)
00578 struct fproc *rfp;
00579 {
00580
00581
00582 int i;
00583
00584
00585 for (i = 0; i < OPEN_MAX; i++)
00586 if ( FD_ISSET(i, &rfp->fp_cloexec_set))
00587 (void) close_fd(rfp, i);
00588 }
00589