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
5c8c40be
Commit
5c8c40be
authored
Jan 05, 2009
by
James Morris
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
git://git.infradead.org/users/pcmoore/lblnet-2.6_next
into next
parents
90bd49ab
6d3dc07c
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
1122 additions
and
375 deletions
+1122
-375
Documentation/feature-removal-schedule.txt
Documentation/feature-removal-schedule.txt
+12
-0
include/net/cipso_ipv4.h
include/net/cipso_ipv4.h
+4
-2
include/net/netlabel.h
include/net/netlabel.h
+80
-6
net/ipv4/cipso_ipv4.c
net/ipv4/cipso_ipv4.c
+65
-21
net/netlabel/netlabel_cipso_v4.c
net/netlabel/netlabel_cipso_v4.c
+18
-43
net/netlabel/netlabel_domainhash.c
net/netlabel/netlabel_domainhash.c
+67
-0
net/netlabel/netlabel_domainhash.h
net/netlabel/netlabel_domainhash.h
+4
-0
net/netlabel/netlabel_kapi.c
net/netlabel/netlabel_kapi.c
+287
-60
net/netlabel/netlabel_unlabeled.c
net/netlabel/netlabel_unlabeled.c
+13
-13
net/netlabel/netlabel_unlabeled.h
net/netlabel/netlabel_unlabeled.h
+15
-0
security/selinux/Kconfig
security/selinux/Kconfig
+0
-27
security/selinux/hooks.c
security/selinux/hooks.c
+3
-3
security/selinux/selinuxfs.c
security/selinux/selinuxfs.c
+8
-8
security/smack/smack.h
security/smack/smack.h
+29
-2
security/smack/smack_access.c
security/smack/smack_access.c
+19
-9
security/smack/smack_lsm.c
security/smack/smack_lsm.c
+255
-55
security/smack/smackfs.c
security/smack/smackfs.c
+243
-126
No files found.
Documentation/feature-removal-schedule.txt
View file @
5c8c40be
...
...
@@ -324,3 +324,15 @@ When: 2.6.29 (ideally) or 2.6.30 (more likely)
Why: Deprecated by the new (standard) device driver binding model. Use
i2c_driver->probe() and ->remove() instead.
Who: Jean Delvare <khali@linux-fr.org>
---------------------------
What: SELinux "compat_net" functionality
When: 2.6.30 at the earliest
Why: In 2.6.18 the Secmark concept was introduced to replace the "compat_net"
network access control functionality of SELinux. Secmark offers both
better performance and greater flexibility than the "compat_net"
mechanism. Now that the major Linux distributions have moved to
Secmark, it is time to deprecate the older mechanism and start the
process of removing the old code.
Who: Paul Moore <paul.moore@hp.com>
include/net/cipso_ipv4.h
View file @
5c8c40be
...
...
@@ -131,7 +131,8 @@ extern int cipso_v4_rbm_strictvalid;
*/
#ifdef CONFIG_NETLABEL
int
cipso_v4_doi_add
(
struct
cipso_v4_doi
*
doi_def
);
int
cipso_v4_doi_add
(
struct
cipso_v4_doi
*
doi_def
,
struct
netlbl_audit
*
audit_info
);
void
cipso_v4_doi_free
(
struct
cipso_v4_doi
*
doi_def
);
int
cipso_v4_doi_remove
(
u32
doi
,
struct
netlbl_audit
*
audit_info
);
struct
cipso_v4_doi
*
cipso_v4_doi_getdef
(
u32
doi
);
...
...
@@ -140,7 +141,8 @@ int cipso_v4_doi_walk(u32 *skip_cnt,
int
(
*
callback
)
(
struct
cipso_v4_doi
*
doi_def
,
void
*
arg
),
void
*
cb_arg
);
#else
static
inline
int
cipso_v4_doi_add
(
struct
cipso_v4_doi
*
doi_def
)
static
inline
int
cipso_v4_doi_add
(
struct
cipso_v4_doi
*
doi_def
,
struct
netlbl_audit
*
audit_info
)
{
return
-
ENOSYS
;
}
...
...
include/net/netlabel.h
View file @
5c8c40be
...
...
@@ -33,6 +33,8 @@
#include <linux/types.h>
#include <linux/net.h>
#include <linux/skbuff.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <net/netlink.h>
#include <asm/atomic.h>
...
...
@@ -353,13 +355,37 @@ static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr)
/*
* LSM configuration operations
*/
int
netlbl_cfg_map_del
(
const
char
*
domain
,
struct
netlbl_audit
*
audit_info
);
int
netlbl_cfg_unlbl_add_map
(
const
char
*
domain
,
int
netlbl_cfg_map_del
(
const
char
*
domain
,
u16
family
,
const
void
*
addr
,
const
void
*
mask
,
struct
netlbl_audit
*
audit_info
);
int
netlbl_cfg_unlbl_map_add
(
const
char
*
domain
,
u16
family
,
const
void
*
addr
,
const
void
*
mask
,
struct
netlbl_audit
*
audit_info
);
int
netlbl_cfg_cipsov4_add_map
(
struct
cipso_v4_doi
*
doi_def
,
int
netlbl_cfg_unlbl_static_add
(
struct
net
*
net
,
const
char
*
dev_name
,
const
void
*
addr
,
const
void
*
mask
,
u16
family
,
u32
secid
,
struct
netlbl_audit
*
audit_info
);
int
netlbl_cfg_unlbl_static_del
(
struct
net
*
net
,
const
char
*
dev_name
,
const
void
*
addr
,
const
void
*
mask
,
u16
family
,
struct
netlbl_audit
*
audit_info
);
int
netlbl_cfg_cipsov4_add
(
struct
cipso_v4_doi
*
doi_def
,
struct
netlbl_audit
*
audit_info
);
void
netlbl_cfg_cipsov4_del
(
u32
doi
,
struct
netlbl_audit
*
audit_info
);
int
netlbl_cfg_cipsov4_map_add
(
u32
doi
,
const
char
*
domain
,
const
struct
in_addr
*
addr
,
const
struct
in_addr
*
mask
,
struct
netlbl_audit
*
audit_info
);
/*
* LSM security attribute operations
*/
...
...
@@ -401,19 +427,62 @@ void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway);
void
netlbl_cache_invalidate
(
void
);
int
netlbl_cache_add
(
const
struct
sk_buff
*
skb
,
const
struct
netlbl_lsm_secattr
*
secattr
);
/*
* Protocol engine operations
*/
struct
audit_buffer
*
netlbl_audit_start
(
int
type
,
struct
netlbl_audit
*
audit_info
);
#else
static
inline
int
netlbl_cfg_map_del
(
const
char
*
domain
,
u16
family
,
const
void
*
addr
,
const
void
*
mask
,
struct
netlbl_audit
*
audit_info
)
{
return
-
ENOSYS
;
}
static
inline
int
netlbl_cfg_unlbl_add_map
(
const
char
*
domain
,
static
inline
int
netlbl_cfg_unlbl_map_add
(
const
char
*
domain
,
u16
family
,
void
*
addr
,
void
*
mask
,
struct
netlbl_audit
*
audit_info
)
{
return
-
ENOSYS
;
}
static
inline
int
netlbl_cfg_cipsov4_add_map
(
struct
cipso_v4_doi
*
doi_def
,
static
inline
int
netlbl_cfg_unlbl_static_add
(
struct
net
*
net
,
const
char
*
dev_name
,
const
void
*
addr
,
const
void
*
mask
,
u16
family
,
u32
secid
,
struct
netlbl_audit
*
audit_info
)
{
return
-
ENOSYS
;
}
static
inline
int
netlbl_cfg_unlbl_static_del
(
struct
net
*
net
,
const
char
*
dev_name
,
const
void
*
addr
,
const
void
*
mask
,
u16
family
,
struct
netlbl_audit
*
audit_info
)
{
return
-
ENOSYS
;
}
static
inline
int
netlbl_cfg_cipsov4_add
(
struct
cipso_v4_doi
*
doi_def
,
struct
netlbl_audit
*
audit_info
)
{
return
-
ENOSYS
;
}
static
inline
void
netlbl_cfg_cipsov4_del
(
u32
doi
,
struct
netlbl_audit
*
audit_info
)
{
return
;
}
static
inline
int
netlbl_cfg_cipsov4_map_add
(
u32
doi
,
const
char
*
domain
,
const
struct
in_addr
*
addr
,
const
struct
in_addr
*
mask
,
struct
netlbl_audit
*
audit_info
)
{
return
-
ENOSYS
;
...
...
@@ -495,6 +564,11 @@ static inline int netlbl_cache_add(const struct sk_buff *skb,
{
return
0
;
}
static
inline
struct
audit_buffer
*
netlbl_audit_start
(
int
type
,
struct
netlbl_audit
*
audit_info
)
{
return
NULL
;
}
#endif
/* CONFIG_NETLABEL */
#endif
/* _NETLABEL_H */
net/ipv4/cipso_ipv4.c
View file @
5c8c40be
...
...
@@ -38,6 +38,7 @@
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/jhash.h>
#include <linux/audit.h>
#include <net/ip.h>
#include <net/icmp.h>
#include <net/tcp.h>
...
...
@@ -449,6 +450,7 @@ static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi)
/**
* cipso_v4_doi_add - Add a new DOI to the CIPSO protocol engine
* @doi_def: the DOI structure
* @audit_info: NetLabel audit information
*
* Description:
* The caller defines a new DOI for use by the CIPSO engine and calls this
...
...
@@ -458,50 +460,78 @@ static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi)
* zero on success and non-zero on failure.
*
*/
int
cipso_v4_doi_add
(
struct
cipso_v4_doi
*
doi_def
)
int
cipso_v4_doi_add
(
struct
cipso_v4_doi
*
doi_def
,
struct
netlbl_audit
*
audit_info
)
{
int
ret_val
=
-
EINVAL
;
u32
iter
;
u32
doi
;
u32
doi_type
;
struct
audit_buffer
*
audit_buf
;
doi
=
doi_def
->
doi
;
doi_type
=
doi_def
->
type
;
if
(
doi_def
==
NULL
||
doi_def
->
doi
==
CIPSO_V4_DOI_UNKNOWN
)
return
-
EINVAL
;
goto
doi_add_return
;
for
(
iter
=
0
;
iter
<
CIPSO_V4_TAG_MAXCNT
;
iter
++
)
{
switch
(
doi_def
->
tags
[
iter
])
{
case
CIPSO_V4_TAG_RBITMAP
:
break
;
case
CIPSO_V4_TAG_RANGE
:
if
(
doi_def
->
type
!=
CIPSO_V4_MAP_PASS
)
return
-
EINVAL
;
break
;
case
CIPSO_V4_TAG_INVALID
:
if
(
iter
==
0
)
return
-
EINVAL
;
break
;
case
CIPSO_V4_TAG_ENUM
:
if
(
doi_def
->
type
!=
CIPSO_V4_MAP_PASS
)
return
-
EINVAL
;
goto
doi_add_return
;
break
;
case
CIPSO_V4_TAG_LOCAL
:
if
(
doi_def
->
type
!=
CIPSO_V4_MAP_LOCAL
)
return
-
EINVAL
;
goto
doi_add_return
;
break
;
case
CIPSO_V4_TAG_INVALID
:
if
(
iter
==
0
)
goto
doi_add_return
;
break
;
default:
return
-
EINVAL
;
goto
doi_add_return
;
}
}
atomic_set
(
&
doi_def
->
refcount
,
1
);
spin_lock
(
&
cipso_v4_doi_list_lock
);
if
(
cipso_v4_doi_search
(
doi_def
->
doi
)
!=
NULL
)
goto
doi_add_failure
;
if
(
cipso_v4_doi_search
(
doi_def
->
doi
)
!=
NULL
)
{
spin_unlock
(
&
cipso_v4_doi_list_lock
);
ret_val
=
-
EEXIST
;
goto
doi_add_return
;
}
list_add_tail_rcu
(
&
doi_def
->
list
,
&
cipso_v4_doi_list
);
spin_unlock
(
&
cipso_v4_doi_list_lock
);
ret_val
=
0
;
return
0
;
doi_add_return:
audit_buf
=
netlbl_audit_start
(
AUDIT_MAC_CIPSOV4_ADD
,
audit_info
);
if
(
audit_buf
!=
NULL
)
{
const
char
*
type_str
;
switch
(
doi_type
)
{
case
CIPSO_V4_MAP_TRANS
:
type_str
=
"trans"
;
break
;
case
CIPSO_V4_MAP_PASS
:
type_str
=
"pass"
;
break
;
case
CIPSO_V4_MAP_LOCAL
:
type_str
=
"local"
;
break
;
default:
type_str
=
"(unknown)"
;
}
audit_log_format
(
audit_buf
,
" cipso_doi=%u cipso_type=%s res=%u"
,
doi
,
type_str
,
ret_val
==
0
?
1
:
0
);
audit_log_end
(
audit_buf
);
}
doi_add_failure:
spin_unlock
(
&
cipso_v4_doi_list_lock
);
return
-
EEXIST
;
return
ret_val
;
}
/**
...
...
@@ -559,25 +589,39 @@ static void cipso_v4_doi_free_rcu(struct rcu_head *entry)
*/
int
cipso_v4_doi_remove
(
u32
doi
,
struct
netlbl_audit
*
audit_info
)
{
int
ret_val
;
struct
cipso_v4_doi
*
doi_def
;
struct
audit_buffer
*
audit_buf
;
spin_lock
(
&
cipso_v4_doi_list_lock
);
doi_def
=
cipso_v4_doi_search
(
doi
);
if
(
doi_def
==
NULL
)
{
spin_unlock
(
&
cipso_v4_doi_list_lock
);
return
-
ENOENT
;
ret_val
=
-
ENOENT
;
goto
doi_remove_return
;
}
if
(
!
atomic_dec_and_test
(
&
doi_def
->
refcount
))
{
spin_unlock
(
&
cipso_v4_doi_list_lock
);
return
-
EBUSY
;
ret_val
=
-
EBUSY
;
goto
doi_remove_return
;
}
list_del_rcu
(
&
doi_def
->
list
);
spin_unlock
(
&
cipso_v4_doi_list_lock
);
cipso_v4_cache_invalidate
();
call_rcu
(
&
doi_def
->
rcu
,
cipso_v4_doi_free_rcu
);
ret_val
=
0
;
doi_remove_return:
audit_buf
=
netlbl_audit_start
(
AUDIT_MAC_CIPSOV4_DEL
,
audit_info
);
if
(
audit_buf
!=
NULL
)
{
audit_log_format
(
audit_buf
,
" cipso_doi=%u res=%u"
,
doi
,
ret_val
==
0
?
1
:
0
);
audit_log_end
(
audit_buf
);
}
return
0
;
return
ret_val
;
}
/**
...
...
net/netlabel/netlabel_cipso_v4.c
View file @
5c8c40be
...
...
@@ -130,6 +130,7 @@ static int netlbl_cipsov4_add_common(struct genl_info *info,
/**
* netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition
* @info: the Generic NETLINK info block
* @audit_info: NetLabel audit information
*
* Description:
* Create a new CIPSO_V4_MAP_TRANS DOI definition based on the given ADD
...
...
@@ -137,7 +138,8 @@ static int netlbl_cipsov4_add_common(struct genl_info *info,
* non-zero on error.
*
*/
static
int
netlbl_cipsov4_add_std
(
struct
genl_info
*
info
)
static
int
netlbl_cipsov4_add_std
(
struct
genl_info
*
info
,
struct
netlbl_audit
*
audit_info
)
{
int
ret_val
=
-
EINVAL
;
struct
cipso_v4_doi
*
doi_def
=
NULL
;
...
...
@@ -316,7 +318,7 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
}
}
ret_val
=
cipso_v4_doi_add
(
doi_def
);
ret_val
=
cipso_v4_doi_add
(
doi_def
,
audit_info
);
if
(
ret_val
!=
0
)
goto
add_std_failure
;
return
0
;
...
...
@@ -330,6 +332,7 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
/**
* netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition
* @info: the Generic NETLINK info block
* @audit_info: NetLabel audit information
*
* Description:
* Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message
...
...
@@ -337,7 +340,8 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
* error.
*
*/
static
int
netlbl_cipsov4_add_pass
(
struct
genl_info
*
info
)
static
int
netlbl_cipsov4_add_pass
(
struct
genl_info
*
info
,
struct
netlbl_audit
*
audit_info
)
{
int
ret_val
;
struct
cipso_v4_doi
*
doi_def
=
NULL
;
...
...
@@ -354,7 +358,7 @@ static int netlbl_cipsov4_add_pass(struct genl_info *info)
if
(
ret_val
!=
0
)
goto
add_pass_failure
;
ret_val
=
cipso_v4_doi_add
(
doi_def
);
ret_val
=
cipso_v4_doi_add
(
doi_def
,
audit_info
);
if
(
ret_val
!=
0
)
goto
add_pass_failure
;
return
0
;
...
...
@@ -367,6 +371,7 @@ static int netlbl_cipsov4_add_pass(struct genl_info *info)
/**
* netlbl_cipsov4_add_local - Adds a CIPSO V4 DOI definition
* @info: the Generic NETLINK info block
* @audit_info: NetLabel audit information
*
* Description:
* Create a new CIPSO_V4_MAP_LOCAL DOI definition based on the given ADD
...
...
@@ -374,7 +379,8 @@ static int netlbl_cipsov4_add_pass(struct genl_info *info)
* non-zero on error.
*
*/
static
int
netlbl_cipsov4_add_local
(
struct
genl_info
*
info
)
static
int
netlbl_cipsov4_add_local
(
struct
genl_info
*
info
,
struct
netlbl_audit
*
audit_info
)
{
int
ret_val
;
struct
cipso_v4_doi
*
doi_def
=
NULL
;
...
...
@@ -391,7 +397,7 @@ static int netlbl_cipsov4_add_local(struct genl_info *info)
if
(
ret_val
!=
0
)
goto
add_local_failure
;
ret_val
=
cipso_v4_doi_add
(
doi_def
);
ret_val
=
cipso_v4_doi_add
(
doi_def
,
audit_info
);
if
(
ret_val
!=
0
)
goto
add_local_failure
;
return
0
;
...
...
@@ -415,48 +421,31 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info)
{
int
ret_val
=
-
EINVAL
;
u32
type
;
u32
doi
;
const
char
*
type_str
=
"(unknown)"
;
struct
audit_buffer
*
audit_buf
;
struct
netlbl_audit
audit_info
;
if
(
!
info
->
attrs
[
NLBL_CIPSOV4_A_DOI
]
||
!
info
->
attrs
[
NLBL_CIPSOV4_A_MTYPE
])
return
-
EINVAL
;
doi
=
nla_get_u32
(
info
->
attrs
[
NLBL_CIPSOV4_A_DOI
]);
netlbl_netlink_auditinfo
(
skb
,
&
audit_info
);
type
=
nla_get_u32
(
info
->
attrs
[
NLBL_CIPSOV4_A_MTYPE
]);
switch
(
type
)
{
switch
(
nla_get_u32
(
info
->
attrs
[
NLBL_CIPSOV4_A_MTYPE
]))
{
case
CIPSO_V4_MAP_TRANS
:
type_str
=
"trans"
;
ret_val
=
netlbl_cipsov4_add_std
(
info
);
ret_val
=
netlbl_cipsov4_add_std
(
info
,
&
audit_info
);
break
;
case
CIPSO_V4_MAP_PASS
:
type_str
=
"pass"
;
ret_val
=
netlbl_cipsov4_add_pass
(
info
);
ret_val
=
netlbl_cipsov4_add_pass
(
info
,
&
audit_info
);
break
;
case
CIPSO_V4_MAP_LOCAL
:
type_str
=
"local"
;
ret_val
=
netlbl_cipsov4_add_local
(
info
);
ret_val
=
netlbl_cipsov4_add_local
(
info
,
&
audit_info
);
break
;
}
if
(
ret_val
==
0
)
atomic_inc
(
&
netlabel_mgmt_protocount
);
audit_buf
=
netlbl_audit_start_common
(
AUDIT_MAC_CIPSOV4_ADD
,
&
audit_info
);
if
(
audit_buf
!=
NULL
)
{
audit_log_format
(
audit_buf
,
" cipso_doi=%u cipso_type=%s res=%u"
,
doi
,
type_str
,
ret_val
==
0
?
1
:
0
);
audit_log_end
(
audit_buf
);
}
return
ret_val
;
}
...
...
@@ -725,9 +714,7 @@ static int netlbl_cipsov4_remove_cb(struct netlbl_dom_map *entry, void *arg)
static
int
netlbl_cipsov4_remove
(
struct
sk_buff
*
skb
,
struct
genl_info
*
info
)
{
int
ret_val
=
-
EINVAL
;
u32
doi
=
0
;
struct
netlbl_domhsh_walk_arg
cb_arg
;
struct
audit_buffer
*
audit_buf
;
struct
netlbl_audit
audit_info
;
u32
skip_bkt
=
0
;
u32
skip_chain
=
0
;
...
...
@@ -735,29 +722,17 @@ static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
if
(
!
info
->
attrs
[
NLBL_CIPSOV4_A_DOI
])
return
-
EINVAL
;
doi
=
nla_get_u32
(
info
->
attrs
[
NLBL_CIPSOV4_A_DOI
]);
netlbl_netlink_auditinfo
(
skb
,
&
audit_info
);
cb_arg
.
doi
=
doi
;
cb_arg
.
doi
=
nla_get_u32
(
info
->
attrs
[
NLBL_CIPSOV4_A_DOI
]);
cb_arg
.
audit_info
=
&
audit_info
;
ret_val
=
netlbl_domhsh_walk
(
&
skip_bkt
,
&
skip_chain
,
netlbl_cipsov4_remove_cb
,
&
cb_arg
);
if
(
ret_val
==
0
||
ret_val
==
-
ENOENT
)
{
ret_val
=
cipso_v4_doi_remove
(
doi
,
&
audit_info
);
ret_val
=
cipso_v4_doi_remove
(
cb_arg
.
doi
,
&
audit_info
);
if
(
ret_val
==
0
)
atomic_dec
(
&
netlabel_mgmt_protocount
);
}
audit_buf
=
netlbl_audit_start_common
(
AUDIT_MAC_CIPSOV4_DEL
,
&
audit_info
);
if
(
audit_buf
!=
NULL
)
{
audit_log_format
(
audit_buf
,
" cipso_doi=%u res=%u"
,
doi
,
ret_val
==
0
?
1
:
0
);
audit_log_end
(
audit_buf
);
}
return
ret_val
;
}
...
...
net/netlabel/netlabel_domainhash.c
View file @
5c8c40be
...
...
@@ -482,6 +482,73 @@ int netlbl_domhsh_remove_entry(struct netlbl_dom_map *entry,
return
ret_val
;
}
/**
* netlbl_domhsh_remove_af4 - Removes an address selector entry
* @domain: the domain
* @addr: IPv4 address
* @mask: IPv4 address mask
* @audit_info: NetLabel audit information
*
* Description:
* Removes an individual address selector from a domain mapping and potentially
* the entire mapping if it is empty. Returns zero on success, negative values
* on failure.
*
*/
int
netlbl_domhsh_remove_af4
(
const
char
*
domain
,
const
struct
in_addr
*
addr
,
const
struct
in_addr
*
mask
,
struct
netlbl_audit
*
audit_info
)
{
struct
netlbl_dom_map
*
entry_map
;
struct
netlbl_af4list
*
entry_addr
;
struct
netlbl_af4list
*
iter4
;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct
netlbl_af6list
*
iter6
;
#endif
/* IPv6 */
struct
netlbl_domaddr4_map
*
entry
;
rcu_read_lock
();
if
(
domain
)
entry_map
=
netlbl_domhsh_search
(
domain
);
else
entry_map
=
netlbl_domhsh_search_def
(
domain
);
if
(
entry_map
==
NULL
||
entry_map
->
type
!=
NETLBL_NLTYPE_ADDRSELECT
)
goto
remove_af4_failure
;
spin_lock
(
&
netlbl_domhsh_lock
);
entry_addr
=
netlbl_af4list_remove
(
addr
->
s_addr
,
mask
->
s_addr
,
&
entry_map
->
type_def
.
addrsel
->
list4
);
spin_unlock
(
&
netlbl_domhsh_lock
);
if
(
entry_addr
==
NULL
)
goto
remove_af4_failure
;
netlbl_af4list_foreach_rcu
(
iter4
,
&
entry_map
->
type_def
.
addrsel
->
list4
)
goto
remove_af4_single_addr
;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
netlbl_af6list_foreach_rcu
(
iter6
,
&
entry_map
->
type_def
.
addrsel
->
list6
)
goto
remove_af4_single_addr
;
#endif
/* IPv6 */
/* the domain mapping is empty so remove it from the mapping table */
netlbl_domhsh_remove_entry
(
entry_map
,
audit_info
);
remove_af4_single_addr:
rcu_read_unlock
();
/* yick, we can't use call_rcu here because we don't have a rcu head
* pointer but hopefully this should be a rare case so the pause
* shouldn't be a problem */
synchronize_rcu
();
entry
=
netlbl_domhsh_addr4_entry
(
entry_addr
);
cipso_v4_doi_putdef
(
entry
->
type_def
.
cipsov4
);
kfree
(
entry
);
return
0
;
remove_af4_failure:
rcu_read_unlock
();
return
-
ENOENT
;
}
/**
* netlbl_domhsh_remove - Removes an entry from the domain hash table
* @domain: the domain to remove
...
...
net/netlabel/netlabel_domainhash.h
View file @
5c8c40be
...
...
@@ -90,6 +90,10 @@ int netlbl_domhsh_add_default(struct netlbl_dom_map *entry,
struct
netlbl_audit
*
audit_info
);
int
netlbl_domhsh_remove_entry
(
struct
netlbl_dom_map
*
entry
,
struct
netlbl_audit
*
audit_info
);
int
netlbl_domhsh_remove_af4
(
const
char
*
domain
,
const
struct
in_addr
*
addr
,
const
struct
in_addr
*
mask
,
struct
netlbl_audit
*
audit_info
);
int
netlbl_domhsh_remove
(
const
char
*
domain
,
struct
netlbl_audit
*
audit_info
);
int
netlbl_domhsh_remove_default
(
struct
netlbl_audit
*
audit_info
);
struct
netlbl_dom_map
*
netlbl_domhsh_getentry
(
const
char
*
domain
);
...
...
net/netlabel/netlabel_kapi.c
View file @
5c8c40be
...
...
@@ -31,7 +31,10 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/audit.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/netlabel.h>
#include <net/cipso_ipv4.h>
#include <asm/bug.h>
...
...
@@ -42,6 +45,7 @@
#include "netlabel_cipso_v4.h"
#include "netlabel_user.h"
#include "netlabel_mgmt.h"
#include "netlabel_addrlist.h"
/*
* Configuration Functions
...
...
@@ -50,6 +54,9 @@
/**
* netlbl_cfg_map_del - Remove a NetLabel/LSM domain mapping
* @domain: the domain mapping to remove
* @family: address family
* @addr: IP address
* @mask: IP address mask
* @audit_info: NetLabel audit information
*
* Description:
...
...
@@ -58,14 +65,32 @@
* values on failure.
*
*/
int
netlbl_cfg_map_del
(
const
char
*
domain
,
struct
netlbl_audit
*
audit_info
)
int
netlbl_cfg_map_del
(
const
char
*
domain
,
u16
family
,
const
void
*
addr
,
const
void
*
mask
,
struct
netlbl_audit
*
audit_info
)
{
return
netlbl_domhsh_remove
(
domain
,
audit_info
);
if
(
addr
==
NULL
&&
mask
==
NULL
)
{
return
netlbl_domhsh_remove
(
domain
,
audit_info
);
}
else
if
(
addr
!=
NULL
&&
mask
!=
NULL
)
{
switch
(
family
)
{
case
AF_INET
:
return
netlbl_domhsh_remove_af4
(
domain
,
addr
,
mask
,
audit_info
);
default:
return
-
EPFNOSUPPORT
;
}
}
else
return
-
EINVAL
;
}
/**
* netlbl_cfg_unlbl_
add_map - Add an unlabeled NetLabel/LSM domain
mapping
* netlbl_cfg_unlbl_
map_add - Add a new unlabeled
mapping
* @domain: the domain mapping to add
* @family: address family
* @addr: IP address
* @mask: IP address mask
* @audit_info: NetLabel audit information
*
* Description:
...
...
@@ -74,11 +99,19 @@ int netlbl_cfg_map_del(const char *domain, struct netlbl_audit *audit_info)
* negative values on failure.
*
*/
int
netlbl_cfg_unlbl_add_map
(
const
char
*
domain
,
int
netlbl_cfg_unlbl_map_add
(
const
char
*
domain
,
u16
family
,
const
void
*
addr
,
const
void
*
mask
,
struct
netlbl_audit
*
audit_info
)
{
int
ret_val
=
-
ENOMEM
;
struct
netlbl_dom_map
*
entry
;
struct
netlbl_domaddr_map
*
addrmap
=
NULL
;
struct
netlbl_domaddr4_map
*
map4
=
NULL
;
struct
netlbl_domaddr6_map
*
map6
=
NULL
;
const
struct
in_addr
*
addr4
,
*
mask4
;
const
struct
in6_addr
*
addr6
,
*
mask6
;
entry
=
kzalloc
(
sizeof
(
*
entry
),
GFP_ATOMIC
);
if
(
entry
==
NULL
)
...
...
@@ -86,49 +119,225 @@ int netlbl_cfg_unlbl_add_map(const char *domain,
if
(
domain
!=
NULL
)
{
entry
->
domain
=
kstrdup
(
domain
,
GFP_ATOMIC
);
if
(
entry
->
domain
==
NULL
)
goto
cfg_unlbl_add_map_failure
;
goto
cfg_unlbl_map_add_failure
;
}
if
(
addr
==
NULL
&&
mask
==
NULL
)
entry
->
type
=
NETLBL_NLTYPE_UNLABELED
;
else
if
(
addr
!=
NULL
&&
mask
!=
NULL
)
{
addrmap
=
kzalloc
(
sizeof
(
*
addrmap
),
GFP_ATOMIC
);
if
(
addrmap
==
NULL
)
goto
cfg_unlbl_map_add_failure
;
INIT_LIST_HEAD
(
&
addrmap
->
list4
);
INIT_LIST_HEAD
(
&
addrmap
->
list6
);
switch
(
family
)
{
case
AF_INET
:
addr4
=
addr
;
mask4
=
mask
;
map4
=
kzalloc
(
sizeof
(
*
map4
),
GFP_ATOMIC
);
if
(
map4
==
NULL
)
goto
cfg_unlbl_map_add_failure
;
map4
->
type
=
NETLBL_NLTYPE_UNLABELED
;
map4
->
list
.
addr
=
addr4
->
s_addr
&
mask4
->
s_addr
;
map4
->
list
.
mask
=
mask4
->
s_addr
;
map4
->
list
.
valid
=
1
;
ret_val
=
netlbl_af4list_add
(
&
map4
->
list
,
&
addrmap
->
list4
);
if
(
ret_val
!=
0
)
goto
cfg_unlbl_map_add_failure
;
break
;
case
AF_INET6
:
addr6
=
addr
;
mask6
=
mask
;
map6
=
kzalloc
(
sizeof
(
*
map6
),
GFP_ATOMIC
);
if
(
map4
==
NULL
)
goto
cfg_unlbl_map_add_failure
;
map6
->
type
=
NETLBL_NLTYPE_UNLABELED
;
ipv6_addr_copy
(
&
map6
->
list
.
addr
,
addr6
);
map6
->
list
.
addr
.
s6_addr32
[
0
]
&=
mask6
->
s6_addr32
[
0
];
map6
->
list
.
addr
.
s6_addr32
[
1
]
&=
mask6
->
s6_addr32
[
1
];
map6
->
list
.
addr
.
s6_addr32
[
2
]
&=
mask6
->
s6_addr32
[
2
];
map6
->
list
.
addr
.
s6_addr32
[
3
]
&=
mask6
->
s6_addr32
[
3
];
ipv6_addr_copy
(
&
map6
->
list
.
mask
,
mask6
);
map6
->
list
.
valid
=
1
;
ret_val
=
netlbl_af4list_add
(
&
map4
->
list
,
&
addrmap
->
list4
);
if
(
ret_val
!=
0
)
goto
cfg_unlbl_map_add_failure
;
break
;
default:
goto
cfg_unlbl_map_add_failure
;
break
;
}
entry
->
type_def
.
addrsel
=
addrmap
;
entry
->
type
=
NETLBL_NLTYPE_ADDRSELECT
;
}
else
{
ret_val
=
-
EINVAL
;
goto
cfg_unlbl_map_add_failure
;
}
entry
->
type
=
NETLBL_NLTYPE_UNLABELED
;
ret_val
=
netlbl_domhsh_add
(
entry
,
audit_info
);
if
(
ret_val
!=
0
)
goto
cfg_unlbl_
add_map
_failure
;
goto
cfg_unlbl_
map_add
_failure
;
return
0
;
cfg_unlbl_
add_map
_failure:
cfg_unlbl_
map_add
_failure:
if
(
entry
!=
NULL
)
kfree
(
entry
->
domain
);
kfree
(
entry
);
kfree
(
addrmap
);
kfree
(
map4
);
kfree
(
map6
);
return
ret_val
;
}
/**
* netlbl_cfg_unlbl_static_add - Adds a new static label
* @net: network namespace
* @dev_name: interface name
* @addr: IP address in network byte order (struct in[6]_addr)
* @mask: address mask in network byte order (struct in[6]_addr)
* @family: address family
* @secid: LSM secid value for the entry
* @audit_info: NetLabel audit information
*
* Description:
* Adds a new NetLabel static label to be used when protocol provided labels
* are not present on incoming traffic. If @dev_name is NULL then the default
* interface will be used. Returns zero on success, negative values on failure.
*
*/
int
netlbl_cfg_unlbl_static_add
(
struct
net
*
net
,
const
char
*
dev_name
,
const
void
*
addr
,
const
void
*
mask
,
u16
family
,
u32
secid
,
struct
netlbl_audit
*
audit_info
)
{
u32
addr_len
;
switch
(
family
)
{
case
AF_INET
:
addr_len
=
sizeof
(
struct
in_addr
);
break
;
case
AF_INET6
:
addr_len
=
sizeof
(
struct
in6_addr
);
break
;
default:
return
-
EPFNOSUPPORT
;
}
return
netlbl_unlhsh_add
(
net
,
dev_name
,
addr
,
mask
,
addr_len
,
secid
,
audit_info
);
}
/**
* netlbl_cfg_unlbl_static_del - Removes an existing static label
* @net: network namespace
* @dev_name: interface name
* @addr: IP address in network byte order (struct in[6]_addr)
* @mask: address mask in network byte order (struct in[6]_addr)
* @family: address family
* @secid: LSM secid value for the entry
* @audit_info: NetLabel audit information
*
* Description:
* Removes an existing NetLabel static label used when protocol provided labels
* are not present on incoming traffic. If @dev_name is NULL then the default
* interface will be used. Returns zero on success, negative values on failure.
*
*/
int
netlbl_cfg_unlbl_static_del
(
struct
net
*
net
,
const
char
*
dev_name
,
const
void
*
addr
,
const
void
*
mask
,
u16
family
,
struct
netlbl_audit
*
audit_info
)
{
u32
addr_len
;
switch
(
family
)
{
case
AF_INET
:
addr_len
=
sizeof
(
struct
in_addr
);
break
;
case
AF_INET6
:
addr_len
=
sizeof
(
struct
in6_addr
);
break
;
default:
return
-
EPFNOSUPPORT
;
}
return
netlbl_unlhsh_remove
(
net
,
dev_name
,
addr
,
mask
,
addr_len
,
audit_info
);
}
/**
* netlbl_cfg_cipsov4_add - Add a new CIPSOv4 DOI definition
* @doi_def: CIPSO DOI definition
* @audit_info: NetLabel audit information
*
* Description:
* Add a new CIPSO DOI definition as defined by @doi_def. Returns zero on
* success and negative values on failure.
*
*/
int
netlbl_cfg_cipsov4_add
(
struct
cipso_v4_doi
*
doi_def
,
struct
netlbl_audit
*
audit_info
)
{
return
cipso_v4_doi_add
(
doi_def
,
audit_info
);
}
/**
* netlbl_cfg_cipsov4_del - Remove an existing CIPSOv4 DOI definition
* @doi: CIPSO DOI
* @audit_info: NetLabel audit information
*
* Description:
* Remove an existing CIPSO DOI definition matching @doi. Returns zero on
* success and negative values on failure.
*
*/
void
netlbl_cfg_cipsov4_del
(
u32
doi
,
struct
netlbl_audit
*
audit_info
)
{
cipso_v4_doi_remove
(
doi
,
audit_info
);
}
/**
* netlbl_cfg_cipsov4_
add_map - Add a new CIPSOv4 DOI definition and
mapping
* @doi
_def: the DOI definition
* netlbl_cfg_cipsov4_
map_add - Add a new CIPSOv4 DOI
mapping
* @doi
: the CIPSO DOI
* @domain: the domain mapping to add
* @addr: IP address
* @mask: IP address mask
* @audit_info: NetLabel audit information
*
* Description:
* Add a new CIPSOv4 DOI definition and NetLabel/LSM domain mapping for this
* new DOI definition to the NetLabel subsystem. A @domain value of NULL adds
* a new default domain mapping. Returns zero on success, negative values on
* failure.
* Add a new NetLabel/LSM domain mapping for the given CIPSO DOI to the NetLabel
* subsystem. A @domain value of NULL adds a new default domain mapping.
* Returns zero on success, negative values on failure.
*
*/
int
netlbl_cfg_cipsov4_
add_map
(
struct
cipso_v4_doi
*
doi_def
,
int
netlbl_cfg_cipsov4_
map_add
(
u32
doi
,
const
char
*
domain
,
const
struct
in_addr
*
addr
,
const
struct
in_addr
*
mask
,
struct
netlbl_audit
*
audit_info
)
{
int
ret_val
=
-
ENOMEM
;
u32
doi
;
u32
doi_type
;
struct
cipso_v4_doi
*
doi_def
;
struct
netlbl_dom_map
*
entry
;
const
char
*
type_str
;
struct
audit_buffer
*
audit_buf
;
struct
netlbl_domaddr_map
*
addrmap
=
NULL
;
struct
netlbl_domaddr4_map
*
addrinfo
=
NULL
;
doi
=
doi_def
->
doi
;
doi_type
=
doi_def
->
type
;
doi_def
=
cipso_v4_doi_getdef
(
doi
);
if
(
doi_def
==
NULL
)
return
-
ENOENT
;
entry
=
kzalloc
(
sizeof
(
*
entry
),
GFP_ATOMIC
);
if
(
entry
==
NULL
)
...
...
@@ -136,56 +345,52 @@ int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def,
if
(
domain
!=
NULL
)
{
entry
->
domain
=
kstrdup
(
domain
,
GFP_ATOMIC
);
if
(
entry
->
domain
==
NULL
)
goto
cfg_cipsov4_
add_map
_failure
;
goto
cfg_cipsov4_
map_add
_failure
;
}
ret_val
=
cipso_v4_doi_add
(
doi_def
);
if
(
ret_val
!=
0
)
goto
cfg_cipsov4_add_map_failure_remove_doi
;
entry
->
type
=
NETLBL_NLTYPE_CIPSOV4
;
entry
->
type_def
.
cipsov4
=
cipso_v4_doi_getdef
(
doi
);
if
(
entry
->
type_def
.
cipsov4
==
NULL
)
{
ret_val
=
-
ENOENT
;
goto
cfg_cipsov4_add_map_failure_remove_doi
;
if
(
addr
==
NULL
&&
mask
==
NULL
)
{
entry
->
type_def
.
cipsov4
=
doi_def
;
entry
->
type
=
NETLBL_NLTYPE_CIPSOV4
;
}
else
if
(
addr
!=
NULL
&&
mask
!=
NULL
)
{
addrmap
=
kzalloc
(
sizeof
(
*
addrmap
),
GFP_ATOMIC
);
if
(
addrmap
==
NULL
)
goto
cfg_cipsov4_map_add_failure
;
INIT_LIST_HEAD
(
&
addrmap
->
list4
);
INIT_LIST_HEAD
(
&
addrmap
->
list6
);
addrinfo
=
kzalloc
(
sizeof
(
*
addrinfo
),
GFP_ATOMIC
);
if
(
addrinfo
==
NULL
)
goto
cfg_cipsov4_map_add_failure
;
addrinfo
->
type_def
.
cipsov4
=
doi_def
;
addrinfo
->
type
=
NETLBL_NLTYPE_CIPSOV4
;
addrinfo
->
list
.
addr
=
addr
->
s_addr
&
mask
->
s_addr
;
addrinfo
->
list
.
mask
=
mask
->
s_addr
;
addrinfo
->
list
.
valid
=
1
;
ret_val
=
netlbl_af4list_add
(
&
addrinfo
->
list
,
&
addrmap
->
list4
);
if
(
ret_val
!=
0
)
goto
cfg_cipsov4_map_add_failure
;
entry
->
type_def
.
addrsel
=
addrmap
;
entry
->
type
=
NETLBL_NLTYPE_ADDRSELECT
;
}
else
{
ret_val
=
-
EINVAL
;
goto
cfg_cipsov4_map_add_failure
;
}
ret_val
=
netlbl_domhsh_add
(
entry
,
audit_info
);
if
(
ret_val
!=
0
)
goto
cfg_cipsov4_add_map_failure_release_doi
;
cfg_cipsov4_add_map_return:
audit_buf
=
netlbl_audit_start_common
(
AUDIT_MAC_CIPSOV4_ADD
,
audit_info
);
if
(
audit_buf
!=
NULL
)
{
switch
(
doi_type
)
{
case
CIPSO_V4_MAP_TRANS
:
type_str
=
"trans"
;
break
;
case
CIPSO_V4_MAP_PASS
:
type_str
=
"pass"
;
break
;
case
CIPSO_V4_MAP_LOCAL
:
type_str
=
"local"
;
break
;
default:
type_str
=
"(unknown)"
;
}
audit_log_format
(
audit_buf
,
" cipso_doi=%u cipso_type=%s res=%u"
,
doi
,
type_str
,
ret_val
==
0
?
1
:
0
);
audit_log_end
(
audit_buf
);
}
goto
cfg_cipsov4_map_add_failure
;
return
ret_val
;
return
0
;
cfg_cipsov4_
add_map_failure_release_doi
:
cfg_cipsov4_
map_add_failure
:
cipso_v4_doi_putdef
(
doi_def
);
cfg_cipsov4_add_map_failure_remove_doi:
cipso_v4_doi_remove
(
doi
,
audit_info
);
cfg_cipsov4_add_map_failure:
if
(
entry
!=
NULL
)
kfree
(
entry
->
domain
);
kfree
(
entry
);
goto
cfg_cipsov4_add_map_return
;
kfree
(
addrmap
);
kfree
(
addrinfo
);
return
ret_val
;
}
/*
...
...
@@ -690,6 +895,28 @@ int netlbl_cache_add(const struct sk_buff *skb,
return
-
ENOMSG
;
}
/*
* Protocol Engine Functions
*/
/**
* netlbl_audit_start - Start an audit message
* @type: audit message type
* @audit_info: NetLabel audit information
*
* Description:
* Start an audit message using the type specified in @type and fill the audit
* message with some fields common to all NetLabel audit messages. This
* function should only be used by protocol engines, not LSMs. Returns a
* pointer to the audit buffer on success, NULL on failure.
*
*/
struct
audit_buffer
*
netlbl_audit_start
(
int
type
,
struct
netlbl_audit
*
audit_info
)
{
return
netlbl_audit_start_common
(
type
,
audit_info
);
}
/*
* Setup Functions
*/
...
...
net/netlabel/netlabel_unlabeled.c
View file @
5c8c40be
...
...
@@ -450,13 +450,13 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex)
* success, negative values on failure.
*
*/
static
int
netlbl_unlhsh_add
(
struct
net
*
net
,
const
char
*
dev_name
,
const
void
*
addr
,
const
void
*
mask
,
u32
addr_len
,
u32
secid
,
struct
netlbl_audit
*
audit_info
)
int
netlbl_unlhsh_add
(
struct
net
*
net
,
const
char
*
dev_name
,
const
void
*
addr
,
const
void
*
mask
,
u32
addr_len
,
u32
secid
,
struct
netlbl_audit
*
audit_info
)
{
int
ret_val
;
int
ifindex
;
...
...
@@ -720,12 +720,12 @@ static void netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface *iface)
* Returns zero on success, negative values on failure.
*
*/
static
int
netlbl_unlhsh_remove
(
struct
net
*
net
,
const
char
*
dev_name
,
const
void
*
addr
,
const
void
*
mask
,
u32
addr_len
,
struct
netlbl_audit
*
audit_info
)
int
netlbl_unlhsh_remove
(
struct
net
*
net
,
const
char
*
dev_name
,
const
void
*
addr
,
const
void
*
mask
,
u32
addr_len
,
struct
netlbl_audit
*
audit_info
)
{
int
ret_val
;
struct
net_device
*
dev
;
...
...
net/netlabel/netlabel_unlabeled.h
View file @
5c8c40be
...
...
@@ -221,6 +221,21 @@ int netlbl_unlabel_genl_init(void);
/* General Unlabeled init function */
int
netlbl_unlabel_init
(
u32
size
);
/* Static/Fallback label management functions */
int
netlbl_unlhsh_add
(
struct
net
*
net
,
const
char
*
dev_name
,
const
void
*
addr
,
const
void
*
mask
,
u32
addr_len
,
u32
secid
,
struct
netlbl_audit
*
audit_info
);
int
netlbl_unlhsh_remove
(
struct
net
*
net
,
const
char
*
dev_name
,
const
void
*
addr
,
const
void
*
mask
,
u32
addr_len
,
struct
netlbl_audit
*
audit_info
);
/* Process Unlabeled incoming network packets */
int
netlbl_unlabel_getattr
(
const
struct
sk_buff
*
skb
,
u16
family
,
...
...
security/selinux/Kconfig
View file @
5c8c40be
...
...
@@ -94,33 +94,6 @@ config SECURITY_SELINUX_CHECKREQPROT_VALUE
If you are unsure how to answer this question, answer 1.
config SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
bool "NSA SELinux enable new secmark network controls by default"
depends on SECURITY_SELINUX
default n
help
This option determines whether the new secmark-based network
controls will be enabled by default. If not, the old internal
per-packet controls will be enabled by default, preserving
old behavior.
If you enable the new controls, you will need updated
SELinux userspace libraries, tools and policy. Typically,
your distribution will provide these and enable the new controls
in the kernel they also distribute.
Note that this option can be overridden at boot with the
selinux_compat_net parameter, and after boot via
/selinux/compat_net. See Documentation/kernel-parameters.txt
for details on this parameter.
If you enable the new network controls, you will likely
also require the SECMARK and CONNSECMARK targets, as
well as any conntrack helpers for protocols which you
wish to control.
If you are unsure what to do here, select N.
config SECURITY_SELINUX_POLICYDB_VERSION_MAX
bool "NSA SELinux maximum supported policy format version"
depends on SECURITY_SELINUX
...
...
security/selinux/hooks.c
View file @
5c8c40be
...
...
@@ -4185,7 +4185,7 @@ static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
static
int
selinux_sock_rcv_skb_compat
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
,
u16
family
)
{
int
err
;
int
err
=
0
;
struct
sk_security_struct
*
sksec
=
sk
->
sk_security
;
u32
peer_sid
;
u32
sk_sid
=
sksec
->
sid
;
...
...
@@ -4202,7 +4202,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
if
(
selinux_compat_net
)
err
=
selinux_sock_rcv_skb_iptables_compat
(
sk
,
skb
,
&
ad
,
family
,
addrp
);
else
else
if
(
selinux_secmark_enabled
())
err
=
avc_has_perm
(
sk_sid
,
skb
->
secmark
,
SECCLASS_PACKET
,
PACKET__RECV
,
&
ad
);
if
(
err
)
...
...
@@ -4705,7 +4705,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
if
(
selinux_ip_postroute_iptables_compat
(
skb
->
sk
,
ifindex
,
&
ad
,
family
,
addrp
))
return
NF_DROP
;
}
else
{
}
else
if
(
selinux_secmark_enabled
())
{
if
(
avc_has_perm
(
sksec
->
sid
,
skb
->
secmark
,
SECCLASS_PACKET
,
PACKET__SEND
,
&
ad
))
return
NF_DROP
;
...
...
security/selinux/selinuxfs.c
View file @
5c8c40be
...
...
@@ -47,13 +47,7 @@ static char *policycap_names[] = {
unsigned
int
selinux_checkreqprot
=
CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE
;
#ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
#define SELINUX_COMPAT_NET_VALUE 0
#else
#define SELINUX_COMPAT_NET_VALUE 1
#endif
int
selinux_compat_net
=
SELINUX_COMPAT_NET_VALUE
;
int
selinux_compat_net
=
0
;
static
int
__init
checkreqprot_setup
(
char
*
str
)
{
...
...
@@ -494,7 +488,13 @@ static ssize_t sel_write_compat_net(struct file *file, const char __user *buf,
if
(
sscanf
(
page
,
"%d"
,
&
new_value
)
!=
1
)
goto
out
;
selinux_compat_net
=
new_value
?
1
:
0
;
if
(
new_value
)
{
printk
(
KERN_NOTICE
"SELinux: compat_net is deprecated, please use secmark"
" instead
\n
"
);
selinux_compat_net
=
1
;
}
else
selinux_compat_net
=
0
;
length
=
count
;
out:
free_page
((
unsigned
long
)
page
);
...
...
security/smack/smack.h
View file @
5c8c40be
...
...
@@ -16,6 +16,7 @@
#include <linux/capability.h>
#include <linux/spinlock.h>
#include <linux/security.h>
#include <linux/in.h>
#include <net/netlabel.h>
/*
...
...
@@ -39,6 +40,7 @@ struct superblock_smack {
struct
socket_smack
{
char
*
smk_out
;
/* outbound label */
char
*
smk_in
;
/* inbound label */
int
smk_labeled
;
/* label scheme */
char
smk_packet
[
SMK_LABELLEN
];
/* TCP peer label */
};
...
...
@@ -79,6 +81,16 @@ struct smack_cipso {
char
smk_catset
[
SMK_LABELLEN
];
};
/*
* An entry in the table identifying hosts.
*/
struct
smk_netlbladdr
{
struct
smk_netlbladdr
*
smk_next
;
struct
sockaddr_in
smk_host
;
/* network address */
struct
in_addr
smk_mask
;
/* network mask */
char
*
smk_label
;
/* label */
};
/*
* This is the repository for labels seen so that it is
* not necessary to keep allocating tiny chuncks of memory
...
...
@@ -127,6 +139,20 @@ struct smack_known {
#define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT
/*
* How communications on this socket are treated.
* Usually it's determined by the underlying netlabel code
* but there are certain cases, including single label hosts
* and potentially single label interfaces for which the
* treatment can not be known in advance.
*
* The possibility of additional labeling schemes being
* introduced in the future exists as well.
*/
#define SMACK_UNLABELED_SOCKET 0
#define SMACK_CIPSO_SOCKET 1
/*
* smackfs magic number
* smackfs macic number
*/
#define SMACK_MAGIC 0x43415d53
/* "SMAC" */
...
...
@@ -141,6 +167,7 @@ struct smack_known {
* CIPSO defaults.
*/
#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_MAXCATVAL 63
/* Bigger gets harder */
#define SMACK_CIPSO_MAXLEVEL 255
/* CIPSO 2.2 standard */
...
...
@@ -176,7 +203,6 @@ u32 smack_to_secid(const char *);
* Shared data.
*/
extern
int
smack_cipso_direct
;
extern
int
smack_net_nltype
;
extern
char
*
smack_net_ambient
;
extern
char
*
smack_onlycap
;
...
...
@@ -186,9 +212,10 @@ extern struct smack_known smack_known_hat;
extern
struct
smack_known
smack_known_huh
;
extern
struct
smack_known
smack_known_invalid
;
extern
struct
smack_known
smack_known_star
;
extern
struct
smack_known
smack_known_
unset
;
extern
struct
smack_known
smack_known_
web
;
extern
struct
smk_list_entry
*
smack_list
;
extern
struct
smk_netlbladdr
*
smack_netlbladdrs
;
extern
struct
security_operations
smack_ops
;
/*
...
...
security/smack/smack_access.c
View file @
5c8c40be
...
...
@@ -15,15 +15,8 @@
#include <linux/sched.h>
#include "smack.h"
struct
smack_known
smack_known_unset
=
{
.
smk_next
=
NULL
,
.
smk_known
=
"UNSET"
,
.
smk_secid
=
1
,
.
smk_cipso
=
NULL
,
};
struct
smack_known
smack_known_huh
=
{
.
smk_next
=
&
smack_known_unset
,
.
smk_next
=
NULL
,
.
smk_known
=
"?"
,
.
smk_secid
=
2
,
.
smk_cipso
=
NULL
,
...
...
@@ -57,7 +50,14 @@ struct smack_known smack_known_invalid = {
.
smk_cipso
=
NULL
,
};
struct
smack_known
*
smack_known
=
&
smack_known_invalid
;
struct
smack_known
smack_known_web
=
{
.
smk_next
=
&
smack_known_invalid
,
.
smk_known
=
"@"
,
.
smk_secid
=
7
,
.
smk_cipso
=
NULL
,
};
struct
smack_known
*
smack_known
=
&
smack_known_web
;
/*
* The initial value needs to be bigger than any of the
...
...
@@ -98,6 +98,16 @@ int smk_access(char *subject_label, char *object_label, int request)
if
(
subject_label
==
smack_known_star
.
smk_known
||
strcmp
(
subject_label
,
smack_known_star
.
smk_known
)
==
0
)
return
-
EACCES
;
/*
* An internet object can be accessed by any subject.
* Tasks cannot be assigned the internet label.
* An internet subject can access any object.
*/
if
(
object_label
==
smack_known_web
.
smk_known
||
subject_label
==
smack_known_web
.
smk_known
||
strcmp
(
object_label
,
smack_known_web
.
smk_known
)
==
0
||
strcmp
(
subject_label
,
smack_known_web
.
smk_known
)
==
0
)
return
0
;
/*
* A star object can be accessed by any subject.
*/
...
...
security/smack/smack_lsm.c
View file @
5c8c40be
...
...
@@ -1277,6 +1277,7 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
ssp
->
smk_in
=
csp
;
ssp
->
smk_out
=
csp
;
ssp
->
smk_labeled
=
SMACK_CIPSO_SOCKET
;
ssp
->
smk_packet
[
0
]
=
'\0'
;
sk
->
sk_security
=
ssp
;
...
...
@@ -1341,45 +1342,69 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
struct
smack_cipso
cipso
;
int
rc
;
switch
(
smack_net_nltype
)
{
case
NETLBL_NLTYPE_CIPSOV4
:
nlsp
->
domain
=
smack
;
nlsp
->
flags
=
NETLBL_SECATTR_DOMAIN
|
NETLBL_SECATTR_MLS_LVL
;
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
);
}
break
;
default:
break
;
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
* @labeled: socket label scheme
*
* Convert the outbound smack value (smk_out) to a
* secattr and attach it to the socket.
*
* Returns 0 on success or an error code
*/
static
int
smack_netlabel
(
struct
sock
*
sk
)
static
int
smack_netlabel
(
struct
sock
*
sk
,
int
labeled
)
{
struct
socket_smack
*
ssp
;
struct
netlbl_lsm_secattr
secattr
;
int
rc
;
int
rc
=
0
;
ssp
=
sk
->
sk_security
;
netlbl_secattr_init
(
&
secattr
);
smack_to_secattr
(
ssp
->
smk_out
,
&
secattr
);
rc
=
netlbl_sock_setattr
(
sk
,
&
secattr
);
netlbl_secattr_destroy
(
&
secattr
);
/*
* Usually the netlabel code will handle changing the
* packet labeling based on the label.
* The case of a single label host is different, because
* a single label host should never get a labeled packet
* even though the label is usually associated with a packet
* label.
*/
local_bh_disable
();
bh_lock_sock_nested
(
sk
);
if
(
ssp
->
smk_out
==
smack_net_ambient
||
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
,
&
secattr
);
netlbl_secattr_destroy
(
&
secattr
);
}
bh_unlock_sock
(
sk
);
local_bh_enable
();
/*
* Remember the label scheme used so that it is not
* necessary to do the netlabel setting if it has not
* changed the next time through.
*
* The -EDESTADDRREQ case is an indication that there's
* a single level host involved.
*/
if
(
rc
==
0
)
ssp
->
smk_labeled
=
labeled
;
return
rc
;
}
...
...
@@ -1432,7 +1457,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
ssp
->
smk_in
=
sp
;
else
if
(
strcmp
(
name
,
XATTR_SMACK_IPOUT
)
==
0
)
{
ssp
->
smk_out
=
sp
;
rc
=
smack_netlabel
(
sock
->
sk
);
rc
=
smack_netlabel
(
sock
->
sk
,
SMACK_CIPSO_SOCKET
);
if
(
rc
!=
0
)
printk
(
KERN_WARNING
"Smack:
\"
%s
\"
netlbl error %d.
\n
"
,
__func__
,
-
rc
);
...
...
@@ -1462,7 +1487,108 @@ static int smack_socket_post_create(struct socket *sock, int family,
/*
* Set the outbound netlbl.
*/
return
smack_netlabel
(
sock
->
sk
);
return
smack_netlabel
(
sock
->
sk
,
SMACK_CIPSO_SOCKET
);
}
/**
* smack_host_label - check host based restrictions
* @sip: the object end
*
* looks for host based access restrictions
*
* This version will only be appropriate for really small
* sets of single label hosts. Because of the masking
* it cannot shortcut out on the first match. There are
* numerious ways to address the problem, but none of them
* have been applied here.
*
* Returns the label of the far end or NULL if it's not special.
*/
static
char
*
smack_host_label
(
struct
sockaddr_in
*
sip
)
{
struct
smk_netlbladdr
*
snp
;
char
*
bestlabel
=
NULL
;
struct
in_addr
*
siap
=
&
sip
->
sin_addr
;
struct
in_addr
*
liap
;
struct
in_addr
*
miap
;
struct
in_addr
bestmask
;
if
(
siap
->
s_addr
==
0
)
return
NULL
;
bestmask
.
s_addr
=
0
;
for
(
snp
=
smack_netlbladdrs
;
snp
!=
NULL
;
snp
=
snp
->
smk_next
)
{
liap
=
&
snp
->
smk_host
.
sin_addr
;
miap
=
&
snp
->
smk_mask
;
/*
* If the addresses match after applying the list entry mask
* the entry matches the address. If it doesn't move along to
* the next entry.
*/
if
((
liap
->
s_addr
&
miap
->
s_addr
)
!=
(
siap
->
s_addr
&
miap
->
s_addr
))
continue
;
/*
* If the list entry mask identifies a single address
* it can't get any more specific.
*/
if
(
miap
->
s_addr
==
0xffffffff
)
return
snp
->
smk_label
;
/*
* If the list entry mask is less specific than the best
* already found this entry is uninteresting.
*/
if
((
miap
->
s_addr
|
bestmask
.
s_addr
)
==
bestmask
.
s_addr
)
continue
;
/*
* This is better than any entry found so far.
*/
bestmask
.
s_addr
=
miap
->
s_addr
;
bestlabel
=
snp
->
smk_label
;
}
return
bestlabel
;
}
/**
* smack_socket_connect - connect access check
* @sock: the socket
* @sap: the other end
* @addrlen: size of sap
*
* Verifies that a connection may be possible
*
* Returns 0 on success, and error code otherwise
*/
static
int
smack_socket_connect
(
struct
socket
*
sock
,
struct
sockaddr
*
sap
,
int
addrlen
)
{
struct
socket_smack
*
ssp
=
sock
->
sk
->
sk_security
;
char
*
hostsp
;
int
rc
;
if
(
sock
->
sk
==
NULL
||
sock
->
sk
->
sk_family
!=
PF_INET
)
return
0
;
if
(
addrlen
<
sizeof
(
struct
sockaddr_in
))
return
-
EINVAL
;
hostsp
=
smack_host_label
((
struct
sockaddr_in
*
)
sap
);
if
(
hostsp
==
NULL
)
{
if
(
ssp
->
smk_labeled
!=
SMACK_CIPSO_SOCKET
)
return
smack_netlabel
(
sock
->
sk
,
SMACK_CIPSO_SOCKET
);
return
0
;
}
rc
=
smk_access
(
ssp
->
smk_out
,
hostsp
,
MAY_WRITE
);
if
(
rc
!=
0
)
return
rc
;
if
(
ssp
->
smk_labeled
!=
SMACK_UNLABELED_SOCKET
)
return
smack_netlabel
(
sock
->
sk
,
SMACK_UNLABELED_SOCKET
);
return
0
;
}
/**
...
...
@@ -2101,8 +2227,14 @@ static int smack_setprocattr(struct task_struct *p, char *name,
if
(
newsmack
==
NULL
)
return
-
EINVAL
;
/*
* No process is ever allowed the web ("@") label.
*/
if
(
newsmack
==
smack_known_web
.
smk_known
)
return
-
EPERM
;
new
=
prepare_creds
();
if
(
!
new
)
if
(
new
==
NULL
)
return
-
ENOMEM
;
new
->
security
=
newsmack
;
commit_creds
(
new
);
...
...
@@ -2143,6 +2275,49 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
return
smk_access
(
smk_of_inode
(
sp
),
smk_of_inode
(
op
),
MAY_WRITE
);
}
/**
* smack_socket_sendmsg - Smack check based on destination host
* @sock: the socket
* @msghdr: the message
* @size: the size of the message
*
* Return 0 if the current subject can write to the destination
* host. This is only a question if the destination is a single
* label host.
*/
static
int
smack_socket_sendmsg
(
struct
socket
*
sock
,
struct
msghdr
*
msg
,
int
size
)
{
struct
sockaddr_in
*
sip
=
(
struct
sockaddr_in
*
)
msg
->
msg_name
;
struct
socket_smack
*
ssp
=
sock
->
sk
->
sk_security
;
char
*
hostsp
;
int
rc
;
/*
* Perfectly reasonable for this to be NULL
*/
if
(
sip
==
NULL
||
sip
->
sin_family
!=
PF_INET
)
return
0
;
hostsp
=
smack_host_label
(
sip
);
if
(
hostsp
==
NULL
)
{
if
(
ssp
->
smk_labeled
!=
SMACK_CIPSO_SOCKET
)
return
smack_netlabel
(
sock
->
sk
,
SMACK_CIPSO_SOCKET
);
return
0
;
}
rc
=
smk_access
(
ssp
->
smk_out
,
hostsp
,
MAY_WRITE
);
if
(
rc
!=
0
)
return
rc
;
if
(
ssp
->
smk_labeled
!=
SMACK_UNLABELED_SOCKET
)
return
smack_netlabel
(
sock
->
sk
,
SMACK_UNLABELED_SOCKET
);
return
0
;
}
/**
* smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat
* pair to smack
...
...
@@ -2154,44 +2329,66 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
static
void
smack_from_secattr
(
struct
netlbl_lsm_secattr
*
sap
,
char
*
sip
)
{
char
smack
[
SMK_LABELLEN
];
char
*
sp
;
int
pcat
;
if
((
sap
->
flags
&
NETLBL_SECATTR_MLS_LVL
)
=
=
0
)
{
if
((
sap
->
flags
&
NETLBL_SECATTR_MLS_LVL
)
!
=
0
)
{
/*
* Looks like a CIPSO packet.
* If there are flags but no level netlabel isn't
* behaving the way we expect it to.
*
* Get the categories, if any
* Without guidance regarding the smack value
* for the packet fall back on the network
* ambient value.
*/
strncpy
(
sip
,
smack_net_ambient
,
SMK_MAXLEN
);
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
)
{
memcpy
(
sip
,
smack
,
SMK_MAXLEN
);
return
;
}
/*
* Look it up in the supplied table if it is not
* a direct mapping.
*/
smack_from_cipso
(
sap
->
attr
.
mls
.
lvl
,
smack
,
sip
);
return
;
}
/*
* Get the categories, if any
*/
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
)
{
memcpy
(
sip
,
smack
,
SMK_MAXLEN
);
if
((
sap
->
flags
&
NETLBL_SECATTR_SECID
)
!=
0
)
{
/*
* Looks like a fallback, which gives us a secid.
*/
sp
=
smack_from_secid
(
sap
->
attr
.
secid
);
/*
* This has got to be a bug because it is
* impossible to specify a fallback without
* specifying the label, which will ensure
* it has a secid, and the only way to get a
* secid is from a fallback.
*/
BUG_ON
(
sp
==
NULL
);
strncpy
(
sip
,
sp
,
SMK_MAXLEN
);
return
;
}
/*
* Look it up in the supplied table if it is not a direct mapping.
* Without guidance regarding the smack value
* for the packet fall back on the network
* ambient value.
*/
s
mack_from_cipso
(
sap
->
attr
.
mls
.
lvl
,
smack
,
sip
);
s
trncpy
(
sip
,
smack_net_ambient
,
SMK_MAXLEN
);
return
;
}
...
...
@@ -2207,6 +2404,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
struct
netlbl_lsm_secattr
secattr
;
struct
socket_smack
*
ssp
=
sk
->
sk_security
;
char
smack
[
SMK_LABELLEN
];
char
*
csp
;
int
rc
;
if
(
sk
->
sk_family
!=
PF_INET
&&
sk
->
sk_family
!=
PF_INET6
)
...
...
@@ -2215,21 +2413,24 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
/*
* Translate what netlabel gave us.
*/
memset
(
smack
,
'\0'
,
SMK_LABELLEN
);
netlbl_secattr_init
(
&
secattr
);
rc
=
netlbl_skbuff_getattr
(
skb
,
sk
->
sk_family
,
&
secattr
);
if
(
rc
==
0
)
if
(
rc
==
0
)
{
smack_from_secattr
(
&
secattr
,
smack
);
else
strncpy
(
smack
,
smack_net_ambient
,
SMK_MAXLEN
);
csp
=
smack
;
}
else
csp
=
smack_net_ambient
;
netlbl_secattr_destroy
(
&
secattr
);
/*
* Receiving a packet requires that the other end
* be able to write here. Read access is not required.
* This is the simplist possible security model
* for networking.
*/
rc
=
smk_access
(
smack
,
ssp
->
smk_in
,
MAY_WRITE
);
rc
=
smk_access
(
csp
,
ssp
->
smk_in
,
MAY_WRITE
);
if
(
rc
!=
0
)
netlbl_skbuff_err
(
skb
,
rc
,
0
);
return
rc
;
...
...
@@ -2298,7 +2499,6 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
/*
* Translate what netlabel gave us.
*/
memset
(
smack
,
'\0'
,
SMK_LABELLEN
);
netlbl_secattr_init
(
&
secattr
);
rc
=
netlbl_skbuff_getattr
(
skb
,
family
,
&
secattr
);
if
(
rc
==
0
)
...
...
@@ -2341,7 +2541,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent)
ssp
->
smk_in
=
ssp
->
smk_out
=
current_security
();
ssp
->
smk_packet
[
0
]
=
'\0'
;
rc
=
smack_netlabel
(
sk
);
rc
=
smack_netlabel
(
sk
,
SMACK_CIPSO_SOCKET
);
if
(
rc
!=
0
)
printk
(
KERN_WARNING
"Smack:
\"
%s
\"
netlbl error %d.
\n
"
,
__func__
,
-
rc
);
...
...
@@ -2367,7 +2567,6 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
if
(
skb
==
NULL
)
return
-
EACCES
;
memset
(
smack
,
'\0'
,
SMK_LABELLEN
);
netlbl_secattr_init
(
&
skb_secattr
);
rc
=
netlbl_skbuff_getattr
(
skb
,
sk
->
sk_family
,
&
skb_secattr
);
if
(
rc
==
0
)
...
...
@@ -2732,6 +2931,8 @@ struct security_operations smack_ops = {
.
unix_may_send
=
smack_unix_may_send
,
.
socket_post_create
=
smack_socket_post_create
,
.
socket_connect
=
smack_socket_connect
,
.
socket_sendmsg
=
smack_socket_sendmsg
,
.
socket_sock_rcv_skb
=
smack_socket_sock_rcv_skb
,
.
socket_getpeersec_stream
=
smack_socket_getpeersec_stream
,
.
socket_getpeersec_dgram
=
smack_socket_getpeersec_dgram
,
...
...
@@ -2783,7 +2984,6 @@ static __init int smack_init(void)
/*
* Initialize locks
*/
spin_lock_init
(
&
smack_known_unset
.
smk_cipsolock
);
spin_lock_init
(
&
smack_known_huh
.
smk_cipsolock
);
spin_lock_init
(
&
smack_known_hat
.
smk_cipsolock
);
spin_lock_init
(
&
smack_known_star
.
smk_cipsolock
);
...
...
security/smack/smackfs.c
View file @
5c8c40be
...
...
@@ -20,6 +20,7 @@
#include <linux/vmalloc.h>
#include <linux/security.h>
#include <linux/mutex.h>
#include <net/net_namespace.h>
#include <net/netlabel.h>
#include <net/cipso_ipv4.h>
#include <linux/seq_file.h>
...
...
@@ -38,7 +39,7 @@ enum smk_inos {
SMK_DOI
=
5
,
/* CIPSO DOI */
SMK_DIRECT
=
6
,
/* CIPSO level indicating direct label */
SMK_AMBIENT
=
7
,
/* internet ambient label */
SMK_N
LTYPE
=
8
,
/* label scheme to use by default
*/
SMK_N
ETLBLADDR
=
8
,
/* single label hosts
*/
SMK_ONLYCAP
=
9
,
/* the only "capable" label */
};
...
...
@@ -48,6 +49,7 @@ enum smk_inos {
static
DEFINE_MUTEX
(
smack_list_lock
);
static
DEFINE_MUTEX
(
smack_cipso_lock
);
static
DEFINE_MUTEX
(
smack_ambient_lock
);
static
DEFINE_MUTEX
(
smk_netlbladdr_lock
);
/*
* This is the "ambient" label for network traffic.
...
...
@@ -56,12 +58,6 @@ static DEFINE_MUTEX(smack_ambient_lock);
*/
char
*
smack_net_ambient
=
smack_known_floor
.
smk_known
;
/*
* This is the default packet marking scheme for network traffic.
* It can be reset via smackfs/nltype
*/
int
smack_net_nltype
=
NETLBL_NLTYPE_CIPSOV4
;
/*
* This is the level in a CIPSO header that indicates a
* smack label is contained directly in the category set.
...
...
@@ -79,6 +75,13 @@ int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
*/
char
*
smack_onlycap
;
/*
* Certain IP addresses may be designated as single label hosts.
* Packets are sent there unlabeled, but only from tasks that
* can write to the specified label.
*/
struct
smk_netlbladdr
*
smack_netlbladdrs
;
static
int
smk_cipso_doi_value
=
SMACK_CIPSO_DOI_DEFAULT
;
struct
smk_list_entry
*
smack_list
;
...
...
@@ -104,6 +107,24 @@ struct smk_list_entry *smack_list;
#define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1)
#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
/**
* smk_netlabel_audit_set - fill a netlbl_audit struct
* @nap: structure to fill
*/
static
void
smk_netlabel_audit_set
(
struct
netlbl_audit
*
nap
)
{
nap
->
loginuid
=
audit_get_loginuid
(
current
);
nap
->
sessionid
=
audit_get_sessionid
(
current
);
nap
->
secid
=
smack_to_secid
(
current_security
());
}
/*
* Values 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
/*
* Seq_file read operations for /smack/load
...
...
@@ -344,13 +365,11 @@ static void smk_cipso_doi(void)
{
int
rc
;
struct
cipso_v4_doi
*
doip
;
struct
netlbl_audit
audit_info
;
struct
netlbl_audit
nai
;
audit_info
.
loginuid
=
audit_get_loginuid
(
current
);
audit_info
.
sessionid
=
audit_get_sessionid
(
current
);
audit_info
.
secid
=
smack_to_secid
(
current_security
());
smk_netlabel_audit_set
(
&
nai
);
rc
=
netlbl_cfg_map_del
(
NULL
,
&
audit_info
);
rc
=
netlbl_cfg_map_del
(
NULL
,
PF_INET
,
NULL
,
NULL
,
&
nai
);
if
(
rc
!=
0
)
printk
(
KERN_WARNING
"%s:%d remove rc = %d
\n
"
,
__func__
,
__LINE__
,
rc
);
...
...
@@ -365,11 +384,19 @@ static void smk_cipso_doi(void)
for
(
rc
=
1
;
rc
<
CIPSO_V4_TAG_MAXCNT
;
rc
++
)
doip
->
tags
[
rc
]
=
CIPSO_V4_TAG_INVALID
;
rc
=
netlbl_cfg_cipsov4_add
_map
(
doip
,
NULL
,
&
audit_info
);
rc
=
netlbl_cfg_cipsov4_add
(
doip
,
&
nai
);
if
(
rc
!=
0
)
{
printk
(
KERN_WARNING
"%s:%d add rc = %d
\n
"
,
printk
(
KERN_WARNING
"%s:%d
cipso
add rc = %d
\n
"
,
__func__
,
__LINE__
,
rc
);
kfree
(
doip
);
return
;
}
rc
=
netlbl_cfg_cipsov4_map_add
(
doip
->
doi
,
NULL
,
NULL
,
NULL
,
&
nai
);
if
(
rc
!=
0
)
{
printk
(
KERN_WARNING
"%s:%d map add rc = %d
\n
"
,
__func__
,
__LINE__
,
rc
);
kfree
(
doip
);
return
;
}
}
...
...
@@ -379,20 +406,19 @@ static void smk_cipso_doi(void)
static
void
smk_unlbl_ambient
(
char
*
oldambient
)
{
int
rc
;
struct
netlbl_audit
audit_info
;
struct
netlbl_audit
nai
;
audit_info
.
loginuid
=
audit_get_loginuid
(
current
);
audit_info
.
sessionid
=
audit_get_sessionid
(
current
);
audit_info
.
secid
=
smack_to_secid
(
current_security
());
smk_netlabel_audit_set
(
&
nai
);
if
(
oldambient
!=
NULL
)
{
rc
=
netlbl_cfg_map_del
(
oldambient
,
&
audit_info
);
rc
=
netlbl_cfg_map_del
(
oldambient
,
PF_INET
,
NULL
,
NULL
,
&
nai
);
if
(
rc
!=
0
)
printk
(
KERN_WARNING
"%s:%d remove rc = %d
\n
"
,
__func__
,
__LINE__
,
rc
);
}
rc
=
netlbl_cfg_unlbl_add_map
(
smack_net_ambient
,
&
audit_info
);
rc
=
netlbl_cfg_unlbl_map_add
(
smack_net_ambient
,
PF_INET
,
NULL
,
NULL
,
&
nai
);
if
(
rc
!=
0
)
printk
(
KERN_WARNING
"%s:%d add rc = %d
\n
"
,
__func__
,
__LINE__
,
rc
);
...
...
@@ -603,6 +629,201 @@ static const struct file_operations smk_cipso_ops = {
.
release
=
seq_release
,
};
/*
* Seq_file read operations for /smack/netlabel
*/
static
void
*
netlbladdr_seq_start
(
struct
seq_file
*
s
,
loff_t
*
pos
)
{
if
(
*
pos
==
SEQ_READ_FINISHED
)
return
NULL
;
return
smack_netlbladdrs
;
}
static
void
*
netlbladdr_seq_next
(
struct
seq_file
*
s
,
void
*
v
,
loff_t
*
pos
)
{
struct
smk_netlbladdr
*
skp
=
((
struct
smk_netlbladdr
*
)
v
)
->
smk_next
;
if
(
skp
==
NULL
)
*
pos
=
SEQ_READ_FINISHED
;
return
skp
;
}
/*
#define BEMASK 0x80000000
*/
#define BEMASK 0x00000001
#define BEBITS (sizeof(__be32) * 8)
/*
* Print host/label pairs
*/
static
int
netlbladdr_seq_show
(
struct
seq_file
*
s
,
void
*
v
)
{
struct
smk_netlbladdr
*
skp
=
(
struct
smk_netlbladdr
*
)
v
;
unsigned
char
*
hp
=
(
char
*
)
&
skp
->
smk_host
.
sin_addr
.
s_addr
;
__be32
bebits
;
int
maskn
=
0
;
for
(
bebits
=
BEMASK
;
bebits
!=
0
;
maskn
++
,
bebits
<<=
1
)
if
((
skp
->
smk_mask
.
s_addr
&
bebits
)
==
0
)
break
;
seq_printf
(
s
,
"%u.%u.%u.%u/%d %s
\n
"
,
hp
[
0
],
hp
[
1
],
hp
[
2
],
hp
[
3
],
maskn
,
skp
->
smk_label
);
return
0
;
}
static
void
netlbladdr_seq_stop
(
struct
seq_file
*
s
,
void
*
v
)
{
/* No-op */
}
static
struct
seq_operations
netlbladdr_seq_ops
=
{
.
start
=
netlbladdr_seq_start
,
.
stop
=
netlbladdr_seq_stop
,
.
next
=
netlbladdr_seq_next
,
.
show
=
netlbladdr_seq_show
,
};
/**
* smk_open_netlbladdr - open() for /smack/netlabel
* @inode: inode structure representing file
* @file: "netlabel" file pointer
*
* Connect our netlbladdr_seq_* operations with /smack/netlabel
* file_operations
*/
static
int
smk_open_netlbladdr
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
netlbladdr_seq_ops
);
}
/**
* smk_write_netlbladdr - write() for /smack/netlabel
* @filp: file pointer, not actually used
* @buf: where to get the data from
* @count: bytes sent
* @ppos: where to start
*
* Accepts only one netlbladdr per write call.
* Returns number of bytes written or error code, as appropriate
*/
static
ssize_t
smk_write_netlbladdr
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
smk_netlbladdr
*
skp
;
struct
sockaddr_in
newname
;
char
smack
[
SMK_LABELLEN
];
char
*
sp
;
char
data
[
SMK_NETLBLADDRMAX
];
char
*
host
=
(
char
*
)
&
newname
.
sin_addr
.
s_addr
;
int
rc
;
struct
netlbl_audit
audit_info
;
struct
in_addr
mask
;
unsigned
int
m
;
__be32
bebits
=
BEMASK
;
__be32
nsa
;
/*
* Must have privilege.
* No partial writes.
* Enough data must be present.
* "<addr/mask, as a.b.c.d/e><space><label>"
* "<addr, as a.b.c.d><space><label>"
*/
if
(
!
capable
(
CAP_MAC_ADMIN
))
return
-
EPERM
;
if
(
*
ppos
!=
0
)
return
-
EINVAL
;
if
(
count
<
SMK_NETLBLADDRMIN
||
count
>
SMK_NETLBLADDRMAX
)
return
-
EINVAL
;
if
(
copy_from_user
(
data
,
buf
,
count
)
!=
0
)
return
-
EFAULT
;
data
[
count
]
=
'\0'
;
rc
=
sscanf
(
data
,
"%hhd.%hhd.%hhd.%hhd/%d %s"
,
&
host
[
0
],
&
host
[
1
],
&
host
[
2
],
&
host
[
3
],
&
m
,
smack
);
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
;
m
=
BEBITS
;
}
if
(
m
>
BEBITS
)
return
-
EINVAL
;
sp
=
smk_import
(
smack
,
0
);
if
(
sp
==
NULL
)
return
-
EINVAL
;
for
(
mask
.
s_addr
=
0
;
m
>
0
;
m
--
)
{
mask
.
s_addr
|=
bebits
;
bebits
<<=
1
;
}
/*
* Only allow one writer at a time. Writes should be
* quite rare and small in any case.
*/
mutex_lock
(
&
smk_netlbladdr_lock
);
nsa
=
newname
.
sin_addr
.
s_addr
;
for
(
skp
=
smack_netlbladdrs
;
skp
!=
NULL
;
skp
=
skp
->
smk_next
)
if
(
skp
->
smk_host
.
sin_addr
.
s_addr
==
nsa
&&
skp
->
smk_mask
.
s_addr
==
mask
.
s_addr
)
break
;
smk_netlabel_audit_set
(
&
audit_info
);
if
(
skp
==
NULL
)
{
skp
=
kzalloc
(
sizeof
(
*
skp
),
GFP_KERNEL
);
if
(
skp
==
NULL
)
rc
=
-
ENOMEM
;
else
{
rc
=
0
;
skp
->
smk_host
.
sin_addr
.
s_addr
=
newname
.
sin_addr
.
s_addr
;
skp
->
smk_mask
.
s_addr
=
mask
.
s_addr
;
skp
->
smk_next
=
smack_netlbladdrs
;
skp
->
smk_label
=
sp
;
smack_netlbladdrs
=
skp
;
}
}
else
{
rc
=
netlbl_cfg_unlbl_static_del
(
&
init_net
,
NULL
,
&
skp
->
smk_host
.
sin_addr
,
&
skp
->
smk_mask
,
PF_INET
,
&
audit_info
);
skp
->
smk_label
=
sp
;
}
/*
* Now tell netlabel about the single label nature of
* this host so that incoming packets get labeled.
*/
if
(
rc
==
0
)
rc
=
netlbl_cfg_unlbl_static_add
(
&
init_net
,
NULL
,
&
skp
->
smk_host
.
sin_addr
,
&
skp
->
smk_mask
,
PF_INET
,
smack_to_secid
(
skp
->
smk_label
),
&
audit_info
);
if
(
rc
==
0
)
rc
=
count
;
mutex_unlock
(
&
smk_netlbladdr_lock
);
return
rc
;
}
static
const
struct
file_operations
smk_netlbladdr_ops
=
{
.
open
=
smk_open_netlbladdr
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
write
=
smk_write_netlbladdr
,
.
release
=
seq_release
,
};
/**
* smk_read_doi - read() for /smack/doi
* @filp: file pointer, not actually used
...
...
@@ -891,110 +1112,6 @@ static const struct file_operations smk_onlycap_ops = {
.
write
=
smk_write_onlycap
,
};
struct
option_names
{
int
o_number
;
char
*
o_name
;
char
*
o_alias
;
};
static
struct
option_names
netlbl_choices
[]
=
{
{
NETLBL_NLTYPE_RIPSO
,
NETLBL_NLTYPE_RIPSO_NAME
,
"ripso"
},
{
NETLBL_NLTYPE_CIPSOV4
,
NETLBL_NLTYPE_CIPSOV4_NAME
,
"cipsov4"
},
{
NETLBL_NLTYPE_CIPSOV4
,
NETLBL_NLTYPE_CIPSOV4_NAME
,
"cipso"
},
{
NETLBL_NLTYPE_CIPSOV6
,
NETLBL_NLTYPE_CIPSOV6_NAME
,
"cipsov6"
},
{
NETLBL_NLTYPE_UNLABELED
,
NETLBL_NLTYPE_UNLABELED_NAME
,
"unlabeled"
},
};
/**
* smk_read_nltype - read() for /smack/nltype
* @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_nltype
(
struct
file
*
filp
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
char
bound
[
40
];
ssize_t
rc
;
int
i
;
if
(
count
<
SMK_LABELLEN
)
return
-
EINVAL
;
if
(
*
ppos
!=
0
)
return
0
;
sprintf
(
bound
,
"unknown"
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
netlbl_choices
);
i
++
)
if
(
smack_net_nltype
==
netlbl_choices
[
i
].
o_number
)
{
sprintf
(
bound
,
"%s"
,
netlbl_choices
[
i
].
o_name
);
break
;
}
rc
=
simple_read_from_buffer
(
buf
,
count
,
ppos
,
bound
,
strlen
(
bound
));
return
rc
;
}
/**
* smk_write_nltype - write() for /smack/nltype
* @filp: 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_nltype
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
char
bound
[
40
];
char
*
cp
;
int
i
;
if
(
!
capable
(
CAP_MAC_ADMIN
))
return
-
EPERM
;
if
(
count
>=
40
)
return
-
EINVAL
;
if
(
copy_from_user
(
bound
,
buf
,
count
)
!=
0
)
return
-
EFAULT
;
bound
[
count
]
=
'\0'
;
cp
=
strchr
(
bound
,
' '
);
if
(
cp
!=
NULL
)
*
cp
=
'\0'
;
cp
=
strchr
(
bound
,
'\n'
);
if
(
cp
!=
NULL
)
*
cp
=
'\0'
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
netlbl_choices
);
i
++
)
if
(
strcmp
(
bound
,
netlbl_choices
[
i
].
o_name
)
==
0
||
strcmp
(
bound
,
netlbl_choices
[
i
].
o_alias
)
==
0
)
{
smack_net_nltype
=
netlbl_choices
[
i
].
o_number
;
return
count
;
}
/*
* Not a valid choice.
*/
return
-
EINVAL
;
}
static
const
struct
file_operations
smk_nltype_ops
=
{
.
read
=
smk_read_nltype
,
.
write
=
smk_write_nltype
,
};
/**
* smk_fill_super - fill the /smackfs superblock
* @sb: the empty superblock
...
...
@@ -1021,8 +1138,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
{
"direct"
,
&
smk_direct_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_AMBIENT
]
=
{
"ambient"
,
&
smk_ambient_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_N
LTYPE
]
=
{
"n
ltype"
,
&
smk_nltype
_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_N
ETLBLADDR
]
=
{
"n
etlabel"
,
&
smk_netlbladdr
_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_ONLYCAP
]
=
{
"onlycap"
,
&
smk_onlycap_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