Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F110460201
D6544.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D6544.diff
View Options
Index: head/sys/kern/kern_exec.c
===================================================================
--- head/sys/kern/kern_exec.c
+++ head/sys/kern/kern_exec.c
@@ -356,7 +356,7 @@
{
struct proc *p = td->td_proc;
struct nameidata nd;
- struct ucred *newcred = NULL, *oldcred;
+ struct ucred *oldcred;
struct uidinfo *euip = NULL;
register_t *stack_base;
int error, i;
@@ -404,6 +404,7 @@
imgp->proc = p;
imgp->attr = &attr;
imgp->args = args;
+ oldcred = p->p_ucred;
#ifdef MAC
error = mac_execve_enter(imgp, mac_p);
@@ -485,6 +486,87 @@
goto exec_fail_dealloc;
imgp->proc->p_osrel = 0;
+
+ /*
+ * Implement image setuid/setgid.
+ *
+ * Determine new credentials before attempting image activators
+ * so that it can be used by process_exec handlers to determine
+ * credential/setid changes.
+ *
+ * Don't honor setuid/setgid if the filesystem prohibits it or if
+ * the process is being traced.
+ *
+ * We disable setuid/setgid/etc in capability mode on the basis
+ * that most setugid applications are not written with that
+ * environment in mind, and will therefore almost certainly operate
+ * incorrectly. In principle there's no reason that setugid
+ * applications might not be useful in capability mode, so we may want
+ * to reconsider this conservative design choice in the future.
+ *
+ * XXXMAC: For the time being, use NOSUID to also prohibit
+ * transitions on the file system.
+ */
+ credential_changing = 0;
+ credential_changing |= (attr.va_mode & S_ISUID) &&
+ oldcred->cr_uid != attr.va_uid;
+ credential_changing |= (attr.va_mode & S_ISGID) &&
+ oldcred->cr_gid != attr.va_gid;
+#ifdef MAC
+ will_transition = mac_vnode_execve_will_transition(oldcred, imgp->vp,
+ interpvplabel, imgp);
+ credential_changing |= will_transition;
+#endif
+
+ if (credential_changing &&
+#ifdef CAPABILITY_MODE
+ ((oldcred->cr_flags & CRED_FLAG_CAPMODE) == 0) &&
+#endif
+ (imgp->vp->v_mount->mnt_flag & MNT_NOSUID) == 0 &&
+ (p->p_flag & P_TRACED) == 0) {
+ imgp->credential_setid = true;
+ VOP_UNLOCK(imgp->vp, 0);
+ imgp->newcred = crdup(oldcred);
+ if (attr.va_mode & S_ISUID) {
+ euip = uifind(attr.va_uid);
+ change_euid(imgp->newcred, euip);
+ }
+ vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
+ if (attr.va_mode & S_ISGID)
+ change_egid(imgp->newcred, attr.va_gid);
+ /*
+ * Implement correct POSIX saved-id behavior.
+ *
+ * XXXMAC: Note that the current logic will save the
+ * uid and gid if a MAC domain transition occurs, even
+ * though maybe it shouldn't.
+ */
+ change_svuid(imgp->newcred, imgp->newcred->cr_uid);
+ change_svgid(imgp->newcred, imgp->newcred->cr_gid);
+ } else {
+ /*
+ * Implement correct POSIX saved-id behavior.
+ *
+ * XXX: It's not clear that the existing behavior is
+ * POSIX-compliant. A number of sources indicate that the
+ * saved uid/gid should only be updated if the new ruid is
+ * not equal to the old ruid, or the new euid is not equal
+ * to the old euid and the new euid is not equal to the old
+ * ruid. The FreeBSD code always updates the saved uid/gid.
+ * Also, this code uses the new (replaced) euid and egid as
+ * the source, which may or may not be the right ones to use.
+ */
+ if (oldcred->cr_svuid != oldcred->cr_uid ||
+ oldcred->cr_svgid != oldcred->cr_gid) {
+ VOP_UNLOCK(imgp->vp, 0);
+ imgp->newcred = crdup(oldcred);
+ vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
+ change_svuid(imgp->newcred, imgp->newcred->cr_uid);
+ change_svgid(imgp->newcred, imgp->newcred->cr_gid);
+ }
+ }
+ /* The new credentials are installed into the process later. */
+
/*
* If the current process has a special image activator it
* wants to try first, call it. For example, emulating shell
@@ -542,6 +624,11 @@
vput(newtextvp);
vm_object_deallocate(imgp->object);
imgp->object = NULL;
+ imgp->credential_setid = false;
+ if (imgp->newcred != NULL) {
+ crfree(imgp->newcred);
+ imgp->newcred = NULL;
+ }
/* set new name to that of the interpreter */
NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME,
UIO_SYSSPACE, imgp->interpreter_name, td);
@@ -639,7 +726,6 @@
PROC_LOCK(p);
if (oldsigacts)
p->p_sigacts = newsigacts;
- oldcred = p->p_ucred;
/* Stop profiling */
stopprofclock(p);
@@ -671,38 +757,9 @@
}
/*
- * Implement image setuid/setgid.
- *
- * Don't honor setuid/setgid if the filesystem prohibits it or if
- * the process is being traced.
- *
- * We disable setuid/setgid/etc in capability mode on the basis
- * that most setugid applications are not written with that
- * environment in mind, and will therefore almost certainly operate
- * incorrectly. In principle there's no reason that setugid
- * applications might not be useful in capability mode, so we may want
- * to reconsider this conservative design choice in the future.
- *
- * XXXMAC: For the time being, use NOSUID to also prohibit
- * transitions on the file system.
+ * Implement image setuid/setgid installation.
*/
- credential_changing = 0;
- credential_changing |= (attr.va_mode & S_ISUID) && oldcred->cr_uid !=
- attr.va_uid;
- credential_changing |= (attr.va_mode & S_ISGID) && oldcred->cr_gid !=
- attr.va_gid;
-#ifdef MAC
- will_transition = mac_vnode_execve_will_transition(oldcred, imgp->vp,
- interpvplabel, imgp);
- credential_changing |= will_transition;
-#endif
-
- if (credential_changing &&
-#ifdef CAPABILITY_MODE
- ((oldcred->cr_flags & CRED_FLAG_CAPMODE) == 0) &&
-#endif
- (imgp->vp->v_mount->mnt_flag & MNT_NOSUID) == 0 &&
- (p->p_flag & P_TRACED) == 0) {
+ if (imgp->credential_setid) {
/*
* Turn off syscall tracing for set-id programs, except for
* root. Record any set-id flags first to make sure that
@@ -728,61 +785,24 @@
error = fdcheckstd(td);
if (error != 0)
goto done1;
- newcred = crdup(oldcred);
- euip = uifind(attr.va_uid);
vn_lock(imgp->vp, LK_SHARED | LK_RETRY);
PROC_LOCK(p);
- /*
- * Set the new credentials.
- */
- if (attr.va_mode & S_ISUID)
- change_euid(newcred, euip);
- if (attr.va_mode & S_ISGID)
- change_egid(newcred, attr.va_gid);
#ifdef MAC
if (will_transition) {
- mac_vnode_execve_transition(oldcred, newcred, imgp->vp,
- interpvplabel, imgp);
+ mac_vnode_execve_transition(oldcred, imgp->newcred,
+ imgp->vp, interpvplabel, imgp);
}
#endif
- /*
- * Implement correct POSIX saved-id behavior.
- *
- * XXXMAC: Note that the current logic will save the
- * uid and gid if a MAC domain transition occurs, even
- * though maybe it shouldn't.
- */
- change_svuid(newcred, newcred->cr_uid);
- change_svgid(newcred, newcred->cr_gid);
- proc_set_cred(p, newcred);
} else {
if (oldcred->cr_uid == oldcred->cr_ruid &&
oldcred->cr_gid == oldcred->cr_rgid)
p->p_flag &= ~P_SUGID;
- /*
- * Implement correct POSIX saved-id behavior.
- *
- * XXX: It's not clear that the existing behavior is
- * POSIX-compliant. A number of sources indicate that the
- * saved uid/gid should only be updated if the new ruid is
- * not equal to the old ruid, or the new euid is not equal
- * to the old euid and the new euid is not equal to the old
- * ruid. The FreeBSD code always updates the saved uid/gid.
- * Also, this code uses the new (replaced) euid and egid as
- * the source, which may or may not be the right ones to use.
- */
- if (oldcred->cr_svuid != oldcred->cr_uid ||
- oldcred->cr_svgid != oldcred->cr_gid) {
- PROC_UNLOCK(p);
- VOP_UNLOCK(imgp->vp, 0);
- newcred = crdup(oldcred);
- vn_lock(imgp->vp, LK_SHARED | LK_RETRY);
- PROC_LOCK(p);
- change_svuid(newcred, newcred->cr_uid);
- change_svgid(newcred, newcred->cr_gid);
- proc_set_cred(p, newcred);
- }
}
+ /*
+ * Set the new credentials.
+ */
+ if (imgp->newcred != NULL)
+ proc_set_cred(p, imgp->newcred);
/*
* Store the vp for use in procfs. This vnode was referenced by namei
@@ -856,14 +876,6 @@
VOP_UNLOCK(imgp->vp, 0);
done1:
/*
- * Free any resources malloc'd earlier that we didn't use.
- */
- if (euip != NULL)
- uifree(euip);
- if (newcred != NULL)
- crfree(oldcred);
-
- /*
* Handle deferred decrement of ref counts.
*/
if (oldtextvp != NULL)
@@ -881,10 +893,12 @@
sigacts_free(oldsigacts);
exec_fail_dealloc:
-
/*
* free various allocated resources
*/
+ if (euip != NULL)
+ uifree(euip);
+
if (imgp->firstpage != NULL)
exec_unmap_first_page(imgp);
@@ -926,6 +940,8 @@
SDT_PROBE1(proc, , , exec__failure, error);
done2:
+ if (imgp->newcred != NULL)
+ crfree(oldcred);
#ifdef MAC
mac_execve_exit(imgp);
mac_execve_interpreter_exit(interpvplabel);
Index: head/sys/sys/imgact.h
===================================================================
--- head/sys/sys/imgact.h
+++ head/sys/sys/imgact.h
@@ -38,6 +38,8 @@
#define MAXSHELLCMDLEN PAGE_SIZE
+struct ucred;
+
struct image_args {
char *buf; /* pointer to string buffer */
char *begin_argv; /* beginning of argv in buf */
@@ -82,6 +84,8 @@
int pagesizeslen;
vm_prot_t stack_prot;
u_long stack_sz;
+ struct ucred *newcred; /* new credentials if changing */
+ bool credential_setid; /* true if becoming setid */
};
#ifdef _KERNEL
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Feb 19, 6:23 PM (21 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16725727
Default Alt Text
D6544.diff (9 KB)
Attached To
Mode
D6544: exec: Add credential change information into imgp for process_exec hook.
Attached
Detach File
Event Timeline
Log In to Comment