示例#1
0
void
main(int, char **)
{
	int ctl;

	wdog = open("#w/wdctl", ORDWR);
	if (wdog < 0)
		sysfatal("open #w/wdctl: %r");

	switch(rfork(RFPROC|RFNOWAIT|RFFDG)){
	case 0:
		break;
	default:
		exits(0);
	}

	ctl = procctl(getpid());
	fprint(ctl, "pri 18");
	close(ctl);

	if (fprint(wdog, "enable") < 0)
		sysfatal("write #w/wdctl enable: %r");
	for(;;){
		sleep(300);		/* allows 4.2GHz CPU, with some slop */
		seek(wdog, 0, 0);
		if (fprint(wdog, "restart") < 0)
			sysfatal("write #w/wdctl restart: %r");
	}
}
示例#2
0
int subreap_relinquish ()
{
#if defined(__FreeBSD__) || defined(__DragonFly__)
    return procctl (P_PID, getpid (), PROC_REAP_RELEASE, NULL);
#elif defined(__linux__)
    return prctl (PR_SET_CHILD_SUBREAPER, 0);
#endif
}
示例#3
0
int subreap_acquire ()
{
#if defined(__FreeBSD__) || defined(__DragonFly__)
    return procctl (P_PID, getpid (), PROC_REAP_ACQUIRE, NULL);
#elif defined(__linux__)
    return prctl (PR_SET_CHILD_SUBREAPER, 1);
#endif
}
示例#4
0
文件: protect.c 项目: 2asoft/freebsd
int
main(int argc, char *argv[])
{
	idtype_t idtype;
	id_t id;
	int ch, flags;
	bool descend, inherit, idset;

	idtype = P_PID;
	id = getpid();
	flags = PPROT_SET;
	descend = inherit = idset = false;
	while ((ch = getopt(argc, argv, "cdig:p:")) != -1)
		switch (ch) {
		case 'c':
			flags = PPROT_CLEAR;
			break;
		case 'd':
			descend = true;
			break;
		case 'i':
			inherit = true;
			break;
		case 'g':
			idtype = P_PGID;
			id = parse_id(optarg);
			idset = true;
			break;
		case 'p':
			idtype = P_PID;
			id = parse_id(optarg);
			idset = true;
			break;
		}
	argc -= optind;
	argv += optind;

	if ((idset && argc != 0) || (!idset && (argc == 0 || descend)))
		usage();

	if (descend)
		flags |= PPROT_DESCEND;
	if (inherit)
		flags |= PPROT_INHERIT;
	if (procctl(idtype, id, PROC_SPROTECT, &flags) == -1)
		err(1, "procctl");

	if (argc != 0) {
		errno = 0;
		execvp(*argv, argv);
		err(errno == ENOENT ? 127 : 126, "%s", *argv);
	}
	return (0);
}
示例#5
0
int subreap_status ()
{
#if defined(__FreeBSD__) || defined(__DragonFly__)
    struct procctl_reaper_status pctl;
    procctl (P_PID, getpid (), PROC_REAP_STATUS, &pctl);
    return (pctl.rs_flags & REAPER_STATUS_OWNED);
#elif defined(__linux__)
    int status;
    prctl (PR_GET_CHILD_SUBREAPER, &status);
    return status;
#endif
}
示例#6
0
文件: tcore.c 项目: Harvey-OS/harvey
/*
 * Cleanup done by runacore to pretend we are going back to user space.
 * We won't return and won't do what syscall() would normally do.
 * Do it here instead.
 */
