diff options
Diffstat (limited to 'security/smack/smack_lsm.c')
-rw-r--r-- | security/smack/smack_lsm.c | 185 |
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 @@ | |||
57 | static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp) | 56 | static 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 | */ | ||
1833 | static 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 | */ | ||
1867 | static 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 | */ |
1895 | static int smack_netlabel(struct sock *sk, int labeled) | 1842 | static 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, | |||
2921 | static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, | 2866 | static 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 = { | |||
3669 | static __init void init_smack_known_list(void) | 3581 | static __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); |