Bug 472325 (CVE-2008-5182) - CVE-2008-5182 kernel: fix inotify watch removal/umount races
Summary: CVE-2008-5182 kernel: fix inotify watch removal/umount races
Keywords:
Status: CLOSED ERRATA
Alias: CVE-2008-5182
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
high
high
Target Milestone: ---
Assignee: Red Hat Product Security
QA Contact:
URL:
Whiteboard:
Depends On: 472327 472328 472329
Blocks:
TreeView+ depends on / blocked
 
Reported: 2008-11-20 03:29 UTC by Eugene Teo (Security Response)
Modified: 2019-09-29 12:27 UTC (History)
13 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2010-12-21 17:53:01 UTC
Embargoed:


Attachments (Terms of Use)
Proposed patch for real-time kernel (15.85 KB, patch)
2008-11-27 08:19 UTC, Eugene Teo (Security Response)
no flags Details | Diff


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHSA-2009:0021 0 normal SHIPPED_LIVE Important: kernel security update 2009-02-25 01:04:12 UTC
Red Hat Product Errata RHSA-2009:0053 0 normal SHIPPED_LIVE Important: kernel-rt security and bug fix update 2009-02-04 15:05:12 UTC
Red Hat Product Errata RHSA-2009:0225 0 normal SHIPPED_LIVE Important: Red Hat Enterprise Linux 5.3 kernel security and bug fix update 2009-01-20 16:06:24 UTC

Description Eugene Teo (Security Response) 2008-11-20 03:29:21 UTC
From: Al Viro <viro.org.uk>

Inotify watch removals suck violently.

To kick the watch out we need (in this order) inode->inotify_mutex and ih->mutex.  That's fine if we have a hold on inode; however, for all other cases we need to make damn sure we don't race with umount.  We can *NOT* just grab a reference to a watch - inotify_unmount_inodes() will happily sail past it and we'll end with reference to inode potentially outliving its superblock.

Ideally we just want to grab an active reference to superblock if we can; that will make sure we won't go into inotify_umount_inodes() until we are done.  Cleanup is just deactivate_super().

However, that leaves a messy case - what if we *are* racing with umount() and active references to superblock can't be acquired anymore? We can bump ->s_count, grab ->s_umount, which will almost certainly wait until the superblock is shut down and the watch in question is pining for fjords.  That's fine, but there is a problem - we might have hit the window between ->s_active getting to 0 / ->s_count - below S_BIAS (i.e. the moment when superblock is past the point of no return and is heading for shutdown) and the moment when deactivate_super() acquires ->s_umount.

We could just do drop_super() yield() and retry, but that's rather antisocial and this stuff is luser-triggerable.  OTOH, having grabbed ->s_umount and having found that we'd got there first (i.e.  that ->s_root is non-NULL) we know that we won't race with inotify_umount_inodes().

So we could grab a reference to watch and do the rest as above, just with drop_super() instead of deactivate_super(), right? Wrong.  We had to drop ih->mutex before we could grab ->s_umount.  So the watch could've been gone already.

That still can be dealt with - we need to save watch->wd, do idr_find() and compare its result with our pointer.  If they match, we either have the damn thing still alive or we'd lost not one but two races at once, the watch had been killed and a new one got created with the same ->wd at the same address.  That couldn't have happened in inotify_destroy(), but inotify_rm_wd() could run into that.  Still, "new one got created" is not a problem - we have every right to kill it or leave it alone, whatever's more convenient.

So we can use idr_find(...) == watch && watch->inode->i_sb == sb as "grab it and kill it" check.  If it's been our original watch, we are fine, if it's a newcomer - nevermind, just pretend that we'd won the race and kill the fscker anyway; we are safe since we know that its superblock won't be going away.

And yes, this is far beyond mere "not very pretty"; so's the entire concept of inotify to start with.

Comment 5 Eugene Teo (Security Response) 2008-11-27 08:19:12 UTC
Created attachment 324842 [details]
Proposed patch for real-time kernel

Luis, kindly review. Only boot tested. Thanks.

Comment 6 Fedora Update System 2008-12-17 16:21:13 UTC
kernel-2.6.27.9-159.fc10 has been submitted as an update for Fedora 10.
http://admin.fedoraproject.org/updates/kernel-2.6.27.9-159.fc10

Comment 7 Fedora Update System 2008-12-17 16:22:12 UTC
kernel-2.6.27.9-73.fc9 has been submitted as an update for Fedora 9.
http://admin.fedoraproject.org/updates/kernel-2.6.27.9-73.fc9

Comment 8 Fedora Update System 2008-12-24 18:45:23 UTC
kernel-2.6.27.9-159.fc10 has been pushed to the Fedora 10 stable repository.  If problems still persist, please make note of it in this bug report.

Comment 9 Fedora Update System 2008-12-24 18:47:39 UTC
kernel-2.6.27.9-73.fc9 has been pushed to the Fedora 9 stable repository.  If problems still persist, please make note of it in this bug report.

Comment 11 Fedora Update System 2009-01-07 09:17:45 UTC
kernel-2.6.26.8-57.fc8 has been pushed to the Fedora 8 stable repository.  If problems still persist, please make note of it in this bug report.

Comment 14 Vincent Danen 2010-12-21 17:53:01 UTC
This was addressed via:

Red Hat Enterprise Linux (v. 5.2.z server) (RHSA-2009:0021)
MRG Realtime for RHEL 5 Server (RHSA-2009:0053)
Red Hat Enterprise Linux version 5 (RHSA-2009:0225)


Note You need to log in before you can comment on or make changes to this bug.