aboutsummaryrefslogtreecommitdiffstats
path: root/security/smack
diff options
context:
space:
mode:
authorLukasz Pawelczyk <l.pawelczyk@samsung.com>2015-04-20 11:12:54 -0400
committerCasey Schaufler <casey@schaufler-ca.com>2015-05-15 11:36:03 -0400
commite774ad683f425a51f87711164ea166d9dcc41477 (patch)
tree0dcb99f91fe29472664f1ac4cd8714f30a6a020c /security/smack
parent9777582e8d604f69ce3a93805065e451487e26b4 (diff)
smack: pass error code through pointers
This patch makes the following functions to use ERR_PTR() and related macros to pass the appropriate error code through returned pointers: smk_parse_smack() smk_import_entry() smk_fetch() It also makes all the other functions that use them to handle the error cases properly. This ways correct error codes from places where they happened can be propagated to the user space if necessary. Doing this it fixes a bug in onlycap and unconfined files handling. Previously their content was cleared on any error from smk_import_entry/smk_parse_smack, be it EINVAL (as originally intended) or ENOMEM. Right now it only reacts on EINVAL passing other codes properly to userspace. Comments have been updated accordingly. Signed-off-by: Lukasz Pawelczyk <l.pawelczyk@samsung.com>
Diffstat (limited to 'security/smack')
-rw-r--r--security/smack/smack_access.c27
-rw-r--r--security/smack/smack_lsm.c93
-rw-r--r--security/smack/smackfs.c116
3 files changed, 139 insertions, 97 deletions
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 0f410fc56e33..408e20be1ad7 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:
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index f09b8c7cf1e7..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;
@@ -2403,8 +2413,8 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
2403 return -EINVAL; 2413 return -EINVAL;
2404 2414
2405 skp = smk_import_entry(value, size); 2415 skp = smk_import_entry(value, size);
2406 if (skp == NULL) 2416 if (IS_ERR(skp))
2407 return -EINVAL; 2417 return PTR_ERR(skp);
2408 2418
2409 if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { 2419 if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) {
2410 nsp->smk_inode = skp; 2420 nsp->smk_inode = skp;
@@ -3177,7 +3187,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
3177 */ 3187 */
3178 dp = dget(opt_dentry); 3188 dp = dget(opt_dentry);
3179 skp = smk_fetch(XATTR_NAME_SMACK, inode, dp); 3189 skp = smk_fetch(XATTR_NAME_SMACK, inode, dp);
3180 if (skp != NULL) 3190 if (!IS_ERR_OR_NULL(skp))
3181 final = skp; 3191 final = skp;
3182 3192
3183 /* 3193 /*
@@ -3214,11 +3224,14 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
3214 * Don't let the exec or mmap label be "*" or "@". 3224 * Don't let the exec or mmap label be "*" or "@".
3215 */ 3225 */
3216 skp = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); 3226 skp = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp);
3217 if (skp == &smack_known_star || skp == &smack_known_web) 3227 if (IS_ERR(skp) || skp == &smack_known_star ||
3228 skp == &smack_known_web)
3218 skp = NULL; 3229 skp = NULL;
3219 isp->smk_task = skp; 3230 isp->smk_task = skp;
3231
3220 skp = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp); 3232 skp = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp);
3221 if (skp == &smack_known_star || skp == &smack_known_web) 3233 if (IS_ERR(skp) || skp == &smack_known_star ||
3234 skp == &smack_known_web)
3222 skp = NULL; 3235 skp = NULL;
3223 isp->smk_mmap = skp; 3236 isp->smk_mmap = skp;
3224 3237
@@ -3302,8 +3315,8 @@ static int smack_setprocattr(struct task_struct *p, char *name,
3302 return -EINVAL; 3315 return -EINVAL;
3303 3316
3304 skp = smk_import_entry(value, size); 3317 skp = smk_import_entry(value, size);
3305 if (skp == NULL) 3318 if (IS_ERR(skp))
3306 return -EINVAL; 3319 return PTR_ERR(skp);
3307 3320
3308 /* 3321 /*
3309 * No process is ever allowed the web ("@") label. 3322 * No process is ever allowed the web ("@") label.
@@ -4078,8 +4091,10 @@ static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
4078 return -EINVAL; 4091 return -EINVAL;
4079 4092
4080 skp = smk_import_entry(rulestr, 0); 4093 skp = smk_import_entry(rulestr, 0);
4081 if (skp) 4094 if (IS_ERR(skp))
4082 *rule = skp->smk_known; 4095 return PTR_ERR(skp);
4096
4097 *rule = skp->smk_known;
4083 4098
4084 return 0; 4099 return 0;
4085} 4100}
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 4aa12c8d3c63..3e4242617eea 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -338,8 +338,7 @@ static int smk_perm_from_str(const char *string)
338 * @import: if non-zero, import labels 338 * @import: if non-zero, import labels
339 * @len: label length limit 339 * @len: label length limit
340 * 340 *
341 * Returns 0 on success, -EINVAL on failure and -ENOENT when either subject 341 * Returns 0 on success, appropriate error code on failure.
342 * or object is missing.
343 */ 342 */
344static int smk_fill_rule(const char *subject, const char *object, 343static int smk_fill_rule(const char *subject, const char *object,
345 const char *access1, const char *access2, 344 const char *access1, const char *access2,
@@ -351,16 +350,16 @@ static int smk_fill_rule(const char *subject, const char *object,
351 350
352 if (import) { 351 if (import) {
353 rule->smk_subject = smk_import_entry(subject, len); 352 rule->smk_subject = smk_import_entry(subject, len);
354 if (rule->smk_subject == NULL) 353 if (IS_ERR(rule->smk_subject))
355 return -EINVAL; 354 return PTR_ERR(rule->smk_subject);
356 355
357 rule->smk_object = smk_import_entry(object, len); 356 rule->smk_object = smk_import_entry(object, len);
358 if (rule->smk_object == NULL) 357 if (IS_ERR(rule->smk_object))
359 return -EINVAL; 358 return PTR_ERR(rule->smk_object);
360 } else { 359 } else {
361 cp = smk_parse_smack(subject, len); 360 cp = smk_parse_smack(subject, len);
362 if (cp == NULL) 361 if (IS_ERR(cp))
363 return -EINVAL; 362 return PTR_ERR(cp);
364 skp = smk_find_entry(cp); 363 skp = smk_find_entry(cp);
365 kfree(cp); 364 kfree(cp);
366 if (skp == NULL) 365 if (skp == NULL)
@@ -368,8 +367,8 @@ static int smk_fill_rule(const char *subject, const char *object,
368 rule->smk_subject = skp; 367 rule->smk_subject = skp;
369 368
370 cp = smk_parse_smack(object, len); 369 cp = smk_parse_smack(object, len);
371 if (cp == NULL) 370 if (IS_ERR(cp))
372 return -EINVAL; 371 return PTR_ERR(cp);
373 skp = smk_find_entry(cp); 372 skp = smk_find_entry(cp);
374 kfree(cp); 373 kfree(cp);
375 if (skp == NULL) 374 if (skp == NULL)
@@ -412,7 +411,7 @@ static int smk_parse_rule(const char *data, struct smack_parsed_rule *rule,
412 * @import: if non-zero, import labels 411 * @import: if non-zero, import labels
413 * @tokens: numer of substrings expected in data 412 * @tokens: numer of substrings expected in data
414 * 413 *
415 * Returns number of processed bytes on success, -1 on failure. 414 * Returns number of processed bytes on success, -ERRNO on failure.
416 */ 415 */
417static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule, 416static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule,
418 int import, int tokens) 417 int import, int tokens)
@@ -431,7 +430,7 @@ static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule,
431 430
432 if (data[cnt] == '\0') 431 if (data[cnt] == '\0')
433 /* Unexpected end of data */ 432 /* Unexpected end of data */
434 return -1; 433 return -EINVAL;
435 434
436 tok[i] = data + cnt; 435 tok[i] = data + cnt;
437 436
@@ -529,14 +528,14 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
529 while (cnt < count) { 528 while (cnt < count) {
530 if (format == SMK_FIXED24_FMT) { 529 if (format == SMK_FIXED24_FMT) {
531 rc = smk_parse_rule(data, &rule, 1); 530 rc = smk_parse_rule(data, &rule, 1);
532 if (rc != 0) { 531 if (rc < 0)
533 rc = -EINVAL;
534 goto out; 532 goto out;
535 }
536 cnt = count; 533 cnt = count;
537 } else { 534 } else {
538 rc = smk_parse_long_rule(data + cnt, &rule, 1, tokens); 535 rc = smk_parse_long_rule(data + cnt, &rule, 1, tokens);
539 if (rc <= 0) { 536 if (rc < 0)
537 goto out;
538 if (rc == 0) {
540 rc = -EINVAL; 539 rc = -EINVAL;
541 goto out; 540 goto out;
542 } 541 }
@@ -915,8 +914,10 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
915 mutex_lock(&smack_cipso_lock); 914 mutex_lock(&smack_cipso_lock);
916 915
917 skp = smk_import_entry(rule, 0); 916 skp = smk_import_entry(rule, 0);
918 if (skp == NULL) 917 if (IS_ERR(skp)) {
918 rc = PTR_ERR(skp);
919 goto out; 919 goto out;
920 }
920 921
921 if (format == SMK_FIXED24_FMT) 922 if (format == SMK_FIXED24_FMT)
922 rule += SMK_LABELLEN; 923 rule += SMK_LABELLEN;
@@ -1237,8 +1238,8 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
1237 */ 1238 */
1238 if (smack[0] != '-') { 1239 if (smack[0] != '-') {
1239 skp = smk_import_entry(smack, 0); 1240 skp = smk_import_entry(smack, 0);
1240 if (skp == NULL) { 1241 if (IS_ERR(skp)) {
1241 rc = -EINVAL; 1242 rc = PTR_ERR(skp);
1242 goto free_out; 1243 goto free_out;
1243 } 1244 }
1244 } else { 1245 } else {
@@ -1619,8 +1620,8 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
1619 } 1620 }
1620 1621
1621 skp = smk_import_entry(data, count); 1622 skp = smk_import_entry(data, count);
1622 if (skp == NULL) { 1623 if (IS_ERR(skp)) {
1623 rc = -EINVAL; 1624 rc = PTR_ERR(skp);
1624 goto out; 1625 goto out;
1625 } 1626 }
1626 1627
@@ -1704,21 +1705,31 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
1704 if (data == NULL) 1705 if (data == NULL)
1705 return -ENOMEM; 1706 return -ENOMEM;
1706 1707
1708 if (copy_from_user(data, buf, count) != 0) {
1709 rc = -EFAULT;
1710 goto freeout;
1711 }
1712
1707 /* 1713 /*
1708 * Should the null string be passed in unset the onlycap value. 1714 * Clear the smack_onlycap on invalid label errors. This means
1709 * This seems like something to be careful with as usually 1715 * 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 * 1716 *
1714 * smk_import will also reject a label beginning with '-', 1717 * Importing will also reject a label beginning with '-',
1715 * so "-usecapabilities" will also work. 1718 * so "-usecapabilities" will also work.
1719 *
1720 * But do so only on invalid label, not on system errors.
1716 */ 1721 */
1717 if (copy_from_user(data, buf, count) != 0) 1722 skp = smk_import_entry(data, count);
1718 rc = -EFAULT; 1723 if (PTR_ERR(skp) == -EINVAL)
1719 else 1724 skp = NULL;
1720 smack_onlycap = smk_import_entry(data, count); 1725 else if (IS_ERR(skp)) {
1726 rc = PTR_ERR(skp);
1727 goto freeout;
1728 }
1729
1730 smack_onlycap = skp;
1721 1731
1732freeout:
1722 kfree(data); 1733 kfree(data);
1723 return rc; 1734 return rc;
1724} 1735}
@@ -1773,6 +1784,7 @@ static ssize_t smk_write_unconfined(struct file *file, const char __user *buf,
1773 size_t count, loff_t *ppos) 1784 size_t count, loff_t *ppos)
1774{ 1785{
1775 char *data; 1786 char *data;
1787 struct smack_known *skp;
1776 int rc = count; 1788 int rc = count;
1777 1789
1778 if (!smack_privileged(CAP_MAC_ADMIN)) 1790 if (!smack_privileged(CAP_MAC_ADMIN))
@@ -1782,21 +1794,31 @@ static ssize_t smk_write_unconfined(struct file *file, const char __user *buf,
1782 if (data == NULL) 1794 if (data == NULL)
1783 return -ENOMEM; 1795 return -ENOMEM;
1784 1796
1797 if (copy_from_user(data, buf, count) != 0) {
1798 rc = -EFAULT;
1799 goto freeout;
1800 }
1801
1785 /* 1802 /*
1786 * Should the null string be passed in unset the unconfined value. 1803 * Clear the smack_unconfined on invalid label errors. This means
1787 * This seems like something to be careful with as usually 1804 * 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 * 1805 *
1792 * smk_import will also reject a label beginning with '-', 1806 * Importing will also reject a label beginning with '-',
1793 * so "-confine" will also work. 1807 * so "-confine" will also work.
1808 *
1809 * But do so only on invalid label, not on system errors.
1794 */ 1810 */
1795 if (copy_from_user(data, buf, count) != 0) 1811 skp = smk_import_entry(data, count);
1796 rc = -EFAULT; 1812 if (PTR_ERR(skp) == -EINVAL)
1797 else 1813 skp = NULL;
1798 smack_unconfined = smk_import_entry(data, count); 1814 else if (IS_ERR(skp)) {
1815 rc = PTR_ERR(skp);
1816 goto freeout;
1817 }
1818
1819 smack_unconfined = skp;
1799 1820
1821freeout:
1800 kfree(data); 1822 kfree(data);
1801 return rc; 1823 return rc;
1802} 1824}
@@ -1980,7 +2002,7 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf,
1980 res = smk_access(rule.smk_subject, rule.smk_object, 2002 res = smk_access(rule.smk_subject, rule.smk_object,
1981 rule.smk_access1, NULL); 2003 rule.smk_access1, NULL);
1982 else if (res != -ENOENT) 2004 else if (res != -ENOENT)
1983 return -EINVAL; 2005 return res;
1984 2006
1985 /* 2007 /*
1986 * smk_access() can return a value > 0 in the "bringup" case. 2008 * smk_access() can return a value > 0 in the "bringup" case.
@@ -2209,8 +2231,8 @@ static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf,
2209 } 2231 }
2210 2232
2211 cp = smk_parse_smack(data, count); 2233 cp = smk_parse_smack(data, count);
2212 if (cp == NULL) { 2234 if (IS_ERR(cp)) {
2213 rc = -EINVAL; 2235 rc = PTR_ERR(cp);
2214 goto free_out; 2236 goto free_out;
2215 } 2237 }
2216 2238
@@ -2341,10 +2363,10 @@ static ssize_t smk_write_syslog(struct file *file, const char __user *buf,
2341 rc = -EFAULT; 2363 rc = -EFAULT;
2342 else { 2364 else {
2343 skp = smk_import_entry(data, count); 2365 skp = smk_import_entry(data, count);
2344 if (skp == NULL) 2366 if (IS_ERR(skp))
2345 rc = -EINVAL; 2367 rc = PTR_ERR(skp);
2346 else 2368 else
2347 smack_syslog_label = smk_import_entry(data, count); 2369 smack_syslog_label = skp;
2348 } 2370 }
2349 2371
2350 kfree(data); 2372 kfree(data);