diff options
author | Jan Kara <jack@suse.cz> | 2016-02-18 13:20:20 +0100 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2016-02-18 13:34:41 +0100 |
commit | 044c9b6753a6b6cf486e16b53296b4707b35dbe3 (patch) | |
tree | 4854ad052572bab2d07d6d74b247d0017b177452 /fs/quota | |
parent | 5a9530e498ed25173d426cd93e31a04468d0dc24 (diff) | |
download | linux-044c9b6753a6b6cf486e16b53296b4707b35dbe3.tar.gz linux-044c9b6753a6b6cf486e16b53296b4707b35dbe3.tar.bz2 linux-044c9b6753a6b6cf486e16b53296b4707b35dbe3.zip |
quota: Fix possible races during quota loading
When loading new quota structure from disk, there is a possibility caller
of dqget() will see uninitialized data due to CPU reordering loads or
stores - loads from dquot can be reordered before test of DQ_ACTIVE_B
bit or setting of this bit could be reordered before filling of the
structure. Fix the issue by adding proper memory barriers.
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/quota')
-rw-r--r-- | fs/quota/dquot.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 7e0137bde6d6..e8467dc90c7e 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -411,6 +411,8 @@ int dquot_acquire(struct dquot *dquot) ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot); if (ret < 0) goto out_iolock; + /* Make sure flags update is visible after dquot has been filled */ + smp_mb__before_atomic(); set_bit(DQ_READ_B, &dquot->dq_flags); /* Instantiate dquot if needed */ if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && !dquot->dq_off) { @@ -427,6 +429,11 @@ int dquot_acquire(struct dquot *dquot) goto out_iolock; } } + /* + * Make sure flags update is visible after on-disk struct has been + * allocated. Paired with smp_rmb() in dqget(). + */ + smp_mb__before_atomic(); set_bit(DQ_ACTIVE_B, &dquot->dq_flags); out_iolock: mutex_unlock(&dqopt->dqio_mutex); @@ -887,6 +894,11 @@ we_slept: goto out; } } + /* + * Make sure following reads see filled structure - paired with + * smp_mb__before_atomic() in dquot_acquire(). + */ + smp_rmb(); #ifdef CONFIG_QUOTA_DEBUG BUG_ON(!dquot->dq_sb); /* Has somebody invalidated entry under us? */ #endif |