1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 27ed1ee61SAl Viro #include <linux/syscalls.h> 3630d9c47SPaul Gortmaker #include <linux/export.h> 47ed1ee61SAl Viro #include <linux/fs.h> 57ed1ee61SAl Viro #include <linux/file.h> 6365b1818SChristoph Hellwig #include <linux/mount.h> 77ed1ee61SAl Viro #include <linux/namei.h> 87ed1ee61SAl Viro #include <linux/statfs.h> 97ed1ee61SAl Viro #include <linux/security.h> 107ed1ee61SAl Viro #include <linux/uaccess.h> 114ada54eeSAl Viro #include <linux/compat.h> 12cf31e70dSAl Viro #include "internal.h" 137ed1ee61SAl Viro 14365b1818SChristoph Hellwig static int flags_by_mnt(int mnt_flags) 15365b1818SChristoph Hellwig { 16365b1818SChristoph Hellwig int flags = 0; 17365b1818SChristoph Hellwig 18365b1818SChristoph Hellwig if (mnt_flags & MNT_READONLY) 19365b1818SChristoph Hellwig flags |= ST_RDONLY; 20365b1818SChristoph Hellwig if (mnt_flags & MNT_NOSUID) 21365b1818SChristoph Hellwig flags |= ST_NOSUID; 22365b1818SChristoph Hellwig if (mnt_flags & MNT_NODEV) 23365b1818SChristoph Hellwig flags |= ST_NODEV; 24365b1818SChristoph Hellwig if (mnt_flags & MNT_NOEXEC) 25365b1818SChristoph Hellwig flags |= ST_NOEXEC; 26365b1818SChristoph Hellwig if (mnt_flags & MNT_NOATIME) 27365b1818SChristoph Hellwig flags |= ST_NOATIME; 28365b1818SChristoph Hellwig if (mnt_flags & MNT_NODIRATIME) 29365b1818SChristoph Hellwig flags |= ST_NODIRATIME; 30365b1818SChristoph Hellwig if (mnt_flags & MNT_RELATIME) 31365b1818SChristoph Hellwig flags |= ST_RELATIME; 32dab741e0SMattias Nissler if (mnt_flags & MNT_NOSYMFOLLOW) 33dab741e0SMattias Nissler flags |= ST_NOSYMFOLLOW; 34365b1818SChristoph Hellwig return flags; 35365b1818SChristoph Hellwig } 36365b1818SChristoph Hellwig 37365b1818SChristoph Hellwig static int flags_by_sb(int s_flags) 38365b1818SChristoph Hellwig { 39365b1818SChristoph Hellwig int flags = 0; 401751e8a6SLinus Torvalds if (s_flags & SB_SYNCHRONOUS) 41365b1818SChristoph Hellwig flags |= ST_SYNCHRONOUS; 421751e8a6SLinus Torvalds if (s_flags & SB_MANDLOCK) 43365b1818SChristoph Hellwig flags |= ST_MANDLOCK; 441751e8a6SLinus Torvalds if (s_flags & SB_RDONLY) 45a8e2b636SCarlos Maiolino flags |= ST_RDONLY; 46365b1818SChristoph Hellwig return flags; 47365b1818SChristoph Hellwig } 48365b1818SChristoph Hellwig 49365b1818SChristoph Hellwig static int calculate_f_flags(struct vfsmount *mnt) 50365b1818SChristoph Hellwig { 51365b1818SChristoph Hellwig return ST_VALID | flags_by_mnt(mnt->mnt_flags) | 52365b1818SChristoph Hellwig flags_by_sb(mnt->mnt_sb->s_flags); 53365b1818SChristoph Hellwig } 54365b1818SChristoph Hellwig 55cf31e70dSAl Viro static int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf) 567ed1ee61SAl Viro { 57ebabe9a9SChristoph Hellwig int retval; 587ed1ee61SAl Viro 59ebabe9a9SChristoph Hellwig if (!dentry->d_sb->s_op->statfs) 60ebabe9a9SChristoph Hellwig return -ENOSYS; 61ebabe9a9SChristoph Hellwig 627ed1ee61SAl Viro memset(buf, 0, sizeof(*buf)); 637ed1ee61SAl Viro retval = security_sb_statfs(dentry); 647ed1ee61SAl Viro if (retval) 657ed1ee61SAl Viro return retval; 667ed1ee61SAl Viro retval = dentry->d_sb->s_op->statfs(dentry, buf); 677ed1ee61SAl Viro if (retval == 0 && buf->f_frsize == 0) 687ed1ee61SAl Viro buf->f_frsize = buf->f_bsize; 697ed1ee61SAl Viro return retval; 707ed1ee61SAl Viro } 717ed1ee61SAl Viro 72ec86ff56SAmir Goldstein int vfs_get_fsid(struct dentry *dentry, __kernel_fsid_t *fsid) 73ec86ff56SAmir Goldstein { 74ec86ff56SAmir Goldstein struct kstatfs st; 75ec86ff56SAmir Goldstein int error; 76ec86ff56SAmir Goldstein 77ec86ff56SAmir Goldstein error = statfs_by_dentry(dentry, &st); 78ec86ff56SAmir Goldstein if (error) 79ec86ff56SAmir Goldstein return error; 80ec86ff56SAmir Goldstein 81ec86ff56SAmir Goldstein *fsid = st.f_fsid; 82ec86ff56SAmir Goldstein return 0; 83ec86ff56SAmir Goldstein } 84ec86ff56SAmir Goldstein EXPORT_SYMBOL(vfs_get_fsid); 85ec86ff56SAmir Goldstein 86f0bb5aafSAl Viro int vfs_statfs(const struct path *path, struct kstatfs *buf) 87ebabe9a9SChristoph Hellwig { 88365b1818SChristoph Hellwig int error; 89365b1818SChristoph Hellwig 90365b1818SChristoph Hellwig error = statfs_by_dentry(path->dentry, buf); 91365b1818SChristoph Hellwig if (!error) 92365b1818SChristoph Hellwig buf->f_flags = calculate_f_flags(path->mnt); 93365b1818SChristoph Hellwig return error; 94ebabe9a9SChristoph Hellwig } 957ed1ee61SAl Viro EXPORT_SYMBOL(vfs_statfs); 967ed1ee61SAl Viro 97c8b91accSAl Viro int user_statfs(const char __user *pathname, struct kstatfs *st) 987ed1ee61SAl Viro { 99c8b91accSAl Viro struct path path; 10096948fc6SJeff Layton int error; 10196948fc6SJeff Layton unsigned int lookup_flags = LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT; 10296948fc6SJeff Layton retry: 10396948fc6SJeff Layton error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); 104c8b91accSAl Viro if (!error) { 105c8b91accSAl Viro error = vfs_statfs(&path, st); 106c8b91accSAl Viro path_put(&path); 10796948fc6SJeff Layton if (retry_estale(error, lookup_flags)) { 10896948fc6SJeff Layton lookup_flags |= LOOKUP_REVAL; 10996948fc6SJeff Layton goto retry; 11096948fc6SJeff Layton } 111c8b91accSAl Viro } 112c8b91accSAl Viro return error; 113c8b91accSAl Viro } 1147ed1ee61SAl Viro 115c8b91accSAl Viro int fd_statfs(int fd, struct kstatfs *st) 116c8b91accSAl Viro { 1179d05746eSLinus Torvalds struct fd f = fdget_raw(fd); 118c8b91accSAl Viro int error = -EBADF; 1192903ff01SAl Viro if (f.file) { 1202903ff01SAl Viro error = vfs_statfs(&f.file->f_path, st); 1212903ff01SAl Viro fdput(f); 122c8b91accSAl Viro } 123c8b91accSAl Viro return error; 124c8b91accSAl Viro } 1257ed1ee61SAl Viro 126c8b91accSAl Viro static int do_statfs_native(struct kstatfs *st, struct statfs __user *p) 127c8b91accSAl Viro { 128c8b91accSAl Viro struct statfs buf; 129c8b91accSAl Viro 130c8b91accSAl Viro if (sizeof(buf) == sizeof(*st)) 131c8b91accSAl Viro memcpy(&buf, st, sizeof(*st)); 1327ed1ee61SAl Viro else { 133c8b91accSAl Viro if (sizeof buf.f_blocks == 4) { 134c8b91accSAl Viro if ((st->f_blocks | st->f_bfree | st->f_bavail | 135c8b91accSAl Viro st->f_bsize | st->f_frsize) & 1367ed1ee61SAl Viro 0xffffffff00000000ULL) 1377ed1ee61SAl Viro return -EOVERFLOW; 1387ed1ee61SAl Viro /* 1397ed1ee61SAl Viro * f_files and f_ffree may be -1; it's okay to stuff 1407ed1ee61SAl Viro * that into 32 bits 1417ed1ee61SAl Viro */ 142c8b91accSAl Viro if (st->f_files != -1 && 143c8b91accSAl Viro (st->f_files & 0xffffffff00000000ULL)) 1447ed1ee61SAl Viro return -EOVERFLOW; 145c8b91accSAl Viro if (st->f_ffree != -1 && 146c8b91accSAl Viro (st->f_ffree & 0xffffffff00000000ULL)) 1477ed1ee61SAl Viro return -EOVERFLOW; 1487ed1ee61SAl Viro } 1497ed1ee61SAl Viro 150c8b91accSAl Viro buf.f_type = st->f_type; 151c8b91accSAl Viro buf.f_bsize = st->f_bsize; 152c8b91accSAl Viro buf.f_blocks = st->f_blocks; 153c8b91accSAl Viro buf.f_bfree = st->f_bfree; 154c8b91accSAl Viro buf.f_bavail = st->f_bavail; 155c8b91accSAl Viro buf.f_files = st->f_files; 156c8b91accSAl Viro buf.f_ffree = st->f_ffree; 157c8b91accSAl Viro buf.f_fsid = st->f_fsid; 158c8b91accSAl Viro buf.f_namelen = st->f_namelen; 159c8b91accSAl Viro buf.f_frsize = st->f_frsize; 160c8b91accSAl Viro buf.f_flags = st->f_flags; 161c8b91accSAl Viro memset(buf.f_spare, 0, sizeof(buf.f_spare)); 1627ed1ee61SAl Viro } 163c8b91accSAl Viro if (copy_to_user(p, &buf, sizeof(buf))) 164c8b91accSAl Viro return -EFAULT; 1657ed1ee61SAl Viro return 0; 1667ed1ee61SAl Viro } 1677ed1ee61SAl Viro 168c8b91accSAl Viro static int do_statfs64(struct kstatfs *st, struct statfs64 __user *p) 1697ed1ee61SAl Viro { 170c8b91accSAl Viro struct statfs64 buf; 171c8b91accSAl Viro if (sizeof(buf) == sizeof(*st)) 172c8b91accSAl Viro memcpy(&buf, st, sizeof(*st)); 1737ed1ee61SAl Viro else { 174c8b91accSAl Viro buf.f_type = st->f_type; 175c8b91accSAl Viro buf.f_bsize = st->f_bsize; 176c8b91accSAl Viro buf.f_blocks = st->f_blocks; 177c8b91accSAl Viro buf.f_bfree = st->f_bfree; 178c8b91accSAl Viro buf.f_bavail = st->f_bavail; 179c8b91accSAl Viro buf.f_files = st->f_files; 180c8b91accSAl Viro buf.f_ffree = st->f_ffree; 181c8b91accSAl Viro buf.f_fsid = st->f_fsid; 182c8b91accSAl Viro buf.f_namelen = st->f_namelen; 183c8b91accSAl Viro buf.f_frsize = st->f_frsize; 184c8b91accSAl Viro buf.f_flags = st->f_flags; 185c8b91accSAl Viro memset(buf.f_spare, 0, sizeof(buf.f_spare)); 1867ed1ee61SAl Viro } 187c8b91accSAl Viro if (copy_to_user(p, &buf, sizeof(buf))) 188c8b91accSAl Viro return -EFAULT; 1897ed1ee61SAl Viro return 0; 1907ed1ee61SAl Viro } 1917ed1ee61SAl Viro 1927ed1ee61SAl Viro SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf) 1937ed1ee61SAl Viro { 194c8b91accSAl Viro struct kstatfs st; 195c8b91accSAl Viro int error = user_statfs(pathname, &st); 196c8b91accSAl Viro if (!error) 197c8b91accSAl Viro error = do_statfs_native(&st, buf); 1987ed1ee61SAl Viro return error; 1997ed1ee61SAl Viro } 2007ed1ee61SAl Viro 2017ed1ee61SAl Viro SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf) 2027ed1ee61SAl Viro { 203c8b91accSAl Viro struct kstatfs st; 204c8b91accSAl Viro int error; 2057ed1ee61SAl Viro if (sz != sizeof(*buf)) 2067ed1ee61SAl Viro return -EINVAL; 207c8b91accSAl Viro error = user_statfs(pathname, &st); 208c8b91accSAl Viro if (!error) 209c8b91accSAl Viro error = do_statfs64(&st, buf); 2107ed1ee61SAl Viro return error; 2117ed1ee61SAl Viro } 2127ed1ee61SAl Viro 2137ed1ee61SAl Viro SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf) 2147ed1ee61SAl Viro { 215c8b91accSAl Viro struct kstatfs st; 216c8b91accSAl Viro int error = fd_statfs(fd, &st); 217c8b91accSAl Viro if (!error) 218c8b91accSAl Viro error = do_statfs_native(&st, buf); 2197ed1ee61SAl Viro return error; 2207ed1ee61SAl Viro } 2217ed1ee61SAl Viro 2227ed1ee61SAl Viro SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf) 2237ed1ee61SAl Viro { 224c8b91accSAl Viro struct kstatfs st; 2257ed1ee61SAl Viro int error; 2267ed1ee61SAl Viro 2277ed1ee61SAl Viro if (sz != sizeof(*buf)) 2287ed1ee61SAl Viro return -EINVAL; 2297ed1ee61SAl Viro 230c8b91accSAl Viro error = fd_statfs(fd, &st); 231c8b91accSAl Viro if (!error) 232c8b91accSAl Viro error = do_statfs64(&st, buf); 2337ed1ee61SAl Viro return error; 2347ed1ee61SAl Viro } 2357ed1ee61SAl Viro 23653fd88abSAl Viro static int vfs_ustat(dev_t dev, struct kstatfs *sbuf) 2377ed1ee61SAl Viro { 238*4e7b5671SChristoph Hellwig struct super_block *s = user_get_super(dev, false); 2397ed1ee61SAl Viro int err; 2407ed1ee61SAl Viro if (!s) 2417ed1ee61SAl Viro return -EINVAL; 2427ed1ee61SAl Viro 243cf31e70dSAl Viro err = statfs_by_dentry(s->s_root, sbuf); 2447ed1ee61SAl Viro drop_super(s); 245cf31e70dSAl Viro return err; 246cf31e70dSAl Viro } 247cf31e70dSAl Viro 248cf31e70dSAl Viro SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf) 249cf31e70dSAl Viro { 250cf31e70dSAl Viro struct ustat tmp; 251cf31e70dSAl Viro struct kstatfs sbuf; 252cf31e70dSAl Viro int err = vfs_ustat(new_decode_dev(dev), &sbuf); 2537ed1ee61SAl Viro if (err) 2547ed1ee61SAl Viro return err; 2557ed1ee61SAl Viro 2567ed1ee61SAl Viro memset(&tmp,0,sizeof(struct ustat)); 2577ed1ee61SAl Viro tmp.f_tfree = sbuf.f_bfree; 2587ed1ee61SAl Viro tmp.f_tinode = sbuf.f_ffree; 2597ed1ee61SAl Viro 2607ed1ee61SAl Viro return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0; 2617ed1ee61SAl Viro } 2624ada54eeSAl Viro 2634ada54eeSAl Viro #ifdef CONFIG_COMPAT 2644ada54eeSAl Viro static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf) 2654ada54eeSAl Viro { 266ae2a9762SAl Viro struct compat_statfs buf; 2674ada54eeSAl Viro if (sizeof ubuf->f_blocks == 4) { 2684ada54eeSAl Viro if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail | 2694ada54eeSAl Viro kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL) 2704ada54eeSAl Viro return -EOVERFLOW; 2714ada54eeSAl Viro /* f_files and f_ffree may be -1; it's okay 2724ada54eeSAl Viro * to stuff that into 32 bits */ 2734ada54eeSAl Viro if (kbuf->f_files != 0xffffffffffffffffULL 2744ada54eeSAl Viro && (kbuf->f_files & 0xffffffff00000000ULL)) 2754ada54eeSAl Viro return -EOVERFLOW; 2764ada54eeSAl Viro if (kbuf->f_ffree != 0xffffffffffffffffULL 2774ada54eeSAl Viro && (kbuf->f_ffree & 0xffffffff00000000ULL)) 2784ada54eeSAl Viro return -EOVERFLOW; 2794ada54eeSAl Viro } 280ae2a9762SAl Viro memset(&buf, 0, sizeof(struct compat_statfs)); 281ae2a9762SAl Viro buf.f_type = kbuf->f_type; 282ae2a9762SAl Viro buf.f_bsize = kbuf->f_bsize; 283ae2a9762SAl Viro buf.f_blocks = kbuf->f_blocks; 284ae2a9762SAl Viro buf.f_bfree = kbuf->f_bfree; 285ae2a9762SAl Viro buf.f_bavail = kbuf->f_bavail; 286ae2a9762SAl Viro buf.f_files = kbuf->f_files; 287ae2a9762SAl Viro buf.f_ffree = kbuf->f_ffree; 288ae2a9762SAl Viro buf.f_namelen = kbuf->f_namelen; 289ae2a9762SAl Viro buf.f_fsid.val[0] = kbuf->f_fsid.val[0]; 290ae2a9762SAl Viro buf.f_fsid.val[1] = kbuf->f_fsid.val[1]; 291ae2a9762SAl Viro buf.f_frsize = kbuf->f_frsize; 292ae2a9762SAl Viro buf.f_flags = kbuf->f_flags; 293ae2a9762SAl Viro if (copy_to_user(ubuf, &buf, sizeof(struct compat_statfs))) 2944ada54eeSAl Viro return -EFAULT; 2954ada54eeSAl Viro return 0; 2964ada54eeSAl Viro } 2974ada54eeSAl Viro 2984ada54eeSAl Viro /* 2994ada54eeSAl Viro * The following statfs calls are copies of code from fs/statfs.c and 3004ada54eeSAl Viro * should be checked against those from time to time 3014ada54eeSAl Viro */ 3024ada54eeSAl Viro COMPAT_SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct compat_statfs __user *, buf) 3034ada54eeSAl Viro { 3044ada54eeSAl Viro struct kstatfs tmp; 3054ada54eeSAl Viro int error = user_statfs(pathname, &tmp); 3064ada54eeSAl Viro if (!error) 3074ada54eeSAl Viro error = put_compat_statfs(buf, &tmp); 3084ada54eeSAl Viro return error; 3094ada54eeSAl Viro } 3104ada54eeSAl Viro 3114ada54eeSAl Viro COMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *, buf) 3124ada54eeSAl Viro { 3134ada54eeSAl Viro struct kstatfs tmp; 3144ada54eeSAl Viro int error = fd_statfs(fd, &tmp); 3154ada54eeSAl Viro if (!error) 3164ada54eeSAl Viro error = put_compat_statfs(buf, &tmp); 3174ada54eeSAl Viro return error; 3184ada54eeSAl Viro } 3194ada54eeSAl Viro 3204ada54eeSAl Viro static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf) 3214ada54eeSAl Viro { 322ae2a9762SAl Viro struct compat_statfs64 buf; 323cc3a7bfeSEric Sandeen 324cc3a7bfeSEric Sandeen if ((kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL) 3254ada54eeSAl Viro return -EOVERFLOW; 326cc3a7bfeSEric Sandeen 327ae2a9762SAl Viro memset(&buf, 0, sizeof(struct compat_statfs64)); 328ae2a9762SAl Viro buf.f_type = kbuf->f_type; 329ae2a9762SAl Viro buf.f_bsize = kbuf->f_bsize; 330ae2a9762SAl Viro buf.f_blocks = kbuf->f_blocks; 331ae2a9762SAl Viro buf.f_bfree = kbuf->f_bfree; 332ae2a9762SAl Viro buf.f_bavail = kbuf->f_bavail; 333ae2a9762SAl Viro buf.f_files = kbuf->f_files; 334ae2a9762SAl Viro buf.f_ffree = kbuf->f_ffree; 335ae2a9762SAl Viro buf.f_namelen = kbuf->f_namelen; 336ae2a9762SAl Viro buf.f_fsid.val[0] = kbuf->f_fsid.val[0]; 337ae2a9762SAl Viro buf.f_fsid.val[1] = kbuf->f_fsid.val[1]; 338ae2a9762SAl Viro buf.f_frsize = kbuf->f_frsize; 339ae2a9762SAl Viro buf.f_flags = kbuf->f_flags; 340ae2a9762SAl Viro if (copy_to_user(ubuf, &buf, sizeof(struct compat_statfs64))) 3414ada54eeSAl Viro return -EFAULT; 3424ada54eeSAl Viro return 0; 3434ada54eeSAl Viro } 3444ada54eeSAl Viro 3459b54bf9dSMark Rutland int kcompat_sys_statfs64(const char __user * pathname, compat_size_t sz, struct compat_statfs64 __user * buf) 3464ada54eeSAl Viro { 3474ada54eeSAl Viro struct kstatfs tmp; 3484ada54eeSAl Viro int error; 3494ada54eeSAl Viro 3504ada54eeSAl Viro if (sz != sizeof(*buf)) 3514ada54eeSAl Viro return -EINVAL; 3524ada54eeSAl Viro 3534ada54eeSAl Viro error = user_statfs(pathname, &tmp); 3544ada54eeSAl Viro if (!error) 3554ada54eeSAl Viro error = put_compat_statfs64(buf, &tmp); 3564ada54eeSAl Viro return error; 3574ada54eeSAl Viro } 3584ada54eeSAl Viro 3599b54bf9dSMark Rutland COMPAT_SYSCALL_DEFINE3(statfs64, const char __user *, pathname, compat_size_t, sz, struct compat_statfs64 __user *, buf) 3609b54bf9dSMark Rutland { 3619b54bf9dSMark Rutland return kcompat_sys_statfs64(pathname, sz, buf); 3629b54bf9dSMark Rutland } 3639b54bf9dSMark Rutland 3649b54bf9dSMark Rutland int kcompat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user * buf) 3654ada54eeSAl Viro { 3664ada54eeSAl Viro struct kstatfs tmp; 3674ada54eeSAl Viro int error; 3684ada54eeSAl Viro 3694ada54eeSAl Viro if (sz != sizeof(*buf)) 3704ada54eeSAl Viro return -EINVAL; 3714ada54eeSAl Viro 3724ada54eeSAl Viro error = fd_statfs(fd, &tmp); 3734ada54eeSAl Viro if (!error) 3744ada54eeSAl Viro error = put_compat_statfs64(buf, &tmp); 3754ada54eeSAl Viro return error; 3764ada54eeSAl Viro } 3774ada54eeSAl Viro 3789b54bf9dSMark Rutland COMPAT_SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, compat_size_t, sz, struct compat_statfs64 __user *, buf) 3799b54bf9dSMark Rutland { 3809b54bf9dSMark Rutland return kcompat_sys_fstatfs64(fd, sz, buf); 3819b54bf9dSMark Rutland } 3829b54bf9dSMark Rutland 3834ada54eeSAl Viro /* 3844ada54eeSAl Viro * This is a copy of sys_ustat, just dealing with a structure layout. 3854ada54eeSAl Viro * Given how simple this syscall is that apporach is more maintainable 3864ada54eeSAl Viro * than the various conversion hacks. 3874ada54eeSAl Viro */ 3884ada54eeSAl Viro COMPAT_SYSCALL_DEFINE2(ustat, unsigned, dev, struct compat_ustat __user *, u) 3894ada54eeSAl Viro { 3904ada54eeSAl Viro struct compat_ustat tmp; 3914ada54eeSAl Viro struct kstatfs sbuf; 3924ada54eeSAl Viro int err = vfs_ustat(new_decode_dev(dev), &sbuf); 3934ada54eeSAl Viro if (err) 3944ada54eeSAl Viro return err; 3954ada54eeSAl Viro 3964ada54eeSAl Viro memset(&tmp, 0, sizeof(struct compat_ustat)); 3974ada54eeSAl Viro tmp.f_tfree = sbuf.f_bfree; 3984ada54eeSAl Viro tmp.f_tinode = sbuf.f_ffree; 3994ada54eeSAl Viro if (copy_to_user(u, &tmp, sizeof(struct compat_ustat))) 4004ada54eeSAl Viro return -EFAULT; 4014ada54eeSAl Viro return 0; 4024ada54eeSAl Viro } 4034ada54eeSAl Viro #endif 404