Пример #1
0
static void fatal_sig_handler(int signum)
{
    putty_signal(signum, SIG_DFL);
    cleanup_utmp();
    setuid(getuid());
    raise(signum);
}
Пример #2
0
/*
 * Pre-initialisation. This is here to get around the fact that GTK
 * doesn't like being run in setuid/setgid programs (probably
 * sensibly). So before we initialise GTK - and therefore before we
 * even process the command line - we check to see if we're running
 * set[ug]id. If so, we open our pty master _now_, chown it as
 * necessary, and drop privileges. We can always close it again
 * later. If we're potentially going to be doing utmp as well, we
 * also fork off a utmp helper process and communicate with it by
 * means of a pipe; the utmp helper will keep privileges in order
 * to clean up utmp when we exit (i.e. when its end of our pipe
 * closes).
 */
void pty_pre_init(void)
{
    Pty pty;

#ifndef OMIT_UTMP
    pid_t pid;
    int pipefd[2];
#endif

    pty = single_pty = snew(struct pty_tag);
    pty->conf = NULL;
    bufchain_init(&pty->output_data);

    /* set the child signal handler straight away; it needs to be set
     * before we ever fork. */
    putty_signal(SIGCHLD, sigchld_handler);
    pty->master_fd = pty->slave_fd = -1;
#ifndef OMIT_UTMP
    pty_stamped_utmp = FALSE;
#endif

    if (geteuid() != getuid() || getegid() != getgid()) {
	pty_open_master(pty);

#ifndef OMIT_UTMP
        /*
         * Fork off the utmp helper.
         */
        if (pipe(pipefd) < 0) {
            perror("pterm: pipe");
            exit(1);
        }
        cloexec(pipefd[0]);
        cloexec(pipefd[1]);
        pid = fork();
        if (pid < 0) {
            perror("pterm: fork");
            exit(1);
        } else if (pid == 0) {
            char display[128], buffer[128];
            int dlen, ret;

            close(pipefd[1]);
            /*
             * Now sit here until we receive a display name from the
             * other end of the pipe, and then stamp utmp. Unstamp utmp
             * again, and exit, when the pipe closes.
             */

            dlen = 0;
            while (1) {
	    
                ret = read(pipefd[0], buffer, lenof(buffer));
                if (ret <= 0) {
                    cleanup_utmp();
                    _exit(0);
                } else if (!pty_stamped_utmp) {
                    if (dlen < lenof(display))
                        memcpy(display+dlen, buffer,
                               min(ret, lenof(display)-dlen));
                    if (buffer[ret-1] == '\0') {
                        /*
                         * Now we have a display name. NUL-terminate
                         * it, and stamp utmp.
                         */
                        display[lenof(display)-1] = '\0';
                        /*
                         * Trap as many fatal signals as we can in the
                         * hope of having the best possible chance to
                         * clean up utmp before termination. We are
                         * unfortunately unprotected against SIGKILL,
                         * but that's life.
                         */
                        putty_signal(SIGHUP, fatal_sig_handler);
                        putty_signal(SIGINT, fatal_sig_handler);
                        putty_signal(SIGQUIT, fatal_sig_handler);
                        putty_signal(SIGILL, fatal_sig_handler);
                        putty_signal(SIGABRT, fatal_sig_handler);
                        putty_signal(SIGFPE, fatal_sig_handler);
                        putty_signal(SIGPIPE, fatal_sig_handler);
                        putty_signal(SIGALRM, fatal_sig_handler);
                        putty_signal(SIGTERM, fatal_sig_handler);
                        putty_signal(SIGSEGV, fatal_sig_handler);
                        putty_signal(SIGUSR1, fatal_sig_handler);
                        putty_signal(SIGUSR2, fatal_sig_handler);
#ifdef SIGBUS
                        putty_signal(SIGBUS, fatal_sig_handler);
#endif
#ifdef SIGPOLL
                        putty_signal(SIGPOLL, fatal_sig_handler);
#endif
#ifdef SIGPROF
                        putty_signal(SIGPROF, fatal_sig_handler);
#endif
#ifdef SIGSYS
                        putty_signal(SIGSYS, fatal_sig_handler);
#endif
#ifdef SIGTRAP
                        putty_signal(SIGTRAP, fatal_sig_handler);
#endif
#ifdef SIGVTALRM
                        putty_signal(SIGVTALRM, fatal_sig_handler);
#endif
#ifdef SIGXCPU
                        putty_signal(SIGXCPU, fatal_sig_handler);
#endif
#ifdef SIGXFSZ
                        putty_signal(SIGXFSZ, fatal_sig_handler);
#endif
#ifdef SIGIO
                        putty_signal(SIGIO, fatal_sig_handler);
#endif
                        setup_utmp(pty->name, display);
                    }
                }
            }
        } else {
            close(pipefd[0]);
            pty_utmp_helper_pid = pid;
            pty_utmp_helper_pipe = pipefd[1];
        }
#endif
    }

    /* Drop privs. */
    {
#ifndef HAVE_NO_SETRESUID
	int gid = getgid(), uid = getuid();
	int setresgid(gid_t, gid_t, gid_t);
	int setresuid(uid_t, uid_t, uid_t);
	if (setresgid(gid, gid, gid) < 0) {
            perror("setresgid");
            exit(1);
        }
	if (setresuid(uid, uid, uid) < 0) {
            perror("setresuid");
            exit(1);
        }
#else
	if (setgid(getgid()) < 0) {
            perror("setgid");
            exit(1);
        }
	if (setuid(getuid()) < 0) {
            perror("setuid");
            exit(1);
        }
#endif
    }
}