summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_descrip.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r--sys/kern/kern_descrip.c185
1 files changed, 102 insertions, 83 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 30cd545..48c6db9 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -67,7 +67,6 @@ __FBSDID("$FreeBSD$");
#include <sys/resourcevar.h>
#include <sys/sbuf.h>
#include <sys/signalvar.h>
-#include <sys/socketvar.h>
#include <sys/kdb.h>
#include <sys/stat.h>
#include <sys/sx.h>
@@ -517,28 +516,26 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
break;
case F_GETFD:
+ error = EBADF;
FILEDESC_SLOCK(fdp);
- if (fget_locked(fdp, fd) == NULL) {
- FILEDESC_SUNLOCK(fdp);
- error = EBADF;
- break;
+ fde = fdeget_locked(fdp, fd);
+ if (fde != NULL) {
+ td->td_retval[0] =
+ (fde->fde_flags & UF_EXCLOSE) ? FD_CLOEXEC : 0;
+ error = 0;
}
- fde = &fdp->fd_ofiles[fd];
- td->td_retval[0] =
- (fde->fde_flags & UF_EXCLOSE) ? FD_CLOEXEC : 0;
FILEDESC_SUNLOCK(fdp);
break;
case F_SETFD:
+ error = EBADF;
FILEDESC_XLOCK(fdp);
- if (fget_locked(fdp, fd) == NULL) {
- FILEDESC_XUNLOCK(fdp);
- error = EBADF;
- break;
+ fde = fdeget_locked(fdp, fd);
+ if (fde != NULL) {
+ fde->fde_flags = (fde->fde_flags & ~UF_EXCLOSE) |
+ (arg & FD_CLOEXEC ? UF_EXCLOSE : 0);
+ error = 0;
}
- fde = &fdp->fd_ofiles[fd];
- fde->fde_flags = (fde->fde_flags & ~UF_EXCLOSE) |
- (arg & FD_CLOEXEC ? UF_EXCLOSE : 0);
FILEDESC_XUNLOCK(fdp);
break;
@@ -2450,6 +2447,82 @@ finit(struct file *fp, u_int flag, short type, void *data, struct fileops *ops)
}
int
+fget_cap_locked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
+ struct file **fpp, struct filecaps *havecapsp)
+{
+ struct filedescent *fde;
+ int error;
+
+ FILEDESC_LOCK_ASSERT(fdp);
+
+ fde = fdeget_locked(fdp, fd);
+ if (fde == NULL) {
+ error = EBADF;
+ goto out;
+ }
+
+#ifdef CAPABILITIES
+ error = cap_check(cap_rights_fde(fde), needrightsp);
+ if (error != 0)
+ goto out;
+#endif
+
+ if (havecapsp != NULL)
+ filecaps_copy(&fde->fde_caps, havecapsp, true);
+
+ *fpp = fde->fde_file;
+
+ error = 0;
+out:
+ return (error);
+}
+
+int
+fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp,
+ struct file **fpp, struct filecaps *havecapsp)
+{
+ struct filedesc *fdp = td->td_proc->p_fd;
+ int error;
+#ifndef CAPABILITIES
+ error = fget_unlocked(fdp, fd, needrightsp, fpp, NULL);
+ if (error == 0 && havecapsp != NULL)
+ filecaps_fill(havecapsp);
+#else
+ struct file *fp;
+ seq_t seq;
+
+ for (;;) {
+ error = fget_unlocked(fdp, fd, needrightsp, &fp, &seq);
+ if (error != 0)
+ return (error);
+
+ if (havecapsp != NULL) {
+ if (!filecaps_copy(&fdp->fd_ofiles[fd].fde_caps,
+ havecapsp, false)) {
+ fdrop(fp, td);
+ goto get_locked;
+ }
+ }
+
+ if (!fd_modified(fdp, fd, seq))
+ break;
+ fdrop(fp, td);
+ }
+
+ *fpp = fp;
+ return (0);
+
+get_locked:
+ FILEDESC_SLOCK(fdp);
+ error = fget_cap_locked(fdp, fd, needrightsp, fpp, havecapsp);
+ if (error == 0)
+ fhold(*fpp);
+ FILEDESC_SUNLOCK(fdp);
+#endif
+ return (error);
+}
+
+int
fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
struct file **fpp, seq_t *seqp)
{
@@ -2712,30 +2785,31 @@ fgetvp_rights(struct thread *td, int fd, cap_rights_t *needrightsp,
struct filecaps *havecaps, struct vnode **vpp)
{
struct filedesc *fdp;
+ struct filecaps caps;
struct file *fp;
-#ifdef CAPABILITIES
int error;
-#endif
fdp = td->td_proc->p_fd;
- fp = fget_locked(fdp, fd);
- if (fp == NULL || fp->f_ops == &badfileops)
- return (EBADF);
-
-#ifdef CAPABILITIES
- error = cap_check(cap_rights(fdp, fd), needrightsp);
+ error = fget_cap_locked(fdp, fd, needrightsp, &fp, &caps);
if (error != 0)
return (error);
-#endif
-
- if (fp->f_vnode == NULL)
- return (EINVAL);
+ if (fp->f_ops == &badfileops) {
+ error = EBADF;
+ goto out;
+ }
+ if (fp->f_vnode == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+ *havecaps = caps;
*vpp = fp->f_vnode;
vrefact(*vpp);
- filecaps_copy(&fdp->fd_ofiles[fd].fde_caps, havecaps, true);
return (0);
+out:
+ filecaps_free(&caps);
+ return (error);
}
int
@@ -2763,61 +2837,6 @@ fgetvp_write(struct thread *td, int fd, cap_rights_t *rightsp,
#endif
/*
- * Like fget() but loads the underlying socket, or returns an error if the
- * descriptor does not represent a socket.
- *
- * We bump the ref count on the returned socket. XXX Also obtain the SX lock
- * in the future.
- *
- * Note: fgetsock() and fputsock() are deprecated, as consumers should rely
- * on their file descriptor reference to prevent the socket from being free'd
- * during use.
- */
-int
-fgetsock(struct thread *td, int fd, cap_rights_t *rightsp, struct socket **spp,
- u_int *fflagp)
-{
- struct file *fp;
- int error;
-
- *spp = NULL;
- if (fflagp != NULL)
- *fflagp = 0;
- if ((error = _fget(td, fd, &fp, 0, rightsp, NULL)) != 0)
- return (error);
- if (fp->f_type != DTYPE_SOCKET) {
- error = ENOTSOCK;
- } else {
- *spp = fp->f_data;
- if (fflagp)
- *fflagp = fp->f_flag;
- SOCK_LOCK(*spp);
- soref(*spp);
- SOCK_UNLOCK(*spp);
- }
- fdrop(fp, td);
-
- return (error);
-}
-
-/*
- * Drop the reference count on the socket and XXX release the SX lock in the
- * future. The last reference closes the socket.
- *
- * Note: fputsock() is deprecated, see comment for fgetsock().
- */
-void
-fputsock(struct socket *so)
-{
-
- ACCEPT_LOCK();
- SOCK_LOCK(so);
- CURVNET_SET(so->so_vnet);
- sorele(so);
- CURVNET_RESTORE();
-}
-
-/*
* Handle the last reference to a file being closed.
*/
int
OpenPOWER on IntegriCloud