changeset 12151:a78c082f61ab

6867268 sol10 on T2000: vn_rele: vnode ref count 0
author Milan Cermak <Milan.Cermak@Sun.COM>
date Tue, 13 Apr 2010 08:51:42 +0200
parents 4af87752eaf2
children c0b746bffad6
files usr/src/uts/common/syscall/fcntl.c
diffstat 1 files changed, 22 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/syscall/fcntl.c	Mon Apr 12 23:02:08 2010 -0700
+++ b/usr/src/uts/common/syscall/fcntl.c	Tue Apr 13 08:51:42 2010 +0200
@@ -21,8 +21,7 @@
 
 /* ONC_PLUS EXTRACT START */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
@@ -149,12 +148,28 @@
 			if (iarg >= 0)
 				fd_too_big(p);
 			error = EINVAL;
-		} else if ((retval = ufalloc_file(iarg, fp)) == -1) {
+			goto done;
+		}
+		/*
+		 * We need to increment the f_count reference counter
+		 * before allocating a new file descriptor.
+		 * Doing it other way round opens a window for race condition
+		 * with closeandsetf() on the target file descriptor which can
+		 * close the file still referenced by the original
+		 * file descriptor.
+		 */
+		mutex_enter(&fp->f_tlock);
+		fp->f_count++;
+		mutex_exit(&fp->f_tlock);
+		if ((retval = ufalloc_file(iarg, fp)) == -1) {
+			/*
+			 * New file descriptor can't be allocated.
+			 * Revert the reference count.
+			 */
+			mutex_enter(&fp->f_tlock);
+			fp->f_count--;
+			mutex_exit(&fp->f_tlock);
 			error = EMFILE;
-		} else {
-			mutex_enter(&fp->f_tlock);
-			fp->f_count++;
-			mutex_exit(&fp->f_tlock);
 		}
 		goto done;