Back to home page

LXR

 
 

    


0001 #include <linux/syscalls.h>
0002 #include <linux/export.h>
0003 #include <linux/fs.h>
0004 #include <linux/file.h>
0005 #include <linux/mount.h>
0006 #include <linux/namei.h>
0007 #include <linux/statfs.h>
0008 #include <linux/security.h>
0009 #include <linux/uaccess.h>
0010 #include "internal.h"
0011 
0012 static int flags_by_mnt(int mnt_flags)
0013 {
0014     int flags = 0;
0015 
0016     if (mnt_flags & MNT_READONLY)
0017         flags |= ST_RDONLY;
0018     if (mnt_flags & MNT_NOSUID)
0019         flags |= ST_NOSUID;
0020     if (mnt_flags & MNT_NODEV)
0021         flags |= ST_NODEV;
0022     if (mnt_flags & MNT_NOEXEC)
0023         flags |= ST_NOEXEC;
0024     if (mnt_flags & MNT_NOATIME)
0025         flags |= ST_NOATIME;
0026     if (mnt_flags & MNT_NODIRATIME)
0027         flags |= ST_NODIRATIME;
0028     if (mnt_flags & MNT_RELATIME)
0029         flags |= ST_RELATIME;
0030     return flags;
0031 }
0032 
0033 static int flags_by_sb(int s_flags)
0034 {
0035     int flags = 0;
0036     if (s_flags & MS_SYNCHRONOUS)
0037         flags |= ST_SYNCHRONOUS;
0038     if (s_flags & MS_MANDLOCK)
0039         flags |= ST_MANDLOCK;
0040     return flags;
0041 }
0042 
0043 static int calculate_f_flags(struct vfsmount *mnt)
0044 {
0045     return ST_VALID | flags_by_mnt(mnt->mnt_flags) |
0046         flags_by_sb(mnt->mnt_sb->s_flags);
0047 }
0048 
0049 static int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
0050 {
0051     int retval;
0052 
0053     if (!dentry->d_sb->s_op->statfs)
0054         return -ENOSYS;
0055 
0056     memset(buf, 0, sizeof(*buf));
0057     retval = security_sb_statfs(dentry);
0058     if (retval)
0059         return retval;
0060     retval = dentry->d_sb->s_op->statfs(dentry, buf);
0061     if (retval == 0 && buf->f_frsize == 0)
0062         buf->f_frsize = buf->f_bsize;
0063     return retval;
0064 }
0065 
0066 int vfs_statfs(const struct path *path, struct kstatfs *buf)
0067 {
0068     int error;
0069 
0070     error = statfs_by_dentry(path->dentry, buf);
0071     if (!error)
0072         buf->f_flags = calculate_f_flags(path->mnt);
0073     return error;
0074 }
0075 EXPORT_SYMBOL(vfs_statfs);
0076 
0077 int user_statfs(const char __user *pathname, struct kstatfs *st)
0078 {
0079     struct path path;
0080     int error;
0081     unsigned int lookup_flags = LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT;
0082 retry:
0083     error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
0084     if (!error) {
0085         error = vfs_statfs(&path, st);
0086         path_put(&path);
0087         if (retry_estale(error, lookup_flags)) {
0088             lookup_flags |= LOOKUP_REVAL;
0089             goto retry;
0090         }
0091     }
0092     return error;
0093 }
0094 
0095 int fd_statfs(int fd, struct kstatfs *st)
0096 {
0097     struct fd f = fdget_raw(fd);
0098     int error = -EBADF;
0099     if (f.file) {
0100         error = vfs_statfs(&f.file->f_path, st);
0101         fdput(f);
0102     }
0103     return error;
0104 }
0105 
0106 static int do_statfs_native(struct kstatfs *st, struct statfs __user *p)
0107 {
0108     struct statfs buf;
0109 
0110     if (sizeof(buf) == sizeof(*st))
0111         memcpy(&buf, st, sizeof(*st));
0112     else {
0113         if (sizeof buf.f_blocks == 4) {
0114             if ((st->f_blocks | st->f_bfree | st->f_bavail |
0115                  st->f_bsize | st->f_frsize) &
0116                 0xffffffff00000000ULL)
0117                 return -EOVERFLOW;
0118             /*
0119              * f_files and f_ffree may be -1; it's okay to stuff
0120              * that into 32 bits
0121              */
0122             if (st->f_files != -1 &&
0123                 (st->f_files & 0xffffffff00000000ULL))
0124                 return -EOVERFLOW;
0125             if (st->f_ffree != -1 &&
0126                 (st->f_ffree & 0xffffffff00000000ULL))
0127                 return -EOVERFLOW;
0128         }
0129 
0130         buf.f_type = st->f_type;
0131         buf.f_bsize = st->f_bsize;
0132         buf.f_blocks = st->f_blocks;
0133         buf.f_bfree = st->f_bfree;
0134         buf.f_bavail = st->f_bavail;
0135         buf.f_files = st->f_files;
0136         buf.f_ffree = st->f_ffree;
0137         buf.f_fsid = st->f_fsid;
0138         buf.f_namelen = st->f_namelen;
0139         buf.f_frsize = st->f_frsize;
0140         buf.f_flags = st->f_flags;
0141         memset(buf.f_spare, 0, sizeof(buf.f_spare));
0142     }
0143     if (copy_to_user(p, &buf, sizeof(buf)))
0144         return -EFAULT;
0145     return 0;
0146 }
0147 
0148 static int do_statfs64(struct kstatfs *st, struct statfs64 __user *p)
0149 {
0150     struct statfs64 buf;
0151     if (sizeof(buf) == sizeof(*st))
0152         memcpy(&buf, st, sizeof(*st));
0153     else {
0154         buf.f_type = st->f_type;
0155         buf.f_bsize = st->f_bsize;
0156         buf.f_blocks = st->f_blocks;
0157         buf.f_bfree = st->f_bfree;
0158         buf.f_bavail = st->f_bavail;
0159         buf.f_files = st->f_files;
0160         buf.f_ffree = st->f_ffree;
0161         buf.f_fsid = st->f_fsid;
0162         buf.f_namelen = st->f_namelen;
0163         buf.f_frsize = st->f_frsize;
0164         buf.f_flags = st->f_flags;
0165         memset(buf.f_spare, 0, sizeof(buf.f_spare));
0166     }
0167     if (copy_to_user(p, &buf, sizeof(buf)))
0168         return -EFAULT;
0169     return 0;
0170 }
0171 
0172 SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf)
0173 {
0174     struct kstatfs st;
0175     int error = user_statfs(pathname, &st);
0176     if (!error)
0177         error = do_statfs_native(&st, buf);
0178     return error;
0179 }
0180 
0181 SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf)
0182 {
0183     struct kstatfs st;
0184     int error;
0185     if (sz != sizeof(*buf))
0186         return -EINVAL;
0187     error = user_statfs(pathname, &st);
0188     if (!error)
0189         error = do_statfs64(&st, buf);
0190     return error;
0191 }
0192 
0193 SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf)
0194 {
0195     struct kstatfs st;
0196     int error = fd_statfs(fd, &st);
0197     if (!error)
0198         error = do_statfs_native(&st, buf);
0199     return error;
0200 }
0201 
0202 SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf)
0203 {
0204     struct kstatfs st;
0205     int error;
0206 
0207     if (sz != sizeof(*buf))
0208         return -EINVAL;
0209 
0210     error = fd_statfs(fd, &st);
0211     if (!error)
0212         error = do_statfs64(&st, buf);
0213     return error;
0214 }
0215 
0216 int vfs_ustat(dev_t dev, struct kstatfs *sbuf)
0217 {
0218     struct super_block *s = user_get_super(dev);
0219     int err;
0220     if (!s)
0221         return -EINVAL;
0222 
0223     err = statfs_by_dentry(s->s_root, sbuf);
0224     drop_super(s);
0225     return err;
0226 }
0227 
0228 SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf)
0229 {
0230     struct ustat tmp;
0231     struct kstatfs sbuf;
0232     int err = vfs_ustat(new_decode_dev(dev), &sbuf);
0233     if (err)
0234         return err;
0235 
0236     memset(&tmp,0,sizeof(struct ustat));
0237     tmp.f_tfree = sbuf.f_bfree;
0238     tmp.f_tinode = sbuf.f_ffree;
0239 
0240     return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0;
0241 }