Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27 
     28 #include <stdio.h>
     29 #include <stdlib.h>
     30 #include <unistd.h>
     31 #include <ctype.h>
     32 #include <fcntl.h>
     33 #include <string.h>
     34 #include <memory.h>
     35 #include <errno.h>
     36 #include <dirent.h>
     37 #include <limits.h>
     38 #include <signal.h>
     39 #include <sys/types.h>
     40 #include <sys/uio.h>
     41 #include <sys/stat.h>
     42 #include <sys/resource.h>
     43 #include <sys/param.h>
     44 #include <sys/stack.h>
     45 #include <sys/fault.h>
     46 #include <sys/syscall.h>
     47 #include <sys/sysmacros.h>
     48 
     49 #include "libproc.h"
     50 #include "Pcontrol.h"
     51 #include "Putil.h"
     52 #include "P32ton.h"
     53 #include "Pisadep.h"
     54 
     55 extern sigset_t blockable_sigs;
     56 
     57 static void
     58 Pabort_agent(struct ps_prochandle *P)
     59 {
     60 	int sysnum = P->status.pr_lwp.pr_syscall;
     61 	int stop;
     62 
     63 	dprintf("agent LWP is asleep in syscall %d\n", sysnum);
     64 	(void) Pstop(P, 0);
     65 	stop = Psysexit(P, sysnum, TRUE);
     66 
     67 	if (Psetrun(P, 0, PRSABORT) == 0) {
     68 		while (Pwait(P, 0) == -1 && errno == EINTR)
     69 			continue;
     70 		(void) Psysexit(P, sysnum, stop);
     71 		dprintf("agent LWP system call aborted\n");
     72 	}
     73 }
     74 
     75 /*
     76  * Create the /proc agent LWP for further operations.
     77  */
     78 int
     79 Pcreate_agent(struct ps_prochandle *P)
     80 {
     81 	int fd;
     82 	char pathname[PATH_MAX];
     83 	char *fname;
     84 	struct {
     85 		long	cmd;
     86 		prgregset_t regs;
     87 	} cmd;
     88 
     89 	/*
     90 	 * If not first reference, we already have the /proc agent LWP active.
     91 	 */
     92 	if (P->agentcnt > 0) {
     93 		P->agentcnt++;
     94 		return (0);
     95 	}
     96 
     97 	/*
     98 	 * The agent is not available for use as a mortician or as an
     99 	 * obstetrician.
    100 	 */
    101 	if (P->state == PS_DEAD || P->state == PS_UNDEAD ||
    102 	    P->state == PS_IDLE) {
    103 		errno = ENOENT;
    104 		return (-1);
    105 	}
    106 
    107 	/*
    108 	 * Create the special /proc agent LWP if it doesn't already exist.
    109 	 * Give it the registers of the representative LWP.
    110 	 */
    111 	(void) Pstop(P, 0);
    112 	Psync(P);
    113 	if (!(P->status.pr_lwp.pr_flags & PR_AGENT)) {
    114 		cmd.cmd = PCAGENT;
    115 		(void) memcpy(&cmd.regs, &P->status.pr_lwp.pr_reg[0],
    116 		    sizeof (P->status.pr_lwp.pr_reg));
    117 		if (write(P->ctlfd, &cmd, sizeof (cmd)) != sizeof (cmd))
    118 			goto bad;
    119 	}
    120 
    121 	/* refresh the process status */
    122 	(void) Pstopstatus(P, PCNULL, 0);
    123 
    124 	/* open the agent LWP files */
    125 	(void) snprintf(pathname, sizeof (pathname), "%s/%d/lwp/agent/",
    126 	    procfs_path, (int)P->pid);
    127 	fname = pathname + strlen(pathname);
    128 	(void) set_minfd();
    129 
    130 	/*
    131 	 * It is difficult to know how to recover from the two errors
    132 	 * that follow.  The agent LWP exists and we need to kill it,
    133 	 * but we can't because we need it active in order to kill it.
    134 	 * We just hope that these failures never occur.
    135 	 */
    136 	(void) strcpy(fname, "lwpstatus");
    137 	if ((fd = open(pathname, O_RDONLY)) < 0 ||
    138 	    (fd = dupfd(fd, 0)) < 0)
    139 		goto bad;
    140 	P->agentstatfd = fd;
    141 
    142 	(void) strcpy(fname, "lwpctl");
    143 	if ((fd = open(pathname, O_WRONLY)) < 0 ||
    144 	    (fd = dupfd(fd, 0)) < 0)
    145 		goto bad;
    146 	P->agentctlfd = fd;
    147 
    148 	/*
    149 	 * If the agent is currently asleep in a system call, attempt
    150 	 * to abort the system call so it's ready to serve.
    151 	 */
    152 	if (P->status.pr_lwp.pr_flags & PR_ASLEEP) {
    153 		dprintf("Pcreate_agent: aborting agent syscall\n");
    154 		Pabort_agent(P);
    155 	}
    156 
    157 	/* get the agent LWP status */
    158 	P->agentcnt++;
    159 	if (Pstopstatus(P, PCNULL, 0) != 0) {
    160 		Pdestroy_agent(P);
    161 		return (-1);
    162 	}
    163 
    164 	return (0);
    165 
    166 bad:
    167 	if (P->agentstatfd >= 0)
    168 		(void) close(P->agentstatfd);
    169 	if (P->agentctlfd >= 0)
    170 		(void) close(P->agentctlfd);
    171 	P->agentstatfd = -1;
    172 	P->agentctlfd = -1;
    173 	/* refresh the process status */
    174 	(void) Pstopstatus(P, PCNULL, 0);
    175 	return (-1);
    176 }
    177 
    178 /*
    179  * Decrement the /proc agent agent reference count.
    180  * On last reference, destroy the agent.
    181  */
    182 void
    183 Pdestroy_agent(struct ps_prochandle *P)
    184 {
    185 	if (P->agentcnt > 1)
    186 		P->agentcnt--;
    187 	else {
    188 		int flags;
    189 
    190 		Psync(P); /* Flush out any pending changes */
    191 
    192 		(void) Pstopstatus(P, PCNULL, 0);
    193 		flags = P->status.pr_lwp.pr_flags;
    194 
    195 		/*
    196 		 * If the agent is currently asleep in a system call, attempt
    197 		 * to abort the system call so we can terminate the agent.
    198 		 */
    199 		if ((flags & (PR_AGENT|PR_ASLEEP)) == (PR_AGENT|PR_ASLEEP)) {
    200 			dprintf("Pdestroy_agent: aborting agent syscall\n");
    201 			Pabort_agent(P);
    202 		}
    203 
    204 		/*
    205 		 * The agent itself is destroyed by forcing it to execute
    206 		 * the _lwp_exit(2) system call.  Close our agent descriptors
    207 		 * regardless of whether this is successful.
    208 		 */
    209 		(void) pr_lwp_exit(P);
    210 		(void) close(P->agentctlfd);
    211 		(void) close(P->agentstatfd);
    212 		P->agentctlfd = -1;
    213 		P->agentstatfd = -1;
    214 		P->agentcnt = 0;
    215 
    216 		/*
    217 		 * Now that (hopefully) the agent has exited, refresh the
    218 		 * status: the representative LWP is no longer the agent.
    219 		 */
    220 		(void) Pstopstatus(P, PCNULL, 0);
    221 	}
    222 }
    223 
    224 /*
    225  * Execute the syscall instruction.
    226  */
    227 static int
    228 execute(struct ps_prochandle *P, int sysindex)
    229 {
    230 	int ctlfd = (P->agentctlfd >= 0)? P->agentctlfd : P->ctlfd;
    231 	int washeld = FALSE;
    232 	sigset_t hold;		/* mask of held signals */
    233 	int cursig;
    234 	struct {
    235 		long cmd;
    236 		siginfo_t siginfo;
    237 	} ctl;
    238 	int sentry;		/* old value of stop-on-syscall-entry */
    239 
    240 	sentry = Psysentry(P, sysindex, TRUE);	/* set stop-on-syscall-entry */
    241 
    242 	/*
    243 	 * If not already blocked, block all signals now.
    244 	 */
    245 	if (memcmp(&P->status.pr_lwp.pr_lwphold, &blockable_sigs,
    246 	    sizeof (sigset_t)) != 0) {
    247 		hold = P->status.pr_lwp.pr_lwphold;
    248 		P->status.pr_lwp.pr_lwphold = blockable_sigs;
    249 		P->flags |= SETHOLD;
    250 		washeld = TRUE;
    251 	}
    252 
    253 	/*
    254 	 * If there is a current signal, remember it and cancel it.
    255 	 */
    256 	if ((cursig = P->status.pr_lwp.pr_cursig) != 0) {
    257 		ctl.cmd = PCSSIG;
    258 		ctl.siginfo = P->status.pr_lwp.pr_info;
    259 	}
    260 
    261 	if (Psetrun(P, 0, PRCSIG | PRCFAULT) == -1)
    262 		goto bad;
    263 
    264 	while (P->state == PS_RUN) {
    265 		(void) Pwait(P, 0);
    266 	}
    267 	if (P->state != PS_STOP)
    268 		goto bad;
    269 
    270 	if (cursig)				/* restore cursig */
    271 		(void) write(ctlfd, &ctl, sizeof (ctl));
    272 	if (washeld) {		/* restore the signal mask if we set it */
    273 		P->status.pr_lwp.pr_lwphold = hold;
    274 		P->flags |= SETHOLD;
    275 	}
    276 
    277 	(void) Psysentry(P, sysindex, sentry);	/* restore sysentry stop */
    278 
    279 	if (P->status.pr_lwp.pr_why  == PR_SYSENTRY &&
    280 	    P->status.pr_lwp.pr_what == sysindex)
    281 		return (0);
    282 bad:
    283 	return (-1);
    284 }
    285 
    286 
    287 /*
    288  * Perform system call in controlled process.
    289  */
    290 int
    291 Psyscall(struct ps_prochandle *P,
    292 	sysret_t *rval,		/* syscall return values */
    293 	int sysindex,		/* system call index */
    294 	uint_t nargs,		/* number of arguments to system call */
    295 	argdes_t *argp)		/* argument descriptor array */
    296 {
    297 	int agent_created = FALSE;
    298 	pstatus_t save_pstatus;
    299 	argdes_t *adp;			/* pointer to argument descriptor */
    300 	int i;				/* general index value */
    301 	int model;			/* data model */
    302 	int error = 0;			/* syscall errno */
    303 	int Perr = 0;			/* local error number */
    304 	int sexit;			/* old value of stop-on-syscall-exit */
    305 	prgreg_t sp;			/* adjusted stack pointer */
    306 	prgreg_t ap;			/* adjusted argument pointer */
    307 	sigset_t unblock;
    308 
    309 	(void) sigprocmask(SIG_BLOCK, &blockable_sigs, &unblock);
    310 
    311 	rval->sys_rval1 = 0;		/* initialize return values */
    312 	rval->sys_rval2 = 0;
    313 
    314 	if (sysindex <= 0 || sysindex > PRMAXSYS || nargs > MAXARGS)
    315 		goto bad1;	/* programming error */
    316 
    317 	if (P->state == PS_DEAD || P->state == PS_UNDEAD || P->state == PS_IDLE)
    318 		goto bad1;	/* dead processes can't perform system calls */
    319 
    320 	model = P->status.pr_dmodel;
    321 #ifndef _LP64
    322 	/* We must be a 64-bit process to deal with a 64-bit process */
    323 	if (model == PR_MODEL_LP64)
    324 		goto bad9;
    325 #endif
    326 
    327 	/*
    328 	 * Create the /proc agent LWP in the process to do all the work.
    329 	 * (It may already exist; nested create/destroy is permitted
    330 	 * by virtue of the reference count.)
    331 	 */
    332 	if (Pcreate_agent(P) != 0)
    333 		goto bad8;
    334 
    335 	/*
    336 	 * Save agent's status to restore on exit.
    337 	 */
    338 	agent_created = TRUE;
    339 	save_pstatus = P->status;
    340 
    341 	if (P->state != PS_STOP ||		/* check state of LWP */
    342 	    (P->status.pr_flags & PR_ASLEEP))
    343 		goto bad2;
    344 
    345 	if (Pscantext(P))			/* bad text ? */
    346 		goto bad3;
    347 
    348 	/*
    349 	 * Validate arguments and compute the stack frame parameters.
    350 	 * Begin with the current stack pointer.
    351 	 */
    352 #ifdef _LP64
    353 	if (model == PR_MODEL_LP64) {
    354 		sp = P->status.pr_lwp.pr_reg[R_SP] + STACK_BIAS;
    355 		sp = PSTACK_ALIGN64(sp);
    356 	} else {
    357 #endif
    358 		sp = (uint32_t)P->status.pr_lwp.pr_reg[R_SP];
    359 		sp = PSTACK_ALIGN32(sp);
    360 #ifdef _LP64
    361 	}
    362 #endif
    363 
    364 	/*
    365 	 * For each AT_BYREF argument, compute the necessary
    366 	 * stack space and the object's stack address.
    367 	 */
    368 	for (i = 0, adp = argp; i < nargs; i++, adp++) {
    369 		rval->sys_rval1 = i;		/* in case of error */
    370 		switch (adp->arg_type) {
    371 		default:			/* programming error */
    372 			goto bad4;
    373 		case AT_BYVAL:			/* simple argument */
    374 			break;
    375 		case AT_BYREF:			/* must allocate space */
    376 			switch (adp->arg_inout) {
    377 			case AI_INPUT:
    378 			case AI_OUTPUT:
    379 			case AI_INOUT:
    380 				if (adp->arg_object == NULL)
    381 					goto bad5;	/* programming error */
    382 				break;
    383 			default:		/* programming error */
    384 				goto bad6;
    385 			}
    386 			/* allocate stack space for BYREF argument */
    387 			if (adp->arg_size == 0 || adp->arg_size > MAXARGL)
    388 				goto bad7;	/* programming error */
    389 #ifdef _LP64
    390 			if (model == PR_MODEL_LP64)
    391 				sp = PSTACK_ALIGN64(sp - adp->arg_size);
    392 			else
    393 #endif
    394 				sp = PSTACK_ALIGN32(sp - adp->arg_size);
    395 			adp->arg_value = sp;	/* stack address for object */
    396 			break;
    397 		}
    398 	}
    399 	rval->sys_rval1 = 0;			/* in case of error */
    400 	/*
    401 	 * Point of no return.
    402 	 * Perform the system call entry, adjusting %sp.
    403 	 * This moves the LWP to the stopped-on-syscall-entry state
    404 	 * just before the arguments to the system call are fetched.
    405 	 */
    406 	ap = Psyscall_setup(P, nargs, sysindex, sp);
    407 	P->flags |= SETREGS;	/* set registers before continuing */
    408 	dprintf("Psyscall(): execute(sysindex = %d)\n", sysindex);
    409 
    410 	/*
    411 	 * Execute the syscall instruction and stop on syscall entry.
    412 	 */
    413 	if (execute(P, sysindex) != 0 ||
    414 	    (!Pissyscall(P, P->status.pr_lwp.pr_reg[R_PC]) &&
    415 	    !Pissyscall_prev(P, P->status.pr_lwp.pr_reg[R_PC], NULL)))
    416 		goto bad10;
    417 
    418 	dprintf("Psyscall(): copying arguments\n");
    419 
    420 	/*
    421 	 * The LWP is stopped at syscall entry.
    422 	 * Copy objects to stack frame for each argument.
    423 	 */
    424 	for (i = 0, adp = argp; i < nargs; i++, adp++) {
    425 		rval->sys_rval1 = i;		/* in case of error */
    426 		if (adp->arg_type != AT_BYVAL &&
    427 		    adp->arg_inout != AI_OUTPUT) {
    428 			/* copy input byref parameter to process */
    429 			if (Pwrite(P, adp->arg_object, adp->arg_size,
    430 			    (uintptr_t)adp->arg_value) != adp->arg_size)
    431 				goto bad17;
    432 		}
    433 	}
    434 	rval->sys_rval1 = 0;			/* in case of error */
    435 	if (Psyscall_copyinargs(P, nargs, argp, ap) != 0)
    436 		goto bad18;
    437 
    438 	/*
    439 	 * Complete the system call.
    440 	 * This moves the LWP to the stopped-on-syscall-exit state.
    441 	 */
    442 	dprintf("Psyscall(): set running at sysentry\n");
    443 
    444 	sexit = Psysexit(P, sysindex, TRUE);	/* catch this syscall exit */
    445 	do {
    446 		if (Psetrun(P, 0, 0) == -1)
    447 			goto bad21;
    448 		while (P->state == PS_RUN)
    449 			(void) Pwait(P, 0);
    450 	} while (P->state == PS_STOP && P->status.pr_lwp.pr_why != PR_SYSEXIT);
    451 	(void) Psysexit(P, sysindex, sexit);	/* restore original setting */
    452 
    453 	/*
    454 	 * If the system call was _lwp_exit(), we expect that our last call
    455 	 * to Pwait() will yield ENOENT because the LWP no longer exists.
    456 	 */
    457 	if (sysindex == SYS_lwp_exit && errno == ENOENT) {
    458 		dprintf("Psyscall(): _lwp_exit successful\n");
    459 		rval->sys_rval1 = rval->sys_rval2 = 0;
    460 		goto out;
    461 	}
    462 
    463 	if (P->state != PS_STOP || P->status.pr_lwp.pr_why != PR_SYSEXIT)
    464 		goto bad22;
    465 
    466 	if (P->status.pr_lwp.pr_what != sysindex)
    467 		goto bad23;
    468 
    469 	if (!Pissyscall_prev(P, P->status.pr_lwp.pr_reg[R_PC], NULL)) {
    470 		dprintf("Pissyscall_prev() failed\n");
    471 		goto bad24;
    472 	}
    473 
    474 	dprintf("Psyscall(): caught at sysexit\n");
    475 
    476 	/*
    477 	 * For each argument.
    478 	 */
    479 	for (i = 0, adp = argp; i < nargs; i++, adp++) {
    480 		rval->sys_rval1 = i;		/* in case of error */
    481 		if (adp->arg_type != AT_BYVAL &&
    482 		    adp->arg_inout != AI_INPUT) {
    483 			/* copy output byref parameter from process */
    484 			if (Pread(P, adp->arg_object, adp->arg_size,
    485 			    (uintptr_t)adp->arg_value) != adp->arg_size)
    486 				goto bad25;
    487 		}
    488 	}
    489 
    490 	if (Psyscall_copyoutargs(P, nargs, argp, ap) != 0)
    491 		goto bad26;
    492 
    493 	/*
    494 	 * Get the return values from the syscall.
    495 	 */
    496 	if (P->status.pr_lwp.pr_errno) {	/* error return */
    497 		error = P->status.pr_lwp.pr_errno;
    498 		rval->sys_rval1 = -1L;
    499 		rval->sys_rval2 = -1L;
    500 		dprintf("Psyscall(%d) fails with errno %d\n",
    501 		    sysindex, error);
    502 	} else {				/* normal return */
    503 		rval->sys_rval1 = P->status.pr_lwp.pr_rval1;
    504 		rval->sys_rval2 = P->status.pr_lwp.pr_rval2;
    505 		dprintf("Psyscall(%d) returns 0x%lx 0x%lx\n", sysindex,
    506 		    P->status.pr_lwp.pr_rval1, P->status.pr_lwp.pr_rval2);
    507 	}
    508 
    509 	goto out;
    510 
    511 bad26:	Perr++;
    512 bad25:	Perr++;
    513 bad24:	Perr++;
    514 bad23:	Perr++;
    515 bad22:	Perr++;
    516 bad21:	Perr++;
    517 	Perr++;
    518 	Perr++;
    519 bad18:	Perr++;
    520 bad17:	Perr++;
    521 	Perr++;
    522 	Perr++;
    523 	Perr++;
    524 	Perr++;
    525 	Perr++;
    526 	Perr++;
    527 bad10:	Perr++;
    528 bad9:	Perr++;
    529 bad8:	Perr++;
    530 bad7:	Perr++;
    531 bad6:	Perr++;
    532 bad5:	Perr++;
    533 bad4:	Perr++;
    534 bad3:	Perr++;
    535 bad2:	Perr++;
    536 bad1:	Perr++;
    537 	error = -1;
    538 	dprintf("Psyscall(%d) fails with local error %d\n", sysindex, Perr);
    539 
    540 out:
    541 	/*
    542 	 * Destroy the /proc agent LWP now (or just bump down the ref count).
    543 	 */
    544 	if (agent_created) {
    545 		if (P->state != PS_UNDEAD) {
    546 			P->status = save_pstatus;
    547 			P->flags |= SETREGS;
    548 			Psync(P);
    549 		}
    550 		Pdestroy_agent(P);
    551 	}
    552 
    553 	(void) sigprocmask(SIG_SETMASK, &unblock, NULL);
    554 	return (error);
    555 }
    556