|
@@ -345,13 +345,23 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
|
|
struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
|
|
struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
|
|
struct inode *inode;
|
|
struct inode *inode;
|
|
size_t len = strlen(symname);
|
|
size_t len = strlen(symname);
|
|
- size_t p_len;
|
|
|
|
- char *p_str;
|
|
|
|
- struct f2fs_str disk_link = FSTR_INIT(NULL, 0);
|
|
|
|
|
|
+ struct f2fs_str disk_link = FSTR_INIT((char *)symname, len + 1);
|
|
struct f2fs_encrypted_symlink_data *sd = NULL;
|
|
struct f2fs_encrypted_symlink_data *sd = NULL;
|
|
int err;
|
|
int err;
|
|
|
|
|
|
- if (len > dir->i_sb->s_blocksize)
|
|
|
|
|
|
+ if (f2fs_encrypted_inode(dir)) {
|
|
|
|
+ err = f2fs_get_encryption_info(dir);
|
|
|
|
+ if (err)
|
|
|
|
+ return err;
|
|
|
|
+
|
|
|
|
+ if (!f2fs_encrypted_inode(dir))
|
|
|
|
+ return -EPERM;
|
|
|
|
+
|
|
|
|
+ disk_link.len = (f2fs_fname_encrypted_size(dir, len) +
|
|
|
|
+ sizeof(struct f2fs_encrypted_symlink_data));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (disk_link.len > dir->i_sb->s_blocksize)
|
|
return -ENAMETOOLONG;
|
|
return -ENAMETOOLONG;
|
|
|
|
|
|
inode = f2fs_new_inode(dir, S_IFLNK | S_IRWXUGO);
|
|
inode = f2fs_new_inode(dir, S_IFLNK | S_IRWXUGO);
|
|
@@ -374,42 +384,36 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
|
|
f2fs_unlock_op(sbi);
|
|
f2fs_unlock_op(sbi);
|
|
alloc_nid_done(sbi, inode->i_ino);
|
|
alloc_nid_done(sbi, inode->i_ino);
|
|
|
|
|
|
- if (f2fs_encrypted_inode(dir)) {
|
|
|
|
|
|
+ if (f2fs_encrypted_inode(inode)) {
|
|
struct qstr istr = QSTR_INIT(symname, len);
|
|
struct qstr istr = QSTR_INIT(symname, len);
|
|
|
|
+ struct f2fs_str ostr;
|
|
|
|
|
|
- err = f2fs_get_encryption_info(inode);
|
|
|
|
- if (err)
|
|
|
|
|
|
+ sd = kzalloc(disk_link.len, GFP_NOFS);
|
|
|
|
+ if (!sd) {
|
|
|
|
+ err = -ENOMEM;
|
|
goto err_out;
|
|
goto err_out;
|
|
|
|
+ }
|
|
|
|
|
|
- err = f2fs_fname_crypto_alloc_buffer(inode, len, &disk_link);
|
|
|
|
|
|
+ err = f2fs_get_encryption_info(inode);
|
|
if (err)
|
|
if (err)
|
|
goto err_out;
|
|
goto err_out;
|
|
|
|
|
|
- err = f2fs_fname_usr_to_disk(inode, &istr, &disk_link);
|
|
|
|
- if (err < 0)
|
|
|
|
- goto err_out;
|
|
|
|
-
|
|
|
|
- p_len = encrypted_symlink_data_len(disk_link.len) + 1;
|
|
|
|
-
|
|
|
|
- if (p_len > dir->i_sb->s_blocksize) {
|
|
|
|
- err = -ENAMETOOLONG;
|
|
|
|
|
|
+ if (!f2fs_encrypted_inode(inode)) {
|
|
|
|
+ err = -EPERM;
|
|
goto err_out;
|
|
goto err_out;
|
|
}
|
|
}
|
|
|
|
|
|
- sd = kzalloc(p_len, GFP_NOFS);
|
|
|
|
- if (!sd) {
|
|
|
|
- err = -ENOMEM;
|
|
|
|
|
|
+ ostr.name = sd->encrypted_path;
|
|
|
|
+ ostr.len = disk_link.len;
|
|
|
|
+ err = f2fs_fname_usr_to_disk(inode, &istr, &ostr);
|
|
|
|
+ if (err < 0)
|
|
goto err_out;
|
|
goto err_out;
|
|
- }
|
|
|
|
- memcpy(sd->encrypted_path, disk_link.name, disk_link.len);
|
|
|
|
- sd->len = cpu_to_le16(disk_link.len);
|
|
|
|
- p_str = (char *)sd;
|
|
|
|
- } else {
|
|
|
|
- p_len = len + 1;
|
|
|
|
- p_str = (char *)symname;
|
|
|
|
|
|
+
|
|
|
|
+ sd->len = cpu_to_le16(ostr.len);
|
|
|
|
+ disk_link.name = (char *)sd;
|
|
}
|
|
}
|
|
|
|
|
|
- err = page_symlink(inode, p_str, p_len);
|
|
|
|
|
|
+ err = page_symlink(inode, disk_link.name, disk_link.len);
|
|
|
|
|
|
err_out:
|
|
err_out:
|
|
d_instantiate(dentry, inode);
|
|
d_instantiate(dentry, inode);
|
|
@@ -425,7 +429,8 @@ err_out:
|
|
* performance regression.
|
|
* performance regression.
|
|
*/
|
|
*/
|
|
if (!err) {
|
|
if (!err) {
|
|
- filemap_write_and_wait_range(inode->i_mapping, 0, p_len - 1);
|
|
|
|
|
|
+ filemap_write_and_wait_range(inode->i_mapping, 0,
|
|
|
|
+ disk_link.len - 1);
|
|
|
|
|
|
if (IS_DIRSYNC(dir))
|
|
if (IS_DIRSYNC(dir))
|
|
f2fs_sync_fs(sbi->sb, 1);
|
|
f2fs_sync_fs(sbi->sb, 1);
|
|
@@ -434,7 +439,6 @@ err_out:
|
|
}
|
|
}
|
|
|
|
|
|
kfree(sd);
|
|
kfree(sd);
|
|
- f2fs_fname_crypto_free_buffer(&disk_link);
|
|
|
|
return err;
|
|
return err;
|
|
out:
|
|
out:
|
|
handle_failed_inode(inode);
|
|
handle_failed_inode(inode);
|
|
@@ -966,6 +970,7 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry,
|
|
|
|
|
|
/* Symlink is encrypted */
|
|
/* Symlink is encrypted */
|
|
sd = (struct f2fs_encrypted_symlink_data *)caddr;
|
|
sd = (struct f2fs_encrypted_symlink_data *)caddr;
|
|
|
|
+ cstr.name = sd->encrypted_path;
|
|
cstr.len = le16_to_cpu(sd->len);
|
|
cstr.len = le16_to_cpu(sd->len);
|
|
|
|
|
|
/* this is broken symlink case */
|
|
/* this is broken symlink case */
|
|
@@ -973,12 +978,6 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry,
|
|
res = -ENOENT;
|
|
res = -ENOENT;
|
|
goto errout;
|
|
goto errout;
|
|
}
|
|
}
|
|
- cstr.name = kmalloc(cstr.len, GFP_NOFS);
|
|
|
|
- if (!cstr.name) {
|
|
|
|
- res = -ENOMEM;
|
|
|
|
- goto errout;
|
|
|
|
- }
|
|
|
|
- memcpy(cstr.name, sd->encrypted_path, cstr.len);
|
|
|
|
|
|
|
|
/* this is broken symlink case */
|
|
/* this is broken symlink case */
|
|
if (unlikely(cstr.name[0] == 0)) {
|
|
if (unlikely(cstr.name[0] == 0)) {
|
|
@@ -1000,8 +999,6 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry,
|
|
if (res < 0)
|
|
if (res < 0)
|
|
goto errout;
|
|
goto errout;
|
|
|
|
|
|
- kfree(cstr.name);
|
|
|
|
-
|
|
|
|
paddr = pstr.name;
|
|
paddr = pstr.name;
|
|
|
|
|
|
/* Null-terminate the name */
|
|
/* Null-terminate the name */
|
|
@@ -1011,7 +1008,6 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry,
|
|
set_delayed_call(done, kfree_link, paddr);
|
|
set_delayed_call(done, kfree_link, paddr);
|
|
return paddr;
|
|
return paddr;
|
|
errout:
|
|
errout:
|
|
- kfree(cstr.name);
|
|
|
|
f2fs_fname_crypto_free_buffer(&pstr);
|
|
f2fs_fname_crypto_free_buffer(&pstr);
|
|
page_cache_release(cpage);
|
|
page_cache_release(cpage);
|
|
return ERR_PTR(res);
|
|
return ERR_PTR(res);
|