Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
93db6286
K
Kernel
项目概览
openeuler
/
Kernel
12 个月 前同步成功
通知
5
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
93db6286
编写于
10月 13, 2008
作者:
J
James Morris
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'next' into for-linus
上级
f1b2a5ac
0da939b0
变更
25
展开全部
隐藏空白更改
内联
并排
Showing
25 changed file
with
2793 addition
and
1024 deletion
+2793
-1024
drivers/char/tpm/tpm.c
drivers/char/tpm/tpm.c
+46
-50
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm.h
+2
-1
drivers/char/tpm/tpm_tis.c
drivers/char/tpm/tpm_tis.c
+13
-1
include/net/cipso_ipv4.h
include/net/cipso_ipv4.h
+41
-14
include/net/netlabel.h
include/net/netlabel.h
+33
-18
net/ipv4/cipso_ipv4.c
net/ipv4/cipso_ipv4.c
+461
-195
net/ipv4/ip_options.c
net/ipv4/ip_options.c
+1
-1
net/netlabel/Makefile
net/netlabel/Makefile
+2
-1
net/netlabel/netlabel_addrlist.c
net/netlabel/netlabel_addrlist.c
+388
-0
net/netlabel/netlabel_addrlist.h
net/netlabel/netlabel_addrlist.h
+189
-0
net/netlabel/netlabel_cipso_v4.c
net/netlabel/netlabel_cipso_v4.c
+94
-42
net/netlabel/netlabel_cipso_v4.h
net/netlabel/netlabel_cipso_v4.h
+6
-4
net/netlabel/netlabel_domainhash.c
net/netlabel/netlabel_domainhash.c
+304
-89
net/netlabel/netlabel_domainhash.h
net/netlabel/netlabel_domainhash.h
+38
-2
net/netlabel/netlabel_kapi.c
net/netlabel/netlabel_kapi.c
+192
-80
net/netlabel/netlabel_mgmt.c
net/netlabel/netlabel_mgmt.c
+304
-106
net/netlabel/netlabel_mgmt.h
net/netlabel/netlabel_mgmt.h
+54
-5
net/netlabel/netlabel_unlabeled.c
net/netlabel/netlabel_unlabeled.c
+153
-303
security/selinux/hooks.c
security/selinux/hooks.c
+169
-60
security/selinux/include/netlabel.h
security/selinux/include/netlabel.h
+41
-3
security/selinux/include/objsec.h
security/selinux/include/objsec.h
+6
-3
security/selinux/netlabel.c
security/selinux/netlabel.c
+239
-41
security/selinux/ss/services.c
security/selinux/ss/services.c
+10
-3
security/smack/smack_lsm.c
security/smack/smack_lsm.c
+4
-1
security/smack/smackfs.c
security/smack/smackfs.c
+3
-1
未找到文件。
drivers/char/tpm/tpm.c
浏览文件 @
93db6286
...
...
@@ -954,72 +954,63 @@ EXPORT_SYMBOL_GPL(tpm_store_cancel);
/*
* Device file system interface to the TPM
*
* It's assured that the chip will be opened just once,
* by the check of is_open variable, which is protected
* by driver_lock.
*/
int
tpm_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
int
rc
=
0
,
minor
=
iminor
(
inode
);
int
minor
=
iminor
(
inode
);
struct
tpm_chip
*
chip
=
NULL
,
*
pos
;
lock_kernel
();
spin_lock
(
&
driver_lock
);
list_for_each_entry
(
pos
,
&
tpm_chip_list
,
list
)
{
rcu_read_lock
();
list_for_each_entry_rcu
(
pos
,
&
tpm_chip_list
,
list
)
{
if
(
pos
->
vendor
.
miscdev
.
minor
==
minor
)
{
chip
=
pos
;
get_device
(
chip
->
dev
);
break
;
}
}
rcu_read_unlock
();
if
(
chip
==
NULL
)
{
rc
=
-
ENODEV
;
goto
err_out
;
}
if
(
!
chip
)
return
-
ENODEV
;
if
(
chip
->
num_opens
)
{
if
(
test_and_set_bit
(
0
,
&
chip
->
is_open
)
)
{
dev_dbg
(
chip
->
dev
,
"Another process owns this TPM
\n
"
);
rc
=
-
EBUSY
;
goto
err_out
;
put_device
(
chip
->
dev
)
;
return
-
EBUSY
;
}
chip
->
num_opens
++
;
get_device
(
chip
->
dev
);
spin_unlock
(
&
driver_lock
);
chip
->
data_buffer
=
kmalloc
(
TPM_BUFSIZE
*
sizeof
(
u8
),
GFP_KERNEL
);
if
(
chip
->
data_buffer
==
NULL
)
{
c
hip
->
num_opens
--
;
c
lear_bit
(
0
,
&
chip
->
is_open
)
;
put_device
(
chip
->
dev
);
unlock_kernel
();
return
-
ENOMEM
;
}
atomic_set
(
&
chip
->
data_pending
,
0
);
file
->
private_data
=
chip
;
unlock_kernel
();
return
0
;
err_out:
spin_unlock
(
&
driver_lock
);
unlock_kernel
();
return
rc
;
}
EXPORT_SYMBOL_GPL
(
tpm_open
);
/*
* Called on file close
*/
int
tpm_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
tpm_chip
*
chip
=
file
->
private_data
;
del_singleshot_timer_sync
(
&
chip
->
user_read_timer
);
flush_scheduled_work
();
spin_lock
(
&
driver_lock
);
file
->
private_data
=
NULL
;
del_singleshot_timer_sync
(
&
chip
->
user_read_timer
);
atomic_set
(
&
chip
->
data_pending
,
0
);
chip
->
num_opens
--
;
put_device
(
chip
->
dev
);
kfree
(
chip
->
data_buffer
);
spin_unlock
(
&
driver_lock
);
clear_bit
(
0
,
&
chip
->
is_open
);
put_device
(
chip
->
dev
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
tpm_release
);
...
...
@@ -1093,13 +1084,11 @@ void tpm_remove_hardware(struct device *dev)
}
spin_lock
(
&
driver_lock
);
list_del
(
&
chip
->
list
);
list_del_rcu
(
&
chip
->
list
);
spin_unlock
(
&
driver_lock
);
synchronize_rcu
();
misc_deregister
(
&
chip
->
vendor
.
miscdev
);
sysfs_remove_group
(
&
dev
->
kobj
,
chip
->
vendor
.
attr_group
);
tpm_bios_log_teardown
(
chip
->
bios_dir
);
...
...
@@ -1144,25 +1133,33 @@ int tpm_pm_resume(struct device *dev)
}
EXPORT_SYMBOL_GPL
(
tpm_pm_resume
);
/* In case vendor provided release function, call it too.*/
void
tpm_dev_vendor_release
(
struct
tpm_chip
*
chip
)
{
if
(
chip
->
vendor
.
release
)
chip
->
vendor
.
release
(
chip
->
dev
);
clear_bit
(
chip
->
dev_num
,
dev_mask
);
kfree
(
chip
->
vendor
.
miscdev
.
name
);
}
EXPORT_SYMBOL_GPL
(
tpm_dev_vendor_release
);
/*
* Once all references to platform device are down to 0,
* release all allocated structures.
* In case vendor provided release function,
* call it too.
*/
static
void
tpm_dev_release
(
struct
device
*
dev
)
{
struct
tpm_chip
*
chip
=
dev_get_drvdata
(
dev
);
if
(
chip
->
vendor
.
release
)
chip
->
vendor
.
release
(
dev
);
tpm_dev_vendor_release
(
chip
);
chip
->
release
(
dev
);
clear_bit
(
chip
->
dev_num
,
dev_mask
);
kfree
(
chip
->
vendor
.
miscdev
.
name
);
kfree
(
chip
);
}
EXPORT_SYMBOL_GPL
(
tpm_dev_release
);
/*
* Called from tpm_<specific>.c probe function only for devices
...
...
@@ -1171,8 +1168,8 @@ static void tpm_dev_release(struct device *dev)
* upon errant exit from this function specific probe function should call
* pci_disable_device
*/
struct
tpm_chip
*
tpm_register_hardware
(
struct
device
*
dev
,
const
struct
tpm_vendor_specific
*
entry
)
struct
tpm_chip
*
tpm_register_hardware
(
struct
device
*
dev
,
const
struct
tpm_vendor_specific
*
entry
)
{
#define DEVNAME_SIZE 7
...
...
@@ -1231,21 +1228,20 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
return
NULL
;
}
spin_lock
(
&
driver_lock
);
list_add
(
&
chip
->
list
,
&
tpm_chip_list
);
spin_unlock
(
&
driver_lock
);
if
(
sysfs_create_group
(
&
dev
->
kobj
,
chip
->
vendor
.
attr_group
))
{
list_del
(
&
chip
->
list
);
misc_deregister
(
&
chip
->
vendor
.
miscdev
);
put_device
(
chip
->
dev
);
return
NULL
;
}
chip
->
bios_dir
=
tpm_bios_log_setup
(
devname
);
/* Make chip available */
spin_lock
(
&
driver_lock
);
list_add_rcu
(
&
chip
->
list
,
&
tpm_chip_list
);
spin_unlock
(
&
driver_lock
);
return
chip
;
}
EXPORT_SYMBOL_GPL
(
tpm_register_hardware
);
...
...
drivers/char/tpm/tpm.h
浏览文件 @
93db6286
...
...
@@ -90,7 +90,7 @@ struct tpm_chip {
struct
device
*
dev
;
/* Device stuff */
int
dev_num
;
/* /dev/tpm# */
int
num_opens
;
/* only one allowed */
unsigned
long
is_open
;
/* only one allowed */
int
time_expired
;
/* Data passed to and from the tpm via the read/write calls */
...
...
@@ -132,6 +132,7 @@ extern struct tpm_chip* tpm_register_hardware(struct device *,
const
struct
tpm_vendor_specific
*
);
extern
int
tpm_open
(
struct
inode
*
,
struct
file
*
);
extern
int
tpm_release
(
struct
inode
*
,
struct
file
*
);
extern
void
tpm_dev_vendor_release
(
struct
tpm_chip
*
);
extern
ssize_t
tpm_write
(
struct
file
*
,
const
char
__user
*
,
size_t
,
loff_t
*
);
extern
ssize_t
tpm_read
(
struct
file
*
,
char
__user
*
,
size_t
,
loff_t
*
);
...
...
drivers/char/tpm/tpm_tis.c
浏览文件 @
93db6286
...
...
@@ -630,12 +630,23 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
{
""
,
0
}
/* Terminator */
};
static
__devexit
void
tpm_tis_pnp_remove
(
struct
pnp_dev
*
dev
)
{
struct
tpm_chip
*
chip
=
pnp_get_drvdata
(
dev
);
tpm_dev_vendor_release
(
chip
);
kfree
(
chip
);
}
static
struct
pnp_driver
tis_pnp_driver
=
{
.
name
=
"tpm_tis"
,
.
id_table
=
tpm_pnp_tbl
,
.
probe
=
tpm_tis_pnp_init
,
.
suspend
=
tpm_tis_pnp_suspend
,
.
resume
=
tpm_tis_pnp_resume
,
.
remove
=
tpm_tis_pnp_remove
,
};
#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2
...
...
@@ -683,6 +694,7 @@ static void __exit cleanup_tis(void)
spin_lock
(
&
tis_lock
);
list_for_each_entry_safe
(
i
,
j
,
&
tis_chips
,
list
)
{
chip
=
to_tpm_chip
(
i
);
tpm_remove_hardware
(
chip
->
dev
);
iowrite32
(
~
TPM_GLOBAL_INT_ENABLE
&
ioread32
(
chip
->
vendor
.
iobase
+
TPM_INT_ENABLE
(
chip
->
vendor
.
...
...
@@ -694,9 +706,9 @@ static void __exit cleanup_tis(void)
free_irq
(
chip
->
vendor
.
irq
,
chip
);
iounmap
(
i
->
iobase
);
list_del
(
&
i
->
list
);
tpm_remove_hardware
(
chip
->
dev
);
}
spin_unlock
(
&
tis_lock
);
if
(
force
)
{
platform_device_unregister
(
pdev
);
driver_unregister
(
&
tis_drv
);
...
...
include/net/cipso_ipv4.h
浏览文件 @
93db6286
...
...
@@ -40,11 +40,12 @@
#include <linux/net.h>
#include <linux/skbuff.h>
#include <net/netlabel.h>
#include <asm/atomic.h>
/* known doi values */
#define CIPSO_V4_DOI_UNKNOWN 0x00000000
/* tag types */
/*
standard
tag types */
#define CIPSO_V4_TAG_INVALID 0
#define CIPSO_V4_TAG_RBITMAP 1
#define CIPSO_V4_TAG_ENUM 2
...
...
@@ -52,10 +53,14 @@
#define CIPSO_V4_TAG_PBITMAP 6
#define CIPSO_V4_TAG_FREEFORM 7
/* non-standard tag types (tags > 127) */
#define CIPSO_V4_TAG_LOCAL 128
/* doi mapping types */
#define CIPSO_V4_MAP_UNKNOWN 0
#define CIPSO_V4_MAP_
STD
1
#define CIPSO_V4_MAP_
TRANS
1
#define CIPSO_V4_MAP_PASS 2
#define CIPSO_V4_MAP_LOCAL 3
/* limits */
#define CIPSO_V4_MAX_REM_LVLS 255
...
...
@@ -79,10 +84,9 @@ struct cipso_v4_doi {
}
map
;
u8
tags
[
CIPSO_V4_TAG_MAXCNT
];
u32
valid
;
atomic_t
refcount
;
struct
list_head
list
;
struct
rcu_head
rcu
;
struct
list_head
dom_list
;
};
/* Standard CIPSO mapping table */
...
...
@@ -128,25 +132,26 @@ extern int cipso_v4_rbm_strictvalid;
#ifdef CONFIG_NETLABEL
int
cipso_v4_doi_add
(
struct
cipso_v4_doi
*
doi_def
);
int
cipso_v4_doi_remove
(
u32
doi
,
struct
netlbl_audit
*
audit_info
,
void
(
*
callback
)
(
struct
rcu_head
*
head
));
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
);
void
cipso_v4_doi_putdef
(
struct
cipso_v4_doi
*
doi_def
);
int
cipso_v4_doi_walk
(
u32
*
skip_cnt
,
int
(
*
callback
)
(
struct
cipso_v4_doi
*
doi_def
,
void
*
arg
),
void
*
cb_arg
);
int
cipso_v4_doi_domhsh_add
(
struct
cipso_v4_doi
*
doi_def
,
const
char
*
domain
);
int
cipso_v4_doi_domhsh_remove
(
struct
cipso_v4_doi
*
doi_def
,
const
char
*
domain
);
#else
static
inline
int
cipso_v4_doi_add
(
struct
cipso_v4_doi
*
doi_def
)
{
return
-
ENOSYS
;
}
static
inline
void
cipso_v4_doi_free
(
struct
cipso_v4_doi
*
doi_def
)
{
return
;
}
static
inline
int
cipso_v4_doi_remove
(
u32
doi
,
struct
netlbl_audit
*
audit_info
,
void
(
*
callback
)
(
struct
rcu_head
*
head
))
struct
netlbl_audit
*
audit_info
)
{
return
0
;
}
...
...
@@ -206,10 +211,15 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway);
int
cipso_v4_sock_setattr
(
struct
sock
*
sk
,
const
struct
cipso_v4_doi
*
doi_def
,
const
struct
netlbl_lsm_secattr
*
secattr
);
void
cipso_v4_sock_delattr
(
struct
sock
*
sk
);
int
cipso_v4_sock_getattr
(
struct
sock
*
sk
,
struct
netlbl_lsm_secattr
*
secattr
);
int
cipso_v4_skbuff_setattr
(
struct
sk_buff
*
skb
,
const
struct
cipso_v4_doi
*
doi_def
,
const
struct
netlbl_lsm_secattr
*
secattr
);
int
cipso_v4_skbuff_delattr
(
struct
sk_buff
*
skb
);
int
cipso_v4_skbuff_getattr
(
const
struct
sk_buff
*
skb
,
struct
netlbl_lsm_secattr
*
secattr
);
int
cipso_v4_validate
(
unsigned
char
**
option
);
int
cipso_v4_validate
(
const
struct
sk_buff
*
skb
,
unsigned
char
**
option
);
#else
static
inline
void
cipso_v4_error
(
struct
sk_buff
*
skb
,
int
error
,
...
...
@@ -225,19 +235,36 @@ static inline int cipso_v4_sock_setattr(struct sock *sk,
return
-
ENOSYS
;
}
static
inline
void
cipso_v4_sock_delattr
(
struct
sock
*
sk
)
{
}
static
inline
int
cipso_v4_sock_getattr
(
struct
sock
*
sk
,
struct
netlbl_lsm_secattr
*
secattr
)
{
return
-
ENOSYS
;
}
static
inline
int
cipso_v4_skbuff_setattr
(
struct
sk_buff
*
skb
,
const
struct
cipso_v4_doi
*
doi_def
,
const
struct
netlbl_lsm_secattr
*
secattr
)
{
return
-
ENOSYS
;
}
static
inline
int
cipso_v4_skbuff_delattr
(
struct
sk_buff
*
skb
)
{
return
-
ENOSYS
;
}
static
inline
int
cipso_v4_skbuff_getattr
(
const
struct
sk_buff
*
skb
,
struct
netlbl_lsm_secattr
*
secattr
)
{
return
-
ENOSYS
;
}
static
inline
int
cipso_v4_validate
(
unsigned
char
**
option
)
static
inline
int
cipso_v4_validate
(
const
struct
sk_buff
*
skb
,
unsigned
char
**
option
)
{
return
-
ENOSYS
;
}
...
...
include/net/netlabel.h
浏览文件 @
93db6286
...
...
@@ -9,7 +9,7 @@
*/
/*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
, 2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -72,8 +72,10 @@ struct cipso_v4_doi;
/* NetLabel NETLINK protocol version
* 1: initial version
* 2: added static labels for unlabeled connections
* 3: network selectors added to the NetLabel/LSM domain mapping and the
* CIPSO_V4_MAP_LOCAL CIPSO mapping was added
*/
#define NETLBL_PROTO_VERSION
2
#define NETLBL_PROTO_VERSION
3
/* NetLabel NETLINK types/families */
#define NETLBL_NLTYPE_NONE 0
...
...
@@ -87,6 +89,8 @@ struct cipso_v4_doi;
#define NETLBL_NLTYPE_CIPSOV6_NAME "NLBL_CIPSOv6"
#define NETLBL_NLTYPE_UNLABELED 5
#define NETLBL_NLTYPE_UNLABELED_NAME "NLBL_UNLBL"
#define NETLBL_NLTYPE_ADDRSELECT 6
#define NETLBL_NLTYPE_ADDRSELECT_NAME "NLBL_ADRSEL"
/*
* NetLabel - Kernel API for accessing the network packet label mappings.
...
...
@@ -200,7 +204,7 @@ struct netlbl_lsm_secattr {
u32
type
;
char
*
domain
;
struct
netlbl_lsm_cache
*
cache
;
union
{
struct
{
struct
{
struct
netlbl_lsm_secattr_catmap
*
cat
;
u32
lvl
;
...
...
@@ -352,12 +356,9 @@ static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr)
int
netlbl_cfg_map_del
(
const
char
*
domain
,
struct
netlbl_audit
*
audit_info
);
int
netlbl_cfg_unlbl_add_map
(
const
char
*
domain
,
struct
netlbl_audit
*
audit_info
);
int
netlbl_cfg_cipsov4_add
(
struct
cipso_v4_doi
*
doi_def
,
struct
netlbl_audit
*
audit_info
);
int
netlbl_cfg_cipsov4_add_map
(
struct
cipso_v4_doi
*
doi_def
,
const
char
*
domain
,
struct
netlbl_audit
*
audit_info
);
int
netlbl_cfg_cipsov4_del
(
u32
doi
,
struct
netlbl_audit
*
audit_info
);
/*
* LSM security attribute operations
...
...
@@ -380,12 +381,19 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
int
netlbl_enabled
(
void
);
int
netlbl_sock_setattr
(
struct
sock
*
sk
,
const
struct
netlbl_lsm_secattr
*
secattr
);
void
netlbl_sock_delattr
(
struct
sock
*
sk
);
int
netlbl_sock_getattr
(
struct
sock
*
sk
,
struct
netlbl_lsm_secattr
*
secattr
);
int
netlbl_conn_setattr
(
struct
sock
*
sk
,
struct
sockaddr
*
addr
,
const
struct
netlbl_lsm_secattr
*
secattr
);
int
netlbl_skbuff_setattr
(
struct
sk_buff
*
skb
,
u16
family
,
const
struct
netlbl_lsm_secattr
*
secattr
);
int
netlbl_skbuff_getattr
(
const
struct
sk_buff
*
skb
,
u16
family
,
struct
netlbl_lsm_secattr
*
secattr
);
void
netlbl_skbuff_err
(
struct
sk_buff
*
skb
,
int
error
);
void
netlbl_skbuff_err
(
struct
sk_buff
*
skb
,
int
error
,
int
gateway
);
/*
* LSM label mapping cache operations
...
...
@@ -404,22 +412,12 @@ static inline int netlbl_cfg_unlbl_add_map(const char *domain,
{
return
-
ENOSYS
;
}
static
inline
int
netlbl_cfg_cipsov4_add
(
struct
cipso_v4_doi
*
doi_def
,
struct
netlbl_audit
*
audit_info
)
{
return
-
ENOSYS
;
}
static
inline
int
netlbl_cfg_cipsov4_add_map
(
struct
cipso_v4_doi
*
doi_def
,
const
char
*
domain
,
struct
netlbl_audit
*
audit_info
)
{
return
-
ENOSYS
;
}
static
inline
int
netlbl_cfg_cipsov4_del
(
u32
doi
,
struct
netlbl_audit
*
audit_info
)
{
return
-
ENOSYS
;
}
static
inline
int
netlbl_secattr_catmap_walk
(
struct
netlbl_lsm_secattr_catmap
*
catmap
,
u32
offset
)
...
...
@@ -456,18 +454,35 @@ static inline int netlbl_sock_setattr(struct sock *sk,
{
return
-
ENOSYS
;
}
static
inline
void
netlbl_sock_delattr
(
struct
sock
*
sk
)
{
}
static
inline
int
netlbl_sock_getattr
(
struct
sock
*
sk
,
struct
netlbl_lsm_secattr
*
secattr
)
{
return
-
ENOSYS
;
}
static
inline
int
netlbl_conn_setattr
(
struct
sock
*
sk
,
struct
sockaddr
*
addr
,
const
struct
netlbl_lsm_secattr
*
secattr
)
{
return
-
ENOSYS
;
}
static
inline
int
netlbl_skbuff_setattr
(
struct
sk_buff
*
skb
,
u16
family
,
const
struct
netlbl_lsm_secattr
*
secattr
)
{
return
-
ENOSYS
;
}
static
inline
int
netlbl_skbuff_getattr
(
const
struct
sk_buff
*
skb
,
u16
family
,
struct
netlbl_lsm_secattr
*
secattr
)
{
return
-
ENOSYS
;
}
static
inline
void
netlbl_skbuff_err
(
struct
sk_buff
*
skb
,
int
error
)
static
inline
void
netlbl_skbuff_err
(
struct
sk_buff
*
skb
,
int
error
,
int
gateway
)
{
return
;
}
...
...
net/ipv4/cipso_ipv4.c
浏览文件 @
93db6286
此差异已折叠。
点击以展开。
net/ipv4/ip_options.c
浏览文件 @
93db6286
...
...
@@ -438,7 +438,7 @@ int ip_options_compile(struct net *net,
goto
error
;
}
opt
->
cipso
=
optptr
-
iph
;
if
(
cipso_v4_validate
(
&
optptr
))
{
if
(
cipso_v4_validate
(
skb
,
&
optptr
))
{
pp_ptr
=
optptr
;
goto
error
;
}
...
...
net/netlabel/Makefile
浏览文件 @
93db6286
...
...
@@ -5,7 +5,8 @@
#
# base objects
obj-y
:=
netlabel_user.o netlabel_kapi.o netlabel_domainhash.o
obj-y
:=
netlabel_user.o netlabel_kapi.o
obj-y
+=
netlabel_domainhash.o netlabel_addrlist.o
# management objects
obj-y
+=
netlabel_mgmt.o
...
...
net/netlabel/netlabel_addrlist.c
0 → 100644
浏览文件 @
93db6286
/*
* NetLabel Network Address Lists
*
* This file contains network address list functions used to manage ordered
* lists of network addresses for use by the NetLabel subsystem. The NetLabel
* system manages static and dynamic label mappings for network protocols such
* as CIPSO and RIPSO.
*
* Author: Paul Moore <paul.moore@hp.com>
*
*/
/*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/types.h>
#include <linux/rcupdate.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <linux/audit.h>
#include "netlabel_addrlist.h"
/*
* Address List Functions
*/
/**
* netlbl_af4list_search - Search for a matching IPv4 address entry
* @addr: IPv4 address
* @head: the list head
*
* Description:
* Searches the IPv4 address list given by @head. If a matching address entry
* is found it is returned, otherwise NULL is returned. The caller is
* responsible for calling the rcu_read_[un]lock() functions.
*
*/
struct
netlbl_af4list
*
netlbl_af4list_search
(
__be32
addr
,
struct
list_head
*
head
)
{
struct
netlbl_af4list
*
iter
;
list_for_each_entry_rcu
(
iter
,
head
,
list
)
if
(
iter
->
valid
&&
(
addr
&
iter
->
mask
)
==
iter
->
addr
)
return
iter
;
return
NULL
;
}
/**
* netlbl_af4list_search_exact - Search for an exact IPv4 address entry
* @addr: IPv4 address
* @mask: IPv4 address mask
* @head: the list head
*
* Description:
* Searches the IPv4 address list given by @head. If an exact match if found
* it is returned, otherwise NULL is returned. The caller is responsible for
* calling the rcu_read_[un]lock() functions.
*
*/
struct
netlbl_af4list
*
netlbl_af4list_search_exact
(
__be32
addr
,
__be32
mask
,
struct
list_head
*
head
)
{
struct
netlbl_af4list
*
iter
;
list_for_each_entry_rcu
(
iter
,
head
,
list
)
if
(
iter
->
valid
&&
iter
->
addr
==
addr
&&
iter
->
mask
==
mask
)
return
iter
;
return
NULL
;
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
/**
* netlbl_af6list_search - Search for a matching IPv6 address entry
* @addr: IPv6 address
* @head: the list head
*
* Description:
* Searches the IPv6 address list given by @head. If a matching address entry
* is found it is returned, otherwise NULL is returned. The caller is
* responsible for calling the rcu_read_[un]lock() functions.
*
*/
struct
netlbl_af6list
*
netlbl_af6list_search
(
const
struct
in6_addr
*
addr
,
struct
list_head
*
head
)
{
struct
netlbl_af6list
*
iter
;
list_for_each_entry_rcu
(
iter
,
head
,
list
)
if
(
iter
->
valid
&&
ipv6_masked_addr_cmp
(
&
iter
->
addr
,
&
iter
->
mask
,
addr
)
==
0
)
return
iter
;
return
NULL
;
}
/**
* netlbl_af6list_search_exact - Search for an exact IPv6 address entry
* @addr: IPv6 address
* @mask: IPv6 address mask
* @head: the list head
*
* Description:
* Searches the IPv6 address list given by @head. If an exact match if found
* it is returned, otherwise NULL is returned. The caller is responsible for
* calling the rcu_read_[un]lock() functions.
*
*/
struct
netlbl_af6list
*
netlbl_af6list_search_exact
(
const
struct
in6_addr
*
addr
,
const
struct
in6_addr
*
mask
,
struct
list_head
*
head
)
{
struct
netlbl_af6list
*
iter
;
list_for_each_entry_rcu
(
iter
,
head
,
list
)
if
(
iter
->
valid
&&
ipv6_addr_equal
(
&
iter
->
addr
,
addr
)
&&
ipv6_addr_equal
(
&
iter
->
mask
,
mask
))
return
iter
;
return
NULL
;
}
#endif
/* IPv6 */
/**
* netlbl_af4list_add - Add a new IPv4 address entry to a list
* @entry: address entry
* @head: the list head
*
* Description:
* Add a new address entry to the list pointed to by @head. On success zero is
* returned, otherwise a negative value is returned. The caller is responsible
* for calling the necessary locking functions.
*
*/
int
netlbl_af4list_add
(
struct
netlbl_af4list
*
entry
,
struct
list_head
*
head
)
{
struct
netlbl_af4list
*
iter
;
iter
=
netlbl_af4list_search
(
entry
->
addr
,
head
);
if
(
iter
!=
NULL
&&
iter
->
addr
==
entry
->
addr
&&
iter
->
mask
==
entry
->
mask
)
return
-
EEXIST
;
/* in order to speed up address searches through the list (the common
* case) we need to keep the list in order based on the size of the
* address mask such that the entry with the widest mask (smallest
* numerical value) appears first in the list */
list_for_each_entry_rcu
(
iter
,
head
,
list
)
if
(
iter
->
valid
&&
ntohl
(
entry
->
mask
)
>
ntohl
(
iter
->
mask
))
{
__list_add_rcu
(
&
entry
->
list
,
iter
->
list
.
prev
,
&
iter
->
list
);
return
0
;
}
list_add_tail_rcu
(
&
entry
->
list
,
head
);
return
0
;
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
/**
* netlbl_af6list_add - Add a new IPv6 address entry to a list
* @entry: address entry
* @head: the list head
*
* Description:
* Add a new address entry to the list pointed to by @head. On success zero is
* returned, otherwise a negative value is returned. The caller is responsible
* for calling the necessary locking functions.
*
*/
int
netlbl_af6list_add
(
struct
netlbl_af6list
*
entry
,
struct
list_head
*
head
)
{
struct
netlbl_af6list
*
iter
;
iter
=
netlbl_af6list_search
(
&
entry
->
addr
,
head
);
if
(
iter
!=
NULL
&&
ipv6_addr_equal
(
&
iter
->
addr
,
&
entry
->
addr
)
&&
ipv6_addr_equal
(
&
iter
->
mask
,
&
entry
->
mask
))
return
-
EEXIST
;
/* in order to speed up address searches through the list (the common
* case) we need to keep the list in order based on the size of the
* address mask such that the entry with the widest mask (smallest
* numerical value) appears first in the list */
list_for_each_entry_rcu
(
iter
,
head
,
list
)
if
(
iter
->
valid
&&
ipv6_addr_cmp
(
&
entry
->
mask
,
&
iter
->
mask
)
>
0
)
{
__list_add_rcu
(
&
entry
->
list
,
iter
->
list
.
prev
,
&
iter
->
list
);
return
0
;
}
list_add_tail_rcu
(
&
entry
->
list
,
head
);
return
0
;
}
#endif
/* IPv6 */
/**
* netlbl_af4list_remove_entry - Remove an IPv4 address entry
* @entry: address entry
*
* Description:
* Remove the specified IP address entry. The caller is responsible for
* calling the necessary locking functions.
*
*/
void
netlbl_af4list_remove_entry
(
struct
netlbl_af4list
*
entry
)
{
entry
->
valid
=
0
;
list_del_rcu
(
&
entry
->
list
);
}
/**
* netlbl_af4list_remove - Remove an IPv4 address entry
* @addr: IP address
* @mask: IP address mask
* @head: the list head
*
* Description:
* Remove an IP address entry from the list pointed to by @head. Returns the
* entry on success, NULL on failure. The caller is responsible for calling
* the necessary locking functions.
*
*/
struct
netlbl_af4list
*
netlbl_af4list_remove
(
__be32
addr
,
__be32
mask
,
struct
list_head
*
head
)
{
struct
netlbl_af4list
*
entry
;
entry
=
netlbl_af4list_search
(
addr
,
head
);
if
(
entry
!=
NULL
&&
entry
->
addr
==
addr
&&
entry
->
mask
==
mask
)
{
netlbl_af4list_remove_entry
(
entry
);
return
entry
;
}
return
NULL
;
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
/**
* netlbl_af6list_remove_entry - Remove an IPv6 address entry
* @entry: address entry
*
* Description:
* Remove the specified IP address entry. The caller is responsible for
* calling the necessary locking functions.
*
*/
void
netlbl_af6list_remove_entry
(
struct
netlbl_af6list
*
entry
)
{
entry
->
valid
=
0
;
list_del_rcu
(
&
entry
->
list
);
}
/**
* netlbl_af6list_remove - Remove an IPv6 address entry
* @addr: IP address
* @mask: IP address mask
* @head: the list head
*
* Description:
* Remove an IP address entry from the list pointed to by @head. Returns the
* entry on success, NULL on failure. The caller is responsible for calling
* the necessary locking functions.
*
*/
struct
netlbl_af6list
*
netlbl_af6list_remove
(
const
struct
in6_addr
*
addr
,
const
struct
in6_addr
*
mask
,
struct
list_head
*
head
)
{
struct
netlbl_af6list
*
entry
;
entry
=
netlbl_af6list_search
(
addr
,
head
);
if
(
entry
!=
NULL
&&
ipv6_addr_equal
(
&
entry
->
addr
,
addr
)
&&
ipv6_addr_equal
(
&
entry
->
mask
,
mask
))
{
netlbl_af6list_remove_entry
(
entry
);
return
entry
;
}
return
NULL
;
}
#endif
/* IPv6 */
/*
* Audit Helper Functions
*/
/**
* netlbl_af4list_audit_addr - Audit an IPv4 address
* @audit_buf: audit buffer
* @src: true if source address, false if destination
* @dev: network interface
* @addr: IP address
* @mask: IP address mask
*
* Description:
* Write the IPv4 address and address mask, if necessary, to @audit_buf.
*
*/
void
netlbl_af4list_audit_addr
(
struct
audit_buffer
*
audit_buf
,
int
src
,
const
char
*
dev
,
__be32
addr
,
__be32
mask
)
{
u32
mask_val
=
ntohl
(
mask
);
char
*
dir
=
(
src
?
"src"
:
"dst"
);
if
(
dev
!=
NULL
)
audit_log_format
(
audit_buf
,
" netif=%s"
,
dev
);
audit_log_format
(
audit_buf
,
" %s="
NIPQUAD_FMT
,
dir
,
NIPQUAD
(
addr
));
if
(
mask_val
!=
0xffffffff
)
{
u32
mask_len
=
0
;
while
(
mask_val
>
0
)
{
mask_val
<<=
1
;
mask_len
++
;
}
audit_log_format
(
audit_buf
,
" %s_prefixlen=%d"
,
dir
,
mask_len
);
}
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
/**
* netlbl_af6list_audit_addr - Audit an IPv6 address
* @audit_buf: audit buffer
* @src: true if source address, false if destination
* @dev: network interface
* @addr: IP address
* @mask: IP address mask
*
* Description:
* Write the IPv6 address and address mask, if necessary, to @audit_buf.
*
*/
void
netlbl_af6list_audit_addr
(
struct
audit_buffer
*
audit_buf
,
int
src
,
const
char
*
dev
,
const
struct
in6_addr
*
addr
,
const
struct
in6_addr
*
mask
)
{
char
*
dir
=
(
src
?
"src"
:
"dst"
);
if
(
dev
!=
NULL
)
audit_log_format
(
audit_buf
,
" netif=%s"
,
dev
);
audit_log_format
(
audit_buf
,
" %s="
NIP6_FMT
,
dir
,
NIP6
(
*
addr
));
if
(
ntohl
(
mask
->
s6_addr32
[
3
])
!=
0xffffffff
)
{
u32
mask_len
=
0
;
u32
mask_val
;
int
iter
=
-
1
;
while
(
ntohl
(
mask
->
s6_addr32
[
++
iter
])
==
0xffffffff
)
mask_len
+=
32
;
mask_val
=
ntohl
(
mask
->
s6_addr32
[
iter
]);
while
(
mask_val
>
0
)
{
mask_val
<<=
1
;
mask_len
++
;
}
audit_log_format
(
audit_buf
,
" %s_prefixlen=%d"
,
dir
,
mask_len
);
}
}
#endif
/* IPv6 */
net/netlabel/netlabel_addrlist.h
0 → 100644
浏览文件 @
93db6286
/*
* NetLabel Network Address Lists
*
* This file contains network address list functions used to manage ordered
* lists of network addresses for use by the NetLabel subsystem. The NetLabel
* system manages static and dynamic label mappings for network protocols such
* as CIPSO and RIPSO.
*
* Author: Paul Moore <paul.moore@hp.com>
*
*/
/*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef _NETLABEL_ADDRLIST_H
#define _NETLABEL_ADDRLIST_H
#include <linux/types.h>
#include <linux/rcupdate.h>
#include <linux/list.h>
#include <linux/in6.h>
#include <linux/audit.h>
/**
* struct netlbl_af4list - NetLabel IPv4 address list
* @addr: IPv4 address
* @mask: IPv4 address mask
* @valid: valid flag
* @list: list structure, used internally
*/
struct
netlbl_af4list
{
__be32
addr
;
__be32
mask
;
u32
valid
;
struct
list_head
list
;
};
/**
* struct netlbl_af6list - NetLabel IPv6 address list
* @addr: IPv6 address
* @mask: IPv6 address mask
* @valid: valid flag
* @list: list structure, used internally
*/
struct
netlbl_af6list
{
struct
in6_addr
addr
;
struct
in6_addr
mask
;
u32
valid
;
struct
list_head
list
;
};
#define __af4list_entry(ptr) container_of(ptr, struct netlbl_af4list, list)
static
inline
struct
netlbl_af4list
*
__af4list_valid
(
struct
list_head
*
s
,
struct
list_head
*
h
)
{
struct
list_head
*
i
=
s
;
struct
netlbl_af4list
*
n
=
__af4list_entry
(
s
);
while
(
i
!=
h
&&
!
n
->
valid
)
{
i
=
i
->
next
;
n
=
__af4list_entry
(
i
);
}
return
n
;
}
static
inline
struct
netlbl_af4list
*
__af4list_valid_rcu
(
struct
list_head
*
s
,
struct
list_head
*
h
)
{
struct
list_head
*
i
=
s
;
struct
netlbl_af4list
*
n
=
__af4list_entry
(
s
);
while
(
i
!=
h
&&
!
n
->
valid
)
{
i
=
rcu_dereference
(
i
->
next
);
n
=
__af4list_entry
(
i
);
}
return
n
;
}
#define netlbl_af4list_foreach(iter, head) \
for (iter = __af4list_valid((head)->next, head); \
prefetch(iter->list.next), &iter->list != (head); \
iter = __af4list_valid(iter->list.next, head))
#define netlbl_af4list_foreach_rcu(iter, head) \
for (iter = __af4list_valid_rcu((head)->next, head); \
prefetch(iter->list.next), &iter->list != (head); \
iter = __af4list_valid_rcu(iter->list.next, head))
#define netlbl_af4list_foreach_safe(iter, tmp, head) \
for (iter = __af4list_valid((head)->next, head), \
tmp = __af4list_valid(iter->list.next, head); \
&iter->list != (head); \
iter = tmp, tmp = __af4list_valid(iter->list.next, head))
int
netlbl_af4list_add
(
struct
netlbl_af4list
*
entry
,
struct
list_head
*
head
);
struct
netlbl_af4list
*
netlbl_af4list_remove
(
__be32
addr
,
__be32
mask
,
struct
list_head
*
head
);
void
netlbl_af4list_remove_entry
(
struct
netlbl_af4list
*
entry
);
struct
netlbl_af4list
*
netlbl_af4list_search
(
__be32
addr
,
struct
list_head
*
head
);
struct
netlbl_af4list
*
netlbl_af4list_search_exact
(
__be32
addr
,
__be32
mask
,
struct
list_head
*
head
);
void
netlbl_af4list_audit_addr
(
struct
audit_buffer
*
audit_buf
,
int
src
,
const
char
*
dev
,
__be32
addr
,
__be32
mask
);
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#define __af6list_entry(ptr) container_of(ptr, struct netlbl_af6list, list)
static
inline
struct
netlbl_af6list
*
__af6list_valid
(
struct
list_head
*
s
,
struct
list_head
*
h
)
{
struct
list_head
*
i
=
s
;
struct
netlbl_af6list
*
n
=
__af6list_entry
(
s
);
while
(
i
!=
h
&&
!
n
->
valid
)
{
i
=
i
->
next
;
n
=
__af6list_entry
(
i
);
}
return
n
;
}
static
inline
struct
netlbl_af6list
*
__af6list_valid_rcu
(
struct
list_head
*
s
,
struct
list_head
*
h
)
{
struct
list_head
*
i
=
s
;
struct
netlbl_af6list
*
n
=
__af6list_entry
(
s
);
while
(
i
!=
h
&&
!
n
->
valid
)
{
i
=
rcu_dereference
(
i
->
next
);
n
=
__af6list_entry
(
i
);
}
return
n
;
}
#define netlbl_af6list_foreach(iter, head) \
for (iter = __af6list_valid((head)->next, head); \
prefetch(iter->list.next), &iter->list != (head); \
iter = __af6list_valid(iter->list.next, head))
#define netlbl_af6list_foreach_rcu(iter, head) \
for (iter = __af6list_valid_rcu((head)->next, head); \
prefetch(iter->list.next), &iter->list != (head); \
iter = __af6list_valid_rcu(iter->list.next, head))
#define netlbl_af6list_foreach_safe(iter, tmp, head) \
for (iter = __af6list_valid((head)->next, head), \
tmp = __af6list_valid(iter->list.next, head); \
&iter->list != (head); \
iter = tmp, tmp = __af6list_valid(iter->list.next, head))
int
netlbl_af6list_add
(
struct
netlbl_af6list
*
entry
,
struct
list_head
*
head
);
struct
netlbl_af6list
*
netlbl_af6list_remove
(
const
struct
in6_addr
*
addr
,
const
struct
in6_addr
*
mask
,
struct
list_head
*
head
);
void
netlbl_af6list_remove_entry
(
struct
netlbl_af6list
*
entry
);
struct
netlbl_af6list
*
netlbl_af6list_search
(
const
struct
in6_addr
*
addr
,
struct
list_head
*
head
);
struct
netlbl_af6list
*
netlbl_af6list_search_exact
(
const
struct
in6_addr
*
addr
,
const
struct
in6_addr
*
mask
,
struct
list_head
*
head
);
void
netlbl_af6list_audit_addr
(
struct
audit_buffer
*
audit_buf
,
int
src
,
const
char
*
dev
,
const
struct
in6_addr
*
addr
,
const
struct
in6_addr
*
mask
);
#endif
/* IPV6 */
#endif
net/netlabel/netlabel_cipso_v4.c
浏览文件 @
93db6286
...
...
@@ -43,6 +43,7 @@
#include "netlabel_user.h"
#include "netlabel_cipso_v4.h"
#include "netlabel_mgmt.h"
#include "netlabel_domainhash.h"
/* Argument struct for cipso_v4_doi_walk() */
struct
netlbl_cipsov4_doiwalk_arg
{
...
...
@@ -51,6 +52,12 @@ struct netlbl_cipsov4_doiwalk_arg {
u32
seq
;
};
/* Argument struct for netlbl_domhsh_walk() */
struct
netlbl_domhsh_walk_arg
{
struct
netlbl_audit
*
audit_info
;
u32
doi
;
};
/* NetLabel Generic NETLINK CIPSOv4 family */
static
struct
genl_family
netlbl_cipsov4_gnl_family
=
{
.
id
=
GENL_ID_GENERATE
,
...
...
@@ -80,32 +87,6 @@ static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1
* Helper Functions
*/
/**
* netlbl_cipsov4_doi_free - Frees a CIPSO V4 DOI definition
* @entry: the entry's RCU field
*
* Description:
* This function is designed to be used as a callback to the call_rcu()
* function so that the memory allocated to the DOI definition can be released
* safely.
*
*/
void
netlbl_cipsov4_doi_free
(
struct
rcu_head
*
entry
)
{
struct
cipso_v4_doi
*
ptr
;
ptr
=
container_of
(
entry
,
struct
cipso_v4_doi
,
rcu
);
switch
(
ptr
->
type
)
{
case
CIPSO_V4_MAP_STD
:
kfree
(
ptr
->
map
.
std
->
lvl
.
cipso
);
kfree
(
ptr
->
map
.
std
->
lvl
.
local
);
kfree
(
ptr
->
map
.
std
->
cat
.
cipso
);
kfree
(
ptr
->
map
.
std
->
cat
.
local
);
break
;
}
kfree
(
ptr
);
}
/**
* netlbl_cipsov4_add_common - Parse the common sections of a ADD message
* @info: the Generic NETLINK info block
...
...
@@ -151,9 +132,9 @@ static int netlbl_cipsov4_add_common(struct genl_info *info,
* @info: the Generic NETLINK info block
*
* Description:
* Create a new CIPSO_V4_MAP_
STD DOI definition based on the given ADD message
*
and add it to the CIPSO V4 engine. Return zero on success and non-zero on
* error.
* Create a new CIPSO_V4_MAP_
TRANS DOI definition based on the given ADD
*
message and add it to the CIPSO V4 engine. Return zero on success and
*
non-zero on
error.
*
*/
static
int
netlbl_cipsov4_add_std
(
struct
genl_info
*
info
)
...
...
@@ -183,7 +164,7 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
ret_val
=
-
ENOMEM
;
goto
add_std_failure
;
}
doi_def
->
type
=
CIPSO_V4_MAP_
STD
;
doi_def
->
type
=
CIPSO_V4_MAP_
TRANS
;
ret_val
=
netlbl_cipsov4_add_common
(
info
,
doi_def
);
if
(
ret_val
!=
0
)
...
...
@@ -342,7 +323,7 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
add_std_failure:
if
(
doi_def
)
netlbl_cipsov4_doi_free
(
&
doi_def
->
rcu
);
cipso_v4_doi_free
(
doi_def
);
return
ret_val
;
}
...
...
@@ -379,7 +360,44 @@ static int netlbl_cipsov4_add_pass(struct genl_info *info)
return
0
;
add_pass_failure:
netlbl_cipsov4_doi_free
(
&
doi_def
->
rcu
);
cipso_v4_doi_free
(
doi_def
);
return
ret_val
;
}
/**
* netlbl_cipsov4_add_local - Adds a CIPSO V4 DOI definition
* @info: the Generic NETLINK info block
*
* Description:
* Create a new CIPSO_V4_MAP_LOCAL DOI definition based on the given ADD
* message and add it to the CIPSO V4 engine. Return zero on success and
* non-zero on error.
*
*/
static
int
netlbl_cipsov4_add_local
(
struct
genl_info
*
info
)
{
int
ret_val
;
struct
cipso_v4_doi
*
doi_def
=
NULL
;
if
(
!
info
->
attrs
[
NLBL_CIPSOV4_A_TAGLST
])
return
-
EINVAL
;
doi_def
=
kmalloc
(
sizeof
(
*
doi_def
),
GFP_KERNEL
);
if
(
doi_def
==
NULL
)
return
-
ENOMEM
;
doi_def
->
type
=
CIPSO_V4_MAP_LOCAL
;
ret_val
=
netlbl_cipsov4_add_common
(
info
,
doi_def
);
if
(
ret_val
!=
0
)
goto
add_local_failure
;
ret_val
=
cipso_v4_doi_add
(
doi_def
);
if
(
ret_val
!=
0
)
goto
add_local_failure
;
return
0
;
add_local_failure:
cipso_v4_doi_free
(
doi_def
);
return
ret_val
;
}
...
...
@@ -412,14 +430,18 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info)
type
=
nla_get_u32
(
info
->
attrs
[
NLBL_CIPSOV4_A_MTYPE
]);
switch
(
type
)
{
case
CIPSO_V4_MAP_
STD
:
type_str
=
"
std
"
;
case
CIPSO_V4_MAP_
TRANS
:
type_str
=
"
trans
"
;
ret_val
=
netlbl_cipsov4_add_std
(
info
);
break
;
case
CIPSO_V4_MAP_PASS
:
type_str
=
"pass"
;
ret_val
=
netlbl_cipsov4_add_pass
(
info
);
break
;
case
CIPSO_V4_MAP_LOCAL
:
type_str
=
"local"
;
ret_val
=
netlbl_cipsov4_add_local
(
info
);
break
;
}
if
(
ret_val
==
0
)
atomic_inc
(
&
netlabel_mgmt_protocount
);
...
...
@@ -491,7 +513,7 @@ static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info)
doi_def
=
cipso_v4_doi_getdef
(
doi
);
if
(
doi_def
==
NULL
)
{
ret_val
=
-
EINVAL
;
goto
list_failure
;
goto
list_failure
_lock
;
}
ret_val
=
nla_put_u32
(
ans_skb
,
NLBL_CIPSOV4_A_MTYPE
,
doi_def
->
type
);
...
...
@@ -516,7 +538,7 @@ static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info)
nla_nest_end
(
ans_skb
,
nla_a
);
switch
(
doi_def
->
type
)
{
case
CIPSO_V4_MAP_
STD
:
case
CIPSO_V4_MAP_
TRANS
:
nla_a
=
nla_nest_start
(
ans_skb
,
NLBL_CIPSOV4_A_MLSLVLLST
);
if
(
nla_a
==
NULL
)
{
ret_val
=
-
ENOMEM
;
...
...
@@ -655,7 +677,7 @@ static int netlbl_cipsov4_listall(struct sk_buff *skb,
struct
netlink_callback
*
cb
)
{
struct
netlbl_cipsov4_doiwalk_arg
cb_arg
;
int
doi_skip
=
cb
->
args
[
0
];
u32
doi_skip
=
cb
->
args
[
0
];
cb_arg
.
nl_cb
=
cb
;
cb_arg
.
skb
=
skb
;
...
...
@@ -667,6 +689,29 @@ static int netlbl_cipsov4_listall(struct sk_buff *skb,
return
skb
->
len
;
}
/**
* netlbl_cipsov4_remove_cb - netlbl_cipsov4_remove() callback for REMOVE
* @entry: LSM domain mapping entry
* @arg: the netlbl_domhsh_walk_arg structure
*
* Description:
* This function is intended for use by netlbl_cipsov4_remove() as the callback
* for the netlbl_domhsh_walk() function; it removes LSM domain map entries
* which are associated with the CIPSO DOI specified in @arg. Returns zero on
* success, negative values on failure.
*
*/
static
int
netlbl_cipsov4_remove_cb
(
struct
netlbl_dom_map
*
entry
,
void
*
arg
)
{
struct
netlbl_domhsh_walk_arg
*
cb_arg
=
arg
;
if
(
entry
->
type
==
NETLBL_NLTYPE_CIPSOV4
&&
entry
->
type_def
.
cipsov4
->
doi
==
cb_arg
->
doi
)
return
netlbl_domhsh_remove_entry
(
entry
,
cb_arg
->
audit_info
);
return
0
;
}
/**
* netlbl_cipsov4_remove - Handle a REMOVE message
* @skb: the NETLINK buffer
...
...
@@ -681,8 +726,11 @@ 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
;
if
(
!
info
->
attrs
[
NLBL_CIPSOV4_A_DOI
])
return
-
EINVAL
;
...
...
@@ -690,11 +738,15 @@ static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
doi
=
nla_get_u32
(
info
->
attrs
[
NLBL_CIPSOV4_A_DOI
]);
netlbl_netlink_auditinfo
(
skb
,
&
audit_info
);
ret_val
=
cipso_v4_doi_remove
(
doi
,
&
audit_info
,
netlbl_cipsov4_doi_free
);
if
(
ret_val
==
0
)
atomic_dec
(
&
netlabel_mgmt_protocount
);
cb_arg
.
doi
=
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
);
if
(
ret_val
==
0
)
atomic_dec
(
&
netlabel_mgmt_protocount
);
}
audit_buf
=
netlbl_audit_start_common
(
AUDIT_MAC_CIPSOV4_DEL
,
&
audit_info
);
...
...
net/netlabel/netlabel_cipso_v4.h
浏览文件 @
93db6286
...
...
@@ -45,12 +45,13 @@
* NLBL_CIPSOV4_A_MTYPE
* NLBL_CIPSOV4_A_TAGLST
*
* If using CIPSO_V4_MAP_
STD
the following attributes are required:
* If using CIPSO_V4_MAP_
TRANS
the following attributes are required:
*
* NLBL_CIPSOV4_A_MLSLVLLST
* NLBL_CIPSOV4_A_MLSCATLST
*
* If using CIPSO_V4_MAP_PASS no additional attributes are required.
* If using CIPSO_V4_MAP_PASS or CIPSO_V4_MAP_LOCAL no additional attributes
* are required.
*
* o REMOVE:
* Sent by an application to remove a specific DOI mapping table from the
...
...
@@ -76,12 +77,13 @@
* NLBL_CIPSOV4_A_MTYPE
* NLBL_CIPSOV4_A_TAGLST
*
* If using CIPSO_V4_MAP_
STD
the following attributes are required:
* If using CIPSO_V4_MAP_
TRANS
the following attributes are required:
*
* NLBL_CIPSOV4_A_MLSLVLLST
* NLBL_CIPSOV4_A_MLSCATLST
*
* If using CIPSO_V4_MAP_PASS no additional attributes are required.
* If using CIPSO_V4_MAP_PASS or CIPSO_V4_MAP_LOCAL no additional attributes
* are required.
*
* o LISTALL:
* This message is sent by an application to list the valid DOIs on the
...
...
net/netlabel/netlabel_domainhash.c
浏览文件 @
93db6286
...
...
@@ -11,7 +11,7 @@
*/
/*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
, 2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -40,6 +40,7 @@
#include <asm/bug.h>
#include "netlabel_mgmt.h"
#include "netlabel_addrlist.h"
#include "netlabel_domainhash.h"
#include "netlabel_user.h"
...
...
@@ -72,8 +73,28 @@ static struct netlbl_dom_map *netlbl_domhsh_def = NULL;
static
void
netlbl_domhsh_free_entry
(
struct
rcu_head
*
entry
)
{
struct
netlbl_dom_map
*
ptr
;
struct
netlbl_af4list
*
iter4
;
struct
netlbl_af4list
*
tmp4
;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct
netlbl_af6list
*
iter6
;
struct
netlbl_af6list
*
tmp6
;
#endif
/* IPv6 */
ptr
=
container_of
(
entry
,
struct
netlbl_dom_map
,
rcu
);
if
(
ptr
->
type
==
NETLBL_NLTYPE_ADDRSELECT
)
{
netlbl_af4list_foreach_safe
(
iter4
,
tmp4
,
&
ptr
->
type_def
.
addrsel
->
list4
)
{
netlbl_af4list_remove_entry
(
iter4
);
kfree
(
netlbl_domhsh_addr4_entry
(
iter4
));
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
netlbl_af6list_foreach_safe
(
iter6
,
tmp6
,
&
ptr
->
type_def
.
addrsel
->
list6
)
{
netlbl_af6list_remove_entry
(
iter6
);
kfree
(
netlbl_domhsh_addr6_entry
(
iter6
));
}
#endif
/* IPv6 */
}
kfree
(
ptr
->
domain
);
kfree
(
ptr
);
}
...
...
@@ -115,13 +136,13 @@ static u32 netlbl_domhsh_hash(const char *key)
static
struct
netlbl_dom_map
*
netlbl_domhsh_search
(
const
char
*
domain
)
{
u32
bkt
;
struct
list_head
*
bkt_list
;
struct
netlbl_dom_map
*
iter
;
if
(
domain
!=
NULL
)
{
bkt
=
netlbl_domhsh_hash
(
domain
);
list_for_each_entry_rcu
(
iter
,
&
rcu_dereference
(
netlbl_domhsh
)
->
tbl
[
bkt
],
list
)
bkt_list
=
&
rcu_dereference
(
netlbl_domhsh
)
->
tbl
[
bkt
];
list_for_each_entry_rcu
(
iter
,
bkt_list
,
list
)
if
(
iter
->
valid
&&
strcmp
(
iter
->
domain
,
domain
)
==
0
)
return
iter
;
}
...
...
@@ -156,6 +177,69 @@ static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain)
return
entry
;
}
/**
* netlbl_domhsh_audit_add - Generate an audit entry for an add event
* @entry: the entry being added
* @addr4: the IPv4 address information
* @addr6: the IPv6 address information
* @result: the result code
* @audit_info: NetLabel audit information
*
* Description:
* Generate an audit record for adding a new NetLabel/LSM mapping entry with
* the given information. Caller is responsibile for holding the necessary
* locks.
*
*/
static
void
netlbl_domhsh_audit_add
(
struct
netlbl_dom_map
*
entry
,
struct
netlbl_af4list
*
addr4
,
struct
netlbl_af6list
*
addr6
,
int
result
,
struct
netlbl_audit
*
audit_info
)
{
struct
audit_buffer
*
audit_buf
;
struct
cipso_v4_doi
*
cipsov4
=
NULL
;
u32
type
;
audit_buf
=
netlbl_audit_start_common
(
AUDIT_MAC_MAP_ADD
,
audit_info
);
if
(
audit_buf
!=
NULL
)
{
audit_log_format
(
audit_buf
,
" nlbl_domain=%s"
,
entry
->
domain
?
entry
->
domain
:
"(default)"
);
if
(
addr4
!=
NULL
)
{
struct
netlbl_domaddr4_map
*
map4
;
map4
=
netlbl_domhsh_addr4_entry
(
addr4
);
type
=
map4
->
type
;
cipsov4
=
map4
->
type_def
.
cipsov4
;
netlbl_af4list_audit_addr
(
audit_buf
,
0
,
NULL
,
addr4
->
addr
,
addr4
->
mask
);
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
}
else
if
(
addr6
!=
NULL
)
{
struct
netlbl_domaddr6_map
*
map6
;
map6
=
netlbl_domhsh_addr6_entry
(
addr6
);
type
=
map6
->
type
;
netlbl_af6list_audit_addr
(
audit_buf
,
0
,
NULL
,
&
addr6
->
addr
,
&
addr6
->
mask
);
#endif
/* IPv6 */
}
else
{
type
=
entry
->
type
;
cipsov4
=
entry
->
type_def
.
cipsov4
;
}
switch
(
type
)
{
case
NETLBL_NLTYPE_UNLABELED
:
audit_log_format
(
audit_buf
,
" nlbl_protocol=unlbl"
);
break
;
case
NETLBL_NLTYPE_CIPSOV4
:
BUG_ON
(
cipsov4
==
NULL
);
audit_log_format
(
audit_buf
,
" nlbl_protocol=cipsov4 cipso_doi=%u"
,
cipsov4
->
doi
);
break
;
}
audit_log_format
(
audit_buf
,
" res=%u"
,
result
==
0
?
1
:
0
);
audit_log_end
(
audit_buf
);
}
}
/*
* Domain Hash Table Functions
*/
...
...
@@ -213,74 +297,106 @@ int __init netlbl_domhsh_init(u32 size)
int
netlbl_domhsh_add
(
struct
netlbl_dom_map
*
entry
,
struct
netlbl_audit
*
audit_info
)
{
int
ret_val
;
u32
bkt
;
struct
audit_buffer
*
audit_buf
;
switch
(
entry
->
type
)
{
case
NETLBL_NLTYPE_UNLABELED
:
ret_val
=
0
;
break
;
case
NETLBL_NLTYPE_CIPSOV4
:
ret_val
=
cipso_v4_doi_domhsh_add
(
entry
->
type_def
.
cipsov4
,
entry
->
domain
);
break
;
default:
return
-
EINVAL
;
}
if
(
ret_val
!=
0
)
return
ret_val
;
entry
->
valid
=
1
;
INIT_RCU_HEAD
(
&
entry
->
rcu
);
int
ret_val
=
0
;
struct
netlbl_dom_map
*
entry_old
;
struct
netlbl_af4list
*
iter4
;
struct
netlbl_af4list
*
tmp4
;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct
netlbl_af6list
*
iter6
;
struct
netlbl_af6list
*
tmp6
;
#endif
/* IPv6 */
rcu_read_lock
();
spin_lock
(
&
netlbl_domhsh_lock
);
if
(
entry
->
domain
!=
NULL
)
{
bkt
=
netlbl_domhsh_hash
(
entry
->
domain
);
if
(
netlbl_domhsh_search
(
entry
->
domain
)
==
NULL
)
if
(
entry
->
domain
!=
NULL
)
entry_old
=
netlbl_domhsh_search
(
entry
->
domain
);
else
entry_old
=
netlbl_domhsh_search_def
(
entry
->
domain
);
if
(
entry_old
==
NULL
)
{
entry
->
valid
=
1
;
INIT_RCU_HEAD
(
&
entry
->
rcu
);
if
(
entry
->
domain
!=
NULL
)
{
u32
bkt
=
netlbl_domhsh_hash
(
entry
->
domain
);
list_add_tail_rcu
(
&
entry
->
list
,
&
rcu_dereference
(
netlbl_domhsh
)
->
tbl
[
bkt
]);
else
ret_val
=
-
EEXIST
;
}
else
{
INIT_LIST_HEAD
(
&
entry
->
list
);
if
(
rcu_dereference
(
netlbl_domhsh_def
)
==
NULL
)
}
else
{
INIT_LIST_HEAD
(
&
entry
->
list
);
rcu_assign_pointer
(
netlbl_domhsh_def
,
entry
);
else
ret_val
=
-
EEXIST
;
}
spin_unlock
(
&
netlbl_domhsh_lock
);
audit_buf
=
netlbl_audit_start_common
(
AUDIT_MAC_MAP_ADD
,
audit_info
);
if
(
audit_buf
!=
NULL
)
{
audit_log_format
(
audit_buf
,
" nlbl_domain=%s"
,
entry
->
domain
?
entry
->
domain
:
"(default)"
);
switch
(
entry
->
type
)
{
case
NETLBL_NLTYPE_UNLABELED
:
audit_log_format
(
audit_buf
,
" nlbl_protocol=unlbl"
);
break
;
case
NETLBL_NLTYPE_CIPSOV4
:
audit_log_format
(
audit_buf
,
" nlbl_protocol=cipsov4 cipso_doi=%u"
,
entry
->
type_def
.
cipsov4
->
doi
);
break
;
}
audit_log_format
(
audit_buf
,
" res=%u"
,
ret_val
==
0
?
1
:
0
);
audit_log_end
(
audit_buf
);
}
rcu_read_unlock
();
if
(
ret_val
!=
0
)
{
switch
(
entry
->
type
)
{
case
NETLBL_NLTYPE_CIPSOV4
:
if
(
cipso_v4_doi_domhsh_remove
(
entry
->
type_def
.
cipsov4
,
entry
->
domain
)
!=
0
)
BUG
();
break
;
if
(
entry
->
type
==
NETLBL_NLTYPE_ADDRSELECT
)
{
netlbl_af4list_foreach_rcu
(
iter4
,
&
entry
->
type_def
.
addrsel
->
list4
)
netlbl_domhsh_audit_add
(
entry
,
iter4
,
NULL
,
ret_val
,
audit_info
);
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
netlbl_af6list_foreach_rcu
(
iter6
,
&
entry
->
type_def
.
addrsel
->
list6
)
netlbl_domhsh_audit_add
(
entry
,
NULL
,
iter6
,
ret_val
,
audit_info
);
#endif
/* IPv6 */
}
else
netlbl_domhsh_audit_add
(
entry
,
NULL
,
NULL
,
ret_val
,
audit_info
);
}
else
if
(
entry_old
->
type
==
NETLBL_NLTYPE_ADDRSELECT
&&
entry
->
type
==
NETLBL_NLTYPE_ADDRSELECT
)
{
struct
list_head
*
old_list4
;
struct
list_head
*
old_list6
;
old_list4
=
&
entry_old
->
type_def
.
addrsel
->
list4
;
old_list6
=
&
entry_old
->
type_def
.
addrsel
->
list6
;
/* we only allow the addition of address selectors if all of
* the selectors do not exist in the existing domain map */
netlbl_af4list_foreach_rcu
(
iter4
,
&
entry
->
type_def
.
addrsel
->
list4
)
if
(
netlbl_af4list_search_exact
(
iter4
->
addr
,
iter4
->
mask
,
old_list4
))
{
ret_val
=
-
EEXIST
;
goto
add_return
;
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
netlbl_af6list_foreach_rcu
(
iter6
,
&
entry
->
type_def
.
addrsel
->
list6
)
if
(
netlbl_af6list_search_exact
(
&
iter6
->
addr
,
&
iter6
->
mask
,
old_list6
))
{
ret_val
=
-
EEXIST
;
goto
add_return
;
}
#endif
/* IPv6 */
netlbl_af4list_foreach_safe
(
iter4
,
tmp4
,
&
entry
->
type_def
.
addrsel
->
list4
)
{
netlbl_af4list_remove_entry
(
iter4
);
iter4
->
valid
=
1
;
ret_val
=
netlbl_af4list_add
(
iter4
,
old_list4
);
netlbl_domhsh_audit_add
(
entry_old
,
iter4
,
NULL
,
ret_val
,
audit_info
);
if
(
ret_val
!=
0
)
goto
add_return
;
}
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
netlbl_af6list_foreach_safe
(
iter6
,
tmp6
,
&
entry
->
type_def
.
addrsel
->
list6
)
{
netlbl_af6list_remove_entry
(
iter6
);
iter6
->
valid
=
1
;
ret_val
=
netlbl_af6list_add
(
iter6
,
old_list6
);
netlbl_domhsh_audit_add
(
entry_old
,
NULL
,
iter6
,
ret_val
,
audit_info
);
if
(
ret_val
!=
0
)
goto
add_return
;
}
#endif
/* IPv6 */
}
else
ret_val
=
-
EINVAL
;
add_return:
spin_unlock
(
&
netlbl_domhsh_lock
);
rcu_read_unlock
();
return
ret_val
;
}
...
...
@@ -302,35 +418,26 @@ int netlbl_domhsh_add_default(struct netlbl_dom_map *entry,
}
/**
* netlbl_domhsh_remove
- Removes an entry from the domain hash
table
* @
domain: the domain
to remove
* netlbl_domhsh_remove
_entry - Removes a given entry from the domain
table
* @
entry: the entry
to remove
* @audit_info: NetLabel audit information
*
* Description:
* Removes an entry from the domain hash table and handles any updates to the
* lower level protocol handler (i.e. CIPSO). Returns zero on success,
* negative on failure.
* lower level protocol handler (i.e. CIPSO). Caller is responsible for
* ensuring that the RCU read lock is held. Returns zero on success, negative
* on failure.
*
*/
int
netlbl_domhsh_remove
(
const
char
*
domain
,
struct
netlbl_audit
*
audit_info
)
int
netlbl_domhsh_remove_entry
(
struct
netlbl_dom_map
*
entry
,
struct
netlbl_audit
*
audit_info
)
{
int
ret_val
=
-
ENOENT
;
struct
netlbl_dom_map
*
entry
;
int
ret_val
=
0
;
struct
audit_buffer
*
audit_buf
;
rcu_read_lock
();
if
(
domain
)
entry
=
netlbl_domhsh_search
(
domain
);
else
entry
=
netlbl_domhsh_search_def
(
domain
);
if
(
entry
==
NULL
)
goto
remove_return
;
switch
(
entry
->
type
)
{
case
NETLBL_NLTYPE_CIPSOV4
:
cipso_v4_doi_domhsh_remove
(
entry
->
type_def
.
cipsov4
,
entry
->
domain
);
break
;
}
return
-
ENOENT
;
spin_lock
(
&
netlbl_domhsh_lock
);
if
(
entry
->
valid
)
{
entry
->
valid
=
0
;
...
...
@@ -338,8 +445,8 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info)
list_del_rcu
(
&
entry
->
list
);
else
rcu_assign_pointer
(
netlbl_domhsh_def
,
NULL
);
ret_val
=
0
;
}
}
else
ret_val
=
-
ENOENT
;
spin_unlock
(
&
netlbl_domhsh_lock
);
audit_buf
=
netlbl_audit_start_common
(
AUDIT_MAC_MAP_DEL
,
audit_info
);
...
...
@@ -351,10 +458,54 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info)
audit_log_end
(
audit_buf
);
}
remove_return:
rcu_read_unlock
();
if
(
ret_val
==
0
)
if
(
ret_val
==
0
)
{
struct
netlbl_af4list
*
iter4
;
struct
netlbl_domaddr4_map
*
map4
;
switch
(
entry
->
type
)
{
case
NETLBL_NLTYPE_ADDRSELECT
:
netlbl_af4list_foreach_rcu
(
iter4
,
&
entry
->
type_def
.
addrsel
->
list4
)
{
map4
=
netlbl_domhsh_addr4_entry
(
iter4
);
cipso_v4_doi_putdef
(
map4
->
type_def
.
cipsov4
);
}
/* no need to check the IPv6 list since we currently
* support only unlabeled protocols for IPv6 */
break
;
case
NETLBL_NLTYPE_CIPSOV4
:
cipso_v4_doi_putdef
(
entry
->
type_def
.
cipsov4
);
break
;
}
call_rcu
(
&
entry
->
rcu
,
netlbl_domhsh_free_entry
);
}
return
ret_val
;
}
/**
* netlbl_domhsh_remove - Removes an entry from the domain hash table
* @domain: the domain to remove
* @audit_info: NetLabel audit information
*
* Description:
* Removes an entry from the domain hash table and handles any updates to the
* lower level protocol handler (i.e. CIPSO). Returns zero on success,
* negative on failure.
*
*/
int
netlbl_domhsh_remove
(
const
char
*
domain
,
struct
netlbl_audit
*
audit_info
)
{
int
ret_val
;
struct
netlbl_dom_map
*
entry
;
rcu_read_lock
();
if
(
domain
)
entry
=
netlbl_domhsh_search
(
domain
);
else
entry
=
netlbl_domhsh_search_def
(
domain
);
ret_val
=
netlbl_domhsh_remove_entry
(
entry
,
audit_info
);
rcu_read_unlock
();
return
ret_val
;
}
...
...
@@ -388,6 +539,70 @@ struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain)
return
netlbl_domhsh_search_def
(
domain
);
}
/**
* netlbl_domhsh_getentry_af4 - Get an entry from the domain hash table
* @domain: the domain name to search for
* @addr: the IP address to search for
*
* Description:
* Look through the domain hash table searching for an entry to match @domain
* and @addr, return a pointer to a copy of the entry or NULL. The caller is
* responsible for ensuring that rcu_read_[un]lock() is called.
*
*/
struct
netlbl_domaddr4_map
*
netlbl_domhsh_getentry_af4
(
const
char
*
domain
,
__be32
addr
)
{
struct
netlbl_dom_map
*
dom_iter
;
struct
netlbl_af4list
*
addr_iter
;
dom_iter
=
netlbl_domhsh_search_def
(
domain
);
if
(
dom_iter
==
NULL
)
return
NULL
;
if
(
dom_iter
->
type
!=
NETLBL_NLTYPE_ADDRSELECT
)
return
NULL
;
addr_iter
=
netlbl_af4list_search
(
addr
,
&
dom_iter
->
type_def
.
addrsel
->
list4
);
if
(
addr_iter
==
NULL
)
return
NULL
;
return
netlbl_domhsh_addr4_entry
(
addr_iter
);
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
/**
* netlbl_domhsh_getentry_af6 - Get an entry from the domain hash table
* @domain: the domain name to search for
* @addr: the IP address to search for
*
* Description:
* Look through the domain hash table searching for an entry to match @domain
* and @addr, return a pointer to a copy of the entry or NULL. The caller is
* responsible for ensuring that rcu_read_[un]lock() is called.
*
*/
struct
netlbl_domaddr6_map
*
netlbl_domhsh_getentry_af6
(
const
char
*
domain
,
const
struct
in6_addr
*
addr
)
{
struct
netlbl_dom_map
*
dom_iter
;
struct
netlbl_af6list
*
addr_iter
;
dom_iter
=
netlbl_domhsh_search_def
(
domain
);
if
(
dom_iter
==
NULL
)
return
NULL
;
if
(
dom_iter
->
type
!=
NETLBL_NLTYPE_ADDRSELECT
)
return
NULL
;
addr_iter
=
netlbl_af6list_search
(
addr
,
&
dom_iter
->
type_def
.
addrsel
->
list6
);
if
(
addr_iter
==
NULL
)
return
NULL
;
return
netlbl_domhsh_addr6_entry
(
addr_iter
);
}
#endif
/* IPv6 */
/**
* netlbl_domhsh_walk - Iterate through the domain mapping hash table
* @skip_bkt: the number of buckets to skip at the start
...
...
@@ -410,6 +625,7 @@ int netlbl_domhsh_walk(u32 *skip_bkt,
{
int
ret_val
=
-
ENOENT
;
u32
iter_bkt
;
struct
list_head
*
iter_list
;
struct
netlbl_dom_map
*
iter_entry
;
u32
chain_cnt
=
0
;
...
...
@@ -417,9 +633,8 @@ int netlbl_domhsh_walk(u32 *skip_bkt,
for
(
iter_bkt
=
*
skip_bkt
;
iter_bkt
<
rcu_dereference
(
netlbl_domhsh
)
->
size
;
iter_bkt
++
,
chain_cnt
=
0
)
{
list_for_each_entry_rcu
(
iter_entry
,
&
rcu_dereference
(
netlbl_domhsh
)
->
tbl
[
iter_bkt
],
list
)
iter_list
=
&
rcu_dereference
(
netlbl_domhsh
)
->
tbl
[
iter_bkt
];
list_for_each_entry_rcu
(
iter_entry
,
iter_list
,
list
)
if
(
iter_entry
->
valid
)
{
if
(
chain_cnt
++
<
*
skip_chain
)
continue
;
...
...
net/netlabel/netlabel_domainhash.h
浏览文件 @
93db6286
...
...
@@ -11,7 +11,7 @@
*/
/*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
, 2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -36,16 +36,43 @@
#include <linux/rcupdate.h>
#include <linux/list.h>
#include "netlabel_addrlist.h"
/* Domain hash table size */
/* XXX - currently this number is an uneducated guess */
#define NETLBL_DOMHSH_BITSIZE 7
/* Domain mapping definition struct */
/* Domain mapping definition structures */
#define netlbl_domhsh_addr4_entry(iter) \
container_of(iter, struct netlbl_domaddr4_map, list)
struct
netlbl_domaddr4_map
{
u32
type
;
union
{
struct
cipso_v4_doi
*
cipsov4
;
}
type_def
;
struct
netlbl_af4list
list
;
};
#define netlbl_domhsh_addr6_entry(iter) \
container_of(iter, struct netlbl_domaddr6_map, list)
struct
netlbl_domaddr6_map
{
u32
type
;
/* NOTE: no 'type_def' union needed at present since we don't currently
* support any IPv6 labeling protocols */
struct
netlbl_af6list
list
;
};
struct
netlbl_domaddr_map
{
struct
list_head
list4
;
struct
list_head
list6
;
};
struct
netlbl_dom_map
{
char
*
domain
;
u32
type
;
union
{
struct
cipso_v4_doi
*
cipsov4
;
struct
netlbl_domaddr_map
*
addrsel
;
}
type_def
;
u32
valid
;
...
...
@@ -61,12 +88,21 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
struct
netlbl_audit
*
audit_info
);
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
(
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
);
struct
netlbl_domaddr4_map
*
netlbl_domhsh_getentry_af4
(
const
char
*
domain
,
__be32
addr
);
int
netlbl_domhsh_walk
(
u32
*
skip_bkt
,
u32
*
skip_chain
,
int
(
*
callback
)
(
struct
netlbl_dom_map
*
entry
,
void
*
arg
),
void
*
cb_arg
);
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct
netlbl_domaddr6_map
*
netlbl_domhsh_getentry_af6
(
const
char
*
domain
,
const
struct
in6_addr
*
addr
);
#endif
/* IPv6 */
#endif
net/netlabel/netlabel_kapi.c
浏览文件 @
93db6286
...
...
@@ -10,7 +10,7 @@
*/
/*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
, 2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -82,7 +82,7 @@ int netlbl_cfg_unlbl_add_map(const char *domain,
entry
=
kzalloc
(
sizeof
(
*
entry
),
GFP_ATOMIC
);
if
(
entry
==
NULL
)
goto
cfg_unlbl_add_map_failure
;
return
-
ENOMEM
;
if
(
domain
!=
NULL
)
{
entry
->
domain
=
kstrdup
(
domain
,
GFP_ATOMIC
);
if
(
entry
->
domain
==
NULL
)
...
...
@@ -103,49 +103,6 @@ int netlbl_cfg_unlbl_add_map(const char *domain,
return
ret_val
;
}
/**
* netlbl_cfg_cipsov4_add - Add a new CIPSOv4 DOI definition
* @doi_def: the DOI definition
* @audit_info: NetLabel audit information
*
* Description:
* Add a new CIPSOv4 DOI definition to the NetLabel subsystem. Returns zero on
* success, negative values on failure.
*
*/
int
netlbl_cfg_cipsov4_add
(
struct
cipso_v4_doi
*
doi_def
,
struct
netlbl_audit
*
audit_info
)
{
int
ret_val
;
const
char
*
type_str
;
struct
audit_buffer
*
audit_buf
;
ret_val
=
cipso_v4_doi_add
(
doi_def
);
audit_buf
=
netlbl_audit_start_common
(
AUDIT_MAC_CIPSOV4_ADD
,
audit_info
);
if
(
audit_buf
!=
NULL
)
{
switch
(
doi_def
->
type
)
{
case
CIPSO_V4_MAP_STD
:
type_str
=
"std"
;
break
;
case
CIPSO_V4_MAP_PASS
:
type_str
=
"pass"
;
break
;
default:
type_str
=
"(unknown)"
;
}
audit_log_format
(
audit_buf
,
" cipso_doi=%u cipso_type=%s res=%u"
,
doi_def
->
doi
,
type_str
,
ret_val
==
0
?
1
:
0
);
audit_log_end
(
audit_buf
);
}
return
ret_val
;
}
/**
* netlbl_cfg_cipsov4_add_map - Add a new CIPSOv4 DOI definition and mapping
* @doi_def: the DOI definition
...
...
@@ -164,58 +121,71 @@ int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def,
struct
netlbl_audit
*
audit_info
)
{
int
ret_val
=
-
ENOMEM
;
u32
doi
;
u32
doi_type
;
struct
netlbl_dom_map
*
entry
;
const
char
*
type_str
;
struct
audit_buffer
*
audit_buf
;
doi
=
doi_def
->
doi
;
doi_type
=
doi_def
->
type
;
entry
=
kzalloc
(
sizeof
(
*
entry
),
GFP_ATOMIC
);
if
(
entry
==
NULL
)
goto
cfg_cipsov4_add_map_failure
;
return
-
ENOMEM
;
if
(
domain
!=
NULL
)
{
entry
->
domain
=
kstrdup
(
domain
,
GFP_ATOMIC
);
if
(
entry
->
domain
==
NULL
)
goto
cfg_cipsov4_add_map_failure
;
}
entry
->
type
=
NETLBL_NLTYPE_CIPSOV4
;
entry
->
type_def
.
cipsov4
=
doi_def
;
/* Grab a RCU read lock here so nothing happens to the doi_def variable
* between adding it to the CIPSOv4 protocol engine and adding a
* domain mapping for it. */
rcu_read_lock
();
ret_val
=
netlbl_cfg_cipsov4_add
(
doi_def
,
audit_info
);
ret_val
=
cipso_v4_doi_add
(
doi_def
);
if
(
ret_val
!=
0
)
goto
cfg_cipsov4_add_map_failure_unlock
;
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
;
}
ret_val
=
netlbl_domhsh_add
(
entry
,
audit_info
);
if
(
ret_val
!=
0
)
goto
cfg_cipsov4_add_map_failure_remove_doi
;
rcu_read_unlock
();
goto
cfg_cipsov4_add_map_failure_release_doi
;
return
0
;
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
);
}
return
ret_val
;
cfg_cipsov4_add_map_failure_release_doi:
cipso_v4_doi_putdef
(
doi_def
);
cfg_cipsov4_add_map_failure_remove_doi:
cipso_v4_doi_remove
(
doi_def
->
doi
,
audit_info
,
netlbl_cipsov4_doi_free
);
cfg_cipsov4_add_map_failure_unlock:
rcu_read_unlock
();
cipso_v4_doi_remove
(
doi
,
audit_info
);
cfg_cipsov4_add_map_failure:
if
(
entry
!=
NULL
)
kfree
(
entry
->
domain
);
kfree
(
entry
);
return
ret_val
;
}
/**
* netlbl_cfg_cipsov4_del - Removean existing CIPSOv4 DOI definition
* @doi: the CIPSO DOI value
* @audit_info: NetLabel audit information
*
* Description:
* Removes an existing CIPSOv4 DOI definition from the NetLabel subsystem.
* Returns zero on success, negative values on failure.
*
*/
int
netlbl_cfg_cipsov4_del
(
u32
doi
,
struct
netlbl_audit
*
audit_info
)
{
return
cipso_v4_doi_remove
(
doi
,
audit_info
,
netlbl_cipsov4_doi_free
);
goto
cfg_cipsov4_add_map_return
;
}
/*
...
...
@@ -452,7 +422,9 @@ int netlbl_enabled(void)
* Attach the correct label to the given socket using the security attributes
* specified in @secattr. This function requires exclusive access to @sk,
* which means it either needs to be in the process of being created or locked.
* Returns zero on success, negative values on failure.
* Returns zero on success, -EDESTADDRREQ if the domain is configured to use
* network address selectors (can't blindly label the socket), and negative
* values on all other failures.
*
*/
int
netlbl_sock_setattr
(
struct
sock
*
sk
,
...
...
@@ -466,6 +438,9 @@ int netlbl_sock_setattr(struct sock *sk,
if
(
dom_entry
==
NULL
)
goto
socket_setattr_return
;
switch
(
dom_entry
->
type
)
{
case
NETLBL_NLTYPE_ADDRSELECT
:
ret_val
=
-
EDESTADDRREQ
;
break
;
case
NETLBL_NLTYPE_CIPSOV4
:
ret_val
=
cipso_v4_sock_setattr
(
sk
,
dom_entry
->
type_def
.
cipsov4
,
...
...
@@ -483,6 +458,20 @@ int netlbl_sock_setattr(struct sock *sk,
return
ret_val
;
}
/**
* netlbl_sock_delattr - Delete all the NetLabel labels on a socket
* @sk: the socket
*
* Description:
* Remove all the NetLabel labeling from @sk. The caller is responsible for
* ensuring that @sk is locked.
*
*/
void
netlbl_sock_delattr
(
struct
sock
*
sk
)
{
cipso_v4_sock_delattr
(
sk
);
}
/**
* netlbl_sock_getattr - Determine the security attributes of a sock
* @sk: the sock
...
...
@@ -500,6 +489,128 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
return
cipso_v4_sock_getattr
(
sk
,
secattr
);
}
/**
* netlbl_conn_setattr - Label a connected socket using the correct protocol
* @sk: the socket to label
* @addr: the destination address
* @secattr: the security attributes
*
* Description:
* Attach the correct label to the given connected socket using the security
* attributes specified in @secattr. The caller is responsible for ensuring
* that @sk is locked. Returns zero on success, negative values on failure.
*
*/
int
netlbl_conn_setattr
(
struct
sock
*
sk
,
struct
sockaddr
*
addr
,
const
struct
netlbl_lsm_secattr
*
secattr
)
{
int
ret_val
;
struct
sockaddr_in
*
addr4
;
struct
netlbl_domaddr4_map
*
af4_entry
;
rcu_read_lock
();
switch
(
addr
->
sa_family
)
{
case
AF_INET
:
addr4
=
(
struct
sockaddr_in
*
)
addr
;
af4_entry
=
netlbl_domhsh_getentry_af4
(
secattr
->
domain
,
addr4
->
sin_addr
.
s_addr
);
if
(
af4_entry
==
NULL
)
{
ret_val
=
-
ENOENT
;
goto
conn_setattr_return
;
}
switch
(
af4_entry
->
type
)
{
case
NETLBL_NLTYPE_CIPSOV4
:
ret_val
=
cipso_v4_sock_setattr
(
sk
,
af4_entry
->
type_def
.
cipsov4
,
secattr
);
break
;
case
NETLBL_NLTYPE_UNLABELED
:
/* just delete the protocols we support for right now
* but we could remove other protocols if needed */
cipso_v4_sock_delattr
(
sk
);
ret_val
=
0
;
break
;
default:
ret_val
=
-
ENOENT
;
}
break
;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case
AF_INET6
:
/* since we don't support any IPv6 labeling protocols right
* now we can optimize everything away until we do */
ret_val
=
0
;
break
;
#endif
/* IPv6 */
default:
ret_val
=
0
;
}
conn_setattr_return:
rcu_read_unlock
();
return
ret_val
;
}
/**
* netlbl_skbuff_setattr - Label a packet using the correct protocol
* @skb: the packet
* @family: protocol family
* @secattr: the security attributes
*
* Description:
* Attach the correct label to the given packet using the security attributes
* specified in @secattr. Returns zero on success, negative values on failure.
*
*/
int
netlbl_skbuff_setattr
(
struct
sk_buff
*
skb
,
u16
family
,
const
struct
netlbl_lsm_secattr
*
secattr
)
{
int
ret_val
;
struct
iphdr
*
hdr4
;
struct
netlbl_domaddr4_map
*
af4_entry
;
rcu_read_lock
();
switch
(
family
)
{
case
AF_INET
:
hdr4
=
ip_hdr
(
skb
);
af4_entry
=
netlbl_domhsh_getentry_af4
(
secattr
->
domain
,
hdr4
->
daddr
);
if
(
af4_entry
==
NULL
)
{
ret_val
=
-
ENOENT
;
goto
skbuff_setattr_return
;
}
switch
(
af4_entry
->
type
)
{
case
NETLBL_NLTYPE_CIPSOV4
:
ret_val
=
cipso_v4_skbuff_setattr
(
skb
,
af4_entry
->
type_def
.
cipsov4
,
secattr
);
break
;
case
NETLBL_NLTYPE_UNLABELED
:
/* just delete the protocols we support for right now
* but we could remove other protocols if needed */
ret_val
=
cipso_v4_skbuff_delattr
(
skb
);
break
;
default:
ret_val
=
-
ENOENT
;
}
break
;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case
AF_INET6
:
/* since we don't support any IPv6 labeling protocols right
* now we can optimize everything away until we do */
ret_val
=
0
;
break
;
#endif
/* IPv6 */
default:
ret_val
=
0
;
}
skbuff_setattr_return:
rcu_read_unlock
();
return
ret_val
;
}
/**
* netlbl_skbuff_getattr - Determine the security attributes of a packet
* @skb: the packet
...
...
@@ -528,6 +639,7 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb,
* netlbl_skbuff_err - Handle a LSM error on a sk_buff
* @skb: the packet
* @error: the error code
* @gateway: true if host is acting as a gateway, false otherwise
*
* Description:
* Deal with a LSM problem when handling the packet in @skb, typically this is
...
...
@@ -535,10 +647,10 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb,
* according to the packet's labeling protocol.
*
*/
void
netlbl_skbuff_err
(
struct
sk_buff
*
skb
,
int
error
)
void
netlbl_skbuff_err
(
struct
sk_buff
*
skb
,
int
error
,
int
gateway
)
{
if
(
CIPSO_V4_OPTEXIST
(
skb
))
cipso_v4_error
(
skb
,
error
,
0
);
cipso_v4_error
(
skb
,
error
,
gateway
);
}
/**
...
...
net/netlabel/netlabel_mgmt.c
浏览文件 @
93db6286
...
...
@@ -10,7 +10,7 @@
*/
/*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
, 2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -32,9 +32,13 @@
#include <linux/socket.h>
#include <linux/string.h>
#include <linux/skbuff.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <net/sock.h>
#include <net/netlink.h>
#include <net/genetlink.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/netlabel.h>
#include <net/cipso_ipv4.h>
#include <asm/atomic.h>
...
...
@@ -71,85 +75,336 @@ static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
};
/*
*
NetLabel Command Handler
s
*
Helper Function
s
*/
/**
* netlbl_mgmt_add - Handle an ADD message
* @skb: the NETLINK buffer
* @info: the Generic NETLINK info block
* @audit_info: NetLabel audit information
*
* Description:
*
Process a user generated ADD message and add the domains from the message
*
to the hash table. See netlabel.h for a description of the message format.
* Returns zero on success, negative values on failure.
*
Helper function for the ADD and ADDDEF messages to add the domain mappings
*
from the message to the hash table. See netlabel.h for a description of the
*
message format.
Returns zero on success, negative values on failure.
*
*/
static
int
netlbl_mgmt_add
(
struct
sk_buff
*
skb
,
struct
genl_info
*
info
)
static
int
netlbl_mgmt_add_common
(
struct
genl_info
*
info
,
struct
netlbl_audit
*
audit_info
)
{
int
ret_val
=
-
EINVAL
;
struct
netlbl_dom_map
*
entry
=
NULL
;
size_t
tmp_size
;
struct
netlbl_domaddr_map
*
addrmap
=
NULL
;
struct
cipso_v4_doi
*
cipsov4
=
NULL
;
u32
tmp_val
;
struct
netlbl_audit
audit_info
;
if
(
!
info
->
attrs
[
NLBL_MGMT_A_DOMAIN
]
||
!
info
->
attrs
[
NLBL_MGMT_A_PROTOCOL
])
goto
add_failure
;
netlbl_netlink_auditinfo
(
skb
,
&
audit_info
);
entry
=
kzalloc
(
sizeof
(
*
entry
),
GFP_KERNEL
);
if
(
entry
==
NULL
)
{
ret_val
=
-
ENOMEM
;
goto
add_failure
;
}
tmp_size
=
nla_len
(
info
->
attrs
[
NLBL_MGMT_A_DOMAIN
]);
entry
->
domain
=
kmalloc
(
tmp_size
,
GFP_KERNEL
);
if
(
entry
->
domain
==
NULL
)
{
ret_val
=
-
ENOMEM
;
goto
add_failure
;
}
entry
->
type
=
nla_get_u32
(
info
->
attrs
[
NLBL_MGMT_A_PROTOCOL
]);
nla_strlcpy
(
entry
->
domain
,
info
->
attrs
[
NLBL_MGMT_A_DOMAIN
],
tmp_size
);
if
(
info
->
attrs
[
NLBL_MGMT_A_DOMAIN
])
{
size_t
tmp_size
=
nla_len
(
info
->
attrs
[
NLBL_MGMT_A_DOMAIN
]);
entry
->
domain
=
kmalloc
(
tmp_size
,
GFP_KERNEL
);
if
(
entry
->
domain
==
NULL
)
{
ret_val
=
-
ENOMEM
;
goto
add_failure
;
}
nla_strlcpy
(
entry
->
domain
,
info
->
attrs
[
NLBL_MGMT_A_DOMAIN
],
tmp_size
);
}
/* NOTE: internally we allow/use a entry->type value of
* NETLBL_NLTYPE_ADDRSELECT but we don't currently allow users
* to pass that as a protocol value because we need to know the
* "real" protocol */
switch
(
entry
->
type
)
{
case
NETLBL_NLTYPE_UNLABELED
:
ret_val
=
netlbl_domhsh_add
(
entry
,
&
audit_info
);
break
;
case
NETLBL_NLTYPE_CIPSOV4
:
if
(
!
info
->
attrs
[
NLBL_MGMT_A_CV4DOI
])
goto
add_failure
;
tmp_val
=
nla_get_u32
(
info
->
attrs
[
NLBL_MGMT_A_CV4DOI
]);
/* We should be holding a rcu_read_lock() here while we hold
* the result but since the entry will always be deleted when
* the CIPSO DOI is deleted we aren't going to keep the
* lock. */
rcu_read_lock
();
entry
->
type_def
.
cipsov4
=
cipso_v4_doi_getdef
(
tmp_val
);
if
(
entry
->
type_def
.
cipsov4
==
NULL
)
{
rcu_read_unlock
();
cipsov4
=
cipso_v4_doi_getdef
(
tmp_val
);
if
(
cipsov4
==
NULL
)
goto
add_failure
;
}
ret_val
=
netlbl_domhsh_add
(
entry
,
&
audit_info
);
rcu_read_unlock
();
entry
->
type_def
.
cipsov4
=
cipsov4
;
break
;
default:
goto
add_failure
;
}
if
(
info
->
attrs
[
NLBL_MGMT_A_IPV4ADDR
])
{
struct
in_addr
*
addr
;
struct
in_addr
*
mask
;
struct
netlbl_domaddr4_map
*
map
;
addrmap
=
kzalloc
(
sizeof
(
*
addrmap
),
GFP_KERNEL
);
if
(
addrmap
==
NULL
)
{
ret_val
=
-
ENOMEM
;
goto
add_failure
;
}
INIT_LIST_HEAD
(
&
addrmap
->
list4
);
INIT_LIST_HEAD
(
&
addrmap
->
list6
);
if
(
nla_len
(
info
->
attrs
[
NLBL_MGMT_A_IPV4ADDR
])
!=
sizeof
(
struct
in_addr
))
{
ret_val
=
-
EINVAL
;
goto
add_failure
;
}
if
(
nla_len
(
info
->
attrs
[
NLBL_MGMT_A_IPV4MASK
])
!=
sizeof
(
struct
in_addr
))
{
ret_val
=
-
EINVAL
;
goto
add_failure
;
}
addr
=
nla_data
(
info
->
attrs
[
NLBL_MGMT_A_IPV4ADDR
]);
mask
=
nla_data
(
info
->
attrs
[
NLBL_MGMT_A_IPV4MASK
]);
map
=
kzalloc
(
sizeof
(
*
map
),
GFP_KERNEL
);
if
(
map
==
NULL
)
{
ret_val
=
-
ENOMEM
;
goto
add_failure
;
}
map
->
list
.
addr
=
addr
->
s_addr
&
mask
->
s_addr
;
map
->
list
.
mask
=
mask
->
s_addr
;
map
->
list
.
valid
=
1
;
map
->
type
=
entry
->
type
;
if
(
cipsov4
)
map
->
type_def
.
cipsov4
=
cipsov4
;
ret_val
=
netlbl_af4list_add
(
&
map
->
list
,
&
addrmap
->
list4
);
if
(
ret_val
!=
0
)
{
kfree
(
map
);
goto
add_failure
;
}
entry
->
type
=
NETLBL_NLTYPE_ADDRSELECT
;
entry
->
type_def
.
addrsel
=
addrmap
;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
}
else
if
(
info
->
attrs
[
NLBL_MGMT_A_IPV6ADDR
])
{
struct
in6_addr
*
addr
;
struct
in6_addr
*
mask
;
struct
netlbl_domaddr6_map
*
map
;
addrmap
=
kzalloc
(
sizeof
(
*
addrmap
),
GFP_KERNEL
);
if
(
addrmap
==
NULL
)
{
ret_val
=
-
ENOMEM
;
goto
add_failure
;
}
INIT_LIST_HEAD
(
&
addrmap
->
list4
);
INIT_LIST_HEAD
(
&
addrmap
->
list6
);
if
(
nla_len
(
info
->
attrs
[
NLBL_MGMT_A_IPV6ADDR
])
!=
sizeof
(
struct
in6_addr
))
{
ret_val
=
-
EINVAL
;
goto
add_failure
;
}
if
(
nla_len
(
info
->
attrs
[
NLBL_MGMT_A_IPV6MASK
])
!=
sizeof
(
struct
in6_addr
))
{
ret_val
=
-
EINVAL
;
goto
add_failure
;
}
addr
=
nla_data
(
info
->
attrs
[
NLBL_MGMT_A_IPV6ADDR
]);
mask
=
nla_data
(
info
->
attrs
[
NLBL_MGMT_A_IPV6MASK
]);
map
=
kzalloc
(
sizeof
(
*
map
),
GFP_KERNEL
);
if
(
map
==
NULL
)
{
ret_val
=
-
ENOMEM
;
goto
add_failure
;
}
ipv6_addr_copy
(
&
map
->
list
.
addr
,
addr
);
map
->
list
.
addr
.
s6_addr32
[
0
]
&=
mask
->
s6_addr32
[
0
];
map
->
list
.
addr
.
s6_addr32
[
1
]
&=
mask
->
s6_addr32
[
1
];
map
->
list
.
addr
.
s6_addr32
[
2
]
&=
mask
->
s6_addr32
[
2
];
map
->
list
.
addr
.
s6_addr32
[
3
]
&=
mask
->
s6_addr32
[
3
];
ipv6_addr_copy
(
&
map
->
list
.
mask
,
mask
);
map
->
list
.
valid
=
1
;
map
->
type
=
entry
->
type
;
ret_val
=
netlbl_af6list_add
(
&
map
->
list
,
&
addrmap
->
list6
);
if
(
ret_val
!=
0
)
{
kfree
(
map
);
goto
add_failure
;
}
entry
->
type
=
NETLBL_NLTYPE_ADDRSELECT
;
entry
->
type_def
.
addrsel
=
addrmap
;
#endif
/* IPv6 */
}
ret_val
=
netlbl_domhsh_add
(
entry
,
audit_info
);
if
(
ret_val
!=
0
)
goto
add_failure
;
return
0
;
add_failure:
if
(
cipsov4
)
cipso_v4_doi_putdef
(
cipsov4
);
if
(
entry
)
kfree
(
entry
->
domain
);
kfree
(
addrmap
);
kfree
(
entry
);
return
ret_val
;
}
/**
* netlbl_mgmt_listentry - List a NetLabel/LSM domain map entry
* @skb: the NETLINK buffer
* @entry: the map entry
*
* Description:
* This function is a helper function used by the LISTALL and LISTDEF command
* handlers. The caller is responsibile for ensuring that the RCU read lock
* is held. Returns zero on success, negative values on failure.
*
*/
static
int
netlbl_mgmt_listentry
(
struct
sk_buff
*
skb
,
struct
netlbl_dom_map
*
entry
)
{
int
ret_val
;
struct
nlattr
*
nla_a
;
struct
nlattr
*
nla_b
;
struct
netlbl_af4list
*
iter4
;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct
netlbl_af6list
*
iter6
;
#endif
if
(
entry
->
domain
!=
NULL
)
{
ret_val
=
nla_put_string
(
skb
,
NLBL_MGMT_A_DOMAIN
,
entry
->
domain
);
if
(
ret_val
!=
0
)
return
ret_val
;
}
switch
(
entry
->
type
)
{
case
NETLBL_NLTYPE_ADDRSELECT
:
nla_a
=
nla_nest_start
(
skb
,
NLBL_MGMT_A_SELECTORLIST
);
if
(
nla_a
==
NULL
)
return
-
ENOMEM
;
netlbl_af4list_foreach_rcu
(
iter4
,
&
entry
->
type_def
.
addrsel
->
list4
)
{
struct
netlbl_domaddr4_map
*
map4
;
struct
in_addr
addr_struct
;
nla_b
=
nla_nest_start
(
skb
,
NLBL_MGMT_A_ADDRSELECTOR
);
if
(
nla_b
==
NULL
)
return
-
ENOMEM
;
addr_struct
.
s_addr
=
iter4
->
addr
;
ret_val
=
nla_put
(
skb
,
NLBL_MGMT_A_IPV4ADDR
,
sizeof
(
struct
in_addr
),
&
addr_struct
);
if
(
ret_val
!=
0
)
return
ret_val
;
addr_struct
.
s_addr
=
iter4
->
mask
;
ret_val
=
nla_put
(
skb
,
NLBL_MGMT_A_IPV4MASK
,
sizeof
(
struct
in_addr
),
&
addr_struct
);
if
(
ret_val
!=
0
)
return
ret_val
;
map4
=
netlbl_domhsh_addr4_entry
(
iter4
);
ret_val
=
nla_put_u32
(
skb
,
NLBL_MGMT_A_PROTOCOL
,
map4
->
type
);
if
(
ret_val
!=
0
)
return
ret_val
;
switch
(
map4
->
type
)
{
case
NETLBL_NLTYPE_CIPSOV4
:
ret_val
=
nla_put_u32
(
skb
,
NLBL_MGMT_A_CV4DOI
,
map4
->
type_def
.
cipsov4
->
doi
);
if
(
ret_val
!=
0
)
return
ret_val
;
break
;
}
nla_nest_end
(
skb
,
nla_b
);
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
netlbl_af6list_foreach_rcu
(
iter6
,
&
entry
->
type_def
.
addrsel
->
list6
)
{
struct
netlbl_domaddr6_map
*
map6
;
nla_b
=
nla_nest_start
(
skb
,
NLBL_MGMT_A_ADDRSELECTOR
);
if
(
nla_b
==
NULL
)
return
-
ENOMEM
;
ret_val
=
nla_put
(
skb
,
NLBL_MGMT_A_IPV6ADDR
,
sizeof
(
struct
in6_addr
),
&
iter6
->
addr
);
if
(
ret_val
!=
0
)
return
ret_val
;
ret_val
=
nla_put
(
skb
,
NLBL_MGMT_A_IPV6MASK
,
sizeof
(
struct
in6_addr
),
&
iter6
->
mask
);
if
(
ret_val
!=
0
)
return
ret_val
;
map6
=
netlbl_domhsh_addr6_entry
(
iter6
);
ret_val
=
nla_put_u32
(
skb
,
NLBL_MGMT_A_PROTOCOL
,
map6
->
type
);
if
(
ret_val
!=
0
)
return
ret_val
;
nla_nest_end
(
skb
,
nla_b
);
}
#endif
/* IPv6 */
nla_nest_end
(
skb
,
nla_a
);
break
;
case
NETLBL_NLTYPE_UNLABELED
:
ret_val
=
nla_put_u32
(
skb
,
NLBL_MGMT_A_PROTOCOL
,
entry
->
type
);
break
;
case
NETLBL_NLTYPE_CIPSOV4
:
ret_val
=
nla_put_u32
(
skb
,
NLBL_MGMT_A_PROTOCOL
,
entry
->
type
);
if
(
ret_val
!=
0
)
return
ret_val
;
ret_val
=
nla_put_u32
(
skb
,
NLBL_MGMT_A_CV4DOI
,
entry
->
type_def
.
cipsov4
->
doi
);
break
;
}
return
ret_val
;
}
/*
* NetLabel Command Handlers
*/
/**
* netlbl_mgmt_add - Handle an ADD message
* @skb: the NETLINK buffer
* @info: the Generic NETLINK info block
*
* Description:
* Process a user generated ADD message and add the domains from the message
* to the hash table. See netlabel.h for a description of the message format.
* Returns zero on success, negative values on failure.
*
*/
static
int
netlbl_mgmt_add
(
struct
sk_buff
*
skb
,
struct
genl_info
*
info
)
{
struct
netlbl_audit
audit_info
;
if
((
!
info
->
attrs
[
NLBL_MGMT_A_DOMAIN
])
||
(
!
info
->
attrs
[
NLBL_MGMT_A_PROTOCOL
])
||
(
info
->
attrs
[
NLBL_MGMT_A_IPV4ADDR
]
&&
info
->
attrs
[
NLBL_MGMT_A_IPV6ADDR
])
||
(
info
->
attrs
[
NLBL_MGMT_A_IPV4MASK
]
&&
info
->
attrs
[
NLBL_MGMT_A_IPV6MASK
])
||
((
info
->
attrs
[
NLBL_MGMT_A_IPV4ADDR
]
!=
NULL
)
^
(
info
->
attrs
[
NLBL_MGMT_A_IPV4MASK
]
!=
NULL
))
||
((
info
->
attrs
[
NLBL_MGMT_A_IPV6ADDR
]
!=
NULL
)
^
(
info
->
attrs
[
NLBL_MGMT_A_IPV6MASK
]
!=
NULL
)))
return
-
EINVAL
;
netlbl_netlink_auditinfo
(
skb
,
&
audit_info
);
return
netlbl_mgmt_add_common
(
info
,
&
audit_info
);
}
/**
* netlbl_mgmt_remove - Handle a REMOVE message
* @skb: the NETLINK buffer
...
...
@@ -198,23 +453,9 @@ static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg)
if
(
data
==
NULL
)
goto
listall_cb_failure
;
ret_val
=
nla_put_string
(
cb_arg
->
skb
,
NLBL_MGMT_A_DOMAIN
,
entry
->
domain
);
ret_val
=
netlbl_mgmt_listentry
(
cb_arg
->
skb
,
entry
);
if
(
ret_val
!=
0
)
goto
listall_cb_failure
;
ret_val
=
nla_put_u32
(
cb_arg
->
skb
,
NLBL_MGMT_A_PROTOCOL
,
entry
->
type
);
if
(
ret_val
!=
0
)
goto
listall_cb_failure
;
switch
(
entry
->
type
)
{
case
NETLBL_NLTYPE_CIPSOV4
:
ret_val
=
nla_put_u32
(
cb_arg
->
skb
,
NLBL_MGMT_A_CV4DOI
,
entry
->
type_def
.
cipsov4
->
doi
);
if
(
ret_val
!=
0
)
goto
listall_cb_failure
;
break
;
}
cb_arg
->
seq
++
;
return
genlmsg_end
(
cb_arg
->
skb
,
data
);
...
...
@@ -268,56 +509,22 @@ static int netlbl_mgmt_listall(struct sk_buff *skb,
*/
static
int
netlbl_mgmt_adddef
(
struct
sk_buff
*
skb
,
struct
genl_info
*
info
)
{
int
ret_val
=
-
EINVAL
;
struct
netlbl_dom_map
*
entry
=
NULL
;
u32
tmp_val
;
struct
netlbl_audit
audit_info
;
if
(
!
info
->
attrs
[
NLBL_MGMT_A_PROTOCOL
])
goto
adddef_failure
;
if
((
!
info
->
attrs
[
NLBL_MGMT_A_PROTOCOL
])
||
(
info
->
attrs
[
NLBL_MGMT_A_IPV4ADDR
]
&&
info
->
attrs
[
NLBL_MGMT_A_IPV6ADDR
])
||
(
info
->
attrs
[
NLBL_MGMT_A_IPV4MASK
]
&&
info
->
attrs
[
NLBL_MGMT_A_IPV6MASK
])
||
((
info
->
attrs
[
NLBL_MGMT_A_IPV4ADDR
]
!=
NULL
)
^
(
info
->
attrs
[
NLBL_MGMT_A_IPV4MASK
]
!=
NULL
))
||
((
info
->
attrs
[
NLBL_MGMT_A_IPV6ADDR
]
!=
NULL
)
^
(
info
->
attrs
[
NLBL_MGMT_A_IPV6MASK
]
!=
NULL
)))
return
-
EINVAL
;
netlbl_netlink_auditinfo
(
skb
,
&
audit_info
);
entry
=
kzalloc
(
sizeof
(
*
entry
),
GFP_KERNEL
);
if
(
entry
==
NULL
)
{
ret_val
=
-
ENOMEM
;
goto
adddef_failure
;
}
entry
->
type
=
nla_get_u32
(
info
->
attrs
[
NLBL_MGMT_A_PROTOCOL
]);
switch
(
entry
->
type
)
{
case
NETLBL_NLTYPE_UNLABELED
:
ret_val
=
netlbl_domhsh_add_default
(
entry
,
&
audit_info
);
break
;
case
NETLBL_NLTYPE_CIPSOV4
:
if
(
!
info
->
attrs
[
NLBL_MGMT_A_CV4DOI
])
goto
adddef_failure
;
tmp_val
=
nla_get_u32
(
info
->
attrs
[
NLBL_MGMT_A_CV4DOI
]);
/* We should be holding a rcu_read_lock() here while we hold
* the result but since the entry will always be deleted when
* the CIPSO DOI is deleted we aren't going to keep the
* lock. */
rcu_read_lock
();
entry
->
type_def
.
cipsov4
=
cipso_v4_doi_getdef
(
tmp_val
);
if
(
entry
->
type_def
.
cipsov4
==
NULL
)
{
rcu_read_unlock
();
goto
adddef_failure
;
}
ret_val
=
netlbl_domhsh_add_default
(
entry
,
&
audit_info
);
rcu_read_unlock
();
break
;
default:
goto
adddef_failure
;
}
if
(
ret_val
!=
0
)
goto
adddef_failure
;
return
0
;
adddef_failure:
kfree
(
entry
);
return
ret_val
;
return
netlbl_mgmt_add_common
(
info
,
&
audit_info
);
}
/**
...
...
@@ -371,19 +578,10 @@ static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info)
ret_val
=
-
ENOENT
;
goto
listdef_failure_lock
;
}
ret_val
=
nla_put_u32
(
ans_skb
,
NLBL_MGMT_A_PROTOCOL
,
entry
->
type
);
if
(
ret_val
!=
0
)
goto
listdef_failure_lock
;
switch
(
entry
->
type
)
{
case
NETLBL_NLTYPE_CIPSOV4
:
ret_val
=
nla_put_u32
(
ans_skb
,
NLBL_MGMT_A_CV4DOI
,
entry
->
type_def
.
cipsov4
->
doi
);
if
(
ret_val
!=
0
)
goto
listdef_failure_lock
;
break
;
}
ret_val
=
netlbl_mgmt_listentry
(
ans_skb
,
entry
);
rcu_read_unlock
();
if
(
ret_val
!=
0
)
goto
listdef_failure
;
genlmsg_end
(
ans_skb
,
data
);
return
genlmsg_reply
(
ans_skb
,
info
);
...
...
net/netlabel/netlabel_mgmt.h
浏览文件 @
93db6286
...
...
@@ -45,6 +45,16 @@
* NLBL_MGMT_A_DOMAIN
* NLBL_MGMT_A_PROTOCOL
*
* If IPv4 is specified the following attributes are required:
*
* NLBL_MGMT_A_IPV4ADDR
* NLBL_MGMT_A_IPV4MASK
*
* If IPv6 is specified the following attributes are required:
*
* NLBL_MGMT_A_IPV6ADDR
* NLBL_MGMT_A_IPV6MASK
*
* If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
*
* NLBL_MGMT_A_CV4DOI
...
...
@@ -68,13 +78,24 @@
* Required attributes:
*
* NLBL_MGMT_A_DOMAIN
*
* If the IP address selectors are not used the following attribute is
* required:
*
* NLBL_MGMT_A_PROTOCOL
*
* If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
* If the IP address selectors are used then the following attritbute is
* required:
*
* NLBL_MGMT_A_SELECTORLIST
*
* If the mapping is using the NETLBL_NLTYPE_CIPSOV4 type then the following
* attributes are required:
*
* NLBL_MGMT_A_CV4DOI
*
* If using NETLBL_NLTYPE_UNLABELED no other attributes are required.
* If the mapping is using the NETLBL_NLTYPE_UNLABELED type no other
* attributes are required.
*
* o ADDDEF:
* Sent by an application to set the default domain mapping for the NetLabel
...
...
@@ -100,15 +121,23 @@
* application there is no payload. On success the kernel should send a
* response using the following format.
*
* Required attributes:
* If the IP address selectors are not used the following attribute is
* required:
*
* NLBL_MGMT_A_PROTOCOL
*
* If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
* If the IP address selectors are used then the following attritbute is
* required:
*
* NLBL_MGMT_A_SELECTORLIST
*
* If the mapping is using the NETLBL_NLTYPE_CIPSOV4 type then the following
* attributes are required:
*
* NLBL_MGMT_A_CV4DOI
*
* If using NETLBL_NLTYPE_UNLABELED no other attributes are required.
* If the mapping is using the NETLBL_NLTYPE_UNLABELED type no other
* attributes are required.
*
* o PROTOCOLS:
* Sent by an application to request a list of configured NetLabel protocols
...
...
@@ -162,6 +191,26 @@ enum {
NLBL_MGMT_A_CV4DOI
,
/* (NLA_U32)
* the CIPSOv4 DOI value */
NLBL_MGMT_A_IPV6ADDR
,
/* (NLA_BINARY, struct in6_addr)
* an IPv6 address */
NLBL_MGMT_A_IPV6MASK
,
/* (NLA_BINARY, struct in6_addr)
* an IPv6 address mask */
NLBL_MGMT_A_IPV4ADDR
,
/* (NLA_BINARY, struct in_addr)
* an IPv4 address */
NLBL_MGMT_A_IPV4MASK
,
/* (NLA_BINARY, struct in_addr)
* and IPv4 address mask */
NLBL_MGMT_A_ADDRSELECTOR
,
/* (NLA_NESTED)
* an IP address selector, must contain an address, mask, and protocol
* attribute plus any protocol specific attributes */
NLBL_MGMT_A_SELECTORLIST
,
/* (NLA_NESTED)
* the selector list, there must be at least one
* NLBL_MGMT_A_ADDRSELECTOR attribute */
__NLBL_MGMT_A_MAX
,
};
#define NLBL_MGMT_A_MAX (__NLBL_MGMT_A_MAX - 1)
...
...
net/netlabel/netlabel_unlabeled.c
浏览文件 @
93db6286
此差异已折叠。
点击以展开。
security/selinux/hooks.c
浏览文件 @
93db6286
...
...
@@ -291,6 +291,7 @@ static void sk_free_security(struct sock *sk)
struct
sk_security_struct
*
ssec
=
sk
->
sk_security
;
sk
->
sk_security
=
NULL
;
selinux_netlbl_sk_security_free
(
ssec
);
kfree
(
ssec
);
}
...
...
@@ -3801,6 +3802,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
static
int
selinux_socket_connect
(
struct
socket
*
sock
,
struct
sockaddr
*
address
,
int
addrlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
inode_security_struct
*
isec
;
int
err
;
...
...
@@ -3814,7 +3816,6 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
isec
=
SOCK_INODE
(
sock
)
->
i_security
;
if
(
isec
->
sclass
==
SECCLASS_TCP_SOCKET
||
isec
->
sclass
==
SECCLASS_DCCP_SOCKET
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
avc_audit_data
ad
;
struct
sockaddr_in
*
addr4
=
NULL
;
struct
sockaddr_in6
*
addr6
=
NULL
;
...
...
@@ -3848,6 +3849,8 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
goto
out
;
}
err
=
selinux_netlbl_socket_connect
(
sk
,
address
);
out:
return
err
;
}
...
...
@@ -4077,20 +4080,28 @@ 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
,
struct
avc_audit_data
*
ad
,
u16
family
,
char
*
addrp
)
u16
family
)
{
int
err
;
struct
sk_security_struct
*
sksec
=
sk
->
sk_security
;
u32
peer_sid
;
u32
sk_sid
=
sksec
->
sid
;
struct
avc_audit_data
ad
;
char
*
addrp
;
AVC_AUDIT_DATA_INIT
(
&
ad
,
NET
);
ad
.
u
.
net
.
netif
=
skb
->
iif
;
ad
.
u
.
net
.
family
=
family
;
err
=
selinux_parse_skb
(
skb
,
&
ad
,
&
addrp
,
1
,
NULL
);
if
(
err
)
return
err
;
if
(
selinux_compat_net
)
err
=
selinux_sock_rcv_skb_iptables_compat
(
sk
,
skb
,
ad
,
err
=
selinux_sock_rcv_skb_iptables_compat
(
sk
,
skb
,
&
ad
,
family
,
addrp
);
else
err
=
avc_has_perm
(
sk_sid
,
skb
->
secmark
,
SECCLASS_PACKET
,
PACKET__RECV
,
ad
);
PACKET__RECV
,
&
ad
);
if
(
err
)
return
err
;
...
...
@@ -4099,12 +4110,14 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
if
(
err
)
return
err
;
err
=
avc_has_perm
(
sk_sid
,
peer_sid
,
SECCLASS_PEER
,
PEER__RECV
,
ad
);
SECCLASS_PEER
,
PEER__RECV
,
&
ad
);
if
(
err
)
selinux_netlbl_err
(
skb
,
err
,
0
);
}
else
{
err
=
selinux_netlbl_sock_rcv_skb
(
sksec
,
skb
,
family
,
ad
);
err
=
selinux_netlbl_sock_rcv_skb
(
sksec
,
skb
,
family
,
&
ad
);
if
(
err
)
return
err
;
err
=
selinux_xfrm_sock_rcv_skb
(
sksec
->
sid
,
skb
,
ad
);
err
=
selinux_xfrm_sock_rcv_skb
(
sksec
->
sid
,
skb
,
&
ad
);
}
return
err
;
...
...
@@ -4118,6 +4131,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
u32
sk_sid
=
sksec
->
sid
;
struct
avc_audit_data
ad
;
char
*
addrp
;
u8
secmark_active
;
u8
peerlbl_active
;
if
(
family
!=
PF_INET
&&
family
!=
PF_INET6
)
return
0
;
...
...
@@ -4126,6 +4141,18 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
if
(
family
==
PF_INET6
&&
skb
->
protocol
==
htons
(
ETH_P_IP
))
family
=
PF_INET
;
/* If any sort of compatibility mode is enabled then handoff processing
* to the selinux_sock_rcv_skb_compat() function to deal with the
* special handling. We do this in an attempt to keep this function
* as fast and as clean as possible. */
if
(
selinux_compat_net
||
!
selinux_policycap_netpeer
)
return
selinux_sock_rcv_skb_compat
(
sk
,
skb
,
family
);
secmark_active
=
selinux_secmark_enabled
();
peerlbl_active
=
netlbl_enabled
()
||
selinux_xfrm_enabled
();
if
(
!
secmark_active
&&
!
peerlbl_active
)
return
0
;
AVC_AUDIT_DATA_INIT
(
&
ad
,
NET
);
ad
.
u
.
net
.
netif
=
skb
->
iif
;
ad
.
u
.
net
.
family
=
family
;
...
...
@@ -4133,15 +4160,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
if
(
err
)
return
err
;
/* If any sort of compatibility mode is enabled then handoff processing
* to the selinux_sock_rcv_skb_compat() function to deal with the
* special handling. We do this in an attempt to keep this function
* as fast and as clean as possible. */
if
(
selinux_compat_net
||
!
selinux_policycap_netpeer
)
return
selinux_sock_rcv_skb_compat
(
sk
,
skb
,
&
ad
,
family
,
addrp
);
if
(
netlbl_enabled
()
||
selinux_xfrm_enabled
())
{
if
(
peerlbl_active
)
{
u32
peer_sid
;
err
=
selinux_skb_peerlbl_sid
(
skb
,
family
,
&
peer_sid
);
...
...
@@ -4149,13 +4168,17 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
return
err
;
err
=
selinux_inet_sys_rcv_skb
(
skb
->
iif
,
addrp
,
family
,
peer_sid
,
&
ad
);
if
(
err
)
if
(
err
)
{
selinux_netlbl_err
(
skb
,
err
,
0
);
return
err
;
}
err
=
avc_has_perm
(
sk_sid
,
peer_sid
,
SECCLASS_PEER
,
PEER__RECV
,
&
ad
);
if
(
err
)
selinux_netlbl_err
(
skb
,
err
,
0
);
}
if
(
se
linux_secmark_enabled
()
)
{
if
(
se
cmark_active
)
{
err
=
avc_has_perm
(
sk_sid
,
skb
->
secmark
,
SECCLASS_PACKET
,
PACKET__RECV
,
&
ad
);
if
(
err
)
...
...
@@ -4214,10 +4237,12 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
u32
peer_secid
=
SECSID_NULL
;
u16
family
;
if
(
sock
)
if
(
skb
&&
skb
->
protocol
==
htons
(
ETH_P_IP
))
family
=
PF_INET
;
else
if
(
skb
&&
skb
->
protocol
==
htons
(
ETH_P_IPV6
))
family
=
PF_INET6
;
else
if
(
sock
)
family
=
sock
->
sk
->
sk_family
;
else
if
(
skb
&&
skb
->
sk
)
family
=
skb
->
sk
->
sk_family
;
else
goto
out
;
...
...
@@ -4275,8 +4300,6 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent)
sk
->
sk_family
==
PF_UNIX
)
isec
->
sid
=
sksec
->
sid
;
sksec
->
sclass
=
isec
->
sclass
;
selinux_netlbl_sock_graft
(
sk
,
parent
);
}
static
int
selinux_inet_conn_request
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
,
...
...
@@ -4284,10 +4307,15 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
{
struct
sk_security_struct
*
sksec
=
sk
->
sk_security
;
int
err
;
u16
family
=
sk
->
sk_family
;
u32
newsid
;
u32
peersid
;
err
=
selinux_skb_peerlbl_sid
(
skb
,
sk
->
sk_family
,
&
peersid
);
/* handle mapped IPv4 packets arriving via IPv6 sockets */
if
(
family
==
PF_INET6
&&
skb
->
protocol
==
htons
(
ETH_P_IP
))
family
=
PF_INET
;
err
=
selinux_skb_peerlbl_sid
(
skb
,
family
,
&
peersid
);
if
(
err
)
return
err
;
if
(
peersid
==
SECSID_NULL
)
{
...
...
@@ -4322,12 +4350,18 @@ static void selinux_inet_csk_clone(struct sock *newsk,
selinux_netlbl_sk_security_reset
(
newsksec
,
req
->
rsk_ops
->
family
);
}
static
void
selinux_inet_conn_established
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
static
void
selinux_inet_conn_established
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
{
u16
family
=
sk
->
sk_family
;
struct
sk_security_struct
*
sksec
=
sk
->
sk_security
;
selinux_skb_peerlbl_sid
(
skb
,
sk
->
sk_family
,
&
sksec
->
peer_sid
);
/* handle mapped IPv4 packets arriving via IPv6 sockets */
if
(
family
==
PF_INET6
&&
skb
->
protocol
==
htons
(
ETH_P_IP
))
family
=
PF_INET
;
selinux_skb_peerlbl_sid
(
skb
,
family
,
&
sksec
->
peer_sid
);
selinux_netlbl_inet_conn_established
(
sk
,
family
);
}
static
void
selinux_req_classify_flow
(
const
struct
request_sock
*
req
,
...
...
@@ -4377,39 +4411,54 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
static
unsigned
int
selinux_ip_forward
(
struct
sk_buff
*
skb
,
int
ifindex
,
u16
family
)
{
int
err
;
char
*
addrp
;
u32
peer_sid
;
struct
avc_audit_data
ad
;
u8
secmark_active
;
u8
netlbl_active
;
u8
peerlbl_active
;
if
(
!
selinux_policycap_netpeer
)
return
NF_ACCEPT
;
secmark_active
=
selinux_secmark_enabled
();
peerlbl_active
=
netlbl_enabled
()
||
selinux_xfrm_enabled
();
netlbl_active
=
netlbl_enabled
();
peerlbl_active
=
netlbl_active
||
selinux_xfrm_enabled
();
if
(
!
secmark_active
&&
!
peerlbl_active
)
return
NF_ACCEPT
;
if
(
selinux_skb_peerlbl_sid
(
skb
,
family
,
&
peer_sid
)
!=
0
)
return
NF_DROP
;
AVC_AUDIT_DATA_INIT
(
&
ad
,
NET
);
ad
.
u
.
net
.
netif
=
ifindex
;
ad
.
u
.
net
.
family
=
family
;
if
(
selinux_parse_skb
(
skb
,
&
ad
,
&
addrp
,
1
,
NULL
)
!=
0
)
return
NF_DROP
;
if
(
selinux_skb_peerlbl_sid
(
skb
,
family
,
&
peer_sid
)
!=
0
)
return
NF_DROP
;
if
(
peerlbl_active
)
if
(
selinux_inet_sys_rcv_skb
(
ifindex
,
addrp
,
family
,
peer_sid
,
&
ad
)
!=
0
)
if
(
peerlbl_active
)
{
err
=
selinux_inet_sys_rcv_skb
(
ifindex
,
addrp
,
family
,
peer_sid
,
&
ad
);
if
(
err
)
{
selinux_netlbl_err
(
skb
,
err
,
1
);
return
NF_DROP
;
}
}
if
(
secmark_active
)
if
(
avc_has_perm
(
peer_sid
,
skb
->
secmark
,
SECCLASS_PACKET
,
PACKET__FORWARD_IN
,
&
ad
))
return
NF_DROP
;
if
(
netlbl_active
)
/* we do this in the FORWARD path and not the POST_ROUTING
* path because we want to make sure we apply the necessary
* labeling before IPsec is applied so we can leverage AH
* protection */
if
(
selinux_netlbl_skbuff_setsid
(
skb
,
family
,
peer_sid
)
!=
0
)
return
NF_DROP
;
return
NF_ACCEPT
;
}
...
...
@@ -4433,6 +4482,37 @@ static unsigned int selinux_ipv6_forward(unsigned int hooknum,
}
#endif
/* IPV6 */
static
unsigned
int
selinux_ip_output
(
struct
sk_buff
*
skb
,
u16
family
)
{
u32
sid
;
if
(
!
netlbl_enabled
())
return
NF_ACCEPT
;
/* we do this in the LOCAL_OUT path and not the POST_ROUTING path
* because we want to make sure we apply the necessary labeling
* before IPsec is applied so we can leverage AH protection */
if
(
skb
->
sk
)
{
struct
sk_security_struct
*
sksec
=
skb
->
sk
->
sk_security
;
sid
=
sksec
->
sid
;
}
else
sid
=
SECINITSID_KERNEL
;
if
(
selinux_netlbl_skbuff_setsid
(
skb
,
family
,
sid
)
!=
0
)
return
NF_DROP
;
return
NF_ACCEPT
;
}
static
unsigned
int
selinux_ipv4_output
(
unsigned
int
hooknum
,
struct
sk_buff
*
skb
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
int
(
*
okfn
)(
struct
sk_buff
*
))
{
return
selinux_ip_output
(
skb
,
PF_INET
);
}
static
int
selinux_ip_postroute_iptables_compat
(
struct
sock
*
sk
,
int
ifindex
,
struct
avc_audit_data
*
ad
,
...
...
@@ -4500,30 +4580,36 @@ static int selinux_ip_postroute_iptables_compat(struct sock *sk,
static
unsigned
int
selinux_ip_postroute_compat
(
struct
sk_buff
*
skb
,
int
ifindex
,
struct
avc_audit_data
*
ad
,
u16
family
,
char
*
addrp
,
u8
proto
)
u16
family
)
{
struct
sock
*
sk
=
skb
->
sk
;
struct
sk_security_struct
*
sksec
;
struct
avc_audit_data
ad
;
char
*
addrp
;
u8
proto
;
if
(
sk
==
NULL
)
return
NF_ACCEPT
;
sksec
=
sk
->
sk_security
;
AVC_AUDIT_DATA_INIT
(
&
ad
,
NET
);
ad
.
u
.
net
.
netif
=
ifindex
;
ad
.
u
.
net
.
family
=
family
;
if
(
selinux_parse_skb
(
skb
,
&
ad
,
&
addrp
,
0
,
&
proto
))
return
NF_DROP
;
if
(
selinux_compat_net
)
{
if
(
selinux_ip_postroute_iptables_compat
(
skb
->
sk
,
ifindex
,
ad
,
family
,
addrp
))
&
ad
,
family
,
addrp
))
return
NF_DROP
;
}
else
{
if
(
avc_has_perm
(
sksec
->
sid
,
skb
->
secmark
,
SECCLASS_PACKET
,
PACKET__SEND
,
ad
))
SECCLASS_PACKET
,
PACKET__SEND
,
&
ad
))
return
NF_DROP
;
}
if
(
selinux_policycap_netpeer
)
if
(
selinux_xfrm_postroute_last
(
sksec
->
sid
,
skb
,
ad
,
proto
))
if
(
selinux_xfrm_postroute_last
(
sksec
->
sid
,
skb
,
&
ad
,
proto
))
return
NF_DROP
;
return
NF_ACCEPT
;
...
...
@@ -4537,23 +4623,15 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
struct
sock
*
sk
;
struct
avc_audit_data
ad
;
char
*
addrp
;
u8
proto
;
u8
secmark_active
;
u8
peerlbl_active
;
AVC_AUDIT_DATA_INIT
(
&
ad
,
NET
);
ad
.
u
.
net
.
netif
=
ifindex
;
ad
.
u
.
net
.
family
=
family
;
if
(
selinux_parse_skb
(
skb
,
&
ad
,
&
addrp
,
0
,
&
proto
))
return
NF_DROP
;
/* If any sort of compatibility mode is enabled then handoff processing
* to the selinux_ip_postroute_compat() function to deal with the
* special handling. We do this in an attempt to keep this function
* as fast and as clean as possible. */
if
(
selinux_compat_net
||
!
selinux_policycap_netpeer
)
return
selinux_ip_postroute_compat
(
skb
,
ifindex
,
&
ad
,
family
,
addrp
,
proto
);
return
selinux_ip_postroute_compat
(
skb
,
ifindex
,
family
);
/* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
* packet transformation so allow the packet to pass without any checks
...
...
@@ -4569,21 +4647,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
if
(
!
secmark_active
&&
!
peerlbl_active
)
return
NF_ACCEPT
;
/* if the packet is
locally generated (skb->sk != NULL) then use
the
*
socket's label as the peer label, otherwise the packet is being
*
forwarded through this system and we need to fetch
the peer label
*
directly from the packet
*/
/* if the packet is
being forwarded then get the peer label from
the
*
packet itself; otherwise check to see if it is from a local
*
application or the kernel, if from an application get
the peer label
*
from the sending socket, otherwise use the kernel's sid
*/
sk
=
skb
->
sk
;
if
(
sk
)
{
if
(
sk
==
NULL
)
{
switch
(
family
)
{
case
PF_INET
:
if
(
IPCB
(
skb
)
->
flags
&
IPSKB_FORWARDED
)
secmark_perm
=
PACKET__FORWARD_OUT
;
else
secmark_perm
=
PACKET__SEND
;
break
;
case
PF_INET6
:
if
(
IP6CB
(
skb
)
->
flags
&
IP6SKB_FORWARDED
)
secmark_perm
=
PACKET__FORWARD_OUT
;
else
secmark_perm
=
PACKET__SEND
;
break
;
default:
return
NF_DROP
;
}
if
(
secmark_perm
==
PACKET__FORWARD_OUT
)
{
if
(
selinux_skb_peerlbl_sid
(
skb
,
family
,
&
peer_sid
))
return
NF_DROP
;
}
else
peer_sid
=
SECINITSID_KERNEL
;
}
else
{
struct
sk_security_struct
*
sksec
=
sk
->
sk_security
;
peer_sid
=
sksec
->
sid
;
secmark_perm
=
PACKET__SEND
;
}
else
{
if
(
selinux_skb_peerlbl_sid
(
skb
,
family
,
&
peer_sid
))
return
NF_DROP
;
secmark_perm
=
PACKET__FORWARD_OUT
;
}
AVC_AUDIT_DATA_INIT
(
&
ad
,
NET
);
ad
.
u
.
net
.
netif
=
ifindex
;
ad
.
u
.
net
.
family
=
family
;
if
(
selinux_parse_skb
(
skb
,
&
ad
,
&
addrp
,
0
,
NULL
))
return
NF_DROP
;
if
(
secmark_active
)
if
(
avc_has_perm
(
peer_sid
,
skb
->
secmark
,
SECCLASS_PACKET
,
secmark_perm
,
&
ad
))
...
...
@@ -5657,6 +5759,13 @@ static struct nf_hook_ops selinux_ipv4_ops[] = {
.
pf
=
PF_INET
,
.
hooknum
=
NF_INET_FORWARD
,
.
priority
=
NF_IP_PRI_SELINUX_FIRST
,
},
{
.
hook
=
selinux_ipv4_output
,
.
owner
=
THIS_MODULE
,
.
pf
=
PF_INET
,
.
hooknum
=
NF_INET_LOCAL_OUT
,
.
priority
=
NF_IP_PRI_SELINUX_FIRST
,
}
};
...
...
security/selinux/include/netlabel.h
浏览文件 @
93db6286
...
...
@@ -39,6 +39,9 @@
#ifdef CONFIG_NETLABEL
void
selinux_netlbl_cache_invalidate
(
void
);
void
selinux_netlbl_err
(
struct
sk_buff
*
skb
,
int
error
,
int
gateway
);
void
selinux_netlbl_sk_security_free
(
struct
sk_security_struct
*
ssec
);
void
selinux_netlbl_sk_security_reset
(
struct
sk_security_struct
*
ssec
,
int
family
);
...
...
@@ -46,8 +49,11 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
u16
family
,
u32
*
type
,
u32
*
sid
);
int
selinux_netlbl_skbuff_setsid
(
struct
sk_buff
*
skb
,
u16
family
,
u32
sid
);
void
selinux_netlbl_
sock_graft
(
struct
sock
*
sk
,
struct
socket
*
sock
);
void
selinux_netlbl_
inet_conn_established
(
struct
sock
*
sk
,
u16
family
);
int
selinux_netlbl_socket_post_create
(
struct
socket
*
sock
);
int
selinux_netlbl_inode_permission
(
struct
inode
*
inode
,
int
mask
);
int
selinux_netlbl_sock_rcv_skb
(
struct
sk_security_struct
*
sksec
,
...
...
@@ -57,12 +63,27 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
int
selinux_netlbl_socket_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
);
int
selinux_netlbl_socket_connect
(
struct
sock
*
sk
,
struct
sockaddr
*
addr
);
#else
static
inline
void
selinux_netlbl_cache_invalidate
(
void
)
{
return
;
}
static
inline
void
selinux_netlbl_err
(
struct
sk_buff
*
skb
,
int
error
,
int
gateway
)
{
return
;
}
static
inline
void
selinux_netlbl_sk_security_free
(
struct
sk_security_struct
*
ssec
)
{
return
;
}
static
inline
void
selinux_netlbl_sk_security_reset
(
struct
sk_security_struct
*
ssec
,
int
family
)
...
...
@@ -79,9 +100,21 @@ static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
*
sid
=
SECSID_NULL
;
return
0
;
}
static
inline
int
selinux_netlbl_skbuff_setsid
(
struct
sk_buff
*
skb
,
u16
family
,
u32
sid
)
{
return
0
;
}
static
inline
void
selinux_netlbl_sock_graft
(
struct
sock
*
sk
,
struct
socket
*
sock
)
static
inline
int
selinux_netlbl_conn_setsid
(
struct
sock
*
sk
,
struct
sockaddr
*
addr
)
{
return
0
;
}
static
inline
void
selinux_netlbl_inet_conn_established
(
struct
sock
*
sk
,
u16
family
)
{
return
;
}
...
...
@@ -107,6 +140,11 @@ static inline int selinux_netlbl_socket_setsockopt(struct socket *sock,
{
return
0
;
}
static
inline
int
selinux_netlbl_socket_connect
(
struct
sock
*
sk
,
struct
sockaddr
*
addr
)
{
return
0
;
}
#endif
/* CONFIG_NETLABEL */
#endif
security/selinux/include/objsec.h
浏览文件 @
93db6286
此差异已折叠。
点击以展开。
security/selinux/netlabel.c
浏览文件 @
93db6286
此差异已折叠。
点击以展开。
security/selinux/ss/services.c
浏览文件 @
93db6286
此差异已折叠。
点击以展开。
security/smack/smack_lsm.c
浏览文件 @
93db6286
此差异已折叠。
点击以展开。
security/smack/smackfs.c
浏览文件 @
93db6286
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录