示例#1
0
/* do the preparatory tasks, needed before entering the main event loop */
void init(int xid)
{
	char qrexec_error_log_name[256];
	int logfd;
	int i;

	if (xid <= 0) {
		fprintf(stderr, "domain id=0?\n");
		exit(1);
	}
	signal(SIGUSR1, sigusr1_handler);
	switch (fork()) {
	case -1:
		perror("fork");
		exit(1);
	case 0:
		break;
	default:
		fprintf(stderr, "Waiting for VM's qrexec agent.");
		for (i=0;i<MAX_STARTUP_TIME;i++) {
			sleep(1);
			fprintf(stderr, ".");
		}
		fprintf(stderr, "Cannot connect to qrexec agent for %d seconds, giving up\n", MAX_STARTUP_TIME);
		exit(1);
	}
	close(0);
	snprintf(qrexec_error_log_name, sizeof(qrexec_error_log_name),
		 "/var/log/qubes/qrexec.%d.log", xid);
	umask(0007);		// make the log readable by the "qubes" group
	logfd =
	    open(qrexec_error_log_name, O_WRONLY | O_CREAT | O_TRUNC,
		 0640);

	if (logfd < 0) {
		perror("open");
		exit(1);
	}

	dup2(logfd, 1);
	dup2(logfd, 2);

	chdir("/var/run/qubes");
	if (setsid() < 0) {
		perror("setsid()");
		exit(1);
	}

	remote_domain_name = peer_client_init(xid, REXEC_PORT);
	setuid(getuid());
	/* When running as root, make the socket accessible; perms on /var/run/qubes still apply */
	umask(0);
	qrexec_daemon_unix_socket_fd =
	    create_qrexec_socket(xid, remote_domain_name);
	umask(0077);
	signal(SIGPIPE, SIG_IGN);
	signal(SIGCHLD, sigchld_handler);
	signal(SIGUSR1, SIG_DFL);
	kill(getppid(), SIGUSR1);	// let the parent know we are ready
}
/* do the preparatory tasks, needed before entering the main event loop */
void init(int xid)
{
    char qrexec_error_log_name[256];
    int logfd;
    int i;
    pid_t pid;
    int startup_timeout = MAX_STARTUP_TIME_DEFAULT;
    const char *startup_timeout_str = NULL;

    if (xid <= 0) {
        fprintf(stderr, "domain id=0?\n");
        exit(1);
    }
    startup_timeout_str = getenv("QREXEC_STARTUP_TIMEOUT");
    if (startup_timeout_str) {
        startup_timeout = atoi(startup_timeout_str);
        if (startup_timeout <= 0)
            // invalid or negative number
            startup_timeout = MAX_STARTUP_TIME_DEFAULT;
    }
    signal(SIGUSR1, sigusr1_handler);
    signal(SIGCHLD, sigchld_parent_handler);
    switch (pid=fork()) {
    case -1:
        perror("fork");
        exit(1);
    case 0:
        break;
    default:
        if (getenv("QREXEC_STARTUP_NOWAIT"))
            exit(0);
        if (!opt_quiet)
            fprintf(stderr, "Waiting for VM's qrexec agent.");
        for (i=0;i<startup_timeout;i++) {
            sleep(1);
            if (!opt_quiet)
                fprintf(stderr, ".");
            if (i==startup_timeout-1) {
                break;
            }
        }
        fprintf(stderr, "Cannot connect to '%s' qrexec agent for %d seconds, giving up\n", remote_domain_name, startup_timeout);
        exit(3);
    }
    close(0);
    snprintf(qrexec_error_log_name, sizeof(qrexec_error_log_name),
         "/var/log/qubes/qrexec.%s.log", remote_domain_name);
    umask(0007);        // make the log readable by the "qubes" group
    logfd =
        open(qrexec_error_log_name, O_WRONLY | O_CREAT | O_TRUNC,
         0660);

    if (logfd < 0) {
        perror("open");
        exit(1);
    }

    dup2(logfd, 1);
    dup2(logfd, 2);

    chdir("/var/run/qubes");
    if (setsid() < 0) {
        perror("setsid()");
        exit(1);
    }

    vchan = libvchan_client_init(xid, VCHAN_BASE_PORT);
    if (!vchan) {
        perror("cannot connect to qrexec agent");
        exit(1);
    }
    if (handle_agent_hello(vchan, remote_domain_name) < 0) {
        exit(1);
    }

    if (setgid(getgid()) < 0) {
        perror("setgid()");
        exit(1);
    }
    if (setuid(getuid()) < 0) {
        perror("setuid()");
        exit(1);
    }

    /* initialize clients state arrays */
    for (i = 0; i < MAX_CLIENTS; i++) {
        clients[i].state = CLIENT_INVALID;
        policy_pending[i].pid = 0;
        used_vchan_ports[i] = VCHAN_PORT_UNUSED;
        vchan_port_notify_client[i] = VCHAN_PORT_UNUSED;
    }

    /* When running as root, make the socket accessible; perms on /var/run/qubes still apply */
    umask(0);
    qrexec_daemon_unix_socket_fd =
        create_qrexec_socket(xid, remote_domain_name);
    umask(0077);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGCHLD, sigchld_handler);
    signal(SIGUSR1, SIG_DFL);
    kill(getppid(), SIGUSR1);   // let the parent know we are ready
}