Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 113659
b: refs/heads/master
c: 948bf85
h: refs/heads/master
i:
  113657: 9744006
  113655: f203f34
v: v3
  • Loading branch information
Paul Moore committed Oct 10, 2008
1 parent 6d50ba8 commit e1dffb2
Show file tree
Hide file tree
Showing 9 changed files with 394 additions and 43 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 63c41688743760631188cf0f4ae986a6793ccb0a
refs/heads/master: 948bf85c1bc9a84754786a9d5dd99b7ecc46451e
16 changes: 16 additions & 0 deletions trunk/include/net/cipso_ipv4.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ int cipso_v4_sock_setattr(struct sock *sk,
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_skbuff_setattr(struct sk_buff *skb,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr);
int cipso_v4_skbuff_delattr(struct sk_buff *skb);
int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
struct netlbl_lsm_secattr *secattr);
int cipso_v4_validate(unsigned char **option);
Expand All @@ -232,6 +236,18 @@ static inline int cipso_v4_sock_getattr(struct sock *sk,
return -ENOSYS;
}

static inline int cipso_v4_skbuff_setattr(struct sk_buff *skb,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
}

static inline int cipso_v4_skbuff_delattr(struct sk_buff *skb)
{
return -ENOSYS;
}

static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
struct netlbl_lsm_secattr *secattr)
{
Expand Down
9 changes: 9 additions & 0 deletions trunk/include/net/netlabel.h
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,9 @@ int netlbl_sock_setattr(struct sock *sk,
const struct netlbl_lsm_secattr *secattr);
int netlbl_sock_getattr(struct sock *sk,
struct netlbl_lsm_secattr *secattr);
int netlbl_skbuff_setattr(struct sk_buff *skb,
u16 family,
const struct netlbl_lsm_secattr *secattr);
int netlbl_skbuff_getattr(const struct sk_buff *skb,
u16 family,
struct netlbl_lsm_secattr *secattr);
Expand Down Expand Up @@ -451,6 +454,12 @@ static inline int netlbl_sock_getattr(struct sock *sk,
{
return -ENOSYS;
}
static inline int netlbl_skbuff_setattr(struct sk_buff *skb,
u16 family,
const struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
}
static inline int netlbl_skbuff_getattr(const struct sk_buff *skb,
u16 family,
struct netlbl_lsm_secattr *secattr)
Expand Down
222 changes: 183 additions & 39 deletions trunk/net/ipv4/cipso_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*/

/*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -1665,48 +1665,27 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
}

/**
* cipso_v4_sock_setattr - Add a CIPSO option to a socket
* @sk: the socket
* cipso_v4_genopt - Generate a CIPSO option
* @buf: the option buffer
* @buf_len: the size of opt_buf
* @doi_def: the CIPSO DOI to use
* @secattr: the specific security attributes of the socket
* @secattr: the security attributes
*
* Description:
* Set the CIPSO option on the given socket using the DOI definition and
* security attributes passed to the function. This function requires
* exclusive access to @sk, which means it either needs to be in the
* process of being created or locked. Returns zero on success and negative
* values on failure.
* Generate a CIPSO option using the DOI definition and security attributes
* passed to the function. Returns the length of the option on success and
* negative values on failure.
*
*/
int cipso_v4_sock_setattr(struct sock *sk,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr)
static int cipso_v4_genopt(unsigned char *buf, u32 buf_len,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr)
{
int ret_val = -EPERM;
int ret_val;
u32 iter;
unsigned char *buf;
u32 buf_len = 0;
u32 opt_len;
struct ip_options *opt = NULL;
struct inet_sock *sk_inet;
struct inet_connection_sock *sk_conn;

/* In the case of sock_create_lite(), the sock->sk field is not
* defined yet but it is not a problem as the only users of these
* "lite" PF_INET sockets are functions which do an accept() call
* afterwards so we will label the socket as part of the accept(). */
if (sk == NULL)
return 0;

/* We allocate the maximum CIPSO option size here so we are probably
* being a little wasteful, but it makes our life _much_ easier later
* on and after all we are only talking about 40 bytes. */
buf_len = CIPSO_V4_OPT_LEN_MAX;
buf = kmalloc(buf_len, GFP_ATOMIC);
if (buf == NULL) {
ret_val = -ENOMEM;
goto socket_setattr_failure;
}
if (buf_len <= CIPSO_V4_HDR_LEN)
return -ENOSPC;

/* XXX - This code assumes only one tag per CIPSO option which isn't
* really a good assumption to make but since we only support the MAC
Expand Down Expand Up @@ -1734,18 +1713,66 @@ int cipso_v4_sock_setattr(struct sock *sk,
buf_len - CIPSO_V4_HDR_LEN);
break;
default:
ret_val = -EPERM;
goto socket_setattr_failure;
return -EPERM;
}

iter++;
} while (ret_val < 0 &&
iter < CIPSO_V4_TAG_MAXCNT &&
doi_def->tags[iter] != CIPSO_V4_TAG_INVALID);
if (ret_val < 0)
goto socket_setattr_failure;
return ret_val;
cipso_v4_gentag_hdr(doi_def, buf, ret_val);
buf_len = CIPSO_V4_HDR_LEN + ret_val;
return CIPSO_V4_HDR_LEN + ret_val;
}

/**
* cipso_v4_sock_setattr - Add a CIPSO option to a socket
* @sk: the socket
* @doi_def: the CIPSO DOI to use
* @secattr: the specific security attributes of the socket
*
* Description:
* Set the CIPSO option on the given socket using the DOI definition and
* security attributes passed to the function. This function requires
* exclusive access to @sk, which means it either needs to be in the
* process of being created or locked. Returns zero on success and negative
* values on failure.
*
*/
int cipso_v4_sock_setattr(struct sock *sk,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr)
{
int ret_val = -EPERM;
unsigned char *buf = NULL;
u32 buf_len;
u32 opt_len;
struct ip_options *opt = NULL;
struct inet_sock *sk_inet;
struct inet_connection_sock *sk_conn;

/* In the case of sock_create_lite(), the sock->sk field is not
* defined yet but it is not a problem as the only users of these
* "lite" PF_INET sockets are functions which do an accept() call
* afterwards so we will label the socket as part of the accept(). */
if (sk == NULL)
return 0;

/* We allocate the maximum CIPSO option size here so we are probably
* being a little wasteful, but it makes our life _much_ easier later
* on and after all we are only talking about 40 bytes. */
buf_len = CIPSO_V4_OPT_LEN_MAX;
buf = kmalloc(buf_len, GFP_ATOMIC);
if (buf == NULL) {
ret_val = -ENOMEM;
goto socket_setattr_failure;
}

ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
if (ret_val < 0)
goto socket_setattr_failure;
buf_len = ret_val;

/* We can't use ip_options_get() directly because it makes a call to
* ip_options_get_alloc() which allocates memory with GFP_KERNEL and
Expand Down Expand Up @@ -1853,6 +1880,123 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
secattr);
}

/**
* cipso_v4_skbuff_setattr - Set the CIPSO option on a packet
* @skb: the packet
* @secattr: the security attributes
*
* Description:
* Set the CIPSO option on the given packet based on the security attributes.
* Returns a pointer to the IP header on success and NULL on failure.
*
*/
int cipso_v4_skbuff_setattr(struct sk_buff *skb,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr)
{
int ret_val;
struct iphdr *iph;
struct ip_options *opt = &IPCB(skb)->opt;
unsigned char buf[CIPSO_V4_OPT_LEN_MAX];
u32 buf_len = CIPSO_V4_OPT_LEN_MAX;
u32 opt_len;
int len_delta;

buf_len = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
if (buf_len < 0)
return buf_len;
opt_len = (buf_len + 3) & ~3;

/* we overwrite any existing options to ensure that we have enough
* room for the CIPSO option, the reason is that we _need_ to guarantee
* that the security label is applied to the packet - we do the same
* thing when using the socket options and it hasn't caused a problem,
* if we need to we can always revisit this choice later */

len_delta = opt_len - opt->optlen;
/* if we don't ensure enough headroom we could panic on the skb_push()
* call below so make sure we have enough, we are also "mangling" the
* packet so we should probably do a copy-on-write call anyway */
ret_val = skb_cow(skb, skb_headroom(skb) + len_delta);
if (ret_val < 0)
return ret_val;

if (len_delta > 0) {
/* we assume that the header + opt->optlen have already been
* "pushed" in ip_options_build() or similar */
iph = ip_hdr(skb);
skb_push(skb, len_delta);
memmove((char *)iph - len_delta, iph, iph->ihl << 2);
skb_reset_network_header(skb);
iph = ip_hdr(skb);
} else if (len_delta < 0) {
iph = ip_hdr(skb);
memset(iph + 1, IPOPT_NOP, opt->optlen);
} else
iph = ip_hdr(skb);

if (opt->optlen > 0)
memset(opt, 0, sizeof(*opt));
opt->optlen = opt_len;
opt->cipso = sizeof(struct iphdr);
opt->is_changed = 1;

/* we have to do the following because we are being called from a
* netfilter hook which means the packet already has had the header
* fields populated and the checksum calculated - yes this means we
* are doing more work than needed but we do it to keep the core
* stack clean and tidy */
memcpy(iph + 1, buf, buf_len);
if (opt_len > buf_len)
memset((char *)(iph + 1) + buf_len, 0, opt_len - buf_len);
if (len_delta != 0) {
iph->ihl = 5 + (opt_len >> 2);
iph->tot_len = htons(skb->len);
}
ip_send_check(iph);

return 0;
}

/**
* cipso_v4_skbuff_delattr - Delete any CIPSO options from a packet
* @skb: the packet
*
* Description:
* Removes any and all CIPSO options from the given packet. Returns zero on
* success, negative values on failure.
*
*/
int cipso_v4_skbuff_delattr(struct sk_buff *skb)
{
int ret_val;
struct iphdr *iph;
struct ip_options *opt = &IPCB(skb)->opt;
unsigned char *cipso_ptr;

if (opt->cipso == 0)
return 0;

/* since we are changing the packet we should make a copy */
ret_val = skb_cow(skb, skb_headroom(skb));
if (ret_val < 0)
return ret_val;

/* the easiest thing to do is just replace the cipso option with noop
* options since we don't change the size of the packet, although we
* still need to recalculate the checksum */

iph = ip_hdr(skb);
cipso_ptr = (unsigned char *)iph + opt->cipso;
memset(cipso_ptr, IPOPT_NOOP, cipso_ptr[1]);
opt->cipso = 0;
opt->is_changed = 1;

ip_send_check(iph);

return 0;
}

/**
* cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option
* @skb: the packet
Expand Down
60 changes: 60 additions & 0 deletions trunk/net/netlabel/netlabel_kapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,66 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
return cipso_v4_sock_getattr(sk, secattr);
}

/**
* netlbl_skbuff_setattr - Label a packet using the correct protocol
* @skb: the packet
* @family: protocol family
* @secattr: the security attributes
*
* Description:
* Attach the correct label to the given packet using the security attributes
* specified in @secattr. Returns zero on success, negative values on failure.
*
*/
int netlbl_skbuff_setattr(struct sk_buff *skb,
u16 family,
const struct netlbl_lsm_secattr *secattr)
{
int ret_val;
struct iphdr *hdr4;
struct netlbl_domaddr4_map *af4_entry;

rcu_read_lock();
switch (family) {
case AF_INET:
hdr4 = ip_hdr(skb);
af4_entry = netlbl_domhsh_getentry_af4(secattr->domain,
hdr4->daddr);
if (af4_entry == NULL) {
ret_val = -ENOENT;
goto skbuff_setattr_return;
}
switch (af4_entry->type) {
case NETLBL_NLTYPE_CIPSOV4:
ret_val = cipso_v4_skbuff_setattr(skb,
af4_entry->type_def.cipsov4,
secattr);
break;
case NETLBL_NLTYPE_UNLABELED:
/* just delete the protocols we support for right now
* but we could remove other protocols if needed */
ret_val = cipso_v4_skbuff_delattr(skb);
break;
default:
ret_val = -ENOENT;
}
break;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case AF_INET6:
/* since we don't support any IPv6 labeling protocols right
* now we can optimize everything away until we do */
ret_val = 0;
break;
#endif /* IPv6 */
default:
ret_val = 0;
}

skbuff_setattr_return:
rcu_read_unlock();
return ret_val;
}

/**
* netlbl_skbuff_getattr - Determine the security attributes of a packet
* @skb: the packet
Expand Down
Loading

0 comments on commit e1dffb2

Please sign in to comment.