static void
fakeretfromsyscall(Ureg *ureg)
{
	Proc *up = externup();
	int s;

	poperror();	/* as syscall() would do if we would return */
	if(up->procctl == Proc_tracesyscall){	/* Would this work? */
		up->procctl = Proc_stopme;
		s = splhi();
		procctl(up);
		splx(s);
	}

	up->insyscall = 0;
	/* if we delayed sched because we held a lock, sched now */
	if(up->delaysched){
		sched();
		splhi();
	}
	kexit(ureg);
}
示例#7
0
文件: timeout.c 项目: fengsi/freebsd
int
main(int argc, char **argv)
{
    int ch;
    unsigned long i;
    int foreground, preserve;
    int error, pstat, status;
    int killsig = SIGTERM;
    pid_t pid, cpid;
    double first_kill;
    double second_kill;
    bool timedout = false;
    bool do_second_kill = false;
    bool child_done = false;
    struct sigaction signals;
    struct procctl_reaper_status info;
    struct procctl_reaper_kill killemall;
    int signums[] = {
        -1,
        SIGTERM,
        SIGINT,
        SIGHUP,
        SIGCHLD,
        SIGALRM,
        SIGQUIT,
    };

    foreground = preserve = 0;
    second_kill = 0;

    const struct option longopts[] = {
        { "preserve-status", no_argument,       &preserve,    1 },
        { "foreground",      no_argument,       &foreground,  1 },
        { "kill-after",      required_argument, NULL,        'k'},
        { "signal",          required_argument, NULL,        's'},
        { "help",            no_argument,       NULL,        'h'},
        { NULL,              0,                 NULL,         0 }
    };

    while ((ch = getopt_long(argc, argv, "+k:s:h", longopts, NULL)) != -1) {
        switch (ch) {
        case 'k':
            do_second_kill = true;
            second_kill = parse_duration(optarg);
            break;
        case 's':
            killsig = parse_signal(optarg);
            break;
        case 0:
            break;
        case 'h':
        default:
            usage();
            break;
        }
    }

    argc -= optind;
    argv += optind;

    if (argc < 2)
        usage();

    first_kill = parse_duration(argv[0]);
    argc--;
    argv++;

    if (!foreground) {
        /* Aquire a reaper */
        if (procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == -1)
            err(EX_OSERR, "Fail to acquire the reaper");
    }

    memset(&signals, 0, sizeof(signals));
    sigemptyset(&signals.sa_mask);

    if (killsig != SIGKILL && killsig != SIGSTOP)
        signums[0] = killsig;

    for (i = 0; i < sizeof(signums) / sizeof(signums[0]); i ++)
        sigaddset(&signals.sa_mask, signums[i]);

    signals.sa_handler = sig_handler;
    signals.sa_flags = SA_RESTART;

    for (i = 0; i < sizeof(signums) / sizeof(signums[0]); i ++)
        if (signums[i] != -1 && signums[i] != 0 &&
                sigaction(signums[i], &signals, NULL) == -1)
            err(EX_OSERR, "sigaction()");

    signal(SIGTTIN, SIG_IGN);
    signal(SIGTTOU, SIG_IGN);

    pid = fork();
    if (pid == -1)
        err(EX_OSERR, "fork()");
    else if (pid == 0) {
        /* child process */
        signal(SIGTTIN, SIG_DFL);
        signal(SIGTTOU, SIG_DFL);

        error = execvp(argv[0], argv);
        if (error == -1) {
            if (errno == ENOENT)
                err(127, "exec(%s)", argv[0]);
            else
                err(126, "exec(%s)", argv[0]);
        }
    }

    if (sigprocmask(SIG_BLOCK, &signals.sa_mask, NULL) == -1)
        err(EX_OSERR, "sigprocmask()");

    /* parent continues here */
    set_interval(first_kill);

    for (;;) {
        sigemptyset(&signals.sa_mask);
        sigsuspend(&signals.sa_mask);

        if (sig_chld) {
            sig_chld = 0;

            while ((cpid = waitpid(-1, &status, WNOHANG)) != 0) {
                if (cpid < 0) {
                    if (errno == EINTR)
                        continue;
                    else
                        break;
                } else if (cpid == pid) {
                    pstat = status;
                    child_done = true;
                }
            }
            if (child_done) {
                if (foreground) {
                    break;
                } else {
                    procctl(P_PID, getpid(),
                            PROC_REAP_STATUS, &info);
                    if (info.rs_children == 0)
                        break;
                }
            }
        } else if (sig_alrm) {
            sig_alrm = 0;

            timedout = true;
            if (!foreground) {
                killemall.rk_sig = killsig;
                killemall.rk_flags = 0;
                procctl(P_PID, getpid(), PROC_REAP_KILL,
                        &killemall);
            } else
                kill(pid, killsig);

            if (do_second_kill) {
                set_interval(second_kill);
                second_kill = 0;
                sig_ign = killsig;
                killsig = SIGKILL;
            } else
                break;

        } else if (sig_term) {
            if (!foreground) {
                killemall.rk_sig = sig_term;
                killemall.rk_flags = 0;
                procctl(P_PID, getpid(), PROC_REAP_KILL,
                        &killemall);
            } else
                kill(pid, sig_term);

            if (do_second_kill) {
                set_interval(second_kill);
                second_kill = 0;
                sig_ign = killsig;
                killsig = SIGKILL;
            } else
                break;
        }
    }

    while (!child_done && wait(&pstat) == -1) {
        if (errno != EINTR)
            err(EX_OSERR, "waitpid()");
    }

    if (!foreground)
        procctl(P_PID, getpid(), PROC_REAP_RELEASE, NULL);

    if (WEXITSTATUS(pstat))
        pstat = WEXITSTATUS(pstat);
    else if(WIFSIGNALED(pstat))
        pstat = 128 + WTERMSIG(pstat);

    if (timedout && !preserve)
        pstat = EXIT_TIMEOUT;

    return (pstat);
}
示例#8
0
文件: exec_general.c 项目: Jimx-/lyos
PUBLIC int libexec_clearproc(struct exec_info * execi)
{
    return procctl(execi->proc_e, PCTL_CLEARPROC);
}
示例#9
0
文件: syscall.c 项目: 99years/plan9
/* it should be unsigned. FIXME */
void
syscall(int badscallnr, Ureg* ureg)
{
	unsigned int scallnr = (unsigned int) badscallnr;
	char *e;
	uintptr	sp;
	int s;
	vlong startns, stopns;
	Ar0 ar0;
	static Ar0 zar0;

	if(!userureg(ureg))
		panic("syscall: cs %#llux\n", ureg->cs);

	cycles(&up->kentry);

	m->syscall++;
	up->nsyscall++;
	up->nqsyscall++;
	up->insyscall = 1;
	up->pc = ureg->ip;
	up->dbgreg = ureg;
	sp = ureg->sp;
	startns = 0;

	if(up->procctl == Proc_tracesyscall){
		/*
		 * Redundant validaddr.  Do we care?
		 * Tracing syscalls is not exactly a fast path...
		 * Beware, validaddr currently does a pexit rather
		 * than an error if there's a problem; that might
		 * change in the future.
		 */
		if(sp < (USTKTOP-BIGPGSZ) || sp > (USTKTOP-sizeof(up->arg)-BY2SE))
			validaddr(UINT2PTR(sp), sizeof(up->arg)+BY2SE, 0);

		syscallfmt(scallnr, (va_list)(sp+BY2SE));	
		up->procctl = Proc_stopme;
		procctl(up);
		if(up->syscalltrace)
			free(up->syscalltrace);
		up->syscalltrace = nil;
		startns = todget(nil);		
	}

	up->scallnr = scallnr;
	if(scallnr == RFORK)
		fpusysrfork(ureg);
	spllo();

	sp = ureg->sp;
	up->nerrlab = 0;
	ar0 = zar0;
	if(!waserror()){
		if(scallnr >= nsyscall || systab[scallnr].f == nil){
			pprint("bad sys call number %d pc %#llux\n",
				scallnr, ureg->ip);
			postnote(up, 1, "sys: bad sys call", NDebug);
			error(Ebadarg);
		}

		if(sp < (USTKTOP-BIGPGSZ) || sp > (USTKTOP-sizeof(up->arg)-BY2SE))
			validaddr(UINT2PTR(sp), sizeof(up->arg)+BY2SE, 0);

		memmove(up->arg, UINT2PTR(sp+BY2SE), sizeof(up->arg));
		up->psstate = systab[scallnr].n;

		systab[scallnr].f(&ar0, (va_list)up->arg);
		if(scallnr == SYSR1){
			/*
			 * BUG: must go when ron binaries go.
			 * NIX: Returning from execac().
			 * This means that the process is back to the
			 * time sharing core. However, the process did
			 * already return from the system call, when dispatching
			 * the user code to the AC. The only thing left is to
			 * return. The user registers should be ok, because
			 * up->dbgreg has been the user context for the process.
			 */
			return;
		}
		poperror();
	}
	else{
		/* failure: save the error buffer for errstr */
		e = up->syserrstr;
		up->syserrstr = up->errstr;
		up->errstr = e;
		if(DBGFLG && up->pid == 1)
			iprint("%s: syscall %s error %s\n",
				up->text, systab[scallnr].n, up->syserrstr);
		ar0 = systab[scallnr].r;
	}

	/*
	 * NIX: for the execac() syscall, what follows is done within
	 * the system call, because it never returns.
	 * See acore.c:/^retfromsyscall
	 */

	noerrorsleft();

	/*
	 * Put return value in frame.
	 */
	ureg->ax = ar0.p;

	if(up->procctl == Proc_tracesyscall){
		stopns = todget(nil);
		up->procctl = Proc_stopme;
		sysretfmt(scallnr, (va_list)(sp+BY2SE), &ar0, startns, stopns);
		s = splhi();
		procctl(up);
		splx(s);
		if(up->syscalltrace)
			free(up->syscalltrace);
		up->syscalltrace = nil;		
	}else if(up->procctl == Proc_totc || up->procctl == Proc_toac)
		procctl(up);


	up->insyscall = 0;
	up->psstate = 0;

	if(scallnr == NOTED)
		noted(ureg, *(uintptr*)(sp+BY2SE));

	splhi();
	if(scallnr != RFORK && (up->procctl || up->nnote))
		notify(ureg);

	/* if we delayed sched because we held a lock, sched now */
	if(up->delaysched){
		sched();
		splhi();
	}
	kexit(ureg);
}
示例#10
0
文件: syscall.c 项目: 99years/plan9
/*
 *  Call user, if necessary, with note.
 *  Pass user the Ureg struct and the note on his stack.
 */
