aboutsummaryrefslogtreecommitdiffstats
path: root/security/smack
diff options
context:
space:
mode:
authorCasey Schaufler <casey@schaufler-ca.com>2015-03-21 21:26:40 -0400
committerCasey Schaufler <casey@schaufler-ca.com>2015-03-23 16:21:34 -0400
commitbf4b2fee99799780ea3dbb6d79d1909b3e32be13 (patch)
tree70224834f619caa3bf5abd39a7334f5b77bf5656 /security/smack
parent7fc5f36e980a8f4830efdae3858f6e64eee538b7 (diff)
Smack: Allow an unconfined label in bringup mode
I have vehemently opposed adding a "permissive" mode to Smack for the simple reasons that it would be subject to massive abuse and that developers refuse to turn it off come product release. I still believe that this is true, and still refuse to add a general "permissive mode". So don't ask again. Bumjin Im suggested an approach that addresses most of the concerns, and I have implemented it here. I still believe that we'd be better off without this sort of thing, but it looks like this minimizes the abuse potential. Firstly, you have to configure Smack Bringup Mode. That allows for "release" software to be ammune from abuse. Second, only one label gets to be "permissive" at a time. You can use it for debugging, but that's about it. A label written to smackfs/unconfined is treated specially. If either the subject or object label of an access check matches the "unconfined" label, and the access would not have been allowed otherwise an audit record and a console message are generated. The audit record "request" string is marked with either "(US)" or "(UO)", to indicate that the request was granted because of an unconfined label. The fact that an inode was accessed by an unconfined label is remembered, and subsequent accesses to that "impure" object are noted in the log. The impurity is not stored in the filesystem, so a file mislabled as a side effect of using an unconfined label may still cause concern after a reboot. So, it's there, it's dangerous, but so many application developers seem incapable of living without it I have given in. I've tried to make it as safe as I can, but in the end it's still a chain saw. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Diffstat (limited to 'security/smack')
-rw-r--r--security/smack/smack.h8
-rw-r--r--security/smack/smack_access.c43
-rw-r--r--security/smack/smack_lsm.c52
-rw-r--r--security/smack/smackfs.c96
4 files changed, 182 insertions, 17 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 67ccb7b2b89b..49eada6266ec 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -105,6 +105,7 @@ struct task_smack {
105#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ 105#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */
106#define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */ 106#define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */
107#define SMK_INODE_CHANGED 0x04 /* smack was transmuted */ 107#define SMK_INODE_CHANGED 0x04 /* smack was transmuted */
108#define SMK_INODE_IMPURE 0x08 /* involved in an impure transaction */
108 109
109/* 110/*
110 * A label access rule. 111 * A label access rule.
@@ -193,6 +194,10 @@ struct smk_port_label {
193#define MAY_LOCK 0x00002000 /* Locks should be writes, but ... */ 194#define MAY_LOCK 0x00002000 /* Locks should be writes, but ... */
194#define MAY_BRINGUP 0x00004000 /* Report use of this rule */ 195#define MAY_BRINGUP 0x00004000 /* Report use of this rule */
195 196
197#define SMACK_BRINGUP_ALLOW 1 /* Allow bringup mode */
198#define SMACK_UNCONFINED_SUBJECT 2 /* Allow unconfined label */
199#define SMACK_UNCONFINED_OBJECT 3 /* Allow unconfined label */
200
196/* 201/*
197 * Just to make the common cases easier to deal with 202 * Just to make the common cases easier to deal with
198 */ 203 */
@@ -254,6 +259,9 @@ extern int smack_cipso_mapped;
254extern struct smack_known *smack_net_ambient; 259extern struct smack_known *smack_net_ambient;
255extern struct smack_known *smack_onlycap; 260extern struct smack_known *smack_onlycap;
256extern struct smack_known *smack_syslog_label; 261extern struct smack_known *smack_syslog_label;
262#ifdef CONFIG_SECURITY_SMACK_BRINGUP
263extern struct smack_known *smack_unconfined;
264#endif
257extern struct smack_known smack_cipso_option; 265extern struct smack_known smack_cipso_option;
258extern int smack_ptrace_rule; 266extern int smack_ptrace_rule;
259 267
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 1158430f5bb9..0f410fc56e33 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -130,7 +130,8 @@ int smk_access(struct smack_known *subject, struct smack_known *object,
130 130
131 /* 131 /*
132 * Hardcoded comparisons. 132 * Hardcoded comparisons.
133 * 133 */
134 /*
134 * A star subject can't access any object. 135 * A star subject can't access any object.
135 */ 136 */
136 if (subject == &smack_known_star) { 137 if (subject == &smack_known_star) {
@@ -189,10 +190,20 @@ int smk_access(struct smack_known *subject, struct smack_known *object,
189 * succeed because of "b" rules. 190 * succeed because of "b" rules.
190 */ 191 */
191 if (may & MAY_BRINGUP) 192 if (may & MAY_BRINGUP)
192 rc = MAY_BRINGUP; 193 rc = SMACK_BRINGUP_ALLOW;
193#endif 194#endif
194 195
195out_audit: 196out_audit:
197
198#ifdef CONFIG_SECURITY_SMACK_BRINGUP
199 if (rc < 0) {
200 if (object == smack_unconfined)
201 rc = SMACK_UNCONFINED_OBJECT;
202 if (subject == smack_unconfined)
203 rc = SMACK_UNCONFINED_SUBJECT;
204 }
205#endif
206
196#ifdef CONFIG_AUDIT 207#ifdef CONFIG_AUDIT
197 if (a) 208 if (a)
198 smack_log(subject->smk_known, object->smk_known, 209 smack_log(subject->smk_known, object->smk_known,
@@ -338,19 +349,16 @@ static void smack_log_callback(struct audit_buffer *ab, void *a)
338void smack_log(char *subject_label, char *object_label, int request, 349void smack_log(char *subject_label, char *object_label, int request,
339 int result, struct smk_audit_info *ad) 350 int result, struct smk_audit_info *ad)
340{ 351{
352#ifdef CONFIG_SECURITY_SMACK_BRINGUP
353 char request_buffer[SMK_NUM_ACCESS_TYPE + 5];
354#else
341 char request_buffer[SMK_NUM_ACCESS_TYPE + 1]; 355 char request_buffer[SMK_NUM_ACCESS_TYPE + 1];
356#endif
342 struct smack_audit_data *sad; 357 struct smack_audit_data *sad;
343 struct common_audit_data *a = &ad->a; 358 struct common_audit_data *a = &ad->a;
344 359
345#ifdef CONFIG_SECURITY_SMACK_BRINGUP
346 /*
347 * The result may be positive in bringup mode.
348 */
349 if (result > 0)
350 result = 0;
351#endif
352 /* check if we have to log the current event */ 360 /* check if we have to log the current event */
353 if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0) 361 if (result < 0 && (log_policy & SMACK_AUDIT_DENIED) == 0)
354 return; 362 return;
355 if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0) 363 if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
356 return; 364 return;
@@ -364,6 +372,21 @@ void smack_log(char *subject_label, char *object_label, int request,
364 smack_str_from_perm(request_buffer, request); 372 smack_str_from_perm(request_buffer, request);
365 sad->subject = subject_label; 373 sad->subject = subject_label;
366 sad->object = object_label; 374 sad->object = object_label;
375#ifdef CONFIG_SECURITY_SMACK_BRINGUP
376 /*
377 * The result may be positive in bringup mode.
378 * A positive result is an allow, but not for normal reasons.
379 * Mark it as successful, but don't filter it out even if
380 * the logging policy says to do so.
381 */
382 if (result == SMACK_UNCONFINED_SUBJECT)
383 strcat(request_buffer, "(US)");
384 else if (result == SMACK_UNCONFINED_OBJECT)
385 strcat(request_buffer, "(UO)");
386
387 if (result > 0)
388 result = 0;
389#endif
367 sad->request = request_buffer; 390 sad->request = request_buffer;
368 sad->result = result; 391 sad->result = result;
369 392
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index e2d1a7b073c0..6f3c7d866d04 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -57,6 +57,13 @@ static struct kmem_cache *smack_inode_cache;
57int smack_enabled; 57int smack_enabled;
58 58
59#ifdef CONFIG_SECURITY_SMACK_BRINGUP 59#ifdef CONFIG_SECURITY_SMACK_BRINGUP
60static char *smk_bu_mess[] = {
61 "Bringup Error", /* Unused */
62 "Bringup", /* SMACK_BRINGUP_ALLOW */
63 "Unconfined Subject", /* SMACK_UNCONFINED_SUBJECT */
64 "Unconfined Object", /* SMACK_UNCONFINED_OBJECT */
65};
66
60static void smk_bu_mode(int mode, char *s) 67static void smk_bu_mode(int mode, char *s)
61{ 68{
62 int i = 0; 69 int i = 0;
@@ -87,9 +94,11 @@ static int smk_bu_note(char *note, struct smack_known *sskp,
87 94
88 if (rc <= 0) 95 if (rc <= 0)
89 return rc; 96 return rc;
97 if (rc > SMACK_UNCONFINED_OBJECT)
98 rc = 0;
90 99
91 smk_bu_mode(mode, acc); 100 smk_bu_mode(mode, acc);
92 pr_info("Smack Bringup: (%s %s %s) %s\n", 101 pr_info("Smack %s: (%s %s %s) %s\n", smk_bu_mess[rc],
93 sskp->smk_known, oskp->smk_known, acc, note); 102 sskp->smk_known, oskp->smk_known, acc, note);
94 return 0; 103 return 0;
95} 104}
@@ -106,9 +115,11 @@ static int smk_bu_current(char *note, struct smack_known *oskp,
106 115
107 if (rc <= 0) 116 if (rc <= 0)
108 return rc; 117 return rc;
118 if (rc > SMACK_UNCONFINED_OBJECT)
119 rc = 0;
109 120
110 smk_bu_mode(mode, acc); 121 smk_bu_mode(mode, acc);
111 pr_info("Smack Bringup: (%s %s %s) %s %s\n", 122 pr_info("Smack %s: (%s %s %s) %s %s\n", smk_bu_mess[rc],
112 tsp->smk_task->smk_known, oskp->smk_known, 123 tsp->smk_task->smk_known, oskp->smk_known,
113 acc, current->comm, note); 124 acc, current->comm, note);
114 return 0; 125 return 0;
@@ -126,9 +137,11 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc)
126 137
127 if (rc <= 0) 138 if (rc <= 0)
128 return rc; 139 return rc;
140 if (rc > SMACK_UNCONFINED_OBJECT)
141 rc = 0;
129 142
130 smk_bu_mode(mode, acc); 143 smk_bu_mode(mode, acc);
131 pr_info("Smack Bringup: (%s %s %s) %s to %s\n", 144 pr_info("Smack %s: (%s %s %s) %s to %s\n", smk_bu_mess[rc],
132 tsp->smk_task->smk_known, smk_task->smk_known, acc, 145 tsp->smk_task->smk_known, smk_task->smk_known, acc,
133 current->comm, otp->comm); 146 current->comm, otp->comm);
134 return 0; 147 return 0;
@@ -141,14 +154,25 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc)
141static int smk_bu_inode(struct inode *inode, int mode, int rc) 154static int smk_bu_inode(struct inode *inode, int mode, int rc)
142{ 155{
143 struct task_smack *tsp = current_security(); 156 struct task_smack *tsp = current_security();
157 struct inode_smack *isp = inode->i_security;
144 char acc[SMK_NUM_ACCESS_TYPE + 1]; 158 char acc[SMK_NUM_ACCESS_TYPE + 1];
145 159
160 if (isp->smk_flags & SMK_INODE_IMPURE)
161 pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
162 inode->i_sb->s_id, inode->i_ino, current->comm);
163
146 if (rc <= 0) 164 if (rc <= 0)
147 return rc; 165 return rc;
166 if (rc > SMACK_UNCONFINED_OBJECT)
167 rc = 0;
168 if (rc == SMACK_UNCONFINED_SUBJECT &&
169 (mode & (MAY_WRITE | MAY_APPEND)))
170 isp->smk_flags |= SMK_INODE_IMPURE;
148 171
149 smk_bu_mode(mode, acc); 172 smk_bu_mode(mode, acc);
150 pr_info("Smack Bringup: (%s %s %s) inode=(%s %ld) %s\n", 173
151 tsp->smk_task->smk_known, smk_of_inode(inode)->smk_known, acc, 174 pr_info("Smack %s: (%s %s %s) inode=(%s %ld) %s\n", smk_bu_mess[rc],
175 tsp->smk_task->smk_known, isp->smk_inode->smk_known, acc,
152 inode->i_sb->s_id, inode->i_ino, current->comm); 176 inode->i_sb->s_id, inode->i_ino, current->comm);
153 return 0; 177 return 0;
154} 178}
@@ -162,13 +186,20 @@ static int smk_bu_file(struct file *file, int mode, int rc)
162 struct task_smack *tsp = current_security(); 186 struct task_smack *tsp = current_security();
163 struct smack_known *sskp = tsp->smk_task; 187 struct smack_known *sskp = tsp->smk_task;
164 struct inode *inode = file_inode(file); 188 struct inode *inode = file_inode(file);
189 struct inode_smack *isp = inode->i_security;
165 char acc[SMK_NUM_ACCESS_TYPE + 1]; 190 char acc[SMK_NUM_ACCESS_TYPE + 1];
166 191
192 if (isp->smk_flags & SMK_INODE_IMPURE)
193 pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
194 inode->i_sb->s_id, inode->i_ino, current->comm);
195
167 if (rc <= 0) 196 if (rc <= 0)
168 return rc; 197 return rc;
198 if (rc > SMACK_UNCONFINED_OBJECT)
199 rc = 0;
169 200
170 smk_bu_mode(mode, acc); 201 smk_bu_mode(mode, acc);
171 pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n", 202 pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc],
172 sskp->smk_known, smk_of_inode(inode)->smk_known, acc, 203 sskp->smk_known, smk_of_inode(inode)->smk_known, acc,
173 inode->i_sb->s_id, inode->i_ino, file, 204 inode->i_sb->s_id, inode->i_ino, file,
174 current->comm); 205 current->comm);
@@ -185,13 +216,20 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file,
185 struct task_smack *tsp = cred->security; 216 struct task_smack *tsp = cred->security;
186 struct smack_known *sskp = tsp->smk_task; 217 struct smack_known *sskp = tsp->smk_task;
187 struct inode *inode = file->f_inode; 218 struct inode *inode = file->f_inode;
219 struct inode_smack *isp = inode->i_security;
188 char acc[SMK_NUM_ACCESS_TYPE + 1]; 220 char acc[SMK_NUM_ACCESS_TYPE + 1];
189 221
222 if (isp->smk_flags & SMK_INODE_IMPURE)
223 pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
224 inode->i_sb->s_id, inode->i_ino, current->comm);
225
190 if (rc <= 0) 226 if (rc <= 0)
191 return rc; 227 return rc;
228 if (rc > SMACK_UNCONFINED_OBJECT)
229 rc = 0;
192 230
193 smk_bu_mode(mode, acc); 231 smk_bu_mode(mode, acc);
194 pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n", 232 pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc],
195 sskp->smk_known, smk_of_inode(inode)->smk_known, acc, 233 sskp->smk_known, smk_of_inode(inode)->smk_known, acc,
196 inode->i_sb->s_id, inode->i_ino, file, 234 inode->i_sb->s_id, inode->i_ino, file,
197 current->comm); 235 current->comm);
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index bce4e8f1b267..deb3d3bfbbf3 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -54,6 +54,9 @@ enum smk_inos {
54 SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */ 54 SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */
55 SMK_SYSLOG = 20, /* change syslog label) */ 55 SMK_SYSLOG = 20, /* change syslog label) */
56 SMK_PTRACE = 21, /* set ptrace rule */ 56 SMK_PTRACE = 21, /* set ptrace rule */
57#ifdef CONFIG_SECURITY_SMACK_BRINGUP
58 SMK_UNCONFINED = 22, /* define an unconfined label */
59#endif
57}; 60};
58 61
59/* 62/*
@@ -95,6 +98,16 @@ int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT;
95 */ 98 */
96struct smack_known *smack_onlycap; 99struct smack_known *smack_onlycap;
97 100
101#ifdef CONFIG_SECURITY_SMACK_BRINGUP
102/*
103 * Allow one label to be unconfined. This is for
104 * debugging and application bring-up purposes only.
105 * It is bad and wrong, but everyone seems to expect
106 * to have it.
107 */
108struct smack_known *smack_unconfined;
109#endif
110
98/* 111/*
99 * If this value is set restrict syslog use to the label specified. 112 * If this value is set restrict syslog use to the label specified.
100 * It can be reset via smackfs/syslog 113 * It can be reset via smackfs/syslog
@@ -1717,6 +1730,85 @@ static const struct file_operations smk_onlycap_ops = {
1717 .llseek = default_llseek, 1730 .llseek = default_llseek,
1718}; 1731};
1719 1732
1733#ifdef CONFIG_SECURITY_SMACK_BRINGUP
1734/**
1735 * smk_read_unconfined - read() for smackfs/unconfined
1736 * @filp: file pointer, not actually used
1737 * @buf: where to put the result
1738 * @cn: maximum to send along
1739 * @ppos: where to start
1740 *
1741 * Returns number of bytes read or error code, as appropriate
1742 */
1743static ssize_t smk_read_unconfined(struct file *filp, char __user *buf,
1744 size_t cn, loff_t *ppos)
1745{
1746 char *smack = "";
1747 ssize_t rc = -EINVAL;
1748 int asize;
1749
1750 if (*ppos != 0)
1751 return 0;
1752
1753 if (smack_unconfined != NULL)
1754 smack = smack_unconfined->smk_known;
1755
1756 asize = strlen(smack) + 1;
1757
1758 if (cn >= asize)
1759 rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
1760
1761 return rc;
1762}
1763
1764/**
1765 * smk_write_unconfined - write() for smackfs/unconfined
1766 * @file: file pointer, not actually used
1767 * @buf: where to get the data from
1768 * @count: bytes sent
1769 * @ppos: where to start
1770 *
1771 * Returns number of bytes written or error code, as appropriate
1772 */
1773static ssize_t smk_write_unconfined(struct file *file, const char __user *buf,
1774 size_t count, loff_t *ppos)
1775{
1776 char *data;
1777 int rc = count;
1778
1779 if (!smack_privileged(CAP_MAC_ADMIN))
1780 return -EPERM;
1781
1782 data = kzalloc(count + 1, GFP_KERNEL);
1783 if (data == NULL)
1784 return -ENOMEM;
1785
1786 /*
1787 * Should the null string be passed in unset the unconfined value.
1788 * This seems like something to be careful with as usually
1789 * smk_import only expects to return NULL for errors. It
1790 * is usually the case that a nullstring or "\n" would be
1791 * bad to pass to smk_import but in fact this is useful here.
1792 *
1793 * smk_import will also reject a label beginning with '-',
1794 * so "-confine" will also work.
1795 */
1796 if (copy_from_user(data, buf, count) != 0)
1797 rc = -EFAULT;
1798 else
1799 smack_unconfined = smk_import_entry(data, count);
1800
1801 kfree(data);
1802 return rc;
1803}
1804
1805static const struct file_operations smk_unconfined_ops = {
1806 .read = smk_read_unconfined,
1807 .write = smk_write_unconfined,
1808 .llseek = default_llseek,
1809};
1810#endif /* CONFIG_SECURITY_SMACK_BRINGUP */
1811
1720/** 1812/**
1721 * smk_read_logging - read() for /smack/logging 1813 * smk_read_logging - read() for /smack/logging
1722 * @filp: file pointer, not actually used 1814 * @filp: file pointer, not actually used
@@ -2384,6 +2476,10 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
2384 "syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR}, 2476 "syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR},
2385 [SMK_PTRACE] = { 2477 [SMK_PTRACE] = {
2386 "ptrace", &smk_ptrace_ops, S_IRUGO|S_IWUSR}, 2478 "ptrace", &smk_ptrace_ops, S_IRUGO|S_IWUSR},
2479#ifdef CONFIG_SECURITY_SMACK_BRINGUP
2480 [SMK_UNCONFINED] = {
2481 "unconfined", &smk_unconfined_ops, S_IRUGO|S_IWUSR},
2482#endif
2387 /* last one */ 2483 /* last one */
2388 {""} 2484 {""}
2389 }; 2485 };