Skip to content

Commit 7a400bf

Browse files
committed
Merge tag 'for-linus-5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs
Pull UBIFS updates from Richard Weinberger: - Fix for a race xattr list and modification - Various minor fixes (spelling, return codes, ...) * tag 'for-linus-5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs: ubifs: Set/Clear I_LINKABLE under i_lock for whiteout inode ubifs: Fix spelling mistakes ubifs: Remove ui_mutex in ubifs_xattr_get and change_xattr ubifs: Fix races between xattr_{set|get} and listxattr operations ubifs: fix snprintf() checking ubifs: journal: Fix error return code in ubifs_jnl_write_inode()
2 parents e49d68c + a801fcf commit 7a400bf

10 files changed

Lines changed: 52 additions & 23 deletions

File tree

drivers/mtd/ubi/debug.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi)
511511

512512
n = snprintf(d->dfs_dir_name, UBI_DFS_DIR_LEN + 1, UBI_DFS_DIR_NAME,
513513
ubi->ubi_num);
514-
if (n == UBI_DFS_DIR_LEN) {
514+
if (n > UBI_DFS_DIR_LEN) {
515515
/* The array size is too small */
516516
return -EINVAL;
517517
}

fs/ubifs/debug.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2824,7 +2824,7 @@ void dbg_debugfs_init_fs(struct ubifs_info *c)
28242824

28252825
n = snprintf(d->dfs_dir_name, UBIFS_DFS_DIR_LEN + 1, UBIFS_DFS_DIR_NAME,
28262826
c->vi.ubi_num, c->vi.vol_id);
2827-
if (n == UBIFS_DFS_DIR_LEN) {
2827+
if (n > UBIFS_DFS_DIR_LEN) {
28282828
/* The array size is too small */
28292829
return;
28302830
}

fs/ubifs/dir.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,7 +1337,10 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
13371337
goto out_release;
13381338
}
13391339

1340+
spin_lock(&whiteout->i_lock);
13401341
whiteout->i_state |= I_LINKABLE;
1342+
spin_unlock(&whiteout->i_lock);
1343+
13411344
whiteout_ui = ubifs_inode(whiteout);
13421345
whiteout_ui->data = dev;
13431346
whiteout_ui->data_len = ubifs_encode_dev(dev, MKDEV(0, 0));
@@ -1430,7 +1433,11 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
14301433

14311434
inc_nlink(whiteout);
14321435
mark_inode_dirty(whiteout);
1436+
1437+
spin_lock(&whiteout->i_lock);
14331438
whiteout->i_state &= ~I_LINKABLE;
1439+
spin_unlock(&whiteout->i_lock);
1440+
14341441
iput(whiteout);
14351442
}
14361443

fs/ubifs/journal.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
882882
struct ubifs_dent_node *xent, *pxent = NULL;
883883

884884
if (ui->xattr_cnt > ubifs_xattr_max_cnt(c)) {
885+
err = -EPERM;
885886
ubifs_err(c, "Cannot delete inode, it has too much xattrs!");
886887
goto out_release;
887888
}
@@ -1431,7 +1432,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
14311432
/**
14321433
* truncate_data_node - re-compress/encrypt a truncated data node.
14331434
* @c: UBIFS file-system description object
1434-
* @inode: inode which referes to the data node
1435+
* @inode: inode which refers to the data node
14351436
* @block: data block number
14361437
* @dn: data node to re-compress
14371438
* @new_len: new length

fs/ubifs/master.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ int ubifs_compare_master_node(struct ubifs_info *c, void *m1, void *m2)
3737
return ret;
3838

3939
/*
40-
* Do not compare the embedded HMAC aswell which also must be different
40+
* Do not compare the embedded HMAC as well which also must be different
4141
* due to the different common node header.
4242
*/
4343
behind = hmac_offs + UBIFS_MAX_HMAC_LEN;

