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, |
