Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F162774910
D58117.id181772.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D58117.id181772.diff
View Options
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -1562,14 +1562,9 @@
if (error != 0)
return (error);
- error = fget(td, fd, &cap_pdwait_rights, &fp);
+ error = fget_procdesc(td, fd, &cap_pdwait_rights, &fp, &pd, NULL);
if (error != 0)
- return (error);
- if (fp->f_type != DTYPE_PROCDESC) {
- error = EINVAL;
goto exit_unlocked;
- }
- pd = fp->f_data;
for (;;) {
/* We own a reference on the procdesc file. */
@@ -1620,7 +1615,8 @@
exit_tree_locked:
sx_xunlock(&proctree_lock);
exit_unlocked:
- fdrop(fp, td);
+ if (fp != NULL)
+ fdrop(fp, td);
return (error);
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1956,6 +1956,7 @@
sys_pdkill(struct thread *td, struct pdkill_args *uap)
{
struct proc *p;
+ struct file *fp;
int error;
AUDIT_ARG_SIGNUM(uap->signum);
@@ -1963,14 +1964,19 @@
if ((u_int)uap->signum > _SIG_MAXSIG)
return (EINVAL);
- error = procdesc_find(td, uap->fd, &cap_pdkill_rights, &p);
- if (error)
- return (error);
+ sx_slock(&proctree_lock);
+ error = fget_procdesc(td, uap->fd, &cap_pdkill_rights, &fp, NULL, &p);
+ sx_sunlock(&proctree_lock);
+ if (error != 0)
+ goto out;
AUDIT_ARG_PROCESS(p);
error = p_cansignal(td, p, uap->signum);
- if (error == 0 && uap->signum)
+ if (error == 0 && uap->signum != 0)
kern_psignal(p, uap->signum);
PROC_UNLOCK(p);
+out:
+ if (fp != NULL)
+ fdrop(fp, td);
return (error);
}
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -115,38 +115,6 @@
.fo_flags = DFLAG_PASSABLE,
};
-/*
- * Return a locked process given a process descriptor, or ESRCH if it has
- * died.
- */
-int
-procdesc_find(struct thread *td, int fd, const cap_rights_t *rightsp,
- struct proc **p)
-{
- struct procdesc *pd;
- struct file *fp;
- int error;
-
- error = fget(td, fd, rightsp, &fp);
- if (error)
- return (error);
- if (fp->f_type != DTYPE_PROCDESC) {
- error = EINVAL;
- goto out;
- }
- pd = fp->f_data;
- sx_slock(&proctree_lock);
- if (pd->pd_proc != NULL) {
- *p = pd->pd_proc;
- PROC_LOCK(*p);
- } else
- error = ESRCH;
- sx_sunlock(&proctree_lock);
-out:
- fdrop(fp, td);
- return (error);
-}
-
/*
* Function to be used by procstat(1) sysctls when returning procdesc
* information.
@@ -173,16 +141,11 @@
struct file *fp;
int error;
- error = fget(td, fd, rightsp, &fp);
- if (error)
- return (error);
- if (fp->f_type != DTYPE_PROCDESC) {
- error = EBADF;
- goto out;
- }
- *pidp = procdesc_pid(fp);
-out:
- fdrop(fp, td);
+ error = fget_procdesc(td, fd, rightsp, &fp, NULL, NULL);
+ if (error == 0)
+ *pidp = procdesc_pid(fp);
+ if (fp != NULL)
+ fdrop(fp, td);
return (error);
}
@@ -704,59 +667,88 @@
return (kern_pdopenpid(td, args->pid, args->flags));
}
+/*
+ * Get the file/process descriptor/process from the procdesc file
+ * descriptor. The process descriptor and process returns are
+ * optional. The process is returned locked. If the process return
+ * is requested, proctree_lock must be owned.
+ *
+ * The caller must fdrop(*pfp) if *pfp != NULL, regardless of the
+ * error returned, after the procdesc_lock is unlocked. The
+ * procdesc_close() takes the proctree_lock.
+ */
+int
+fget_procdesc(struct thread *td, int pdfd, const cap_rights_t *cap_rights,
+ struct file **pfp, struct procdesc **pdp, struct proc **pp)
+{
+ struct file *fp;
+ struct procdesc *pd;
+ struct proc *p;
+ int error;
+
+ if (pp != NULL)
+ sx_assert(&proctree_lock, SX_LOCKED);
+
+ *pfp = NULL;
+ error = fget(td, pdfd, cap_rights, &fp);
+ if (error != 0)
+ return (error);
+ *pfp = fp;
+ if (fp->f_type != DTYPE_PROCDESC)
+ return (EBADF);
+ pd = fp->f_data;
+ if (pp != NULL) {
+ p = pd->pd_proc;
+ if (p == NULL) {
+ return (ESRCH);
+ } else {
+ *pp = p;
+ PROC_LOCK(p);
+ }
+ }
+ if (pdp != NULL)
+ *pdp = pd;
+ return (0);
+}
+
static int
kern_pddupfd(struct thread *td, int pdfd, int fd, int flags)
{
struct proc *p;
struct file *fp, *pfp;
- struct procdesc *pd;
struct filecaps fcaps;
uint8_t fd_flags;
int error, fdr;
- error = fget(td, pdfd, &cap_pddupfd_rights, &pfp);
- if (error != 0)
- return (error);
- if (pfp->f_type != DTYPE_PROCDESC) {
- error = EBADF;
- goto out;
- }
- pd = pfp->f_data;
-again:
sx_slock(&proctree_lock);
- p = pd->pd_proc;
- if (p != NULL) {
- AUDIT_ARG_PROCESS(p);
- PROC_LOCK(p);
- sx_sunlock(&proctree_lock);
+ error = fget_procdesc(td, pdfd, &cap_pddupfd_rights, &pfp, NULL, &p);
+ if (error == 0) {
if ((p->p_flag & P_WEXIT) != 0) {
error = ESRCH;
+ PROC_UNLOCK(p);
} else {
- /*
- * Block the target process from entering
- * execve(). We need to ensure that the
- * p_candebug() predicate is stable until the
- * fget_remote() call ends even after the
- * process lock is dropped. For that, the
- * process must not change uid/suid.
- */
- if (!execve_block(td, p))
- goto again;
- error = p_candebug(td, p);
- if (error == 0)
- _PHOLD(p);
- else
- execve_unblock(td, p);
+ _PHOLD(p);
}
- PROC_UNLOCK(p);
- if (error != 0)
- goto out;
+ }
+ sx_sunlock(&proctree_lock);
+ if (error != 0)
+ goto out;
+ AUDIT_ARG_PROCESS(p);
+ PROC_LOCK_ASSERT(p, MA_OWNED);
- error = fget_remote(td, p, fd, &fcaps, &fd_flags, &fp);
- PROC_LOCK(p);
- execve_unblock(td, p);
- _PRELE(p);
+ /*
+ * Block the target process from entering execve().
+ * We need to ensure that the p_candebug() predicate
+ * is stable until the fget_remote() call ends even
+ * after the process lock is dropped. For that, the
+ * process must not change uid/suid.
+ */
+ execve_block_wait(td, p);
+ error = p_candebug(td, p);
+
+ if (error == 0) {
PROC_UNLOCK(p);
+ error = fget_remote(td, p, fd, &fcaps, &fd_flags, &fp);
if (error == 0) {
error = finstall_refed(td, fp, &fdr, O_CLOEXEC |
((fd_flags & FD_RESOLVE_BENEATH) != 0 ?
@@ -768,12 +760,14 @@
td->td_retval[0] = fdr;
}
}
- } else {
- sx_sunlock(&proctree_lock);
- error = ESRCH;
+ PROC_LOCK(p);
}
+ execve_unblock(td, p);
+ _PRELE(p);
+ PROC_UNLOCK(p);
out:
- fdrop(pfp, td);
+ if (pfp != NULL)
+ fdrop(pfp, td);
return (error);
}
diff --git a/sys/sys/procdesc.h b/sys/sys/procdesc.h
--- a/sys/sys/procdesc.h
+++ b/sys/sys/procdesc.h
@@ -102,8 +102,6 @@
* In-kernel interfaces to process descriptors.
*/
int procdesc_exit(struct proc *);
-int procdesc_find(struct thread *, int fd, const cap_rights_t *,
- struct proc **);
int kern_pdgetpid(struct thread *, int fd, const cap_rights_t *,
pid_t *pidp);
void procdesc_new(struct proc *, int);
@@ -113,7 +111,9 @@
int procdesc_falloc(struct thread *, struct file **, int *, int,
struct filecaps *);
-
+int fget_procdesc(struct thread *td, int pfd,
+ const cap_rights_t *cap_rights, struct file **pfp,
+ struct procdesc **pdp, struct proc **pp);
#else /* !_KERNEL */
#include <sys/cdefs.h>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jul 17, 6:27 PM (16 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35173822
Default Alt Text
D58117.id181772.diff (6 KB)
Attached To
Mode
D58117: kern: add fget_procdesc()
Attached
Detach File
Event Timeline
Log In to Comment