Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
ca7f85be
Commit
ca7f85be
authored
Oct 08, 2016
by
Richard Weinberger
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ubifs: Add support for encrypted symlinks
Signed-off-by:
Richard Weinberger
<
richard@nod.at
>
parent
f4f61d2c
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
126 additions
and
13 deletions
+126
-13
fs/ubifs/dir.c
fs/ubifs/dir.c
+72
-11
fs/ubifs/file.c
fs/ubifs/file.c
+54
-1
fs/ubifs/super.c
fs/ubifs/super.c
+0
-1
No files found.
fs/ubifs/dir.c
View file @
ca7f85be
...
...
@@ -629,7 +629,7 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx)
fstr
.
len
=
fstr_real_len
;
err
=
fscrypt_fname_disk_to_usr
(
dir
,
key_hash_flash
(
c
,
&
dent
->
key
),
0
,
&
nm
.
disk_name
,
&
fstr
);
if
(
err
<
0
)
if
(
err
)
goto
out
;
}
else
{
fstr
.
len
=
fname_len
(
&
nm
);
...
...
@@ -1164,10 +1164,27 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
struct
ubifs_inode
*
dir_ui
=
ubifs_inode
(
dir
);
struct
ubifs_info
*
c
=
dir
->
i_sb
->
s_fs_info
;
int
err
,
len
=
strlen
(
symname
);
int
sz_change
=
CALC_DENT_SIZE
(
dentry
->
d_name
.
len
);
int
sz_change
=
CALC_DENT_SIZE
(
len
);
struct
fscrypt_str
disk_link
=
FSTR_INIT
((
char
*
)
symname
,
len
+
1
);
struct
fscrypt_symlink_data
*
sd
=
NULL
;
struct
ubifs_budget_req
req
=
{
.
new_ino
=
1
,
.
new_dent
=
1
,
.
new_ino_d
=
ALIGN
(
len
,
8
),
.
dirtied_ino
=
1
};
struct
fscrypt_name
nm
;
if
(
ubifs_crypt_is_encrypted
(
dir
))
{
err
=
fscrypt_get_encryption_info
(
dir
);
if
(
err
)
goto
out_budg
;
if
(
!
fscrypt_has_encryption_key
(
dir
))
{
err
=
-
EPERM
;
goto
out_budg
;
}
disk_link
.
len
=
(
fscrypt_fname_encrypted_size
(
dir
,
len
)
+
sizeof
(
struct
fscrypt_symlink_data
));
}
/*
* Budget request settings: new inode, new direntry and changing parent
...
...
@@ -1177,36 +1194,77 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
dbg_gen
(
"dent '%pd', target '%s' in dir ino %lu"
,
dentry
,
symname
,
dir
->
i_ino
);
if
(
len
>
UBIFS_MAX_INO_DATA
)
if
(
disk_link
.
len
>
UBIFS_MAX_INO_DATA
)
return
-
ENAMETOOLONG
;
err
=
ubifs_budget_space
(
c
,
&
req
);
if
(
err
)
return
err
;
err
=
fscrypt_setup_filename
(
dir
,
&
dentry
->
d_name
,
0
,
&
nm
);
if
(
err
)
goto
out_budg
;
inode
=
ubifs_new_inode
(
c
,
dir
,
S_IFLNK
|
S_IRWXUGO
);
if
(
IS_ERR
(
inode
))
{
err
=
PTR_ERR
(
inode
);
goto
out_
budg
;
goto
out_
fname
;
}
ui
=
ubifs_inode
(
inode
);
ui
->
data
=
kmalloc
(
len
+
1
,
GFP_NOFS
);
ui
->
data
=
kmalloc
(
disk_link
.
len
,
GFP_NOFS
);
if
(
!
ui
->
data
)
{
err
=
-
ENOMEM
;
goto
out_inode
;
}
memcpy
(
ui
->
data
,
symname
,
len
);
((
char
*
)
ui
->
data
)[
len
]
=
'\0'
;
if
(
ubifs_crypt_is_encrypted
(
dir
))
{
struct
qstr
istr
=
QSTR_INIT
(
symname
,
len
);
struct
fscrypt_str
ostr
;
sd
=
kzalloc
(
disk_link
.
len
,
GFP_NOFS
);
if
(
!
sd
)
{
err
=
-
ENOMEM
;
goto
out_inode
;
}
err
=
fscrypt_get_encryption_info
(
inode
);
if
(
err
)
{
kfree
(
sd
);
goto
out_inode
;
}
if
(
!
fscrypt_has_encryption_key
(
inode
))
{
kfree
(
sd
);
err
=
-
EPERM
;
goto
out_inode
;
}
ostr
.
name
=
sd
->
encrypted_path
;
ostr
.
len
=
disk_link
.
len
;
err
=
fscrypt_fname_usr_to_disk
(
inode
,
&
istr
,
&
ostr
);
if
(
err
)
{
kfree
(
sd
);
goto
out_inode
;
}
sd
->
len
=
cpu_to_le16
(
ostr
.
len
);
disk_link
.
name
=
(
char
*
)
sd
;
}
else
{
inode
->
i_link
=
ui
->
data
;
}
memcpy
(
ui
->
data
,
disk_link
.
name
,
disk_link
.
len
);
((
char
*
)
ui
->
data
)[
disk_link
.
len
-
1
]
=
'\0'
;
/*
* The terminating zero byte is not written to the flash media and it
* is put just to make later in-memory string processing simpler. Thus,
* data length is @len, not @len + %1.
*/
ui
->
data_len
=
len
;
inode
->
i_size
=
ubifs_inode
(
inode
)
->
ui_size
=
len
;
ui
->
data_len
=
disk_link
.
len
-
1
;
inode
->
i_size
=
ubifs_inode
(
inode
)
->
ui_size
=
disk_link
.
len
-
1
;
err
=
ubifs_init_security
(
dir
,
inode
,
&
dentry
->
d_name
);
if
(
err
)
...
...
@@ -1216,7 +1274,7 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
dir
->
i_size
+=
sz_change
;
dir_ui
->
ui_size
=
dir
->
i_size
;
dir
->
i_mtime
=
dir
->
i_ctime
=
inode
->
i_ctime
;
err
=
ubifs_jnl_update
(
c
,
dir
,
&
dentry
->
d_name
,
inode
,
0
,
0
);
err
=
ubifs_jnl_update
(
c
,
dir
,
&
nm
,
inode
,
0
,
0
);
if
(
err
)
goto
out_cancel
;
mutex_unlock
(
&
dir_ui
->
ui_mutex
);
...
...
@@ -1224,6 +1282,7 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
ubifs_release_budget
(
c
,
&
req
);
insert_inode_hash
(
inode
);
d_instantiate
(
dentry
,
inode
);
fscrypt_free_filename
(
&
nm
);
return
0
;
out_cancel:
...
...
@@ -1233,6 +1292,8 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
out_inode:
make_bad_inode
(
inode
);
iput
(
inode
);
out_fname:
fscrypt_free_filename
(
&
nm
);
out_budg:
ubifs_release_budget
(
c
,
&
req
);
return
err
;
...
...
fs/ubifs/file.c
View file @
ca7f85be
...
...
@@ -1657,6 +1657,59 @@ static int ubifs_file_open(struct inode *inode, struct file *filp)
return
0
;
}
static
const
char
*
ubifs_get_link
(
struct
dentry
*
dentry
,
struct
inode
*
inode
,
struct
delayed_call
*
done
)
{
int
err
;
struct
fscrypt_symlink_data
*
sd
;
struct
ubifs_inode
*
ui
=
ubifs_inode
(
inode
);
struct
fscrypt_str
cstr
;
struct
fscrypt_str
pstr
;
if
(
!
ubifs_crypt_is_encrypted
(
inode
))
return
ui
->
data
;
if
(
!
dentry
)
return
ERR_PTR
(
-
ECHILD
);
err
=
fscrypt_get_encryption_info
(
inode
);
if
(
err
)
return
ERR_PTR
(
err
);
sd
=
(
struct
fscrypt_symlink_data
*
)
ui
->
data
;
cstr
.
name
=
sd
->
encrypted_path
;
cstr
.
len
=
le16_to_cpu
(
sd
->
len
);
if
(
cstr
.
len
==
0
)
return
ERR_PTR
(
-
ENOENT
);
if
((
cstr
.
len
+
sizeof
(
struct
fscrypt_symlink_data
)
-
1
)
>
ui
->
data_len
)
return
ERR_PTR
(
-
EIO
);
err
=
fscrypt_fname_alloc_buffer
(
inode
,
cstr
.
len
,
&
pstr
);
if
(
err
)
return
ERR_PTR
(
err
);
err
=
fscrypt_fname_disk_to_usr
(
inode
,
0
,
0
,
&
cstr
,
&
pstr
);
if
(
err
)
{
fscrypt_fname_free_buffer
(
&
pstr
);
return
ERR_PTR
(
err
);
}
pstr
.
name
[
pstr
.
len
]
=
'\0'
;
// XXX this probably won't happen anymore...
if
(
pstr
.
name
[
0
]
==
'\0'
)
{
fscrypt_fname_free_buffer
(
&
pstr
);
return
ERR_PTR
(
-
ENOENT
);
}
set_delayed_call
(
done
,
kfree_link
,
pstr
.
name
);
return
pstr
.
name
;
}
const
struct
address_space_operations
ubifs_file_address_operations
=
{
.
readpage
=
ubifs_readpage
,
.
writepage
=
ubifs_writepage
,
...
...
@@ -1681,7 +1734,7 @@ const struct inode_operations ubifs_file_inode_operations = {
const
struct
inode_operations
ubifs_symlink_inode_operations
=
{
.
readlink
=
generic_readlink
,
.
get_link
=
simple
_get_link
,
.
get_link
=
ubifs
_get_link
,
.
setattr
=
ubifs_setattr
,
.
getattr
=
ubifs_getattr
,
.
listxattr
=
ubifs_listxattr
,
...
...
fs/ubifs/super.c
View file @
ca7f85be
...
...
@@ -198,7 +198,6 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
}
memcpy
(
ui
->
data
,
ino
->
data
,
ui
->
data_len
);
((
char
*
)
ui
->
data
)[
ui
->
data_len
]
=
'\0'
;
inode
->
i_link
=
ui
->
data
;
break
;
case
S_IFBLK
:
case
S_IFCHR
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment