Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'smack-for-4.4' of https://github.com/cschaufler/smack-next into next

+248 -47
+10
Documentation/security/Smack.txt
··· 255 255 the access permitted if it wouldn't be otherwise. Note that this 256 256 is dangerous and can ruin the proper labeling of your system. 257 257 It should never be used in production. 258 + relabel-self 259 + This interface contains a list of labels to which the process can 260 + transition to, by writing to /proc/self/attr/current. 261 + Normally a process can change its own label to any legal value, but only 262 + if it has CAP_MAC_ADMIN. This interface allows a process without 263 + CAP_MAC_ADMIN to relabel itself to one of labels from predefined list. 264 + A process without CAP_MAC_ADMIN can change its label only once. When it 265 + does, this list will be cleared. 266 + The values are set by writing the desired labels, separated 267 + by spaces, to the file or cleared by writing "-" to the file. 258 268 259 269 If you are using the smackload utility 260 270 you can add access rules in /etc/smack/accesses. They take the form:
+3 -1
security/smack/smack.h
··· 115 115 struct smack_known *smk_forked; /* label when forked */ 116 116 struct list_head smk_rules; /* per task access rules */ 117 117 struct mutex smk_rules_lock; /* lock for the rules */ 118 + struct list_head smk_relabel; /* transit allowed labels */ 118 119 }; 119 120 120 121 #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ ··· 170 169 }; 171 170 #endif /* SMACK_IPV6_PORT_LABELING */ 172 171 173 - struct smack_onlycap { 172 + struct smack_known_list_elem { 174 173 struct list_head list; 175 174 struct smack_known *smk_label; 176 175 }; ··· 302 301 void smk_insert_entry(struct smack_known *skp); 303 302 struct smack_known *smk_find_entry(const char *); 304 303 int smack_privileged(int cap); 304 + void smk_destroy_label_list(struct list_head *list); 305 305 306 306 /* 307 307 * Shared data.
+3 -3
security/smack/smack_access.c
··· 637 637 int smack_privileged(int cap) 638 638 { 639 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 643 * All kernel tasks are privileged ··· 654 654 return 1; 655 655 } 656 656 657 - list_for_each_entry_rcu(sop, &smack_onlycap_list, list) { 658 - if (sop->smk_label == skp) { 657 + list_for_each_entry_rcu(sklep, &smack_onlycap_list, list) { 658 + if (sklep->smk_label == skp) { 659 659 rcu_read_unlock(); 660 660 return 1; 661 661 }
+62 -5
security/smack/smack_lsm.c
··· 52 52 #define SMK_SENDING 2 53 53 54 54 #ifdef SMACK_IPV6_PORT_LABELING 55 - LIST_HEAD(smk_ipv6_port_list); 55 + static LIST_HEAD(smk_ipv6_port_list); 56 56 #endif 57 57 static struct kmem_cache *smack_inode_cache; 58 58 int smack_enabled; ··· 326 326 tsp->smk_task = task; 327 327 tsp->smk_forked = forked; 328 328 INIT_LIST_HEAD(&tsp->smk_rules); 329 + INIT_LIST_HEAD(&tsp->smk_relabel); 329 330 mutex_init(&tsp->smk_rules_lock); 330 331 331 332 return tsp; ··· 359 358 list_add_rcu(&nrp->list, nhead); 360 359 } 361 360 return rc; 361 + } 362 + 363 + /** 364 + * smk_copy_relabel - copy smk_relabel labels list 365 + * @nhead: new rules header pointer 366 + * @ohead: old rules header pointer 367 + * @gfp: type of the memory for the allocation 368 + * 369 + * Returns 0 on success, -ENOMEM on error 370 + */ 371 + static int smk_copy_relabel(struct list_head *nhead, struct list_head *ohead, 372 + gfp_t gfp) 373 + { 374 + struct smack_known_list_elem *nklep; 375 + struct smack_known_list_elem *oklep; 376 + 377 + INIT_LIST_HEAD(nhead); 378 + 379 + list_for_each_entry(oklep, ohead, list) { 380 + nklep = kzalloc(sizeof(struct smack_known_list_elem), gfp); 381 + if (nklep == NULL) { 382 + smk_destroy_label_list(nhead); 383 + return -ENOMEM; 384 + } 385 + nklep->smk_label = oklep->smk_label; 386 + list_add(&nklep->list, nhead); 387 + } 388 + 389 + return 0; 362 390 } 363 391 364 392 /** ··· 1952 1922 return; 1953 1923 cred->security = NULL; 1954 1924 1925 + smk_destroy_label_list(&tsp->smk_relabel); 1926 + 1955 1927 list_for_each_safe(l, n, &tsp->smk_rules) { 1956 1928 rp = list_entry(l, struct smack_rule, list); 1957 1929 list_del(&rp->list); ··· 1982 1950 return -ENOMEM; 1983 1951 1984 1952 rc = smk_copy_rules(&new_tsp->smk_rules, &old_tsp->smk_rules, gfp); 1953 + if (rc != 0) 1954 + return rc; 1955 + 1956 + rc = smk_copy_relabel(&new_tsp->smk_relabel, &old_tsp->smk_relabel, 1957 + gfp); 1985 1958 if (rc != 0) 1986 1959 return rc; 1987 1960 ··· 3391 3354 */ 3392 3355 isp->smk_inode = smk_of_current(); 3393 3356 break; 3357 + case PIPEFS_MAGIC: 3358 + isp->smk_inode = smk_of_current(); 3359 + break; 3394 3360 default: 3395 3361 isp->smk_inode = sbsp->smk_root; 3396 3362 break; ··· 3589 3549 static int smack_setprocattr(struct task_struct *p, char *name, 3590 3550 void *value, size_t size) 3591 3551 { 3592 - struct task_smack *tsp; 3552 + struct task_smack *tsp = current_security(); 3593 3553 struct cred *new; 3594 3554 struct smack_known *skp; 3555 + struct smack_known_list_elem *sklep; 3556 + int rc; 3595 3557 3596 3558 /* 3597 3559 * Changing another process' Smack value is too dangerous ··· 3602 3560 if (p != current) 3603 3561 return -EPERM; 3604 3562 3605 - if (!smack_privileged(CAP_MAC_ADMIN)) 3563 + if (!smack_privileged(CAP_MAC_ADMIN) && list_empty(&tsp->smk_relabel)) 3606 3564 return -EPERM; 3607 3565 3608 3566 if (value == NULL || size == 0 || size >= SMK_LONGLABEL) ··· 3621 3579 if (skp == &smack_known_web) 3622 3580 return -EPERM; 3623 3581 3582 + if (!smack_privileged(CAP_MAC_ADMIN)) { 3583 + rc = -EPERM; 3584 + list_for_each_entry(sklep, &tsp->smk_relabel, list) 3585 + if (sklep->smk_label == skp) { 3586 + rc = 0; 3587 + break; 3588 + } 3589 + if (rc) 3590 + return rc; 3591 + } 3592 + 3624 3593 new = prepare_creds(); 3625 3594 if (new == NULL) 3626 3595 return -ENOMEM; 3627 3596 3628 3597 tsp = new->security; 3629 3598 tsp->smk_task = skp; 3599 + /* 3600 + * process can change its label only once 3601 + */ 3602 + smk_destroy_label_list(&tsp->smk_relabel); 3630 3603 3631 3604 commit_creds(new); 3632 3605 return size; ··· 4765 4708 if (!security_module_enable("smack")) 4766 4709 return 0; 4767 4710 4768 - smack_enabled = 1; 4769 - 4770 4711 smack_inode_cache = KMEM_CACHE(inode_smack, 0); 4771 4712 if (!smack_inode_cache) 4772 4713 return -ENOMEM; ··· 4775 4720 kmem_cache_destroy(smack_inode_cache); 4776 4721 return -ENOMEM; 4777 4722 } 4723 + 4724 + smack_enabled = 1; 4778 4725 4779 4726 pr_info("Smack: Initializing.\n"); 4780 4727 #ifdef CONFIG_SECURITY_SMACK_NETFILTER
+170 -38
security/smack/smackfs.c
··· 61 61 #if IS_ENABLED(CONFIG_IPV6) 62 62 SMK_NET6ADDR = 23, /* single label IPv6 hosts */ 63 63 #endif /* CONFIG_IPV6 */ 64 + SMK_RELABEL_SELF = 24, /* relabel possible without CAP_MAC_ADMIN */ 64 65 }; 65 66 66 67 /* ··· 1502 1501 */ 1503 1502 if (smack[0] != '-') { 1504 1503 skp = smk_import_entry(smack, 0); 1505 - if (skp == NULL) { 1506 - rc = -EINVAL; 1504 + if (IS_ERR(skp)) { 1505 + rc = PTR_ERR(skp); 1507 1506 goto free_out; 1508 1507 } 1509 1508 } else { ··· 1915 1914 static int onlycap_seq_show(struct seq_file *s, void *v) 1916 1915 { 1917 1916 struct list_head *list = v; 1918 - struct smack_onlycap *sop = 1919 - list_entry_rcu(list, struct smack_onlycap, list); 1917 + struct smack_known_list_elem *sklep = 1918 + list_entry_rcu(list, struct smack_known_list_elem, list); 1920 1919 1921 - seq_puts(s, sop->smk_label->smk_known); 1920 + seq_puts(s, sklep->smk_label->smk_known); 1922 1921 seq_putc(s, ' '); 1923 1922 1924 1923 return 0; ··· 1975 1974 } 1976 1975 1977 1976 /** 1977 + * smk_parse_label_list - parse list of Smack labels, separated by spaces 1978 + * 1979 + * @data: the string to parse 1980 + * @private: destination list 1981 + * 1982 + * Returns zero on success or error code, as appropriate 1983 + */ 1984 + static int smk_parse_label_list(char *data, struct list_head *list) 1985 + { 1986 + char *tok; 1987 + struct smack_known *skp; 1988 + struct smack_known_list_elem *sklep; 1989 + 1990 + while ((tok = strsep(&data, " ")) != NULL) { 1991 + if (!*tok) 1992 + continue; 1993 + 1994 + skp = smk_import_entry(tok, 0); 1995 + if (IS_ERR(skp)) 1996 + return PTR_ERR(skp); 1997 + 1998 + sklep = kzalloc(sizeof(*sklep), GFP_KERNEL); 1999 + if (sklep == NULL) 2000 + return -ENOMEM; 2001 + 2002 + sklep->smk_label = skp; 2003 + list_add(&sklep->list, list); 2004 + } 2005 + 2006 + return 0; 2007 + } 2008 + 2009 + /** 2010 + * smk_destroy_label_list - destroy a list of smack_known_list_elem 2011 + * @head: header pointer of the list to destroy 2012 + */ 2013 + void smk_destroy_label_list(struct list_head *list) 2014 + { 2015 + struct smack_known_list_elem *sklep; 2016 + struct smack_known_list_elem *sklep2; 2017 + 2018 + list_for_each_entry_safe(sklep, sklep2, list, list) 2019 + kfree(sklep); 2020 + 2021 + INIT_LIST_HEAD(list); 2022 + } 2023 + 2024 + /** 1978 2025 * smk_write_onlycap - write() for smackfs/onlycap 1979 2026 * @file: file pointer, not actually used 1980 2027 * @buf: where to get the data from ··· 2035 1986 size_t count, loff_t *ppos) 2036 1987 { 2037 1988 char *data; 2038 - char *data_parse; 2039 - char *tok; 2040 - struct smack_known *skp; 2041 - struct smack_onlycap *sop; 2042 - struct smack_onlycap *sop2; 2043 1989 LIST_HEAD(list_tmp); 2044 - int rc = count; 1990 + int rc; 2045 1991 2046 1992 if (!smack_privileged(CAP_MAC_ADMIN)) 2047 1993 return -EPERM; ··· 2050 2006 return -EFAULT; 2051 2007 } 2052 2008 2053 - data_parse = data; 2054 - while ((tok = strsep(&data_parse, " ")) != NULL) { 2055 - if (!*tok) 2056 - continue; 2057 - 2058 - skp = smk_import_entry(tok, 0); 2059 - if (IS_ERR(skp)) { 2060 - rc = PTR_ERR(skp); 2061 - break; 2062 - } 2063 - 2064 - sop = kzalloc(sizeof(*sop), GFP_KERNEL); 2065 - if (sop == NULL) { 2066 - rc = -ENOMEM; 2067 - break; 2068 - } 2069 - 2070 - sop->smk_label = skp; 2071 - list_add_rcu(&sop->list, &list_tmp); 2072 - } 2009 + rc = smk_parse_label_list(data, &list_tmp); 2073 2010 kfree(data); 2074 2011 2075 2012 /* ··· 2063 2038 * But do so only on invalid label, not on system errors. 2064 2039 * The invalid label must be first to count as clearing attempt. 2065 2040 */ 2066 - if (rc == -EINVAL && list_empty(&list_tmp)) 2067 - rc = count; 2068 - 2069 - if (rc >= 0) { 2041 + if (!rc || (rc == -EINVAL && list_empty(&list_tmp))) { 2070 2042 mutex_lock(&smack_onlycap_lock); 2071 2043 smk_list_swap_rcu(&smack_onlycap_list, &list_tmp); 2072 2044 mutex_unlock(&smack_onlycap_lock); 2045 + rc = count; 2073 2046 } 2074 2047 2075 - list_for_each_entry_safe(sop, sop2, &list_tmp, list) 2076 - kfree(sop); 2048 + smk_destroy_label_list(&list_tmp); 2077 2049 2078 2050 return rc; 2079 2051 } ··· 2720 2698 .llseek = default_llseek, 2721 2699 }; 2722 2700 2701 + /* 2702 + * Seq_file read operations for /smack/relabel-self 2703 + */ 2704 + 2705 + static void *relabel_self_seq_start(struct seq_file *s, loff_t *pos) 2706 + { 2707 + struct task_smack *tsp = current_security(); 2708 + 2709 + return smk_seq_start(s, pos, &tsp->smk_relabel); 2710 + } 2711 + 2712 + static void *relabel_self_seq_next(struct seq_file *s, void *v, loff_t *pos) 2713 + { 2714 + struct task_smack *tsp = current_security(); 2715 + 2716 + return smk_seq_next(s, v, pos, &tsp->smk_relabel); 2717 + } 2718 + 2719 + static int relabel_self_seq_show(struct seq_file *s, void *v) 2720 + { 2721 + struct list_head *list = v; 2722 + struct smack_known_list_elem *sklep = 2723 + list_entry(list, struct smack_known_list_elem, list); 2724 + 2725 + seq_puts(s, sklep->smk_label->smk_known); 2726 + seq_putc(s, ' '); 2727 + 2728 + return 0; 2729 + } 2730 + 2731 + static const struct seq_operations relabel_self_seq_ops = { 2732 + .start = relabel_self_seq_start, 2733 + .next = relabel_self_seq_next, 2734 + .show = relabel_self_seq_show, 2735 + .stop = smk_seq_stop, 2736 + }; 2737 + 2738 + /** 2739 + * smk_open_relabel_self - open() for /smack/relabel-self 2740 + * @inode: inode structure representing file 2741 + * @file: "relabel-self" file pointer 2742 + * 2743 + * Connect our relabel_self_seq_* operations with /smack/relabel-self 2744 + * file_operations 2745 + */ 2746 + static int smk_open_relabel_self(struct inode *inode, struct file *file) 2747 + { 2748 + return seq_open(file, &relabel_self_seq_ops); 2749 + } 2750 + 2751 + /** 2752 + * smk_write_relabel_self - write() for /smack/relabel-self 2753 + * @file: file pointer, not actually used 2754 + * @buf: where to get the data from 2755 + * @count: bytes sent 2756 + * @ppos: where to start - must be 0 2757 + * 2758 + */ 2759 + static ssize_t smk_write_relabel_self(struct file *file, const char __user *buf, 2760 + size_t count, loff_t *ppos) 2761 + { 2762 + struct task_smack *tsp = current_security(); 2763 + char *data; 2764 + int rc; 2765 + LIST_HEAD(list_tmp); 2766 + 2767 + /* 2768 + * Must have privilege. 2769 + */ 2770 + if (!smack_privileged(CAP_MAC_ADMIN)) 2771 + return -EPERM; 2772 + 2773 + /* 2774 + * Enough data must be present. 2775 + */ 2776 + if (*ppos != 0) 2777 + return -EINVAL; 2778 + 2779 + data = kzalloc(count + 1, GFP_KERNEL); 2780 + if (data == NULL) 2781 + return -ENOMEM; 2782 + 2783 + if (copy_from_user(data, buf, count) != 0) { 2784 + kfree(data); 2785 + return -EFAULT; 2786 + } 2787 + 2788 + rc = smk_parse_label_list(data, &list_tmp); 2789 + kfree(data); 2790 + 2791 + if (!rc || (rc == -EINVAL && list_empty(&list_tmp))) { 2792 + smk_destroy_label_list(&tsp->smk_relabel); 2793 + list_splice(&list_tmp, &tsp->smk_relabel); 2794 + return count; 2795 + } 2796 + 2797 + smk_destroy_label_list(&list_tmp); 2798 + return rc; 2799 + } 2800 + 2801 + static const struct file_operations smk_relabel_self_ops = { 2802 + .open = smk_open_relabel_self, 2803 + .read = seq_read, 2804 + .llseek = seq_lseek, 2805 + .write = smk_write_relabel_self, 2806 + .release = seq_release, 2807 + }; 2723 2808 2724 2809 /** 2725 2810 * smk_read_ptrace - read() for /smack/ptrace ··· 2953 2824 [SMK_NET6ADDR] = { 2954 2825 "ipv6host", &smk_net6addr_ops, S_IRUGO|S_IWUSR}, 2955 2826 #endif /* CONFIG_IPV6 */ 2827 + [SMK_RELABEL_SELF] = { 2828 + "relabel-self", &smk_relabel_self_ops, 2829 + S_IRUGO|S_IWUGO}, 2956 2830 /* last one */ 2957 2831 {""} 2958 2832 }; ··· 3024 2892 int err; 3025 2893 int rc; 3026 2894 3027 - if (!security_module_enable("smack")) 2895 + if (smack_enabled == 0) 3028 2896 return 0; 3029 2897 3030 2898 err = smk_init_sysfs();