Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

statfs: move compat syscalls from compat.c

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro 4ada54ee 1a060ba3

+140 -138
-138
fs/compat.c
··· 137 137 return error; 138 138 } 139 139 140 - static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf) 141 - { 142 - 143 - if (sizeof ubuf->f_blocks == 4) { 144 - if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail | 145 - kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL) 146 - return -EOVERFLOW; 147 - /* f_files and f_ffree may be -1; it's okay 148 - * to stuff that into 32 bits */ 149 - if (kbuf->f_files != 0xffffffffffffffffULL 150 - && (kbuf->f_files & 0xffffffff00000000ULL)) 151 - return -EOVERFLOW; 152 - if (kbuf->f_ffree != 0xffffffffffffffffULL 153 - && (kbuf->f_ffree & 0xffffffff00000000ULL)) 154 - return -EOVERFLOW; 155 - } 156 - if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) || 157 - __put_user(kbuf->f_type, &ubuf->f_type) || 158 - __put_user(kbuf->f_bsize, &ubuf->f_bsize) || 159 - __put_user(kbuf->f_blocks, &ubuf->f_blocks) || 160 - __put_user(kbuf->f_bfree, &ubuf->f_bfree) || 161 - __put_user(kbuf->f_bavail, &ubuf->f_bavail) || 162 - __put_user(kbuf->f_files, &ubuf->f_files) || 163 - __put_user(kbuf->f_ffree, &ubuf->f_ffree) || 164 - __put_user(kbuf->f_namelen, &ubuf->f_namelen) || 165 - __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) || 166 - __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) || 167 - __put_user(kbuf->f_frsize, &ubuf->f_frsize) || 168 - __put_user(kbuf->f_flags, &ubuf->f_flags) || 169 - __clear_user(ubuf->f_spare, sizeof(ubuf->f_spare))) 170 - return -EFAULT; 171 - return 0; 172 - } 173 - 174 - /* 175 - * The following statfs calls are copies of code from fs/statfs.c and 176 - * should be checked against those from time to time 177 - */ 178 - COMPAT_SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct compat_statfs __user *, buf) 179 - { 180 - struct kstatfs tmp; 181 - int error = user_statfs(pathname, &tmp); 182 - if (!error) 183 - error = put_compat_statfs(buf, &tmp); 184 - return error; 185 - } 186 - 187 - COMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *, buf) 188 - { 189 - struct kstatfs tmp; 190 - int error = fd_statfs(fd, &tmp); 191 - if (!error) 192 - error = put_compat_statfs(buf, &tmp); 193 - return error; 194 - } 195 - 196 - static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf) 197 - { 198 - if (sizeof(ubuf->f_bsize) == 4) { 199 - if ((kbuf->f_type | kbuf->f_bsize | kbuf->f_namelen | 200 - kbuf->f_frsize | kbuf->f_flags) & 0xffffffff00000000ULL) 201 - return -EOVERFLOW; 202 - /* f_files and f_ffree may be -1; it's okay 203 - * to stuff that into 32 bits */ 204 - if (kbuf->f_files != 0xffffffffffffffffULL 205 - && (kbuf->f_files & 0xffffffff00000000ULL)) 206 - return -EOVERFLOW; 207 - if (kbuf->f_ffree != 0xffffffffffffffffULL 208 - && (kbuf->f_ffree & 0xffffffff00000000ULL)) 209 - return -EOVERFLOW; 210 - } 211 - if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) || 212 - __put_user(kbuf->f_type, &ubuf->f_type) || 213 - __put_user(kbuf->f_bsize, &ubuf->f_bsize) || 214 - __put_user(kbuf->f_blocks, &ubuf->f_blocks) || 215 - __put_user(kbuf->f_bfree, &ubuf->f_bfree) || 216 - __put_user(kbuf->f_bavail, &ubuf->f_bavail) || 217 - __put_user(kbuf->f_files, &ubuf->f_files) || 218 - __put_user(kbuf->f_ffree, &ubuf->f_ffree) || 219 - __put_user(kbuf->f_namelen, &ubuf->f_namelen) || 220 - __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) || 221 - __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) || 222 - __put_user(kbuf->f_frsize, &ubuf->f_frsize) || 223 - __put_user(kbuf->f_flags, &ubuf->f_flags) || 224 - __clear_user(ubuf->f_spare, sizeof(ubuf->f_spare))) 225 - return -EFAULT; 226 - return 0; 227 - } 228 - 229 - COMPAT_SYSCALL_DEFINE3(statfs64, const char __user *, pathname, compat_size_t, sz, struct compat_statfs64 __user *, buf) 230 - { 231 - struct kstatfs tmp; 232 - int error; 233 - 234 - if (sz != sizeof(*buf)) 235 - return -EINVAL; 236 - 237 - error = user_statfs(pathname, &tmp); 238 - if (!error) 239 - error = put_compat_statfs64(buf, &tmp); 240 - return error; 241 - } 242 - 243 - COMPAT_SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, compat_size_t, sz, struct compat_statfs64 __user *, buf) 244 - { 245 - struct kstatfs tmp; 246 - int error; 247 - 248 - if (sz != sizeof(*buf)) 249 - return -EINVAL; 250 - 251 - error = fd_statfs(fd, &tmp); 252 - if (!error) 253 - error = put_compat_statfs64(buf, &tmp); 254 - return error; 255 - } 256 - 257 - /* 258 - * This is a copy of sys_ustat, just dealing with a structure layout. 259 - * Given how simple this syscall is that apporach is more maintainable 260 - * than the various conversion hacks. 261 - */ 262 - COMPAT_SYSCALL_DEFINE2(ustat, unsigned, dev, struct compat_ustat __user *, u) 263 - { 264 - struct compat_ustat tmp; 265 - struct kstatfs sbuf; 266 - int err = vfs_ustat(new_decode_dev(dev), &sbuf); 267 - if (err) 268 - return err; 269 - 270 - memset(&tmp, 0, sizeof(struct compat_ustat)); 271 - tmp.f_tfree = sbuf.f_bfree; 272 - tmp.f_tinode = sbuf.f_ffree; 273 - if (copy_to_user(u, &tmp, sizeof(struct compat_ustat))) 274 - return -EFAULT; 275 - return 0; 276 - } 277 - 278 140 static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl) 279 141 { 280 142 if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
+140
fs/statfs.c
··· 7 7 #include <linux/statfs.h> 8 8 #include <linux/security.h> 9 9 #include <linux/uaccess.h> 10 + #include <linux/compat.h> 10 11 #include "internal.h" 11 12 12 13 static int flags_by_mnt(int mnt_flags) ··· 240 239 241 240 return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0; 242 241 } 242 + 243 + #ifdef CONFIG_COMPAT 244 + static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf) 245 + { 246 + if (sizeof ubuf->f_blocks == 4) { 247 + if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail | 248 + kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL) 249 + return -EOVERFLOW; 250 + /* f_files and f_ffree may be -1; it's okay 251 + * to stuff that into 32 bits */ 252 + if (kbuf->f_files != 0xffffffffffffffffULL 253 + && (kbuf->f_files & 0xffffffff00000000ULL)) 254 + return -EOVERFLOW; 255 + if (kbuf->f_ffree != 0xffffffffffffffffULL 256 + && (kbuf->f_ffree & 0xffffffff00000000ULL)) 257 + return -EOVERFLOW; 258 + } 259 + if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) || 260 + __put_user(kbuf->f_type, &ubuf->f_type) || 261 + __put_user(kbuf->f_bsize, &ubuf->f_bsize) || 262 + __put_user(kbuf->f_blocks, &ubuf->f_blocks) || 263 + __put_user(kbuf->f_bfree, &ubuf->f_bfree) || 264 + __put_user(kbuf->f_bavail, &ubuf->f_bavail) || 265 + __put_user(kbuf->f_files, &ubuf->f_files) || 266 + __put_user(kbuf->f_ffree, &ubuf->f_ffree) || 267 + __put_user(kbuf->f_namelen, &ubuf->f_namelen) || 268 + __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) || 269 + __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) || 270 + __put_user(kbuf->f_frsize, &ubuf->f_frsize) || 271 + __put_user(kbuf->f_flags, &ubuf->f_flags) || 272 + __clear_user(ubuf->f_spare, sizeof(ubuf->f_spare))) 273 + return -EFAULT; 274 + return 0; 275 + } 276 + 277 + /* 278 + * The following statfs calls are copies of code from fs/statfs.c and 279 + * should be checked against those from time to time 280 + */ 281 + COMPAT_SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct compat_statfs __user *, buf) 282 + { 283 + struct kstatfs tmp; 284 + int error = user_statfs(pathname, &tmp); 285 + if (!error) 286 + error = put_compat_statfs(buf, &tmp); 287 + return error; 288 + } 289 + 290 + COMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *, buf) 291 + { 292 + struct kstatfs tmp; 293 + int error = fd_statfs(fd, &tmp); 294 + if (!error) 295 + error = put_compat_statfs(buf, &tmp); 296 + return error; 297 + } 298 + 299 + static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf) 300 + { 301 + if (sizeof(ubuf->f_bsize) == 4) { 302 + if ((kbuf->f_type | kbuf->f_bsize | kbuf->f_namelen | 303 + kbuf->f_frsize | kbuf->f_flags) & 0xffffffff00000000ULL) 304 + return -EOVERFLOW; 305 + /* f_files and f_ffree may be -1; it's okay 306 + * to stuff that into 32 bits */ 307 + if (kbuf->f_files != 0xffffffffffffffffULL 308 + && (kbuf->f_files & 0xffffffff00000000ULL)) 309 + return -EOVERFLOW; 310 + if (kbuf->f_ffree != 0xffffffffffffffffULL 311 + && (kbuf->f_ffree & 0xffffffff00000000ULL)) 312 + return -EOVERFLOW; 313 + } 314 + if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) || 315 + __put_user(kbuf->f_type, &ubuf->f_type) || 316 + __put_user(kbuf->f_bsize, &ubuf->f_bsize) || 317 + __put_user(kbuf->f_blocks, &ubuf->f_blocks) || 318 + __put_user(kbuf->f_bfree, &ubuf->f_bfree) || 319 + __put_user(kbuf->f_bavail, &ubuf->f_bavail) || 320 + __put_user(kbuf->f_files, &ubuf->f_files) || 321 + __put_user(kbuf->f_ffree, &ubuf->f_ffree) || 322 + __put_user(kbuf->f_namelen, &ubuf->f_namelen) || 323 + __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) || 324 + __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) || 325 + __put_user(kbuf->f_frsize, &ubuf->f_frsize) || 326 + __put_user(kbuf->f_flags, &ubuf->f_flags) || 327 + __clear_user(ubuf->f_spare, sizeof(ubuf->f_spare))) 328 + return -EFAULT; 329 + return 0; 330 + } 331 + 332 + COMPAT_SYSCALL_DEFINE3(statfs64, const char __user *, pathname, compat_size_t, sz, struct compat_statfs64 __user *, buf) 333 + { 334 + struct kstatfs tmp; 335 + int error; 336 + 337 + if (sz != sizeof(*buf)) 338 + return -EINVAL; 339 + 340 + error = user_statfs(pathname, &tmp); 341 + if (!error) 342 + error = put_compat_statfs64(buf, &tmp); 343 + return error; 344 + } 345 + 346 + COMPAT_SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, compat_size_t, sz, struct compat_statfs64 __user *, buf) 347 + { 348 + struct kstatfs tmp; 349 + int error; 350 + 351 + if (sz != sizeof(*buf)) 352 + return -EINVAL; 353 + 354 + error = fd_statfs(fd, &tmp); 355 + if (!error) 356 + error = put_compat_statfs64(buf, &tmp); 357 + return error; 358 + } 359 + 360 + /* 361 + * This is a copy of sys_ustat, just dealing with a structure layout. 362 + * Given how simple this syscall is that apporach is more maintainable 363 + * than the various conversion hacks. 364 + */ 365 + COMPAT_SYSCALL_DEFINE2(ustat, unsigned, dev, struct compat_ustat __user *, u) 366 + { 367 + struct compat_ustat tmp; 368 + struct kstatfs sbuf; 369 + int err = vfs_ustat(new_decode_dev(dev), &sbuf); 370 + if (err) 371 + return err; 372 + 373 + memset(&tmp, 0, sizeof(struct compat_ustat)); 374 + tmp.f_tfree = sbuf.f_bfree; 375 + tmp.f_tinode = sbuf.f_ffree; 376 + if (copy_to_user(u, &tmp, sizeof(struct compat_ustat))) 377 + return -EFAULT; 378 + return 0; 379 + } 380 + #endif