lkml.org 
[lkml]   [2019]   [Nov]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 4.14 049/127] xfs: Fix bulkstat compat ioctls on x32 userspace.
    Date
    From: Nick Bowler <nbowler@draconx.ca>

    [ Upstream commit 7ca860e3c1a74ad6bd8949364073ef1044cad758 ]

    The bulkstat family of ioctls are problematic on x32, because there is
    a mixup of native 32-bit and 64-bit conventions. The xfs_fsop_bulkreq
    struct contains pointers and 32-bit integers so that matches the native
    32-bit layout, and that means the ioctl implementation goes into the
    regular compat path on x32.

    However, the 'ubuffer' member of that struct in turn refers to either
    struct xfs_inogrp or xfs_bstat (or an array of these). On x32, those
    structures match the native 64-bit layout. The compat implementation
    writes out the 32-bit version of these structures. This is not the
    expected format for x32 userspace, causing problems.

    Fortunately the functions which actually output these xfs_inogrp and
    xfs_bstat structures have an easy way to select which output format
    is required, so we just need a little tweak to select the right format
    on x32.

    Signed-off-by: Nick Bowler <nbowler@draconx.ca>
    Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
    Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/xfs/xfs_ioctl32.c | 34 ++++++++++++++++++++++++++++++----
    1 file changed, 30 insertions(+), 4 deletions(-)

    diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
    index d3c0e4b8bf421..5f616a6a5358d 100644
    --- a/fs/xfs/xfs_ioctl32.c
    +++ b/fs/xfs/xfs_ioctl32.c
    @@ -252,6 +252,32 @@ xfs_compat_ioc_bulkstat(
    int done;
    int error;

    + /*
    + * Output structure handling functions. Depending on the command,
    + * either the xfs_bstat and xfs_inogrp structures are written out
    + * to userpace memory via bulkreq.ubuffer. Normally the compat
    + * functions and structure size are the correct ones to use ...
    + */
    + inumbers_fmt_pf inumbers_func = xfs_inumbers_fmt_compat;
    + bulkstat_one_pf bs_one_func = xfs_bulkstat_one_compat;
    + size_t bs_one_size = sizeof(struct compat_xfs_bstat);
    +
    +#ifdef CONFIG_X86_X32
    + if (in_x32_syscall()) {
    + /*
    + * ... but on x32 the input xfs_fsop_bulkreq has pointers
    + * which must be handled in the "compat" (32-bit) way, while
    + * the xfs_bstat and xfs_inogrp structures follow native 64-
    + * bit layout convention. So adjust accordingly, otherwise
    + * the data written out in compat layout will not match what
    + * x32 userspace expects.
    + */
    + inumbers_func = xfs_inumbers_fmt;
    + bs_one_func = xfs_bulkstat_one;
    + bs_one_size = sizeof(struct xfs_bstat);
    + }
    +#endif
    +
    /* done = 1 if there are more stats to get and if bulkstat */
    /* should be called again (unused here, but used in dmapi) */

    @@ -283,15 +309,15 @@ xfs_compat_ioc_bulkstat(

    if (cmd == XFS_IOC_FSINUMBERS_32) {
    error = xfs_inumbers(mp, &inlast, &count,
    - bulkreq.ubuffer, xfs_inumbers_fmt_compat);
    + bulkreq.ubuffer, inumbers_func);
    } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE_32) {
    int res;

    - error = xfs_bulkstat_one_compat(mp, inlast, bulkreq.ubuffer,
    - sizeof(compat_xfs_bstat_t), NULL, &res);
    + error = bs_one_func(mp, inlast, bulkreq.ubuffer,
    + bs_one_size, NULL, &res);
    } else if (cmd == XFS_IOC_FSBULKSTAT_32) {
    error = xfs_bulkstat(mp, &inlast, &count,
    - xfs_bulkstat_one_compat, sizeof(compat_xfs_bstat_t),
    + bs_one_func, bs_one_size,
    bulkreq.ubuffer, &done);
    } else
    error = -EINVAL;
    --
    2.20.1
    \
     
     \ /
      Last update: 2019-11-22 07:11    [W:4.262 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site