diff options
-rw-r--r-- | ChangeLog.txt | 10 | ||||
-rw-r--r-- | guts/clone.c | 33 | ||||
-rw-r--r-- | guts/execve.c | 1 | ||||
-rw-r--r-- | guts/fork.c | 9 | ||||
-rw-r--r-- | pseudo_client.c | 127 | ||||
-rw-r--r-- | pseudo_client.h | 1 | ||||
-rw-r--r-- | pseudo_server.c | 63 | ||||
-rw-r--r-- | pseudo_wrappers.c | 72 |
8 files changed, 193 insertions, 123 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt index 121fe12..d1e18fc 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,13 @@ +2010-12-08: + * (mhatle) Add guts/clone.c to cleanup the clone support + * (mhatle) guts/clone.c only run setupenv and reinit when NOT PSEUDO_RELOADED + * (mhatle) guts/execve.c whitespace fixe + * (mhatle) guts/fork.c similar to guts/clone.c change + * (mhatle) pseudo_client.c add reinit function + * (mhatle) pseudo_client.c revise client reset, include code from pseudo_wrappers.c + * (mhatle) pseudo_server.c move the pid writing to the parent + * (mhatle) pseudo_wrappers.c clone cleanup and populate cleanup + 2010-12-07: * (seebs) whitespace fixes * (seebs) improve fork and PSEUDO_DISABLED diff --git a/guts/clone.c b/guts/clone.c new file mode 100644 index 0000000..61c8bf9 --- /dev/null +++ b/guts/clone.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2008-2010 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * static int + * clone(...) { + * .... + */ + /* because clone() doesn't actually continue in this function, we + * can't check the return and fix up environment variables in the + * child. Instead, we have to temporarily do any fixup, then possibly + * undo it later. UGH! + */ + pseudo_debug(1, "client resetting for clone(2) call\n"); + if (real_clone) { + if (!pseudo_get_value("PSEUDO_RELOADED")) { + pseudo_setupenv(); + pseudo_client_reinit(); + } else { + pseudo_setupenv(); + pseudo_dropenv(); + } + /* call the real syscall */ + rc = (*real_clone)(fn, child_stack, flags, arg, pid, tls, ctid); + } else { + /* rc was initialized to the "failure" value */ + pseudo_enosys("clone"); + } + +/* ... + * return rc; + * } + */ diff --git a/guts/execve.c b/guts/execve.c index 36d4bfd..febcf80 100644 --- a/guts/execve.c +++ b/guts/execve.c @@ -14,6 +14,7 @@ * design will likely be revisited. */ pseudo_client_op(OP_EXEC, PSA_EXEC, -1, -1, file, 0); + if (!pseudo_get_value("PSEUDO_RELOADED")) new_environ = pseudo_setupenvp(envp); else { diff --git a/guts/fork.c b/guts/fork.c index fa23be1..8febd13 100644 --- a/guts/fork.c +++ b/guts/fork.c @@ -12,8 +12,13 @@ * pseudo in the child process */ if (rc == 0) { - pseudo_setupenv(); - pseudo_client_reset(); + if (!pseudo_get_value("PSEUDO_RELOADED")) { + pseudo_setupenv(); + pseudo_client_reinit(); + } else { + pseudo_setupenv(); + pseudo_dropenv(); + } } } else { /* rc was initialized to the "failure" value */ diff --git a/pseudo_client.c b/pseudo_client.c index e30d3e7..8bad083 100644 --- a/pseudo_client.c +++ b/pseudo_client.c @@ -311,10 +311,16 @@ pseudo_client_close(int fd) { fd_paths[fd] = 0; } + void +pseudo_client_reinit() { + pseudo_debug(1, "called: pseudo_client_reinit\n"); + pseudo_inited = 0; + pseudo_reinit_environment(); + pseudo_client_reset(); +} + void pseudo_client_reset() { - char *env_disabled = NULL; - pseudo_antimagic(); pseudo_new_pid(); if (connect_fd != -1) { @@ -322,43 +328,94 @@ pseudo_client_reset() { connect_fd = -1; } - /* in child processes, PSEUDO_DISABLED may have become set to - * some truthy value, in which case we'd disable pseudo, - * or it may have gone away, in which case we'd enable - * pseudo. - */ - env_disabled = getenv("PSEUDO_DISABLED"); - if (env_disabled) { - int actually_disabled = 1; - switch (*env_disabled) { - case 'f': - case 'F': - case 'n': - case 'N': - actually_disabled = 0; - break; - case '0': - actually_disabled = atoi(env_disabled); - break; + if (!pseudo_inited) { + char *pseudo_path = 0; + char *env; + + /* Ensure that all of the values are reset */ + server_pid = 0; + pseudo_prefix_dir_fd = -1; + pseudo_localstate_dir_fd = -1; + pseudo_pwd_fd = -1; + pseudo_pwd_lck_fd = -1; + pseudo_pwd_lck_name = NULL; + pseudo_pwd = NULL; + pseudo_grp_fd = -1; + pseudo_grp = NULL; + pseudo_cwd = NULL; + pseudo_cwd_len = 0; + pseudo_chroot = NULL; + pseudo_passwd = NULL; + pseudo_chroot_len = 0; + pseudo_cwd_rel = NULL; + + pseudo_path = pseudo_prefix_path(NULL); + if (pseudo_prefix_dir_fd == -1) { + if (pseudo_path) { + pseudo_prefix_dir_fd = open(pseudo_path, O_RDONLY); + pseudo_prefix_dir_fd = pseudo_fd(pseudo_prefix_dir_fd, MOVE_FD); + } else { + pseudo_diag("No prefix available to to find server.\n"); + exit(1); + } + if (pseudo_prefix_dir_fd == -1) { + pseudo_diag("Can't open prefix path (%s) for server: %s\n", + pseudo_path, + strerror(errno)); + exit(1); + } } - if (actually_disabled) { - if (!pseudo_disabled) { - pseudo_antimagic(); - pseudo_disabled = 1; + free(pseudo_path); + pseudo_path = pseudo_localstatedir_path(NULL); + if (pseudo_localstate_dir_fd == -1) { + if (pseudo_path) { + pseudo_localstate_dir_fd = open(pseudo_path, O_RDONLY); + pseudo_localstate_dir_fd = pseudo_fd(pseudo_localstate_dir_fd, MOVE_FD); + } else { + pseudo_diag("No prefix available to to find server.\n"); + exit(1); } - env_disabled = "1"; - } else { - if (pseudo_disabled) { - pseudo_magic(); - pseudo_disabled = 0; + if (pseudo_localstate_dir_fd == -1) { + pseudo_diag("Can't open prefix path (%s) for server: %s\n", + pseudo_path, + strerror(errno)); + exit(1); } - env_disabled = "0"; } - pseudo_set_value("PSEUDO_DISABLED", env_disabled); - } + free(pseudo_path); - if (!pseudo_inited) { - char *env; + /* in child processes, PSEUDO_DISABLED may have become set to + * some truthy value, in which case we'd disable pseudo, + * or it may have gone away, in which case we'd enable + * pseudo. + */ + env = getenv("PSEUDO_DISABLED"); + if (!env) pseudo_get_value("PSEUDO_DISABLED"); + if (env) { + int actually_disabled = 1; + switch (*env) { + case '0': + case 'f': + case 'F': + case 'n': + case 'N': + actually_disabled = 0; + break; + } + if (actually_disabled) { + if (!pseudo_disabled) { + pseudo_antimagic(); + pseudo_disabled = 1; + } + pseudo_set_value("PSEUDO_DISABLED", "1"); + } else { + if (pseudo_disabled) { + pseudo_magic(); + pseudo_disabled = 0; + } + pseudo_set_value("PSEUDO_DISABLED", "0"); + } + } env = pseudo_get_value("PSEUDO_UIDS"); if (env) @@ -394,8 +451,6 @@ pseudo_client_reset() { pseudo_inited = 1; } pseudo_client_getcwd(); - /* make sure environment variables are back in sync */ - pseudo_reinit_environment(); pseudo_magic(); } diff --git a/pseudo_client.h b/pseudo_client.h index 7eac3c8..ea92f6a 100644 --- a/pseudo_client.h +++ b/pseudo_client.h @@ -20,6 +20,7 @@ extern pseudo_msg_t *pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path, const struct stat64 *buf, ...); extern void pseudo_antimagic(void); extern void pseudo_magic(void); +extern void pseudo_client_reinit(void); extern void pseudo_client_reset(void); extern void pseudo_client_touchuid(void); extern void pseudo_client_touchgid(void); diff --git a/pseudo_server.c b/pseudo_server.c index 071614c..50425de 100644 --- a/pseudo_server.c +++ b/pseudo_server.c @@ -81,12 +81,33 @@ static struct timeval message_time = { .tv_sec = 0 }; static void pseudo_server_loop(void); +static int +pseudo_server_write_pid(pid_t pid) { + char *pseudo_path; + FILE *fp; + + pseudo_path = pseudo_localstatedir_path(PSEUDO_PIDFILE); + if (!pseudo_path) { + pseudo_diag("Couldn't get path for prefix/%s\n", PSEUDO_PIDFILE); + return 1; + } + fp = fopen(pseudo_path, "w"); + if (!fp) { + pseudo_diag("Couldn't open %s: %s\n", + pseudo_path, strerror(errno)); + return 1; + } + fprintf(fp, "%lld\n", (long long) pid); + fclose(fp); + free(pseudo_path); + return 0; +} + int pseudo_server_start(int daemonize) { struct sockaddr_un sun = { AF_UNIX, PSEUDO_SOCKET }; char *pseudo_path; int rc, newfd; - FILE *fp; listen_fd = socket(PF_UNIX, SOCK_STREAM, 0); if (listen_fd < 0) { @@ -124,37 +145,29 @@ pseudo_server_start(int daemonize) { pseudo_diag("couldn't listen on socket: %s\n", strerror(errno)); return 1; } - if (daemonize && ((rc = fork()) != 0)) { - if (rc == -1) { - pseudo_diag("couldn't spawn server: %s\n", strerror(errno)); - return 0; - } - pseudo_debug(2, "started server, pid %d\n", rc); - close(listen_fd); - return 0; - } - setsid(); - pseudo_path = pseudo_localstatedir_path(PSEUDO_PIDFILE); - if (!pseudo_path) { - pseudo_diag("Couldn't get path for prefix/%s\n", PSEUDO_PIDFILE); - return 1; - } - fp = fopen(pseudo_path, "w"); - if (!fp) { - pseudo_diag("Couldn't open %s: %s\n", - pseudo_path, strerror(errno)); - return 1; - } - fprintf(fp, "%lld\n", (long long) getpid()); - fclose(fp); - free(pseudo_path); if (daemonize) { + if ((rc = fork()) != 0) { + if (rc == -1) { + pseudo_diag("couldn't spawn server: %s\n", strerror(errno)); + return 0; + } + pseudo_debug(2, "started server, pid %d\n", rc); + close(listen_fd); + /* Parent writes pid, that way it's always correct */ + return pseudo_server_write_pid(rc); + } + /* In child */ pseudo_new_pid(); fclose(stdin); fclose(stdout); if (!pseudo_logfile(PSEUDO_LOGFILE)) fclose(stderr); + } else { + /* Write the pid if we don't daemonize */ + pseudo_server_write_pid(getpid()); } + + setsid(); signal(SIGHUP, quit_now); signal(SIGINT, quit_now); signal(SIGALRM, quit_now); diff --git a/pseudo_wrappers.c b/pseudo_wrappers.c index 0321fe2..ee1d3ea 100644 --- a/pseudo_wrappers.c +++ b/pseudo_wrappers.c @@ -144,7 +144,6 @@ pseudo_populate_wrappers(void) { int i; char *debug; static int done = 0; - char *pseudo_path = 0; char *no_symlink_exp; if (done) @@ -206,40 +205,6 @@ pseudo_populate_wrappers(void) { * value for cwd. */ pseudo_client_reset(); - pseudo_path = pseudo_prefix_path(NULL); - if (pseudo_prefix_dir_fd == -1) { - if (pseudo_path) { - pseudo_prefix_dir_fd = open(pseudo_path, O_RDONLY); - pseudo_prefix_dir_fd = pseudo_fd(pseudo_prefix_dir_fd, MOVE_FD); - } else { - pseudo_diag("No prefix available to to find server.\n"); - exit(1); - } - if (pseudo_prefix_dir_fd == -1) { - pseudo_diag("Can't open prefix path (%s) for server: %s\n", - pseudo_path, - strerror(errno)); - exit(1); - } - } - free(pseudo_path); - pseudo_path = pseudo_localstatedir_path(NULL); - if (pseudo_localstate_dir_fd == -1) { - if (pseudo_path) { - pseudo_localstate_dir_fd = open(pseudo_path, O_RDONLY); - pseudo_localstate_dir_fd = pseudo_fd(pseudo_localstate_dir_fd, MOVE_FD); - } else { - pseudo_diag("No prefix available to to find server.\n"); - exit(1); - } - if (pseudo_localstate_dir_fd == -1) { - pseudo_diag("Can't open prefix path (%s) for server: %s\n", - pseudo_path, - strerror(errno)); - exit(1); - } - } - free(pseudo_path); pseudo_debug(2, "(%s) set up wrappers\n", program_invocation_short_name); pseudo_magic(); pseudo_droplock(); @@ -537,32 +502,17 @@ clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...) { * child. Instead, we have to temporarily do any fixup, then possibly * undo it later. UGH! */ - pseudo_debug(1, "client resetting for clone(2) call\n"); - if (real_clone) { - pseudo_setupenv(); - pseudo_client_reset(); - /* call the real syscall */ - rc = (*real_clone)(fn, child_stack, flags, arg, pid, tls, ctid); - - /* if we got here, we're the parent process. And if we changed - * pseudo_disabled because of the environment, now we want to - * bring it back. We can't use the normal path for this in - * pseudo_client_reset() because that would trust the environment - * variable, which was intended only to modify the behavior of - * the child process. - */ - if (save_disabled != pseudo_disabled) { - if (pseudo_disabled) { - pseudo_disabled = 0; - pseudo_magic(); - } else { - pseudo_disabled = 1; - pseudo_antimagic(); - } + +#include "guts/clone.c" + + if (save_disabled != pseudo_disabled) { + if (pseudo_disabled) { + pseudo_disabled = 0; + pseudo_magic(); + } else { + pseudo_disabled = 1; + pseudo_antimagic(); } - } else { - /* rc was initialized to the "failure" value */ - pseudo_enosys("clone"); } save_errno = errno; @@ -583,9 +533,11 @@ clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...) { } static int (*real_fork)(void) = NULL; +#if 0 static int (*real_execlp)(const char *file, const char *arg, ...) = NULL; static int (*real_execl)(const char *file, const char *arg, ...) = NULL; static int (*real_execle)(const char *file, const char *arg, ...) = NULL; +#endif static int (*real_clone)(int (*)(void *), void *, int, void *, ...) = NULL; static int |