aboutsummaryrefslogtreecommitdiffstats
path: root/security/smack/smack_lsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/smack/smack_lsm.c')
-rw-r--r--security/smack/smack_lsm.c185
1 files changed, 44 insertions, 141 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 5f80075d7713..952b1f41fc78 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -30,7 +30,6 @@
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/mutex.h> 31#include <linux/mutex.h>
32#include <linux/pipe_fs_i.h> 32#include <linux/pipe_fs_i.h>
33#include <net/netlabel.h>
34#include <net/cipso_ipv4.h> 33#include <net/cipso_ipv4.h>
35#include <linux/audit.h> 34#include <linux/audit.h>
36#include <linux/magic.h> 35#include <linux/magic.h>
@@ -57,16 +56,23 @@
57static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp) 56static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp)
58{ 57{
59 int rc; 58 int rc;
60 char in[SMK_LABELLEN]; 59 char *buffer;
60 char *result = NULL;
61 61
62 if (ip->i_op->getxattr == NULL) 62 if (ip->i_op->getxattr == NULL)
63 return NULL; 63 return NULL;
64 64
65 rc = ip->i_op->getxattr(dp, name, in, SMK_LABELLEN); 65 buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
66 if (rc < 0) 66 if (buffer == NULL)
67 return NULL; 67 return NULL;
68 68
69 return smk_import(in, rc); 69 rc = ip->i_op->getxattr(dp, name, buffer, SMK_LONGLABEL);
70 if (rc > 0)
71 result = smk_import(buffer, rc);
72
73 kfree(buffer);
74
75 return result;
70} 76}
71 77
72/** 78/**
@@ -825,7 +831,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
825 * check label validity here so import wont fail on 831 * check label validity here so import wont fail on
826 * post_setxattr 832 * post_setxattr
827 */ 833 */
828 if (size == 0 || size >= SMK_LABELLEN || 834 if (size == 0 || size >= SMK_LONGLABEL ||
829 smk_import(value, size) == NULL) 835 smk_import(value, size) == NULL)
830 rc = -EINVAL; 836 rc = -EINVAL;
831 } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { 837 } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
@@ -1824,65 +1830,6 @@ static char *smack_host_label(struct sockaddr_in *sip)
1824} 1830}
1825 1831
1826/** 1832/**
1827 * smack_set_catset - convert a capset to netlabel mls categories
1828 * @catset: the Smack categories
1829 * @sap: where to put the netlabel categories
1830 *
1831 * Allocates and fills attr.mls.cat
1832 */
1833static void smack_set_catset(char *catset, struct netlbl_lsm_secattr *sap)
1834{
1835 unsigned char *cp;
1836 unsigned char m;
1837 int cat;
1838 int rc;
1839 int byte;
1840
1841 if (!catset)
1842 return;
1843
1844 sap->flags |= NETLBL_SECATTR_MLS_CAT;
1845 sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
1846 sap->attr.mls.cat->startbit = 0;
1847
1848 for (cat = 1, cp = catset, byte = 0; byte < SMK_LABELLEN; cp++, byte++)
1849 for (m = 0x80; m != 0; m >>= 1, cat++) {
1850 if ((m & *cp) == 0)
1851 continue;
1852 rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat,
1853 cat, GFP_ATOMIC);
1854 }
1855}
1856
1857/**
1858 * smack_to_secattr - fill a secattr from a smack value
1859 * @smack: the smack value
1860 * @nlsp: where the result goes
1861 *
1862 * Casey says that CIPSO is good enough for now.
1863 * It can be used to effect.
1864 * It can also be abused to effect when necessary.
1865 * Apologies to the TSIG group in general and GW in particular.
1866 */
1867static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
1868{
1869 struct smack_cipso cipso;
1870 int rc;
1871
1872 nlsp->domain = smack;
1873 nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
1874
1875 rc = smack_to_cipso(smack, &cipso);
1876 if (rc == 0) {
1877 nlsp->attr.mls.lvl = cipso.smk_level;
1878 smack_set_catset(cipso.smk_catset, nlsp);
1879 } else {
1880 nlsp->attr.mls.lvl = smack_cipso_direct;
1881 smack_set_catset(smack, nlsp);
1882 }
1883}
1884
1885/**
1886 * smack_netlabel - Set the secattr on a socket 1833 * smack_netlabel - Set the secattr on a socket
1887 * @sk: the socket 1834 * @sk: the socket
1888 * @labeled: socket label scheme 1835 * @labeled: socket label scheme
@@ -1894,8 +1841,8 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
1894 */ 1841 */
1895static int smack_netlabel(struct sock *sk, int labeled) 1842static int smack_netlabel(struct sock *sk, int labeled)
1896{ 1843{
1844 struct smack_known *skp;
1897 struct socket_smack *ssp = sk->sk_security; 1845 struct socket_smack *ssp = sk->sk_security;
1898 struct netlbl_lsm_secattr secattr;
1899 int rc = 0; 1846 int rc = 0;
1900 1847
1901 /* 1848 /*
@@ -1913,10 +1860,8 @@ static int smack_netlabel(struct sock *sk, int labeled)
1913 labeled == SMACK_UNLABELED_SOCKET) 1860 labeled == SMACK_UNLABELED_SOCKET)
1914 netlbl_sock_delattr(sk); 1861 netlbl_sock_delattr(sk);
1915 else { 1862 else {
1916 netlbl_secattr_init(&secattr); 1863 skp = smk_find_entry(ssp->smk_out);
1917 smack_to_secattr(ssp->smk_out, &secattr); 1864 rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel);
1918 rc = netlbl_sock_setattr(sk, sk->sk_family, &secattr);
1919 netlbl_secattr_destroy(&secattr);
1920 } 1865 }
1921 1866
1922 bh_unlock_sock(sk); 1867 bh_unlock_sock(sk);
@@ -1989,7 +1934,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
1989 struct socket *sock; 1934 struct socket *sock;
1990 int rc = 0; 1935 int rc = 0;
1991 1936
1992 if (value == NULL || size > SMK_LABELLEN || size == 0) 1937 if (value == NULL || size > SMK_LONGLABEL || size == 0)
1993 return -EACCES; 1938 return -EACCES;
1994 1939
1995 sp = smk_import(value, size); 1940 sp = smk_import(value, size);
@@ -2785,7 +2730,7 @@ static int smack_setprocattr(struct task_struct *p, char *name,
2785 if (!capable(CAP_MAC_ADMIN)) 2730 if (!capable(CAP_MAC_ADMIN))
2786 return -EPERM; 2731 return -EPERM;
2787 2732
2788 if (value == NULL || size == 0 || size >= SMK_LABELLEN) 2733 if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
2789 return -EINVAL; 2734 return -EINVAL;
2790 2735
2791 if (strcmp(name, "current") != 0) 2736 if (strcmp(name, "current") != 0)
@@ -2921,10 +2866,9 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
2921static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, 2866static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
2922 struct socket_smack *ssp) 2867 struct socket_smack *ssp)
2923{ 2868{
2924 struct smack_known *skp; 2869 struct smack_known *kp;
2925 char smack[SMK_LABELLEN];
2926 char *sp; 2870 char *sp;
2927 int pcat; 2871 int found = 0;
2928 2872
2929 if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) { 2873 if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) {
2930 /* 2874 /*
@@ -2932,59 +2876,27 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
2932 * If there are flags but no level netlabel isn't 2876 * If there are flags but no level netlabel isn't
2933 * behaving the way we expect it to. 2877 * behaving the way we expect it to.
2934 * 2878 *
2935 * Get the categories, if any 2879 * Look it up in the label table
2936 * Without guidance regarding the smack value 2880 * Without guidance regarding the smack value
2937 * for the packet fall back on the network 2881 * for the packet fall back on the network
2938 * ambient value. 2882 * ambient value.
2939 */ 2883 */
2940 memset(smack, '\0', SMK_LABELLEN); 2884 rcu_read_lock();
2941 if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0) 2885 list_for_each_entry(kp, &smack_known_list, list) {
2942 for (pcat = -1;;) { 2886 if (sap->attr.mls.lvl != kp->smk_netlabel.attr.mls.lvl)
2943 pcat = netlbl_secattr_catmap_walk( 2887 continue;
2944 sap->attr.mls.cat, pcat + 1); 2888 if (memcmp(sap->attr.mls.cat,
2945 if (pcat < 0) 2889 kp->smk_netlabel.attr.mls.cat,
2946 break; 2890 SMK_CIPSOLEN) != 0)
2947 smack_catset_bit(pcat, smack); 2891 continue;
2948 } 2892 found = 1;
2949 /* 2893 break;
2950 * If it is CIPSO using smack direct mapping
2951 * we are already done. WeeHee.
2952 */
2953 if (sap->attr.mls.lvl == smack_cipso_direct) {
2954 /*
2955 * The label sent is usually on the label list.
2956 *
2957 * If it is not we may still want to allow the
2958 * delivery.
2959 *
2960 * If the recipient is accepting all packets
2961 * because it is using the star ("*") label
2962 * for SMACK64IPIN provide the web ("@") label
2963 * so that a directed response will succeed.
2964 * This is not very correct from a MAC point
2965 * of view, but gets around the problem that
2966 * locking prevents adding the newly discovered
2967 * label to the list.
2968 * The case where the recipient is not using
2969 * the star label should obviously fail.
2970 * The easy way to do this is to provide the
2971 * star label as the subject label.
2972 */
2973 skp = smk_find_entry(smack);
2974 if (skp != NULL)
2975 return skp->smk_known;
2976 if (ssp != NULL &&
2977 ssp->smk_in == smack_known_star.smk_known)
2978 return smack_known_web.smk_known;
2979 return smack_known_star.smk_known;
2980 } 2894 }
2981 /* 2895 rcu_read_unlock();
2982 * Look it up in the supplied table if it is not 2896
2983 * a direct mapping. 2897 if (found)
2984 */ 2898 return kp->smk_known;
2985 sp = smack_from_cipso(sap->attr.mls.lvl, smack); 2899
2986 if (sp != NULL)
2987 return sp;
2988 if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known) 2900 if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known)
2989 return smack_known_web.smk_known; 2901 return smack_known_web.smk_known;
2990 return smack_known_star.smk_known; 2902 return smack_known_star.smk_known;
@@ -3184,11 +3096,13 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3184 struct request_sock *req) 3096 struct request_sock *req)
3185{ 3097{
3186 u16 family = sk->sk_family; 3098 u16 family = sk->sk_family;
3099 struct smack_known *skp;
3187 struct socket_smack *ssp = sk->sk_security; 3100 struct socket_smack *ssp = sk->sk_security;
3188 struct netlbl_lsm_secattr secattr; 3101 struct netlbl_lsm_secattr secattr;
3189 struct sockaddr_in addr; 3102 struct sockaddr_in addr;
3190 struct iphdr *hdr; 3103 struct iphdr *hdr;
3191 char *sp; 3104 char *sp;
3105 char *hsp;
3192 int rc; 3106 int rc;
3193 struct smk_audit_info ad; 3107 struct smk_audit_info ad;
3194#ifdef CONFIG_AUDIT 3108#ifdef CONFIG_AUDIT
@@ -3235,16 +3149,14 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3235 hdr = ip_hdr(skb); 3149 hdr = ip_hdr(skb);
3236 addr.sin_addr.s_addr = hdr->saddr; 3150 addr.sin_addr.s_addr = hdr->saddr;
3237 rcu_read_lock(); 3151 rcu_read_lock();
3238 if (smack_host_label(&addr) == NULL) { 3152 hsp = smack_host_label(&addr);
3239 rcu_read_unlock(); 3153 rcu_read_unlock();
3240 netlbl_secattr_init(&secattr); 3154
3241 smack_to_secattr(sp, &secattr); 3155 if (hsp == NULL) {
3242 rc = netlbl_req_setattr(req, &secattr); 3156 skp = smk_find_entry(sp);
3243 netlbl_secattr_destroy(&secattr); 3157 rc = netlbl_req_setattr(req, &skp->smk_netlabel);
3244 } else { 3158 } else
3245 rcu_read_unlock();
3246 netlbl_req_delattr(req); 3159 netlbl_req_delattr(req);
3247 }
3248 3160
3249 return rc; 3161 return rc;
3250} 3162}
@@ -3669,15 +3581,6 @@ struct security_operations smack_ops = {
3669static __init void init_smack_known_list(void) 3581static __init void init_smack_known_list(void)
3670{ 3582{
3671 /* 3583 /*
3672 * Initialize CIPSO locks
3673 */
3674 spin_lock_init(&smack_known_huh.smk_cipsolock);
3675 spin_lock_init(&smack_known_hat.smk_cipsolock);
3676 spin_lock_init(&smack_known_star.smk_cipsolock);
3677 spin_lock_init(&smack_known_floor.smk_cipsolock);
3678 spin_lock_init(&smack_known_invalid.smk_cipsolock);
3679 spin_lock_init(&smack_known_web.smk_cipsolock);
3680 /*
3681 * Initialize rule list locks 3584 * Initialize rule list locks
3682 */ 3585 */
3683 mutex_init(&smack_known_huh.smk_rules_lock); 3586 mutex_init(&smack_known_huh.smk_rules_lock);