Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F143576942
D18930.id53110.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
32 KB
Referenced Files
None
Subscribers
None
D18930.id53110.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D18930: Per-thread credentials
Attached
Detach File
Event Timeline
Log In to Comment