int
notify(Ureg* ureg)
{
	int l;
	Mpl pl;
	Note note;
	uintptr sp;
	NFrame *nf;

	/*
	 * Calls procctl splhi, see comment in procctl for the reasoning.
	 */
	if(up->procctl)
		procctl(up);
	if(up->nnote == 0)
		return 0;

	fpunotify(ureg);

	pl = spllo();
	qlock(&up->debug);

	up->notepending = 0;
	memmove(&note, &up->note[0], sizeof(Note));
	if(strncmp(note.msg, "sys:", 4) == 0){
		l = strlen(note.msg);
		if(l > ERRMAX-sizeof(" pc=0x0123456789abcdef"))
			l = ERRMAX-sizeof(" pc=0x0123456789abcdef");
		sprint(note.msg+l, " pc=%#p", ureg->ip);
	}

	if(note.flag != NUser && (up->notified || up->notify == nil)){
		qunlock(&up->debug);
		if(note.flag == NDebug)
			pprint("suicide: %s\n", note.msg);
		pexit(note.msg, note.flag != NDebug);
	}

	if(up->notified){
		qunlock(&up->debug);
		splhi();
		return 0;
	}

	if(up->notify == nil){
		qunlock(&up->debug);
		pexit(note.msg, note.flag != NDebug);
	}
	if(!okaddr(PTR2UINT(up->notify), sizeof(ureg->ip), 0)){
		qunlock(&up->debug);
		pprint("suicide: bad function address %#p in notify\n",
			up->notify);
		pexit("Suicide", 0);
	}

	sp = ureg->sp - sizeof(NFrame);
	if(!okaddr(sp, sizeof(NFrame), 1)){
		qunlock(&up->debug);
		pprint("suicide: bad stack address %#p in notify\n", sp);
		pexit("Suicide", 0);
	}

	nf = UINT2PTR(sp);
	memmove(&nf->ureg, ureg, sizeof(Ureg));
	nf->old = up->ureg;
	up->ureg = nf;	/* actually the NFrame, for noted */
	memmove(nf->msg, note.msg, ERRMAX);
	nf->arg1 = nf->msg;
	nf->arg0 = &nf->ureg;
	ureg->bp = PTR2UINT(nf->arg0);
	nf->ip = 0;

	ureg->sp = sp;
	ureg->ip = PTR2UINT(up->notify);
	up->notified = 1;
	up->nnote--;
	memmove(&up->lastnote, &note, sizeof(Note));
	memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));

	qunlock(&up->debug);
	splx(pl);

	return 1;
}
示例#11
0
/*
 *  Call user, if necessary, with note.
 *  Pass user the Ureg struct and the note on his stack.
 */
