diff options
-rw-r--r-- | security/selinux/hooks.c | 59 |
1 files changed, 47 insertions, 12 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b0e940497e23..6c90d491fab4 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -2097,6 +2097,41 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) | |||
2097 | 2097 | ||
2098 | /* binprm security operations */ | 2098 | /* binprm security operations */ |
2099 | 2099 | ||
2100 | static int check_nnp_nosuid(const struct linux_binprm *bprm, | ||
2101 | const struct task_security_struct *old_tsec, | ||
2102 | const struct task_security_struct *new_tsec) | ||
2103 | { | ||
2104 | int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS); | ||
2105 | int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID); | ||
2106 | int rc; | ||
2107 | |||
2108 | if (!nnp && !nosuid) | ||
2109 | return 0; /* neither NNP nor nosuid */ | ||
2110 | |||
2111 | if (new_tsec->sid == old_tsec->sid) | ||
2112 | return 0; /* No change in credentials */ | ||
2113 | |||
2114 | /* | ||
2115 | * The only transitions we permit under NNP or nosuid | ||
2116 | * are transitions to bounded SIDs, i.e. SIDs that are | ||
2117 | * guaranteed to only be allowed a subset of the permissions | ||
2118 | * of the current SID. | ||
2119 | */ | ||
2120 | rc = security_bounded_transition(old_tsec->sid, new_tsec->sid); | ||
2121 | if (rc) { | ||
2122 | /* | ||
2123 | * On failure, preserve the errno values for NNP vs nosuid. | ||
2124 | * NNP: Operation not permitted for caller. | ||
2125 | * nosuid: Permission denied to file. | ||
2126 | */ | ||
2127 | if (nnp) | ||
2128 | return -EPERM; | ||
2129 | else | ||
2130 | return -EACCES; | ||
2131 | } | ||
2132 | return 0; | ||
2133 | } | ||
2134 | |||
2100 | static int selinux_bprm_set_creds(struct linux_binprm *bprm) | 2135 | static int selinux_bprm_set_creds(struct linux_binprm *bprm) |
2101 | { | 2136 | { |
2102 | const struct task_security_struct *old_tsec; | 2137 | const struct task_security_struct *old_tsec; |
@@ -2133,14 +2168,10 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2133 | /* Reset exec SID on execve. */ | 2168 | /* Reset exec SID on execve. */ |
2134 | new_tsec->exec_sid = 0; | 2169 | new_tsec->exec_sid = 0; |
2135 | 2170 | ||
2136 | /* | 2171 | /* Fail on NNP or nosuid if not an allowed transition. */ |
2137 | * Minimize confusion: if no_new_privs or nosuid and a | 2172 | rc = check_nnp_nosuid(bprm, old_tsec, new_tsec); |
2138 | * transition is explicitly requested, then fail the exec. | 2173 | if (rc) |
2139 | */ | 2174 | return rc; |
2140 | if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) | ||
2141 | return -EPERM; | ||
2142 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) | ||
2143 | return -EACCES; | ||
2144 | } else { | 2175 | } else { |
2145 | /* Check for a default transition on this program. */ | 2176 | /* Check for a default transition on this program. */ |
2146 | rc = security_transition_sid(old_tsec->sid, isec->sid, | 2177 | rc = security_transition_sid(old_tsec->sid, isec->sid, |
@@ -2148,15 +2179,19 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2148 | &new_tsec->sid); | 2179 | &new_tsec->sid); |
2149 | if (rc) | 2180 | if (rc) |
2150 | return rc; | 2181 | return rc; |
2182 | |||
2183 | /* | ||
2184 | * Fallback to old SID on NNP or nosuid if not an allowed | ||
2185 | * transition. | ||
2186 | */ | ||
2187 | rc = check_nnp_nosuid(bprm, old_tsec, new_tsec); | ||
2188 | if (rc) | ||
2189 | new_tsec->sid = old_tsec->sid; | ||
2151 | } | 2190 | } |
2152 | 2191 | ||
2153 | ad.type = LSM_AUDIT_DATA_PATH; | 2192 | ad.type = LSM_AUDIT_DATA_PATH; |
2154 | ad.u.path = bprm->file->f_path; | 2193 | ad.u.path = bprm->file->f_path; |
2155 | 2194 | ||
2156 | if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) || | ||
2157 | (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)) | ||
2158 | new_tsec->sid = old_tsec->sid; | ||
2159 | |||
2160 | if (new_tsec->sid == old_tsec->sid) { | 2195 | if (new_tsec->sid == old_tsec->sid) { |
2161 | rc = avc_has_perm(old_tsec->sid, isec->sid, | 2196 | rc = avc_has_perm(old_tsec->sid, isec->sid, |
2162 | SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); | 2197 | SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); |