Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

selinux: fix avdcache auditing

The per-task avdcache was incorrectly saving and reusing the
audited vector computed by avc_audit_required() rather than
recomputing based on the currently requested permissions and
distinguishing the denied versus allowed cases. As a result,
some permission checks were not being audited, e.g.
directory write checks after a previously cached directory
search check.

Cc: stable@vger.kernel.org
Fixes: dde3a5d0f4dce ("selinux: move avdcache to per-task security struct")
Signed-off-by: Stephen Smalley <stephen.smalley.work@gmail.com>
[PM: line wrap tweaks]
Signed-off-by: Paul Moore <paul@paul-moore.com>

authored by

Stephen Smalley and committed by
Paul Moore
f92d5425 1e5a8eed

+14 -21
+13 -18
security/selinux/hooks.c
··· 3209 3209 * @tsec: the task's security state 3210 3210 * @isec: the inode associated with the cache entry 3211 3211 * @avd: the AVD to cache 3212 - * @audited: the permission audit bitmask to cache 3213 3212 * 3214 - * Update the AVD cache in @tsec with the @avdc and @audited info associated 3213 + * Update the AVD cache in @tsec with the @avd info associated 3215 3214 * with @isec. 3216 3215 */ 3217 3216 static inline void task_avdcache_update(struct task_security_struct *tsec, 3218 3217 struct inode_security_struct *isec, 3219 - struct av_decision *avd, 3220 - u32 audited) 3218 + struct av_decision *avd) 3221 3219 { 3222 3220 int spot; 3223 3221 ··· 3227 3229 spot = (tsec->avdcache.dir_spot + 1) & (TSEC_AVDC_DIR_SIZE - 1); 3228 3230 tsec->avdcache.dir_spot = spot; 3229 3231 tsec->avdcache.dir[spot].isid = isec->sid; 3230 - tsec->avdcache.dir[spot].audited = audited; 3231 - tsec->avdcache.dir[spot].allowed = avd->allowed; 3232 - tsec->avdcache.dir[spot].permissive = avd->flags & AVD_FLAGS_PERMISSIVE; 3232 + tsec->avdcache.dir[spot].avd = *avd; 3233 3233 tsec->avdcache.permissive_neveraudit = 3234 3234 (avd->flags == (AVD_FLAGS_PERMISSIVE|AVD_FLAGS_NEVERAUDIT)); 3235 3235 } ··· 3248 3252 struct task_security_struct *tsec; 3249 3253 struct inode_security_struct *isec; 3250 3254 struct avdc_entry *avdc; 3255 + struct av_decision avd, *avdp = &avd; 3251 3256 int rc, rc2; 3252 3257 u32 audited, denied; 3253 3258 ··· 3270 3273 rc = task_avdcache_search(tsec, isec, &avdc); 3271 3274 if (likely(!rc)) { 3272 3275 /* Cache hit. */ 3273 - audited = perms & avdc->audited; 3274 - denied = perms & ~avdc->allowed; 3275 - if (unlikely(denied && enforcing_enabled() && 3276 - !avdc->permissive)) 3276 + avdp = &avdc->avd; 3277 + denied = perms & ~avdp->allowed; 3278 + if (unlikely(denied) && enforcing_enabled() && 3279 + !(avdp->flags & AVD_FLAGS_PERMISSIVE)) 3277 3280 rc = -EACCES; 3278 3281 } else { 3279 - struct av_decision avd; 3280 - 3281 3282 /* Cache miss. */ 3282 3283 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, 3283 - perms, 0, &avd); 3284 - audited = avc_audit_required(perms, &avd, rc, 3285 - (requested & MAY_ACCESS) ? FILE__AUDIT_ACCESS : 0, 3286 - &denied); 3287 - task_avdcache_update(tsec, isec, &avd, audited); 3284 + perms, 0, avdp); 3285 + task_avdcache_update(tsec, isec, avdp); 3288 3286 } 3289 3287 3288 + audited = avc_audit_required(perms, avdp, rc, 3289 + (requested & MAY_ACCESS) ? 3290 + FILE__AUDIT_ACCESS : 0, &denied); 3290 3291 if (likely(!audited)) 3291 3292 return rc; 3292 3293
+1 -3
security/selinux/include/objsec.h
··· 32 32 33 33 struct avdc_entry { 34 34 u32 isid; /* inode SID */ 35 - u32 allowed; /* allowed permission bitmask */ 36 - u32 audited; /* audited permission bitmask */ 37 - bool permissive; /* AVC permissive flag */ 35 + struct av_decision avd; /* av decision */ 38 36 }; 39 37 40 38 struct cred_security_struct {