Skip to content

Commit 9ca2d73

Browse files
ubifs: Limit number of xattrs per inode
Since we have to write one deletion inode per xattr into the journal, limit the max number of xattrs. In theory UBIFS supported up to 65535 xattrs per inode. But this never worked correctly, expect no powercuts happened. Now we support only as many xattrs as we can store in 50% of a LEB. Even for tiny flashes this allows dozens of xattrs per inode, which is for an embedded filesystem still fine. In case someone has existing inodes with much more xattrs, it is still possible to delete them. UBIFS will fall back to an non-atomic deletion mode. Reported-by: Stefan Agner <[email protected]> Fixes: 1e51764 ("UBIFS: add new flash file system") Signed-off-by: Richard Weinberger <[email protected]>
1 parent 988bec4 commit 9ca2d73

File tree

6 files changed

+101
-8
lines changed

6 files changed

+101
-8
lines changed

fs/ubifs/dir.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,10 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
796796
if (err)
797797
return err;
798798

799+
err = ubifs_purge_xattrs(inode);
800+
if (err)
801+
return err;
802+
799803
sz_change = CALC_DENT_SIZE(fname_len(&nm));
800804

801805
ubifs_assert(c, inode_is_locked(dir));
@@ -900,6 +904,10 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
900904
if (err)
901905
return err;
902906

907+
err = ubifs_purge_xattrs(inode);
908+
if (err)
909+
return err;
910+
903911
sz_change = CALC_DENT_SIZE(fname_len(&nm));
904912

905913
err = ubifs_budget_space(c, &req);
@@ -1282,9 +1290,14 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
12821290
old_dentry, old_inode->i_ino, old_dir->i_ino,
12831291
new_dentry, new_dir->i_ino, flags);
12841292

1285-
if (unlink)
1293+
if (unlink) {
12861294
ubifs_assert(c, inode_is_locked(new_inode));
12871295

1296+
err = ubifs_purge_xattrs(new_inode);
1297+
if (err)
1298+
return err;
1299+
}
1300+
12881301
if (unlink && is_dir) {
12891302
err = ubifs_check_dir_empty(new_inode);
12901303
if (err)

fs/ubifs/journal.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,11 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
892892
struct inode *xino;
893893
struct ubifs_dent_node *xent, *pxent = NULL;
894894

895+
if (ui->xattr_cnt >= ubifs_xattr_max_cnt(c)) {
896+
ubifs_err(c, "Cannot delete inode, it has too much xattrs!");
897+
goto out_release;
898+
}
899+
895900
lowest_xent_key(c, &key, inode->i_ino);
896901
while (1) {
897902
xent = ubifs_tnc_next_ent(c, &key, &nm);
@@ -907,6 +912,13 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
907912
fname_len(&nm) = le16_to_cpu(xent->nlen);
908913

909914
xino = ubifs_iget(c->vfs_sb, xent->inum);
915+
if (IS_ERR(xino)) {
916+
err = PTR_ERR(xino);
917+
ubifs_err(c, "dead directory entry '%s', error %d",
918+
xent->name, err);
919+
ubifs_ro_mode(c, err);
920+
goto out_release;
921+
}
910922
ubifs_assert(c, ubifs_inode(xino)->xattr);
911923

912924
clear_nlink(xino);

fs/ubifs/misc.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,14 @@ static inline int ubifs_next_log_lnum(const struct ubifs_info *c, int lnum)
288288
return lnum;
289289
}
290290

291+
static inline int ubifs_xattr_max_cnt(struct ubifs_info *c)
292+
{
293+
int max_xattrs = (c->leb_size / 2) / UBIFS_INO_NODE_SZ;
294+
295+
ubifs_assert(c, max_xattrs < c->max_orphans);
296+
return max_xattrs;
297+
}
298+
291299
const char *ubifs_assert_action_name(struct ubifs_info *c);
292300

293301
#endif /* __UBIFS_MISC_H__ */

fs/ubifs/super.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,6 +1548,8 @@ static int mount_ubifs(struct ubifs_info *c)
15481548
c->bud_bytes, c->bud_bytes >> 10, c->bud_bytes >> 20);
15491549
dbg_gen("max. seq. number: %llu", c->max_sqnum);
15501550
dbg_gen("commit number: %llu", c->cmt_no);
1551+
dbg_gen("max. xattrs per inode: %d", ubifs_xattr_max_cnt(c));
1552+
dbg_gen("max orphans: %d", c->max_orphans);
15511553

