[comp.unix.wizards] syscall

kerchen@iris.ucdavis.edu (Paul Kerchen) (02/28/89)

Hello all!
Currently I'm researching computer viruses here at UCD and I have
encountered an interesting question (at least I think it's
interesting):  Is the system call "syscall()" necessary?  I am *not*
asking if system calls in general are necessary.  I *am* asking about a
particular system call called "syscall" which allows indirect system
calls (see section 2 of the man pages for more info).  It seems like
anything one could do with syscall() could be done just using the
needed system call directly.  I'd like to know if there are certain
applications for which this function is a *necessity*, not just a
convenience.  Also, I am looking for *real* examples, not contrived
ones with no basis in reality.
(Sorry for being so verbose.  I want to make sure that it is clear
what I am asking--I've already received enough replies which go
something like, "System calls are needed so that applications become
independent of changes in the kernel....")



Paul Kerchen				| kerchen@iris.ucdavis.edu

gwyn@smoke.BRL.MIL (Doug Gwyn ) (02/28/89)

In article <3740@ucdavis.ucdavis.edu> kerchen@iris.ucdavis.edu (Paul Kerchen) writes:
>Is the system call "syscall()" necessary?

It's not a system call, just a library function.
Of course it is not necessary in any logical sense.
I don't even think it's particularly useful these days;
the last time I saw it used was on a Sixth Edition UNIX system.

lee@doc.cs.unm.edu (Lee Ward) (02/28/89)

In article <9742@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>In article <3740@ucdavis.ucdavis.edu> kerchen@iris.ucdavis.edu (Paul Kerchen) writes:
>>Is the system call "syscall()" necessary?
>
>It's not a system call, just a library function.
>Of course it is not necessary in any logical sense.
>I don't even think it's particularly useful these days;
>the last time I saw it used was on a Sixth Edition UNIX system.


It still has uses...

#include <stdio.h>

/* 4.{2,3} reset UBA - BSD VAX */

#define	RESUBA		119

main(argc, argv)
	int	argc;
	char	*argv[];
{

	if (argc != 2) {
		fprintf(stderr, "Usage: %s UBA#\n", argv[0]);
		exit(1);
	}

	exit (syscall(RESUBA, atoi(argv[1])));
}
			--Lee (Ward)

ekrell@hector.UUCP (Eduardo Krell) (02/28/89)

In article <3740@ucdavis.ucdavis.edu> kerchen@iris.ucdavis.edu (Paul Kerchen) writes:

>Is the system call "syscall()" necessary?

Yes, and I'll give you an example where I use it. We have a user level
C library which implements an extension to the Unix File System.
This work was originally done inside the kernel (where it belongs), but
for practical reasons we decided to write a user level library which
emulates the semantics of our extensions (we didn't want to force our
users to run a new kernel just to play with our stuff).

This user level library contains functions for all the system calls which
take pathnames as arguments (like stat, open, link, etc.). We do some
magic with the pathnames supplied to these functions and then call the *real*
system calls with maybe different pathnames. The call to the real system
call is accomplished through syscall().

I could have done it without syscall(), but it would have required
major kludges to do it in a portable way.
    
Eduardo Krell                   AT&T Bell Laboratories, Murray Hill, NJ

UUCP: {att,decvax,ucbvax}!ulysses!ekrell  Internet: ekrell@ulysses.att.com

haahr@phoenix.Princeton.EDU (Paul Gluckauf Haahr) (02/28/89)

kerchen@iris.ucdavis.edu (Paul Kerchen) writes:
> Is the system call "syscall()" necessary?

as doug points out, it's just a library function not a system call.
all it provides is a (portable) C callable interface to the assembly
language glue that traps to the operating system.  it is the moral
equivalent of an inline asm directive for a "chmk" or "trap #0" or
"syscall" instruction.

on some systems i've seen, the system calls that can be implemented
as calls to syscall() are.  (things like wait() and pipe() often are hard
to do)  this makes it easy to write the syscalls directly in c.

gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) responds:
> It's not a system call, just a library function.
> Of course it is not necessary in any logical sense.
> I don't even think it's particularly useful these days;
> the last time I saw it used was on a Sixth Edition UNIX system.

it can be useful if one is spoofing other system calls.  i have code,
for example, that replaces read() and write() with functions that
somewhere down the road do real syscalls.
with syscall() declared as
	int syscall(int, ...);
one can conveniently use
	#define	_read(fd, buf, n) syscall(SYS_read, fd, buf, n)

[ to do this in an ansi c environment, one would probably have to
spoof out _SYS_read as well. ]

paul haahr
princeton!haahr	  haahr@princeton.edu	haahr@pucc.bitnet

gwyn@smoke.BRL.MIL (Doug Gwyn ) (02/28/89)

