Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
12fa8a27
cloud-kernel
项目概览
openanolis
/
cloud-kernel
大约 1 年 前同步成功
通知
158
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
12fa8a27
编写于
5月 16, 2012
作者:
J
James Morris
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-1205' of
http://git.gitorious.org/smack-next/kernel
into next
Pull request from Casey.
上级
b404aef7
f7112e6c
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
1145 addition
and
579 deletion
+1145
-579
Documentation/security/Smack.txt
Documentation/security/Smack.txt
+164
-40
security/smack/smack.h
security/smack/smack.h
+21
-36
security/smack/smack_access.c
security/smack/smack_access.c
+116
-117
security/smack/smack_lsm.c
security/smack/smack_lsm.c
+83
-154
security/smack/smackfs.c
security/smack/smackfs.c
+761
-232
未找到文件。
Documentation/security/Smack.txt
浏览文件 @
12fa8a27
...
...
@@ -15,7 +15,7 @@ at hand.
Smack consists of three major components:
- The kernel
-
A start-up script and a few modified applications
-
Basic utilities, which are helpful but not required
- Configuration data
The kernel component of Smack is implemented as a Linux
...
...
@@ -23,37 +23,28 @@ Security Modules (LSM) module. It requires netlabel and
works best with file systems that support extended attributes,
although xattr support is not strictly required.
It is safe to run a Smack kernel under a "vanilla" distribution.
Smack kernels use the CIPSO IP option. Some network
configurations are intolerant of IP options and can impede
access to systems that use them as Smack does.
The startup script etc-init.d-smack should be installed
in /etc/init.d/smack and should be invoked early in the
start-up process. On Fedora rc5.d/S02smack is recommended.
This script ensures that certain devices have the correct
Smack attributes and loads the Smack configuration if
any is defined. This script invokes two programs that
ensure configuration data is properly formatted. These
programs are /usr/sbin/smackload and /usr/sin/smackcipso.
The system will run just fine without these programs,
but it will be difficult to set access rules properly.
A version of "ls" that provides a "-M" option to display
Smack labels on long listing is available.
The current git repositories for Smack user space are:
A hacked version of sshd that allows network logins by users
with specific Smack labels is available. This version does
not work for scp. You must set the /etc/ssh/sshd_config
line:
UsePrivilegeSeparation no
git@gitorious.org:meego-platform-security/smackutil.git
git@gitorious.org:meego-platform-security/libsmack.git
The format of /etc/smack/usr is:
These should make and install on most modern distributions.
There are three commands included in smackutil:
username smack
smackload - properly formats data for writing to /smack/load
smackcipso - properly formats data for writing to /smack/cipso
chsmack - display or set Smack extended attribute values
In keeping with the intent of Smack, configuration data is
minimal and not strictly required. The most important
configuration step is mounting the smackfs pseudo filesystem.
If smackutil is installed the startup script will take care
of this, but it can be manually as well.
Add this line to /etc/fstab:
...
...
@@ -61,19 +52,148 @@ Add this line to /etc/fstab:
and create the /smack directory for mounting.
Smack uses extended attributes (xattrs) to store file labels.
The command to set a Smack label on a file is:
Smack uses extended attributes (xattrs) to store labels on filesystem
objects. The attributes are stored in the extended attribute security
name space. A process must have CAP_MAC_ADMIN to change any of these
attributes.
The extended attributes that Smack uses are:
SMACK64
Used to make access control decisions. In almost all cases
the label given to a new filesystem object will be the label
of the process that created it.
SMACK64EXEC
The Smack label of a process that execs a program file with
this attribute set will run with this attribute's value.
SMACK64MMAP
Don't allow the file to be mmapped by a process whose Smack
label does not allow all of the access permitted to a process
with the label contained in this attribute. This is a very
specific use case for shared libraries.
SMACK64TRANSMUTE
Can only have the value "TRUE". If this attribute is present
on a directory when an object is created in the directory and
the Smack rule (more below) that permitted the write access
to the directory includes the transmute ("t") mode the object
gets the label of the directory instead of the label of the
creating process. If the object being created is a directory
the SMACK64TRANSMUTE attribute is set as well.
SMACK64IPIN
This attribute is only available on file descriptors for sockets.
Use the Smack label in this attribute for access control
decisions on packets being delivered to this socket.
SMACK64IPOUT
This attribute is only available on file descriptors for sockets.
Use the Smack label in this attribute for access control
decisions on packets coming from this socket.
There are multiple ways to set a Smack label on a file:
# attr -S -s SMACK64 -V "value" path
# chsmack -a value path
NOTE: Smack labels are limited to 23 characters. The attr command
does not enforce this restriction and can be used to set
invalid Smack labels on files.
If you don't do anything special all users will get the floor ("_")
label when they log in. If you do want to log in via the hacked ssh
at other labels use the attr command to set the smack value on the
home directory and its contents.
A process can see the smack label it is running with by
reading /proc/self/attr/current. A process with CAP_MAC_ADMIN
can set the process smack by writing there.
Most Smack configuration is accomplished by writing to files
in the smackfs filesystem. This pseudo-filesystem is usually
mounted on /smack.
access
This interface reports whether a subject with the specified
Smack label has a particular access to an object with a
specified Smack label. Write a fixed format access rule to
this file. The next read will indicate whether the access
would be permitted. The text will be either "1" indicating
access, or "0" indicating denial.
access2
This interface reports whether a subject with the specified
Smack label has a particular access to an object with a
specified Smack label. Write a long format access rule to
this file. The next read will indicate whether the access
would be permitted. The text will be either "1" indicating
access, or "0" indicating denial.
ambient
This contains the Smack label applied to unlabeled network
packets.
cipso
This interface allows a specific CIPSO header to be assigned
to a Smack label. The format accepted on write is:
"%24s%4d%4d"["%4d"]...
The first string is a fixed Smack label. The first number is
the level to use. The second number is the number of categories.
The following numbers are the categories.
"level-3-cats-5-19 3 2 5 19"
cipso2
This interface allows a specific CIPSO header to be assigned
to a Smack label. The format accepted on write is:
"%s%4d%4d"["%4d"]...
The first string is a long Smack label. The first number is
the level to use. The second number is the number of categories.
The following numbers are the categories.
"level-3-cats-5-19 3 2 5 19"
direct
This contains the CIPSO level used for Smack direct label
representation in network packets.
doi
This contains the CIPSO domain of interpretation used in
network packets.
load
This interface allows access control rules in addition to
the system defined rules to be specified. The format accepted
on write is:
"%24s%24s%5s"
where the first string is the subject label, the second the
object label, and the third the requested access. The access
string may contain only the characters "rwxat-", and specifies
which sort of access is allowed. The "-" is a placeholder for
permissions that are not allowed. The string "r-x--" would
specify read and execute access. Labels are limited to 23
characters in length.
load2
This interface allows access control rules in addition to
the system defined rules to be specified. The format accepted
on write is:
"%s %s %s"
where the first string is the subject label, the second the
object label, and the third the requested access. The access
string may contain only the characters "rwxat-", and specifies
which sort of access is allowed. The "-" is a placeholder for
permissions that are not allowed. The string "r-x--" would
specify read and execute access.
load-self
This interface allows process specific access rules to be
defined. These rules are only consulted if access would
otherwise be permitted, and are intended to provide additional
restrictions on the process. The format is the same as for
the load interface.
load-self2
This interface allows process specific access rules to be
defined. These rules are only consulted if access would
otherwise be permitted, and are intended to provide additional
restrictions on the process. The format is the same as for
the load2 interface.
logging
This contains the Smack logging state.
mapped
This contains the CIPSO level used for Smack mapped label
representation in network packets.
netlabel
This interface allows specific internet addresses to be
treated as single label hosts. Packets are sent to single
label hosts without CIPSO headers, but only from processes
that have Smack write access to the host label. All packets
received from single label hosts are given the specified
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
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.
You can add access rules in /etc/smack/accesses. They take the form:
...
...
@@ -83,10 +203,6 @@ access is a combination of the letters rwxa which specify the
kind of access permitted a subject with subjectlabel on an
object with objectlabel. If there is no rule no access is allowed.
A process can see the smack label it is running with by
reading /proc/self/attr/current. A privileged process can
set the process smack by writing there.
Look for additional programs on http://schaufler-ca.com
From the Smack Whitepaper:
...
...
@@ -186,7 +302,7 @@ team. Smack labels are unstructured, case sensitive, and the only operation
ever performed on them is comparison for equality. Smack labels cannot
contain unprintable characters, the "/" (slash), the "\" (backslash), the "'"
(quote) and '"' (double-quote) characters.
Smack labels cannot begin with a '-'
, which
is reserved for special options.
Smack labels cannot begin with a '-'
. This
is reserved for special options.
There are some predefined labels:
...
...
@@ -194,7 +310,7 @@ There are some predefined labels:
^ Pronounced "hat", a single circumflex character.
* Pronounced "star", a single asterisk character.
? Pronounced "huh", a single question mark character.
@ Pronounced "
Internet
", a single at sign character.
@ Pronounced "
web
", a single at sign character.
Every task on a Smack system is assigned a label. System tasks, such as
init(8) and systems daemons, are run with the floor ("_") label. User tasks
...
...
@@ -246,13 +362,14 @@ The format of an access rule is:
Where subject-label is the Smack label of the task, object-label is the Smack
label of the thing being accessed, and access is a string specifying the sort
of access allowed. The
Smack labels are limited to 23 characters. The access
specification is searched for letters that
describe access modes:
of access allowed. The
access specification is searched for letters that
describe access modes:
a: indicates that append access should be granted.
r: indicates that read access should be granted.
w: indicates that write access should be granted.
x: indicates that execute access should be granted.
t: indicates that the rule requests transmutation.
Uppercase values for the specification letters are allowed as well.
Access mode specifications can be in any order. Examples of acceptable rules
...
...
@@ -273,7 +390,7 @@ Examples of unacceptable rules are:
Spaces are not allowed in labels. Since a subject always has access to files
with the same label specifying a rule for that case is pointless. Only
valid letters (rwxa
RWXA
) and the dash ('-') character are allowed in
valid letters (rwxa
tRWXAT
) and the dash ('-') character are allowed in
access specifications. The dash is a placeholder, so "a-r" is the same
as "ar". A lone dash is used to specify that no access should be allowed.
...
...
@@ -297,6 +414,13 @@ but not any of its attributes by the circumstance of having read access to the
containing directory but not to the differently labeled file. This is an
artifact of the file name being data in the directory, not a part of the file.
If a directory is marked as transmuting (SMACK64TRANSMUTE=TRUE) and the
access rule that allows a process to create an object in that directory
includes 't' access the label assigned to the new object will be that
of the directory, not the creating process. This makes it much easier
for two processes with different labels to share data without granting
access to all of their files.
IPC objects, message queues, semaphore sets, and memory segments exist in flat
namespaces and access requests are only required to match the object in
question.
...
...
security/smack/smack.h
浏览文件 @
12fa8a27
...
...
@@ -23,13 +23,19 @@
#include <linux/lsm_audit.h>
/*
* Smack labels were limited to 23 characters for a long time.
*/
#define SMK_LABELLEN 24
#define SMK_LONGLABEL 256
/*
* Maximum number of bytes for the levels in a CIPSO IP option.
* Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
* bigger than can be used, and 24 is the next lower multiple
* of 8, and there are too many issues if there isn't space set
* aside for the terminating null byte.
*/
#define SMK_MAXLEN 23
#define SMK_LABELLEN (SMK_MAXLEN+1)
#define SMK_CIPSOLEN 24
struct
superblock_smack
{
char
*
smk_root
;
...
...
@@ -66,6 +72,7 @@ struct task_smack {
#define SMK_INODE_INSTANT 0x01
/* inode is instantiated */
#define SMK_INODE_TRANSMUTE 0x02
/* directory is transmuting */
#define SMK_INODE_CHANGED 0x04
/* smack was transmuted */
/*
* A label access rule.
...
...
@@ -77,15 +84,6 @@ struct smack_rule {
int
smk_access
;
};
/*
* An entry in the table mapping smack values to
* CIPSO level/category-set values.
*/
struct
smack_cipso
{
int
smk_level
;
char
smk_catset
[
SMK_LABELLEN
];
};
/*
* An entry in the table identifying hosts.
*/
...
...
@@ -113,22 +111,19 @@ struct smk_netlbladdr {
* interfaces don't. The secid should go away when all of
* these components have been repaired.
*
* If there is a cipso value associated with the label it
* gets stored here, too. This will most likely be rare as
* the cipso direct mapping in used internally.
* The cipso value associated with the label gets stored here, too.
*
* Keep the access rules for this subject label here so that
* the entire set of rules does not need to be examined every
* time.
*/
struct
smack_known
{
struct
list_head
list
;
char
smk_known
[
SMK_LABELLEN
];
u32
smk_secid
;
struct
smack_cipso
*
smk_cipso
;
spinlock_t
smk_cipsolock
;
/* for changing cipso map */
struct
list_head
smk_rules
;
/* access rules */
struct
mutex
smk_rules_lock
;
/* lock for the rules */
struct
list_head
list
;
char
*
smk_known
;
u32
smk_secid
;
struct
netlbl_lsm_secattr
smk_netlabel
;
/* on wire labels */
struct
list_head
smk_rules
;
/* access rules */
struct
mutex
smk_rules_lock
;
/* lock for rules */
};
/*
...
...
@@ -165,6 +160,7 @@ struct smack_known {
#define SMACK_CIPSO_DOI_DEFAULT 3
/* Historical */
#define SMACK_CIPSO_DOI_INVALID -1
/* Not a DOI */
#define SMACK_CIPSO_DIRECT_DEFAULT 250
/* Arbitrary */
#define SMACK_CIPSO_MAPPED_DEFAULT 251
/* Also arbitrary */
#define SMACK_CIPSO_MAXCATVAL 63
/* Bigger gets harder */
#define SMACK_CIPSO_MAXLEVEL 255
/* CIPSO 2.2 standard */
#define SMACK_CIPSO_MAXCATNUM 239
/* CIPSO 2.2 standard */
...
...
@@ -215,10 +211,9 @@ struct inode_smack *new_inode_smack(char *);
int
smk_access_entry
(
char
*
,
char
*
,
struct
list_head
*
);
int
smk_access
(
char
*
,
char
*
,
int
,
struct
smk_audit_info
*
);
int
smk_curacc
(
char
*
,
u32
,
struct
smk_audit_info
*
);
int
smack_to_cipso
(
const
char
*
,
struct
smack_cipso
*
);
char
*
smack_from_cipso
(
u32
,
char
*
);
char
*
smack_from_secid
(
const
u32
);
void
smk_parse_smack
(
const
char
*
string
,
int
len
,
char
*
smack
);
char
*
smk_parse_smack
(
const
char
*
string
,
int
len
);
int
smk_netlbl_mls
(
int
,
char
*
,
struct
netlbl_lsm_secattr
*
,
int
);
char
*
smk_import
(
const
char
*
,
int
);
struct
smack_known
*
smk_import_entry
(
const
char
*
,
int
);
struct
smack_known
*
smk_find_entry
(
const
char
*
);
...
...
@@ -228,6 +223,7 @@ u32 smack_to_secid(const char *);
* Shared data.
*/
extern
int
smack_cipso_direct
;
extern
int
smack_cipso_mapped
;
extern
char
*
smack_net_ambient
;
extern
char
*
smack_onlycap
;
extern
const
char
*
smack_cipso_option
;
...
...
@@ -239,23 +235,12 @@ extern struct smack_known smack_known_invalid;
extern
struct
smack_known
smack_known_star
;
extern
struct
smack_known
smack_known_web
;
extern
struct
mutex
smack_known_lock
;
extern
struct
list_head
smack_known_list
;
extern
struct
list_head
smk_netlbladdr_list
;
extern
struct
security_operations
smack_ops
;
/*
* Stricly for CIPSO level manipulation.
* Set the category bit number in a smack label sized buffer.
*/
static
inline
void
smack_catset_bit
(
int
cat
,
char
*
catsetp
)
{
if
(
cat
>
SMK_LABELLEN
*
8
)
return
;
catsetp
[(
cat
-
1
)
/
8
]
|=
0x80
>>
((
cat
-
1
)
%
8
);
}
/*
* Is the directory transmuting?
*/
...
...
security/smack/smack_access.c
浏览文件 @
12fa8a27
...
...
@@ -19,37 +19,31 @@
struct
smack_known
smack_known_huh
=
{
.
smk_known
=
"?"
,
.
smk_secid
=
2
,
.
smk_cipso
=
NULL
,
};
struct
smack_known
smack_known_hat
=
{
.
smk_known
=
"^"
,
.
smk_secid
=
3
,
.
smk_cipso
=
NULL
,
};
struct
smack_known
smack_known_star
=
{
.
smk_known
=
"*"
,
.
smk_secid
=
4
,
.
smk_cipso
=
NULL
,
};
struct
smack_known
smack_known_floor
=
{
.
smk_known
=
"_"
,
.
smk_secid
=
5
,
.
smk_cipso
=
NULL
,
};
struct
smack_known
smack_known_invalid
=
{
.
smk_known
=
""
,
.
smk_secid
=
6
,
.
smk_cipso
=
NULL
,
};
struct
smack_known
smack_known_web
=
{
.
smk_known
=
"@"
,
.
smk_secid
=
7
,
.
smk_cipso
=
NULL
,
};
LIST_HEAD
(
smack_known_list
);
...
...
@@ -331,7 +325,7 @@ void smack_log(char *subject_label, char *object_label, int request,
}
#endif
static
DEFINE_MUTEX
(
smack_known_lock
);
DEFINE_MUTEX
(
smack_known_lock
);
/**
* smk_find_entry - find a label on the list, return the list entry
...
...
@@ -345,7 +339,7 @@ struct smack_known *smk_find_entry(const char *string)
struct
smack_known
*
skp
;
list_for_each_entry_rcu
(
skp
,
&
smack_known_list
,
list
)
{
if
(
str
ncmp
(
skp
->
smk_known
,
string
,
SMK_MAXLEN
)
==
0
)
if
(
str
cmp
(
skp
->
smk_known
,
string
)
==
0
)
return
skp
;
}
...
...
@@ -356,27 +350,76 @@ struct smack_known *smk_find_entry(const char *string)
* smk_parse_smack - parse smack label from a text string
* @string: a text string that might contain a Smack label
* @len: the maximum size, or zero if it is NULL terminated.
* @smack: parsed smack label, or NULL if parse error
*
* Returns a pointer to the clean label, or NULL
*/
void
smk_parse_smack
(
const
char
*
string
,
int
len
,
char
*
smack
)
char
*
smk_parse_smack
(
const
char
*
string
,
int
len
)
{
int
found
;
char
*
smack
;
int
i
;
if
(
len
<=
0
||
len
>
SMK_MAXLEN
)
len
=
SMK_MAXLEN
;
for
(
i
=
0
,
found
=
0
;
i
<
SMK_LABELLEN
;
i
++
)
{
if
(
found
)
smack
[
i
]
=
'\0'
;
else
if
(
i
>=
len
||
string
[
i
]
>
'~'
||
string
[
i
]
<=
' '
||
string
[
i
]
==
'/'
||
string
[
i
]
==
'"'
||
string
[
i
]
==
'\\'
||
string
[
i
]
==
'\''
)
{
smack
[
i
]
=
'\0'
;
found
=
1
;
}
else
smack
[
i
]
=
string
[
i
];
if
(
len
<=
0
)
len
=
strlen
(
string
)
+
1
;
/*
* Reserve a leading '-' as an indicator that
* this isn't a label, but an option to interfaces
* including /smack/cipso and /smack/cipso2
*/
if
(
string
[
0
]
==
'-'
)
return
NULL
;
for
(
i
=
0
;
i
<
len
;
i
++
)
if
(
string
[
i
]
>
'~'
||
string
[
i
]
<=
' '
||
string
[
i
]
==
'/'
||
string
[
i
]
==
'"'
||
string
[
i
]
==
'\\'
||
string
[
i
]
==
'\''
)
break
;
if
(
i
==
0
||
i
>=
SMK_LONGLABEL
)
return
NULL
;
smack
=
kzalloc
(
i
+
1
,
GFP_KERNEL
);
if
(
smack
!=
NULL
)
{
strncpy
(
smack
,
string
,
i
+
1
);
smack
[
i
]
=
'\0'
;
}
return
smack
;
}
/**
* smk_netlbl_mls - convert a catset to netlabel mls categories
* @catset: the Smack categories
* @sap: where to put the netlabel categories
*
* Allocates and fills attr.mls
* Returns 0 on success, error code on failure.
*/
int
smk_netlbl_mls
(
int
level
,
char
*
catset
,
struct
netlbl_lsm_secattr
*
sap
,
int
len
)
{
unsigned
char
*
cp
;
unsigned
char
m
;
int
cat
;
int
rc
;
int
byte
;
sap
->
flags
|=
NETLBL_SECATTR_MLS_CAT
;
sap
->
attr
.
mls
.
lvl
=
level
;
sap
->
attr
.
mls
.
cat
=
netlbl_secattr_catmap_alloc
(
GFP_ATOMIC
);
sap
->
attr
.
mls
.
cat
->
startbit
=
0
;
for
(
cat
=
1
,
cp
=
catset
,
byte
=
0
;
byte
<
len
;
cp
++
,
byte
++
)
for
(
m
=
0x80
;
m
!=
0
;
m
>>=
1
,
cat
++
)
{
if
((
m
&
*
cp
)
==
0
)
continue
;
rc
=
netlbl_secattr_catmap_setbit
(
sap
->
attr
.
mls
.
cat
,
cat
,
GFP_ATOMIC
);
if
(
rc
<
0
)
{
netlbl_secattr_catmap_free
(
sap
->
attr
.
mls
.
cat
);
return
rc
;
}
}
return
0
;
}
/**
...
...
@@ -390,33 +433,59 @@ void smk_parse_smack(const char *string, int len, char *smack)
struct
smack_known
*
smk_import_entry
(
const
char
*
string
,
int
len
)
{
struct
smack_known
*
skp
;
char
smack
[
SMK_LABELLEN
];
char
*
smack
;
int
slen
;
int
rc
;
sm
k_parse_smack
(
string
,
len
,
smack
);
if
(
smack
[
0
]
==
'\0'
)
sm
ack
=
smk_parse_smack
(
string
,
len
);
if
(
smack
==
NULL
)
return
NULL
;
mutex_lock
(
&
smack_known_lock
);
skp
=
smk_find_entry
(
smack
);
if
(
skp
!=
NULL
)
goto
freeout
;
if
(
skp
==
NULL
)
{
skp
=
kzalloc
(
sizeof
(
struct
smack_known
),
GFP_KERNEL
);
if
(
skp
!=
NULL
)
{
strncpy
(
skp
->
smk_known
,
smack
,
SMK_MAXLEN
);
skp
->
smk_secid
=
smack_next_secid
++
;
skp
->
smk_cipso
=
NULL
;
INIT_LIST_HEAD
(
&
skp
->
smk_rules
);
spin_lock_init
(
&
skp
->
smk_cipsolock
);
mutex_init
(
&
skp
->
smk_rules_lock
);
/*
* Make sure that the entry is actually
* filled before putting it on the list.
*/
list_add_rcu
(
&
skp
->
list
,
&
smack_known_list
);
}
}
skp
=
kzalloc
(
sizeof
(
*
skp
),
GFP_KERNEL
);
if
(
skp
==
NULL
)
goto
freeout
;
skp
->
smk_known
=
smack
;
skp
->
smk_secid
=
smack_next_secid
++
;
skp
->
smk_netlabel
.
domain
=
skp
->
smk_known
;
skp
->
smk_netlabel
.
flags
=
NETLBL_SECATTR_DOMAIN
|
NETLBL_SECATTR_MLS_LVL
;
/*
* If direct labeling works use it.
* Otherwise use mapped labeling.
*/
slen
=
strlen
(
smack
);
if
(
slen
<
SMK_CIPSOLEN
)
rc
=
smk_netlbl_mls
(
smack_cipso_direct
,
skp
->
smk_known
,
&
skp
->
smk_netlabel
,
slen
);
else
rc
=
smk_netlbl_mls
(
smack_cipso_mapped
,
(
char
*
)
&
skp
->
smk_secid
,
&
skp
->
smk_netlabel
,
sizeof
(
skp
->
smk_secid
));
if
(
rc
>=
0
)
{
INIT_LIST_HEAD
(
&
skp
->
smk_rules
);
mutex_init
(
&
skp
->
smk_rules_lock
);
/*
* Make sure that the entry is actually
* filled before putting it on the list.
*/
list_add_rcu
(
&
skp
->
list
,
&
smack_known_list
);
goto
unlockout
;
}
/*
* smk_netlbl_mls failed.
*/
kfree
(
skp
);
skp
=
NULL
;
freeout:
kfree
(
smack
);
unlockout:
mutex_unlock
(
&
smack_known_lock
);
return
skp
;
...
...
@@ -479,79 +548,9 @@ char *smack_from_secid(const u32 secid)
*/
u32
smack_to_secid
(
const
char
*
smack
)
{
struct
smack_known
*
skp
;
struct
smack_known
*
skp
=
smk_find_entry
(
smack
)
;
rcu_read_lock
();
list_for_each_entry_rcu
(
skp
,
&
smack_known_list
,
list
)
{
if
(
strncmp
(
skp
->
smk_known
,
smack
,
SMK_MAXLEN
)
==
0
)
{
rcu_read_unlock
();
return
skp
->
smk_secid
;
}
}
rcu_read_unlock
();
return
0
;
}
/**
* smack_from_cipso - find the Smack label associated with a CIPSO option
* @level: Bell & LaPadula level from the network
* @cp: Bell & LaPadula categories from the network
*
* This is a simple lookup in the label table.
*
* Return the matching label from the label list or NULL.
*/
char
*
smack_from_cipso
(
u32
level
,
char
*
cp
)
{
struct
smack_known
*
kp
;
char
*
final
=
NULL
;
rcu_read_lock
();
list_for_each_entry
(
kp
,
&
smack_known_list
,
list
)
{
if
(
kp
->
smk_cipso
==
NULL
)
continue
;
spin_lock_bh
(
&
kp
->
smk_cipsolock
);
if
(
kp
->
smk_cipso
->
smk_level
==
level
&&
memcmp
(
kp
->
smk_cipso
->
smk_catset
,
cp
,
SMK_LABELLEN
)
==
0
)
final
=
kp
->
smk_known
;
spin_unlock_bh
(
&
kp
->
smk_cipsolock
);
if
(
final
!=
NULL
)
break
;
}
rcu_read_unlock
();
return
final
;
}
/**
* smack_to_cipso - find the CIPSO option to go with a Smack label
* @smack: a pointer to the smack label in question
* @cp: where to put the result
*
* Returns zero if a value is available, non-zero otherwise.
*/
int
smack_to_cipso
(
const
char
*
smack
,
struct
smack_cipso
*
cp
)
{
struct
smack_known
*
kp
;
int
found
=
0
;
rcu_read_lock
();
list_for_each_entry_rcu
(
kp
,
&
smack_known_list
,
list
)
{
if
(
kp
->
smk_known
==
smack
||
strcmp
(
kp
->
smk_known
,
smack
)
==
0
)
{
found
=
1
;
break
;
}
}
rcu_read_unlock
();
if
(
found
==
0
||
kp
->
smk_cipso
==
NULL
)
return
-
ENOENT
;
memcpy
(
cp
,
kp
->
smk_cipso
,
sizeof
(
struct
smack_cipso
));
return
0
;
if
(
skp
==
NULL
)
return
0
;
return
skp
->
smk_secid
;
}
security/smack/smack_lsm.c
浏览文件 @
12fa8a27
...
...
@@ -30,7 +30,6 @@
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/pipe_fs_i.h>
#include <net/netlabel.h>
#include <net/cipso_ipv4.h>
#include <linux/audit.h>
#include <linux/magic.h>
...
...
@@ -57,16 +56,23 @@
static
char
*
smk_fetch
(
const
char
*
name
,
struct
inode
*
ip
,
struct
dentry
*
dp
)
{
int
rc
;
char
in
[
SMK_LABELLEN
];
char
*
buffer
;
char
*
result
=
NULL
;
if
(
ip
->
i_op
->
getxattr
==
NULL
)
return
NULL
;
rc
=
ip
->
i_op
->
getxattr
(
dp
,
name
,
in
,
SMK_LABELLEN
);
if
(
rc
<
0
)
buffer
=
kzalloc
(
SMK_LONGLABEL
,
GFP_KERNEL
);
if
(
buffer
==
NULL
)
return
NULL
;
return
smk_import
(
in
,
rc
);
rc
=
ip
->
i_op
->
getxattr
(
dp
,
name
,
buffer
,
SMK_LONGLABEL
);
if
(
rc
>
0
)
result
=
smk_import
(
buffer
,
rc
);
kfree
(
buffer
);
return
result
;
}
/**
...
...
@@ -79,7 +85,7 @@ struct inode_smack *new_inode_smack(char *smack)
{
struct
inode_smack
*
isp
;
isp
=
kzalloc
(
sizeof
(
struct
inode_smack
),
GFP_
KERNEL
);
isp
=
kzalloc
(
sizeof
(
struct
inode_smack
),
GFP_
NOFS
);
if
(
isp
==
NULL
)
return
NULL
;
...
...
@@ -556,13 +562,14 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
void
**
value
,
size_t
*
len
)
{
struct
smack_known
*
skp
;
struct
inode_smack
*
issp
=
inode
->
i_security
;
char
*
csp
=
smk_of_current
();
char
*
isp
=
smk_of_inode
(
inode
);
char
*
dsp
=
smk_of_inode
(
dir
);
int
may
;
if
(
name
)
{
*
name
=
kstrdup
(
XATTR_SMACK_SUFFIX
,
GFP_
KERNEL
);
*
name
=
kstrdup
(
XATTR_SMACK_SUFFIX
,
GFP_
NOFS
);
if
(
*
name
==
NULL
)
return
-
ENOMEM
;
}
...
...
@@ -577,12 +584,15 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
* If the access rule allows transmutation and
* the directory requests transmutation then
* by all means transmute.
* Mark the inode as changed.
*/
if
(
may
>
0
&&
((
may
&
MAY_TRANSMUTE
)
!=
0
)
&&
smk_inode_transmutable
(
dir
))
smk_inode_transmutable
(
dir
))
{
isp
=
dsp
;
issp
->
smk_flags
|=
SMK_INODE_CHANGED
;
}
*
value
=
kstrdup
(
isp
,
GFP_
KERNEL
);
*
value
=
kstrdup
(
isp
,
GFP_
NOFS
);
if
(
*
value
==
NULL
)
return
-
ENOMEM
;
}
...
...
@@ -821,7 +831,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
* check label validity here so import wont fail on
* post_setxattr
*/
if
(
size
==
0
||
size
>=
SMK_L
ABELLEN
||
if
(
size
==
0
||
size
>=
SMK_L
ONGLABEL
||
smk_import
(
value
,
size
)
==
NULL
)
rc
=
-
EINVAL
;
}
else
if
(
strcmp
(
name
,
XATTR_NAME_SMACKTRANSMUTE
)
==
0
)
{
...
...
@@ -1819,65 +1829,6 @@ static char *smack_host_label(struct sockaddr_in *sip)
return
NULL
;
}
/**
* smack_set_catset - convert a capset to netlabel mls categories
* @catset: the Smack categories
* @sap: where to put the netlabel categories
*
* Allocates and fills attr.mls.cat
*/
static
void
smack_set_catset
(
char
*
catset
,
struct
netlbl_lsm_secattr
*
sap
)
{
unsigned
char
*
cp
;
unsigned
char
m
;
int
cat
;
int
rc
;
int
byte
;
if
(
!
catset
)
return
;
sap
->
flags
|=
NETLBL_SECATTR_MLS_CAT
;
sap
->
attr
.
mls
.
cat
=
netlbl_secattr_catmap_alloc
(
GFP_ATOMIC
);
sap
->
attr
.
mls
.
cat
->
startbit
=
0
;
for
(
cat
=
1
,
cp
=
catset
,
byte
=
0
;
byte
<
SMK_LABELLEN
;
cp
++
,
byte
++
)
for
(
m
=
0x80
;
m
!=
0
;
m
>>=
1
,
cat
++
)
{
if
((
m
&
*
cp
)
==
0
)
continue
;
rc
=
netlbl_secattr_catmap_setbit
(
sap
->
attr
.
mls
.
cat
,
cat
,
GFP_ATOMIC
);
}
}
/**
* smack_to_secattr - fill a secattr from a smack value
* @smack: the smack value
* @nlsp: where the result goes
*
* Casey says that CIPSO is good enough for now.
* It can be used to effect.
* It can also be abused to effect when necessary.
* Apologies to the TSIG group in general and GW in particular.
*/
static
void
smack_to_secattr
(
char
*
smack
,
struct
netlbl_lsm_secattr
*
nlsp
)
{
struct
smack_cipso
cipso
;
int
rc
;
nlsp
->
domain
=
smack
;
nlsp
->
flags
=
NETLBL_SECATTR_DOMAIN
|
NETLBL_SECATTR_MLS_LVL
;
rc
=
smack_to_cipso
(
smack
,
&
cipso
);
if
(
rc
==
0
)
{
nlsp
->
attr
.
mls
.
lvl
=
cipso
.
smk_level
;
smack_set_catset
(
cipso
.
smk_catset
,
nlsp
);
}
else
{
nlsp
->
attr
.
mls
.
lvl
=
smack_cipso_direct
;
smack_set_catset
(
smack
,
nlsp
);
}
}
/**
* smack_netlabel - Set the secattr on a socket
* @sk: the socket
...
...
@@ -1890,8 +1841,8 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
*/
static
int
smack_netlabel
(
struct
sock
*
sk
,
int
labeled
)
{
struct
smack_known
*
skp
;
struct
socket_smack
*
ssp
=
sk
->
sk_security
;
struct
netlbl_lsm_secattr
secattr
;
int
rc
=
0
;
/*
...
...
@@ -1909,10 +1860,8 @@ static int smack_netlabel(struct sock *sk, int labeled)
labeled
==
SMACK_UNLABELED_SOCKET
)
netlbl_sock_delattr
(
sk
);
else
{
netlbl_secattr_init
(
&
secattr
);
smack_to_secattr
(
ssp
->
smk_out
,
&
secattr
);
rc
=
netlbl_sock_setattr
(
sk
,
sk
->
sk_family
,
&
secattr
);
netlbl_secattr_destroy
(
&
secattr
);
skp
=
smk_find_entry
(
ssp
->
smk_out
);
rc
=
netlbl_sock_setattr
(
sk
,
sk
->
sk_family
,
&
skp
->
smk_netlabel
);
}
bh_unlock_sock
(
sk
);
...
...
@@ -1985,7 +1934,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
struct
socket
*
sock
;
int
rc
=
0
;
if
(
value
==
NULL
||
size
>
SMK_L
ABELLEN
||
size
==
0
)
if
(
value
==
NULL
||
size
>
SMK_L
ONGLABEL
||
size
==
0
)
return
-
EACCES
;
sp
=
smk_import
(
value
,
size
);
...
...
@@ -2552,6 +2501,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
char
*
final
;
char
trattr
[
TRANS_TRUE_SIZE
];
int
transflag
=
0
;
int
rc
;
struct
dentry
*
dp
;
if
(
inode
==
NULL
)
...
...
@@ -2670,17 +2620,38 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
*/
dp
=
dget
(
opt_dentry
);
fetched
=
smk_fetch
(
XATTR_NAME_SMACK
,
inode
,
dp
);
if
(
fetched
!=
NULL
)
{
if
(
fetched
!=
NULL
)
final
=
fetched
;
if
(
S_ISDIR
(
inode
->
i_mode
))
{
trattr
[
0
]
=
'\0'
;
inode
->
i_op
->
getxattr
(
dp
,
/*
* Transmuting directory
*/
if
(
S_ISDIR
(
inode
->
i_mode
))
{
/*
* If this is a new directory and the label was
* transmuted when the inode was initialized
* set the transmute attribute on the directory
* and mark the inode.
*
* If there is a transmute attribute on the
* directory mark the inode.
*/
if
(
isp
->
smk_flags
&
SMK_INODE_CHANGED
)
{
isp
->
smk_flags
&=
~
SMK_INODE_CHANGED
;
rc
=
inode
->
i_op
->
setxattr
(
dp
,
XATTR_NAME_SMACKTRANSMUTE
,
trattr
,
TRANS_TRUE_SIZE
);
if
(
strncmp
(
trattr
,
TRANS_TRUE
,
TRANS_TRUE_SIZE
)
==
0
)
transflag
=
SMK_INODE_TRANSMUTE
;
TRANS_TRUE
,
TRANS_TRUE_SIZE
,
0
);
}
else
{
rc
=
inode
->
i_op
->
getxattr
(
dp
,
XATTR_NAME_SMACKTRANSMUTE
,
trattr
,
TRANS_TRUE_SIZE
);
if
(
rc
>=
0
&&
strncmp
(
trattr
,
TRANS_TRUE
,
TRANS_TRUE_SIZE
)
!=
0
)
rc
=
-
EINVAL
;
}
if
(
rc
>=
0
)
transflag
=
SMK_INODE_TRANSMUTE
;
}
isp
->
smk_task
=
smk_fetch
(
XATTR_NAME_SMACKEXEC
,
inode
,
dp
);
isp
->
smk_mmap
=
smk_fetch
(
XATTR_NAME_SMACKMMAP
,
inode
,
dp
);
...
...
@@ -2759,7 +2730,7 @@ static int smack_setprocattr(struct task_struct *p, char *name,
if
(
!
capable
(
CAP_MAC_ADMIN
))
return
-
EPERM
;
if
(
value
==
NULL
||
size
==
0
||
size
>=
SMK_L
ABELLEN
)
if
(
value
==
NULL
||
size
==
0
||
size
>=
SMK_L
ONGLABEL
)
return
-
EINVAL
;
if
(
strcmp
(
name
,
"current"
)
!=
0
)
...
...
@@ -2895,10 +2866,9 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
static
char
*
smack_from_secattr
(
struct
netlbl_lsm_secattr
*
sap
,
struct
socket_smack
*
ssp
)
{
struct
smack_known
*
skp
;
char
smack
[
SMK_LABELLEN
];
struct
smack_known
*
kp
;
char
*
sp
;
int
pcat
;
int
found
=
0
;
if
((
sap
->
flags
&
NETLBL_SECATTR_MLS_LVL
)
!=
0
)
{
/*
...
...
@@ -2906,59 +2876,27 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
* If there are flags but no level netlabel isn't
* behaving the way we expect it to.
*
*
Get the categories, if any
*
Look it up in the label table
* Without guidance regarding the smack value
* for the packet fall back on the network
* ambient value.
*/
memset
(
smack
,
'\0'
,
SMK_LABELLEN
);
if
((
sap
->
flags
&
NETLBL_SECATTR_MLS_CAT
)
!=
0
)
for
(
pcat
=
-
1
;;)
{
pcat
=
netlbl_secattr_catmap_walk
(
sap
->
attr
.
mls
.
cat
,
pcat
+
1
);
if
(
pcat
<
0
)
break
;
smack_catset_bit
(
pcat
,
smack
);
}
/*
* If it is CIPSO using smack direct mapping
* we are already done. WeeHee.
*/
if
(
sap
->
attr
.
mls
.
lvl
==
smack_cipso_direct
)
{
/*
* The label sent is usually on the label list.
*
* If it is not we may still want to allow the
* delivery.
*
* If the recipient is accepting all packets
* because it is using the star ("*") label
* for SMACK64IPIN provide the web ("@") label
* so that a directed response will succeed.
* This is not very correct from a MAC point
* of view, but gets around the problem that
* locking prevents adding the newly discovered
* label to the list.
* The case where the recipient is not using
* the star label should obviously fail.
* The easy way to do this is to provide the
* star label as the subject label.
*/
skp
=
smk_find_entry
(
smack
);
if
(
skp
!=
NULL
)
return
skp
->
smk_known
;
if
(
ssp
!=
NULL
&&
ssp
->
smk_in
==
smack_known_star
.
smk_known
)
return
smack_known_web
.
smk_known
;
return
smack_known_star
.
smk_known
;
rcu_read_lock
();
list_for_each_entry
(
kp
,
&
smack_known_list
,
list
)
{
if
(
sap
->
attr
.
mls
.
lvl
!=
kp
->
smk_netlabel
.
attr
.
mls
.
lvl
)
continue
;
if
(
memcmp
(
sap
->
attr
.
mls
.
cat
,
kp
->
smk_netlabel
.
attr
.
mls
.
cat
,
SMK_CIPSOLEN
)
!=
0
)
continue
;
found
=
1
;
break
;
}
/*
* Look it up in the supplied table if it is not
* a direct mapping.
*/
sp
=
smack_from_cipso
(
sap
->
attr
.
mls
.
lvl
,
smack
);
if
(
sp
!=
NULL
)
return
sp
;
rcu_read_unlock
();
if
(
found
)
return
kp
->
smk_known
;
if
(
ssp
!=
NULL
&&
ssp
->
smk_in
==
smack_known_star
.
smk_known
)
return
smack_known_web
.
smk_known
;
return
smack_known_star
.
smk_known
;
...
...
@@ -3158,11 +3096,13 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
struct
request_sock
*
req
)
{
u16
family
=
sk
->
sk_family
;
struct
smack_known
*
skp
;
struct
socket_smack
*
ssp
=
sk
->
sk_security
;
struct
netlbl_lsm_secattr
secattr
;
struct
sockaddr_in
addr
;
struct
iphdr
*
hdr
;
char
*
sp
;
char
*
hsp
;
int
rc
;
struct
smk_audit_info
ad
;
#ifdef CONFIG_AUDIT
...
...
@@ -3209,16 +3149,14 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
hdr
=
ip_hdr
(
skb
);
addr
.
sin_addr
.
s_addr
=
hdr
->
saddr
;
rcu_read_lock
();
if
(
smack_host_label
(
&
addr
)
==
NULL
)
{
rcu_read_unlock
();
netlbl_secattr_init
(
&
secattr
);
smack_to_secattr
(
sp
,
&
secattr
);
rc
=
netlbl_req_setattr
(
req
,
&
secattr
);
netlbl_secattr_destroy
(
&
secattr
);
}
else
{
rcu_read_unlock
();
hsp
=
smack_host_label
(
&
addr
);
rcu_read_unlock
();
if
(
hsp
==
NULL
)
{
skp
=
smk_find_entry
(
sp
);
rc
=
netlbl_req_setattr
(
req
,
&
skp
->
smk_netlabel
);
}
else
netlbl_req_delattr
(
req
);
}
return
rc
;
}
...
...
@@ -3400,7 +3338,7 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule,
char
*
rule
=
vrule
;
if
(
!
rule
)
{
audit_log
(
actx
,
GFP_
KERNEL
,
AUDIT_SELINUX_ERR
,
audit_log
(
actx
,
GFP_
ATOMIC
,
AUDIT_SELINUX_ERR
,
"Smack: missing rule
\n
"
);
return
-
ENOENT
;
}
...
...
@@ -3642,15 +3580,6 @@ struct security_operations smack_ops = {
static
__init
void
init_smack_known_list
(
void
)
{
/*
* Initialize CIPSO locks
*/
spin_lock_init
(
&
smack_known_huh
.
smk_cipsolock
);
spin_lock_init
(
&
smack_known_hat
.
smk_cipsolock
);
spin_lock_init
(
&
smack_known_star
.
smk_cipsolock
);
spin_lock_init
(
&
smack_known_floor
.
smk_cipsolock
);
spin_lock_init
(
&
smack_known_invalid
.
smk_cipsolock
);
spin_lock_init
(
&
smack_known_web
.
smk_cipsolock
);
/*
* Initialize rule list locks
*/
...
...
security/smack/smackfs.c
浏览文件 @
12fa8a27
...
...
@@ -22,7 +22,6 @@
#include <linux/mutex.h>
#include <linux/slab.h>
#include <net/net_namespace.h>
#include <net/netlabel.h>
#include <net/cipso_ipv4.h>
#include <linux/seq_file.h>
#include <linux/ctype.h>
...
...
@@ -45,6 +44,11 @@ enum smk_inos {
SMK_LOGGING
=
10
,
/* logging */
SMK_LOAD_SELF
=
11
,
/* task specific rules */
SMK_ACCESSES
=
12
,
/* access policy */
SMK_MAPPED
=
13
,
/* CIPSO level indicating mapped label */
SMK_LOAD2
=
14
,
/* load policy with long labels */
SMK_LOAD_SELF2
=
15
,
/* load task specific rules with long labels */
SMK_ACCESS2
=
16
,
/* make an access check with long labels */
SMK_CIPSO2
=
17
,
/* load long label -> CIPSO mapping */
};
/*
...
...
@@ -60,7 +64,7 @@ static DEFINE_MUTEX(smk_netlbladdr_lock);
* If it isn't somehow marked, use this.
* It can be reset via smackfs/ambient
*/
char
*
smack_net_ambient
=
smack_known_floor
.
smk_known
;
char
*
smack_net_ambient
;
/*
* This is the level in a CIPSO header that indicates a
...
...
@@ -69,6 +73,13 @@ char *smack_net_ambient = smack_known_floor.smk_known;
*/
int
smack_cipso_direct
=
SMACK_CIPSO_DIRECT_DEFAULT
;
/*
* This is the level in a CIPSO header that indicates a
* secid is contained directly in the category set.
* It can be reset via smackfs/mapped
*/
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
...
...
@@ -89,7 +100,7 @@ LIST_HEAD(smk_netlbladdr_list);
/*
* Rule lists are maintained for each label.
* This master list is just for reading /smack/load.
* This master list is just for reading /smack/load
and /smack/load2
.
*/
struct
smack_master_list
{
struct
list_head
list
;
...
...
@@ -125,6 +136,18 @@ const char *smack_cipso_option = SMACK_CIPSO_OPTION;
#define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN)
#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
/*
* Stricly for CIPSO level manipulation.
* Set the category bit number in a smack label sized buffer.
*/
static
inline
void
smack_catset_bit
(
unsigned
int
cat
,
char
*
catsetp
)
{
if
(
cat
==
0
||
cat
>
(
SMK_CIPSOLEN
*
8
))
return
;
catsetp
[(
cat
-
1
)
/
8
]
|=
0x80
>>
((
cat
-
1
)
%
8
);
}
/**
* smk_netlabel_audit_set - fill a netlbl_audit struct
* @nap: structure to fill
...
...
@@ -137,12 +160,10 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap)
}
/*
* Value
s
for parsing single label host rules
* Value for parsing single label host rules
* "1.2.3.4 X"
* "192.168.138.129/32 abcdefghijklmnopqrstuvw"
*/
#define SMK_NETLBLADDRMIN 9
#define SMK_NETLBLADDRMAX 42
/**
* smk_set_access - add a rule to the rule list
...
...
@@ -188,33 +209,47 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
}
/**
* smk_parse_rule - parse Smack rule from load string
* @data: string to be parsed whose size is SMK_LOADLEN
* smk_fill_rule - Fill Smack rule from strings
* @subject: subject label string
* @object: object label string
* @access: access string
* @rule: Smack rule
* @import: if non-zero, import labels
*
* Returns 0 on success, -1 on failure
*/
static
int
smk_parse_rule
(
const
char
*
data
,
struct
smack_rule
*
rule
,
int
import
)
static
int
smk_fill_rule
(
const
char
*
subject
,
const
char
*
object
,
const
char
*
access
,
struct
smack_rule
*
rule
,
int
import
)
{
char
smack
[
SMK_LABELLEN
];
int
rc
=
-
1
;
int
done
;
const
char
*
cp
;
struct
smack_known
*
skp
;
if
(
import
)
{
rule
->
smk_subject
=
smk_import
(
data
,
0
);
rule
->
smk_subject
=
smk_import
(
subject
,
0
);
if
(
rule
->
smk_subject
==
NULL
)
return
-
1
;
rule
->
smk_object
=
smk_import
(
data
+
SMK_LABELLEN
,
0
);
rule
->
smk_object
=
smk_import
(
object
,
0
);
if
(
rule
->
smk_object
==
NULL
)
return
-
1
;
}
else
{
smk_parse_smack
(
data
,
0
,
smack
);
skp
=
smk_find_entry
(
smack
);
cp
=
smk_parse_smack
(
subject
,
0
);
if
(
cp
==
NULL
)
return
-
1
;
skp
=
smk_find_entry
(
cp
);
kfree
(
cp
);
if
(
skp
==
NULL
)
return
-
1
;
rule
->
smk_subject
=
skp
->
smk_known
;
smk_parse_smack
(
data
+
SMK_LABELLEN
,
0
,
smack
);
skp
=
smk_find_entry
(
smack
);
cp
=
smk_parse_smack
(
object
,
0
);
if
(
cp
==
NULL
)
return
-
1
;
skp
=
smk_find_entry
(
cp
);
kfree
(
cp
);
if
(
skp
==
NULL
)
return
-
1
;
rule
->
smk_object
=
skp
->
smk_known
;
...
...
@@ -222,90 +257,127 @@ static int smk_parse_rule(const char *data, struct smack_rule *rule, int import)
rule
->
smk_access
=
0
;
switch
(
data
[
SMK_LABELLEN
+
SMK_LABELLEN
])
{
case
'-'
:
break
;
case
'r'
:
case
'R'
:
rule
->
smk_access
|=
MAY_READ
;
break
;
default:
return
-
1
;
for
(
cp
=
access
,
done
=
0
;
*
cp
&&
!
done
;
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:
done
=
1
;
break
;
}
}
rc
=
0
;
switch
(
data
[
SMK_LABELLEN
+
SMK_LABELLEN
+
1
])
{
case
'-'
:
break
;
case
'w'
:
case
'W'
:
rule
->
smk_access
|=
MAY_WRITE
;
break
;
default:
return
-
1
;
}
return
rc
;
}
switch
(
data
[
SMK_LABELLEN
+
SMK_LABELLEN
+
2
])
{
case
'-'
:
break
;
case
'x'
:
case
'X'
:
rule
->
smk_access
|=
MAY_EXEC
;
break
;
default:
return
-
1
;
}
/**
* smk_parse_rule - parse Smack rule from load string
* @data: string to be parsed whose size is SMK_LOADLEN
* @rule: Smack rule
* @import: if non-zero, import labels
*
* Returns 0 on success, -1 on errors.
*/
static
int
smk_parse_rule
(
const
char
*
data
,
struct
smack_rule
*
rule
,
int
import
)
{
int
rc
;
switch
(
data
[
SMK_LABELLEN
+
SMK_LABELLEN
+
3
])
{
case
'-'
:
break
;
case
'a'
:
case
'A'
:
rule
->
smk_access
|=
MAY_APPEND
;
break
;
default:
return
-
1
;
}
rc
=
smk_fill_rule
(
data
,
data
+
SMK_LABELLEN
,
data
+
SMK_LABELLEN
+
SMK_LABELLEN
,
rule
,
import
);
return
rc
;
}
switch
(
data
[
SMK_LABELLEN
+
SMK_LABELLEN
+
4
])
{
case
'-'
:
break
;
case
't'
:
case
'T'
:
rule
->
smk_access
|=
MAY_TRANSMUTE
;
break
;
default:
return
-
1
;
}
/**
* smk_parse_long_rule - parse Smack rule from rule string
* @data: string to be parsed, null terminated
* @rule: Smack rule
* @import: if non-zero, import labels
*
* Returns 0 on success, -1 on failure
*/
static
int
smk_parse_long_rule
(
const
char
*
data
,
struct
smack_rule
*
rule
,
int
import
)
{
char
*
subject
;
char
*
object
;
char
*
access
;
int
datalen
;
int
rc
=
-
1
;
return
0
;
/*
* This is probably inefficient, but safe.
*/
datalen
=
strlen
(
data
);
subject
=
kzalloc
(
datalen
,
GFP_KERNEL
);
if
(
subject
==
NULL
)
return
-
1
;
object
=
kzalloc
(
datalen
,
GFP_KERNEL
);
if
(
object
==
NULL
)
goto
free_out_s
;
access
=
kzalloc
(
datalen
,
GFP_KERNEL
);
if
(
access
==
NULL
)
goto
free_out_o
;
if
(
sscanf
(
data
,
"%s %s %s"
,
subject
,
object
,
access
)
==
3
)
rc
=
smk_fill_rule
(
subject
,
object
,
access
,
rule
,
import
);
kfree
(
access
);
free_out_o:
kfree
(
object
);
free_out_s:
kfree
(
subject
);
return
rc
;
}
#define SMK_FIXED24_FMT 0
/* Fixed 24byte label format */
#define SMK_LONG_FMT 1
/* Variable long label format */
/**
* smk_write_
load_list - write() for any /smack/load
* smk_write_
rules_list - write() for any /smack rule file
* @file: file pointer, not actually used
* @buf: where to get the data from
* @count: bytes sent
* @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.
*
* Get one smack access rule from above.
* The format is exactly:
* char subject[SMK_LABELLEN]
* char object[SMK_LABELLEN]
* char access[SMK_ACCESSLEN]
*
* writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes.
* The format for SMK_LONG_FMT is:
* "subject<whitespace>object<whitespace>access[<whitespace>...]"
* The format for SMK_FIXED24_FMT is exactly:
* "subject object rwxat"
*/
static
ssize_t
smk_write_
load
_list
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
,
struct
list_head
*
rule_list
,
struct
mutex
*
rule_lock
)
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
;
char
*
data
;
int
datalen
;
int
rc
=
-
EINVAL
;
int
load
=
0
;
...
...
@@ -315,13 +387,18 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
*/
if
(
*
ppos
!=
0
)
return
-
EINVAL
;
/*
* Minor hack for backward compatibility
*/
if
(
count
<
(
SMK_OLOADLEN
)
||
count
>
SMK_LOADLEN
)
return
-
EINVAL
;
data
=
kzalloc
(
SMK_LOADLEN
,
GFP_KERNEL
);
if
(
format
==
SMK_FIXED24_FMT
)
{
/*
* Minor hack for backward compatibility
*/
if
(
count
!=
SMK_OLOADLEN
&&
count
!=
SMK_LOADLEN
)
return
-
EINVAL
;
datalen
=
SMK_LOADLEN
;
}
else
datalen
=
count
+
1
;
data
=
kzalloc
(
datalen
,
GFP_KERNEL
);
if
(
data
==
NULL
)
return
-
ENOMEM
;
...
...
@@ -330,20 +407,29 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
goto
out
;
}
/*
* More on the minor hack for backward compatibility
*/
if
(
count
==
(
SMK_OLOADLEN
))
data
[
SMK_OLOADLEN
]
=
'-'
;
rule
=
kzalloc
(
sizeof
(
*
rule
),
GFP_KERNEL
);
if
(
rule
==
NULL
)
{
rc
=
-
ENOMEM
;
goto
out
;
}
if
(
smk_parse_rule
(
data
,
rule
,
1
))
goto
out_free_rule
;
if
(
format
==
SMK_LONG_FMT
)
{
/*
* Be sure the data string is terminated.
*/
data
[
count
]
=
'\0'
;
if
(
smk_parse_long_rule
(
data
,
rule
,
1
))
goto
out_free_rule
;
}
else
{
/*
* More on the minor hack for backward compatibility
*/
if
(
count
==
(
SMK_OLOADLEN
))
data
[
SMK_OLOADLEN
]
=
'-'
;
if
(
smk_parse_rule
(
data
,
rule
,
1
))
goto
out_free_rule
;
}
if
(
rule_list
==
NULL
)
{
load
=
1
;
...
...
@@ -354,18 +440,20 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
rc
=
count
;
/*
* If this is
"load" as opposed to "load-self"
and a new rule
* 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
(
load
&&
!
smk_set_access
(
rule
,
rule_list
,
rule_lock
))
{
smlp
=
kzalloc
(
sizeof
(
*
smlp
),
GFP_KERNEL
);
if
(
smlp
!=
NULL
)
{
smlp
->
smk_rule
=
rule
;
list_add_rcu
(
&
smlp
->
list
,
&
smack_rule_list
);
}
else
rc
=
-
ENOMEM
;
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
;
}
...
...
@@ -421,29 +509,18 @@ static void smk_seq_stop(struct seq_file *s, void *v)
/* No-op */
}
/*
* Seq_file read operations for /smack/load
*/
static
void
*
load_seq_start
(
struct
seq_file
*
s
,
loff_t
*
pos
)
{
return
smk_seq_start
(
s
,
pos
,
&
smack_rule_list
);
}
static
void
*
load_seq_next
(
struct
seq_file
*
s
,
void
*
v
,
loff_t
*
pos
)
static
void
smk_rule_show
(
struct
seq_file
*
s
,
struct
smack_rule
*
srp
,
int
max
)
{
return
smk_seq_next
(
s
,
v
,
pos
,
&
smack_rule_list
);
}
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
);
struct
smack_rule
*
srp
=
smlp
->
smk_rule
;
/*
* Don't show any rules with label names too long for
* interface file (/smack/load or /smack/load2)
* because you should expect to be able to write
* anything you read back.
*/
if
(
strlen
(
srp
->
smk_subject
)
>=
max
||
strlen
(
srp
->
smk_object
)
>=
max
)
return
;
seq_printf
(
s
,
"%s %s"
,
(
char
*
)
srp
->
smk_subject
,
(
char
*
)
srp
->
smk_object
);
seq_printf
(
s
,
"%s %s"
,
srp
->
smk_subject
,
srp
->
smk_object
);
seq_putc
(
s
,
' '
);
...
...
@@ -461,13 +538,36 @@ static int load_seq_show(struct seq_file *s, void *v)
seq_putc
(
s
,
'-'
);
seq_putc
(
s
,
'\n'
);
}
/*
* Seq_file read operations for /smack/load
*/
static
void
*
load2_seq_start
(
struct
seq_file
*
s
,
loff_t
*
pos
)
{
return
smk_seq_start
(
s
,
pos
,
&
smack_rule_list
);
}
static
void
*
load2_seq_next
(
struct
seq_file
*
s
,
void
*
v
,
loff_t
*
pos
)
{
return
smk_seq_next
(
s
,
v
,
pos
,
&
smack_rule_list
);
}
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
);
smk_rule_show
(
s
,
smlp
->
smk_rule
,
SMK_LABELLEN
);
return
0
;
}
static
const
struct
seq_operations
load_seq_ops
=
{
.
start
=
load_seq_start
,
.
next
=
load_seq_next
,
.
start
=
load
2
_seq_start
,
.
next
=
load
2
_seq_next
,
.
show
=
load_seq_show
,
.
stop
=
smk_seq_stop
,
};
...
...
@@ -504,7 +604,8 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
if
(
!
capable
(
CAP_MAC_ADMIN
))
return
-
EPERM
;
return
smk_write_load_list
(
file
,
buf
,
count
,
ppos
,
NULL
,
NULL
);
return
smk_write_rules_list
(
file
,
buf
,
count
,
ppos
,
NULL
,
NULL
,
SMK_FIXED24_FMT
);
}
static
const
struct
file_operations
smk_load_ops
=
{
...
...
@@ -574,6 +675,8 @@ static void smk_unlbl_ambient(char *oldambient)
printk
(
KERN_WARNING
"%s:%d remove rc = %d
\n
"
,
__func__
,
__LINE__
,
rc
);
}
if
(
smack_net_ambient
==
NULL
)
smack_net_ambient
=
smack_known_floor
.
smk_known
;
rc
=
netlbl_cfg_unlbl_map_add
(
smack_net_ambient
,
PF_INET
,
NULL
,
NULL
,
&
nai
);
...
...
@@ -605,27 +708,28 @@ 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
);
struct
smack_cipso
*
scp
=
skp
->
smk_cipso
;
char
*
cbp
;
struct
netlbl_lsm_secattr_catmap
*
cmp
=
skp
->
smk_netlabel
.
attr
.
mls
.
cat
;
char
sep
=
'/'
;
int
cat
=
1
;
int
i
;
unsigned
char
m
;
if
(
scp
==
NULL
)
/*
* Don't show a label that could not have been set using
* /smack/cipso. This is in support of the notion that
* anything read from /smack/cipso ought to be writeable
* to /smack/cipso.
*
* /smack/cipso2 should be used instead.
*/
if
(
strlen
(
skp
->
smk_known
)
>=
SMK_LABELLEN
)
return
0
;
seq_printf
(
s
,
"%s %3d"
,
(
char
*
)
&
skp
->
smk_known
,
scp
->
smk_leve
l
);
seq_printf
(
s
,
"%s %3d"
,
skp
->
smk_known
,
skp
->
smk_netlabel
.
attr
.
mls
.
lv
l
);
cbp
=
scp
->
smk_catset
;
for
(
i
=
0
;
i
<
SMK_LABELLEN
;
i
++
)
for
(
m
=
0x80
;
m
!=
0
;
m
>>=
1
)
{
if
(
m
&
cbp
[
i
])
{
seq_printf
(
s
,
"%c%d"
,
sep
,
cat
);
sep
=
','
;
}
cat
++
;
}
for
(
i
=
netlbl_secattr_catmap_walk
(
cmp
,
0
);
i
>=
0
;
i
=
netlbl_secattr_catmap_walk
(
cmp
,
i
+
1
))
{
seq_printf
(
s
,
"%c%d"
,
sep
,
i
);
sep
=
','
;
}
seq_putc
(
s
,
'\n'
);
...
...
@@ -653,23 +757,24 @@ static int smk_open_cipso(struct inode *inode, struct file *file)
}
/**
* smk_
write_cipso - write() for /smack/cipso
* smk_
set_cipso - do the work for write() for cipso and cipso2
* @file: file pointer, not actually used
* @buf: where to get the data from
* @count: bytes sent
* @ppos: where to start
* @format: /smack/cipso or /smack/cipso2
*
* Accepts only one cipso rule per write call.
* Returns number of bytes written or error code, as appropriate
*/
static
ssize_t
smk_
write
_cipso
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
static
ssize_t
smk_
set
_cipso
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
,
int
format
)
{
struct
smack_known
*
skp
;
struct
smack_cipso
*
scp
=
NULL
;
char
mapcatset
[
SMK_
LABEL
LEN
];
struct
netlbl_lsm_secattr
ncats
;
char
mapcatset
[
SMK_
CIPSO
LEN
];
int
maplevel
;
int
cat
;
unsigned
int
cat
;
int
catlen
;
ssize_t
rc
=
-
EINVAL
;
char
*
data
=
NULL
;
...
...
@@ -686,7 +791,8 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
return
-
EPERM
;
if
(
*
ppos
!=
0
)
return
-
EINVAL
;
if
(
count
<
SMK_CIPSOMIN
||
count
>
SMK_CIPSOMAX
)
if
(
format
==
SMK_FIXED24_FMT
&&
(
count
<
SMK_CIPSOMIN
||
count
>
SMK_CIPSOMAX
))
return
-
EINVAL
;
data
=
kzalloc
(
count
+
1
,
GFP_KERNEL
);
...
...
@@ -698,11 +804,6 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
goto
unlockedout
;
}
/* labels cannot begin with a '-' */
if
(
data
[
0
]
==
'-'
)
{
rc
=
-
EINVAL
;
goto
unlockedout
;
}
data
[
count
]
=
'\0'
;
rule
=
data
;
/*
...
...
@@ -715,7 +816,11 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
if
(
skp
==
NULL
)
goto
out
;
rule
+=
SMK_LABELLEN
;
if
(
format
==
SMK_FIXED24_FMT
)
rule
+=
SMK_LABELLEN
;
else
rule
+=
strlen
(
skp
->
smk_known
);
ret
=
sscanf
(
rule
,
"%d"
,
&
maplevel
);
if
(
ret
!=
1
||
maplevel
>
SMACK_CIPSO_MAXLEVEL
)
goto
out
;
...
...
@@ -725,41 +830,29 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
if
(
ret
!=
1
||
catlen
>
SMACK_CIPSO_MAXCATNUM
)
goto
out
;
if
(
count
!=
(
SMK_CIPSOMIN
+
catlen
*
SMK_DIGITLEN
))
if
(
format
==
SMK_FIXED24_FMT
&&
count
!=
(
SMK_CIPSOMIN
+
catlen
*
SMK_DIGITLEN
))
goto
out
;
memset
(
mapcatset
,
0
,
sizeof
(
mapcatset
));
for
(
i
=
0
;
i
<
catlen
;
i
++
)
{
rule
+=
SMK_DIGITLEN
;
ret
=
sscanf
(
rule
,
"%
d
"
,
&
cat
);
ret
=
sscanf
(
rule
,
"%
u
"
,
&
cat
);
if
(
ret
!=
1
||
cat
>
SMACK_CIPSO_MAXCATVAL
)
goto
out
;
smack_catset_bit
(
cat
,
mapcatset
);
}
if
(
skp
->
smk_cipso
==
NULL
)
{
scp
=
kzalloc
(
sizeof
(
struct
smack_cipso
),
GFP_KERNEL
);
if
(
scp
==
NULL
)
{
rc
=
-
ENOMEM
;
goto
out
;
}
rc
=
smk_netlbl_mls
(
maplevel
,
mapcatset
,
&
ncats
,
SMK_CIPSOLEN
);
if
(
rc
>=
0
)
{
netlbl_secattr_catmap_free
(
skp
->
smk_netlabel
.
attr
.
mls
.
cat
);
skp
->
smk_netlabel
.
attr
.
mls
.
cat
=
ncats
.
attr
.
mls
.
cat
;
skp
->
smk_netlabel
.
attr
.
mls
.
lvl
=
ncats
.
attr
.
mls
.
lvl
;
rc
=
count
;
}
spin_lock_bh
(
&
skp
->
smk_cipsolock
);
if
(
scp
==
NULL
)
scp
=
skp
->
smk_cipso
;
else
skp
->
smk_cipso
=
scp
;
scp
->
smk_level
=
maplevel
;
memcpy
(
scp
->
smk_catset
,
mapcatset
,
sizeof
(
mapcatset
));
spin_unlock_bh
(
&
skp
->
smk_cipsolock
);
rc
=
count
;
out:
mutex_unlock
(
&
smack_cipso_lock
);
unlockedout:
...
...
@@ -767,6 +860,22 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
return
rc
;
}
/**
* smk_write_cipso - write() for /smack/cipso
* @file: file pointer, not actually used
* @buf: where to get the data from
* @count: bytes sent
* @ppos: where to start
*
* Accepts only one cipso rule per write call.
* Returns number of bytes written or error code, as appropriate
*/
static
ssize_t
smk_write_cipso
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
return
smk_set_cipso
(
file
,
buf
,
count
,
ppos
,
SMK_FIXED24_FMT
);
}
static
const
struct
file_operations
smk_cipso_ops
=
{
.
open
=
smk_open_cipso
,
.
read
=
seq_read
,
...
...
@@ -775,6 +884,80 @@ static const struct file_operations smk_cipso_ops = {
.
release
=
seq_release
,
};
/*
* Seq_file read operations for /smack/cipso2
*/
/*
* Print cipso labels in format:
* label level[/cat[,cat]]
*/
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
);
struct
netlbl_lsm_secattr_catmap
*
cmp
=
skp
->
smk_netlabel
.
attr
.
mls
.
cat
;
char
sep
=
'/'
;
int
i
;
seq_printf
(
s
,
"%s %3d"
,
skp
->
smk_known
,
skp
->
smk_netlabel
.
attr
.
mls
.
lvl
);
for
(
i
=
netlbl_secattr_catmap_walk
(
cmp
,
0
);
i
>=
0
;
i
=
netlbl_secattr_catmap_walk
(
cmp
,
i
+
1
))
{
seq_printf
(
s
,
"%c%d"
,
sep
,
i
);
sep
=
','
;
}
seq_putc
(
s
,
'\n'
);
return
0
;
}
static
const
struct
seq_operations
cipso2_seq_ops
=
{
.
start
=
cipso_seq_start
,
.
next
=
cipso_seq_next
,
.
show
=
cipso2_seq_show
,
.
stop
=
smk_seq_stop
,
};
/**
* smk_open_cipso2 - open() for /smack/cipso2
* @inode: inode structure representing file
* @file: "cipso2" file pointer
*
* Connect our cipso_seq_* operations with /smack/cipso2
* file_operations
*/
static
int
smk_open_cipso2
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
cipso2_seq_ops
);
}
/**
* smk_write_cipso2 - write() for /smack/cipso2
* @file: file pointer, not actually used
* @buf: where to get the data from
* @count: bytes sent
* @ppos: where to start
*
* Accepts only one cipso rule per write call.
* Returns number of bytes written or error code, as appropriate
*/
static
ssize_t
smk_write_cipso2
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
return
smk_set_cipso
(
file
,
buf
,
count
,
ppos
,
SMK_LONG_FMT
);
}
static
const
struct
file_operations
smk_cipso2_ops
=
{
.
open
=
smk_open_cipso2
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
write
=
smk_write_cipso2
,
.
release
=
seq_release
,
};
/*
* Seq_file read operations for /smack/netlabel
*/
...
...
@@ -887,9 +1070,9 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
{
struct
smk_netlbladdr
*
skp
;
struct
sockaddr_in
newname
;
char
smack
[
SMK_LABELLEN
]
;
char
*
smack
;
char
*
sp
;
char
data
[
SMK_NETLBLADDRMAX
+
1
]
;
char
*
data
;
char
*
host
=
(
char
*
)
&
newname
.
sin_addr
.
s_addr
;
int
rc
;
struct
netlbl_audit
audit_info
;
...
...
@@ -911,10 +1094,23 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
return
-
EPERM
;
if
(
*
ppos
!=
0
)
return
-
EINVAL
;
if
(
count
<
SMK_NETLBLADDRMIN
||
count
>
SMK_NETLBLADDRMAX
)
if
(
count
<
SMK_NETLBLADDRMIN
)
return
-
EINVAL
;
if
(
copy_from_user
(
data
,
buf
,
count
)
!=
0
)
return
-
EFAULT
;
data
=
kzalloc
(
count
+
1
,
GFP_KERNEL
);
if
(
data
==
NULL
)
return
-
ENOMEM
;
if
(
copy_from_user
(
data
,
buf
,
count
)
!=
0
)
{
rc
=
-
EFAULT
;
goto
free_data_out
;
}
smack
=
kzalloc
(
count
+
1
,
GFP_KERNEL
);
if
(
smack
==
NULL
)
{
rc
=
-
ENOMEM
;
goto
free_data_out
;
}
data
[
count
]
=
'\0'
;
...
...
@@ -923,24 +1119,34 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
if
(
rc
!=
6
)
{
rc
=
sscanf
(
data
,
"%hhd.%hhd.%hhd.%hhd %s"
,
&
host
[
0
],
&
host
[
1
],
&
host
[
2
],
&
host
[
3
],
smack
);
if
(
rc
!=
5
)
return
-
EINVAL
;
if
(
rc
!=
5
)
{
rc
=
-
EINVAL
;
goto
free_out
;
}
m
=
BEBITS
;
}
if
(
m
>
BEBITS
)
return
-
EINVAL
;
if
(
m
>
BEBITS
)
{
rc
=
-
EINVAL
;
goto
free_out
;
}
/* if smack begins with '-', its an option, don't import it */
/*
* If smack begins with '-', it is an option, don't import it
*/
if
(
smack
[
0
]
!=
'-'
)
{
sp
=
smk_import
(
smack
,
0
);
if
(
sp
==
NULL
)
return
-
EINVAL
;
if
(
sp
==
NULL
)
{
rc
=
-
EINVAL
;
goto
free_out
;
}
}
else
{
/* check known options */
if
(
strcmp
(
smack
,
smack_cipso_option
)
==
0
)
sp
=
(
char
*
)
smack_cipso_option
;
else
return
-
EINVAL
;
else
{
rc
=
-
EINVAL
;
goto
free_out
;
}
}
for
(
temp_mask
=
0
;
m
>
0
;
m
--
)
{
...
...
@@ -1006,6 +1212,11 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
mutex_unlock
(
&
smk_netlbladdr_lock
);
free_out:
kfree
(
smack
);
free_data_out:
kfree
(
data
);
return
rc
;
}
...
...
@@ -1119,6 +1330,7 @@ static ssize_t smk_read_direct(struct file *filp, char __user *buf,
static
ssize_t
smk_write_direct
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
smack_known
*
skp
;
char
temp
[
80
];
int
i
;
...
...
@@ -1136,7 +1348,20 @@ static ssize_t smk_write_direct(struct file *file, const char __user *buf,
if
(
sscanf
(
temp
,
"%d"
,
&
i
)
!=
1
)
return
-
EINVAL
;
smack_cipso_direct
=
i
;
/*
* Don't do anything if the value hasn't actually changed.
* If it is changing reset the level on entries that were
* set up to be direct when they were created.
*/
if
(
smack_cipso_direct
!=
i
)
{
mutex_lock
(
&
smack_known_lock
);
list_for_each_entry_rcu
(
skp
,
&
smack_known_list
,
list
)
if
(
skp
->
smk_netlabel
.
attr
.
mls
.
lvl
==
smack_cipso_direct
)
skp
->
smk_netlabel
.
attr
.
mls
.
lvl
=
i
;
smack_cipso_direct
=
i
;
mutex_unlock
(
&
smack_known_lock
);
}
return
count
;
}
...
...
@@ -1147,6 +1372,84 @@ static const struct file_operations smk_direct_ops = {
.
llseek
=
default_llseek
,
};
/**
* smk_read_mapped - read() for /smack/mapped
* @filp: file pointer, not actually used
* @buf: where to put the result
* @count: maximum to send along
* @ppos: where to start
*
* Returns number of bytes read or error code, as appropriate
*/
static
ssize_t
smk_read_mapped
(
struct
file
*
filp
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
char
temp
[
80
];
ssize_t
rc
;
if
(
*
ppos
!=
0
)
return
0
;
sprintf
(
temp
,
"%d"
,
smack_cipso_mapped
);
rc
=
simple_read_from_buffer
(
buf
,
count
,
ppos
,
temp
,
strlen
(
temp
));
return
rc
;
}
/**
* smk_write_mapped - write() for /smack/mapped
* @file: file pointer, not actually used
* @buf: where to get the data from
* @count: bytes sent
* @ppos: where to start
*
* Returns number of bytes written or error code, as appropriate
*/
static
ssize_t
smk_write_mapped
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
smack_known
*
skp
;
char
temp
[
80
];
int
i
;
if
(
!
capable
(
CAP_MAC_ADMIN
))
return
-
EPERM
;
if
(
count
>=
sizeof
(
temp
)
||
count
==
0
)
return
-
EINVAL
;
if
(
copy_from_user
(
temp
,
buf
,
count
)
!=
0
)
return
-
EFAULT
;
temp
[
count
]
=
'\0'
;
if
(
sscanf
(
temp
,
"%d"
,
&
i
)
!=
1
)
return
-
EINVAL
;
/*
* Don't do anything if the value hasn't actually changed.
* If it is changing reset the level on entries that were
* set up to be mapped when they were created.
*/
if
(
smack_cipso_mapped
!=
i
)
{
mutex_lock
(
&
smack_known_lock
);
list_for_each_entry_rcu
(
skp
,
&
smack_known_list
,
list
)
if
(
skp
->
smk_netlabel
.
attr
.
mls
.
lvl
==
smack_cipso_mapped
)
skp
->
smk_netlabel
.
attr
.
mls
.
lvl
=
i
;
smack_cipso_mapped
=
i
;
mutex_unlock
(
&
smack_known_lock
);
}
return
count
;
}
static
const
struct
file_operations
smk_mapped_ops
=
{
.
read
=
smk_read_mapped
,
.
write
=
smk_write_mapped
,
.
llseek
=
default_llseek
,
};
/**
* smk_read_ambient - read() for /smack/ambient
* @filp: file pointer, not actually used
...
...
@@ -1195,22 +1498,28 @@ static ssize_t smk_read_ambient(struct file *filp, char __user *buf,
static
ssize_t
smk_write_ambient
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
char
in
[
SMK_LABELLEN
];
char
*
oldambient
;
char
*
smack
;
char
*
smack
=
NULL
;
char
*
data
;
int
rc
=
count
;
if
(
!
capable
(
CAP_MAC_ADMIN
))
return
-
EPERM
;
if
(
count
>=
SMK_LABELLEN
)
return
-
EINVAL
;
data
=
kzalloc
(
count
+
1
,
GFP_KERNEL
);
if
(
data
==
NULL
)
return
-
ENOMEM
;
if
(
copy_from_user
(
in
,
buf
,
count
)
!=
0
)
return
-
EFAULT
;
if
(
copy_from_user
(
data
,
buf
,
count
)
!=
0
)
{
rc
=
-
EFAULT
;
goto
out
;
}
smack
=
smk_import
(
in
,
count
);
if
(
smack
==
NULL
)
return
-
EINVAL
;
smack
=
smk_import
(
data
,
count
);
if
(
smack
==
NULL
)
{
rc
=
-
EINVAL
;
goto
out
;
}
mutex_lock
(
&
smack_ambient_lock
);
...
...
@@ -1220,7 +1529,9 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
mutex_unlock
(
&
smack_ambient_lock
);
return
count
;
out:
kfree
(
data
);
return
rc
;
}
static
const
struct
file_operations
smk_ambient_ops
=
{
...
...
@@ -1271,8 +1582,9 @@ static ssize_t smk_read_onlycap(struct file *filp, char __user *buf,
static
ssize_t
smk_write_onlycap
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
char
in
[
SMK_LABELLEN
]
;
char
*
data
;
char
*
sp
=
smk_of_task
(
current
->
cred
->
security
);
int
rc
=
count
;
if
(
!
capable
(
CAP_MAC_ADMIN
))
return
-
EPERM
;
...
...
@@ -1285,11 +1597,9 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
if
(
smack_onlycap
!=
NULL
&&
smack_onlycap
!=
sp
)
return
-
EPERM
;
if
(
count
>=
SMK_LABELLEN
)
return
-
EINVAL
;
if
(
copy_from_user
(
in
,
buf
,
count
)
!=
0
)
return
-
EFAULT
;
data
=
kzalloc
(
count
,
GFP_KERNEL
);
if
(
data
==
NULL
)
return
-
ENOMEM
;
/*
* Should the null string be passed in unset the onlycap value.
...
...
@@ -1297,10 +1607,17 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
* 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.
*
* smk_import will also reject a label beginning with '-',
* so "-usecapabilities" will also work.
*/
smack_onlycap
=
smk_import
(
in
,
count
);
if
(
copy_from_user
(
data
,
buf
,
count
)
!=
0
)
rc
=
-
EFAULT
;
else
smack_onlycap
=
smk_import
(
data
,
count
);
return
count
;
kfree
(
data
);
return
rc
;
}
static
const
struct
file_operations
smk_onlycap_ops
=
{
...
...
@@ -1398,25 +1715,7 @@ static int load_self_seq_show(struct seq_file *s, void *v)
struct
smack_rule
*
srp
=
list_entry
(
list
,
struct
smack_rule
,
list
);
seq_printf
(
s
,
"%s %s"
,
(
char
*
)
srp
->
smk_subject
,
(
char
*
)
srp
->
smk_object
);
seq_putc
(
s
,
' '
);
if
(
srp
->
smk_access
&
MAY_READ
)
seq_putc
(
s
,
'r'
);
if
(
srp
->
smk_access
&
MAY_WRITE
)
seq_putc
(
s
,
'w'
);
if
(
srp
->
smk_access
&
MAY_EXEC
)
seq_putc
(
s
,
'x'
);
if
(
srp
->
smk_access
&
MAY_APPEND
)
seq_putc
(
s
,
'a'
);
if
(
srp
->
smk_access
&
MAY_TRANSMUTE
)
seq_putc
(
s
,
't'
);
if
(
srp
->
smk_access
==
0
)
seq_putc
(
s
,
'-'
);
seq_putc
(
s
,
'\n'
);
smk_rule_show
(
s
,
srp
,
SMK_LABELLEN
);
return
0
;
}
...
...
@@ -1430,7 +1729,7 @@ static const struct seq_operations load_self_seq_ops = {
/**
* smk_open_load_self - open() for /smack/load-self
* smk_open_load_self - open() for /smack/load-self
2
* @inode: inode structure representing file
* @file: "load" file pointer
*
...
...
@@ -1454,8 +1753,8 @@ static ssize_t smk_write_load_self(struct file *file, const char __user *buf,
{
struct
task_smack
*
tsp
=
current_security
();
return
smk_write_
load
_list
(
file
,
buf
,
count
,
ppos
,
&
tsp
->
smk_rules
,
&
tsp
->
smk_rules_lock
);
return
smk_write_
rules
_list
(
file
,
buf
,
count
,
ppos
,
&
tsp
->
smk_rules
,
&
tsp
->
smk_rules_lock
,
SMK_FIXED24_FMT
);
}
static
const
struct
file_operations
smk_load_self_ops
=
{
...
...
@@ -1467,24 +1766,42 @@ static const struct file_operations smk_load_self_ops = {
};
/**
* smk_
write
_access - handle access check transaction
* smk_
user
_access - handle access check transaction
* @file: file pointer
* @buf: data from user space
* @count: bytes sent
* @ppos: where to start - must be 0
*/
static
ssize_t
smk_
write
_access
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
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
;
char
*
data
;
char
*
cod
;
int
res
;
data
=
simple_transaction_get
(
file
,
buf
,
count
);
if
(
IS_ERR
(
data
))
return
PTR_ERR
(
data
);
if
(
count
<
SMK_LOADLEN
||
smk_parse_rule
(
data
,
&
rule
,
0
))
if
(
format
==
SMK_FIXED24_FMT
)
{
if
(
count
<
SMK_LOADLEN
)
return
-
EINVAL
;
res
=
smk_parse_rule
(
data
,
&
rule
,
0
);
}
else
{
/*
* Copy the data to make sure the string is terminated.
*/
cod
=
kzalloc
(
count
+
1
,
GFP_KERNEL
);
if
(
cod
==
NULL
)
return
-
ENOMEM
;
memcpy
(
cod
,
data
,
count
);
cod
[
count
]
=
'\0'
;
res
=
smk_parse_long_rule
(
cod
,
&
rule
,
0
);
kfree
(
cod
);
}
if
(
res
)
return
-
EINVAL
;
res
=
smk_access
(
rule
.
smk_subject
,
rule
.
smk_object
,
rule
.
smk_access
,
...
...
@@ -1493,7 +1810,23 @@ static ssize_t smk_write_access(struct file *file, const char __user *buf,
data
[
1
]
=
'\0'
;
simple_transaction_set
(
file
,
2
);
return
SMK_LOADLEN
;
if
(
format
==
SMK_FIXED24_FMT
)
return
SMK_LOADLEN
;
return
count
;
}
/**
* smk_write_access - handle access check transaction
* @file: file pointer
* @buf: data from user space
* @count: bytes sent
* @ppos: where to start - must be 0
*/
static
ssize_t
smk_write_access
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
return
smk_user_access
(
file
,
buf
,
count
,
ppos
,
SMK_FIXED24_FMT
);
}
static
const
struct
file_operations
smk_access_ops
=
{
...
...
@@ -1503,6 +1836,163 @@ static const struct file_operations smk_access_ops = {
.
llseek
=
generic_file_llseek
,
};
/*
* Seq_file read operations for /smack/load2
*/
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
);
smk_rule_show
(
s
,
smlp
->
smk_rule
,
SMK_LONGLABEL
);
return
0
;
}
static
const
struct
seq_operations
load2_seq_ops
=
{
.
start
=
load2_seq_start
,
.
next
=
load2_seq_next
,
.
show
=
load2_seq_show
,
.
stop
=
smk_seq_stop
,
};
/**
* smk_open_load2 - open() for /smack/load2
* @inode: inode structure representing file
* @file: "load2" file pointer
*
* For reading, use load2_seq_* seq_file reading operations.
*/
static
int
smk_open_load2
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
load2_seq_ops
);
}
/**
* smk_write_load2 - write() for /smack/load2
* @file: file pointer, not actually used
* @buf: where to get the data from
* @count: bytes sent
* @ppos: where to start - must be 0
*
*/
static
ssize_t
smk_write_load2
(
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_LONG_FMT
);
}
static
const
struct
file_operations
smk_load2_ops
=
{
.
open
=
smk_open_load2
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
write
=
smk_write_load2
,
.
release
=
seq_release
,
};
/*
* Seq_file read operations for /smack/load-self2
*/
static
void
*
load_self2_seq_start
(
struct
seq_file
*
s
,
loff_t
*
pos
)
{
struct
task_smack
*
tsp
=
current_security
();
return
smk_seq_start
(
s
,
pos
,
&
tsp
->
smk_rules
);
}
static
void
*
load_self2_seq_next
(
struct
seq_file
*
s
,
void
*
v
,
loff_t
*
pos
)
{
struct
task_smack
*
tsp
=
current_security
();
return
smk_seq_next
(
s
,
v
,
pos
,
&
tsp
->
smk_rules
);
}
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
);
smk_rule_show
(
s
,
srp
,
SMK_LONGLABEL
);
return
0
;
}
static
const
struct
seq_operations
load_self2_seq_ops
=
{
.
start
=
load_self2_seq_start
,
.
next
=
load_self2_seq_next
,
.
show
=
load_self2_seq_show
,
.
stop
=
smk_seq_stop
,
};
/**
* smk_open_load_self2 - open() for /smack/load-self2
* @inode: inode structure representing file
* @file: "load" file pointer
*
* For reading, use load_seq_* seq_file reading operations.
*/
static
int
smk_open_load_self2
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
load_self2_seq_ops
);
}
/**
* smk_write_load_self2 - write() for /smack/load-self2
* @file: file pointer, not actually used
* @buf: where to get the data from
* @count: bytes sent
* @ppos: where to start - must be 0
*
*/
static
ssize_t
smk_write_load_self2
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
task_smack
*
tsp
=
current_security
();
return
smk_write_rules_list
(
file
,
buf
,
count
,
ppos
,
&
tsp
->
smk_rules
,
&
tsp
->
smk_rules_lock
,
SMK_LONG_FMT
);
}
static
const
struct
file_operations
smk_load_self2_ops
=
{
.
open
=
smk_open_load_self2
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
write
=
smk_write_load_self2
,
.
release
=
seq_release
,
};
/**
* smk_write_access2 - handle access check transaction
* @file: file pointer
* @buf: data from user space
* @count: bytes sent
* @ppos: where to start - must be 0
*/
static
ssize_t
smk_write_access2
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
return
smk_user_access
(
file
,
buf
,
count
,
ppos
,
SMK_LONG_FMT
);
}
static
const
struct
file_operations
smk_access2_ops
=
{
.
write
=
smk_write_access2
,
.
read
=
simple_transaction_read
,
.
release
=
simple_transaction_release
,
.
llseek
=
generic_file_llseek
,
};
/**
* smk_fill_super - fill the /smackfs superblock
* @sb: the empty superblock
...
...
@@ -1539,6 +2029,16 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
"load-self"
,
&
smk_load_self_ops
,
S_IRUGO
|
S_IWUGO
},
[
SMK_ACCESSES
]
=
{
"access"
,
&
smk_access_ops
,
S_IRUGO
|
S_IWUGO
},
[
SMK_MAPPED
]
=
{
"mapped"
,
&
smk_mapped_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_LOAD2
]
=
{
"load2"
,
&
smk_load2_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_LOAD_SELF2
]
=
{
"load-self2"
,
&
smk_load_self2_ops
,
S_IRUGO
|
S_IWUGO
},
[
SMK_ACCESS2
]
=
{
"access2"
,
&
smk_access2_ops
,
S_IRUGO
|
S_IWUGO
},
[
SMK_CIPSO2
]
=
{
"cipso2"
,
&
smk_cipso2_ops
,
S_IRUGO
|
S_IWUSR
},
/* last one */
{
""
}
};
...
...
@@ -1581,6 +2081,15 @@ static struct file_system_type smk_fs_type = {
static
struct
vfsmount
*
smackfs_mount
;
static
int
__init
smk_preset_netlabel
(
struct
smack_known
*
skp
)
{
skp
->
smk_netlabel
.
domain
=
skp
->
smk_known
;
skp
->
smk_netlabel
.
flags
=
NETLBL_SECATTR_DOMAIN
|
NETLBL_SECATTR_MLS_LVL
;
return
smk_netlbl_mls
(
smack_cipso_direct
,
skp
->
smk_known
,
&
skp
->
smk_netlabel
,
strlen
(
skp
->
smk_known
));
}
/**
* init_smk_fs - get the smackfs superblock
*
...
...
@@ -1597,6 +2106,7 @@ static struct vfsmount *smackfs_mount;
static
int
__init
init_smk_fs
(
void
)
{
int
err
;
int
rc
;
if
(
!
security_module_enable
(
&
smack_ops
))
return
0
;
...
...
@@ -1614,6 +2124,25 @@ static int __init init_smk_fs(void)
smk_cipso_doi
();
smk_unlbl_ambient
(
NULL
);
rc
=
smk_preset_netlabel
(
&
smack_known_floor
);
if
(
err
==
0
&&
rc
<
0
)
err
=
rc
;
rc
=
smk_preset_netlabel
(
&
smack_known_hat
);
if
(
err
==
0
&&
rc
<
0
)
err
=
rc
;
rc
=
smk_preset_netlabel
(
&
smack_known_huh
);
if
(
err
==
0
&&
rc
<
0
)
err
=
rc
;
rc
=
smk_preset_netlabel
(
&
smack_known_invalid
);
if
(
err
==
0
&&
rc
<
0
)
err
=
rc
;
rc
=
smk_preset_netlabel
(
&
smack_known_star
);
if
(
err
==
0
&&
rc
<
0
)
err
=
rc
;
rc
=
smk_preset_netlabel
(
&
smack_known_web
);
if
(
err
==
0
&&
rc
<
0
)
err
=
rc
;
return
err
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录