Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/syscalls.h>
0003 #include <linux/export.h>
0004 #include <linux/fs.h>
0005 #include <linux/file.h>
0006 #include <linux/mount.h>
0007 #include <linux/namei.h>
0008 #include <linux/statfs.h>
0009 #include <linux/security.h>
0010 #include <linux/uaccess.h>
0011 #include <linux/compat.h>
0012 #include "internal.h"
0013 
0014 static int flags_by_mnt(int mnt_flags)
0015 {
0016     int flags = 0;
0017 
0018     if (mnt_flags & MNT_READONLY)
0019         flags |= ST_RDONLY;
0020     if (mnt_flags & MNT_NOSUID)
0021         flags |= ST_NOSUID;
0022     if (mnt_flags & MNT_NODEV)
0023         flags |= ST_NODEV;
0024     if (mnt_flags & MNT_NOEXEC)
0025         flags |= ST_NOEXEC;
0026     if (mnt_flags & MNT_NOATIME)
0027         flags |= ST_NOATIME;
0028     if (mnt_flags & MNT_NODIRATIME)
0029         flags |= ST_NODIRATIME;
0030     if (mnt_flags & MNT_RELATIME)
0031         flags |= ST_RELATIME;
0032     if (mnt_flags & MNT_NOSYMFOLLOW)
0033         flags |= ST_NOSYMFOLLOW;
0034     return flags;
0035 }
0036 
0037 static int flags_by_sb(int s_flags)
0038 {
0039     int flags = 0;
0040     if (s_flags & SB_SYNCHRONOUS)
0041         flags |= ST_SYNCHRONOUS;
0042     if (s_flags & SB_MANDLOCK)
0043         flags |= ST_MANDLOCK;
0044     if (s_flags & SB_RDONLY)
0045         flags |= ST_RDONLY;
0046     return flags;
0047 }
0048 
0049 static int calculate_f_flags(struct vfsmount *mnt)
0050 {
0051     return ST_VALID | flags_by_mnt(mnt->mnt_flags) |
0052         flags_by_sb(mnt->mnt_sb->s_flags);
0053 }
0054 
0055 static int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
0056 {
0057     int retval;
0058 
0059     if (!dentry->d_sb->s_op->statfs)
0060         return -ENOSYS;
0061 
0062     memset(buf, 0, sizeof(*buf));
0063     retval = security_sb_statfs(dentry);
0064     if (retval)
0065         return retval;
0066     retval = dentry->d_sb->s_op->statfs(dentry, buf);
0067     if (retval == 0 && buf->f_frsize == 0)
0068         buf->f_frsize = buf->f_bsize;
0069     return retval;
0070 }
0071 
0072 int vfs_get_fsid(struct dentry *dentry, __kernel_fsid_t *fsid)
0073 {
0074     struct kstatfs st;
0075     int error;
0076 
0077     error = statfs_by_dentry(dentry, &st);
0078     if (error)
0079         return error;
0080 
0081     *fsid = st.f_fsid;
0082     return 0;
0083 }
0084 EXPORT_SYMBOL(vfs_get_fsid);
0085 
0086 int vfs_statfs(const struct path *path, struct kstatfs *buf)
0087 {
0088     int error;
0089 
0090     error = statfs_by_dentry(path->dentry, buf);
0091     if (!error)
0092         buf->f_flags = calculate_f_flags(path->mnt);
0093     return error;
0094 }
0095 EXPORT_SYMBOL(vfs_statfs);
0096 
0097 int user_statfs(const char __user *pathname, struct kstatfs *st)
0098 {
0099     struct path path;
0100     int error;
0101     unsigned int lookup_flags = LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT;
0102 retry:
0103     error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
0104     if (!error) {
0105         error = vfs_statfs(&path, st);
0106         path_put(&path);
0107         if (retry_estale(error, lookup_flags)) {
0108             lookup_flags |= LOOKUP_REVAL;
0109             goto retry;
0110         }
0111     }
0112     return error;
0113 }
0114 
0115 int fd_statfs(int fd, struct kstatfs *st)
0116 {
0117     struct fd f = fdget_raw(fd);
0118     int error = -EBADF;
0119     if (f.file) {
0120         error = vfs_statfs(&f.file->f_path, st);
0121         fdput(f);
0122     }
0123     return error;
0124 }
0125 
0126 static int do_statfs_native(struct kstatfs *st, struct statfs __user *p)
0127 {
0128     struct statfs buf;
0129 
0130     if (sizeof(buf) == sizeof(*st))
0131         memcpy(&buf, st, sizeof(*st));
0132     else {
0133         if (sizeof buf.f_blocks == 4) {
0134             if ((st->f_blocks | st->f_bfree | st->f_bavail |
0135                  st->f_bsize | st->f_frsize) &
0136                 0xffffffff00000000ULL)
0137                 return -EOVERFLOW;
0138             /*
0139              * f_files and f_ffree may be -1; it's okay to stuff
0140              * that into 32 bits
0141              */
0142             if (st->f_files != -1 &&
0143                 (st->f_files & 0xffffffff00000000ULL))
0144                 return -EOVERFLOW;
0145             if (st->f_ffree != -1 &&
0146                 (st->f_ffree & 0xffffffff00000000ULL))
0147                 return -EOVERFLOW;
0148         }
0149 
0150         buf.f_type = st->f_type;
0151         buf.f_bsize = st->f_bsize;
0152         buf.f_blocks = st->f_blocks;
0153         buf.f_bfree = st->f_bfree;
0154         buf.f_bavail = st->f_bavail;
0155         buf.f_files = st->f_files;
0156         buf.f_ffree = st->f_ffree;
0157         buf.f_fsid = st->f_fsid;
0158         buf.f_namelen = st->f_namelen;
0159         buf.f_frsize = st->f_frsize;
0160         buf.f_flags = st->f_flags;
0161         memset(buf.f_spare, 0, sizeof(buf.f_spare));
0162     }
0163     if (copy_to_user(p, &buf, sizeof(buf)))
0164         return -EFAULT;
0165     return 0;
0166 }
0167 
0168 static int do_statfs64(struct kstatfs *st, struct statfs64 __user *p)
0169 {
0170     struct statfs64 buf;
0171     if (sizeof(buf) == sizeof(*st))
0172         memcpy(&buf, st, sizeof(*st));
0173     else {
0174         buf.f_type = st->f_type;
0175         buf.f_bsize = st->f_bsize;
0176         buf.f_blocks = st->f_blocks;
0177         buf.f_bfree = st->f_bfree;
0178         buf.f_bavail = st->f_bavail;
0179         buf.f_files = st->f_files;
0180         buf.f_ffree = st->f_ffree;
0181         buf.f_fsid = st->f_fsid;
0182         buf.f_namelen = st->f_namelen;
0183         buf.f_frsize = st->f_frsize;
0184         buf.f_flags = st->f_flags;
0185         memset(buf.f_spare, 0, sizeof(buf.f_spare));
0186     }
0187     if (copy_to_user(p, &buf, sizeof(buf)))
0188         return -EFAULT;
0189     return 0;
0190 }
0191 
0192 SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf)
0193 {
0194     struct kstatfs st;
0195     int error = user_statfs(pathname, &st);
0196     if (!error)
0197         error = do_statfs_native(&st, buf);
0198     return error;
0199 }
0200 
0201 SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf)
0202 {
0203     struct kstatfs st;
0204     int error;
0205     if (sz != sizeof(*buf))
0206         return -EINVAL;
0207     error = user_statfs(pathname, &st);
0208     if (!error)
0209         error = do_statfs64(&st, buf);
0210     return error;
0211 }
0212 
0213 SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf)
0214 {
0215     struct kstatfs st;
0216     int error = fd_statfs(fd, &st);
0217     if (!error)
0218         error = do_statfs_native(&st, buf);
0219     return error;
0220 }
0221 
0222 SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf)
0223 {
0224     struct kstatfs st;
0225     int error;
0226 
0227     if (sz != sizeof(*buf))
0228         return -EINVAL;
0229 
0230     error = fd_statfs(fd, &st);
0231     if (!error)
0232         error = do_statfs64(&st, buf);
0233     return error;
0234 }
0235 
0236 static int vfs_ustat(dev_t dev, struct kstatfs *sbuf)
0237 {
0238     struct super_block *s = user_get_super(dev, false);
0239     int err;
0240     if (!s)
0241         return -EINVAL;
0242 
0243     err = statfs_by_dentry(s->s_root, sbuf);
0244     drop_super(s);
0245     return err;
0246 }
0247 
0248 SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf)
0249 {
0250     struct ustat tmp;
0251     struct kstatfs sbuf;
0252     int err = vfs_ustat(new_decode_dev(dev), &sbuf);
0253     if (err)
0254         return err;
0255 
0256     memset(&tmp,0,sizeof(struct ustat));
0257     tmp.f_tfree = sbuf.f_bfree;
0258     if (IS_ENABLED(CONFIG_ARCH_32BIT_USTAT_F_TINODE))
0259         tmp.f_tinode = min_t(u64, sbuf.f_ffree, UINT_MAX);
0260     else
0261         tmp.f_tinode = sbuf.f_ffree;
0262 
0263     return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0;
0264 }
0265 
0266 #ifdef CONFIG_COMPAT
0267 static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf)
0268 {
0269     struct compat_statfs buf;
0270     if (sizeof ubuf->f_blocks == 4) {
0271         if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail |
0272              kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
0273             return -EOVERFLOW;
0274         /* f_files and f_ffree may be -1; it's okay
0275          * to stuff that into 32 bits */
0276         if (kbuf->f_files != 0xffffffffffffffffULL
0277          && (kbuf->f_files & 0xffffffff00000000ULL))
0278             return -EOVERFLOW;
0279         if (kbuf->f_ffree != 0xffffffffffffffffULL
0280          && (kbuf->f_ffree & 0xffffffff00000000ULL))
0281             return -EOVERFLOW;
0282     }
0283     memset(&buf, 0, sizeof(struct compat_statfs));
0284     buf.f_type = kbuf->f_type;
0285     buf.f_bsize = kbuf->f_bsize;
0286     buf.f_blocks = kbuf->f_blocks;
0287     buf.f_bfree = kbuf->f_bfree;
0288     buf.f_bavail = kbuf->f_bavail;
0289     buf.f_files = kbuf->f_files;
0290     buf.f_ffree = kbuf->f_ffree;
0291     buf.f_namelen = kbuf->f_namelen;
0292     buf.f_fsid.val[0] = kbuf->f_fsid.val[0];
0293     buf.f_fsid.val[1] = kbuf->f_fsid.val[1];
0294     buf.f_frsize = kbuf->f_frsize;
0295     buf.f_flags = kbuf->f_flags;
0296     if (copy_to_user(ubuf, &buf, sizeof(struct compat_statfs)))
0297         return -EFAULT;
0298     return 0;
0299 }
0300 
0301 /*
0302  * The following statfs calls are copies of code from fs/statfs.c and
0303  * should be checked against those from time to time
0304  */
0305 COMPAT_SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct compat_statfs __user *, buf)
0306 {
0307     struct kstatfs tmp;
0308     int error = user_statfs(pathname, &tmp);
0309     if (!error)
0310         error = put_compat_statfs(buf, &tmp);
0311     return error;
0312 }
0313 
0314 COMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *, buf)
0315 {
0316     struct kstatfs tmp;
0317     int error = fd_statfs(fd, &tmp);
0318     if (!error)
0319         error = put_compat_statfs(buf, &tmp);
0320     return error;
0321 }
0322 
0323 static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf)
0324 {
0325     struct compat_statfs64 buf;
0326 
0327     if ((kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
0328         return -EOVERFLOW;
0329 
0330     memset(&buf, 0, sizeof(struct compat_statfs64));
0331     buf.f_type = kbuf->f_type;
0332     buf.f_bsize = kbuf->f_bsize;
0333     buf.f_blocks = kbuf->f_blocks;
0334     buf.f_bfree = kbuf->f_bfree;
0335     buf.f_bavail = kbuf->f_bavail;
0336     buf.f_files = kbuf->f_files;
0337     buf.f_ffree = kbuf->f_ffree;
0338     buf.f_namelen = kbuf->f_namelen;
0339     buf.f_fsid.val[0] = kbuf->f_fsid.val[0];
0340     buf.f_fsid.val[1] = kbuf->f_fsid.val[1];
0341     buf.f_frsize = kbuf->f_frsize;
0342     buf.f_flags = kbuf->f_flags;
0343     if (copy_to_user(ubuf, &buf, sizeof(struct compat_statfs64)))
0344         return -EFAULT;
0345     return 0;
0346 }
0347 
0348 int kcompat_sys_statfs64(const char __user * pathname, compat_size_t sz, struct compat_statfs64 __user * buf)
0349 {
0350     struct kstatfs tmp;
0351     int error;
0352 
0353     if (sz != sizeof(*buf))
0354         return -EINVAL;
0355 
0356     error = user_statfs(pathname, &tmp);
0357     if (!error)
0358         error = put_compat_statfs64(buf, &tmp);
0359     return error;
0360 }
0361 
0362 COMPAT_SYSCALL_DEFINE3(statfs64, const char __user *, pathname, compat_size_t, sz, struct compat_statfs64 __user *, buf)
0363 {
0364     return kcompat_sys_statfs64(pathname, sz, buf);
0365 }
0366 
0367 int kcompat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user * buf)
0368 {
0369     struct kstatfs tmp;
0370     int error;
0371 
0372     if (sz != sizeof(*buf))
0373         return -EINVAL;
0374 
0375     error = fd_statfs(fd, &tmp);
0376     if (!error)
0377         error = put_compat_statfs64(buf, &tmp);
0378     return error;
0379 }
0380 
0381 COMPAT_SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, compat_size_t, sz, struct compat_statfs64 __user *, buf)
0382 {
0383     return kcompat_sys_fstatfs64(fd, sz, buf);
0384 }
0385 
0386 /*
0387  * This is a copy of sys_ustat, just dealing with a structure layout.
0388  * Given how simple this syscall is that apporach is more maintainable
0389  * than the various conversion hacks.
0390  */
0391 COMPAT_SYSCALL_DEFINE2(ustat, unsigned, dev, struct compat_ustat __user *, u)
0392 {
0393     struct compat_ustat tmp;
0394     struct kstatfs sbuf;
0395     int err = vfs_ustat(new_decode_dev(dev), &sbuf);
0396     if (err)
0397         return err;
0398 
0399     memset(&tmp, 0, sizeof(struct compat_ustat));
0400     tmp.f_tfree = sbuf.f_bfree;
0401     tmp.f_tinode = sbuf.f_ffree;
0402     if (copy_to_user(u, &tmp, sizeof(struct compat_ustat)))
0403         return -EFAULT;
0404     return 0;
0405 }
0406 #endif