Commit 8a23348d authored by Richard Weinberger's avatar Richard Weinberger Committed by Greg Kroah-Hartman

ubifs: xattr: Don't operate on deleted inodes

commit 11a6fc3d upstream.

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: 1e51764a ("UBIFS: add new flash file system")
Signed-off-by: Richard Weinberger's avatarRichard Weinberger <richard@nod.at>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f6d7acc1
......@@ -152,6 +152,12 @@ static int create_xattr(struct ubifs_info *c, struct inode *host,
ui->data_len = size;
mutex_lock(&host_ui->ui_mutex);
if (!host->i_nlink) {
err = -ENOENT;
goto out_noent;
}
host->i_ctime = current_time(host);
host_ui->xattr_cnt += 1;
host_ui->xattr_size += CALC_DENT_SIZE(fname_len(nm));
......@@ -183,6 +189,7 @@ static int create_xattr(struct ubifs_info *c, struct inode *host,
host_ui->xattr_size -= CALC_XATTR_BYTES(size);
host_ui->xattr_names -= fname_len(nm);
host_ui->flags &= ~UBIFS_CRYPT_FL;
out_noent:
mutex_unlock(&host_ui->ui_mutex);
out_free:
make_bad_inode(inode);
......@@ -234,6 +241,12 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
mutex_unlock(&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_ui->xattr_size -= CALC_XATTR_BYTES(old_size);
host_ui->xattr_size += CALC_XATTR_BYTES(size);
......@@ -255,6 +268,7 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
out_cancel:
host_ui->xattr_size -= CALC_XATTR_BYTES(size);
host_ui->xattr_size += CALC_XATTR_BYTES(old_size);
out_noent:
mutex_unlock(&host_ui->ui_mutex);
make_bad_inode(inode);
out_free:
......@@ -483,6 +497,12 @@ static int remove_xattr(struct ubifs_info *c, struct inode *host,
return err;
mutex_lock(&host_ui->ui_mutex);
if (!host->i_nlink) {
err = -ENOENT;
goto out_noent;
}
host->i_ctime = current_time(host);
host_ui->xattr_cnt -= 1;
host_ui->xattr_size -= CALC_DENT_SIZE(fname_len(nm));
......@@ -502,6 +522,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_XATTR_BYTES(ui->data_len);
host_ui->xattr_names += fname_len(nm);
out_noent:
mutex_unlock(&host_ui->ui_mutex);
ubifs_release_budget(c, &req);
make_bad_inode(inode);
......@@ -541,6 +562,9 @@ static int ubifs_xattr_remove(struct inode *host, const char *name)
ubifs_assert(inode_is_locked(host));
if (!host->i_nlink)
return -ENOENT;
if (fname_len(&nm) > UBIFS_MAX_NLEN)
return -ENAMETOOLONG;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment