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 <linux/compat.h> 11 #include "internal.h" 12 13 static int flags_by_mnt(int mnt_flags) 14 { 15 int flags = 0; 16 17 if (mnt_flags & MNT_READONLY) 18 flags |= ST_RDONLY; 19 if (mnt_flags & MNT_NOSUID) 20 flags |= ST_NOSUID; 21 if (mnt_flags & MNT_NODEV) 22 flags |= ST_NODEV; 23 if (mnt_flags & MNT_NOEXEC) 24 flags |= ST_NOEXEC; 25 if (mnt_flags & MNT_NOATIME) 26 flags |= ST_NOATIME; 27 if (mnt_flags & MNT_NODIRATIME) 28 flags |= ST_NODIRATIME; 29 if (mnt_flags & MNT_RELATIME) 30 flags |= ST_RELATIME; 31 return flags; 32 } 33 34 static int flags_by_sb(int s_flags) 35 { 36 int flags = 0; 37 if (s_flags & MS_SYNCHRONOUS) 38 flags |= ST_SYNCHRONOUS; 39 if (s_flags & MS_MANDLOCK) 40 flags |= ST_MANDLOCK; 41 if (s_flags & MS_RDONLY) 42 flags |= ST_RDONLY; 43 return flags; 44 } 45 46 static int calculate_f_flags(struct vfsmount *mnt) 47 { 48 return ST_VALID | flags_by_mnt(mnt->mnt_flags) | 49 flags_by_sb(mnt->mnt_sb->s_flags); 50 } 51 52 static int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf) 53 { 54 int retval; 55 56 if (!dentry->d_sb->s_op->statfs) 57 return -ENOSYS; 58 59 memset(buf, 0, sizeof(*buf)); 60 retval = security_sb_statfs(dentry); 61 if (retval) 62 return retval; 63 retval = dentry->d_sb->s_op->statfs(dentry, buf); 64 if (retval == 0 && buf->f_frsize == 0) 65 buf->f_frsize = buf->f_bsize; 66 return retval; 67 } 68 69 int vfs_statfs(const struct path *path, struct kstatfs *buf) 70 { 71 int error; 72 73 error = statfs_by_dentry(path->dentry, buf); 74 if (!error) 75 buf->f_flags = calculate_f_flags(path->mnt); 76 return error; 77 } 78 EXPORT_SYMBOL(vfs_statfs); 79 80 int user_statfs(const char __user *pathname, struct kstatfs *st) 81 { 82 struct path path; 83 int error; 84 unsigned int lookup_flags = LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT; 85 retry: 86 error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); 87 if (!error) { 88 error = vfs_statfs(&path, st); 89 path_put(&path); 90 if (retry_estale(error, lookup_flags)) { 91 lookup_flags |= LOOKUP_REVAL; 92 goto retry; 93 } 94 } 95 return error; 96 } 97 98 int fd_statfs(int fd, struct kstatfs *st) 99 { 100 struct fd f = fdget_raw(fd); 101 int error = -EBADF; 102 if (f.file) { 103 error = vfs_statfs(&f.file->f_path, st); 104 fdput(f); 105 } 106 return error; 107 } 108 109 static int do_statfs_native(struct kstatfs *st, struct statfs __user *p) 110 { 111 struct statfs buf; 112 113 if (sizeof(buf) == sizeof(*st)) 114 memcpy(&buf, st, sizeof(*st)); 115 else { 116 if (sizeof buf.f_blocks == 4) { 117 if ((st->f_blocks | st->f_bfree | st->f_bavail | 118 st->f_bsize | st->f_frsize) & 119 0xffffffff00000000ULL) 120 return -EOVERFLOW; 121 /* 122 * f_files and f_ffree may be -1; it's okay to stuff 123 * that into 32 bits 124 */ 125 if (st->f_files != -1 && 126 (st->f_files & 0xffffffff00000000ULL)) 127 return -EOVERFLOW; 128 if (st->f_ffree != -1 && 129 (st->f_ffree & 0xffffffff00000000ULL)) 130 return -EOVERFLOW; 131 } 132 133 buf.f_type = st->f_type; 134 buf.f_bsize = st->f_bsize; 135 buf.f_blocks = st->f_blocks; 136 buf.f_bfree = st->f_bfree; 137 buf.f_bavail = st->f_bavail; 138 buf.f_files = st->f_files; 139 buf.f_ffree = st->f_ffree; 140 buf.f_fsid = st->f_fsid; 141 buf.f_namelen = st->f_namelen; 142 buf.f_frsize = st->f_frsize; 143 buf.f_flags = st->f_flags; 144 memset(buf.f_spare, 0, sizeof(buf.f_spare)); 145 } 146 if (copy_to_user(p, &buf, sizeof(buf))) 147 return -EFAULT; 148 return 0; 149 } 150 151 static int do_statfs64(struct kstatfs *st, struct statfs64 __user *p) 152 { 153 struct statfs64 buf; 154 if (sizeof(buf) == sizeof(*st)) 155 memcpy(&buf, st, sizeof(*st)); 156 else { 157 buf.f_type = st->f_type; 158 buf.f_bsize = st->f_bsize; 159 buf.f_blocks = st->f_blocks; 160 buf.f_bfree = st->f_bfree; 161 buf.f_bavail = st->f_bavail; 162 buf.f_files = st->f_files; 163 buf.f_ffree = st->f_ffree; 164 buf.f_fsid = st->f_fsid; 165 buf.f_namelen = st->f_namelen; 166 buf.f_frsize = st->f_frsize; 167 buf.f_flags = st->f_flags; 168 memset(buf.f_spare, 0, sizeof(buf.f_spare)); 169 } 170 if (copy_to_user(p, &buf, sizeof(buf))) 171 return -EFAULT; 172 return 0; 173 } 174 175 SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf) 176 { 177 struct kstatfs st; 178 int error = user_statfs(pathname, &st); 179 if (!error) 180 error = do_statfs_native(&st, buf); 181 return error; 182 } 183 184 SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf) 185 { 186 struct kstatfs st; 187 int error; 188 if (sz != sizeof(*buf)) 189 return -EINVAL; 190 error = user_statfs(pathname, &st); 191 if (!error) 192 error = do_statfs64(&st, buf); 193 return error; 194 } 195 196 SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf) 197 { 198 struct kstatfs st; 199 int error = fd_statfs(fd, &st); 200 if (!error) 201 error = do_statfs_native(&st, buf); 202 return error; 203 } 204 205 SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf) 206 { 207 struct kstatfs st; 208 int error; 209 210 if (sz != sizeof(*buf)) 211 return -EINVAL; 212 213 error = fd_statfs(fd, &st); 214 if (!error) 215 error = do_statfs64(&st, buf); 216 return error; 217 } 218 219 int vfs_ustat(dev_t dev, struct kstatfs *sbuf) 220 { 221 struct super_block *s = user_get_super(dev); 222 int err; 223 if (!s) 224 return -EINVAL; 225 226 err = statfs_by_dentry(s->s_root, sbuf); 227 drop_super(s); 228 return err; 229 } 230 231 SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf) 232 { 233 struct ustat tmp; 234 struct kstatfs sbuf; 235 int err = vfs_ustat(new_decode_dev(dev), &sbuf); 236 if (err) 237 return err; 238 239 memset(&tmp,0,sizeof(struct ustat)); 240 tmp.f_tfree = sbuf.f_bfree; 241 tmp.f_tinode = sbuf.f_ffree; 242 243 return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0; 244 } 245 246 #ifdef CONFIG_COMPAT 247 static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf) 248 { 249 struct compat_statfs buf; 250 if (sizeof ubuf->f_blocks == 4) { 251 if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail | 252 kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL) 253 return -EOVERFLOW; 254 /* f_files and f_ffree may be -1; it's okay 255 * to stuff that into 32 bits */ 256 if (kbuf->f_files != 0xffffffffffffffffULL 257 && (kbuf->f_files & 0xffffffff00000000ULL)) 258 return -EOVERFLOW; 259 if (kbuf->f_ffree != 0xffffffffffffffffULL 260 && (kbuf->f_ffree & 0xffffffff00000000ULL)) 261 return -EOVERFLOW; 262 } 263 memset(&buf, 0, sizeof(struct compat_statfs)); 264 buf.f_type = kbuf->f_type; 265 buf.f_bsize = kbuf->f_bsize; 266 buf.f_blocks = kbuf->f_blocks; 267 buf.f_bfree = kbuf->f_bfree; 268 buf.f_bavail = kbuf->f_bavail; 269 buf.f_files = kbuf->f_files; 270 buf.f_ffree = kbuf->f_ffree; 271 buf.f_namelen = kbuf->f_namelen; 272 buf.f_fsid.val[0] = kbuf->f_fsid.val[0]; 273 buf.f_fsid.val[1] = kbuf->f_fsid.val[1]; 274 buf.f_frsize = kbuf->f_frsize; 275 buf.f_flags = kbuf->f_flags; 276 if (copy_to_user(ubuf, &buf, sizeof(struct compat_statfs))) 277 return -EFAULT; 278 return 0; 279 } 280 281 /* 282 * The following statfs calls are copies of code from fs/statfs.c and 283 * should be checked against those from time to time 284 */ 285 COMPAT_SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct compat_statfs __user *, buf) 286 { 287 struct kstatfs tmp; 288 int error = user_statfs(pathname, &tmp); 289 if (!error) 290 error = put_compat_statfs(buf, &tmp); 291 return error; 292 } 293 294 COMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *, buf) 295 { 296 struct kstatfs tmp; 297 int error = fd_statfs(fd, &tmp); 298 if (!error) 299 error = put_compat_statfs(buf, &tmp); 300 return error; 301 } 302 303 static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf) 304 { 305 struct compat_statfs64 buf; 306 if (sizeof(ubuf->f_bsize) == 4) { 307 if ((kbuf->f_type | kbuf->f_bsize | kbuf->f_namelen | 308 kbuf->f_frsize | kbuf->f_flags) & 0xffffffff00000000ULL) 309 return -EOVERFLOW; 310 /* f_files and f_ffree may be -1; it's okay 311 * to stuff that into 32 bits */ 312 if (kbuf->f_files != 0xffffffffffffffffULL 313 && (kbuf->f_files & 0xffffffff00000000ULL)) 314 return -EOVERFLOW; 315 if (kbuf->f_ffree != 0xffffffffffffffffULL 316 && (kbuf->f_ffree & 0xffffffff00000000ULL)) 317 return -EOVERFLOW; 318 } 319 memset(&buf, 0, sizeof(struct compat_statfs64)); 320 buf.f_type = kbuf->f_type; 321 buf.f_bsize = kbuf->f_bsize; 322 buf.f_blocks = kbuf->f_blocks; 323 buf.f_bfree = kbuf->f_bfree; 324 buf.f_bavail = kbuf->f_bavail; 325 buf.f_files = kbuf->f_files; 326 buf.f_ffree = kbuf->f_ffree; 327 buf.f_namelen = kbuf->f_namelen; 328 buf.f_fsid.val[0] = kbuf->f_fsid.val[0]; 329 buf.f_fsid.val[1] = kbuf->f_fsid.val[1]; 330 buf.f_frsize = kbuf->f_frsize; 331 buf.f_flags = kbuf->f_flags; 332 if (copy_to_user(ubuf, &buf, sizeof(struct compat_statfs64))) 333 return -EFAULT; 334 return 0; 335 } 336 337 COMPAT_SYSCALL_DEFINE3(statfs64, const char __user *, pathname, compat_size_t, sz, struct compat_statfs64 __user *, buf) 338 { 339 struct kstatfs tmp; 340 int error; 341 342 if (sz != sizeof(*buf)) 343 return -EINVAL; 344 345 error = user_statfs(pathname, &tmp); 346 if (!error) 347 error = put_compat_statfs64(buf, &tmp); 348 return error; 349 } 350 351 COMPAT_SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, compat_size_t, sz, struct compat_statfs64 __user *, buf) 352 { 353 struct kstatfs tmp; 354 int error; 355 356 if (sz != sizeof(*buf)) 357 return -EINVAL; 358 359 error = fd_statfs(fd, &tmp); 360 if (!error) 361 error = put_compat_statfs64(buf, &tmp); 362 return error; 363 } 364 365 /* 366 * This is a copy of sys_ustat, just dealing with a structure layout. 367 * Given how simple this syscall is that apporach is more maintainable 368 * than the various conversion hacks. 369 */ 370 COMPAT_SYSCALL_DEFINE2(ustat, unsigned, dev, struct compat_ustat __user *, u) 371 { 372 struct compat_ustat tmp; 373 struct kstatfs sbuf; 374 int err = vfs_ustat(new_decode_dev(dev), &sbuf); 375 if (err) 376 return err; 377 378 memset(&tmp, 0, sizeof(struct compat_ustat)); 379 tmp.f_tfree = sbuf.f_bfree; 380 tmp.f_tinode = sbuf.f_ffree; 381 if (copy_to_user(u, &tmp, sizeof(struct compat_ustat))) 382 return -EFAULT; 383 return 0; 384 } 385 #endif 386