Page MenuHomeFreeBSD

D18930.id53110.diff
No OneTemporary

D18930.id53110.diff

Index: include/pthread_np.h
===================================================================
--- include/pthread_np.h
+++ include/pthread_np.h
@@ -71,6 +71,9 @@
int pthread_switch_add_np(pthread_switch_routine_t);
int pthread_switch_delete_np(pthread_switch_routine_t);
int pthread_timedjoin_np(pthread_t, void **, const struct timespec *);
+int pthread_getcred_np(uid_t *, int *, gid_t *);
+int pthread_setcred_np(uid_t , int , gid_t *);
+int pthread_revertcred_np(void);
__END_DECLS
#endif
Index: include/unistd.h
===================================================================
--- include/unistd.h
+++ include/unistd.h
@@ -585,6 +585,9 @@
int undelete(const char *);
int unwhiteout(const char *);
void *valloc(size_t); /* obsoleted by malloc() */
+int setcred(uid_t, int, const gid_t *);
+int getcred(uid_t *, int *, gid_t *);
+int revertcred(void);
#ifndef _OPTRESET_DECLARED
#define _OPTRESET_DECLARED
Index: lib/libc/include/namespace.h
===================================================================
--- lib/libc/include/namespace.h
+++ lib/libc/include/namespace.h
@@ -138,6 +138,7 @@
#define pthread_getaffinity_np _pthread_getaffinity_np
#define pthread_getconcurrency _pthread_getconcurrency
#define pthread_getcpuclockid _pthread_getcpuclockid
+#define pthread_getcred_np _pthread_getcred_np
#define pthread_getprio _pthread_getprio
#define pthread_getschedparam _pthread_getschedparam
#define pthread_getspecific _pthread_getspecific
@@ -172,6 +173,7 @@
#define pthread_once _pthread_once
#define pthread_resume_all_np _pthread_resume_all_np
#define pthread_resume_np _pthread_resume_np
+#define pthread_revertcred_np _pthread_revertcred_np
#define pthread_rwlock_destroy _pthread_rwlock_destroy
#define pthread_rwlock_init _pthread_rwlock_init
#define pthread_rwlock_rdlock _pthread_rwlock_rdlock
@@ -191,6 +193,7 @@
#define pthread_setcancelstate _pthread_setcancelstate
#define pthread_setcanceltype _pthread_setcanceltype
#define pthread_setconcurrency _pthread_setconcurrency
+#define pthread_setcred_np _pthread_setcred_np
#define pthread_setprio _pthread_setprio
#define pthread_setschedparam _pthread_setschedparam
#define pthread_setspecific _pthread_setspecific
Index: lib/libc/include/un-namespace.h
===================================================================
--- lib/libc/include/un-namespace.h
+++ lib/libc/include/un-namespace.h
@@ -119,6 +119,7 @@
#undef pthread_getaffinity_np
#undef pthread_getconcurrency
#undef pthread_getcpuclockid
+#undef pthread_getcred_np
#undef pthread_getprio
#undef pthread_getschedparam
#undef pthread_getspecific
@@ -153,6 +154,7 @@
#undef pthread_once
#undef pthread_resume_all_np
#undef pthread_resume_np
+#undef pthread_revertcred_np
#undef pthread_rwlock_destroy
#undef pthread_rwlock_init
#undef pthread_rwlock_rdlock
@@ -172,6 +174,7 @@
#undef pthread_setcancelstate
#undef pthread_setcanceltype
#undef pthread_setconcurrency
+#undef pthread_setcred_np
#undef pthread_setprio
#undef pthread_setschedparam
#undef pthread_setspecific
Index: lib/libc/sys/Makefile.inc
===================================================================
--- lib/libc/sys/Makefile.inc
+++ lib/libc/sys/Makefile.inc
@@ -297,6 +297,7 @@
semget.2 \
semop.2 \
send.2 \
+ setcred.2 \
setfib.2 \
sendfile.2 \
setgroups.2 \
@@ -463,6 +464,8 @@
select.2 FD_ZERO.3
MLINKS+=send.2 sendmsg.2 \
send.2 sendto.2
+MLINKS+=setcred.2 getcred.2 \
+ setcred.2 revertcred.2
MLINKS+=setpgid.2 setpgrp.2
MLINKS+=setresuid.2 getresgid.2 \
setresuid.2 getresuid.2 \
Index: lib/libc/sys/Symbol.map
===================================================================
--- lib/libc/sys/Symbol.map
+++ lib/libc/sys/Symbol.map
@@ -406,6 +406,9 @@
fhlinkat;
fhreadlink;
getfhat;
+ getcred;
+ setcred;
+ revertcred;
};
FBSDprivate_1.0 {
Index: lib/libc/sys/setcred.2
===================================================================
--- /dev/null
+++ lib/libc/sys/setcred.2
@@ -0,0 +1,118 @@
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 2019 Gandi
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 23, 2019
+.Dt SETCRED 2
+.Os
+.Sh NAME
+.Nm setcred ,
+.Nm getcred ,
+.Nm revertcred
+.Nd control per-thread user credentials
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.In sys/param.h
+.Ft int
+.Fn setcred "uid_t uid" "int gidsetlen" "const gid_t *gidset"
+.Ft int
+.Fn getcred "uid_t *uid" "int *gidsetlen" "const gid_t *gidset"
+.Ft int
+.Fn revertcred "void"
+.Sh Description
+The
+.Fn setcred
+system call sets the real, effective, and saved UIDs and GIDs,
+along with supplementary group access list of the current thread.
+.Pp
+The
+.Fa uid
+parameter can be any UID. The
+.Fa gidsetlen
+parameter indicates the number of entries in the array and must be no more
+than NGROUPS. The
+.Fa gidset
+parameter is an array of GIDs, the first being the primary GID to set.
+This call will replace all supplementary groups in the credential.
+.Pp
+The
+.Fn getcred
+system call retrieves the real user ID of the calling thread and stores it in
+.Fa uid .
+It also retrieves the current group access list of the calling thread and
+stores it in
+.Fa gidset .
+The gidsetlen argument indicates the number of entries that may be placed in
+gidset.
+.Pp
+The
+.Fn getcred
+system call sets this variable to the actual number of groups returned in
+gidset, even on error.
+.Pp
+The
+.Fn revertcred
+system call reverts the thread's credential, including the real, effective and
+saved UIDs and GIDs, to the per-process credential.
+.Pp
+These system calls may only be called if the process has super-user privileges.
+.Sh RETURN VALUES
+.Rv -std
+.Sh ERRORS
+The
+.Fn revertcred
+system call will only fail if:
+.Bl -tag -width Er
+.It Bq Er EPERM
+The user is not the super user.
+.El
+.Pp
+In addition to the error returned by
+.Fn revertcred ,
+the
+.Fn setcred
+and
+.Fn getcred
+system calls may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value of
+.Fa gidsetlen
+is not valid.
+.It Bq Er ENOENT
+The per-thread credential has not yet been explicitly set with
+.Fn setcred ,
+or it has been reverted with
+.Fn revertcred .
+.It Bq Er ERANGE
+The incoming
+.Fa gidsetlen
+is less than the number of groups in the credential.
+.It Bq Er EFAULT
+One of the parameters points to an invalid address.
+.El
Index: lib/libthr/pthread.map
===================================================================
--- lib/libthr/pthread.map
+++ lib/libthr/pthread.map
@@ -325,3 +325,9 @@
FBSD_1.5 {
pthread_get_name_np;
};
+
+FBSD_1.6 {
+ pthread_getcred_np;
+ pthread_setcred_np;
+ pthread_revertcred_np;
+};
Index: lib/libthr/thread/Makefile.inc
===================================================================
--- lib/libthr/thread/Makefile.inc
+++ lib/libthr/thread/Makefile.inc
@@ -14,6 +14,7 @@
thr_cond.c \
thr_condattr.c \
thr_create.c \
+ thr_cred_np.c \
thr_ctrdtr.c \
thr_detach.c \
thr_equal.c \
Index: lib/libthr/thread/thr_cred_np.c
===================================================================
--- /dev/null
+++ lib/libthr/thread/thr_cred_np.c
@@ -0,0 +1,58 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2018 Gandi
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <unistd.h>
+#include <pthread.h>
+#include <pthread_np.h>
+#include "un-namespace.h"
+
+__weak_reference(_pthread_getcred_np, pthread_getcred_np);
+__weak_reference(_pthread_setcred_np, pthread_setcred_np);
+__weak_reference(_pthread_revertcred_np, pthread_revertcred_np);
+
+int _pthread_getcred_np(uid_t *uid, int *gidsetlen, gid_t *gidset)
+{
+
+ return (getcred(uid, gidsetlen, gidset));
+}
+
+int _pthread_setcred_np(uid_t uid, int gidsetlen, gid_t *gidset)
+{
+
+ return (setcred(uid, gidsetlen, gidset));
+}
+
+int _pthread_revertcred_np(void)
+{
+
+ return (revertcred());
+}
Index: share/man/man3/Makefile
===================================================================
--- share/man/man3/Makefile
+++ share/man/man3/Makefile
@@ -275,6 +275,7 @@
pthread_rwlock_wrlock.3 \
pthread_schedparam.3 \
pthread_self.3 \
+ pthread_setcred_np.3 \
pthread_set_name_np.3 \
pthread_setspecific.3 \
pthread_sigmask.3 \
@@ -339,6 +340,8 @@
PTHREAD_MLINKS+=pthread_rwlock_wrlock.3 pthread_rwlock_trywrlock.3
PTHREAD_MLINKS+=pthread_schedparam.3 pthread_getschedparam.3 \
pthread_schedparam.3 pthread_setschedparam.3
+PTHREAD_MLINKS+=pthread_setcred_np.3 pthread_getcred_np.3 \
+ pthread_setcred_np.3 pthread_revertcred_np.3
PTHREAD_MLINKS+=pthread_set_name_np.3 pthread_get_name_np.3
PTHREAD_MLINKS+=pthread_spin_init.3 pthread_spin_destroy.3 \
pthread_spin_lock.3 pthread_spin_trylock.3 \
Index: share/man/man3/pthread_setcred_np.3
===================================================================
--- /dev/null
+++ share/man/man3/pthread_setcred_np.3
@@ -0,0 +1,124 @@
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 2019 Gandi
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 23, 2019
+.Dt pthread_setcred_np 3
+.Os
+.Sh NAME
+.Nm pthread_setcred_np ,
+.Nm pthread_getcred_np ,
+.Nm pthread_revertcred_np
+.Nd control per-thread user credentials
+.Sh LIBRARY
+.Lb libpthread
+.Sh SYNOPSIS
+.In pthread_np.h
+.In sys/param.h
+.Ft int
+.Fn pthread_setcred_np "uid_t uid" "int gidsetlen" "const gid_t *gidset"
+.Ft int
+.Fn pthread_getcred_np "uid_t *uid" "int *gidsetlen" "const gid_t *gidset"
+.Ft int
+.Fn pthread_revertcred_np "void"
+.Sh Description
+The
+.Fn pthread_setcred_np
+function sets the real, effective, and saved UIDs and GIDs,
+along with supplementary group access list of the current thread.
+.Pp
+The
+.Fa uid
+parameter can be any UID. The
+.Fa gidsetlen
+parameter indicates the number of entries in the array and must be no more
+than NGROUPS. The
+.Fa gidset
+parameter is an array of GIDs, the first being the primary GID to set.
+This call will replace all supplementary groups in the credential.
+.Pp
+The
+.Fn pthread_getcred_np
+function retrieves the real user ID of the calling thread and stores it in
+.Fa uid .
+It also retrieves the current group access list of the calling thread and
+stores it in
+.Fa gidset .
+The gidsetlen argument indicates the number of entries that may be placed in
+gidset.
+.Pp
+The
+.Fn pthread_getcred_np
+sets this variable to the actual number of groups returned in
+gidset, even on error.
+.Pp
+The
+.Fn pthread_revertcred_np
+function reverts the thread's credential, including the real, effective and
+saved UIDs and GIDs, to the per-process credential.
+.Pp
+These functions may only be called if the process has super-user privileges.
+.Sh RETURN VALUES
+.Rv -std
+.Sh ERRORS
+The
+.Fn pthread_revertcred_np
+function will only fail if:
+.Bl -tag -width Er
+.It Bq Er EPERM
+The user is not the super user.
+.El
+.Pp
+In addition to the error returned by
+.Fn pthread_revertcred_np ,
+the
+.Fn pthread_setcred_np
+and
+.Fn pthread_getcred_np
+functions calls may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value of
+.Fa gidsetlen
+is not valid.
+.It Bq Er ENOENT
+The per-thread credential has not yet been explicitly set with
+.Fn pthread_setcred_np ,
+or it has been reverted with
+.Fn pthread_revertcred_np .
+.It Bq Er ERANGE
+The incoming
+.Fa gidsetlen
+is less than the number of groups in the credential.
+.It Bq Er EFAULT
+One of the parameters points to an invalid address.
+.El
+.Sh STANDARDS
+These functions are non standard extensions.
+.Sh SEE ALSO
+.Xr setcred 2 ,
+.Xr getcred 2 ,
+.Xr revertcred 2 ,
Index: share/man/man9/Makefile
===================================================================
--- share/man/man9/Makefile
+++ share/man/man9/Makefile
@@ -2095,8 +2095,7 @@
timeout.9 callout_stop.9 \
timeout.9 callout_when.9 \
timeout.9 untimeout.9
-MLINKS+=ucred.9 cred_update_thread.9 \
- ucred.9 crcopy.9 \
+MLINKS+=ucred.9 crcopy.9 \
ucred.9 crcopysafe.9 \
ucred.9 crdup.9 \
ucred.9 crfree.9 \
Index: share/man/man9/ucred.9
===================================================================
--- share/man/man9/ucred.9
+++ share/man/man9/ucred.9
@@ -36,8 +36,7 @@
.Nm crfree ,
.Nm crcopy ,
.Nm crdup ,
-.Nm cru2x ,
-.Nm cred_update_thread
+.Nm cru2x
.Nd "functions related to user credentials"
.Sh SYNOPSIS
.In sys/param.h
@@ -58,8 +57,6 @@
.Fn crsetgroups "struct ucred *cr" "int ngrp" "gid_t *groups"
.Ft void
.Fn cru2x "struct ucred *cr" "struct xucred *xcr"
-.Ft void
-.Fn cred_update_thread "struct thread *td"
.Sh DESCRIPTION
The
.Nm
@@ -146,12 +143,6 @@
the former
(e.g.,
.Va cr_version ) .
-.Pp
-The
-.Fn cred_update_thread
-function sets the credentials of
-.Fa td
-to that of its process, freeing its old credential if required.
.Sh RETURN VALUES
.Fn crget ,
.Fn crhold ,
Index: sys/bsm/audit_kevents.h
===================================================================
--- sys/bsm/audit_kevents.h
+++ sys/bsm/audit_kevents.h
@@ -644,6 +644,9 @@
#define AUE_SETLOGINCLASS 43238 /* FreeBSD-specific. */
#define AUE_POSIX_FADVISE 43239 /* FreeBSD-specific. */
#define AUE_SCTP_GENERIC_SENDMSG_IOV 43240 /* FreeBSD-specific. */
+#define AUE_GETCRED 43263 /* FreeBSD-specific. */
+#define AUE_SETCRED 43264 /* FreeBSD-specific. */
+#define AUE_REVERTCRED 43265 /* FreeBSD-specific. */
/*
* Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the
Index: sys/compat/freebsd32/syscalls.master
===================================================================
--- sys/compat/freebsd32/syscalls.master
+++ sys/compat/freebsd32/syscalls.master
@@ -1145,5 +1145,10 @@
const char *to); }
567 AUE_NULL NOPROTO { int fhreadlink( struct fhandle *fhp, char *buf, \
size_t bufsize); }
+568 AUE_SETCRED NOPROTO { int setcred( uid_t uid, int gidsetlen, \
+ const gid_t *gidset); }
+569 AUE_GETCRED NOPROTO { int getcred( uid_t *uid, int *gidsetlen, \
+ gid_t *gidset); }
+570 AUE_REVERTCRED NOPROTO { int revertcred(void); }
; vim: syntax=off
Index: sys/ddb/db_ps.c
===================================================================
--- sys/ddb/db_ps.c
+++ sys/ddb/db_ps.c
@@ -257,7 +257,11 @@
void *wchan;
if (all) {
- db_printf("%6d ", td->td_tid);
+ db_printf("%6d ", td->td_tid);
+ if ((td->td_flags & TDP_SUGID) != 0)
+ db_printf("%5d ", td->td_ucred->cr_ruid);
+ else
+ db_printf(" ");
switch (td->td_state) {
case TDS_RUNNING:
snprintf(state, sizeof(state), "Run");
@@ -340,6 +344,7 @@
struct lock_object *lock;
bool comma;
int delta;
+ int i;
/* Determine which thread to examine. */
if (have_addr)
@@ -350,6 +355,15 @@
db_printf("Thread %d at %p:\n", td->td_tid, td);
db_printf(" proc (pid %d): %p\n", td->td_proc->p_pid, td->td_proc);
+ if ((td->td_flags & TDP_SUGID) != 0) {
+ db_printf(" uid: %d gids: ", td->td_ucred->cr_uid);
+ for (i = 0; i < td->td_ucred->cr_ngroups; i++) {
+ db_printf("%d", td->td_ucred->cr_groups[i]);
+ if (i < (td->td_ucred->cr_ngroups - 1))
+ db_printf(", ");
+ }
+ db_printf("\n");
+ }
if (td->td_name[0] != '\0')
db_printf(" name: %s\n", td->td_name);
db_printf(" stack: %p-%p\n", (void *)td->td_kstack,
Index: sys/fs/unionfs/union_subr.c
===================================================================
--- sys/fs/unionfs/union_subr.c
+++ sys/fs/unionfs/union_subr.c
@@ -772,7 +772,7 @@
*/
chgproccnt(cred->cr_ruidinfo, 1, 0);
change_euid(cred, rootinfo);
- change_ruid(cred, rootinfo);
+ change_ruid(cred, rootinfo, 1);
change_svuid(cred, (uid_t)0);
uifree(rootinfo);
cnp->cn_cred = cred;
Index: sys/kern/kern_prot.c
===================================================================
--- sys/kern/kern_prot.c
+++ sys/kern/kern_prot.c
@@ -87,6 +87,11 @@
static void crsetgroups_locked(struct ucred *cr, int ngrp,
gid_t *groups);
+static int kern_setresuid(struct thread *td,
+ struct ucred *newcred, struct ucred *oldcred,
+ uid_t ruid, uid_t euid, uid_t suid,
+ struct uidinfo *euip, struct uidinfo *ruip,
+ int chgproccnt);
#ifndef _SYS_SYSPROTO_H_
struct getpid_args {
@@ -219,9 +224,9 @@
sys_getuid(struct thread *td, struct getuid_args *uap)
{
- td->td_retval[0] = td->td_ucred->cr_ruid;
+ td->td_retval[0] = td->td_proc->p_ucred->cr_ruid;
#if defined(COMPAT_43)
- td->td_retval[1] = td->td_ucred->cr_uid;
+ td->td_retval[1] = td->td_proc->p_ucred->cr_uid;
#endif
return (0);
}
@@ -236,7 +241,7 @@
sys_geteuid(struct thread *td, struct geteuid_args *uap)
{
- td->td_retval[0] = td->td_ucred->cr_uid;
+ td->td_retval[0] = td->td_proc->p_ucred->cr_uid;
return (0);
}
@@ -250,9 +255,9 @@
sys_getgid(struct thread *td, struct getgid_args *uap)
{
- td->td_retval[0] = td->td_ucred->cr_rgid;
+ td->td_retval[0] = td->td_proc->p_ucred->cr_rgid;
#if defined(COMPAT_43)
- td->td_retval[1] = td->td_ucred->cr_groups[0];
+ td->td_retval[1] = td->td_proc->p_ucred->cr_groups[0];
#endif
return (0);
}
@@ -272,7 +277,7 @@
sys_getegid(struct thread *td, struct getegid_args *uap)
{
- td->td_retval[0] = td->td_ucred->cr_groups[0];
+ td->td_retval[0] = td->td_proc->p_ucred->cr_groups[0];
return (0);
}
@@ -289,7 +294,7 @@
u_int ngrp;
int error;
- cred = td->td_ucred;
+ cred = td->td_proc->p_ucred;
ngrp = cred->cr_ngroups;
if (uap->gidsetsize == 0) {
@@ -538,7 +543,7 @@
* Set the real uid and transfer proc count to new user.
*/
if (uid != oldcred->cr_ruid) {
- change_ruid(newcred, uip);
+ change_ruid(newcred, uip, 1);
setsugid(p);
}
/*
@@ -792,6 +797,8 @@
int
sys_setgroups(struct thread *td, struct setgroups_args *uap)
{
+ struct ucred *newcred, *oldcred;
+ struct proc *p = td->td_proc;
gid_t smallgroups[XU_NGROUPS];
gid_t *groups;
u_int gidsetsize;
@@ -806,38 +813,42 @@
else
groups = smallgroups;
+ newcred = crget();
+ crextend(newcred, gidsetsize);
+ PROC_LOCK(p);
+ oldcred = crcopysafe(p, newcred);
error = copyin(uap->gidset, groups, gidsetsize * sizeof(gid_t));
+ if (error != 0)
+ goto out;
+ error = kern_setgroups(td, newcred, oldcred, gidsetsize, groups);
if (error == 0)
- error = kern_setgroups(td, gidsetsize, groups);
-
+ proc_set_cred(p, newcred);
+out:
+ PROC_UNLOCK(p);
+ crfree(error ? newcred : oldcred);
if (gidsetsize > XU_NGROUPS)
free(groups, M_TEMP);
return (error);
}
int
-kern_setgroups(struct thread *td, u_int ngrp, gid_t *groups)
+kern_setgroups(struct thread *td, struct ucred *newcred, struct ucred *oldcred,
+ u_int ngrp, gid_t *groups)
{
struct proc *p = td->td_proc;
- struct ucred *newcred, *oldcred;
int error;
MPASS(ngrp <= ngroups_max + 1);
AUDIT_ARG_GROUPSET(groups, ngrp);
- newcred = crget();
- crextend(newcred, ngrp);
- PROC_LOCK(p);
- oldcred = crcopysafe(p, newcred);
-
#ifdef MAC
error = mac_cred_check_setgroups(oldcred, ngrp, groups);
if (error)
- goto fail;
+ goto out;
#endif
error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS);
if (error)
- goto fail;
+ goto out;
if (ngrp == 0) {
/*
@@ -851,14 +862,8 @@
crsetgroups_locked(newcred, ngrp, groups);
}
setsugid(p);
- proc_set_cred(p, newcred);
- PROC_UNLOCK(p);
- crfree(oldcred);
- return (0);
-fail:
- PROC_UNLOCK(p);
- crfree(newcred);
+out:
return (error);
}
@@ -906,7 +911,7 @@
setsugid(p);
}
if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
- change_ruid(newcred, ruip);
+ change_ruid(newcred, ruip, 1);
setsugid(p);
}
if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) &&
@@ -1030,10 +1035,45 @@
PROC_LOCK(p);
oldcred = crcopysafe(p, newcred);
+ error = kern_setresuid(td, newcred, oldcred, ruid, euid, suid,
+ euip, ruip, 1);
+ if (error != 0)
+ goto fail;
+ proc_set_cred(p, newcred);
+#ifdef RACCT
+ racct_proc_ucred_changed(p, oldcred, newcred);
+ crhold(newcred);
+#endif
+ PROC_UNLOCK(p);
+#ifdef RCTL
+ rctl_proc_ucred_changed(p, newcred);
+ crfree(newcred);
+#endif
+ uifree(ruip);
+ uifree(euip);
+ crfree(oldcred);
+ return (0);
+
+fail:
+ PROC_UNLOCK(p);
+ uifree(ruip);
+ uifree(euip);
+ crfree(newcred);
+ return (error);
+
+}
+
+static int __always_inline
+kern_setresuid(struct thread *td, struct ucred *newcred, struct ucred *oldcred,
+ uid_t ruid, uid_t euid, uid_t suid,
+ struct uidinfo *euip, struct uidinfo *ruip, int chgproccnt)
+{
+ int error;
+
#ifdef MAC
error = mac_cred_check_setresuid(oldcred, ruid, euid, suid);
if (error)
- goto fail;
+ return (error);
#endif
if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
@@ -1046,42 +1086,22 @@
suid != oldcred->cr_svuid &&
suid != oldcred->cr_uid)) &&
(error = priv_check_cred(oldcred, PRIV_CRED_SETRESUID)) != 0)
- goto fail;
+ return (error);
if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
change_euid(newcred, euip);
- setsugid(p);
+ setsugid(td->td_proc);
}
if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
- change_ruid(newcred, ruip);
- setsugid(p);
+ change_ruid(newcred, ruip, chgproccnt);
+ setsugid(td->td_proc);
}
if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) {
change_svuid(newcred, suid);
- setsugid(p);
+ setsugid(td->td_proc);
}
- proc_set_cred(p, newcred);
-#ifdef RACCT
- racct_proc_ucred_changed(p, oldcred, newcred);
- crhold(newcred);
-#endif
- PROC_UNLOCK(p);
-#ifdef RCTL
- rctl_proc_ucred_changed(p, newcred);
- crfree(newcred);
-#endif
- uifree(ruip);
- uifree(euip);
- crfree(oldcred);
- return (0);
-
-fail:
- PROC_UNLOCK(p);
- uifree(ruip);
- uifree(euip);
- crfree(newcred);
- return (error);
+ return (0);
}
/*
@@ -1169,7 +1189,7 @@
struct ucred *cred;
int error1 = 0, error2 = 0, error3 = 0;
- cred = td->td_ucred;
+ cred = td->td_proc->p_ucred;
if (uap->ruid)
error1 = copyout(&cred->cr_ruid,
uap->ruid, sizeof(cred->cr_ruid));
@@ -1196,7 +1216,7 @@
struct ucred *cred;
int error1 = 0, error2 = 0, error3 = 0;
- cred = td->td_ucred;
+ cred = td->td_proc->p_ucred;
if (uap->rgid)
error1 = copyout(&cred->cr_rgid,
uap->rgid, sizeof(cred->cr_rgid));
@@ -1729,7 +1749,7 @@
/*
* Has the credential of the process changed since the last exec()?
*/
- credentialchanged = (p->p_flag & P_SUGID);
+ credentialchanged = (p->p_flag & P_SUGID || td->td_flags & TDP_SUGID);
/*
* If p's gids aren't a subset, or the uids aren't a subset,
@@ -2219,15 +2239,16 @@
* duration of the call.
*/
void
-change_ruid(struct ucred *newcred, struct uidinfo *ruip)
+change_ruid(struct ucred *newcred, struct uidinfo *ruip, int do_chgproccnt)
{
-
- (void)chgproccnt(newcred->cr_ruidinfo, -1, 0);
+ if (do_chgproccnt != 0)
+ (void)chgproccnt(newcred->cr_ruidinfo, -1, 0);
newcred->cr_ruid = ruip->ui_uid;
uihold(ruip);
uifree(newcred->cr_ruidinfo);
newcred->cr_ruidinfo = ruip;
- (void)chgproccnt(newcred->cr_ruidinfo, 1, 0);
+ if (do_chgproccnt != 0)
+ (void)chgproccnt(newcred->cr_ruidinfo, 1, 0);
}
/*-
@@ -2268,3 +2289,120 @@
newcred->cr_svgid = svgid;
}
+
+/*
+ * Set credentials.
+ */
+#ifndef _SYS_SYSPROTO_H_
+struct setcred_args {
+ uid_t uid;
+ int gidsetlen;
+ const gid_t *gidset;
+};
+#endif
+/* ARGSUSED */
+int
+sys_setcred(struct thread *td, struct setcred_args *uap)
+{
+ struct ucred *newcred, *oldcred;
+ struct uidinfo *uip;
+ gid_t smallgroups[XU_NGROUPS];
+ gid_t *groups;
+ int gidsetlen;
+ int error;
+
+ gidsetlen = uap->gidsetlen;
+ if (gidsetlen > ngroups_max + 1)
+ return (EINVAL);
+ AUDIT_ARG_UID(uap->uid);
+ error = priv_check_cred(td->td_proc->p_ucred, PRIV_CRED_SETUID);
+ if (error != 0)
+ return (error);
+
+ oldcred = td->td_ucred;
+ newcred = crdup(oldcred);
+ crextend(newcred, gidsetlen);
+ uip = uifind(uap->uid);
+ if (gidsetlen > XU_NGROUPS)
+ groups = malloc(gidsetlen * sizeof(gid_t), M_TEMP, M_WAITOK);
+ else
+ groups = smallgroups;
+ error = copyin(uap->gidset, groups, gidsetlen * sizeof(gid_t));
+ if (error != 0)
+ goto out;
+
+ PROC_LOCK(td->td_proc);
+ error = kern_setresuid(td, newcred, td->td_proc->p_ucred, uap->uid,
+ uap->uid, uap->uid, uip, uip, 0);
+ if (error != 0)
+ goto unlock;
+ error = kern_setgroups(td, newcred, td->td_proc->p_ucred, gidsetlen,
+ groups);
+ if (error != 0)
+ goto unlock;
+ td->td_ucred = newcred;
+ td->td_flags |= TDP_SUGID;
+
+unlock:
+ PROC_UNLOCK(td->td_proc);
+out:
+ if (uap->gidsetlen > XU_NGROUPS)
+ free(groups, M_TEMP);
+ uifree(uip);
+ crfree(error ? newcred : oldcred);
+ return (error);
+}
+
+/*
+ * Get credentials.
+ */
+#ifndef _SYS_SYSPROTO_H_
+struct getcred_args {
+ uid_t *uid;
+ int *gidsetlen;
+ gid_t *gidset;
+};
+#endif
+/* ARGSUSED */
+int
+sys_getcred(struct thread *td, struct getcred_args *uap)
+{
+ struct ucred *cred;
+ int error;
+ int gidsetlen;
+
+ error = priv_check_cred(td->td_proc->p_ucred, PRIV_CRED_SETUID);
+ if (error != 0)
+ return (error);
+ if ((td->td_flags & TDP_SUGID) == 0)
+ return (ENOENT);
+ cred = td->td_ucred;
+ error = copyout(&cred->cr_ruid, uap->uid, sizeof(uid_t));
+ if (error != 0)
+ return (error);
+ error = copyin(uap->gidsetlen, &gidsetlen, sizeof(int));
+ if (error != 0)
+ return (error);
+ error = copyout(&cred->cr_ngroups, uap->gidsetlen, sizeof(int));
+ if (error != 0)
+ return (error);
+ else if (gidsetlen < cred->cr_ngroups)
+ return (ERANGE);
+ error = copyout(cred->cr_groups, uap->gidset,
+ cred->cr_ngroups * sizeof(gid_t));
+ return (error);
+}
+
+int
+sys_revertcred(struct thread *td, struct revertcred_args *uap)
+{
+ int error;
+
+ error = priv_check_cred(td->td_proc->p_ucred, PRIV_CRED_SETUID);
+ if (error != 0)
+ return (error);
+ /* We need to untaint the thread to restore the process credentials */
+ td->td_flags &= ~TDP_SUGID;
+ thread_cow_update(td);
+ return (0);
+}
Index: sys/kern/kern_thread.c
===================================================================
--- sys/kern/kern_thread.c
+++ sys/kern/kern_thread.c
@@ -488,7 +488,7 @@
oldcred = NULL;
oldlimit = NULL;
PROC_LOCK(p);
- if (td->td_ucred != p->p_ucred) {
+ if (td->td_ucred != p->p_ucred && (td->td_pflags & TDP_SUGID) == 0) {
oldcred = td->td_ucred;
td->td_ucred = crhold(p->p_ucred);
}
Index: sys/kern/syscalls.master
===================================================================
--- sys/kern/syscalls.master
+++ sys/kern/syscalls.master
@@ -3167,6 +3167,23 @@
size_t bufsize
);
}
+568 AUE_GETCRED STD {
+ int getcred(
+ _Out_ uid_t *uid,
+ _Inout_ int *gidsetlen,
+ _Out_writes_(gidsetlen) gid_t *gidset
+ );
+ }
+569 AUE_SETCRED STD {
+ int setcred(
+ uid_t uid,
+ int gidsetlen,
+ _In_reads_(gidsetlen) const gid_t *gidset
+ );
+ }
+570 AUE_REVERTCRED STD {
+ int revertcred(void);
+ }
; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master
Index: sys/security/audit/audit_bsm.c
===================================================================
--- sys/security/audit/audit_bsm.c
+++ sys/security/audit/audit_bsm.c
@@ -1466,6 +1466,29 @@
}
break;
+ case AUE_SETCRED:
+ if (ARG_IS_VALID(kar, ARG_UID)) {
+ tok = au_to_arg32(1, "uid", ar->ar_arg_uid);
+ kau_write(rec, tok);
+ }
+ if (ARG_IS_VALID(kar, ARG_GROUPSET)) {
+ for(ctr = 0; ctr < ar->ar_arg_groups.gidset_size; ctr++)
+ {
+ tok = au_to_arg32(1, "gidset",
+ ar->ar_arg_groups.gidset[ctr]);
+ kau_write(rec, tok);
+ }
+ }
+ break;
+
+ case AUE_GETCRED:
+ case AUE_REVERTCRED:
+
+ /*
+ * Header, subject, and return tokens added at end.
+ */
+ break;
+
case AUE_SETLOGIN:
if (ARG_IS_VALID(kar, ARG_LOGIN)) {
tok = au_to_text(ar->ar_arg_login);
Index: sys/sys/proc.h
===================================================================
--- sys/sys/proc.h
+++ sys/sys/proc.h
@@ -492,6 +492,7 @@
#define TDP_UIOHELD 0x10000000 /* Current uio has pages held in td_ma */
#define TDP_FORKING 0x20000000 /* Thread is being created through fork() */
#define TDP_EXECVMSPC 0x40000000 /* Execve destroyed old vmspace */
+#define TDP_SUGID 0x80000000 /* Thread is tainted by setcred(2) */
/*
* Reasons that the current thread can not be run yet.
Index: sys/sys/syscallsubr.h
===================================================================
--- sys/sys/syscallsubr.h
+++ sys/sys/syscallsubr.h
@@ -238,7 +238,8 @@
fd_set *fd_ex, struct timeval *tvp, int abi_nfdbits);
int kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags,
struct mbuf *control, enum uio_seg segflg);
-int kern_setgroups(struct thread *td, u_int ngrp, gid_t *groups);
+int kern_setgroups(struct thread *td, struct ucred *newcred,
+ struct ucred *oldcred, u_int ngrp, gid_t *groups);
int kern_setitimer(struct thread *, u_int, struct itimerval *,
struct itimerval *);
int kern_setrlimit(struct thread *, u_int, struct rlimit *);
Index: sys/sys/ucred.h
===================================================================
--- sys/sys/ucred.h
+++ sys/sys/ucred.h
@@ -101,7 +101,7 @@
void change_egid(struct ucred *newcred, gid_t egid);
void change_euid(struct ucred *newcred, struct uidinfo *euip);
void change_rgid(struct ucred *newcred, gid_t rgid);
-void change_ruid(struct ucred *newcred, struct uidinfo *ruip);
+void change_ruid(struct ucred *newcred, struct uidinfo *ruip, int do_chgproccnt);
void change_svgid(struct ucred *newcred, gid_t svgid);
void change_svuid(struct ucred *newcred, uid_t svuid);
void crcopy(struct ucred *dest, struct ucred *src);

File Metadata

Mime Type
text/plain
Expires
Sat, Jan 31, 11:26 PM (12 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28215758
Default Alt Text
D18930.id53110.diff (32 KB)

Event Timeline