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