aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-05-07 21:48:09 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-05-07 21:48:09 -0400
commitf72dae20891d7bcc43e9263ab206960b6ae5209f (patch)
tree59a5b8c026adad15855d3824d1a7014468033274 /security/selinux/hooks.c
parent498e8631f27ed649bd3e31998a00b2b9b288cf3a (diff)
parent35a196bef449b5824033865b963ed9a43fb8c730 (diff)
Merge tag 'selinux-pr-20190507' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux
Pull selinux updates from Paul Moore: "We've got a few SELinux patches for the v5.2 merge window, the highlights are below: - Add LSM hooks, and the SELinux implementation, for proper labeling of kernfs. While we are only including the SELinux implementation here, the rest of the LSM folks have given the hooks a thumbs-up. - Update the SELinux mdp (Make Dummy Policy) script to actually work on a modern system. - Disallow userspace to change the LSM credentials via /proc/self/attr when the task's credentials are already overridden. The change was made in procfs because all the LSM folks agreed this was the Right Thing To Do and duplicating it across each LSM was going to be annoying" * tag 'selinux-pr-20190507' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: proc: prevent changes to overridden credentials selinux: Check address length before reading address family kernfs: fix xattr name handling in LSM helpers MAINTAINERS: update SELinux file patterns selinux: avoid uninitialized variable warning selinux: remove useless assignments LSM: lsm_hooks.h - fix missing colon in docstring selinux: Make selinux_kernfs_init_security static kernfs: initialize security of newly created nodes selinux: implement the kernfs_init_security hook LSM: add new hook for kernfs node initialization kernfs: use simple_xattrs for security attributes selinux: try security xattr after genfs for kernfs filesystems kernfs: do not alloc iattrs in kernfs_xattr_get kernfs: clean up struct kernfs_iattrs scripts/selinux: fix build selinux: use kernel linux/socket.h for genheaders and mdp scripts/selinux: modernize mdp
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),