fs/ubifs/replay.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ static int apply_replay_entry(struct ubifs_info *c, struct replay_entry *r)
296296
* @b: second replay entry
297297
*
298298
* This is a comparios function for 'list_sort()' which compares 2 replay
299-
* entries @a and @b by comparing their sequence numer. Returns %1 if @a has
299+
* entries @a and @b by comparing their sequence number. Returns %1 if @a has
300300
* greater sequence number and %-1 otherwise.
301301
*/
302302
static int replay_entries_cmp(void *priv, const struct list_head *a,

fs/ubifs/super.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ static struct inode *ubifs_alloc_inode(struct super_block *sb)
275275
memset((void *)ui + sizeof(struct inode), 0,
276276
sizeof(struct ubifs_inode) - sizeof(struct inode));
277277
mutex_init(&ui->ui_mutex);
278+
init_rwsem(&ui->xattr_sem);
278279
spin_lock_init(&ui->ui_lock);
279280
return &ui->vfs_inode;
280281
};
@@ -2060,7 +2061,7 @@ const struct super_operations ubifs_super_operations = {
20602061
* @mode: UBI volume open mode
20612062
*
20622063
* The primary method of mounting UBIFS is by specifying the UBI volume
2063-
* character device node path. However, UBIFS may also be mounted withoug any
2064+
* character device node path. However, UBIFS may also be mounted without any
20642065
* character device node using one of the following methods:
20652066
*
20662067
* o ubiX_Y - mount UBI device number X, volume Y;

fs/ubifs/tnc_commit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -930,7 +930,7 @@ static int write_index(struct ubifs_info *c)
930930
* flag cleared before %COW_ZNODE. Specifically, it matters in
931931
* the 'dirty_cow_znode()' function. This is the reason for the
932932
* first barrier. Also, we want the bit changes to be seen to
933-
* other threads ASAP, to avoid unnecesarry copying, which is
933+
* other threads ASAP, to avoid unnecessary copying, which is
934934
* the reason for the second barrier.
935935
*/
936936
clear_bit(DIRTY_ZNODE, &znode->flags);

fs/ubifs/ubifs.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ struct ubifs_gced_idx_leb {
356356
* @ui_mutex: serializes inode write-back with the rest of VFS operations,
357357
* serializes "clean <-> dirty" state changes, serializes bulk-read,
358358
* protects @dirty, @bulk_read, @ui_size, and @xattr_size
359+
* @xattr_sem: serilizes write operations (remove|set|create) on xattr
359360
* @ui_lock: protects @synced_i_size
360361
* @synced_i_size: synchronized size of inode, i.e. the value of inode size
361362
* currently stored on the flash; used only for regular file
@@ -409,6 +410,7 @@ struct ubifs_inode {
409410
unsigned int bulk_read:1;
410411
unsigned int compr_type:2;
411412
struct mutex ui_mutex;
413+
struct rw_semaphore xattr_sem;
412414
spinlock_t ui_lock;
413415
loff_t synced_i_size;
414416
loff_t ui_size;
@@ -912,7 +914,7 @@ struct ubifs_budget_req {
912914
* @rb: rb-tree node of rb-tree of orphans sorted by inode number
913915
* @list: list head of list of orphans in order added
914916
* @new_list: list head of list of orphans added since the last commit
915-
* @child_list: list of xattr childs if this orphan hosts xattrs, list head
917+
* @child_list: list of xattr children if this orphan hosts xattrs, list head
916918
* if this orphan is a xattr, not used otherwise.
917919
* @cnext: next orphan to commit
918920
* @dnext: next orphan to delete

fs/ubifs/xattr.c

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -208,13 +208,11 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
208208
err = -ENOMEM;
209209
goto out_free;
210210
}
211-
mutex_lock(&ui->ui_mutex);
212211
kfree(ui->data);
213212
ui->data = buf;
214213
inode->i_size = ui->ui_size = size;
215214
old_size = ui->data_len;
216215
ui->data_len = size;
217-
mutex_unlock(&ui->ui_mutex);
218216

219217
mutex_lock(&host_ui->ui_mutex);
220218
host->i_ctime = current_time(host);
@@ -285,6 +283,7 @@ int ubifs_xattr_set(struct inode *host, const char *name, const void *value,
285283
if (!xent)
286284
return -ENOMEM;
287285

286+
down_write(&ubifs_inode(host)->xattr_sem);
288287
/*
289288
* The extended attribute entries are stored in LNC, so multiple
290289
* look-ups do not involve reading the flash.
@@ -319,6 +318,7 @@ int ubifs_xattr_set(struct inode *host, const char *name, const void *value,
319318
iput(inode);
320319

321320
out_free:
321+
up_write(&ubifs_inode(host)->xattr_sem);
322322
kfree(xent);
323323
return err;
324324
}
@@ -341,25 +341,25 @@ ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf,
341341
if (!xent)
342342
return -ENOMEM;
343343

344+
down_read(&ubifs_inode(host)->xattr_sem);
344345
xent_key_init(c, &key, host->i_ino, &nm);
345346
err = ubifs_tnc_lookup_nm(c, &key, xent, &nm);
346347
if (err) {
347348
if (err == -ENOENT)
348349
err = -ENODATA;
349-
goto out_unlock;
350+
goto out_cleanup;
350351
}
351352

352353
inode = iget_xattr(c, le64_to_cpu(xent->inum));
353354
if (IS_ERR(inode)) {
354355
err = PTR_ERR(inode);
355-
goto out_unlock;
356+
goto out_cleanup;
356357
}
357358

358359
ui = ubifs_inode(inode);
359360
ubifs_assert(c, inode->i_size == ui->data_len);
360361
ubifs_assert(c, ubifs_inode(host)->xattr_size > ui->data_len);
361362

362-
mutex_lock(&ui->ui_mutex);
363363
if (buf) {
364364
/* If @buf is %NULL we are supposed to return the length */
365365
if (ui->data_len > size) {
@@ -372,9 +372,9 @@ ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf,
372372
err = ui->data_len;
373373

374374
out_iput:
375-
mutex_unlock(&ui->ui_mutex);
376375
iput(inode);
377-
out_unlock:
376+
out_cleanup:
377+
up_read(&ubifs_inode(host)->xattr_sem);
378378
kfree(xent);
379379
return err;
380380
}
@@ -406,16 +406,21 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size)
406406
dbg_gen("ino %lu ('%pd'), buffer size %zd", host->i_ino,
407407
dentry, size);
408408

409+
down_read(&host_ui->xattr_sem);
409410
len = host_ui->xattr_names + host_ui->xattr_cnt;
410-
if (!buffer)
411+
if (!buffer) {
411412
/*
412413
* We should return the minimum buffer size which will fit a
413414
* null-terminated list of all the extended attribute names.
414415
*/
415-
return len;
416+
err = len;
417+
goto out_err;
418+
}
416419

417-
if (len > size)
418-
return -ERANGE;
420+
if (len > size) {
421+
err = -ERANGE;
422+
goto out_err;
423+
}
419424

420425
lowest_xent_key(c, &key, host->i_ino);
421426
while (1) {
@@ -437,15 +442,20 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size)
437442
pxent = xent;
438443
key_read(c, &xent->key, &key);
439444
}
440-
441445
kfree(pxent);
446+
up_read(&host_ui->xattr_sem);
447+
442448
if (err != -ENOENT) {
443449
ubifs_err(c, "cannot find next direntry, error %d", err);
444450
return err;
445451
}
446452

447453
ubifs_assert(c, written <= size);
448454
return written;
455+
456+
out_err:
457+
up_read(&host_ui->xattr_sem);
458+
return err;
449459
}
450460

451461
static int remove_xattr(struct ubifs_info *c, struct inode *host,
@@ -504,6 +514,7 @@ int ubifs_purge_xattrs(struct inode *host)
504514
ubifs_warn(c, "inode %lu has too many xattrs, doing a non-atomic deletion",
505515
host->i_ino);
506516

517+
down_write(&ubifs_inode(host)->xattr_sem);
507518
lowest_xent_key(c, &key, host->i_ino);
508519
while (1) {
509520
xent = ubifs_tnc_next_ent(c, &key, &nm);
@@ -523,7 +534,7 @@ int ubifs_purge_xattrs(struct inode *host)
523534
ubifs_ro_mode(c, err);
524535
kfree(pxent);
525536
kfree(xent);
526-
return err;
537+
goto out_err;
527538
}
528539

529540
ubifs_assert(c, ubifs_inode(xino)->xattr);
@@ -535,7 +546,7 @@ int ubifs_purge_xattrs(struct inode *host)
535546
kfree(xent);
536547
iput(xino);
537548
ubifs_err(c, "cannot remove xattr, error %d", err);
538-
return err;
549+
goto out_err;
539550
}
540551

541552
iput(xino);
@@ -544,14 +555,19 @@ int ubifs_purge_xattrs(struct inode *host)
544555
pxent = xent;
545556
key_read(c, &xent->key, &key);
546557
}
547-
548558
kfree(pxent);
559+
up_write(&ubifs_inode(host)->xattr_sem);
560+
549561
if (err != -ENOENT) {
550562
ubifs_err(c, "cannot find next direntry, error %d", err);
551563
return err;
552564
}
553565

554566
return 0;
567+
568+
out_err:
569+
up_write(&ubifs_inode(host)->xattr_sem);
570+
return err;
555571
}
556572

557573
/**
@@ -594,6 +610,7 @@ static int ubifs_xattr_remove(struct inode *host, const char *name)
594610
if (!xent)
595611
return -ENOMEM;
596612

613+
down_write(&ubifs_inode(host)->xattr_sem);
597614
xent_key_init(c, &key, host->i_ino, &nm);
598615
err = ubifs_tnc_lookup_nm(c, &key, xent, &nm);
599616
if (err) {
@@ -618,6 +635,7 @@ static int ubifs_xattr_remove(struct inode *host, const char *name)
618635
iput(inode);
619636

620637
out_free:
638+
up_write(&ubifs_inode(host)->xattr_sem);
621639
kfree(xent);
622640
return err;
623641
}

0 commit comments

Comments
 (0)