* Copyright (c) 1982, 1986, 1989, 1990, 1991 Regents of the University
* of California. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* from: @(#)kern_prot.c 7.21 (Berkeley) 5/3/91
* $Id: kern_prot.c,v 1.5 1993/12/19 00:51:29 wollman Exp $
* System calls related to processes and protection
retval
[1] = p
->p_pptr
->p_pid
;
*retval
= p
->p_pptr
->p_pid
;
/* Get process group ID; note that POSIX getpgrp takes no parameter */
*retval
= p
->p_pgrp
->pg_id
;
*retval
= p
->p_cred
->p_ruid
;
retval
[1] = p
->p_ucred
->cr_uid
;
*retval
= p
->p_ucred
->cr_uid
;
*retval
= p
->p_cred
->p_rgid
;
retval
[1] = p
->p_ucred
->cr_groups
[0];
* Get effective group ID. The "egid" is groups[0], and could be obtained
* via getgroups. This syscall exists because it is somewhat painful to do
* correctly in a library function.
*retval
= p
->p_ucred
->cr_groups
[0];
int *gidset
; /* XXX not yet POSIX */
getgroups(p
, uap
, retval
)
register struct getgroups_args
*uap
;
register struct pcred
*pc
= p
->p_cred
;
if ((ngrp
= uap
->gidsetsize
) == 0) {
*retval
= pc
->pc_ucred
->cr_ngroups
;
if (ngrp
< pc
->pc_ucred
->cr_ngroups
)
ngrp
= pc
->pc_ucred
->cr_ngroups
;
for (gp
= pc
->pc_ucred
->cr_groups
, lp
= groups
; lp
< &groups
[ngrp
]; )
if (error
= copyout((caddr_t
)groups
, (caddr_t
)uap
->gidset
,
ngrp
* sizeof (groups
[0])))
if (p
->p_pgid
== p
->p_pid
|| pgfind(p
->p_pid
)) {
enterpgrp(p
, p
->p_pid
, 1);
* set process group (setpgid/old setpgrp)
* caller does setpgid(targpid, targpgid)
* pid must be caller or child of caller (ESRCH)
* pid must be in same session (EPERM)
* pid can't have done an exec (EACCES)
* there must exist some pid in same session having pgid (EPERM)
* pid must not be session leader (EPERM)
int pid
; /* target process id */
int pgid
; /* target pgrp id */
setpgid(curp
, uap
, retval
)
register struct setpgid_args
*uap
;
register struct proc
*targp
; /* target process */
register struct pgrp
*pgrp
; /* target pgrp */
if (uap
->pid
!= 0 && uap
->pid
!= curp
->p_pid
) {
if ((targp
= pfind(uap
->pid
)) == 0 || !inferior(targp
))
if (targp
->p_session
!= curp
->p_session
)
uap
->pgid
= targp
->p_pid
;
else if (uap
->pgid
!= targp
->p_pid
)
if ((pgrp
= pgfind(uap
->pgid
)) == 0 ||
pgrp
->pg_session
!= curp
->p_session
)
enterpgrp(targp
, uap
->pgid
, 0);
register struct pcred
*pc
= p
->p_cred
;
(error
= suser(pc
->pc_ucred
, &p
->p_acflag
)))
* Everything's okay, do it. Copy credentials so other references do
pc
->pc_ucred
= crcopy(pc
->pc_ucred
);
pc
->pc_ucred
->cr_uid
= uid
;
struct seteuid_args
*uap
;
register struct pcred
*pc
= p
->p_cred
;
if (euid
!= pc
->p_ruid
&& euid
!= pc
->p_svuid
&&
(error
= suser(pc
->pc_ucred
, &p
->p_acflag
)))
* Everything's okay, do it. Copy credentials so other references do
pc
->pc_ucred
= crcopy(pc
->pc_ucred
);
pc
->pc_ucred
->cr_uid
= euid
;
register struct pcred
*pc
= p
->p_cred
;
if (gid
!= pc
->p_rgid
&& (error
= suser(pc
->pc_ucred
, &p
->p_acflag
)))
pc
->pc_ucred
= crcopy(pc
->pc_ucred
);
pc
->pc_ucred
->cr_groups
[0] = gid
;
struct setegid_args
*uap
;
register struct pcred
*pc
= p
->p_cred
;
if (egid
!= pc
->p_rgid
&& egid
!= pc
->p_svgid
&&
(error
= suser(pc
->pc_ucred
, &p
->p_acflag
)))
pc
->pc_ucred
= crcopy(pc
->pc_ucred
);
pc
->pc_ucred
->cr_groups
[0] = egid
;
osetreuid(p
, uap
, retval
)
struct osetreuid_args
*uap
;
register struct pcred
*pc
= p
->p_cred
;
struct seteuid_args e_args
;
* Most calls to setreuid() are done in order to swap real and
* effective uids. In old versions of BSD, this was the only
* way to temporarily renounce privileges and be able to get
* them back. In the presence of the POSIX saved id, however,
* we can do this without modifying the real uid, which could have
* opened up a security hole. So, we implement this: when the user
* attempts to set its real uid, we just check to make sure
* that they will be able to seteuid() back to that id at some
* later time, but don't actually change the real uid.
* Logic taken from 4.4BSD.
if(uap
->ruid
!= -1 && uap
->ruid
!= pc
->p_ruid
&& uap
->ruid
!= pc
->p_svuid
) {
return seteuid(p
, &e_args
, retval
);
osetregid(p
, uap
, retval
)
struct osetregid_args
*uap
;
register struct pcred
*pc
= p
->p_cred
;
struct setegid_args e_args
;
* Same comments as for setreuid() apply here.
&& uap
->rgid
!= pc
->p_rgid
&& uap
->rgid
!= pc
->p_svgid
) {
return setegid(p
, &e_args
, retval
);
setgroups(p
, uap
, retval
)
struct setgroups_args
*uap
;
register struct pcred
*pc
= p
->p_cred
;
int error
, groups
[NGROUPS
];
if (error
= suser(pc
->pc_ucred
, &p
->p_acflag
))
if ((ngrp
= uap
->gidsetsize
) > NGROUPS
)
if (error
= copyin((caddr_t
)uap
->gidset
, (caddr_t
)groups
,
ngrp
* sizeof (groups
[0])))
pc
->pc_ucred
= crcopy(pc
->pc_ucred
);
pc
->pc_ucred
->cr_ngroups
= ngrp
;
/* convert from int's to gid_t's */
for (gp
= pc
->pc_ucred
->cr_groups
, lp
= groups
; ngrp
--; )
* Check if gid is a member of the group set.
register struct ucred
*cred
;
egp
= &(cred
->cr_groups
[cred
->cr_ngroups
]);
for (gp
= cred
->cr_groups
; gp
< egp
; gp
++)
* Test whether the specified credentials imply "super-user"
* privilege; if so, and we have accounting info, set the flag
* indicating use of super-powers.
* Allocate a zeroed cred structure.
register struct ucred
*cr
;
MALLOC(cr
, struct ucred
*, sizeof(*cr
), M_CRED
, M_WAITOK
);
bzero((caddr_t
)cr
, sizeof(*cr
));
* Throws away space when ref count gets to 0.
int s
= splimp(); /* ??? XXX FIXME */
FREE((caddr_t
)cr
, M_CRED
);
* Copy cred structure to a new one and free the old one.
* Dup cred struct to a new held one.
* Get login name, if available.
struct getlogin_args
*uap
;
if (uap
->namelen
> sizeof (p
->p_pgrp
->pg_session
->s_login
))
uap
->namelen
= sizeof (p
->p_pgrp
->pg_session
->s_login
);
return (copyout((caddr_t
) p
->p_pgrp
->pg_session
->s_login
,
(caddr_t
) uap
->namebuf
, uap
->namelen
));
struct setlogin_args
*uap
;
if (error
= suser(p
->p_ucred
, &p
->p_acflag
))
error
= copyinstr((caddr_t
) uap
->namebuf
,
(caddr_t
) p
->p_pgrp
->pg_session
->s_login
,
sizeof (p
->p_pgrp
->pg_session
->s_login
) - 1, (u_int
*)0);
if (error
== ENAMETOOLONG
)