--- linux/fs/namei.c	Mon Aug  3 22:20:09 1998
+++ linux-tmpcheck/fs/namei.c	Thu Sep  3 00:38:45 1998
@@ -488,6 +488,46 @@
 	return dir;
 }
 
+/* 
+ * /tmp exploit logging, used by open_namei()
+ */
+static void log_race_condition(struct dentry *file)
+{
+	char *buf=(char *)__get_free_pages(GFP_KERNEL, 1);
+	char *path_to_file, *path_to_prog, *p;
+	struct vm_area_struct * vma;
+	struct dentry *prog;
+
+	if (!buf) return;
+	if (!current->mm) goto out;
+	for (vma=current->mm->mmap; vma; vma=vma->vm_next)
+		if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) break;
+	if (!vma) goto out;
+	prog=dget(vma->vm_file->f_dentry);
+	if (IS_ERR(prog)) goto out;
+	path_to_file=d_path(file, buf, PAGE_SIZE);
+	path_to_prog=d_path(prog, buf+PAGE_SIZE, PAGE_SIZE);
+	dput(prog);
+	for (p=path_to_file; *p; p++) if (*p=='\n') *p='?';
+	for (p=path_to_prog; *p; p++) if (*p=='\n') *p='?';
+	if (file->d_inode)
+	{
+		printk(KERN_WARNING "tmp race: fsuid %d, i_uid %d, pid %d: "
+			"%s created %s without O_EXCL\n",
+			current->fsuid, file->d_inode->i_uid, current->pid, 
+			path_to_prog, path_to_file);
+	}
+	else
+	{
+		printk(KERN_WARNING "tmp race: fsuid %d, pid %d: "
+			"%s created %s without O_EXCL\n", 
+			current->fsuid, current->pid, 
+			path_to_prog, path_to_file);
+	}
+out:
+	free_pages((unsigned long)buf, 1);
+}
+
 /*
  *	open_namei()
  *
@@ -523,10 +563,12 @@
 	acc_mode = ACC_MODE(flag);
 	if (flag & O_CREAT) {
 		struct dentry *dir;
+		int exists;
 
 		error = -EEXIST;
 		if (dentry->d_inode && (flag & O_EXCL))
 			goto exit;
+		exists=dentry->d_inode?1:0;
 
 		dir = lock_parent(dentry);
 		error = PTR_ERR(dir);
@@ -542,12 +584,24 @@
 			error = 0;
 			if (flag & O_EXCL)
 				error = -EEXIST;
+			else {
+				if (dir->d_inode->i_mode & S_ISVTX)
+					log_race_condition(dentry);
+			}
 		} else if (IS_RDONLY(dir->d_inode))
 			error = -EROFS;
 		else if (!dir->d_inode->i_op || !dir->d_inode->i_op->create)
 			error = -EACCES;
 		else if ((error = permission(dir->d_inode,MAY_WRITE | MAY_EXEC)) == 0) {
 			DQUOT_INIT(dir->d_inode);
+			if (!(flag & O_EXCL) 
+				&& (dir->d_inode->i_mode & S_ISVTX)) {
+				/* 
+				 * We're creating a file in a sticky directory
+				 * without O_EXCL - possible /tmp race.
+				 */
+				log_race_condition(dentry);
+			}
 			error = dir->d_inode->i_op->create(dir->d_inode, dentry, mode);
 			/* Don't check for write permission, don't truncate */
 			acc_mode = 0;

