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