From: "Eric W. Biederman" <[email protected]>

- Modify the ioctl to convert from uids, gid, and projids in the
  current user namespace to kuids, kgids, and kprojids, and to report
  an error if the conversion fails.

- Create struct xfs_internal_eofblocks to hold the same information as
  struct xfs_eofblocks but with uids, gids, and projids stored as
  kuids, kgids, and kprojids preventing confusion.

- Pass struct xfs_interanl_eofblocks into xfs_icache_free_eofblocks
  and it's helpers ensuring there will not be confusing about which
  user namespace identifiers that need to be compared are in.

Cc: Ben Myers <[email protected]>
Cc: Alex Elder <[email protected]>
Cc: Dave Chinner <[email protected]>
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
 fs/xfs/xfs_icache.c |    8 ++++----
 fs/xfs/xfs_icache.h |   11 ++++++++++-
 fs/xfs/xfs_ioctl.c  |   22 +++++++++++++++++++++-
 3 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 0583649..e4cdc02 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -1199,7 +1199,7 @@ xfs_reclaim_inodes_count(
 STATIC int
 xfs_inode_match_id(
        struct xfs_inode        *ip,
-       struct xfs_eofblocks    *eofb)
+       struct xfs_internal_eofblocks   *eofb)
 {
        if (eofb->eof_flags & XFS_EOF_FLAGS_UID &&
            !uid_eq(VFS_I(ip)->i_uid, eofb->eof_uid))
@@ -1210,7 +1210,7 @@ xfs_inode_match_id(
                return 0;
 
        if (eofb->eof_flags & XFS_EOF_FLAGS_PRID &&
-           !projid_eq(ip->i_projid, eofb->eof_prid))
+           !projid_eq(ip->i_projid, eofb->eof_projid))
                return 0;
 
        return 1;
@@ -1224,7 +1224,7 @@ xfs_inode_free_eofblocks(
        void                    *args)
 {
        int ret;
-       struct xfs_eofblocks *eofb = args;
+       struct xfs_internal_eofblocks *eofb = args;
 
        if (!xfs_can_free_eofblocks(ip, false)) {
                /* inode could be preallocated or append-only */
@@ -1263,7 +1263,7 @@ xfs_inode_free_eofblocks(
 int
 xfs_icache_free_eofblocks(
        struct xfs_mount        *mp,
-       struct xfs_eofblocks    *eofb)
+       struct xfs_internal_eofblocks   *eofb)
 {
        int flags = SYNC_TRYLOCK;
 
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index e0f138c..260dc27 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -35,9 +35,18 @@ void xfs_reclaim_inodes_nr(struct xfs_mount *mp, int 
nr_to_scan);
 
 void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
 
+struct xfs_internal_eofblocks {
+       u32             eof_version;
+       u32             eof_flags;
+       kuid_t          eof_uid;
+       kgid_t          eof_gid;
+       kprojid_t       eof_projid;
+       u64             eof_min_file_size;
+};
+
 void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip);
 void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip);
-int xfs_icache_free_eofblocks(struct xfs_mount *, struct xfs_eofblocks *);
+int xfs_icache_free_eofblocks(struct xfs_mount *, struct 
xfs_internal_eofblocks *);
 void xfs_eofblocks_worker(struct work_struct *);
 
 int xfs_sync_inode_grab(struct xfs_inode *ip);
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 4a55f50..1a74b56 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1615,6 +1615,7 @@ xfs_file_ioctl(
 
        case XFS_IOC_FREE_EOFBLOCKS: {
                struct xfs_eofblocks eofb;
+               struct xfs_internal_eofblocks keofb;
 
                if (copy_from_user(&eofb, arg, sizeof(eofb)))
                        return -XFS_ERROR(EFAULT);
@@ -1629,7 +1630,26 @@ xfs_file_ioctl(
                    memchr_inv(eofb.pad64, 0, sizeof(eofb.pad64)))
                        return -XFS_ERROR(EINVAL);
 
-               error = xfs_icache_free_eofblocks(mp, &eofb);
+               keofb.eof_version = eofb.eof_version;
+               keofb.eof_flags   = eofb.eof_flags;
+               if (eofb.eof_flags & XFS_EOF_FLAGS_UID) {
+                       keofb.eof_uid = make_kuid(current_user_ns(), 
eofb.eof_uid);
+                       if (!uid_valid(keofb.eof_uid))
+                               return -XFS_ERROR(EINVAL);
+               }
+               if (eofb.eof_flags & XFS_EOF_FLAGS_GID) {
+                       keofb.eof_gid = make_kgid(current_user_ns(), 
eofb.eof_gid);
+                       if (!gid_valid(keofb.eof_gid))
+                               return -XFS_ERROR(EINVAL);
+               }
+               if (eofb.eof_flags & XFS_EOF_FLAGS_PRID) {
+                       keofb.eof_projid = make_kprojid(current_user_ns(), 
eofb.eof_prid);
+                       if (!projid_valid(keofb.eof_projid))
+                               return -XFS_ERROR(EINVAL);
+               }
+               keofb.eof_min_file_size = eofb.eof_min_file_size;
+
+               error = xfs_icache_free_eofblocks(mp, &keofb);
                return -error;
        }
 
-- 
1.7.5.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to