* [PATCH 0/6] NetLabel fixes and reworked Netlink interface
@ 2006-09-21 16:57 paul.moore
2006-09-21 16:57 ` [PATCH 1/6] NetLabel: correct improper handling of non-NetLabel peer contexts paul.moore
` (5 more replies)
0 siblings, 6 replies; 14+ messages in thread
From: paul.moore @ 2006-09-21 16:57 UTC (permalink / raw)
To: selinux, netdev; +Cc: sds, jmorris, tgraf
This patchset, made against net-2.6.19, contains a collection of fixes for bugs found over the past few weeks as well as reworked Netlink interface which should bring NetLabel more inline with common Netlink methods. My apologies for not getting this out sooner, but the Netlink interface rewrite was a bit more involved than I originally thought. For those wishing to test/use these patches you will need a new copy of netlabel_tools; you can get a working version from the SVN respository at http://netlabel.sf.net.
I have tested these patches and verified that they work and solve all known issues. Please review and consider them for 2.6.19.
Thanks.
--
paul moore
linux security @ hp
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/6] NetLabel: correct improper handling of non-NetLabel peer contexts
2006-09-21 16:57 [PATCH 0/6] NetLabel fixes and reworked Netlink interface paul.moore
@ 2006-09-21 16:57 ` paul.moore
2006-09-21 18:08 ` James Morris
2006-09-21 16:57 ` [PATCH 2/6] NetLabel: make the CIPSOv4 cache spinlocks bottom half safe paul.moore
` (4 subsequent siblings)
5 siblings, 1 reply; 14+ messages in thread
From: paul.moore @ 2006-09-21 16:57 UTC (permalink / raw)
To: selinux, netdev; +Cc: sds, jmorris, tgraf, Paul Moore
[-- Attachment #1: netlabel-bug_peersec --]
[-- Type: text/plain, Size: 7496 bytes --]
Fix a problem where NetLabel would always set the value of
sk_security_struct->peer_sid in selinux_netlbl_sock_graft() to the context of
the socket, causing problems when users would query the context of the
connection. This patch fixes this so that the value in
sk_security_struct->peer_sid is only set when the connection is NetLabel based,
otherwise the value is untouched.
Signed-off-by: Paul Moore <paul.moore@hp.com>
---
include/net/cipso_ipv4.h | 7 +++++
include/net/netlabel.h | 8 ++++++
net/ipv4/cipso_ipv4.c | 48 ++++++++++++++++++++++++++++-------------
net/netlabel/netlabel_kapi.c | 23 +++++++++++++++++++
security/selinux/ss/services.c | 12 +++++++++-
5 files changed, 82 insertions(+), 16 deletions(-)
Index: net-2.6.19/include/net/cipso_ipv4.h
===================================================================
--- net-2.6.19.orig/include/net/cipso_ipv4.h
+++ net-2.6.19/include/net/cipso_ipv4.h
@@ -205,6 +205,7 @@ void cipso_v4_error(struct sk_buff *skb,
int cipso_v4_socket_setattr(const struct socket *sock,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr);
+int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr);
int cipso_v4_socket_getattr(const struct socket *sock,
struct netlbl_lsm_secattr *secattr);
int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
@@ -225,6 +226,12 @@ static inline int cipso_v4_socket_setatt
return -ENOSYS;
}
+static inline int cipso_v4_sock_getattr(struct sock *sk,
+ struct netlbl_lsm_secattr *secattr)
+{
+ return -ENOSYS;
+}
+
static inline int cipso_v4_socket_getattr(const struct socket *sock,
struct netlbl_lsm_secattr *secattr)
{
Index: net-2.6.19/include/net/netlabel.h
===================================================================
--- net-2.6.19.orig/include/net/netlabel.h
+++ net-2.6.19/include/net/netlabel.h
@@ -238,6 +238,8 @@ static inline void netlbl_secattr_free(s
#ifdef CONFIG_NETLABEL
int netlbl_socket_setattr(const struct socket *sock,
const struct netlbl_lsm_secattr *secattr);
+int netlbl_sock_getattr(struct sock *sk,
+ struct netlbl_lsm_secattr *secattr);
int netlbl_socket_getattr(const struct socket *sock,
struct netlbl_lsm_secattr *secattr);
int netlbl_skbuff_getattr(const struct sk_buff *skb,
@@ -250,6 +252,12 @@ static inline int netlbl_socket_setattr(
return -ENOSYS;
}
+static inline int netlbl_sock_getattr(struct sock *sk,
+ struct netlbl_lsm_secattr *secattr)
+{
+ return -ENOSYS;
+}
+
static inline int netlbl_socket_getattr(const struct socket *sock,
struct netlbl_lsm_secattr *secattr)
{
Index: net-2.6.19/net/ipv4/cipso_ipv4.c
===================================================================
--- net-2.6.19.orig/net/ipv4/cipso_ipv4.c
+++ net-2.6.19/net/ipv4/cipso_ipv4.c
@@ -1486,43 +1486,40 @@ socket_setattr_failure:
}
/**
- * cipso_v4_socket_getattr - Get the security attributes from a socket
- * @sock: the socket
+ * cipso_v4_sock_getattr - Get the security attributes from a sock
+ * @sk: the sock
* @secattr: the security attributes
*
* Description:
- * Query @sock to see if there is a CIPSO option attached to the socket and if
- * there is return the CIPSO security attributes in @secattr. Returns zero on
- * success and negative values on failure.
+ * Query @sk to see if there is a CIPSO option attached to the sock and if
+ * there is return the CIPSO security attributes in @secattr. This function
+ * requires that @sk be locked, or privately held, but it does not do any
+ * locking itself. Returns zero on success and negative values on failure.
*
*/
-int cipso_v4_socket_getattr(const struct socket *sock,
- struct netlbl_lsm_secattr *secattr)
+int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
{
int ret_val = -ENOMSG;
- struct sock *sk;
struct inet_sock *sk_inet;
unsigned char *cipso_ptr;
u32 doi;
struct cipso_v4_doi *doi_def;
- sk = sock->sk;
- lock_sock(sk);
sk_inet = inet_sk(sk);
if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0)
- goto socket_getattr_return;
+ return -ENOMSG;
cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso -
sizeof(struct iphdr);
ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr);
if (ret_val == 0)
- goto socket_getattr_return;
+ return ret_val;
doi = ntohl(*(u32 *)&cipso_ptr[2]);
rcu_read_lock();
doi_def = cipso_v4_doi_getdef(doi);
if (doi_def == NULL) {
rcu_read_unlock();
- goto socket_getattr_return;
+ return -ENOMSG;
}
switch (cipso_ptr[6]) {
case CIPSO_V4_TAG_RBITMAP:
@@ -1533,8 +1530,29 @@ int cipso_v4_socket_getattr(const struct
}
rcu_read_unlock();
-socket_getattr_return:
- release_sock(sk);
+ return ret_val;
+}
+
+/**
+ * cipso_v4_socket_getattr - Get the security attributes from a socket
+ * @sock: the socket
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Query @sock to see if there is a CIPSO option attached to the socket and if
+ * there is return the CIPSO security attributes in @secattr. Returns zero on
+ * success and negative values on failure.
+ *
+ */
+int cipso_v4_socket_getattr(const struct socket *sock,
+ struct netlbl_lsm_secattr *secattr)
+{
+ int ret_val;
+
+ lock_sock(sock->sk);
+ ret_val = cipso_v4_sock_getattr(sock->sk, secattr);
+ release_sock(sock->sk);
+
return ret_val;
}
Index: net-2.6.19/net/netlabel/netlabel_kapi.c
===================================================================
--- net-2.6.19.orig/net/netlabel/netlabel_kapi.c
+++ net-2.6.19/net/netlabel/netlabel_kapi.c
@@ -85,6 +85,29 @@ socket_setattr_return:
}
/**
+ * netlbl_sock_getattr - Determine the security attributes of a sock
+ * @sk: the sock
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Examines the given sock to see any NetLabel style labeling has been
+ * applied to the sock, if so it parses the socket label and returns the
+ * security attributes in @secattr. Returns zero on success, negative values
+ * on failure.
+ *
+ */
+int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
+{
+ int ret_val;
+
+ ret_val = cipso_v4_sock_getattr(sk, secattr);
+ if (ret_val == 0)
+ return 0;
+
+ return netlbl_unlabel_getattr(secattr);
+}
+
+/**
* netlbl_socket_getattr - Determine the security attributes of a socket
* @sock: the socket
* @secattr: the security attributes
Index: net-2.6.19/security/selinux/ss/services.c
===================================================================
--- net-2.6.19.orig/security/selinux/ss/services.c
+++ net-2.6.19/security/selinux/ss/services.c
@@ -2502,14 +2502,24 @@ void selinux_netlbl_sock_graft(struct so
{
struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
struct sk_security_struct *sksec = sk->sk_security;
+ struct netlbl_lsm_secattr secattr;
+ u32 nlbl_peer_sid;
sksec->sclass = isec->sclass;
if (sk->sk_family != PF_INET)
return;
+ netlbl_secattr_init(&secattr);
+ if (netlbl_sock_getattr(sk, &secattr) == 0 &&
+ selinux_netlbl_secattr_to_sid(NULL,
+ &secattr,
+ sksec->sid,
+ &nlbl_peer_sid) == 0)
+ sksec->peer_sid = nlbl_peer_sid;
+ netlbl_secattr_destroy(&secattr, 0);
+
sksec->nlbl_state = NLBL_REQUIRE;
- sksec->peer_sid = sksec->sid;
/* Try to set the NetLabel on the socket to save time later, if we fail
* here we will pick up the pieces in later calls to
--
paul moore
linux security @ hp
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/6] NetLabel: make the CIPSOv4 cache spinlocks bottom half safe
2006-09-21 16:57 [PATCH 0/6] NetLabel fixes and reworked Netlink interface paul.moore
2006-09-21 16:57 ` [PATCH 1/6] NetLabel: correct improper handling of non-NetLabel peer contexts paul.moore
@ 2006-09-21 16:57 ` paul.moore
2006-09-21 16:57 ` [PATCH 3/6] NetLabel: change the SELinux permissions paul.moore
` (3 subsequent siblings)
5 siblings, 0 replies; 14+ messages in thread
From: paul.moore @ 2006-09-21 16:57 UTC (permalink / raw)
To: selinux, netdev; +Cc: sds, jmorris, tgraf, Paul Moore
[-- Attachment #1: netlabel-bug_spinlock --]
[-- Type: text/plain, Size: 3019 bytes --]
The CIPSOv4 cache traversal routines are triggered both the userspace events
(cache invalidation due to DOI removal or updated SELinux policy) and network
packet processing events. As a result there is a problem with the existing
CIPSOv4 cache spinlocks as they are not bottom-half/softirq safe. This patch
converts the CIPSOv4 cache spin_[un]lock() calls into spin_[un]lock_bh() calls
to address this problem.
Signed-off-by: Paul Moore <paul.moore@hp.com>
---
net/ipv4/cipso_ipv4.c | 16 ++++++++--------
1 files changed, 8 insertions(+), 8 deletions(-)
Index: net-2.6.19/net/ipv4/cipso_ipv4.c
===================================================================
--- net-2.6.19.orig/net/ipv4/cipso_ipv4.c
+++ net-2.6.19/net/ipv4/cipso_ipv4.c
@@ -259,7 +259,7 @@ void cipso_v4_cache_invalidate(void)
u32 iter;
for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) {
- spin_lock(&cipso_v4_cache[iter].lock);
+ spin_lock_bh(&cipso_v4_cache[iter].lock);
list_for_each_entry_safe(entry,
tmp_entry,
&cipso_v4_cache[iter].list, list) {
@@ -267,7 +267,7 @@ void cipso_v4_cache_invalidate(void)
cipso_v4_cache_entry_free(entry);
}
cipso_v4_cache[iter].size = 0;
- spin_unlock(&cipso_v4_cache[iter].lock);
+ spin_unlock_bh(&cipso_v4_cache[iter].lock);
}
return;
@@ -309,7 +309,7 @@ static int cipso_v4_cache_check(const un
hash = cipso_v4_map_cache_hash(key, key_len);
bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
- spin_lock(&cipso_v4_cache[bkt].lock);
+ spin_lock_bh(&cipso_v4_cache[bkt].lock);
list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) {
if (entry->hash == hash &&
entry->key_len == key_len &&
@@ -318,7 +318,7 @@ static int cipso_v4_cache_check(const un
secattr->cache.free = entry->lsm_data.free;
secattr->cache.data = entry->lsm_data.data;
if (prev_entry == NULL) {
- spin_unlock(&cipso_v4_cache[bkt].lock);
+ spin_unlock_bh(&cipso_v4_cache[bkt].lock);
return 0;
}
@@ -333,12 +333,12 @@ static int cipso_v4_cache_check(const un
&prev_entry->list);
}
- spin_unlock(&cipso_v4_cache[bkt].lock);
+ spin_unlock_bh(&cipso_v4_cache[bkt].lock);
return 0;
}
prev_entry = entry;
}
- spin_unlock(&cipso_v4_cache[bkt].lock);
+ spin_unlock_bh(&cipso_v4_cache[bkt].lock);
return -ENOENT;
}
@@ -387,7 +387,7 @@ int cipso_v4_cache_add(const struct sk_b
entry->lsm_data.data = secattr->cache.data;
bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
- spin_lock(&cipso_v4_cache[bkt].lock);
+ spin_lock_bh(&cipso_v4_cache[bkt].lock);
if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) {
list_add(&entry->list, &cipso_v4_cache[bkt].list);
cipso_v4_cache[bkt].size += 1;
@@ -398,7 +398,7 @@ int cipso_v4_cache_add(const struct sk_b
list_add(&entry->list, &cipso_v4_cache[bkt].list);
cipso_v4_cache_entry_free(old_entry);
}
- spin_unlock(&cipso_v4_cache[bkt].lock);
+ spin_unlock_bh(&cipso_v4_cache[bkt].lock);
return 0;
--
paul moore
linux security @ hp
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 3/6] NetLabel: change the SELinux permissions
2006-09-21 16:57 [PATCH 0/6] NetLabel fixes and reworked Netlink interface paul.moore
2006-09-21 16:57 ` [PATCH 1/6] NetLabel: correct improper handling of non-NetLabel peer contexts paul.moore
2006-09-21 16:57 ` [PATCH 2/6] NetLabel: make the CIPSOv4 cache spinlocks bottom half safe paul.moore
@ 2006-09-21 16:57 ` paul.moore
2006-09-21 16:57 ` [PATCH 4/6] NetLabel: rework the Netlink attribute handling (part 1) paul.moore
` (2 subsequent siblings)
5 siblings, 0 replies; 14+ messages in thread
From: paul.moore @ 2006-09-21 16:57 UTC (permalink / raw)
To: selinux, netdev; +Cc: sds, jmorris, tgraf
[-- Attachment #1: netlabel-selinux_perm --]
[-- Type: text/plain, Size: 1365 bytes --]
Change NetLabel to use the 'recvfrom' socket permission and the
SECINITSID_NETMSG SELinux SID as the NetLabel base SID for incoming packets.
This patch effectively makes the old, and currently unused, SELinux NETMSG
permissions NetLabel permissions.
Signed-of-by: Paul Moore <paul.moore@hp.com>
---
security/selinux/ss/services.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
Index: net-2.6.19/security/selinux/ss/services.c
===================================================================
--- net-2.6.19.orig/security/selinux/ss/services.c
+++ net-2.6.19/security/selinux/ss/services.c
@@ -2611,7 +2611,7 @@ int selinux_netlbl_sock_rcv_skb(struct s
u32 netlbl_sid;
u32 recv_perm;
- rc = selinux_netlbl_skbuff_getsid(skb, sksec->sid, &netlbl_sid);
+ rc = selinux_netlbl_skbuff_getsid(skb, SECINITSID_NETMSG, &netlbl_sid);
if (rc != 0)
return rc;
@@ -2620,13 +2620,13 @@ int selinux_netlbl_sock_rcv_skb(struct s
switch (sksec->sclass) {
case SECCLASS_UDP_SOCKET:
- recv_perm = UDP_SOCKET__RECV_MSG;
+ recv_perm = UDP_SOCKET__RECVFROM;
break;
case SECCLASS_TCP_SOCKET:
- recv_perm = TCP_SOCKET__RECV_MSG;
+ recv_perm = TCP_SOCKET__RECVFROM;
break;
default:
- recv_perm = RAWIP_SOCKET__RECV_MSG;
+ recv_perm = RAWIP_SOCKET__RECVFROM;
}
rc = avc_has_perm(sksec->sid,
--
paul moore
linux security @ hp
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 4/6] NetLabel: rework the Netlink attribute handling (part 1)
2006-09-21 16:57 [PATCH 0/6] NetLabel fixes and reworked Netlink interface paul.moore
` (2 preceding siblings ...)
2006-09-21 16:57 ` [PATCH 3/6] NetLabel: change the SELinux permissions paul.moore
@ 2006-09-21 16:57 ` paul.moore
2006-09-25 9:12 ` Thomas Graf
2006-09-21 16:57 ` [PATCH 5/6] NetLabel: rework the Netlink attribute handling (part 2) paul.moore
2006-09-21 16:57 ` [PATCH 6/6] NetLabel: update docs with website information paul.moore
5 siblings, 1 reply; 14+ messages in thread
From: paul.moore @ 2006-09-21 16:57 UTC (permalink / raw)
To: selinux, netdev; +Cc: sds, jmorris, tgraf, Paul Moore
[-- Attachment #1: netlabel-nlattr_change_p1 --]
[-- Type: text/plain, Size: 25560 bytes --]
At the suggestion of Thomas Graf, rewrite NetLabel's use of Netlink attributes
to better follow the common Netlink attribute usage.
Signed-off-by: Paul Moore <paul.moore@hp.com>
---
include/net/cipso_ipv4.h | 16 +-
include/net/netlabel.h | 49 --------
net/ipv4/cipso_ipv4.c | 203 ++++---------------------------------
net/netlabel/netlabel_domainhash.c | 183 ++++++---------------------------
net/netlabel/netlabel_domainhash.h | 6 -
net/netlabel/netlabel_user.c | 65 ++---------
net/netlabel/netlabel_user.h | 146 +-------------------------
7 files changed, 93 insertions(+), 575 deletions(-)
Index: net-2.6.19/include/net/cipso_ipv4.h
===================================================================
--- net-2.6.19.orig/include/net/cipso_ipv4.h
+++ net-2.6.19/include/net/cipso_ipv4.h
@@ -130,8 +130,9 @@ extern int cipso_v4_rbm_strictvalid;
int cipso_v4_doi_add(struct cipso_v4_doi *doi_def);
int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head));
struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi);
-struct sk_buff *cipso_v4_doi_dump_all(size_t headroom);
-struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom);
+int cipso_v4_doi_walk(u32 *skip_cnt,
+ int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
+ void *cb_arg);
int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain);
int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
const char *domain);
@@ -152,14 +153,11 @@ static inline struct cipso_v4_doi *cipso
return NULL;
}
-static inline struct sk_buff *cipso_v4_doi_dump_all(size_t headroom)
+static inline int cipso_v4_doi_walk(u32 *skip_cnt,
+ int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
+ void *cb_arg)
{
- return NULL;
-}
-
-static inline struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom)
-{
- return NULL;
+ return 0;
}
static inline int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def,
Index: net-2.6.19/include/net/netlabel.h
===================================================================
--- net-2.6.19.orig/include/net/netlabel.h
+++ net-2.6.19/include/net/netlabel.h
@@ -57,9 +57,8 @@
* The payload is dependent on the subsystem specified in the
* 'nlmsghdr->nlmsg_type' and should be defined below, supporting functions
* should be defined in the corresponding net/netlabel/netlabel_<subsys>.h|c
- * file. All of the fields in the NetLabel payload are NETLINK attributes, the
- * length of each field is the length of the NETLINK attribute payload, see
- * include/net/netlink.h for more information on NETLINK attributes.
+ * file. All of the fields in the NetLabel payload are NETLINK attributes, see
+ * the include/net/netlink.h file for more information on NETLINK attributes.
*
*/
@@ -82,50 +81,6 @@
#define NETLBL_NLTYPE_UNLABELED 5
#define NETLBL_NLTYPE_UNLABELED_NAME "NLBL_UNLBL"
-/* NetLabel return codes */
-#define NETLBL_E_OK 0
-
-/*
- * Helper functions
- */
-
-#define NETLBL_LEN_U8 nla_total_size(sizeof(u8))
-#define NETLBL_LEN_U16 nla_total_size(sizeof(u16))
-#define NETLBL_LEN_U32 nla_total_size(sizeof(u32))
-
-/**
- * netlbl_netlink_alloc_skb - Allocate a NETLINK message buffer
- * @head: the amount of headroom in bytes
- * @body: the desired size (minus headroom) in bytes
- * @gfp_flags: the alloc flags to pass to alloc_skb()
- *
- * Description:
- * Allocate a NETLINK message buffer based on the sizes given in @head and
- * @body. If @head is greater than zero skb_reserve() is called to reserve
- * @head bytes at the start of the buffer. Returns a valid sk_buff pointer on
- * success, NULL on failure.
- *
- */
-static inline struct sk_buff *netlbl_netlink_alloc_skb(size_t head,
- size_t body,
- int gfp_flags)
-{
- struct sk_buff *skb;
-
- skb = alloc_skb(NLMSG_ALIGN(head + body), gfp_flags);
- if (skb == NULL)
- return NULL;
- if (head > 0) {
- skb_reserve(skb, head);
- if (skb_tailroom(skb) < body) {
- kfree_skb(skb);
- return NULL;
- }
- }
-
- return skb;
-}
-
/*
* NetLabel - Kernel API for accessing the network packet label mappings.
*
Index: net-2.6.19/net/ipv4/cipso_ipv4.c
===================================================================
--- net-2.6.19.orig/net/ipv4/cipso_ipv4.c
+++ net-2.6.19/net/ipv4/cipso_ipv4.c
@@ -530,197 +530,42 @@ struct cipso_v4_doi *cipso_v4_doi_getdef
}
/**
- * cipso_v4_doi_dump_all - Dump all the CIPSO DOI definitions into a sk_buff
- * @headroom: the amount of headroom to allocate for the sk_buff
+ * cipso_v4_doi_walk - Iterate through the DOI definitions
+ * @skip_cnt: skip past this number of DOI definitions, updated
+ * @callback: callback for each DOI definition
+ * @cb_arg: argument for the callback function
*
* Description:
- * Dump a list of all the configured DOI values into a sk_buff. The returned
- * sk_buff has room at the front of the sk_buff for @headroom bytes. See
- * net/netlabel/netlabel_cipso_v4.h for the LISTALL message format. This
- * function may fail if another process is changing the DOI list at the same
- * time. Returns a pointer to a sk_buff on success, NULL on error.
+ * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
+ * For each entry call @callback, if @callback returns a negative value stop
+ * 'walking' through the list and return. Updates the value in @skip_cnt upon
+ * return. Returns zero on success, negative values on failure.
*
*/
-struct sk_buff *cipso_v4_doi_dump_all(size_t headroom)
+int cipso_v4_doi_walk(u32 *skip_cnt,
+ int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
+ void *cb_arg)
{
- struct sk_buff *skb = NULL;
- struct cipso_v4_doi *iter;
+ int ret_val = -ENOENT;
u32 doi_cnt = 0;
- ssize_t buf_len;
+ struct cipso_v4_doi *iter_doi;
- buf_len = NETLBL_LEN_U32;
rcu_read_lock();
- list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
- if (iter->valid) {
- doi_cnt += 1;
- buf_len += 2 * NETLBL_LEN_U32;
- }
-
- skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
- if (skb == NULL)
- goto doi_dump_all_failure;
-
- if (nla_put_u32(skb, NLA_U32, doi_cnt) != 0)
- goto doi_dump_all_failure;
- buf_len -= NETLBL_LEN_U32;
- list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
- if (iter->valid) {
- if (buf_len < 2 * NETLBL_LEN_U32)
- goto doi_dump_all_failure;
- if (nla_put_u32(skb, NLA_U32, iter->doi) != 0)
- goto doi_dump_all_failure;
- if (nla_put_u32(skb, NLA_U32, iter->type) != 0)
- goto doi_dump_all_failure;
- buf_len -= 2 * NETLBL_LEN_U32;
- }
- rcu_read_unlock();
-
- return skb;
-
-doi_dump_all_failure:
- rcu_read_unlock();
- kfree(skb);
- return NULL;
-}
-
-/**
- * cipso_v4_doi_dump - Dump a CIPSO DOI definition into a sk_buff
- * @doi: the DOI value
- * @headroom: the amount of headroom to allocate for the sk_buff
- *
- * Description:
- * Lookup the DOI definition matching @doi and dump it's contents into a
- * sk_buff. The returned sk_buff has room at the front of the sk_buff for
- * @headroom bytes. See net/netlabel/netlabel_cipso_v4.h for the LIST message
- * format. This function may fail if another process is changing the DOI list
- * at the same time. Returns a pointer to a sk_buff on success, NULL on error.
- *
- */
-struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom)
-{
- struct sk_buff *skb = NULL;
- struct cipso_v4_doi *iter;
- u32 tag_cnt = 0;
- u32 lvl_cnt = 0;
- u32 cat_cnt = 0;
- ssize_t buf_len;
- ssize_t tmp;
-
- rcu_read_lock();
- iter = cipso_v4_doi_getdef(doi);
- if (iter == NULL)
- goto doi_dump_failure;
- buf_len = NETLBL_LEN_U32;
- switch (iter->type) {
- case CIPSO_V4_MAP_PASS:
- buf_len += NETLBL_LEN_U32;
- while(tag_cnt < CIPSO_V4_TAG_MAXCNT &&
- iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) {
- tag_cnt += 1;
- buf_len += NETLBL_LEN_U8;
- }
- break;
- case CIPSO_V4_MAP_STD:
- buf_len += 3 * NETLBL_LEN_U32;
- while (tag_cnt < CIPSO_V4_TAG_MAXCNT &&
- iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) {
- tag_cnt += 1;
- buf_len += NETLBL_LEN_U8;
- }
- for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++)
- if (iter->map.std->lvl.local[tmp] !=
- CIPSO_V4_INV_LVL) {
- lvl_cnt += 1;
- buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U8;
+ list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list)
+ if (iter_doi->valid) {
+ if (doi_cnt++ < *skip_cnt)
+ continue;
+ ret_val = callback(iter_doi, cb_arg);
+ if (ret_val < 0) {
+ doi_cnt--;
+ goto doi_walk_return;
}
- for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++)
- if (iter->map.std->cat.local[tmp] !=
- CIPSO_V4_INV_CAT) {
- cat_cnt += 1;
- buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U16;
- }
- break;
- }
-
- skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
- if (skb == NULL)
- goto doi_dump_failure;
-
- if (nla_put_u32(skb, NLA_U32, iter->type) != 0)
- goto doi_dump_failure;
- buf_len -= NETLBL_LEN_U32;
- if (iter != cipso_v4_doi_getdef(doi))
- goto doi_dump_failure;
- switch (iter->type) {
- case CIPSO_V4_MAP_PASS:
- if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0)
- goto doi_dump_failure;
- buf_len -= NETLBL_LEN_U32;
- for (tmp = 0;
- tmp < CIPSO_V4_TAG_MAXCNT &&
- iter->tags[tmp] != CIPSO_V4_TAG_INVALID;
- tmp++) {
- if (buf_len < NETLBL_LEN_U8)
- goto doi_dump_failure;
- if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0)
- goto doi_dump_failure;
- buf_len -= NETLBL_LEN_U8;
- }
- break;
- case CIPSO_V4_MAP_STD:
- if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0)
- goto doi_dump_failure;
- if (nla_put_u32(skb, NLA_U32, lvl_cnt) != 0)
- goto doi_dump_failure;
- if (nla_put_u32(skb, NLA_U32, cat_cnt) != 0)
- goto doi_dump_failure;
- buf_len -= 3 * NETLBL_LEN_U32;
- for (tmp = 0;
- tmp < CIPSO_V4_TAG_MAXCNT &&
- iter->tags[tmp] != CIPSO_V4_TAG_INVALID;
- tmp++) {
- if (buf_len < NETLBL_LEN_U8)
- goto doi_dump_failure;
- if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0)
- goto doi_dump_failure;
- buf_len -= NETLBL_LEN_U8;
}
- for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++)
- if (iter->map.std->lvl.local[tmp] !=
- CIPSO_V4_INV_LVL) {
- if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U8)
- goto doi_dump_failure;
- if (nla_put_u32(skb, NLA_U32, tmp) != 0)
- goto doi_dump_failure;
- if (nla_put_u8(skb,
- NLA_U8,
- iter->map.std->lvl.local[tmp]) != 0)
- goto doi_dump_failure;
- buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U8;
- }
- for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++)
- if (iter->map.std->cat.local[tmp] !=
- CIPSO_V4_INV_CAT) {
- if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U16)
- goto doi_dump_failure;
- if (nla_put_u32(skb, NLA_U32, tmp) != 0)
- goto doi_dump_failure;
- if (nla_put_u16(skb,
- NLA_U16,
- iter->map.std->cat.local[tmp]) != 0)
- goto doi_dump_failure;
- buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U16;
- }
- break;
- }
- rcu_read_unlock();
- return skb;
-
-doi_dump_failure:
+doi_walk_return:
rcu_read_unlock();
- kfree(skb);
- return NULL;
+ *skip_cnt = doi_cnt;
+ return ret_val;
}
/**
Index: net-2.6.19/net/netlabel/netlabel_domainhash.c
===================================================================
--- net-2.6.19.orig/net/netlabel/netlabel_domainhash.c
+++ net-2.6.19/net/netlabel/netlabel_domainhash.c
@@ -354,160 +354,51 @@ struct netlbl_dom_map *netlbl_domhsh_get
}
/**
- * netlbl_domhsh_dump - Dump the domain hash table into a sk_buff
+ * netlbl_domhsh_walk - Iterate through the domain mapping hash table
+ * @skip_bkt: the number of buckets to skip at the start
+ * @skip_chain: the number of entries to skip in the first iterated bucket
+ * @callback: callback for each entry
+ * @cb_arg: argument for the callback function
*
* Description:
- * Dump the domain hash table into a buffer suitable for returning to an
- * application in response to a NetLabel management DOMAIN message. This
- * function may fail if another process is growing the hash table at the same
- * time. The returned sk_buff has room at the front of the sk_buff for
- * @headroom bytes. See netlabel.h for the DOMAIN message format. Returns a
- * pointer to a sk_buff on success, NULL on error.
+ * Interate over the domain mapping hash table, skipping the first @skip_bkt
+ * buckets and @skip_chain entries. For each entry in the table call
+ * @callback, if @callback returns a negative value stop 'walking' through the
+ * table and return. Updates the values in @skip_bkt and @skip_chain on
+ * return. Returns zero on succcess, negative values on failure.
*
*/
-struct sk_buff *netlbl_domhsh_dump(size_t headroom)
+int netlbl_domhsh_walk(u32 *skip_bkt,
+ u32 *skip_chain,
+ int (*callback) (struct netlbl_dom_map *entry, void *arg),
+ void *cb_arg)
{
- struct sk_buff *skb = NULL;
- ssize_t buf_len;
- u32 bkt_iter;
- u32 dom_cnt = 0;
- struct netlbl_domhsh_tbl *hsh_tbl;
- struct netlbl_dom_map *list_iter;
- ssize_t tmp_len;
+ int ret_val = -ENOENT;
+ u32 iter_bkt;
+ struct netlbl_dom_map *iter_entry;
+ u32 chain_cnt = 0;
- buf_len = NETLBL_LEN_U32;
rcu_read_lock();
- hsh_tbl = rcu_dereference(netlbl_domhsh);
- for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++)
- list_for_each_entry_rcu(list_iter,
- &hsh_tbl->tbl[bkt_iter], list) {
- buf_len += NETLBL_LEN_U32 +
- nla_total_size(strlen(list_iter->domain) + 1);
- switch (list_iter->type) {
- case NETLBL_NLTYPE_UNLABELED:
- break;
- case NETLBL_NLTYPE_CIPSOV4:
- buf_len += 2 * NETLBL_LEN_U32;
- break;
+ for (iter_bkt = *skip_bkt;
+ iter_bkt < rcu_dereference(netlbl_domhsh)->size;
+ iter_bkt++, chain_cnt = 0) {
+ list_for_each_entry_rcu(iter_entry,
+ &netlbl_domhsh->tbl[iter_bkt],
+ list)
+ if (iter_entry->valid) {
+ if (chain_cnt++ < *skip_chain)
+ continue;
+ ret_val = callback(iter_entry, cb_arg);
+ if (ret_val < 0) {
+ chain_cnt--;
+ goto walk_return;
+ }
}
- dom_cnt++;
- }
+ }
- skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
- if (skb == NULL)
- goto dump_failure;
-
- if (nla_put_u32(skb, NLA_U32, dom_cnt) != 0)
- goto dump_failure;
- buf_len -= NETLBL_LEN_U32;
- hsh_tbl = rcu_dereference(netlbl_domhsh);
- for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++)
- list_for_each_entry_rcu(list_iter,
- &hsh_tbl->tbl[bkt_iter], list) {
- tmp_len = nla_total_size(strlen(list_iter->domain) +
- 1);
- if (buf_len < NETLBL_LEN_U32 + tmp_len)
- goto dump_failure;
- if (nla_put_string(skb,
- NLA_STRING,
- list_iter->domain) != 0)
- goto dump_failure;
- if (nla_put_u32(skb, NLA_U32, list_iter->type) != 0)
- goto dump_failure;
- buf_len -= NETLBL_LEN_U32 + tmp_len;
- switch (list_iter->type) {
- case NETLBL_NLTYPE_UNLABELED:
- break;
- case NETLBL_NLTYPE_CIPSOV4:
- if (buf_len < 2 * NETLBL_LEN_U32)
- goto dump_failure;
- if (nla_put_u32(skb,
- NLA_U32,
- list_iter->type_def.cipsov4->type) != 0)
- goto dump_failure;
- if (nla_put_u32(skb,
- NLA_U32,
- list_iter->type_def.cipsov4->doi) != 0)
- goto dump_failure;
- buf_len -= 2 * NETLBL_LEN_U32;
- break;
- }
- }
- rcu_read_unlock();
-
- return skb;
-
-dump_failure:
- rcu_read_unlock();
- kfree_skb(skb);
- return NULL;
-}
-
-/**
- * netlbl_domhsh_dump_default - Dump the default domain mapping into a sk_buff
- *
- * Description:
- * Dump the default domain mapping into a buffer suitable for returning to an
- * application in response to a NetLabel management DEFDOMAIN message. This
- * function may fail if another process is changing the default domain mapping
- * at the same time. The returned sk_buff has room at the front of the
- * skb_buff for @headroom bytes. See netlabel.h for the DEFDOMAIN message
- * format. Returns a pointer to a sk_buff on success, NULL on error.
- *
- */
-struct sk_buff *netlbl_domhsh_dump_default(size_t headroom)
-{
- struct sk_buff *skb;
- ssize_t buf_len;
- struct netlbl_dom_map *entry;
-
- buf_len = NETLBL_LEN_U32;
- rcu_read_lock();
- entry = rcu_dereference(netlbl_domhsh_def);
- if (entry != NULL)
- switch (entry->type) {
- case NETLBL_NLTYPE_UNLABELED:
- break;
- case NETLBL_NLTYPE_CIPSOV4:
- buf_len += 2 * NETLBL_LEN_U32;
- break;
- }
-
- skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
- if (skb == NULL)
- goto dump_default_failure;
-
- if (entry != rcu_dereference(netlbl_domhsh_def))
- goto dump_default_failure;
- if (entry != NULL) {
- if (nla_put_u32(skb, NLA_U32, entry->type) != 0)
- goto dump_default_failure;
- buf_len -= NETLBL_LEN_U32;
- switch (entry->type) {
- case NETLBL_NLTYPE_UNLABELED:
- break;
- case NETLBL_NLTYPE_CIPSOV4:
- if (buf_len < 2 * NETLBL_LEN_U32)
- goto dump_default_failure;
- if (nla_put_u32(skb,
- NLA_U32,
- entry->type_def.cipsov4->type) != 0)
- goto dump_default_failure;
- if (nla_put_u32(skb,
- NLA_U32,
- entry->type_def.cipsov4->doi) != 0)
- goto dump_default_failure;
- buf_len -= 2 * NETLBL_LEN_U32;
- break;
- }
- } else
- nla_put_u32(skb, NLA_U32, NETLBL_NLTYPE_NONE);
- rcu_read_unlock();
-
- return skb;
-
-dump_default_failure:
+walk_return:
rcu_read_unlock();
- kfree_skb(skb);
- return NULL;
+ *skip_bkt = iter_bkt;
+ *skip_chain = chain_cnt;
+ return ret_val;
}
Index: net-2.6.19/net/netlabel/netlabel_domainhash.h
===================================================================
--- net-2.6.19.orig/net/netlabel/netlabel_domainhash.h
+++ net-2.6.19/net/netlabel/netlabel_domainhash.h
@@ -61,7 +61,9 @@ int netlbl_domhsh_add(struct netlbl_dom_
int netlbl_domhsh_add_default(struct netlbl_dom_map *entry);
int netlbl_domhsh_remove_default(void);
struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain);
-struct sk_buff *netlbl_domhsh_dump(size_t headroom);
-struct sk_buff *netlbl_domhsh_dump_default(size_t headroom);
+int netlbl_domhsh_walk(u32 *skip_bkt,
+ u32 *skip_chain,
+ int (*callback) (struct netlbl_dom_map *entry, void *arg),
+ void *cb_arg);
#endif
Index: net-2.6.19/net/netlabel/netlabel_user.c
===================================================================
--- net-2.6.19.orig/net/netlabel/netlabel_user.c
+++ net-2.6.19/net/netlabel/netlabel_user.c
@@ -76,83 +76,42 @@ int netlbl_netlink_init(void)
}
/*
- * NetLabel Common Protocol Functions
- */
-
-/**
- * netlbl_netlink_send_ack - Send an ACK message
- * @info: the generic NETLINK information
- * @genl_family: the generic NETLINK family ID value
- * @ack_cmd: the generic NETLINK family ACK command value
- * @ret_code: return code to use
- *
- * Description:
- * This function sends an ACK message to the sender of the NETLINK message
- * specified by @info.
- *
- */
-void netlbl_netlink_send_ack(const struct genl_info *info,
- u32 genl_family,
- u8 ack_cmd,
- u32 ret_code)
-{
- size_t data_size;
- struct sk_buff *skb;
-
- data_size = GENL_HDRLEN + 2 * NETLBL_LEN_U32;
- skb = netlbl_netlink_alloc_skb(0, data_size, GFP_KERNEL);
- if (skb == NULL)
- return;
-
- if (netlbl_netlink_hdr_put(skb,
- info->snd_pid,
- 0,
- genl_family,
- ack_cmd) == NULL)
- goto send_ack_failure;
-
- if (nla_put_u32(skb, NLA_U32, info->snd_seq) != 0)
- goto send_ack_failure;
- if (nla_put_u32(skb, NLA_U32, ret_code) != 0)
- goto send_ack_failure;
-
- netlbl_netlink_snd(skb, info->snd_pid);
- return;
-
-send_ack_failure:
- kfree_skb(skb);
-}
-
-/*
* NETLINK I/O Functions
*/
/**
* netlbl_netlink_snd - Send a NetLabel message
* @skb: NetLabel message
+ * @buf: start of message
* @pid: destination PID
*
* Description:
- * Sends a unicast NetLabel message over the NETLINK socket.
+ * End a NetLabel message and do a unicast send over the NETLINK socket.
*
*/
-int netlbl_netlink_snd(struct sk_buff *skb, u32 pid)
+int netlbl_netlink_snd(struct sk_buff *skb, void *buf, u32 pid)
{
+ genlmsg_end(skb, buf);
return genlmsg_unicast(skb, pid);
}
/**
* netlbl_netlink_snd - Send a NetLabel message
* @skb: NetLabel message
+ * @buf: start of message
* @pid: sending PID
* @group: multicast group id
*
* Description:
- * Sends a multicast NetLabel message over the NETLINK socket to all members
- * of @group except @pid.
+ * End a NetLabel message and do a multicast send message over the NETLINK
+ * socket to all members of @group except @pid.
*
*/
-int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group)
+int netlbl_netlink_snd_multicast(struct sk_buff *skb,
+ void *buf,
+ u32 pid,
+ u32 group)
{
+ genlmsg_end(skb, buf);
return genlmsg_multicast(skb, pid, group, GFP_KERNEL);
}
Index: net-2.6.19/net/netlabel/netlabel_user.h
===================================================================
--- net-2.6.19.orig/net/netlabel/netlabel_user.h
+++ net-2.6.19/net/netlabel/netlabel_user.h
@@ -41,72 +41,6 @@
/* NetLabel NETLINK helper functions */
/**
- * netlbl_netlink_cap_check - Check the NETLINK msg capabilities
- * @skb: the NETLINK buffer
- * @req_cap: the required capability
- *
- * Description:
- * Check the NETLINK buffer's capabilities against the required capabilities.
- * Returns zero on success, negative values on failure.
- *
- */
-static inline int netlbl_netlink_cap_check(const struct sk_buff *skb,
- kernel_cap_t req_cap)
-{
- if (cap_raised(NETLINK_CB(skb).eff_cap, req_cap))
- return 0;
- return -EPERM;
-}
-
-/**
- * netlbl_getinc_u8 - Read a u8 value from a nlattr stream and move on
- * @nla: the attribute
- * @rem_len: remaining length
- *
- * Description:
- * Return a u8 value pointed to by @nla and advance it to the next attribute.
- *
- */
-static inline u8 netlbl_getinc_u8(struct nlattr **nla, int *rem_len)
-{
- u8 val = nla_get_u8(*nla);
- *nla = nla_next(*nla, rem_len);
- return val;
-}
-
-/**
- * netlbl_getinc_u16 - Read a u16 value from a nlattr stream and move on
- * @nla: the attribute
- * @rem_len: remaining length
- *
- * Description:
- * Return a u16 value pointed to by @nla and advance it to the next attribute.
- *
- */
-static inline u16 netlbl_getinc_u16(struct nlattr **nla, int *rem_len)
-{
- u16 val = nla_get_u16(*nla);
- *nla = nla_next(*nla, rem_len);
- return val;
-}
-
-/**
- * netlbl_getinc_u32 - Read a u32 value from a nlattr stream and move on
- * @nla: the attribute
- * @rem_len: remaining length
- *
- * Description:
- * Return a u32 value pointed to by @nla and advance it to the next attribute.
- *
- */
-static inline u32 netlbl_getinc_u32(struct nlattr **nla, int *rem_len)
-{
- u32 val = nla_get_u32(*nla);
- *nla = nla_next(*nla, rem_len);
- return val;
-}
-
-/**
* netlbl_netlink_hdr_put - Write the NETLINK buffers into a sk_buff
* @skb: the packet
* @pid: the PID of the receipient
@@ -124,6 +58,7 @@ static inline void *netlbl_netlink_hdr_p
u32 pid,
u32 seq,
int type,
+ int flags,
u8 cmd)
{
return genlmsg_put(skb,
@@ -131,85 +66,18 @@ static inline void *netlbl_netlink_hdr_p
seq,
type,
0,
- 0,
+ flags,
cmd,
NETLBL_PROTO_VERSION);
}
-/**
- * netlbl_netlink_hdr_push - Write the NETLINK buffers into a sk_buff
- * @skb: the packet
- * @pid: the PID of the receipient
- * @seq: the sequence number
- * @type: the generic NETLINK message family type
- * @cmd: command
- *
- * Description:
- * Write both a NETLINK nlmsghdr structure and a Generic NETLINK genlmsghdr
- * struct to the packet.
- *
- */
-static inline void netlbl_netlink_hdr_push(struct sk_buff *skb,
- u32 pid,
- u32 seq,
- int type,
- u8 cmd)
-
-{
- struct nlmsghdr *nlh;
- struct genlmsghdr *hdr;
-
- nlh = (struct nlmsghdr *)skb_push(skb, NLMSG_SPACE(GENL_HDRLEN));
- nlh->nlmsg_type = type;
- nlh->nlmsg_len = skb->len;
- nlh->nlmsg_flags = 0;
- nlh->nlmsg_pid = pid;
- nlh->nlmsg_seq = seq;
-
- hdr = nlmsg_data(nlh);
- hdr->cmd = cmd;
- hdr->version = NETLBL_PROTO_VERSION;
- hdr->reserved = 0;
-}
-
-/**
- * netlbl_netlink_payload_len - Return the length of the payload
- * @skb: the NETLINK buffer
- *
- * Description:
- * This function returns the length of the NetLabel payload.
- *
- */
-static inline u32 netlbl_netlink_payload_len(const struct sk_buff *skb)
-{
- return nlmsg_len((struct nlmsghdr *)skb->data) - GENL_HDRLEN;
-}
-
-/**
- * netlbl_netlink_payload_data - Returns a pointer to the start of the payload
- * @skb: the NETLINK buffer
- *
- * Description:
- * This function returns a pointer to the start of the NetLabel payload.
- *
- */
-static inline void *netlbl_netlink_payload_data(const struct sk_buff *skb)
-{
- return (unsigned char *)nlmsg_data((struct nlmsghdr *)skb->data) +
- GENL_HDRLEN;
-}
-
-/* NetLabel common protocol functions */
-
-void netlbl_netlink_send_ack(const struct genl_info *info,
- u32 genl_family,
- u8 ack_cmd,
- u32 ret_code);
-
/* NetLabel NETLINK I/O functions */
int netlbl_netlink_init(void);
-int netlbl_netlink_snd(struct sk_buff *skb, u32 pid);
-int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group);
+int netlbl_netlink_snd(struct sk_buff *skb, void *buf, u32 pid);
+int netlbl_netlink_snd_multicast(struct sk_buff *skb,
+ void *buf,
+ u32 pid,
+ u32 group);
#endif
--
paul moore
linux security @ hp
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 5/6] NetLabel: rework the Netlink attribute handling (part 2)
2006-09-21 16:57 [PATCH 0/6] NetLabel fixes and reworked Netlink interface paul.moore
` (3 preceding siblings ...)
2006-09-21 16:57 ` [PATCH 4/6] NetLabel: rework the Netlink attribute handling (part 1) paul.moore
@ 2006-09-21 16:57 ` paul.moore
2006-09-25 9:43 ` Thomas Graf
2006-09-21 16:57 ` [PATCH 6/6] NetLabel: update docs with website information paul.moore
5 siblings, 1 reply; 14+ messages in thread
From: paul.moore @ 2006-09-21 16:57 UTC (permalink / raw)
To: selinux, netdev; +Cc: sds, jmorris, tgraf, Paul Moore
[-- Attachment #1: netlabel-nlattr_change_p2 --]
[-- Type: text/plain, Size: 72152 bytes --]
At the suggestion of Thomas Graf, rewrite NetLabel's use of Netlink attributes
to better follow the common Netlink attribute usage.
Signed-off-by: Paul Moore <paul.moore@hp.com>
---
net/netlabel/netlabel_cipso_v4.c | 593 +++++++++++++++++++++++++-------------
net/netlabel/netlabel_cipso_v4.h | 235 +++++----------
net/netlabel/netlabel_mgmt.c | 531 +++++++++++++++++-----------------
net/netlabel/netlabel_mgmt.h | 213 ++++---------
net/netlabel/netlabel_unlabeled.c | 77 ++--
net/netlabel/netlabel_unlabeled.h | 41 +-
6 files changed, 875 insertions(+), 815 deletions(-)
Index: net-2.6.19/net/netlabel/netlabel_cipso_v4.c
===================================================================
--- net-2.6.19.orig/net/netlabel/netlabel_cipso_v4.c
+++ net-2.6.19/net/netlabel/netlabel_cipso_v4.c
@@ -41,15 +41,37 @@
#include "netlabel_user.h"
#include "netlabel_cipso_v4.h"
+/* Argument struct for cipso_v4_doi_walk() */
+struct netlbl_cipsov4_doiwalk_arg {
+ struct netlink_callback *nl_cb;
+ struct sk_buff *skb;
+ u32 seq;
+};
+
/* NetLabel Generic NETLINK CIPSOv4 family */
static struct genl_family netlbl_cipsov4_gnl_family = {
.id = GENL_ID_GENERATE,
.hdrsize = 0,
.name = NETLBL_NLTYPE_CIPSOV4_NAME,
.version = NETLBL_PROTO_VERSION,
- .maxattr = 0,
+ .maxattr = NLBL_CIPSOV4_A_MAX,
};
+/* NetLabel Netlink attribute policy */
+static struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
+ [NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 },
+ [NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 },
+ [NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 },
+ [NLBL_CIPSOV4_A_TAGLST] = { .type = NLA_NESTED },
+ [NLBL_CIPSOV4_A_MLSLVLLOC] = { .type = NLA_U32 },
+ [NLBL_CIPSOV4_A_MLSLVLREM] = { .type = NLA_U32 },
+ [NLBL_CIPSOV4_A_MLSLVL] = { .type = NLA_NESTED },
+ [NLBL_CIPSOV4_A_MLSLVLLST] = { .type = NLA_NESTED },
+ [NLBL_CIPSOV4_A_MLSCATLOC] = { .type = NLA_U32 },
+ [NLBL_CIPSOV4_A_MLSCATREM] = { .type = NLA_U32 },
+ [NLBL_CIPSOV4_A_MLSCAT] = { .type = NLA_NESTED },
+ [NLBL_CIPSOV4_A_MLSCATLST] = { .type = NLA_NESTED },
+};
/*
* Helper Functions
@@ -81,16 +103,13 @@ static void netlbl_cipsov4_doi_free(stru
kfree(ptr);
}
-
/*
* NetLabel Command Handlers
*/
/**
* netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition
- * @doi: the DOI value
- * @msg: the ADD message data
- * @msg_size: the size of the ADD message buffer
+ * @info: the Generic NETLINK info block
*
* Description:
* Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message
@@ -98,22 +117,31 @@ static void netlbl_cipsov4_doi_free(stru
* error.
*
*/
-static int netlbl_cipsov4_add_std(u32 doi, struct nlattr *msg, size_t msg_size)
+static int netlbl_cipsov4_add_std(struct genl_info *info)
{
int ret_val = -EINVAL;
- int msg_len = msg_size;
- u32 num_tags;
- u32 num_lvls;
- u32 num_cats;
struct cipso_v4_doi *doi_def = NULL;
- u32 iter;
- u32 tmp_val_a;
- u32 tmp_val_b;
-
- if (msg_len < NETLBL_LEN_U32)
- goto add_std_failure;
- num_tags = netlbl_getinc_u32(&msg, &msg_len);
- if (num_tags == 0 || num_tags > CIPSO_V4_TAG_MAXCNT)
+ struct nlattr *nla_a;
+ struct nlattr *nla_b;
+ struct nlattr *nla_c;
+ int nla_a_rem;
+ int nla_b_rem;
+ u32 iter = 0;
+
+ if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
+ !info->attrs[NLBL_CIPSOV4_A_TAGLST] ||
+ !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST])
+ goto add_std_failure;
+
+ if (nla_validate(nla_data(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
+ nla_len(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
+ NLBL_CIPSOV4_A_MAX,
+ netlbl_cipsov4_genl_policy) != 0)
+ goto add_std_failure;
+ if (nla_validate(nla_data(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
+ nla_len(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
+ NLBL_CIPSOV4_A_MAX,
+ netlbl_cipsov4_genl_policy) != 0)
goto add_std_failure;
doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
@@ -128,28 +156,44 @@ static int netlbl_cipsov4_add_std(u32 do
}
doi_def->type = CIPSO_V4_MAP_STD;
- for (iter = 0; iter < num_tags; iter++) {
- if (msg_len < NETLBL_LEN_U8)
- goto add_std_failure;
- doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len);
- switch (doi_def->tags[iter]) {
- case CIPSO_V4_TAG_RBITMAP:
- break;
- default:
- goto add_std_failure;
+ nla_for_each_attr(nla_a,
+ nla_data(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
+ nla_len(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
+ nla_a_rem)
+ if (nla_a->nla_type == NLBL_CIPSOV4_A_TAG) {
+ if (iter > CIPSO_V4_TAG_MAXCNT)
+ goto add_std_failure;
+ doi_def->tags[iter++] = nla_get_u8(nla_a);
}
- }
if (iter < CIPSO_V4_TAG_MAXCNT)
doi_def->tags[iter] = CIPSO_V4_TAG_INVALID;
- if (msg_len < 6 * NETLBL_LEN_U32)
- goto add_std_failure;
-
- num_lvls = netlbl_getinc_u32(&msg, &msg_len);
- if (num_lvls == 0)
- goto add_std_failure;
- doi_def->map.std->lvl.local_size = netlbl_getinc_u32(&msg, &msg_len);
- if (doi_def->map.std->lvl.local_size > CIPSO_V4_MAX_LOC_LVLS)
+ nla_for_each_attr(nla_a,
+ nla_data(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
+ nla_len(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
+ nla_a_rem)
+ if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) {
+ nla_for_each_attr(nla_b,
+ nla_data(nla_a),
+ nla_len(nla_a),
+ nla_b_rem)
+ switch (nla_b->nla_type) {
+ case NLBL_CIPSOV4_A_MLSLVLLOC:
+ if (nla_get_u32(nla_b) >=
+ doi_def->map.std->lvl.local_size)
+ doi_def->map.std->lvl.local_size =
+ nla_get_u32(nla_b) + 1;
+ break;
+ case NLBL_CIPSOV4_A_MLSLVLREM:
+ if (nla_get_u32(nla_b) >=
+ doi_def->map.std->lvl.cipso_size)
+ doi_def->map.std->lvl.cipso_size =
+ nla_get_u32(nla_b) + 1;
+ break;
+ }
+ }
+ if (doi_def->map.std->lvl.local_size > CIPSO_V4_MAX_LOC_LVLS ||
+ doi_def->map.std->lvl.cipso_size > CIPSO_V4_MAX_REM_LVLS)
goto add_std_failure;
doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size,
sizeof(u32),
@@ -158,9 +202,6 @@ static int netlbl_cipsov4_add_std(u32 do
ret_val = -ENOMEM;
goto add_std_failure;
}
- doi_def->map.std->lvl.cipso_size = netlbl_getinc_u8(&msg, &msg_len);
- if (doi_def->map.std->lvl.cipso_size > CIPSO_V4_MAX_REM_LVLS)
- goto add_std_failure;
doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size,
sizeof(u32),
GFP_KERNEL);
@@ -168,68 +209,96 @@ static int netlbl_cipsov4_add_std(u32 do
ret_val = -ENOMEM;
goto add_std_failure;
}
+ nla_for_each_attr(nla_a,
+ nla_data(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
+ nla_len(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
+ nla_a_rem)
+ if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) {
+ nla_b = nla_find_nested(nla_a,
+ NLBL_CIPSOV4_A_MLSLVLLOC);
+ nla_c = nla_find_nested(nla_a,
+ NLBL_CIPSOV4_A_MLSLVLREM);
+ if (nla_b == NULL || nla_c == NULL)
+ goto add_std_failure;
+ doi_def->map.std->lvl.local[nla_get_u32(nla_b)] =
+ nla_get_u32(nla_c);
+ doi_def->map.std->lvl.cipso[nla_get_u32(nla_c)] =
+ nla_get_u32(nla_b);
+ }
- num_cats = netlbl_getinc_u32(&msg, &msg_len);
- doi_def->map.std->cat.local_size = netlbl_getinc_u32(&msg, &msg_len);
- if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS)
- goto add_std_failure;
- doi_def->map.std->cat.local = kcalloc(doi_def->map.std->cat.local_size,
+ if (info->attrs[NLBL_CIPSOV4_A_MLSCATLST]) {
+ if (nla_validate(
+ nla_data(info->attrs[NLBL_CIPSOV4_A_MLSCATLST]),
+ nla_len(info->attrs[NLBL_CIPSOV4_A_MLSCATLST]),
+ NLBL_CIPSOV4_A_MAX,
+ netlbl_cipsov4_genl_policy) != 0)
+ goto add_std_failure;
+
+ nla_for_each_attr(nla_a,
+ nla_data(info->attrs[NLBL_CIPSOV4_A_MLSCATLST]),
+ nla_len(info->attrs[NLBL_CIPSOV4_A_MLSCATLST]),
+ nla_a_rem)
+ if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSCAT) {
+ nla_for_each_attr(nla_b,
+ nla_data(nla_a),
+ nla_len(nla_a),
+ nla_b_rem)
+ switch (nla_b->nla_type) {
+ case NLBL_CIPSOV4_A_MLSCATLOC:
+ if (nla_get_u32(nla_b) >=
+ doi_def->map.std->cat.local_size)
+ doi_def->map.std->cat.local_size =
+ nla_get_u32(nla_b) + 1;
+ break;
+ case NLBL_CIPSOV4_A_MLSCATREM:
+ if (nla_get_u32(nla_b) >=
+ doi_def->map.std->cat.cipso_size)
+ doi_def->map.std->cat.cipso_size =
+ nla_get_u32(nla_b) + 1;
+ break;
+ }
+ }
+ if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS ||
+ doi_def->map.std->cat.cipso_size > CIPSO_V4_MAX_REM_CATS)
+ goto add_std_failure;
+ doi_def->map.std->cat.local = kcalloc(
+ doi_def->map.std->cat.local_size,
sizeof(u32),
GFP_KERNEL);
- if (doi_def->map.std->cat.local == NULL) {
- ret_val = -ENOMEM;
- goto add_std_failure;
- }
- doi_def->map.std->cat.cipso_size = netlbl_getinc_u16(&msg, &msg_len);
- if (doi_def->map.std->cat.cipso_size > CIPSO_V4_MAX_REM_CATS)
- goto add_std_failure;
- doi_def->map.std->cat.cipso = kcalloc(doi_def->map.std->cat.cipso_size,
+ if (doi_def->map.std->cat.local == NULL) {
+ ret_val = -ENOMEM;
+ goto add_std_failure;
+ }
+ doi_def->map.std->cat.cipso = kcalloc(
+ doi_def->map.std->cat.cipso_size,
sizeof(u32),
GFP_KERNEL);
- if (doi_def->map.std->cat.cipso == NULL) {
- ret_val = -ENOMEM;
- goto add_std_failure;
- }
-
- if (msg_len <
- num_lvls * (NETLBL_LEN_U32 + NETLBL_LEN_U8) +
- num_cats * (NETLBL_LEN_U32 + NETLBL_LEN_U16))
- goto add_std_failure;
-
- for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++)
- doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL;
- for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++)
- doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL;
- for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++)
- doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT;
- for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++)
- doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT;
-
- for (iter = 0; iter < num_lvls; iter++) {
- tmp_val_a = netlbl_getinc_u32(&msg, &msg_len);
- tmp_val_b = netlbl_getinc_u8(&msg, &msg_len);
-
- if (tmp_val_a >= doi_def->map.std->lvl.local_size ||
- tmp_val_b >= doi_def->map.std->lvl.cipso_size)
+ if (doi_def->map.std->cat.cipso == NULL) {
+ ret_val = -ENOMEM;
goto add_std_failure;
-
- doi_def->map.std->lvl.cipso[tmp_val_b] = tmp_val_a;
- doi_def->map.std->lvl.local[tmp_val_a] = tmp_val_b;
+ }
+ nla_for_each_attr(nla_a,
+ nla_data(info->attrs[NLBL_CIPSOV4_A_MLSCATLST]),
+ nla_len(info->attrs[NLBL_CIPSOV4_A_MLSCATLST]),
+ nla_a_rem)
+ if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSCAT) {
+ nla_b = nla_find_nested(nla_a,
+ NLBL_CIPSOV4_A_MLSCATLOC);
+ nla_c = nla_find_nested(nla_a,
+ NLBL_CIPSOV4_A_MLSCATREM);
+ if (nla_b == NULL || nla_c == NULL)
+ goto add_std_failure;
+ doi_def->map.std->cat.local[
+ nla_get_u32(nla_b)] =
+ nla_get_u32(nla_c);
+ doi_def->map.std->cat.cipso[
+ nla_get_u32(nla_c)] =
+ nla_get_u32(nla_b);
+ }
}
- for (iter = 0; iter < num_cats; iter++) {
- tmp_val_a = netlbl_getinc_u32(&msg, &msg_len);
- tmp_val_b = netlbl_getinc_u16(&msg, &msg_len);
-
- if (tmp_val_a >= doi_def->map.std->cat.local_size ||
- tmp_val_b >= doi_def->map.std->cat.cipso_size)
- goto add_std_failure;
+ doi_def->doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
- doi_def->map.std->cat.cipso[tmp_val_b] = tmp_val_a;
- doi_def->map.std->cat.local[tmp_val_a] = tmp_val_b;
- }
-
- doi_def->doi = doi;
ret_val = cipso_v4_doi_add(doi_def);
if (ret_val != 0)
goto add_std_failure;
@@ -243,9 +312,7 @@ add_std_failure:
/**
* netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition
- * @doi: the DOI value
- * @msg: the ADD message data
- * @msg_size: the size of the ADD message buffer
+ * @info: the Generic NETLINK info block
*
* Description:
* Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message
@@ -253,20 +320,22 @@ add_std_failure:
* error.
*
*/
-static int netlbl_cipsov4_add_pass(u32 doi,
- struct nlattr *msg,
- size_t msg_size)
+static int netlbl_cipsov4_add_pass(struct genl_info *info)
{
int ret_val = -EINVAL;
- int msg_len = msg_size;
- u32 num_tags;
struct cipso_v4_doi *doi_def = NULL;
- u32 iter;
+ struct nlattr *nla;
+ int nla_rem;
+ u32 iter = 0;
- if (msg_len < NETLBL_LEN_U32)
+ if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
+ !info->attrs[NLBL_CIPSOV4_A_TAGLST])
goto add_pass_failure;
- num_tags = netlbl_getinc_u32(&msg, &msg_len);
- if (num_tags == 0 || num_tags > CIPSO_V4_TAG_MAXCNT)
+
+ if (nla_validate(nla_data(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
+ nla_len(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
+ NLBL_CIPSOV4_A_MAX,
+ netlbl_cipsov4_genl_policy) != 0)
goto add_pass_failure;
doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
@@ -276,21 +345,20 @@ static int netlbl_cipsov4_add_pass(u32 d
}
doi_def->type = CIPSO_V4_MAP_PASS;
- for (iter = 0; iter < num_tags; iter++) {
- if (msg_len < NETLBL_LEN_U8)
- goto add_pass_failure;
- doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len);
- switch (doi_def->tags[iter]) {
- case CIPSO_V4_TAG_RBITMAP:
- break;
- default:
- goto add_pass_failure;
+ nla_for_each_attr(nla,
+ nla_data(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
+ nla_len(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
+ nla_rem)
+ if (nla->nla_type == NLBL_CIPSOV4_A_TAG) {
+ if (iter > CIPSO_V4_TAG_MAXCNT)
+ goto add_pass_failure;
+ doi_def->tags[iter++] = nla_get_u8(nla);
}
- }
if (iter < CIPSO_V4_TAG_MAXCNT)
doi_def->tags[iter] = CIPSO_V4_TAG_INVALID;
- doi_def->doi = doi;
+ doi_def->doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
+
ret_val = cipso_v4_doi_add(doi_def);
if (ret_val != 0)
goto add_pass_failure;
@@ -316,34 +384,21 @@ static int netlbl_cipsov4_add(struct sk_
{
int ret_val = -EINVAL;
- u32 doi;
u32 map_type;
- int msg_len = netlbl_netlink_payload_len(skb);
- struct nlattr *msg = netlbl_netlink_payload_data(skb);
- ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
- if (ret_val != 0)
- goto add_return;
-
- if (msg_len < 2 * NETLBL_LEN_U32)
- goto add_return;
+ if (!info->attrs[NLBL_CIPSOV4_A_MTYPE])
+ return -EINVAL;
- doi = netlbl_getinc_u32(&msg, &msg_len);
- map_type = netlbl_getinc_u32(&msg, &msg_len);
+ map_type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]);
switch (map_type) {
case CIPSO_V4_MAP_STD:
- ret_val = netlbl_cipsov4_add_std(doi, msg, msg_len);
+ ret_val = netlbl_cipsov4_add_std(info);
break;
case CIPSO_V4_MAP_PASS:
- ret_val = netlbl_cipsov4_add_pass(doi, msg, msg_len);
+ ret_val = netlbl_cipsov4_add_pass(info);
break;
}
-add_return:
- netlbl_netlink_send_ack(info,
- netlbl_cipsov4_gnl_family.id,
- NLBL_CIPSOV4_C_ACK,
- -ret_val);
return ret_val;
}
@@ -353,84 +408,237 @@ add_return:
* @info: the Generic NETLINK info block
*
* Description:
- * Process a user generated LIST message and respond accordingly. Returns
- * zero on success and negative values on error.
+ * Process a user generated LIST message and respond accordingly. While the
+ * response message generated by the kernel is straightforward, determining
+ * before hand the size of the buffer to allocate is not (we have to generate
+ * the message to know the size). In order to keep this function sane what we
+ * do is allocate a buffer of NLMSG_GOODSIZE and try to fit the response in
+ * that size, if we fail then we restart with a larger buffer and try again.
+ * We continue in this manner until we hit a limit of failed attempts then we
+ * give up and just send an error message. Returns zero on success and
+ * negative values on error.
*
*/
static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info)
{
- int ret_val = -EINVAL;
+ int ret_val;
+ struct sk_buff *ans_skb = NULL;
+ u32 nlsze_mult = 1;
+ void *data;
u32 doi;
- struct nlattr *msg = netlbl_netlink_payload_data(skb);
- struct sk_buff *ans_skb;
+ struct nlattr *nla_a;
+ struct nlattr *nla_b;
+ struct cipso_v4_doi *doi_def;
+ u32 iter;
- if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32)
+ if (!info->attrs[NLBL_CIPSOV4_A_DOI]) {
+ ret_val = -EINVAL;
goto list_failure;
+ }
- doi = nla_get_u32(msg);
- ans_skb = cipso_v4_doi_dump(doi, NLMSG_SPACE(GENL_HDRLEN));
+list_start:
+ ans_skb = nlmsg_new(NLMSG_GOODSIZE * nlsze_mult, GFP_KERNEL);
if (ans_skb == NULL) {
ret_val = -ENOMEM;
goto list_failure;
}
- netlbl_netlink_hdr_push(ans_skb,
- info->snd_pid,
- 0,
- netlbl_cipsov4_gnl_family.id,
- NLBL_CIPSOV4_C_LIST);
+ data = netlbl_netlink_hdr_put(ans_skb,
+ info->snd_pid,
+ info->snd_seq,
+ netlbl_cipsov4_gnl_family.id,
+ 0,
+ NLBL_CIPSOV4_C_LIST);
+ if (data == NULL) {
+ ret_val = -ENOMEM;
+ goto list_failure;
+ }
+
+ doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
+
+ rcu_read_lock();
+ doi_def = cipso_v4_doi_getdef(doi);
+ if (doi_def == NULL) {
+ ret_val = -EINVAL;
+ goto list_failure;
+ }
+
+ ret_val = nla_put_u32(ans_skb, NLBL_CIPSOV4_A_MTYPE, doi_def->type);
+ if (ret_val != 0)
+ goto list_failure_lock;
+
+ nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_TAGLST);
+ if (nla_a == NULL) {
+ ret_val = -ENOMEM;
+ goto list_failure_lock;
+ }
+ for (iter = 0;
+ iter < CIPSO_V4_TAG_MAXCNT &&
+ doi_def->tags[iter] != CIPSO_V4_TAG_INVALID;
+ iter++) {
+ ret_val = nla_put_u8(ans_skb,
+ NLBL_CIPSOV4_A_TAG,
+ doi_def->tags[iter]);
+ if (ret_val != 0)
+ goto list_failure_lock;
+ }
+ nla_nest_end(ans_skb, nla_a);
- ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
+ switch (doi_def->type) {
+ case CIPSO_V4_MAP_STD:
+ nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVLLST);
+ if (nla_a == NULL) {
+ ret_val = -ENOMEM;
+ goto list_failure_lock;
+ }
+ for (iter = 0;
+ iter < doi_def->map.std->lvl.local_size;
+ iter++) {
+ if (doi_def->map.std->lvl.local[iter] ==
+ CIPSO_V4_INV_LVL)
+ continue;
+
+ nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVL);
+ if (nla_b == NULL) {
+ ret_val = -ENOMEM;
+ goto list_retry;
+ }
+ ret_val = nla_put_u32(ans_skb,
+ NLBL_CIPSOV4_A_MLSLVLLOC,
+ iter);
+ if (ret_val != 0)
+ goto list_retry;
+ ret_val = nla_put_u32(ans_skb,
+ NLBL_CIPSOV4_A_MLSLVLREM,
+ doi_def->map.std->lvl.local[iter]);
+ if (ret_val != 0)
+ goto list_retry;
+ nla_nest_end(ans_skb, nla_b);
+ }
+ nla_nest_end(ans_skb, nla_a);
+
+ nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCATLST);
+ if (nla_a == NULL) {
+ ret_val = -ENOMEM;
+ goto list_retry;
+ }
+ for (iter = 0;
+ iter < doi_def->map.std->cat.local_size;
+ iter++) {
+ if (doi_def->map.std->cat.local[iter] ==
+ CIPSO_V4_INV_CAT)
+ continue;
+
+ nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCAT);
+ if (nla_b == NULL) {
+ ret_val = -ENOMEM;
+ goto list_retry;
+ }
+ ret_val = nla_put_u32(ans_skb,
+ NLBL_CIPSOV4_A_MLSCATLOC,
+ iter);
+ if (ret_val != 0)
+ goto list_retry;
+ ret_val = nla_put_u32(ans_skb,
+ NLBL_CIPSOV4_A_MLSCATREM,
+ doi_def->map.std->cat.local[iter]);
+ if (ret_val != 0)
+ goto list_retry;
+ nla_nest_end(ans_skb, nla_b);
+ }
+ nla_nest_end(ans_skb, nla_a);
+
+ break;
+ }
+ rcu_read_unlock();
+
+ ret_val = netlbl_netlink_snd(ans_skb, data, info->snd_pid);
if (ret_val != 0)
goto list_failure;
return 0;
+list_retry:
+ /* XXX - this limit is a guesstimate */
+ if (nlsze_mult < 4) {
+ rcu_read_unlock();
+ kfree_skb(ans_skb);
+ nlsze_mult++;
+ goto list_start;
+ }
+list_failure_lock:
+ rcu_read_unlock();
list_failure:
- netlbl_netlink_send_ack(info,
- netlbl_cipsov4_gnl_family.id,
- NLBL_CIPSOV4_C_ACK,
- -ret_val);
+ kfree_skb(ans_skb);
+ return ret_val;
+}
+
+/**
+ * netlbl_cipsov4_listall_cb - cipso_v4_doi_walk() callback for LISTALL
+ * @doi_def: the CIPSOv4 DOI definition
+ * @arg: the netlbl_cipsov4_doiwalk_arg structure
+ *
+ * Description:
+ * This function is designed to be used as a callback to the
+ * cipso_v4_doi_walk() function for use in generating a response for a LISTALL
+ * message. Returns the size of the message on success, negative values on
+ * failure.
+ *
+ */
+static int netlbl_cipsov4_listall_cb(struct cipso_v4_doi *doi_def, void *arg)
+{
+ int ret_val = -ENOMEM;
+ struct netlbl_cipsov4_doiwalk_arg *cb_arg = arg;
+ void *data;
+
+ data = netlbl_netlink_hdr_put(cb_arg->skb,
+ NETLINK_CB(cb_arg->nl_cb->skb).pid,
+ cb_arg->seq,
+ netlbl_cipsov4_gnl_family.id,
+ NLM_F_MULTI,
+ NLBL_CIPSOV4_C_LISTALL);
+ if (data == NULL)
+ goto listall_cb_failure;
+
+ ret_val = nla_put_u32(cb_arg->skb, NLBL_CIPSOV4_A_DOI, doi_def->doi);
+ if (ret_val != 0)
+ goto listall_cb_failure;
+ ret_val = nla_put_u32(cb_arg->skb,
+ NLBL_CIPSOV4_A_MTYPE,
+ doi_def->type);
+ if (ret_val != 0)
+ goto listall_cb_failure;
+
+ return genlmsg_end(cb_arg->skb, data);
+
+listall_cb_failure:
+ genlmsg_cancel(cb_arg->skb, data);
return ret_val;
}
/**
* netlbl_cipsov4_listall - Handle a LISTALL message
* @skb: the NETLINK buffer
- * @info: the Generic NETLINK info block
+ * @cb: the NETLINK callback
*
* Description:
* Process a user generated LISTALL message and respond accordingly. Returns
* zero on success and negative values on error.
*
*/
-static int netlbl_cipsov4_listall(struct sk_buff *skb, struct genl_info *info)
+static int netlbl_cipsov4_listall(struct sk_buff *skb,
+ struct netlink_callback *cb)
{
- int ret_val = -EINVAL;
- struct sk_buff *ans_skb;
+ struct netlbl_cipsov4_doiwalk_arg cb_arg;
+ int doi_skip = cb->args[0];
- ans_skb = cipso_v4_doi_dump_all(NLMSG_SPACE(GENL_HDRLEN));
- if (ans_skb == NULL) {
- ret_val = -ENOMEM;
- goto listall_failure;
- }
- netlbl_netlink_hdr_push(ans_skb,
- info->snd_pid,
- 0,
- netlbl_cipsov4_gnl_family.id,
- NLBL_CIPSOV4_C_LISTALL);
+ cb_arg.nl_cb = cb;
+ cb_arg.skb = skb;
+ cb_arg.seq = cb->nlh->nlmsg_seq;
- ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
- if (ret_val != 0)
- goto listall_failure;
-
- return 0;
+ cipso_v4_doi_walk(&doi_skip, netlbl_cipsov4_listall_cb, &cb_arg);
-listall_failure:
- netlbl_netlink_send_ack(info,
- netlbl_cipsov4_gnl_family.id,
- NLBL_CIPSOV4_C_ACK,
- -ret_val);
- return ret_val;
+ cb->args[0] = doi_skip;
+ return skb->len;
}
/**
@@ -445,27 +653,14 @@ listall_failure:
*/
static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
{
- int ret_val;
+ int ret_val = -EINVAL;
u32 doi;
- struct nlattr *msg = netlbl_netlink_payload_data(skb);
- ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
- if (ret_val != 0)
- goto remove_return;
-
- if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32) {
- ret_val = -EINVAL;
- goto remove_return;
+ if (info->attrs[NLBL_CIPSOV4_A_DOI]) {
+ doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
+ ret_val = cipso_v4_doi_remove(doi, netlbl_cipsov4_doi_free);
}
- doi = nla_get_u32(msg);
- ret_val = cipso_v4_doi_remove(doi, netlbl_cipsov4_doi_free);
-
-remove_return:
- netlbl_netlink_send_ack(info,
- netlbl_cipsov4_gnl_family.id,
- NLBL_CIPSOV4_C_ACK,
- -ret_val);
return ret_val;
}
@@ -475,14 +670,16 @@ remove_return:
static struct genl_ops netlbl_cipsov4_genl_c_add = {
.cmd = NLBL_CIPSOV4_C_ADD,
- .flags = 0,
+ .flags = GENL_ADMIN_PERM,
+ .policy = netlbl_cipsov4_genl_policy,
.doit = netlbl_cipsov4_add,
.dumpit = NULL,
};
static struct genl_ops netlbl_cipsov4_genl_c_remove = {
.cmd = NLBL_CIPSOV4_C_REMOVE,
- .flags = 0,
+ .flags = GENL_ADMIN_PERM,
+ .policy = netlbl_cipsov4_genl_policy,
.doit = netlbl_cipsov4_remove,
.dumpit = NULL,
};
@@ -490,6 +687,7 @@ static struct genl_ops netlbl_cipsov4_ge
static struct genl_ops netlbl_cipsov4_genl_c_list = {
.cmd = NLBL_CIPSOV4_C_LIST,
.flags = 0,
+ .policy = netlbl_cipsov4_genl_policy,
.doit = netlbl_cipsov4_list,
.dumpit = NULL,
};
@@ -497,8 +695,9 @@ static struct genl_ops netlbl_cipsov4_ge
static struct genl_ops netlbl_cipsov4_genl_c_listall = {
.cmd = NLBL_CIPSOV4_C_LISTALL,
.flags = 0,
- .doit = netlbl_cipsov4_listall,
- .dumpit = NULL,
+ .policy = netlbl_cipsov4_genl_policy,
+ .doit = NULL,
+ .dumpit = netlbl_cipsov4_listall,
};
/*
Index: net-2.6.19/net/netlabel/netlabel_cipso_v4.h
===================================================================
--- net-2.6.19.orig/net/netlabel/netlabel_cipso_v4.h
+++ net-2.6.19/net/netlabel/netlabel_cipso_v4.h
@@ -34,175 +34,71 @@
#include <net/netlabel.h>
/*
- * The following NetLabel payloads are supported by the CIPSO subsystem, all
- * of which are preceeded by the nlmsghdr struct.
- *
- * o ACK:
- * Sent by the kernel in response to an applications message, applications
- * should never send this message.
- *
- * +----------------------+-----------------------+
- * | seq number (32 bits) | return code (32 bits) |
- * +----------------------+-----------------------+
- *
- * seq number: the sequence number of the original message, taken from the
- * nlmsghdr structure
- * return code: return value, based on errno values
+ * The following NetLabel payloads are supported by the CIPSO subsystem.
*
* o ADD:
- * Sent by an application to add a new DOI mapping table, after completion
- * of the task the kernel should ACK this message.
+ * Sent by an application to add a new DOI mapping table.
+ *
+ * Required attributes:
+ *
+ * NLBL_CIPSOV4_A_DOI
+ * NLBL_CIPSOV4_A_MTYPE
+ * NLBL_CIPSOV4_A_TAGLST
*
- * +---------------+--------------------+---------------------+
- * | DOI (32 bits) | map type (32 bits) | tag count (32 bits) | ...
- * +---------------+--------------------+---------------------+
- *
- * +-----------------+
- * | tag #X (8 bits) | ... repeated
- * +-----------------+
- *
- * +-------------- ---- --- -- -
- * | mapping data
- * +-------------- ---- --- -- -
- *
- * DOI: the DOI value
- * map type: the mapping table type (defined in the cipso_ipv4.h header
- * as CIPSO_V4_MAP_*)
- * tag count: the number of tags, must be greater than zero
- * tag: the CIPSO tag for the DOI, tags listed first are given
- * higher priorirty when sending packets
- * mapping data: specific to the map type (see below)
- *
- * CIPSO_V4_MAP_STD
- *
- * +------------------+-----------------------+----------------------+
- * | levels (32 bits) | max l level (32 bits) | max r level (8 bits) | ...
- * +------------------+-----------------------+----------------------+
- *
- * +----------------------+---------------------+---------------------+
- * | categories (32 bits) | max l cat (32 bits) | max r cat (16 bits) | ...
- * +----------------------+---------------------+---------------------+
- *
- * +--------------------------+-------------------------+
- * | local level #X (32 bits) | CIPSO level #X (8 bits) | ... repeated
- * +--------------------------+-------------------------+
- *
- * +-----------------------------+-----------------------------+
- * | local category #X (32 bits) | CIPSO category #X (16 bits) | ... repeated
- * +-----------------------------+-----------------------------+
- *
- * levels: the number of level mappings
- * max l level: the highest local level
- * max r level: the highest remote/CIPSO level
- * categories: the number of category mappings
- * max l cat: the highest local category
- * max r cat: the highest remote/CIPSO category
- * local level: the local part of a level mapping
- * CIPSO level: the remote/CIPSO part of a level mapping
- * local category: the local part of a category mapping
- * CIPSO category: the remote/CIPSO part of a category mapping
+ * If using CIPSO_V4_MAP_STD the following attributes are required:
*
- * CIPSO_V4_MAP_PASS
+ * NLBL_CIPSOV4_A_MLSLVLLST
+ * NLBL_CIPSOV4_A_MLSCATLST
*
- * No mapping data is needed for this map type.
+ * If using CIPSO_V4_MAP_PASS no additional attributes are required.
*
* o REMOVE:
* Sent by an application to remove a specific DOI mapping table from the
- * CIPSO V4 system. The kernel should ACK this message.
+ * CIPSO V4 system.
*
- * +---------------+
- * | DOI (32 bits) |
- * +---------------+
+ * Required attributes:
*
- * DOI: the DOI value
+ * NLBL_CIPSOV4_A_DOI
*
* o LIST:
- * Sent by an application to list the details of a DOI definition. The
- * kernel should send an ACK on error or a response as indicated below. The
- * application generated message format is shown below.
- *
- * +---------------+
- * | DOI (32 bits) |
- * +---------------+
+ * Sent by an application to list the details of a DOI definition. On
+ * success the kernel should send a response using the following format.
*
- * DOI: the DOI value
+ * Required attributes:
+ *
+ * NLBL_CIPSOV4_A_DOI
*
* The valid response message format depends on the type of the DOI mapping,
- * the known formats are shown below.
+ * the defined formats are shown below.
+ *
+ * Required attributes:
+ *
+ * NLBL_CIPSOV4_A_MTYPE
+ * NLBL_CIPSOV4_A_TAGLST
*
- * +--------------------+
- * | map type (32 bits) | ...
- * +--------------------+
- *
- * map type: the DOI mapping table type (defined in the cipso_ipv4.h
- * header as CIPSO_V4_MAP_*)
- *
- * (map type == CIPSO_V4_MAP_STD)
- *
- * +----------------+------------------+----------------------+
- * | tags (32 bits) | levels (32 bits) | categories (32 bits) | ...
- * +----------------+------------------+----------------------+
- *
- * +-----------------+
- * | tag #X (8 bits) | ... repeated
- * +-----------------+
- *
- * +--------------------------+-------------------------+
- * | local level #X (32 bits) | CIPSO level #X (8 bits) | ... repeated
- * +--------------------------+-------------------------+
- *
- * +-----------------------------+-----------------------------+
- * | local category #X (32 bits) | CIPSO category #X (16 bits) | ... repeated
- * +-----------------------------+-----------------------------+
- *
- * tags: the number of CIPSO tag types
- * levels: the number of level mappings
- * categories: the number of category mappings
- * tag: the tag number, tags listed first are given higher
- * priority when sending packets
- * local level: the local part of a level mapping
- * CIPSO level: the remote/CIPSO part of a level mapping
- * local category: the local part of a category mapping
- * CIPSO category: the remote/CIPSO part of a category mapping
- *
- * (map type == CIPSO_V4_MAP_PASS)
- *
- * +----------------+
- * | tags (32 bits) | ...
- * +----------------+
- *
- * +-----------------+
- * | tag #X (8 bits) | ... repeated
- * +-----------------+
- *
- * tags: the number of CIPSO tag types
- * tag: the tag number, tags listed first are given higher
- * priority when sending packets
+ * If using CIPSO_V4_MAP_STD the following attributes are required:
+ *
+ * NLBL_CIPSOV4_A_MLSLVLLST
+ * NLBL_CIPSOV4_A_MLSCATLST
+ *
+ * If using CIPSO_V4_MAP_PASS no additional attributes are required.
*
* o LISTALL:
* This message is sent by an application to list the valid DOIs on the
- * system. There is no payload and the kernel should respond with an ACK
- * or the following message.
+ * system. When sent by an application there is no payload and the
+ * NLM_F_DUMP flag should be set. The kernel should respond with a series of
+ * the following messages.
+ *
+ * Required attributes:
*
- * +---------------------+------------------+-----------------------+
- * | DOI count (32 bits) | DOI #X (32 bits) | map type #X (32 bits) |
- * +---------------------+------------------+-----------------------+
- *
- * +-----------------------+
- * | map type #X (32 bits) | ...
- * +-----------------------+
- *
- * DOI count: the number of DOIs
- * DOI: the DOI value
- * map type: the DOI mapping table type (defined in the cipso_ipv4.h
- * header as CIPSO_V4_MAP_*)
+ * NLBL_CIPSOV4_A_DOI
+ * NLBL_CIPSOV4_A_MTYPE
*
*/
/* NetLabel CIPSOv4 commands */
enum {
NLBL_CIPSOV4_C_UNSPEC,
- NLBL_CIPSOV4_C_ACK,
NLBL_CIPSOV4_C_ADD,
NLBL_CIPSOV4_C_REMOVE,
NLBL_CIPSOV4_C_LIST,
@@ -211,6 +107,59 @@ enum {
};
#define NLBL_CIPSOV4_C_MAX (__NLBL_CIPSOV4_C_MAX - 1)
+/* NetLabel CIPSOv4 attributes */
+enum {
+ NLBL_CIPSOV4_A_UNSPEC,
+ NLBL_CIPSOV4_A_DOI,
+ /* (NLA_U32)
+ * the DOI value */
+ NLBL_CIPSOV4_A_MTYPE,
+ /* (NLA_U32)
+ * the mapping table type (defined in the cipso_ipv4.h header as
+ * CIPSO_V4_MAP_*) */
+ NLBL_CIPSOV4_A_TAG,
+ /* (NLA_U8)
+ * a CIPSO tag type, meant to be used within a NLBL_CIPSOV4_A_TAGLST
+ * attribute */
+ NLBL_CIPSOV4_A_TAGLST,
+ /* (NLA_NESTED)
+ * the CIPSO tag list for the DOI, there must be at least one
+ * NLBL_CIPSOV4_A_TAG attribute, tags listed first are given higher
+ * priorirty when sending packets */
+ NLBL_CIPSOV4_A_MLSLVLLOC,
+ /* (NLA_U32)
+ * the local MLS sensitivity level */
+ NLBL_CIPSOV4_A_MLSLVLREM,
+ /* (NLA_U32)
+ * the remote MLS sensitivity level */
+ NLBL_CIPSOV4_A_MLSLVL,
+ /* (NLA_NESTED)
+ * a MLS sensitivity level mapping, must contain only one attribute of
+ * each of the following types: NLBL_CIPSOV4_A_MLSLVLLOC and
+ * NLBL_CIPSOV4_A_MLSLVLREM */
+ NLBL_CIPSOV4_A_MLSLVLLST,
+ /* (NLA_NESTED)
+ * the CIPSO level mappings, there must be at least one
+ * NLBL_CIPSOV4_A_MLSLVL attribute */
+ NLBL_CIPSOV4_A_MLSCATLOC,
+ /* (NLA_U32)
+ * the local MLS category */
+ NLBL_CIPSOV4_A_MLSCATREM,
+ /* (NLA_U32)
+ * the remote MLS category */
+ NLBL_CIPSOV4_A_MLSCAT,
+ /* (NLA_NESTED)
+ * a MLS category mapping, must contain only one attribute of each of
+ * the following types: NLBL_CIPSOV4_A_MLSCATLOC and
+ * NLBL_CIPSOV4_A_MLSCATREM */
+ NLBL_CIPSOV4_A_MLSCATLST,
+ /* (NLA_NESTED)
+ * the CIPSO category mappings, there must be at least one
+ * NLBL_CIPSOV4_A_MLSCAT attribute */
+ __NLBL_CIPSOV4_A_MAX,
+};
+#define NLBL_CIPSOV4_A_MAX (__NLBL_CIPSOV4_A_MAX - 1)
+
/* NetLabel protocol functions */
int netlbl_cipsov4_genl_init(void);
Index: net-2.6.19/net/netlabel/netlabel_mgmt.c
===================================================================
--- net-2.6.19.orig/net/netlabel/netlabel_mgmt.c
+++ net-2.6.19/net/netlabel/netlabel_mgmt.c
@@ -42,15 +42,29 @@
#include "netlabel_user.h"
#include "netlabel_mgmt.h"
+/* Argument struct for netlbl_domhsh_walk() */
+struct netlbl_domhsh_walk_arg {
+ struct netlink_callback *nl_cb;
+ struct sk_buff *skb;
+ u32 seq;
+};
+
/* NetLabel Generic NETLINK CIPSOv4 family */
static struct genl_family netlbl_mgmt_gnl_family = {
.id = GENL_ID_GENERATE,
.hdrsize = 0,
.name = NETLBL_NLTYPE_MGMT_NAME,
.version = NETLBL_PROTO_VERSION,
- .maxattr = 0,
+ .maxattr = NLBL_MGMT_A_MAX,
};
+/* NetLabel Netlink attribute policy */
+static struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
+ [NLBL_MGMT_A_DOMAIN] = { .type = NLA_NUL_STRING },
+ [NLBL_MGMT_A_PROTOCOL] = { .type = NLA_U32 },
+ [NLBL_MGMT_A_VERSION] = { .type = NLA_U32 },
+ [NLBL_MGMT_A_CV4DOI] = { .type = NLA_U32 },
+};
/*
* NetLabel Command Handlers
@@ -70,97 +84,62 @@ static struct genl_family netlbl_mgmt_gn
static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info)
{
int ret_val = -EINVAL;
- struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb);
- int msg_len = netlbl_netlink_payload_len(skb);
- u32 count;
struct netlbl_dom_map *entry = NULL;
- u32 iter;
+ size_t tmp_size;
u32 tmp_val;
- int tmp_size;
- ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
- if (ret_val != 0)
+ if (!info->attrs[NLBL_MGMT_A_DOMAIN] ||
+ !info->attrs[NLBL_MGMT_A_PROTOCOL])
goto add_failure;
- if (msg_len < NETLBL_LEN_U32)
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (entry == NULL) {
+ ret_val = -ENOMEM;
goto add_failure;
- count = netlbl_getinc_u32(&msg_ptr, &msg_len);
+ }
+ tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]);
+ entry->domain = kmalloc(tmp_size, GFP_KERNEL);
+ if (entry->domain == NULL) {
+ ret_val = -ENOMEM;
+ goto add_failure;
+ }
+ entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]);
+ nla_strlcpy(entry->domain, info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size);
- for (iter = 0; iter < count && msg_len > 0; iter++, entry = NULL) {
- if (msg_len <= 0) {
- ret_val = -EINVAL;
- goto add_failure;
- }
- entry = kzalloc(sizeof(*entry), GFP_KERNEL);
- if (entry == NULL) {
- ret_val = -ENOMEM;
- goto add_failure;
- }
- tmp_size = nla_len(msg_ptr);
- if (tmp_size <= 0 || tmp_size > msg_len) {
- ret_val = -EINVAL;
- goto add_failure;
- }
- entry->domain = kmalloc(tmp_size, GFP_KERNEL);
- if (entry->domain == NULL) {
- ret_val = -ENOMEM;
+ switch (entry->type) {
+ case NETLBL_NLTYPE_UNLABELED:
+ ret_val = netlbl_domhsh_add(entry);
+ break;
+ case NETLBL_NLTYPE_CIPSOV4:
+ if (!info->attrs[NLBL_MGMT_A_CV4DOI])
goto add_failure;
- }
- nla_strlcpy(entry->domain, msg_ptr, tmp_size);
- entry->domain[tmp_size - 1] = '\0';
- msg_ptr = nla_next(msg_ptr, &msg_len);
- if (msg_len < NETLBL_LEN_U32) {
- ret_val = -EINVAL;
- goto add_failure;
- }
- tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len);
- entry->type = tmp_val;
- switch (tmp_val) {
- case NETLBL_NLTYPE_UNLABELED:
- ret_val = netlbl_domhsh_add(entry);
- break;
- case NETLBL_NLTYPE_CIPSOV4:
- if (msg_len < NETLBL_LEN_U32) {
- ret_val = -EINVAL;
- goto add_failure;
- }
- tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len);
- /* We should be holding a rcu_read_lock() here
- * while we hold the result but since the entry
- * will always be deleted when the CIPSO DOI
- * is deleted we aren't going to keep the lock. */
- rcu_read_lock();
- entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val);
- if (entry->type_def.cipsov4 == NULL) {
- rcu_read_unlock();
- ret_val = -EINVAL;
- goto add_failure;
- }
- ret_val = netlbl_domhsh_add(entry);
+ tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]);
+ /* We should be holding a rcu_read_lock() here while we hold
+ * the result but since the entry will always be deleted when
+ * the CIPSO DOI is deleted we aren't going to keep the
+ * lock. */
+ rcu_read_lock();
+ entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val);
+ if (entry->type_def.cipsov4 == NULL) {
rcu_read_unlock();
- break;
- default:
- ret_val = -EINVAL;
- }
- if (ret_val != 0)
goto add_failure;
+ }
+ ret_val = netlbl_domhsh_add(entry);
+ rcu_read_unlock();
+ break;
+ default:
+ goto add_failure;
}
+ if (ret_val != 0)
+ goto add_failure;
- netlbl_netlink_send_ack(info,
- netlbl_mgmt_gnl_family.id,
- NLBL_MGMT_C_ACK,
- NETLBL_E_OK);
return 0;
add_failure:
if (entry)
kfree(entry->domain);
kfree(entry);
- netlbl_netlink_send_ack(info,
- netlbl_mgmt_gnl_family.id,
- NLBL_MGMT_C_ACK,
- -ret_val);
return ret_val;
}
@@ -176,90 +155,101 @@ add_failure:
*/
static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info)
{
- int ret_val = -EINVAL;
- struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb);
- int msg_len = netlbl_netlink_payload_len(skb);
- u32 count;
- u32 iter;
- int tmp_size;
- unsigned char *domain;
-
- ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
- if (ret_val != 0)
- goto remove_return;
-
- if (msg_len < NETLBL_LEN_U32)
- goto remove_return;
- count = netlbl_getinc_u32(&msg_ptr, &msg_len);
-
- for (iter = 0; iter < count && msg_len > 0; iter++) {
- if (msg_len <= 0) {
- ret_val = -EINVAL;
- goto remove_return;
- }
- tmp_size = nla_len(msg_ptr);
- domain = nla_data(msg_ptr);
- if (tmp_size <= 0 || tmp_size > msg_len ||
- domain[tmp_size - 1] != '\0') {
- ret_val = -EINVAL;
- goto remove_return;
- }
- ret_val = netlbl_domhsh_remove(domain);
- if (ret_val != 0)
- goto remove_return;
- msg_ptr = nla_next(msg_ptr, &msg_len);
- }
+ char *domain;
- ret_val = 0;
+ if (!info->attrs[NLBL_MGMT_A_DOMAIN])
+ return -EINVAL;
-remove_return:
- netlbl_netlink_send_ack(info,
- netlbl_mgmt_gnl_family.id,
- NLBL_MGMT_C_ACK,
- -ret_val);
- return ret_val;
+ domain = nla_data(info->attrs[NLBL_MGMT_A_DOMAIN]);
+ return netlbl_domhsh_remove(domain);
}
/**
- * netlbl_mgmt_list - Handle a LIST message
- * @skb: the NETLINK buffer
- * @info: the Generic NETLINK info block
+ * netlbl_mgmt_listall_cb - netlbl_domhsh_walk() callback for LISTALL
+ * @entry: the domain mapping hash table entry
+ * @arg: the netlbl_domhsh_walk_arg structure
*
* Description:
- * Process a user generated LIST message and dumps the domain hash table in a
- * form suitable for use in a kernel generated LIST message. Returns zero on
- * success, negative values on failure.
+ * This function is designed to be used as a callback to the
+ * netlbl_domhsh_walk() function for use in generating a response for a LISTALL
+ * message. Returns the size of the message on success, negative values on
+ * failure.
*
*/
-static int netlbl_mgmt_list(struct sk_buff *skb, struct genl_info *info)
+static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg)
{
int ret_val = -ENOMEM;
- struct sk_buff *ans_skb;
+ struct netlbl_domhsh_walk_arg *cb_arg = arg;
+ void *data;
- ans_skb = netlbl_domhsh_dump(NLMSG_SPACE(GENL_HDRLEN));
- if (ans_skb == NULL)
- goto list_failure;
- netlbl_netlink_hdr_push(ans_skb,
- info->snd_pid,
- 0,
- netlbl_mgmt_gnl_family.id,
- NLBL_MGMT_C_LIST);
-
- ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
+ data = netlbl_netlink_hdr_put(cb_arg->skb,
+ NETLINK_CB(cb_arg->nl_cb->skb).pid,
+ cb_arg->seq,
+ netlbl_mgmt_gnl_family.id,
+ NLM_F_MULTI,
+ NLBL_MGMT_C_LISTALL);
+ if (data == NULL)
+ goto listall_cb_failure;
+
+ ret_val = nla_put_string(cb_arg->skb,
+ NLBL_MGMT_A_DOMAIN,
+ entry->domain);
+ if (ret_val != 0)
+ goto listall_cb_failure;
+ ret_val = nla_put_u32(cb_arg->skb, NLBL_MGMT_A_PROTOCOL, entry->type);
if (ret_val != 0)
- goto list_failure;
+ goto listall_cb_failure;
+ switch (entry->type) {
+ case NETLBL_NLTYPE_CIPSOV4:
+ ret_val = nla_put_u32(cb_arg->skb,
+ NLBL_MGMT_A_CV4DOI,
+ entry->type_def.cipsov4->doi);
+ if (ret_val != 0)
+ goto listall_cb_failure;
+ break;
+ }
- return 0;
+ cb_arg->seq++;
+ return genlmsg_end(cb_arg->skb, data);
-list_failure:
- netlbl_netlink_send_ack(info,
- netlbl_mgmt_gnl_family.id,
- NLBL_MGMT_C_ACK,
- -ret_val);
+listall_cb_failure:
+ genlmsg_cancel(cb_arg->skb, data);
return ret_val;
}
/**
+ * netlbl_mgmt_listall - Handle a LISTALL message
+ * @skb: the NETLINK buffer
+ * @cb: the NETLINK callback
+ *
+ * Description:
+ * Process a user generated LISTALL message and dumps the domain hash table in
+ * a form suitable for use in a kernel generated LISTALL message. Returns zero
+ * on success, negative values on failure.
+ *
+ */
+static int netlbl_mgmt_listall(struct sk_buff *skb,
+ struct netlink_callback *cb)
+{
+ struct netlbl_domhsh_walk_arg cb_arg;
+ u32 skip_bkt = cb->args[0];
+ u32 skip_chain = cb->args[1];
+
+ cb_arg.nl_cb = cb;
+ cb_arg.skb = skb;
+ cb_arg.seq = cb->nlh->nlmsg_seq;
+
+ netlbl_domhsh_walk(&skip_bkt,
+ &skip_chain,
+ netlbl_mgmt_listall_cb,
+ &cb_arg);
+
+ cb->args[0] = skip_bkt;
+ cb->args[1] = skip_chain;
+ return skb->len;
+}
+
+/**
* netlbl_mgmt_adddef - Handle an ADDDEF message
* @skb: the NETLINK buffer
* @info: the Generic NETLINK info block
@@ -272,68 +262,51 @@ list_failure:
static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info)
{
int ret_val = -EINVAL;
- struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb);
- int msg_len = netlbl_netlink_payload_len(skb);
struct netlbl_dom_map *entry = NULL;
u32 tmp_val;
- ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
- if (ret_val != 0)
- goto adddef_failure;
-
- if (msg_len < NETLBL_LEN_U32)
+ if (!info->attrs[NLBL_MGMT_A_PROTOCOL])
goto adddef_failure;
- tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len);
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (entry == NULL) {
ret_val = -ENOMEM;
goto adddef_failure;
}
+ entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]);
- entry->type = tmp_val;
switch (entry->type) {
case NETLBL_NLTYPE_UNLABELED:
ret_val = netlbl_domhsh_add_default(entry);
break;
case NETLBL_NLTYPE_CIPSOV4:
- if (msg_len < NETLBL_LEN_U32) {
- ret_val = -EINVAL;
+ if (!info->attrs[NLBL_MGMT_A_CV4DOI])
goto adddef_failure;
- }
- tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len);
- /* We should be holding a rcu_read_lock here while we
- * hold the result but since the entry will always be
- * deleted when the CIPSO DOI is deleted we are going
- * to skip the lock. */
+
+ tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]);
+ /* We should be holding a rcu_read_lock() here while we hold
+ * the result but since the entry will always be deleted when
+ * the CIPSO DOI is deleted we aren't going to keep the
+ * lock. */
rcu_read_lock();
entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val);
if (entry->type_def.cipsov4 == NULL) {
rcu_read_unlock();
- ret_val = -EINVAL;
goto adddef_failure;
}
ret_val = netlbl_domhsh_add_default(entry);
rcu_read_unlock();
break;
default:
- ret_val = -EINVAL;
+ goto adddef_failure;
}
if (ret_val != 0)
goto adddef_failure;
- netlbl_netlink_send_ack(info,
- netlbl_mgmt_gnl_family.id,
- NLBL_MGMT_C_ACK,
- NETLBL_E_OK);
return 0;
adddef_failure:
kfree(entry);
- netlbl_netlink_send_ack(info,
- netlbl_mgmt_gnl_family.id,
- NLBL_MGMT_C_ACK,
- -ret_val);
return ret_val;
}
@@ -349,20 +322,7 @@ adddef_failure:
*/
static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info)
{
- int ret_val;
-
- ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
- if (ret_val != 0)
- goto removedef_return;
-
- ret_val = netlbl_domhsh_remove_default();
-
-removedef_return:
- netlbl_netlink_send_ack(info,
- netlbl_mgmt_gnl_family.id,
- NLBL_MGMT_C_ACK,
- -ret_val);
- return ret_val;
+ return netlbl_domhsh_remove_default();
}
/**
@@ -379,85 +339,126 @@ removedef_return:
static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info)
{
int ret_val = -ENOMEM;
- struct sk_buff *ans_skb;
+ struct sk_buff *ans_skb = NULL;
+ void *data;
+ struct netlbl_dom_map *entry;
- ans_skb = netlbl_domhsh_dump_default(NLMSG_SPACE(GENL_HDRLEN));
+ ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
if (ans_skb == NULL)
+ return -ENOMEM;
+ data = netlbl_netlink_hdr_put(ans_skb,
+ info->snd_pid,
+ info->snd_seq,
+ netlbl_mgmt_gnl_family.id,
+ 0,
+ NLBL_MGMT_C_LISTDEF);
+ if (data == NULL)
goto listdef_failure;
- netlbl_netlink_hdr_push(ans_skb,
- info->snd_pid,
- 0,
- netlbl_mgmt_gnl_family.id,
- NLBL_MGMT_C_LISTDEF);
- ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
+ rcu_read_lock();
+ entry = netlbl_domhsh_getentry(NULL);
+ if (entry == NULL) {
+ ret_val = -ENOENT;
+ goto listdef_failure_lock;
+ }
+ ret_val = nla_put_u32(ans_skb, NLBL_MGMT_A_PROTOCOL, entry->type);
if (ret_val != 0)
- goto listdef_failure;
+ goto listdef_failure_lock;
+ switch (entry->type) {
+ case NETLBL_NLTYPE_CIPSOV4:
+ ret_val = nla_put_u32(ans_skb,
+ NLBL_MGMT_A_CV4DOI,
+ entry->type_def.cipsov4->doi);
+ if (ret_val != 0)
+ goto listdef_failure_lock;
+ break;
+ }
+ rcu_read_unlock();
+ ret_val = netlbl_netlink_snd(ans_skb, data, info->snd_pid);
+ if (ret_val != 0)
+ goto listdef_failure;
return 0;
+listdef_failure_lock:
+ rcu_read_unlock();
listdef_failure:
- netlbl_netlink_send_ack(info,
- netlbl_mgmt_gnl_family.id,
- NLBL_MGMT_C_ACK,
- -ret_val);
+ kfree_skb(ans_skb);
return ret_val;
}
/**
- * netlbl_mgmt_modules - Handle a MODULES message
- * @skb: the NETLINK buffer
- * @info: the Generic NETLINK info block
+ * netlbl_mgmt_protocols_cb - Write an individual PROTOCOL message response
+ * @skb: the skb to write to
+ * @seq: the NETLINK sequence number
+ * @cb: the NETLINK callback
+ * @protocol: the NetLabel protocol to use in the message
*
* Description:
- * Process a user generated MODULES message and respond accordingly.
+ * This function is to be used in conjunction with netlbl_mgmt_protocols() to
+ * answer a application's PROTOCOLS message. Returns the size of the message
+ * on success, negative values on failure.
*
*/
-static int netlbl_mgmt_modules(struct sk_buff *skb, struct genl_info *info)
+static int netlbl_mgmt_protocols_cb(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ u32 protocol)
{
int ret_val = -ENOMEM;
- size_t data_size;
- u32 mod_count;
- struct sk_buff *ans_skb = NULL;
+ void *data;
- /* unlabeled + cipsov4 */
- mod_count = 2;
+ data = netlbl_netlink_hdr_put(skb,
+ NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq,
+ netlbl_mgmt_gnl_family.id,
+ NLM_F_MULTI,
+ NLBL_MGMT_C_PROTOCOLS);
+ if (data == NULL)
+ goto protocols_cb_failure;
- data_size = GENL_HDRLEN + NETLBL_LEN_U32 + mod_count * NETLBL_LEN_U32;
- ans_skb = netlbl_netlink_alloc_skb(0, data_size, GFP_KERNEL);
- if (ans_skb == NULL)
- goto modules_failure;
+ ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, protocol);
+ if (ret_val != 0)
+ goto protocols_cb_failure;
- if (netlbl_netlink_hdr_put(ans_skb,
- info->snd_pid,
- 0,
- netlbl_mgmt_gnl_family.id,
- NLBL_MGMT_C_MODULES) == NULL)
- goto modules_failure;
+ return genlmsg_end(skb, data);
- ret_val = nla_put_u32(ans_skb, NLA_U32, mod_count);
- if (ret_val != 0)
- goto modules_failure;
- ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_NLTYPE_UNLABELED);
- if (ret_val != 0)
- goto modules_failure;
- ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_NLTYPE_CIPSOV4);
- if (ret_val != 0)
- goto modules_failure;
+protocols_cb_failure:
+ genlmsg_cancel(skb, data);
+ return ret_val;
+}
- ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
- if (ret_val != 0)
- goto modules_failure;
+/**
+ * netlbl_mgmt_protocols - Handle a PROTOCOLS message
+ * @skb: the NETLINK buffer
+ * @cb: the NETLINK callback
+ *
+ * Description:
+ * Process a user generated PROTOCOLS message and respond accordingly.
+ *
+ */
+static int netlbl_mgmt_protocols(struct sk_buff *skb,
+ struct netlink_callback *cb)
+{
+ u32 protos_sent = cb->args[0];
- return 0;
+ if (protos_sent == 0) {
+ if (netlbl_mgmt_protocols_cb(skb,
+ cb,
+ NETLBL_NLTYPE_UNLABELED) < 0)
+ goto protocols_return;
+ protos_sent++;
+ }
+ if (protos_sent == 1) {
+ if (netlbl_mgmt_protocols_cb(skb,
+ cb,
+ NETLBL_NLTYPE_CIPSOV4) < 0)
+ goto protocols_return;
+ protos_sent++;
+ }
-modules_failure:
- kfree_skb(ans_skb);
- netlbl_netlink_send_ack(info,
- netlbl_mgmt_gnl_family.id,
- NLBL_MGMT_C_ACK,
- -ret_val);
- return ret_val;
+protocols_return:
+ cb->args[0] = protos_sent;
+ return skb->len;
}
/**
@@ -474,35 +475,33 @@ static int netlbl_mgmt_version(struct sk
{
int ret_val = -ENOMEM;
struct sk_buff *ans_skb = NULL;
+ void *data;
- ans_skb = netlbl_netlink_alloc_skb(0,
- GENL_HDRLEN + NETLBL_LEN_U32,
- GFP_KERNEL);
+ ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
if (ans_skb == NULL)
- goto version_failure;
- if (netlbl_netlink_hdr_put(ans_skb,
- info->snd_pid,
- 0,
- netlbl_mgmt_gnl_family.id,
- NLBL_MGMT_C_VERSION) == NULL)
+ return -ENOMEM;
+ data = netlbl_netlink_hdr_put(ans_skb,
+ info->snd_pid,
+ info->snd_seq,
+ netlbl_mgmt_gnl_family.id,
+ 0,
+ NLBL_MGMT_C_VERSION);
+ if (data == NULL)
goto version_failure;
- ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_PROTO_VERSION);
+ ret_val = nla_put_u32(ans_skb,
+ NLBL_MGMT_A_VERSION,
+ NETLBL_PROTO_VERSION);
if (ret_val != 0)
goto version_failure;
- ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
+ ret_val = netlbl_netlink_snd(ans_skb, data, info->snd_pid);
if (ret_val != 0)
goto version_failure;
-
return 0;
version_failure:
kfree_skb(ans_skb);
- netlbl_netlink_send_ack(info,
- netlbl_mgmt_gnl_family.id,
- NLBL_MGMT_C_ACK,
- -ret_val);
return ret_val;
}
@@ -513,35 +512,40 @@ version_failure:
static struct genl_ops netlbl_mgmt_genl_c_add = {
.cmd = NLBL_MGMT_C_ADD,
- .flags = 0,
+ .flags = GENL_ADMIN_PERM,
+ .policy = netlbl_mgmt_genl_policy,
.doit = netlbl_mgmt_add,
.dumpit = NULL,
};
static struct genl_ops netlbl_mgmt_genl_c_remove = {
.cmd = NLBL_MGMT_C_REMOVE,
- .flags = 0,
+ .flags = GENL_ADMIN_PERM,
+ .policy = netlbl_mgmt_genl_policy,
.doit = netlbl_mgmt_remove,
.dumpit = NULL,
};
-static struct genl_ops netlbl_mgmt_genl_c_list = {
- .cmd = NLBL_MGMT_C_LIST,
+static struct genl_ops netlbl_mgmt_genl_c_listall = {
+ .cmd = NLBL_MGMT_C_LISTALL,
.flags = 0,
- .doit = netlbl_mgmt_list,
- .dumpit = NULL,
+ .policy = netlbl_mgmt_genl_policy,
+ .doit = NULL,
+ .dumpit = netlbl_mgmt_listall,
};
static struct genl_ops netlbl_mgmt_genl_c_adddef = {
.cmd = NLBL_MGMT_C_ADDDEF,
- .flags = 0,
+ .flags = GENL_ADMIN_PERM,
+ .policy = netlbl_mgmt_genl_policy,
.doit = netlbl_mgmt_adddef,
.dumpit = NULL,
};
static struct genl_ops netlbl_mgmt_genl_c_removedef = {
.cmd = NLBL_MGMT_C_REMOVEDEF,
- .flags = 0,
+ .flags = GENL_ADMIN_PERM,
+ .policy = netlbl_mgmt_genl_policy,
.doit = netlbl_mgmt_removedef,
.dumpit = NULL,
};
@@ -549,20 +553,23 @@ static struct genl_ops netlbl_mgmt_genl_
static struct genl_ops netlbl_mgmt_genl_c_listdef = {
.cmd = NLBL_MGMT_C_LISTDEF,
.flags = 0,
+ .policy = netlbl_mgmt_genl_policy,
.doit = netlbl_mgmt_listdef,
.dumpit = NULL,
};
-static struct genl_ops netlbl_mgmt_genl_c_modules = {
- .cmd = NLBL_MGMT_C_MODULES,
+static struct genl_ops netlbl_mgmt_genl_c_protocols = {
+ .cmd = NLBL_MGMT_C_PROTOCOLS,
.flags = 0,
- .doit = netlbl_mgmt_modules,
- .dumpit = NULL,
+ .policy = netlbl_mgmt_genl_policy,
+ .doit = NULL,
+ .dumpit = netlbl_mgmt_protocols,
};
static struct genl_ops netlbl_mgmt_genl_c_version = {
.cmd = NLBL_MGMT_C_VERSION,
.flags = 0,
+ .policy = netlbl_mgmt_genl_policy,
.doit = netlbl_mgmt_version,
.dumpit = NULL,
};
@@ -596,7 +603,7 @@ int netlbl_mgmt_genl_init(void)
if (ret_val != 0)
return ret_val;
ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
- &netlbl_mgmt_genl_c_list);
+ &netlbl_mgmt_genl_c_listall);
if (ret_val != 0)
return ret_val;
ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
@@ -612,7 +619,7 @@ int netlbl_mgmt_genl_init(void)
if (ret_val != 0)
return ret_val;
ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
- &netlbl_mgmt_genl_c_modules);
+ &netlbl_mgmt_genl_c_protocols);
if (ret_val != 0)
return ret_val;
ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
Index: net-2.6.19/net/netlabel/netlabel_mgmt.h
===================================================================
--- net-2.6.19.orig/net/netlabel/netlabel_mgmt.h
+++ net-2.6.19/net/netlabel/netlabel_mgmt.h
@@ -34,212 +34,137 @@
#include <net/netlabel.h>
/*
- * The following NetLabel payloads are supported by the management interface,
- * all of which are preceeded by the nlmsghdr struct.
- *
- * o ACK:
- * Sent by the kernel in response to an applications message, applications
- * should never send this message.
- *
- * +----------------------+-----------------------+
- * | seq number (32 bits) | return code (32 bits) |
- * +----------------------+-----------------------+
- *
- * seq number: the sequence number of the original message, taken from the
- * nlmsghdr structure
- * return code: return value, based on errno values
+ * The following NetLabel payloads are supported by the management interface.
*
* o ADD:
* Sent by an application to add a domain mapping to the NetLabel system.
- * The kernel should respond with an ACK.
- *
- * +-------------------+
- * | domains (32 bits) | ...
- * +-------------------+
- *
- * domains: the number of domains in the message
- *
- * +--------------------------+-------------------------+
- * | domain string (variable) | protocol type (32 bits) | ...
- * +--------------------------+-------------------------+
- *
- * +-------------- ---- --- -- -
- * | mapping data ... repeated
- * +-------------- ---- --- -- -
- *
- * domain string: the domain string, NULL terminated
- * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
- * mapping data: specific to the map type (see below)
*
- * NETLBL_NLTYPE_UNLABELED
+ * Required attributes:
*
- * No mapping data for this protocol type.
+ * NLBL_MGMT_A_DOMAIN
+ * NLBL_MGMT_A_PROTOCOL
*
- * NETLBL_NLTYPE_CIPSOV4
+ * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
*
- * +---------------+
- * | doi (32 bits) |
- * +---------------+
+ * NLBL_MGMT_A_CV4DOI
*
- * doi: the CIPSO DOI value
+ * If using NETLBL_NLTYPE_UNLABELED no other attributes are required.
*
* o REMOVE:
* Sent by an application to remove a domain mapping from the NetLabel
- * system. The kernel should ACK this message.
+ * system.
*
- * +-------------------+
- * | domains (32 bits) | ...
- * +-------------------+
+ * Required attributes:
*
- * domains: the number of domains in the message
+ * NLBL_MGMT_A_DOMAIN
*
- * +--------------------------+
- * | domain string (variable) | ...
- * +--------------------------+
- *
- * domain string: the domain string, NULL terminated
- *
- * o LIST:
+ * o LISTALL:
* This message can be sent either from an application or by the kernel in
- * response to an application generated LIST message. When sent by an
- * application there is no payload. The kernel should respond to a LIST
- * message either with a LIST message on success or an ACK message on
- * failure.
- *
- * +-------------------+
- * | domains (32 bits) | ...
- * +-------------------+
- *
- * domains: the number of domains in the message
- *
- * +--------------------------+
- * | domain string (variable) | ...
- * +--------------------------+
- *
- * +-------------------------+-------------- ---- --- -- -
- * | protocol type (32 bits) | mapping data ... repeated
- * +-------------------------+-------------- ---- --- -- -
+ * response to an application generated LISTALL message. When sent by an
+ * application there is no payload and the NLM_F_DUMP flag should be set.
+ * The kernel should respond with a series of the following messages.
*
- * domain string: the domain string, NULL terminated
- * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
- * mapping data: specific to the map type (see below)
+ * Required attributes:
*
- * NETLBL_NLTYPE_UNLABELED
+ * NLBL_MGMT_A_DOMAIN
+ * NLBL_MGMT_A_PROTOCOL
*
- * No mapping data for this protocol type.
+ * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
*
- * NETLBL_NLTYPE_CIPSOV4
+ * NLBL_MGMT_A_CV4DOI
*
- * +----------------+---------------+
- * | type (32 bits) | doi (32 bits) |
- * +----------------+---------------+
- *
- * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header
- * as CIPSO_V4_MAP_*)
- * doi: the CIPSO DOI value
+ * If using NETLBL_NLTYPE_UNLABELED no other attributes are required.
*
* o ADDDEF:
* Sent by an application to set the default domain mapping for the NetLabel
- * system. The kernel should respond with an ACK.
- *
- * +-------------------------+-------------- ---- --- -- -
- * | protocol type (32 bits) | mapping data ... repeated
- * +-------------------------+-------------- ---- --- -- -
- *
- * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
- * mapping data: specific to the map type (see below)
+ * system.
*
- * NETLBL_NLTYPE_UNLABELED
+ * Required attributes:
*
- * No mapping data for this protocol type.
+ * NLBL_MGMT_A_PROTOCOL
*
- * NETLBL_NLTYPE_CIPSOV4
+ * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
*
- * +---------------+
- * | doi (32 bits) |
- * +---------------+
+ * NLBL_MGMT_A_CV4DOI
*
- * doi: the CIPSO DOI value
+ * If using NETLBL_NLTYPE_UNLABELED no other attributes are required.
*
* o REMOVEDEF:
* Sent by an application to remove the default domain mapping from the
- * NetLabel system, there is no payload. The kernel should ACK this message.
+ * NetLabel system, there is no payload.
*
* o LISTDEF:
* This message can be sent either from an application or by the kernel in
* response to an application generated LISTDEF message. When sent by an
- * application there is no payload. The kernel should respond to a
- * LISTDEF message either with a LISTDEF message on success or an ACK message
- * on failure.
- *
- * +-------------------------+-------------- ---- --- -- -
- * | protocol type (32 bits) | mapping data ... repeated
- * +-------------------------+-------------- ---- --- -- -
- *
- * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
- * mapping data: specific to the map type (see below)
- *
- * NETLBL_NLTYPE_UNLABELED
+ * application there is no payload. On success the kernel should send a
+ * response using the following format.
*
- * No mapping data for this protocol type.
+ * Required attributes:
*
- * NETLBL_NLTYPE_CIPSOV4
+ * NLBL_MGMT_A_PROTOCOL
*
- * +----------------+---------------+
- * | type (32 bits) | doi (32 bits) |
- * +----------------+---------------+
+ * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
*
- * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header
- * as CIPSO_V4_MAP_*)
- * doi: the CIPSO DOI value
+ * NLBL_MGMT_A_CV4DOI
*
- * o MODULES:
- * Sent by an application to request a list of configured NetLabel modules
- * in the kernel. When sent by an application there is no payload.
+ * If using NETLBL_NLTYPE_UNLABELED no other attributes are required.
*
- * +-------------------+
- * | modules (32 bits) | ...
- * +-------------------+
+ * o PROTOCOLS:
+ * Sent by an application to request a list of configured NetLabel protocols
+ * in the kernel. When sent by an application there is no payload and the
+ * NLM_F_DUMP flag should be set. The kernel should respond with a series of
+ * the following messages.
*
- * modules: the number of modules in the message, if this is an application
- * generated message and the value is zero then return a list of
- * the configured modules
+ * Required attributes:
*
- * +------------------+
- * | module (32 bits) | ... repeated
- * +------------------+
- *
- * module: the module number as defined by NETLBL_NLTYPE_*
+ * NLBL_MGMT_A_PROTOCOL
*
* o VERSION:
- * Sent by an application to request the NetLabel version string. When sent
- * by an application there is no payload. This message type is also used by
- * the kernel to respond to an VERSION request.
- *
- * +-------------------+
- * | version (32 bits) |
- * +-------------------+
+ * Sent by an application to request the NetLabel version. When sent by an
+ * application there is no payload. This message type is also used by the
+ * kernel to respond to an VERSION request.
+ *
+ * Required attributes:
*
- * version: the protocol version number
+ * NLBL_MGMT_A_VERSION
*
*/
/* NetLabel Management commands */
enum {
NLBL_MGMT_C_UNSPEC,
- NLBL_MGMT_C_ACK,
NLBL_MGMT_C_ADD,
NLBL_MGMT_C_REMOVE,
- NLBL_MGMT_C_LIST,
+ NLBL_MGMT_C_LISTALL,
NLBL_MGMT_C_ADDDEF,
NLBL_MGMT_C_REMOVEDEF,
NLBL_MGMT_C_LISTDEF,
- NLBL_MGMT_C_MODULES,
+ NLBL_MGMT_C_PROTOCOLS,
NLBL_MGMT_C_VERSION,
__NLBL_MGMT_C_MAX,
};
#define NLBL_MGMT_C_MAX (__NLBL_MGMT_C_MAX - 1)
+/* NetLabel Management attributes */
+enum {
+ NLBL_MGMT_A_UNSPEC,
+ NLBL_MGMT_A_DOMAIN,
+ /* (NLA_NUL_STRING)
+ * the NULL terminated LSM domain string */
+ NLBL_MGMT_A_PROTOCOL,
+ /* (NLA_U32)
+ * the NetLabel protocol type (defined by NETLBL_NLTYPE_*) */
+ NLBL_MGMT_A_VERSION,
+ /* (NLA_U32)
+ * the NetLabel protocol version number (defined by
+ * NETLBL_PROTO_VERSION) */
+ NLBL_MGMT_A_CV4DOI,
+ /* (NLA_U32)
+ * the CIPSOv4 DOI value */
+ __NLBL_MGMT_A_MAX,
+};
+#define NLBL_MGMT_A_MAX (__NLBL_MGMT_A_MAX - 1)
+
/* NetLabel protocol functions */
int netlbl_mgmt_genl_init(void);
Index: net-2.6.19/net/netlabel/netlabel_unlabeled.c
===================================================================
--- net-2.6.19.orig/net/netlabel/netlabel_unlabeled.c
+++ net-2.6.19/net/netlabel/netlabel_unlabeled.c
@@ -55,9 +55,13 @@ static struct genl_family netlbl_unlabel
.hdrsize = 0,
.name = NETLBL_NLTYPE_UNLABELED_NAME,
.version = NETLBL_PROTO_VERSION,
- .maxattr = 0,
+ .maxattr = NLBL_UNLABEL_A_MAX,
};
+/* NetLabel Netlink attribute policy */
+static struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
+ [NLBL_UNLABEL_A_ACPTFLG] = { .type = NLA_U8 },
+};
/*
* NetLabel Command Handlers
@@ -75,31 +79,18 @@ static struct genl_family netlbl_unlabel
*/
static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info)
{
- int ret_val;
- struct nlattr *data = netlbl_netlink_payload_data(skb);
- u32 value;
-
- ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
- if (ret_val != 0)
- return ret_val;
+ int ret_val = -EINVAL;
+ u8 value;
- if (netlbl_netlink_payload_len(skb) == NETLBL_LEN_U32) {
- value = nla_get_u32(data);
+ if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) {
+ value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]);
if (value == 1 || value == 0) {
atomic_set(&netlabel_unlabel_accept_flg, value);
- netlbl_netlink_send_ack(info,
- netlbl_unlabel_gnl_family.id,
- NLBL_UNLABEL_C_ACK,
- NETLBL_E_OK);
- return 0;
+ ret_val = 0;
}
}
- netlbl_netlink_send_ack(info,
- netlbl_unlabel_gnl_family.id,
- NLBL_UNLABEL_C_ACK,
- EINVAL);
- return -EINVAL;
+ return ret_val;
}
/**
@@ -114,39 +105,37 @@ static int netlbl_unlabel_accept(struct
*/
static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info)
{
- int ret_val = -ENOMEM;
+ int ret_val = -EINVAL;
struct sk_buff *ans_skb;
+ void *data;
- ans_skb = netlbl_netlink_alloc_skb(0,
- GENL_HDRLEN + NETLBL_LEN_U32,
- GFP_KERNEL);
+ ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
if (ans_skb == NULL)
goto list_failure;
-
- if (netlbl_netlink_hdr_put(ans_skb,
- info->snd_pid,
- 0,
- netlbl_unlabel_gnl_family.id,
- NLBL_UNLABEL_C_LIST) == NULL)
+ data = netlbl_netlink_hdr_put(ans_skb,
+ info->snd_pid,
+ info->snd_seq,
+ netlbl_unlabel_gnl_family.id,
+ 0,
+ NLBL_UNLABEL_C_LIST);
+ if (data == NULL) {
+ ret_val = -ENOMEM;
goto list_failure;
+ }
- ret_val = nla_put_u32(ans_skb,
- NLA_U32,
- atomic_read(&netlabel_unlabel_accept_flg));
+ ret_val = nla_put_u8(ans_skb,
+ NLBL_UNLABEL_A_ACPTFLG,
+ atomic_read(&netlabel_unlabel_accept_flg));
if (ret_val != 0)
goto list_failure;
- ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
+ ret_val = netlbl_netlink_snd(ans_skb, data, info->snd_pid);
if (ret_val != 0)
goto list_failure;
-
return 0;
list_failure:
- netlbl_netlink_send_ack(info,
- netlbl_unlabel_gnl_family.id,
- NLBL_UNLABEL_C_ACK,
- -ret_val);
+ kfree(ans_skb);
return ret_val;
}
@@ -157,7 +146,8 @@ list_failure:
static struct genl_ops netlbl_unlabel_genl_c_accept = {
.cmd = NLBL_UNLABEL_C_ACCEPT,
- .flags = 0,
+ .flags = GENL_ADMIN_PERM,
+ .policy = netlbl_unlabel_genl_policy,
.doit = netlbl_unlabel_accept,
.dumpit = NULL,
};
@@ -165,6 +155,7 @@ static struct genl_ops netlbl_unlabel_ge
static struct genl_ops netlbl_unlabel_genl_c_list = {
.cmd = NLBL_UNLABEL_C_LIST,
.flags = 0,
+ .policy = netlbl_unlabel_genl_policy,
.doit = netlbl_unlabel_list,
.dumpit = NULL,
};
@@ -218,10 +209,8 @@ int netlbl_unlabel_genl_init(void)
*/
int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr)
{
- if (atomic_read(&netlabel_unlabel_accept_flg) == 1) {
- memset(secattr, 0, sizeof(*secattr));
- return 0;
- }
+ if (atomic_read(&netlabel_unlabel_accept_flg) == 1)
+ return netlbl_secattr_init(secattr);
return -ENOMSG;
}
Index: net-2.6.19/net/netlabel/netlabel_unlabeled.h
===================================================================
--- net-2.6.19.orig/net/netlabel/netlabel_unlabeled.h
+++ net-2.6.19/net/netlabel/netlabel_unlabeled.h
@@ -36,56 +36,47 @@
/*
* The following NetLabel payloads are supported by the Unlabeled subsystem.
*
- * o ACK:
- * Sent by the kernel in response to an applications message, applications
- * should never send this message.
- *
- * +----------------------+-----------------------+
- * | seq number (32 bits) | return code (32 bits) |
- * +----------------------+-----------------------+
- *
- * seq number: the sequence number of the original message, taken from the
- * nlmsghdr structure
- * return code: return value, based on errno values
- *
* o ACCEPT
* This message is sent from an application to specify if the kernel should
* allow unlabled packets to pass if they do not match any of the static
* mappings defined in the unlabeled module.
*
- * +-----------------+
- * | allow (32 bits) |
- * +-----------------+
+ * Required attributes:
*
- * allow: if true (1) then allow the packets to pass, if false (0) then
- * reject the packets
+ * NLBL_UNLABEL_A_ACPTFLG
*
* o LIST
* This message can be sent either from an application or by the kernel in
* response to an application generated LIST message. When sent by an
* application there is no payload. The kernel should respond to a LIST
- * message either with a LIST message on success or an ACK message on
- * failure.
+ * message with a LIST message on success.
*
- * +-----------------------+
- * | accept flag (32 bits) |
- * +-----------------------+
+ * Required attributes:
*
- * accept flag: if true (1) then unlabeled packets are allowed to pass,
- * if false (0) then unlabeled packets are rejected
+ * NLBL_UNLABEL_A_ACPTFLG
*
*/
/* NetLabel Unlabeled commands */
enum {
NLBL_UNLABEL_C_UNSPEC,
- NLBL_UNLABEL_C_ACK,
NLBL_UNLABEL_C_ACCEPT,
NLBL_UNLABEL_C_LIST,
__NLBL_UNLABEL_C_MAX,
};
#define NLBL_UNLABEL_C_MAX (__NLBL_UNLABEL_C_MAX - 1)
+/* NetLabel Unlabeled attributes */
+enum {
+ NLBL_UNLABEL_A_UNSPEC,
+ NLBL_UNLABEL_A_ACPTFLG,
+ /* (NLA_U8)
+ * if true then unlabeled packets are allowed to pass, else unlabeled
+ * packets are rejected */
+ __NLBL_UNLABEL_A_MAX,
+};
+#define NLBL_UNLABEL_A_MAX (__NLBL_UNLABEL_A_MAX - 1)
+
/* NetLabel protocol functions */
int netlbl_unlabel_genl_init(void);
--
paul moore
linux security @ hp
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 6/6] NetLabel: update docs with website information
2006-09-21 16:57 [PATCH 0/6] NetLabel fixes and reworked Netlink interface paul.moore
` (4 preceding siblings ...)
2006-09-21 16:57 ` [PATCH 5/6] NetLabel: rework the Netlink attribute handling (part 2) paul.moore
@ 2006-09-21 16:57 ` paul.moore
5 siblings, 0 replies; 14+ messages in thread
From: paul.moore @ 2006-09-21 16:57 UTC (permalink / raw)
To: selinux, netdev; +Cc: sds, jmorris, tgraf, Paul Moore
[-- Attachment #1: netlabel-doc_update --]
[-- Type: text/plain, Size: 1388 bytes --]
Now that all of the supporting pieces of NetLabel have a home at SourceForge
update the Kconfig help text and add an entry to the MAINTAINERS file.
Signed-off-by: Paul Moore <paul.moore@hp.com>
---
MAINTAINERS | 7 +++++++
net/netlabel/Kconfig | 5 ++++-
2 files changed, 11 insertions(+), 1 deletion(-)
Index: net-2.6.19/MAINTAINERS
===================================================================
--- net-2.6.19.orig/MAINTAINERS
+++ net-2.6.19/MAINTAINERS
@@ -2008,6 +2008,13 @@ L: netfilter@lists.netfilter.org
L: netfilter-devel@lists.netfilter.org
S: Supported
+NETLABEL
+P: Paul Moore
+M: paul.moore@hp.com
+W: http://netlabel.sf.net
+L: netdev@vger.kernel.org
+S: Supported
+
NETROM NETWORK LAYER
P: Ralf Baechle
M: ralf@linux-mips.org
Index: net-2.6.19/net/netlabel/Kconfig
===================================================================
--- net-2.6.19.orig/net/netlabel/Kconfig
+++ net-2.6.19/net/netlabel/Kconfig
@@ -9,6 +9,9 @@ config NETLABEL
---help---
NetLabel provides support for explicit network packet labeling
protocols such as CIPSO and RIPSO. For more information see
- Documentation/netlabel.
+ Documentation/netlabel as well as the NetLabel SourceForge project
+ for configuration tools and additional documentation.
+
+ * http://netlabel.sf.net
If you are unsure, say N.
--
paul moore
linux security @ hp
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/6] NetLabel: correct improper handling of non-NetLabel peer contexts
2006-09-21 16:57 ` [PATCH 1/6] NetLabel: correct improper handling of non-NetLabel peer contexts paul.moore
@ 2006-09-21 18:08 ` James Morris
2006-09-21 18:28 ` Paul Moore
0 siblings, 1 reply; 14+ messages in thread
From: James Morris @ 2006-09-21 18:08 UTC (permalink / raw)
To: Paul Moore; +Cc: selinux, netdev, sds, jmorris, tgraf
On Thu, 21 Sep 2006, paul.moore@hp.com wrote:
> Fix a problem where NetLabel would always set the value of
> sk_security_struct->peer_sid in selinux_netlbl_sock_graft() to the context of
> the socket, causing problems when users would query the context of the
> connection. This patch fixes this so that the value in
> sk_security_struct->peer_sid is only set when the connection is NetLabel based,
> otherwise the value is untouched.
I'll let Thomas comment on the Netlink changes, as he's been working with
you on them.
These changes otherwise seem ok. How much testing has this had with and
without Netlabel enabled?
- James
--
James Morris
<jmorris@namei.org>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/6] NetLabel: correct improper handling of non-NetLabel peer contexts
2006-09-21 18:08 ` James Morris
@ 2006-09-21 18:28 ` Paul Moore
0 siblings, 0 replies; 14+ messages in thread
From: Paul Moore @ 2006-09-21 18:28 UTC (permalink / raw)
To: James Morris; +Cc: selinux, netdev, sds, jmorris, tgraf
James Morris wrote:
> On Thu, 21 Sep 2006, paul.moore@hp.com wrote:
>
>
>>Fix a problem where NetLabel would always set the value of
>>sk_security_struct->peer_sid in selinux_netlbl_sock_graft() to the context of
>>the socket, causing problems when users would query the context of the
>>connection. This patch fixes this so that the value in
>>sk_security_struct->peer_sid is only set when the connection is NetLabel based,
>>otherwise the value is untouched.
>
> I'll let Thomas comment on the Netlink changes, as he's been working with
> you on them.
Hey, third times the charm right?
;)
> These changes otherwise seem ok. How much testing has this had with and
> without Netlabel enabled?
Joshua Brindle started a thread on the SELinux list which uncovered at
least two problems that I am aware of, one with NetLabel overriding the
peer's context and one with IPsec labeling returning the context from
the wrong SA (I may have the details of this wrong, Venkat posted about
this in the same thread). This patch correct the NetLabel problem and
was tested using the simple reproducer provided by Joshua; I tested both
on a NetLabel'd and non-NetLabel'd connection and the results were
correct. I have also tested this patch with the getpeercon() enabled
version of xinetd in FC/Rawhide; when configured to use labeled
connections and used with NetLabel the daemon is spawned with the
correct MLS label, when configured to use labeled connections and
NetLabel is not used xinetd reports an error because getpeercon()
returns an error (desired behavior as there is no network label present
for the connection).
If there is some other test you would like to see run let me know and
I'll give it a shot and report the results.
--
paul moore
linux security @ hp
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 4/6] NetLabel: rework the Netlink attribute handling (part 1)
2006-09-21 16:57 ` [PATCH 4/6] NetLabel: rework the Netlink attribute handling (part 1) paul.moore
@ 2006-09-25 9:12 ` Thomas Graf
0 siblings, 0 replies; 14+ messages in thread
From: Thomas Graf @ 2006-09-25 9:12 UTC (permalink / raw)
To: paul.moore; +Cc: selinux, netdev, sds, jmorris
* paul.moore@hp.com <paul.moore@hp.com> 2006-09-21 12:57
> -int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group)
> +int netlbl_netlink_snd_multicast(struct sk_buff *skb,
> + void *buf,
> + u32 pid,
> + u32 group)
> {
> + genlmsg_end(skb, buf);
> return genlmsg_multicast(skb, pid, group, GFP_KERNEL);
> }
This is a bit weird at first, one would expect that the message
is terminated when it is build but I guess this is ok for now.
Rest seems fine.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 5/6] NetLabel: rework the Netlink attribute handling (part 2)
2006-09-21 16:57 ` [PATCH 5/6] NetLabel: rework the Netlink attribute handling (part 2) paul.moore
@ 2006-09-25 9:43 ` Thomas Graf
2006-09-25 14:13 ` Paul Moore
0 siblings, 1 reply; 14+ messages in thread
From: Thomas Graf @ 2006-09-25 9:43 UTC (permalink / raw)
To: paul.moore; +Cc: selinux, netdev, sds, jmorris
* paul.moore@hp.com <paul.moore@hp.com> 2006-09-21 12:57
> At the suggestion of Thomas Graf, rewrite NetLabel's use of Netlink attributes
> to better follow the common Netlink attribute usage.
>
> Signed-off-by: Paul Moore <paul.moore@hp.com>
> ---
> net/netlabel/netlabel_cipso_v4.c | 593 +++++++++++++++++++++++++-------------
> net/netlabel/netlabel_cipso_v4.h | 235 +++++----------
> net/netlabel/netlabel_mgmt.c | 531 +++++++++++++++++-----------------
> net/netlabel/netlabel_mgmt.h | 213 ++++---------
> net/netlabel/netlabel_unlabeled.c | 77 ++--
> net/netlabel/netlabel_unlabeled.h | 41 +-
> 6 files changed, 875 insertions(+), 815 deletions(-)
>
> Index: net-2.6.19/net/netlabel/netlabel_cipso_v4.c
> ===================================================================
> --- net-2.6.19.orig/net/netlabel/netlabel_cipso_v4.c
> +++ net-2.6.19/net/netlabel/netlabel_cipso_v4.c
> @@ -41,15 +41,37 @@
> #include "netlabel_user.h"
> #include "netlabel_cipso_v4.h"
>
> +/* Argument struct for cipso_v4_doi_walk() */
> +struct netlbl_cipsov4_doiwalk_arg {
> + struct netlink_callback *nl_cb;
> + struct sk_buff *skb;
> + u32 seq;
> +};
> +
> /* NetLabel Generic NETLINK CIPSOv4 family */
> static struct genl_family netlbl_cipsov4_gnl_family = {
> .id = GENL_ID_GENERATE,
> .hdrsize = 0,
> .name = NETLBL_NLTYPE_CIPSOV4_NAME,
> .version = NETLBL_PROTO_VERSION,
> - .maxattr = 0,
> + .maxattr = NLBL_CIPSOV4_A_MAX,
> };
>
> +/* NetLabel Netlink attribute policy */
> +static struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
> + [NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 },
> + [NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 },
> + [NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 },
> + [NLBL_CIPSOV4_A_TAGLST] = { .type = NLA_NESTED },
> + [NLBL_CIPSOV4_A_MLSLVLLOC] = { .type = NLA_U32 },
> + [NLBL_CIPSOV4_A_MLSLVLREM] = { .type = NLA_U32 },
> + [NLBL_CIPSOV4_A_MLSLVL] = { .type = NLA_NESTED },
> + [NLBL_CIPSOV4_A_MLSLVLLST] = { .type = NLA_NESTED },
> + [NLBL_CIPSOV4_A_MLSCATLOC] = { .type = NLA_U32 },
> + [NLBL_CIPSOV4_A_MLSCATREM] = { .type = NLA_U32 },
> + [NLBL_CIPSOV4_A_MLSCAT] = { .type = NLA_NESTED },
> + [NLBL_CIPSOV4_A_MLSCATLST] = { .type = NLA_NESTED },
> +};
>
> /*
> * Helper Functions
> @@ -81,16 +103,13 @@ static void netlbl_cipsov4_doi_free(stru
> kfree(ptr);
> }
>
> -
> /*
> * NetLabel Command Handlers
> */
>
> /**
> * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition
> - * @doi: the DOI value
> - * @msg: the ADD message data
> - * @msg_size: the size of the ADD message buffer
> + * @info: the Generic NETLINK info block
> *
> * Description:
> * Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message
> @@ -98,22 +117,31 @@ static void netlbl_cipsov4_doi_free(stru
> * error.
> *
> */
> -static int netlbl_cipsov4_add_std(u32 doi, struct nlattr *msg, size_t msg_size)
> +static int netlbl_cipsov4_add_std(struct genl_info *info)
> {
> int ret_val = -EINVAL;
> - int msg_len = msg_size;
> - u32 num_tags;
> - u32 num_lvls;
> - u32 num_cats;
> struct cipso_v4_doi *doi_def = NULL;
> - u32 iter;
> - u32 tmp_val_a;
> - u32 tmp_val_b;
> -
> - if (msg_len < NETLBL_LEN_U32)
> - goto add_std_failure;
> - num_tags = netlbl_getinc_u32(&msg, &msg_len);
> - if (num_tags == 0 || num_tags > CIPSO_V4_TAG_MAXCNT)
> + struct nlattr *nla_a;
> + struct nlattr *nla_b;
> + struct nlattr *nla_c;
> + int nla_a_rem;
> + int nla_b_rem;
> + u32 iter = 0;
> +
> + if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
> + !info->attrs[NLBL_CIPSOV4_A_TAGLST] ||
> + !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST])
> + goto add_std_failure;
> +
> + if (nla_validate(nla_data(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
> + nla_len(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
> + NLBL_CIPSOV4_A_MAX,
> + netlbl_cipsov4_genl_policy) != 0)
> + goto add_std_failure;
> + if (nla_validate(nla_data(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
> + nla_len(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
> + NLBL_CIPSOV4_A_MAX,
> + netlbl_cipsov4_genl_policy) != 0)
> goto add_std_failure;
>
> doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
> @@ -128,28 +156,44 @@ static int netlbl_cipsov4_add_std(u32 do
> }
> doi_def->type = CIPSO_V4_MAP_STD;
>
> - for (iter = 0; iter < num_tags; iter++) {
> - if (msg_len < NETLBL_LEN_U8)
> - goto add_std_failure;
> - doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len);
> - switch (doi_def->tags[iter]) {
> - case CIPSO_V4_TAG_RBITMAP:
> - break;
> - default:
> - goto add_std_failure;
> + nla_for_each_attr(nla_a,
> + nla_data(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
> + nla_len(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
> + nla_a_rem)
You can use nla_for_each_nested() here.
> + if (nla_a->nla_type == NLBL_CIPSOV4_A_TAG) {
> + if (iter > CIPSO_V4_TAG_MAXCNT)
> + goto add_std_failure;
> + doi_def->tags[iter++] = nla_get_u8(nla_a);
> }
Perfectly validated against generic policy yet flexible, I
like this a lot.
> + nla_for_each_attr(nla_a,
> + nla_data(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
> + nla_len(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
> + nla_a_rem)
Could use nla_for_each_nested() here as well.
> + if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) {
> + nla_for_each_attr(nla_b,
> + nla_data(nla_a),
> + nla_len(nla_a),
> + nla_b_rem)
... and again :-)
> + switch (nla_b->nla_type) {
> + case NLBL_CIPSOV4_A_MLSLVLLOC:
> + if (nla_get_u32(nla_b) >=
Attributes on this level are not yet validated.
> + doi_def->map.std->lvl.local_size)
> + doi_def->map.std->lvl.local_size =
> + nla_get_u32(nla_b) + 1;
> + break;
> + case NLBL_CIPSOV4_A_MLSLVLREM:
> + if (nla_get_u32(nla_b) >=
> + doi_def->map.std->lvl.cipso_size)
> + doi_def->map.std->lvl.cipso_size =
> + nla_get_u32(nla_b) + 1;
> + break;
> + }
> + }
> @@ -168,68 +209,96 @@ static int netlbl_cipsov4_add_std(u32 do
> ret_val = -ENOMEM;
> goto add_std_failure;
> }
> + nla_for_each_attr(nla_a,
> + nla_data(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
> + nla_len(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
> + nla_a_rem)
> + if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) {
> + nla_b = nla_find_nested(nla_a,
> + NLBL_CIPSOV4_A_MLSLVLLOC);
> + nla_c = nla_find_nested(nla_a,
> + NLBL_CIPSOV4_A_MLSLVLREM);
Maybe find better names for nla_a and nla_b, would enhance readability
> + if (nla_b == NULL || nla_c == NULL)
> + goto add_std_failure;
> + doi_def->map.std->lvl.local[nla_get_u32(nla_b)] =
> + nla_get_u32(nla_c);
> + doi_def->map.std->lvl.cipso[nla_get_u32(nla_c)] =
> + nla_get_u32(nla_b);
> + }
>
> - num_cats = netlbl_getinc_u32(&msg, &msg_len);
> - doi_def->map.std->cat.local_size = netlbl_getinc_u32(&msg, &msg_len);
> - if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS)
> - goto add_std_failure;
> - doi_def->map.std->cat.local = kcalloc(doi_def->map.std->cat.local_size,
> + if (info->attrs[NLBL_CIPSOV4_A_MLSCATLST]) {
> + if (nla_validate(
> + nla_data(info->attrs[NLBL_CIPSOV4_A_MLSCATLST]),
> + nla_len(info->attrs[NLBL_CIPSOV4_A_MLSCATLST]),
> + NLBL_CIPSOV4_A_MAX,
> + netlbl_cipsov4_genl_policy) != 0)
We might want to add nla_validate_nested() to the interface as this seems
to become a common usage.
> @@ -276,21 +345,20 @@ static int netlbl_cipsov4_add_pass(u32 d
> }
> doi_def->type = CIPSO_V4_MAP_PASS;
>
> - for (iter = 0; iter < num_tags; iter++) {
> - if (msg_len < NETLBL_LEN_U8)
> - goto add_pass_failure;
> - doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len);
> - switch (doi_def->tags[iter]) {
> - case CIPSO_V4_TAG_RBITMAP:
> - break;
> - default:
> - goto add_pass_failure;
> + nla_for_each_attr(nla,
> + nla_data(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
> + nla_len(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
> + nla_rem)
> + if (nla->nla_type == NLBL_CIPSOV4_A_TAG) {
> + if (iter > CIPSO_V4_TAG_MAXCNT)
> + goto add_pass_failure;
> + doi_def->tags[iter++] = nla_get_u8(nla);
> }
This is duplicated code, put this into netlbl_cipsov4_get_tags()?
> @@ -353,84 +408,237 @@ add_return:
> * @info: the Generic NETLINK info block
> *
> * Description:
> - * Process a user generated LIST message and respond accordingly. Returns
> - * zero on success and negative values on error.
> + * Process a user generated LIST message and respond accordingly. While the
> + * response message generated by the kernel is straightforward, determining
> + * before hand the size of the buffer to allocate is not (we have to generate
> + * the message to know the size). In order to keep this function sane what we
> + * do is allocate a buffer of NLMSG_GOODSIZE and try to fit the response in
> + * that size, if we fail then we restart with a larger buffer and try again.
> + * We continue in this manner until we hit a limit of failed attempts then we
> + * give up and just send an error message. Returns zero on success and
> + * negative values on error.
> *
> */
> static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info)
> {
> - int ret_val = -EINVAL;
> + int ret_val;
> + struct sk_buff *ans_skb = NULL;
> + u32 nlsze_mult = 1;
> + void *data;
> u32 doi;
> - struct nlattr *msg = netlbl_netlink_payload_data(skb);
> - struct sk_buff *ans_skb;
> + struct nlattr *nla_a;
> + struct nlattr *nla_b;
> + struct cipso_v4_doi *doi_def;
> + u32 iter;
>
> - if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32)
> + if (!info->attrs[NLBL_CIPSOV4_A_DOI]) {
> + ret_val = -EINVAL;
> goto list_failure;
> + }
>
> - doi = nla_get_u32(msg);
> - ans_skb = cipso_v4_doi_dump(doi, NLMSG_SPACE(GENL_HDRLEN));
> +list_start:
> + ans_skb = nlmsg_new(NLMSG_GOODSIZE * nlsze_mult, GFP_KERNEL);
> if (ans_skb == NULL) {
> ret_val = -ENOMEM;
> goto list_failure;
> }
> - netlbl_netlink_hdr_push(ans_skb,
> - info->snd_pid,
> - 0,
> - netlbl_cipsov4_gnl_family.id,
> - NLBL_CIPSOV4_C_LIST);
> + data = netlbl_netlink_hdr_put(ans_skb,
> + info->snd_pid,
> + info->snd_seq,
> + netlbl_cipsov4_gnl_family.id,
> + 0,
> + NLBL_CIPSOV4_C_LIST);
> + if (data == NULL) {
> + ret_val = -ENOMEM;
> + goto list_failure;
> + }
> +
> + doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
> +
> + rcu_read_lock();
> + doi_def = cipso_v4_doi_getdef(doi);
> + if (doi_def == NULL) {
> + ret_val = -EINVAL;
> + goto list_failure;
> + }
> +
> + ret_val = nla_put_u32(ans_skb, NLBL_CIPSOV4_A_MTYPE, doi_def->type);
> + if (ret_val != 0)
> + goto list_failure_lock;
> +
> + nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_TAGLST);
> + if (nla_a == NULL) {
> + ret_val = -ENOMEM;
> + goto list_failure_lock;
> + }
> + for (iter = 0;
> + iter < CIPSO_V4_TAG_MAXCNT &&
> + doi_def->tags[iter] != CIPSO_V4_TAG_INVALID;
> + iter++) {
> + ret_val = nla_put_u8(ans_skb,
> + NLBL_CIPSOV4_A_TAG,
> + doi_def->tags[iter]);
> + if (ret_val != 0)
> + goto list_failure_lock;
> + }
> + nla_nest_end(ans_skb, nla_a);
>
> - ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
> + switch (doi_def->type) {
> + case CIPSO_V4_MAP_STD:
> + nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVLLST);
> + if (nla_a == NULL) {
> + ret_val = -ENOMEM;
> + goto list_failure_lock;
> + }
> + for (iter = 0;
> + iter < doi_def->map.std->lvl.local_size;
> + iter++) {
> + if (doi_def->map.std->lvl.local[iter] ==
> + CIPSO_V4_INV_LVL)
> + continue;
Can you estimate the number of entries being dumped here and in the cat
list below?
> +
> + nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVL);
> + if (nla_b == NULL) {
> + ret_val = -ENOMEM;
> + goto list_retry;
> + }
> + ret_val = nla_put_u32(ans_skb,
> + NLBL_CIPSOV4_A_MLSLVLLOC,
> + iter);
> + if (ret_val != 0)
> + goto list_retry;
> + ret_val = nla_put_u32(ans_skb,
> + NLBL_CIPSOV4_A_MLSLVLREM,
> + doi_def->map.std->lvl.local[iter]);
> + if (ret_val != 0)
> + goto list_retry;
> + nla_nest_end(ans_skb, nla_b);
> + }
> + nla_nest_end(ans_skb, nla_a);
> +
> + nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCATLST);
> + if (nla_a == NULL) {
> + ret_val = -ENOMEM;
> + goto list_retry;
> + }
> + for (iter = 0;
> + iter < doi_def->map.std->cat.local_size;
> + iter++) {
> + if (doi_def->map.std->cat.local[iter] ==
> + CIPSO_V4_INV_CAT)
> + continue;
> +
> + nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCAT);
> + if (nla_b == NULL) {
> + ret_val = -ENOMEM;
> + goto list_retry;
> + }
> + ret_val = nla_put_u32(ans_skb,
> + NLBL_CIPSOV4_A_MLSCATLOC,
> + iter);
> + if (ret_val != 0)
> + goto list_retry;
> + ret_val = nla_put_u32(ans_skb,
> + NLBL_CIPSOV4_A_MLSCATREM,
> + doi_def->map.std->cat.local[iter]);
> + if (ret_val != 0)
> + goto list_retry;
> + nla_nest_end(ans_skb, nla_b);
> + }
> + nla_nest_end(ans_skb, nla_a);
> +
> + break;
> + }
> + rcu_read_unlock();
What I meant in the previous posting is to put genlmsg_end() in here
like the rest of the code to be clear and symmetric.
The rest of the code has simliar issues, nevertheless this looks
really great. Everything is extendable and relatively easy to
maintain. This should definitely go into 2.6.19. Good work.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 5/6] NetLabel: rework the Netlink attribute handling (part 2)
2006-09-25 9:43 ` Thomas Graf
@ 2006-09-25 14:13 ` Paul Moore
2006-09-25 15:06 ` Thomas Graf
0 siblings, 1 reply; 14+ messages in thread
From: Paul Moore @ 2006-09-25 14:13 UTC (permalink / raw)
To: Thomas Graf; +Cc: selinux, netdev, sds, jmorris
Thomas Graf wrote:
> * paul.moore@hp.com <paul.moore@hp.com> 2006-09-21 12:57
>
>>At the suggestion of Thomas Graf, rewrite NetLabel's use of Netlink attributes
>>to better follow the common Netlink attribute usage.
>>
>>Signed-off-by: Paul Moore <paul.moore@hp.com>
>>---
>> net/netlabel/netlabel_cipso_v4.c | 593 +++++++++++++++++++++++++-------------
>> net/netlabel/netlabel_cipso_v4.h | 235 +++++----------
>> net/netlabel/netlabel_mgmt.c | 531 +++++++++++++++++-----------------
>> net/netlabel/netlabel_mgmt.h | 213 ++++---------
>> net/netlabel/netlabel_unlabeled.c | 77 ++--
>> net/netlabel/netlabel_unlabeled.h | 41 +-
>> 6 files changed, 875 insertions(+), 815 deletions(-)
>>
>> {snip}
>>
>>@@ -128,28 +156,44 @@ static int netlbl_cipsov4_add_std(u32 do
>> }
>> doi_def->type = CIPSO_V4_MAP_STD;
>>
>>- for (iter = 0; iter < num_tags; iter++) {
>>- if (msg_len < NETLBL_LEN_U8)
>>- goto add_std_failure;
>>- doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len);
>>- switch (doi_def->tags[iter]) {
>>- case CIPSO_V4_TAG_RBITMAP:
>>- break;
>>- default:
>>- goto add_std_failure;
>>+ nla_for_each_attr(nla_a,
>>+ nla_data(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
>>+ nla_len(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
>>+ nla_a_rem)
>
>
> You can use nla_for_each_nested() here.
Huh, look at that, guess I didn't scroll down far enough in the header
file :) Thanks.
>>+ if (nla_a->nla_type == NLBL_CIPSOV4_A_TAG) {
>>+ if (iter > CIPSO_V4_TAG_MAXCNT)
>>+ goto add_std_failure;
>>+ doi_def->tags[iter++] = nla_get_u8(nla_a);
>> }
>
>
> Perfectly validated against generic policy yet flexible, I
> like this a lot.
>
>
>
>>+ nla_for_each_attr(nla_a,
>>+ nla_data(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
>>+ nla_len(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
>>+ nla_a_rem)
>
>
> Could use nla_for_each_nested() here as well.
>
>
>>+ if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) {
>>+ nla_for_each_attr(nla_b,
>>+ nla_data(nla_a),
>>+ nla_len(nla_a),
>>+ nla_b_rem)
>
>
> ... and again :-)
>
>
>>+ switch (nla_b->nla_type) {
>>+ case NLBL_CIPSOV4_A_MLSLVLLOC:
>>+ if (nla_get_u32(nla_b) >=
>
>
> Attributes on this level are not yet validated.
>
Yes, you're right, same problem with the _MLSCAT attribute. Thanks.
>>+ doi_def->map.std->lvl.local_size)
>>+ doi_def->map.std->lvl.local_size =
>>+ nla_get_u32(nla_b) + 1;
>>+ break;
>>+ case NLBL_CIPSOV4_A_MLSLVLREM:
>>+ if (nla_get_u32(nla_b) >=
>>+ doi_def->map.std->lvl.cipso_size)
>>+ doi_def->map.std->lvl.cipso_size =
>>+ nla_get_u32(nla_b) + 1;
>>+ break;
>>+ }
>>+ }
>>@@ -168,68 +209,96 @@ static int netlbl_cipsov4_add_std(u32 do
>> ret_val = -ENOMEM;
>> goto add_std_failure;
>> }
>>+ nla_for_each_attr(nla_a,
>>+ nla_data(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
>>+ nla_len(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
>>+ nla_a_rem)
>
>
>>+ if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) {
>>+ nla_b = nla_find_nested(nla_a,
>>+ NLBL_CIPSOV4_A_MLSLVLLOC);
>>+ nla_c = nla_find_nested(nla_a,
>>+ NLBL_CIPSOV4_A_MLSLVLREM);
>
>
> Maybe find better names for nla_a and nla_b, would enhance readability
>
Fair enough.
>>+ if (nla_b == NULL || nla_c == NULL)
>>+ goto add_std_failure;
>>+ doi_def->map.std->lvl.local[nla_get_u32(nla_b)] =
>>+ nla_get_u32(nla_c);
>>+ doi_def->map.std->lvl.cipso[nla_get_u32(nla_c)] =
>>+ nla_get_u32(nla_b);
>>+ }
>>
>>- num_cats = netlbl_getinc_u32(&msg, &msg_len);
>>- doi_def->map.std->cat.local_size = netlbl_getinc_u32(&msg, &msg_len);
>>- if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS)
>>- goto add_std_failure;
>>- doi_def->map.std->cat.local = kcalloc(doi_def->map.std->cat.local_size,
>>+ if (info->attrs[NLBL_CIPSOV4_A_MLSCATLST]) {
>>+ if (nla_validate(
>>+ nla_data(info->attrs[NLBL_CIPSOV4_A_MLSCATLST]),
>>+ nla_len(info->attrs[NLBL_CIPSOV4_A_MLSCATLST]),
>>+ NLBL_CIPSOV4_A_MAX,
>>+ netlbl_cipsov4_genl_policy) != 0)
>
> We might want to add nla_validate_nested() to the interface as this seems
> to become a common usage.
Easy enough. I'll make that a separate patch in the next patchset.
>>@@ -276,21 +345,20 @@ static int netlbl_cipsov4_add_pass(u32 d
>> }
>> doi_def->type = CIPSO_V4_MAP_PASS;
>>
>>- for (iter = 0; iter < num_tags; iter++) {
>>- if (msg_len < NETLBL_LEN_U8)
>>- goto add_pass_failure;
>>- doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len);
>>- switch (doi_def->tags[iter]) {
>>- case CIPSO_V4_TAG_RBITMAP:
>>- break;
>>- default:
>>- goto add_pass_failure;
>>+ nla_for_each_attr(nla,
>>+ nla_data(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
>>+ nla_len(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
>>+ nla_rem)
>>+ if (nla->nla_type == NLBL_CIPSOV4_A_TAG) {
>>+ if (iter > CIPSO_V4_TAG_MAXCNT)
>>+ goto add_pass_failure;
>>+ doi_def->tags[iter++] = nla_get_u8(nla);
>> }
>
> This is duplicated code, put this into netlbl_cipsov4_get_tags()?
>
There is actually a little bit more than that too, I see your point.
I'll make a netlbl_cipsov4_add_common().
>>@@ -353,84 +408,237 @@ add_return:
>> * @info: the Generic NETLINK info block
>> *
>> * Description:
>>- * Process a user generated LIST message and respond accordingly. Returns
>>- * zero on success and negative values on error.
>>+ * Process a user generated LIST message and respond accordingly. While the
>>+ * response message generated by the kernel is straightforward, determining
>>+ * before hand the size of the buffer to allocate is not (we have to generate
>>+ * the message to know the size). In order to keep this function sane what we
>>+ * do is allocate a buffer of NLMSG_GOODSIZE and try to fit the response in
>>+ * that size, if we fail then we restart with a larger buffer and try again.
>>+ * We continue in this manner until we hit a limit of failed attempts then we
>>+ * give up and just send an error message. Returns zero on success and
>>+ * negative values on error.
>> *
>> */
>> static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info)
>> {
>>- int ret_val = -EINVAL;
>>+ int ret_val;
>>+ struct sk_buff *ans_skb = NULL;
>>+ u32 nlsze_mult = 1;
>>+ void *data;
>> u32 doi;
>>- struct nlattr *msg = netlbl_netlink_payload_data(skb);
>>- struct sk_buff *ans_skb;
>>+ struct nlattr *nla_a;
>>+ struct nlattr *nla_b;
>>+ struct cipso_v4_doi *doi_def;
>>+ u32 iter;
>>
>>- if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32)
>>+ if (!info->attrs[NLBL_CIPSOV4_A_DOI]) {
>>+ ret_val = -EINVAL;
>> goto list_failure;
>>+ }
>>
>>- doi = nla_get_u32(msg);
>>- ans_skb = cipso_v4_doi_dump(doi, NLMSG_SPACE(GENL_HDRLEN));
>>+list_start:
>>+ ans_skb = nlmsg_new(NLMSG_GOODSIZE * nlsze_mult, GFP_KERNEL);
>> if (ans_skb == NULL) {
>> ret_val = -ENOMEM;
>> goto list_failure;
>> }
>>- netlbl_netlink_hdr_push(ans_skb,
>>- info->snd_pid,
>>- 0,
>>- netlbl_cipsov4_gnl_family.id,
>>- NLBL_CIPSOV4_C_LIST);
>>+ data = netlbl_netlink_hdr_put(ans_skb,
>>+ info->snd_pid,
>>+ info->snd_seq,
>>+ netlbl_cipsov4_gnl_family.id,
>>+ 0,
>>+ NLBL_CIPSOV4_C_LIST);
>>+ if (data == NULL) {
>>+ ret_val = -ENOMEM;
>>+ goto list_failure;
>>+ }
>>+
>>+ doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
>>+
>>+ rcu_read_lock();
>>+ doi_def = cipso_v4_doi_getdef(doi);
>>+ if (doi_def == NULL) {
>>+ ret_val = -EINVAL;
>>+ goto list_failure;
>>+ }
>>+
>>+ ret_val = nla_put_u32(ans_skb, NLBL_CIPSOV4_A_MTYPE, doi_def->type);
>>+ if (ret_val != 0)
>>+ goto list_failure_lock;
>>+
>>+ nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_TAGLST);
>>+ if (nla_a == NULL) {
>>+ ret_val = -ENOMEM;
>>+ goto list_failure_lock;
>>+ }
>>+ for (iter = 0;
>>+ iter < CIPSO_V4_TAG_MAXCNT &&
>>+ doi_def->tags[iter] != CIPSO_V4_TAG_INVALID;
>>+ iter++) {
>>+ ret_val = nla_put_u8(ans_skb,
>>+ NLBL_CIPSOV4_A_TAG,
>>+ doi_def->tags[iter]);
>>+ if (ret_val != 0)
>>+ goto list_failure_lock;
>>+ }
>>+ nla_nest_end(ans_skb, nla_a);
>>
>>- ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
>>+ switch (doi_def->type) {
>>+ case CIPSO_V4_MAP_STD:
>>+ nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVLLST);
>>+ if (nla_a == NULL) {
>>+ ret_val = -ENOMEM;
>>+ goto list_failure_lock;
>>+ }
>>+ for (iter = 0;
>>+ iter < doi_def->map.std->lvl.local_size;
>>+ iter++) {
>>+ if (doi_def->map.std->lvl.local[iter] ==
>>+ CIPSO_V4_INV_LVL)
>>+ continue;
>
>
> Can you estimate the number of entries being dumped here and in the cat
> list below?
>
It's too hard to come up with a reasonable estimate without going
through the entire list before hand, which in previous messages (might
of been off-list) you pointed out as a bad thing. If you would prefer I
can go back to doing it that way?
>>+
>>+ nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVL);
>>+ if (nla_b == NULL) {
>>+ ret_val = -ENOMEM;
>>+ goto list_retry;
>>+ }
>>+ ret_val = nla_put_u32(ans_skb,
>>+ NLBL_CIPSOV4_A_MLSLVLLOC,
>>+ iter);
>>+ if (ret_val != 0)
>>+ goto list_retry;
>>+ ret_val = nla_put_u32(ans_skb,
>>+ NLBL_CIPSOV4_A_MLSLVLREM,
>>+ doi_def->map.std->lvl.local[iter]);
>>+ if (ret_val != 0)
>>+ goto list_retry;
>>+ nla_nest_end(ans_skb, nla_b);
>>+ }
>>+ nla_nest_end(ans_skb, nla_a);
>>+
>>+ nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCATLST);
>>+ if (nla_a == NULL) {
>>+ ret_val = -ENOMEM;
>>+ goto list_retry;
>>+ }
>>+ for (iter = 0;
>>+ iter < doi_def->map.std->cat.local_size;
>>+ iter++) {
>>+ if (doi_def->map.std->cat.local[iter] ==
>>+ CIPSO_V4_INV_CAT)
>>+ continue;
>>+
>>+ nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCAT);
>>+ if (nla_b == NULL) {
>>+ ret_val = -ENOMEM;
>>+ goto list_retry;
>>+ }
>>+ ret_val = nla_put_u32(ans_skb,
>>+ NLBL_CIPSOV4_A_MLSCATLOC,
>>+ iter);
>>+ if (ret_val != 0)
>>+ goto list_retry;
>>+ ret_val = nla_put_u32(ans_skb,
>>+ NLBL_CIPSOV4_A_MLSCATREM,
>>+ doi_def->map.std->cat.local[iter]);
>>+ if (ret_val != 0)
>>+ goto list_retry;
>>+ nla_nest_end(ans_skb, nla_b);
>>+ }
>>+ nla_nest_end(ans_skb, nla_a);
>>+
>>+ break;
>>+ }
>>+ rcu_read_unlock();
>
> What I meant in the previous posting is to put genlmsg_end() in here
> like the rest of the code to be clear and symmetric.
Okay, I put it there because it was a common trend in the code, i.e. end
the message then do a write, I thought I would combine them. I'll split
it back out.
> The rest of the code has simliar issues, nevertheless this looks
> really great. Everything is extendable and relatively easy to
> maintain. This should definitely go into 2.6.19. Good work.
Thanks for your patience as I got the hang of the genetlink stuff. I'll
make the changes you suggested and get a new version out soon.
--
paul moore
linux security @ hp
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 5/6] NetLabel: rework the Netlink attribute handling (part 2)
2006-09-25 14:13 ` Paul Moore
@ 2006-09-25 15:06 ` Thomas Graf
2006-09-25 15:42 ` Paul Moore
0 siblings, 1 reply; 14+ messages in thread
From: Thomas Graf @ 2006-09-25 15:06 UTC (permalink / raw)
To: Paul Moore; +Cc: selinux, netdev, sds, jmorris
* Paul Moore <paul.moore@hp.com> 2006-09-25 10:13
> >>- ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
> >>+ switch (doi_def->type) {
> >>+ case CIPSO_V4_MAP_STD:
> >>+ nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVLLST);
> >>+ if (nla_a == NULL) {
> >>+ ret_val = -ENOMEM;
> >>+ goto list_failure_lock;
> >>+ }
> >>+ for (iter = 0;
> >>+ iter < doi_def->map.std->lvl.local_size;
> >>+ iter++) {
> >>+ if (doi_def->map.std->lvl.local[iter] ==
> >>+ CIPSO_V4_INV_LVL)
> >>+ continue;
> >
> >
> > Can you estimate the number of entries being dumped here and in the cat
> > list below?
> >
>
> It's too hard to come up with a reasonable estimate without going
> through the entire list before hand, which in previous messages (might
> of been off-list) you pointed out as a bad thing. If you would prefer I
> can go back to doing it that way?
Sorry, I didn't make myself clear. I didn't mean to estimate the
size of the message. The way you're doing it right now is perfectly
fine. I'm interested in a estimate on how many items are being dumped
in practice. Less than 1K or a couple of K?
High order allocations are likely to fail if under pressure while
using dumpit() allows to reuse memory ressources.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 5/6] NetLabel: rework the Netlink attribute handling (part 2)
2006-09-25 15:06 ` Thomas Graf
@ 2006-09-25 15:42 ` Paul Moore
0 siblings, 0 replies; 14+ messages in thread
From: Paul Moore @ 2006-09-25 15:42 UTC (permalink / raw)
To: Thomas Graf; +Cc: selinux, netdev, sds, jmorris
Thomas Graf wrote:
> * Paul Moore <paul.moore@hp.com> 2006-09-25 10:13
>
>>>>- ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
>>>>+ switch (doi_def->type) {
>>>>+ case CIPSO_V4_MAP_STD:
>>>>+ nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVLLST);
>>>>+ if (nla_a == NULL) {
>>>>+ ret_val = -ENOMEM;
>>>>+ goto list_failure_lock;
>>>>+ }
>>>>+ for (iter = 0;
>>>>+ iter < doi_def->map.std->lvl.local_size;
>>>>+ iter++) {
>>>>+ if (doi_def->map.std->lvl.local[iter] ==
>>>>+ CIPSO_V4_INV_LVL)
>>>>+ continue;
>>>
>>>
>>>Can you estimate the number of entries being dumped here and in the cat
>>>list below?
>>>
>>
>>It's too hard to come up with a reasonable estimate without going
>>through the entire list before hand, which in previous messages (might
>>of been off-list) you pointed out as a bad thing. If you would prefer I
>>can go back to doing it that way?
>
> Sorry, I didn't make myself clear. I didn't mean to estimate the
> size of the message. The way you're doing it right now is perfectly
> fine. I'm interested in a estimate on how many items are being dumped
> in practice. Less than 1K or a couple of K?
>
> High order allocations are likely to fail if under pressure while
> using dumpit() allows to reuse memory ressources.
It's hard to get a good idea of the likely usage scenario as I'm not
sure how users will want to configure NetLabel. However, there is a
possibility of this growing larger than NLMSG_GOODSIZE, which makes
things a bit more difficult. From what I can see dumpit() requires the
message be within NLMSG_GOODSIZE while a doit() response can be of
arbitrary length; this is why I chose a doit() response. Even if the
system is under memory pressure I think a failure here is okay as this
is not what I would consider a critical message.
--
paul moore
linux security @ hp
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2006-09-25 15:42 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-09-21 16:57 [PATCH 0/6] NetLabel fixes and reworked Netlink interface paul.moore
2006-09-21 16:57 ` [PATCH 1/6] NetLabel: correct improper handling of non-NetLabel peer contexts paul.moore
2006-09-21 18:08 ` James Morris
2006-09-21 18:28 ` Paul Moore
2006-09-21 16:57 ` [PATCH 2/6] NetLabel: make the CIPSOv4 cache spinlocks bottom half safe paul.moore
2006-09-21 16:57 ` [PATCH 3/6] NetLabel: change the SELinux permissions paul.moore
2006-09-21 16:57 ` [PATCH 4/6] NetLabel: rework the Netlink attribute handling (part 1) paul.moore
2006-09-25 9:12 ` Thomas Graf
2006-09-21 16:57 ` [PATCH 5/6] NetLabel: rework the Netlink attribute handling (part 2) paul.moore
2006-09-25 9:43 ` Thomas Graf
2006-09-25 14:13 ` Paul Moore
2006-09-25 15:06 ` Thomas Graf
2006-09-25 15:42 ` Paul Moore
2006-09-21 16:57 ` [PATCH 6/6] NetLabel: update docs with website information paul.moore
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).