int
notify(Ureg* ureg)
{
	int l;
	ulong s, sp;
	Note *n;

	if(up->procctl)
		procctl(up);
	if(up->nnote == 0)
		return 0;

	if(up->fpstate == FPactive){
		fpsave(&up->fpsave);
		up->fpstate = FPinactive;
	}
	up->fpstate |= FPillegal;

	s = spllo();
	qlock(&up->debug);
	up->notepending = 0;
	n = &up->note[0];
	if(strncmp(n->msg, "sys:", 4) == 0){
		l = strlen(n->msg);
		if(l > ERRMAX-15)	/* " pc=0x12345678\0" */
			l = ERRMAX-15;
		sprint(n->msg+l, " pc=0x%.8lux", ureg->pc);
	}

	if(n->flag!=NUser && (up->notified || up->notify==0)){
		if(n->flag == NDebug)
			pprint("suicide: %s\n", n->msg);
		qunlock(&up->debug);
		pexit(n->msg, n->flag!=NDebug);
	}

	if(up->notified){
		qunlock(&up->debug);
		splhi();
		return 0;
	}

	if(!up->notify){
		qunlock(&up->debug);
		pexit(n->msg, n->flag!=NDebug);
	}
	sp = ureg->usp;
	sp -= 256;	/* debugging: preserve context causing problem */
	sp -= sizeof(Ureg);
if(0) print("%s %lud: notify %.8lux %.8lux %.8lux %s\n", 
	up->text, up->pid, ureg->pc, ureg->usp, sp, n->msg);

	if(!okaddr((ulong)up->notify, 1, 0)
	|| !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)){
		pprint("suicide: bad address in notify\n");
		qunlock(&up->debug);
		pexit("Suicide", 0);
	}

	memmove((Ureg*)sp, ureg, sizeof(Ureg));
	*(Ureg**)(sp-BY2WD) = up->ureg;	/* word under Ureg is old up->ureg */
	up->ureg = (void*)sp;
	sp -= BY2WD+ERRMAX;
	memmove((char*)sp, up->note[0].msg, ERRMAX);
	sp -= 3*BY2WD;
	*(ulong*)(sp+2*BY2WD) = sp+3*BY2WD;		/* arg 2 is string */
	*(ulong*)(sp+1*BY2WD) = (ulong)up->ureg;	/* arg 1 is ureg* */
	*(ulong*)(sp+0*BY2WD) = 0;			/* arg 0 is pc */
	ureg->usp = sp;
	ureg->pc = (ulong)up->notify;
	up->notified = 1;
	up->nnote--;
	memmove(&up->lastnote, &up->note[0], sizeof(Note));
	memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));

	qunlock(&up->debug);
	splx(s);
	return 1;
}
示例#12
0
/*
 *  Syscall is called directly from assembler without going through trap().
 */
