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
9b0271d8
Commit
9b0271d8
authored
Apr 02, 2013
by
James Morris
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'stage-for-3.10' of
git://git.gitorious.org/smack-next/kernel
into ra-next
parents
d1327479
cdb56b60
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
187 additions
and
89 deletions
+187
-89
Documentation/security/Smack.txt
Documentation/security/Smack.txt
+11
-0
include/uapi/linux/magic.h
include/uapi/linux/magic.h
+1
-0
security/smack/smack.h
security/smack/smack.h
+0
-5
security/smack/smack_access.c
security/smack/smack_access.c
+2
-0
security/smack/smack_lsm.c
security/smack/smack_lsm.c
+2
-2
security/smack/smackfs.c
security/smack/smackfs.c
+171
-82
No files found.
Documentation/security/Smack.txt
View file @
9b0271d8
...
...
@@ -117,6 +117,17 @@ access2
ambient
This contains the Smack label applied to unlabeled network
packets.
change-rule
This interface allows modification of existing access control rules.
The format accepted on write is:
"%s %s %s %s"
where the first string is the subject label, the second the
object label, the third the access to allow and the fourth the
access to deny. The access strings may contain only the characters
"rwxat-". If a rule for a given subject and object exists it will be
modified by enabling the permissions in the third string and disabling
those in the fourth string. If there is no such rule it will be
created using the access specified in the third and the fourth strings.
cipso
This interface allows a specific CIPSO header to be assigned
to a Smack label. The format accepted on write is:
...
...
include/uapi/linux/magic.h
View file @
9b0271d8
...
...
@@ -11,6 +11,7 @@
#define DEBUGFS_MAGIC 0x64626720
#define SECURITYFS_MAGIC 0x73636673
#define SELINUX_MAGIC 0xf97cff8c
#define SMACK_MAGIC 0x43415d53
/* "SMAC" */
#define RAMFS_MAGIC 0x858458f6
/* some random number */
#define TMPFS_MAGIC 0x01021994
#define HUGETLBFS_MAGIC 0x958458f6
/* some random number */
...
...
security/smack/smack.h
View file @
9b0271d8
...
...
@@ -148,11 +148,6 @@ struct smack_known {
#define SMACK_UNLABELED_SOCKET 0
#define SMACK_CIPSO_SOCKET 1
/*
* smackfs magic number
*/
#define SMACK_MAGIC 0x43415d53
/* "SMAC" */
/*
* CIPSO defaults.
*/
...
...
security/smack/smack_access.c
View file @
9b0271d8
...
...
@@ -252,6 +252,8 @@ static inline void smack_str_from_perm(char *string, int access)
string
[
i
++
]
=
'x'
;
if
(
access
&
MAY_APPEND
)
string
[
i
++
]
=
'a'
;
if
(
access
&
MAY_TRANSMUTE
)
string
[
i
++
]
=
't'
;
string
[
i
]
=
'\0'
;
}
/**
...
...
security/smack/smack_lsm.c
View file @
9b0271d8
...
...
@@ -654,7 +654,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
/*
* You also need write access to the containing directory
*/
smk_ad_
setfield_u_fs_path_dentry
(
&
ad
,
NULL
);
smk_ad_
init
(
&
ad
,
__func__
,
LSM_AUDIT_DATA_INODE
);
smk_ad_setfield_u_fs_inode
(
&
ad
,
dir
);
rc
=
smk_curacc
(
smk_of_inode
(
dir
),
MAY_WRITE
,
&
ad
);
}
...
...
@@ -685,7 +685,7 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
/*
* You also need write access to the containing directory
*/
smk_ad_
setfield_u_fs_path_dentry
(
&
ad
,
NULL
);
smk_ad_
init
(
&
ad
,
__func__
,
LSM_AUDIT_DATA_INODE
);
smk_ad_setfield_u_fs_inode
(
&
ad
,
dir
);
rc
=
smk_curacc
(
smk_of_inode
(
dir
),
MAY_WRITE
,
&
ad
);
}
...
...
security/smack/smackfs.c
View file @
9b0271d8
...
...
@@ -50,12 +50,12 @@ enum smk_inos {
SMK_ACCESS2
=
16
,
/* make an access check with long labels */
SMK_CIPSO2
=
17
,
/* load long label -> CIPSO mapping */
SMK_REVOKE_SUBJ
=
18
,
/* set rules with subject label to '-' */
SMK_CHANGE_RULE
=
19
,
/* change or add rules (long labels) */
};
/*
* List locks
*/
static
DEFINE_MUTEX
(
smack_list_lock
);
static
DEFINE_MUTEX
(
smack_cipso_lock
);
static
DEFINE_MUTEX
(
smack_ambient_lock
);
static
DEFINE_MUTEX
(
smk_netlbladdr_lock
);
...
...
@@ -110,6 +110,13 @@ struct smack_master_list {
LIST_HEAD
(
smack_rule_list
);
struct
smack_parsed_rule
{
char
*
smk_subject
;
char
*
smk_object
;
int
smk_access1
;
int
smk_access2
;
};
static
int
smk_cipso_doi_value
=
SMACK_CIPSO_DOI_DEFAULT
;
const
char
*
smack_cipso_option
=
SMACK_CIPSO_OPTION
;
...
...
@@ -167,25 +174,28 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap)
#define SMK_NETLBLADDRMIN 9
/**
* smk_set_access - add a rule to the rule list
* @srp: the
new rule to add
* smk_set_access - add a rule to the rule list
or replace an old rule
* @srp: the
rule to add or replace
* @rule_list: the list of rules
* @rule_lock: the rule list lock
* @global: if non-zero, indicates a global rule
*
* Looks through the current subject/object/access list for
* the subject/object pair and replaces the access that was
* there. If the pair isn't found add it with the specified
* access.
*
* Returns 1 if a rule was found to exist already, 0 if it is new
* Returns 0 if nothing goes wrong or -ENOMEM if it fails
* during the allocation of the new pair to add.
*/
static
int
smk_set_access
(
struct
smack_rule
*
srp
,
struct
list_head
*
rule_list
,
struct
mutex
*
rule_lock
)
static
int
smk_set_access
(
struct
smack_parsed_rule
*
srp
,
struct
list_head
*
rule_list
,
struct
mutex
*
rule_lock
,
int
global
)
{
struct
smack_rule
*
sp
;
struct
smack_master_list
*
smlp
;
int
found
=
0
;
int
rc
=
0
;
mutex_lock
(
rule_lock
);
...
...
@@ -197,23 +207,89 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
if
(
sp
->
smk_object
==
srp
->
smk_object
&&
sp
->
smk_subject
==
srp
->
smk_subject
)
{
found
=
1
;
sp
->
smk_access
=
srp
->
smk_access
;
sp
->
smk_access
|=
srp
->
smk_access1
;
sp
->
smk_access
&=
~
srp
->
smk_access2
;
break
;
}
}
if
(
found
==
0
)
list_add_rcu
(
&
srp
->
list
,
rule_list
);
if
(
found
==
0
)
{
sp
=
kzalloc
(
sizeof
(
*
sp
),
GFP_KERNEL
);
if
(
sp
==
NULL
)
{
rc
=
-
ENOMEM
;
goto
out
;
}
sp
->
smk_subject
=
srp
->
smk_subject
;
sp
->
smk_object
=
srp
->
smk_object
;
sp
->
smk_access
=
srp
->
smk_access1
&
~
srp
->
smk_access2
;
list_add_rcu
(
&
sp
->
list
,
rule_list
);
/*
* If this is a global as opposed to self and a new rule
* it needs to get added for reporting.
*/
if
(
global
)
{
smlp
=
kzalloc
(
sizeof
(
*
smlp
),
GFP_KERNEL
);
if
(
smlp
!=
NULL
)
{
smlp
->
smk_rule
=
sp
;
list_add_rcu
(
&
smlp
->
list
,
&
smack_rule_list
);
}
else
rc
=
-
ENOMEM
;
}
}
out:
mutex_unlock
(
rule_lock
);
return
rc
;
}
/**
* smk_perm_from_str - parse smack accesses from a text string
* @string: a text string that contains a Smack accesses code
*
* Returns an integer with respective bits set for specified accesses.
*/
static
int
smk_perm_from_str
(
const
char
*
string
)
{
int
perm
=
0
;
const
char
*
cp
;
return
found
;
for
(
cp
=
string
;
;
cp
++
)
switch
(
*
cp
)
{
case
'-'
:
break
;
case
'r'
:
case
'R'
:
perm
|=
MAY_READ
;
break
;
case
'w'
:
case
'W'
:
perm
|=
MAY_WRITE
;
break
;
case
'x'
:
case
'X'
:
perm
|=
MAY_EXEC
;
break
;
case
'a'
:
case
'A'
:
perm
|=
MAY_APPEND
;
break
;
case
't'
:
case
'T'
:
perm
|=
MAY_TRANSMUTE
;
break
;
default:
return
perm
;
}
}
/**
* smk_fill_rule - Fill Smack rule from strings
* @subject: subject label string
* @object: object label string
* @access: access string
* @access1: access string
* @access2: string with permissions to be removed
* @rule: Smack rule
* @import: if non-zero, import labels
* @len: label length limit
...
...
@@ -221,8 +297,9 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
* Returns 0 on success, -1 on failure
*/
static
int
smk_fill_rule
(
const
char
*
subject
,
const
char
*
object
,
const
char
*
access
,
struct
smack_rule
*
rule
,
int
import
,
int
len
)
const
char
*
access1
,
const
char
*
access2
,
struct
smack_parsed_rule
*
rule
,
int
import
,
int
len
)
{
const
char
*
cp
;
struct
smack_known
*
skp
;
...
...
@@ -255,36 +332,11 @@ static int smk_fill_rule(const char *subject, const char *object,
rule
->
smk_object
=
skp
->
smk_known
;
}
rule
->
smk_access
=
0
;
for
(
cp
=
access
;
*
cp
!=
'\0'
;
cp
++
)
{
switch
(
*
cp
)
{
case
'-'
:
break
;
case
'r'
:
case
'R'
:
rule
->
smk_access
|=
MAY_READ
;
break
;
case
'w'
:
case
'W'
:
rule
->
smk_access
|=
MAY_WRITE
;
break
;
case
'x'
:
case
'X'
:
rule
->
smk_access
|=
MAY_EXEC
;
break
;
case
'a'
:
case
'A'
:
rule
->
smk_access
|=
MAY_APPEND
;
break
;
case
't'
:
case
'T'
:
rule
->
smk_access
|=
MAY_TRANSMUTE
;
break
;
default:
return
0
;
}
}
rule
->
smk_access1
=
smk_perm_from_str
(
access1
);
if
(
access2
)
rule
->
smk_access2
=
smk_perm_from_str
(
access2
);
else
rule
->
smk_access2
=
~
rule
->
smk_access1
;
return
0
;
}
...
...
@@ -297,30 +349,33 @@ static int smk_fill_rule(const char *subject, const char *object,
*
* Returns 0 on success, -1 on errors.
*/
static
int
smk_parse_rule
(
const
char
*
data
,
struct
smack_rule
*
rule
,
int
import
)
static
int
smk_parse_rule
(
const
char
*
data
,
struct
smack_parsed_rule
*
rule
,
int
import
)
{
int
rc
;
rc
=
smk_fill_rule
(
data
,
data
+
SMK_LABELLEN
,
data
+
SMK_LABELLEN
+
SMK_LABELLEN
,
rule
,
import
,
SMK_LABELLEN
);
data
+
SMK_LABELLEN
+
SMK_LABELLEN
,
NULL
,
rule
,
import
,
SMK_LABELLEN
);
return
rc
;
}
/**
* smk_parse_long_rule - parse Smack rule from rule string
* @data: string to be parsed, null terminated
* @rule:
Smack
rule
* @rule:
Will be filled with Smack parsed
rule
* @import: if non-zero, import labels
* @change: if non-zero, data is from /smack/change-rule
*
* Returns 0 on success, -1 on failure
*/
static
int
smk_parse_long_rule
(
const
char
*
data
,
struct
smack_rule
*
rule
,
int
import
)
static
int
smk_parse_long_rule
(
const
char
*
data
,
struct
smack_
parsed_
rule
*
rule
,
int
import
,
int
change
)
{
char
*
subject
;
char
*
object
;
char
*
access
;
char
*
access1
;
char
*
access2
;
int
datalen
;
int
rc
=
-
1
;
...
...
@@ -334,14 +389,27 @@ static int smk_parse_long_rule(const char *data, struct smack_rule *rule,
object
=
kzalloc
(
datalen
,
GFP_KERNEL
);
if
(
object
==
NULL
)
goto
free_out_s
;
access
=
kzalloc
(
datalen
,
GFP_KERNEL
);
if
(
access
==
NULL
)
access
1
=
kzalloc
(
datalen
,
GFP_KERNEL
);
if
(
access
1
==
NULL
)
goto
free_out_o
;
access2
=
kzalloc
(
datalen
,
GFP_KERNEL
);
if
(
access2
==
NULL
)
goto
free_out_a
;
if
(
change
)
{
if
(
sscanf
(
data
,
"%s %s %s %s"
,
subject
,
object
,
access1
,
access2
)
==
4
)
rc
=
smk_fill_rule
(
subject
,
object
,
access1
,
access2
,
rule
,
import
,
0
);
}
else
{
if
(
sscanf
(
data
,
"%s %s %s"
,
subject
,
object
,
access1
)
==
3
)
rc
=
smk_fill_rule
(
subject
,
object
,
access1
,
NULL
,
rule
,
import
,
0
);
}
if
(
sscanf
(
data
,
"%s %s %s"
,
subject
,
object
,
access
)
==
3
)
rc
=
smk_fill_rule
(
subject
,
object
,
access
,
rule
,
import
,
0
);
kfree
(
access
);
kfree
(
access2
);
free_out_a:
kfree
(
access1
);
free_out_o:
kfree
(
object
);
free_out_s:
...
...
@@ -351,6 +419,7 @@ static int smk_parse_long_rule(const char *data, struct smack_rule *rule,
#define SMK_FIXED24_FMT 0
/* Fixed 24byte label format */
#define SMK_LONG_FMT 1
/* Variable long label format */
#define SMK_CHANGE_FMT 2
/* Rule modification format */
/**
* smk_write_rules_list - write() for any /smack rule file
* @file: file pointer, not actually used
...
...
@@ -359,22 +428,24 @@ static int smk_parse_long_rule(const char *data, struct smack_rule *rule,
* @ppos: where to start - must be 0
* @rule_list: the list of rules to write to
* @rule_lock: lock for the rule list
* @format: /smack/load or /smack/load2 format.
* @format: /smack/load or /smack/load2
or /smack/change-rule
format.
*
* Get one smack access rule from above.
* The format for SMK_LONG_FMT is:
* "subject<whitespace>object<whitespace>access[<whitespace>...]"
* The format for SMK_FIXED24_FMT is exactly:
* "subject object rwxat"
* The format for SMK_CHANGE_FMT is:
* "subject<whitespace>object<whitespace>
* acc_enable<whitespace>acc_disable[<whitespace>...]"
*/
static
ssize_t
smk_write_rules_list
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
,
struct
list_head
*
rule_list
,
struct
mutex
*
rule_lock
,
int
format
)
{
struct
smack_master_list
*
smlp
;
struct
smack_known
*
skp
;
struct
smack_rule
*
rule
;
struct
smack_
parsed_
rule
*
rule
;
char
*
data
;
int
datalen
;
int
rc
=
-
EINVAL
;
...
...
@@ -417,7 +488,11 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
* Be sure the data string is terminated.
*/
data
[
count
]
=
'\0'
;
if
(
smk_parse_long_rule
(
data
,
rule
,
1
))
if
(
smk_parse_long_rule
(
data
,
rule
,
1
,
0
))
goto
out_free_rule
;
}
else
if
(
format
==
SMK_CHANGE_FMT
)
{
data
[
count
]
=
'\0'
;
if
(
smk_parse_long_rule
(
data
,
rule
,
1
,
1
))
goto
out_free_rule
;
}
else
{
/*
...
...
@@ -437,22 +512,9 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
rule_lock
=
&
skp
->
smk_rules_lock
;
}
rc
=
smk_set_access
(
rule
,
rule_list
,
rule_lock
,
load
);
if
(
rc
==
0
)
{
rc
=
count
;
/*
* If this is a global as opposed to self and a new rule
* it needs to get added for reporting.
* smk_set_access returns true if there was already a rule
* for the subject/object pair, and false if it was new.
*/
if
(
!
smk_set_access
(
rule
,
rule_list
,
rule_lock
))
{
if
(
load
)
{
smlp
=
kzalloc
(
sizeof
(
*
smlp
),
GFP_KERNEL
);
if
(
smlp
!=
NULL
)
{
smlp
->
smk_rule
=
rule
;
list_add_rcu
(
&
smlp
->
list
,
&
smack_rule_list
);
}
else
rc
=
-
ENOMEM
;
}
goto
out
;
}
...
...
@@ -1774,7 +1836,7 @@ static const struct file_operations smk_load_self_ops = {
static
ssize_t
smk_user_access
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
,
int
format
)
{
struct
smack_rule
rule
;
struct
smack_
parsed_
rule
rule
;
char
*
data
;
char
*
cod
;
int
res
;
...
...
@@ -1796,14 +1858,14 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf,
return
-
ENOMEM
;
memcpy
(
cod
,
data
,
count
);
cod
[
count
]
=
'\0'
;
res
=
smk_parse_long_rule
(
cod
,
&
rule
,
0
);
res
=
smk_parse_long_rule
(
cod
,
&
rule
,
0
,
0
);
kfree
(
cod
);
}
if
(
res
)
return
-
EINVAL
;
res
=
smk_access
(
rule
.
smk_subject
,
rule
.
smk_object
,
rule
.
smk_access
,
res
=
smk_access
(
rule
.
smk_subject
,
rule
.
smk_object
,
rule
.
smk_access
1
,
NULL
);
data
[
0
]
=
res
==
0
?
'1'
:
'0'
;
data
[
1
]
=
'\0'
;
...
...
@@ -2035,10 +2097,8 @@ static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf,
}
skp
=
smk_find_entry
(
cp
);
if
(
skp
==
NULL
)
{
rc
=
-
EINVAL
;
if
(
skp
==
NULL
)
goto
free_out
;
}
rule_list
=
&
skp
->
smk_rules
;
rule_lock
=
&
skp
->
smk_rules_lock
;
...
...
@@ -2076,6 +2136,33 @@ static int smk_init_sysfs(void)
return
0
;
}
/**
* smk_write_change_rule - write() for /smack/change-rule
* @file: file pointer
* @buf: data from user space
* @count: bytes sent
* @ppos: where to start - must be 0
*/
static
ssize_t
smk_write_change_rule
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
/*
* Must have privilege.
*/
if
(
!
capable
(
CAP_MAC_ADMIN
))
return
-
EPERM
;
return
smk_write_rules_list
(
file
,
buf
,
count
,
ppos
,
NULL
,
NULL
,
SMK_CHANGE_FMT
);
}
static
const
struct
file_operations
smk_change_rule_ops
=
{
.
write
=
smk_write_change_rule
,
.
read
=
simple_transaction_read
,
.
release
=
simple_transaction_release
,
.
llseek
=
generic_file_llseek
,
};
/**
* smk_fill_super - fill the /smackfs superblock
* @sb: the empty superblock
...
...
@@ -2125,6 +2212,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
[
SMK_REVOKE_SUBJ
]
=
{
"revoke-subject"
,
&
smk_revoke_subj_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_CHANGE_RULE
]
=
{
"change-rule"
,
&
smk_change_rule_ops
,
S_IRUGO
|
S_IWUSR
},
/* last one */
{
""
}
};
...
...
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