aboutsummaryrefslogtreecommitdiffstats
path: root/security/smack
diff options
context:
space:
mode:
Diffstat (limited to 'security/smack')
-rw-r--r--security/smack/smack.h25
-rw-r--r--security/smack/smack_access.c41
-rw-r--r--security/smack/smackfs.c163
3 files changed, 160 insertions, 69 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h
index b8c1a869d85e..244e035e5a99 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -138,6 +138,11 @@ struct smk_port_label {
138 struct smack_known *smk_out; /* outgoing label */ 138 struct smack_known *smk_out; /* outgoing label */
139}; 139};
140 140
141struct smack_onlycap {
142 struct list_head list;
143 struct smack_known *smk_label;
144};
145
141/* 146/*
142 * Mount options 147 * Mount options
143 */ 148 */
@@ -249,6 +254,7 @@ int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);
249struct smack_known *smk_import_entry(const char *, int); 254struct smack_known *smk_import_entry(const char *, int);
250void smk_insert_entry(struct smack_known *skp); 255void smk_insert_entry(struct smack_known *skp);
251struct smack_known *smk_find_entry(const char *); 256struct smack_known *smk_find_entry(const char *);
257int smack_privileged(int cap);
252 258
253/* 259/*
254 * Shared data. 260 * Shared data.
@@ -257,7 +263,6 @@ extern int smack_enabled;
257extern int smack_cipso_direct; 263extern int smack_cipso_direct;
258extern int smack_cipso_mapped; 264extern int smack_cipso_mapped;
259extern struct smack_known *smack_net_ambient; 265extern struct smack_known *smack_net_ambient;
260extern struct smack_known *smack_onlycap;
261extern struct smack_known *smack_syslog_label; 266extern struct smack_known *smack_syslog_label;
262#ifdef CONFIG_SECURITY_SMACK_BRINGUP 267#ifdef CONFIG_SECURITY_SMACK_BRINGUP
263extern struct smack_known *smack_unconfined; 268extern struct smack_known *smack_unconfined;
@@ -276,6 +281,9 @@ extern struct mutex smack_known_lock;
276extern struct list_head smack_known_list; 281extern struct list_head smack_known_list;
277extern struct list_head smk_netlbladdr_list; 282extern struct list_head smk_netlbladdr_list;
278 283
284extern struct mutex smack_onlycap_lock;
285extern struct list_head smack_onlycap_list;
286
279#define SMACK_HASH_SLOTS 16 287#define SMACK_HASH_SLOTS 16
280extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS]; 288extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS];
281 289
@@ -332,21 +340,6 @@ static inline struct smack_known *smk_of_current(void)
332} 340}
333 341
334/* 342/*
335 * Is the task privileged and allowed to be privileged
336 * by the onlycap rule.
337 */
338static inline int smack_privileged(int cap)
339{
340 struct smack_known *skp = smk_of_current();
341
342 if (!capable(cap))
343 return 0;
344 if (smack_onlycap == NULL || smack_onlycap == skp)
345 return 1;
346 return 0;
347}
348
349/*
350 * logging functions 343 * logging functions
351 */ 344 */
352#define SMACK_AUDIT_DENIED 0x1 345#define SMACK_AUDIT_DENIED 0x1
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 408e20be1ad7..00f6b38bffbd 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -617,3 +617,44 @@ struct smack_known *smack_from_secid(const u32 secid)
617 rcu_read_unlock(); 617 rcu_read_unlock();
618 return &smack_known_invalid; 618 return &smack_known_invalid;
619} 619}
620
621/*
622 * Unless a process is running with one of these labels
623 * even having CAP_MAC_OVERRIDE isn't enough to grant
624 * privilege to violate MAC policy. If no labels are
625 * designated (the empty list case) capabilities apply to
626 * everyone.
627 */
628LIST_HEAD(smack_onlycap_list);
629DEFINE_MUTEX(smack_onlycap_lock);
630
631/*
632 * Is the task privileged and allowed to be privileged
633 * by the onlycap rule.
634 *
635 * Returns 1 if the task is allowed to be privileged, 0 if it's not.
636 */
637int smack_privileged(int cap)
638{
639 struct smack_known *skp = smk_of_current();
640 struct smack_onlycap *sop;
641
642 if (!capable(cap))
643 return 0;
644
645 rcu_read_lock();
646 if (list_empty(&smack_onlycap_list)) {
647 rcu_read_unlock();
648 return 1;
649 }
650
651 list_for_each_entry_rcu(sop, &smack_onlycap_list, list) {
652 if (sop->smk_label == skp) {
653 rcu_read_unlock();
654 return 1;
655 }
656 }
657 rcu_read_unlock();
658
659 return 0;
660}
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index e40dc48737ff..f1c22a891b1a 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -87,16 +87,6 @@ int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
87 */ 87 */
88int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT; 88int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT;
89 89
90/*
91 * Unless a process is running with this label even
92 * having CAP_MAC_OVERRIDE isn't enough to grant
93 * privilege to violate MAC policy. If no label is
94 * designated (the NULL case) capabilities apply to
95 * everyone. It is expected that the hat (^) label
96 * will be used if any label is used.
97 */
98struct smack_known *smack_onlycap;
99
100#ifdef CONFIG_SECURITY_SMACK_BRINGUP 90#ifdef CONFIG_SECURITY_SMACK_BRINGUP
101/* 91/*
102 * Allow one label to be unconfined. This is for 92 * Allow one label to be unconfined. This is for
@@ -1636,34 +1626,79 @@ static const struct file_operations smk_ambient_ops = {
1636 .llseek = default_llseek, 1626 .llseek = default_llseek,
1637}; 1627};
1638 1628
1639/** 1629/*
1640 * smk_read_onlycap - read() for smackfs/onlycap 1630 * Seq_file operations for /smack/onlycap
1641 * @filp: file pointer, not actually used
1642 * @buf: where to put the result
1643 * @cn: maximum to send along
1644 * @ppos: where to start
1645 *
1646 * Returns number of bytes read or error code, as appropriate
1647 */ 1631 */
1648static ssize_t smk_read_onlycap(struct file *filp, char __user *buf, 1632static void *onlycap_seq_start(struct seq_file *s, loff_t *pos)
1649 size_t cn, loff_t *ppos)
1650{ 1633{
1651 char *smack = ""; 1634 return smk_seq_start(s, pos, &smack_onlycap_list);
1652 ssize_t rc = -EINVAL; 1635}
1653 int asize;
1654 1636
1655 if (*ppos != 0) 1637static void *onlycap_seq_next(struct seq_file *s, void *v, loff_t *pos)
1656 return 0; 1638{
1639 return smk_seq_next(s, v, pos, &smack_onlycap_list);
1640}
1657 1641
1658 if (smack_onlycap != NULL) 1642static int onlycap_seq_show(struct seq_file *s, void *v)
1659 smack = smack_onlycap->smk_known; 1643{
1644 struct list_head *list = v;
1645 struct smack_onlycap *sop =
1646 list_entry_rcu(list, struct smack_onlycap, list);
1660 1647
1661 asize = strlen(smack) + 1; 1648 seq_puts(s, sop->smk_label->smk_known);
1649 seq_putc(s, ' ');
1662 1650
1663 if (cn >= asize) 1651 return 0;
1664 rc = simple_read_from_buffer(buf, cn, ppos, smack, asize); 1652}
1665 1653
1666 return rc; 1654static const struct seq_operations onlycap_seq_ops = {
1655 .start = onlycap_seq_start,
1656 .next = onlycap_seq_next,
1657 .show = onlycap_seq_show,
1658 .stop = smk_seq_stop,
1659};
1660
1661static int smk_open_onlycap(struct inode *inode, struct file *file)
1662{
1663 return seq_open(file, &onlycap_seq_ops);
1664}
1665
1666/**
1667 * smk_list_swap_rcu - swap public list with a private one in RCU-safe way
1668 * The caller must hold appropriate mutex to prevent concurrent modifications
1669 * to the public list.
1670 * Private list is assumed to be not accessible to other threads yet.
1671 *
1672 * @public: public list
1673 * @private: private list
1674 */
1675static void smk_list_swap_rcu(struct list_head *public,
1676 struct list_head *private)
1677{
1678 struct list_head *first, *last;
1679
1680 if (list_empty(public)) {
1681 list_splice_init_rcu(private, public, synchronize_rcu);
1682 } else {
1683 /* Remember public list before replacing it */
1684 first = public->next;
1685 last = public->prev;
1686
1687 /* Publish private list in place of public in RCU-safe way */
1688 private->prev->next = public;
1689 private->next->prev = public;
1690 rcu_assign_pointer(public->next, private->next);
1691 public->prev = private->prev;
1692
1693 synchronize_rcu();
1694
1695 /* When all readers are done with the old public list,
1696 * attach it in place of private */
1697 private->next = first;
1698 private->prev = last;
1699 first->prev = private;
1700 last->next = private;
1701 }
1667} 1702}
1668 1703
1669/** 1704/**
@@ -1679,28 +1714,47 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
1679 size_t count, loff_t *ppos) 1714 size_t count, loff_t *ppos)
1680{ 1715{
1681 char *data; 1716 char *data;
1682 struct smack_known *skp = smk_of_task(current->cred->security); 1717 char *data_parse;
1718 char *tok;
1719 struct smack_known *skp;
1720 struct smack_onlycap *sop;
1721 struct smack_onlycap *sop2;
1722 LIST_HEAD(list_tmp);
1683 int rc = count; 1723 int rc = count;
1684 1724
1685 if (!smack_privileged(CAP_MAC_ADMIN)) 1725 if (!smack_privileged(CAP_MAC_ADMIN))
1686 return -EPERM; 1726 return -EPERM;
1687 1727
1688 /*
1689 * This can be done using smk_access() but is done
1690 * explicitly for clarity. The smk_access() implementation
1691 * would use smk_access(smack_onlycap, MAY_WRITE)
1692 */
1693 if (smack_onlycap != NULL && smack_onlycap != skp)
1694 return -EPERM;
1695
1696 data = kzalloc(count + 1, GFP_KERNEL); 1728 data = kzalloc(count + 1, GFP_KERNEL);
1697 if (data == NULL) 1729 if (data == NULL)
1698 return -ENOMEM; 1730 return -ENOMEM;
1699 1731
1700 if (copy_from_user(data, buf, count) != 0) { 1732 if (copy_from_user(data, buf, count) != 0) {
1701 rc = -EFAULT; 1733 kfree(data);
1702 goto freeout; 1734 return -EFAULT;
1735 }
1736
1737 data_parse = data;
1738 while ((tok = strsep(&data_parse, " ")) != NULL) {
1739 if (!*tok)
1740 continue;
1741
1742 skp = smk_import_entry(tok, 0);
1743 if (IS_ERR(skp)) {
1744 rc = PTR_ERR(skp);
1745 break;
1746 }
1747
1748 sop = kzalloc(sizeof(*sop), GFP_KERNEL);
1749 if (sop == NULL) {
1750 rc = -ENOMEM;
1751 break;
1752 }
1753
1754 sop->smk_label = skp;
1755 list_add_rcu(&sop->list, &list_tmp);
1703 } 1756 }
1757 kfree(data);
1704 1758
1705 /* 1759 /*
1706 * Clear the smack_onlycap on invalid label errors. This means 1760 * Clear the smack_onlycap on invalid label errors. This means
@@ -1710,26 +1764,29 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
1710 * so "-usecapabilities" will also work. 1764 * so "-usecapabilities" will also work.
1711 * 1765 *
1712 * But do so only on invalid label, not on system errors. 1766 * But do so only on invalid label, not on system errors.
1767 * The invalid label must be first to count as clearing attempt.
1713 */ 1768 */
1714 skp = smk_import_entry(data, count); 1769 if (rc == -EINVAL && list_empty(&list_tmp))
1715 if (PTR_ERR(skp) == -EINVAL) 1770 rc = count;
1716 skp = NULL; 1771
1717 else if (IS_ERR(skp)) { 1772 if (rc >= 0) {
1718 rc = PTR_ERR(skp); 1773 mutex_lock(&smack_onlycap_lock);
1719 goto freeout; 1774 smk_list_swap_rcu(&smack_onlycap_list, &list_tmp);
1775 mutex_unlock(&smack_onlycap_lock);
1720 } 1776 }
1721 1777
1722 smack_onlycap = skp; 1778 list_for_each_entry_safe(sop, sop2, &list_tmp, list)
1779 kfree(sop);
1723 1780
1724freeout:
1725 kfree(data);
1726 return rc; 1781 return rc;
1727} 1782}
1728 1783
1729static const struct file_operations smk_onlycap_ops = { 1784static const struct file_operations smk_onlycap_ops = {
1730 .read = smk_read_onlycap, 1785 .open = smk_open_onlycap,
1786 .read = seq_read,
1731 .write = smk_write_onlycap, 1787 .write = smk_write_onlycap,
1732 .llseek = default_llseek, 1788 .llseek = seq_lseek,
1789 .release = seq_release,
1733}; 1790};
1734 1791
1735#ifdef CONFIG_SECURITY_SMACK_BRINGUP 1792#ifdef CONFIG_SECURITY_SMACK_BRINGUP