In article <2292@unmvax.unm.edu> lee@doc.cs.unm.edu () writes:
-In article <9742@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
->In article <3740@ucdavis.ucdavis.edu> kerchen@iris.ucdavis.edu (Paul Kerchen) writes:
->>Is the system call "syscall()" necessary?
->I don't even think it's particularly useful these days; ...
-It still has uses...
-	exit (syscall(RESUBA, atoi(argv[1])));

Only because Berkeley neglected to provide a resuba() hook in
the C library!  Given direct hooks in the library for all system
calls, I know of no real requirement for the syscall() function.

jik@athena.mit.edu (Jonathan I. Kamens) (02/28/89)

The workstation installation floppies at Project Athena are severely
limited by space -- they must fit on a 1.2meg floppy (for a VAX
workstation) or on 2 1.2meg floppies (for an IBM RT).  We can't
include a different binary for every system call we need to use, so we
write one binary with a simple interface to syscall() and then write
shell scripts to do what the rest of the binaries would do.

Works great for us :-)


Jonathan Kamens			              USnail:
MIT Project Athena				410 Memorial Drive, No. 223F
jik@Athena.MIT.EDU				Cambridge, MA 02139-4318
Office: 617-253-4261			      Home: 617-225-8218

debra@alice.UUCP (Paul De Bra) (03/01/89)

In article <3740@ucdavis.ucdavis.edu> kerchen@iris.ucdavis.edu (Paul Kerchen) writes:
>Hello all!
>Currently I'm researching computer viruses here at UCD and I have
>encountered an interesting question (at least I think it's
>interesting):  Is the system call "syscall()" necessary?...
>...  Also, I am looking for *real* examples, not contrived
>ones with no basis in reality.

A *real* example can be found in the EUUG UUCP source.
Uucp used to create *lots* of files in /usr/spool/uucp. It is more
convenient to distribute these files among several directories, as modern
uucp's do. What this uucp does is modify names like "D.systemXXXX" into
"D.system/XXXX" or something. The way this works is as follows:

1) the source code for uucp is not modified.
2) a new routine "open()" is written, which modifies the "D.systemXXXX"
   into "D.system/XXXX", and then calls syscall() with the right
   parameters to do the real open(). By having your own open() routine
   there is no way to access the real open() system call any more, so
   they use syscall instead.

Paul.
-- 
------------------------------------------------------
|debra@research.att.com   | uunet!research!debra     |
------------------------------------------------------

guy@auspex.UUCP (Guy Harris) (03/01/89)

An omnibus reply:

