[PATCH 2/4] userns: ioctl: convert project id between user and kernel space

Gao feng
2013-09-04T06:37:27Z

User namespace use /proc/<pid>/projid_map to map the project ids
in user namespace to the global project ids.

This patch adds the conversion of xfs proj_t to the global project
id struct kprojid_t, and adds the validating check.

User in un-init user namespace can only change file's project id
to the specified ids which are configured in projid_map of userns.

Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
fs/xfs/xfs_ioctl.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index bdebc21..8db622f 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -855,7 +855,7 @@ xfs_ioc_fsgetxattr(
xfs_ilock(ip, XFS_ILOCK_SHARED);
fa.fsx_xflags = xfs_ip2xflags(ip);
fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
- fa.fsx_projid = xfs_get_projid(ip);
+ fa.fsx_projid = xfs_convert_to_user_projid(xfs_get_projid(ip));

if (attr) {
if (ip->i_afp) {
@@ -965,6 +965,7 @@ xfs_ioctl_setattr(
struct xfs_dquot *pdqp = NULL;
struct xfs_dquot *olddquot = NULL;
int code;
+ prid_t projid = 0;

trace_xfs_ioctl_setattr(ip);

@@ -976,9 +977,12 @@ xfs_ioctl_setattr(
/*
* Disallow 32bit project ids when projid32bit feature is not enabled.
*/
- if ((mask & FSX_PROJID) && (fa->fsx_projid > (__uint16_t)-1) &&
- !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb))
- return XFS_ERROR(EINVAL);
+ if ((mask & FSX_PROJID)) {
+ if ((xfs_convert_to_kernel_projid(fa->fsx_projid, &projid) < 0) ||
+ ((projid > (__uint16_t)-1) &&
+ !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb)))
+ return XFS_ERROR(EINVAL);
+ }

/*
* If disk quotas is on, we make sure that the dquots do exist on disk,
@@ -990,7 +994,7 @@ xfs_ioctl_setattr(
*/
if (XFS_IS_QUOTA_ON(mp) && (mask & FSX_PROJID)) {
code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid,
- ip->i_d.di_gid, fa->fsx_projid,
+ ip->i_d.di_gid, projid,
XFS_QMOPT_PQUOTA, &udqp, NULL, &pdqp);
if (code)
return code;
@@ -1033,7 +1037,7 @@ xfs_ioctl_setattr(

if (XFS_IS_QUOTA_RUNNING(mp) &&
XFS_IS_PQUOTA_ON(mp) &&
- xfs_get_projid(ip) != fa->fsx_projid) {
+ xfs_get_projid(ip) != projid) {
ASSERT(tp);
code = xfs_qm_vop_chown_reserve(tp, ip, udqp, NULL,
pdqp, capable(CAP_FOWNER) ?
@@ -1151,12 +1155,12 @@ xfs_ioctl_setattr(
* Change the ownerships and register quota modifications
* in the transaction.
*/
- if (xfs_get_projid(ip) != fa->fsx_projid) {
+ if (xfs_get_projid(ip) != projid) {
if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
olddquot = xfs_qm_vop_chown(tp, ip,
&ip->i_pdquot, pdqp);
}
- xfs_set_projid(ip, fa->fsx_projid);
+ xfs_set_projid(ip, projid);

/*
* We may have to rev the inode as well as