void
syscall(Ureg* ureg)
{
	char *e;
	ulong	sp;
	long	ret;
	int	i, s;
	ulong scallnr;

	if((ureg->cs & 0xFFFF) != UESEL)
		panic("syscall: cs 0x%4.4luX", ureg->cs);

	cycles(&up->kentry);

	m->syscall++;
	up->insyscall = 1;
	up->pc = ureg->pc;
	up->dbgreg = ureg;

	if(up->procctl == Proc_tracesyscall){
		up->procctl = Proc_stopme;
		procctl(up);
	}

	scallnr = ureg->ax;
	up->scallnr = scallnr;
	if(scallnr == RFORK && up->fpstate == FPactive){
		fpsave(&up->fpsave);
		up->fpstate = FPinactive;
	}
	spllo();

	sp = ureg->usp;
	up->nerrlab = 0;
	ret = -1;
	if(!waserror()){
		if(scallnr >= nsyscall || systab[scallnr] == 0){
			pprint("bad sys call number %lud pc %lux\n",
				scallnr, ureg->pc);
			postnote(up, 1, "sys: bad sys call", NDebug);
			error(Ebadarg);
		}

		if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
			validaddr(sp, sizeof(Sargs)+BY2WD, 0);

		up->s = *((Sargs*)(sp+BY2WD));
		up->psstate = sysctab[scallnr];

		ret = systab[scallnr](up->s.args);
		poperror();
	}else{
		/* failure: save the error buffer for errstr */
		e = up->syserrstr;
		up->syserrstr = up->errstr;
		up->errstr = e;
		if(0 && up->pid == 1)
			print("syscall %lud error %s\n", scallnr, up->syserrstr);
	}
	if(up->nerrlab){
		print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
		for(i = 0; i < NERR; i++)
			print("sp=%lux pc=%lux\n",
				up->errlab[i].sp, up->errlab[i].pc);
		panic("error stack");
	}

	/*
	 *  Put return value in frame.  On the x86 the syscall is
	 *  just another trap and the return value from syscall is
	 *  ignored.  On other machines the return value is put into
	 *  the results register by caller of syscall.
	 */
	ureg->ax = ret;

	if(up->procctl == Proc_tracesyscall){
		up->procctl = Proc_stopme;
		s = splhi();
		procctl(up);
		splx(s);
	}

	up->insyscall = 0;
	up->psstate = 0;

	if(scallnr == NOTED)
		noted(ureg, *(ulong*)(sp+BY2WD));

	if(scallnr!=RFORK && (up->procctl || up->nnote)){
		splhi();
		notify(ureg);
	}
	/* if we delayed sched because we held a lock, sched now */
	if(up->delaysched)
		sched();
	kexit(ureg);
}
示例#13
0
void
syscall(Ureg* ureg)
{
	char *e;
	u32int s;
	ulong sp;
	long ret;
	int i, scallnr;
	vlong startns, stopns;

	if(!userureg(ureg))
		panic("syscall: from kernel: pc %#lux r14 %#lux psr %#lux",
			ureg->pc, ureg->r14, ureg->psr);

	cycles(&up->kentry);

	m->syscall++;
	up->insyscall = 1;
	up->pc = ureg->pc;
	up->dbgreg = ureg;

	scallnr = ureg->r0;
	up->scallnr = scallnr;
	if(scallnr == RFORK)
		fpusysrfork(ureg);
	spllo();
	sp = ureg->sp;

	if(up->procctl == Proc_tracesyscall){
		/*
		 * Redundant validaddr.  Do we care?
		 * Tracing syscalls is not exactly a fast path...
		 * Beware, validaddr currently does a pexit rather
		 * than an error if there's a problem; that might
		 * change in the future.
		 */
		if(sp < (USTKTOP-BY2PG) || sp > (USTKTOP-sizeof(Sargs)-BY2WD))
			validaddr(sp, sizeof(Sargs)+BY2WD, 0);

		syscallfmt(scallnr, ureg->pc, (va_list)(sp+BY2WD));
		up->procctl = Proc_stopme;
		procctl(up);
		if (up->syscalltrace) 
			free(up->syscalltrace);
		up->syscalltrace = nil;
	}

	up->nerrlab = 0;
	ret = -1;
	startns = todget(nil);
	if(!waserror()){
		if(scallnr >= nsyscall){
			pprint("bad sys call number %d pc %#lux\n",
				scallnr, ureg->pc);
			postnote(up, 1, "sys: bad sys call", NDebug);
			error(Ebadarg);
		}

		if(sp < (USTKTOP-BY2PG) || sp > (USTKTOP-sizeof(Sargs)-BY2WD))
			validaddr(sp, sizeof(Sargs)+BY2WD, 0);

		up->s = *((Sargs*)(sp+BY2WD));
		up->psstate = sysctab[scallnr];

	/*	iprint("%s: syscall %s\n", up->text, sysctab[scallnr]?sysctab[scallnr]:"huh?"); */

		ret = systab[scallnr](up->s.args);
		poperror();
	}else{
		/* failure: save the error buffer for errstr */
		e = up->syserrstr;
		up->syserrstr = up->errstr;
		up->errstr = e;
	}
	if(up->nerrlab){
		print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab);
		for(i = 0; i < NERR; i++)
			print("sp=%#p pc=%#p\n",
				up->errlab[i].sp, up->errlab[i].pc);
		panic("error stack");
	}

	/*
	 *  Put return value in frame.  On the x86 the syscall is
	 *  just another trap and the return value from syscall is
	 *  ignored.  On other machines the return value is put into
	 *  the results register by caller of syscall.
	 */
	ureg->r0 = ret;

	if(up->procctl == Proc_tracesyscall){
		stopns = todget(nil);
		up->procctl = Proc_stopme;
		sysretfmt(scallnr, (va_list)(sp+BY2WD), ret, startns, stopns);
		s = splhi();
		procctl(up);
		splx(s);
		if(up->syscalltrace)
			free(up->syscalltrace);
		up->syscalltrace = nil;
	}

	up->insyscall = 0;
	up->psstate = 0;

	if(scallnr == NOTED)
		noted(ureg, *(ulong*)(sp+BY2WD));

	splhi();
	if(scallnr != RFORK && (up->procctl || up->nnote))
		notify(ureg);

	/* if we delayed sched because we held a lock, sched now */
	if(up->delaysched){
		sched();
		splhi();
	}
	kexit(ureg);
}
示例#14
0
/*
 *  Call user, if necessary, with note.
 *  Pass user the Ureg struct and the note on his stack.
 */
