mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	allow the temp files created by open() to be linked to
O_TMPFILE | O_CREAT => linkat() with AT_SYMLINK_FOLLOW and /proc/self/fd/<n> as oldpath (i.e. flink()) will create a link O_TMPFILE | O_CREAT | O_EXCL => ENOENT on attempt to link those guys Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
							parent
							
								
									60545d0d46
								
							
						
					
					
						commit
						f4e0c30c19
					
				
					 3 changed files with 18 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -333,8 +333,10 @@ EXPORT_SYMBOL(set_nlink);
 | 
			
		|||
 */
 | 
			
		||||
void inc_nlink(struct inode *inode)
 | 
			
		||||
{
 | 
			
		||||
	if (WARN_ON(inode->i_nlink == 0))
 | 
			
		||||
	if (unlikely(inode->i_nlink == 0)) {
 | 
			
		||||
		WARN_ON(!(inode->i_state & I_LINKABLE));
 | 
			
		||||
		atomic_long_dec(&inode->i_sb->s_remove_count);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inode->__i_nlink++;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								fs/namei.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								fs/namei.c
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -2948,8 +2948,14 @@ static int do_tmpfile(int dfd, struct filename *pathname,
 | 
			
		|||
	if (error)
 | 
			
		||||
		goto out2;
 | 
			
		||||
	error = open_check_o_direct(file);
 | 
			
		||||
	if (error)
 | 
			
		||||
	if (error) {
 | 
			
		||||
		fput(file);
 | 
			
		||||
	} else if (!(op->open_flag & O_EXCL)) {
 | 
			
		||||
		struct inode *inode = file_inode(file);
 | 
			
		||||
		spin_lock(&inode->i_lock);
 | 
			
		||||
		inode->i_state |= I_LINKABLE;
 | 
			
		||||
		spin_unlock(&inode->i_lock);
 | 
			
		||||
	}
 | 
			
		||||
out2:
 | 
			
		||||
	mnt_drop_write(nd->path.mnt);
 | 
			
		||||
out:
 | 
			
		||||
| 
						 | 
				
			
			@ -3628,12 +3634,18 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
 | 
			
		|||
 | 
			
		||||
	mutex_lock(&inode->i_mutex);
 | 
			
		||||
	/* Make sure we don't allow creating hardlink to an unlinked file */
 | 
			
		||||
	if (inode->i_nlink == 0)
 | 
			
		||||
	if (inode->i_nlink == 0 && !(inode->i_state & I_LINKABLE))
 | 
			
		||||
		error =  -ENOENT;
 | 
			
		||||
	else if (max_links && inode->i_nlink >= max_links)
 | 
			
		||||
		error = -EMLINK;
 | 
			
		||||
	else
 | 
			
		||||
		error = dir->i_op->link(old_dentry, dir, new_dentry);
 | 
			
		||||
 | 
			
		||||
	if (!error && (inode->i_state & I_LINKABLE)) {
 | 
			
		||||
		spin_lock(&inode->i_lock);
 | 
			
		||||
		inode->i_state &= ~I_LINKABLE;
 | 
			
		||||
		spin_unlock(&inode->i_lock);
 | 
			
		||||
	}
 | 
			
		||||
	mutex_unlock(&inode->i_mutex);
 | 
			
		||||
	if (!error)
 | 
			
		||||
		fsnotify_link(dir, inode, new_dentry);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1744,6 +1744,7 @@ struct super_operations {
 | 
			
		|||
#define I_REFERENCED		(1 << 8)
 | 
			
		||||
#define __I_DIO_WAKEUP		9
 | 
			
		||||
#define I_DIO_WAKEUP		(1 << I_DIO_WAKEUP)
 | 
			
		||||
#define I_LINKABLE		(1 << 10)
 | 
			
		||||
 | 
			
		||||
#define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue