18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <linux/syscalls.h> 38c2ecf20Sopenharmony_ci#include <linux/export.h> 48c2ecf20Sopenharmony_ci#include <linux/fs.h> 58c2ecf20Sopenharmony_ci#include <linux/file.h> 68c2ecf20Sopenharmony_ci#include <linux/mount.h> 78c2ecf20Sopenharmony_ci#include <linux/namei.h> 88c2ecf20Sopenharmony_ci#include <linux/statfs.h> 98c2ecf20Sopenharmony_ci#include <linux/security.h> 108c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 118c2ecf20Sopenharmony_ci#include <linux/compat.h> 128c2ecf20Sopenharmony_ci#include "internal.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistatic int flags_by_mnt(int mnt_flags) 158c2ecf20Sopenharmony_ci{ 168c2ecf20Sopenharmony_ci int flags = 0; 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci if (mnt_flags & MNT_READONLY) 198c2ecf20Sopenharmony_ci flags |= ST_RDONLY; 208c2ecf20Sopenharmony_ci if (mnt_flags & MNT_NOSUID) 218c2ecf20Sopenharmony_ci flags |= ST_NOSUID; 228c2ecf20Sopenharmony_ci if (mnt_flags & MNT_NODEV) 238c2ecf20Sopenharmony_ci flags |= ST_NODEV; 248c2ecf20Sopenharmony_ci if (mnt_flags & MNT_NOEXEC) 258c2ecf20Sopenharmony_ci flags |= ST_NOEXEC; 268c2ecf20Sopenharmony_ci if (mnt_flags & MNT_NOATIME) 278c2ecf20Sopenharmony_ci flags |= ST_NOATIME; 288c2ecf20Sopenharmony_ci if (mnt_flags & MNT_NODIRATIME) 298c2ecf20Sopenharmony_ci flags |= ST_NODIRATIME; 308c2ecf20Sopenharmony_ci if (mnt_flags & MNT_RELATIME) 318c2ecf20Sopenharmony_ci flags |= ST_RELATIME; 328c2ecf20Sopenharmony_ci if (mnt_flags & MNT_NOSYMFOLLOW) 338c2ecf20Sopenharmony_ci flags |= ST_NOSYMFOLLOW; 348c2ecf20Sopenharmony_ci return flags; 358c2ecf20Sopenharmony_ci} 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic int flags_by_sb(int s_flags) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci int flags = 0; 408c2ecf20Sopenharmony_ci if (s_flags & SB_SYNCHRONOUS) 418c2ecf20Sopenharmony_ci flags |= ST_SYNCHRONOUS; 428c2ecf20Sopenharmony_ci if (s_flags & SB_MANDLOCK) 438c2ecf20Sopenharmony_ci flags |= ST_MANDLOCK; 448c2ecf20Sopenharmony_ci if (s_flags & SB_RDONLY) 458c2ecf20Sopenharmony_ci flags |= ST_RDONLY; 468c2ecf20Sopenharmony_ci return flags; 478c2ecf20Sopenharmony_ci} 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic int calculate_f_flags(struct vfsmount *mnt) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci return ST_VALID | flags_by_mnt(mnt->mnt_flags) | 528c2ecf20Sopenharmony_ci flags_by_sb(mnt->mnt_sb->s_flags); 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci int retval; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci if (!dentry->d_sb->s_op->statfs) 608c2ecf20Sopenharmony_ci return -ENOSYS; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci memset(buf, 0, sizeof(*buf)); 638c2ecf20Sopenharmony_ci retval = security_sb_statfs(dentry); 648c2ecf20Sopenharmony_ci if (retval) 658c2ecf20Sopenharmony_ci return retval; 668c2ecf20Sopenharmony_ci retval = dentry->d_sb->s_op->statfs(dentry, buf); 678c2ecf20Sopenharmony_ci if (retval == 0 && buf->f_frsize == 0) 688c2ecf20Sopenharmony_ci buf->f_frsize = buf->f_bsize; 698c2ecf20Sopenharmony_ci return retval; 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ciint vfs_get_fsid(struct dentry *dentry, __kernel_fsid_t *fsid) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci struct kstatfs st; 758c2ecf20Sopenharmony_ci int error; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci error = statfs_by_dentry(dentry, &st); 788c2ecf20Sopenharmony_ci if (error) 798c2ecf20Sopenharmony_ci return error; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci *fsid = st.f_fsid; 828c2ecf20Sopenharmony_ci return 0; 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vfs_get_fsid); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ciint vfs_statfs(const struct path *path, struct kstatfs *buf) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci int error; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci error = statfs_by_dentry(path->dentry, buf); 918c2ecf20Sopenharmony_ci if (!error) 928c2ecf20Sopenharmony_ci buf->f_flags = calculate_f_flags(path->mnt); 938c2ecf20Sopenharmony_ci return error; 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vfs_statfs); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ciint user_statfs(const char __user *pathname, struct kstatfs *st) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci struct path path; 1008c2ecf20Sopenharmony_ci int error; 1018c2ecf20Sopenharmony_ci unsigned int lookup_flags = LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT; 1028c2ecf20Sopenharmony_ciretry: 1038c2ecf20Sopenharmony_ci error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); 1048c2ecf20Sopenharmony_ci if (!error) { 1058c2ecf20Sopenharmony_ci error = vfs_statfs(&path, st); 1068c2ecf20Sopenharmony_ci path_put(&path); 1078c2ecf20Sopenharmony_ci if (retry_estale(error, lookup_flags)) { 1088c2ecf20Sopenharmony_ci lookup_flags |= LOOKUP_REVAL; 1098c2ecf20Sopenharmony_ci goto retry; 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci return error; 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ciint fd_statfs(int fd, struct kstatfs *st) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci struct fd f = fdget_raw(fd); 1188c2ecf20Sopenharmony_ci int error = -EBADF; 1198c2ecf20Sopenharmony_ci if (f.file) { 1208c2ecf20Sopenharmony_ci error = vfs_statfs(&f.file->f_path, st); 1218c2ecf20Sopenharmony_ci fdput(f); 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci return error; 1248c2ecf20Sopenharmony_ci} 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_cistatic int do_statfs_native(struct kstatfs *st, struct statfs __user *p) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci struct statfs buf; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci if (sizeof(buf) == sizeof(*st)) 1318c2ecf20Sopenharmony_ci memcpy(&buf, st, sizeof(*st)); 1328c2ecf20Sopenharmony_ci else { 1338c2ecf20Sopenharmony_ci memset(&buf, 0, sizeof(buf)); 1348c2ecf20Sopenharmony_ci if (sizeof buf.f_blocks == 4) { 1358c2ecf20Sopenharmony_ci if ((st->f_blocks | st->f_bfree | st->f_bavail | 1368c2ecf20Sopenharmony_ci st->f_bsize | st->f_frsize) & 1378c2ecf20Sopenharmony_ci 0xffffffff00000000ULL) 1388c2ecf20Sopenharmony_ci return -EOVERFLOW; 1398c2ecf20Sopenharmony_ci /* 1408c2ecf20Sopenharmony_ci * f_files and f_ffree may be -1; it's okay to stuff 1418c2ecf20Sopenharmony_ci * that into 32 bits 1428c2ecf20Sopenharmony_ci */ 1438c2ecf20Sopenharmony_ci if (st->f_files != -1 && 1448c2ecf20Sopenharmony_ci (st->f_files & 0xffffffff00000000ULL)) 1458c2ecf20Sopenharmony_ci return -EOVERFLOW; 1468c2ecf20Sopenharmony_ci if (st->f_ffree != -1 && 1478c2ecf20Sopenharmony_ci (st->f_ffree & 0xffffffff00000000ULL)) 1488c2ecf20Sopenharmony_ci return -EOVERFLOW; 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci buf.f_type = st->f_type; 1528c2ecf20Sopenharmony_ci buf.f_bsize = st->f_bsize; 1538c2ecf20Sopenharmony_ci buf.f_blocks = st->f_blocks; 1548c2ecf20Sopenharmony_ci buf.f_bfree = st->f_bfree; 1558c2ecf20Sopenharmony_ci buf.f_bavail = st->f_bavail; 1568c2ecf20Sopenharmony_ci buf.f_files = st->f_files; 1578c2ecf20Sopenharmony_ci buf.f_ffree = st->f_ffree; 1588c2ecf20Sopenharmony_ci buf.f_fsid = st->f_fsid; 1598c2ecf20Sopenharmony_ci buf.f_namelen = st->f_namelen; 1608c2ecf20Sopenharmony_ci buf.f_frsize = st->f_frsize; 1618c2ecf20Sopenharmony_ci buf.f_flags = st->f_flags; 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci if (copy_to_user(p, &buf, sizeof(buf))) 1648c2ecf20Sopenharmony_ci return -EFAULT; 1658c2ecf20Sopenharmony_ci return 0; 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic int do_statfs64(struct kstatfs *st, struct statfs64 __user *p) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci struct statfs64 buf; 1718c2ecf20Sopenharmony_ci if (sizeof(buf) == sizeof(*st)) 1728c2ecf20Sopenharmony_ci memcpy(&buf, st, sizeof(*st)); 1738c2ecf20Sopenharmony_ci else { 1748c2ecf20Sopenharmony_ci memset(&buf, 0, sizeof(buf)); 1758c2ecf20Sopenharmony_ci buf.f_type = st->f_type; 1768c2ecf20Sopenharmony_ci buf.f_bsize = st->f_bsize; 1778c2ecf20Sopenharmony_ci buf.f_blocks = st->f_blocks; 1788c2ecf20Sopenharmony_ci buf.f_bfree = st->f_bfree; 1798c2ecf20Sopenharmony_ci buf.f_bavail = st->f_bavail; 1808c2ecf20Sopenharmony_ci buf.f_files = st->f_files; 1818c2ecf20Sopenharmony_ci buf.f_ffree = st->f_ffree; 1828c2ecf20Sopenharmony_ci buf.f_fsid = st->f_fsid; 1838c2ecf20Sopenharmony_ci buf.f_namelen = st->f_namelen; 1848c2ecf20Sopenharmony_ci buf.f_frsize = st->f_frsize; 1858c2ecf20Sopenharmony_ci buf.f_flags = st->f_flags; 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci if (copy_to_user(p, &buf, sizeof(buf))) 1888c2ecf20Sopenharmony_ci return -EFAULT; 1898c2ecf20Sopenharmony_ci return 0; 1908c2ecf20Sopenharmony_ci} 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ciSYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci struct kstatfs st; 1958c2ecf20Sopenharmony_ci int error = user_statfs(pathname, &st); 1968c2ecf20Sopenharmony_ci if (!error) 1978c2ecf20Sopenharmony_ci error = do_statfs_native(&st, buf); 1988c2ecf20Sopenharmony_ci return error; 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ciSYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci struct kstatfs st; 2048c2ecf20Sopenharmony_ci int error; 2058c2ecf20Sopenharmony_ci if (sz != sizeof(*buf)) 2068c2ecf20Sopenharmony_ci return -EINVAL; 2078c2ecf20Sopenharmony_ci error = user_statfs(pathname, &st); 2088c2ecf20Sopenharmony_ci if (!error) 2098c2ecf20Sopenharmony_ci error = do_statfs64(&st, buf); 2108c2ecf20Sopenharmony_ci return error; 2118c2ecf20Sopenharmony_ci} 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ciSYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf) 2148c2ecf20Sopenharmony_ci{ 2158c2ecf20Sopenharmony_ci struct kstatfs st; 2168c2ecf20Sopenharmony_ci int error = fd_statfs(fd, &st); 2178c2ecf20Sopenharmony_ci if (!error) 2188c2ecf20Sopenharmony_ci error = do_statfs_native(&st, buf); 2198c2ecf20Sopenharmony_ci return error; 2208c2ecf20Sopenharmony_ci} 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ciSYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci struct kstatfs st; 2258c2ecf20Sopenharmony_ci int error; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci if (sz != sizeof(*buf)) 2288c2ecf20Sopenharmony_ci return -EINVAL; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci error = fd_statfs(fd, &st); 2318c2ecf20Sopenharmony_ci if (!error) 2328c2ecf20Sopenharmony_ci error = do_statfs64(&st, buf); 2338c2ecf20Sopenharmony_ci return error; 2348c2ecf20Sopenharmony_ci} 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_cistatic int vfs_ustat(dev_t dev, struct kstatfs *sbuf) 2378c2ecf20Sopenharmony_ci{ 2388c2ecf20Sopenharmony_ci struct super_block *s = user_get_super(dev); 2398c2ecf20Sopenharmony_ci int err; 2408c2ecf20Sopenharmony_ci if (!s) 2418c2ecf20Sopenharmony_ci return -EINVAL; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci err = statfs_by_dentry(s->s_root, sbuf); 2448c2ecf20Sopenharmony_ci drop_super(s); 2458c2ecf20Sopenharmony_ci return err; 2468c2ecf20Sopenharmony_ci} 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ciSYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf) 2498c2ecf20Sopenharmony_ci{ 2508c2ecf20Sopenharmony_ci struct ustat tmp; 2518c2ecf20Sopenharmony_ci struct kstatfs sbuf; 2528c2ecf20Sopenharmony_ci int err = vfs_ustat(new_decode_dev(dev), &sbuf); 2538c2ecf20Sopenharmony_ci if (err) 2548c2ecf20Sopenharmony_ci return err; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci memset(&tmp,0,sizeof(struct ustat)); 2578c2ecf20Sopenharmony_ci tmp.f_tfree = sbuf.f_bfree; 2588c2ecf20Sopenharmony_ci tmp.f_tinode = sbuf.f_ffree; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0; 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT 2648c2ecf20Sopenharmony_cistatic int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci struct compat_statfs buf; 2678c2ecf20Sopenharmony_ci if (sizeof ubuf->f_blocks == 4) { 2688c2ecf20Sopenharmony_ci if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail | 2698c2ecf20Sopenharmony_ci kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL) 2708c2ecf20Sopenharmony_ci return -EOVERFLOW; 2718c2ecf20Sopenharmony_ci /* f_files and f_ffree may be -1; it's okay 2728c2ecf20Sopenharmony_ci * to stuff that into 32 bits */ 2738c2ecf20Sopenharmony_ci if (kbuf->f_files != 0xffffffffffffffffULL 2748c2ecf20Sopenharmony_ci && (kbuf->f_files & 0xffffffff00000000ULL)) 2758c2ecf20Sopenharmony_ci return -EOVERFLOW; 2768c2ecf20Sopenharmony_ci if (kbuf->f_ffree != 0xffffffffffffffffULL 2778c2ecf20Sopenharmony_ci && (kbuf->f_ffree & 0xffffffff00000000ULL)) 2788c2ecf20Sopenharmony_ci return -EOVERFLOW; 2798c2ecf20Sopenharmony_ci } 2808c2ecf20Sopenharmony_ci memset(&buf, 0, sizeof(struct compat_statfs)); 2818c2ecf20Sopenharmony_ci buf.f_type = kbuf->f_type; 2828c2ecf20Sopenharmony_ci buf.f_bsize = kbuf->f_bsize; 2838c2ecf20Sopenharmony_ci buf.f_blocks = kbuf->f_blocks; 2848c2ecf20Sopenharmony_ci buf.f_bfree = kbuf->f_bfree; 2858c2ecf20Sopenharmony_ci buf.f_bavail = kbuf->f_bavail; 2868c2ecf20Sopenharmony_ci buf.f_files = kbuf->f_files; 2878c2ecf20Sopenharmony_ci buf.f_ffree = kbuf->f_ffree; 2888c2ecf20Sopenharmony_ci buf.f_namelen = kbuf->f_namelen; 2898c2ecf20Sopenharmony_ci buf.f_fsid.val[0] = kbuf->f_fsid.val[0]; 2908c2ecf20Sopenharmony_ci buf.f_fsid.val[1] = kbuf->f_fsid.val[1]; 2918c2ecf20Sopenharmony_ci buf.f_frsize = kbuf->f_frsize; 2928c2ecf20Sopenharmony_ci buf.f_flags = kbuf->f_flags; 2938c2ecf20Sopenharmony_ci if (copy_to_user(ubuf, &buf, sizeof(struct compat_statfs))) 2948c2ecf20Sopenharmony_ci return -EFAULT; 2958c2ecf20Sopenharmony_ci return 0; 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci/* 2998c2ecf20Sopenharmony_ci * The following statfs calls are copies of code from fs/statfs.c and 3008c2ecf20Sopenharmony_ci * should be checked against those from time to time 3018c2ecf20Sopenharmony_ci */ 3028c2ecf20Sopenharmony_ciCOMPAT_SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct compat_statfs __user *, buf) 3038c2ecf20Sopenharmony_ci{ 3048c2ecf20Sopenharmony_ci struct kstatfs tmp; 3058c2ecf20Sopenharmony_ci int error = user_statfs(pathname, &tmp); 3068c2ecf20Sopenharmony_ci if (!error) 3078c2ecf20Sopenharmony_ci error = put_compat_statfs(buf, &tmp); 3088c2ecf20Sopenharmony_ci return error; 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ciCOMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *, buf) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci struct kstatfs tmp; 3148c2ecf20Sopenharmony_ci int error = fd_statfs(fd, &tmp); 3158c2ecf20Sopenharmony_ci if (!error) 3168c2ecf20Sopenharmony_ci error = put_compat_statfs(buf, &tmp); 3178c2ecf20Sopenharmony_ci return error; 3188c2ecf20Sopenharmony_ci} 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_cistatic int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci struct compat_statfs64 buf; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci if ((kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL) 3258c2ecf20Sopenharmony_ci return -EOVERFLOW; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci memset(&buf, 0, sizeof(struct compat_statfs64)); 3288c2ecf20Sopenharmony_ci buf.f_type = kbuf->f_type; 3298c2ecf20Sopenharmony_ci buf.f_bsize = kbuf->f_bsize; 3308c2ecf20Sopenharmony_ci buf.f_blocks = kbuf->f_blocks; 3318c2ecf20Sopenharmony_ci buf.f_bfree = kbuf->f_bfree; 3328c2ecf20Sopenharmony_ci buf.f_bavail = kbuf->f_bavail; 3338c2ecf20Sopenharmony_ci buf.f_files = kbuf->f_files; 3348c2ecf20Sopenharmony_ci buf.f_ffree = kbuf->f_ffree; 3358c2ecf20Sopenharmony_ci buf.f_namelen = kbuf->f_namelen; 3368c2ecf20Sopenharmony_ci buf.f_fsid.val[0] = kbuf->f_fsid.val[0]; 3378c2ecf20Sopenharmony_ci buf.f_fsid.val[1] = kbuf->f_fsid.val[1]; 3388c2ecf20Sopenharmony_ci buf.f_frsize = kbuf->f_frsize; 3398c2ecf20Sopenharmony_ci buf.f_flags = kbuf->f_flags; 3408c2ecf20Sopenharmony_ci if (copy_to_user(ubuf, &buf, sizeof(struct compat_statfs64))) 3418c2ecf20Sopenharmony_ci return -EFAULT; 3428c2ecf20Sopenharmony_ci return 0; 3438c2ecf20Sopenharmony_ci} 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ciint kcompat_sys_statfs64(const char __user * pathname, compat_size_t sz, struct compat_statfs64 __user * buf) 3468c2ecf20Sopenharmony_ci{ 3478c2ecf20Sopenharmony_ci struct kstatfs tmp; 3488c2ecf20Sopenharmony_ci int error; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci if (sz != sizeof(*buf)) 3518c2ecf20Sopenharmony_ci return -EINVAL; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci error = user_statfs(pathname, &tmp); 3548c2ecf20Sopenharmony_ci if (!error) 3558c2ecf20Sopenharmony_ci error = put_compat_statfs64(buf, &tmp); 3568c2ecf20Sopenharmony_ci return error; 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ciCOMPAT_SYSCALL_DEFINE3(statfs64, const char __user *, pathname, compat_size_t, sz, struct compat_statfs64 __user *, buf) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci return kcompat_sys_statfs64(pathname, sz, buf); 3628c2ecf20Sopenharmony_ci} 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ciint kcompat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user * buf) 3658c2ecf20Sopenharmony_ci{ 3668c2ecf20Sopenharmony_ci struct kstatfs tmp; 3678c2ecf20Sopenharmony_ci int error; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci if (sz != sizeof(*buf)) 3708c2ecf20Sopenharmony_ci return -EINVAL; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci error = fd_statfs(fd, &tmp); 3738c2ecf20Sopenharmony_ci if (!error) 3748c2ecf20Sopenharmony_ci error = put_compat_statfs64(buf, &tmp); 3758c2ecf20Sopenharmony_ci return error; 3768c2ecf20Sopenharmony_ci} 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ciCOMPAT_SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, compat_size_t, sz, struct compat_statfs64 __user *, buf) 3798c2ecf20Sopenharmony_ci{ 3808c2ecf20Sopenharmony_ci return kcompat_sys_fstatfs64(fd, sz, buf); 3818c2ecf20Sopenharmony_ci} 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci/* 3848c2ecf20Sopenharmony_ci * This is a copy of sys_ustat, just dealing with a structure layout. 3858c2ecf20Sopenharmony_ci * Given how simple this syscall is that apporach is more maintainable 3868c2ecf20Sopenharmony_ci * than the various conversion hacks. 3878c2ecf20Sopenharmony_ci */ 3888c2ecf20Sopenharmony_ciCOMPAT_SYSCALL_DEFINE2(ustat, unsigned, dev, struct compat_ustat __user *, u) 3898c2ecf20Sopenharmony_ci{ 3908c2ecf20Sopenharmony_ci struct compat_ustat tmp; 3918c2ecf20Sopenharmony_ci struct kstatfs sbuf; 3928c2ecf20Sopenharmony_ci int err = vfs_ustat(new_decode_dev(dev), &sbuf); 3938c2ecf20Sopenharmony_ci if (err) 3948c2ecf20Sopenharmony_ci return err; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci memset(&tmp, 0, sizeof(struct compat_ustat)); 3978c2ecf20Sopenharmony_ci tmp.f_tfree = sbuf.f_bfree; 3988c2ecf20Sopenharmony_ci tmp.f_tinode = sbuf.f_ffree; 3998c2ecf20Sopenharmony_ci if (copy_to_user(u, &tmp, sizeof(struct compat_ustat))) 4008c2ecf20Sopenharmony_ci return -EFAULT; 4018c2ecf20Sopenharmony_ci return 0; 4028c2ecf20Sopenharmony_ci} 4038c2ecf20Sopenharmony_ci#endif 404