diff options
| -rw-r--r-- | security/selinux/hooks.c | 157 | ||||
| -rw-r--r-- | security/selinux/include/security.h | 1 |
2 files changed, 85 insertions, 73 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 1d0b37af2444..085409b36794 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -751,11 +751,13 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
| 751 | 751 | ||
| 752 | if (!strcmp(sb->s_type->name, "debugfs") || | 752 | if (!strcmp(sb->s_type->name, "debugfs") || |
| 753 | !strcmp(sb->s_type->name, "tracefs") || | 753 | !strcmp(sb->s_type->name, "tracefs") || |
| 754 | !strcmp(sb->s_type->name, "sysfs") || | 754 | !strcmp(sb->s_type->name, "pstore")) |
| 755 | !strcmp(sb->s_type->name, "pstore") || | 755 | sbsec->flags |= SE_SBGENFS; |
| 756 | |||
| 757 | if (!strcmp(sb->s_type->name, "sysfs") || | ||
| 756 | !strcmp(sb->s_type->name, "cgroup") || | 758 | !strcmp(sb->s_type->name, "cgroup") || |
| 757 | !strcmp(sb->s_type->name, "cgroup2")) | 759 | !strcmp(sb->s_type->name, "cgroup2")) |
| 758 | sbsec->flags |= SE_SBGENFS; | 760 | sbsec->flags |= SE_SBGENFS | SE_SBGENFS_XATTR; |
| 759 | 761 | ||
| 760 | if (!sbsec->behavior) { | 762 | if (!sbsec->behavior) { |
| 761 | /* | 763 | /* |
| @@ -1354,6 +1356,67 @@ static int selinux_genfs_get_sid(struct dentry *dentry, | |||
| 1354 | return rc; | 1356 | return rc; |
| 1355 | } | 1357 | } |
| 1356 | 1358 | ||
| 1359 | static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry, | ||
| 1360 | u32 def_sid, u32 *sid) | ||
| 1361 | { | ||
| 1362 | #define INITCONTEXTLEN 255 | ||
| 1363 | char *context; | ||
| 1364 | unsigned int len; | ||
| 1365 | int rc; | ||
| 1366 | |||
| 1367 | len = INITCONTEXTLEN; | ||
| 1368 | context = kmalloc(len + 1, GFP_NOFS); | ||
| 1369 | if (!context) | ||
| 1370 | return -ENOMEM; | ||
| 1371 | |||
| 1372 | context[len] = '\0'; | ||
| 1373 | rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len); | ||
| 1374 | if (rc == -ERANGE) { | ||
| 1375 | kfree(context); | ||
| 1376 | |||
| 1377 | /* Need a larger buffer. Query for the right size. */ | ||
| 1378 | rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0); | ||
| 1379 | if (rc < 0) | ||
| 1380 | return rc; | ||
| 1381 | |||
| 1382 | len = rc; | ||
| 1383 | context = kmalloc(len + 1, GFP_NOFS); | ||
| 1384 | if (!context) | ||
| 1385 | return -ENOMEM; | ||
| 1386 | |||
| 1387 | context[len] = '\0'; | ||
| 1388 | rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, | ||
| 1389 | context, len); | ||
| 1390 | } | ||
| 1391 | if (rc < 0) { | ||
| 1392 | kfree(context); | ||
| 1393 | if (rc != -ENODATA) { | ||
| 1394 | pr_warn("SELinux: %s: getxattr returned %d for dev=%s ino=%ld\n", | ||
| 1395 | __func__, -rc, inode->i_sb->s_id, inode->i_ino); | ||
| 1396 | return rc; | ||
| 1397 | } | ||
| 1398 | *sid = def_sid; | ||
| 1399 | return 0; | ||
| 1400 | } | ||
| 1401 | |||
| 1402 | rc = security_context_to_sid_default(&selinux_state, context, rc, sid, | ||
| 1403 | def_sid, GFP_NOFS); | ||
| 1404 | if (rc) { | ||
| 1405 | char *dev = inode->i_sb->s_id; | ||
| 1406 | unsigned long ino = inode->i_ino; | ||
| 1407 | |||
| 1408 | if (rc == -EINVAL) { | ||
| 1409 | pr_notice_ratelimited("SELinux: inode=%lu on dev=%s was found to have an invalid context=%s. This indicates you may need to relabel the inode or the filesystem in question.\n", | ||
| 1410 | ino, dev, context); | ||
| 1411 | } else { | ||
| 1412 | pr_warn("SELinux: %s: context_to_sid(%s) returned %d for dev=%s ino=%ld\n", | ||
| 1413 | __func__, context, -rc, dev, ino); | ||
| 1414 | } | ||
| 1415 | } | ||
| 1416 | kfree(context); | ||
| 1417 | return 0; | ||
| 1418 | } | ||
| 1419 | |||
| 1357 | /* The inode's security attributes must be initialized before first use. */ | 1420 | /* The inode's security attributes must be initialized before first use. */ |
| 1358 | static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry) | 1421 | static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry) |
| 1359 | { | 1422 | { |
| @@ -1362,9 +1425,6 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
| 1362 | u32 task_sid, sid = 0; | 1425 | u32 task_sid, sid = 0; |
| 1363 | u16 sclass; | 1426 | u16 sclass; |
| 1364 | struct dentry *dentry; | 1427 | struct dentry *dentry; |
| 1365 | #define INITCONTEXTLEN 255 | ||
| 1366 | char *context = NULL; | ||
| 1367 | unsigned len = 0; | ||
| 1368 | int rc = 0; | 1428 | int rc = 0; |
| 1369 | 1429 | ||
| 1370 | if (isec->initialized == LABEL_INITIALIZED) | 1430 | if (isec->initialized == LABEL_INITIALIZED) |
| @@ -1432,72 +1492,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
| 1432 | goto out; | 1492 | goto out; |
| 1433 | } | 1493 | } |
| 1434 | 1494 | ||
| 1435 | len = INITCONTEXTLEN; | 1495 | rc = inode_doinit_use_xattr(inode, dentry, sbsec->def_sid, |
| 1436 | context = kmalloc(len+1, GFP_NOFS); | 1496 | &sid); |
| 1437 | if (!context) { | ||
| 1438 | rc = -ENOMEM; | ||
| 1439 | dput(dentry); | ||
| 1440 | goto out; | ||
| 1441 | } | ||
| 1442 | context[len] = '\0'; | ||
| 1443 | rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len); | ||
| 1444 | if (rc == -ERANGE) { | ||
| 1445 | kfree(context); | ||
| 1446 | |||
| 1447 | /* Need a larger buffer. Query for the right size. */ | ||
| 1448 | rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0); | ||
| 1449 | if (rc < 0) { | ||
| 1450 | dput(dentry); | ||
| 1451 | goto out; | ||
| 1452 | } | ||
| 1453 | len = rc; | ||
| 1454 | context = kmalloc(len+1, GFP_NOFS); | ||
| 1455 | if (!context) { | ||
| 1456 | rc = -ENOMEM; | ||
| 1457 | dput(dentry); | ||
| 1458 | goto out; | ||
| 1459 | } | ||
| 1460 | context[len] = '\0'; | ||
| 1461 | rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len); | ||
| 1462 | } | ||
| 1463 | dput(dentry); | 1497 | dput(dentry); |
| 1464 | if (rc < 0) { | 1498 | if (rc) |
| 1465 | if (rc != -ENODATA) { | 1499 | goto out; |
| 1466 | pr_warn("SELinux: %s: getxattr returned " | ||
| 1467 | "%d for dev=%s ino=%ld\n", __func__, | ||
| 1468 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
| 1469 | kfree(context); | ||
| 1470 | goto out; | ||
| 1471 | } | ||
| 1472 | /* Map ENODATA to the default file SID */ | ||
| 1473 | sid = sbsec->def_sid; | ||
| 1474 | rc = 0; | ||
| 1475 | } else { | ||
| 1476 | rc = security_context_to_sid_default(&selinux_state, | ||
| 1477 | context, rc, &sid, | ||
| 1478 | sbsec->def_sid, | ||
| 1479 | GFP_NOFS); | ||
| 1480 | if (rc) { | ||
| 1481 | char *dev = inode->i_sb->s_id; | ||
| 1482 | unsigned long ino = inode->i_ino; | ||
| 1483 | |||
| 1484 | if (rc == -EINVAL) { | ||
| 1485 | if (printk_ratelimit()) | ||
| 1486 | pr_notice("SELinux: inode=%lu on dev=%s was found to have an invalid " | ||
| 1487 | "context=%s. This indicates you may need to relabel the inode or the " | ||
| 1488 | "filesystem in question.\n", ino, dev, context); | ||
| 1489 | } else { | ||
| 1490 | pr_warn("SELinux: %s: context_to_sid(%s) " | ||
| 1491 | "returned %d for dev=%s ino=%ld\n", | ||
| 1492 | __func__, context, -rc, dev, ino); | ||
| 1493 | } | ||
| 1494 | kfree(context); | ||
| 1495 | /* Leave with the unlabeled SID */ | ||
| 1496 | rc = 0; | ||
| 1497 | break; | ||
| 1498 | } | ||
| 1499 | } | ||
| 1500 | kfree(context); | ||
| 1501 | break; | 1500 | break; |
| 1502 | case SECURITY_FS_USE_TASK: | 1501 | case SECURITY_FS_USE_TASK: |
| 1503 | sid = task_sid; | 1502 | sid = task_sid; |
| @@ -1548,9 +1547,21 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
| 1548 | goto out; | 1547 | goto out; |
| 1549 | rc = selinux_genfs_get_sid(dentry, sclass, | 1548 | rc = selinux_genfs_get_sid(dentry, sclass, |
| 1550 | sbsec->flags, &sid); | 1549 | sbsec->flags, &sid); |
| 1551 | dput(dentry); | 1550 | if (rc) { |
| 1552 | if (rc) | 1551 | dput(dentry); |
| 1553 | goto out; | 1552 | goto out; |
| 1553 | } | ||
| 1554 | |||
| 1555 | if ((sbsec->flags & SE_SBGENFS_XATTR) && | ||
| 1556 | (inode->i_opflags & IOP_XATTR)) { | ||
| 1557 | rc = inode_doinit_use_xattr(inode, dentry, | ||
| 1558 | sid, &sid); | ||
| 1559 | if (rc) { | ||
| 1560 | dput(dentry); | ||
| 1561 | goto out; | ||
| 1562 | } | ||
| 1563 | } | ||
| 1564 | dput(dentry); | ||
| 1554 | } | 1565 | } |
| 1555 | break; | 1566 | break; |
| 1556 | } | 1567 | } |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index b5b7c5aade8c..111121281c47 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
| @@ -58,6 +58,7 @@ | |||
| 58 | #define SE_SBINITIALIZED 0x0100 | 58 | #define SE_SBINITIALIZED 0x0100 |
| 59 | #define SE_SBPROC 0x0200 | 59 | #define SE_SBPROC 0x0200 |
| 60 | #define SE_SBGENFS 0x0400 | 60 | #define SE_SBGENFS 0x0400 |
| 61 | #define SE_SBGENFS_XATTR 0x0800 | ||
| 61 | 62 | ||
| 62 | #define CONTEXT_STR "context" | 63 | #define CONTEXT_STR "context" |
| 63 | #define FSCONTEXT_STR "fscontext" | 64 | #define FSCONTEXT_STR "fscontext" |