> (Sorry for being so verbose.  I want to make sure that it is clear
> what I am asking--I've already received enough replies which go
> something like, "System calls are needed so that applications become
> independent of changes in the kernel....")

It's unfortunate that people believe that, because it's not true.  There
exist other mechanisms for dynamically binding code to a particular
procedure, which is what the person is *really* saying is needed here;
those other mechanisms work for functions *not* implemented in the
kernel, and that greater generality can be a big win.

It should be possible to make applications independent of changes to the
implementation of user-mode library routines, as well; that way, for
example, you can have the same application binary work, regardless of
whether "gethostbyname" reads "/etc/hosts", or talks to the Internet
name server, or talks to the Yellow Pages server, or talks to an Apollo
Registry server, or....  The application just binds to whatever the
local implementation of "gethostbyname" is.  (Sun has put a version of
its SunOS 4.0 "libc" shared library on "uunet" that contains a
"gethost*" that talks to the Internet name server rather than to the
Yellow Pages server, for example, so this isn't just a theoretical "this
could be done" argument - it *has* been done.)

> It still has uses...

> #include <stdio.h>

> /* 4.{2,3} reset UBA - BSD VAX */

It is useful there only because there's no library routine in the
4.{2,3}BSD C library that directly executes the appropriate trap, or
whatever.  Had they included such a routine, "syscall" wouldn't be
necessary in this case; nothing *prevented* them from including such a
routine, so the example does not at all demonstrate that "syscall" is an
absolute necessity, merely that a deficiency in the OS requires that
"syscall" be used to work around it.

>This user level library contains functions for all the system calls which
>take pathnames as arguments (like stat, open, link, etc.). We do some
>magic with the pathnames supplied to these functions and then call the *real*
>system calls with maybe different pathnames. The call to the real system
>call is accomplished through syscall().
>
>I could have done it without syscall(), but it would have required
>major kludges to do it in a portable way.

Again, this is a special-case solution to a more general problem; had a
more general mechanism for writing "wrappers" for existing procedure
calls existed - one that would, say, permit you to write "wrappers"
around routines that *aren't* just stubs that trap to the kernel - such
a mechanism could have been used.  So again, it doesn't demonstrate that
"syscall" is an absolute necessity, merely that it's required in some
cases to get around deficiencies in the OS.

Leisner.Henr@xerox.com (marty) (03/01/89)

Geez, I never knew about syscall.

Recently I wanted to control the amount of ram my program had to work with
so I could see how it failed under various memory-short environments.

I wanted to move my stack to N bytes over my data area, so I had a heap N
bytes large (only in effect for this process) and I wanted N configurable
at run time.  I wrote my own sbrk which checked against the current stack
pointer to see whether or not to allocate space for malloc (which used
morecore).

Turns out sbrk and brk were in the same module -- so I had to unassemble
and synthesize my own brk system call (this was on an Opus board with a
National 32016 running Sys V.?).

If I knew about syscall, I support I could have just coded brk as:

brk(void *address)
{
	return (int) syscall(BRK_#, address)
}

instead of messing with assembler.  (It didn't take long anyway).

When I get back to playing with that piece of software, I'll try the
syscall apporach.

marty
ARPA:	leisner.henr@xerox.com
GV:  leisner.henr
NS:  martin leisner:wbst139:xerox
UUCP:  hplabs!arisia!leisner

kerchen@iris.ucdavis.edu (Paul Kerchen) (03/01/89)

Thank you to everyone who replied to my question about syscall().  I'm
posting this here because I couldn't reply to everyone who sent me
responses ( mailer bounced 'em )-: ).  I did get several good reasons
for having the beast, so I'm more or less satisfied.  Again, thank
you.


Paul Kerchen				| kerchen@iris.ucdavis.edu

gwyn@smoke.BRL.MIL (Doug Gwyn ) (03/01/89)

In article <8984@alice.UUCP> debra@alice.UUCP () writes:
>2) a new routine "open()" is written, which modifies the "D.systemXXXX"
>   into "D.system/XXXX", and then calls syscall() with the right
>   parameters to do the real open(). By having your own open() routine
>   there is no way to access the real open() system call any more, so
>   they use syscall instead.

There is a danger here that you need to be aware of.
Quite possibly some of the application code opens files via calls
to fopen() rather than directly using open().
The above trick has worked so far because UNIX fopen() eventually
invokes the open() function in the C library.
In the near future, it is probable that UNIX fopen() will instead
invoke a function called __open() or some such;
this is required for compliance with the (forthcoming) ANSI C standard.
(There are actually some ways around this but the simplest
implementation is as I've just described.)
Therefore the application will no longer have all its file-opening
attempts intercepted by your "wrapper" around the OPEN system call.

mirk@warwick.UUCP (Mike Taylor) (03/07/89)

In article <9757@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB)) writes:
>Quite possibly some of the application code opens files via calls to
>fopen() rather than directly using open().  The above trick has worked
>so far because UNIX fopen() eventually invokes the open() function in
>the C library.  In the near future, it is probable that UNIX fopen()
>will instead invoke a function called __open() or some such;

Am I missing something here, or is this a major disaster?  I always
thought that the beauty of UNIX was supposed be that everything went
through a simple, elegant and well-defined interface of system-calls,
that *all* reading was via read(2), that *all* writing was via
write(2), and so on.  I thought that UNIX was the operating system
where the user Knows Where He Stands?

It's kinda sad to see how the minimal set of low-level routines in
primitive UNICES has mushroomed to the incredible 178 distinct system
calls that our current UNIX (SunOS 4.3, in fact) seems to find
necessary.  But surely once you start saying that fopen() doesn't have
to use the system-calls at all, the whole ethos goes right out the
window?  I remember the quote from Ken Thompson: "The only thing I
would chnage if I designed UNIX now is that I would call the creat()
system call create()".  Ask yourself how *that* ties in with this
apalling move?
______________________________________________________________________________
Mike Taylor - {Christ,M{athemat,us}ic}ian ...  Email to: mirk@uk.ac.warwick.cs
"Can't say my name's well-known, you don't see my face in Rolling Stone (yet)"
------------------------------------------------------------------------------

lm@snafu.Sun.COM (Larry McVoy) (03/08/89)

In article <1449@ubu.warwick.UUCP> mirk@uk.ac.warwick.cs (Mike Taylor) writes:
>It's kinda sad to see how the minimal set of low-level routines in
>primitive UNICES has mushroomed to the incredible 178 distinct system
>calls that our current UNIX (SunOS 4.3, in fact) seems to find
>necessary.

Umm, this is a bit naive.  Granted, I'm working at Sun at the moment, but 
those of you who remember my screaming and yelling about the size of the
SunOS kernel will realize that I tend to speak my mind without letting
any corporation's feelings get in the way.  Anyway, counting system calls
is bogus, completely bogus.  You need to count syscalls & ioctls.  ioctls()
bop right down into the kernel too, you know.  AT&T adds ioctls like 
there is no tomorrow.

I'm not saying that the kernel isn't too big, in fact I agree completely 
if that is the poster's point.  I am saying that it is naive to simply 
count system calls.  It's a lot more than 178; Unix is corporate software.

Larry McVoy, Lachman Associates.			...!sun!lm or lm@sun.com

kerchen@iris.ucdavis.edu (Paul Kerchen) (03/08/89)

At the request of several people, here's a brief list of reasons supporting 
the need for syscall(2).  For those who are tired of this discussion,
hit 'n' now! :-}



Compelling reasons for the use of syscall(2):

1) Changing the functionality of a system call, keeping track of the number
	of times a call is made, or intervening before a call is made.
2) Testing new system calls before adding them to the kernel.
3) Simulating system calls.
4) Backwards compatibility to phased-out system calls (eg. stty vs. ioctl).
5) Certain other, specific applications.

