diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-25 20:39:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-25 20:39:55 -0400 |
commit | 7e4720201ad44ace85a443f41d668a62a737e7d0 (patch) | |
tree | 8b9118dffcfd9511d9ce31b87776e04095f9acf1 | |
parent | 7b29122f9ec54db5c38a66a11127d94db0817c17 (diff) | |
parent | 4cc6773508299377099aa30cf30e6a2196c5872d (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
[NetLabel]: update docs with website information
[NetLabel]: rework the Netlink attribute handling (part 2)
[NetLabel]: rework the Netlink attribute handling (part 1)
[Netlink]: add nla_validate_nested()
[NETLINK]: add nla_for_each_nested() to the interface list
[NetLabel]: change the SELinux permissions
[NetLabel]: make the CIPSOv4 cache spinlocks bottom half safe
[NetLabel]: correct improper handling of non-NetLabel peer contexts
[TCP]: make cubic the default
[TCP]: default congestion control menu
[ATM] he: Fix __init/__devinit conflict
[NETFILTER]: Add dscp,DSCP headers to header-y
[DCCP]: Introduce dccp_probe
[DCCP]: Use constants for CCIDs
[DCCP]: Introduce constants for CCID numbers
[DCCP]: Allow default/fallback service code.
32 files changed, 1389 insertions, 1505 deletions
diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt index c45daabd3bfe..74563b38ffd9 100644 --- a/Documentation/networking/dccp.txt +++ b/Documentation/networking/dccp.txt | |||
@@ -1,7 +1,6 @@ | |||
1 | DCCP protocol | 1 | DCCP protocol |
2 | ============ | 2 | ============ |
3 | 3 | ||
4 | Last updated: 10 November 2005 | ||
5 | 4 | ||
6 | Contents | 5 | Contents |
7 | ======== | 6 | ======== |
@@ -42,8 +41,11 @@ Socket options | |||
42 | DCCP_SOCKOPT_PACKET_SIZE is used for CCID3 to set default packet size for | 41 | DCCP_SOCKOPT_PACKET_SIZE is used for CCID3 to set default packet size for |
43 | calculations. | 42 | calculations. |
44 | 43 | ||
45 | DCCP_SOCKOPT_SERVICE sets the service. This is compulsory as per the | 44 | DCCP_SOCKOPT_SERVICE sets the service. The specification mandates use of |
46 | specification. If you don't set it you will get EPROTO. | 45 | service codes (RFC 4340, sec. 8.1.2); if this socket option is not set, |
46 | the socket will fall back to 0 (which means that no meaningful service code | ||
47 | is present). Connecting sockets set at most one service option; for | ||
48 | listening sockets, multiple service codes can be specified. | ||
47 | 49 | ||
48 | Notes | 50 | Notes |
49 | ===== | 51 | ===== |
diff --git a/MAINTAINERS b/MAINTAINERS index 16af51ba44a5..23348c0d37bc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -2031,6 +2031,13 @@ L: netfilter@lists.netfilter.org | |||
2031 | L: netfilter-devel@lists.netfilter.org | 2031 | L: netfilter-devel@lists.netfilter.org |
2032 | S: Supported | 2032 | S: Supported |
2033 | 2033 | ||
2034 | NETLABEL | ||
2035 | P: Paul Moore | ||
2036 | M: paul.moore@hp.com | ||
2037 | W: http://netlabel.sf.net | ||
2038 | L: netdev@vger.kernel.org | ||
2039 | S: Supported | ||
2040 | |||
2034 | NETROM NETWORK LAYER | 2041 | NETROM NETWORK LAYER |
2035 | P: Ralf Baechle | 2042 | P: Ralf Baechle |
2036 | M: ralf@linux-mips.org | 2043 | M: ralf@linux-mips.org |
diff --git a/drivers/atm/he.c b/drivers/atm/he.c index 41e052fecd7f..f2511b42dba2 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c | |||
@@ -454,7 +454,7 @@ rate_to_atmf(unsigned rate) /* cps to atm forum format */ | |||
454 | return (NONZERO | (exp << 9) | (rate & 0x1ff)); | 454 | return (NONZERO | (exp << 9) | (rate & 0x1ff)); |
455 | } | 455 | } |
456 | 456 | ||
457 | static void __init | 457 | static void __devinit |
458 | he_init_rx_lbfp0(struct he_dev *he_dev) | 458 | he_init_rx_lbfp0(struct he_dev *he_dev) |
459 | { | 459 | { |
460 | unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; | 460 | unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; |
@@ -485,7 +485,7 @@ he_init_rx_lbfp0(struct he_dev *he_dev) | |||
485 | he_writel(he_dev, he_dev->r0_numbuffs, RLBF0_C); | 485 | he_writel(he_dev, he_dev->r0_numbuffs, RLBF0_C); |
486 | } | 486 | } |
487 | 487 | ||
488 | static void __init | 488 | static void __devinit |
489 | he_init_rx_lbfp1(struct he_dev *he_dev) | 489 | he_init_rx_lbfp1(struct he_dev *he_dev) |
490 | { | 490 | { |
491 | unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; | 491 | unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; |
@@ -516,7 +516,7 @@ he_init_rx_lbfp1(struct he_dev *he_dev) | |||
516 | he_writel(he_dev, he_dev->r1_numbuffs, RLBF1_C); | 516 | he_writel(he_dev, he_dev->r1_numbuffs, RLBF1_C); |
517 | } | 517 | } |
518 | 518 | ||
519 | static void __init | 519 | static void __devinit |
520 | he_init_tx_lbfp(struct he_dev *he_dev) | 520 | he_init_tx_lbfp(struct he_dev *he_dev) |
521 | { | 521 | { |
522 | unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; | 522 | unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; |
@@ -546,7 +546,7 @@ he_init_tx_lbfp(struct he_dev *he_dev) | |||
546 | he_writel(he_dev, lbufd_index - 1, TLBF_T); | 546 | he_writel(he_dev, lbufd_index - 1, TLBF_T); |
547 | } | 547 | } |
548 | 548 | ||
549 | static int __init | 549 | static int __devinit |
550 | he_init_tpdrq(struct he_dev *he_dev) | 550 | he_init_tpdrq(struct he_dev *he_dev) |
551 | { | 551 | { |
552 | he_dev->tpdrq_base = pci_alloc_consistent(he_dev->pci_dev, | 552 | he_dev->tpdrq_base = pci_alloc_consistent(he_dev->pci_dev, |
@@ -568,7 +568,7 @@ he_init_tpdrq(struct he_dev *he_dev) | |||
568 | return 0; | 568 | return 0; |
569 | } | 569 | } |
570 | 570 | ||
571 | static void __init | 571 | static void __devinit |
572 | he_init_cs_block(struct he_dev *he_dev) | 572 | he_init_cs_block(struct he_dev *he_dev) |
573 | { | 573 | { |
574 | unsigned clock, rate, delta; | 574 | unsigned clock, rate, delta; |
@@ -664,7 +664,7 @@ he_init_cs_block(struct he_dev *he_dev) | |||
664 | 664 | ||
665 | } | 665 | } |
666 | 666 | ||
667 | static int __init | 667 | static int __devinit |
668 | he_init_cs_block_rcm(struct he_dev *he_dev) | 668 | he_init_cs_block_rcm(struct he_dev *he_dev) |
669 | { | 669 | { |
670 | unsigned (*rategrid)[16][16]; | 670 | unsigned (*rategrid)[16][16]; |
@@ -785,7 +785,7 @@ he_init_cs_block_rcm(struct he_dev *he_dev) | |||
785 | return 0; | 785 | return 0; |
786 | } | 786 | } |
787 | 787 | ||
788 | static int __init | 788 | static int __devinit |
789 | he_init_group(struct he_dev *he_dev, int group) | 789 | he_init_group(struct he_dev *he_dev, int group) |
790 | { | 790 | { |
791 | int i; | 791 | int i; |
@@ -955,7 +955,7 @@ he_init_group(struct he_dev *he_dev, int group) | |||
955 | return 0; | 955 | return 0; |
956 | } | 956 | } |
957 | 957 | ||
958 | static int __init | 958 | static int __devinit |
959 | he_init_irq(struct he_dev *he_dev) | 959 | he_init_irq(struct he_dev *he_dev) |
960 | { | 960 | { |
961 | int i; | 961 | int i; |
diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 2d7671c92c0b..d6f4ec467a4b 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h | |||
@@ -169,6 +169,12 @@ enum { | |||
169 | DCCPO_MAX_CCID_SPECIFIC = 255, | 169 | DCCPO_MAX_CCID_SPECIFIC = 255, |
170 | }; | 170 | }; |
171 | 171 | ||
172 | /* DCCP CCIDS */ | ||
173 | enum { | ||
174 | DCCPC_CCID2 = 2, | ||
175 | DCCPC_CCID3 = 3, | ||
176 | }; | ||
177 | |||
172 | /* DCCP features */ | 178 | /* DCCP features */ |
173 | enum { | 179 | enum { |
174 | DCCPF_RESERVED = 0, | 180 | DCCPF_RESERVED = 0, |
@@ -320,7 +326,7 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) | |||
320 | /* initial values for each feature */ | 326 | /* initial values for each feature */ |
321 | #define DCCPF_INITIAL_SEQUENCE_WINDOW 100 | 327 | #define DCCPF_INITIAL_SEQUENCE_WINDOW 100 |
322 | #define DCCPF_INITIAL_ACK_RATIO 2 | 328 | #define DCCPF_INITIAL_ACK_RATIO 2 |
323 | #define DCCPF_INITIAL_CCID 2 | 329 | #define DCCPF_INITIAL_CCID DCCPC_CCID2 |
324 | #define DCCPF_INITIAL_SEND_ACK_VECTOR 1 | 330 | #define DCCPF_INITIAL_SEND_ACK_VECTOR 1 |
325 | /* FIXME: for now we're default to 1 but it should really be 0 */ | 331 | /* FIXME: for now we're default to 1 but it should really be 0 */ |
326 | #define DCCPF_INITIAL_SEND_NDP_COUNT 1 | 332 | #define DCCPF_INITIAL_SEND_NDP_COUNT 1 |
@@ -404,6 +410,7 @@ struct dccp_service_list { | |||
404 | }; | 410 | }; |
405 | 411 | ||
406 | #define DCCP_SERVICE_INVALID_VALUE htonl((__u32)-1) | 412 | #define DCCP_SERVICE_INVALID_VALUE htonl((__u32)-1) |
413 | #define DCCP_SERVICE_CODE_IS_ABSENT 0 | ||
407 | 414 | ||
408 | static inline int dccp_list_has_service(const struct dccp_service_list *sl, | 415 | static inline int dccp_list_has_service(const struct dccp_service_list *sl, |
409 | const __be32 service) | 416 | const __be32 service) |
@@ -484,11 +491,6 @@ static inline struct dccp_minisock *dccp_msk(const struct sock *sk) | |||
484 | return (struct dccp_minisock *)&dccp_sk(sk)->dccps_minisock; | 491 | return (struct dccp_minisock *)&dccp_sk(sk)->dccps_minisock; |
485 | } | 492 | } |
486 | 493 | ||
487 | static inline int dccp_service_not_initialized(const struct sock *sk) | ||
488 | { | ||
489 | return dccp_sk(sk)->dccps_service == DCCP_SERVICE_INVALID_VALUE; | ||
490 | } | ||
491 | |||
492 | static inline const char *dccp_role(const struct sock *sk) | 494 | static inline const char *dccp_role(const struct sock *sk) |
493 | { | 495 | { |
494 | switch (dccp_sk(sk)->dccps_role) { | 496 | switch (dccp_sk(sk)->dccps_role) { |
diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild index 9a285cecf249..312bd2ffee33 100644 --- a/include/linux/netfilter/Kbuild +++ b/include/linux/netfilter/Kbuild | |||
@@ -10,6 +10,8 @@ header-y += xt_connmark.h | |||
10 | header-y += xt_CONNMARK.h | 10 | header-y += xt_CONNMARK.h |
11 | header-y += xt_conntrack.h | 11 | header-y += xt_conntrack.h |
12 | header-y += xt_dccp.h | 12 | header-y += xt_dccp.h |
13 | header-y += xt_dscp.h | ||
14 | header-y += xt_DSCP.h | ||
13 | header-y += xt_esp.h | 15 | header-y += xt_esp.h |
14 | header-y += xt_helper.h | 16 | header-y += xt_helper.h |
15 | header-y += xt_length.h | 17 | header-y += xt_length.h |
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h index 59406e0dc5b2..2d72496c2029 100644 --- a/include/net/cipso_ipv4.h +++ b/include/net/cipso_ipv4.h | |||
@@ -130,8 +130,9 @@ extern int cipso_v4_rbm_strictvalid; | |||
130 | int cipso_v4_doi_add(struct cipso_v4_doi *doi_def); | 130 | int cipso_v4_doi_add(struct cipso_v4_doi *doi_def); |
131 | int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head)); | 131 | int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head)); |
132 | struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi); | 132 | struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi); |
133 | struct sk_buff *cipso_v4_doi_dump_all(size_t headroom); | 133 | int cipso_v4_doi_walk(u32 *skip_cnt, |
134 | struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom); | 134 | int (*callback) (struct cipso_v4_doi *doi_def, void *arg), |
135 | void *cb_arg); | ||
135 | int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain); | 136 | int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain); |
136 | int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, | 137 | int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, |
137 | const char *domain); | 138 | const char *domain); |
@@ -152,14 +153,11 @@ static inline struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi) | |||
152 | return NULL; | 153 | return NULL; |
153 | } | 154 | } |
154 | 155 | ||
155 | static inline struct sk_buff *cipso_v4_doi_dump_all(size_t headroom) | 156 | static inline int cipso_v4_doi_walk(u32 *skip_cnt, |
157 | int (*callback) (struct cipso_v4_doi *doi_def, void *arg), | ||
158 | void *cb_arg) | ||
156 | { | 159 | { |
157 | return NULL; | 160 | return 0; |
158 | } | ||
159 | |||
160 | static inline struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom) | ||
161 | { | ||
162 | return NULL; | ||
163 | } | 161 | } |
164 | 162 | ||
165 | static inline int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, | 163 | static inline int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, |
@@ -205,6 +203,7 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway); | |||
205 | int cipso_v4_socket_setattr(const struct socket *sock, | 203 | int cipso_v4_socket_setattr(const struct socket *sock, |
206 | const struct cipso_v4_doi *doi_def, | 204 | const struct cipso_v4_doi *doi_def, |
207 | const struct netlbl_lsm_secattr *secattr); | 205 | const struct netlbl_lsm_secattr *secattr); |
206 | int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr); | ||
208 | int cipso_v4_socket_getattr(const struct socket *sock, | 207 | int cipso_v4_socket_getattr(const struct socket *sock, |
209 | struct netlbl_lsm_secattr *secattr); | 208 | struct netlbl_lsm_secattr *secattr); |
210 | int cipso_v4_skbuff_getattr(const struct sk_buff *skb, | 209 | int cipso_v4_skbuff_getattr(const struct sk_buff *skb, |
@@ -225,6 +224,12 @@ static inline int cipso_v4_socket_setattr(const struct socket *sock, | |||
225 | return -ENOSYS; | 224 | return -ENOSYS; |
226 | } | 225 | } |
227 | 226 | ||
227 | static inline int cipso_v4_sock_getattr(struct sock *sk, | ||
228 | struct netlbl_lsm_secattr *secattr) | ||
229 | { | ||
230 | return -ENOSYS; | ||
231 | } | ||
232 | |||
228 | static inline int cipso_v4_socket_getattr(const struct socket *sock, | 233 | static inline int cipso_v4_socket_getattr(const struct socket *sock, |
229 | struct netlbl_lsm_secattr *secattr) | 234 | struct netlbl_lsm_secattr *secattr) |
230 | { | 235 | { |
diff --git a/include/net/netlabel.h b/include/net/netlabel.h index dd5780b36919..6692430063fd 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h | |||
@@ -57,9 +57,8 @@ | |||
57 | * The payload is dependent on the subsystem specified in the | 57 | * The payload is dependent on the subsystem specified in the |
58 | * 'nlmsghdr->nlmsg_type' and should be defined below, supporting functions | 58 | * 'nlmsghdr->nlmsg_type' and should be defined below, supporting functions |
59 | * should be defined in the corresponding net/netlabel/netlabel_<subsys>.h|c | 59 | * should be defined in the corresponding net/netlabel/netlabel_<subsys>.h|c |
60 | * file. All of the fields in the NetLabel payload are NETLINK attributes, the | 60 | * file. All of the fields in the NetLabel payload are NETLINK attributes, see |
61 | * length of each field is the length of the NETLINK attribute payload, see | 61 | * the include/net/netlink.h file for more information on NETLINK attributes. |
62 | * include/net/netlink.h for more information on NETLINK attributes. | ||
63 | * | 62 | * |
64 | */ | 63 | */ |
65 | 64 | ||
@@ -82,50 +81,6 @@ | |||
82 | #define NETLBL_NLTYPE_UNLABELED 5 | 81 | #define NETLBL_NLTYPE_UNLABELED 5 |
83 | #define NETLBL_NLTYPE_UNLABELED_NAME "NLBL_UNLBL" | 82 | #define NETLBL_NLTYPE_UNLABELED_NAME "NLBL_UNLBL" |
84 | 83 | ||
85 | /* NetLabel return codes */ | ||
86 | #define NETLBL_E_OK 0 | ||
87 | |||
88 | /* | ||
89 | * Helper functions | ||
90 | */ | ||
91 | |||
92 | #define NETLBL_LEN_U8 nla_total_size(sizeof(u8)) | ||
93 | #define NETLBL_LEN_U16 nla_total_size(sizeof(u16)) | ||
94 | #define NETLBL_LEN_U32 nla_total_size(sizeof(u32)) | ||
95 | |||
96 | /** | ||
97 | * netlbl_netlink_alloc_skb - Allocate a NETLINK message buffer | ||
98 | * @head: the amount of headroom in bytes | ||
99 | * @body: the desired size (minus headroom) in bytes | ||
100 | * @gfp_flags: the alloc flags to pass to alloc_skb() | ||
101 | * | ||
102 | * Description: | ||
103 | * Allocate a NETLINK message buffer based on the sizes given in @head and | ||
104 | * @body. If @head is greater than zero skb_reserve() is called to reserve | ||
105 | * @head bytes at the start of the buffer. Returns a valid sk_buff pointer on | ||
106 | * success, NULL on failure. | ||
107 | * | ||
108 | */ | ||
109 | static inline struct sk_buff *netlbl_netlink_alloc_skb(size_t head, | ||
110 | size_t body, | ||
111 | gfp_t gfp_flags) | ||
112 | { | ||
113 | struct sk_buff *skb; | ||
114 | |||
115 | skb = alloc_skb(NLMSG_ALIGN(head + body), gfp_flags); | ||
116 | if (skb == NULL) | ||
117 | return NULL; | ||
118 | if (head > 0) { | ||
119 | skb_reserve(skb, head); | ||
120 | if (skb_tailroom(skb) < body) { | ||
121 | kfree_skb(skb); | ||
122 | return NULL; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | return skb; | ||
127 | } | ||
128 | |||
129 | /* | 84 | /* |
130 | * NetLabel - Kernel API for accessing the network packet label mappings. | 85 | * NetLabel - Kernel API for accessing the network packet label mappings. |
131 | * | 86 | * |
@@ -238,6 +193,8 @@ static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr, | |||
238 | #ifdef CONFIG_NETLABEL | 193 | #ifdef CONFIG_NETLABEL |
239 | int netlbl_socket_setattr(const struct socket *sock, | 194 | int netlbl_socket_setattr(const struct socket *sock, |
240 | const struct netlbl_lsm_secattr *secattr); | 195 | const struct netlbl_lsm_secattr *secattr); |
196 | int netlbl_sock_getattr(struct sock *sk, | ||
197 | struct netlbl_lsm_secattr *secattr); | ||
241 | int netlbl_socket_getattr(const struct socket *sock, | 198 | int netlbl_socket_getattr(const struct socket *sock, |
242 | struct netlbl_lsm_secattr *secattr); | 199 | struct netlbl_lsm_secattr *secattr); |
243 | int netlbl_skbuff_getattr(const struct sk_buff *skb, | 200 | int netlbl_skbuff_getattr(const struct sk_buff *skb, |
@@ -250,6 +207,12 @@ static inline int netlbl_socket_setattr(const struct socket *sock, | |||
250 | return -ENOSYS; | 207 | return -ENOSYS; |
251 | } | 208 | } |
252 | 209 | ||
210 | static inline int netlbl_sock_getattr(struct sock *sk, | ||
211 | struct netlbl_lsm_secattr *secattr) | ||
212 | { | ||
213 | return -ENOSYS; | ||
214 | } | ||
215 | |||
253 | static inline int netlbl_socket_getattr(const struct socket *sock, | 216 | static inline int netlbl_socket_getattr(const struct socket *sock, |
254 | struct netlbl_lsm_secattr *secattr) | 217 | struct netlbl_lsm_secattr *secattr) |
255 | { | 218 | { |
diff --git a/include/net/netlink.h b/include/net/netlink.h index 11dc2e7f679a..4ab68a7a636a 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h | |||
@@ -146,11 +146,13 @@ | |||
146 | * nla_ok(nla, remaining) does nla fit into remaining bytes? | 146 | * nla_ok(nla, remaining) does nla fit into remaining bytes? |
147 | * nla_next(nla, remaining) get next netlink attribute | 147 | * nla_next(nla, remaining) get next netlink attribute |
148 | * nla_validate() validate a stream of attributes | 148 | * nla_validate() validate a stream of attributes |
149 | * nla_validate_nested() validate a stream of nested attributes | ||
149 | * nla_find() find attribute in stream of attributes | 150 | * nla_find() find attribute in stream of attributes |
150 | * nla_find_nested() find attribute in nested attributes | 151 | * nla_find_nested() find attribute in nested attributes |
151 | * nla_parse() parse and validate stream of attrs | 152 | * nla_parse() parse and validate stream of attrs |
152 | * nla_parse_nested() parse nested attribuets | 153 | * nla_parse_nested() parse nested attribuets |
153 | * nla_for_each_attr() loop over all attributes | 154 | * nla_for_each_attr() loop over all attributes |
155 | * nla_for_each_nested() loop over the nested attributes | ||
154 | *========================================================================= | 156 | *========================================================================= |
155 | */ | 157 | */ |
156 | 158 | ||
@@ -950,6 +952,24 @@ static inline int nla_nest_cancel(struct sk_buff *skb, struct nlattr *start) | |||
950 | } | 952 | } |
951 | 953 | ||
952 | /** | 954 | /** |
955 | * nla_validate_nested - Validate a stream of nested attributes | ||
956 | * @start: container attribute | ||
957 | * @maxtype: maximum attribute type to be expected | ||
958 | * @policy: validation policy | ||
959 | * | ||
960 | * Validates all attributes in the nested attribute stream against the | ||
961 | * specified policy. Attributes with a type exceeding maxtype will be | ||
962 | * ignored. See documenation of struct nla_policy for more details. | ||
963 | * | ||
964 | * Returns 0 on success or a negative error code. | ||
965 | */ | ||
966 | static inline int nla_validate_nested(struct nlattr *start, int maxtype, | ||
967 | struct nla_policy *policy) | ||
968 | { | ||
969 | return nla_validate(nla_data(start), nla_len(start), maxtype, policy); | ||
970 | } | ||
971 | |||
972 | /** | ||
953 | * nla_for_each_attr - iterate over a stream of attributes | 973 | * nla_for_each_attr - iterate over a stream of attributes |
954 | * @pos: loop counter, set to current attribute | 974 | * @pos: loop counter, set to current attribute |
955 | * @head: head of attribute stream | 975 | * @head: head of attribute stream |
diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig index 859e3359fcda..e2a095d0fd80 100644 --- a/net/dccp/Kconfig +++ b/net/dccp/Kconfig | |||
@@ -40,6 +40,22 @@ config IP_DCCP_DEBUG | |||
40 | 40 | ||
41 | Just say N. | 41 | Just say N. |
42 | 42 | ||
43 | config NET_DCCPPROBE | ||
44 | tristate "DCCP connection probing" | ||
45 | depends on PROC_FS && KPROBES | ||
46 | ---help--- | ||
47 | This module allows for capturing the changes to DCCP connection | ||
48 | state in response to incoming packets. It is used for debugging | ||
49 | DCCP congestion avoidance modules. If you don't understand | ||
50 | what was just said, you don't need it: say N. | ||
51 | |||
52 | Documentation on how to use the packet generator can be found | ||
53 | at http://linux-net.osdl.org/index.php/DccpProbe | ||
54 | |||
55 | To compile this code as a module, choose M here: the | ||
56 | module will be called dccp_probe. | ||
57 | |||
58 | |||
43 | endmenu | 59 | endmenu |
44 | 60 | ||
45 | endmenu | 61 | endmenu |
diff --git a/net/dccp/Makefile b/net/dccp/Makefile index 7696e219b05d..17ed99c46617 100644 --- a/net/dccp/Makefile +++ b/net/dccp/Makefile | |||
@@ -11,9 +11,11 @@ dccp_ipv4-y := ipv4.o | |||
11 | dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o | 11 | dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o |
12 | 12 | ||
13 | obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o | 13 | obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o |
14 | obj-$(CONFIG_NET_DCCPPROBE) += dccp_probe.o | ||
14 | 15 | ||
15 | dccp-$(CONFIG_SYSCTL) += sysctl.o | 16 | dccp-$(CONFIG_SYSCTL) += sysctl.o |
16 | 17 | ||
17 | dccp_diag-y := diag.o | 18 | dccp_diag-y := diag.o |
19 | dccp_probe-y := probe.o | ||
18 | 20 | ||
19 | obj-y += ccids/ | 21 | obj-y += ccids/ |
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 457dd3db7f41..2efb505aeb35 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c | |||
@@ -808,7 +808,7 @@ static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
808 | } | 808 | } |
809 | 809 | ||
810 | static struct ccid_operations ccid2 = { | 810 | static struct ccid_operations ccid2 = { |
811 | .ccid_id = 2, | 811 | .ccid_id = DCCPC_CCID2, |
812 | .ccid_name = "ccid2", | 812 | .ccid_name = "ccid2", |
813 | .ccid_owner = THIS_MODULE, | 813 | .ccid_owner = THIS_MODULE, |
814 | .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock), | 814 | .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock), |
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 195aa9566228..67d2dc0e7c67 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -1240,7 +1240,7 @@ static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len, | |||
1240 | } | 1240 | } |
1241 | 1241 | ||
1242 | static struct ccid_operations ccid3 = { | 1242 | static struct ccid_operations ccid3 = { |
1243 | .ccid_id = 3, | 1243 | .ccid_id = DCCPC_CCID3, |
1244 | .ccid_name = "ccid3", | 1244 | .ccid_name = "ccid3", |
1245 | .ccid_owner = THIS_MODULE, | 1245 | .ccid_owner = THIS_MODULE, |
1246 | .ccid_hc_tx_obj_size = sizeof(struct ccid3_hc_tx_sock), | 1246 | .ccid_hc_tx_obj_size = sizeof(struct ccid3_hc_tx_sock), |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 9a1a76a7dc41..66be29b6f508 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -56,9 +56,6 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
56 | 56 | ||
57 | dp->dccps_role = DCCP_ROLE_CLIENT; | 57 | dp->dccps_role = DCCP_ROLE_CLIENT; |
58 | 58 | ||
59 | if (dccp_service_not_initialized(sk)) | ||
60 | return -EPROTO; | ||
61 | |||
62 | if (addr_len < sizeof(struct sockaddr_in)) | 59 | if (addr_len < sizeof(struct sockaddr_in)) |
63 | return -EINVAL; | 60 | return -EINVAL; |
64 | 61 | ||
diff --git a/net/dccp/probe.c b/net/dccp/probe.c new file mode 100644 index 000000000000..146496fce2e2 --- /dev/null +++ b/net/dccp/probe.c | |||
@@ -0,0 +1,198 @@ | |||
1 | /* | ||
2 | * dccp_probe - Observe the DCCP flow with kprobes. | ||
3 | * | ||
4 | * The idea for this came from Werner Almesberger's umlsim | ||
5 | * Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org> | ||
6 | * | ||
7 | * Modified for DCCP from Stephen Hemminger's code | ||
8 | * Copyright (C) 2006, Ian McDonald <ian.mcdonald@jandi.co.nz> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/kprobes.h> | ||
27 | #include <linux/socket.h> | ||
28 | #include <linux/dccp.h> | ||
29 | #include <linux/proc_fs.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/kfifo.h> | ||
32 | #include <linux/vmalloc.h> | ||
33 | |||
34 | #include "dccp.h" | ||
35 | #include "ccid.h" | ||
36 | #include "ccids/ccid3.h" | ||
37 | |||
38 | static int port; | ||
39 | |||
40 | static int bufsize = 64 * 1024; | ||
41 | |||
42 | static const char procname[] = "dccpprobe"; | ||
43 | |||
44 | struct { | ||
45 | struct kfifo *fifo; | ||
46 | spinlock_t lock; | ||
47 | wait_queue_head_t wait; | ||
48 | struct timeval tstart; | ||
49 | } dccpw; | ||
50 | |||
51 | static void printl(const char *fmt, ...) | ||
52 | { | ||
53 | va_list args; | ||
54 | int len; | ||
55 | struct timeval now; | ||
56 | char tbuf[256]; | ||
57 | |||
58 | va_start(args, fmt); | ||
59 | do_gettimeofday(&now); | ||
60 | |||
61 | now.tv_sec -= dccpw.tstart.tv_sec; | ||
62 | now.tv_usec -= dccpw.tstart.tv_usec; | ||
63 | if (now.tv_usec < 0) { | ||
64 | --now.tv_sec; | ||
65 | now.tv_usec += 1000000; | ||
66 | } | ||
67 | |||
68 | len = sprintf(tbuf, "%lu.%06lu ", | ||
69 | (unsigned long) now.tv_sec, | ||
70 | (unsigned long) now.tv_usec); | ||
71 | len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args); | ||
72 | va_end(args); | ||
73 | |||
74 | kfifo_put(dccpw.fifo, tbuf, len); | ||
75 | wake_up(&dccpw.wait); | ||
76 | } | ||
77 | |||
78 | static int jdccp_sendmsg(struct kiocb *iocb, struct sock *sk, | ||
79 | struct msghdr *msg, size_t size) | ||
80 | { | ||
81 | const struct dccp_minisock *dmsk = dccp_msk(sk); | ||
82 | const struct inet_sock *inet = inet_sk(sk); | ||
83 | const struct ccid3_hc_tx_sock *hctx; | ||
84 | |||
85 | if (dmsk->dccpms_tx_ccid == DCCPC_CCID3) | ||
86 | hctx = ccid3_hc_tx_sk(sk); | ||
87 | else | ||
88 | hctx = NULL; | ||
89 | |||
90 | if (port == 0 || ntohs(inet->dport) == port || | ||
91 | ntohs(inet->sport) == port) { | ||
92 | if (hctx) | ||
93 | printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d %d %d %d %d\n", | ||
94 | NIPQUAD(inet->saddr), ntohs(inet->sport), | ||
95 | NIPQUAD(inet->daddr), ntohs(inet->dport), size, | ||
96 | hctx->ccid3hctx_s, hctx->ccid3hctx_rtt, | ||
97 | hctx->ccid3hctx_p, hctx->ccid3hctx_t_ipi); | ||
98 | else | ||
99 | printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d\n", | ||
100 | NIPQUAD(inet->saddr), ntohs(inet->sport), | ||
101 | NIPQUAD(inet->daddr), ntohs(inet->dport), size); | ||
102 | } | ||
103 | |||
104 | jprobe_return(); | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static struct jprobe dccp_send_probe = { | ||
109 | .kp = { .addr = (kprobe_opcode_t *)&dccp_sendmsg, }, | ||
110 | .entry = (kprobe_opcode_t *)&jdccp_sendmsg, | ||
111 | }; | ||
112 | |||
113 | static int dccpprobe_open(struct inode *inode, struct file *file) | ||
114 | { | ||
115 | kfifo_reset(dccpw.fifo); | ||
116 | do_gettimeofday(&dccpw.tstart); | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static ssize_t dccpprobe_read(struct file *file, char __user *buf, | ||
121 | size_t len, loff_t *ppos) | ||
122 | { | ||
123 | int error = 0, cnt = 0; | ||
124 | unsigned char *tbuf; | ||
125 | |||
126 | if (!buf || len < 0) | ||
127 | return -EINVAL; | ||
128 | |||
129 | if (len == 0) | ||
130 | return 0; | ||
131 | |||
132 | tbuf = vmalloc(len); | ||
133 | if (!tbuf) | ||
134 | return -ENOMEM; | ||
135 | |||
136 | error = wait_event_interruptible(dccpw.wait, | ||
137 | __kfifo_len(dccpw.fifo) != 0); | ||
138 | if (error) | ||
139 | goto out_free; | ||
140 | |||
141 | cnt = kfifo_get(dccpw.fifo, tbuf, len); | ||
142 | error = copy_to_user(buf, tbuf, cnt); | ||
143 | |||
144 | out_free: | ||
145 | vfree(tbuf); | ||
146 | |||
147 | return error ? error : cnt; | ||
148 | } | ||
149 | |||
150 | static struct file_operations dccpprobe_fops = { | ||
151 | .owner = THIS_MODULE, | ||
152 | .open = dccpprobe_open, | ||
153 | .read = dccpprobe_read, | ||
154 | }; | ||
155 | |||
156 | static __init int dccpprobe_init(void) | ||
157 | { | ||
158 | int ret = -ENOMEM; | ||
159 | |||
160 | init_waitqueue_head(&dccpw.wait); | ||
161 | spin_lock_init(&dccpw.lock); | ||
162 | dccpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &dccpw.lock); | ||
163 | |||
164 | if (!proc_net_fops_create(procname, S_IRUSR, &dccpprobe_fops)) | ||
165 | goto err0; | ||
166 | |||
167 | ret = register_jprobe(&dccp_send_probe); | ||
168 | if (ret) | ||
169 | goto err1; | ||
170 | |||
171 | pr_info("DCCP watch registered (port=%d)\n", port); | ||
172 | return 0; | ||
173 | err1: | ||
174 | proc_net_remove(procname); | ||
175 | err0: | ||
176 | kfifo_free(dccpw.fifo); | ||
177 | return ret; | ||
178 | } | ||
179 | module_init(dccpprobe_init); | ||
180 | |||
181 | static __exit void dccpprobe_exit(void) | ||
182 | { | ||
183 | kfifo_free(dccpw.fifo); | ||
184 | proc_net_remove(procname); | ||
185 | unregister_jprobe(&dccp_send_probe); | ||
186 | |||
187 | } | ||
188 | module_exit(dccpprobe_exit); | ||
189 | |||
190 | MODULE_PARM_DESC(port, "Port to match (0=all)"); | ||
191 | module_param(port, int, 0); | ||
192 | |||
193 | MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k)"); | ||
194 | module_param(bufsize, int, 0); | ||
195 | |||
196 | MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>"); | ||
197 | MODULE_DESCRIPTION("DCCP snooper"); | ||
198 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 962df0ea31aa..72cbdcfc2c65 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -217,7 +217,7 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) | |||
217 | icsk->icsk_sync_mss = dccp_sync_mss; | 217 | icsk->icsk_sync_mss = dccp_sync_mss; |
218 | dp->dccps_mss_cache = 536; | 218 | dp->dccps_mss_cache = 536; |
219 | dp->dccps_role = DCCP_ROLE_UNDEFINED; | 219 | dp->dccps_role = DCCP_ROLE_UNDEFINED; |
220 | dp->dccps_service = DCCP_SERVICE_INVALID_VALUE; | 220 | dp->dccps_service = DCCP_SERVICE_CODE_IS_ABSENT; |
221 | dp->dccps_l_ack_ratio = dp->dccps_r_ack_ratio = 1; | 221 | dp->dccps_l_ack_ratio = dp->dccps_r_ack_ratio = 1; |
222 | 222 | ||
223 | return 0; | 223 | return 0; |
@@ -267,12 +267,6 @@ static inline int dccp_listen_start(struct sock *sk) | |||
267 | struct dccp_sock *dp = dccp_sk(sk); | 267 | struct dccp_sock *dp = dccp_sk(sk); |
268 | 268 | ||
269 | dp->dccps_role = DCCP_ROLE_LISTEN; | 269 | dp->dccps_role = DCCP_ROLE_LISTEN; |
270 | /* | ||
271 | * Apps need to use setsockopt(DCCP_SOCKOPT_SERVICE) | ||
272 | * before calling listen() | ||
273 | */ | ||
274 | if (dccp_service_not_initialized(sk)) | ||
275 | return -EPROTO; | ||
276 | return inet_csk_listen_start(sk, TCP_SYNQ_HSIZE); | 270 | return inet_csk_listen_start(sk, TCP_SYNQ_HSIZE); |
277 | } | 271 | } |
278 | 272 | ||
@@ -540,9 +534,6 @@ static int dccp_getsockopt_service(struct sock *sk, int len, | |||
540 | int err = -ENOENT, slen = 0, total_len = sizeof(u32); | 534 | int err = -ENOENT, slen = 0, total_len = sizeof(u32); |
541 | 535 | ||
542 | lock_sock(sk); | 536 | lock_sock(sk); |
543 | if (dccp_service_not_initialized(sk)) | ||
544 | goto out; | ||
545 | |||
546 | if ((sl = dp->dccps_service_list) != NULL) { | 537 | if ((sl = dp->dccps_service_list) != NULL) { |
547 | slen = sl->dccpsl_nr * sizeof(u32); | 538 | slen = sl->dccpsl_nr * sizeof(u32); |
548 | total_len += slen; | 539 | total_len += slen; |
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 1650b64415aa..30af4a4dfcc8 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig | |||
@@ -448,24 +448,22 @@ config INET_TCP_DIAG | |||
448 | depends on INET_DIAG | 448 | depends on INET_DIAG |
449 | def_tristate INET_DIAG | 449 | def_tristate INET_DIAG |
450 | 450 | ||
451 | config TCP_CONG_ADVANCED | 451 | menuconfig TCP_CONG_ADVANCED |
452 | bool "TCP: advanced congestion control" | 452 | bool "TCP: advanced congestion control" |
453 | ---help--- | 453 | ---help--- |
454 | Support for selection of various TCP congestion control | 454 | Support for selection of various TCP congestion control |
455 | modules. | 455 | modules. |
456 | 456 | ||
457 | Nearly all users can safely say no here, and a safe default | 457 | Nearly all users can safely say no here, and a safe default |
458 | selection will be made (BIC-TCP with new Reno as a fallback). | 458 | selection will be made (CUBIC with new Reno as a fallback). |
459 | 459 | ||
460 | If unsure, say N. | 460 | If unsure, say N. |
461 | 461 | ||
462 | # TCP Reno is builtin (required as fallback) | 462 | if TCP_CONG_ADVANCED |
463 | menu "TCP congestion control" | ||
464 | depends on TCP_CONG_ADVANCED | ||
465 | 463 | ||
466 | config TCP_CONG_BIC | 464 | config TCP_CONG_BIC |
467 | tristate "Binary Increase Congestion (BIC) control" | 465 | tristate "Binary Increase Congestion (BIC) control" |
468 | default y | 466 | default m |
469 | ---help--- | 467 | ---help--- |
470 | BIC-TCP is a sender-side only change that ensures a linear RTT | 468 | BIC-TCP is a sender-side only change that ensures a linear RTT |
471 | fairness under large windows while offering both scalability and | 469 | fairness under large windows while offering both scalability and |
@@ -479,7 +477,7 @@ config TCP_CONG_BIC | |||
479 | 477 | ||
480 | config TCP_CONG_CUBIC | 478 | config TCP_CONG_CUBIC |
481 | tristate "CUBIC TCP" | 479 | tristate "CUBIC TCP" |
482 | default m | 480 | default y |
483 | ---help--- | 481 | ---help--- |
484 | This is version 2.0 of BIC-TCP which uses a cubic growth function | 482 | This is version 2.0 of BIC-TCP which uses a cubic growth function |
485 | among other techniques. | 483 | among other techniques. |
@@ -574,12 +572,49 @@ config TCP_CONG_VENO | |||
574 | loss packets. | 572 | loss packets. |
575 | See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf | 573 | See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf |
576 | 574 | ||
577 | endmenu | 575 | choice |
576 | prompt "Default TCP congestion control" | ||
577 | default DEFAULT_CUBIC | ||
578 | help | ||
579 | Select the TCP congestion control that will be used by default | ||
580 | for all connections. | ||
578 | 581 | ||
579 | config TCP_CONG_BIC | 582 | config DEFAULT_BIC |
583 | bool "Bic" if TCP_CONG_BIC=y | ||
584 | |||
585 | config DEFAULT_CUBIC | ||
586 | bool "Cubic" if TCP_CONG_CUBIC=y | ||
587 | |||
588 | config DEFAULT_HTCP | ||
589 | bool "Htcp" if TCP_CONG_HTCP=y | ||
590 | |||
591 | config DEFAULT_VEGAS | ||
592 | bool "Vegas" if TCP_CONG_VEGAS=y | ||
593 | |||
594 | config DEFAULT_WESTWOOD | ||
595 | bool "Westwood" if TCP_CONG_WESTWOOD=y | ||
596 | |||
597 | config DEFAULT_RENO | ||
598 | bool "Reno" | ||
599 | |||
600 | endchoice | ||
601 | |||
602 | endif | ||
603 | |||
604 | config TCP_CONG_CUBIC | ||
580 | tristate | 605 | tristate |
581 | depends on !TCP_CONG_ADVANCED | 606 | depends on !TCP_CONG_ADVANCED |
582 | default y | 607 | default y |
583 | 608 | ||
609 | config DEFAULT_TCP_CONG | ||
610 | string | ||
611 | default "bic" if DEFAULT_BIC | ||
612 | default "cubic" if DEFAULT_CUBIC | ||
613 | default "htcp" if DEFAULT_HTCP | ||
614 | default "vegas" if DEFAULT_VEGAS | ||
615 | default "westwood" if DEFAULT_WESTWOOD | ||
616 | default "reno" if DEFAULT_RENO | ||
617 | default "cubic" | ||
618 | |||
584 | source "net/ipv4/ipvs/Kconfig" | 619 | source "net/ipv4/ipvs/Kconfig" |
585 | 620 | ||
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 80a2a0911b49..e6ce0b3ba62a 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c | |||
@@ -259,7 +259,7 @@ void cipso_v4_cache_invalidate(void) | |||
259 | u32 iter; | 259 | u32 iter; |
260 | 260 | ||
261 | for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) { | 261 | for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) { |
262 | spin_lock(&cipso_v4_cache[iter].lock); | 262 | spin_lock_bh(&cipso_v4_cache[iter].lock); |
263 | list_for_each_entry_safe(entry, | 263 | list_for_each_entry_safe(entry, |
264 | tmp_entry, | 264 | tmp_entry, |
265 | &cipso_v4_cache[iter].list, list) { | 265 | &cipso_v4_cache[iter].list, list) { |
@@ -267,7 +267,7 @@ void cipso_v4_cache_invalidate(void) | |||
267 | cipso_v4_cache_entry_free(entry); | 267 | cipso_v4_cache_entry_free(entry); |
268 | } | 268 | } |
269 | cipso_v4_cache[iter].size = 0; | 269 | cipso_v4_cache[iter].size = 0; |
270 | spin_unlock(&cipso_v4_cache[iter].lock); | 270 | spin_unlock_bh(&cipso_v4_cache[iter].lock); |
271 | } | 271 | } |
272 | 272 | ||
273 | return; | 273 | return; |
@@ -309,7 +309,7 @@ static int cipso_v4_cache_check(const unsigned char *key, | |||
309 | 309 | ||
310 | hash = cipso_v4_map_cache_hash(key, key_len); | 310 | hash = cipso_v4_map_cache_hash(key, key_len); |
311 | bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); | 311 | bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); |
312 | spin_lock(&cipso_v4_cache[bkt].lock); | 312 | spin_lock_bh(&cipso_v4_cache[bkt].lock); |
313 | list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) { | 313 | list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) { |
314 | if (entry->hash == hash && | 314 | if (entry->hash == hash && |
315 | entry->key_len == key_len && | 315 | entry->key_len == key_len && |
@@ -318,7 +318,7 @@ static int cipso_v4_cache_check(const unsigned char *key, | |||
318 | secattr->cache.free = entry->lsm_data.free; | 318 | secattr->cache.free = entry->lsm_data.free; |
319 | secattr->cache.data = entry->lsm_data.data; | 319 | secattr->cache.data = entry->lsm_data.data; |
320 | if (prev_entry == NULL) { | 320 | if (prev_entry == NULL) { |
321 | spin_unlock(&cipso_v4_cache[bkt].lock); | 321 | spin_unlock_bh(&cipso_v4_cache[bkt].lock); |
322 | return 0; | 322 | return 0; |
323 | } | 323 | } |
324 | 324 | ||
@@ -333,12 +333,12 @@ static int cipso_v4_cache_check(const unsigned char *key, | |||
333 | &prev_entry->list); | 333 | &prev_entry->list); |
334 | } | 334 | } |
335 | 335 | ||
336 | spin_unlock(&cipso_v4_cache[bkt].lock); | 336 | spin_unlock_bh(&cipso_v4_cache[bkt].lock); |
337 | return 0; | 337 | return 0; |
338 | } | 338 | } |
339 | prev_entry = entry; | 339 | prev_entry = entry; |
340 | } | 340 | } |
341 | spin_unlock(&cipso_v4_cache[bkt].lock); | 341 | spin_unlock_bh(&cipso_v4_cache[bkt].lock); |
342 | 342 | ||
343 | return -ENOENT; | 343 | return -ENOENT; |
344 | } | 344 | } |
@@ -387,7 +387,7 @@ int cipso_v4_cache_add(const struct sk_buff *skb, | |||
387 | entry->lsm_data.data = secattr->cache.data; | 387 | entry->lsm_data.data = secattr->cache.data; |
388 | 388 | ||
389 | bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); | 389 | bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); |
390 | spin_lock(&cipso_v4_cache[bkt].lock); | 390 | spin_lock_bh(&cipso_v4_cache[bkt].lock); |
391 | if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) { | 391 | if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) { |
392 | list_add(&entry->list, &cipso_v4_cache[bkt].list); | 392 | list_add(&entry->list, &cipso_v4_cache[bkt].list); |
393 | cipso_v4_cache[bkt].size += 1; | 393 | cipso_v4_cache[bkt].size += 1; |
@@ -398,7 +398,7 @@ int cipso_v4_cache_add(const struct sk_buff *skb, | |||
398 | list_add(&entry->list, &cipso_v4_cache[bkt].list); | 398 | list_add(&entry->list, &cipso_v4_cache[bkt].list); |
399 | cipso_v4_cache_entry_free(old_entry); | 399 | cipso_v4_cache_entry_free(old_entry); |
400 | } | 400 | } |
401 | spin_unlock(&cipso_v4_cache[bkt].lock); | 401 | spin_unlock_bh(&cipso_v4_cache[bkt].lock); |
402 | 402 | ||
403 | return 0; | 403 | return 0; |
404 | 404 | ||
@@ -530,197 +530,42 @@ struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi) | |||
530 | } | 530 | } |
531 | 531 | ||
532 | /** | 532 | /** |
533 | * cipso_v4_doi_dump_all - Dump all the CIPSO DOI definitions into a sk_buff | 533 | * cipso_v4_doi_walk - Iterate through the DOI definitions |
534 | * @headroom: the amount of headroom to allocate for the sk_buff | 534 | * @skip_cnt: skip past this number of DOI definitions, updated |
535 | * @callback: callback for each DOI definition | ||
536 | * @cb_arg: argument for the callback function | ||
535 | * | 537 | * |
536 | * Description: | 538 | * Description: |
537 | * Dump a list of all the configured DOI values into a sk_buff. The returned | 539 | * Iterate over the DOI definition list, skipping the first @skip_cnt entries. |
538 | * sk_buff has room at the front of the sk_buff for @headroom bytes. See | 540 | * For each entry call @callback, if @callback returns a negative value stop |
539 | * net/netlabel/netlabel_cipso_v4.h for the LISTALL message format. This | 541 | * 'walking' through the list and return. Updates the value in @skip_cnt upon |
540 | * function may fail if another process is changing the DOI list at the same | 542 | * return. Returns zero on success, negative values on failure. |
541 | * time. Returns a pointer to a sk_buff on success, NULL on error. | ||
542 | * | 543 | * |
543 | */ | 544 | */ |
544 | struct sk_buff *cipso_v4_doi_dump_all(size_t headroom) | 545 | int cipso_v4_doi_walk(u32 *skip_cnt, |
546 | int (*callback) (struct cipso_v4_doi *doi_def, void *arg), | ||
547 | void *cb_arg) | ||
545 | { | 548 | { |
546 | struct sk_buff *skb = NULL; | 549 | int ret_val = -ENOENT; |
547 | struct cipso_v4_doi *iter; | ||
548 | u32 doi_cnt = 0; | 550 | u32 doi_cnt = 0; |
549 | ssize_t buf_len; | 551 | struct cipso_v4_doi *iter_doi; |
550 | 552 | ||
551 | buf_len = NETLBL_LEN_U32; | ||
552 | rcu_read_lock(); | 553 | rcu_read_lock(); |
553 | list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list) | 554 | list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list) |
554 | if (iter->valid) { | 555 | if (iter_doi->valid) { |
555 | doi_cnt += 1; | 556 | if (doi_cnt++ < *skip_cnt) |
556 | buf_len += 2 * NETLBL_LEN_U32; | 557 | continue; |
557 | } | 558 | ret_val = callback(iter_doi, cb_arg); |
558 | 559 | if (ret_val < 0) { | |
559 | skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC); | 560 | doi_cnt--; |
560 | if (skb == NULL) | 561 | goto doi_walk_return; |
561 | goto doi_dump_all_failure; | ||
562 | |||
563 | if (nla_put_u32(skb, NLA_U32, doi_cnt) != 0) | ||
564 | goto doi_dump_all_failure; | ||
565 | buf_len -= NETLBL_LEN_U32; | ||
566 | list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list) | ||
567 | if (iter->valid) { | ||
568 | if (buf_len < 2 * NETLBL_LEN_U32) | ||
569 | goto doi_dump_all_failure; | ||
570 | if (nla_put_u32(skb, NLA_U32, iter->doi) != 0) | ||
571 | goto doi_dump_all_failure; | ||
572 | if (nla_put_u32(skb, NLA_U32, iter->type) != 0) | ||
573 | goto doi_dump_all_failure; | ||
574 | buf_len -= 2 * NETLBL_LEN_U32; | ||
575 | } | ||
576 | rcu_read_unlock(); | ||
577 | |||
578 | return skb; | ||
579 | |||
580 | doi_dump_all_failure: | ||
581 | rcu_read_unlock(); | ||
582 | kfree(skb); | ||
583 | return NULL; | ||
584 | } | ||
585 | |||
586 | /** | ||
587 | * cipso_v4_doi_dump - Dump a CIPSO DOI definition into a sk_buff | ||
588 | * @doi: the DOI value | ||
589 | * @headroom: the amount of headroom to allocate for the sk_buff | ||
590 | * | ||
591 | * Description: | ||
592 | * Lookup the DOI definition matching @doi and dump it's contents into a | ||
593 | * sk_buff. The returned sk_buff has room at the front of the sk_buff for | ||
594 | * @headroom bytes. See net/netlabel/netlabel_cipso_v4.h for the LIST message | ||
595 | * format. This function may fail if another process is changing the DOI list | ||
596 | * at the same time. Returns a pointer to a sk_buff on success, NULL on error. | ||
597 | * | ||
598 | */ | ||
599 | struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom) | ||
600 | { | ||
601 | struct sk_buff *skb = NULL; | ||
602 | struct cipso_v4_doi *iter; | ||
603 | u32 tag_cnt = 0; | ||
604 | u32 lvl_cnt = 0; | ||
605 | u32 cat_cnt = 0; | ||
606 | ssize_t buf_len; | ||
607 | ssize_t tmp; | ||
608 | |||
609 | rcu_read_lock(); | ||
610 | iter = cipso_v4_doi_getdef(doi); | ||
611 | if (iter == NULL) | ||
612 | goto doi_dump_failure; | ||
613 | buf_len = NETLBL_LEN_U32; | ||
614 | switch (iter->type) { | ||
615 | case CIPSO_V4_MAP_PASS: | ||
616 | buf_len += NETLBL_LEN_U32; | ||
617 | while(tag_cnt < CIPSO_V4_TAG_MAXCNT && | ||
618 | iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) { | ||
619 | tag_cnt += 1; | ||
620 | buf_len += NETLBL_LEN_U8; | ||
621 | } | ||
622 | break; | ||
623 | case CIPSO_V4_MAP_STD: | ||
624 | buf_len += 3 * NETLBL_LEN_U32; | ||
625 | while (tag_cnt < CIPSO_V4_TAG_MAXCNT && | ||
626 | iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) { | ||
627 | tag_cnt += 1; | ||
628 | buf_len += NETLBL_LEN_U8; | ||
629 | } | ||
630 | for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++) | ||
631 | if (iter->map.std->lvl.local[tmp] != | ||
632 | CIPSO_V4_INV_LVL) { | ||
633 | lvl_cnt += 1; | ||
634 | buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U8; | ||
635 | } | ||
636 | for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++) | ||
637 | if (iter->map.std->cat.local[tmp] != | ||
638 | CIPSO_V4_INV_CAT) { | ||
639 | cat_cnt += 1; | ||
640 | buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U16; | ||
641 | } | 562 | } |
642 | break; | ||
643 | } | ||
644 | |||
645 | skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC); | ||
646 | if (skb == NULL) | ||
647 | goto doi_dump_failure; | ||
648 | |||
649 | if (nla_put_u32(skb, NLA_U32, iter->type) != 0) | ||
650 | goto doi_dump_failure; | ||
651 | buf_len -= NETLBL_LEN_U32; | ||
652 | if (iter != cipso_v4_doi_getdef(doi)) | ||
653 | goto doi_dump_failure; | ||
654 | switch (iter->type) { | ||
655 | case CIPSO_V4_MAP_PASS: | ||
656 | if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0) | ||
657 | goto doi_dump_failure; | ||
658 | buf_len -= NETLBL_LEN_U32; | ||
659 | for (tmp = 0; | ||
660 | tmp < CIPSO_V4_TAG_MAXCNT && | ||
661 | iter->tags[tmp] != CIPSO_V4_TAG_INVALID; | ||
662 | tmp++) { | ||
663 | if (buf_len < NETLBL_LEN_U8) | ||
664 | goto doi_dump_failure; | ||
665 | if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0) | ||
666 | goto doi_dump_failure; | ||
667 | buf_len -= NETLBL_LEN_U8; | ||
668 | } | 563 | } |
669 | break; | ||
670 | case CIPSO_V4_MAP_STD: | ||
671 | if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0) | ||
672 | goto doi_dump_failure; | ||
673 | if (nla_put_u32(skb, NLA_U32, lvl_cnt) != 0) | ||
674 | goto doi_dump_failure; | ||
675 | if (nla_put_u32(skb, NLA_U32, cat_cnt) != 0) | ||
676 | goto doi_dump_failure; | ||
677 | buf_len -= 3 * NETLBL_LEN_U32; | ||
678 | for (tmp = 0; | ||
679 | tmp < CIPSO_V4_TAG_MAXCNT && | ||
680 | iter->tags[tmp] != CIPSO_V4_TAG_INVALID; | ||
681 | tmp++) { | ||
682 | if (buf_len < NETLBL_LEN_U8) | ||
683 | goto doi_dump_failure; | ||
684 | if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0) | ||
685 | goto doi_dump_failure; | ||
686 | buf_len -= NETLBL_LEN_U8; | ||
687 | } | ||
688 | for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++) | ||
689 | if (iter->map.std->lvl.local[tmp] != | ||
690 | CIPSO_V4_INV_LVL) { | ||
691 | if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U8) | ||
692 | goto doi_dump_failure; | ||
693 | if (nla_put_u32(skb, NLA_U32, tmp) != 0) | ||
694 | goto doi_dump_failure; | ||
695 | if (nla_put_u8(skb, | ||
696 | NLA_U8, | ||
697 | iter->map.std->lvl.local[tmp]) != 0) | ||
698 | goto doi_dump_failure; | ||
699 | buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U8; | ||
700 | } | ||
701 | for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++) | ||
702 | if (iter->map.std->cat.local[tmp] != | ||
703 | CIPSO_V4_INV_CAT) { | ||
704 | if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U16) | ||
705 | goto doi_dump_failure; | ||
706 | if (nla_put_u32(skb, NLA_U32, tmp) != 0) | ||
707 | goto doi_dump_failure; | ||
708 | if (nla_put_u16(skb, | ||
709 | NLA_U16, | ||
710 | iter->map.std->cat.local[tmp]) != 0) | ||
711 | goto doi_dump_failure; | ||
712 | buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U16; | ||
713 | } | ||
714 | break; | ||
715 | } | ||
716 | rcu_read_unlock(); | ||
717 | |||
718 | return skb; | ||
719 | 564 | ||
720 | doi_dump_failure: | 565 | doi_walk_return: |
721 | rcu_read_unlock(); | 566 | rcu_read_unlock(); |
722 | kfree(skb); | 567 | *skip_cnt = doi_cnt; |
723 | return NULL; | 568 | return ret_val; |
724 | } | 569 | } |
725 | 570 | ||
726 | /** | 571 | /** |
@@ -1486,43 +1331,40 @@ socket_setattr_failure: | |||
1486 | } | 1331 | } |
1487 | 1332 | ||
1488 | /** | 1333 | /** |
1489 | * cipso_v4_socket_getattr - Get the security attributes from a socket | 1334 | * cipso_v4_sock_getattr - Get the security attributes from a sock |
1490 | * @sock: the socket | 1335 | * @sk: the sock |
1491 | * @secattr: the security attributes | 1336 | * @secattr: the security attributes |
1492 | * | 1337 | * |
1493 | * Description: | 1338 | * Description: |
1494 | * Query @sock to see if there is a CIPSO option attached to the socket and if | 1339 | * Query @sk to see if there is a CIPSO option attached to the sock and if |
1495 | * there is return the CIPSO security attributes in @secattr. Returns zero on | 1340 | * there is return the CIPSO security attributes in @secattr. This function |
1496 | * success and negative values on failure. | 1341 | * requires that @sk be locked, or privately held, but it does not do any |
1342 | * locking itself. Returns zero on success and negative values on failure. | ||
1497 | * | 1343 | * |
1498 | */ | 1344 | */ |
1499 | int cipso_v4_socket_getattr(const struct socket *sock, | 1345 | int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) |
1500 | struct netlbl_lsm_secattr *secattr) | ||
1501 | { | 1346 | { |
1502 | int ret_val = -ENOMSG; | 1347 | int ret_val = -ENOMSG; |
1503 | struct sock *sk; | ||
1504 | struct inet_sock *sk_inet; | 1348 | struct inet_sock *sk_inet; |
1505 | unsigned char *cipso_ptr; | 1349 | unsigned char *cipso_ptr; |
1506 | u32 doi; | 1350 | u32 doi; |
1507 | struct cipso_v4_doi *doi_def; | 1351 | struct cipso_v4_doi *doi_def; |
1508 | 1352 | ||
1509 | sk = sock->sk; | ||
1510 | lock_sock(sk); | ||
1511 | sk_inet = inet_sk(sk); | 1353 | sk_inet = inet_sk(sk); |
1512 | if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0) | 1354 | if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0) |
1513 | goto socket_getattr_return; | 1355 | return -ENOMSG; |
1514 | cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso - | 1356 | cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso - |
1515 | sizeof(struct iphdr); | 1357 | sizeof(struct iphdr); |
1516 | ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr); | 1358 | ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr); |
1517 | if (ret_val == 0) | 1359 | if (ret_val == 0) |
1518 | goto socket_getattr_return; | 1360 | return ret_val; |
1519 | 1361 | ||
1520 | doi = ntohl(*(u32 *)&cipso_ptr[2]); | 1362 | doi = ntohl(*(u32 *)&cipso_ptr[2]); |
1521 | rcu_read_lock(); | 1363 | rcu_read_lock(); |
1522 | doi_def = cipso_v4_doi_getdef(doi); | 1364 | doi_def = cipso_v4_doi_getdef(doi); |
1523 | if (doi_def == NULL) { | 1365 | if (doi_def == NULL) { |
1524 | rcu_read_unlock(); | 1366 | rcu_read_unlock(); |
1525 | goto socket_getattr_return; | 1367 | return -ENOMSG; |
1526 | } | 1368 | } |
1527 | switch (cipso_ptr[6]) { | 1369 | switch (cipso_ptr[6]) { |
1528 | case CIPSO_V4_TAG_RBITMAP: | 1370 | case CIPSO_V4_TAG_RBITMAP: |
@@ -1533,8 +1375,29 @@ int cipso_v4_socket_getattr(const struct socket *sock, | |||
1533 | } | 1375 | } |
1534 | rcu_read_unlock(); | 1376 | rcu_read_unlock(); |
1535 | 1377 | ||
1536 | socket_getattr_return: | 1378 | return ret_val; |
1537 | release_sock(sk); | 1379 | } |
1380 | |||
1381 | /** | ||
1382 | * cipso_v4_socket_getattr - Get the security attributes from a socket | ||
1383 | * @sock: the socket | ||
1384 | * @secattr: the security attributes | ||
1385 | * | ||
1386 | * Description: | ||
1387 | * Query @sock to see if there is a CIPSO option attached to the socket and if | ||
1388 | * there is return the CIPSO security attributes in @secattr. Returns zero on | ||
1389 | * success and negative values on failure. | ||
1390 | * | ||
1391 | */ | ||
1392 | int cipso_v4_socket_getattr(const struct socket *sock, | ||
1393 | struct netlbl_lsm_secattr *secattr) | ||
1394 | { | ||
1395 | int ret_val; | ||
1396 | |||
1397 | lock_sock(sock->sk); | ||
1398 | ret_val = cipso_v4_sock_getattr(sock->sk, secattr); | ||
1399 | release_sock(sock->sk); | ||
1400 | |||
1538 | return ret_val; | 1401 | return ret_val; |
1539 | } | 1402 | } |
1540 | 1403 | ||
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 19b2071ff319..e82a5be894b5 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -129,6 +129,12 @@ static int sysctl_tcp_congestion_control(ctl_table *table, int __user *name, | |||
129 | return ret; | 129 | return ret; |
130 | } | 130 | } |
131 | 131 | ||
132 | static int __init tcp_congestion_default(void) | ||
133 | { | ||
134 | return tcp_set_default_congestion_control(CONFIG_DEFAULT_TCP_CONG); | ||
135 | } | ||
136 | |||
137 | late_initcall(tcp_congestion_default); | ||
132 | 138 | ||
133 | ctl_table ipv4_table[] = { | 139 | ctl_table ipv4_table[] = { |
134 | { | 140 | { |
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 7ff2e4273a7c..af0aca1e6be6 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c | |||
@@ -48,7 +48,7 @@ int tcp_register_congestion_control(struct tcp_congestion_ops *ca) | |||
48 | printk(KERN_NOTICE "TCP %s already registered\n", ca->name); | 48 | printk(KERN_NOTICE "TCP %s already registered\n", ca->name); |
49 | ret = -EEXIST; | 49 | ret = -EEXIST; |
50 | } else { | 50 | } else { |
51 | list_add_rcu(&ca->list, &tcp_cong_list); | 51 | list_add_tail_rcu(&ca->list, &tcp_cong_list); |
52 | printk(KERN_INFO "TCP %s registered\n", ca->name); | 52 | printk(KERN_INFO "TCP %s registered\n", ca->name); |
53 | } | 53 | } |
54 | spin_unlock(&tcp_cong_list_lock); | 54 | spin_unlock(&tcp_cong_list_lock); |
diff --git a/net/netlabel/Kconfig b/net/netlabel/Kconfig index fe23cb7f1e87..9f7121ae13e9 100644 --- a/net/netlabel/Kconfig +++ b/net/netlabel/Kconfig | |||
@@ -9,6 +9,9 @@ config NETLABEL | |||
9 | ---help--- | 9 | ---help--- |
10 | NetLabel provides support for explicit network packet labeling | 10 | NetLabel provides support for explicit network packet labeling |
11 | protocols such as CIPSO and RIPSO. For more information see | 11 | protocols such as CIPSO and RIPSO. For more information see |
12 | Documentation/netlabel. | 12 | Documentation/netlabel as well as the NetLabel SourceForge project |
13 | for configuration tools and additional documentation. | ||
14 | |||
15 | * http://netlabel.sf.net | ||
13 | 16 | ||
14 | If you are unsure, say N. | 17 | If you are unsure, say N. |
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index a4f40adc447b..4125a55f469f 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c | |||
@@ -41,15 +41,37 @@ | |||
41 | #include "netlabel_user.h" | 41 | #include "netlabel_user.h" |
42 | #include "netlabel_cipso_v4.h" | 42 | #include "netlabel_cipso_v4.h" |
43 | 43 | ||
44 | /* Argument struct for cipso_v4_doi_walk() */ | ||
45 | struct netlbl_cipsov4_doiwalk_arg { | ||
46 | struct netlink_callback *nl_cb; | ||
47 | struct sk_buff *skb; | ||
48 | u32 seq; | ||
49 | }; | ||
50 | |||
44 | /* NetLabel Generic NETLINK CIPSOv4 family */ | 51 | /* NetLabel Generic NETLINK CIPSOv4 family */ |
45 | static struct genl_family netlbl_cipsov4_gnl_family = { | 52 | static struct genl_family netlbl_cipsov4_gnl_family = { |
46 | .id = GENL_ID_GENERATE, | 53 | .id = GENL_ID_GENERATE, |
47 | .hdrsize = 0, | 54 | .hdrsize = 0, |
48 | .name = NETLBL_NLTYPE_CIPSOV4_NAME, | 55 | .name = NETLBL_NLTYPE_CIPSOV4_NAME, |
49 | .version = NETLBL_PROTO_VERSION, | 56 | .version = NETLBL_PROTO_VERSION, |
50 | .maxattr = 0, | 57 | .maxattr = NLBL_CIPSOV4_A_MAX, |
51 | }; | 58 | }; |
52 | 59 | ||
60 | /* NetLabel Netlink attribute policy */ | ||
61 | static struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = { | ||
62 | [NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 }, | ||
63 | [NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 }, | ||
64 | [NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 }, | ||
65 | [NLBL_CIPSOV4_A_TAGLST] = { .type = NLA_NESTED }, | ||
66 | [NLBL_CIPSOV4_A_MLSLVLLOC] = { .type = NLA_U32 }, | ||
67 | [NLBL_CIPSOV4_A_MLSLVLREM] = { .type = NLA_U32 }, | ||
68 | [NLBL_CIPSOV4_A_MLSLVL] = { .type = NLA_NESTED }, | ||
69 | [NLBL_CIPSOV4_A_MLSLVLLST] = { .type = NLA_NESTED }, | ||
70 | [NLBL_CIPSOV4_A_MLSCATLOC] = { .type = NLA_U32 }, | ||
71 | [NLBL_CIPSOV4_A_MLSCATREM] = { .type = NLA_U32 }, | ||
72 | [NLBL_CIPSOV4_A_MLSCAT] = { .type = NLA_NESTED }, | ||
73 | [NLBL_CIPSOV4_A_MLSCATLST] = { .type = NLA_NESTED }, | ||
74 | }; | ||
53 | 75 | ||
54 | /* | 76 | /* |
55 | * Helper Functions | 77 | * Helper Functions |
@@ -81,6 +103,41 @@ static void netlbl_cipsov4_doi_free(struct rcu_head *entry) | |||
81 | kfree(ptr); | 103 | kfree(ptr); |
82 | } | 104 | } |
83 | 105 | ||
106 | /** | ||
107 | * netlbl_cipsov4_add_common - Parse the common sections of a ADD message | ||
108 | * @info: the Generic NETLINK info block | ||
109 | * @doi_def: the CIPSO V4 DOI definition | ||
110 | * | ||
111 | * Description: | ||
112 | * Parse the common sections of a ADD message and fill in the related values | ||
113 | * in @doi_def. Returns zero on success, negative values on failure. | ||
114 | * | ||
115 | */ | ||
116 | static int netlbl_cipsov4_add_common(struct genl_info *info, | ||
117 | struct cipso_v4_doi *doi_def) | ||
118 | { | ||
119 | struct nlattr *nla; | ||
120 | int nla_rem; | ||
121 | u32 iter = 0; | ||
122 | |||
123 | doi_def->doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); | ||
124 | |||
125 | if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_TAGLST], | ||
126 | NLBL_CIPSOV4_A_MAX, | ||
127 | netlbl_cipsov4_genl_policy) != 0) | ||
128 | return -EINVAL; | ||
129 | |||
130 | nla_for_each_nested(nla, info->attrs[NLBL_CIPSOV4_A_TAGLST], nla_rem) | ||
131 | if (nla->nla_type == NLBL_CIPSOV4_A_TAG) { | ||
132 | if (iter > CIPSO_V4_TAG_MAXCNT) | ||
133 | return -EINVAL; | ||
134 | doi_def->tags[iter++] = nla_get_u8(nla); | ||
135 | } | ||
136 | if (iter < CIPSO_V4_TAG_MAXCNT) | ||
137 | doi_def->tags[iter] = CIPSO_V4_TAG_INVALID; | ||
138 | |||
139 | return 0; | ||
140 | } | ||
84 | 141 | ||
85 | /* | 142 | /* |
86 | * NetLabel Command Handlers | 143 | * NetLabel Command Handlers |
@@ -88,9 +145,7 @@ static void netlbl_cipsov4_doi_free(struct rcu_head *entry) | |||
88 | 145 | ||
89 | /** | 146 | /** |
90 | * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition | 147 | * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition |
91 | * @doi: the DOI value | 148 | * @info: the Generic NETLINK info block |
92 | * @msg: the ADD message data | ||
93 | * @msg_size: the size of the ADD message buffer | ||
94 | * | 149 | * |
95 | * Description: | 150 | * Description: |
96 | * Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message | 151 | * Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message |
@@ -98,29 +153,28 @@ static void netlbl_cipsov4_doi_free(struct rcu_head *entry) | |||
98 | * error. | 153 | * error. |
99 | * | 154 | * |
100 | */ | 155 | */ |
101 | static int netlbl_cipsov4_add_std(u32 doi, struct nlattr *msg, size_t msg_size) | 156 | static int netlbl_cipsov4_add_std(struct genl_info *info) |
102 | { | 157 | { |
103 | int ret_val = -EINVAL; | 158 | int ret_val = -EINVAL; |
104 | int msg_len = msg_size; | ||
105 | u32 num_tags; | ||
106 | u32 num_lvls; | ||
107 | u32 num_cats; | ||
108 | struct cipso_v4_doi *doi_def = NULL; | 159 | struct cipso_v4_doi *doi_def = NULL; |
109 | u32 iter; | 160 | struct nlattr *nla_a; |
110 | u32 tmp_val_a; | 161 | struct nlattr *nla_b; |
111 | u32 tmp_val_b; | 162 | int nla_a_rem; |
163 | int nla_b_rem; | ||
112 | 164 | ||
113 | if (msg_len < NETLBL_LEN_U32) | 165 | if (!info->attrs[NLBL_CIPSOV4_A_DOI] || |
114 | goto add_std_failure; | 166 | !info->attrs[NLBL_CIPSOV4_A_TAGLST] || |
115 | num_tags = netlbl_getinc_u32(&msg, &msg_len); | 167 | !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]) |
116 | if (num_tags == 0 || num_tags > CIPSO_V4_TAG_MAXCNT) | 168 | return -EINVAL; |
117 | goto add_std_failure; | 169 | |
170 | if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST], | ||
171 | NLBL_CIPSOV4_A_MAX, | ||
172 | netlbl_cipsov4_genl_policy) != 0) | ||
173 | return -EINVAL; | ||
118 | 174 | ||
119 | doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); | 175 | doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); |
120 | if (doi_def == NULL) { | 176 | if (doi_def == NULL) |
121 | ret_val = -ENOMEM; | 177 | return -ENOMEM; |
122 | goto add_std_failure; | ||
123 | } | ||
124 | doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL); | 178 | doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL); |
125 | if (doi_def->map.std == NULL) { | 179 | if (doi_def->map.std == NULL) { |
126 | ret_val = -ENOMEM; | 180 | ret_val = -ENOMEM; |
@@ -128,28 +182,32 @@ static int netlbl_cipsov4_add_std(u32 doi, struct nlattr *msg, size_t msg_size) | |||
128 | } | 182 | } |
129 | doi_def->type = CIPSO_V4_MAP_STD; | 183 | doi_def->type = CIPSO_V4_MAP_STD; |
130 | 184 | ||
131 | for (iter = 0; iter < num_tags; iter++) { | 185 | ret_val = netlbl_cipsov4_add_common(info, doi_def); |
132 | if (msg_len < NETLBL_LEN_U8) | 186 | if (ret_val != 0) |
133 | goto add_std_failure; | ||
134 | doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len); | ||
135 | switch (doi_def->tags[iter]) { | ||
136 | case CIPSO_V4_TAG_RBITMAP: | ||
137 | break; | ||
138 | default: | ||
139 | goto add_std_failure; | ||
140 | } | ||
141 | } | ||
142 | if (iter < CIPSO_V4_TAG_MAXCNT) | ||
143 | doi_def->tags[iter] = CIPSO_V4_TAG_INVALID; | ||
144 | |||
145 | if (msg_len < 6 * NETLBL_LEN_U32) | ||
146 | goto add_std_failure; | 187 | goto add_std_failure; |
147 | 188 | ||
148 | num_lvls = netlbl_getinc_u32(&msg, &msg_len); | 189 | nla_for_each_nested(nla_a, |
149 | if (num_lvls == 0) | 190 | info->attrs[NLBL_CIPSOV4_A_MLSLVLLST], |
150 | goto add_std_failure; | 191 | nla_a_rem) |
151 | doi_def->map.std->lvl.local_size = netlbl_getinc_u32(&msg, &msg_len); | 192 | if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) { |
152 | if (doi_def->map.std->lvl.local_size > CIPSO_V4_MAX_LOC_LVLS) | 193 | nla_for_each_nested(nla_b, nla_a, nla_b_rem) |
194 | switch (nla_b->nla_type) { | ||
195 | case NLBL_CIPSOV4_A_MLSLVLLOC: | ||
196 | if (nla_get_u32(nla_b) >= | ||
197 | doi_def->map.std->lvl.local_size) | ||
198 | doi_def->map.std->lvl.local_size = | ||
199 | nla_get_u32(nla_b) + 1; | ||
200 | break; | ||
201 | case NLBL_CIPSOV4_A_MLSLVLREM: | ||
202 | if (nla_get_u32(nla_b) >= | ||
203 | doi_def->map.std->lvl.cipso_size) | ||
204 | doi_def->map.std->lvl.cipso_size = | ||
205 | nla_get_u32(nla_b) + 1; | ||
206 | break; | ||
207 | } | ||
208 | } | ||
209 | if (doi_def->map.std->lvl.local_size > CIPSO_V4_MAX_LOC_LVLS || | ||
210 | doi_def->map.std->lvl.cipso_size > CIPSO_V4_MAX_REM_LVLS) | ||
153 | goto add_std_failure; | 211 | goto add_std_failure; |
154 | doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size, | 212 | doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size, |
155 | sizeof(u32), | 213 | sizeof(u32), |
@@ -158,9 +216,6 @@ static int netlbl_cipsov4_add_std(u32 doi, struct nlattr *msg, size_t msg_size) | |||
158 | ret_val = -ENOMEM; | 216 | ret_val = -ENOMEM; |
159 | goto add_std_failure; | 217 | goto add_std_failure; |
160 | } | 218 | } |
161 | doi_def->map.std->lvl.cipso_size = netlbl_getinc_u8(&msg, &msg_len); | ||
162 | if (doi_def->map.std->lvl.cipso_size > CIPSO_V4_MAX_REM_LVLS) | ||
163 | goto add_std_failure; | ||
164 | doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size, | 219 | doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size, |
165 | sizeof(u32), | 220 | sizeof(u32), |
166 | GFP_KERNEL); | 221 | GFP_KERNEL); |
@@ -168,68 +223,101 @@ static int netlbl_cipsov4_add_std(u32 doi, struct nlattr *msg, size_t msg_size) | |||
168 | ret_val = -ENOMEM; | 223 | ret_val = -ENOMEM; |
169 | goto add_std_failure; | 224 | goto add_std_failure; |
170 | } | 225 | } |
226 | nla_for_each_nested(nla_a, | ||
227 | info->attrs[NLBL_CIPSOV4_A_MLSLVLLST], | ||
228 | nla_a_rem) | ||
229 | if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) { | ||
230 | struct nlattr *lvl_loc; | ||
231 | struct nlattr *lvl_rem; | ||
232 | |||
233 | if (nla_validate_nested(nla_a, | ||
234 | NLBL_CIPSOV4_A_MAX, | ||
235 | netlbl_cipsov4_genl_policy) != 0) | ||
236 | goto add_std_failure; | ||
237 | |||
238 | lvl_loc = nla_find_nested(nla_a, | ||
239 | NLBL_CIPSOV4_A_MLSLVLLOC); | ||
240 | lvl_rem = nla_find_nested(nla_a, | ||
241 | NLBL_CIPSOV4_A_MLSLVLREM); | ||
242 | if (lvl_loc == NULL || lvl_rem == NULL) | ||
243 | goto add_std_failure; | ||
244 | doi_def->map.std->lvl.local[nla_get_u32(lvl_loc)] = | ||
245 | nla_get_u32(lvl_rem); | ||
246 | doi_def->map.std->lvl.cipso[nla_get_u32(lvl_rem)] = | ||
247 | nla_get_u32(lvl_loc); | ||
248 | } | ||
171 | 249 | ||
172 | num_cats = netlbl_getinc_u32(&msg, &msg_len); | 250 | if (info->attrs[NLBL_CIPSOV4_A_MLSCATLST]) { |
173 | doi_def->map.std->cat.local_size = netlbl_getinc_u32(&msg, &msg_len); | 251 | if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSCATLST], |
174 | if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS) | 252 | NLBL_CIPSOV4_A_MAX, |
175 | goto add_std_failure; | 253 | netlbl_cipsov4_genl_policy) != 0) |
176 | doi_def->map.std->cat.local = kcalloc(doi_def->map.std->cat.local_size, | 254 | goto add_std_failure; |
255 | |||
256 | nla_for_each_nested(nla_a, | ||
257 | info->attrs[NLBL_CIPSOV4_A_MLSCATLST], | ||
258 | nla_a_rem) | ||
259 | if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSCAT) { | ||
260 | if (nla_validate_nested(nla_a, | ||
261 | NLBL_CIPSOV4_A_MAX, | ||
262 | netlbl_cipsov4_genl_policy) != 0) | ||
263 | goto add_std_failure; | ||
264 | nla_for_each_nested(nla_b, nla_a, nla_b_rem) | ||
265 | switch (nla_b->nla_type) { | ||
266 | case NLBL_CIPSOV4_A_MLSCATLOC: | ||
267 | if (nla_get_u32(nla_b) >= | ||
268 | doi_def->map.std->cat.local_size) | ||
269 | doi_def->map.std->cat.local_size = | ||
270 | nla_get_u32(nla_b) + 1; | ||
271 | break; | ||
272 | case NLBL_CIPSOV4_A_MLSCATREM: | ||
273 | if (nla_get_u32(nla_b) >= | ||
274 | doi_def->map.std->cat.cipso_size) | ||
275 | doi_def->map.std->cat.cipso_size = | ||
276 | nla_get_u32(nla_b) + 1; | ||
277 | break; | ||
278 | } | ||
279 | } | ||
280 | if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS || | ||
281 | doi_def->map.std->cat.cipso_size > CIPSO_V4_MAX_REM_CATS) | ||
282 | goto add_std_failure; | ||
283 | doi_def->map.std->cat.local = kcalloc( | ||
284 | doi_def->map.std->cat.local_size, | ||
177 | sizeof(u32), | 285 | sizeof(u32), |
178 | GFP_KERNEL); | 286 | GFP_KERNEL); |
179 | if (doi_def->map.std->cat.local == NULL) { | 287 | if (doi_def->map.std->cat.local == NULL) { |
180 | ret_val = -ENOMEM; | 288 | ret_val = -ENOMEM; |
181 | goto add_std_failure; | 289 | goto add_std_failure; |
182 | } | 290 | } |
183 | doi_def->map.std->cat.cipso_size = netlbl_getinc_u16(&msg, &msg_len); | 291 | doi_def->map.std->cat.cipso = kcalloc( |
184 | if (doi_def->map.std->cat.cipso_size > CIPSO_V4_MAX_REM_CATS) | 292 | doi_def->map.std->cat.cipso_size, |
185 | goto add_std_failure; | ||
186 | doi_def->map.std->cat.cipso = kcalloc(doi_def->map.std->cat.cipso_size, | ||
187 | sizeof(u32), | 293 | sizeof(u32), |
188 | GFP_KERNEL); | 294 | GFP_KERNEL); |
189 | if (doi_def->map.std->cat.cipso == NULL) { | 295 | if (doi_def->map.std->cat.cipso == NULL) { |
190 | ret_val = -ENOMEM; | 296 | ret_val = -ENOMEM; |
191 | goto add_std_failure; | ||
192 | } | ||
193 | |||
194 | if (msg_len < | ||
195 | num_lvls * (NETLBL_LEN_U32 + NETLBL_LEN_U8) + | ||
196 | num_cats * (NETLBL_LEN_U32 + NETLBL_LEN_U16)) | ||
197 | goto add_std_failure; | ||
198 | |||
199 | for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++) | ||
200 | doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL; | ||
201 | for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++) | ||
202 | doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL; | ||
203 | for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++) | ||
204 | doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT; | ||
205 | for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++) | ||
206 | doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT; | ||
207 | |||
208 | for (iter = 0; iter < num_lvls; iter++) { | ||
209 | tmp_val_a = netlbl_getinc_u32(&msg, &msg_len); | ||
210 | tmp_val_b = netlbl_getinc_u8(&msg, &msg_len); | ||
211 | |||
212 | if (tmp_val_a >= doi_def->map.std->lvl.local_size || | ||
213 | tmp_val_b >= doi_def->map.std->lvl.cipso_size) | ||
214 | goto add_std_failure; | ||
215 | |||
216 | doi_def->map.std->lvl.cipso[tmp_val_b] = tmp_val_a; | ||
217 | doi_def->map.std->lvl.local[tmp_val_a] = tmp_val_b; | ||
218 | } | ||
219 | |||
220 | for (iter = 0; iter < num_cats; iter++) { | ||
221 | tmp_val_a = netlbl_getinc_u32(&msg, &msg_len); | ||
222 | tmp_val_b = netlbl_getinc_u16(&msg, &msg_len); | ||
223 | |||
224 | if (tmp_val_a >= doi_def->map.std->cat.local_size || | ||
225 | tmp_val_b >= doi_def->map.std->cat.cipso_size) | ||
226 | goto add_std_failure; | 297 | goto add_std_failure; |
227 | 298 | } | |
228 | doi_def->map.std->cat.cipso[tmp_val_b] = tmp_val_a; | 299 | nla_for_each_nested(nla_a, |
229 | doi_def->map.std->cat.local[tmp_val_a] = tmp_val_b; | 300 | info->attrs[NLBL_CIPSOV4_A_MLSCATLST], |
301 | nla_a_rem) | ||
302 | if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSCAT) { | ||
303 | struct nlattr *cat_loc; | ||
304 | struct nlattr *cat_rem; | ||
305 | |||
306 | cat_loc = nla_find_nested(nla_a, | ||
307 | NLBL_CIPSOV4_A_MLSCATLOC); | ||
308 | cat_rem = nla_find_nested(nla_a, | ||
309 | NLBL_CIPSOV4_A_MLSCATREM); | ||
310 | if (cat_loc == NULL || cat_rem == NULL) | ||
311 | goto add_std_failure; | ||
312 | doi_def->map.std->cat.local[ | ||
313 | nla_get_u32(cat_loc)] = | ||
314 | nla_get_u32(cat_rem); | ||
315 | doi_def->map.std->cat.cipso[ | ||
316 | nla_get_u32(cat_rem)] = | ||
317 | nla_get_u32(cat_loc); | ||
318 | } | ||
230 | } | 319 | } |
231 | 320 | ||
232 | doi_def->doi = doi; | ||
233 | ret_val = cipso_v4_doi_add(doi_def); | 321 | ret_val = cipso_v4_doi_add(doi_def); |
234 | if (ret_val != 0) | 322 | if (ret_val != 0) |
235 | goto add_std_failure; | 323 | goto add_std_failure; |
@@ -243,9 +331,7 @@ add_std_failure: | |||
243 | 331 | ||
244 | /** | 332 | /** |
245 | * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition | 333 | * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition |
246 | * @doi: the DOI value | 334 | * @info: the Generic NETLINK info block |
247 | * @msg: the ADD message data | ||
248 | * @msg_size: the size of the ADD message buffer | ||
249 | * | 335 | * |
250 | * Description: | 336 | * Description: |
251 | * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message | 337 | * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message |
@@ -253,52 +339,31 @@ add_std_failure: | |||
253 | * error. | 339 | * error. |
254 | * | 340 | * |
255 | */ | 341 | */ |
256 | static int netlbl_cipsov4_add_pass(u32 doi, | 342 | static int netlbl_cipsov4_add_pass(struct genl_info *info) |
257 | struct nlattr *msg, | ||
258 | size_t msg_size) | ||
259 | { | 343 | { |
260 | int ret_val = -EINVAL; | 344 | int ret_val; |
261 | int msg_len = msg_size; | ||
262 | u32 num_tags; | ||
263 | struct cipso_v4_doi *doi_def = NULL; | 345 | struct cipso_v4_doi *doi_def = NULL; |
264 | u32 iter; | ||
265 | 346 | ||
266 | if (msg_len < NETLBL_LEN_U32) | 347 | if (!info->attrs[NLBL_CIPSOV4_A_DOI] || |
267 | goto add_pass_failure; | 348 | !info->attrs[NLBL_CIPSOV4_A_TAGLST]) |
268 | num_tags = netlbl_getinc_u32(&msg, &msg_len); | 349 | return -EINVAL; |
269 | if (num_tags == 0 || num_tags > CIPSO_V4_TAG_MAXCNT) | ||
270 | goto add_pass_failure; | ||
271 | 350 | ||
272 | doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); | 351 | doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); |
273 | if (doi_def == NULL) { | 352 | if (doi_def == NULL) |
274 | ret_val = -ENOMEM; | 353 | return -ENOMEM; |
275 | goto add_pass_failure; | ||
276 | } | ||
277 | doi_def->type = CIPSO_V4_MAP_PASS; | 354 | doi_def->type = CIPSO_V4_MAP_PASS; |
278 | 355 | ||
279 | for (iter = 0; iter < num_tags; iter++) { | 356 | ret_val = netlbl_cipsov4_add_common(info, doi_def); |
280 | if (msg_len < NETLBL_LEN_U8) | 357 | if (ret_val != 0) |
281 | goto add_pass_failure; | 358 | goto add_pass_failure; |
282 | doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len); | ||
283 | switch (doi_def->tags[iter]) { | ||
284 | case CIPSO_V4_TAG_RBITMAP: | ||
285 | break; | ||
286 | default: | ||
287 | goto add_pass_failure; | ||
288 | } | ||
289 | } | ||
290 | if (iter < CIPSO_V4_TAG_MAXCNT) | ||
291 | doi_def->tags[iter] = CIPSO_V4_TAG_INVALID; | ||
292 | 359 | ||
293 | doi_def->doi = doi; | ||
294 | ret_val = cipso_v4_doi_add(doi_def); | 360 | ret_val = cipso_v4_doi_add(doi_def); |
295 | if (ret_val != 0) | 361 | if (ret_val != 0) |
296 | goto add_pass_failure; | 362 | goto add_pass_failure; |
297 | return 0; | 363 | return 0; |
298 | 364 | ||
299 | add_pass_failure: | 365 | add_pass_failure: |
300 | if (doi_def) | 366 | netlbl_cipsov4_doi_free(&doi_def->rcu); |
301 | netlbl_cipsov4_doi_free(&doi_def->rcu); | ||
302 | return ret_val; | 367 | return ret_val; |
303 | } | 368 | } |
304 | 369 | ||
@@ -316,34 +381,21 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) | |||
316 | 381 | ||
317 | { | 382 | { |
318 | int ret_val = -EINVAL; | 383 | int ret_val = -EINVAL; |
319 | u32 doi; | ||
320 | u32 map_type; | 384 | u32 map_type; |
321 | int msg_len = netlbl_netlink_payload_len(skb); | ||
322 | struct nlattr *msg = netlbl_netlink_payload_data(skb); | ||
323 | |||
324 | ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); | ||
325 | if (ret_val != 0) | ||
326 | goto add_return; | ||
327 | 385 | ||
328 | if (msg_len < 2 * NETLBL_LEN_U32) | 386 | if (!info->attrs[NLBL_CIPSOV4_A_MTYPE]) |
329 | goto add_return; | 387 | return -EINVAL; |
330 | 388 | ||
331 | doi = netlbl_getinc_u32(&msg, &msg_len); | 389 | map_type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]); |
332 | map_type = netlbl_getinc_u32(&msg, &msg_len); | ||
333 | switch (map_type) { | 390 | switch (map_type) { |
334 | case CIPSO_V4_MAP_STD: | 391 | case CIPSO_V4_MAP_STD: |
335 | ret_val = netlbl_cipsov4_add_std(doi, msg, msg_len); | 392 | ret_val = netlbl_cipsov4_add_std(info); |
336 | break; | 393 | break; |
337 | case CIPSO_V4_MAP_PASS: | 394 | case CIPSO_V4_MAP_PASS: |
338 | ret_val = netlbl_cipsov4_add_pass(doi, msg, msg_len); | 395 | ret_val = netlbl_cipsov4_add_pass(info); |
339 | break; | 396 | break; |
340 | } | 397 | } |
341 | 398 | ||
342 | add_return: | ||
343 | netlbl_netlink_send_ack(info, | ||
344 | netlbl_cipsov4_gnl_family.id, | ||
345 | NLBL_CIPSOV4_C_ACK, | ||
346 | -ret_val); | ||
347 | return ret_val; | 399 | return ret_val; |
348 | } | 400 | } |
349 | 401 | ||
@@ -353,84 +405,239 @@ add_return: | |||
353 | * @info: the Generic NETLINK info block | 405 | * @info: the Generic NETLINK info block |
354 | * | 406 | * |
355 | * Description: | 407 | * Description: |
356 | * Process a user generated LIST message and respond accordingly. Returns | 408 | * Process a user generated LIST message and respond accordingly. While the |
357 | * zero on success and negative values on error. | 409 | * response message generated by the kernel is straightforward, determining |
410 | * before hand the size of the buffer to allocate is not (we have to generate | ||
411 | * the message to know the size). In order to keep this function sane what we | ||
412 | * do is allocate a buffer of NLMSG_GOODSIZE and try to fit the response in | ||
413 | * that size, if we fail then we restart with a larger buffer and try again. | ||
414 | * We continue in this manner until we hit a limit of failed attempts then we | ||
415 | * give up and just send an error message. Returns zero on success and | ||
416 | * negative values on error. | ||
358 | * | 417 | * |
359 | */ | 418 | */ |
360 | static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info) | 419 | static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info) |
361 | { | 420 | { |
362 | int ret_val = -EINVAL; | 421 | int ret_val; |
422 | struct sk_buff *ans_skb = NULL; | ||
423 | u32 nlsze_mult = 1; | ||
424 | void *data; | ||
363 | u32 doi; | 425 | u32 doi; |
364 | struct nlattr *msg = netlbl_netlink_payload_data(skb); | 426 | struct nlattr *nla_a; |
365 | struct sk_buff *ans_skb; | 427 | struct nlattr *nla_b; |
428 | struct cipso_v4_doi *doi_def; | ||
429 | u32 iter; | ||
366 | 430 | ||
367 | if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32) | 431 | if (!info->attrs[NLBL_CIPSOV4_A_DOI]) { |
432 | ret_val = -EINVAL; | ||
368 | goto list_failure; | 433 | goto list_failure; |
434 | } | ||
369 | 435 | ||
370 | doi = nla_get_u32(msg); | 436 | list_start: |
371 | ans_skb = cipso_v4_doi_dump(doi, NLMSG_SPACE(GENL_HDRLEN)); | 437 | ans_skb = nlmsg_new(NLMSG_GOODSIZE * nlsze_mult, GFP_KERNEL); |
372 | if (ans_skb == NULL) { | 438 | if (ans_skb == NULL) { |
373 | ret_val = -ENOMEM; | 439 | ret_val = -ENOMEM; |
374 | goto list_failure; | 440 | goto list_failure; |
375 | } | 441 | } |
376 | netlbl_netlink_hdr_push(ans_skb, | 442 | data = netlbl_netlink_hdr_put(ans_skb, |
377 | info->snd_pid, | 443 | info->snd_pid, |
378 | 0, | 444 | info->snd_seq, |
379 | netlbl_cipsov4_gnl_family.id, | 445 | netlbl_cipsov4_gnl_family.id, |
380 | NLBL_CIPSOV4_C_LIST); | 446 | 0, |
447 | NLBL_CIPSOV4_C_LIST); | ||
448 | if (data == NULL) { | ||
449 | ret_val = -ENOMEM; | ||
450 | goto list_failure; | ||
451 | } | ||
452 | |||
453 | doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); | ||
454 | |||
455 | rcu_read_lock(); | ||
456 | doi_def = cipso_v4_doi_getdef(doi); | ||
457 | if (doi_def == NULL) { | ||
458 | ret_val = -EINVAL; | ||
459 | goto list_failure; | ||
460 | } | ||
461 | |||
462 | ret_val = nla_put_u32(ans_skb, NLBL_CIPSOV4_A_MTYPE, doi_def->type); | ||
463 | if (ret_val != 0) | ||
464 | goto list_failure_lock; | ||
465 | |||
466 | nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_TAGLST); | ||
467 | if (nla_a == NULL) { | ||
468 | ret_val = -ENOMEM; | ||
469 | goto list_failure_lock; | ||
470 | } | ||
471 | for (iter = 0; | ||
472 | iter < CIPSO_V4_TAG_MAXCNT && | ||
473 | doi_def->tags[iter] != CIPSO_V4_TAG_INVALID; | ||
474 | iter++) { | ||
475 | ret_val = nla_put_u8(ans_skb, | ||
476 | NLBL_CIPSOV4_A_TAG, | ||
477 | doi_def->tags[iter]); | ||
478 | if (ret_val != 0) | ||
479 | goto list_failure_lock; | ||
480 | } | ||
481 | nla_nest_end(ans_skb, nla_a); | ||
482 | |||
483 | switch (doi_def->type) { | ||
484 | case CIPSO_V4_MAP_STD: | ||
485 | nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVLLST); | ||
486 | if (nla_a == NULL) { | ||
487 | ret_val = -ENOMEM; | ||
488 | goto list_failure_lock; | ||
489 | } | ||
490 | for (iter = 0; | ||
491 | iter < doi_def->map.std->lvl.local_size; | ||
492 | iter++) { | ||
493 | if (doi_def->map.std->lvl.local[iter] == | ||
494 | CIPSO_V4_INV_LVL) | ||
495 | continue; | ||
496 | |||
497 | nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVL); | ||
498 | if (nla_b == NULL) { | ||
499 | ret_val = -ENOMEM; | ||
500 | goto list_retry; | ||
501 | } | ||
502 | ret_val = nla_put_u32(ans_skb, | ||
503 | NLBL_CIPSOV4_A_MLSLVLLOC, | ||
504 | iter); | ||
505 | if (ret_val != 0) | ||
506 | goto list_retry; | ||
507 | ret_val = nla_put_u32(ans_skb, | ||
508 | NLBL_CIPSOV4_A_MLSLVLREM, | ||
509 | doi_def->map.std->lvl.local[iter]); | ||
510 | if (ret_val != 0) | ||
511 | goto list_retry; | ||
512 | nla_nest_end(ans_skb, nla_b); | ||
513 | } | ||
514 | nla_nest_end(ans_skb, nla_a); | ||
515 | |||
516 | nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCATLST); | ||
517 | if (nla_a == NULL) { | ||
518 | ret_val = -ENOMEM; | ||
519 | goto list_retry; | ||
520 | } | ||
521 | for (iter = 0; | ||
522 | iter < doi_def->map.std->cat.local_size; | ||
523 | iter++) { | ||
524 | if (doi_def->map.std->cat.local[iter] == | ||
525 | CIPSO_V4_INV_CAT) | ||
526 | continue; | ||
527 | |||
528 | nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCAT); | ||
529 | if (nla_b == NULL) { | ||
530 | ret_val = -ENOMEM; | ||
531 | goto list_retry; | ||
532 | } | ||
533 | ret_val = nla_put_u32(ans_skb, | ||
534 | NLBL_CIPSOV4_A_MLSCATLOC, | ||
535 | iter); | ||
536 | if (ret_val != 0) | ||
537 | goto list_retry; | ||
538 | ret_val = nla_put_u32(ans_skb, | ||
539 | NLBL_CIPSOV4_A_MLSCATREM, | ||
540 | doi_def->map.std->cat.local[iter]); | ||
541 | if (ret_val != 0) | ||
542 | goto list_retry; | ||
543 | nla_nest_end(ans_skb, nla_b); | ||
544 | } | ||
545 | nla_nest_end(ans_skb, nla_a); | ||
546 | |||
547 | break; | ||
548 | } | ||
549 | rcu_read_unlock(); | ||
381 | 550 | ||
382 | ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); | 551 | genlmsg_end(ans_skb, data); |
552 | |||
553 | ret_val = genlmsg_unicast(ans_skb, info->snd_pid); | ||
383 | if (ret_val != 0) | 554 | if (ret_val != 0) |
384 | goto list_failure; | 555 | goto list_failure; |
385 | 556 | ||
386 | return 0; | 557 | return 0; |
387 | 558 | ||
559 | list_retry: | ||
560 | /* XXX - this limit is a guesstimate */ | ||
561 | if (nlsze_mult < 4) { | ||
562 | rcu_read_unlock(); | ||
563 | kfree_skb(ans_skb); | ||
564 | nlsze_mult++; | ||
565 | goto list_start; | ||
566 | } | ||
567 | list_failure_lock: | ||
568 | rcu_read_unlock(); | ||
388 | list_failure: | 569 | list_failure: |
389 | netlbl_netlink_send_ack(info, | 570 | kfree_skb(ans_skb); |
390 | netlbl_cipsov4_gnl_family.id, | 571 | return ret_val; |
391 | NLBL_CIPSOV4_C_ACK, | 572 | } |
392 | -ret_val); | 573 | |
574 | /** | ||
575 | * netlbl_cipsov4_listall_cb - cipso_v4_doi_walk() callback for LISTALL | ||
576 | * @doi_def: the CIPSOv4 DOI definition | ||
577 | * @arg: the netlbl_cipsov4_doiwalk_arg structure | ||
578 | * | ||
579 | * Description: | ||
580 | * This function is designed to be used as a callback to the | ||
581 | * cipso_v4_doi_walk() function for use in generating a response for a LISTALL | ||
582 | * message. Returns the size of the message on success, negative values on | ||
583 | * failure. | ||
584 | * | ||
585 | */ | ||
586 | static int netlbl_cipsov4_listall_cb(struct cipso_v4_doi *doi_def, void *arg) | ||
587 | { | ||
588 | int ret_val = -ENOMEM; | ||
589 | struct netlbl_cipsov4_doiwalk_arg *cb_arg = arg; | ||
590 | void *data; | ||
591 | |||
592 | data = netlbl_netlink_hdr_put(cb_arg->skb, | ||
593 | NETLINK_CB(cb_arg->nl_cb->skb).pid, | ||
594 | cb_arg->seq, | ||
595 | netlbl_cipsov4_gnl_family.id, | ||
596 | NLM_F_MULTI, | ||
597 | NLBL_CIPSOV4_C_LISTALL); | ||
598 | if (data == NULL) | ||
599 | goto listall_cb_failure; | ||
600 | |||
601 | ret_val = nla_put_u32(cb_arg->skb, NLBL_CIPSOV4_A_DOI, doi_def->doi); | ||
602 | if (ret_val != 0) | ||
603 | goto listall_cb_failure; | ||
604 | ret_val = nla_put_u32(cb_arg->skb, | ||
605 | NLBL_CIPSOV4_A_MTYPE, | ||
606 | doi_def->type); | ||
607 | if (ret_val != 0) | ||
608 | goto listall_cb_failure; | ||
609 | |||
610 | return genlmsg_end(cb_arg->skb, data); | ||
611 | |||
612 | listall_cb_failure: | ||
613 | genlmsg_cancel(cb_arg->skb, data); | ||
393 | return ret_val; | 614 | return ret_val; |
394 | } | 615 | } |
395 | 616 | ||
396 | /** | 617 | /** |
397 | * netlbl_cipsov4_listall - Handle a LISTALL message | 618 | * netlbl_cipsov4_listall - Handle a LISTALL message |
398 | * @skb: the NETLINK buffer | 619 | * @skb: the NETLINK buffer |
399 | * @info: the Generic NETLINK info block | 620 | * @cb: the NETLINK callback |
400 | * | 621 | * |
401 | * Description: | 622 | * Description: |
402 | * Process a user generated LISTALL message and respond accordingly. Returns | 623 | * Process a user generated LISTALL message and respond accordingly. Returns |
403 | * zero on success and negative values on error. | 624 | * zero on success and negative values on error. |
404 | * | 625 | * |
405 | */ | 626 | */ |
406 | static int netlbl_cipsov4_listall(struct sk_buff *skb, struct genl_info *info) | 627 | static int netlbl_cipsov4_listall(struct sk_buff *skb, |
628 | struct netlink_callback *cb) | ||
407 | { | 629 | { |
408 | int ret_val = -EINVAL; | 630 | struct netlbl_cipsov4_doiwalk_arg cb_arg; |
409 | struct sk_buff *ans_skb; | 631 | int doi_skip = cb->args[0]; |
410 | 632 | ||
411 | ans_skb = cipso_v4_doi_dump_all(NLMSG_SPACE(GENL_HDRLEN)); | 633 | cb_arg.nl_cb = cb; |
412 | if (ans_skb == NULL) { | 634 | cb_arg.skb = skb; |
413 | ret_val = -ENOMEM; | 635 | cb_arg.seq = cb->nlh->nlmsg_seq; |
414 | goto listall_failure; | ||
415 | } | ||
416 | netlbl_netlink_hdr_push(ans_skb, | ||
417 | info->snd_pid, | ||
418 | 0, | ||
419 | netlbl_cipsov4_gnl_family.id, | ||
420 | NLBL_CIPSOV4_C_LISTALL); | ||
421 | 636 | ||
422 | ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); | 637 | cipso_v4_doi_walk(&doi_skip, netlbl_cipsov4_listall_cb, &cb_arg); |
423 | if (ret_val != 0) | ||
424 | goto listall_failure; | ||
425 | |||
426 | return 0; | ||
427 | 638 | ||
428 | listall_failure: | 639 | cb->args[0] = doi_skip; |
429 | netlbl_netlink_send_ack(info, | 640 | return skb->len; |
430 | netlbl_cipsov4_gnl_family.id, | ||
431 | NLBL_CIPSOV4_C_ACK, | ||
432 | -ret_val); | ||
433 | return ret_val; | ||
434 | } | 641 | } |
435 | 642 | ||
436 | /** | 643 | /** |
@@ -445,27 +652,14 @@ listall_failure: | |||
445 | */ | 652 | */ |
446 | static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) | 653 | static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) |
447 | { | 654 | { |
448 | int ret_val; | 655 | int ret_val = -EINVAL; |
449 | u32 doi; | 656 | u32 doi; |
450 | struct nlattr *msg = netlbl_netlink_payload_data(skb); | ||
451 | 657 | ||
452 | ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); | 658 | if (info->attrs[NLBL_CIPSOV4_A_DOI]) { |
453 | if (ret_val != 0) | 659 | doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); |
454 | goto remove_return; | 660 | ret_val = cipso_v4_doi_remove(doi, netlbl_cipsov4_doi_free); |
455 | |||
456 | if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32) { | ||
457 | ret_val = -EINVAL; | ||
458 | goto remove_return; | ||
459 | } | 661 | } |
460 | 662 | ||
461 | doi = nla_get_u32(msg); | ||
462 | ret_val = cipso_v4_doi_remove(doi, netlbl_cipsov4_doi_free); | ||
463 | |||
464 | remove_return: | ||
465 | netlbl_netlink_send_ack(info, | ||
466 | netlbl_cipsov4_gnl_family.id, | ||
467 | NLBL_CIPSOV4_C_ACK, | ||
468 | -ret_val); | ||
469 | return ret_val; | 663 | return ret_val; |
470 | } | 664 | } |
471 | 665 | ||
@@ -475,14 +669,16 @@ remove_return: | |||
475 | 669 | ||
476 | static struct genl_ops netlbl_cipsov4_genl_c_add = { | 670 | static struct genl_ops netlbl_cipsov4_genl_c_add = { |
477 | .cmd = NLBL_CIPSOV4_C_ADD, | 671 | .cmd = NLBL_CIPSOV4_C_ADD, |
478 | .flags = 0, | 672 | .flags = GENL_ADMIN_PERM, |
673 | .policy = netlbl_cipsov4_genl_policy, | ||
479 | .doit = netlbl_cipsov4_add, | 674 | .doit = netlbl_cipsov4_add, |
480 | .dumpit = NULL, | 675 | .dumpit = NULL, |
481 | }; | 676 | }; |
482 | 677 | ||
483 | static struct genl_ops netlbl_cipsov4_genl_c_remove = { | 678 | static struct genl_ops netlbl_cipsov4_genl_c_remove = { |
484 | .cmd = NLBL_CIPSOV4_C_REMOVE, | 679 | .cmd = NLBL_CIPSOV4_C_REMOVE, |
485 | .flags = 0, | 680 | .flags = GENL_ADMIN_PERM, |
681 | .policy = netlbl_cipsov4_genl_policy, | ||
486 | .doit = netlbl_cipsov4_remove, | 682 | .doit = netlbl_cipsov4_remove, |
487 | .dumpit = NULL, | 683 | .dumpit = NULL, |
488 | }; | 684 | }; |
@@ -490,6 +686,7 @@ static struct genl_ops netlbl_cipsov4_genl_c_remove = { | |||
490 | static struct genl_ops netlbl_cipsov4_genl_c_list = { | 686 | static struct genl_ops netlbl_cipsov4_genl_c_list = { |
491 | .cmd = NLBL_CIPSOV4_C_LIST, | 687 | .cmd = NLBL_CIPSOV4_C_LIST, |
492 | .flags = 0, | 688 | .flags = 0, |
689 | .policy = netlbl_cipsov4_genl_policy, | ||
493 | .doit = netlbl_cipsov4_list, | 690 | .doit = netlbl_cipsov4_list, |
494 | .dumpit = NULL, | 691 | .dumpit = NULL, |
495 | }; | 692 | }; |
@@ -497,8 +694,9 @@ static struct genl_ops netlbl_cipsov4_genl_c_list = { | |||
497 | static struct genl_ops netlbl_cipsov4_genl_c_listall = { | 694 | static struct genl_ops netlbl_cipsov4_genl_c_listall = { |
498 | .cmd = NLBL_CIPSOV4_C_LISTALL, | 695 | .cmd = NLBL_CIPSOV4_C_LISTALL, |
499 | .flags = 0, | 696 | .flags = 0, |
500 | .doit = netlbl_cipsov4_listall, | 697 | .policy = netlbl_cipsov4_genl_policy, |
501 | .dumpit = NULL, | 698 | .doit = NULL, |
699 | .dumpit = netlbl_cipsov4_listall, | ||
502 | }; | 700 | }; |
503 | 701 | ||
504 | /* | 702 | /* |
diff --git a/net/netlabel/netlabel_cipso_v4.h b/net/netlabel/netlabel_cipso_v4.h index 4c6ff4b93004..f03cf9b78286 100644 --- a/net/netlabel/netlabel_cipso_v4.h +++ b/net/netlabel/netlabel_cipso_v4.h | |||
@@ -34,175 +34,71 @@ | |||
34 | #include <net/netlabel.h> | 34 | #include <net/netlabel.h> |
35 | 35 | ||
36 | /* | 36 | /* |
37 | * The following NetLabel payloads are supported by the CIPSO subsystem, all | 37 | * The following NetLabel payloads are supported by the CIPSO subsystem. |
38 | * of which are preceeded by the nlmsghdr struct. | ||
39 | * | 38 | * |
40 | * o ACK: | 39 | * o ADD: |
41 | * Sent by the kernel in response to an applications message, applications | 40 | * Sent by an application to add a new DOI mapping table. |
42 | * should never send this message. | ||
43 | * | 41 | * |
44 | * +----------------------+-----------------------+ | 42 | * Required attributes: |
45 | * | seq number (32 bits) | return code (32 bits) | | ||
46 | * +----------------------+-----------------------+ | ||
47 | * | 43 | * |
48 | * seq number: the sequence number of the original message, taken from the | 44 | * NLBL_CIPSOV4_A_DOI |
49 | * nlmsghdr structure | 45 | * NLBL_CIPSOV4_A_MTYPE |
50 | * return code: return value, based on errno values | 46 | * NLBL_CIPSOV4_A_TAGLST |
51 | * | 47 | * |
52 | * o ADD: | 48 | * If using CIPSO_V4_MAP_STD the following attributes are required: |
53 | * Sent by an application to add a new DOI mapping table, after completion | 49 | * |
54 | * of the task the kernel should ACK this message. | 50 | * NLBL_CIPSOV4_A_MLSLVLLST |
55 | * | 51 | * NLBL_CIPSOV4_A_MLSCATLST |
56 | * +---------------+--------------------+---------------------+ | 52 | * |
57 | * | DOI (32 bits) | map type (32 bits) | tag count (32 bits) | ... | 53 | * If using CIPSO_V4_MAP_PASS no additional attributes are required. |
58 | * +---------------+--------------------+---------------------+ | ||
59 | * | ||
60 | * +-----------------+ | ||
61 | * | tag #X (8 bits) | ... repeated | ||
62 | * +-----------------+ | ||
63 | * | ||
64 | * +-------------- ---- --- -- - | ||
65 | * | mapping data | ||
66 | * +-------------- ---- --- -- - | ||
67 | * | ||
68 | * DOI: the DOI value | ||
69 | * map type: the mapping table type (defined in the cipso_ipv4.h header | ||
70 | * as CIPSO_V4_MAP_*) | ||
71 | * tag count: the number of tags, must be greater than zero | ||
72 | * tag: the CIPSO tag for the DOI, tags listed first are given | ||
73 | * higher priorirty when sending packets | ||
74 | * mapping data: specific to the map type (see below) | ||
75 | * | ||
76 | * CIPSO_V4_MAP_STD | ||
77 | * | ||
78 | * +------------------+-----------------------+----------------------+ | ||
79 | * | levels (32 bits) | max l level (32 bits) | max r level (8 bits) | ... | ||
80 | * +------------------+-----------------------+----------------------+ | ||
81 | * | ||
82 | * +----------------------+---------------------+---------------------+ | ||
83 | * | categories (32 bits) | max l cat (32 bits) | max r cat (16 bits) | ... | ||
84 | * +----------------------+---------------------+---------------------+ | ||
85 | * | ||
86 | * +--------------------------+-------------------------+ | ||
87 | * | local level #X (32 bits) | CIPSO level #X (8 bits) | ... repeated | ||
88 | * +--------------------------+-------------------------+ | ||
89 | * | ||
90 | * +-----------------------------+-----------------------------+ | ||
91 | * | local category #X (32 bits) | CIPSO category #X (16 bits) | ... repeated | ||
92 | * +-----------------------------+-----------------------------+ | ||
93 | * | ||
94 | * levels: the number of level mappings | ||
95 | * max l level: the highest local level | ||
96 | * max r level: the highest remote/CIPSO level | ||
97 | * categories: the number of category mappings | ||
98 | * max l cat: the highest local category | ||
99 | * max r cat: the highest remote/CIPSO category | ||
100 | * local level: the local part of a level mapping | ||
101 | * CIPSO level: the remote/CIPSO part of a level mapping | ||
102 | * local category: the local part of a category mapping | ||
103 | * CIPSO category: the remote/CIPSO part of a category mapping | ||
104 | * | ||
105 | * CIPSO_V4_MAP_PASS | ||
106 | * | ||
107 | * No mapping data is needed for this map type. | ||
108 | * | 54 | * |
109 | * o REMOVE: | 55 | * o REMOVE: |
110 | * Sent by an application to remove a specific DOI mapping table from the | 56 | * Sent by an application to remove a specific DOI mapping table from the |
111 | * CIPSO V4 system. The kernel should ACK this message. | 57 | * CIPSO V4 system. |
112 | * | 58 | * |
113 | * +---------------+ | 59 | * Required attributes: |
114 | * | DOI (32 bits) | | ||
115 | * +---------------+ | ||
116 | * | 60 | * |
117 | * DOI: the DOI value | 61 | * NLBL_CIPSOV4_A_DOI |
118 | * | 62 | * |
119 | * o LIST: | 63 | * o LIST: |
120 | * Sent by an application to list the details of a DOI definition. The | 64 | * Sent by an application to list the details of a DOI definition. On |
121 | * kernel should send an ACK on error or a response as indicated below. The | 65 | * success the kernel should send a response using the following format. |
122 | * application generated message format is shown below. | ||
123 | * | 66 | * |
124 | * +---------------+ | 67 | * Required attributes: |
125 | * | DOI (32 bits) | | ||
126 | * +---------------+ | ||
127 | * | 68 | * |
128 | * DOI: the DOI value | 69 | * NLBL_CIPSOV4_A_DOI |
129 | * | 70 | * |
130 | * The valid response message format depends on the type of the DOI mapping, | 71 | * The valid response message format depends on the type of the DOI mapping, |
131 | * the known formats are shown below. | 72 | * the defined formats are shown below. |
132 | * | ||
133 | * +--------------------+ | ||
134 | * | map type (32 bits) | ... | ||
135 | * +--------------------+ | ||
136 | * | ||
137 | * map type: the DOI mapping table type (defined in the cipso_ipv4.h | ||
138 | * header as CIPSO_V4_MAP_*) | ||
139 | * | ||
140 | * (map type == CIPSO_V4_MAP_STD) | ||
141 | * | ||
142 | * +----------------+------------------+----------------------+ | ||
143 | * | tags (32 bits) | levels (32 bits) | categories (32 bits) | ... | ||
144 | * +----------------+------------------+----------------------+ | ||
145 | * | 73 | * |
146 | * +-----------------+ | 74 | * Required attributes: |
147 | * | tag #X (8 bits) | ... repeated | ||
148 | * +-----------------+ | ||
149 | * | 75 | * |
150 | * +--------------------------+-------------------------+ | 76 | * NLBL_CIPSOV4_A_MTYPE |
151 | * | local level #X (32 bits) | CIPSO level #X (8 bits) | ... repeated | 77 | * NLBL_CIPSOV4_A_TAGLST |
152 | * +--------------------------+-------------------------+ | ||
153 | * | 78 | * |
154 | * +-----------------------------+-----------------------------+ | 79 | * If using CIPSO_V4_MAP_STD the following attributes are required: |
155 | * | local category #X (32 bits) | CIPSO category #X (16 bits) | ... repeated | ||
156 | * +-----------------------------+-----------------------------+ | ||
157 | * | 80 | * |
158 | * tags: the number of CIPSO tag types | 81 | * NLBL_CIPSOV4_A_MLSLVLLST |
159 | * levels: the number of level mappings | 82 | * NLBL_CIPSOV4_A_MLSCATLST |
160 | * categories: the number of category mappings | ||
161 | * tag: the tag number, tags listed first are given higher | ||
162 | * priority when sending packets | ||
163 | * local level: the local part of a level mapping | ||
164 | * CIPSO level: the remote/CIPSO part of a level mapping | ||
165 | * local category: the local part of a category mapping | ||
166 | * CIPSO category: the remote/CIPSO part of a category mapping | ||
167 | * | 83 | * |
168 | * (map type == CIPSO_V4_MAP_PASS) | 84 | * If using CIPSO_V4_MAP_PASS no additional attributes are required. |
169 | * | ||
170 | * +----------------+ | ||
171 | * | tags (32 bits) | ... | ||
172 | * +----------------+ | ||
173 | * | ||
174 | * +-----------------+ | ||
175 | * | tag #X (8 bits) | ... repeated | ||
176 | * +-----------------+ | ||
177 | * | ||
178 | * tags: the number of CIPSO tag types | ||
179 | * tag: the tag number, tags listed first are given higher | ||
180 | * priority when sending packets | ||
181 | * | 85 | * |
182 | * o LISTALL: | 86 | * o LISTALL: |
183 | * This message is sent by an application to list the valid DOIs on the | 87 | * This message is sent by an application to list the valid DOIs on the |
184 | * system. There is no payload and the kernel should respond with an ACK | 88 | * system. When sent by an application there is no payload and the |
185 | * or the following message. | 89 | * NLM_F_DUMP flag should be set. The kernel should respond with a series of |
186 | * | 90 | * the following messages. |
187 | * +---------------------+------------------+-----------------------+ | ||
188 | * | DOI count (32 bits) | DOI #X (32 bits) | map type #X (32 bits) | | ||
189 | * +---------------------+------------------+-----------------------+ | ||
190 | * | 91 | * |
191 | * +-----------------------+ | 92 | * Required attributes: |
192 | * | map type #X (32 bits) | ... | ||
193 | * +-----------------------+ | ||
194 | * | 93 | * |
195 | * DOI count: the number of DOIs | 94 | * NLBL_CIPSOV4_A_DOI |
196 | * DOI: the DOI value | 95 | * NLBL_CIPSOV4_A_MTYPE |
197 | * map type: the DOI mapping table type (defined in the cipso_ipv4.h | ||
198 | * header as CIPSO_V4_MAP_*) | ||
199 | * | 96 | * |
200 | */ | 97 | */ |
201 | 98 | ||
202 | /* NetLabel CIPSOv4 commands */ | 99 | /* NetLabel CIPSOv4 commands */ |
203 | enum { | 100 | enum { |
204 | NLBL_CIPSOV4_C_UNSPEC, | 101 | NLBL_CIPSOV4_C_UNSPEC, |
205 | NLBL_CIPSOV4_C_ACK, | ||
206 | NLBL_CIPSOV4_C_ADD, | 102 | NLBL_CIPSOV4_C_ADD, |
207 | NLBL_CIPSOV4_C_REMOVE, | 103 | NLBL_CIPSOV4_C_REMOVE, |
208 | NLBL_CIPSOV4_C_LIST, | 104 | NLBL_CIPSOV4_C_LIST, |
@@ -211,6 +107,59 @@ enum { | |||
211 | }; | 107 | }; |
212 | #define NLBL_CIPSOV4_C_MAX (__NLBL_CIPSOV4_C_MAX - 1) | 108 | #define NLBL_CIPSOV4_C_MAX (__NLBL_CIPSOV4_C_MAX - 1) |
213 | 109 | ||
110 | /* NetLabel CIPSOv4 attributes */ | ||
111 | enum { | ||
112 | NLBL_CIPSOV4_A_UNSPEC, | ||
113 | NLBL_CIPSOV4_A_DOI, | ||
114 | /* (NLA_U32) | ||
115 | * the DOI value */ | ||
116 | NLBL_CIPSOV4_A_MTYPE, | ||
117 | /* (NLA_U32) | ||
118 | * the mapping table type (defined in the cipso_ipv4.h header as | ||
119 | * CIPSO_V4_MAP_*) */ | ||
120 | NLBL_CIPSOV4_A_TAG, | ||
121 | /* (NLA_U8) | ||
122 | * a CIPSO tag type, meant to be used within a NLBL_CIPSOV4_A_TAGLST | ||
123 | * attribute */ | ||
124 | NLBL_CIPSOV4_A_TAGLST, | ||
125 | /* (NLA_NESTED) | ||
126 | * the CIPSO tag list for the DOI, there must be at least one | ||
127 | * NLBL_CIPSOV4_A_TAG attribute, tags listed first are given higher | ||
128 | * priorirty when sending packets */ | ||
129 | NLBL_CIPSOV4_A_MLSLVLLOC, | ||
130 | /* (NLA_U32) | ||
131 | * the local MLS sensitivity level */ | ||
132 | NLBL_CIPSOV4_A_MLSLVLREM, | ||
133 | /* (NLA_U32) | ||
134 | * the remote MLS sensitivity level */ | ||
135 | NLBL_CIPSOV4_A_MLSLVL, | ||
136 | /* (NLA_NESTED) | ||
137 | * a MLS sensitivity level mapping, must contain only one attribute of | ||
138 | * each of the following types: NLBL_CIPSOV4_A_MLSLVLLOC and | ||
139 | * NLBL_CIPSOV4_A_MLSLVLREM */ | ||
140 | NLBL_CIPSOV4_A_MLSLVLLST, | ||
141 | /* (NLA_NESTED) | ||
142 | * the CIPSO level mappings, there must be at least one | ||
143 | * NLBL_CIPSOV4_A_MLSLVL attribute */ | ||
144 | NLBL_CIPSOV4_A_MLSCATLOC, | ||
145 | /* (NLA_U32) | ||
146 | * the local MLS category */ | ||
147 | NLBL_CIPSOV4_A_MLSCATREM, | ||
148 | /* (NLA_U32) | ||
149 | * the remote MLS category */ | ||
150 | NLBL_CIPSOV4_A_MLSCAT, | ||
151 | /* (NLA_NESTED) | ||
152 | * a MLS category mapping, must contain only one attribute of each of | ||
153 | * the following types: NLBL_CIPSOV4_A_MLSCATLOC and | ||
154 | * NLBL_CIPSOV4_A_MLSCATREM */ | ||
155 | NLBL_CIPSOV4_A_MLSCATLST, | ||
156 | /* (NLA_NESTED) | ||
157 | * the CIPSO category mappings, there must be at least one | ||
158 | * NLBL_CIPSOV4_A_MLSCAT attribute */ | ||
159 | __NLBL_CIPSOV4_A_MAX, | ||
160 | }; | ||
161 | #define NLBL_CIPSOV4_A_MAX (__NLBL_CIPSOV4_A_MAX - 1) | ||
162 | |||
214 | /* NetLabel protocol functions */ | 163 | /* NetLabel protocol functions */ |
215 | int netlbl_cipsov4_genl_init(void); | 164 | int netlbl_cipsov4_genl_init(void); |
216 | 165 | ||
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index 0489a1378101..f56d7a8ac7b7 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c | |||
@@ -354,160 +354,51 @@ struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain) | |||
354 | } | 354 | } |
355 | 355 | ||
356 | /** | 356 | /** |
357 | * netlbl_domhsh_dump - Dump the domain hash table into a sk_buff | 357 | * netlbl_domhsh_walk - Iterate through the domain mapping hash table |
358 | * @skip_bkt: the number of buckets to skip at the start | ||
359 | * @skip_chain: the number of entries to skip in the first iterated bucket | ||
360 | * @callback: callback for each entry | ||
361 | * @cb_arg: argument for the callback function | ||
358 | * | 362 | * |
359 | * Description: | 363 | * Description: |
360 | * Dump the domain hash table into a buffer suitable for returning to an | 364 | * Interate over the domain mapping hash table, skipping the first @skip_bkt |
361 | * application in response to a NetLabel management DOMAIN message. This | 365 | * buckets and @skip_chain entries. For each entry in the table call |
362 | * function may fail if another process is growing the hash table at the same | 366 | * @callback, if @callback returns a negative value stop 'walking' through the |
363 | * time. The returned sk_buff has room at the front of the sk_buff for | 367 | * table and return. Updates the values in @skip_bkt and @skip_chain on |
364 | * @headroom bytes. See netlabel.h for the DOMAIN message format. Returns a | 368 | * return. Returns zero on succcess, negative values on failure. |
365 | * pointer to a sk_buff on success, NULL on error. | ||
366 | * | 369 | * |
367 | */ | 370 | */ |
368 | struct sk_buff *netlbl_domhsh_dump(size_t headroom) | 371 | int netlbl_domhsh_walk(u32 *skip_bkt, |
372 | u32 *skip_chain, | ||
373 | int (*callback) (struct netlbl_dom_map *entry, void *arg), | ||
374 | void *cb_arg) | ||
369 | { | 375 | { |
370 | struct sk_buff *skb = NULL; | 376 | int ret_val = -ENOENT; |
371 | ssize_t buf_len; | 377 | u32 iter_bkt; |
372 | u32 bkt_iter; | 378 | struct netlbl_dom_map *iter_entry; |
373 | u32 dom_cnt = 0; | 379 | u32 chain_cnt = 0; |
374 | struct netlbl_domhsh_tbl *hsh_tbl; | ||
375 | struct netlbl_dom_map *list_iter; | ||
376 | ssize_t tmp_len; | ||
377 | 380 | ||
378 | buf_len = NETLBL_LEN_U32; | ||
379 | rcu_read_lock(); | 381 | rcu_read_lock(); |
380 | hsh_tbl = rcu_dereference(netlbl_domhsh); | 382 | for (iter_bkt = *skip_bkt; |
381 | for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++) | 383 | iter_bkt < rcu_dereference(netlbl_domhsh)->size; |
382 | list_for_each_entry_rcu(list_iter, | 384 | iter_bkt++, chain_cnt = 0) { |
383 | &hsh_tbl->tbl[bkt_iter], list) { | 385 | list_for_each_entry_rcu(iter_entry, |
384 | buf_len += NETLBL_LEN_U32 + | 386 | &netlbl_domhsh->tbl[iter_bkt], |
385 | nla_total_size(strlen(list_iter->domain) + 1); | 387 | list) |
386 | switch (list_iter->type) { | 388 | if (iter_entry->valid) { |
387 | case NETLBL_NLTYPE_UNLABELED: | 389 | if (chain_cnt++ < *skip_chain) |
388 | break; | 390 | continue; |
389 | case NETLBL_NLTYPE_CIPSOV4: | 391 | ret_val = callback(iter_entry, cb_arg); |
390 | buf_len += 2 * NETLBL_LEN_U32; | 392 | if (ret_val < 0) { |
391 | break; | 393 | chain_cnt--; |
392 | } | 394 | goto walk_return; |
393 | dom_cnt++; | 395 | } |
394 | } | ||
395 | |||
396 | skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC); | ||
397 | if (skb == NULL) | ||
398 | goto dump_failure; | ||
399 | |||
400 | if (nla_put_u32(skb, NLA_U32, dom_cnt) != 0) | ||
401 | goto dump_failure; | ||
402 | buf_len -= NETLBL_LEN_U32; | ||
403 | hsh_tbl = rcu_dereference(netlbl_domhsh); | ||
404 | for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++) | ||
405 | list_for_each_entry_rcu(list_iter, | ||
406 | &hsh_tbl->tbl[bkt_iter], list) { | ||
407 | tmp_len = nla_total_size(strlen(list_iter->domain) + | ||
408 | 1); | ||
409 | if (buf_len < NETLBL_LEN_U32 + tmp_len) | ||
410 | goto dump_failure; | ||
411 | if (nla_put_string(skb, | ||
412 | NLA_STRING, | ||
413 | list_iter->domain) != 0) | ||
414 | goto dump_failure; | ||
415 | if (nla_put_u32(skb, NLA_U32, list_iter->type) != 0) | ||
416 | goto dump_failure; | ||
417 | buf_len -= NETLBL_LEN_U32 + tmp_len; | ||
418 | switch (list_iter->type) { | ||
419 | case NETLBL_NLTYPE_UNLABELED: | ||
420 | break; | ||
421 | case NETLBL_NLTYPE_CIPSOV4: | ||
422 | if (buf_len < 2 * NETLBL_LEN_U32) | ||
423 | goto dump_failure; | ||
424 | if (nla_put_u32(skb, | ||
425 | NLA_U32, | ||
426 | list_iter->type_def.cipsov4->type) != 0) | ||
427 | goto dump_failure; | ||
428 | if (nla_put_u32(skb, | ||
429 | NLA_U32, | ||
430 | list_iter->type_def.cipsov4->doi) != 0) | ||
431 | goto dump_failure; | ||
432 | buf_len -= 2 * NETLBL_LEN_U32; | ||
433 | break; | ||
434 | } | 396 | } |
435 | } | 397 | } |
436 | rcu_read_unlock(); | ||
437 | |||
438 | return skb; | ||
439 | |||
440 | dump_failure: | ||
441 | rcu_read_unlock(); | ||
442 | kfree_skb(skb); | ||
443 | return NULL; | ||
444 | } | ||
445 | |||
446 | /** | ||
447 | * netlbl_domhsh_dump_default - Dump the default domain mapping into a sk_buff | ||
448 | * | ||
449 | * Description: | ||
450 | * Dump the default domain mapping into a buffer suitable for returning to an | ||
451 | * application in response to a NetLabel management DEFDOMAIN message. This | ||
452 | * function may fail if another process is changing the default domain mapping | ||
453 | * at the same time. The returned sk_buff has room at the front of the | ||
454 | * skb_buff for @headroom bytes. See netlabel.h for the DEFDOMAIN message | ||
455 | * format. Returns a pointer to a sk_buff on success, NULL on error. | ||
456 | * | ||
457 | */ | ||
458 | struct sk_buff *netlbl_domhsh_dump_default(size_t headroom) | ||
459 | { | ||
460 | struct sk_buff *skb; | ||
461 | ssize_t buf_len; | ||
462 | struct netlbl_dom_map *entry; | ||
463 | |||
464 | buf_len = NETLBL_LEN_U32; | ||
465 | rcu_read_lock(); | ||
466 | entry = rcu_dereference(netlbl_domhsh_def); | ||
467 | if (entry != NULL) | ||
468 | switch (entry->type) { | ||
469 | case NETLBL_NLTYPE_UNLABELED: | ||
470 | break; | ||
471 | case NETLBL_NLTYPE_CIPSOV4: | ||
472 | buf_len += 2 * NETLBL_LEN_U32; | ||
473 | break; | ||
474 | } | ||
475 | |||
476 | skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC); | ||
477 | if (skb == NULL) | ||
478 | goto dump_default_failure; | ||
479 | |||
480 | if (entry != rcu_dereference(netlbl_domhsh_def)) | ||
481 | goto dump_default_failure; | ||
482 | if (entry != NULL) { | ||
483 | if (nla_put_u32(skb, NLA_U32, entry->type) != 0) | ||
484 | goto dump_default_failure; | ||
485 | buf_len -= NETLBL_LEN_U32; | ||
486 | switch (entry->type) { | ||
487 | case NETLBL_NLTYPE_UNLABELED: | ||
488 | break; | ||
489 | case NETLBL_NLTYPE_CIPSOV4: | ||
490 | if (buf_len < 2 * NETLBL_LEN_U32) | ||
491 | goto dump_default_failure; | ||
492 | if (nla_put_u32(skb, | ||
493 | NLA_U32, | ||
494 | entry->type_def.cipsov4->type) != 0) | ||
495 | goto dump_default_failure; | ||
496 | if (nla_put_u32(skb, | ||
497 | NLA_U32, | ||
498 | entry->type_def.cipsov4->doi) != 0) | ||
499 | goto dump_default_failure; | ||
500 | buf_len -= 2 * NETLBL_LEN_U32; | ||
501 | break; | ||
502 | } | ||
503 | } else | ||
504 | nla_put_u32(skb, NLA_U32, NETLBL_NLTYPE_NONE); | ||
505 | rcu_read_unlock(); | ||
506 | |||
507 | return skb; | ||
508 | 398 | ||
509 | dump_default_failure: | 399 | walk_return: |
510 | rcu_read_unlock(); | 400 | rcu_read_unlock(); |
511 | kfree_skb(skb); | 401 | *skip_bkt = iter_bkt; |
512 | return NULL; | 402 | *skip_chain = chain_cnt; |
403 | return ret_val; | ||
513 | } | 404 | } |
diff --git a/net/netlabel/netlabel_domainhash.h b/net/netlabel/netlabel_domainhash.h index 99a2287de246..02af72a7877c 100644 --- a/net/netlabel/netlabel_domainhash.h +++ b/net/netlabel/netlabel_domainhash.h | |||
@@ -61,7 +61,9 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry); | |||
61 | int netlbl_domhsh_add_default(struct netlbl_dom_map *entry); | 61 | int netlbl_domhsh_add_default(struct netlbl_dom_map *entry); |
62 | int netlbl_domhsh_remove_default(void); | 62 | int netlbl_domhsh_remove_default(void); |
63 | struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain); | 63 | struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain); |
64 | struct sk_buff *netlbl_domhsh_dump(size_t headroom); | 64 | int netlbl_domhsh_walk(u32 *skip_bkt, |
65 | struct sk_buff *netlbl_domhsh_dump_default(size_t headroom); | 65 | u32 *skip_chain, |
66 | int (*callback) (struct netlbl_dom_map *entry, void *arg), | ||
67 | void *cb_arg); | ||
66 | 68 | ||
67 | #endif | 69 | #endif |
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 0fd8aaafe23f..54fb7de3c2b1 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c | |||
@@ -85,6 +85,29 @@ socket_setattr_return: | |||
85 | } | 85 | } |
86 | 86 | ||
87 | /** | 87 | /** |
88 | * netlbl_sock_getattr - Determine the security attributes of a sock | ||
89 | * @sk: the sock | ||
90 | * @secattr: the security attributes | ||
91 | * | ||
92 | * Description: | ||
93 | * Examines the given sock to see any NetLabel style labeling has been | ||
94 | * applied to the sock, if so it parses the socket label and returns the | ||
95 | * security attributes in @secattr. Returns zero on success, negative values | ||
96 | * on failure. | ||
97 | * | ||
98 | */ | ||
99 | int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) | ||
100 | { | ||
101 | int ret_val; | ||
102 | |||
103 | ret_val = cipso_v4_sock_getattr(sk, secattr); | ||
104 | if (ret_val == 0) | ||
105 | return 0; | ||
106 | |||
107 | return netlbl_unlabel_getattr(secattr); | ||
108 | } | ||
109 | |||
110 | /** | ||
88 | * netlbl_socket_getattr - Determine the security attributes of a socket | 111 | * netlbl_socket_getattr - Determine the security attributes of a socket |
89 | * @sock: the socket | 112 | * @sock: the socket |
90 | * @secattr: the security attributes | 113 | * @secattr: the security attributes |
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index 85bc11a1fc46..8626c9f678eb 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c | |||
@@ -42,15 +42,29 @@ | |||
42 | #include "netlabel_user.h" | 42 | #include "netlabel_user.h" |
43 | #include "netlabel_mgmt.h" | 43 | #include "netlabel_mgmt.h" |
44 | 44 | ||
45 | /* Argument struct for netlbl_domhsh_walk() */ | ||
46 | struct netlbl_domhsh_walk_arg { | ||
47 | struct netlink_callback *nl_cb; | ||
48 | struct sk_buff *skb; | ||
49 | u32 seq; | ||
50 | }; | ||
51 | |||
45 | /* NetLabel Generic NETLINK CIPSOv4 family */ | 52 | /* NetLabel Generic NETLINK CIPSOv4 family */ |
46 | static struct genl_family netlbl_mgmt_gnl_family = { | 53 | static struct genl_family netlbl_mgmt_gnl_family = { |
47 | .id = GENL_ID_GENERATE, | 54 | .id = GENL_ID_GENERATE, |
48 | .hdrsize = 0, | 55 | .hdrsize = 0, |
49 | .name = NETLBL_NLTYPE_MGMT_NAME, | 56 | .name = NETLBL_NLTYPE_MGMT_NAME, |
50 | .version = NETLBL_PROTO_VERSION, | 57 | .version = NETLBL_PROTO_VERSION, |
51 | .maxattr = 0, | 58 | .maxattr = NLBL_MGMT_A_MAX, |
52 | }; | 59 | }; |
53 | 60 | ||
61 | /* NetLabel Netlink attribute policy */ | ||
62 | static struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = { | ||
63 | [NLBL_MGMT_A_DOMAIN] = { .type = NLA_NUL_STRING }, | ||
64 | [NLBL_MGMT_A_PROTOCOL] = { .type = NLA_U32 }, | ||
65 | [NLBL_MGMT_A_VERSION] = { .type = NLA_U32 }, | ||
66 | [NLBL_MGMT_A_CV4DOI] = { .type = NLA_U32 }, | ||
67 | }; | ||
54 | 68 | ||
55 | /* | 69 | /* |
56 | * NetLabel Command Handlers | 70 | * NetLabel Command Handlers |
@@ -70,97 +84,62 @@ static struct genl_family netlbl_mgmt_gnl_family = { | |||
70 | static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info) | 84 | static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info) |
71 | { | 85 | { |
72 | int ret_val = -EINVAL; | 86 | int ret_val = -EINVAL; |
73 | struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb); | ||
74 | int msg_len = netlbl_netlink_payload_len(skb); | ||
75 | u32 count; | ||
76 | struct netlbl_dom_map *entry = NULL; | 87 | struct netlbl_dom_map *entry = NULL; |
77 | u32 iter; | 88 | size_t tmp_size; |
78 | u32 tmp_val; | 89 | u32 tmp_val; |
79 | int tmp_size; | ||
80 | 90 | ||
81 | ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); | 91 | if (!info->attrs[NLBL_MGMT_A_DOMAIN] || |
82 | if (ret_val != 0) | 92 | !info->attrs[NLBL_MGMT_A_PROTOCOL]) |
83 | goto add_failure; | 93 | goto add_failure; |
84 | 94 | ||
85 | if (msg_len < NETLBL_LEN_U32) | 95 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
96 | if (entry == NULL) { | ||
97 | ret_val = -ENOMEM; | ||
98 | goto add_failure; | ||
99 | } | ||
100 | tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]); | ||
101 | entry->domain = kmalloc(tmp_size, GFP_KERNEL); | ||
102 | if (entry->domain == NULL) { | ||
103 | ret_val = -ENOMEM; | ||
86 | goto add_failure; | 104 | goto add_failure; |
87 | count = netlbl_getinc_u32(&msg_ptr, &msg_len); | 105 | } |
106 | entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]); | ||
107 | nla_strlcpy(entry->domain, info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size); | ||
88 | 108 | ||
89 | for (iter = 0; iter < count && msg_len > 0; iter++, entry = NULL) { | 109 | switch (entry->type) { |
90 | if (msg_len <= 0) { | 110 | case NETLBL_NLTYPE_UNLABELED: |
91 | ret_val = -EINVAL; | 111 | ret_val = netlbl_domhsh_add(entry); |
92 | goto add_failure; | 112 | break; |
93 | } | 113 | case NETLBL_NLTYPE_CIPSOV4: |
94 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | 114 | if (!info->attrs[NLBL_MGMT_A_CV4DOI]) |
95 | if (entry == NULL) { | ||
96 | ret_val = -ENOMEM; | ||
97 | goto add_failure; | ||
98 | } | ||
99 | tmp_size = nla_len(msg_ptr); | ||
100 | if (tmp_size <= 0 || tmp_size > msg_len) { | ||
101 | ret_val = -EINVAL; | ||
102 | goto add_failure; | ||
103 | } | ||
104 | entry->domain = kmalloc(tmp_size, GFP_KERNEL); | ||
105 | if (entry->domain == NULL) { | ||
106 | ret_val = -ENOMEM; | ||
107 | goto add_failure; | 115 | goto add_failure; |
108 | } | ||
109 | nla_strlcpy(entry->domain, msg_ptr, tmp_size); | ||
110 | entry->domain[tmp_size - 1] = '\0'; | ||
111 | msg_ptr = nla_next(msg_ptr, &msg_len); | ||
112 | 116 | ||
113 | if (msg_len < NETLBL_LEN_U32) { | 117 | tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]); |
114 | ret_val = -EINVAL; | 118 | /* We should be holding a rcu_read_lock() here while we hold |
115 | goto add_failure; | 119 | * the result but since the entry will always be deleted when |
116 | } | 120 | * the CIPSO DOI is deleted we aren't going to keep the |
117 | tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len); | 121 | * lock. */ |
118 | entry->type = tmp_val; | 122 | rcu_read_lock(); |
119 | switch (tmp_val) { | 123 | entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); |
120 | case NETLBL_NLTYPE_UNLABELED: | 124 | if (entry->type_def.cipsov4 == NULL) { |
121 | ret_val = netlbl_domhsh_add(entry); | ||
122 | break; | ||
123 | case NETLBL_NLTYPE_CIPSOV4: | ||
124 | if (msg_len < NETLBL_LEN_U32) { | ||
125 | ret_val = -EINVAL; | ||
126 | goto add_failure; | ||
127 | } | ||
128 | tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len); | ||
129 | /* We should be holding a rcu_read_lock() here | ||
130 | * while we hold the result but since the entry | ||
131 | * will always be deleted when the CIPSO DOI | ||
132 | * is deleted we aren't going to keep the lock. */ | ||
133 | rcu_read_lock(); | ||
134 | entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); | ||
135 | if (entry->type_def.cipsov4 == NULL) { | ||
136 | rcu_read_unlock(); | ||
137 | ret_val = -EINVAL; | ||
138 | goto add_failure; | ||
139 | } | ||
140 | ret_val = netlbl_domhsh_add(entry); | ||
141 | rcu_read_unlock(); | 125 | rcu_read_unlock(); |
142 | break; | ||
143 | default: | ||
144 | ret_val = -EINVAL; | ||
145 | } | ||
146 | if (ret_val != 0) | ||
147 | goto add_failure; | 126 | goto add_failure; |
127 | } | ||
128 | ret_val = netlbl_domhsh_add(entry); | ||
129 | rcu_read_unlock(); | ||
130 | break; | ||
131 | default: | ||
132 | goto add_failure; | ||
148 | } | 133 | } |
134 | if (ret_val != 0) | ||
135 | goto add_failure; | ||
149 | 136 | ||
150 | netlbl_netlink_send_ack(info, | ||
151 | netlbl_mgmt_gnl_family.id, | ||
152 | NLBL_MGMT_C_ACK, | ||
153 | NETLBL_E_OK); | ||
154 | return 0; | 137 | return 0; |
155 | 138 | ||
156 | add_failure: | 139 | add_failure: |
157 | if (entry) | 140 | if (entry) |
158 | kfree(entry->domain); | 141 | kfree(entry->domain); |
159 | kfree(entry); | 142 | kfree(entry); |
160 | netlbl_netlink_send_ack(info, | ||
161 | netlbl_mgmt_gnl_family.id, | ||
162 | NLBL_MGMT_C_ACK, | ||
163 | -ret_val); | ||
164 | return ret_val; | 143 | return ret_val; |
165 | } | 144 | } |
166 | 145 | ||
@@ -176,87 +155,98 @@ add_failure: | |||
176 | */ | 155 | */ |
177 | static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info) | 156 | static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info) |
178 | { | 157 | { |
179 | int ret_val = -EINVAL; | 158 | char *domain; |
180 | struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb); | ||
181 | int msg_len = netlbl_netlink_payload_len(skb); | ||
182 | u32 count; | ||
183 | u32 iter; | ||
184 | int tmp_size; | ||
185 | unsigned char *domain; | ||
186 | |||
187 | ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); | ||
188 | if (ret_val != 0) | ||
189 | goto remove_return; | ||
190 | 159 | ||
191 | if (msg_len < NETLBL_LEN_U32) | 160 | if (!info->attrs[NLBL_MGMT_A_DOMAIN]) |
192 | goto remove_return; | 161 | return -EINVAL; |
193 | count = netlbl_getinc_u32(&msg_ptr, &msg_len); | ||
194 | 162 | ||
195 | for (iter = 0; iter < count && msg_len > 0; iter++) { | 163 | domain = nla_data(info->attrs[NLBL_MGMT_A_DOMAIN]); |
196 | if (msg_len <= 0) { | 164 | return netlbl_domhsh_remove(domain); |
197 | ret_val = -EINVAL; | 165 | } |
198 | goto remove_return; | 166 | |
199 | } | 167 | /** |
200 | tmp_size = nla_len(msg_ptr); | 168 | * netlbl_mgmt_listall_cb - netlbl_domhsh_walk() callback for LISTALL |
201 | domain = nla_data(msg_ptr); | 169 | * @entry: the domain mapping hash table entry |
202 | if (tmp_size <= 0 || tmp_size > msg_len || | 170 | * @arg: the netlbl_domhsh_walk_arg structure |
203 | domain[tmp_size - 1] != '\0') { | 171 | * |
204 | ret_val = -EINVAL; | 172 | * Description: |
205 | goto remove_return; | 173 | * This function is designed to be used as a callback to the |
206 | } | 174 | * netlbl_domhsh_walk() function for use in generating a response for a LISTALL |
207 | ret_val = netlbl_domhsh_remove(domain); | 175 | * message. Returns the size of the message on success, negative values on |
176 | * failure. | ||
177 | * | ||
178 | */ | ||
179 | static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg) | ||
180 | { | ||
181 | int ret_val = -ENOMEM; | ||
182 | struct netlbl_domhsh_walk_arg *cb_arg = arg; | ||
183 | void *data; | ||
184 | |||
185 | data = netlbl_netlink_hdr_put(cb_arg->skb, | ||
186 | NETLINK_CB(cb_arg->nl_cb->skb).pid, | ||
187 | cb_arg->seq, | ||
188 | netlbl_mgmt_gnl_family.id, | ||
189 | NLM_F_MULTI, | ||
190 | NLBL_MGMT_C_LISTALL); | ||
191 | if (data == NULL) | ||
192 | goto listall_cb_failure; | ||
193 | |||
194 | ret_val = nla_put_string(cb_arg->skb, | ||
195 | NLBL_MGMT_A_DOMAIN, | ||
196 | entry->domain); | ||
197 | if (ret_val != 0) | ||
198 | goto listall_cb_failure; | ||
199 | ret_val = nla_put_u32(cb_arg->skb, NLBL_MGMT_A_PROTOCOL, entry->type); | ||
200 | if (ret_val != 0) | ||
201 | goto listall_cb_failure; | ||
202 | switch (entry->type) { | ||
203 | case NETLBL_NLTYPE_CIPSOV4: | ||
204 | ret_val = nla_put_u32(cb_arg->skb, | ||
205 | NLBL_MGMT_A_CV4DOI, | ||
206 | entry->type_def.cipsov4->doi); | ||
208 | if (ret_val != 0) | 207 | if (ret_val != 0) |
209 | goto remove_return; | 208 | goto listall_cb_failure; |
210 | msg_ptr = nla_next(msg_ptr, &msg_len); | 209 | break; |
211 | } | 210 | } |
212 | 211 | ||
213 | ret_val = 0; | 212 | cb_arg->seq++; |
213 | return genlmsg_end(cb_arg->skb, data); | ||
214 | 214 | ||
215 | remove_return: | 215 | listall_cb_failure: |
216 | netlbl_netlink_send_ack(info, | 216 | genlmsg_cancel(cb_arg->skb, data); |
217 | netlbl_mgmt_gnl_family.id, | ||
218 | NLBL_MGMT_C_ACK, | ||
219 | -ret_val); | ||
220 | return ret_val; | 217 | return ret_val; |
221 | } | 218 | } |
222 | 219 | ||
223 | /** | 220 | /** |
224 | * netlbl_mgmt_list - Handle a LIST message | 221 | * netlbl_mgmt_listall - Handle a LISTALL message |
225 | * @skb: the NETLINK buffer | 222 | * @skb: the NETLINK buffer |
226 | * @info: the Generic NETLINK info block | 223 | * @cb: the NETLINK callback |
227 | * | 224 | * |
228 | * Description: | 225 | * Description: |
229 | * Process a user generated LIST message and dumps the domain hash table in a | 226 | * Process a user generated LISTALL message and dumps the domain hash table in |
230 | * form suitable for use in a kernel generated LIST message. Returns zero on | 227 | * a form suitable for use in a kernel generated LISTALL message. Returns zero |
231 | * success, negative values on failure. | 228 | * on success, negative values on failure. |
232 | * | 229 | * |
233 | */ | 230 | */ |
234 | static int netlbl_mgmt_list(struct sk_buff *skb, struct genl_info *info) | 231 | static int netlbl_mgmt_listall(struct sk_buff *skb, |
232 | struct netlink_callback *cb) | ||
235 | { | 233 | { |
236 | int ret_val = -ENOMEM; | 234 | struct netlbl_domhsh_walk_arg cb_arg; |
237 | struct sk_buff *ans_skb; | 235 | u32 skip_bkt = cb->args[0]; |
238 | 236 | u32 skip_chain = cb->args[1]; | |
239 | ans_skb = netlbl_domhsh_dump(NLMSG_SPACE(GENL_HDRLEN)); | 237 | |
240 | if (ans_skb == NULL) | 238 | cb_arg.nl_cb = cb; |
241 | goto list_failure; | 239 | cb_arg.skb = skb; |
242 | netlbl_netlink_hdr_push(ans_skb, | 240 | cb_arg.seq = cb->nlh->nlmsg_seq; |
243 | info->snd_pid, | 241 | |
244 | 0, | 242 | netlbl_domhsh_walk(&skip_bkt, |
245 | netlbl_mgmt_gnl_family.id, | 243 | &skip_chain, |
246 | NLBL_MGMT_C_LIST); | 244 | netlbl_mgmt_listall_cb, |
247 | 245 | &cb_arg); | |
248 | ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); | 246 | |
249 | if (ret_val != 0) | 247 | cb->args[0] = skip_bkt; |
250 | goto list_failure; | 248 | cb->args[1] = skip_chain; |
251 | 249 | return skb->len; | |
252 | return 0; | ||
253 | |||
254 | list_failure: | ||
255 | netlbl_netlink_send_ack(info, | ||
256 | netlbl_mgmt_gnl_family.id, | ||
257 | NLBL_MGMT_C_ACK, | ||
258 | -ret_val); | ||
259 | return ret_val; | ||
260 | } | 250 | } |
261 | 251 | ||
262 | /** | 252 | /** |
@@ -272,68 +262,51 @@ list_failure: | |||
272 | static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info) | 262 | static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info) |
273 | { | 263 | { |
274 | int ret_val = -EINVAL; | 264 | int ret_val = -EINVAL; |
275 | struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb); | ||
276 | int msg_len = netlbl_netlink_payload_len(skb); | ||
277 | struct netlbl_dom_map *entry = NULL; | 265 | struct netlbl_dom_map *entry = NULL; |
278 | u32 tmp_val; | 266 | u32 tmp_val; |
279 | 267 | ||
280 | ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); | 268 | if (!info->attrs[NLBL_MGMT_A_PROTOCOL]) |
281 | if (ret_val != 0) | ||
282 | goto adddef_failure; | ||
283 | |||
284 | if (msg_len < NETLBL_LEN_U32) | ||
285 | goto adddef_failure; | 269 | goto adddef_failure; |
286 | tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len); | ||
287 | 270 | ||
288 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | 271 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
289 | if (entry == NULL) { | 272 | if (entry == NULL) { |
290 | ret_val = -ENOMEM; | 273 | ret_val = -ENOMEM; |
291 | goto adddef_failure; | 274 | goto adddef_failure; |
292 | } | 275 | } |
276 | entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]); | ||
293 | 277 | ||
294 | entry->type = tmp_val; | ||
295 | switch (entry->type) { | 278 | switch (entry->type) { |
296 | case NETLBL_NLTYPE_UNLABELED: | 279 | case NETLBL_NLTYPE_UNLABELED: |
297 | ret_val = netlbl_domhsh_add_default(entry); | 280 | ret_val = netlbl_domhsh_add_default(entry); |
298 | break; | 281 | break; |
299 | case NETLBL_NLTYPE_CIPSOV4: | 282 | case NETLBL_NLTYPE_CIPSOV4: |
300 | if (msg_len < NETLBL_LEN_U32) { | 283 | if (!info->attrs[NLBL_MGMT_A_CV4DOI]) |
301 | ret_val = -EINVAL; | ||
302 | goto adddef_failure; | 284 | goto adddef_failure; |
303 | } | 285 | |
304 | tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len); | 286 | tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]); |
305 | /* We should be holding a rcu_read_lock here while we | 287 | /* We should be holding a rcu_read_lock() here while we hold |
306 | * hold the result but since the entry will always be | 288 | * the result but since the entry will always be deleted when |
307 | * deleted when the CIPSO DOI is deleted we are going | 289 | * the CIPSO DOI is deleted we aren't going to keep the |
308 | * to skip the lock. */ | 290 | * lock. */ |
309 | rcu_read_lock(); | 291 | rcu_read_lock(); |
310 | entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); | 292 | entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); |
311 | if (entry->type_def.cipsov4 == NULL) { | 293 | if (entry->type_def.cipsov4 == NULL) { |
312 | rcu_read_unlock(); | 294 | rcu_read_unlock(); |
313 | ret_val = -EINVAL; | ||
314 | goto adddef_failure; | 295 | goto adddef_failure; |
315 | } | 296 | } |
316 | ret_val = netlbl_domhsh_add_default(entry); | 297 | ret_val = netlbl_domhsh_add_default(entry); |
317 | rcu_read_unlock(); | 298 | rcu_read_unlock(); |
318 | break; | 299 | break; |
319 | default: | 300 | default: |
320 | ret_val = -EINVAL; | 301 | goto adddef_failure; |
321 | } | 302 | } |
322 | if (ret_val != 0) | 303 | if (ret_val != 0) |
323 | goto adddef_failure; | 304 | goto adddef_failure; |
324 | 305 | ||
325 | netlbl_netlink_send_ack(info, | ||
326 | netlbl_mgmt_gnl_family.id, | ||
327 | NLBL_MGMT_C_ACK, | ||
328 | NETLBL_E_OK); | ||
329 | return 0; | 306 | return 0; |
330 | 307 | ||
331 | adddef_failure: | 308 | adddef_failure: |
332 | kfree(entry); | 309 | kfree(entry); |
333 | netlbl_netlink_send_ack(info, | ||
334 | netlbl_mgmt_gnl_family.id, | ||
335 | NLBL_MGMT_C_ACK, | ||
336 | -ret_val); | ||
337 | return ret_val; | 310 | return ret_val; |
338 | } | 311 | } |
339 | 312 | ||
@@ -349,20 +322,7 @@ adddef_failure: | |||
349 | */ | 322 | */ |
350 | static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info) | 323 | static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info) |
351 | { | 324 | { |
352 | int ret_val; | 325 | return netlbl_domhsh_remove_default(); |
353 | |||
354 | ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); | ||
355 | if (ret_val != 0) | ||
356 | goto removedef_return; | ||
357 | |||
358 | ret_val = netlbl_domhsh_remove_default(); | ||
359 | |||
360 | removedef_return: | ||
361 | netlbl_netlink_send_ack(info, | ||
362 | netlbl_mgmt_gnl_family.id, | ||
363 | NLBL_MGMT_C_ACK, | ||
364 | -ret_val); | ||
365 | return ret_val; | ||
366 | } | 326 | } |
367 | 327 | ||
368 | /** | 328 | /** |
@@ -379,88 +339,131 @@ removedef_return: | |||
379 | static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info) | 339 | static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info) |
380 | { | 340 | { |
381 | int ret_val = -ENOMEM; | 341 | int ret_val = -ENOMEM; |
382 | struct sk_buff *ans_skb; | 342 | struct sk_buff *ans_skb = NULL; |
343 | void *data; | ||
344 | struct netlbl_dom_map *entry; | ||
383 | 345 | ||
384 | ans_skb = netlbl_domhsh_dump_default(NLMSG_SPACE(GENL_HDRLEN)); | 346 | ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); |
385 | if (ans_skb == NULL) | 347 | if (ans_skb == NULL) |
348 | return -ENOMEM; | ||
349 | data = netlbl_netlink_hdr_put(ans_skb, | ||
350 | info->snd_pid, | ||
351 | info->snd_seq, | ||
352 | netlbl_mgmt_gnl_family.id, | ||
353 | 0, | ||
354 | NLBL_MGMT_C_LISTDEF); | ||
355 | if (data == NULL) | ||
386 | goto listdef_failure; | 356 | goto listdef_failure; |
387 | netlbl_netlink_hdr_push(ans_skb, | ||
388 | info->snd_pid, | ||
389 | 0, | ||
390 | netlbl_mgmt_gnl_family.id, | ||
391 | NLBL_MGMT_C_LISTDEF); | ||
392 | 357 | ||
393 | ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); | 358 | rcu_read_lock(); |
359 | entry = netlbl_domhsh_getentry(NULL); | ||
360 | if (entry == NULL) { | ||
361 | ret_val = -ENOENT; | ||
362 | goto listdef_failure_lock; | ||
363 | } | ||
364 | ret_val = nla_put_u32(ans_skb, NLBL_MGMT_A_PROTOCOL, entry->type); | ||
394 | if (ret_val != 0) | 365 | if (ret_val != 0) |
395 | goto listdef_failure; | 366 | goto listdef_failure_lock; |
367 | switch (entry->type) { | ||
368 | case NETLBL_NLTYPE_CIPSOV4: | ||
369 | ret_val = nla_put_u32(ans_skb, | ||
370 | NLBL_MGMT_A_CV4DOI, | ||
371 | entry->type_def.cipsov4->doi); | ||
372 | if (ret_val != 0) | ||
373 | goto listdef_failure_lock; | ||
374 | break; | ||
375 | } | ||
376 | rcu_read_unlock(); | ||
396 | 377 | ||
378 | genlmsg_end(ans_skb, data); | ||
379 | |||
380 | ret_val = genlmsg_unicast(ans_skb, info->snd_pid); | ||
381 | if (ret_val != 0) | ||
382 | goto listdef_failure; | ||
397 | return 0; | 383 | return 0; |
398 | 384 | ||
385 | listdef_failure_lock: | ||
386 | rcu_read_unlock(); | ||
399 | listdef_failure: | 387 | listdef_failure: |
400 | netlbl_netlink_send_ack(info, | 388 | kfree_skb(ans_skb); |
401 | netlbl_mgmt_gnl_family.id, | ||
402 | NLBL_MGMT_C_ACK, | ||
403 | -ret_val); | ||
404 | return ret_val; | 389 | return ret_val; |
405 | } | 390 | } |
406 | 391 | ||
407 | /** | 392 | /** |
408 | * netlbl_mgmt_modules - Handle a MODULES message | 393 | * netlbl_mgmt_protocols_cb - Write an individual PROTOCOL message response |
409 | * @skb: the NETLINK buffer | 394 | * @skb: the skb to write to |
410 | * @info: the Generic NETLINK info block | 395 | * @seq: the NETLINK sequence number |
396 | * @cb: the NETLINK callback | ||
397 | * @protocol: the NetLabel protocol to use in the message | ||
411 | * | 398 | * |
412 | * Description: | 399 | * Description: |
413 | * Process a user generated MODULES message and respond accordingly. | 400 | * This function is to be used in conjunction with netlbl_mgmt_protocols() to |
401 | * answer a application's PROTOCOLS message. Returns the size of the message | ||
402 | * on success, negative values on failure. | ||
414 | * | 403 | * |
415 | */ | 404 | */ |
416 | static int netlbl_mgmt_modules(struct sk_buff *skb, struct genl_info *info) | 405 | static int netlbl_mgmt_protocols_cb(struct sk_buff *skb, |
406 | struct netlink_callback *cb, | ||
407 | u32 protocol) | ||
417 | { | 408 | { |
418 | int ret_val = -ENOMEM; | 409 | int ret_val = -ENOMEM; |
419 | size_t data_size; | 410 | void *data; |
420 | u32 mod_count; | 411 | |
421 | struct sk_buff *ans_skb = NULL; | 412 | data = netlbl_netlink_hdr_put(skb, |
422 | 413 | NETLINK_CB(cb->skb).pid, | |
423 | /* unlabeled + cipsov4 */ | 414 | cb->nlh->nlmsg_seq, |
424 | mod_count = 2; | 415 | netlbl_mgmt_gnl_family.id, |
425 | 416 | NLM_F_MULTI, | |
426 | data_size = GENL_HDRLEN + NETLBL_LEN_U32 + mod_count * NETLBL_LEN_U32; | 417 | NLBL_MGMT_C_PROTOCOLS); |
427 | ans_skb = netlbl_netlink_alloc_skb(0, data_size, GFP_KERNEL); | 418 | if (data == NULL) |
428 | if (ans_skb == NULL) | 419 | goto protocols_cb_failure; |
429 | goto modules_failure; | 420 | |
430 | 421 | ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, protocol); | |
431 | if (netlbl_netlink_hdr_put(ans_skb, | ||
432 | info->snd_pid, | ||
433 | 0, | ||
434 | netlbl_mgmt_gnl_family.id, | ||
435 | NLBL_MGMT_C_MODULES) == NULL) | ||
436 | goto modules_failure; | ||
437 | |||
438 | ret_val = nla_put_u32(ans_skb, NLA_U32, mod_count); | ||
439 | if (ret_val != 0) | ||
440 | goto modules_failure; | ||
441 | ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_NLTYPE_UNLABELED); | ||
442 | if (ret_val != 0) | 422 | if (ret_val != 0) |
443 | goto modules_failure; | 423 | goto protocols_cb_failure; |
444 | ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_NLTYPE_CIPSOV4); | ||
445 | if (ret_val != 0) | ||
446 | goto modules_failure; | ||
447 | |||
448 | ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); | ||
449 | if (ret_val != 0) | ||
450 | goto modules_failure; | ||
451 | 424 | ||
452 | return 0; | 425 | return genlmsg_end(skb, data); |
453 | 426 | ||
454 | modules_failure: | 427 | protocols_cb_failure: |
455 | kfree_skb(ans_skb); | 428 | genlmsg_cancel(skb, data); |
456 | netlbl_netlink_send_ack(info, | ||
457 | netlbl_mgmt_gnl_family.id, | ||
458 | NLBL_MGMT_C_ACK, | ||
459 | -ret_val); | ||
460 | return ret_val; | 429 | return ret_val; |
461 | } | 430 | } |
462 | 431 | ||
463 | /** | 432 | /** |
433 | * netlbl_mgmt_protocols - Handle a PROTOCOLS message | ||
434 | * @skb: the NETLINK buffer | ||
435 | * @cb: the NETLINK callback | ||
436 | * | ||
437 | * Description: | ||
438 | * Process a user generated PROTOCOLS message and respond accordingly. | ||
439 | * | ||
440 | */ | ||
441 | static int netlbl_mgmt_protocols(struct sk_buff *skb, | ||
442 | struct netlink_callback *cb) | ||
443 | { | ||
444 | u32 protos_sent = cb->args[0]; | ||
445 | |||
446 | if (protos_sent == 0) { | ||
447 | if (netlbl_mgmt_protocols_cb(skb, | ||
448 | cb, | ||
449 | NETLBL_NLTYPE_UNLABELED) < 0) | ||
450 | goto protocols_return; | ||
451 | protos_sent++; | ||
452 | } | ||
453 | if (protos_sent == 1) { | ||
454 | if (netlbl_mgmt_protocols_cb(skb, | ||
455 | cb, | ||
456 | NETLBL_NLTYPE_CIPSOV4) < 0) | ||
457 | goto protocols_return; | ||
458 | protos_sent++; | ||
459 | } | ||
460 | |||
461 | protocols_return: | ||
462 | cb->args[0] = protos_sent; | ||
463 | return skb->len; | ||
464 | } | ||
465 | |||
466 | /** | ||
464 | * netlbl_mgmt_version - Handle a VERSION message | 467 | * netlbl_mgmt_version - Handle a VERSION message |
465 | * @skb: the NETLINK buffer | 468 | * @skb: the NETLINK buffer |
466 | * @info: the Generic NETLINK info block | 469 | * @info: the Generic NETLINK info block |
@@ -474,35 +477,35 @@ static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info) | |||
474 | { | 477 | { |
475 | int ret_val = -ENOMEM; | 478 | int ret_val = -ENOMEM; |
476 | struct sk_buff *ans_skb = NULL; | 479 | struct sk_buff *ans_skb = NULL; |
480 | void *data; | ||
477 | 481 | ||
478 | ans_skb = netlbl_netlink_alloc_skb(0, | 482 | ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); |
479 | GENL_HDRLEN + NETLBL_LEN_U32, | ||
480 | GFP_KERNEL); | ||
481 | if (ans_skb == NULL) | 483 | if (ans_skb == NULL) |
482 | goto version_failure; | 484 | return -ENOMEM; |
483 | if (netlbl_netlink_hdr_put(ans_skb, | 485 | data = netlbl_netlink_hdr_put(ans_skb, |
484 | info->snd_pid, | 486 | info->snd_pid, |
485 | 0, | 487 | info->snd_seq, |
486 | netlbl_mgmt_gnl_family.id, | 488 | netlbl_mgmt_gnl_family.id, |
487 | NLBL_MGMT_C_VERSION) == NULL) | 489 | 0, |
490 | NLBL_MGMT_C_VERSION); | ||
491 | if (data == NULL) | ||
488 | goto version_failure; | 492 | goto version_failure; |
489 | 493 | ||
490 | ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_PROTO_VERSION); | 494 | ret_val = nla_put_u32(ans_skb, |
495 | NLBL_MGMT_A_VERSION, | ||
496 | NETLBL_PROTO_VERSION); | ||
491 | if (ret_val != 0) | 497 | if (ret_val != 0) |
492 | goto version_failure; | 498 | goto version_failure; |
493 | 499 | ||
494 | ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); | 500 | genlmsg_end(ans_skb, data); |
501 | |||
502 | ret_val = genlmsg_unicast(ans_skb, info->snd_pid); | ||
495 | if (ret_val != 0) | 503 | if (ret_val != 0) |
496 | goto version_failure; | 504 | goto version_failure; |
497 | |||
498 | return 0; | 505 | return 0; |
499 | 506 | ||
500 | version_failure: | 507 | version_failure: |
501 | kfree_skb(ans_skb); | 508 | kfree_skb(ans_skb); |
502 | netlbl_netlink_send_ack(info, | ||
503 | netlbl_mgmt_gnl_family.id, | ||
504 | NLBL_MGMT_C_ACK, | ||
505 | -ret_val); | ||
506 | return ret_val; | 509 | return ret_val; |
507 | } | 510 | } |
508 | 511 | ||
@@ -513,35 +516,40 @@ version_failure: | |||
513 | 516 | ||
514 | static struct genl_ops netlbl_mgmt_genl_c_add = { | 517 | static struct genl_ops netlbl_mgmt_genl_c_add = { |
515 | .cmd = NLBL_MGMT_C_ADD, | 518 | .cmd = NLBL_MGMT_C_ADD, |
516 | .flags = 0, | 519 | .flags = GENL_ADMIN_PERM, |
520 | .policy = netlbl_mgmt_genl_policy, | ||
517 | .doit = netlbl_mgmt_add, | 521 | .doit = netlbl_mgmt_add, |
518 | .dumpit = NULL, | 522 | .dumpit = NULL, |
519 | }; | 523 | }; |
520 | 524 | ||
521 | static struct genl_ops netlbl_mgmt_genl_c_remove = { | 525 | static struct genl_ops netlbl_mgmt_genl_c_remove = { |
522 | .cmd = NLBL_MGMT_C_REMOVE, | 526 | .cmd = NLBL_MGMT_C_REMOVE, |
523 | .flags = 0, | 527 | .flags = GENL_ADMIN_PERM, |
528 | .policy = netlbl_mgmt_genl_policy, | ||
524 | .doit = netlbl_mgmt_remove, | 529 | .doit = netlbl_mgmt_remove, |
525 | .dumpit = NULL, | 530 | .dumpit = NULL, |
526 | }; | 531 | }; |
527 | 532 | ||
528 | static struct genl_ops netlbl_mgmt_genl_c_list = { | 533 | static struct genl_ops netlbl_mgmt_genl_c_listall = { |
529 | .cmd = NLBL_MGMT_C_LIST, | 534 | .cmd = NLBL_MGMT_C_LISTALL, |
530 | .flags = 0, | 535 | .flags = 0, |
531 | .doit = netlbl_mgmt_list, | 536 | .policy = netlbl_mgmt_genl_policy, |
532 | .dumpit = NULL, | 537 | .doit = NULL, |
538 | .dumpit = netlbl_mgmt_listall, | ||
533 | }; | 539 | }; |
534 | 540 | ||
535 | static struct genl_ops netlbl_mgmt_genl_c_adddef = { | 541 | static struct genl_ops netlbl_mgmt_genl_c_adddef = { |
536 | .cmd = NLBL_MGMT_C_ADDDEF, | 542 | .cmd = NLBL_MGMT_C_ADDDEF, |
537 | .flags = 0, | 543 | .flags = GENL_ADMIN_PERM, |
544 | .policy = netlbl_mgmt_genl_policy, | ||
538 | .doit = netlbl_mgmt_adddef, | 545 | .doit = netlbl_mgmt_adddef, |
539 | .dumpit = NULL, | 546 | .dumpit = NULL, |
540 | }; | 547 | }; |
541 | 548 | ||
542 | static struct genl_ops netlbl_mgmt_genl_c_removedef = { | 549 | static struct genl_ops netlbl_mgmt_genl_c_removedef = { |
543 | .cmd = NLBL_MGMT_C_REMOVEDEF, | 550 | .cmd = NLBL_MGMT_C_REMOVEDEF, |
544 | .flags = 0, | 551 | .flags = GENL_ADMIN_PERM, |
552 | .policy = netlbl_mgmt_genl_policy, | ||
545 | .doit = netlbl_mgmt_removedef, | 553 | .doit = netlbl_mgmt_removedef, |
546 | .dumpit = NULL, | 554 | .dumpit = NULL, |
547 | }; | 555 | }; |
@@ -549,20 +557,23 @@ static struct genl_ops netlbl_mgmt_genl_c_removedef = { | |||
549 | static struct genl_ops netlbl_mgmt_genl_c_listdef = { | 557 | static struct genl_ops netlbl_mgmt_genl_c_listdef = { |
550 | .cmd = NLBL_MGMT_C_LISTDEF, | 558 | .cmd = NLBL_MGMT_C_LISTDEF, |
551 | .flags = 0, | 559 | .flags = 0, |
560 | .policy = netlbl_mgmt_genl_policy, | ||
552 | .doit = netlbl_mgmt_listdef, | 561 | .doit = netlbl_mgmt_listdef, |
553 | .dumpit = NULL, | 562 | .dumpit = NULL, |
554 | }; | 563 | }; |
555 | 564 | ||
556 | static struct genl_ops netlbl_mgmt_genl_c_modules = { | 565 | static struct genl_ops netlbl_mgmt_genl_c_protocols = { |
557 | .cmd = NLBL_MGMT_C_MODULES, | 566 | .cmd = NLBL_MGMT_C_PROTOCOLS, |
558 | .flags = 0, | 567 | .flags = 0, |
559 | .doit = netlbl_mgmt_modules, | 568 | .policy = netlbl_mgmt_genl_policy, |
560 | .dumpit = NULL, | 569 | .doit = NULL, |
570 | .dumpit = netlbl_mgmt_protocols, | ||
561 | }; | 571 | }; |
562 | 572 | ||
563 | static struct genl_ops netlbl_mgmt_genl_c_version = { | 573 | static struct genl_ops netlbl_mgmt_genl_c_version = { |
564 | .cmd = NLBL_MGMT_C_VERSION, | 574 | .cmd = NLBL_MGMT_C_VERSION, |
565 | .flags = 0, | 575 | .flags = 0, |
576 | .policy = netlbl_mgmt_genl_policy, | ||
566 | .doit = netlbl_mgmt_version, | 577 | .doit = netlbl_mgmt_version, |
567 | .dumpit = NULL, | 578 | .dumpit = NULL, |
568 | }; | 579 | }; |
@@ -596,7 +607,7 @@ int netlbl_mgmt_genl_init(void) | |||
596 | if (ret_val != 0) | 607 | if (ret_val != 0) |
597 | return ret_val; | 608 | return ret_val; |
598 | ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, | 609 | ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, |
599 | &netlbl_mgmt_genl_c_list); | 610 | &netlbl_mgmt_genl_c_listall); |
600 | if (ret_val != 0) | 611 | if (ret_val != 0) |
601 | return ret_val; | 612 | return ret_val; |
602 | ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, | 613 | ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, |
@@ -612,7 +623,7 @@ int netlbl_mgmt_genl_init(void) | |||
612 | if (ret_val != 0) | 623 | if (ret_val != 0) |
613 | return ret_val; | 624 | return ret_val; |
614 | ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, | 625 | ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, |
615 | &netlbl_mgmt_genl_c_modules); | 626 | &netlbl_mgmt_genl_c_protocols); |
616 | if (ret_val != 0) | 627 | if (ret_val != 0) |
617 | return ret_val; | 628 | return ret_val; |
618 | ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, | 629 | ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, |
diff --git a/net/netlabel/netlabel_mgmt.h b/net/netlabel/netlabel_mgmt.h index fd6c6acbfa08..3642d3bfc8eb 100644 --- a/net/netlabel/netlabel_mgmt.h +++ b/net/netlabel/netlabel_mgmt.h | |||
@@ -34,212 +34,137 @@ | |||
34 | #include <net/netlabel.h> | 34 | #include <net/netlabel.h> |
35 | 35 | ||
36 | /* | 36 | /* |
37 | * The following NetLabel payloads are supported by the management interface, | 37 | * The following NetLabel payloads are supported by the management interface. |
38 | * all of which are preceeded by the nlmsghdr struct. | ||
39 | * | ||
40 | * o ACK: | ||
41 | * Sent by the kernel in response to an applications message, applications | ||
42 | * should never send this message. | ||
43 | * | ||
44 | * +----------------------+-----------------------+ | ||
45 | * | seq number (32 bits) | return code (32 bits) | | ||
46 | * +----------------------+-----------------------+ | ||
47 | * | ||
48 | * seq number: the sequence number of the original message, taken from the | ||
49 | * nlmsghdr structure | ||
50 | * return code: return value, based on errno values | ||
51 | * | 38 | * |
52 | * o ADD: | 39 | * o ADD: |
53 | * Sent by an application to add a domain mapping to the NetLabel system. | 40 | * Sent by an application to add a domain mapping to the NetLabel system. |
54 | * The kernel should respond with an ACK. | ||
55 | * | ||
56 | * +-------------------+ | ||
57 | * | domains (32 bits) | ... | ||
58 | * +-------------------+ | ||
59 | * | ||
60 | * domains: the number of domains in the message | ||
61 | * | ||
62 | * +--------------------------+-------------------------+ | ||
63 | * | domain string (variable) | protocol type (32 bits) | ... | ||
64 | * +--------------------------+-------------------------+ | ||
65 | * | 41 | * |
66 | * +-------------- ---- --- -- - | 42 | * Required attributes: |
67 | * | mapping data ... repeated | ||
68 | * +-------------- ---- --- -- - | ||
69 | * | 43 | * |
70 | * domain string: the domain string, NULL terminated | 44 | * NLBL_MGMT_A_DOMAIN |
71 | * protocol type: the protocol type (defined by NETLBL_NLTYPE_*) | 45 | * NLBL_MGMT_A_PROTOCOL |
72 | * mapping data: specific to the map type (see below) | ||
73 | * | 46 | * |
74 | * NETLBL_NLTYPE_UNLABELED | 47 | * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required: |
75 | * | 48 | * |
76 | * No mapping data for this protocol type. | 49 | * NLBL_MGMT_A_CV4DOI |
77 | * | 50 | * |
78 | * NETLBL_NLTYPE_CIPSOV4 | 51 | * If using NETLBL_NLTYPE_UNLABELED no other attributes are required. |
79 | * | ||
80 | * +---------------+ | ||
81 | * | doi (32 bits) | | ||
82 | * +---------------+ | ||
83 | * | ||
84 | * doi: the CIPSO DOI value | ||
85 | * | 52 | * |
86 | * o REMOVE: | 53 | * o REMOVE: |
87 | * Sent by an application to remove a domain mapping from the NetLabel | 54 | * Sent by an application to remove a domain mapping from the NetLabel |
88 | * system. The kernel should ACK this message. | 55 | * system. |
89 | * | ||
90 | * +-------------------+ | ||
91 | * | domains (32 bits) | ... | ||
92 | * +-------------------+ | ||
93 | * | 56 | * |
94 | * domains: the number of domains in the message | 57 | * Required attributes: |
95 | * | 58 | * |
96 | * +--------------------------+ | 59 | * NLBL_MGMT_A_DOMAIN |
97 | * | domain string (variable) | ... | ||
98 | * +--------------------------+ | ||
99 | * | 60 | * |
100 | * domain string: the domain string, NULL terminated | 61 | * o LISTALL: |
101 | * | ||
102 | * o LIST: | ||
103 | * This message can be sent either from an application or by the kernel in | 62 | * This message can be sent either from an application or by the kernel in |
104 | * response to an application generated LIST message. When sent by an | 63 | * response to an application generated LISTALL message. When sent by an |
105 | * application there is no payload. The kernel should respond to a LIST | 64 | * application there is no payload and the NLM_F_DUMP flag should be set. |
106 | * message either with a LIST message on success or an ACK message on | 65 | * The kernel should respond with a series of the following messages. |
107 | * failure. | ||
108 | * | ||
109 | * +-------------------+ | ||
110 | * | domains (32 bits) | ... | ||
111 | * +-------------------+ | ||
112 | * | ||
113 | * domains: the number of domains in the message | ||
114 | * | 66 | * |
115 | * +--------------------------+ | 67 | * Required attributes: |
116 | * | domain string (variable) | ... | ||
117 | * +--------------------------+ | ||
118 | * | 68 | * |
119 | * +-------------------------+-------------- ---- --- -- - | 69 | * NLBL_MGMT_A_DOMAIN |
120 | * | protocol type (32 bits) | mapping data ... repeated | 70 | * NLBL_MGMT_A_PROTOCOL |
121 | * +-------------------------+-------------- ---- --- -- - | ||
122 | * | 71 | * |
123 | * domain string: the domain string, NULL terminated | 72 | * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required: |
124 | * protocol type: the protocol type (defined by NETLBL_NLTYPE_*) | ||
125 | * mapping data: specific to the map type (see below) | ||
126 | * | 73 | * |
127 | * NETLBL_NLTYPE_UNLABELED | 74 | * NLBL_MGMT_A_CV4DOI |
128 | * | 75 | * |
129 | * No mapping data for this protocol type. | 76 | * If using NETLBL_NLTYPE_UNLABELED no other attributes are required. |
130 | * | ||
131 | * NETLBL_NLTYPE_CIPSOV4 | ||
132 | * | ||
133 | * +----------------+---------------+ | ||
134 | * | type (32 bits) | doi (32 bits) | | ||
135 | * +----------------+---------------+ | ||
136 | * | ||
137 | * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header | ||
138 | * as CIPSO_V4_MAP_*) | ||
139 | * doi: the CIPSO DOI value | ||
140 | * | 77 | * |
141 | * o ADDDEF: | 78 | * o ADDDEF: |
142 | * Sent by an application to set the default domain mapping for the NetLabel | 79 | * Sent by an application to set the default domain mapping for the NetLabel |
143 | * system. The kernel should respond with an ACK. | 80 | * system. |
144 | * | 81 | * |
145 | * +-------------------------+-------------- ---- --- -- - | 82 | * Required attributes: |
146 | * | protocol type (32 bits) | mapping data ... repeated | ||
147 | * +-------------------------+-------------- ---- --- -- - | ||
148 | * | 83 | * |
149 | * protocol type: the protocol type (defined by NETLBL_NLTYPE_*) | 84 | * NLBL_MGMT_A_PROTOCOL |
150 | * mapping data: specific to the map type (see below) | ||
151 | * | 85 | * |
152 | * NETLBL_NLTYPE_UNLABELED | 86 | * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required: |
153 | * | 87 | * |
154 | * No mapping data for this protocol type. | 88 | * NLBL_MGMT_A_CV4DOI |
155 | * | 89 | * |
156 | * NETLBL_NLTYPE_CIPSOV4 | 90 | * If using NETLBL_NLTYPE_UNLABELED no other attributes are required. |
157 | * | ||
158 | * +---------------+ | ||
159 | * | doi (32 bits) | | ||
160 | * +---------------+ | ||
161 | * | ||
162 | * doi: the CIPSO DOI value | ||
163 | * | 91 | * |
164 | * o REMOVEDEF: | 92 | * o REMOVEDEF: |
165 | * Sent by an application to remove the default domain mapping from the | 93 | * Sent by an application to remove the default domain mapping from the |
166 | * NetLabel system, there is no payload. The kernel should ACK this message. | 94 | * NetLabel system, there is no payload. |
167 | * | 95 | * |
168 | * o LISTDEF: | 96 | * o LISTDEF: |
169 | * This message can be sent either from an application or by the kernel in | 97 | * This message can be sent either from an application or by the kernel in |
170 | * response to an application generated LISTDEF message. When sent by an | 98 | * response to an application generated LISTDEF message. When sent by an |
171 | * application there is no payload. The kernel should respond to a | 99 | * application there is no payload. On success the kernel should send a |
172 | * LISTDEF message either with a LISTDEF message on success or an ACK message | 100 | * response using the following format. |
173 | * on failure. | ||
174 | * | ||
175 | * +-------------------------+-------------- ---- --- -- - | ||
176 | * | protocol type (32 bits) | mapping data ... repeated | ||
177 | * +-------------------------+-------------- ---- --- -- - | ||
178 | * | 101 | * |
179 | * protocol type: the protocol type (defined by NETLBL_NLTYPE_*) | 102 | * Required attributes: |
180 | * mapping data: specific to the map type (see below) | ||
181 | * | 103 | * |
182 | * NETLBL_NLTYPE_UNLABELED | 104 | * NLBL_MGMT_A_PROTOCOL |
183 | * | 105 | * |
184 | * No mapping data for this protocol type. | 106 | * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required: |
185 | * | 107 | * |
186 | * NETLBL_NLTYPE_CIPSOV4 | 108 | * NLBL_MGMT_A_CV4DOI |
187 | * | 109 | * |
188 | * +----------------+---------------+ | 110 | * If using NETLBL_NLTYPE_UNLABELED no other attributes are required. |
189 | * | type (32 bits) | doi (32 bits) | | ||
190 | * +----------------+---------------+ | ||
191 | * | 111 | * |
192 | * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header | 112 | * o PROTOCOLS: |
193 | * as CIPSO_V4_MAP_*) | 113 | * Sent by an application to request a list of configured NetLabel protocols |
194 | * doi: the CIPSO DOI value | 114 | * in the kernel. When sent by an application there is no payload and the |
115 | * NLM_F_DUMP flag should be set. The kernel should respond with a series of | ||
116 | * the following messages. | ||
195 | * | 117 | * |
196 | * o MODULES: | 118 | * Required attributes: |
197 | * Sent by an application to request a list of configured NetLabel modules | ||
198 | * in the kernel. When sent by an application there is no payload. | ||
199 | * | 119 | * |
200 | * +-------------------+ | 120 | * NLBL_MGMT_A_PROTOCOL |
201 | * | modules (32 bits) | ... | ||
202 | * +-------------------+ | ||
203 | * | ||
204 | * modules: the number of modules in the message, if this is an application | ||
205 | * generated message and the value is zero then return a list of | ||
206 | * the configured modules | ||
207 | * | ||
208 | * +------------------+ | ||
209 | * | module (32 bits) | ... repeated | ||
210 | * +------------------+ | ||
211 | * | ||
212 | * module: the module number as defined by NETLBL_NLTYPE_* | ||
213 | * | 121 | * |
214 | * o VERSION: | 122 | * o VERSION: |
215 | * Sent by an application to request the NetLabel version string. When sent | 123 | * Sent by an application to request the NetLabel version. When sent by an |
216 | * by an application there is no payload. This message type is also used by | 124 | * application there is no payload. This message type is also used by the |
217 | * the kernel to respond to an VERSION request. | 125 | * kernel to respond to an VERSION request. |
218 | * | 126 | * |
219 | * +-------------------+ | 127 | * Required attributes: |
220 | * | version (32 bits) | | ||
221 | * +-------------------+ | ||
222 | * | 128 | * |
223 | * version: the protocol version number | 129 | * NLBL_MGMT_A_VERSION |
224 | * | 130 | * |
225 | */ | 131 | */ |
226 | 132 | ||
227 | /* NetLabel Management commands */ | 133 | /* NetLabel Management commands */ |
228 | enum { | 134 | enum { |
229 | NLBL_MGMT_C_UNSPEC, | 135 | NLBL_MGMT_C_UNSPEC, |
230 | NLBL_MGMT_C_ACK, | ||
231 | NLBL_MGMT_C_ADD, | 136 | NLBL_MGMT_C_ADD, |
232 | NLBL_MGMT_C_REMOVE, | 137 | NLBL_MGMT_C_REMOVE, |
233 | NLBL_MGMT_C_LIST, | 138 | NLBL_MGMT_C_LISTALL, |
234 | NLBL_MGMT_C_ADDDEF, | 139 | NLBL_MGMT_C_ADDDEF, |
235 | NLBL_MGMT_C_REMOVEDEF, | 140 | NLBL_MGMT_C_REMOVEDEF, |
236 | NLBL_MGMT_C_LISTDEF, | 141 | NLBL_MGMT_C_LISTDEF, |
237 | NLBL_MGMT_C_MODULES, | 142 | NLBL_MGMT_C_PROTOCOLS, |
238 | NLBL_MGMT_C_VERSION, | 143 | NLBL_MGMT_C_VERSION, |
239 | __NLBL_MGMT_C_MAX, | 144 | __NLBL_MGMT_C_MAX, |
240 | }; | 145 | }; |
241 | #define NLBL_MGMT_C_MAX (__NLBL_MGMT_C_MAX - 1) | 146 | #define NLBL_MGMT_C_MAX (__NLBL_MGMT_C_MAX - 1) |
242 | 147 | ||
148 | /* NetLabel Management attributes */ | ||
149 | enum { | ||
150 | NLBL_MGMT_A_UNSPEC, | ||
151 | NLBL_MGMT_A_DOMAIN, | ||
152 | /* (NLA_NUL_STRING) | ||
153 | * the NULL terminated LSM domain string */ | ||
154 | NLBL_MGMT_A_PROTOCOL, | ||
155 | /* (NLA_U32) | ||
156 | * the NetLabel protocol type (defined by NETLBL_NLTYPE_*) */ | ||
157 | NLBL_MGMT_A_VERSION, | ||
158 | /* (NLA_U32) | ||
159 | * the NetLabel protocol version number (defined by | ||
160 | * NETLBL_PROTO_VERSION) */ | ||
161 | NLBL_MGMT_A_CV4DOI, | ||
162 | /* (NLA_U32) | ||
163 | * the CIPSOv4 DOI value */ | ||
164 | __NLBL_MGMT_A_MAX, | ||
165 | }; | ||
166 | #define NLBL_MGMT_A_MAX (__NLBL_MGMT_A_MAX - 1) | ||
167 | |||
243 | /* NetLabel protocol functions */ | 168 | /* NetLabel protocol functions */ |
244 | int netlbl_mgmt_genl_init(void); | 169 | int netlbl_mgmt_genl_init(void); |
245 | 170 | ||
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 785f4960e0d3..440f5c4e1e2d 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c | |||
@@ -55,9 +55,13 @@ static struct genl_family netlbl_unlabel_gnl_family = { | |||
55 | .hdrsize = 0, | 55 | .hdrsize = 0, |
56 | .name = NETLBL_NLTYPE_UNLABELED_NAME, | 56 | .name = NETLBL_NLTYPE_UNLABELED_NAME, |
57 | .version = NETLBL_PROTO_VERSION, | 57 | .version = NETLBL_PROTO_VERSION, |
58 | .maxattr = 0, | 58 | .maxattr = NLBL_UNLABEL_A_MAX, |
59 | }; | 59 | }; |
60 | 60 | ||
61 | /* NetLabel Netlink attribute policy */ | ||
62 | static struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = { | ||
63 | [NLBL_UNLABEL_A_ACPTFLG] = { .type = NLA_U8 }, | ||
64 | }; | ||
61 | 65 | ||
62 | /* | 66 | /* |
63 | * NetLabel Command Handlers | 67 | * NetLabel Command Handlers |
@@ -75,31 +79,18 @@ static struct genl_family netlbl_unlabel_gnl_family = { | |||
75 | */ | 79 | */ |
76 | static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info) | 80 | static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info) |
77 | { | 81 | { |
78 | int ret_val; | 82 | int ret_val = -EINVAL; |
79 | struct nlattr *data = netlbl_netlink_payload_data(skb); | 83 | u8 value; |
80 | u32 value; | ||
81 | |||
82 | ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); | ||
83 | if (ret_val != 0) | ||
84 | return ret_val; | ||
85 | 84 | ||
86 | if (netlbl_netlink_payload_len(skb) == NETLBL_LEN_U32) { | 85 | if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) { |
87 | value = nla_get_u32(data); | 86 | value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]); |
88 | if (value == 1 || value == 0) { | 87 | if (value == 1 || value == 0) { |
89 | atomic_set(&netlabel_unlabel_accept_flg, value); | 88 | atomic_set(&netlabel_unlabel_accept_flg, value); |
90 | netlbl_netlink_send_ack(info, | 89 | ret_val = 0; |
91 | netlbl_unlabel_gnl_family.id, | ||
92 | NLBL_UNLABEL_C_ACK, | ||
93 | NETLBL_E_OK); | ||
94 | return 0; | ||
95 | } | 90 | } |
96 | } | 91 | } |
97 | 92 | ||
98 | netlbl_netlink_send_ack(info, | 93 | return ret_val; |
99 | netlbl_unlabel_gnl_family.id, | ||
100 | NLBL_UNLABEL_C_ACK, | ||
101 | EINVAL); | ||
102 | return -EINVAL; | ||
103 | } | 94 | } |
104 | 95 | ||
105 | /** | 96 | /** |
@@ -114,39 +105,39 @@ static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info) | |||
114 | */ | 105 | */ |
115 | static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) | 106 | static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) |
116 | { | 107 | { |
117 | int ret_val = -ENOMEM; | 108 | int ret_val = -EINVAL; |
118 | struct sk_buff *ans_skb; | 109 | struct sk_buff *ans_skb; |
110 | void *data; | ||
119 | 111 | ||
120 | ans_skb = netlbl_netlink_alloc_skb(0, | 112 | ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); |
121 | GENL_HDRLEN + NETLBL_LEN_U32, | ||
122 | GFP_KERNEL); | ||
123 | if (ans_skb == NULL) | 113 | if (ans_skb == NULL) |
124 | goto list_failure; | 114 | goto list_failure; |
125 | 115 | data = netlbl_netlink_hdr_put(ans_skb, | |
126 | if (netlbl_netlink_hdr_put(ans_skb, | 116 | info->snd_pid, |
127 | info->snd_pid, | 117 | info->snd_seq, |
128 | 0, | 118 | netlbl_unlabel_gnl_family.id, |
129 | netlbl_unlabel_gnl_family.id, | 119 | 0, |
130 | NLBL_UNLABEL_C_LIST) == NULL) | 120 | NLBL_UNLABEL_C_LIST); |
121 | if (data == NULL) { | ||
122 | ret_val = -ENOMEM; | ||
131 | goto list_failure; | 123 | goto list_failure; |
124 | } | ||
132 | 125 | ||
133 | ret_val = nla_put_u32(ans_skb, | 126 | ret_val = nla_put_u8(ans_skb, |
134 | NLA_U32, | 127 | NLBL_UNLABEL_A_ACPTFLG, |
135 | atomic_read(&netlabel_unlabel_accept_flg)); | 128 | atomic_read(&netlabel_unlabel_accept_flg)); |
136 | if (ret_val != 0) | 129 | if (ret_val != 0) |
137 | goto list_failure; | 130 | goto list_failure; |
138 | 131 | ||
139 | ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); | 132 | genlmsg_end(ans_skb, data); |
133 | |||
134 | ret_val = genlmsg_unicast(ans_skb, info->snd_pid); | ||
140 | if (ret_val != 0) | 135 | if (ret_val != 0) |
141 | goto list_failure; | 136 | goto list_failure; |
142 | |||
143 | return 0; | 137 | return 0; |
144 | 138 | ||
145 | list_failure: | 139 | list_failure: |
146 | netlbl_netlink_send_ack(info, | 140 | kfree(ans_skb); |
147 | netlbl_unlabel_gnl_family.id, | ||
148 | NLBL_UNLABEL_C_ACK, | ||
149 | -ret_val); | ||
150 | return ret_val; | 141 | return ret_val; |
151 | } | 142 | } |
152 | 143 | ||
@@ -157,7 +148,8 @@ list_failure: | |||
157 | 148 | ||
158 | static struct genl_ops netlbl_unlabel_genl_c_accept = { | 149 | static struct genl_ops netlbl_unlabel_genl_c_accept = { |
159 | .cmd = NLBL_UNLABEL_C_ACCEPT, | 150 | .cmd = NLBL_UNLABEL_C_ACCEPT, |
160 | .flags = 0, | 151 | .flags = GENL_ADMIN_PERM, |
152 | .policy = netlbl_unlabel_genl_policy, | ||
161 | .doit = netlbl_unlabel_accept, | 153 | .doit = netlbl_unlabel_accept, |
162 | .dumpit = NULL, | 154 | .dumpit = NULL, |
163 | }; | 155 | }; |
@@ -165,6 +157,7 @@ static struct genl_ops netlbl_unlabel_genl_c_accept = { | |||
165 | static struct genl_ops netlbl_unlabel_genl_c_list = { | 157 | static struct genl_ops netlbl_unlabel_genl_c_list = { |
166 | .cmd = NLBL_UNLABEL_C_LIST, | 158 | .cmd = NLBL_UNLABEL_C_LIST, |
167 | .flags = 0, | 159 | .flags = 0, |
160 | .policy = netlbl_unlabel_genl_policy, | ||
168 | .doit = netlbl_unlabel_list, | 161 | .doit = netlbl_unlabel_list, |
169 | .dumpit = NULL, | 162 | .dumpit = NULL, |
170 | }; | 163 | }; |
@@ -218,10 +211,8 @@ int netlbl_unlabel_genl_init(void) | |||
218 | */ | 211 | */ |
219 | int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr) | 212 | int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr) |
220 | { | 213 | { |
221 | if (atomic_read(&netlabel_unlabel_accept_flg) == 1) { | 214 | if (atomic_read(&netlabel_unlabel_accept_flg) == 1) |
222 | memset(secattr, 0, sizeof(*secattr)); | 215 | return netlbl_secattr_init(secattr); |
223 | return 0; | ||
224 | } | ||
225 | 216 | ||
226 | return -ENOMSG; | 217 | return -ENOMSG; |
227 | } | 218 | } |
diff --git a/net/netlabel/netlabel_unlabeled.h b/net/netlabel/netlabel_unlabeled.h index f300e54e14b6..c2917fbb42cf 100644 --- a/net/netlabel/netlabel_unlabeled.h +++ b/net/netlabel/netlabel_unlabeled.h | |||
@@ -36,56 +36,47 @@ | |||
36 | /* | 36 | /* |
37 | * The following NetLabel payloads are supported by the Unlabeled subsystem. | 37 | * The following NetLabel payloads are supported by the Unlabeled subsystem. |
38 | * | 38 | * |
39 | * o ACK: | ||
40 | * Sent by the kernel in response to an applications message, applications | ||
41 | * should never send this message. | ||
42 | * | ||
43 | * +----------------------+-----------------------+ | ||
44 | * | seq number (32 bits) | return code (32 bits) | | ||
45 | * +----------------------+-----------------------+ | ||
46 | * | ||
47 | * seq number: the sequence number of the original message, taken from the | ||
48 | * nlmsghdr structure | ||
49 | * return code: return value, based on errno values | ||
50 | * | ||
51 | * o ACCEPT | 39 | * o ACCEPT |
52 | * This message is sent from an application to specify if the kernel should | 40 | * This message is sent from an application to specify if the kernel should |
53 | * allow unlabled packets to pass if they do not match any of the static | 41 | * allow unlabled packets to pass if they do not match any of the static |
54 | * mappings defined in the unlabeled module. | 42 | * mappings defined in the unlabeled module. |
55 | * | 43 | * |
56 | * +-----------------+ | 44 | * Required attributes: |
57 | * | allow (32 bits) | | ||
58 | * +-----------------+ | ||
59 | * | 45 | * |
60 | * allow: if true (1) then allow the packets to pass, if false (0) then | 46 | * NLBL_UNLABEL_A_ACPTFLG |
61 | * reject the packets | ||
62 | * | 47 | * |
63 | * o LIST | 48 | * o LIST |
64 | * This message can be sent either from an application or by the kernel in | 49 | * This message can be sent either from an application or by the kernel in |
65 | * response to an application generated LIST message. When sent by an | 50 | * response to an application generated LIST message. When sent by an |
66 | * application there is no payload. The kernel should respond to a LIST | 51 | * application there is no payload. The kernel should respond to a LIST |
67 | * message either with a LIST message on success or an ACK message on | 52 | * message with a LIST message on success. |
68 | * failure. | ||
69 | * | 53 | * |
70 | * +-----------------------+ | 54 | * Required attributes: |
71 | * | accept flag (32 bits) | | ||
72 | * +-----------------------+ | ||
73 | * | 55 | * |
74 | * accept flag: if true (1) then unlabeled packets are allowed to pass, | 56 | * NLBL_UNLABEL_A_ACPTFLG |
75 | * if false (0) then unlabeled packets are rejected | ||
76 | * | 57 | * |
77 | */ | 58 | */ |
78 | 59 | ||
79 | /* NetLabel Unlabeled commands */ | 60 | /* NetLabel Unlabeled commands */ |
80 | enum { | 61 | enum { |
81 | NLBL_UNLABEL_C_UNSPEC, | 62 | NLBL_UNLABEL_C_UNSPEC, |
82 | NLBL_UNLABEL_C_ACK, | ||
83 | NLBL_UNLABEL_C_ACCEPT, | 63 | NLBL_UNLABEL_C_ACCEPT, |
84 | NLBL_UNLABEL_C_LIST, | 64 | NLBL_UNLABEL_C_LIST, |
85 | __NLBL_UNLABEL_C_MAX, | 65 | __NLBL_UNLABEL_C_MAX, |
86 | }; | 66 | }; |
87 | #define NLBL_UNLABEL_C_MAX (__NLBL_UNLABEL_C_MAX - 1) | 67 | #define NLBL_UNLABEL_C_MAX (__NLBL_UNLABEL_C_MAX - 1) |
88 | 68 | ||
69 | /* NetLabel Unlabeled attributes */ | ||
70 | enum { | ||
71 | NLBL_UNLABEL_A_UNSPEC, | ||
72 | NLBL_UNLABEL_A_ACPTFLG, | ||
73 | /* (NLA_U8) | ||
74 | * if true then unlabeled packets are allowed to pass, else unlabeled | ||
75 | * packets are rejected */ | ||
76 | __NLBL_UNLABEL_A_MAX, | ||
77 | }; | ||
78 | #define NLBL_UNLABEL_A_MAX (__NLBL_UNLABEL_A_MAX - 1) | ||
79 | |||
89 | /* NetLabel protocol functions */ | 80 | /* NetLabel protocol functions */ |
90 | int netlbl_unlabel_genl_init(void); | 81 | int netlbl_unlabel_genl_init(void); |
91 | 82 | ||
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c index 73cbe66e42ff..eeb7d768d2bb 100644 --- a/net/netlabel/netlabel_user.c +++ b/net/netlabel/netlabel_user.c | |||
@@ -74,85 +74,3 @@ int netlbl_netlink_init(void) | |||
74 | 74 | ||
75 | return 0; | 75 | return 0; |
76 | } | 76 | } |
77 | |||
78 | /* | ||
79 | * NetLabel Common Protocol Functions | ||
80 | */ | ||
81 | |||
82 | /** | ||
83 | * netlbl_netlink_send_ack - Send an ACK message | ||
84 | * @info: the generic NETLINK information | ||
85 | * @genl_family: the generic NETLINK family ID value | ||
86 | * @ack_cmd: the generic NETLINK family ACK command value | ||
87 | * @ret_code: return code to use | ||
88 | * | ||
89 | * Description: | ||
90 | * This function sends an ACK message to the sender of the NETLINK message | ||
91 | * specified by @info. | ||
92 | * | ||
93 | */ | ||
94 | void netlbl_netlink_send_ack(const struct genl_info *info, | ||
95 | u32 genl_family, | ||
96 | u8 ack_cmd, | ||
97 | u32 ret_code) | ||
98 | { | ||
99 | size_t data_size; | ||
100 | struct sk_buff *skb; | ||
101 | |||
102 | data_size = GENL_HDRLEN + 2 * NETLBL_LEN_U32; | ||
103 | skb = netlbl_netlink_alloc_skb(0, data_size, GFP_KERNEL); | ||
104 | if (skb == NULL) | ||
105 | return; | ||
106 | |||
107 | if (netlbl_netlink_hdr_put(skb, | ||
108 | info->snd_pid, | ||
109 | 0, | ||
110 | genl_family, | ||
111 | ack_cmd) == NULL) | ||
112 | goto send_ack_failure; | ||
113 | |||
114 | if (nla_put_u32(skb, NLA_U32, info->snd_seq) != 0) | ||
115 | goto send_ack_failure; | ||
116 | if (nla_put_u32(skb, NLA_U32, ret_code) != 0) | ||
117 | goto send_ack_failure; | ||
118 | |||
119 | netlbl_netlink_snd(skb, info->snd_pid); | ||
120 | return; | ||
121 | |||
122 | send_ack_failure: | ||
123 | kfree_skb(skb); | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * NETLINK I/O Functions | ||
128 | */ | ||
129 | |||
130 | /** | ||
131 | * netlbl_netlink_snd - Send a NetLabel message | ||
132 | * @skb: NetLabel message | ||
133 | * @pid: destination PID | ||
134 | * | ||
135 | * Description: | ||
136 | * Sends a unicast NetLabel message over the NETLINK socket. | ||
137 | * | ||
138 | */ | ||
139 | int netlbl_netlink_snd(struct sk_buff *skb, u32 pid) | ||
140 | { | ||
141 | return genlmsg_unicast(skb, pid); | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * netlbl_netlink_snd - Send a NetLabel message | ||
146 | * @skb: NetLabel message | ||
147 | * @pid: sending PID | ||
148 | * @group: multicast group id | ||
149 | * | ||
150 | * Description: | ||
151 | * Sends a multicast NetLabel message over the NETLINK socket to all members | ||
152 | * of @group except @pid. | ||
153 | * | ||
154 | */ | ||
155 | int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group) | ||
156 | { | ||
157 | return genlmsg_multicast(skb, pid, group, GFP_KERNEL); | ||
158 | } | ||
diff --git a/net/netlabel/netlabel_user.h b/net/netlabel/netlabel_user.h index 385a6c7488c6..3f9386b917df 100644 --- a/net/netlabel/netlabel_user.h +++ b/net/netlabel/netlabel_user.h | |||
@@ -41,72 +41,6 @@ | |||
41 | /* NetLabel NETLINK helper functions */ | 41 | /* NetLabel NETLINK helper functions */ |
42 | 42 | ||
43 | /** | 43 | /** |
44 | * netlbl_netlink_cap_check - Check the NETLINK msg capabilities | ||
45 | * @skb: the NETLINK buffer | ||
46 | * @req_cap: the required capability | ||
47 | * | ||
48 | * Description: | ||
49 | * Check the NETLINK buffer's capabilities against the required capabilities. | ||
50 | * Returns zero on success, negative values on failure. | ||
51 | * | ||
52 | */ | ||
53 | static inline int netlbl_netlink_cap_check(const struct sk_buff *skb, | ||
54 | kernel_cap_t req_cap) | ||
55 | { | ||
56 | if (cap_raised(NETLINK_CB(skb).eff_cap, req_cap)) | ||
57 | return 0; | ||
58 | return -EPERM; | ||
59 | } | ||
60 | |||
61 | /** | ||
62 | * netlbl_getinc_u8 - Read a u8 value from a nlattr stream and move on | ||
63 | * @nla: the attribute | ||
64 | * @rem_len: remaining length | ||
65 | * | ||
66 | * Description: | ||
67 | * Return a u8 value pointed to by @nla and advance it to the next attribute. | ||
68 | * | ||
69 | */ | ||
70 | static inline u8 netlbl_getinc_u8(struct nlattr **nla, int *rem_len) | ||
71 | { | ||
72 | u8 val = nla_get_u8(*nla); | ||
73 | *nla = nla_next(*nla, rem_len); | ||
74 | return val; | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * netlbl_getinc_u16 - Read a u16 value from a nlattr stream and move on | ||
79 | * @nla: the attribute | ||
80 | * @rem_len: remaining length | ||
81 | * | ||
82 | * Description: | ||
83 | * Return a u16 value pointed to by @nla and advance it to the next attribute. | ||
84 | * | ||
85 | */ | ||
86 | static inline u16 netlbl_getinc_u16(struct nlattr **nla, int *rem_len) | ||
87 | { | ||
88 | u16 val = nla_get_u16(*nla); | ||
89 | *nla = nla_next(*nla, rem_len); | ||
90 | return val; | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * netlbl_getinc_u32 - Read a u32 value from a nlattr stream and move on | ||
95 | * @nla: the attribute | ||
96 | * @rem_len: remaining length | ||
97 | * | ||
98 | * Description: | ||
99 | * Return a u32 value pointed to by @nla and advance it to the next attribute. | ||
100 | * | ||
101 | */ | ||
102 | static inline u32 netlbl_getinc_u32(struct nlattr **nla, int *rem_len) | ||
103 | { | ||
104 | u32 val = nla_get_u32(*nla); | ||
105 | *nla = nla_next(*nla, rem_len); | ||
106 | return val; | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * netlbl_netlink_hdr_put - Write the NETLINK buffers into a sk_buff | 44 | * netlbl_netlink_hdr_put - Write the NETLINK buffers into a sk_buff |
111 | * @skb: the packet | 45 | * @skb: the packet |
112 | * @pid: the PID of the receipient | 46 | * @pid: the PID of the receipient |
@@ -124,6 +58,7 @@ static inline void *netlbl_netlink_hdr_put(struct sk_buff *skb, | |||
124 | u32 pid, | 58 | u32 pid, |
125 | u32 seq, | 59 | u32 seq, |
126 | int type, | 60 | int type, |
61 | int flags, | ||
127 | u8 cmd) | 62 | u8 cmd) |
128 | { | 63 | { |
129 | return genlmsg_put(skb, | 64 | return genlmsg_put(skb, |
@@ -131,85 +66,13 @@ static inline void *netlbl_netlink_hdr_put(struct sk_buff *skb, | |||
131 | seq, | 66 | seq, |
132 | type, | 67 | type, |
133 | 0, | 68 | 0, |
134 | 0, | 69 | flags, |
135 | cmd, | 70 | cmd, |
136 | NETLBL_PROTO_VERSION); | 71 | NETLBL_PROTO_VERSION); |
137 | } | 72 | } |
138 | 73 | ||
139 | /** | ||
140 | * netlbl_netlink_hdr_push - Write the NETLINK buffers into a sk_buff | ||
141 | * @skb: the packet | ||
142 | * @pid: the PID of the receipient | ||
143 | * @seq: the sequence number | ||
144 | * @type: the generic NETLINK message family type | ||
145 | * @cmd: command | ||
146 | * | ||
147 | * Description: | ||
148 | * Write both a NETLINK nlmsghdr structure and a Generic NETLINK genlmsghdr | ||
149 | * struct to the packet. | ||
150 | * | ||
151 | */ | ||
152 | static inline void netlbl_netlink_hdr_push(struct sk_buff *skb, | ||
153 | u32 pid, | ||
154 | u32 seq, | ||
155 | int type, | ||
156 | u8 cmd) | ||
157 | |||
158 | { | ||
159 | struct nlmsghdr *nlh; | ||
160 | struct genlmsghdr *hdr; | ||
161 | |||
162 | nlh = (struct nlmsghdr *)skb_push(skb, NLMSG_SPACE(GENL_HDRLEN)); | ||
163 | nlh->nlmsg_type = type; | ||
164 | nlh->nlmsg_len = skb->len; | ||
165 | nlh->nlmsg_flags = 0; | ||
166 | nlh->nlmsg_pid = pid; | ||
167 | nlh->nlmsg_seq = seq; | ||
168 | |||
169 | hdr = nlmsg_data(nlh); | ||
170 | hdr->cmd = cmd; | ||
171 | hdr->version = NETLBL_PROTO_VERSION; | ||
172 | hdr->reserved = 0; | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * netlbl_netlink_payload_len - Return the length of the payload | ||
177 | * @skb: the NETLINK buffer | ||
178 | * | ||
179 | * Description: | ||
180 | * This function returns the length of the NetLabel payload. | ||
181 | * | ||
182 | */ | ||
183 | static inline u32 netlbl_netlink_payload_len(const struct sk_buff *skb) | ||
184 | { | ||
185 | return nlmsg_len((struct nlmsghdr *)skb->data) - GENL_HDRLEN; | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * netlbl_netlink_payload_data - Returns a pointer to the start of the payload | ||
190 | * @skb: the NETLINK buffer | ||
191 | * | ||
192 | * Description: | ||
193 | * This function returns a pointer to the start of the NetLabel payload. | ||
194 | * | ||
195 | */ | ||
196 | static inline void *netlbl_netlink_payload_data(const struct sk_buff *skb) | ||
197 | { | ||
198 | return (unsigned char *)nlmsg_data((struct nlmsghdr *)skb->data) + | ||
199 | GENL_HDRLEN; | ||
200 | } | ||
201 | |||
202 | /* NetLabel common protocol functions */ | ||
203 | |||
204 | void netlbl_netlink_send_ack(const struct genl_info *info, | ||
205 | u32 genl_family, | ||
206 | u8 ack_cmd, | ||
207 | u32 ret_code); | ||
208 | |||
209 | /* NetLabel NETLINK I/O functions */ | 74 | /* NetLabel NETLINK I/O functions */ |
210 | 75 | ||
211 | int netlbl_netlink_init(void); | 76 | int netlbl_netlink_init(void); |
212 | int netlbl_netlink_snd(struct sk_buff *skb, u32 pid); | ||
213 | int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group); | ||
214 | 77 | ||
215 | #endif | 78 | #endif |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 7eb69a602d8f..22ed17c17718 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -2502,14 +2502,24 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) | |||
2502 | { | 2502 | { |
2503 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; | 2503 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; |
2504 | struct sk_security_struct *sksec = sk->sk_security; | 2504 | struct sk_security_struct *sksec = sk->sk_security; |
2505 | struct netlbl_lsm_secattr secattr; | ||
2506 | u32 nlbl_peer_sid; | ||
2505 | 2507 | ||
2506 | sksec->sclass = isec->sclass; | 2508 | sksec->sclass = isec->sclass; |
2507 | 2509 | ||
2508 | if (sk->sk_family != PF_INET) | 2510 | if (sk->sk_family != PF_INET) |
2509 | return; | 2511 | return; |
2510 | 2512 | ||
2513 | netlbl_secattr_init(&secattr); | ||
2514 | if (netlbl_sock_getattr(sk, &secattr) == 0 && | ||
2515 | selinux_netlbl_secattr_to_sid(NULL, | ||
2516 | &secattr, | ||
2517 | sksec->sid, | ||
2518 | &nlbl_peer_sid) == 0) | ||
2519 | sksec->peer_sid = nlbl_peer_sid; | ||
2520 | netlbl_secattr_destroy(&secattr, 0); | ||
2521 | |||
2511 | sksec->nlbl_state = NLBL_REQUIRE; | 2522 | sksec->nlbl_state = NLBL_REQUIRE; |
2512 | sksec->peer_sid = sksec->sid; | ||
2513 | 2523 | ||
2514 | /* Try to set the NetLabel on the socket to save time later, if we fail | 2524 | /* Try to set the NetLabel on the socket to save time later, if we fail |
2515 | * here we will pick up the pieces in later calls to | 2525 | * here we will pick up the pieces in later calls to |
@@ -2601,7 +2611,7 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | |||
2601 | u32 netlbl_sid; | 2611 | u32 netlbl_sid; |
2602 | u32 recv_perm; | 2612 | u32 recv_perm; |
2603 | 2613 | ||
2604 | rc = selinux_netlbl_skbuff_getsid(skb, sksec->sid, &netlbl_sid); | 2614 | rc = selinux_netlbl_skbuff_getsid(skb, SECINITSID_NETMSG, &netlbl_sid); |
2605 | if (rc != 0) | 2615 | if (rc != 0) |
2606 | return rc; | 2616 | return rc; |
2607 | 2617 | ||
@@ -2610,13 +2620,13 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | |||
2610 | 2620 | ||
2611 | switch (sksec->sclass) { | 2621 | switch (sksec->sclass) { |
2612 | case SECCLASS_UDP_SOCKET: | 2622 | case SECCLASS_UDP_SOCKET: |
2613 | recv_perm = UDP_SOCKET__RECV_MSG; | 2623 | recv_perm = UDP_SOCKET__RECVFROM; |
2614 | break; | 2624 | break; |
2615 | case SECCLASS_TCP_SOCKET: | 2625 | case SECCLASS_TCP_SOCKET: |
2616 | recv_perm = TCP_SOCKET__RECV_MSG; | 2626 | recv_perm = TCP_SOCKET__RECVFROM; |
2617 | break; | 2627 | break; |
2618 | default: | 2628 | default: |
2619 | recv_perm = RAWIP_SOCKET__RECV_MSG; | 2629 | recv_perm = RAWIP_SOCKET__RECVFROM; |
2620 | } | 2630 | } |
2621 | 2631 | ||
2622 | rc = avc_has_perm(sksec->sid, | 2632 | rc = avc_has_perm(sksec->sid, |