mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	ubifs: xattr: Don't operate on deleted inodes
xattr operations can race with unlink and the following assert triggers:
UBIFS assert failed in ubifs_jnl_change_xattr at 1606 (pid 6256)
Fix this by checking i_nlink before working on the host inode.
Cc: <stable@vger.kernel.org>
Fixes: 1e51764a3c ("UBIFS: add new flash file system")
Signed-off-by: Richard Weinberger <richard@nod.at>
			
			
This commit is contained in:
		
							parent
							
								
									312c39bd6d
								
							
						
					
					
						commit
						11a6fc3dc7
					
				
					 1 changed files with 24 additions and 0 deletions
				
			
		| 
						 | 
					@ -152,6 +152,12 @@ static int create_xattr(struct ubifs_info *c, struct inode *host,
 | 
				
			||||||
	ui->data_len = size;
 | 
						ui->data_len = size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&host_ui->ui_mutex);
 | 
						mutex_lock(&host_ui->ui_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!host->i_nlink) {
 | 
				
			||||||
 | 
							err = -ENOENT;
 | 
				
			||||||
 | 
							goto out_noent;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	host->i_ctime = current_time(host);
 | 
						host->i_ctime = current_time(host);
 | 
				
			||||||
	host_ui->xattr_cnt += 1;
 | 
						host_ui->xattr_cnt += 1;
 | 
				
			||||||
	host_ui->xattr_size += CALC_DENT_SIZE(fname_len(nm));
 | 
						host_ui->xattr_size += CALC_DENT_SIZE(fname_len(nm));
 | 
				
			||||||
| 
						 | 
					@ -184,6 +190,7 @@ static int create_xattr(struct ubifs_info *c, struct inode *host,
 | 
				
			||||||
	host_ui->xattr_size -= CALC_XATTR_BYTES(size);
 | 
						host_ui->xattr_size -= CALC_XATTR_BYTES(size);
 | 
				
			||||||
	host_ui->xattr_names -= fname_len(nm);
 | 
						host_ui->xattr_names -= fname_len(nm);
 | 
				
			||||||
	host_ui->flags &= ~UBIFS_CRYPT_FL;
 | 
						host_ui->flags &= ~UBIFS_CRYPT_FL;
 | 
				
			||||||
 | 
					out_noent:
 | 
				
			||||||
	mutex_unlock(&host_ui->ui_mutex);
 | 
						mutex_unlock(&host_ui->ui_mutex);
 | 
				
			||||||
out_free:
 | 
					out_free:
 | 
				
			||||||
	make_bad_inode(inode);
 | 
						make_bad_inode(inode);
 | 
				
			||||||
| 
						 | 
					@ -235,6 +242,12 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
 | 
				
			||||||
	mutex_unlock(&ui->ui_mutex);
 | 
						mutex_unlock(&ui->ui_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&host_ui->ui_mutex);
 | 
						mutex_lock(&host_ui->ui_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!host->i_nlink) {
 | 
				
			||||||
 | 
							err = -ENOENT;
 | 
				
			||||||
 | 
							goto out_noent;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	host->i_ctime = current_time(host);
 | 
						host->i_ctime = current_time(host);
 | 
				
			||||||
	host_ui->xattr_size -= CALC_XATTR_BYTES(old_size);
 | 
						host_ui->xattr_size -= CALC_XATTR_BYTES(old_size);
 | 
				
			||||||
	host_ui->xattr_size += CALC_XATTR_BYTES(size);
 | 
						host_ui->xattr_size += CALC_XATTR_BYTES(size);
 | 
				
			||||||
| 
						 | 
					@ -256,6 +269,7 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
 | 
				
			||||||
out_cancel:
 | 
					out_cancel:
 | 
				
			||||||
	host_ui->xattr_size -= CALC_XATTR_BYTES(size);
 | 
						host_ui->xattr_size -= CALC_XATTR_BYTES(size);
 | 
				
			||||||
	host_ui->xattr_size += CALC_XATTR_BYTES(old_size);
 | 
						host_ui->xattr_size += CALC_XATTR_BYTES(old_size);
 | 
				
			||||||
 | 
					out_noent:
 | 
				
			||||||
	mutex_unlock(&host_ui->ui_mutex);
 | 
						mutex_unlock(&host_ui->ui_mutex);
 | 
				
			||||||
	make_bad_inode(inode);
 | 
						make_bad_inode(inode);
 | 
				
			||||||
out_free:
 | 
					out_free:
 | 
				
			||||||
| 
						 | 
					@ -482,6 +496,12 @@ static int remove_xattr(struct ubifs_info *c, struct inode *host,
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&host_ui->ui_mutex);
 | 
						mutex_lock(&host_ui->ui_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!host->i_nlink) {
 | 
				
			||||||
 | 
							err = -ENOENT;
 | 
				
			||||||
 | 
							goto out_noent;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	host->i_ctime = current_time(host);
 | 
						host->i_ctime = current_time(host);
 | 
				
			||||||
	host_ui->xattr_cnt -= 1;
 | 
						host_ui->xattr_cnt -= 1;
 | 
				
			||||||
	host_ui->xattr_size -= CALC_DENT_SIZE(fname_len(nm));
 | 
						host_ui->xattr_size -= CALC_DENT_SIZE(fname_len(nm));
 | 
				
			||||||
| 
						 | 
					@ -501,6 +521,7 @@ static int remove_xattr(struct ubifs_info *c, struct inode *host,
 | 
				
			||||||
	host_ui->xattr_size += CALC_DENT_SIZE(fname_len(nm));
 | 
						host_ui->xattr_size += CALC_DENT_SIZE(fname_len(nm));
 | 
				
			||||||
	host_ui->xattr_size += CALC_XATTR_BYTES(ui->data_len);
 | 
						host_ui->xattr_size += CALC_XATTR_BYTES(ui->data_len);
 | 
				
			||||||
	host_ui->xattr_names += fname_len(nm);
 | 
						host_ui->xattr_names += fname_len(nm);
 | 
				
			||||||
 | 
					out_noent:
 | 
				
			||||||
	mutex_unlock(&host_ui->ui_mutex);
 | 
						mutex_unlock(&host_ui->ui_mutex);
 | 
				
			||||||
	ubifs_release_budget(c, &req);
 | 
						ubifs_release_budget(c, &req);
 | 
				
			||||||
	make_bad_inode(inode);
 | 
						make_bad_inode(inode);
 | 
				
			||||||
| 
						 | 
					@ -540,6 +561,9 @@ static int ubifs_xattr_remove(struct inode *host, const char *name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ubifs_assert(inode_is_locked(host));
 | 
						ubifs_assert(inode_is_locked(host));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!host->i_nlink)
 | 
				
			||||||
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (fname_len(&nm) > UBIFS_MAX_NLEN)
 | 
						if (fname_len(&nm) > UBIFS_MAX_NLEN)
 | 
				
			||||||
		return -ENAMETOOLONG;
 | 
							return -ENAMETOOLONG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue