.. | .. |
---|
973 | 973 | const struct qstr *qstr, const char **name, |
---|
974 | 974 | void **value, size_t *len) |
---|
975 | 975 | { |
---|
| 976 | + struct task_smack *tsp = smack_cred(current_cred()); |
---|
976 | 977 | struct inode_smack *issp = smack_inode(inode); |
---|
977 | | - struct smack_known *skp = smk_of_current(); |
---|
| 978 | + struct smack_known *skp = smk_of_task(tsp); |
---|
978 | 979 | struct smack_known *isp = smk_of_inode(inode); |
---|
979 | 980 | struct smack_known *dsp = smk_of_inode(dir); |
---|
980 | 981 | int may; |
---|
.. | .. |
---|
983 | 984 | *name = XATTR_SMACK_SUFFIX; |
---|
984 | 985 | |
---|
985 | 986 | if (value && len) { |
---|
986 | | - rcu_read_lock(); |
---|
987 | | - may = smk_access_entry(skp->smk_known, dsp->smk_known, |
---|
988 | | - &skp->smk_rules); |
---|
989 | | - rcu_read_unlock(); |
---|
| 987 | + /* |
---|
| 988 | + * If equal, transmuting already occurred in |
---|
| 989 | + * smack_dentry_create_files_as(). No need to check again. |
---|
| 990 | + */ |
---|
| 991 | + if (tsp->smk_task != tsp->smk_transmuted) { |
---|
| 992 | + rcu_read_lock(); |
---|
| 993 | + may = smk_access_entry(skp->smk_known, dsp->smk_known, |
---|
| 994 | + &skp->smk_rules); |
---|
| 995 | + rcu_read_unlock(); |
---|
| 996 | + } |
---|
990 | 997 | |
---|
991 | 998 | /* |
---|
992 | | - * If the access rule allows transmutation and |
---|
993 | | - * the directory requests transmutation then |
---|
994 | | - * by all means transmute. |
---|
| 999 | + * In addition to having smk_task equal to smk_transmuted, |
---|
| 1000 | + * if the access rule allows transmutation and the directory |
---|
| 1001 | + * requests transmutation then by all means transmute. |
---|
995 | 1002 | * Mark the inode as changed. |
---|
996 | 1003 | */ |
---|
997 | | - if (may > 0 && ((may & MAY_TRANSMUTE) != 0) && |
---|
998 | | - smk_inode_transmutable(dir)) { |
---|
999 | | - isp = dsp; |
---|
| 1004 | + if ((tsp->smk_task == tsp->smk_transmuted) || |
---|
| 1005 | + (may > 0 && ((may & MAY_TRANSMUTE) != 0) && |
---|
| 1006 | + smk_inode_transmutable(dir))) { |
---|
| 1007 | + /* |
---|
| 1008 | + * The caller of smack_dentry_create_files_as() |
---|
| 1009 | + * should have overridden the current cred, so the |
---|
| 1010 | + * inode label was already set correctly in |
---|
| 1011 | + * smack_inode_alloc_security(). |
---|
| 1012 | + */ |
---|
| 1013 | + if (tsp->smk_task != tsp->smk_transmuted) |
---|
| 1014 | + isp = dsp; |
---|
1000 | 1015 | issp->smk_flags |= SMK_INODE_CHANGED; |
---|
1001 | 1016 | } |
---|
1002 | 1017 | |
---|
.. | .. |
---|
1430 | 1445 | struct super_block *sbp; |
---|
1431 | 1446 | struct inode *ip = (struct inode *)inode; |
---|
1432 | 1447 | struct smack_known *isp; |
---|
| 1448 | + struct inode_smack *ispp; |
---|
| 1449 | + size_t label_len; |
---|
| 1450 | + char *label = NULL; |
---|
1433 | 1451 | |
---|
1434 | | - if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) |
---|
| 1452 | + if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { |
---|
1435 | 1453 | isp = smk_of_inode(inode); |
---|
1436 | | - else { |
---|
| 1454 | + } else if (strcmp(name, XATTR_SMACK_TRANSMUTE) == 0) { |
---|
| 1455 | + ispp = smack_inode(inode); |
---|
| 1456 | + if (ispp->smk_flags & SMK_INODE_TRANSMUTE) |
---|
| 1457 | + label = TRANS_TRUE; |
---|
| 1458 | + else |
---|
| 1459 | + label = ""; |
---|
| 1460 | + } else { |
---|
1437 | 1461 | /* |
---|
1438 | 1462 | * The rest of the Smack xattrs are only on sockets. |
---|
1439 | 1463 | */ |
---|
.. | .. |
---|
1455 | 1479 | return -EOPNOTSUPP; |
---|
1456 | 1480 | } |
---|
1457 | 1481 | |
---|
| 1482 | + if (!label) |
---|
| 1483 | + label = isp->smk_known; |
---|
| 1484 | + |
---|
| 1485 | + label_len = strlen(label); |
---|
| 1486 | + |
---|
1458 | 1487 | if (alloc) { |
---|
1459 | | - *buffer = kstrdup(isp->smk_known, GFP_KERNEL); |
---|
| 1488 | + *buffer = kstrdup(label, GFP_KERNEL); |
---|
1460 | 1489 | if (*buffer == NULL) |
---|
1461 | 1490 | return -ENOMEM; |
---|
1462 | 1491 | } |
---|
1463 | 1492 | |
---|
1464 | | - return strlen(isp->smk_known); |
---|
| 1493 | + return label_len; |
---|
1465 | 1494 | } |
---|
1466 | 1495 | |
---|
1467 | 1496 | |
---|
.. | .. |
---|
4635 | 4664 | /* |
---|
4636 | 4665 | * Get label from overlay inode and set it in create_sid |
---|
4637 | 4666 | */ |
---|
4638 | | - isp = smack_inode(d_inode(dentry->d_parent)); |
---|
| 4667 | + isp = smack_inode(d_inode(dentry)); |
---|
4639 | 4668 | skp = isp->smk_inode; |
---|
4640 | 4669 | tsp->smk_task = skp; |
---|
4641 | 4670 | *new = new_creds; |
---|
.. | .. |
---|
4686 | 4715 | * providing access is transmuting use the containing |
---|
4687 | 4716 | * directory label instead of the process label. |
---|
4688 | 4717 | */ |
---|
4689 | | - if (may > 0 && (may & MAY_TRANSMUTE)) |
---|
| 4718 | + if (may > 0 && (may & MAY_TRANSMUTE)) { |
---|
4690 | 4719 | ntsp->smk_task = isp->smk_inode; |
---|
| 4720 | + ntsp->smk_transmuted = ntsp->smk_task; |
---|
| 4721 | + } |
---|
4691 | 4722 | } |
---|
4692 | 4723 | return 0; |
---|
4693 | 4724 | } |
---|