xref: /openbmc/linux/fs/statfs.c (revision 7ed1ee6118ae77330cae2a6d5e9383532f7dfb48)
1*7ed1ee61SAl Viro #include <linux/syscalls.h>
2*7ed1ee61SAl Viro #include <linux/module.h>
3*7ed1ee61SAl Viro #include <linux/fs.h>
4*7ed1ee61SAl Viro #include <linux/file.h>
5*7ed1ee61SAl Viro #include <linux/namei.h>
6*7ed1ee61SAl Viro #include <linux/statfs.h>
7*7ed1ee61SAl Viro #include <linux/security.h>
8*7ed1ee61SAl Viro #include <linux/uaccess.h>
9*7ed1ee61SAl Viro 
10*7ed1ee61SAl Viro int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
11*7ed1ee61SAl Viro {
12*7ed1ee61SAl Viro 	int retval = -ENODEV;
13*7ed1ee61SAl Viro 
14*7ed1ee61SAl Viro 	if (dentry) {
15*7ed1ee61SAl Viro 		retval = -ENOSYS;
16*7ed1ee61SAl Viro 		if (dentry->d_sb->s_op->statfs) {
17*7ed1ee61SAl Viro 			memset(buf, 0, sizeof(*buf));
18*7ed1ee61SAl Viro 			retval = security_sb_statfs(dentry);
19*7ed1ee61SAl Viro 			if (retval)
20*7ed1ee61SAl Viro 				return retval;
21*7ed1ee61SAl Viro 			retval = dentry->d_sb->s_op->statfs(dentry, buf);
22*7ed1ee61SAl Viro 			if (retval == 0 && buf->f_frsize == 0)
23*7ed1ee61SAl Viro 				buf->f_frsize = buf->f_bsize;
24*7ed1ee61SAl Viro 		}
25*7ed1ee61SAl Viro 	}
26*7ed1ee61SAl Viro 	return retval;
27*7ed1ee61SAl Viro }
28*7ed1ee61SAl Viro 
29*7ed1ee61SAl Viro EXPORT_SYMBOL(vfs_statfs);
30*7ed1ee61SAl Viro 
31*7ed1ee61SAl Viro static int vfs_statfs_native(struct dentry *dentry, struct statfs *buf)
32*7ed1ee61SAl Viro {
33*7ed1ee61SAl Viro 	struct kstatfs st;
34*7ed1ee61SAl Viro 	int retval;
35*7ed1ee61SAl Viro 
36*7ed1ee61SAl Viro 	retval = vfs_statfs(dentry, &st);
37*7ed1ee61SAl Viro 	if (retval)
38*7ed1ee61SAl Viro 		return retval;
39*7ed1ee61SAl Viro 
40*7ed1ee61SAl Viro 	if (sizeof(*buf) == sizeof(st))
41*7ed1ee61SAl Viro 		memcpy(buf, &st, sizeof(st));
42*7ed1ee61SAl Viro 	else {
43*7ed1ee61SAl Viro 		if (sizeof buf->f_blocks == 4) {
44*7ed1ee61SAl Viro 			if ((st.f_blocks | st.f_bfree | st.f_bavail |
45*7ed1ee61SAl Viro 			     st.f_bsize | st.f_frsize) &
46*7ed1ee61SAl Viro 			    0xffffffff00000000ULL)
47*7ed1ee61SAl Viro 				return -EOVERFLOW;
48*7ed1ee61SAl Viro 			/*
49*7ed1ee61SAl Viro 			 * f_files and f_ffree may be -1; it's okay to stuff
50*7ed1ee61SAl Viro 			 * that into 32 bits
51*7ed1ee61SAl Viro 			 */
52*7ed1ee61SAl Viro 			if (st.f_files != -1 &&
53*7ed1ee61SAl Viro 			    (st.f_files & 0xffffffff00000000ULL))
54*7ed1ee61SAl Viro 				return -EOVERFLOW;
55*7ed1ee61SAl Viro 			if (st.f_ffree != -1 &&
56*7ed1ee61SAl Viro 			    (st.f_ffree & 0xffffffff00000000ULL))
57*7ed1ee61SAl Viro 				return -EOVERFLOW;
58*7ed1ee61SAl Viro 		}
59*7ed1ee61SAl Viro 
60*7ed1ee61SAl Viro 		buf->f_type = st.f_type;
61*7ed1ee61SAl Viro 		buf->f_bsize = st.f_bsize;
62*7ed1ee61SAl Viro 		buf->f_blocks = st.f_blocks;
63*7ed1ee61SAl Viro 		buf->f_bfree = st.f_bfree;
64*7ed1ee61SAl Viro 		buf->f_bavail = st.f_bavail;
65*7ed1ee61SAl Viro 		buf->f_files = st.f_files;
66*7ed1ee61SAl Viro 		buf->f_ffree = st.f_ffree;
67*7ed1ee61SAl Viro 		buf->f_fsid = st.f_fsid;
68*7ed1ee61SAl Viro 		buf->f_namelen = st.f_namelen;
69*7ed1ee61SAl Viro 		buf->f_frsize = st.f_frsize;
70*7ed1ee61SAl Viro 		memset(buf->f_spare, 0, sizeof(buf->f_spare));
71*7ed1ee61SAl Viro 	}
72*7ed1ee61SAl Viro 	return 0;
73*7ed1ee61SAl Viro }
74*7ed1ee61SAl Viro 
75*7ed1ee61SAl Viro static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf)
76*7ed1ee61SAl Viro {
77*7ed1ee61SAl Viro 	struct kstatfs st;
78*7ed1ee61SAl Viro 	int retval;
79*7ed1ee61SAl Viro 
80*7ed1ee61SAl Viro 	retval = vfs_statfs(dentry, &st);
81*7ed1ee61SAl Viro 	if (retval)
82*7ed1ee61SAl Viro 		return retval;
83*7ed1ee61SAl Viro 
84*7ed1ee61SAl Viro 	if (sizeof(*buf) == sizeof(st))
85*7ed1ee61SAl Viro 		memcpy(buf, &st, sizeof(st));
86*7ed1ee61SAl Viro 	else {
87*7ed1ee61SAl Viro 		buf->f_type = st.f_type;
88*7ed1ee61SAl Viro 		buf->f_bsize = st.f_bsize;
89*7ed1ee61SAl Viro 		buf->f_blocks = st.f_blocks;
90*7ed1ee61SAl Viro 		buf->f_bfree = st.f_bfree;
91*7ed1ee61SAl Viro 		buf->f_bavail = st.f_bavail;
92*7ed1ee61SAl Viro 		buf->f_files = st.f_files;
93*7ed1ee61SAl Viro 		buf->f_ffree = st.f_ffree;
94*7ed1ee61SAl Viro 		buf->f_fsid = st.f_fsid;
95*7ed1ee61SAl Viro 		buf->f_namelen = st.f_namelen;
96*7ed1ee61SAl Viro 		buf->f_frsize = st.f_frsize;
97*7ed1ee61SAl Viro 		memset(buf->f_spare, 0, sizeof(buf->f_spare));
98*7ed1ee61SAl Viro 	}
99*7ed1ee61SAl Viro 	return 0;
100*7ed1ee61SAl Viro }
101*7ed1ee61SAl Viro 
102*7ed1ee61SAl Viro SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf)
103*7ed1ee61SAl Viro {
104*7ed1ee61SAl Viro 	struct path path;
105*7ed1ee61SAl Viro 	int error;
106*7ed1ee61SAl Viro 
107*7ed1ee61SAl Viro 	error = user_path(pathname, &path);
108*7ed1ee61SAl Viro 	if (!error) {
109*7ed1ee61SAl Viro 		struct statfs tmp;
110*7ed1ee61SAl Viro 		error = vfs_statfs_native(path.dentry, &tmp);
111*7ed1ee61SAl Viro 		if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
112*7ed1ee61SAl Viro 			error = -EFAULT;
113*7ed1ee61SAl Viro 		path_put(&path);
114*7ed1ee61SAl Viro 	}
115*7ed1ee61SAl Viro 	return error;
116*7ed1ee61SAl Viro }
117*7ed1ee61SAl Viro 
118*7ed1ee61SAl Viro SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf)
119*7ed1ee61SAl Viro {
120*7ed1ee61SAl Viro 	struct path path;
121*7ed1ee61SAl Viro 	long error;
122*7ed1ee61SAl Viro 
123*7ed1ee61SAl Viro 	if (sz != sizeof(*buf))
124*7ed1ee61SAl Viro 		return -EINVAL;
125*7ed1ee61SAl Viro 	error = user_path(pathname, &path);
126*7ed1ee61SAl Viro 	if (!error) {
127*7ed1ee61SAl Viro 		struct statfs64 tmp;
128*7ed1ee61SAl Viro 		error = vfs_statfs64(path.dentry, &tmp);
129*7ed1ee61SAl Viro 		if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
130*7ed1ee61SAl Viro 			error = -EFAULT;
131*7ed1ee61SAl Viro 		path_put(&path);
132*7ed1ee61SAl Viro 	}
133*7ed1ee61SAl Viro 	return error;
134*7ed1ee61SAl Viro }
135*7ed1ee61SAl Viro 
136*7ed1ee61SAl Viro SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf)
137*7ed1ee61SAl Viro {
138*7ed1ee61SAl Viro 	struct file *file;
139*7ed1ee61SAl Viro 	struct statfs tmp;
140*7ed1ee61SAl Viro 	int error;
141*7ed1ee61SAl Viro 
142*7ed1ee61SAl Viro 	error = -EBADF;
143*7ed1ee61SAl Viro 	file = fget(fd);
144*7ed1ee61SAl Viro 	if (!file)
145*7ed1ee61SAl Viro 		goto out;
146*7ed1ee61SAl Viro 	error = vfs_statfs_native(file->f_path.dentry, &tmp);
147*7ed1ee61SAl Viro 	if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
148*7ed1ee61SAl Viro 		error = -EFAULT;
149*7ed1ee61SAl Viro 	fput(file);
150*7ed1ee61SAl Viro out:
151*7ed1ee61SAl Viro 	return error;
152*7ed1ee61SAl Viro }
153*7ed1ee61SAl Viro 
154*7ed1ee61SAl Viro SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf)
155*7ed1ee61SAl Viro {
156*7ed1ee61SAl Viro 	struct file *file;
157*7ed1ee61SAl Viro 	struct statfs64 tmp;
158*7ed1ee61SAl Viro 	int error;
159*7ed1ee61SAl Viro 
160*7ed1ee61SAl Viro 	if (sz != sizeof(*buf))
161*7ed1ee61SAl Viro 		return -EINVAL;
162*7ed1ee61SAl Viro 
163*7ed1ee61SAl Viro 	error = -EBADF;
164*7ed1ee61SAl Viro 	file = fget(fd);
165*7ed1ee61SAl Viro 	if (!file)
166*7ed1ee61SAl Viro 		goto out;
167*7ed1ee61SAl Viro 	error = vfs_statfs64(file->f_path.dentry, &tmp);
168*7ed1ee61SAl Viro 	if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
169*7ed1ee61SAl Viro 		error = -EFAULT;
170*7ed1ee61SAl Viro 	fput(file);
171*7ed1ee61SAl Viro out:
172*7ed1ee61SAl Viro 	return error;
173*7ed1ee61SAl Viro }
174*7ed1ee61SAl Viro 
175*7ed1ee61SAl Viro SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf)
176*7ed1ee61SAl Viro {
177*7ed1ee61SAl Viro 	struct super_block *s;
178*7ed1ee61SAl Viro 	struct ustat tmp;
179*7ed1ee61SAl Viro 	struct kstatfs sbuf;
180*7ed1ee61SAl Viro 	int err;
181*7ed1ee61SAl Viro 
182*7ed1ee61SAl Viro 	s = user_get_super(new_decode_dev(dev));
183*7ed1ee61SAl Viro 	if (!s)
184*7ed1ee61SAl Viro 		return -EINVAL;
185*7ed1ee61SAl Viro 
186*7ed1ee61SAl Viro 	err = vfs_statfs(s->s_root, &sbuf);
187*7ed1ee61SAl Viro 	drop_super(s);
188*7ed1ee61SAl Viro 	if (err)
189*7ed1ee61SAl Viro 		return err;
190*7ed1ee61SAl Viro 
191*7ed1ee61SAl Viro 	memset(&tmp,0,sizeof(struct ustat));
192*7ed1ee61SAl Viro 	tmp.f_tfree = sbuf.f_bfree;
193*7ed1ee61SAl Viro 	tmp.f_tinode = sbuf.f_ffree;
194*7ed1ee61SAl Viro 
195*7ed1ee61SAl Viro 	return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0;
196*7ed1ee61SAl Viro }
197