summaryrefslogtreecommitdiffstats
path: root/fs/ubifs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ubifs/dir.c')
-rw-r--r--fs/ubifs/dir.c298
1 files changed, 255 insertions, 43 deletions
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 8c230da8f3..a16546e615 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -42,15 +42,26 @@
#include "ubifs.h"
+/*
+ * removed in barebox
+static int inherit_flags(const struct inode *dir, umode_t mode)
+ */
+
+/*
+ * removed in barebox
+struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
+ umode_t mode)
+ */
+
static int dbg_check_name(const struct ubifs_info *c,
const struct ubifs_dent_node *dent,
- const struct qstr *nm)
+ const struct fscrypt_name *nm)
{
if (!dbg_is_chk_gen(c))
return 0;
- if (le16_to_cpu(dent->nlen) != nm->len)
+ if (le16_to_cpu(dent->nlen) != fname_len(nm))
return -EINVAL;
- if (memcmp(dent->name, nm->name, nm->len))
+ if (memcmp(dent->name, fname_name(nm), fname_len(nm)))
return -EINVAL;
return 0;
}
@@ -61,32 +72,52 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
int err;
union ubifs_key key;
struct inode *inode = NULL;
- struct ubifs_dent_node *dent;
+ struct ubifs_dent_node *dent = NULL;
struct ubifs_info *c = dir->i_sb->s_fs_info;
+ struct fscrypt_name nm;
dbg_gen("'%pd' in dir ino %lu", dentry, dir->i_ino);
- if (dentry->d_name.len > UBIFS_MAX_NLEN)
- return ERR_PTR(-ENAMETOOLONG);
+ err = fscrypt_prepare_lookup(dir, dentry, flags);
+ if (err)
+ return ERR_PTR(err);
+
+ err = fscrypt_setup_filename(dir, &dentry->d_name, 1, &nm);
+ if (err)
+ return ERR_PTR(err);
+
+ if (fname_len(&nm) > UBIFS_MAX_NLEN) {
+ inode = ERR_PTR(-ENAMETOOLONG);
+ goto done;
+ }
dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
- if (!dent)
- return ERR_PTR(-ENOMEM);
+ if (!dent) {
+ inode = ERR_PTR(-ENOMEM);
+ goto done;
+ }
- dent_key_init(c, &key, dir->i_ino, &dentry->d_name);
+ if (nm.hash) {
+ ubifs_assert(c, fname_len(&nm) == 0);
+ ubifs_assert(c, fname_name(&nm) == NULL);
+ dent_key_init_hash(c, &key, dir->i_ino, nm.hash);
+ err = ubifs_tnc_lookup_dh(c, &key, dent, nm.minor_hash);
+ } else {
+ dent_key_init(c, &key, dir->i_ino, &nm);
+ err = ubifs_tnc_lookup_nm(c, &key, dent, &nm);
+ }
- err = ubifs_tnc_lookup_nm(c, &key, dent, &dentry->d_name);
if (err) {
- if (err == -ENOENT) {
+ if (err == -ENOENT)
dbg_gen("not found");
- goto done;
- }
- goto out;
+ else
+ inode = ERR_PTR(err);
+ goto done;
}
- if (dbg_check_name(c, dent, &dentry->d_name)) {
- err = -EINVAL;
- goto out;
+ if (dbg_check_name(c, dent, &nm)) {
+ inode = ERR_PTR(-EINVAL);
+ goto done;
}
inode = ubifs_iget(dir->i_sb, le64_to_cpu(dent->inum));
@@ -97,25 +128,45 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
*/
err = PTR_ERR(inode);
ubifs_err(c, "dead directory entry '%pd', error %d",
- dentry, err);
+ dentry, err);
ubifs_ro_mode(c, err);
- goto out;
+ goto done;
+ }
+
+ if (ubifs_crypt_is_encrypted(dir) &&
+ (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) &&
+ !fscrypt_has_permitted_context(dir, inode)) {
+ ubifs_warn(c, "Inconsistent encryption contexts: %lu/%lu",
+ dir->i_ino, inode->i_ino);
+ iput(inode);
+ inode = ERR_PTR(-EPERM);
}
done:
kfree(dent);
- /*
- * Note, d_splice_alias() would be required instead if we supported
- * NFS.
- */
+ fscrypt_free_filename(&nm);
d_add(dentry, inode);
return NULL;
-
-out:
- kfree(dent);
- return ERR_PTR(err);
}
+/*
+ * removed in barebox
+static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+ bool excl)
+ */
+
+/*
+ * removed in barebox
+static int do_tmpfile(struct inode *dir, struct dentry *dentry,
+ umode_t mode, struct inode **whiteout)
+ */
+
+/*
+ * removed in barebox
+static int ubifs_tmpfile(struct inode *dir, struct dentry *dentry,
+ umode_t mode)
+ */
+
/**
* vfs_dent_type - get VFS directory entry type.
* @type: UBIFS directory entry type
@@ -165,13 +216,14 @@ static unsigned int vfs_dent_type(uint8_t type)
*/
static int ubifs_readdir(struct file *file, struct dir_context *ctx)
{
- int err = 0;
- struct qstr nm;
+ int fstr_real_len = 0, err = 0;
+ struct fscrypt_name nm;
+ struct fscrypt_str fstr = {0};
union ubifs_key key;
struct ubifs_dent_node *dent;
- struct dentry *dentry = file->f_path.dentry;
- struct inode *dir = d_inode(dentry);
+ struct inode *dir = file_inode(file);
struct ubifs_info *c = dir->i_sb->s_fs_info;
+ bool encrypted = ubifs_crypt_is_encrypted(dir);
dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, ctx->pos);
@@ -182,6 +234,18 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx)
*/
return 0;
+ if (encrypted) {
+ err = fscrypt_get_encryption_info(dir);
+ if (err && err != -ENOKEY)
+ return err;
+
+ err = fscrypt_fname_alloc_buffer(dir, UBIFS_MAX_NLEN, &fstr);
+ if (err)
+ return err;
+
+ fstr_real_len = fstr.len;
+ }
+
if (file->f_version == 0) {
/*
* The file was seek'ed, which means that @file->private_data
@@ -202,12 +266,16 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx)
/* File positions 0 and 1 correspond to "." and ".." */
if (ctx->pos < 2) {
- ubifs_assert(!file->private_data);
- dir_emit_dots(file, ctx);
+ ubifs_assert(c, !file->private_data);
+ if (!dir_emit_dots(file, ctx)) {
+ if (encrypted)
+ fscrypt_fname_free_buffer(&fstr);
+ return 0;
+ }
/* Find the first entry in TNC and save it */
lowest_dent_key(c, &key, dir->i_ino);
- nm.name = NULL;
+ fname_len(&nm) = 0;
dent = ubifs_tnc_next_ent(c, &key, &nm);
if (IS_ERR(dent)) {
err = PTR_ERR(dent);
@@ -225,7 +293,7 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx)
* Find the entry corresponding to @ctx->pos or the closest one.
*/
dent_key_init_hash(c, &key, dir->i_ino, ctx->pos);
- nm.name = NULL;
+ fname_len(&nm) = 0;
dent = ubifs_tnc_next_ent(c, &key, &nm);
if (IS_ERR(dent)) {
err = PTR_ERR(dent);
@@ -236,20 +304,39 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx)
}
while (1) {
- dbg_gen("feed '%s', ino %llu, new f_pos %#x",
- dent->name, (unsigned long long)le64_to_cpu(dent->inum),
+ dbg_gen("ino %llu, new f_pos %#x",
+ (unsigned long long)le64_to_cpu(dent->inum),
key_hash_flash(c, &dent->key));
- ubifs_assert(le64_to_cpu(dent->ch.sqnum) >
+ ubifs_assert(c, le64_to_cpu(dent->ch.sqnum) >
ubifs_inode(dir)->creat_sqnum);
- nm.len = le16_to_cpu(dent->nlen);
- dir_emit(ctx, dent->name, nm.len,
+ fname_len(&nm) = le16_to_cpu(dent->nlen);
+ fname_name(&nm) = dent->name;
+
+ if (encrypted) {
+ fstr.len = fstr_real_len;
+
+ err = fscrypt_fname_disk_to_usr(dir, key_hash_flash(c,
+ &dent->key),
+ le32_to_cpu(dent->cookie),
+ &nm.disk_name, &fstr);
+ if (err)
+ goto out;
+ } else {
+ fstr.len = fname_len(&nm);
+ fstr.name = fname_name(&nm);
+ }
+
+ if (!dir_emit(ctx, fstr.name, fstr.len,
le64_to_cpu(dent->inum),
- vfs_dent_type(dent->type));
+ vfs_dent_type(dent->type))) {
+ if (encrypted)
+ fscrypt_fname_free_buffer(&fstr);
+ return 0;
+ }
/* Switch to the next entry */
key_read(c, &dent->key, &key);
- nm.name = dent->name;
dent = ubifs_tnc_next_ent(c, &key, &nm);
if (IS_ERR(dent)) {
err = PTR_ERR(dent);
@@ -266,6 +353,9 @@ out:
kfree(file->private_data);
file->private_data = NULL;
+ if (encrypted)
+ fscrypt_fname_free_buffer(&fstr);
+
if (err != -ENOENT)
ubifs_err(c, "cannot find next direntry, error %d", err);
else
@@ -282,10 +372,132 @@ out:
return err;
}
+/*
+ * removed in barebox
+static int ubifs_dir_release(struct inode *dir, struct file *file)
+ */
+
+/*
+ * removed in barebox
+static void lock_2_inodes(struct inode *inode1, struct inode *inode2)
+ */
+
+/*
+ * removed in barebox
+static void unlock_2_inodes(struct inode *inode1, struct inode *inode2)
+ */
+
+/*
+ * removed in barebox
+static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
+ struct dentry *dentry)
+ */
+
+/*
+ * removed in barebox
+static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
+ */
+
+/*
+ * removed in barebox
+int ubifs_check_dir_empty(struct inode *dir)
+ */
+
+/*
+ * removed in barebox
+static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
+ */
+
+/*
+ * removed in barebox
+static int ubifs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+ */
+
+/*
+ * removed in barebox
+static int ubifs_mknod(struct inode *dir, struct dentry *dentry,
+ umode_t mode, dev_t rdev)
+ */
+
+/*
+ * removed in barebox
+static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
+ const char *symname)
+ */
+
+/*
+ * removed in barebox
+static void lock_4_inodes(struct inode *inode1, struct inode *inode2,
+ struct inode *inode3, struct inode *inode4)
+ */
+
+/*
+ * removed in barebox
+static void unlock_4_inodes(struct inode *inode1, struct inode *inode2,
+ struct inode *inode3, struct inode *inode4)
+ */
+
+/*
+ * removed in barebox
+static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry,
+ unsigned int flags)
+ */
+
+/*
+ * removed in barebox
+static int ubifs_xrename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
+ */
+
+/*
+ * removed in barebox
+static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry,
+ unsigned int flags)
+ */
+
+/*
+ * removed in barebox
+int ubifs_getattr(const struct path *path, struct kstat *stat,
+ u32 request_mask, unsigned int flags)
+ */
+
+/*
+ * removed in barebox
+static int ubifs_dir_open(struct inode *dir, struct file *file)
+ */
+
const struct inode_operations ubifs_dir_inode_operations = {
.lookup = ubifs_lookup,
+ .create = NULL, /* not present in barebox */
+ .link = NULL, /* not present in barebox */
+ .symlink = NULL, /* not present in barebox */
+ .unlink = NULL, /* not present in barebox */
+ .mkdir = NULL, /* not present in barebox */
+ .rmdir = NULL, /* not present in barebox */
+/* .mknod = NULL, not present in barebox */
+ .rename = NULL, /* not present in barebox */
+/* .setattr = NULL, not present in barebox */
+/* .getattr = NULL, not present in barebox */
+#ifdef CONFIG_UBIFS_FS_XATTR
+ .listxattr = NULL, /* not present in barebox */
+#endif
+#ifdef CONFIG_UBIFS_ATIME_SUPPORT
+ .update_time = NULL, /* not present in barebox */
+#endif
+/* .tmpfile = NULL, not present in barebox */
};
const struct file_operations ubifs_dir_operations = {
- .iterate = ubifs_readdir,
+/* .llseek = NULL, not present in barebox */
+/* .release = NULL, not present in barebox */
+ .read = NULL, /* not present in barebox */
+ .iterate = ubifs_readdir,
+/* .fsync = NULL, not present in barebox */
+/* .unlocked_ioctl = NULL, not present in barebox */
+/* .open = NULL, not present in barebox */
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = NULL, /* not present in barebox */
+#endif
};