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