Esempio n. 1
0
static int
client_ping(void) {
	pseudo_msg_t ping;
	pseudo_msg_t *ack;
	char tagbuf[pseudo_path_max()];
	char *tag = pseudo_get_value("PSEUDO_TAG");

	memset(&ping, 0, sizeof(ping));

	ping.type = PSEUDO_MSG_PING;
	ping.op = OP_NONE;

	ping.pathlen = snprintf(tagbuf, sizeof(tagbuf), "%s%c%s",
		program_invocation_name ? program_invocation_name : "<unknown>",
		0,
		tag ? tag : "");
	free(tag);
	ping.client = getpid();
	ping.result = 0;
	errno = 0;
	pseudo_debug(4, "sending ping\n");
	if (pseudo_msg_send(connect_fd, &ping, ping.pathlen, tagbuf)) {
		pseudo_debug(3, "error pinging server: %s\n", strerror(errno));
		return 1;
	}
	ack = pseudo_msg_receive(connect_fd);
	if (!ack) {
		pseudo_debug(2, "no ping response from server: %s\n", strerror(errno));
		/* and that's not good, so... */
		server_pid = 0;
		return 1;
	}
	if (ack->type != PSEUDO_MSG_ACK) {
		pseudo_debug(1, "invalid ping response from server: expected ack, got %d\n", ack->type);
		/* and that's not good, so... */
		server_pid = 0;
		return 1;
	}
	pseudo_debug(5, "ping ok\n");
	return 0;
}
int wrap_clone_child(void *args) {
	struct clone_args *clargs = args;

	int (*fn)(void *) = clargs->fn;
	int flags = clargs->flags;
	void *arg = clargs->arg;

	/* We always free in the client */
	free(clargs);

	if (!(flags & CLONE_VM)) {
		pseudo_setupenv();
		if (!pseudo_get_value("PSEUDO_UNLOAD")) {
			pseudo_reinit_libpseudo();
		} else {
			pseudo_dropenv();
		}
	}

	return fn(arg);
}
Esempio n. 3
0
/* spawn server */
static int
client_spawn_server(void) {
	int status;
	FILE *fp;
	char * pseudo_pidfile;

	if ((server_pid = fork()) != 0) {
		if (server_pid == -1) {
			pseudo_diag("couldn't fork server: %s\n", strerror(errno));
			return 1;
		}
		pseudo_debug(4, "spawned server, pid %d\n", server_pid);
		/* wait for the child process to terminate, indicating server
		 * is ready
		 */
		waitpid(server_pid, &status, 0);
		server_pid = -2;
		pseudo_pidfile = pseudo_localstatedir_path(PSEUDO_PIDFILE);
		fp = fopen(pseudo_pidfile, "r");
		if (fp) {
			if (fscanf(fp, "%d", &server_pid) != 1) {
				pseudo_debug(1, "Opened server PID file, but didn't get a pid.\n");
			}
			fclose(fp);
		} else {
			pseudo_debug(1, "no pid file (%s): %s\n",
				pseudo_pidfile, strerror(errno));
		}
		pseudo_debug(2, "read new pid file: %d\n", server_pid);
		free(pseudo_pidfile);
		/* at this point, we should have a new server_pid */
		return 0;
	} else {
		char *base_args[] = { NULL, NULL, NULL };
		char **argv;
		char *option_string = pseudo_get_value("PSEUDO_OPTS");
		int args;
		int fd;

		pseudo_new_pid();
		base_args[0] = pseudo_bindir_path("pseudo");
		base_args[1] = "-d";
		if (option_string) {
			char *s;
			int arg;

			/* count arguments in PSEUDO_OPTS, starting at 2
			 * for pseudo/-d/NULL, plus one for the option string.
			 * The number of additional arguments may be less
			 * than the number of spaces, but can't be more.
			 */
			args = 4;
			for (s = option_string; *s; ++s)
				if (*s == ' ')
					++args;

			argv = malloc(args * sizeof(char *));
			argv[0] = base_args[0];
			argv[1] = base_args[1];
			arg = 2;
			while ((s = strsep(&option_string, " ")) != NULL) {
				if (*s) {
					argv[arg++] = strdup(s);
				}
			}
			argv[arg] = 0;
		} else {
			argv = base_args;
		}

		/* close any higher-numbered fds which might be open,
		 * such as sockets.  We don't have to worry about 0 and 1;
		 * the server closes them already, and more importantly,
		 * they can't have been opened or closed without us already
		 * having spawned a server... The issue is just socket()
		 * calls which could result in fds being left open, and those
		 * can't overwrite fds 0-2 unless we closed them...
		 * 
		 * No, really.  It works.
		 */
		for (fd = 3; fd < 1024; ++fd) {
			if (fd != pseudo_util_debug_fd)
				close(fd);
		}
		/* and now, execute the server */

		pseudo_set_value("PSEUDO_RELOADED", "YES");
		pseudo_setupenv();
		pseudo_dropenv(); /* drop PRELINK_LIBRARIES */

		pseudo_debug(4, "calling execv on %s\n", argv[0]);

		execv(argv[0], argv);
		pseudo_diag("critical failure: exec of pseudo daemon failed: %s\n", strerror(errno));
		exit(1);
	}
}
Esempio n. 4
0
void
pseudo_init_client(void) {
	char *env;

	pseudo_antimagic();
	pseudo_new_pid();
	if (connect_fd != -1) {
		close(connect_fd);
		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 (and cause it to reinit the defaults).
	 */
	env = getenv("PSEUDO_DISABLED");
	if (!env) {
		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;
		case 's':
		case 'S':
			actually_disabled = 0;
			pseudo_local_only = 1;
			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_inited = 0; /* Re-read the initial values! */
			}
			pseudo_set_value("PSEUDO_DISABLED", "0");
		}
	} else {
		pseudo_set_value("PSEUDO_DISABLED", "0");
	}

	/* Setup global items needed for pseudo to function... */
	if (!pseudo_inited) {
		/* 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_nosymlinkexp = 0;
	}

	if (!pseudo_disabled && !pseudo_inited) {
		char *pseudo_path = 0;

		pseudo_path = pseudo_prefix_path(NULL);
		if (pseudo_prefix_dir_fd == -1) {
			if (pseudo_path) {
				pseudo_prefix_dir_fd = open(pseudo_path, O_RDONLY);
				/* directory is missing? */
				if (pseudo_prefix_dir_fd == -1 && errno == ENOENT) {
					pseudo_debug(1, "prefix directory doesn't exist, trying to create\n");
					mkdir_p(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);
				/* directory is missing? */
				if (pseudo_localstate_dir_fd == -1 && errno == ENOENT) {
					pseudo_debug(1, "local state directory doesn't exist, trying to create\n");
					mkdir_p(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 local state path (%s) for server: %s\n",
					pseudo_path,
					strerror(errno));
				exit(1);
			}
		}
		free(pseudo_path);

		env = pseudo_get_value("PSEUDO_NOSYMLINKEXP");
		if (env) {
			char *endptr;
			/* if the environment variable is not an empty string,
			 * parse it; "0" means turn NOSYMLINKEXP off, "1" means
			 * turn it on (disabling the feature).  An empty string
			 * or something we can't parse means to set the flag; this
			 * is a safe default because if you didn't want the flag
			 * set, you normally wouldn't set the environment variable
			 * at all.
			 */
			if (*env) {
				pseudo_nosymlinkexp = strtol(env, &endptr, 10);
				if (*endptr)
					pseudo_nosymlinkexp = 1;
			} else {
				pseudo_nosymlinkexp = 1;
			}
		} else {
			pseudo_nosymlinkexp = 0;
		}
		free(env);
		env = pseudo_get_value("PSEUDO_UIDS");
		if (env)
			sscanf(env, "%d,%d,%d,%d",
				&pseudo_ruid, &pseudo_euid,
				&pseudo_suid, &pseudo_fuid);
		free(env);

		env = pseudo_get_value("PSEUDO_GIDS");
		if (env)
			sscanf(env, "%d,%d,%d,%d",
				&pseudo_rgid, &pseudo_egid,
				&pseudo_sgid, &pseudo_fuid);
		free(env);

		env = pseudo_get_value("PSEUDO_CHROOT");
		if (env) {
			pseudo_chroot = strdup(env);
			if (pseudo_chroot) {
				pseudo_chroot_len = strlen(pseudo_chroot);
			} else {
				pseudo_diag("can't store chroot path (%s)\n", env);
			}
		}
		free(env);

		env = pseudo_get_value("PSEUDO_PASSWD");
		if (env) {
			pseudo_passwd = strdup(env);
		}
		free(env);

		pseudo_inited = 1;
	}
	if (!pseudo_disabled)
		pseudo_client_getcwd();

	pseudo_magic();
}