xref: /openbmc/linux/fs/statfs.c (revision ed40866e)
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 
flags_by_mnt(int mnt_flags)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 
flags_by_sb(int s_flags)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 
calculate_f_flags(struct vfsmount * mnt)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 
statfs_by_dentry(struct dentry * dentry,struct kstatfs * buf)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 
vfs_get_fsid(struct dentry * dentry,__kernel_fsid_t * fsid)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 
vfs_statfs(const struct path * path,struct kstatfs * buf)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 
user_statfs(const char __user * pathname,struct kstatfs * st)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 
fd_statfs(int fd,struct kstatfs * st)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 
do_statfs_native(struct kstatfs * st,struct statfs __user * p)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 {
133*ed40866eSIlya Leoshkevich 		memset(&buf, 0, sizeof(buf));
134c8b91accSAl Viro 		if (sizeof buf.f_blocks == 4) {
135c8b91accSAl Viro 			if ((st->f_blocks | st->f_bfree | st->f_bavail |
136c8b91accSAl Viro 			     st->f_bsize | st->f_frsize) &
1377ed1ee61SAl Viro 			    0xffffffff00000000ULL)
1387ed1ee61SAl Viro 				return -EOVERFLOW;
1397ed1ee61SAl Viro 			/*
1407ed1ee61SAl Viro 			 * f_files and f_ffree may be -1; it's okay to stuff
1417ed1ee61SAl Viro 			 * that into 32 bits
1427ed1ee61SAl Viro 			 */
143c8b91accSAl Viro 			if (st->f_files != -1 &&
144c8b91accSAl Viro 			    (st->f_files & 0xffffffff00000000ULL))
1457ed1ee61SAl Viro 				return -EOVERFLOW;
146c8b91accSAl Viro 			if (st->f_ffree != -1 &&
147c8b91accSAl Viro 			    (st->f_ffree & 0xffffffff00000000ULL))
1487ed1ee61SAl Viro 				return -EOVERFLOW;
1497ed1ee61SAl Viro 		}
1507ed1ee61SAl Viro 
151c8b91accSAl Viro 		buf.f_type = st->f_type;
152c8b91accSAl Viro 		buf.f_bsize = st->f_bsize;
153c8b91accSAl Viro 		buf.f_blocks = st->f_blocks;
154c8b91accSAl Viro 		buf.f_bfree = st->f_bfree;
155c8b91accSAl Viro 		buf.f_bavail = st->f_bavail;
156c8b91accSAl Viro 		buf.f_files = st->f_files;
157c8b91accSAl Viro 		buf.f_ffree = st->f_ffree;
158c8b91accSAl Viro 		buf.f_fsid = st->f_fsid;
159c8b91accSAl Viro 		buf.f_namelen = st->f_namelen;
160c8b91accSAl Viro 		buf.f_frsize = st->f_frsize;
161c8b91accSAl Viro 		buf.f_flags = st->f_flags;
1627ed1ee61SAl Viro 	}
163c8b91accSAl Viro 	if (copy_to_user(p, &buf, sizeof(buf)))
164c8b91accSAl Viro 		return -EFAULT;
1657ed1ee61SAl Viro 	return 0;
1667ed1ee61SAl Viro }
1677ed1ee61SAl Viro 
do_statfs64(struct kstatfs * st,struct statfs64 __user * p)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 {
174*ed40866eSIlya Leoshkevich 		memset(&buf, 0, sizeof(buf));
175c8b91accSAl Viro 		buf.f_type = st->f_type;
176c8b91accSAl Viro 		buf.f_bsize = st->f_bsize;
177c8b91accSAl Viro 		buf.f_blocks = st->f_blocks;
178c8b91accSAl Viro 		buf.f_bfree = st->f_bfree;
179c8b91accSAl Viro 		buf.f_bavail = st->f_bavail;
180c8b91accSAl Viro 		buf.f_files = st->f_files;
181c8b91accSAl Viro 		buf.f_ffree = st->f_ffree;
182c8b91accSAl Viro 		buf.f_fsid = st->f_fsid;
183c8b91accSAl Viro 		buf.f_namelen = st->f_namelen;
184c8b91accSAl Viro 		buf.f_frsize = st->f_frsize;
185c8b91accSAl Viro 		buf.f_flags = st->f_flags;
1867ed1ee61SAl Viro 	}
187c8b91accSAl Viro 	if (copy_to_user(p, &buf, sizeof(buf)))
188c8b91accSAl Viro 		return -EFAULT;
1897ed1ee61SAl Viro 	return 0;
1907ed1ee61SAl Viro }
1917ed1ee61SAl Viro 
SYSCALL_DEFINE2(statfs,const char __user *,pathname,struct statfs __user *,buf)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 
SYSCALL_DEFINE3(statfs64,const char __user *,pathname,size_t,sz,struct statfs64 __user *,buf)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 
SYSCALL_DEFINE2(fstatfs,unsigned int,fd,struct statfs __user *,buf)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 
SYSCALL_DEFINE3(fstatfs64,unsigned int,fd,size_t,sz,struct statfs64 __user *,buf)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 
vfs_ustat(dev_t dev,struct kstatfs * sbuf)23653fd88abSAl Viro static int vfs_ustat(dev_t dev, struct kstatfs *sbuf)
2377ed1ee61SAl Viro {
2384e7b5671SChristoph 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 
SYSCALL_DEFINE2(ustat,unsigned,dev,struct ustat __user *,ubuf)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;
25896c0a6a7SHeiko Carstens 	if (IS_ENABLED(CONFIG_ARCH_32BIT_USTAT_F_TINODE))
25996c0a6a7SHeiko Carstens 		tmp.f_tinode = min_t(u64, sbuf.f_ffree, UINT_MAX);
26096c0a6a7SHeiko Carstens 	else
2617ed1ee61SAl Viro 		tmp.f_tinode = sbuf.f_ffree;
2627ed1ee61SAl Viro 
2637ed1ee61SAl Viro 	return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0;
2647ed1ee61SAl Viro }
2654ada54eeSAl Viro 
2664ada54eeSAl Viro #ifdef CONFIG_COMPAT
put_compat_statfs(struct compat_statfs __user * ubuf,struct kstatfs * kbuf)2674ada54eeSAl Viro static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf)
2684ada54eeSAl Viro {
269ae2a9762SAl Viro 	struct compat_statfs buf;
2704ada54eeSAl Viro 	if (sizeof ubuf->f_blocks == 4) {
2714ada54eeSAl Viro 		if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail |
2724ada54eeSAl Viro 		     kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
2734ada54eeSAl Viro 			return -EOVERFLOW;
2744ada54eeSAl Viro 		/* f_files and f_ffree may be -1; it's okay
2754ada54eeSAl Viro 		 * to stuff that into 32 bits */
2764ada54eeSAl Viro 		if (kbuf->f_files != 0xffffffffffffffffULL
2774ada54eeSAl Viro 		 && (kbuf->f_files & 0xffffffff00000000ULL))
2784ada54eeSAl Viro 			return -EOVERFLOW;
2794ada54eeSAl Viro 		if (kbuf->f_ffree != 0xffffffffffffffffULL
2804ada54eeSAl Viro 		 && (kbuf->f_ffree & 0xffffffff00000000ULL))
2814ada54eeSAl Viro 			return -EOVERFLOW;
2824ada54eeSAl Viro 	}
283ae2a9762SAl Viro 	memset(&buf, 0, sizeof(struct compat_statfs));
284ae2a9762SAl Viro 	buf.f_type = kbuf->f_type;
285ae2a9762SAl Viro 	buf.f_bsize = kbuf->f_bsize;
286ae2a9762SAl Viro 	buf.f_blocks = kbuf->f_blocks;
287ae2a9762SAl Viro 	buf.f_bfree = kbuf->f_bfree;
288ae2a9762SAl Viro 	buf.f_bavail = kbuf->f_bavail;
289ae2a9762SAl Viro 	buf.f_files = kbuf->f_files;
290ae2a9762SAl Viro 	buf.f_ffree = kbuf->f_ffree;
291ae2a9762SAl Viro 	buf.f_namelen = kbuf->f_namelen;
292ae2a9762SAl Viro 	buf.f_fsid.val[0] = kbuf->f_fsid.val[0];
293ae2a9762SAl Viro 	buf.f_fsid.val[1] = kbuf->f_fsid.val[1];
294ae2a9762SAl Viro 	buf.f_frsize = kbuf->f_frsize;
295ae2a9762SAl Viro 	buf.f_flags = kbuf->f_flags;
296ae2a9762SAl Viro 	if (copy_to_user(ubuf, &buf, sizeof(struct compat_statfs)))
2974ada54eeSAl Viro 		return -EFAULT;
2984ada54eeSAl Viro 	return 0;
2994ada54eeSAl Viro }
3004ada54eeSAl Viro 
3014ada54eeSAl Viro /*
3024ada54eeSAl Viro  * The following statfs calls are copies of code from fs/statfs.c and
3034ada54eeSAl Viro  * should be checked against those from time to time
3044ada54eeSAl Viro  */
COMPAT_SYSCALL_DEFINE2(statfs,const char __user *,pathname,struct compat_statfs __user *,buf)3054ada54eeSAl Viro COMPAT_SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct compat_statfs __user *, buf)
3064ada54eeSAl Viro {
3074ada54eeSAl Viro 	struct kstatfs tmp;
3084ada54eeSAl Viro 	int error = user_statfs(pathname, &tmp);
3094ada54eeSAl Viro 	if (!error)
3104ada54eeSAl Viro 		error = put_compat_statfs(buf, &tmp);
3114ada54eeSAl Viro 	return error;
3124ada54eeSAl Viro }
3134ada54eeSAl Viro 
COMPAT_SYSCALL_DEFINE2(fstatfs,unsigned int,fd,struct compat_statfs __user *,buf)3144ada54eeSAl Viro COMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *, buf)
3154ada54eeSAl Viro {
3164ada54eeSAl Viro 	struct kstatfs tmp;
3174ada54eeSAl Viro 	int error = fd_statfs(fd, &tmp);
3184ada54eeSAl Viro 	if (!error)
3194ada54eeSAl Viro 		error = put_compat_statfs(buf, &tmp);
3204ada54eeSAl Viro 	return error;
3214ada54eeSAl Viro }
3224ada54eeSAl Viro 
put_compat_statfs64(struct compat_statfs64 __user * ubuf,struct kstatfs * kbuf)3234ada54eeSAl Viro static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf)
3244ada54eeSAl Viro {
325ae2a9762SAl Viro 	struct compat_statfs64 buf;
326cc3a7bfeSEric Sandeen 
327cc3a7bfeSEric Sandeen 	if ((kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
3284ada54eeSAl Viro 		return -EOVERFLOW;
329cc3a7bfeSEric Sandeen 
330ae2a9762SAl Viro 	memset(&buf, 0, sizeof(struct compat_statfs64));
331ae2a9762SAl Viro 	buf.f_type = kbuf->f_type;
332ae2a9762SAl Viro 	buf.f_bsize = kbuf->f_bsize;
333ae2a9762SAl Viro 	buf.f_blocks = kbuf->f_blocks;
334ae2a9762SAl Viro 	buf.f_bfree = kbuf->f_bfree;
335ae2a9762SAl Viro 	buf.f_bavail = kbuf->f_bavail;
336ae2a9762SAl Viro 	buf.f_files = kbuf->f_files;
337ae2a9762SAl Viro 	buf.f_ffree = kbuf->f_ffree;
338ae2a9762SAl Viro 	buf.f_namelen = kbuf->f_namelen;
339ae2a9762SAl Viro 	buf.f_fsid.val[0] = kbuf->f_fsid.val[0];
340ae2a9762SAl Viro 	buf.f_fsid.val[1] = kbuf->f_fsid.val[1];
341ae2a9762SAl Viro 	buf.f_frsize = kbuf->f_frsize;
342ae2a9762SAl Viro 	buf.f_flags = kbuf->f_flags;
343ae2a9762SAl Viro 	if (copy_to_user(ubuf, &buf, sizeof(struct compat_statfs64)))
3444ada54eeSAl Viro 		return -EFAULT;
3454ada54eeSAl Viro 	return 0;
3464ada54eeSAl Viro }
3474ada54eeSAl Viro 
kcompat_sys_statfs64(const char __user * pathname,compat_size_t sz,struct compat_statfs64 __user * buf)3489b54bf9dSMark Rutland int kcompat_sys_statfs64(const char __user * pathname, compat_size_t sz, struct compat_statfs64 __user * buf)
3494ada54eeSAl Viro {
3504ada54eeSAl Viro 	struct kstatfs tmp;
3514ada54eeSAl Viro 	int error;
3524ada54eeSAl Viro 
3534ada54eeSAl Viro 	if (sz != sizeof(*buf))
3544ada54eeSAl Viro 		return -EINVAL;
3554ada54eeSAl Viro 
3564ada54eeSAl Viro 	error = user_statfs(pathname, &tmp);
3574ada54eeSAl Viro 	if (!error)
3584ada54eeSAl Viro 		error = put_compat_statfs64(buf, &tmp);
3594ada54eeSAl Viro 	return error;
3604ada54eeSAl Viro }
3614ada54eeSAl Viro 
COMPAT_SYSCALL_DEFINE3(statfs64,const char __user *,pathname,compat_size_t,sz,struct compat_statfs64 __user *,buf)3629b54bf9dSMark Rutland COMPAT_SYSCALL_DEFINE3(statfs64, const char __user *, pathname, compat_size_t, sz, struct compat_statfs64 __user *, buf)
3639b54bf9dSMark Rutland {
3649b54bf9dSMark Rutland 	return kcompat_sys_statfs64(pathname, sz, buf);
3659b54bf9dSMark Rutland }
3669b54bf9dSMark Rutland 
kcompat_sys_fstatfs64(unsigned int fd,compat_size_t sz,struct compat_statfs64 __user * buf)3679b54bf9dSMark Rutland int kcompat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user * buf)
3684ada54eeSAl Viro {
3694ada54eeSAl Viro 	struct kstatfs tmp;
3704ada54eeSAl Viro 	int error;
3714ada54eeSAl Viro 
3724ada54eeSAl Viro 	if (sz != sizeof(*buf))
3734ada54eeSAl Viro 		return -EINVAL;
3744ada54eeSAl Viro 
3754ada54eeSAl Viro 	error = fd_statfs(fd, &tmp);
3764ada54eeSAl Viro 	if (!error)
3774ada54eeSAl Viro 		error = put_compat_statfs64(buf, &tmp);
3784ada54eeSAl Viro 	return error;
3794ada54eeSAl Viro }
3804ada54eeSAl Viro 
COMPAT_SYSCALL_DEFINE3(fstatfs64,unsigned int,fd,compat_size_t,sz,struct compat_statfs64 __user *,buf)3819b54bf9dSMark Rutland COMPAT_SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, compat_size_t, sz, struct compat_statfs64 __user *, buf)
3829b54bf9dSMark Rutland {
3839b54bf9dSMark Rutland 	return kcompat_sys_fstatfs64(fd, sz, buf);
3849b54bf9dSMark Rutland }
3859b54bf9dSMark Rutland 
3864ada54eeSAl Viro /*
3874ada54eeSAl Viro  * This is a copy of sys_ustat, just dealing with a structure layout.
3884ada54eeSAl Viro  * Given how simple this syscall is that apporach is more maintainable
3894ada54eeSAl Viro  * than the various conversion hacks.
3904ada54eeSAl Viro  */
COMPAT_SYSCALL_DEFINE2(ustat,unsigned,dev,struct compat_ustat __user *,u)3914ada54eeSAl Viro COMPAT_SYSCALL_DEFINE2(ustat, unsigned, dev, struct compat_ustat __user *, u)
3924ada54eeSAl Viro {
3934ada54eeSAl Viro 	struct compat_ustat tmp;
3944ada54eeSAl Viro 	struct kstatfs sbuf;
3954ada54eeSAl Viro 	int err = vfs_ustat(new_decode_dev(dev), &sbuf);
3964ada54eeSAl Viro 	if (err)
3974ada54eeSAl Viro 		return err;
3984ada54eeSAl Viro 
3994ada54eeSAl Viro 	memset(&tmp, 0, sizeof(struct compat_ustat));
4004ada54eeSAl Viro 	tmp.f_tfree = sbuf.f_bfree;
4014ada54eeSAl Viro 	tmp.f_tinode = sbuf.f_ffree;
4024ada54eeSAl Viro 	if (copy_to_user(u, &tmp, sizeof(struct compat_ustat)))
4034ada54eeSAl Viro 		return -EFAULT;
4044ada54eeSAl Viro 	return 0;
4054ada54eeSAl Viro }
4064ada54eeSAl Viro #endif
407