Branch data Line data Source code
1 : : #include <linux/syscalls.h>
2 : : #include <linux/export.h>
3 : : #include <linux/fs.h>
4 : : #include <linux/file.h>
5 : : #include <linux/mount.h>
6 : : #include <linux/namei.h>
7 : : #include <linux/statfs.h>
8 : : #include <linux/security.h>
9 : : #include <linux/uaccess.h>
10 : : #include "internal.h"
11 : :
12 : 0 : static int flags_by_mnt(int mnt_flags)
13 : : {
14 : : int flags = 0;
15 : :
16 [ - + ]: 8241 : if (mnt_flags & MNT_READONLY)
17 : : flags |= ST_RDONLY;
18 [ + + ]: 8241 : if (mnt_flags & MNT_NOSUID)
19 : 2 : flags |= ST_NOSUID;
20 [ - + ]: 8241 : if (mnt_flags & MNT_NODEV)
21 : 0 : flags |= ST_NODEV;
22 [ + + ]: 8241 : if (mnt_flags & MNT_NOEXEC)
23 : 2 : flags |= ST_NOEXEC;
24 [ # # ]: 8241 : if (mnt_flags & MNT_NOATIME)
25 : 0 : flags |= ST_NOATIME;
26 [ # # ]: 0 : if (mnt_flags & MNT_NODIRATIME)
27 : 0 : flags |= ST_NODIRATIME;
28 [ # # ]: 0 : if (mnt_flags & MNT_RELATIME)
29 : 8241 : flags |= ST_RELATIME;
30 : 0 : return flags;
31 : : }
32 : :
33 : : static int flags_by_sb(int s_flags)
34 : : {
35 : : int flags = 0;
36 [ - + ]: 8241 : if (s_flags & MS_SYNCHRONOUS)
37 : : flags |= ST_SYNCHRONOUS;
38 [ + ]: 8241 : if (s_flags & MS_MANDLOCK)
39 : 4 : flags |= ST_MANDLOCK;
40 : : return flags;
41 : : }
42 : :
43 : 0 : static int calculate_f_flags(struct vfsmount *mnt)
44 : : {
45 : 8241 : return ST_VALID | flags_by_mnt(mnt->mnt_flags) |
46 : 8241 : flags_by_sb(mnt->mnt_sb->s_flags);
47 : : }
48 : :
49 : 0 : static int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
50 : : {
51 : : int retval;
52 : :
53 [ + + ]: 8243 : if (!dentry->d_sb->s_op->statfs)
54 : : return -ENOSYS;
55 : :
56 : 8242 : memset(buf, 0, sizeof(*buf));
57 : 8243 : retval = security_sb_statfs(dentry);
58 [ + ]: 8242 : if (retval)
59 : : return retval;
60 : 8243 : retval = dentry->d_sb->s_op->statfs(dentry, buf);
61 [ + - ][ + - ]: 16486 : if (retval == 0 && buf->f_frsize == 0)
62 : 8243 : buf->f_frsize = buf->f_bsize;
63 : 8243 : return retval;
64 : : }
65 : :
66 : 0 : int vfs_statfs(struct path *path, struct kstatfs *buf)
67 : : {
68 : : int error;
69 : :
70 : 8241 : error = statfs_by_dentry(path->dentry, buf);
71 [ + - ]: 8241 : if (!error)
72 : 8241 : buf->f_flags = calculate_f_flags(path->mnt);
73 : 0 : return error;
74 : : }
75 : : EXPORT_SYMBOL(vfs_statfs);
76 : :
77 : 16370 : int user_statfs(const char __user *pathname, struct kstatfs *st)
78 : : {
79 : : struct path path;
80 : : int error;
81 : : unsigned int lookup_flags = LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT;
82 : : retry:
83 : 16370 : error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
84 [ + + ]: 16370 : if (!error) {
85 : 8232 : error = vfs_statfs(&path, st);
86 : 8232 : path_put(&path);
87 [ - ]: 8232 : if (retry_estale(error, lookup_flags)) {
88 : : lookup_flags |= LOOKUP_REVAL;
89 : : goto retry;
90 : : }
91 : : }
92 : 0 : return error;
93 : : }
94 : :
95 : 0 : int fd_statfs(int fd, struct kstatfs *st)
96 : : {
97 : 10 : struct fd f = fdget_raw(fd);
98 : : int error = -EBADF;
99 [ + + ]: 10 : if (f.file) {
100 : 8 : error = vfs_statfs(&f.file->f_path, st);
101 : : fdput(f);
102 : : }
103 : 0 : return error;
104 : : }
105 : :
106 : 0 : static int do_statfs_native(struct kstatfs *st, struct statfs __user *p)
107 : : {
108 : : struct statfs buf;
109 : :
110 : : if (sizeof(buf) == sizeof(*st))
111 : : memcpy(&buf, st, sizeof(*st));
112 : : else {
113 : : if (sizeof buf.f_blocks == 4) {
114 [ + - ]: 100 : if ((st->f_blocks | st->f_bfree | st->f_bavail |
115 : 200 : st->f_bsize | st->f_frsize) &
116 : : 0xffffffff00000000ULL)
117 : : return -EOVERFLOW;
118 : : /*
119 : : * f_files and f_ffree may be -1; it's okay to stuff
120 : : * that into 32 bits
121 : : */
122 [ + - ][ + - ]: 100 : if (st->f_files != -1 &&
123 : 100 : (st->f_files & 0xffffffff00000000ULL))
124 : : return -EOVERFLOW;
125 [ + - ][ + - ]: 100 : if (st->f_ffree != -1 &&
126 : 100 : (st->f_ffree & 0xffffffff00000000ULL))
127 : : return -EOVERFLOW;
128 : : }
129 : :
130 : 100 : buf.f_type = st->f_type;
131 : 100 : buf.f_bsize = st->f_bsize;
132 : 100 : buf.f_blocks = st->f_blocks;
133 : 100 : buf.f_bfree = st->f_bfree;
134 : 100 : buf.f_bavail = st->f_bavail;
135 : 100 : buf.f_files = st->f_files;
136 : 100 : buf.f_ffree = st->f_ffree;
137 : 100 : buf.f_fsid = st->f_fsid;
138 : 100 : buf.f_namelen = st->f_namelen;
139 : 100 : buf.f_frsize = st->f_frsize;
140 : 100 : buf.f_flags = st->f_flags;
141 : 100 : memset(buf.f_spare, 0, sizeof(buf.f_spare));
142 : : }
143 [ + + ]: 200 : if (copy_to_user(p, &buf, sizeof(buf)))
144 : : return -EFAULT;
145 : 98 : return 0;
146 : : }
147 : :
148 : 0 : static int do_statfs64(struct kstatfs *st, struct statfs64 __user *p)
149 : : {
150 : : struct statfs64 buf;
151 : : if (sizeof(buf) == sizeof(*st))
152 : : memcpy(&buf, st, sizeof(*st));
153 : : else {
154 : 8140 : buf.f_type = st->f_type;
155 : 8140 : buf.f_bsize = st->f_bsize;
156 : 8140 : buf.f_blocks = st->f_blocks;
157 : 8140 : buf.f_bfree = st->f_bfree;
158 : 8140 : buf.f_bavail = st->f_bavail;
159 : 8140 : buf.f_files = st->f_files;
160 : 8140 : buf.f_ffree = st->f_ffree;
161 : 8140 : buf.f_fsid = st->f_fsid;
162 : 8140 : buf.f_namelen = st->f_namelen;
163 : 8140 : buf.f_frsize = st->f_frsize;
164 : 8140 : buf.f_flags = st->f_flags;
165 : 8140 : memset(buf.f_spare, 0, sizeof(buf.f_spare));
166 : : }
167 [ + + ]: 16280 : if (copy_to_user(p, &buf, sizeof(buf)))
168 : : return -EFAULT;
169 : 8138 : return 0;
170 : : }
171 : :
172 : 0 : SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf)
173 : : {
174 : : struct kstatfs st;
175 : 99 : int error = user_statfs(pathname, &st);
176 [ + + ]: 99 : if (!error)
177 : 94 : error = do_statfs_native(&st, buf);
178 : : return error;
179 : : }
180 : :
181 : 0 : SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf)
182 : : {
183 : : struct kstatfs st;
184 : : int error;
185 [ + - ]: 16271 : if (sz != sizeof(*buf))
186 : : return -EINVAL;
187 : 16271 : error = user_statfs(pathname, &st);
188 [ + + ]: 16271 : if (!error)
189 : 8138 : error = do_statfs64(&st, buf);
190 : : return error;
191 : : }
192 : :
193 : 0 : SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf)
194 : : {
195 : : struct kstatfs st;
196 : 7 : int error = fd_statfs(fd, &st);
197 [ + + ]: 7 : if (!error)
198 : 6 : error = do_statfs_native(&st, buf);
199 : : return error;
200 : : }
201 : :
202 : 0 : SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf)
203 : : {
204 : : struct kstatfs st;
205 : : int error;
206 : :
207 [ + - ]: 3 : if (sz != sizeof(*buf))
208 : : return -EINVAL;
209 : :
210 : 3 : error = fd_statfs(fd, &st);
211 [ + + ]: 3 : if (!error)
212 : 2 : error = do_statfs64(&st, buf);
213 : : return error;
214 : : }
215 : :
216 : 0 : int vfs_ustat(dev_t dev, struct kstatfs *sbuf)
217 : : {
218 : 2 : struct super_block *s = user_get_super(dev);
219 : : int err;
220 [ + - ]: 2 : if (!s)
221 : : return -EINVAL;
222 : :
223 : 2 : err = statfs_by_dentry(s->s_root, sbuf);
224 : 2 : drop_super(s);
225 : 2 : return err;
226 : : }
227 : :
228 : 0 : SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf)
229 : : {
230 : : struct ustat tmp;
231 : : struct kstatfs sbuf;
232 : 2 : int err = vfs_ustat(new_decode_dev(dev), &sbuf);
233 [ + - ]: 2 : if (err)
234 : : return err;
235 : :
236 : 2 : memset(&tmp,0,sizeof(struct ustat));
237 : 2 : tmp.f_tfree = sbuf.f_bfree;
238 : 2 : tmp.f_tinode = sbuf.f_ffree;
239 : :
240 [ + + ]: 4 : return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0;
241 : : }
|