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

Merge branch 'stage-for-3.10' of git://git.gitorious.org/smack-next/kernel into ra-next

+186 -88
+11
Documentation/security/Smack.txt
··· 117 117 ambient 118 118 This contains the Smack label applied to unlabeled network 119 119 packets. 120 + change-rule 121 + This interface allows modification of existing access control rules. 122 + The format accepted on write is: 123 + "%s %s %s %s" 124 + where the first string is the subject label, the second the 125 + object label, the third the access to allow and the fourth the 126 + access to deny. The access strings may contain only the characters 127 + "rwxat-". If a rule for a given subject and object exists it will be 128 + modified by enabling the permissions in the third string and disabling 129 + those in the fourth string. If there is no such rule it will be 130 + created using the access specified in the third and the fourth strings. 120 131 cipso 121 132 This interface allows a specific CIPSO header to be assigned 122 133 to a Smack label. The format accepted on write is:
+1
include/uapi/linux/magic.h
··· 11 11 #define DEBUGFS_MAGIC 0x64626720 12 12 #define SECURITYFS_MAGIC 0x73636673 13 13 #define SELINUX_MAGIC 0xf97cff8c 14 + #define SMACK_MAGIC 0x43415d53 /* "SMAC" */ 14 15 #define RAMFS_MAGIC 0x858458f6 /* some random number */ 15 16 #define TMPFS_MAGIC 0x01021994 16 17 #define HUGETLBFS_MAGIC 0x958458f6 /* some random number */
-5
security/smack/smack.h
··· 149 149 #define SMACK_CIPSO_SOCKET 1 150 150 151 151 /* 152 - * smackfs magic number 153 - */ 154 - #define SMACK_MAGIC 0x43415d53 /* "SMAC" */ 155 - 156 - /* 157 152 * CIPSO defaults. 158 153 */ 159 154 #define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */
+2
security/smack/smack_access.c
··· 252 252 string[i++] = 'x'; 253 253 if (access & MAY_APPEND) 254 254 string[i++] = 'a'; 255 + if (access & MAY_TRANSMUTE) 256 + string[i++] = 't'; 255 257 string[i] = '\0'; 256 258 } 257 259 /**
+2 -2
security/smack/smack_lsm.c
··· 654 654 /* 655 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 658 smk_ad_setfield_u_fs_inode(&ad, dir); 659 659 rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); 660 660 } ··· 685 685 /* 686 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 689 smk_ad_setfield_u_fs_inode(&ad, dir); 690 690 rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); 691 691 }
+170 -81
security/smack/smackfs.c
··· 50 50 SMK_ACCESS2 = 16, /* make an access check with long labels */ 51 51 SMK_CIPSO2 = 17, /* load long label -> CIPSO mapping */ 52 52 SMK_REVOKE_SUBJ = 18, /* set rules with subject label to '-' */ 53 + SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */ 53 54 }; 54 55 55 56 /* 56 57 * List locks 57 58 */ 58 - static DEFINE_MUTEX(smack_list_lock); 59 59 static DEFINE_MUTEX(smack_cipso_lock); 60 60 static DEFINE_MUTEX(smack_ambient_lock); 61 61 static DEFINE_MUTEX(smk_netlbladdr_lock); ··· 109 109 }; 110 110 111 111 LIST_HEAD(smack_rule_list); 112 + 113 + struct smack_parsed_rule { 114 + char *smk_subject; 115 + char *smk_object; 116 + int smk_access1; 117 + int smk_access2; 118 + }; 112 119 113 120 static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; 114 121 ··· 174 167 #define SMK_NETLBLADDRMIN 9 175 168 176 169 /** 177 - * smk_set_access - add a rule to the rule list 178 - * @srp: the new rule to add 170 + * smk_set_access - add a rule to the rule list or replace an old rule 171 + * @srp: the rule to add or replace 179 172 * @rule_list: the list of rules 180 173 * @rule_lock: the rule list lock 174 + * @global: if non-zero, indicates a global rule 181 175 * 182 176 * Looks through the current subject/object/access list for 183 177 * the subject/object pair and replaces the access that was 184 178 * there. If the pair isn't found add it with the specified 185 179 * access. 186 180 * 187 - * Returns 1 if a rule was found to exist already, 0 if it is new 188 181 * Returns 0 if nothing goes wrong or -ENOMEM if it fails 189 182 * during the allocation of the new pair to add. 190 183 */ 191 - static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list, 192 - struct mutex *rule_lock) 184 + static int smk_set_access(struct smack_parsed_rule *srp, 185 + struct list_head *rule_list, 186 + struct mutex *rule_lock, int global) 193 187 { 194 188 struct smack_rule *sp; 189 + struct smack_master_list *smlp; 195 190 int found = 0; 191 + int rc = 0; 196 192 197 193 mutex_lock(rule_lock); 198 194 ··· 207 197 if (sp->smk_object == srp->smk_object && 208 198 sp->smk_subject == srp->smk_subject) { 209 199 found = 1; 210 - sp->smk_access = srp->smk_access; 200 + sp->smk_access |= srp->smk_access1; 201 + sp->smk_access &= ~srp->smk_access2; 211 202 break; 212 203 } 213 204 } 214 - if (found == 0) 215 - list_add_rcu(&srp->list, rule_list); 216 205 206 + if (found == 0) { 207 + sp = kzalloc(sizeof(*sp), GFP_KERNEL); 208 + if (sp == NULL) { 209 + rc = -ENOMEM; 210 + goto out; 211 + } 212 + 213 + sp->smk_subject = srp->smk_subject; 214 + sp->smk_object = srp->smk_object; 215 + sp->smk_access = srp->smk_access1 & ~srp->smk_access2; 216 + 217 + list_add_rcu(&sp->list, rule_list); 218 + /* 219 + * If this is a global as opposed to self and a new rule 220 + * it needs to get added for reporting. 221 + */ 222 + if (global) { 223 + smlp = kzalloc(sizeof(*smlp), GFP_KERNEL); 224 + if (smlp != NULL) { 225 + smlp->smk_rule = sp; 226 + list_add_rcu(&smlp->list, &smack_rule_list); 227 + } else 228 + rc = -ENOMEM; 229 + } 230 + } 231 + 232 + out: 217 233 mutex_unlock(rule_lock); 234 + return rc; 235 + } 218 236 219 - return found; 237 + /** 238 + * smk_perm_from_str - parse smack accesses from a text string 239 + * @string: a text string that contains a Smack accesses code 240 + * 241 + * Returns an integer with respective bits set for specified accesses. 242 + */ 243 + static int smk_perm_from_str(const char *string) 244 + { 245 + int perm = 0; 246 + const char *cp; 247 + 248 + for (cp = string; ; cp++) 249 + switch (*cp) { 250 + case '-': 251 + break; 252 + case 'r': 253 + case 'R': 254 + perm |= MAY_READ; 255 + break; 256 + case 'w': 257 + case 'W': 258 + perm |= MAY_WRITE; 259 + break; 260 + case 'x': 261 + case 'X': 262 + perm |= MAY_EXEC; 263 + break; 264 + case 'a': 265 + case 'A': 266 + perm |= MAY_APPEND; 267 + break; 268 + case 't': 269 + case 'T': 270 + perm |= MAY_TRANSMUTE; 271 + break; 272 + default: 273 + return perm; 274 + } 220 275 } 221 276 222 277 /** 223 278 * smk_fill_rule - Fill Smack rule from strings 224 279 * @subject: subject label string 225 280 * @object: object label string 226 - * @access: access string 281 + * @access1: access string 282 + * @access2: string with permissions to be removed 227 283 * @rule: Smack rule 228 284 * @import: if non-zero, import labels 229 285 * @len: label length limit ··· 297 221 * Returns 0 on success, -1 on failure 298 222 */ 299 223 static int smk_fill_rule(const char *subject, const char *object, 300 - const char *access, struct smack_rule *rule, 301 - int import, int len) 224 + const char *access1, const char *access2, 225 + struct smack_parsed_rule *rule, int import, 226 + int len) 302 227 { 303 228 const char *cp; 304 229 struct smack_known *skp; ··· 332 255 rule->smk_object = skp->smk_known; 333 256 } 334 257 335 - rule->smk_access = 0; 336 - 337 - for (cp = access; *cp != '\0'; cp++) { 338 - switch (*cp) { 339 - case '-': 340 - break; 341 - case 'r': 342 - case 'R': 343 - rule->smk_access |= MAY_READ; 344 - break; 345 - case 'w': 346 - case 'W': 347 - rule->smk_access |= MAY_WRITE; 348 - break; 349 - case 'x': 350 - case 'X': 351 - rule->smk_access |= MAY_EXEC; 352 - break; 353 - case 'a': 354 - case 'A': 355 - rule->smk_access |= MAY_APPEND; 356 - break; 357 - case 't': 358 - case 'T': 359 - rule->smk_access |= MAY_TRANSMUTE; 360 - break; 361 - default: 362 - return 0; 363 - } 364 - } 258 + rule->smk_access1 = smk_perm_from_str(access1); 259 + if (access2) 260 + rule->smk_access2 = smk_perm_from_str(access2); 261 + else 262 + rule->smk_access2 = ~rule->smk_access1; 365 263 366 264 return 0; 367 265 } ··· 349 297 * 350 298 * Returns 0 on success, -1 on errors. 351 299 */ 352 - static int smk_parse_rule(const char *data, struct smack_rule *rule, int import) 300 + static int smk_parse_rule(const char *data, struct smack_parsed_rule *rule, 301 + int import) 353 302 { 354 303 int rc; 355 304 356 305 rc = smk_fill_rule(data, data + SMK_LABELLEN, 357 - data + SMK_LABELLEN + SMK_LABELLEN, rule, import, 358 - SMK_LABELLEN); 306 + data + SMK_LABELLEN + SMK_LABELLEN, NULL, rule, 307 + import, SMK_LABELLEN); 359 308 return rc; 360 309 } 361 310 362 311 /** 363 312 * smk_parse_long_rule - parse Smack rule from rule string 364 313 * @data: string to be parsed, null terminated 365 - * @rule: Smack rule 314 + * @rule: Will be filled with Smack parsed rule 366 315 * @import: if non-zero, import labels 316 + * @change: if non-zero, data is from /smack/change-rule 367 317 * 368 318 * Returns 0 on success, -1 on failure 369 319 */ 370 - static int smk_parse_long_rule(const char *data, struct smack_rule *rule, 371 - int import) 320 + static int smk_parse_long_rule(const char *data, struct smack_parsed_rule *rule, 321 + int import, int change) 372 322 { 373 323 char *subject; 374 324 char *object; 375 - char *access; 325 + char *access1; 326 + char *access2; 376 327 int datalen; 377 328 int rc = -1; 378 329 ··· 389 334 object = kzalloc(datalen, GFP_KERNEL); 390 335 if (object == NULL) 391 336 goto free_out_s; 392 - access = kzalloc(datalen, GFP_KERNEL); 393 - if (access == NULL) 337 + access1 = kzalloc(datalen, GFP_KERNEL); 338 + if (access1 == NULL) 394 339 goto free_out_o; 340 + access2 = kzalloc(datalen, GFP_KERNEL); 341 + if (access2 == NULL) 342 + goto free_out_a; 395 343 396 - if (sscanf(data, "%s %s %s", subject, object, access) == 3) 397 - rc = smk_fill_rule(subject, object, access, rule, import, 0); 344 + if (change) { 345 + if (sscanf(data, "%s %s %s %s", 346 + subject, object, access1, access2) == 4) 347 + rc = smk_fill_rule(subject, object, access1, access2, 348 + rule, import, 0); 349 + } else { 350 + if (sscanf(data, "%s %s %s", subject, object, access1) == 3) 351 + rc = smk_fill_rule(subject, object, access1, NULL, 352 + rule, import, 0); 353 + } 398 354 399 - kfree(access); 355 + kfree(access2); 356 + free_out_a: 357 + kfree(access1); 400 358 free_out_o: 401 359 kfree(object); 402 360 free_out_s: ··· 419 351 420 352 #define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */ 421 353 #define SMK_LONG_FMT 1 /* Variable long label format */ 354 + #define SMK_CHANGE_FMT 2 /* Rule modification format */ 422 355 /** 423 356 * smk_write_rules_list - write() for any /smack rule file 424 357 * @file: file pointer, not actually used ··· 428 359 * @ppos: where to start - must be 0 429 360 * @rule_list: the list of rules to write to 430 361 * @rule_lock: lock for the rule list 431 - * @format: /smack/load or /smack/load2 format. 362 + * @format: /smack/load or /smack/load2 or /smack/change-rule format. 432 363 * 433 364 * Get one smack access rule from above. 434 365 * The format for SMK_LONG_FMT is: 435 366 * "subject<whitespace>object<whitespace>access[<whitespace>...]" 436 367 * The format for SMK_FIXED24_FMT is exactly: 437 368 * "subject object rwxat" 369 + * The format for SMK_CHANGE_FMT is: 370 + * "subject<whitespace>object<whitespace> 371 + * acc_enable<whitespace>acc_disable[<whitespace>...]" 438 372 */ 439 373 static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, 440 374 size_t count, loff_t *ppos, 441 375 struct list_head *rule_list, 442 376 struct mutex *rule_lock, int format) 443 377 { 444 - struct smack_master_list *smlp; 445 378 struct smack_known *skp; 446 - struct smack_rule *rule; 379 + struct smack_parsed_rule *rule; 447 380 char *data; 448 381 int datalen; 449 382 int rc = -EINVAL; ··· 488 417 * Be sure the data string is terminated. 489 418 */ 490 419 data[count] = '\0'; 491 - if (smk_parse_long_rule(data, rule, 1)) 420 + if (smk_parse_long_rule(data, rule, 1, 0)) 421 + goto out_free_rule; 422 + } else if (format == SMK_CHANGE_FMT) { 423 + data[count] = '\0'; 424 + if (smk_parse_long_rule(data, rule, 1, 1)) 492 425 goto out_free_rule; 493 426 } else { 494 427 /* ··· 512 437 rule_lock = &skp->smk_rules_lock; 513 438 } 514 439 515 - rc = count; 516 - /* 517 - * If this is a global as opposed to self and a new rule 518 - * it needs to get added for reporting. 519 - * smk_set_access returns true if there was already a rule 520 - * for the subject/object pair, and false if it was new. 521 - */ 522 - if (!smk_set_access(rule, rule_list, rule_lock)) { 523 - if (load) { 524 - smlp = kzalloc(sizeof(*smlp), GFP_KERNEL); 525 - if (smlp != NULL) { 526 - smlp->smk_rule = rule; 527 - list_add_rcu(&smlp->list, &smack_rule_list); 528 - } else 529 - rc = -ENOMEM; 530 - } 440 + rc = smk_set_access(rule, rule_list, rule_lock, load); 441 + if (rc == 0) { 442 + rc = count; 531 443 goto out; 532 444 } 533 445 ··· 1836 1774 static ssize_t smk_user_access(struct file *file, const char __user *buf, 1837 1775 size_t count, loff_t *ppos, int format) 1838 1776 { 1839 - struct smack_rule rule; 1777 + struct smack_parsed_rule rule; 1840 1778 char *data; 1841 1779 char *cod; 1842 1780 int res; ··· 1858 1796 return -ENOMEM; 1859 1797 memcpy(cod, data, count); 1860 1798 cod[count] = '\0'; 1861 - res = smk_parse_long_rule(cod, &rule, 0); 1799 + res = smk_parse_long_rule(cod, &rule, 0, 0); 1862 1800 kfree(cod); 1863 1801 } 1864 1802 1865 1803 if (res) 1866 1804 return -EINVAL; 1867 1805 1868 - res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access, 1806 + res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access1, 1869 1807 NULL); 1870 1808 data[0] = res == 0 ? '1' : '0'; 1871 1809 data[1] = '\0'; ··· 2097 2035 } 2098 2036 2099 2037 skp = smk_find_entry(cp); 2100 - if (skp == NULL) { 2101 - rc = -EINVAL; 2038 + if (skp == NULL) 2102 2039 goto free_out; 2103 - } 2104 2040 2105 2041 rule_list = &skp->smk_rules; 2106 2042 rule_lock = &skp->smk_rules_lock; ··· 2135 2075 return -ENOMEM; 2136 2076 return 0; 2137 2077 } 2078 + 2079 + /** 2080 + * smk_write_change_rule - write() for /smack/change-rule 2081 + * @file: file pointer 2082 + * @buf: data from user space 2083 + * @count: bytes sent 2084 + * @ppos: where to start - must be 0 2085 + */ 2086 + static ssize_t smk_write_change_rule(struct file *file, const char __user *buf, 2087 + size_t count, loff_t *ppos) 2088 + { 2089 + /* 2090 + * Must have privilege. 2091 + */ 2092 + if (!capable(CAP_MAC_ADMIN)) 2093 + return -EPERM; 2094 + 2095 + return smk_write_rules_list(file, buf, count, ppos, NULL, NULL, 2096 + SMK_CHANGE_FMT); 2097 + } 2098 + 2099 + static const struct file_operations smk_change_rule_ops = { 2100 + .write = smk_write_change_rule, 2101 + .read = simple_transaction_read, 2102 + .release = simple_transaction_release, 2103 + .llseek = generic_file_llseek, 2104 + }; 2138 2105 2139 2106 /** 2140 2107 * smk_fill_super - fill the /smackfs superblock ··· 2212 2125 [SMK_REVOKE_SUBJ] = { 2213 2126 "revoke-subject", &smk_revoke_subj_ops, 2214 2127 S_IRUGO|S_IWUSR}, 2128 + [SMK_CHANGE_RULE] = { 2129 + "change-rule", &smk_change_rule_ops, S_IRUGO|S_IWUSR}, 2215 2130 /* last one */ 2216 2131 {""} 2217 2132 };