15521554
return 0;
15531555

fs/ubifs/ubifs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2017,6 +2017,7 @@ int ubifs_xattr_set(struct inode *host, const char *name, const void *value,
20172017
size_t size, int flags, bool check_lock);
20182018
ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf,
20192019
size_t size);
2020+
int ubifs_purge_xattrs(struct inode *host);
20202021

20212022
#ifdef CONFIG_UBIFS_FS_XATTR
20222023
void ubifs_evict_xattr_inode(struct ubifs_info *c, ino_t xattr_inum);

fs/ubifs/xattr.c

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,6 @@
6060
#include <linux/slab.h>
6161
#include <linux/xattr.h>
6262

63-
/*
64-
* Limit the number of extended attributes per inode so that the total size
65-
* (@xattr_size) is guaranteeded to fit in an 'unsigned int'.
66-
*/
67-
#define MAX_XATTRS_PER_INODE 65535
68-
6963
/*
7064
* Extended attribute type constants.
7165
*
@@ -106,7 +100,7 @@ static int create_xattr(struct ubifs_info *c, struct inode *host,
106100
.new_ino_d = ALIGN(size, 8), .dirtied_ino = 1,
107101
.dirtied_ino_d = ALIGN(host_ui->data_len, 8) };
108102

109-
if (host_ui->xattr_cnt >= MAX_XATTRS_PER_INODE) {
103+
if (host_ui->xattr_cnt >= ubifs_xattr_max_cnt(c)) {
110104
ubifs_err(c, "inode %lu already has too many xattrs (%d), cannot create more",
111105
host->i_ino, host_ui->xattr_cnt);
112106
return -ENOSPC;
@@ -507,6 +501,69 @@ static int remove_xattr(struct ubifs_info *c, struct inode *host,
507501
return err;
508502
}
509503

504+
int ubifs_purge_xattrs(struct inode *host)
505+
{
506+
union ubifs_key key;
507+
struct ubifs_info *c = host->i_sb->s_fs_info;
508+
struct ubifs_dent_node *xent, *pxent = NULL;
509+
struct inode *xino;
510+
struct fscrypt_name nm = {0};
511+
int err;
512+
513+
if (ubifs_inode(host)->xattr_cnt < ubifs_xattr_max_cnt(c))
514+
return 0;
515+
516+
ubifs_warn(c, "inode %lu has too many xattrs, doing a non-atomic deletion",
517+
host->i_ino);
518+
519+
lowest_xent_key(c, &key, host->i_ino);
520+
while (1) {
521+
xent = ubifs_tnc_next_ent(c, &key, &nm);
522+
if (IS_ERR(xent)) {
523+
err = PTR_ERR(xent);
524+
break;
525+
}
526+
527+
fname_name(&nm) = xent->name;
528+
fname_len(&nm) = le16_to_cpu(xent->nlen);
529+
530+
xino = ubifs_iget(c->vfs_sb, xent->inum);
531+
if (IS_ERR(xino)) {
532+
err = PTR_ERR(xino);
533+
ubifs_err(c, "dead directory entry '%s', error %d",
534+
xent->name, err);
535+
ubifs_ro_mode(c, err);
536+
kfree(pxent);
537+
return err;
538+
}
539+
540+
ubifs_assert(c, ubifs_inode(xino)->xattr);
541+
542+
clear_nlink(xino);
543+
err = remove_xattr(c, host, xino, &nm);
544+
if (err) {
545+
kfree(pxent);
546+
iput(xino);
547+
ubifs_err(c, "cannot remove xattr, error %d", err);
548+
return err;
549+
}
550+
551+
iput(xino);
552+
553+
kfree(pxent);
554+
pxent = xent;
555+
key_read(c, &xent->key, &key);
556+
}
557+
558+
kfree(pxent);
559+
if (err != -ENOENT) {
560+
ubifs_err(c, "cannot find next direntry, error %d", err);
561+
return err;
562+
}
563+
564+
return 0;
565+
}
566+
510567
/**
511568
* ubifs_evict_xattr_inode - Evict an xattr inode.
512569
* @c: UBIFS file-system description object

0 commit comments

Comments
 (0)