int
notify(Ureg* ureg)
{
	int l;
	Note *n;
	u32int s;
	uintptr sp;
	NFrame *nf;

	if(up->procctl)
		procctl(up);
	if(up->nnote == 0)
		return 0;

	fpunotify(ureg);

	s = spllo();
	qlock(&up->debug);

	up->notepending = 0;
	n = &up->note[0];
	if(strncmp(n->msg, "sys:", 4) == 0){
		l = strlen(n->msg);
		if(l > ERRMAX-23)	/* " pc=0x0123456789abcdef\0" */
			l = ERRMAX-23;
		snprint(n->msg + l, sizeof n->msg - l, " pc=%#lux", ureg->pc);
	}

	if(n->flag != NUser && (up->notified || up->notify == 0)){
		if(n->flag == NDebug)
			pprint("suicide: %s\n", n->msg);
		qunlock(&up->debug);
		pexit(n->msg, n->flag != NDebug);
	}

	if(up->notified){
		qunlock(&up->debug);
		splhi();
		return 0;
	}
		
	if(up->notify == nil){
		qunlock(&up->debug);
		pexit(n->msg, n->flag != NDebug);
	}
	if(!okaddr(PTR2UINT(up->notify), 1, 0)){
		pprint("suicide: notify function address %#p\n", up->notify);
		qunlock(&up->debug);
		pexit("Suicide", 0);
	}

	sp = ureg->sp - sizeof(NFrame);
	if(!okaddr(sp, sizeof(NFrame), 1)){
		qunlock(&up->debug);
		pprint("suicide: notify stack address %#p\n", sp);
		pexit("Suicide", 0);
	}

	nf = UINT2PTR(sp);
	memmove(&nf->ureg, ureg, sizeof(Ureg));
	nf->old = up->ureg;
	up->ureg = nf;
	memmove(nf->msg, up->note[0].msg, ERRMAX);
	nf->arg1 = nf->msg;
	nf->arg0 = &nf->ureg;
	ureg->r0 = PTR2UINT(nf->arg0);
	nf->ip = 0;

	ureg->sp = sp;
	ureg->pc = PTR2UINT(up->notify);
	up->notified = 1;
	up->nnote--;
	memmove(&up->lastnote, &up->note[0], sizeof(Note));
	memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));

	qunlock(&up->debug);
	splx(s);

	return 1;
}
示例#15
0
int main(int argc, char* argv[])
{
    // disable ptrace on the greeter
#if HAVE_PR_SET_DUMPABLE
    prctl(PR_SET_DUMPABLE, 0);
#endif
#if HAVE_PROC_TRACE_CTL
    int mode = PROC_TRACE_CTL_DISABLE;
    procctl(P_PID, getpid(), PROC_TRACE_CTL, &mode);
#endif

    KLocalizedString::setApplicationDomain("kscreenlocker_greet");

    // explicitly disable input methods as it makes it impossible to unlock, see BUG 306932
    // but explicitly set on screen keyboard such as maliit is allowed
    if (qEnvironmentVariableIsSet("QT_IM_MODULE") && qgetenv("QT_IM_MODULE") != QByteArrayLiteral("maliit")) {
        qputenv("QT_IM_MODULE", QByteArrayLiteral("compose"));
    }
    ScreenLocker::UnlockApp app(argc, argv);
    app.setQuitOnLastWindowClosed(false);
    QCoreApplication::setApplicationName(QStringLiteral("kscreenlocker_greet"));
    QCoreApplication::setApplicationVersion(QStringLiteral("0.1"));
    QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org"));

    // disable session management for the greeter
    auto disableSessionManagement = [](QSessionManager &sm) {
        sm.setRestartHint(QSessionManager::RestartNever);
    };
    QObject::connect(&app, &QGuiApplication::commitDataRequest, disableSessionManagement);
    QObject::connect(&app, &QGuiApplication::saveStateRequest, disableSessionManagement);

    QCommandLineParser parser;
    parser.setApplicationDescription(i18n("Greeter for the KDE Plasma Workspaces Screen locker"));
    parser.addHelpOption();
    parser.addVersionOption();

    QCommandLineOption testingOption(QStringLiteral("testing"),
                                     i18n("Starts the greeter in testing mode"));

    QCommandLineOption themeOption(QStringLiteral("theme"),
                                     i18n("Starts the greeter with the selected theme (only in Testing mode)"),
                                     QStringLiteral("theme"),
                                     QStringLiteral(""));

    QCommandLineOption immediateLockOption(QStringLiteral("immediateLock"),
                                           i18n("Lock immediately, ignoring any grace time etc."));
    QCommandLineOption graceTimeOption(QStringLiteral("graceTime"),
                                       i18n("Delay till the lock user interface gets shown in milliseconds."),
                                       QStringLiteral("milliseconds"),
                                       QStringLiteral("0"));
    QCommandLineOption nolockOption(QStringLiteral("nolock"),
                                    i18n("Don't show any lock user interface."));
    QCommandLineOption switchUserOption(QStringLiteral("switchuser"),
                                    i18n("Default to the switch user UI."));

    QCommandLineOption waylandFdOption(QStringLiteral("ksldfd"),
                                       i18n("File descriptor for connecting to ksld."),
                                       QStringLiteral("fd"));

    parser.addOption(testingOption);
    parser.addOption(themeOption);
    parser.addOption(immediateLockOption);
    parser.addOption(graceTimeOption);
    parser.addOption(nolockOption);
    parser.addOption(switchUserOption);
    parser.addOption(waylandFdOption);
    parser.process(app);

    if (parser.isSet(testingOption)) {
        app.setTesting(true);
        app.setImmediateLock(true);

        //parse theme option
        const QString theme = parser.value(themeOption);
        if (!theme.isEmpty()) {
            app.setTheme(theme);
        }

        // allow ptrace if testing is enabled
#if HAVE_PR_SET_DUMPABLE
        prctl(PR_SET_DUMPABLE, 1);
#endif
#if HAVE_PROC_TRACE_CTL
        int mode = PROC_TRACE_CTL_ENABLE;
        procctl(P_PID, getpid(), PROC_TRACE_CTL, &mode);
#endif
    } else {
        app.setImmediateLock(parser.isSet(immediateLockOption));
    }
    app.setNoLock(parser.isSet(nolockOption));

    bool ok = false;
    int graceTime = parser.value(graceTimeOption).toInt(&ok);
    if (ok) {
        app.setGraceTime(graceTime);
    }

    if (parser.isSet(switchUserOption)) {
        app.setDefaultToSwitchUser(true);
    }

    if (parser.isSet(waylandFdOption)) {
        ok = false;
        const int fd = parser.value(waylandFdOption).toInt(&ok);
        if (ok) {
            app.setKsldSocket(fd);
        }
    }
    app.desktopResized();

    // This allow ksmserver to know when the applicaion has actually finished setting itself up.
    // Crucial for blocking until it is ready, ensuring locking happens before sleep, e.g.
    std::cout << "Locked at " << QDateTime::currentDateTime().toTime_t() << std::endl;

    struct sigaction sa;
    sa.sa_handler = signalHandler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    sigaction(SIGTERM, &sa, nullptr);
    sigaction(SIGUSR1, &sa, nullptr);
    return app.exec();
}