aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/cipso_ipv4.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/cipso_ipv4.c')
-rw-r--r--net/ipv4/cipso_ipv4.c222
1 files changed, 183 insertions, 39 deletions
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index bf87eddfec30..e13d6dbb66ab 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -13,7 +13,7 @@
13 */ 13 */
14 14
15/* 15/*
16 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 16 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
17 * 17 *
18 * This program is free software; you can redistribute it and/or modify 18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by 19 * it under the terms of the GNU General Public License as published by
@@ -1665,48 +1665,27 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
1665} 1665}
1666 1666
1667/** 1667/**
1668 * cipso_v4_sock_setattr - Add a CIPSO option to a socket 1668 * cipso_v4_genopt - Generate a CIPSO option
1669 * @sk: the socket 1669 * @buf: the option buffer
1670 * @buf_len: the size of opt_buf
1670 * @doi_def: the CIPSO DOI to use 1671 * @doi_def: the CIPSO DOI to use
1671 * @secattr: the specific security attributes of the socket 1672 * @secattr: the security attributes
1672 * 1673 *
1673 * Description: 1674 * Description:
1674 * Set the CIPSO option on the given socket using the DOI definition and 1675 * Generate a CIPSO option using the DOI definition and security attributes
1675 * security attributes passed to the function. This function requires 1676 * passed to the function. Returns the length of the option on success and
1676 * exclusive access to @sk, which means it either needs to be in the 1677 * negative values on failure.
1677 * process of being created or locked. Returns zero on success and negative
1678 * values on failure.
1679 * 1678 *
1680 */ 1679 */
1681int cipso_v4_sock_setattr(struct sock *sk, 1680static int cipso_v4_genopt(unsigned char *buf, u32 buf_len,
1682 const struct cipso_v4_doi *doi_def, 1681 const struct cipso_v4_doi *doi_def,
1683 const struct netlbl_lsm_secattr *secattr) 1682 const struct netlbl_lsm_secattr *secattr)
1684{ 1683{
1685 int ret_val = -EPERM; 1684 int ret_val;
1686 u32 iter; 1685 u32 iter;
1687 unsigned char *buf;
1688 u32 buf_len = 0;
1689 u32 opt_len;
1690 struct ip_options *opt = NULL;
1691 struct inet_sock *sk_inet;
1692 struct inet_connection_sock *sk_conn;
1693
1694 /* In the case of sock_create_lite(), the sock->sk field is not
1695 * defined yet but it is not a problem as the only users of these
1696 * "lite" PF_INET sockets are functions which do an accept() call
1697 * afterwards so we will label the socket as part of the accept(). */
1698 if (sk == NULL)
1699 return 0;
1700 1686
1701 /* We allocate the maximum CIPSO option size here so we are probably 1687 if (buf_len <= CIPSO_V4_HDR_LEN)
1702 * being a little wasteful, but it makes our life _much_ easier later 1688 return -ENOSPC;
1703 * on and after all we are only talking about 40 bytes. */
1704 buf_len = CIPSO_V4_OPT_LEN_MAX;
1705 buf = kmalloc(buf_len, GFP_ATOMIC);
1706 if (buf == NULL) {
1707 ret_val = -ENOMEM;
1708 goto socket_setattr_failure;
1709 }
1710 1689
1711 /* XXX - This code assumes only one tag per CIPSO option which isn't 1690 /* XXX - This code assumes only one tag per CIPSO option which isn't
1712 * really a good assumption to make but since we only support the MAC 1691 * really a good assumption to make but since we only support the MAC
@@ -1734,8 +1713,7 @@ int cipso_v4_sock_setattr(struct sock *sk,
1734 buf_len - CIPSO_V4_HDR_LEN); 1713 buf_len - CIPSO_V4_HDR_LEN);
1735 break; 1714 break;
1736 default: 1715 default:
1737 ret_val = -EPERM; 1716 return -EPERM;
1738 goto socket_setattr_failure;
1739 } 1717 }
1740 1718
1741 iter++; 1719 iter++;
@@ -1743,9 +1721,58 @@ int cipso_v4_sock_setattr(struct sock *sk,
1743 iter < CIPSO_V4_TAG_MAXCNT && 1721 iter < CIPSO_V4_TAG_MAXCNT &&
1744 doi_def->tags[iter] != CIPSO_V4_TAG_INVALID); 1722 doi_def->tags[iter] != CIPSO_V4_TAG_INVALID);
1745 if (ret_val < 0) 1723 if (ret_val < 0)
1746 goto socket_setattr_failure; 1724 return ret_val;
1747 cipso_v4_gentag_hdr(doi_def, buf, ret_val); 1725 cipso_v4_gentag_hdr(doi_def, buf, ret_val);
1748 buf_len = CIPSO_V4_HDR_LEN + ret_val; 1726 return CIPSO_V4_HDR_LEN + ret_val;
1727}
1728
1729/**
1730 * cipso_v4_sock_setattr - Add a CIPSO option to a socket
1731 * @sk: the socket
1732 * @doi_def: the CIPSO DOI to use
1733 * @secattr: the specific security attributes of the socket
1734 *
1735 * Description:
1736 * Set the CIPSO option on the given socket using the DOI definition and
1737 * security attributes passed to the function. This function requires
1738 * exclusive access to @sk, which means it either needs to be in the
1739 * process of being created or locked. Returns zero on success and negative
1740 * values on failure.
1741 *
1742 */
1743int cipso_v4_sock_setattr(struct sock *sk,
1744 const struct cipso_v4_doi *doi_def,
1745 const struct netlbl_lsm_secattr *secattr)
1746{
1747 int ret_val = -EPERM;
1748 unsigned char *buf = NULL;
1749 u32 buf_len;
1750 u32 opt_len;
1751 struct ip_options *opt = NULL;
1752 struct inet_sock *sk_inet;
1753 struct inet_connection_sock *sk_conn;
1754
1755 /* In the case of sock_create_lite(), the sock->sk field is not
1756 * defined yet but it is not a problem as the only users of these
1757 * "lite" PF_INET sockets are functions which do an accept() call
1758 * afterwards so we will label the socket as part of the accept(). */
1759 if (sk == NULL)
1760 return 0;
1761
1762 /* We allocate the maximum CIPSO option size here so we are probably
1763 * being a little wasteful, but it makes our life _much_ easier later
1764 * on and after all we are only talking about 40 bytes. */
1765 buf_len = CIPSO_V4_OPT_LEN_MAX;
1766 buf = kmalloc(buf_len, GFP_ATOMIC);
1767 if (buf == NULL) {
1768 ret_val = -ENOMEM;
1769 goto socket_setattr_failure;
1770 }
1771
1772 ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
1773 if (ret_val < 0)
1774 goto socket_setattr_failure;
1775 buf_len = ret_val;
1749 1776
1750 /* We can't use ip_options_get() directly because it makes a call to 1777 /* We can't use ip_options_get() directly because it makes a call to
1751 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and 1778 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
@@ -1854,6 +1881,123 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
1854} 1881}
1855 1882
1856/** 1883/**
1884 * cipso_v4_skbuff_setattr - Set the CIPSO option on a packet
1885 * @skb: the packet
1886 * @secattr: the security attributes
1887 *
1888 * Description:
1889 * Set the CIPSO option on the given packet based on the security attributes.
1890 * Returns a pointer to the IP header on success and NULL on failure.
1891 *
1892 */
1893int cipso_v4_skbuff_setattr(struct sk_buff *skb,
1894 const struct cipso_v4_doi *doi_def,
1895 const struct netlbl_lsm_secattr *secattr)
1896{
1897 int ret_val;
1898 struct iphdr *iph;
1899 struct ip_options *opt = &IPCB(skb)->opt;
1900 unsigned char buf[CIPSO_V4_OPT_LEN_MAX];
1901 u32 buf_len = CIPSO_V4_OPT_LEN_MAX;
1902 u32 opt_len;
1903 int len_delta;
1904
1905 buf_len = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
1906 if (buf_len < 0)
1907 return buf_len;
1908 opt_len = (buf_len + 3) & ~3;
1909
1910 /* we overwrite any existing options to ensure that we have enough
1911 * room for the CIPSO option, the reason is that we _need_ to guarantee
1912 * that the security label is applied to the packet - we do the same
1913 * thing when using the socket options and it hasn't caused a problem,
1914 * if we need to we can always revisit this choice later */
1915
1916 len_delta = opt_len - opt->optlen;
1917 /* if we don't ensure enough headroom we could panic on the skb_push()
1918 * call below so make sure we have enough, we are also "mangling" the
1919 * packet so we should probably do a copy-on-write call anyway */
1920 ret_val = skb_cow(skb, skb_headroom(skb) + len_delta);
1921 if (ret_val < 0)
1922 return ret_val;
1923
1924 if (len_delta > 0) {
1925 /* we assume that the header + opt->optlen have already been
1926 * "pushed" in ip_options_build() or similar */
1927 iph = ip_hdr(skb);
1928 skb_push(skb, len_delta);
1929 memmove((char *)iph - len_delta, iph, iph->ihl << 2);
1930 skb_reset_network_header(skb);
1931 iph = ip_hdr(skb);
1932 } else if (len_delta < 0) {
1933 iph = ip_hdr(skb);
1934 memset(iph + 1, IPOPT_NOP, opt->optlen);
1935 } else
1936 iph = ip_hdr(skb);
1937
1938 if (opt->optlen > 0)
1939 memset(opt, 0, sizeof(*opt));
1940 opt->optlen = opt_len;
1941 opt->cipso = sizeof(struct iphdr);
1942 opt->is_changed = 1;
1943
1944 /* we have to do the following because we are being called from a
1945 * netfilter hook which means the packet already has had the header
1946 * fields populated and the checksum calculated - yes this means we
1947 * are doing more work than needed but we do it to keep the core
1948 * stack clean and tidy */
1949 memcpy(iph + 1, buf, buf_len);
1950 if (opt_len > buf_len)
1951 memset((char *)(iph + 1) + buf_len, 0, opt_len - buf_len);
1952 if (len_delta != 0) {
1953 iph->ihl = 5 + (opt_len >> 2);
1954 iph->tot_len = htons(skb->len);
1955 }
1956 ip_send_check(iph);
1957
1958 return 0;
1959}
1960
1961/**
1962 * cipso_v4_skbuff_delattr - Delete any CIPSO options from a packet
1963 * @skb: the packet
1964 *
1965 * Description:
1966 * Removes any and all CIPSO options from the given packet. Returns zero on
1967 * success, negative values on failure.
1968 *
1969 */
1970int cipso_v4_skbuff_delattr(struct sk_buff *skb)
1971{
1972 int ret_val;
1973 struct iphdr *iph;
1974 struct ip_options *opt = &IPCB(skb)->opt;
1975 unsigned char *cipso_ptr;
1976
1977 if (opt->cipso == 0)
1978 return 0;
1979
1980 /* since we are changing the packet we should make a copy */
1981 ret_val = skb_cow(skb, skb_headroom(skb));
1982 if (ret_val < 0)
1983 return ret_val;
1984
1985 /* the easiest thing to do is just replace the cipso option with noop
1986 * options since we don't change the size of the packet, although we
1987 * still need to recalculate the checksum */
1988
1989 iph = ip_hdr(skb);
1990 cipso_ptr = (unsigned char *)iph + opt->cipso;
1991 memset(cipso_ptr, IPOPT_NOOP, cipso_ptr[1]);
1992 opt->cipso = 0;
1993 opt->is_changed = 1;
1994
1995 ip_send_check(iph);
1996
1997 return 0;
1998}
1999
2000/**
1857 * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option 2001 * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option
1858 * @skb: the packet 2002 * @skb: the packet
1859 * @secattr: the security attributes 2003 * @secattr: the security attributes