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.c243
1 files changed, 86 insertions, 157 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 45c32f074166..d583c0545808 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/**
@@ -79,7 +85,7 @@ struct inode_smack *new_inode_smack(char *smack)
79{ 85{
80 struct inode_smack *isp; 86 struct inode_smack *isp;
81 87
82 isp = kzalloc(sizeof(struct inode_smack), GFP_KERNEL); 88 isp = kzalloc(sizeof(struct inode_smack), GFP_NOFS);
83 if (isp == NULL) 89 if (isp == NULL)
84 return NULL; 90 return NULL;
85 91
@@ -556,13 +562,14 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
556 void **value, size_t *len) 562 void **value, size_t *len)
557{ 563{
558 struct smack_known *skp; 564 struct smack_known *skp;
565 struct inode_smack *issp = inode->i_security;
559 char *csp = smk_of_current(); 566 char *csp = smk_of_current();
560 char *isp = smk_of_inode(inode); 567 char *isp = smk_of_inode(inode);
561 char *dsp = smk_of_inode(dir); 568 char *dsp = smk_of_inode(dir);
562 int may; 569 int may;
563 570
564 if (name) { 571 if (name) {
565 *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); 572 *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_NOFS);
566 if (*name == NULL) 573 if (*name == NULL)
567 return -ENOMEM; 574 return -ENOMEM;
568 } 575 }
@@ -577,12 +584,15 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
577 * If the access rule allows transmutation and 584 * If the access rule allows transmutation and
578 * the directory requests transmutation then 585 * the directory requests transmutation then
579 * by all means transmute. 586 * by all means transmute.
587 * Mark the inode as changed.
580 */ 588 */
581 if (may > 0 && ((may & MAY_TRANSMUTE) != 0) && 589 if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
582 smk_inode_transmutable(dir)) 590 smk_inode_transmutable(dir)) {
583 isp = dsp; 591 isp = dsp;
592 issp->smk_flags |= SMK_INODE_CHANGED;
593 }
584 594
585 *value = kstrdup(isp, GFP_KERNEL); 595 *value = kstrdup(isp, GFP_NOFS);
586 if (*value == NULL) 596 if (*value == NULL)
587 return -ENOMEM; 597 return -ENOMEM;
588 } 598 }
@@ -821,7 +831,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
821 * check label validity here so import wont fail on 831 * check label validity here so import wont fail on
822 * post_setxattr 832 * post_setxattr
823 */ 833 */
824 if (size == 0 || size >= SMK_LABELLEN || 834 if (size == 0 || size >= SMK_LONGLABEL ||
825 smk_import(value, size) == NULL) 835 smk_import(value, size) == NULL)
826 rc = -EINVAL; 836 rc = -EINVAL;
827 } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { 837 } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
@@ -1349,7 +1359,7 @@ static int smack_file_receive(struct file *file)
1349} 1359}
1350 1360
1351/** 1361/**
1352 * smack_dentry_open - Smack dentry open processing 1362 * smack_file_open - Smack dentry open processing
1353 * @file: the object 1363 * @file: the object
1354 * @cred: unused 1364 * @cred: unused
1355 * 1365 *
@@ -1357,7 +1367,7 @@ static int smack_file_receive(struct file *file)
1357 * 1367 *
1358 * Returns 0 1368 * Returns 0
1359 */ 1369 */
1360static int smack_dentry_open(struct file *file, const struct cred *cred) 1370static int smack_file_open(struct file *file, const struct cred *cred)
1361{ 1371{
1362 struct inode_smack *isp = file->f_path.dentry->d_inode->i_security; 1372 struct inode_smack *isp = file->f_path.dentry->d_inode->i_security;
1363 1373
@@ -1820,65 +1830,6 @@ static char *smack_host_label(struct sockaddr_in *sip)
1820} 1830}
1821 1831
1822/** 1832/**
1823 * smack_set_catset - convert a capset to netlabel mls categories
1824 * @catset: the Smack categories
1825 * @sap: where to put the netlabel categories
1826 *
1827 * Allocates and fills attr.mls.cat
1828 */
1829static void smack_set_catset(char *catset, struct netlbl_lsm_secattr *sap)
1830{
1831 unsigned char *cp;
1832 unsigned char m;
1833 int cat;
1834 int rc;
1835 int byte;
1836
1837 if (!catset)
1838 return;
1839
1840 sap->flags |= NETLBL_SECATTR_MLS_CAT;
1841 sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
1842 sap->attr.mls.cat->startbit = 0;
1843
1844 for (cat = 1, cp = catset, byte = 0; byte < SMK_LABELLEN; cp++, byte++)
1845 for (m = 0x80; m != 0; m >>= 1, cat++) {
1846 if ((m & *cp) == 0)
1847 continue;
1848 rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat,
1849 cat, GFP_ATOMIC);
1850 }
1851}
1852
1853/**
1854 * smack_to_secattr - fill a secattr from a smack value
1855 * @smack: the smack value
1856 * @nlsp: where the result goes
1857 *
1858 * Casey says that CIPSO is good enough for now.
1859 * It can be used to effect.
1860 * It can also be abused to effect when necessary.
1861 * Apologies to the TSIG group in general and GW in particular.
1862 */
1863static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
1864{
1865 struct smack_cipso cipso;
1866 int rc;
1867
1868 nlsp->domain = smack;
1869 nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
1870
1871 rc = smack_to_cipso(smack, &cipso);
1872 if (rc == 0) {
1873 nlsp->attr.mls.lvl = cipso.smk_level;
1874 smack_set_catset(cipso.smk_catset, nlsp);
1875 } else {
1876 nlsp->attr.mls.lvl = smack_cipso_direct;
1877 smack_set_catset(smack, nlsp);
1878 }
1879}
1880
1881/**
1882 * smack_netlabel - Set the secattr on a socket 1833 * smack_netlabel - Set the secattr on a socket
1883 * @sk: the socket 1834 * @sk: the socket
1884 * @labeled: socket label scheme 1835 * @labeled: socket label scheme
@@ -1890,8 +1841,8 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
1890 */ 1841 */
1891static int smack_netlabel(struct sock *sk, int labeled) 1842static int smack_netlabel(struct sock *sk, int labeled)
1892{ 1843{
1844 struct smack_known *skp;
1893 struct socket_smack *ssp = sk->sk_security; 1845 struct socket_smack *ssp = sk->sk_security;
1894 struct netlbl_lsm_secattr secattr;
1895 int rc = 0; 1846 int rc = 0;
1896 1847
1897 /* 1848 /*
@@ -1909,10 +1860,8 @@ static int smack_netlabel(struct sock *sk, int labeled)
1909 labeled == SMACK_UNLABELED_SOCKET) 1860 labeled == SMACK_UNLABELED_SOCKET)
1910 netlbl_sock_delattr(sk); 1861 netlbl_sock_delattr(sk);
1911 else { 1862 else {
1912 netlbl_secattr_init(&secattr); 1863 skp = smk_find_entry(ssp->smk_out);
1913 smack_to_secattr(ssp->smk_out, &secattr); 1864 rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel);
1914 rc = netlbl_sock_setattr(sk, sk->sk_family, &secattr);
1915 netlbl_secattr_destroy(&secattr);
1916 } 1865 }
1917 1866
1918 bh_unlock_sock(sk); 1867 bh_unlock_sock(sk);
@@ -1985,7 +1934,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
1985 struct socket *sock; 1934 struct socket *sock;
1986 int rc = 0; 1935 int rc = 0;
1987 1936
1988 if (value == NULL || size > SMK_LABELLEN || size == 0) 1937 if (value == NULL || size > SMK_LONGLABEL || size == 0)
1989 return -EACCES; 1938 return -EACCES;
1990 1939
1991 sp = smk_import(value, size); 1940 sp = smk_import(value, size);
@@ -2552,6 +2501,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
2552 char *final; 2501 char *final;
2553 char trattr[TRANS_TRUE_SIZE]; 2502 char trattr[TRANS_TRUE_SIZE];
2554 int transflag = 0; 2503 int transflag = 0;
2504 int rc;
2555 struct dentry *dp; 2505 struct dentry *dp;
2556 2506
2557 if (inode == NULL) 2507 if (inode == NULL)
@@ -2670,17 +2620,38 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
2670 */ 2620 */
2671 dp = dget(opt_dentry); 2621 dp = dget(opt_dentry);
2672 fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp); 2622 fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp);
2673 if (fetched != NULL) { 2623 if (fetched != NULL)
2674 final = fetched; 2624 final = fetched;
2675 if (S_ISDIR(inode->i_mode)) { 2625
2676 trattr[0] = '\0'; 2626 /*
2677 inode->i_op->getxattr(dp, 2627 * Transmuting directory
2628 */
2629 if (S_ISDIR(inode->i_mode)) {
2630 /*
2631 * If this is a new directory and the label was
2632 * transmuted when the inode was initialized
2633 * set the transmute attribute on the directory
2634 * and mark the inode.
2635 *
2636 * If there is a transmute attribute on the
2637 * directory mark the inode.
2638 */
2639 if (isp->smk_flags & SMK_INODE_CHANGED) {
2640 isp->smk_flags &= ~SMK_INODE_CHANGED;
2641 rc = inode->i_op->setxattr(dp,
2678 XATTR_NAME_SMACKTRANSMUTE, 2642 XATTR_NAME_SMACKTRANSMUTE,
2679 trattr, TRANS_TRUE_SIZE); 2643 TRANS_TRUE, TRANS_TRUE_SIZE,
2680 if (strncmp(trattr, TRANS_TRUE, 2644 0);
2681 TRANS_TRUE_SIZE) == 0) 2645 } else {
2682 transflag = SMK_INODE_TRANSMUTE; 2646 rc = inode->i_op->getxattr(dp,
2647 XATTR_NAME_SMACKTRANSMUTE, trattr,
2648 TRANS_TRUE_SIZE);
2649 if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
2650 TRANS_TRUE_SIZE) != 0)
2651 rc = -EINVAL;
2683 } 2652 }
2653 if (rc >= 0)
2654 transflag = SMK_INODE_TRANSMUTE;
2684 } 2655 }
2685 isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); 2656 isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp);
2686 isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp); 2657 isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp);
@@ -2759,7 +2730,7 @@ static int smack_setprocattr(struct task_struct *p, char *name,
2759 if (!capable(CAP_MAC_ADMIN)) 2730 if (!capable(CAP_MAC_ADMIN))
2760 return -EPERM; 2731 return -EPERM;
2761 2732
2762 if (value == NULL || size == 0 || size >= SMK_LABELLEN) 2733 if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
2763 return -EINVAL; 2734 return -EINVAL;
2764 2735
2765 if (strcmp(name, "current") != 0) 2736 if (strcmp(name, "current") != 0)
@@ -2895,10 +2866,9 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
2895static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, 2866static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
2896 struct socket_smack *ssp) 2867 struct socket_smack *ssp)
2897{ 2868{
2898 struct smack_known *skp; 2869 struct smack_known *kp;
2899 char smack[SMK_LABELLEN];
2900 char *sp; 2870 char *sp;
2901 int pcat; 2871 int found = 0;
2902 2872
2903 if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) { 2873 if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) {
2904 /* 2874 /*
@@ -2906,59 +2876,27 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
2906 * If there are flags but no level netlabel isn't 2876 * If there are flags but no level netlabel isn't
2907 * behaving the way we expect it to. 2877 * behaving the way we expect it to.
2908 * 2878 *
2909 * Get the categories, if any 2879 * Look it up in the label table
2910 * Without guidance regarding the smack value 2880 * Without guidance regarding the smack value
2911 * for the packet fall back on the network 2881 * for the packet fall back on the network
2912 * ambient value. 2882 * ambient value.
2913 */ 2883 */
2914 memset(smack, '\0', SMK_LABELLEN); 2884 rcu_read_lock();
2915 if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0) 2885 list_for_each_entry(kp, &smack_known_list, list) {
2916 for (pcat = -1;;) { 2886 if (sap->attr.mls.lvl != kp->smk_netlabel.attr.mls.lvl)
2917 pcat = netlbl_secattr_catmap_walk( 2887 continue;
2918 sap->attr.mls.cat, pcat + 1); 2888 if (memcmp(sap->attr.mls.cat,
2919 if (pcat < 0) 2889 kp->smk_netlabel.attr.mls.cat,
2920 break; 2890 SMK_CIPSOLEN) != 0)
2921 smack_catset_bit(pcat, smack); 2891 continue;
2922 } 2892 found = 1;
2923 /* 2893 break;
2924 * If it is CIPSO using smack direct mapping
2925 * we are already done. WeeHee.
2926 */
2927 if (sap->attr.mls.lvl == smack_cipso_direct) {
2928 /*
2929 * The label sent is usually on the label list.
2930 *
2931 * If it is not we may still want to allow the
2932 * delivery.
2933 *
2934 * If the recipient is accepting all packets
2935 * because it is using the star ("*") label
2936 * for SMACK64IPIN provide the web ("@") label
2937 * so that a directed response will succeed.
2938 * This is not very correct from a MAC point
2939 * of view, but gets around the problem that
2940 * locking prevents adding the newly discovered
2941 * label to the list.
2942 * The case where the recipient is not using
2943 * the star label should obviously fail.
2944 * The easy way to do this is to provide the
2945 * star label as the subject label.
2946 */
2947 skp = smk_find_entry(smack);
2948 if (skp != NULL)
2949 return skp->smk_known;
2950 if (ssp != NULL &&
2951 ssp->smk_in == smack_known_star.smk_known)
2952 return smack_known_web.smk_known;
2953 return smack_known_star.smk_known;
2954 } 2894 }
2955 /* 2895 rcu_read_unlock();
2956 * Look it up in the supplied table if it is not 2896
2957 * a direct mapping. 2897 if (found)
2958 */ 2898 return kp->smk_known;
2959 sp = smack_from_cipso(sap->attr.mls.lvl, smack); 2899
2960 if (sp != NULL)
2961 return sp;
2962 if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known) 2900 if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known)
2963 return smack_known_web.smk_known; 2901 return smack_known_web.smk_known;
2964 return smack_known_star.smk_known; 2902 return smack_known_star.smk_known;
@@ -3158,11 +3096,13 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3158 struct request_sock *req) 3096 struct request_sock *req)
3159{ 3097{
3160 u16 family = sk->sk_family; 3098 u16 family = sk->sk_family;
3099 struct smack_known *skp;
3161 struct socket_smack *ssp = sk->sk_security; 3100 struct socket_smack *ssp = sk->sk_security;
3162 struct netlbl_lsm_secattr secattr; 3101 struct netlbl_lsm_secattr secattr;
3163 struct sockaddr_in addr; 3102 struct sockaddr_in addr;
3164 struct iphdr *hdr; 3103 struct iphdr *hdr;
3165 char *sp; 3104 char *sp;
3105 char *hsp;
3166 int rc; 3106 int rc;
3167 struct smk_audit_info ad; 3107 struct smk_audit_info ad;
3168#ifdef CONFIG_AUDIT 3108#ifdef CONFIG_AUDIT
@@ -3209,16 +3149,14 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3209 hdr = ip_hdr(skb); 3149 hdr = ip_hdr(skb);
3210 addr.sin_addr.s_addr = hdr->saddr; 3150 addr.sin_addr.s_addr = hdr->saddr;
3211 rcu_read_lock(); 3151 rcu_read_lock();
3212 if (smack_host_label(&addr) == NULL) { 3152 hsp = smack_host_label(&addr);
3213 rcu_read_unlock(); 3153 rcu_read_unlock();
3214 netlbl_secattr_init(&secattr); 3154
3215 smack_to_secattr(sp, &secattr); 3155 if (hsp == NULL) {
3216 rc = netlbl_req_setattr(req, &secattr); 3156 skp = smk_find_entry(sp);
3217 netlbl_secattr_destroy(&secattr); 3157 rc = netlbl_req_setattr(req, &skp->smk_netlabel);
3218 } else { 3158 } else
3219 rcu_read_unlock();
3220 netlbl_req_delattr(req); 3159 netlbl_req_delattr(req);
3221 }
3222 3160
3223 return rc; 3161 return rc;
3224} 3162}
@@ -3400,7 +3338,7 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule,
3400 char *rule = vrule; 3338 char *rule = vrule;
3401 3339
3402 if (!rule) { 3340 if (!rule) {
3403 audit_log(actx, GFP_KERNEL, AUDIT_SELINUX_ERR, 3341 audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
3404 "Smack: missing rule\n"); 3342 "Smack: missing rule\n");
3405 return -ENOENT; 3343 return -ENOENT;
3406 } 3344 }
@@ -3549,7 +3487,7 @@ struct security_operations smack_ops = {
3549 .file_send_sigiotask = smack_file_send_sigiotask, 3487 .file_send_sigiotask = smack_file_send_sigiotask,
3550 .file_receive = smack_file_receive, 3488 .file_receive = smack_file_receive,
3551 3489
3552 .dentry_open = smack_dentry_open, 3490 .file_open = smack_file_open,
3553 3491
3554 .cred_alloc_blank = smack_cred_alloc_blank, 3492 .cred_alloc_blank = smack_cred_alloc_blank,
3555 .cred_free = smack_cred_free, 3493 .cred_free = smack_cred_free,
@@ -3643,15 +3581,6 @@ struct security_operations smack_ops = {
3643static __init void init_smack_known_list(void) 3581static __init void init_smack_known_list(void)
3644{ 3582{
3645 /* 3583 /*
3646 * Initialize CIPSO locks
3647 */
3648 spin_lock_init(&smack_known_huh.smk_cipsolock);
3649 spin_lock_init(&smack_known_hat.smk_cipsolock);
3650 spin_lock_init(&smack_known_star.smk_cipsolock);
3651 spin_lock_init(&smack_known_floor.smk_cipsolock);
3652 spin_lock_init(&smack_known_invalid.smk_cipsolock);
3653 spin_lock_init(&smack_known_web.smk_cipsolock);
3654 /*
3655 * Initialize rule list locks 3584 * Initialize rule list locks
3656 */ 3585 */
3657 mutex_init(&smack_known_huh.smk_rules_lock); 3586 mutex_init(&smack_known_huh.smk_rules_lock);