Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 741e1289 authored by Jan Kara's avatar Jan Kara
Browse files

ocfs2: Fix NULL pointer deref when writing local dquot



commit_dqblk() can write quota info to global file. That is actually a bad
thing to do because if we are just modifying local quota file, we are not
prepared (do not hold proper locks, do not have transaction credits) to do
a modification of the global quota file. So do not use commit_dqblk() and
instead call our writing function directly.

Acked-by: default avatarJoel Becker <Joel.Becker@oracle.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 832d09cf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -109,6 +109,7 @@ int ocfs2_read_quota_phys_block(struct inode *inode, u64 p_block,
				struct buffer_head **bh);
int ocfs2_create_local_dquot(struct dquot *dquot);
int ocfs2_local_release_dquot(handle_t *handle, struct dquot *dquot);
int ocfs2_local_write_dquot(struct dquot *dquot);

extern const struct dquot_operations ocfs2_quota_operations;
extern struct quota_format_type ocfs2_quota_format;
+10 −10
Original line number Diff line number Diff line
@@ -612,14 +612,13 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type)
	}
	mutex_lock(&sb_dqopt(sb)->dqio_mutex);
	status = ocfs2_sync_dquot(dquot);
	mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
	if (status < 0)
		mlog_errno(status);
	/* We have to write local structure as well... */
	dquot_mark_dquot_dirty(dquot);
	status = dquot_commit(dquot);
	status = ocfs2_local_write_dquot(dquot);
	if (status < 0)
		mlog_errno(status);
	mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
	ocfs2_commit_trans(osb, handle);
out_ilock:
	ocfs2_unlock_global_qf(oinfo, 1);
@@ -658,7 +657,9 @@ static int ocfs2_write_dquot(struct dquot *dquot)
		mlog_errno(status);
		goto out;
	}
	status = dquot_commit(dquot);
	mutex_lock(&sb_dqopt(dquot->dq_sb)->dqio_mutex);
	status = ocfs2_local_write_dquot(dquot);
	mutex_unlock(&sb_dqopt(dquot->dq_sb)->dqio_mutex);
	ocfs2_commit_trans(osb, handle);
out:
	mlog_exit(status);
@@ -831,7 +832,6 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
	struct ocfs2_super *osb = OCFS2_SB(sb);

	mlog_entry("id=%u, type=%d", dquot->dq_id, type);
	dquot_mark_dquot_dirty(dquot);

	/* In case user set some limits, sync dquot immediately to global
	 * quota file so that information propagates quicker */
@@ -856,14 +856,14 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
	}
	mutex_lock(&sb_dqopt(sb)->dqio_mutex);
	status = ocfs2_sync_dquot(dquot);
	mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
	if (status < 0) {
		mlog_errno(status);
		goto out_trans;
		goto out_dlock;
	}
	/* Now write updated local dquot structure */
	status = dquot_commit(dquot);
out_trans:
	status = ocfs2_local_write_dquot(dquot);
out_dlock:
	mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
	ocfs2_commit_trans(osb, handle);
out_ilock:
	ocfs2_unlock_global_qf(oinfo, 1);
@@ -915,7 +915,7 @@ static void ocfs2_destroy_dquot(struct dquot *dquot)
}

const struct dquot_operations ocfs2_quota_operations = {
	.write_dquot	= ocfs2_write_dquot,
	/* We never make dquot dirty so .write_dquot is never called */
	.acquire_dquot	= ocfs2_acquire_dquot,
	.release_dquot	= ocfs2_release_dquot,
	.mark_dirty	= ocfs2_mark_dquot_dirty,
+1 −2
Original line number Diff line number Diff line
@@ -892,7 +892,7 @@ static void olq_set_dquot(struct buffer_head *bh, void *private)
}

/* Write dquot to local quota file */
static int ocfs2_local_write_dquot(struct dquot *dquot)
int ocfs2_local_write_dquot(struct dquot *dquot)
{
	struct super_block *sb = dquot->dq_sb;
	struct ocfs2_dquot *od = OCFS2_DQUOT(dquot);
@@ -1309,7 +1309,6 @@ static const struct quota_format_ops ocfs2_format_ops = {
	.read_file_info		= ocfs2_local_read_info,
	.write_file_info	= ocfs2_global_write_info,
	.free_file_info		= ocfs2_local_free_info,
	.commit_dqblk		= ocfs2_local_write_dquot,
};

struct quota_format_type ocfs2_quota_format = {