Note: On some OS's (like SunOS), syscall(2) is just another function, while
on others (like Ultrix V2.2), syscall(2) is the only mechanism for making
system calls (ie. all other calls eventually call syscall(2) to do the actual
call).  Therefore, syscall(2) really is a necessity for some systems.  For
a more verbose listing of reasons, send me e-mail and I'll send you a 
trimmed down concatenation of all the responses I've received (provided
the mailer doesn't bounce 'em).  That is, I'll send you a list of verbatim 
responses without all of the extra header junk.




Paul Kerchen				| kerchen@iris.ucdavis.edu

gwyn@smoke.BRL.MIL (Doug Gwyn ) (03/08/89)

In article <1449@ubu.warwick.UUCP> mirk@uk.ac.warwick.cs (Mike Taylor) writes:
>Ask yourself how *that* ties in with this apalling move?

IT HAS NOTHING TO DO WITH IT.

It's also not an "appalling move".  In fact it is designed to make it
possible to port C applications around between widely different types
of operating systems, something that is problematic if each system's
C environment be allowed to preempt names from the application for its
own use.

In a UNIX implementation of C, I would expect that you could still get
at the open() system call by that name.  However, the portable C library
must not use that name if it could accidentally be linked so that an
application-provided function named open() would be used where a system
call interface is expected by the library implementation.  Thus the need
for the library to be implemented using calls to names outside the
application's name space, e.g. __open().

boyd@necisa.necisa.oz (Boyd Roberts) (03/16/89)

This discussion is really getting beyond the pale.  The _correct_
evaluation is probably three-fold:

   1.  In V[67] there was such a feature which worked out the
       system call from the byte following the trap instruction.

       From a historical perspective such functionality was turned
       into a library routine.

   2.  Portability in some bizzare sense.  Although, by rights there
       should be a function for every system call you'd need to make.

   3.  A simple mechanisam for adding system calls without having to
       mess with libc.  Useful for debugging during kernel development.


Now, enough!  Desist!  Stop!


Boyd Roberts			NEC Information Systems Australia

boyd@necisa.necisa.oz

``When the going gets wierd, the weird turn pro...''

friedl@vsi.COM (Stephen J. Friedl) (03/20/89)

In article <807@necisa.necisa.oz>, boyd@necisa.necisa.oz (Boyd Roberts) writes:
> This discussion is really getting beyond the pale.  The _correct_
> evaluation is probably three-fold:

There's another one.  I recally from a V7 man page (From the Onyx, RIP)
talking about syscall that it was implemented so pure-text programs could
do variable system calls without needing to write to their own text
space.

     Steve

-- 
Stephen J. Friedl / V-Systems, Inc. / Santa Ana, CA / +1 714 545 6442 
3B2-kind-of-guy   / friedl@vsi.com  / {attmail, uunet, etc}!vsi!friedl

"I think, therefore I'm a yam." - me

rbj@dsys.icst.nbs.gov (Root Boy Jim) (04/06/89)

? From: Doug Gwyn  <gwyn@smoke.brl.mil>
? Date: 28 Feb 89 04:48:24 GMT

? In article <2292@unmvax.unm.edu> lee@doc.cs.unm.edu () writes:
? -In article <9742@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
? ->In article <3740@ucdavis.ucdavis.edu> kerchen@iris.ucdavis.edu (Paul Kerchen) writes:
? ->>Is the system call "syscall()" necessary?
? ->I don't even think it's particularly useful these days; ...
? -It still has uses...
? -	exit (syscall(RESUBA, atoi(argv[1])));

? Only because Berkeley neglected to provide a resuba() hook in
? the C library!  Given direct hooks in the library for all system
? calls, I know of no real requirement for the syscall() function.

You may be correct in the specific case of what you just said, but
the general case is more like asking whether pointers to functions
are desirable in C or whether "funcall" or "apply" is useful in LISP.

Also note that VMS has (or at least RSX has) an indirect format of
their system call.

	Catman Rshd <rbj@nav.icst.nbs.gov>
	Author of "The Daemonic Versions"