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
Kirill Smelkov
linux
Commits
e6e29a4e
Commit
e6e29a4e
authored
Jun 03, 2015
by
James Morris
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'smack-for-4.2-stacked' of
https://github.com/cschaufler/smack-next
into next
parents
8d94eb9b
c0d77c88
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
317 additions
and
189 deletions
+317
-189
Documentation/security/Smack.txt
Documentation/security/Smack.txt
+3
-3
security/smack/smack.h
security/smack/smack.h
+9
-16
security/smack/smack_access.c
security/smack/smack_access.c
+57
-11
security/smack/smack_lsm.c
security/smack/smack_lsm.c
+57
-39
security/smack/smackfs.c
security/smack/smackfs.c
+191
-120
No files found.
Documentation/security/Smack.txt
View file @
e6e29a4e
...
...
@@ -206,11 +206,11 @@ netlabel
label. The format accepted on write is:
"%d.%d.%d.%d label" or "%d.%d.%d.%d/%d label".
onlycap
This contains
the label
processes must have for CAP_MAC_ADMIN
This contains
labels
processes must have for CAP_MAC_ADMIN
and CAP_MAC_OVERRIDE to be effective. If this file is empty
these capabilities are effective at for processes with any
label. The value
is set by writing the desired label to the
file or cleared by writing "-" to the file.
label. The value
s are set by writing the desired labels, separated
by spaces, to the
file or cleared by writing "-" to the file.
ptrace
This is used to define the current ptrace policy
0 - default: this is the policy that relies on Smack access rules.
...
...
security/smack/smack.h
View file @
e6e29a4e
...
...
@@ -138,6 +138,11 @@ struct smk_port_label {
struct
smack_known
*
smk_out
;
/* outgoing label */
};
struct
smack_onlycap
{
struct
list_head
list
;
struct
smack_known
*
smk_label
;
};
/*
* Mount options
*/
...
...
@@ -249,6 +254,7 @@ int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);
struct
smack_known
*
smk_import_entry
(
const
char
*
,
int
);
void
smk_insert_entry
(
struct
smack_known
*
skp
);
struct
smack_known
*
smk_find_entry
(
const
char
*
);
int
smack_privileged
(
int
cap
);
/*
* Shared data.
...
...
@@ -257,7 +263,6 @@ extern int smack_enabled;
extern
int
smack_cipso_direct
;
extern
int
smack_cipso_mapped
;
extern
struct
smack_known
*
smack_net_ambient
;
extern
struct
smack_known
*
smack_onlycap
;
extern
struct
smack_known
*
smack_syslog_label
;
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
extern
struct
smack_known
*
smack_unconfined
;
...
...
@@ -276,6 +281,9 @@ extern struct mutex smack_known_lock;
extern
struct
list_head
smack_known_list
;
extern
struct
list_head
smk_netlbladdr_list
;
extern
struct
mutex
smack_onlycap_lock
;
extern
struct
list_head
smack_onlycap_list
;
#define SMACK_HASH_SLOTS 16
extern
struct
hlist_head
smack_known_hash
[
SMACK_HASH_SLOTS
];
...
...
@@ -331,21 +339,6 @@ static inline struct smack_known *smk_of_current(void)
return
smk_of_task
(
current_security
());
}
/*
* Is the task privileged and allowed to be privileged
* by the onlycap rule.
*/
static
inline
int
smack_privileged
(
int
cap
)
{
struct
smack_known
*
skp
=
smk_of_current
();
if
(
!
capable
(
cap
))
return
0
;
if
(
smack_onlycap
==
NULL
||
smack_onlycap
==
skp
)
return
1
;
return
0
;
}
/*
* logging functions
*/
...
...
security/smack/smack_access.c
View file @
e6e29a4e
...
...
@@ -425,7 +425,7 @@ void smk_insert_entry(struct smack_known *skp)
* @string: a text string that might be a Smack label
*
* Returns a pointer to the entry in the label list that
* matches the passed string.
* matches the passed string
or NULL if not found
.
*/
struct
smack_known
*
smk_find_entry
(
const
char
*
string
)
{
...
...
@@ -448,7 +448,7 @@ struct smack_known *smk_find_entry(const char *string)
* @string: a text string that might contain a Smack label
* @len: the maximum size, or zero if it is NULL terminated.
*
* Returns a pointer to the clean label
, or NULL
* Returns a pointer to the clean label
or an error code.
*/
char
*
smk_parse_smack
(
const
char
*
string
,
int
len
)
{
...
...
@@ -464,7 +464,7 @@ char *smk_parse_smack(const char *string, int len)
* including /smack/cipso and /smack/cipso2
*/
if
(
string
[
0
]
==
'-'
)
return
NULL
;
return
ERR_PTR
(
-
EINVAL
)
;
for
(
i
=
0
;
i
<
len
;
i
++
)
if
(
string
[
i
]
>
'~'
||
string
[
i
]
<=
' '
||
string
[
i
]
==
'/'
||
...
...
@@ -472,10 +472,12 @@ char *smk_parse_smack(const char *string, int len)
break
;
if
(
i
==
0
||
i
>=
SMK_LONGLABEL
)
return
NULL
;
return
ERR_PTR
(
-
EINVAL
)
;
smack
=
kzalloc
(
i
+
1
,
GFP_KERNEL
);
if
(
smack
!=
NULL
)
if
(
smack
==
NULL
)
return
ERR_PTR
(
-
ENOMEM
);
strncpy
(
smack
,
string
,
i
);
return
smack
;
...
...
@@ -523,7 +525,8 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
* @len: the maximum size, or zero if it is NULL terminated.
*
* Returns a pointer to the entry in the label list that
* matches the passed string, adding it if necessary.
* matches the passed string, adding it if necessary,
* or an error code.
*/
struct
smack_known
*
smk_import_entry
(
const
char
*
string
,
int
len
)
{
...
...
@@ -533,8 +536,8 @@ struct smack_known *smk_import_entry(const char *string, int len)
int
rc
;
smack
=
smk_parse_smack
(
string
,
len
);
if
(
smack
==
NULL
)
return
NULL
;
if
(
IS_ERR
(
smack
)
)
return
ERR_CAST
(
smack
)
;
mutex_lock
(
&
smack_known_lock
);
...
...
@@ -543,8 +546,10 @@ struct smack_known *smk_import_entry(const char *string, int len)
goto
freeout
;
skp
=
kzalloc
(
sizeof
(
*
skp
),
GFP_KERNEL
);
if
(
skp
==
NULL
)
if
(
skp
==
NULL
)
{
skp
=
ERR_PTR
(
-
ENOMEM
);
goto
freeout
;
}
skp
->
smk_known
=
smack
;
skp
->
smk_secid
=
smack_next_secid
++
;
...
...
@@ -577,7 +582,7 @@ struct smack_known *smk_import_entry(const char *string, int len)
* smk_netlbl_mls failed.
*/
kfree
(
skp
);
skp
=
NULL
;
skp
=
ERR_PTR
(
rc
)
;
freeout:
kfree
(
smack
);
unlockout:
...
...
@@ -612,3 +617,44 @@ struct smack_known *smack_from_secid(const u32 secid)
rcu_read_unlock
();
return
&
smack_known_invalid
;
}
/*
* Unless a process is running with one of these labels
* even having CAP_MAC_OVERRIDE isn't enough to grant
* privilege to violate MAC policy. If no labels are
* designated (the empty list case) capabilities apply to
* everyone.
*/
LIST_HEAD
(
smack_onlycap_list
);
DEFINE_MUTEX
(
smack_onlycap_lock
);
/*
* Is the task privileged and allowed to be privileged
* by the onlycap rule.
*
* Returns 1 if the task is allowed to be privileged, 0 if it's not.
*/
int
smack_privileged
(
int
cap
)
{
struct
smack_known
*
skp
=
smk_of_current
();
struct
smack_onlycap
*
sop
;
if
(
!
capable
(
cap
))
return
0
;
rcu_read_lock
();
if
(
list_empty
(
&
smack_onlycap_list
))
{
rcu_read_unlock
();
return
1
;
}
list_for_each_entry_rcu
(
sop
,
&
smack_onlycap_list
,
list
)
{
if
(
sop
->
smk_label
==
skp
)
{
rcu_read_unlock
();
return
1
;
}
}
rcu_read_unlock
();
return
0
;
}
security/smack/smack_lsm.c
View file @
e6e29a4e
...
...
@@ -245,8 +245,8 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file,
* @ip: a pointer to the inode
* @dp: a pointer to the dentry
*
* Returns a pointer to the master list entry for the Smack label
*
or NULL if there was no label to fetch
.
* Returns a pointer to the master list entry for the Smack label
,
*
NULL if there was no label to fetch, or an error code
.
*/
static
struct
smack_known
*
smk_fetch
(
const
char
*
name
,
struct
inode
*
ip
,
struct
dentry
*
dp
)
...
...
@@ -256,14 +256,18 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
struct
smack_known
*
skp
=
NULL
;
if
(
ip
->
i_op
->
getxattr
==
NULL
)
return
NULL
;
return
ERR_PTR
(
-
EOPNOTSUPP
)
;
buffer
=
kzalloc
(
SMK_LONGLABEL
,
GFP_KERNEL
);
if
(
buffer
==
NULL
)
return
NULL
;
return
ERR_PTR
(
-
ENOMEM
)
;
rc
=
ip
->
i_op
->
getxattr
(
dp
,
name
,
buffer
,
SMK_LONGLABEL
);
if
(
rc
>
0
)
if
(
rc
<
0
)
skp
=
ERR_PTR
(
rc
);
else
if
(
rc
==
0
)
skp
=
NULL
;
else
skp
=
smk_import_entry
(
buffer
,
rc
);
kfree
(
buffer
);
...
...
@@ -605,42 +609,46 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
if
(
strncmp
(
op
,
SMK_FSHAT
,
strlen
(
SMK_FSHAT
))
==
0
)
{
op
+=
strlen
(
SMK_FSHAT
);
skp
=
smk_import_entry
(
op
,
0
);
if
(
skp
!=
NULL
)
{
if
(
IS_ERR
(
skp
))
return
PTR_ERR
(
skp
);
sp
->
smk_hat
=
skp
;
specified
=
1
;
}
}
else
if
(
strncmp
(
op
,
SMK_FSFLOOR
,
strlen
(
SMK_FSFLOOR
))
==
0
)
{
op
+=
strlen
(
SMK_FSFLOOR
);
skp
=
smk_import_entry
(
op
,
0
);
if
(
skp
!=
NULL
)
{
if
(
IS_ERR
(
skp
))
return
PTR_ERR
(
skp
);
sp
->
smk_floor
=
skp
;
specified
=
1
;
}
}
else
if
(
strncmp
(
op
,
SMK_FSDEFAULT
,
strlen
(
SMK_FSDEFAULT
))
==
0
)
{
op
+=
strlen
(
SMK_FSDEFAULT
);
skp
=
smk_import_entry
(
op
,
0
);
if
(
skp
!=
NULL
)
{
if
(
IS_ERR
(
skp
))
return
PTR_ERR
(
skp
);
sp
->
smk_default
=
skp
;
specified
=
1
;
}
}
else
if
(
strncmp
(
op
,
SMK_FSROOT
,
strlen
(
SMK_FSROOT
))
==
0
)
{
op
+=
strlen
(
SMK_FSROOT
);
skp
=
smk_import_entry
(
op
,
0
);
if
(
skp
!=
NULL
)
{
if
(
IS_ERR
(
skp
))
return
PTR_ERR
(
skp
);
sp
->
smk_root
=
skp
;
specified
=
1
;
}
}
else
if
(
strncmp
(
op
,
SMK_FSTRANS
,
strlen
(
SMK_FSTRANS
))
==
0
)
{
op
+=
strlen
(
SMK_FSTRANS
);
skp
=
smk_import_entry
(
op
,
0
);
if
(
skp
!=
NULL
)
{
if
(
IS_ERR
(
skp
))
return
PTR_ERR
(
skp
);
sp
->
smk_root
=
skp
;
transmute
=
1
;
specified
=
1
;
}
}
}
if
(
!
smack_privileged
(
CAP_MAC_ADMIN
))
{
/*
...
...
@@ -1118,7 +1126,9 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
if
(
rc
==
0
&&
check_import
)
{
skp
=
size
?
smk_import_entry
(
value
,
size
)
:
NULL
;
if
(
skp
==
NULL
||
(
check_star
&&
if
(
IS_ERR
(
skp
))
rc
=
PTR_ERR
(
skp
);
else
if
(
skp
==
NULL
||
(
check_star
&&
(
skp
==
&
smack_known_star
||
skp
==
&
smack_known_web
)))
rc
=
-
EINVAL
;
}
...
...
@@ -1158,19 +1168,19 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
if
(
strcmp
(
name
,
XATTR_NAME_SMACK
)
==
0
)
{
skp
=
smk_import_entry
(
value
,
size
);
if
(
skp
!=
NULL
)
if
(
!
IS_ERR
(
skp
)
)
isp
->
smk_inode
=
skp
;
else
isp
->
smk_inode
=
&
smack_known_invalid
;
}
else
if
(
strcmp
(
name
,
XATTR_NAME_SMACKEXEC
)
==
0
)
{
skp
=
smk_import_entry
(
value
,
size
);
if
(
skp
!=
NULL
)
if
(
!
IS_ERR
(
skp
)
)
isp
->
smk_task
=
skp
;
else
isp
->
smk_task
=
&
smack_known_invalid
;
}
else
if
(
strcmp
(
name
,
XATTR_NAME_SMACKMMAP
)
==
0
)
{
skp
=
smk_import_entry
(
value
,
size
);
if
(
skp
!=
NULL
)
if
(
!
IS_ERR
(
skp
)
)
isp
->
smk_mmap
=
skp
;
else
isp
->
smk_mmap
=
&
smack_known_invalid
;
...
...
@@ -1658,6 +1668,9 @@ static int smack_file_receive(struct file *file)
struct
smk_audit_info
ad
;
struct
inode
*
inode
=
file_inode
(
file
);
if
(
unlikely
(
IS_PRIVATE
(
inode
)))
return
0
;
smk_ad_init
(
&
ad
,
__func__
,
LSM_AUDIT_DATA_PATH
);
smk_ad_setfield_u_fs_path
(
&
ad
,
file
->
f_path
);
/*
...
...
@@ -2400,8 +2413,8 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
return
-
EINVAL
;
skp
=
smk_import_entry
(
value
,
size
);
if
(
skp
==
NULL
)
return
-
EINVAL
;
if
(
IS_ERR
(
skp
)
)
return
PTR_ERR
(
skp
)
;
if
(
strcmp
(
name
,
XATTR_SMACK_SUFFIX
)
==
0
)
{
nsp
->
smk_inode
=
skp
;
...
...
@@ -3174,7 +3187,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
*/
dp
=
dget
(
opt_dentry
);
skp
=
smk_fetch
(
XATTR_NAME_SMACK
,
inode
,
dp
);
if
(
skp
!=
NULL
)
if
(
!
IS_ERR_OR_NULL
(
skp
)
)
final
=
skp
;
/*
...
...
@@ -3211,11 +3224,14 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
* Don't let the exec or mmap label be "*" or "@".
*/
skp
=
smk_fetch
(
XATTR_NAME_SMACKEXEC
,
inode
,
dp
);
if
(
skp
==
&
smack_known_star
||
skp
==
&
smack_known_web
)
if
(
IS_ERR
(
skp
)
||
skp
==
&
smack_known_star
||
skp
==
&
smack_known_web
)
skp
=
NULL
;
isp
->
smk_task
=
skp
;
skp
=
smk_fetch
(
XATTR_NAME_SMACKMMAP
,
inode
,
dp
);
if
(
skp
==
&
smack_known_star
||
skp
==
&
smack_known_web
)
if
(
IS_ERR
(
skp
)
||
skp
==
&
smack_known_star
||
skp
==
&
smack_known_web
)
skp
=
NULL
;
isp
->
smk_mmap
=
skp
;
...
...
@@ -3299,8 +3315,8 @@ static int smack_setprocattr(struct task_struct *p, char *name,
return
-
EINVAL
;
skp
=
smk_import_entry
(
value
,
size
);
if
(
skp
==
NULL
)
return
-
EINVAL
;
if
(
IS_ERR
(
skp
)
)
return
PTR_ERR
(
skp
)
;
/*
* No process is ever allowed the web ("@") label.
...
...
@@ -4075,7 +4091,9 @@ static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
return
-
EINVAL
;
skp
=
smk_import_entry
(
rulestr
,
0
);
if
(
skp
)
if
(
IS_ERR
(
skp
))
return
PTR_ERR
(
skp
);
*
rule
=
skp
->
smk_known
;
return
0
;
...
...
security/smack/smackfs.c
View file @
e6e29a4e
...
...
@@ -87,16 +87,6 @@ int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
*/
int
smack_cipso_mapped
=
SMACK_CIPSO_MAPPED_DEFAULT
;
/*
* Unless a process is running with this label even
* having CAP_MAC_OVERRIDE isn't enough to grant
* privilege to violate MAC policy. If no label is
* designated (the NULL case) capabilities apply to
* everyone. It is expected that the hat (^) label
* will be used if any label is used.
*/
struct
smack_known
*
smack_onlycap
;
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
/*
* Allow one label to be unconfined. This is for
...
...
@@ -338,8 +328,7 @@ static int smk_perm_from_str(const char *string)
* @import: if non-zero, import labels
* @len: label length limit
*
* Returns 0 on success, -EINVAL on failure and -ENOENT when either subject
* or object is missing.
* Returns 0 on success, appropriate error code on failure.
*/
static
int
smk_fill_rule
(
const
char
*
subject
,
const
char
*
object
,
const
char
*
access1
,
const
char
*
access2
,
...
...
@@ -351,16 +340,16 @@ static int smk_fill_rule(const char *subject, const char *object,
if
(
import
)
{
rule
->
smk_subject
=
smk_import_entry
(
subject
,
len
);
if
(
rule
->
smk_subject
==
NULL
)
return
-
EINVAL
;
if
(
IS_ERR
(
rule
->
smk_subject
)
)
return
PTR_ERR
(
rule
->
smk_subject
)
;
rule
->
smk_object
=
smk_import_entry
(
object
,
len
);
if
(
rule
->
smk_object
==
NULL
)
return
-
EINVAL
;
if
(
IS_ERR
(
rule
->
smk_object
)
)
return
PTR_ERR
(
rule
->
smk_object
)
;
}
else
{
cp
=
smk_parse_smack
(
subject
,
len
);
if
(
cp
==
NULL
)
return
-
EINVAL
;
if
(
IS_ERR
(
cp
)
)
return
PTR_ERR
(
cp
)
;
skp
=
smk_find_entry
(
cp
);
kfree
(
cp
);
if
(
skp
==
NULL
)
...
...
@@ -368,8 +357,8 @@ static int smk_fill_rule(const char *subject, const char *object,
rule
->
smk_subject
=
skp
;
cp
=
smk_parse_smack
(
object
,
len
);
if
(
cp
==
NULL
)
return
-
EINVAL
;
if
(
IS_ERR
(
cp
)
)
return
PTR_ERR
(
cp
)
;
skp
=
smk_find_entry
(
cp
);
kfree
(
cp
);
if
(
skp
==
NULL
)
...
...
@@ -412,7 +401,7 @@ static int smk_parse_rule(const char *data, struct smack_parsed_rule *rule,
* @import: if non-zero, import labels
* @tokens: numer of substrings expected in data
*
* Returns number of processed bytes on success, -
1
on failure.
* Returns number of processed bytes on success, -
ERRNO
on failure.
*/
static
ssize_t
smk_parse_long_rule
(
char
*
data
,
struct
smack_parsed_rule
*
rule
,
int
import
,
int
tokens
)
...
...
@@ -431,7 +420,7 @@ static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule,
if
(
data
[
cnt
]
==
'\0'
)
/* Unexpected end of data */
return
-
1
;
return
-
EINVAL
;
tok
[
i
]
=
data
+
cnt
;
...
...
@@ -529,14 +518,14 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
while
(
cnt
<
count
)
{
if
(
format
==
SMK_FIXED24_FMT
)
{
rc
=
smk_parse_rule
(
data
,
&
rule
,
1
);
if
(
rc
!=
0
)
{
rc
=
-
EINVAL
;
if
(
rc
<
0
)
goto
out
;
}
cnt
=
count
;
}
else
{
rc
=
smk_parse_long_rule
(
data
+
cnt
,
&
rule
,
1
,
tokens
);
if
(
rc
<=
0
)
{
if
(
rc
<
0
)
goto
out
;
if
(
rc
==
0
)
{
rc
=
-
EINVAL
;
goto
out
;
}
...
...
@@ -567,23 +556,17 @@ static void *smk_seq_start(struct seq_file *s, loff_t *pos,
struct
list_head
*
head
)
{
struct
list_head
*
list
;
int
i
=
*
pos
;
/*
* This is 0 the first time through.
*/
if
(
s
->
index
==
0
)
s
->
private
=
head
;
if
(
s
->
private
==
NULL
)
return
NULL
;
rcu_read_lock
();
for
(
list
=
rcu_dereference
(
list_next_rcu
(
head
));
list
!=
head
;
list
=
rcu_dereference
(
list_next_rcu
(
list
)))
{
if
(
i
--
==
0
)
return
list
;
}
list
=
s
->
private
;
if
(
list_empty
(
list
))
return
NULL
;
if
(
s
->
index
==
0
)
return
list
->
next
;
return
list
;
}
static
void
*
smk_seq_next
(
struct
seq_file
*
s
,
void
*
v
,
loff_t
*
pos
,
...
...
@@ -591,17 +574,15 @@ static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos,
{
struct
list_head
*
list
=
v
;
if
(
list_is_last
(
list
,
head
))
{
s
->
private
=
NULL
;
return
NULL
;
}
s
->
private
=
list
->
next
;
return
list
->
next
;
++*
pos
;
list
=
rcu_dereference
(
list_next_rcu
(
list
));
return
(
list
==
head
)
?
NULL
:
list
;
}
static
void
smk_seq_stop
(
struct
seq_file
*
s
,
void
*
v
)
{
/* No-op */
rcu_read_unlock
();
}
static
void
smk_rule_show
(
struct
seq_file
*
s
,
struct
smack_rule
*
srp
,
int
max
)
...
...
@@ -661,7 +642,7 @@ static int load_seq_show(struct seq_file *s, void *v)
{
struct
list_head
*
list
=
v
;
struct
smack_master_list
*
smlp
=
list_entry
(
list
,
struct
smack_master_list
,
list
);
list_entry_rcu
(
list
,
struct
smack_master_list
,
list
);
smk_rule_show
(
s
,
smlp
->
smk_rule
,
SMK_LABELLEN
);
...
...
@@ -809,7 +790,7 @@ static int cipso_seq_show(struct seq_file *s, void *v)
{
struct
list_head
*
list
=
v
;
struct
smack_known
*
skp
=
list_entry
(
list
,
struct
smack_known
,
list
);
list_entry_rcu
(
list
,
struct
smack_known
,
list
);
struct
netlbl_lsm_catmap
*
cmp
=
skp
->
smk_netlabel
.
attr
.
mls
.
cat
;
char
sep
=
'/'
;
int
i
;
...
...
@@ -915,8 +896,10 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
mutex_lock
(
&
smack_cipso_lock
);
skp
=
smk_import_entry
(
rule
,
0
);
if
(
skp
==
NULL
)
if
(
IS_ERR
(
skp
))
{
rc
=
PTR_ERR
(
skp
);
goto
out
;
}
if
(
format
==
SMK_FIXED24_FMT
)
rule
+=
SMK_LABELLEN
;
...
...
@@ -998,7 +981,7 @@ static int cipso2_seq_show(struct seq_file *s, void *v)
{
struct
list_head
*
list
=
v
;
struct
smack_known
*
skp
=
list_entry
(
list
,
struct
smack_known
,
list
);
list_entry_rcu
(
list
,
struct
smack_known
,
list
);
struct
netlbl_lsm_catmap
*
cmp
=
skp
->
smk_netlabel
.
attr
.
mls
.
cat
;
char
sep
=
'/'
;
int
i
;
...
...
@@ -1082,7 +1065,7 @@ static int netlbladdr_seq_show(struct seq_file *s, void *v)
{
struct
list_head
*
list
=
v
;
struct
smk_netlbladdr
*
skp
=
list_entry
(
list
,
struct
smk_netlbladdr
,
list
);
list_entry_rcu
(
list
,
struct
smk_netlbladdr
,
list
);
unsigned
char
*
hp
=
(
char
*
)
&
skp
->
smk_host
.
sin_addr
.
s_addr
;
int
maskn
;
u32
temp_mask
=
be32_to_cpu
(
skp
->
smk_mask
.
s_addr
);
...
...
@@ -1237,8 +1220,8 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
*/
if
(
smack
[
0
]
!=
'-'
)
{
skp
=
smk_import_entry
(
smack
,
0
);
if
(
skp
==
NULL
)
{
rc
=
-
EINVAL
;
if
(
IS_ERR
(
skp
)
)
{
rc
=
PTR_ERR
(
skp
)
;
goto
free_out
;
}
}
else
{
...
...
@@ -1619,8 +1602,8 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
}
skp
=
smk_import_entry
(
data
,
count
);
if
(
skp
==
NULL
)
{
rc
=
-
EINVAL
;
if
(
IS_ERR
(
skp
)
)
{
rc
=
PTR_ERR
(
skp
)
;
goto
out
;
}
...
...
@@ -1643,34 +1626,79 @@ static const struct file_operations smk_ambient_ops = {
.
llseek
=
default_llseek
,
};
/**
* smk_read_onlycap - read() for smackfs/onlycap
* @filp: file pointer, not actually used
* @buf: where to put the result
* @cn: maximum to send along
* @ppos: where to start
*
* Returns number of bytes read or error code, as appropriate
/*
* Seq_file operations for /smack/onlycap
*/
static
ssize_t
smk_read_onlycap
(
struct
file
*
filp
,
char
__user
*
buf
,
size_t
cn
,
loff_t
*
ppos
)
static
void
*
onlycap_seq_start
(
struct
seq_file
*
s
,
loff_t
*
pos
)
{
char
*
smack
=
""
;
ssize_t
rc
=
-
EINVAL
;
int
asize
;
return
smk_seq_start
(
s
,
pos
,
&
smack_onlycap_list
);
}
static
void
*
onlycap_seq_next
(
struct
seq_file
*
s
,
void
*
v
,
loff_t
*
pos
)
{
return
smk_seq_next
(
s
,
v
,
pos
,
&
smack_onlycap_list
);
}
static
int
onlycap_seq_show
(
struct
seq_file
*
s
,
void
*
v
)
{
struct
list_head
*
list
=
v
;
struct
smack_onlycap
*
sop
=
list_entry_rcu
(
list
,
struct
smack_onlycap
,
list
);
seq_puts
(
s
,
sop
->
smk_label
->
smk_known
);
seq_putc
(
s
,
' '
);
if
(
*
ppos
!=
0
)
return
0
;
}
if
(
smack_onlycap
!=
NULL
)
smack
=
smack_onlycap
->
smk_known
;
static
const
struct
seq_operations
onlycap_seq_ops
=
{
.
start
=
onlycap_seq_start
,
.
next
=
onlycap_seq_next
,
.
show
=
onlycap_seq_show
,
.
stop
=
smk_seq_stop
,
};
asize
=
strlen
(
smack
)
+
1
;
static
int
smk_open_onlycap
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
onlycap_seq_ops
);
}
if
(
cn
>=
asize
)
rc
=
simple_read_from_buffer
(
buf
,
cn
,
ppos
,
smack
,
asize
);
/**
* smk_list_swap_rcu - swap public list with a private one in RCU-safe way
* The caller must hold appropriate mutex to prevent concurrent modifications
* to the public list.
* Private list is assumed to be not accessible to other threads yet.
*
* @public: public list
* @private: private list
*/
static
void
smk_list_swap_rcu
(
struct
list_head
*
public
,
struct
list_head
*
private
)
{
struct
list_head
*
first
,
*
last
;
return
rc
;
if
(
list_empty
(
public
))
{
list_splice_init_rcu
(
private
,
public
,
synchronize_rcu
);
}
else
{
/* Remember public list before replacing it */
first
=
public
->
next
;
last
=
public
->
prev
;
/* Publish private list in place of public in RCU-safe way */
private
->
prev
->
next
=
public
;
private
->
next
->
prev
=
public
;
rcu_assign_pointer
(
public
->
next
,
private
->
next
);
public
->
prev
=
private
->
prev
;
synchronize_rcu
();
/* When all readers are done with the old public list,
* attach it in place of private */
private
->
next
=
first
;
private
->
prev
=
last
;
first
->
prev
=
private
;
last
->
next
=
private
;
}
}
/**
...
...
@@ -1686,47 +1714,79 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
size_t
count
,
loff_t
*
ppos
)
{
char
*
data
;
struct
smack_known
*
skp
=
smk_of_task
(
current
->
cred
->
security
);
char
*
data_parse
;
char
*
tok
;
struct
smack_known
*
skp
;
struct
smack_onlycap
*
sop
;
struct
smack_onlycap
*
sop2
;
LIST_HEAD
(
list_tmp
);
int
rc
=
count
;
if
(
!
smack_privileged
(
CAP_MAC_ADMIN
))
return
-
EPERM
;
/*
* This can be done using smk_access() but is done
* explicitly for clarity. The smk_access() implementation
* would use smk_access(smack_onlycap, MAY_WRITE)
*/
if
(
smack_onlycap
!=
NULL
&&
smack_onlycap
!=
skp
)
return
-
EPERM
;
data
=
kzalloc
(
count
+
1
,
GFP_KERNEL
);
if
(
data
==
NULL
)
return
-
ENOMEM
;
if
(
copy_from_user
(
data
,
buf
,
count
)
!=
0
)
{
kfree
(
data
);
return
-
EFAULT
;
}
data_parse
=
data
;
while
((
tok
=
strsep
(
&
data_parse
,
" "
))
!=
NULL
)
{
if
(
!*
tok
)
continue
;
skp
=
smk_import_entry
(
tok
,
0
);
if
(
IS_ERR
(
skp
))
{
rc
=
PTR_ERR
(
skp
);
break
;
}
sop
=
kzalloc
(
sizeof
(
*
sop
),
GFP_KERNEL
);
if
(
sop
==
NULL
)
{
rc
=
-
ENOMEM
;
break
;
}
sop
->
smk_label
=
skp
;
list_add_rcu
(
&
sop
->
list
,
&
list_tmp
);
}
kfree
(
data
);
/*
* Should the null string be passed in unset the onlycap value.
* This seems like something to be careful with as usually
* smk_import only expects to return NULL for errors. It
* is usually the case that a nullstring or "\n" would be
* bad to pass to smk_import but in fact this is useful here.
* Clear the smack_onlycap on invalid label errors. This means
* that we can pass a null string to unset the onlycap value.
*
*
smk_import
will also reject a label beginning with '-',
*
Importing
will also reject a label beginning with '-',
* so "-usecapabilities" will also work.
*
* But do so only on invalid label, not on system errors.
* The invalid label must be first to count as clearing attempt.
*/
if
(
copy_from_user
(
data
,
buf
,
count
)
!=
0
)
rc
=
-
EFAULT
;
else
smack_onlycap
=
smk_import_entry
(
data
,
count
);
if
(
rc
==
-
EINVAL
&&
list_empty
(
&
list_tmp
))
rc
=
count
;
if
(
rc
>=
0
)
{
mutex_lock
(
&
smack_onlycap_lock
);
smk_list_swap_rcu
(
&
smack_onlycap_list
,
&
list_tmp
);
mutex_unlock
(
&
smack_onlycap_lock
);
}
list_for_each_entry_safe
(
sop
,
sop2
,
&
list_tmp
,
list
)
kfree
(
sop
);
kfree
(
data
);
return
rc
;
}
static
const
struct
file_operations
smk_onlycap_ops
=
{
.
read
=
smk_read_onlycap
,
.
open
=
smk_open_onlycap
,
.
read
=
seq_read
,
.
write
=
smk_write_onlycap
,
.
llseek
=
default_llseek
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release
,
};
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
...
...
@@ -1773,6 +1833,7 @@ static ssize_t smk_write_unconfined(struct file *file, const char __user *buf,
size_t
count
,
loff_t
*
ppos
)
{
char
*
data
;
struct
smack_known
*
skp
;
int
rc
=
count
;
if
(
!
smack_privileged
(
CAP_MAC_ADMIN
))
...
...
@@ -1782,21 +1843,31 @@ static ssize_t smk_write_unconfined(struct file *file, const char __user *buf,
if
(
data
==
NULL
)
return
-
ENOMEM
;
if
(
copy_from_user
(
data
,
buf
,
count
)
!=
0
)
{
rc
=
-
EFAULT
;
goto
freeout
;
}
/*
* Should the null string be passed in unset the unconfined value.
* This seems like something to be careful with as usually
* smk_import only expects to return NULL for errors. It
* is usually the case that a nullstring or "\n" would be
* bad to pass to smk_import but in fact this is useful here.
* Clear the smack_unconfined on invalid label errors. This means
* that we can pass a null string to unset the unconfined value.
*
*
smk_import
will also reject a label beginning with '-',
*
Importing
will also reject a label beginning with '-',
* so "-confine" will also work.
*
* But do so only on invalid label, not on system errors.
*/
if
(
copy_from_user
(
data
,
buf
,
count
)
!=
0
)
rc
=
-
EFAULT
;
else
smack_unconfined
=
smk_import_entry
(
data
,
count
);
skp
=
smk_import_entry
(
data
,
count
);
if
(
PTR_ERR
(
skp
)
==
-
EINVAL
)
skp
=
NULL
;
else
if
(
IS_ERR
(
skp
))
{
rc
=
PTR_ERR
(
skp
);
goto
freeout
;
}
smack_unconfined
=
skp
;
freeout:
kfree
(
data
);
return
rc
;
}
...
...
@@ -1895,7 +1966,7 @@ static int load_self_seq_show(struct seq_file *s, void *v)
{
struct
list_head
*
list
=
v
;
struct
smack_rule
*
srp
=
list_entry
(
list
,
struct
smack_rule
,
list
);
list_entry_rcu
(
list
,
struct
smack_rule
,
list
);
smk_rule_show
(
s
,
srp
,
SMK_LABELLEN
);
...
...
@@ -1980,7 +2051,7 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf,
res
=
smk_access
(
rule
.
smk_subject
,
rule
.
smk_object
,
rule
.
smk_access1
,
NULL
);
else
if
(
res
!=
-
ENOENT
)
return
-
EINVAL
;
return
res
;
/*
* smk_access() can return a value > 0 in the "bringup" case.
...
...
@@ -2024,7 +2095,7 @@ static int load2_seq_show(struct seq_file *s, void *v)
{
struct
list_head
*
list
=
v
;
struct
smack_master_list
*
smlp
=
list_entry
(
list
,
struct
smack_master_list
,
list
);
list_entry_rcu
(
list
,
struct
smack_master_list
,
list
);
smk_rule_show
(
s
,
smlp
->
smk_rule
,
SMK_LONGLABEL
);
...
...
@@ -2101,7 +2172,7 @@ static int load_self2_seq_show(struct seq_file *s, void *v)
{
struct
list_head
*
list
=
v
;
struct
smack_rule
*
srp
=
list_entry
(
list
,
struct
smack_rule
,
list
);
list_entry_rcu
(
list
,
struct
smack_rule
,
list
);
smk_rule_show
(
s
,
srp
,
SMK_LONGLABEL
);
...
...
@@ -2209,8 +2280,8 @@ static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf,
}
cp
=
smk_parse_smack
(
data
,
count
);
if
(
cp
==
NULL
)
{
rc
=
-
EINVAL
;
if
(
IS_ERR
(
cp
)
)
{
rc
=
PTR_ERR
(
cp
)
;
goto
free_out
;
}
...
...
@@ -2341,10 +2412,10 @@ static ssize_t smk_write_syslog(struct file *file, const char __user *buf,
rc
=
-
EFAULT
;
else
{
skp
=
smk_import_entry
(
data
,
count
);
if
(
skp
==
NULL
)
rc
=
-
EINVAL
;
if
(
IS_ERR
(
skp
)
)
rc
=
PTR_ERR
(
skp
)
;
else
smack_syslog_label
=
s
mk_import_entry
(
data
,
count
)
;
smack_syslog_label
=
s
kp
;
}
kfree
(
data
);
...
...
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