diff options
| -rw-r--r-- | security/smack/smack.h | 1 | ||||
| -rw-r--r-- | security/smack/smack_lsm.c | 44 |
2 files changed, 36 insertions, 9 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h index 4ede719922ed..cf2594dfa933 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
| @@ -66,6 +66,7 @@ struct task_smack { | |||
| 66 | 66 | ||
| 67 | #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ | 67 | #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ |
| 68 | #define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */ | 68 | #define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */ |
| 69 | #define SMK_INODE_CHANGED 0x04 /* smack was transmuted */ | ||
| 69 | 70 | ||
| 70 | /* | 71 | /* |
| 71 | * A label access rule. | 72 | * A label access rule. |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 45c32f074166..df45d3939188 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
| @@ -556,6 +556,7 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
| 556 | void **value, size_t *len) | 556 | void **value, size_t *len) |
| 557 | { | 557 | { |
| 558 | struct smack_known *skp; | 558 | struct smack_known *skp; |
| 559 | struct inode_smack *issp = inode->i_security; | ||
| 559 | char *csp = smk_of_current(); | 560 | char *csp = smk_of_current(); |
| 560 | char *isp = smk_of_inode(inode); | 561 | char *isp = smk_of_inode(inode); |
| 561 | char *dsp = smk_of_inode(dir); | 562 | char *dsp = smk_of_inode(dir); |
| @@ -577,10 +578,13 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
| 577 | * If the access rule allows transmutation and | 578 | * If the access rule allows transmutation and |
| 578 | * the directory requests transmutation then | 579 | * the directory requests transmutation then |
| 579 | * by all means transmute. | 580 | * by all means transmute. |
| 581 | * Mark the inode as changed. | ||
| 580 | */ | 582 | */ |
| 581 | if (may > 0 && ((may & MAY_TRANSMUTE) != 0) && | 583 | if (may > 0 && ((may & MAY_TRANSMUTE) != 0) && |
| 582 | smk_inode_transmutable(dir)) | 584 | smk_inode_transmutable(dir)) { |
| 583 | isp = dsp; | 585 | isp = dsp; |
| 586 | issp->smk_flags |= SMK_INODE_CHANGED; | ||
| 587 | } | ||
| 584 | 588 | ||
| 585 | *value = kstrdup(isp, GFP_KERNEL); | 589 | *value = kstrdup(isp, GFP_KERNEL); |
| 586 | if (*value == NULL) | 590 | if (*value == NULL) |
| @@ -2552,6 +2556,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
| 2552 | char *final; | 2556 | char *final; |
| 2553 | char trattr[TRANS_TRUE_SIZE]; | 2557 | char trattr[TRANS_TRUE_SIZE]; |
| 2554 | int transflag = 0; | 2558 | int transflag = 0; |
| 2559 | int rc; | ||
| 2555 | struct dentry *dp; | 2560 | struct dentry *dp; |
| 2556 | 2561 | ||
| 2557 | if (inode == NULL) | 2562 | if (inode == NULL) |
| @@ -2670,17 +2675,38 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
| 2670 | */ | 2675 | */ |
| 2671 | dp = dget(opt_dentry); | 2676 | dp = dget(opt_dentry); |
| 2672 | fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp); | 2677 | fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp); |
| 2673 | if (fetched != NULL) { | 2678 | if (fetched != NULL) |
| 2674 | final = fetched; | 2679 | final = fetched; |
| 2675 | if (S_ISDIR(inode->i_mode)) { | 2680 | |
| 2676 | trattr[0] = '\0'; | 2681 | /* |
| 2677 | inode->i_op->getxattr(dp, | 2682 | * Transmuting directory |
| 2683 | */ | ||
| 2684 | if (S_ISDIR(inode->i_mode)) { | ||
| 2685 | /* | ||
| 2686 | * If this is a new directory and the label was | ||
| 2687 | * transmuted when the inode was initialized | ||
| 2688 | * set the transmute attribute on the directory | ||
| 2689 | * and mark the inode. | ||
| 2690 | * | ||
| 2691 | * If there is a transmute attribute on the | ||
| 2692 | * directory mark the inode. | ||
| 2693 | */ | ||
| 2694 | if (isp->smk_flags & SMK_INODE_CHANGED) { | ||
| 2695 | isp->smk_flags &= ~SMK_INODE_CHANGED; | ||
| 2696 | rc = inode->i_op->setxattr(dp, | ||
| 2678 | XATTR_NAME_SMACKTRANSMUTE, | 2697 | XATTR_NAME_SMACKTRANSMUTE, |
| 2679 | trattr, TRANS_TRUE_SIZE); | 2698 | TRANS_TRUE, TRANS_TRUE_SIZE, |
| 2680 | if (strncmp(trattr, TRANS_TRUE, | 2699 | 0); |
| 2681 | TRANS_TRUE_SIZE) == 0) | 2700 | } else { |
| 2682 | transflag = SMK_INODE_TRANSMUTE; | 2701 | rc = inode->i_op->getxattr(dp, |
| 2702 | XATTR_NAME_SMACKTRANSMUTE, trattr, | ||
| 2703 | TRANS_TRUE_SIZE); | ||
| 2704 | if (rc >= 0 && strncmp(trattr, TRANS_TRUE, | ||
| 2705 | TRANS_TRUE_SIZE) != 0) | ||
| 2706 | rc = -EINVAL; | ||
| 2683 | } | 2707 | } |
| 2708 | if (rc >= 0) | ||
| 2709 | transflag = SMK_INODE_TRANSMUTE; | ||
| 2684 | } | 2710 | } |
| 2685 | isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); | 2711 | isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); |
| 2686 | isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp); | 2712 | isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp); |
