Return to BSD News archive
Newsgroups: comp.os.386bsd.development
Path: sserve!newshost.anu.edu.au!munnari.oz.au!news.Hawaii.Edu!ames!haven.umd.edu!darwin.sura.net!sgiblab!majipoor.cygnus.com!kithrup.com!sef
From: sef@kithrup.com (Sean Eric Fagan)
Subject: eaccess() system call
Organization: Kithrup Enterprises, Ltd.
Message-ID: <CA9zvs.82J@kithrup.com>
Date: Fri, 16 Jul 1993 21:04:25 GMT
Lines: 216
I saw a discussion about making ash handle multiple groups correctly
(in determining whether a file could be executed or not), and was
appalled, since it was, basicly, replicating code that was already in
the kernel -- sorta, since access() uses real user and group id's, but
a shell only needs to care about the effective id's.
So, I decided to write eaccess(), which is exactly like access(), only
it uses the effective id's. When I did so, I found three more files
that were missing from the 386BSD distribution, al in /sys/kern:
syscalls.master, makesyscalls.sh, and Makefile. I've let both the
NetBSD and interim groups know about this, so the missing files should
be in the next release. In the meanwhile, you can get them from any
archive site that has net/2.
Anyway, for anyone who really cares, here's eaccess(), and some patches
to /bin/sh to make it use it. The NetBSD folks don't want it, I haven't
heard back from the 4.4 folks, and I have offered it to the interim
folks :). But, if nothing else, it can serve as an example of how to
add a system call to *bsd.
Enjoy.
*** sys.386bsd/kern/vfs_syscalls.c.~1~ Sat May 16 20:22:16 1992
--- sys.386bsd/kern/vfs_syscalls.c Wed Jul 14 21:41:20 1993
***************
*** 969,975 ****
/*
* Check access permissions.
*/
! /* ARGSUSED */
saccess(p, uap, retval)
struct proc *p;
register struct args {
--- 969,989 ----
/*
* Check access permissions.
*/
!
! eaccess(p, uap, retval)
! struct proc *p;
! register struct args {
! char *fname;
! int fmode;
! } *uap;
! int *retval;
! {
! int error;
!
! error = saccess1(p, uap, retval);
! return error;
! }
!
saccess(p, uap, retval)
struct proc *p;
register struct args {
***************
*** 978,994 ****
} *uap;
int *retval;
{
register struct nameidata *ndp;
register struct ucred *cred = p->p_ucred;
register struct vnode *vp;
! int error, mode, svuid, svgid;
struct nameidata nd;
ndp = &nd;
- svuid = cred->cr_uid;
- svgid = cred->cr_groups[0];
- cred->cr_uid = p->p_cred->p_ruid;
- cred->cr_groups[0] = p->p_cred->p_rgid;
ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
ndp->ni_segflg = UIO_USERSPACE;
ndp->ni_dirp = uap->fname;
--- 992,1025 ----
} *uap;
int *retval;
{
+ int error;
+ int svuid = p->p_ucred->cr_uid;
+ int svgid = p->p_ucred->cr_groups[0];
+
+ p->p_ucred->cr_uid = p->p_cred->p_ruid;
+ p->p_ucred->cr_groups[0] = p->p_cred->p_rgid;
+ error = saccess1(p, uap, retval);
+ p->p_ucred->cr_uid = svuid;
+ p->p_ucred->cr_groups[0] = svgid;
+ return error;
+ }
+
+ /* ARGSUSED */
+ saccess1(p, uap, retval)
+ struct proc *p;
+ register struct args {
+ char *fname;
+ int fmode;
+ } *uap;
+ int *retval;
+ {
register struct nameidata *ndp;
register struct ucred *cred = p->p_ucred;
register struct vnode *vp;
! int error, mode;
struct nameidata nd;
ndp = &nd;
ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
ndp->ni_segflg = UIO_USERSPACE;
ndp->ni_dirp = uap->fname;
***************
*** 1011,1018 ****
}
vput(vp);
out1:
- cred->cr_uid = svuid;
- cred->cr_groups[0] = svgid;
return (error);
}
--- 1042,1047 ----
*** sys.386bsd/kern/syscalls.master.~1~ Tue Jul 13 19:48:26 1993
--- sys.386bsd/kern/syscalls.master Wed Jul 14 14:49:21 1993
***************
*** 114,120 ****
78 STD 3 mincore
79 STD 2 getgroups
80 STD 2 setgroups
! 81 STD 0 getpgrp
82 STD 2 setpgid
83 STD 3 setitimer
84 COMPAT 0 wait
--- 114,120 ----
78 STD 3 mincore
79 STD 2 getgroups
80 STD 2 setgroups
! 81 STD 1 getpgrp
82 STD 2 setpgid
83 STD 3 setitimer
84 COMPAT 0 wait
*** lib/libc/sys/Makefile.inc.~1~ Wed Feb 12 23:42:44 1992
--- lib/libc/sys/Makefile.inc Wed Jul 14 17:29:42 1993
***************
*** 11,17 ****
# modules with default implementations on all architectures:
ASM= accept.o access.o acct.o adjtime.o async_daemon.o bind.o chdir.o \
chflags.o chmod.o chown.o chroot.o close.o connect.o dup.o dup2.o \
! execve.o fchdir.o fchflags.o fchmod.o fchown.o fcntl.o flock.o \
fstat.o fstatfs.o fsync.o ftruncate.o getdirentries.o \
getdtablesize.o getegid.o geteuid.o getfh.o getfsstat.o getgid.o \
getgroups.o gethostid.o gethostname.o getitimer.o getkerninfo.o \
--- 11,17 ----
# modules with default implementations on all architectures:
ASM= accept.o access.o acct.o adjtime.o async_daemon.o bind.o chdir.o \
chflags.o chmod.o chown.o chroot.o close.o connect.o dup.o dup2.o \
! eaccess.o execve.o fchdir.o fchflags.o fchmod.o fchown.o fcntl.o flock.o \
fstat.o fstatfs.o fsync.o ftruncate.o getdirentries.o \
getdtablesize.o getegid.o geteuid.o getfh.o getfsstat.o getgid.o \
getgroups.o gethostid.o gethostname.o getitimer.o getkerninfo.o \
*** bin/sh/exec.c.~1~ Mon Apr 15 17:22:50 1991
--- bin/sh/exec.c Wed Jul 14 22:52:49 1993
***************
*** 66,71 ****
--- 66,72 ----
#include "mystring.h"
#include <sys/types.h>
#include <sys/stat.h>
+ #include <unistd.h>
#include <fcntl.h>
#include <errno.h>
***************
*** 459,464 ****
--- 460,473 ----
TRACE(("searchexec \"%s\": no change\n", name));
goto success;
}
+ #if 1
+ while (eaccess(fullname, X_OK) < 0) {
+ if (errno != ENOENT && errno != ENOTDIR)
+ e = errno;
+ goto loop;
+ }
+ e = EACCES;
+ #else
while (stat(fullname, &statb) < 0) {
#ifdef SYSV
if (errno == EINTR)
***************
*** 471,476 ****
--- 480,486 ----
e = EACCES; /* if we fail, this will be the error */
if ((statb.st_mode & S_IFMT) != S_IFREG)
goto loop;
+ #endif
if (pathopt) { /* this is a %func directory */
stalloc(strlen(fullname) + 1);
readcmdfile(fullname);
***************
*** 479,484 ****
--- 489,495 ----
stunalloc(fullname);
goto success;
}
+ #if 0
if (statb.st_uid == geteuid()) {
if ((statb.st_mode & 0100) == 0)
goto loop;
***************
*** 489,494 ****
--- 500,506 ----
if ((statb.st_mode & 01) == 0)
goto loop;
}
+ #endif
TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
INTOFF;
cmdp = cmdlookup(name, 1);