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