Source-Changes-D archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: CVS commit: src/share/man/man4



On Tue, 5 Jan 2016, Christos Zoulas wrote:

| Unless I can reliably determine which fd the program is using for its
| access to /dev/filemon I don't have anything to which I can compare the
| requested activity_log fd.

You could scan the whole fd array and look for DT_MISC with fops ==
filemon ops and if you find one that would cause a deadlock, deny.
Again this is a hack... But at least it should prevent the deadlock.

Yeah, this is workable, even if it is a HACK !  :)

The attached patch borrows extensively from fd_free() routine in kern/kern_descrip.c

Let me know if this looks "good enough" and I will commit it. (I'll also update the BUGS section of the man-page to describe the hack.)

FWIW, I have tested with log-file fd values of 1 and 4, while the /dev/filemon fd is always 3. In the "1" case the patch correctly returned EINVAL (it would cause a deadlock), while the "4" case succeeded and no deadlock occurred.



+------------------+--------------------------+------------------------+
| Paul Goyette     | PGP Key fingerprint:     | E-mail addresses:      |
| (Retired)        | FA29 0E3B 35AF E8AE 6651 | paul at whooppee.com   |
| Kernel Developer | 0786 F758 55DE 53BA 7731 | pgoyette at netbsd.org |
+------------------+--------------------------+------------------------+
Index: filemon.c
===================================================================
RCS file: /cvsroot/src/sys/dev/filemon/filemon.c,v
retrieving revision 1.24
diff -u -p -r1.24 filemon.c
--- filemon.c	5 Jan 2016 22:08:54 -0000	1.24
+++ filemon.c	6 Jan 2016 05:05:04 -0000
@@ -279,8 +279,12 @@ static int
 filemon_ioctl(struct file * fp, u_long cmd, void *data)
 {
 	int error = 0;
+	int i, nf, fd;
 	struct filemon *filemon;
 	struct proc *tp;
+	fdfile_t *ff;
+	filedesc_t *fdp;
+	fdtab_t *dt;
 
 #ifdef DEBUG
 	log(logLevel, "filemon_ioctl(%lu)", cmd);;
@@ -303,8 +307,41 @@ filemon_ioctl(struct file * fp, u_long c
 		if (filemon->fm_fp)
 			fd_putfile(filemon->fm_fd);
 
+		/*
+		 * XXX HACK XXX
+		 *
+		 * Due to our taking an extra reference on the
+		 * descriptor's struct file, we need to ensure that
+		 * the descriptor number is at least as large as
+		 * the one used to access /dev/filemon.  Otherwise,
+		 * we get a deadlock during process exit, waiting
+		 * for the output file's reference count.
+		 */
+		fd = *((int *) data);
+		fdp = curproc->p_fd;
+		dt = curlwp->l_fd->fd_dt;
+		nf = dt->dt_nfiles;
+		error = EINVAL;
+		for (i = 0; i < nf; i++) {
+			if (i >= fd)
+				break;
+			ff = dt->dt_ff[i];
+			KASSERT(fd >= NDFDFILE ||
+				ff == (fdfile_t *)fdp->fd_dfdfile[i]);
+			if (ff == NULL)
+				continue;
+
+			if (ff->ff_file->f_type == DTYPE_MISC &&
+			    ff->ff_file->f_ops == &filemon_fileops) {
+				error = 0;
+				break;
+			}
+		}
+		if (error)
+			break;
+
 		/* Now set up the new one */
-		filemon->fm_fd = *((int *) data);
+		filemon->fm_fd = fd;
 		if ((filemon->fm_fp = fd_getfile(filemon->fm_fd)) == NULL) {
 			error = EBADF;
 			break;


Home | Main Index | Thread Index | Old Index