aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c229
1 files changed, 155 insertions, 74 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 1d0b37af2444..c61787b15f27 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -89,6 +89,8 @@
89#include <linux/msg.h> 89#include <linux/msg.h>
90#include <linux/shm.h> 90#include <linux/shm.h>
91#include <linux/bpf.h> 91#include <linux/bpf.h>
92#include <linux/kernfs.h>
93#include <linux/stringhash.h> /* for hashlen_string() */
92#include <uapi/linux/mount.h> 94#include <uapi/linux/mount.h>
93 95
94#include "avc.h" 96#include "avc.h"
@@ -751,11 +753,13 @@ static int selinux_set_mnt_opts(struct super_block *sb,
751 753
752 if (!strcmp(sb->s_type->name, "debugfs") || 754 if (!strcmp(sb->s_type->name, "debugfs") ||
753 !strcmp(sb->s_type->name, "tracefs") || 755 !strcmp(sb->s_type->name, "tracefs") ||
754 !strcmp(sb->s_type->name, "sysfs") || 756 !strcmp(sb->s_type->name, "pstore"))
755 !strcmp(sb->s_type->name, "pstore") || 757 sbsec->flags |= SE_SBGENFS;
758
759 if (!strcmp(sb->s_type->name, "sysfs") ||
756 !strcmp(sb->s_type->name, "cgroup") || 760 !strcmp(sb->s_type->name, "cgroup") ||
757 !strcmp(sb->s_type->name, "cgroup2")) 761 !strcmp(sb->s_type->name, "cgroup2"))
758 sbsec->flags |= SE_SBGENFS; 762 sbsec->flags |= SE_SBGENFS | SE_SBGENFS_XATTR;
759 763
760 if (!sbsec->behavior) { 764 if (!sbsec->behavior) {
761 /* 765 /*
@@ -1354,6 +1358,67 @@ static int selinux_genfs_get_sid(struct dentry *dentry,
1354 return rc; 1358 return rc;
1355} 1359}
1356 1360
1361static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry,
1362 u32 def_sid, u32 *sid)
1363{
1364#define INITCONTEXTLEN 255
1365 char *context;
1366 unsigned int len;
1367 int rc;
1368
1369 len = INITCONTEXTLEN;
1370 context = kmalloc(len + 1, GFP_NOFS);
1371 if (!context)
1372 return -ENOMEM;
1373
1374 context[len] = '\0';
1375 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
1376 if (rc == -ERANGE) {
1377 kfree(context);
1378
1379 /* Need a larger buffer. Query for the right size. */
1380 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
1381 if (rc < 0)
1382 return rc;
1383
1384 len = rc;
1385 context = kmalloc(len + 1, GFP_NOFS);
1386 if (!context)
1387 return -ENOMEM;
1388
1389 context[len] = '\0';
1390 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX,
1391 context, len);
1392 }
1393 if (rc < 0) {
1394 kfree(context);
1395 if (rc != -ENODATA) {
1396 pr_warn("SELinux: %s: getxattr returned %d for dev=%s ino=%ld\n",
1397 __func__, -rc, inode->i_sb->s_id, inode->i_ino);
1398 return rc;
1399 }
1400 *sid = def_sid;
1401 return 0;
1402 }
1403
1404 rc = security_context_to_sid_default(&selinux_state, context, rc, sid,
1405 def_sid, GFP_NOFS);
1406 if (rc) {
1407 char *dev = inode->i_sb->s_id;
1408 unsigned long ino = inode->i_ino;
1409
1410 if (rc == -EINVAL) {
1411 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",
1412 ino, dev, context);
1413 } else {
1414 pr_warn("SELinux: %s: context_to_sid(%s) returned %d for dev=%s ino=%ld\n",
1415 __func__, context, -rc, dev, ino);
1416 }
1417 }
1418 kfree(context);
1419 return 0;
1420}
1421
1357/* The inode's security attributes must be initialized before first use. */ 1422/* The inode's security attributes must be initialized before first use. */
1358static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry) 1423static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1359{ 1424{
@@ -1362,9 +1427,6 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1362 u32 task_sid, sid = 0; 1427 u32 task_sid, sid = 0;
1363 u16 sclass; 1428 u16 sclass;
1364 struct dentry *dentry; 1429 struct dentry *dentry;
1365#define INITCONTEXTLEN 255
1366 char *context = NULL;
1367 unsigned len = 0;
1368 int rc = 0; 1430 int rc = 0;
1369 1431
1370 if (isec->initialized == LABEL_INITIALIZED) 1432 if (isec->initialized == LABEL_INITIALIZED)
@@ -1432,72 +1494,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1432 goto out; 1494 goto out;
1433 } 1495 }
1434 1496
1435 len = INITCONTEXTLEN; 1497 rc = inode_doinit_use_xattr(inode, dentry, sbsec->def_sid,
1436 context = kmalloc(len+1, GFP_NOFS); 1498 &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); 1499 dput(dentry);
1464 if (rc < 0) { 1500 if (rc)
1465 if (rc != -ENODATA) { 1501 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; 1502 break;
1502 case SECURITY_FS_USE_TASK: 1503 case SECURITY_FS_USE_TASK:
1503 sid = task_sid; 1504 sid = task_sid;
@@ -1548,9 +1549,21 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1548 goto out; 1549 goto out;
1549 rc = selinux_genfs_get_sid(dentry, sclass, 1550 rc = selinux_genfs_get_sid(dentry, sclass,
1550 sbsec->flags, &sid); 1551 sbsec->flags, &sid);
1551 dput(dentry); 1552 if (rc) {
1552 if (rc) 1553 dput(dentry);
1553 goto out; 1554 goto out;
1555 }
1556
1557 if ((sbsec->flags & SE_SBGENFS_XATTR) &&
1558 (inode->i_opflags & IOP_XATTR)) {
1559 rc = inode_doinit_use_xattr(inode, dentry,
1560 sid, &sid);
1561 if (rc) {
1562 dput(dentry);
1563 goto out;
1564 }
1565 }
1566 dput(dentry);
1554 } 1567 }
1555 break; 1568 break;
1556 } 1569 }
@@ -3371,6 +3384,67 @@ static int selinux_inode_copy_up_xattr(const char *name)
3371 return -EOPNOTSUPP; 3384 return -EOPNOTSUPP;
3372} 3385}
3373 3386
3387/* kernfs node operations */
3388
3389static int selinux_kernfs_init_security(struct kernfs_node *kn_dir,
3390 struct kernfs_node *kn)
3391{
3392 const struct task_security_struct *tsec = current_security();
3393 u32 parent_sid, newsid, clen;
3394 int rc;
3395 char *context;
3396
3397 rc = kernfs_xattr_get(kn_dir, XATTR_NAME_SELINUX, NULL, 0);
3398 if (rc == -ENODATA)
3399 return 0;
3400 else if (rc < 0)
3401 return rc;
3402
3403 clen = (u32)rc;
3404 context = kmalloc(clen, GFP_KERNEL);
3405 if (!context)
3406 return -ENOMEM;
3407
3408 rc = kernfs_xattr_get(kn_dir, XATTR_NAME_SELINUX, context, clen);
3409 if (rc < 0) {
3410 kfree(context);
3411 return rc;
3412 }
3413
3414 rc = security_context_to_sid(&selinux_state, context, clen, &parent_sid,
3415 GFP_KERNEL);
3416 kfree(context);
3417 if (rc)
3418 return rc;
3419
3420 if (tsec->create_sid) {
3421 newsid = tsec->create_sid;
3422 } else {
3423 u16 secclass = inode_mode_to_security_class(kn->mode);
3424 struct qstr q;
3425
3426 q.name = kn->name;
3427 q.hash_len = hashlen_string(kn_dir, kn->name);
3428
3429 rc = security_transition_sid(&selinux_state, tsec->sid,
3430 parent_sid, secclass, &q,
3431 &newsid);
3432 if (rc)
3433 return rc;
3434 }
3435
3436 rc = security_sid_to_context_force(&selinux_state, newsid,
3437 &context, &clen);
3438 if (rc)
3439 return rc;
3440
3441 rc = kernfs_xattr_set(kn, XATTR_NAME_SELINUX, context, clen,
3442 XATTR_CREATE);
3443 kfree(context);
3444 return rc;
3445}
3446
3447
3374/* file security operations */ 3448/* file security operations */
3375 3449
3376static int selinux_revalidate_file_permission(struct file *file, int mask) 3450static int selinux_revalidate_file_permission(struct file *file, int mask)
@@ -4438,7 +4512,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
4438 struct lsm_network_audit net = {0,}; 4512 struct lsm_network_audit net = {0,};
4439 struct sockaddr_in *addr4 = NULL; 4513 struct sockaddr_in *addr4 = NULL;
4440 struct sockaddr_in6 *addr6 = NULL; 4514 struct sockaddr_in6 *addr6 = NULL;
4441 u16 family_sa = address->sa_family; 4515 u16 family_sa;
4442 unsigned short snum; 4516 unsigned short snum;
4443 u32 sid, node_perm; 4517 u32 sid, node_perm;
4444 4518
@@ -4448,6 +4522,9 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
4448 * need to check address->sa_family as it is possible to have 4522 * need to check address->sa_family as it is possible to have
4449 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET. 4523 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
4450 */ 4524 */
4525 if (addrlen < offsetofend(struct sockaddr, sa_family))
4526 return -EINVAL;
4527 family_sa = address->sa_family;
4451 switch (family_sa) { 4528 switch (family_sa) {
4452 case AF_UNSPEC: 4529 case AF_UNSPEC:
4453 case AF_INET: 4530 case AF_INET:
@@ -4580,6 +4657,8 @@ static int selinux_socket_connect_helper(struct socket *sock,
4580 * need to check address->sa_family as it is possible to have 4657 * need to check address->sa_family as it is possible to have
4581 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET. 4658 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
4582 */ 4659 */
4660 if (addrlen < offsetofend(struct sockaddr, sa_family))
4661 return -EINVAL;
4583 switch (address->sa_family) { 4662 switch (address->sa_family) {
4584 case AF_INET: 4663 case AF_INET:
4585 addr4 = (struct sockaddr_in *)address; 4664 addr4 = (struct sockaddr_in *)address;
@@ -6719,6 +6798,8 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
6719 LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up), 6798 LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
6720 LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr), 6799 LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr),
6721 6800
6801 LSM_HOOK_INIT(kernfs_init_security, selinux_kernfs_init_security),
6802
6722 LSM_HOOK_INIT(file_permission, selinux_file_permission), 6803 LSM_HOOK_INIT(file_permission, selinux_file_permission),
6723 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security), 6804 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
6724 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl), 6805 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),