aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--security/selinux/hooks.c157
-rw-r--r--security/selinux/include/security.h1
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
1359static 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. */
1358static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry) 1421static 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"