diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-14 16:57:44 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-14 16:57:44 -0500 |
commit | 683b96f4d1d132fcefa4a0bd11916649800d7361 (patch) | |
tree | 95ba7e1c1edc15639be080773b4c32d2be60b0a4 /security/selinux/hooks.c | |
parent | 0f1d6dfe03ca4e36132221b918499c6f0b0f048d (diff) | |
parent | 50523a29d900d5a403e0352d3d7aeda6a33df25c (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris:
"Generally pretty quiet for this release. Highlights:
Yama:
- allow ptrace access for original parent after re-parenting
TPM:
- add documentation
- many bugfixes & cleanups
- define a generic open() method for ascii & bios measurements
Integrity:
- Harden against malformed xattrs
SELinux:
- bugfixes & cleanups
Smack:
- Remove unnecessary smack_known_invalid label
- Do not apply star label in smack_setprocattr hook
- parse mnt opts after privileges check (fixes unpriv DoS vuln)"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (56 commits)
Yama: allow access for the current ptrace parent
tpm: adjust return value of tpm_read_log
tpm: vtpm_proxy: conditionally call tpm_chip_unregister
tpm: Fix handling of missing event log
tpm: Check the bios_dir entry for NULL before accessing it
tpm: return -ENODEV if np is not set
tpm: cleanup of printk error messages
tpm: replace of_find_node_by_name() with dev of_node property
tpm: redefine read_log() to handle ACPI/OF at runtime
tpm: fix the missing .owner in tpm_bios_measurements_ops
tpm: have event log use the tpm_chip
tpm: drop tpm1_chip_register(/unregister)
tpm: replace dynamically allocated bios_dir with a static array
tpm: replace symbolic permission with octal for securityfs files
char: tpm: fix kerneldoc tpm2_unseal_trusted name typo
tpm_tis: Allow tpm_tis to be bound using DT
tpm, tpm_vtpm_proxy: add kdoc comments for VTPM_PROXY_IOC_NEW_DEV
tpm: Only call pm_runtime_get_sync if device has a parent
tpm: define a generic open() method for ascii & bios measurements
Documentation: tpm: add the Physical TPM device tree binding documentation
...
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 120 |
1 files changed, 73 insertions, 47 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 38b79d797aaf..c7c6619431d5 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -231,12 +231,13 @@ static int inode_alloc_security(struct inode *inode) | |||
231 | if (!isec) | 231 | if (!isec) |
232 | return -ENOMEM; | 232 | return -ENOMEM; |
233 | 233 | ||
234 | mutex_init(&isec->lock); | 234 | spin_lock_init(&isec->lock); |
235 | INIT_LIST_HEAD(&isec->list); | 235 | INIT_LIST_HEAD(&isec->list); |
236 | isec->inode = inode; | 236 | isec->inode = inode; |
237 | isec->sid = SECINITSID_UNLABELED; | 237 | isec->sid = SECINITSID_UNLABELED; |
238 | isec->sclass = SECCLASS_FILE; | 238 | isec->sclass = SECCLASS_FILE; |
239 | isec->task_sid = sid; | 239 | isec->task_sid = sid; |
240 | isec->initialized = LABEL_INVALID; | ||
240 | inode->i_security = isec; | 241 | inode->i_security = isec; |
241 | 242 | ||
242 | return 0; | 243 | return 0; |
@@ -247,7 +248,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
247 | /* | 248 | /* |
248 | * Try reloading inode security labels that have been marked as invalid. The | 249 | * Try reloading inode security labels that have been marked as invalid. The |
249 | * @may_sleep parameter indicates when sleeping and thus reloading labels is | 250 | * @may_sleep parameter indicates when sleeping and thus reloading labels is |
250 | * allowed; when set to false, returns ERR_PTR(-ECHILD) when the label is | 251 | * allowed; when set to false, returns -ECHILD when the label is |
251 | * invalid. The @opt_dentry parameter should be set to a dentry of the inode; | 252 | * invalid. The @opt_dentry parameter should be set to a dentry of the inode; |
252 | * when no dentry is available, set it to NULL instead. | 253 | * when no dentry is available, set it to NULL instead. |
253 | */ | 254 | */ |
@@ -1100,11 +1101,12 @@ static int selinux_parse_opts_str(char *options, | |||
1100 | } | 1101 | } |
1101 | 1102 | ||
1102 | rc = -ENOMEM; | 1103 | rc = -ENOMEM; |
1103 | opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC); | 1104 | opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_KERNEL); |
1104 | if (!opts->mnt_opts) | 1105 | if (!opts->mnt_opts) |
1105 | goto out_err; | 1106 | goto out_err; |
1106 | 1107 | ||
1107 | opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC); | 1108 | opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), |
1109 | GFP_KERNEL); | ||
1108 | if (!opts->mnt_opts_flags) { | 1110 | if (!opts->mnt_opts_flags) { |
1109 | kfree(opts->mnt_opts); | 1111 | kfree(opts->mnt_opts); |
1110 | goto out_err; | 1112 | goto out_err; |
@@ -1380,7 +1382,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1380 | { | 1382 | { |
1381 | struct superblock_security_struct *sbsec = NULL; | 1383 | struct superblock_security_struct *sbsec = NULL; |
1382 | struct inode_security_struct *isec = inode->i_security; | 1384 | struct inode_security_struct *isec = inode->i_security; |
1383 | u32 sid; | 1385 | u32 task_sid, sid = 0; |
1386 | u16 sclass; | ||
1384 | struct dentry *dentry; | 1387 | struct dentry *dentry; |
1385 | #define INITCONTEXTLEN 255 | 1388 | #define INITCONTEXTLEN 255 |
1386 | char *context = NULL; | 1389 | char *context = NULL; |
@@ -1388,12 +1391,15 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1388 | int rc = 0; | 1391 | int rc = 0; |
1389 | 1392 | ||
1390 | if (isec->initialized == LABEL_INITIALIZED) | 1393 | if (isec->initialized == LABEL_INITIALIZED) |
1391 | goto out; | 1394 | return 0; |
1392 | 1395 | ||
1393 | mutex_lock(&isec->lock); | 1396 | spin_lock(&isec->lock); |
1394 | if (isec->initialized == LABEL_INITIALIZED) | 1397 | if (isec->initialized == LABEL_INITIALIZED) |
1395 | goto out_unlock; | 1398 | goto out_unlock; |
1396 | 1399 | ||
1400 | if (isec->sclass == SECCLASS_FILE) | ||
1401 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | ||
1402 | |||
1397 | sbsec = inode->i_sb->s_security; | 1403 | sbsec = inode->i_sb->s_security; |
1398 | if (!(sbsec->flags & SE_SBINITIALIZED)) { | 1404 | if (!(sbsec->flags & SE_SBINITIALIZED)) { |
1399 | /* Defer initialization until selinux_complete_init, | 1405 | /* Defer initialization until selinux_complete_init, |
@@ -1406,12 +1412,18 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1406 | goto out_unlock; | 1412 | goto out_unlock; |
1407 | } | 1413 | } |
1408 | 1414 | ||
1415 | sclass = isec->sclass; | ||
1416 | task_sid = isec->task_sid; | ||
1417 | sid = isec->sid; | ||
1418 | isec->initialized = LABEL_PENDING; | ||
1419 | spin_unlock(&isec->lock); | ||
1420 | |||
1409 | switch (sbsec->behavior) { | 1421 | switch (sbsec->behavior) { |
1410 | case SECURITY_FS_USE_NATIVE: | 1422 | case SECURITY_FS_USE_NATIVE: |
1411 | break; | 1423 | break; |
1412 | case SECURITY_FS_USE_XATTR: | 1424 | case SECURITY_FS_USE_XATTR: |
1413 | if (!(inode->i_opflags & IOP_XATTR)) { | 1425 | if (!(inode->i_opflags & IOP_XATTR)) { |
1414 | isec->sid = sbsec->def_sid; | 1426 | sid = sbsec->def_sid; |
1415 | break; | 1427 | break; |
1416 | } | 1428 | } |
1417 | /* Need a dentry, since the xattr API requires one. | 1429 | /* Need a dentry, since the xattr API requires one. |
@@ -1433,7 +1445,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1433 | * inode_doinit with a dentry, before these inodes could | 1445 | * inode_doinit with a dentry, before these inodes could |
1434 | * be used again by userspace. | 1446 | * be used again by userspace. |
1435 | */ | 1447 | */ |
1436 | goto out_unlock; | 1448 | goto out; |
1437 | } | 1449 | } |
1438 | 1450 | ||
1439 | len = INITCONTEXTLEN; | 1451 | len = INITCONTEXTLEN; |
@@ -1441,7 +1453,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1441 | if (!context) { | 1453 | if (!context) { |
1442 | rc = -ENOMEM; | 1454 | rc = -ENOMEM; |
1443 | dput(dentry); | 1455 | dput(dentry); |
1444 | goto out_unlock; | 1456 | goto out; |
1445 | } | 1457 | } |
1446 | context[len] = '\0'; | 1458 | context[len] = '\0'; |
1447 | rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len); | 1459 | rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len); |
@@ -1452,14 +1464,14 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1452 | rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0); | 1464 | rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0); |
1453 | if (rc < 0) { | 1465 | if (rc < 0) { |
1454 | dput(dentry); | 1466 | dput(dentry); |
1455 | goto out_unlock; | 1467 | goto out; |
1456 | } | 1468 | } |
1457 | len = rc; | 1469 | len = rc; |
1458 | context = kmalloc(len+1, GFP_NOFS); | 1470 | context = kmalloc(len+1, GFP_NOFS); |
1459 | if (!context) { | 1471 | if (!context) { |
1460 | rc = -ENOMEM; | 1472 | rc = -ENOMEM; |
1461 | dput(dentry); | 1473 | dput(dentry); |
1462 | goto out_unlock; | 1474 | goto out; |
1463 | } | 1475 | } |
1464 | context[len] = '\0'; | 1476 | context[len] = '\0'; |
1465 | rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len); | 1477 | rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len); |
@@ -1471,7 +1483,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1471 | "%d for dev=%s ino=%ld\n", __func__, | 1483 | "%d for dev=%s ino=%ld\n", __func__, |
1472 | -rc, inode->i_sb->s_id, inode->i_ino); | 1484 | -rc, inode->i_sb->s_id, inode->i_ino); |
1473 | kfree(context); | 1485 | kfree(context); |
1474 | goto out_unlock; | 1486 | goto out; |
1475 | } | 1487 | } |
1476 | /* Map ENODATA to the default file SID */ | 1488 | /* Map ENODATA to the default file SID */ |
1477 | sid = sbsec->def_sid; | 1489 | sid = sbsec->def_sid; |
@@ -1501,29 +1513,25 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1501 | } | 1513 | } |
1502 | } | 1514 | } |
1503 | kfree(context); | 1515 | kfree(context); |
1504 | isec->sid = sid; | ||
1505 | break; | 1516 | break; |
1506 | case SECURITY_FS_USE_TASK: | 1517 | case SECURITY_FS_USE_TASK: |
1507 | isec->sid = isec->task_sid; | 1518 | sid = task_sid; |
1508 | break; | 1519 | break; |
1509 | case SECURITY_FS_USE_TRANS: | 1520 | case SECURITY_FS_USE_TRANS: |
1510 | /* Default to the fs SID. */ | 1521 | /* Default to the fs SID. */ |
1511 | isec->sid = sbsec->sid; | 1522 | sid = sbsec->sid; |
1512 | 1523 | ||
1513 | /* Try to obtain a transition SID. */ | 1524 | /* Try to obtain a transition SID. */ |
1514 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | 1525 | rc = security_transition_sid(task_sid, sid, sclass, NULL, &sid); |
1515 | rc = security_transition_sid(isec->task_sid, sbsec->sid, | ||
1516 | isec->sclass, NULL, &sid); | ||
1517 | if (rc) | 1526 | if (rc) |
1518 | goto out_unlock; | 1527 | goto out; |
1519 | isec->sid = sid; | ||
1520 | break; | 1528 | break; |
1521 | case SECURITY_FS_USE_MNTPOINT: | 1529 | case SECURITY_FS_USE_MNTPOINT: |
1522 | isec->sid = sbsec->mntpoint_sid; | 1530 | sid = sbsec->mntpoint_sid; |
1523 | break; | 1531 | break; |
1524 | default: | 1532 | default: |
1525 | /* Default to the fs superblock SID. */ | 1533 | /* Default to the fs superblock SID. */ |
1526 | isec->sid = sbsec->sid; | 1534 | sid = sbsec->sid; |
1527 | 1535 | ||
1528 | if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) { | 1536 | if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) { |
1529 | /* We must have a dentry to determine the label on | 1537 | /* We must have a dentry to determine the label on |
@@ -1546,25 +1554,30 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1546 | * could be used again by userspace. | 1554 | * could be used again by userspace. |
1547 | */ | 1555 | */ |
1548 | if (!dentry) | 1556 | if (!dentry) |
1549 | goto out_unlock; | 1557 | goto out; |
1550 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | 1558 | rc = selinux_genfs_get_sid(dentry, sclass, |
1551 | rc = selinux_genfs_get_sid(dentry, isec->sclass, | ||
1552 | sbsec->flags, &sid); | 1559 | sbsec->flags, &sid); |
1553 | dput(dentry); | 1560 | dput(dentry); |
1554 | if (rc) | 1561 | if (rc) |
1555 | goto out_unlock; | 1562 | goto out; |
1556 | isec->sid = sid; | ||
1557 | } | 1563 | } |
1558 | break; | 1564 | break; |
1559 | } | 1565 | } |
1560 | 1566 | ||
1561 | isec->initialized = LABEL_INITIALIZED; | 1567 | out: |
1568 | spin_lock(&isec->lock); | ||
1569 | if (isec->initialized == LABEL_PENDING) { | ||
1570 | if (!sid || rc) { | ||
1571 | isec->initialized = LABEL_INVALID; | ||
1572 | goto out_unlock; | ||
1573 | } | ||
1574 | |||
1575 | isec->initialized = LABEL_INITIALIZED; | ||
1576 | isec->sid = sid; | ||
1577 | } | ||
1562 | 1578 | ||
1563 | out_unlock: | 1579 | out_unlock: |
1564 | mutex_unlock(&isec->lock); | 1580 | spin_unlock(&isec->lock); |
1565 | out: | ||
1566 | if (isec->sclass == SECCLASS_FILE) | ||
1567 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | ||
1568 | return rc; | 1581 | return rc; |
1569 | } | 1582 | } |
1570 | 1583 | ||
@@ -3198,9 +3211,11 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
3198 | } | 3211 | } |
3199 | 3212 | ||
3200 | isec = backing_inode_security(dentry); | 3213 | isec = backing_inode_security(dentry); |
3214 | spin_lock(&isec->lock); | ||
3201 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | 3215 | isec->sclass = inode_mode_to_security_class(inode->i_mode); |
3202 | isec->sid = newsid; | 3216 | isec->sid = newsid; |
3203 | isec->initialized = LABEL_INITIALIZED; | 3217 | isec->initialized = LABEL_INITIALIZED; |
3218 | spin_unlock(&isec->lock); | ||
3204 | 3219 | ||
3205 | return; | 3220 | return; |
3206 | } | 3221 | } |
@@ -3293,9 +3308,11 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, | |||
3293 | if (rc) | 3308 | if (rc) |
3294 | return rc; | 3309 | return rc; |
3295 | 3310 | ||
3311 | spin_lock(&isec->lock); | ||
3296 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | 3312 | isec->sclass = inode_mode_to_security_class(inode->i_mode); |
3297 | isec->sid = newsid; | 3313 | isec->sid = newsid; |
3298 | isec->initialized = LABEL_INITIALIZED; | 3314 | isec->initialized = LABEL_INITIALIZED; |
3315 | spin_unlock(&isec->lock); | ||
3299 | return 0; | 3316 | return 0; |
3300 | } | 3317 | } |
3301 | 3318 | ||
@@ -3956,8 +3973,11 @@ static void selinux_task_to_inode(struct task_struct *p, | |||
3956 | struct inode_security_struct *isec = inode->i_security; | 3973 | struct inode_security_struct *isec = inode->i_security; |
3957 | u32 sid = task_sid(p); | 3974 | u32 sid = task_sid(p); |
3958 | 3975 | ||
3976 | spin_lock(&isec->lock); | ||
3977 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | ||
3959 | isec->sid = sid; | 3978 | isec->sid = sid; |
3960 | isec->initialized = LABEL_INITIALIZED; | 3979 | isec->initialized = LABEL_INITIALIZED; |
3980 | spin_unlock(&isec->lock); | ||
3961 | } | 3981 | } |
3962 | 3982 | ||
3963 | /* Returns error only if unable to parse addresses */ | 3983 | /* Returns error only if unable to parse addresses */ |
@@ -4276,24 +4296,24 @@ static int selinux_socket_post_create(struct socket *sock, int family, | |||
4276 | const struct task_security_struct *tsec = current_security(); | 4296 | const struct task_security_struct *tsec = current_security(); |
4277 | struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock)); | 4297 | struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock)); |
4278 | struct sk_security_struct *sksec; | 4298 | struct sk_security_struct *sksec; |
4299 | u16 sclass = socket_type_to_security_class(family, type, protocol); | ||
4300 | u32 sid = SECINITSID_KERNEL; | ||
4279 | int err = 0; | 4301 | int err = 0; |
4280 | 4302 | ||
4281 | isec->sclass = socket_type_to_security_class(family, type, protocol); | 4303 | if (!kern) { |
4282 | 4304 | err = socket_sockcreate_sid(tsec, sclass, &sid); | |
4283 | if (kern) | ||
4284 | isec->sid = SECINITSID_KERNEL; | ||
4285 | else { | ||
4286 | err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid)); | ||
4287 | if (err) | 4305 | if (err) |
4288 | return err; | 4306 | return err; |
4289 | } | 4307 | } |
4290 | 4308 | ||
4309 | isec->sclass = sclass; | ||
4310 | isec->sid = sid; | ||
4291 | isec->initialized = LABEL_INITIALIZED; | 4311 | isec->initialized = LABEL_INITIALIZED; |
4292 | 4312 | ||
4293 | if (sock->sk) { | 4313 | if (sock->sk) { |
4294 | sksec = sock->sk->sk_security; | 4314 | sksec = sock->sk->sk_security; |
4295 | sksec->sid = isec->sid; | 4315 | sksec->sclass = sclass; |
4296 | sksec->sclass = isec->sclass; | 4316 | sksec->sid = sid; |
4297 | err = selinux_netlbl_socket_post_create(sock->sk, family); | 4317 | err = selinux_netlbl_socket_post_create(sock->sk, family); |
4298 | } | 4318 | } |
4299 | 4319 | ||
@@ -4469,16 +4489,22 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
4469 | int err; | 4489 | int err; |
4470 | struct inode_security_struct *isec; | 4490 | struct inode_security_struct *isec; |
4471 | struct inode_security_struct *newisec; | 4491 | struct inode_security_struct *newisec; |
4492 | u16 sclass; | ||
4493 | u32 sid; | ||
4472 | 4494 | ||
4473 | err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT); | 4495 | err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT); |
4474 | if (err) | 4496 | if (err) |
4475 | return err; | 4497 | return err; |
4476 | 4498 | ||
4477 | newisec = inode_security_novalidate(SOCK_INODE(newsock)); | ||
4478 | |||
4479 | isec = inode_security_novalidate(SOCK_INODE(sock)); | 4499 | isec = inode_security_novalidate(SOCK_INODE(sock)); |
4480 | newisec->sclass = isec->sclass; | 4500 | spin_lock(&isec->lock); |
4481 | newisec->sid = isec->sid; | 4501 | sclass = isec->sclass; |
4502 | sid = isec->sid; | ||
4503 | spin_unlock(&isec->lock); | ||
4504 | |||
4505 | newisec = inode_security_novalidate(SOCK_INODE(newsock)); | ||
4506 | newisec->sclass = sclass; | ||
4507 | newisec->sid = sid; | ||
4482 | newisec->initialized = LABEL_INITIALIZED; | 4508 | newisec->initialized = LABEL_INITIALIZED; |
4483 | 4509 | ||
4484 | return 0; | 4510 | return 0; |
@@ -5981,9 +6007,9 @@ static void selinux_inode_invalidate_secctx(struct inode *inode) | |||
5981 | { | 6007 | { |
5982 | struct inode_security_struct *isec = inode->i_security; | 6008 | struct inode_security_struct *isec = inode->i_security; |
5983 | 6009 | ||
5984 | mutex_lock(&isec->lock); | 6010 | spin_lock(&isec->lock); |
5985 | isec->initialized = LABEL_INVALID; | 6011 | isec->initialized = LABEL_INVALID; |
5986 | mutex_unlock(&isec->lock); | 6012 | spin_unlock(&isec->lock); |
5987 | } | 6013 | } |
5988 | 6014 | ||
5989 | /* | 6015 | /* |