aboutsummaryrefslogtreecommitdiffstats
path: root/security/smack/smack_lsm.c
diff options
context:
space:
mode:
authorCasey Schaufler <casey@schaufler-ca.com>2012-05-06 18:22:02 -0400
committerCasey Schaufler <cschaufler@vaio-ubuntu.(none)>2012-05-15 01:48:38 -0400
commitf7112e6c9abf1c70f001dcf097c1d6e218a93f5c (patch)
tree8ddcab31388e3f220f3ef911f4ec9dce8ac4be92 /security/smack/smack_lsm.c
parentceffec5541cc22486d3ff492e3d76a33a68fbfa3 (diff)
Smack: allow for significantly longer Smack labels v4
V4 updated to current linux-security#next Targeted for git://gitorious.org/smack-next/kernel.git Modern application runtime environments like to use naming schemes that are structured and generated without human intervention. Even though the Smack limit of 23 characters for a label name is perfectly rational for human use there have been complaints that the limit is a problem in environments where names are composed from a set or sources, including vendor, author, distribution channel and application name. Names like softwarehouse-pgwodehouse-coolappstore-mellowmuskrats are becoming harder to avoid. This patch introduces long label support in Smack. Labels are now limited to 255 characters instead of the old 23. The primary reason for limiting the labels to 23 characters was so they could be directly contained in CIPSO category sets. This is still done were possible, but for labels that are too large a mapping is required. This is perfectly safe for communication that stays "on the box" and doesn't require much coordination between boxes beyond what would have been required to keep label names consistent. The bulk of this patch is in smackfs, adding and updating administrative interfaces. Because existing APIs can't be changed new ones that do much the same things as old ones have been introduced. The Smack specific CIPSO data representation has been removed and replaced with the data format used by netlabel. The CIPSO header is now computed when a label is imported rather than on use. This results in improved IP performance. The smack label is now allocated separately from the containing structure, allowing for larger strings. Four new /smack interfaces have been introduced as four of the old interfaces strictly required labels be specified in fixed length arrays. The access interface is supplemented with the check interface: access "Subject Object rwxat" access2 "Subject Object rwaxt" The load interface is supplemented with the rules interface: load "Subject Object rwxat" load2 "Subject Object rwaxt" The load-self interface is supplemented with the self-rules interface: load-self "Subject Object rwxat" load-self2 "Subject Object rwaxt" The cipso interface is supplemented with the wire interface: cipso "Subject lvl cnt c1 c2 ..." cipso2 "Subject lvl cnt c1 c2 ..." The old interfaces are maintained for compatibility. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
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);