1 /* This file contains the procedures that manipulate file descriptors.
3 * The entry points into this file are
4 * get_fd: look for free file descriptor and free filp slots
5 * get_filp: look up the filp entry for a given file descriptor
6 * find_filp: find a filp slot that points to a given vnode
7 * inval_filp: invalidate a filp and associated fd's, only let close()
9 * do_copyfd: copies a file descriptor from or to another endpoint
12 #include <sys/select.h>
13 #include <minix/callnr.h>
14 #include <minix/u64.h>
23 /*===========================================================================*
25 *===========================================================================*/
26 void check_filp_locks_by_me(void)
28 /* Check whether this thread still has filp locks held */
32 for (f
= &filp
[0]; f
< &filp
[NR_FILPS
]; f
++) {
33 r
= mutex_trylock(&f
->filp_lock
);
35 panic("Thread %d still holds filp lock on filp %p call_nr=%d\n",
36 mthread_self(), f
, job_call_nr
);
38 /* We just obtained the lock, release it */
39 mutex_unlock(&f
->filp_lock
);
45 /*===========================================================================*
47 *===========================================================================*/
48 void check_filp_locks(void)
53 for (f
= &filp
[0]; f
< &filp
[NR_FILPS
]; f
++) {
54 r
= mutex_trylock(&f
->filp_lock
);
56 /* Mutex is still locked */
59 /* We just obtained a lock, don't want it */
60 mutex_unlock(&f
->filp_lock
);
62 panic("filp_lock weird state");
64 if (count
) panic("locked filps");
66 else printf("check_filp_locks OK\n");
70 /*===========================================================================*
72 *===========================================================================*/
75 /* Initialize filps */
78 for (f
= &filp
[0]; f
< &filp
[NR_FILPS
]; f
++) {
79 if (mutex_init(&f
->filp_lock
, NULL
) != 0)
80 panic("Failed to initialize filp mutex");
85 /*===========================================================================*
87 *===========================================================================*/
88 int check_fds(struct fproc
*rfp
, int nfds
)
90 /* Check whether at least 'nfds' file descriptors can be created in the process
91 * 'rfp'. Return OK on success, or otherwise an appropriate error code.
97 for (i
= 0; i
< OPEN_MAX
; i
++) {
98 if (rfp
->fp_filp
[i
] == NULL
) {
107 /*===========================================================================*
109 *===========================================================================*/
110 int get_fd(struct fproc
*rfp
, int start
, mode_t bits
, int *k
, struct filp
**fpt
)
112 /* Look for a free file descriptor and a free filp slot. Fill in the mode word
113 * in the latter, but don't claim either one yet, since the open() or creat()
117 register struct filp
*f
;
120 /* Search the fproc fp_filp table for a free file descriptor. */
121 for (i
= start
; i
< OPEN_MAX
; i
++) {
122 if (rfp
->fp_filp
[i
] == NULL
) {
123 /* A file descriptor has been located. */
129 /* Check to see if a file descriptor has been found. */
130 if (i
>= OPEN_MAX
) return(EMFILE
);
132 /* If we don't care about a filp, return now */
133 if (fpt
== NULL
) return(OK
);
135 /* Now that a file descriptor has been found, look for a free filp slot. */
136 for (f
= &filp
[0]; f
< &filp
[NR_FILPS
]; f
++) {
137 assert(f
->filp_count
>= 0);
138 if (f
->filp_count
== 0 && mutex_trylock(&f
->filp_lock
) == 0) {
141 f
->filp_selectors
= 0;
142 f
->filp_select_ops
= 0;
143 f
->filp_pipe_select_ops
= 0;
144 f
->filp_select_dev
= NO_DEV
;
146 f
->filp_select_flags
= 0;
147 f
->filp_softlock
= NULL
;
148 f
->filp_ioctl_fp
= NULL
;
154 /* If control passes here, the filp table must be full. Report that back. */
159 /*===========================================================================*
161 *===========================================================================*/
164 int fild
, /* file descriptor */
165 tll_access_t locktype
168 /* See if 'fild' refers to a valid file descr. If so, return its filp ptr. */
170 return get_filp2(fp
, fild
, locktype
);
174 /*===========================================================================*
176 *===========================================================================*/
179 register struct fproc
*rfp
,
180 int fild
, /* file descriptor */
181 tll_access_t locktype
184 /* See if 'fild' refers to a valid file descr. If so, return its filp ptr. */
188 if (fild
< 0 || fild
>= OPEN_MAX
)
190 else if (locktype
!= VNODE_OPCL
&& rfp
->fp_filp
[fild
] != NULL
&&
191 rfp
->fp_filp
[fild
]->filp_mode
== FILP_CLOSED
)
192 err_code
= EIO
; /* disallow all use except close(2) */
193 else if ((filp
= rfp
->fp_filp
[fild
]) == NULL
)
195 else if (locktype
!= VNODE_NONE
) /* Only lock the filp if requested */
196 lock_filp(filp
, locktype
); /* All is fine */
198 return(filp
); /* may also be NULL */
202 /*===========================================================================*
204 *===========================================================================*/
205 struct filp
*find_filp(struct vnode
*vp
, mode_t bits
)
207 /* Find a filp slot that refers to the vnode 'vp' in a way as described
208 * by the mode bit 'bits'. Used for determining whether somebody is still
209 * interested in either end of a pipe. Also used when opening a FIFO to
210 * find partners to share a filp field with (to shared the file position).
211 * Like 'get_fd' it performs its job by linear search through the filp table.
216 for (f
= &filp
[0]; f
< &filp
[NR_FILPS
]; f
++) {
217 if (f
->filp_count
!= 0 && f
->filp_vno
== vp
&& (f
->filp_mode
& bits
)) {
222 /* If control passes here, the filp wasn't there. Report that back. */
226 /*===========================================================================*
227 * find_filp_by_sock_dev *
228 *===========================================================================*/
229 struct filp
*find_filp_by_sock_dev(dev_t dev
)
231 /* See if there is a file pointer for a socket with the given socket device
236 for (f
= &filp
[0]; f
< &filp
[NR_FILPS
]; f
++) {
237 if (f
->filp_count
!= 0 && f
->filp_vno
!= NULL
&&
238 S_ISSOCK(f
->filp_vno
->v_mode
) && f
->filp_vno
->v_sdev
== dev
&&
239 f
->filp_mode
!= FILP_CLOSED
) {
247 /*===========================================================================*
249 *===========================================================================*/
250 void invalidate_filp(struct filp
*rfilp
)
252 /* Invalidate filp. */
254 rfilp
->filp_mode
= FILP_CLOSED
;
257 /*===========================================================================*
258 * invalidate_filp_by_char_major *
259 *===========================================================================*/
260 void invalidate_filp_by_char_major(devmajor_t major
)
264 for (f
= &filp
[0]; f
< &filp
[NR_FILPS
]; f
++) {
265 if (f
->filp_count
!= 0 && f
->filp_vno
!= NULL
) {
266 if (major(f
->filp_vno
->v_sdev
) == major
&&
267 S_ISCHR(f
->filp_vno
->v_mode
)) {
274 /*===========================================================================*
275 * invalidate_filp_by_sock_drv *
276 *===========================================================================*/
277 void invalidate_filp_by_sock_drv(unsigned int num
)
279 /* Invalidate all file pointers for sockets owned by the socket driver with the
285 for (f
= &filp
[0]; f
< &filp
[NR_FILPS
]; f
++) {
286 if (f
->filp_count
!= 0 && f
->filp_vno
!= NULL
) {
287 if (S_ISSOCK(f
->filp_vno
->v_mode
) &&
288 (sp
= get_smap_by_dev(f
->filp_vno
->v_sdev
, NULL
)) != NULL
289 && sp
->smap_num
== num
)
295 /*===========================================================================*
296 * invalidate_filp_by_endpt *
297 *===========================================================================*/
298 void invalidate_filp_by_endpt(endpoint_t proc_e
)
302 for (f
= &filp
[0]; f
< &filp
[NR_FILPS
]; f
++) {
303 if (f
->filp_count
!= 0 && f
->filp_vno
!= NULL
) {
304 if (f
->filp_vno
->v_fs_e
== proc_e
)
310 /*===========================================================================*
312 *===========================================================================*/
314 lock_filp(struct filp
*filp
, tll_access_t locktype
)
316 struct worker_thread
*org_self
;
319 assert(filp
->filp_count
> 0);
323 /* Lock vnode only if we haven't already locked it. If already locked by us,
324 * we're allowed to have one additional 'soft' lock. */
325 if (tll_locked_by_me(&vp
->v_lock
)) {
326 assert(filp
->filp_softlock
== NULL
);
327 filp
->filp_softlock
= fp
;
329 /* We have to make an exception for vnodes belonging to pipes. Even
330 * read(2) operations on pipes change the vnode and therefore require
333 if (S_ISFIFO(vp
->v_mode
) && locktype
== VNODE_READ
)
334 locktype
= VNODE_WRITE
;
335 lock_vnode(vp
, locktype
);
338 assert(vp
->v_ref_count
> 0); /* vnode still in use? */
339 assert(filp
->filp_vno
== vp
); /* vnode still what we think it is? */
341 /* First try to get filp lock right off the bat */
342 if (mutex_trylock(&filp
->filp_lock
) != 0) {
344 /* Already in use, let's wait for our turn */
345 org_self
= worker_suspend();
347 if (mutex_lock(&filp
->filp_lock
) != 0)
348 panic("unable to obtain lock on filp");
350 worker_resume(org_self
);
354 /*===========================================================================*
356 *===========================================================================*/
358 unlock_filp(struct filp
*filp
)
360 /* If this filp holds a soft lock on the vnode, we must be the owner */
361 if (filp
->filp_softlock
!= NULL
)
362 assert(filp
->filp_softlock
== fp
);
364 if (filp
->filp_count
> 0) {
365 /* Only unlock vnode if filp is still in use */
367 /* and if we don't hold a soft lock */
368 if (filp
->filp_softlock
== NULL
) {
369 assert(tll_islocked(&(filp
->filp_vno
->v_lock
)));
370 unlock_vnode(filp
->filp_vno
);
374 filp
->filp_softlock
= NULL
;
375 if (mutex_unlock(&filp
->filp_lock
) != 0)
376 panic("unable to release lock on filp");
379 /*===========================================================================*
381 *===========================================================================*/
383 unlock_filps(struct filp
*filp1
, struct filp
*filp2
)
385 /* Unlock two filps that are tied to the same vnode. As a thread can lock a
386 * vnode only once, unlocking the vnode twice would result in an error. */
388 /* No NULL pointers and not equal */
391 assert(filp1
!= filp2
);
393 /* Must be tied to the same vnode and not NULL */
394 assert(filp1
->filp_vno
== filp2
->filp_vno
);
395 assert(filp1
->filp_vno
!= NULL
);
397 if (filp1
->filp_count
> 0 && filp2
->filp_count
> 0) {
398 /* Only unlock vnode if filps are still in use */
399 unlock_vnode(filp1
->filp_vno
);
402 filp1
->filp_softlock
= NULL
;
403 filp2
->filp_softlock
= NULL
;
404 if (mutex_unlock(&filp2
->filp_lock
) != 0)
405 panic("unable to release filp lock on filp2");
406 if (mutex_unlock(&filp1
->filp_lock
) != 0)
407 panic("unable to release filp lock on filp1");
410 /*===========================================================================*
412 *===========================================================================*/
414 close_filp(struct filp
* f
, int may_suspend
)
416 /* Close a file. Will also unlock filp when done. The 'may_suspend' flag
417 * indicates whether the current process may be suspended closing a socket.
418 * That is currently supported only when the user issued a close(2), and (only)
419 * in that case may this function return SUSPEND instead of OK. In all other
420 * cases, this function will always return OK. It will never return another
421 * error code, for reasons explained below.
428 assert(mutex_trylock(&f
->filp_lock
) == -EDEADLK
);
429 assert(tll_islocked(&f
->filp_vno
->v_lock
));
435 if (f
->filp_count
- 1 == 0 && f
->filp_mode
!= FILP_CLOSED
) {
436 /* Check to see if the file is special. */
437 if (S_ISCHR(vp
->v_mode
) || S_ISBLK(vp
->v_mode
) ||
438 S_ISSOCK(vp
->v_mode
)) {
440 if (S_ISBLK(vp
->v_mode
)) {
442 if (vp
->v_bfs_e
== ROOT_FS_E
&& dev
!= ROOT_DEV
) {
443 /* Invalidate the cache unless the special is
444 * mounted. Be careful not to flush the root
445 * file system either.
447 (void) req_flush(vp
->v_bfs_e
, dev
);
451 (void) bdev_close(dev
); /* Ignore errors */
452 } else if (S_ISCHR(vp
->v_mode
)) {
453 (void) cdev_close(dev
); /* Ignore errors */
456 * Sockets may take a while to be closed (SO_LINGER),
457 * and thus, we may issue a suspending close to a
458 * socket driver. Getting this working for close(2) is
459 * the easy case, and that is all we support for now.
460 * However, there is also eg dup2(2), which if
461 * interrupted by a signal should technically fail
462 * without closing the file descriptor. Then there are
463 * cases where the close should never block: process
464 * exit and close-on-exec for example. Getting all
465 * such cases right is left to future work; currently
466 * they all perform thread-blocking socket closes and
467 * thus cause the socket to perform lingering in the
468 * background if at all.
470 assert(!may_suspend
|| job_call_nr
== VFS_CLOSE
);
472 if (f
->filp_flags
& O_NONBLOCK
)
475 r
= sdev_close(dev
, may_suspend
);
478 * Returning a non-OK error is a bad idea, because it
479 * will leave the application wondering whether closing
480 * the file descriptor actually succeeded.
486 f
->filp_mode
= FILP_CLOSED
;
490 /* If the inode being closed is a pipe, release everyone hanging on it. */
491 if (S_ISFIFO(vp
->v_mode
)) {
492 rw
= (f
->filp_mode
& R_BIT
? VFS_WRITE
: VFS_READ
);
493 release(vp
, rw
, susp_count
);
496 if (--f
->filp_count
== 0) {
497 if (S_ISFIFO(vp
->v_mode
)) {
498 /* Last reader or writer is going. Tell PFS about latest
501 truncate_vnode(vp
, vp
->v_size
);
504 unlock_vnode(f
->filp_vno
);
505 put_vnode(f
->filp_vno
);
507 f
->filp_mode
= FILP_CLOSED
;
509 } else if (f
->filp_count
< 0) {
510 panic("VFS: invalid filp count: %d ino %llx/%llu", f
->filp_count
,
511 vp
->v_dev
, vp
->v_inode_nr
);
513 unlock_vnode(f
->filp_vno
);
516 mutex_unlock(&f
->filp_lock
);
521 /*===========================================================================*
523 *===========================================================================*/
526 /* Copy a file descriptor between processes, or close a remote file descriptor.
527 * This call is used as back-call by device drivers (UDS, VND), and is expected
528 * to be used in response to either an IOCTL to VND or a SEND or RECV socket
536 int r
, fd
, what
, flags
, slot
;
538 /* This should be replaced with an ACL check. */
539 if (!super_user
) return(EPERM
);
541 endpt
= job_m_in
.m_lsys_vfs_copyfd
.endpt
;
542 fd
= job_m_in
.m_lsys_vfs_copyfd
.fd
;
543 what
= job_m_in
.m_lsys_vfs_copyfd
.what
;
545 flags
= what
& COPYFD_FLAGS
;
546 what
&= ~COPYFD_FLAGS
;
548 if (isokendpt(endpt
, &slot
) != OK
) return(EINVAL
);
551 /* FIXME: we should now check that the user process is indeed blocked on an
552 * IOCTL or socket call, so that we can safely mess with its file
553 * descriptors. We currently do not have the necessary state to verify this,
554 * so we assume that the call is always used in the right way.
557 /* Depending on the operation, get the file descriptor from the caller or the
558 * user process. Do not lock the filp yet: we first need to make sure that
559 * locking it will not result in a deadlock.
561 rfilp
= get_filp2((what
== COPYFD_TO
) ? fp
: rfp
, fd
, VNODE_NONE
);
565 /* If the filp is involved in an IOCTL by the user process, locking the filp
566 * here would result in a deadlock. This would happen if a user process
567 * passes in the file descriptor to the device node on which it is performing
568 * the IOCTL. We do not allow manipulation of such device nodes. In
569 * practice, this only applies to block-special files (and thus VND), because
570 * socket files (as used by UDS) are unlocked during the socket operation.
572 if (rfilp
->filp_ioctl_fp
== rfp
)
575 /* Now we can safely lock the filp, copy or close it, and unlock it again. */
576 lock_filp(rfilp
, VNODE_READ
);
581 * If the caller is a socket driver (namely, UDS) and the file
582 * descriptor being copied in is a socket for that socket driver, then
583 * deny the call, because of at least two known issues. Both issues
584 * are related to UDS having an in-flight file descriptor that is the
585 * last reference to a UDS socket:
587 * 1) if UDS tries to close the file descriptor, this will prompt VFS
588 * to close the underlying object, which is a UDS socket. As a
589 * result, while UDS is blocked in the close(2), VFS will try to
590 * send a request to UDS to close the socket. This results in a
591 * deadlock of the UDS service.
593 * 2) if a file descriptor for a UDS socket is sent across that same
594 * UDS socket, the socket will remain referenced by UDS, thus open
595 * in VFS, and therefore also open in UDS. The socket and file
596 * descriptor will both remain in use for the rest of UDS' lifetime.
597 * This can easily result in denial-of-service in the UDS service.
598 * The same problem can be triggered using multiple sockets that
599 * have in-flight file descriptors referencing each other.
601 * A proper solution for these problems may consist of some form of
602 * "soft reference counting" where VFS does not count UDS having a
603 * filp open as a real reference. That is tricky business, so for now
604 * we prevent any such problems with the check here.
606 if ((vp
= rfilp
->filp_vno
) != NULL
&& S_ISSOCK(vp
->v_mode
) &&
607 (sp
= get_smap_by_dev(vp
->v_sdev
, NULL
)) != NULL
&&
608 sp
->smap_endpt
== who_e
) {
615 flags
&= ~COPYFD_CLOEXEC
;
619 /* Find a free file descriptor slot in the local or remote process. */
620 for (fd
= 0; fd
< OPEN_MAX
; fd
++)
621 if (rfp
->fp_filp
[fd
] == NULL
)
624 /* If found, fill the slot and return the slot number. */
626 rfp
->fp_filp
[fd
] = rfilp
;
627 if (flags
& COPYFD_CLOEXEC
)
628 FD_SET(fd
, &rfp
->fp_cloexec_set
);
637 /* This should be used ONLY to revert a successful copy-to operation,
638 * and assumes that the filp is still in use by the caller as well.
640 if (rfilp
->filp_count
> 1) {
642 rfp
->fp_filp
[fd
] = NULL
;