summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorJames Morris <james.l.morris@oracle.com>2015-10-20 19:49:29 -0400
committerJames Morris <james.l.morris@oracle.com>2015-10-20 19:49:29 -0400
commit09302fd19efbff9569eaad3f78ead8f411defd87 (patch)
treeea7445250c19d8af6092eecb6908f1547dde86d6 /security
parentfbf98265891a672111dac8faabd190f62b678545 (diff)
parent38416e53936ecf896948fdeffc36b76979117952 (diff)
Merge branch 'smack-for-4.4' of https://github.com/cschaufler/smack-next into next
Diffstat (limited to 'security')
-rw-r--r--security/smack/smack.h4
-rw-r--r--security/smack/smack_access.c6
-rw-r--r--security/smack/smack_lsm.c67
-rw-r--r--security/smack/smackfs.c208
4 files changed, 238 insertions, 47 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h
index fff0c612bbb7..6c91156ae225 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -115,6 +115,7 @@ struct task_smack {
115 struct smack_known *smk_forked; /* label when forked */ 115 struct smack_known *smk_forked; /* label when forked */
116 struct list_head smk_rules; /* per task access rules */ 116 struct list_head smk_rules; /* per task access rules */
117 struct mutex smk_rules_lock; /* lock for the rules */ 117 struct mutex smk_rules_lock; /* lock for the rules */
118 struct list_head smk_relabel; /* transit allowed labels */
118}; 119};
119 120
120#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ 121#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */
@@ -169,7 +170,7 @@ struct smk_port_label {
169}; 170};
170#endif /* SMACK_IPV6_PORT_LABELING */ 171#endif /* SMACK_IPV6_PORT_LABELING */
171 172
172struct smack_onlycap { 173struct smack_known_list_elem {
173 struct list_head list; 174 struct list_head list;
174 struct smack_known *smk_label; 175 struct smack_known *smk_label;
175}; 176};
@@ -301,6 +302,7 @@ struct smack_known *smk_import_entry(const char *, int);
301void smk_insert_entry(struct smack_known *skp); 302void smk_insert_entry(struct smack_known *skp);
302struct smack_known *smk_find_entry(const char *); 303struct smack_known *smk_find_entry(const char *);
303int smack_privileged(int cap); 304int smack_privileged(int cap);
305void smk_destroy_label_list(struct list_head *list);
304 306
305/* 307/*
306 * Shared data. 308 * Shared data.
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index bc1053fb5d1d..a283f9e796c1 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -637,7 +637,7 @@ DEFINE_MUTEX(smack_onlycap_lock);
637int smack_privileged(int cap) 637int smack_privileged(int cap)
638{ 638{
639 struct smack_known *skp = smk_of_current(); 639 struct smack_known *skp = smk_of_current();
640 struct smack_onlycap *sop; 640 struct smack_known_list_elem *sklep;
641 641
642 /* 642 /*
643 * All kernel tasks are privileged 643 * All kernel tasks are privileged
@@ -654,8 +654,8 @@ int smack_privileged(int cap)
654 return 1; 654 return 1;
655 } 655 }
656 656
657 list_for_each_entry_rcu(sop, &smack_onlycap_list, list) { 657 list_for_each_entry_rcu(sklep, &smack_onlycap_list, list) {
658 if (sop->smk_label == skp) { 658 if (sklep->smk_label == skp) {
659 rcu_read_unlock(); 659 rcu_read_unlock();
660 return 1; 660 return 1;
661 } 661 }
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 996c88956438..ff81026f6ddb 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -52,7 +52,7 @@
52#define SMK_SENDING 2 52#define SMK_SENDING 2
53 53
54#ifdef SMACK_IPV6_PORT_LABELING 54#ifdef SMACK_IPV6_PORT_LABELING
55LIST_HEAD(smk_ipv6_port_list); 55static LIST_HEAD(smk_ipv6_port_list);
56#endif 56#endif
57static struct kmem_cache *smack_inode_cache; 57static struct kmem_cache *smack_inode_cache;
58int smack_enabled; 58int smack_enabled;
@@ -326,6 +326,7 @@ static struct task_smack *new_task_smack(struct smack_known *task,
326 tsp->smk_task = task; 326 tsp->smk_task = task;
327 tsp->smk_forked = forked; 327 tsp->smk_forked = forked;
328 INIT_LIST_HEAD(&tsp->smk_rules); 328 INIT_LIST_HEAD(&tsp->smk_rules);
329 INIT_LIST_HEAD(&tsp->smk_relabel);
329 mutex_init(&tsp->smk_rules_lock); 330 mutex_init(&tsp->smk_rules_lock);
330 331
331 return tsp; 332 return tsp;
@@ -361,6 +362,35 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead,
361} 362}
362 363
363/** 364/**
365 * smk_copy_relabel - copy smk_relabel labels list
366 * @nhead: new rules header pointer
367 * @ohead: old rules header pointer
368 * @gfp: type of the memory for the allocation
369 *
370 * Returns 0 on success, -ENOMEM on error
371 */
372static int smk_copy_relabel(struct list_head *nhead, struct list_head *ohead,
373 gfp_t gfp)
374{
375 struct smack_known_list_elem *nklep;
376 struct smack_known_list_elem *oklep;
377
378 INIT_LIST_HEAD(nhead);
379
380 list_for_each_entry(oklep, ohead, list) {
381 nklep = kzalloc(sizeof(struct smack_known_list_elem), gfp);
382 if (nklep == NULL) {
383 smk_destroy_label_list(nhead);
384 return -ENOMEM;
385 }
386 nklep->smk_label = oklep->smk_label;
387 list_add(&nklep->list, nhead);
388 }
389
390 return 0;
391}
392
393/**
364 * smk_ptrace_mode - helper function for converting PTRACE_MODE_* into MAY_* 394 * smk_ptrace_mode - helper function for converting PTRACE_MODE_* into MAY_*
365 * @mode - input mode in form of PTRACE_MODE_* 395 * @mode - input mode in form of PTRACE_MODE_*
366 * 396 *
@@ -1922,6 +1952,8 @@ static void smack_cred_free(struct cred *cred)
1922 return; 1952 return;
1923 cred->security = NULL; 1953 cred->security = NULL;
1924 1954
1955 smk_destroy_label_list(&tsp->smk_relabel);
1956
1925 list_for_each_safe(l, n, &tsp->smk_rules) { 1957 list_for_each_safe(l, n, &tsp->smk_rules) {
1926 rp = list_entry(l, struct smack_rule, list); 1958 rp = list_entry(l, struct smack_rule, list);
1927 list_del(&rp->list); 1959 list_del(&rp->list);
@@ -1953,6 +1985,11 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old,
1953 if (rc != 0) 1985 if (rc != 0)
1954 return rc; 1986 return rc;
1955 1987
1988 rc = smk_copy_relabel(&new_tsp->smk_relabel, &old_tsp->smk_relabel,
1989 gfp);
1990 if (rc != 0)
1991 return rc;
1992
1956 new->security = new_tsp; 1993 new->security = new_tsp;
1957 return 0; 1994 return 0;
1958} 1995}
@@ -3354,6 +3391,9 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
3354 */ 3391 */
3355 isp->smk_inode = smk_of_current(); 3392 isp->smk_inode = smk_of_current();
3356 break; 3393 break;
3394 case PIPEFS_MAGIC:
3395 isp->smk_inode = smk_of_current();
3396 break;
3357 default: 3397 default:
3358 isp->smk_inode = sbsp->smk_root; 3398 isp->smk_inode = sbsp->smk_root;
3359 break; 3399 break;
@@ -3549,9 +3589,11 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value)
3549static int smack_setprocattr(struct task_struct *p, char *name, 3589static int smack_setprocattr(struct task_struct *p, char *name,
3550 void *value, size_t size) 3590 void *value, size_t size)
3551{ 3591{
3552 struct task_smack *tsp; 3592 struct task_smack *tsp = current_security();
3553 struct cred *new; 3593 struct cred *new;
3554 struct smack_known *skp; 3594 struct smack_known *skp;
3595 struct smack_known_list_elem *sklep;
3596 int rc;
3555 3597
3556 /* 3598 /*
3557 * Changing another process' Smack value is too dangerous 3599 * Changing another process' Smack value is too dangerous
@@ -3560,7 +3602,7 @@ static int smack_setprocattr(struct task_struct *p, char *name,
3560 if (p != current) 3602 if (p != current)
3561 return -EPERM; 3603 return -EPERM;
3562 3604
3563 if (!smack_privileged(CAP_MAC_ADMIN)) 3605 if (!smack_privileged(CAP_MAC_ADMIN) && list_empty(&tsp->smk_relabel))
3564 return -EPERM; 3606 return -EPERM;
3565 3607
3566 if (value == NULL || size == 0 || size >= SMK_LONGLABEL) 3608 if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
@@ -3579,12 +3621,27 @@ static int smack_setprocattr(struct task_struct *p, char *name,
3579 if (skp == &smack_known_web) 3621 if (skp == &smack_known_web)
3580 return -EPERM; 3622 return -EPERM;
3581 3623
3624 if (!smack_privileged(CAP_MAC_ADMIN)) {
3625 rc = -EPERM;
3626 list_for_each_entry(sklep, &tsp->smk_relabel, list)
3627 if (sklep->smk_label == skp) {
3628 rc = 0;
3629 break;
3630 }
3631 if (rc)
3632 return rc;
3633 }
3634
3582 new = prepare_creds(); 3635 new = prepare_creds();
3583 if (new == NULL) 3636 if (new == NULL)
3584 return -ENOMEM; 3637 return -ENOMEM;
3585 3638
3586 tsp = new->security; 3639 tsp = new->security;
3587 tsp->smk_task = skp; 3640 tsp->smk_task = skp;
3641 /*
3642 * process can change its label only once
3643 */
3644 smk_destroy_label_list(&tsp->smk_relabel);
3588 3645
3589 commit_creds(new); 3646 commit_creds(new);
3590 return size; 3647 return size;
@@ -4708,8 +4765,6 @@ static __init int smack_init(void)
4708 if (!security_module_enable("smack")) 4765 if (!security_module_enable("smack"))
4709 return 0; 4766 return 0;
4710 4767
4711 smack_enabled = 1;
4712
4713 smack_inode_cache = KMEM_CACHE(inode_smack, 0); 4768 smack_inode_cache = KMEM_CACHE(inode_smack, 0);
4714 if (!smack_inode_cache) 4769 if (!smack_inode_cache)
4715 return -ENOMEM; 4770 return -ENOMEM;
@@ -4721,6 +4776,8 @@ static __init int smack_init(void)
4721 return -ENOMEM; 4776 return -ENOMEM;
4722 } 4777 }
4723 4778
4779 smack_enabled = 1;
4780
4724 pr_info("Smack: Initializing.\n"); 4781 pr_info("Smack: Initializing.\n");
4725#ifdef CONFIG_SECURITY_SMACK_NETFILTER 4782#ifdef CONFIG_SECURITY_SMACK_NETFILTER
4726 pr_info("Smack: Netfilter enabled.\n"); 4783 pr_info("Smack: Netfilter enabled.\n");
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index c20b154a33f2..94bd9e41c9ec 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -61,6 +61,7 @@ enum smk_inos {
61#if IS_ENABLED(CONFIG_IPV6) 61#if IS_ENABLED(CONFIG_IPV6)
62 SMK_NET6ADDR = 23, /* single label IPv6 hosts */ 62 SMK_NET6ADDR = 23, /* single label IPv6 hosts */
63#endif /* CONFIG_IPV6 */ 63#endif /* CONFIG_IPV6 */
64 SMK_RELABEL_SELF = 24, /* relabel possible without CAP_MAC_ADMIN */
64}; 65};
65 66
66/* 67/*
@@ -1501,8 +1502,8 @@ static ssize_t smk_write_net6addr(struct file *file, const char __user *buf,
1501 */ 1502 */
1502 if (smack[0] != '-') { 1503 if (smack[0] != '-') {
1503 skp = smk_import_entry(smack, 0); 1504 skp = smk_import_entry(smack, 0);
1504 if (skp == NULL) { 1505 if (IS_ERR(skp)) {
1505 rc = -EINVAL; 1506 rc = PTR_ERR(skp);
1506 goto free_out; 1507 goto free_out;
1507 } 1508 }
1508 } else { 1509 } else {
@@ -1914,10 +1915,10 @@ static void *onlycap_seq_next(struct seq_file *s, void *v, loff_t *pos)
1914static int onlycap_seq_show(struct seq_file *s, void *v) 1915static int onlycap_seq_show(struct seq_file *s, void *v)
1915{ 1916{
1916 struct list_head *list = v; 1917 struct list_head *list = v;
1917 struct smack_onlycap *sop = 1918 struct smack_known_list_elem *sklep =
1918 list_entry_rcu(list, struct smack_onlycap, list); 1919 list_entry_rcu(list, struct smack_known_list_elem, list);
1919 1920
1920 seq_puts(s, sop->smk_label->smk_known); 1921 seq_puts(s, sklep->smk_label->smk_known);
1921 seq_putc(s, ' '); 1922 seq_putc(s, ' ');
1922 1923
1923 return 0; 1924 return 0;
@@ -1974,6 +1975,54 @@ static void smk_list_swap_rcu(struct list_head *public,
1974} 1975}
1975 1976
1976/** 1977/**
1978 * smk_parse_label_list - parse list of Smack labels, separated by spaces
1979 *
1980 * @data: the string to parse
1981 * @private: destination list
1982 *
1983 * Returns zero on success or error code, as appropriate
1984 */
1985static int smk_parse_label_list(char *data, struct list_head *list)
1986{
1987 char *tok;
1988 struct smack_known *skp;
1989 struct smack_known_list_elem *sklep;
1990
1991 while ((tok = strsep(&data, " ")) != NULL) {
1992 if (!*tok)
1993 continue;
1994
1995 skp = smk_import_entry(tok, 0);
1996 if (IS_ERR(skp))
1997 return PTR_ERR(skp);
1998
1999 sklep = kzalloc(sizeof(*sklep), GFP_KERNEL);
2000 if (sklep == NULL)
2001 return -ENOMEM;
2002
2003 sklep->smk_label = skp;
2004 list_add(&sklep->list, list);
2005 }
2006
2007 return 0;
2008}
2009
2010/**
2011 * smk_destroy_label_list - destroy a list of smack_known_list_elem
2012 * @head: header pointer of the list to destroy
2013 */
2014void smk_destroy_label_list(struct list_head *list)
2015{
2016 struct smack_known_list_elem *sklep;
2017 struct smack_known_list_elem *sklep2;
2018
2019 list_for_each_entry_safe(sklep, sklep2, list, list)
2020 kfree(sklep);
2021
2022 INIT_LIST_HEAD(list);
2023}
2024
2025/**
1977 * smk_write_onlycap - write() for smackfs/onlycap 2026 * smk_write_onlycap - write() for smackfs/onlycap
1978 * @file: file pointer, not actually used 2027 * @file: file pointer, not actually used
1979 * @buf: where to get the data from 2028 * @buf: where to get the data from
@@ -1986,13 +2035,8 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
1986 size_t count, loff_t *ppos) 2035 size_t count, loff_t *ppos)
1987{ 2036{
1988 char *data; 2037 char *data;
1989 char *data_parse;
1990 char *tok;
1991 struct smack_known *skp;
1992 struct smack_onlycap *sop;
1993 struct smack_onlycap *sop2;
1994 LIST_HEAD(list_tmp); 2038 LIST_HEAD(list_tmp);
1995 int rc = count; 2039 int rc;
1996 2040
1997 if (!smack_privileged(CAP_MAC_ADMIN)) 2041 if (!smack_privileged(CAP_MAC_ADMIN))
1998 return -EPERM; 2042 return -EPERM;
@@ -2006,26 +2050,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
2006 return -EFAULT; 2050 return -EFAULT;
2007 } 2051 }
2008 2052
2009 data_parse = data; 2053 rc = smk_parse_label_list(data, &list_tmp);
2010 while ((tok = strsep(&data_parse, " ")) != NULL) {
2011 if (!*tok)
2012 continue;
2013
2014 skp = smk_import_entry(tok, 0);
2015 if (IS_ERR(skp)) {
2016 rc = PTR_ERR(skp);
2017 break;
2018 }
2019
2020 sop = kzalloc(sizeof(*sop), GFP_KERNEL);
2021 if (sop == NULL) {
2022 rc = -ENOMEM;
2023 break;
2024 }
2025
2026 sop->smk_label = skp;
2027 list_add_rcu(&sop->list, &list_tmp);
2028 }
2029 kfree(data); 2054 kfree(data);
2030 2055
2031 /* 2056 /*
@@ -2038,17 +2063,14 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
2038 * But do so only on invalid label, not on system errors. 2063 * But do so only on invalid label, not on system errors.
2039 * The invalid label must be first to count as clearing attempt. 2064 * The invalid label must be first to count as clearing attempt.
2040 */ 2065 */
2041 if (rc == -EINVAL && list_empty(&list_tmp)) 2066 if (!rc || (rc == -EINVAL && list_empty(&list_tmp))) {
2042 rc = count;
2043
2044 if (rc >= 0) {
2045 mutex_lock(&smack_onlycap_lock); 2067 mutex_lock(&smack_onlycap_lock);
2046 smk_list_swap_rcu(&smack_onlycap_list, &list_tmp); 2068 smk_list_swap_rcu(&smack_onlycap_list, &list_tmp);
2047 mutex_unlock(&smack_onlycap_lock); 2069 mutex_unlock(&smack_onlycap_lock);
2070 rc = count;
2048 } 2071 }
2049 2072
2050 list_for_each_entry_safe(sop, sop2, &list_tmp, list) 2073 smk_destroy_label_list(&list_tmp);
2051 kfree(sop);
2052 2074
2053 return rc; 2075 return rc;
2054} 2076}
@@ -2698,6 +2720,113 @@ static const struct file_operations smk_syslog_ops = {
2698 .llseek = default_llseek, 2720 .llseek = default_llseek,
2699}; 2721};
2700 2722
2723/*
2724 * Seq_file read operations for /smack/relabel-self
2725 */
2726
2727static void *relabel_self_seq_start(struct seq_file *s, loff_t *pos)
2728{
2729 struct task_smack *tsp = current_security();
2730
2731 return smk_seq_start(s, pos, &tsp->smk_relabel);
2732}
2733
2734static void *relabel_self_seq_next(struct seq_file *s, void *v, loff_t *pos)
2735{
2736 struct task_smack *tsp = current_security();
2737
2738 return smk_seq_next(s, v, pos, &tsp->smk_relabel);
2739}
2740
2741static int relabel_self_seq_show(struct seq_file *s, void *v)
2742{
2743 struct list_head *list = v;
2744 struct smack_known_list_elem *sklep =
2745 list_entry(list, struct smack_known_list_elem, list);
2746
2747 seq_puts(s, sklep->smk_label->smk_known);
2748 seq_putc(s, ' ');
2749
2750 return 0;
2751}
2752
2753static const struct seq_operations relabel_self_seq_ops = {
2754 .start = relabel_self_seq_start,
2755 .next = relabel_self_seq_next,
2756 .show = relabel_self_seq_show,
2757 .stop = smk_seq_stop,
2758};
2759
2760/**
2761 * smk_open_relabel_self - open() for /smack/relabel-self
2762 * @inode: inode structure representing file
2763 * @file: "relabel-self" file pointer
2764 *
2765 * Connect our relabel_self_seq_* operations with /smack/relabel-self
2766 * file_operations
2767 */
2768static int smk_open_relabel_self(struct inode *inode, struct file *file)
2769{
2770 return seq_open(file, &relabel_self_seq_ops);
2771}
2772
2773/**
2774 * smk_write_relabel_self - write() for /smack/relabel-self
2775 * @file: file pointer, not actually used
2776 * @buf: where to get the data from
2777 * @count: bytes sent
2778 * @ppos: where to start - must be 0
2779 *
2780 */
2781static ssize_t smk_write_relabel_self(struct file *file, const char __user *buf,
2782 size_t count, loff_t *ppos)
2783{
2784 struct task_smack *tsp = current_security();
2785 char *data;
2786 int rc;
2787 LIST_HEAD(list_tmp);
2788
2789 /*
2790 * Must have privilege.
2791 */
2792 if (!smack_privileged(CAP_MAC_ADMIN))
2793 return -EPERM;
2794
2795 /*
2796 * Enough data must be present.
2797 */
2798 if (*ppos != 0)
2799 return -EINVAL;
2800
2801 data = kzalloc(count + 1, GFP_KERNEL);
2802 if (data == NULL)
2803 return -ENOMEM;
2804
2805 if (copy_from_user(data, buf, count) != 0) {
2806 kfree(data);
2807 return -EFAULT;
2808 }
2809
2810 rc = smk_parse_label_list(data, &list_tmp);
2811 kfree(data);
2812
2813 if (!rc || (rc == -EINVAL && list_empty(&list_tmp))) {
2814 smk_destroy_label_list(&tsp->smk_relabel);
2815 list_splice(&list_tmp, &tsp->smk_relabel);
2816 return count;
2817 }
2818
2819 smk_destroy_label_list(&list_tmp);
2820 return rc;
2821}
2822
2823static const struct file_operations smk_relabel_self_ops = {
2824 .open = smk_open_relabel_self,
2825 .read = seq_read,
2826 .llseek = seq_lseek,
2827 .write = smk_write_relabel_self,
2828 .release = seq_release,
2829};
2701 2830
2702/** 2831/**
2703 * smk_read_ptrace - read() for /smack/ptrace 2832 * smk_read_ptrace - read() for /smack/ptrace
@@ -2824,6 +2953,9 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
2824 [SMK_NET6ADDR] = { 2953 [SMK_NET6ADDR] = {
2825 "ipv6host", &smk_net6addr_ops, S_IRUGO|S_IWUSR}, 2954 "ipv6host", &smk_net6addr_ops, S_IRUGO|S_IWUSR},
2826#endif /* CONFIG_IPV6 */ 2955#endif /* CONFIG_IPV6 */
2956 [SMK_RELABEL_SELF] = {
2957 "relabel-self", &smk_relabel_self_ops,
2958 S_IRUGO|S_IWUGO},
2827 /* last one */ 2959 /* last one */
2828 {""} 2960 {""}
2829 }; 2961 };
@@ -2892,7 +3024,7 @@ static int __init init_smk_fs(void)
2892 int err; 3024 int err;
2893 int rc; 3025 int rc;
2894 3026
2895 if (!security_module_enable("smack")) 3027 if (smack_enabled == 0)
2896 return 0; 3028 return 0;
2897 3029
2898 err = smk_init_sysfs(); 3030 err = smk_init_sysfs();