Commit 94234dda authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Nathan Scott

[XFS] fix direct user memory dereference in bulkstat

SGI Modid: xfs-linux:xfs-kern:171167a
parent 62a604de
...@@ -84,10 +84,9 @@ xfs_bulkstat_one( ...@@ -84,10 +84,9 @@ xfs_bulkstat_one(
xfs_arch_t arch; /* these are set according to */ xfs_arch_t arch; /* these are set according to */
__uint16_t di_flags; /* temp */ __uint16_t di_flags; /* temp */
buf = (xfs_bstat_t *)buffer;
dip = (xfs_dinode_t *)dibuff; dip = (xfs_dinode_t *)dibuff;
if (! buf || ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino || if (!buffer || ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
(XFS_SB_VERSION_HASQUOTA(&mp->m_sb) && (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
(ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino))) { (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino))) {
*stat = BULKSTAT_RV_NOTHING; *stat = BULKSTAT_RV_NOTHING;
...@@ -98,6 +97,8 @@ xfs_bulkstat_one( ...@@ -98,6 +97,8 @@ xfs_bulkstat_one(
return XFS_ERROR(ENOMEM); return XFS_ERROR(ENOMEM);
} }
buf = kmem_alloc(sizeof(*buf), KM_SLEEP);
if (dip == NULL) { if (dip == NULL) {
/* We're not being passed a pointer to a dinode. This happens /* We're not being passed a pointer to a dinode. This happens
* if BULKSTAT_FG_IGET is selected. Do the iget. * if BULKSTAT_FG_IGET is selected. Do the iget.
...@@ -112,6 +113,7 @@ xfs_bulkstat_one( ...@@ -112,6 +113,7 @@ xfs_bulkstat_one(
if (ip->i_d.di_mode == 0) { if (ip->i_d.di_mode == 0) {
xfs_iput_new(ip, XFS_ILOCK_SHARED); xfs_iput_new(ip, XFS_ILOCK_SHARED);
*stat = BULKSTAT_RV_NOTHING; *stat = BULKSTAT_RV_NOTHING;
kmem_free(buf, sizeof(*buf));
return XFS_ERROR(ENOENT); return XFS_ERROR(ENOENT);
} }
dic = &ip->i_d; dic = &ip->i_d;
...@@ -228,6 +230,13 @@ xfs_bulkstat_one( ...@@ -228,6 +230,13 @@ xfs_bulkstat_one(
xfs_iput(ip, XFS_ILOCK_SHARED); xfs_iput(ip, XFS_ILOCK_SHARED);
} }
if (copy_to_user(buffer, buf, sizeof(*buf))) {
kmem_free(buf, sizeof(*buf));
*stat = BULKSTAT_RV_NOTHING;
return EFAULT;
}
kmem_free(buf, sizeof(*buf));
*stat = BULKSTAT_RV_DIDONE; *stat = BULKSTAT_RV_DIDONE;
if (ubused) if (ubused)
*ubused = sizeof(*buf); *ubused = sizeof(*buf);
...@@ -650,7 +659,6 @@ xfs_bulkstat_single( ...@@ -650,7 +659,6 @@ xfs_bulkstat_single(
xfs_caddr_t buffer, /* buffer with inode stats */ xfs_caddr_t buffer, /* buffer with inode stats */
int *done) /* 1 if there're more stats to get */ int *done) /* 1 if there're more stats to get */
{ {
xfs_bstat_t bstat; /* one bulkstat result structure */
int count; /* count value for bulkstat call */ int count; /* count value for bulkstat call */
int error; /* return value */ int error; /* return value */
xfs_ino_t ino; /* filesystem inode number */ xfs_ino_t ino; /* filesystem inode number */
...@@ -666,7 +674,7 @@ xfs_bulkstat_single( ...@@ -666,7 +674,7 @@ xfs_bulkstat_single(
*/ */
ino = (xfs_ino_t)*lastinop; ino = (xfs_ino_t)*lastinop;
error = xfs_bulkstat_one(mp, ino, &bstat, sizeof(bstat), error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t),
NULL, 0, NULL, NULL, &res); NULL, 0, NULL, NULL, &res);
if (error) { if (error) {
/* /*
...@@ -676,8 +684,8 @@ xfs_bulkstat_single( ...@@ -676,8 +684,8 @@ xfs_bulkstat_single(
(*lastinop)--; (*lastinop)--;
count = 1; count = 1;
if (xfs_bulkstat(mp, lastinop, &count, xfs_bulkstat_one, if (xfs_bulkstat(mp, lastinop, &count, xfs_bulkstat_one,
NULL, NULL, sizeof(xfs_bstat_t), buffer,
sizeof(bstat), buffer, BULKSTAT_FG_IGET, done)) BULKSTAT_FG_IGET, done))
return error; return error;
if (count == 0 || (xfs_ino_t)*lastinop != ino) if (count == 0 || (xfs_ino_t)*lastinop != ino)
return error == EFSCORRUPTED ? return error == EFSCORRUPTED ?
...@@ -686,8 +694,6 @@ xfs_bulkstat_single( ...@@ -686,8 +694,6 @@ xfs_bulkstat_single(
return 0; return 0;
} }
*done = 0; *done = 0;
if (copy_to_user(buffer, &bstat, sizeof(bstat)))
return XFS_ERROR(EFAULT);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment