Subject: Per-process personalities in emulations
To: None <tech-kern@NetBSD.ORG>
From: Niklas Hallqvist <niklas@appli.se>
List: tech-kern
Date: 11/09/1995 14:28:00
I'm doing some work on emulations in NetBSD/i386 and have come to know
that different vendors have done small things slightly different and
that applications have come to rely on this.  At first I just made
compile-time options for handling this like COMPAT_SVR4_DELL and
COMPAT_SVR4_NCR which in turn had global impact on the emulation code.
As I'm convinced I'm going to find more of these things, I'd like to
propose a better solution, and would like to get comments on this.

Mainly my idea is to have a per-process set of flags that changes
different aspects of the emulation in use.  I call this set the
"personality" of the process as is customary in other emulation
solutions I've seen.  Here is the design I've come up with:

+	Rename p_unused of struct proc to p_personality.  This will
	contain the personality of the process.  (Will a single u_char
	be enough?  Who knows?)

+	On forks the p_personality flag will be inherited.

+	On execs the p_personality will be reset unless a special bit
	of p_personality (PERS_RETAIN) is set.  If PERS_RETAIN is set,
	just that one bit will be cleared.  This bit will be used by
	the wrappers discussed below.

+	In order to set the p_personality of a process a special
	sysctl will be used.  This sysctl will automatically set
	PERS_RETAIN as well as the specified personality.

In order to use this system, executables that require a certain
personality will have to be wrapped.  A simple script can generate
these wrappers which need to look something like:

int
main (argc, argv)
{
  setpersonality(PERSONALITY);
  return execv(REAL_EXECUTABLE, argv);
}

Perhaps incoming argv isn't NULL terminated but you get the point.
It's easy enough to duplicate argv in that case.  PERSONALITY &
REAL_EXECUTABLE should be provided by the genwrapper script.
setpersonality is just a sysctl(2) wrapper doing the right thing (tm).

This way, when one finds a binary that doesn't run under pure
emulation, you just install it in a well-defined place and generate a
wrapper which sets the personality correct.  The personality will
survive the exec as PERS_RETAIN is set, but not later execs, which is
important because the new executable might fail miserably under the
current personality.

Well comments?

The two personalities apart from "standard" SVR4 I've found so far is
these:

1	Page zero mapped (just read-only, but hell, it's bad enough
	anyway to not want it on all SVR4 executables).  As some
	commercial executables where source is not available does
	NULL-reads and Dell Unix allowed this, this need to be
	handled.  Today I allow all apps do page zero reads, Bleah!

2	An obsolete syscall (#76 rdebug) returns ENXIO instead of
	sending a SIGSYS on NCR Unix.  Informix relies on this fact
	and dumps core otherwise.  Today I solve this be going the NCR
	way in my local SVR4 emulation.  Not nice!

I'm probably going to implement my scheme soon, so if you have
comments that may change my implementation, please speak up.

Niklas

Niklas Hallqvist       Phone: +46-(0)31-40 75 00  Home: +46-(0)31-41 93 95
Applitron Datasystem   Fax:   +46-(0)31-83 39 50  Home: +46-(0)31-41 93 96
Molndalsvagen 95       Email: niklas@appli.se     GSM:  +46-(0)70-714 10 35
S-412 63  GOTEBORG     WWW:   Here
Sweden		       IRC:   niklas (#NetBSD)    ICB:  niklas (netbsd)