aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Morris <james.l.morris@oracle.com>2015-06-03 05:10:29 -0400
committerJames Morris <james.l.morris@oracle.com>2015-06-03 05:10:29 -0400
commite6e29a4eae335059d2cc44ac543de7556ff7ac09 (patch)
treee09595fa1c5e5ac6c9eb1f92c86df1d0cfc62a9d
parent8d94eb9b5cff350ba170848c862ca0006d33d496 (diff)
parentc0d77c884461fc0dec0411e49797dc3f3651c31b (diff)
Merge branch 'smack-for-4.2-stacked' of https://github.com/cschaufler/smack-next into next
-rw-r--r--Documentation/security/Smack.txt6
-rw-r--r--security/smack/smack.h25
-rw-r--r--security/smack/smack_access.c68
-rw-r--r--security/smack/smack_lsm.c96
-rw-r--r--security/smack/smackfs.c311
5 files changed, 317 insertions, 189 deletions
diff --git a/Documentation/security/Smack.txt b/Documentation/security/Smack.txt
index abc82f85215b..de5e1aeca7fb 100644
--- a/Documentation/security/Smack.txt
+++ b/Documentation/security/Smack.txt
@@ -206,11 +206,11 @@ netlabel
206 label. The format accepted on write is: 206 label. The format accepted on write is:
207 "%d.%d.%d.%d label" or "%d.%d.%d.%d/%d label". 207 "%d.%d.%d.%d label" or "%d.%d.%d.%d/%d label".
208onlycap 208onlycap
209 This contains the label processes must have for CAP_MAC_ADMIN 209 This contains labels processes must have for CAP_MAC_ADMIN
210 and CAP_MAC_OVERRIDE to be effective. If this file is empty 210 and CAP_MAC_OVERRIDE to be effective. If this file is empty
211 these capabilities are effective at for processes with any 211 these capabilities are effective at for processes with any
212 label. The value is set by writing the desired label to the 212 label. The values are set by writing the desired labels, separated
213 file or cleared by writing "-" to the file. 213 by spaces, to the file or cleared by writing "-" to the file.
214ptrace 214ptrace
215 This is used to define the current ptrace policy 215 This is used to define the current ptrace policy
216 0 - default: this is the policy that relies on Smack access rules. 216 0 - default: this is the policy that relies on Smack access rules.
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 0f410fc56e33..00f6b38bffbd 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -425,7 +425,7 @@ void smk_insert_entry(struct smack_known *skp)
425 * @string: a text string that might be a Smack label 425 * @string: a text string that might be a Smack label
426 * 426 *
427 * Returns a pointer to the entry in the label list that 427 * Returns a pointer to the entry in the label list that
428 * matches the passed string. 428 * matches the passed string or NULL if not found.
429 */ 429 */
430struct smack_known *smk_find_entry(const char *string) 430struct smack_known *smk_find_entry(const char *string)
431{ 431{
@@ -448,7 +448,7 @@ struct smack_known *smk_find_entry(const char *string)
448 * @string: a text string that might contain a Smack label 448 * @string: a text string that might contain a Smack label
449 * @len: the maximum size, or zero if it is NULL terminated. 449 * @len: the maximum size, or zero if it is NULL terminated.
450 * 450 *
451 * Returns a pointer to the clean label, or NULL 451 * Returns a pointer to the clean label or an error code.
452 */ 452 */
453char *smk_parse_smack(const char *string, int len) 453char *smk_parse_smack(const char *string, int len)
454{ 454{
@@ -464,7 +464,7 @@ char *smk_parse_smack(const char *string, int len)
464 * including /smack/cipso and /smack/cipso2 464 * including /smack/cipso and /smack/cipso2
465 */ 465 */
466 if (string[0] == '-') 466 if (string[0] == '-')
467 return NULL; 467 return ERR_PTR(-EINVAL);
468 468
469 for (i = 0; i < len; i++) 469 for (i = 0; i < len; i++)
470 if (string[i] > '~' || string[i] <= ' ' || string[i] == '/' || 470 if (string[i] > '~' || string[i] <= ' ' || string[i] == '/' ||
@@ -472,11 +472,13 @@ char *smk_parse_smack(const char *string, int len)
472 break; 472 break;
473 473
474 if (i == 0 || i >= SMK_LONGLABEL) 474 if (i == 0 || i >= SMK_LONGLABEL)
475 return NULL; 475 return ERR_PTR(-EINVAL);
476 476
477 smack = kzalloc(i + 1, GFP_KERNEL); 477 smack = kzalloc(i + 1, GFP_KERNEL);
478 if (smack != NULL) 478 if (smack == NULL)
479 strncpy(smack, string, i); 479 return ERR_PTR(-ENOMEM);
480
481 strncpy(smack, string, i);
480 482
481 return smack; 483 return smack;
482} 484}
@@ -523,7 +525,8 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
523 * @len: the maximum size, or zero if it is NULL terminated. 525 * @len: the maximum size, or zero if it is NULL terminated.
524 * 526 *
525 * Returns a pointer to the entry in the label list that 527 * Returns a pointer to the entry in the label list that
526 * matches the passed string, adding it if necessary. 528 * matches the passed string, adding it if necessary,
529 * or an error code.
527 */ 530 */
528struct smack_known *smk_import_entry(const char *string, int len) 531struct smack_known *smk_import_entry(const char *string, int len)
529{ 532{
@@ -533,8 +536,8 @@ struct smack_known *smk_import_entry(const char *string, int len)
533 int rc; 536 int rc;
534 537
535 smack = smk_parse_smack(string, len); 538 smack = smk_parse_smack(string, len);
536 if (smack == NULL) 539 if (IS_ERR(smack))
537 return NULL; 540 return ERR_CAST(smack);
538 541
539 mutex_lock(&smack_known_lock); 542 mutex_lock(&smack_known_lock);
540 543
@@ -543,8 +546,10 @@ struct smack_known *smk_import_entry(const char *string, int len)
543 goto freeout; 546 goto freeout;
544 547
545 skp = kzalloc(sizeof(*skp), GFP_KERNEL); 548 skp = kzalloc(sizeof(*skp), GFP_KERNEL);
546 if (skp == NULL) 549 if (skp == NULL) {
550 skp = ERR_PTR(-ENOMEM);
547 goto freeout; 551 goto freeout;
552 }
548 553
549 skp->smk_known = smack; 554 skp->smk_known = smack;
550 skp->smk_secid = smack_next_secid++; 555 skp->smk_secid = smack_next_secid++;
@@ -577,7 +582,7 @@ struct smack_known *smk_import_entry(const char *string, int len)
577 * smk_netlbl_mls failed. 582 * smk_netlbl_mls failed.
578 */ 583 */
579 kfree(skp); 584 kfree(skp);
580 skp = NULL; 585 skp = ERR_PTR(rc);
581freeout: 586freeout:
582 kfree(smack); 587 kfree(smack);
583unlockout: 588unlockout:
@@ -612,3 +617,44 @@ struct smack_known *smack_from_secid(const u32 secid)
612 rcu_read_unlock(); 617 rcu_read_unlock();
613 return &smack_known_invalid; 618 return &smack_known_invalid;
614} 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/smack_lsm.c b/security/smack/smack_lsm.c
index 5eae42c8d0d5..a143328f75eb 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -245,8 +245,8 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file,
245 * @ip: a pointer to the inode 245 * @ip: a pointer to the inode
246 * @dp: a pointer to the dentry 246 * @dp: a pointer to the dentry
247 * 247 *
248 * Returns a pointer to the master list entry for the Smack label 248 * Returns a pointer to the master list entry for the Smack label,
249 * or NULL if there was no label to fetch. 249 * NULL if there was no label to fetch, or an error code.
250 */ 250 */
251static struct smack_known *smk_fetch(const char *name, struct inode *ip, 251static struct smack_known *smk_fetch(const char *name, struct inode *ip,
252 struct dentry *dp) 252 struct dentry *dp)
@@ -256,14 +256,18 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
256 struct smack_known *skp = NULL; 256 struct smack_known *skp = NULL;
257 257
258 if (ip->i_op->getxattr == NULL) 258 if (ip->i_op->getxattr == NULL)
259 return NULL; 259 return ERR_PTR(-EOPNOTSUPP);
260 260
261 buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL); 261 buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
262 if (buffer == NULL) 262 if (buffer == NULL)
263 return NULL; 263 return ERR_PTR(-ENOMEM);
264 264
265 rc = ip->i_op->getxattr(dp, name, buffer, SMK_LONGLABEL); 265 rc = ip->i_op->getxattr(dp, name, buffer, SMK_LONGLABEL);
266 if (rc > 0) 266 if (rc < 0)
267 skp = ERR_PTR(rc);
268 else if (rc == 0)
269 skp = NULL;
270 else
267 skp = smk_import_entry(buffer, rc); 271 skp = smk_import_entry(buffer, rc);
268 272
269 kfree(buffer); 273 kfree(buffer);
@@ -605,40 +609,44 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
605 if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) { 609 if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) {
606 op += strlen(SMK_FSHAT); 610 op += strlen(SMK_FSHAT);
607 skp = smk_import_entry(op, 0); 611 skp = smk_import_entry(op, 0);
608 if (skp != NULL) { 612 if (IS_ERR(skp))
609 sp->smk_hat = skp; 613 return PTR_ERR(skp);
610 specified = 1; 614 sp->smk_hat = skp;
611 } 615 specified = 1;
616
612 } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) { 617 } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) {
613 op += strlen(SMK_FSFLOOR); 618 op += strlen(SMK_FSFLOOR);
614 skp = smk_import_entry(op, 0); 619 skp = smk_import_entry(op, 0);
615 if (skp != NULL) { 620 if (IS_ERR(skp))
616 sp->smk_floor = skp; 621 return PTR_ERR(skp);
617 specified = 1; 622 sp->smk_floor = skp;
618 } 623 specified = 1;
624
619 } else if (strncmp(op, SMK_FSDEFAULT, 625 } else if (strncmp(op, SMK_FSDEFAULT,
620 strlen(SMK_FSDEFAULT)) == 0) { 626 strlen(SMK_FSDEFAULT)) == 0) {
621 op += strlen(SMK_FSDEFAULT); 627 op += strlen(SMK_FSDEFAULT);
622 skp = smk_import_entry(op, 0); 628 skp = smk_import_entry(op, 0);
623 if (skp != NULL) { 629 if (IS_ERR(skp))
624 sp->smk_default = skp; 630 return PTR_ERR(skp);
625 specified = 1; 631 sp->smk_default = skp;
626 } 632 specified = 1;
633
627 } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) { 634 } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) {
628 op += strlen(SMK_FSROOT); 635 op += strlen(SMK_FSROOT);
629 skp = smk_import_entry(op, 0); 636 skp = smk_import_entry(op, 0);
630 if (skp != NULL) { 637 if (IS_ERR(skp))
631 sp->smk_root = skp; 638 return PTR_ERR(skp);
632 specified = 1; 639 sp->smk_root = skp;
633 } 640 specified = 1;
641
634 } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) { 642 } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) {
635 op += strlen(SMK_FSTRANS); 643 op += strlen(SMK_FSTRANS);
636 skp = smk_import_entry(op, 0); 644 skp = smk_import_entry(op, 0);
637 if (skp != NULL) { 645 if (IS_ERR(skp))
638 sp->smk_root = skp; 646 return PTR_ERR(skp);
639 transmute = 1; 647 sp->smk_root = skp;
640 specified = 1; 648 transmute = 1;
641 } 649 specified = 1;
642 } 650 }
643 } 651 }
644 652
@@ -1118,7 +1126,9 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
1118 1126
1119 if (rc == 0 && check_import) { 1127 if (rc == 0 && check_import) {
1120 skp = size ? smk_import_entry(value, size) : NULL; 1128 skp = size ? smk_import_entry(value, size) : NULL;
1121 if (skp == NULL || (check_star && 1129 if (IS_ERR(skp))
1130 rc = PTR_ERR(skp);
1131 else if (skp == NULL || (check_star &&
1122 (skp == &smack_known_star || skp == &smack_known_web))) 1132 (skp == &smack_known_star || skp == &smack_known_web)))
1123 rc = -EINVAL; 1133 rc = -EINVAL;
1124 } 1134 }
@@ -1158,19 +1168,19 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
1158 1168
1159 if (strcmp(name, XATTR_NAME_SMACK) == 0) { 1169 if (strcmp(name, XATTR_NAME_SMACK) == 0) {
1160 skp = smk_import_entry(value, size); 1170 skp = smk_import_entry(value, size);
1161 if (skp != NULL) 1171 if (!IS_ERR(skp))
1162 isp->smk_inode = skp; 1172 isp->smk_inode = skp;
1163 else 1173 else
1164 isp->smk_inode = &smack_known_invalid; 1174 isp->smk_inode = &smack_known_invalid;
1165 } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { 1175 } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) {
1166 skp = smk_import_entry(value, size); 1176 skp = smk_import_entry(value, size);
1167 if (skp != NULL) 1177 if (!IS_ERR(skp))
1168 isp->smk_task = skp; 1178 isp->smk_task = skp;
1169 else 1179 else
1170 isp->smk_task = &smack_known_invalid; 1180 isp->smk_task = &smack_known_invalid;
1171 } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { 1181 } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
1172 skp = smk_import_entry(value, size); 1182 skp = smk_import_entry(value, size);
1173 if (skp != NULL) 1183 if (!IS_ERR(skp))
1174 isp->smk_mmap = skp; 1184 isp->smk_mmap = skp;
1175 else 1185 else
1176 isp->smk_mmap = &smack_known_invalid; 1186 isp->smk_mmap = &smack_known_invalid;
@@ -1658,6 +1668,9 @@ static int smack_file_receive(struct file *file)
1658 struct smk_audit_info ad; 1668 struct smk_audit_info ad;
1659 struct inode *inode = file_inode(file); 1669 struct inode *inode = file_inode(file);
1660 1670
1671 if (unlikely(IS_PRIVATE(inode)))
1672 return 0;
1673
1661 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); 1674 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
1662 smk_ad_setfield_u_fs_path(&ad, file->f_path); 1675 smk_ad_setfield_u_fs_path(&ad, file->f_path);
1663 /* 1676 /*
@@ -2400,8 +2413,8 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
2400 return -EINVAL; 2413 return -EINVAL;
2401 2414
2402 skp = smk_import_entry(value, size); 2415 skp = smk_import_entry(value, size);
2403 if (skp == NULL) 2416 if (IS_ERR(skp))
2404 return -EINVAL; 2417 return PTR_ERR(skp);
2405 2418
2406 if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { 2419 if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) {
2407 nsp->smk_inode = skp; 2420 nsp->smk_inode = skp;
@@ -3174,7 +3187,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
3174 */ 3187 */
3175 dp = dget(opt_dentry); 3188 dp = dget(opt_dentry);
3176 skp = smk_fetch(XATTR_NAME_SMACK, inode, dp); 3189 skp = smk_fetch(XATTR_NAME_SMACK, inode, dp);
3177 if (skp != NULL) 3190 if (!IS_ERR_OR_NULL(skp))
3178 final = skp; 3191 final = skp;
3179 3192
3180 /* 3193 /*
@@ -3211,11 +3224,14 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
3211 * Don't let the exec or mmap label be "*" or "@". 3224 * Don't let the exec or mmap label be "*" or "@".
3212 */ 3225 */
3213 skp = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); 3226 skp = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp);
3214 if (skp == &smack_known_star || skp == &smack_known_web) 3227 if (IS_ERR(skp) || skp == &smack_known_star ||
3228 skp == &smack_known_web)
3215 skp = NULL; 3229 skp = NULL;
3216 isp->smk_task = skp; 3230 isp->smk_task = skp;
3231
3217 skp = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp); 3232 skp = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp);
3218 if (skp == &smack_known_star || skp == &smack_known_web) 3233 if (IS_ERR(skp) || skp == &smack_known_star ||
3234 skp == &smack_known_web)
3219 skp = NULL; 3235 skp = NULL;
3220 isp->smk_mmap = skp; 3236 isp->smk_mmap = skp;
3221 3237
@@ -3299,8 +3315,8 @@ static int smack_setprocattr(struct task_struct *p, char *name,
3299 return -EINVAL; 3315 return -EINVAL;
3300 3316
3301 skp = smk_import_entry(value, size); 3317 skp = smk_import_entry(value, size);
3302 if (skp == NULL) 3318 if (IS_ERR(skp))
3303 return -EINVAL; 3319 return PTR_ERR(skp);
3304 3320
3305 /* 3321 /*
3306 * No process is ever allowed the web ("@") label. 3322 * No process is ever allowed the web ("@") label.
@@ -4075,8 +4091,10 @@ static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
4075 return -EINVAL; 4091 return -EINVAL;
4076 4092
4077 skp = smk_import_entry(rulestr, 0); 4093 skp = smk_import_entry(rulestr, 0);
4078 if (skp) 4094 if (IS_ERR(skp))
4079 *rule = skp->smk_known; 4095 return PTR_ERR(skp);
4096
4097 *rule = skp->smk_known;
4080 4098
4081 return 0; 4099 return 0;
4082} 4100}
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 4aa12c8d3c63..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
@@ -338,8 +328,7 @@ static int smk_perm_from_str(const char *string)
338 * @import: if non-zero, import labels 328 * @import: if non-zero, import labels
339 * @len: label length limit 329 * @len: label length limit
340 * 330 *
341 * Returns 0 on success, -EINVAL on failure and -ENOENT when either subject 331 * Returns 0 on success, appropriate error code on failure.
342 * or object is missing.
343 */ 332 */
344static int smk_fill_rule(const char *subject, const char *object, 333static int smk_fill_rule(const char *subject, const char *object,
345 const char *access1, const char *access2, 334 const char *access1, const char *access2,
@@ -351,16 +340,16 @@ static int smk_fill_rule(const char *subject, const char *object,
351 340
352 if (import) { 341 if (import) {
353 rule->smk_subject = smk_import_entry(subject, len); 342 rule->smk_subject = smk_import_entry(subject, len);
354 if (rule->smk_subject == NULL) 343 if (IS_ERR(rule->smk_subject))
355 return -EINVAL; 344 return PTR_ERR(rule->smk_subject);
356 345
357 rule->smk_object = smk_import_entry(object, len); 346 rule->smk_object = smk_import_entry(object, len);
358 if (rule->smk_object == NULL) 347 if (IS_ERR(rule->smk_object))
359 return -EINVAL; 348 return PTR_ERR(rule->smk_object);
360 } else { 349 } else {
361 cp = smk_parse_smack(subject, len); 350 cp = smk_parse_smack(subject, len);
362 if (cp == NULL) 351 if (IS_ERR(cp))
363 return -EINVAL; 352 return PTR_ERR(cp);
364 skp = smk_find_entry(cp); 353 skp = smk_find_entry(cp);
365 kfree(cp); 354 kfree(cp);
366 if (skp == NULL) 355 if (skp == NULL)
@@ -368,8 +357,8 @@ static int smk_fill_rule(const char *subject, const char *object,
368 rule->smk_subject = skp; 357 rule->smk_subject = skp;
369 358
370 cp = smk_parse_smack(object, len); 359 cp = smk_parse_smack(object, len);
371 if (cp == NULL) 360 if (IS_ERR(cp))
372 return -EINVAL; 361 return PTR_ERR(cp);
373 skp = smk_find_entry(cp); 362 skp = smk_find_entry(cp);
374 kfree(cp); 363 kfree(cp);
375 if (skp == NULL) 364 if (skp == NULL)
@@ -412,7 +401,7 @@ static int smk_parse_rule(const char *data, struct smack_parsed_rule *rule,
412 * @import: if non-zero, import labels 401 * @import: if non-zero, import labels
413 * @tokens: numer of substrings expected in data 402 * @tokens: numer of substrings expected in data
414 * 403 *
415 * Returns number of processed bytes on success, -1 on failure. 404 * Returns number of processed bytes on success, -ERRNO on failure.
416 */ 405 */
417static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule, 406static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule,
418 int import, int tokens) 407 int import, int tokens)
@@ -431,7 +420,7 @@ static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule,
431 420
432 if (data[cnt] == '\0') 421 if (data[cnt] == '\0')
433 /* Unexpected end of data */ 422 /* Unexpected end of data */
434 return -1; 423 return -EINVAL;
435 424
436 tok[i] = data + cnt; 425 tok[i] = data + cnt;
437 426
@@ -529,14 +518,14 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
529 while (cnt < count) { 518 while (cnt < count) {
530 if (format == SMK_FIXED24_FMT) { 519 if (format == SMK_FIXED24_FMT) {
531 rc = smk_parse_rule(data, &rule, 1); 520 rc = smk_parse_rule(data, &rule, 1);
532 if (rc != 0) { 521 if (rc < 0)
533 rc = -EINVAL;
534 goto out; 522 goto out;
535 }
536 cnt = count; 523 cnt = count;
537 } else { 524 } else {
538 rc = smk_parse_long_rule(data + cnt, &rule, 1, tokens); 525 rc = smk_parse_long_rule(data + cnt, &rule, 1, tokens);
539 if (rc <= 0) { 526 if (rc < 0)
527 goto out;
528 if (rc == 0) {
540 rc = -EINVAL; 529 rc = -EINVAL;
541 goto out; 530 goto out;
542 } 531 }
@@ -567,23 +556,17 @@ static void *smk_seq_start(struct seq_file *s, loff_t *pos,
567 struct list_head *head) 556 struct list_head *head)
568{ 557{
569 struct list_head *list; 558 struct list_head *list;
559 int i = *pos;
560
561 rcu_read_lock();
562 for (list = rcu_dereference(list_next_rcu(head));
563 list != head;
564 list = rcu_dereference(list_next_rcu(list))) {
565 if (i-- == 0)
566 return list;
567 }
570 568
571 /* 569 return NULL;
572 * This is 0 the first time through.
573 */
574 if (s->index == 0)
575 s->private = head;
576
577 if (s->private == NULL)
578 return NULL;
579
580 list = s->private;
581 if (list_empty(list))
582 return NULL;
583
584 if (s->index == 0)
585 return list->next;
586 return list;
587} 570}
588 571
589static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos, 572static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos,
@@ -591,17 +574,15 @@ static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos,
591{ 574{
592 struct list_head *list = v; 575 struct list_head *list = v;
593 576
594 if (list_is_last(list, head)) { 577 ++*pos;
595 s->private = NULL; 578 list = rcu_dereference(list_next_rcu(list));
596 return NULL; 579
597 } 580 return (list == head) ? NULL : list;
598 s->private = list->next;
599 return list->next;
600} 581}
601 582
602static void smk_seq_stop(struct seq_file *s, void *v) 583static void smk_seq_stop(struct seq_file *s, void *v)
603{ 584{
604 /* No-op */ 585 rcu_read_unlock();
605} 586}
606 587
607static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) 588static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
@@ -661,7 +642,7 @@ static int load_seq_show(struct seq_file *s, void *v)
661{ 642{
662 struct list_head *list = v; 643 struct list_head *list = v;
663 struct smack_master_list *smlp = 644 struct smack_master_list *smlp =
664 list_entry(list, struct smack_master_list, list); 645 list_entry_rcu(list, struct smack_master_list, list);
665 646
666 smk_rule_show(s, smlp->smk_rule, SMK_LABELLEN); 647 smk_rule_show(s, smlp->smk_rule, SMK_LABELLEN);
667 648
@@ -809,7 +790,7 @@ static int cipso_seq_show(struct seq_file *s, void *v)
809{ 790{
810 struct list_head *list = v; 791 struct list_head *list = v;
811 struct smack_known *skp = 792 struct smack_known *skp =
812 list_entry(list, struct smack_known, list); 793 list_entry_rcu(list, struct smack_known, list);
813 struct netlbl_lsm_catmap *cmp = skp->smk_netlabel.attr.mls.cat; 794 struct netlbl_lsm_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
814 char sep = '/'; 795 char sep = '/';
815 int i; 796 int i;
@@ -915,8 +896,10 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
915 mutex_lock(&smack_cipso_lock); 896 mutex_lock(&smack_cipso_lock);
916 897
917 skp = smk_import_entry(rule, 0); 898 skp = smk_import_entry(rule, 0);
918 if (skp == NULL) 899 if (IS_ERR(skp)) {
900 rc = PTR_ERR(skp);
919 goto out; 901 goto out;
902 }
920 903
921 if (format == SMK_FIXED24_FMT) 904 if (format == SMK_FIXED24_FMT)
922 rule += SMK_LABELLEN; 905 rule += SMK_LABELLEN;
@@ -998,7 +981,7 @@ static int cipso2_seq_show(struct seq_file *s, void *v)
998{ 981{
999 struct list_head *list = v; 982 struct list_head *list = v;
1000 struct smack_known *skp = 983 struct smack_known *skp =
1001 list_entry(list, struct smack_known, list); 984 list_entry_rcu(list, struct smack_known, list);
1002 struct netlbl_lsm_catmap *cmp = skp->smk_netlabel.attr.mls.cat; 985 struct netlbl_lsm_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
1003 char sep = '/'; 986 char sep = '/';
1004 int i; 987 int i;
@@ -1082,7 +1065,7 @@ static int netlbladdr_seq_show(struct seq_file *s, void *v)
1082{ 1065{
1083 struct list_head *list = v; 1066 struct list_head *list = v;
1084 struct smk_netlbladdr *skp = 1067 struct smk_netlbladdr *skp =
1085 list_entry(list, struct smk_netlbladdr, list); 1068 list_entry_rcu(list, struct smk_netlbladdr, list);
1086 unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr; 1069 unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
1087 int maskn; 1070 int maskn;
1088 u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr); 1071 u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr);
@@ -1237,8 +1220,8 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
1237 */ 1220 */
1238 if (smack[0] != '-') { 1221 if (smack[0] != '-') {
1239 skp = smk_import_entry(smack, 0); 1222 skp = smk_import_entry(smack, 0);
1240 if (skp == NULL) { 1223 if (IS_ERR(skp)) {
1241 rc = -EINVAL; 1224 rc = PTR_ERR(skp);
1242 goto free_out; 1225 goto free_out;
1243 } 1226 }
1244 } else { 1227 } else {
@@ -1619,8 +1602,8 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
1619 } 1602 }
1620 1603
1621 skp = smk_import_entry(data, count); 1604 skp = smk_import_entry(data, count);
1622 if (skp == NULL) { 1605 if (IS_ERR(skp)) {
1623 rc = -EINVAL; 1606 rc = PTR_ERR(skp);
1624 goto out; 1607 goto out;
1625 } 1608 }
1626 1609
@@ -1643,34 +1626,79 @@ static const struct file_operations smk_ambient_ops = {
1643 .llseek = default_llseek, 1626 .llseek = default_llseek,
1644}; 1627};
1645 1628
1646/** 1629/*
1647 * smk_read_onlycap - read() for smackfs/onlycap 1630 * Seq_file operations for /smack/onlycap
1648 * @filp: file pointer, not actually used
1649 * @buf: where to put the result
1650 * @cn: maximum to send along
1651 * @ppos: where to start
1652 *
1653 * Returns number of bytes read or error code, as appropriate
1654 */ 1631 */
1655static ssize_t smk_read_onlycap(struct file *filp, char __user *buf, 1632static void *onlycap_seq_start(struct seq_file *s, loff_t *pos)
1656 size_t cn, loff_t *ppos)
1657{ 1633{
1658 char *smack = ""; 1634 return smk_seq_start(s, pos, &smack_onlycap_list);
1659 ssize_t rc = -EINVAL; 1635}
1660 int asize;
1661 1636
1662 if (*ppos != 0) 1637static void *onlycap_seq_next(struct seq_file *s, void *v, loff_t *pos)
1663 return 0; 1638{
1639 return smk_seq_next(s, v, pos, &smack_onlycap_list);
1640}
1664 1641
1665 if (smack_onlycap != NULL) 1642static int onlycap_seq_show(struct seq_file *s, void *v)
1666 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);
1667 1647
1668 asize = strlen(smack) + 1; 1648 seq_puts(s, sop->smk_label->smk_known);
1649 seq_putc(s, ' ');
1669 1650
1670 if (cn >= asize) 1651 return 0;
1671 rc = simple_read_from_buffer(buf, cn, ppos, smack, asize); 1652}
1672 1653
1673 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 }
1674} 1702}
1675 1703
1676/** 1704/**
@@ -1686,47 +1714,79 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
1686 size_t count, loff_t *ppos) 1714 size_t count, loff_t *ppos)
1687{ 1715{
1688 char *data; 1716 char *data;
1689 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);
1690 int rc = count; 1723 int rc = count;
1691 1724
1692 if (!smack_privileged(CAP_MAC_ADMIN)) 1725 if (!smack_privileged(CAP_MAC_ADMIN))
1693 return -EPERM; 1726 return -EPERM;
1694 1727
1695 /*
1696 * This can be done using smk_access() but is done
1697 * explicitly for clarity. The smk_access() implementation
1698 * would use smk_access(smack_onlycap, MAY_WRITE)
1699 */
1700 if (smack_onlycap != NULL && smack_onlycap != skp)
1701 return -EPERM;
1702
1703 data = kzalloc(count + 1, GFP_KERNEL); 1728 data = kzalloc(count + 1, GFP_KERNEL);
1704 if (data == NULL) 1729 if (data == NULL)
1705 return -ENOMEM; 1730 return -ENOMEM;
1706 1731
1732 if (copy_from_user(data, buf, count) != 0) {
1733 kfree(data);
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);
1756 }
1757 kfree(data);
1758
1707 /* 1759 /*
1708 * Should the null string be passed in unset the onlycap value. 1760 * Clear the smack_onlycap on invalid label errors. This means
1709 * This seems like something to be careful with as usually 1761 * that we can pass a null string to unset the onlycap value.
1710 * smk_import only expects to return NULL for errors. It
1711 * is usually the case that a nullstring or "\n" would be
1712 * bad to pass to smk_import but in fact this is useful here.
1713 * 1762 *
1714 * smk_import will also reject a label beginning with '-', 1763 * Importing will also reject a label beginning with '-',
1715 * so "-usecapabilities" will also work. 1764 * so "-usecapabilities" will also work.
1765 *
1766 * But do so only on invalid label, not on system errors.
1767 * The invalid label must be first to count as clearing attempt.
1716 */ 1768 */
1717 if (copy_from_user(data, buf, count) != 0) 1769 if (rc == -EINVAL && list_empty(&list_tmp))
1718 rc = -EFAULT; 1770 rc = count;
1719 else 1771
1720 smack_onlycap = smk_import_entry(data, count); 1772 if (rc >= 0) {
1773 mutex_lock(&smack_onlycap_lock);
1774 smk_list_swap_rcu(&smack_onlycap_list, &list_tmp);
1775 mutex_unlock(&smack_onlycap_lock);
1776 }
1777
1778 list_for_each_entry_safe(sop, sop2, &list_tmp, list)
1779 kfree(sop);
1721 1780
1722 kfree(data);
1723 return rc; 1781 return rc;
1724} 1782}
1725 1783
1726static const struct file_operations smk_onlycap_ops = { 1784static const struct file_operations smk_onlycap_ops = {
1727 .read = smk_read_onlycap, 1785 .open = smk_open_onlycap,
1786 .read = seq_read,
1728 .write = smk_write_onlycap, 1787 .write = smk_write_onlycap,
1729 .llseek = default_llseek, 1788 .llseek = seq_lseek,
1789 .release = seq_release,
1730}; 1790};
1731 1791
1732#ifdef CONFIG_SECURITY_SMACK_BRINGUP 1792#ifdef CONFIG_SECURITY_SMACK_BRINGUP
@@ -1773,6 +1833,7 @@ static ssize_t smk_write_unconfined(struct file *file, const char __user *buf,
1773 size_t count, loff_t *ppos) 1833 size_t count, loff_t *ppos)
1774{ 1834{
1775 char *data; 1835 char *data;
1836 struct smack_known *skp;
1776 int rc = count; 1837 int rc = count;
1777 1838
1778 if (!smack_privileged(CAP_MAC_ADMIN)) 1839 if (!smack_privileged(CAP_MAC_ADMIN))
@@ -1782,21 +1843,31 @@ static ssize_t smk_write_unconfined(struct file *file, const char __user *buf,
1782 if (data == NULL) 1843 if (data == NULL)
1783 return -ENOMEM; 1844 return -ENOMEM;
1784 1845
1846 if (copy_from_user(data, buf, count) != 0) {
1847 rc = -EFAULT;
1848 goto freeout;
1849 }
1850
1785 /* 1851 /*
1786 * Should the null string be passed in unset the unconfined value. 1852 * Clear the smack_unconfined on invalid label errors. This means
1787 * This seems like something to be careful with as usually 1853 * that we can pass a null string to unset the unconfined value.
1788 * smk_import only expects to return NULL for errors. It
1789 * is usually the case that a nullstring or "\n" would be
1790 * bad to pass to smk_import but in fact this is useful here.
1791 * 1854 *
1792 * smk_import will also reject a label beginning with '-', 1855 * Importing will also reject a label beginning with '-',
1793 * so "-confine" will also work. 1856 * so "-confine" will also work.
1857 *
1858 * But do so only on invalid label, not on system errors.
1794 */ 1859 */
1795 if (copy_from_user(data, buf, count) != 0) 1860 skp = smk_import_entry(data, count);
1796 rc = -EFAULT; 1861 if (PTR_ERR(skp) == -EINVAL)
1797 else 1862 skp = NULL;
1798 smack_unconfined = smk_import_entry(data, count); 1863 else if (IS_ERR(skp)) {
1864 rc = PTR_ERR(skp);
1865 goto freeout;
1866 }
1867
1868 smack_unconfined = skp;
1799 1869
1870freeout:
1800 kfree(data); 1871 kfree(data);
1801 return rc; 1872 return rc;
1802} 1873}
@@ -1895,7 +1966,7 @@ static int load_self_seq_show(struct seq_file *s, void *v)
1895{ 1966{
1896 struct list_head *list = v; 1967 struct list_head *list = v;
1897 struct smack_rule *srp = 1968 struct smack_rule *srp =
1898 list_entry(list, struct smack_rule, list); 1969 list_entry_rcu(list, struct smack_rule, list);
1899 1970
1900 smk_rule_show(s, srp, SMK_LABELLEN); 1971 smk_rule_show(s, srp, SMK_LABELLEN);
1901 1972
@@ -1980,7 +2051,7 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf,
1980 res = smk_access(rule.smk_subject, rule.smk_object, 2051 res = smk_access(rule.smk_subject, rule.smk_object,
1981 rule.smk_access1, NULL); 2052 rule.smk_access1, NULL);
1982 else if (res != -ENOENT) 2053 else if (res != -ENOENT)
1983 return -EINVAL; 2054 return res;
1984 2055
1985 /* 2056 /*
1986 * smk_access() can return a value > 0 in the "bringup" case. 2057 * smk_access() can return a value > 0 in the "bringup" case.
@@ -2024,7 +2095,7 @@ static int load2_seq_show(struct seq_file *s, void *v)
2024{ 2095{
2025 struct list_head *list = v; 2096 struct list_head *list = v;
2026 struct smack_master_list *smlp = 2097 struct smack_master_list *smlp =
2027 list_entry(list, struct smack_master_list, list); 2098 list_entry_rcu(list, struct smack_master_list, list);
2028 2099
2029 smk_rule_show(s, smlp->smk_rule, SMK_LONGLABEL); 2100 smk_rule_show(s, smlp->smk_rule, SMK_LONGLABEL);
2030 2101
@@ -2101,7 +2172,7 @@ static int load_self2_seq_show(struct seq_file *s, void *v)
2101{ 2172{
2102 struct list_head *list = v; 2173 struct list_head *list = v;
2103 struct smack_rule *srp = 2174 struct smack_rule *srp =
2104 list_entry(list, struct smack_rule, list); 2175 list_entry_rcu(list, struct smack_rule, list);
2105 2176
2106 smk_rule_show(s, srp, SMK_LONGLABEL); 2177 smk_rule_show(s, srp, SMK_LONGLABEL);
2107 2178
@@ -2209,8 +2280,8 @@ static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf,
2209 } 2280 }
2210 2281
2211 cp = smk_parse_smack(data, count); 2282 cp = smk_parse_smack(data, count);
2212 if (cp == NULL) { 2283 if (IS_ERR(cp)) {
2213 rc = -EINVAL; 2284 rc = PTR_ERR(cp);
2214 goto free_out; 2285 goto free_out;
2215 } 2286 }
2216 2287
@@ -2341,10 +2412,10 @@ static ssize_t smk_write_syslog(struct file *file, const char __user *buf,
2341 rc = -EFAULT; 2412 rc = -EFAULT;
2342 else { 2413 else {
2343 skp = smk_import_entry(data, count); 2414 skp = smk_import_entry(data, count);
2344 if (skp == NULL) 2415 if (IS_ERR(skp))
2345 rc = -EINVAL; 2416 rc = PTR_ERR(skp);
2346 else 2417 else
2347 smack_syslog_label = smk_import_entry(data, count); 2418 smack_syslog_label = skp;
2348 } 2419 }
2349 2420
2350 kfree(data); 2421 kfree(data);