aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-04-30 19:27:51 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-04-30 19:27:51 -0400
commit2e1deaad1e48453cea782854ab87df3f78c121c2 (patch)
treeda0fe592dcc9ef6b0c4cd104a67af3c1d9e4c5d5 /security
parent50528fabeb25f9883e2845f5147f5e00a1c57cf7 (diff)
parentb7ae9f064bec903bd4a9f257a35da4d1e9bbcc99 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem update from James Morris: "Just some minor updates across the subsystem" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: ima: eliminate passing d_name.name to process_measurement() TPM: Retry SaveState command in suspend path tpm/tpm_i2c_infineon: Add small comment about return value of __i2c_transfer tpm/tpm_i2c_infineon.c: Add OF attributes type and name to the of_device_id table entries tpm_i2c_stm_st33: Remove duplicate inclusion of header files tpm: Add support for new Infineon I2C TPM (SLB 9645 TT 1.2 I2C) char/tpm: Convert struct i2c_msg initialization to C99 format drivers/char/tpm/tpm_ppi: use strlcpy instead of strncpy tpm/tpm_i2c_stm_st33: formatting and white space changes Smack: include magic.h in smackfs.c selinux: make security_sb_clone_mnt_opts return an error on context mismatch seccomp: allow BPF_XOR based ALU instructions. Fix NULL pointer dereference in smack_inode_unlink() and smack_inode_rmdir() Smack: add support for modification of existing rules smack: SMACK_MAGIC to include/uapi/linux/magic.h Smack: add missing support for transmute bit in smack_str_from_perm() Smack: prevent revoke-subject from failing when unseen label is written to it tomoyo: use DEFINE_SRCU() to define tomoyo_ss tomoyo: use DEFINE_SRCU() to define tomoyo_ss
Diffstat (limited to 'security')
-rw-r--r--security/capability.c3
-rw-r--r--security/integrity/ima/ima_main.c14
-rw-r--r--security/security.c4
-rw-r--r--security/selinux/hooks.c39
-rw-r--r--security/smack/smack.h5
-rw-r--r--security/smack/smack_access.c2
-rw-r--r--security/smack/smack_lsm.c4
-rw-r--r--security/smack/smackfs.c254
-rw-r--r--security/tomoyo/tomoyo.c5
9 files changed, 222 insertions, 108 deletions
diff --git a/security/capability.c b/security/capability.c
index 6783c3e6c88e..1728d4e375db 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -98,9 +98,10 @@ static int cap_sb_set_mnt_opts(struct super_block *sb,
98 return 0; 98 return 0;
99} 99}
100 100
101static void cap_sb_clone_mnt_opts(const struct super_block *oldsb, 101static int cap_sb_clone_mnt_opts(const struct super_block *oldsb,
102 struct super_block *newsb) 102 struct super_block *newsb)
103{ 103{
104 return 0;
104} 105}
105 106
106static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) 107static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 3b3b7e6bf8da..6c491a63128e 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -189,11 +189,9 @@ static int process_measurement(struct file *file, const char *filename,
189 if (rc != 0) 189 if (rc != 0)
190 goto out_digsig; 190 goto out_digsig;
191 191
192 if (function != BPRM_CHECK) 192 pathname = !filename ? ima_d_path(&file->f_path, &pathbuf) : filename;
193 pathname = ima_d_path(&file->f_path, &pathbuf);
194
195 if (!pathname) 193 if (!pathname)
196 pathname = filename; 194 pathname = (const char *)file->f_dentry->d_name.name;
197 195
198 if (action & IMA_MEASURE) 196 if (action & IMA_MEASURE)
199 ima_store_measurement(iint, file, pathname); 197 ima_store_measurement(iint, file, pathname);
@@ -226,8 +224,7 @@ out:
226int ima_file_mmap(struct file *file, unsigned long prot) 224int ima_file_mmap(struct file *file, unsigned long prot)
227{ 225{
228 if (file && (prot & PROT_EXEC)) 226 if (file && (prot & PROT_EXEC))
229 return process_measurement(file, file->f_dentry->d_name.name, 227 return process_measurement(file, NULL, MAY_EXEC, MMAP_CHECK);
230 MAY_EXEC, MMAP_CHECK);
231 return 0; 228 return 0;
232} 229}
233 230
@@ -265,7 +262,7 @@ int ima_bprm_check(struct linux_binprm *bprm)
265int ima_file_check(struct file *file, int mask) 262int ima_file_check(struct file *file, int mask)
266{ 263{
267 ima_rdwr_violation_check(file); 264 ima_rdwr_violation_check(file);
268 return process_measurement(file, file->f_dentry->d_name.name, 265 return process_measurement(file, NULL,
269 mask & (MAY_READ | MAY_WRITE | MAY_EXEC), 266 mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
270 FILE_CHECK); 267 FILE_CHECK);
271} 268}
@@ -290,8 +287,7 @@ int ima_module_check(struct file *file)
290#endif 287#endif
291 return 0; /* We rely on module signature checking */ 288 return 0; /* We rely on module signature checking */
292 } 289 }
293 return process_measurement(file, file->f_dentry->d_name.name, 290 return process_measurement(file, NULL, MAY_EXEC, MODULE_CHECK);
294 MAY_EXEC, MODULE_CHECK);
295} 291}
296 292
297static int __init init_ima(void) 293static int __init init_ima(void)
diff --git a/security/security.c b/security/security.c
index 03f248b84e9f..a3dce87d1aef 100644
--- a/security/security.c
+++ b/security/security.c
@@ -299,10 +299,10 @@ int security_sb_set_mnt_opts(struct super_block *sb,
299} 299}
300EXPORT_SYMBOL(security_sb_set_mnt_opts); 300EXPORT_SYMBOL(security_sb_set_mnt_opts);
301 301
302void security_sb_clone_mnt_opts(const struct super_block *oldsb, 302int security_sb_clone_mnt_opts(const struct super_block *oldsb,
303 struct super_block *newsb) 303 struct super_block *newsb)
304{ 304{
305 security_ops->sb_clone_mnt_opts(oldsb, newsb); 305 return security_ops->sb_clone_mnt_opts(oldsb, newsb);
306} 306}
307EXPORT_SYMBOL(security_sb_clone_mnt_opts); 307EXPORT_SYMBOL(security_sb_clone_mnt_opts);
308 308
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 7171a957b933..feb2f42c5a07 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -751,7 +751,37 @@ out_double_mount:
751 goto out; 751 goto out;
752} 752}
753 753
754static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, 754static int selinux_cmp_sb_context(const struct super_block *oldsb,
755 const struct super_block *newsb)
756{
757 struct superblock_security_struct *old = oldsb->s_security;
758 struct superblock_security_struct *new = newsb->s_security;
759 char oldflags = old->flags & SE_MNTMASK;
760 char newflags = new->flags & SE_MNTMASK;
761
762 if (oldflags != newflags)
763 goto mismatch;
764 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
765 goto mismatch;
766 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
767 goto mismatch;
768 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
769 goto mismatch;
770 if (oldflags & ROOTCONTEXT_MNT) {
771 struct inode_security_struct *oldroot = oldsb->s_root->d_inode->i_security;
772 struct inode_security_struct *newroot = newsb->s_root->d_inode->i_security;
773 if (oldroot->sid != newroot->sid)
774 goto mismatch;
775 }
776 return 0;
777mismatch:
778 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
779 "different security settings for (dev %s, "
780 "type %s)\n", newsb->s_id, newsb->s_type->name);
781 return -EBUSY;
782}
783
784static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
755 struct super_block *newsb) 785 struct super_block *newsb)
756{ 786{
757 const struct superblock_security_struct *oldsbsec = oldsb->s_security; 787 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
@@ -766,14 +796,14 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
766 * mount options. thus we can safely deal with this superblock later 796 * mount options. thus we can safely deal with this superblock later
767 */ 797 */
768 if (!ss_initialized) 798 if (!ss_initialized)
769 return; 799 return 0;
770 800
771 /* how can we clone if the old one wasn't set up?? */ 801 /* how can we clone if the old one wasn't set up?? */
772 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); 802 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
773 803
774 /* if fs is reusing a sb, just let its options stand... */ 804 /* if fs is reusing a sb, make sure that the contexts match */
775 if (newsbsec->flags & SE_SBINITIALIZED) 805 if (newsbsec->flags & SE_SBINITIALIZED)
776 return; 806 return selinux_cmp_sb_context(oldsb, newsb);
777 807
778 mutex_lock(&newsbsec->lock); 808 mutex_lock(&newsbsec->lock);
779 809
@@ -806,6 +836,7 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
806 836
807 sb_finish_set_opts(newsb); 837 sb_finish_set_opts(newsb);
808 mutex_unlock(&newsbsec->lock); 838 mutex_unlock(&newsbsec->lock);
839 return 0;
809} 840}
810 841
811static int selinux_parse_opts_str(char *options, 842static int selinux_parse_opts_str(char *options,
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 99b36124f712..8ad30955e15d 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -149,11 +149,6 @@ struct smack_known {
149#define SMACK_CIPSO_SOCKET 1 149#define SMACK_CIPSO_SOCKET 1
150 150
151/* 151/*
152 * smackfs magic number
153 */
154#define SMACK_MAGIC 0x43415d53 /* "SMAC" */
155
156/*
157 * CIPSO defaults. 152 * CIPSO defaults.
158 */ 153 */
159#define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */ 154#define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index db14689a21e0..2e397a88d410 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -252,6 +252,8 @@ static inline void smack_str_from_perm(char *string, int access)
252 string[i++] = 'x'; 252 string[i++] = 'x';
253 if (access & MAY_APPEND) 253 if (access & MAY_APPEND)
254 string[i++] = 'a'; 254 string[i++] = 'a';
255 if (access & MAY_TRANSMUTE)
256 string[i++] = 't';
255 string[i] = '\0'; 257 string[i] = '\0';
256} 258}
257/** 259/**
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index fa64740abb59..d52c780bdb78 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -654,7 +654,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
654 /* 654 /*
655 * You also need write access to the containing directory 655 * You also need write access to the containing directory
656 */ 656 */
657 smk_ad_setfield_u_fs_path_dentry(&ad, NULL); 657 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE);
658 smk_ad_setfield_u_fs_inode(&ad, dir); 658 smk_ad_setfield_u_fs_inode(&ad, dir);
659 rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); 659 rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad);
660 } 660 }
@@ -685,7 +685,7 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
685 /* 685 /*
686 * You also need write access to the containing directory 686 * You also need write access to the containing directory
687 */ 687 */
688 smk_ad_setfield_u_fs_path_dentry(&ad, NULL); 688 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE);
689 smk_ad_setfield_u_fs_inode(&ad, dir); 689 smk_ad_setfield_u_fs_inode(&ad, dir);
690 rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); 690 rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad);
691 } 691 }
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 76a5dca46404..53a08b85bda4 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -26,6 +26,7 @@
26#include <linux/seq_file.h> 26#include <linux/seq_file.h>
27#include <linux/ctype.h> 27#include <linux/ctype.h>
28#include <linux/audit.h> 28#include <linux/audit.h>
29#include <linux/magic.h>
29#include "smack.h" 30#include "smack.h"
30 31
31/* 32/*
@@ -50,12 +51,12 @@ enum smk_inos {
50 SMK_ACCESS2 = 16, /* make an access check with long labels */ 51 SMK_ACCESS2 = 16, /* make an access check with long labels */
51 SMK_CIPSO2 = 17, /* load long label -> CIPSO mapping */ 52 SMK_CIPSO2 = 17, /* load long label -> CIPSO mapping */
52 SMK_REVOKE_SUBJ = 18, /* set rules with subject label to '-' */ 53 SMK_REVOKE_SUBJ = 18, /* set rules with subject label to '-' */
54 SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */
53}; 55};
54 56
55/* 57/*
56 * List locks 58 * List locks
57 */ 59 */
58static DEFINE_MUTEX(smack_list_lock);
59static DEFINE_MUTEX(smack_cipso_lock); 60static DEFINE_MUTEX(smack_cipso_lock);
60static DEFINE_MUTEX(smack_ambient_lock); 61static DEFINE_MUTEX(smack_ambient_lock);
61static DEFINE_MUTEX(smk_netlbladdr_lock); 62static DEFINE_MUTEX(smk_netlbladdr_lock);
@@ -110,6 +111,13 @@ struct smack_master_list {
110 111
111LIST_HEAD(smack_rule_list); 112LIST_HEAD(smack_rule_list);
112 113
114struct smack_parsed_rule {
115 char *smk_subject;
116 char *smk_object;
117 int smk_access1;
118 int smk_access2;
119};
120
113static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; 121static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
114 122
115const char *smack_cipso_option = SMACK_CIPSO_OPTION; 123const char *smack_cipso_option = SMACK_CIPSO_OPTION;
@@ -167,25 +175,28 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap)
167#define SMK_NETLBLADDRMIN 9 175#define SMK_NETLBLADDRMIN 9
168 176
169/** 177/**
170 * smk_set_access - add a rule to the rule list 178 * smk_set_access - add a rule to the rule list or replace an old rule
171 * @srp: the new rule to add 179 * @srp: the rule to add or replace
172 * @rule_list: the list of rules 180 * @rule_list: the list of rules
173 * @rule_lock: the rule list lock 181 * @rule_lock: the rule list lock
182 * @global: if non-zero, indicates a global rule
174 * 183 *
175 * Looks through the current subject/object/access list for 184 * Looks through the current subject/object/access list for
176 * the subject/object pair and replaces the access that was 185 * the subject/object pair and replaces the access that was
177 * there. If the pair isn't found add it with the specified 186 * there. If the pair isn't found add it with the specified
178 * access. 187 * access.
179 * 188 *
180 * Returns 1 if a rule was found to exist already, 0 if it is new
181 * Returns 0 if nothing goes wrong or -ENOMEM if it fails 189 * Returns 0 if nothing goes wrong or -ENOMEM if it fails
182 * during the allocation of the new pair to add. 190 * during the allocation of the new pair to add.
183 */ 191 */
184static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list, 192static int smk_set_access(struct smack_parsed_rule *srp,
185 struct mutex *rule_lock) 193 struct list_head *rule_list,
194 struct mutex *rule_lock, int global)
186{ 195{
187 struct smack_rule *sp; 196 struct smack_rule *sp;
197 struct smack_master_list *smlp;
188 int found = 0; 198 int found = 0;
199 int rc = 0;
189 200
190 mutex_lock(rule_lock); 201 mutex_lock(rule_lock);
191 202
@@ -197,23 +208,89 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
197 if (sp->smk_object == srp->smk_object && 208 if (sp->smk_object == srp->smk_object &&
198 sp->smk_subject == srp->smk_subject) { 209 sp->smk_subject == srp->smk_subject) {
199 found = 1; 210 found = 1;
200 sp->smk_access = srp->smk_access; 211 sp->smk_access |= srp->smk_access1;
212 sp->smk_access &= ~srp->smk_access2;
201 break; 213 break;
202 } 214 }
203 } 215 }
204 if (found == 0)
205 list_add_rcu(&srp->list, rule_list);
206 216
217 if (found == 0) {
218 sp = kzalloc(sizeof(*sp), GFP_KERNEL);
219 if (sp == NULL) {
220 rc = -ENOMEM;
221 goto out;
222 }
223
224 sp->smk_subject = srp->smk_subject;
225 sp->smk_object = srp->smk_object;
226 sp->smk_access = srp->smk_access1 & ~srp->smk_access2;
227
228 list_add_rcu(&sp->list, rule_list);
229 /*
230 * If this is a global as opposed to self and a new rule
231 * it needs to get added for reporting.
232 */
233 if (global) {
234 smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
235 if (smlp != NULL) {
236 smlp->smk_rule = sp;
237 list_add_rcu(&smlp->list, &smack_rule_list);
238 } else
239 rc = -ENOMEM;
240 }
241 }
242
243out:
207 mutex_unlock(rule_lock); 244 mutex_unlock(rule_lock);
245 return rc;
246}
247
248/**
249 * smk_perm_from_str - parse smack accesses from a text string
250 * @string: a text string that contains a Smack accesses code
251 *
252 * Returns an integer with respective bits set for specified accesses.
253 */
254static int smk_perm_from_str(const char *string)
255{
256 int perm = 0;
257 const char *cp;
208 258
209 return found; 259 for (cp = string; ; cp++)
260 switch (*cp) {
261 case '-':
262 break;
263 case 'r':
264 case 'R':
265 perm |= MAY_READ;
266 break;
267 case 'w':
268 case 'W':
269 perm |= MAY_WRITE;
270 break;
271 case 'x':
272 case 'X':
273 perm |= MAY_EXEC;
274 break;
275 case 'a':
276 case 'A':
277 perm |= MAY_APPEND;
278 break;
279 case 't':
280 case 'T':
281 perm |= MAY_TRANSMUTE;
282 break;
283 default:
284 return perm;
285 }
210} 286}
211 287
212/** 288/**
213 * smk_fill_rule - Fill Smack rule from strings 289 * smk_fill_rule - Fill Smack rule from strings
214 * @subject: subject label string 290 * @subject: subject label string
215 * @object: object label string 291 * @object: object label string
216 * @access: access string 292 * @access1: access string
293 * @access2: string with permissions to be removed
217 * @rule: Smack rule 294 * @rule: Smack rule
218 * @import: if non-zero, import labels 295 * @import: if non-zero, import labels
219 * @len: label length limit 296 * @len: label length limit
@@ -221,8 +298,9 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
221 * Returns 0 on success, -1 on failure 298 * Returns 0 on success, -1 on failure
222 */ 299 */
223static int smk_fill_rule(const char *subject, const char *object, 300static int smk_fill_rule(const char *subject, const char *object,
224 const char *access, struct smack_rule *rule, 301 const char *access1, const char *access2,
225 int import, int len) 302 struct smack_parsed_rule *rule, int import,
303 int len)
226{ 304{
227 const char *cp; 305 const char *cp;
228 struct smack_known *skp; 306 struct smack_known *skp;
@@ -255,36 +333,11 @@ static int smk_fill_rule(const char *subject, const char *object,
255 rule->smk_object = skp->smk_known; 333 rule->smk_object = skp->smk_known;
256 } 334 }
257 335
258 rule->smk_access = 0; 336 rule->smk_access1 = smk_perm_from_str(access1);
259 337 if (access2)
260 for (cp = access; *cp != '\0'; cp++) { 338 rule->smk_access2 = smk_perm_from_str(access2);
261 switch (*cp) { 339 else
262 case '-': 340 rule->smk_access2 = ~rule->smk_access1;
263 break;
264 case 'r':
265 case 'R':
266 rule->smk_access |= MAY_READ;
267 break;
268 case 'w':
269 case 'W':
270 rule->smk_access |= MAY_WRITE;
271 break;
272 case 'x':
273 case 'X':
274 rule->smk_access |= MAY_EXEC;
275 break;
276 case 'a':
277 case 'A':
278 rule->smk_access |= MAY_APPEND;
279 break;
280 case 't':
281 case 'T':
282 rule->smk_access |= MAY_TRANSMUTE;
283 break;
284 default:
285 return 0;
286 }
287 }
288 341
289 return 0; 342 return 0;
290} 343}
@@ -297,30 +350,33 @@ static int smk_fill_rule(const char *subject, const char *object,
297 * 350 *
298 * Returns 0 on success, -1 on errors. 351 * Returns 0 on success, -1 on errors.
299 */ 352 */
300static int smk_parse_rule(const char *data, struct smack_rule *rule, int import) 353static int smk_parse_rule(const char *data, struct smack_parsed_rule *rule,
354 int import)
301{ 355{
302 int rc; 356 int rc;
303 357
304 rc = smk_fill_rule(data, data + SMK_LABELLEN, 358 rc = smk_fill_rule(data, data + SMK_LABELLEN,
305 data + SMK_LABELLEN + SMK_LABELLEN, rule, import, 359 data + SMK_LABELLEN + SMK_LABELLEN, NULL, rule,
306 SMK_LABELLEN); 360 import, SMK_LABELLEN);
307 return rc; 361 return rc;
308} 362}
309 363
310/** 364/**
311 * smk_parse_long_rule - parse Smack rule from rule string 365 * smk_parse_long_rule - parse Smack rule from rule string
312 * @data: string to be parsed, null terminated 366 * @data: string to be parsed, null terminated
313 * @rule: Smack rule 367 * @rule: Will be filled with Smack parsed rule
314 * @import: if non-zero, import labels 368 * @import: if non-zero, import labels
369 * @change: if non-zero, data is from /smack/change-rule
315 * 370 *
316 * Returns 0 on success, -1 on failure 371 * Returns 0 on success, -1 on failure
317 */ 372 */
318static int smk_parse_long_rule(const char *data, struct smack_rule *rule, 373static int smk_parse_long_rule(const char *data, struct smack_parsed_rule *rule,
319 int import) 374 int import, int change)
320{ 375{
321 char *subject; 376 char *subject;
322 char *object; 377 char *object;
323 char *access; 378 char *access1;
379 char *access2;
324 int datalen; 380 int datalen;
325 int rc = -1; 381 int rc = -1;
326 382
@@ -334,14 +390,27 @@ static int smk_parse_long_rule(const char *data, struct smack_rule *rule,
334 object = kzalloc(datalen, GFP_KERNEL); 390 object = kzalloc(datalen, GFP_KERNEL);
335 if (object == NULL) 391 if (object == NULL)
336 goto free_out_s; 392 goto free_out_s;
337 access = kzalloc(datalen, GFP_KERNEL); 393 access1 = kzalloc(datalen, GFP_KERNEL);
338 if (access == NULL) 394 if (access1 == NULL)
339 goto free_out_o; 395 goto free_out_o;
396 access2 = kzalloc(datalen, GFP_KERNEL);
397 if (access2 == NULL)
398 goto free_out_a;
399
400 if (change) {
401 if (sscanf(data, "%s %s %s %s",
402 subject, object, access1, access2) == 4)
403 rc = smk_fill_rule(subject, object, access1, access2,
404 rule, import, 0);
405 } else {
406 if (sscanf(data, "%s %s %s", subject, object, access1) == 3)
407 rc = smk_fill_rule(subject, object, access1, NULL,
408 rule, import, 0);
409 }
340 410
341 if (sscanf(data, "%s %s %s", subject, object, access) == 3) 411 kfree(access2);
342 rc = smk_fill_rule(subject, object, access, rule, import, 0); 412free_out_a:
343 413 kfree(access1);
344 kfree(access);
345free_out_o: 414free_out_o:
346 kfree(object); 415 kfree(object);
347free_out_s: 416free_out_s:
@@ -351,6 +420,7 @@ free_out_s:
351 420
352#define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */ 421#define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */
353#define SMK_LONG_FMT 1 /* Variable long label format */ 422#define SMK_LONG_FMT 1 /* Variable long label format */
423#define SMK_CHANGE_FMT 2 /* Rule modification format */
354/** 424/**
355 * smk_write_rules_list - write() for any /smack rule file 425 * smk_write_rules_list - write() for any /smack rule file
356 * @file: file pointer, not actually used 426 * @file: file pointer, not actually used
@@ -359,22 +429,24 @@ free_out_s:
359 * @ppos: where to start - must be 0 429 * @ppos: where to start - must be 0
360 * @rule_list: the list of rules to write to 430 * @rule_list: the list of rules to write to
361 * @rule_lock: lock for the rule list 431 * @rule_lock: lock for the rule list
362 * @format: /smack/load or /smack/load2 format. 432 * @format: /smack/load or /smack/load2 or /smack/change-rule format.
363 * 433 *
364 * Get one smack access rule from above. 434 * Get one smack access rule from above.
365 * The format for SMK_LONG_FMT is: 435 * The format for SMK_LONG_FMT is:
366 * "subject<whitespace>object<whitespace>access[<whitespace>...]" 436 * "subject<whitespace>object<whitespace>access[<whitespace>...]"
367 * The format for SMK_FIXED24_FMT is exactly: 437 * The format for SMK_FIXED24_FMT is exactly:
368 * "subject object rwxat" 438 * "subject object rwxat"
439 * The format for SMK_CHANGE_FMT is:
440 * "subject<whitespace>object<whitespace>
441 * acc_enable<whitespace>acc_disable[<whitespace>...]"
369 */ 442 */
370static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, 443static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
371 size_t count, loff_t *ppos, 444 size_t count, loff_t *ppos,
372 struct list_head *rule_list, 445 struct list_head *rule_list,
373 struct mutex *rule_lock, int format) 446 struct mutex *rule_lock, int format)
374{ 447{
375 struct smack_master_list *smlp;
376 struct smack_known *skp; 448 struct smack_known *skp;
377 struct smack_rule *rule; 449 struct smack_parsed_rule *rule;
378 char *data; 450 char *data;
379 int datalen; 451 int datalen;
380 int rc = -EINVAL; 452 int rc = -EINVAL;
@@ -417,7 +489,11 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
417 * Be sure the data string is terminated. 489 * Be sure the data string is terminated.
418 */ 490 */
419 data[count] = '\0'; 491 data[count] = '\0';
420 if (smk_parse_long_rule(data, rule, 1)) 492 if (smk_parse_long_rule(data, rule, 1, 0))
493 goto out_free_rule;
494 } else if (format == SMK_CHANGE_FMT) {
495 data[count] = '\0';
496 if (smk_parse_long_rule(data, rule, 1, 1))
421 goto out_free_rule; 497 goto out_free_rule;
422 } else { 498 } else {
423 /* 499 /*
@@ -437,22 +513,9 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
437 rule_lock = &skp->smk_rules_lock; 513 rule_lock = &skp->smk_rules_lock;
438 } 514 }
439 515
440 rc = count; 516 rc = smk_set_access(rule, rule_list, rule_lock, load);
441 /* 517 if (rc == 0) {
442 * If this is a global as opposed to self and a new rule 518 rc = count;
443 * it needs to get added for reporting.
444 * smk_set_access returns true if there was already a rule
445 * for the subject/object pair, and false if it was new.
446 */
447 if (!smk_set_access(rule, rule_list, rule_lock)) {
448 if (load) {
449 smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
450 if (smlp != NULL) {
451 smlp->smk_rule = rule;
452 list_add_rcu(&smlp->list, &smack_rule_list);
453 } else
454 rc = -ENOMEM;
455 }
456 goto out; 519 goto out;
457 } 520 }
458 521
@@ -1774,7 +1837,7 @@ static const struct file_operations smk_load_self_ops = {
1774static ssize_t smk_user_access(struct file *file, const char __user *buf, 1837static ssize_t smk_user_access(struct file *file, const char __user *buf,
1775 size_t count, loff_t *ppos, int format) 1838 size_t count, loff_t *ppos, int format)
1776{ 1839{
1777 struct smack_rule rule; 1840 struct smack_parsed_rule rule;
1778 char *data; 1841 char *data;
1779 char *cod; 1842 char *cod;
1780 int res; 1843 int res;
@@ -1796,14 +1859,14 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf,
1796 return -ENOMEM; 1859 return -ENOMEM;
1797 memcpy(cod, data, count); 1860 memcpy(cod, data, count);
1798 cod[count] = '\0'; 1861 cod[count] = '\0';
1799 res = smk_parse_long_rule(cod, &rule, 0); 1862 res = smk_parse_long_rule(cod, &rule, 0, 0);
1800 kfree(cod); 1863 kfree(cod);
1801 } 1864 }
1802 1865
1803 if (res) 1866 if (res)
1804 return -EINVAL; 1867 return -EINVAL;
1805 1868
1806 res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access, 1869 res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access1,
1807 NULL); 1870 NULL);
1808 data[0] = res == 0 ? '1' : '0'; 1871 data[0] = res == 0 ? '1' : '0';
1809 data[1] = '\0'; 1872 data[1] = '\0';
@@ -2035,10 +2098,8 @@ static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf,
2035 } 2098 }
2036 2099
2037 skp = smk_find_entry(cp); 2100 skp = smk_find_entry(cp);
2038 if (skp == NULL) { 2101 if (skp == NULL)
2039 rc = -EINVAL;
2040 goto free_out; 2102 goto free_out;
2041 }
2042 2103
2043 rule_list = &skp->smk_rules; 2104 rule_list = &skp->smk_rules;
2044 rule_lock = &skp->smk_rules_lock; 2105 rule_lock = &skp->smk_rules_lock;
@@ -2077,6 +2138,33 @@ static int smk_init_sysfs(void)
2077} 2138}
2078 2139
2079/** 2140/**
2141 * smk_write_change_rule - write() for /smack/change-rule
2142 * @file: file pointer
2143 * @buf: data from user space
2144 * @count: bytes sent
2145 * @ppos: where to start - must be 0
2146 */
2147static ssize_t smk_write_change_rule(struct file *file, const char __user *buf,
2148 size_t count, loff_t *ppos)
2149{
2150 /*
2151 * Must have privilege.
2152 */
2153 if (!capable(CAP_MAC_ADMIN))
2154 return -EPERM;
2155
2156 return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
2157 SMK_CHANGE_FMT);
2158}
2159
2160static const struct file_operations smk_change_rule_ops = {
2161 .write = smk_write_change_rule,
2162 .read = simple_transaction_read,
2163 .release = simple_transaction_release,
2164 .llseek = generic_file_llseek,
2165};
2166
2167/**
2080 * smk_fill_super - fill the /smackfs superblock 2168 * smk_fill_super - fill the /smackfs superblock
2081 * @sb: the empty superblock 2169 * @sb: the empty superblock
2082 * @data: unused 2170 * @data: unused
@@ -2125,6 +2213,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
2125 [SMK_REVOKE_SUBJ] = { 2213 [SMK_REVOKE_SUBJ] = {
2126 "revoke-subject", &smk_revoke_subj_ops, 2214 "revoke-subject", &smk_revoke_subj_ops,
2127 S_IRUGO|S_IWUSR}, 2215 S_IRUGO|S_IWUSR},
2216 [SMK_CHANGE_RULE] = {
2217 "change-rule", &smk_change_rule_ops, S_IRUGO|S_IWUSR},
2128 /* last one */ 2218 /* last one */
2129 {""} 2219 {""}
2130 }; 2220 };
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index a2ee362546ab..f0b756e27fed 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -536,7 +536,7 @@ static struct security_operations tomoyo_security_ops = {
536}; 536};
537 537
538/* Lock for GC. */ 538/* Lock for GC. */
539struct srcu_struct tomoyo_ss; 539DEFINE_SRCU(tomoyo_ss);
540 540
541/** 541/**
542 * tomoyo_init - Register TOMOYO Linux as a LSM module. 542 * tomoyo_init - Register TOMOYO Linux as a LSM module.
@@ -550,8 +550,7 @@ static int __init tomoyo_init(void)
550 if (!security_module_enable(&tomoyo_security_ops)) 550 if (!security_module_enable(&tomoyo_security_ops))
551 return 0; 551 return 0;
552 /* register ourselves with the security framework */ 552 /* register ourselves with the security framework */
553 if (register_security(&tomoyo_security_ops) || 553 if (register_security(&tomoyo_security_ops))
554 init_srcu_struct(&tomoyo_ss))
555 panic("Failure registering TOMOYO Linux"); 554 panic("Failure registering TOMOYO Linux");
556 printk(KERN_INFO "TOMOYO Linux initialized\n"); 555 printk(KERN_INFO "TOMOYO Linux initialized\n");
557 cred->security = &tomoyo_kernel_domain; 556 cred->security = &tomoyo_kernel_domain;