Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Simon Ruderich
passt-mac
Commits
c98b6b83
Commit
c98b6b83
authored
Jul 17, 2016
by
Lukas Braun
Committed by
Simon Ruderich
Aug 29, 2016
Browse files
slsm: implement profiles_read
parent
95ff1a41
Changes
3
Hide whitespace changes
Inline
Side-by-side
security/slsm/passtfs.c
View file @
c98b6b83
...
...
@@ -17,8 +17,10 @@
struct
passtfs_privdata
{
struct
mutex
mutex
;
char
*
buf
;
size_t
size
;
char
*
write_buf
;
size_t
write_buf_size
;
char
*
read_buf
;
size_t
read_buf_size
;
unsigned
dirty
:
1
;
};
...
...
@@ -49,22 +51,22 @@ static ssize_t profiles_write(struct file *f, const char __user *buf, size_t siz
mutex_lock
(
&
pd
->
mutex
);
size_new
=
pd
->
size
+
size
;
size_new
=
pd
->
write_buf_
size
+
size
;
buf_new
=
krealloc
(
pd
->
buf
,
size_new
,
GFP_KERNEL
);
buf_new
=
krealloc
(
pd
->
write_
buf
,
size_new
,
GFP_KERNEL
);
if
(
!
buf_new
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
pd
->
buf
=
buf_new
;
pd
->
write_
buf
=
buf_new
;
if
(
copy_from_user
(
buf_new
+
pd
->
size
,
buf
,
size
))
{
/* reference to realloced buffer in pd->buf is ok, as long as
* pd->size isn't updated */
if
(
copy_from_user
(
buf_new
+
pd
->
write_buf_
size
,
buf
,
size
))
{
/* reference to realloced buffer in pd->
write_
buf is ok, as long as
* pd->
write_buf_
size isn't updated */
ret
=
-
EFAULT
;
goto
out
;
}
pd
->
size
=
size_new
;
pd
->
write_buf_
size
=
size_new
;
pd
->
dirty
=
1
;
ret
=
(
ssize_t
)
size
;
...
...
@@ -74,6 +76,40 @@ out:
return
ret
;
}
ssize_t
profiles_read
(
struct
file
*
f
,
char
__user
*
buf
,
size_t
size
,
loff_t
*
pos
)
{
struct
passtfs_privdata
*
pd
=
f
->
private_data
;
ssize_t
copy_len
,
ret
;
if
(
size
>
(
ssize_t
)
size
)
return
-
EFBIG
;
mutex_lock
(
&
pd
->
mutex
);
if
(
!
pd
->
read_buf
)
{
if
((
ret
=
slsm_serialize_tree
(
&
pd
->
read_buf
))
<
0
)
goto
out
;
pd
->
read_buf_size
=
(
size_t
)
ret
;
}
copy_len
=
(
ssize_t
)
pd
->
read_buf_size
-
*
pos
;
if
(
size
<
copy_len
)
copy_len
=
(
ssize_t
)
size
;
if
(
copy_to_user
(
buf
,
pd
->
read_buf
+
*
pos
,
(
size_t
)
copy_len
))
{
ret
=
-
EFAULT
;
goto
out
;
}
*
pos
+=
copy_len
;
ret
=
copy_len
;
out:
mutex_unlock
(
&
pd
->
mutex
);
return
ret
;
}
/** profiles_flush - called during close(2)
*
...
...
@@ -86,7 +122,7 @@ static int profiles_flush(struct file *file, fl_owner_t id)
mutex_lock
(
&
pd
->
mutex
);
if
(
pd
->
dirty
)
{
ret
=
slsm_new_tree
(
pd
->
buf
,
pd
->
size
);
ret
=
slsm_new_tree
(
pd
->
write_
buf
,
pd
->
write_buf_
size
);
pd
->
dirty
=
0
;
}
mutex_unlock
(
&
pd
->
mutex
);
...
...
@@ -105,7 +141,8 @@ static int profiles_release(struct inode *inode, struct file *file)
BUG_ON
(
!
pd
);
profiles_flush
(
file
,
0
);
kfree
(
pd
->
buf
);
kfree
(
pd
->
write_buf
);
kfree
(
pd
->
read_buf
);
mutex_destroy
(
&
pd
->
mutex
);
kfree
(
pd
);
file
->
private_data
=
NULL
;
...
...
@@ -116,6 +153,7 @@ static int profiles_release(struct inode *inode, struct file *file)
static
const
struct
file_operations
fs_fops_profiles
=
{
.
owner
=
THIS_MODULE
,
.
open
=
profiles_open
,
.
read
=
profiles_read
,
.
write
=
profiles_write
,
.
flush
=
profiles_flush
,
.
release
=
profiles_release
,
...
...
security/slsm/tree.c
View file @
c98b6b83
...
...
@@ -171,6 +171,133 @@ unsigned slsm_perms_would_elevate(struct slsm_perms perms, struct slsm_perms per
/************************************************************************
* serializing
************************************************************************/
/* a resizeable string buffer */
struct
slsm_str
{
size_t
size
;
size_t
used
;
char
*
buf
;
};
int
slsm_str_init
(
struct
slsm_str
*
buf
,
size_t
size
)
{
buf
->
used
=
0
;
buf
->
size
=
size
;
buf
->
buf
=
kzalloc
(
size
,
GFP_KERNEL
);
if
(
!
buf
->
buf
)
return
-
ENOMEM
;
return
0
;
}
/* appends a trailing null byte */
int
slsm_str_append
(
struct
slsm_str
*
buf
,
const
char
*
fmt
,
...)
{
va_list
args
;
int
written
;
va_start
(
args
,
fmt
);
while
((
written
=
vsnprintf
(
buf
->
buf
+
buf
->
used
,
buf
->
size
-
buf
->
used
,
fmt
,
args
)
+
1
)
>
buf
->
size
-
buf
->
used
)
{
char
*
new_buf
;
size_t
new_size
=
buf
->
size
*
2
;
if
(
new_size
>
(
ssize_t
)
new_size
)
return
-
EFBIG
;
new_buf
=
krealloc
(
&
buf
->
buf
,
new_size
,
GFP_KERNEL
);
if
(
!
new_buf
)
return
-
ENOMEM
;
buf
->
buf
=
new_buf
;
buf
->
size
=
new_size
;
}
va_end
(
args
);
buf
->
used
+=
(
size_t
)
written
;
return
0
;
}
/* path_buf->used doesn't include trailing null
*
* TODO: limit recursion */
ssize_t
slsm_serialize_subtree
(
struct
slsm_str
*
buf
,
struct
slsm_str
*
path_buf
,
struct
tree_node
*
t
)
{
ssize_t
ret
;
size_t
old_path_len
=
path_buf
->
used
;
int
i
;
BUG_ON
(
!
t
);
// appends null to path_buf and includes it in ->used
ret
=
slsm_str_append
(
path_buf
,
"/%s"
,
t
->
name
?
t
->
name
:
""
);
if
(
ret
)
return
ret
;
for
(
i
=
0
;
i
<
t
->
rules_used
;
i
++
)
{
ret
=
slsm_str_append
(
buf
,
"p=%s%cm=%u%cf=%u%c"
,
path_buf
->
buf
,
'\0'
,
t
->
rules
[
i
].
perms
.
mode
,
'\0'
,
t
->
rules
[
i
].
perms
.
flags
,
'\0'
);
if
(
ret
)
return
ret
;
// TODO: get rid of this special case by handling a=\0 in the parser
if
(
t
->
rules
[
i
].
app
)
{
buf
->
used
--
;
// remove second trailing null byte
ret
=
slsm_str_append
(
buf
,
"a=%s%c"
,
t
->
rules
[
i
].
app
,
'\0'
);
if
(
ret
)
return
ret
;
}
}
// exclude null for the recursive calls
path_buf
->
used
--
;
// if we're at root, also remove the / because we'll append one anyway
if
(
!
t
->
name
)
path_buf
->
used
--
;
for
(
i
=
0
;
i
<
t
->
children_used
;
i
++
)
{
ret
=
slsm_serialize_subtree
(
buf
,
path_buf
,
&
t
->
children
[
i
]);
if
(
ret
)
return
ret
;
}
path_buf
->
used
=
old_path_len
;
return
0
;
}
ssize_t
slsm_serialize_tree
(
char
**
retbuf
)
{
struct
tree_node
*
t
;
ssize_t
ret
;
struct
slsm_str
buf
;
struct
slsm_str
path_buf
;
if
(
!
rules
)
return
0
;
ret
=
slsm_str_init
(
&
buf
,
4096
);
if
(
ret
)
return
ret
;
ret
=
slsm_str_init
(
&
path_buf
,
4096
);
if
(
ret
)
return
ret
;
rcu_read_lock
();
t
=
rcu_dereference
(
rules
);
ret
=
slsm_serialize_subtree
(
&
buf
,
&
path_buf
,
t
);
rcu_read_unlock
();
if
(
ret
)
return
ret
;
*
retbuf
=
buf
.
buf
;
return
(
ssize_t
)
buf
.
used
;
}
/************************************************************************
* tree creation
...
...
security/slsm/tree.h
View file @
c98b6b83
...
...
@@ -78,6 +78,14 @@ struct slsm_rule {
*/
int
slsm_new_tree
(
const
char
*
buf
,
size_t
buflen
);
/**
* Serializes the ruleset and points buf to the created buffer.
* Returns 0 and *buf is undefined if no ruleset exists.
* Otherwise returns bytes used in *buf or a negative error, *buf being NULL in
* the latter case.
*/
ssize_t
slsm_serialize_tree
(
char
**
buf
);
struct
slsm_perms
slsm_query_perms
(
const
char
*
path
,
const
char
*
app
);
/**
...
...
Write
Preview
Supports
Markdown
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