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

[PATCH] Common compat_sys_sysinfo

I noticed that almost all architectures implemented exactly the same
sys32_sysinfo... except parisc, where a bug was to be found in handling of
the uptime. So let's remove a whole whack of code for fun and profit.
Cribbed compat_sys_sysinfo from x86_64's implementation, since I figured it
would be the best tested.

This patch incorporates Arnd's suggestion of not using set_fs/get_fs, but
instead extracting out the common code from sys_sysinfo.

Cc: Christoph Hellwig <hch@infradead.org>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Kyle McMartin and committed by
Linus Torvalds
d4d23add 72fd4a35

+112 -453
+1 -1
arch/ia64/ia32/ia32_entry.S
··· 326 326 data8 sys_ni_syscall 327 327 data8 compat_sys_wait4 328 328 data8 sys_swapoff /* 115 */ 329 - data8 sys32_sysinfo 329 + data8 compat_sys_sysinfo 330 330 data8 sys32_ipc 331 331 data8 sys_fsync 332 332 data8 sys32_sigreturn
-68
arch/ia64/ia32/sys_ia32.c
··· 2209 2209 return ret; 2210 2210 } 2211 2211 2212 - struct sysinfo32 { 2213 - s32 uptime; 2214 - u32 loads[3]; 2215 - u32 totalram; 2216 - u32 freeram; 2217 - u32 sharedram; 2218 - u32 bufferram; 2219 - u32 totalswap; 2220 - u32 freeswap; 2221 - u16 procs; 2222 - u16 pad; 2223 - u32 totalhigh; 2224 - u32 freehigh; 2225 - u32 mem_unit; 2226 - char _f[8]; 2227 - }; 2228 - 2229 - asmlinkage long 2230 - sys32_sysinfo (struct sysinfo32 __user *info) 2231 - { 2232 - struct sysinfo s; 2233 - long ret, err; 2234 - int bitcount = 0; 2235 - mm_segment_t old_fs = get_fs(); 2236 - 2237 - set_fs(KERNEL_DS); 2238 - ret = sys_sysinfo((struct sysinfo __user *) &s); 2239 - set_fs(old_fs); 2240 - /* Check to see if any memory value is too large for 32-bit and 2241 - * scale down if needed. 2242 - */ 2243 - if ((s.totalram >> 32) || (s.totalswap >> 32)) { 2244 - while (s.mem_unit < PAGE_SIZE) { 2245 - s.mem_unit <<= 1; 2246 - bitcount++; 2247 - } 2248 - s.totalram >>= bitcount; 2249 - s.freeram >>= bitcount; 2250 - s.sharedram >>= bitcount; 2251 - s.bufferram >>= bitcount; 2252 - s.totalswap >>= bitcount; 2253 - s.freeswap >>= bitcount; 2254 - s.totalhigh >>= bitcount; 2255 - s.freehigh >>= bitcount; 2256 - } 2257 - 2258 - if (!access_ok(VERIFY_WRITE, info, sizeof(*info))) 2259 - return -EFAULT; 2260 - 2261 - err = __put_user(s.uptime, &info->uptime); 2262 - err |= __put_user(s.loads[0], &info->loads[0]); 2263 - err |= __put_user(s.loads[1], &info->loads[1]); 2264 - err |= __put_user(s.loads[2], &info->loads[2]); 2265 - err |= __put_user(s.totalram, &info->totalram); 2266 - err |= __put_user(s.freeram, &info->freeram); 2267 - err |= __put_user(s.sharedram, &info->sharedram); 2268 - err |= __put_user(s.bufferram, &info->bufferram); 2269 - err |= __put_user(s.totalswap, &info->totalswap); 2270 - err |= __put_user(s.freeswap, &info->freeswap); 2271 - err |= __put_user(s.procs, &info->procs); 2272 - err |= __put_user (s.totalhigh, &info->totalhigh); 2273 - err |= __put_user (s.freehigh, &info->freehigh); 2274 - err |= __put_user (s.mem_unit, &info->mem_unit); 2275 - if (err) 2276 - return -EFAULT; 2277 - return ret; 2278 - } 2279 - 2280 2212 asmlinkage long 2281 2213 sys32_sched_rr_get_interval (pid_t pid, struct compat_timespec __user *interval) 2282 2214 {
-44
arch/mips/kernel/linux32.c
··· 193 193 return ret; 194 194 } 195 195 196 - struct sysinfo32 { 197 - s32 uptime; 198 - u32 loads[3]; 199 - u32 totalram; 200 - u32 freeram; 201 - u32 sharedram; 202 - u32 bufferram; 203 - u32 totalswap; 204 - u32 freeswap; 205 - u16 procs; 206 - u32 totalhigh; 207 - u32 freehigh; 208 - u32 mem_unit; 209 - char _f[8]; 210 - }; 211 - 212 - asmlinkage int sys32_sysinfo(struct sysinfo32 __user *info) 213 - { 214 - struct sysinfo s; 215 - int ret, err; 216 - mm_segment_t old_fs = get_fs (); 217 - 218 - set_fs (KERNEL_DS); 219 - ret = sys_sysinfo((struct sysinfo __user *)&s); 220 - set_fs (old_fs); 221 - err = put_user (s.uptime, &info->uptime); 222 - err |= __put_user (s.loads[0], &info->loads[0]); 223 - err |= __put_user (s.loads[1], &info->loads[1]); 224 - err |= __put_user (s.loads[2], &info->loads[2]); 225 - err |= __put_user (s.totalram, &info->totalram); 226 - err |= __put_user (s.freeram, &info->freeram); 227 - err |= __put_user (s.sharedram, &info->sharedram); 228 - err |= __put_user (s.bufferram, &info->bufferram); 229 - err |= __put_user (s.totalswap, &info->totalswap); 230 - err |= __put_user (s.freeswap, &info->freeswap); 231 - err |= __put_user (s.procs, &info->procs); 232 - err |= __put_user (s.totalhigh, &info->totalhigh); 233 - err |= __put_user (s.freehigh, &info->freehigh); 234 - err |= __put_user (s.mem_unit, &info->mem_unit); 235 - if (err) 236 - return -EFAULT; 237 - return ret; 238 - } 239 - 240 196 #define RLIM_INFINITY32 0x7fffffff 241 197 #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) 242 198
+1 -1
arch/mips/kernel/scall64-n32.S
··· 217 217 PTR sys32_gettimeofday 218 218 PTR compat_sys_getrlimit /* 6095 */ 219 219 PTR compat_sys_getrusage 220 - PTR sys32_sysinfo 220 + PTR compat_sys_sysinfo 221 221 PTR compat_sys_times 222 222 PTR sys32_ptrace 223 223 PTR sys_getuid /* 6100 */
+1 -1
arch/mips/kernel/scall64-o32.S
··· 321 321 PTR sys_ni_syscall /* sys_vm86 */ 322 322 PTR compat_sys_wait4 323 323 PTR sys_swapoff /* 4115 */ 324 - PTR sys32_sysinfo 324 + PTR compat_sys_sysinfo 325 325 PTR sys32_ipc 326 326 PTR sys_fsync 327 327 PTR sys32_sigreturn
-64
arch/parisc/kernel/sys_parisc32.c
··· 579 579 } 580 580 581 581 582 - struct sysinfo32 { 583 - s32 uptime; 584 - u32 loads[3]; 585 - u32 totalram; 586 - u32 freeram; 587 - u32 sharedram; 588 - u32 bufferram; 589 - u32 totalswap; 590 - u32 freeswap; 591 - unsigned short procs; 592 - u32 totalhigh; 593 - u32 freehigh; 594 - u32 mem_unit; 595 - char _f[12]; 596 - }; 597 - 598 - /* We used to call sys_sysinfo and translate the result. But sys_sysinfo 599 - * undoes the good work done elsewhere, and rather than undoing the 600 - * damage, I decided to just duplicate the code from sys_sysinfo here. 601 - */ 602 - 603 - asmlinkage int sys32_sysinfo(struct sysinfo32 __user *info) 604 - { 605 - struct sysinfo val; 606 - int err; 607 - unsigned long seq; 608 - 609 - /* We don't need a memset here because we copy the 610 - * struct to userspace once element at a time. 611 - */ 612 - 613 - do { 614 - seq = read_seqbegin(&xtime_lock); 615 - val.uptime = jiffies / HZ; 616 - 617 - val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT); 618 - val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT); 619 - val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT); 620 - 621 - val.procs = nr_threads; 622 - } while (read_seqretry(&xtime_lock, seq)); 623 - 624 - 625 - si_meminfo(&val); 626 - si_swapinfo(&val); 627 - 628 - err = put_user (val.uptime, &info->uptime); 629 - err |= __put_user (val.loads[0], &info->loads[0]); 630 - err |= __put_user (val.loads[1], &info->loads[1]); 631 - err |= __put_user (val.loads[2], &info->loads[2]); 632 - err |= __put_user (val.totalram, &info->totalram); 633 - err |= __put_user (val.freeram, &info->freeram); 634 - err |= __put_user (val.sharedram, &info->sharedram); 635 - err |= __put_user (val.bufferram, &info->bufferram); 636 - err |= __put_user (val.totalswap, &info->totalswap); 637 - err |= __put_user (val.freeswap, &info->freeswap); 638 - err |= __put_user (val.procs, &info->procs); 639 - err |= __put_user (val.totalhigh, &info->totalhigh); 640 - err |= __put_user (val.freehigh, &info->freehigh); 641 - err |= __put_user (val.mem_unit, &info->mem_unit); 642 - return err ? -EFAULT : 0; 643 - } 644 - 645 - 646 582 /* lseek() needs a wrapper because 'offset' can be negative, but the top 647 583 * half of the argument has been zeroed by syscall.S. 648 584 */
+1 -1
arch/parisc/kernel/syscall_table.S
··· 197 197 /* struct rusage contains longs... */ 198 198 ENTRY_COMP(wait4) 199 199 ENTRY_SAME(swapoff) /* 115 */ 200 - ENTRY_DIFF(sysinfo) 200 + ENTRY_COMP(sysinfo) 201 201 ENTRY_SAME(shutdown) 202 202 ENTRY_SAME(fsync) 203 203 ENTRY_SAME(madvise)
-67
arch/powerpc/kernel/sys_ppc32.c
··· 198 198 __put_user(i->tv_usec, &o->tv_usec))); 199 199 } 200 200 201 - struct sysinfo32 { 202 - s32 uptime; 203 - u32 loads[3]; 204 - u32 totalram; 205 - u32 freeram; 206 - u32 sharedram; 207 - u32 bufferram; 208 - u32 totalswap; 209 - u32 freeswap; 210 - unsigned short procs; 211 - unsigned short pad; 212 - u32 totalhigh; 213 - u32 freehigh; 214 - u32 mem_unit; 215 - char _f[20-2*sizeof(int)-sizeof(int)]; 216 - }; 217 - 218 - asmlinkage long compat_sys_sysinfo(struct sysinfo32 __user *info) 219 - { 220 - struct sysinfo s; 221 - int ret, err; 222 - int bitcount=0; 223 - mm_segment_t old_fs = get_fs (); 224 - 225 - /* The __user cast is valid due to set_fs() */ 226 - set_fs (KERNEL_DS); 227 - ret = sys_sysinfo((struct sysinfo __user *)&s); 228 - set_fs (old_fs); 229 - 230 - /* Check to see if any memory value is too large for 32-bit and 231 - * scale down if needed. 232 - */ 233 - if ((s.totalram >> 32) || (s.totalswap >> 32)) { 234 - while (s.mem_unit < PAGE_SIZE) { 235 - s.mem_unit <<= 1; 236 - bitcount++; 237 - } 238 - s.totalram >>=bitcount; 239 - s.freeram >>= bitcount; 240 - s.sharedram >>= bitcount; 241 - s.bufferram >>= bitcount; 242 - s.totalswap >>= bitcount; 243 - s.freeswap >>= bitcount; 244 - s.totalhigh >>= bitcount; 245 - s.freehigh >>= bitcount; 246 - } 247 - 248 - err = put_user (s.uptime, &info->uptime); 249 - err |= __put_user (s.loads[0], &info->loads[0]); 250 - err |= __put_user (s.loads[1], &info->loads[1]); 251 - err |= __put_user (s.loads[2], &info->loads[2]); 252 - err |= __put_user (s.totalram, &info->totalram); 253 - err |= __put_user (s.freeram, &info->freeram); 254 - err |= __put_user (s.sharedram, &info->sharedram); 255 - err |= __put_user (s.bufferram, &info->bufferram); 256 - err |= __put_user (s.totalswap, &info->totalswap); 257 - err |= __put_user (s.freeswap, &info->freeswap); 258 - err |= __put_user (s.procs, &info->procs); 259 - err |= __put_user (s.totalhigh, &info->totalhigh); 260 - err |= __put_user (s.freehigh, &info->freehigh); 261 - err |= __put_user (s.mem_unit, &info->mem_unit); 262 - if (err) 263 - return -EFAULT; 264 - 265 - return ret; 266 - } 267 - 268 201 269 202 270 203
-45
arch/s390/kernel/compat_linux.c
··· 398 398 return err; 399 399 } 400 400 401 - struct sysinfo32 { 402 - s32 uptime; 403 - u32 loads[3]; 404 - u32 totalram; 405 - u32 freeram; 406 - u32 sharedram; 407 - u32 bufferram; 408 - u32 totalswap; 409 - u32 freeswap; 410 - unsigned short procs; 411 - unsigned short pads; 412 - u32 totalhigh; 413 - u32 freehigh; 414 - unsigned int mem_unit; 415 - char _f[8]; 416 - }; 417 - 418 - asmlinkage long sys32_sysinfo(struct sysinfo32 __user *info) 419 - { 420 - struct sysinfo s; 421 - int ret, err; 422 - mm_segment_t old_fs = get_fs (); 423 - 424 - set_fs (KERNEL_DS); 425 - ret = sys_sysinfo((struct sysinfo __force __user *) &s); 426 - set_fs (old_fs); 427 - err = put_user (s.uptime, &info->uptime); 428 - err |= __put_user (s.loads[0], &info->loads[0]); 429 - err |= __put_user (s.loads[1], &info->loads[1]); 430 - err |= __put_user (s.loads[2], &info->loads[2]); 431 - err |= __put_user (s.totalram, &info->totalram); 432 - err |= __put_user (s.freeram, &info->freeram); 433 - err |= __put_user (s.sharedram, &info->sharedram); 434 - err |= __put_user (s.bufferram, &info->bufferram); 435 - err |= __put_user (s.totalswap, &info->totalswap); 436 - err |= __put_user (s.freeswap, &info->freeswap); 437 - err |= __put_user (s.procs, &info->procs); 438 - err |= __put_user (s.totalhigh, &info->totalhigh); 439 - err |= __put_user (s.freehigh, &info->freehigh); 440 - err |= __put_user (s.mem_unit, &info->mem_unit); 441 - if (err) 442 - return -EFAULT; 443 - return ret; 444 - } 445 - 446 401 asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid, 447 402 struct compat_timespec __user *interval) 448 403 {
+3 -3
arch/s390/kernel/compat_wrapper.S
··· 517 517 llgtr %r2,%r2 # const char * 518 518 jg sys_swapoff # branch to system call 519 519 520 - .globl sys32_sysinfo_wrapper 521 - sys32_sysinfo_wrapper: 520 + .globl compat_sys_sysinfo_wrapper 521 + compat_sys_sysinfo_wrapper: 522 522 llgtr %r2,%r2 # struct sysinfo_emu31 * 523 - jg sys32_sysinfo # branch to system call 523 + jg compat_sys_sysinfo # branch to system call 524 524 525 525 .globl sys32_ipc_wrapper 526 526 sys32_ipc_wrapper:
+1 -1
arch/s390/kernel/syscalls.S
··· 124 124 NI_SYSCALL /* vm86old for i386 */ 125 125 SYSCALL(sys_wait4,sys_wait4,compat_sys_wait4_wrapper) 126 126 SYSCALL(sys_swapoff,sys_swapoff,sys32_swapoff_wrapper) /* 115 */ 127 - SYSCALL(sys_sysinfo,sys_sysinfo,sys32_sysinfo_wrapper) 127 + SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper) 128 128 SYSCALL(sys_ipc,sys_ipc,sys32_ipc_wrapper) 129 129 SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper) 130 130 SYSCALL(sys_sigreturn_glue,sys_sigreturn_glue,sys32_sigreturn_glue)
-64
arch/sparc64/kernel/sys_sparc32.c
··· 459 459 return sys_sysfs(option, arg1, arg2); 460 460 } 461 461 462 - struct sysinfo32 { 463 - s32 uptime; 464 - u32 loads[3]; 465 - u32 totalram; 466 - u32 freeram; 467 - u32 sharedram; 468 - u32 bufferram; 469 - u32 totalswap; 470 - u32 freeswap; 471 - unsigned short procs; 472 - unsigned short pad; 473 - u32 totalhigh; 474 - u32 freehigh; 475 - u32 mem_unit; 476 - char _f[20-2*sizeof(int)-sizeof(int)]; 477 - }; 478 - 479 - asmlinkage long sys32_sysinfo(struct sysinfo32 __user *info) 480 - { 481 - struct sysinfo s; 482 - int ret, err; 483 - int bitcount = 0; 484 - mm_segment_t old_fs = get_fs (); 485 - 486 - set_fs(KERNEL_DS); 487 - ret = sys_sysinfo((struct sysinfo __user *) &s); 488 - set_fs(old_fs); 489 - /* Check to see if any memory value is too large for 32-bit and 490 - * scale down if needed. 491 - */ 492 - if ((s.totalram >> 32) || (s.totalswap >> 32)) { 493 - while (s.mem_unit < PAGE_SIZE) { 494 - s.mem_unit <<= 1; 495 - bitcount++; 496 - } 497 - s.totalram >>= bitcount; 498 - s.freeram >>= bitcount; 499 - s.sharedram >>= bitcount; 500 - s.bufferram >>= bitcount; 501 - s.totalswap >>= bitcount; 502 - s.freeswap >>= bitcount; 503 - s.totalhigh >>= bitcount; 504 - s.freehigh >>= bitcount; 505 - } 506 - 507 - err = put_user (s.uptime, &info->uptime); 508 - err |= __put_user (s.loads[0], &info->loads[0]); 509 - err |= __put_user (s.loads[1], &info->loads[1]); 510 - err |= __put_user (s.loads[2], &info->loads[2]); 511 - err |= __put_user (s.totalram, &info->totalram); 512 - err |= __put_user (s.freeram, &info->freeram); 513 - err |= __put_user (s.sharedram, &info->sharedram); 514 - err |= __put_user (s.bufferram, &info->bufferram); 515 - err |= __put_user (s.totalswap, &info->totalswap); 516 - err |= __put_user (s.freeswap, &info->freeswap); 517 - err |= __put_user (s.procs, &info->procs); 518 - err |= __put_user (s.totalhigh, &info->totalhigh); 519 - err |= __put_user (s.freehigh, &info->freehigh); 520 - err |= __put_user (s.mem_unit, &info->mem_unit); 521 - if (err) 522 - return -EFAULT; 523 - return ret; 524 - } 525 - 526 462 asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval) 527 463 { 528 464 struct timespec t;
+1 -1
arch/sparc64/kernel/systbls.S
··· 61 61 .word sys32_epoll_wait, sys32_ioprio_set, sys_getppid, sys32_sigaction, sys_sgetmask 62 62 /*200*/ .word sys32_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_sys_old_readdir 63 63 .word sys32_readahead, sys32_socketcall, sys32_syslog, sys32_lookup_dcookie, sys32_fadvise64 64 - /*210*/ .word sys32_fadvise64_64, sys32_tgkill, sys32_waitpid, sys_swapoff, sys32_sysinfo 64 + /*210*/ .word sys32_fadvise64_64, sys32_tgkill, sys32_waitpid, sys_swapoff, compat_sys_sysinfo 65 65 .word sys32_ipc, sys32_sigreturn, sys_clone, sys32_ioprio_get, compat_sys_adjtimex 66 66 /*220*/ .word sys32_sigprocmask, sys_ni_syscall, sys32_delete_module, sys_ni_syscall, sys32_getpgid 67 67 .word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16
+1 -1
arch/x86_64/ia32/ia32entry.S
··· 515 515 .quad sys32_vm86_warning /* vm86old */ 516 516 .quad compat_sys_wait4 517 517 .quad sys_swapoff /* 115 */ 518 - .quad sys32_sysinfo 518 + .quad compat_sys_sysinfo 519 519 .quad sys32_ipc 520 520 .quad sys_fsync 521 521 .quad stub32_sigreturn
-66
arch/x86_64/ia32/sys_ia32.c
··· 523 523 return sys_sysfs(option, arg1, arg2); 524 524 } 525 525 526 - struct sysinfo32 { 527 - s32 uptime; 528 - u32 loads[3]; 529 - u32 totalram; 530 - u32 freeram; 531 - u32 sharedram; 532 - u32 bufferram; 533 - u32 totalswap; 534 - u32 freeswap; 535 - unsigned short procs; 536 - unsigned short pad; 537 - u32 totalhigh; 538 - u32 freehigh; 539 - u32 mem_unit; 540 - char _f[20-2*sizeof(u32)-sizeof(int)]; 541 - }; 542 - 543 - asmlinkage long 544 - sys32_sysinfo(struct sysinfo32 __user *info) 545 - { 546 - struct sysinfo s; 547 - int ret; 548 - mm_segment_t old_fs = get_fs (); 549 - int bitcount = 0; 550 - 551 - set_fs (KERNEL_DS); 552 - ret = sys_sysinfo((struct sysinfo __user *)&s); 553 - set_fs (old_fs); 554 - 555 - /* Check to see if any memory value is too large for 32-bit and scale 556 - * down if needed 557 - */ 558 - if ((s.totalram >> 32) || (s.totalswap >> 32)) { 559 - while (s.mem_unit < PAGE_SIZE) { 560 - s.mem_unit <<= 1; 561 - bitcount++; 562 - } 563 - s.totalram >>= bitcount; 564 - s.freeram >>= bitcount; 565 - s.sharedram >>= bitcount; 566 - s.bufferram >>= bitcount; 567 - s.totalswap >>= bitcount; 568 - s.freeswap >>= bitcount; 569 - s.totalhigh >>= bitcount; 570 - s.freehigh >>= bitcount; 571 - } 572 - 573 - if (!access_ok(VERIFY_WRITE, info, sizeof(struct sysinfo32)) || 574 - __put_user (s.uptime, &info->uptime) || 575 - __put_user (s.loads[0], &info->loads[0]) || 576 - __put_user (s.loads[1], &info->loads[1]) || 577 - __put_user (s.loads[2], &info->loads[2]) || 578 - __put_user (s.totalram, &info->totalram) || 579 - __put_user (s.freeram, &info->freeram) || 580 - __put_user (s.sharedram, &info->sharedram) || 581 - __put_user (s.bufferram, &info->bufferram) || 582 - __put_user (s.totalswap, &info->totalswap) || 583 - __put_user (s.freeswap, &info->freeswap) || 584 - __put_user (s.procs, &info->procs) || 585 - __put_user (s.totalhigh, &info->totalhigh) || 586 - __put_user (s.freehigh, &info->freehigh) || 587 - __put_user (s.mem_unit, &info->mem_unit)) 588 - return -EFAULT; 589 - return 0; 590 - } 591 - 592 526 asmlinkage long 593 527 sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval) 594 528 {
+3
include/linux/kernel.h
··· 313 313 (void)__tmp; \ 314 314 }) 315 315 316 + struct sysinfo; 317 + extern int do_sysinfo(struct sysinfo *info); 318 + 316 319 #endif /* __KERNEL__ */ 317 320 318 321 #define SI_LOAD_SHIFT 16
+66
kernel/compat.c
··· 1016 1016 return sys_migrate_pages(pid, nr_bits + 1, old, new); 1017 1017 } 1018 1018 #endif 1019 + 1020 + struct compat_sysinfo { 1021 + s32 uptime; 1022 + u32 loads[3]; 1023 + u32 totalram; 1024 + u32 freeram; 1025 + u32 sharedram; 1026 + u32 bufferram; 1027 + u32 totalswap; 1028 + u32 freeswap; 1029 + u16 procs; 1030 + u16 pad; 1031 + u32 totalhigh; 1032 + u32 freehigh; 1033 + u32 mem_unit; 1034 + char _f[20-2*sizeof(u32)-sizeof(int)]; 1035 + }; 1036 + 1037 + asmlinkage long 1038 + compat_sys_sysinfo(struct compat_sysinfo __user *info) 1039 + { 1040 + struct sysinfo s; 1041 + 1042 + do_sysinfo(&s); 1043 + 1044 + /* Check to see if any memory value is too large for 32-bit and scale 1045 + * down if needed 1046 + */ 1047 + if ((s.totalram >> 32) || (s.totalswap >> 32)) { 1048 + int bitcount = 0; 1049 + 1050 + while (s.mem_unit < PAGE_SIZE) { 1051 + s.mem_unit <<= 1; 1052 + bitcount++; 1053 + } 1054 + 1055 + s.totalram >>= bitcount; 1056 + s.freeram >>= bitcount; 1057 + s.sharedram >>= bitcount; 1058 + s.bufferram >>= bitcount; 1059 + s.totalswap >>= bitcount; 1060 + s.freeswap >>= bitcount; 1061 + s.totalhigh >>= bitcount; 1062 + s.freehigh >>= bitcount; 1063 + } 1064 + 1065 + if (!access_ok(VERIFY_WRITE, info, sizeof(struct compat_sysinfo)) || 1066 + __put_user (s.uptime, &info->uptime) || 1067 + __put_user (s.loads[0], &info->loads[0]) || 1068 + __put_user (s.loads[1], &info->loads[1]) || 1069 + __put_user (s.loads[2], &info->loads[2]) || 1070 + __put_user (s.totalram, &info->totalram) || 1071 + __put_user (s.freeram, &info->freeram) || 1072 + __put_user (s.sharedram, &info->sharedram) || 1073 + __put_user (s.bufferram, &info->bufferram) || 1074 + __put_user (s.totalswap, &info->totalswap) || 1075 + __put_user (s.freeswap, &info->freeswap) || 1076 + __put_user (s.procs, &info->procs) || 1077 + __put_user (s.totalhigh, &info->totalhigh) || 1078 + __put_user (s.freehigh, &info->freehigh) || 1079 + __put_user (s.mem_unit, &info->mem_unit)) 1080 + return -EFAULT; 1081 + 1082 + return 0; 1083 + } 1084 +
+33 -25
kernel/timer.c
··· 1392 1392 } 1393 1393 1394 1394 /** 1395 - * sys_sysinfo - fill in sysinfo struct 1395 + * do_sysinfo - fill in sysinfo struct 1396 1396 * @info: pointer to buffer to fill 1397 1397 */ 1398 - asmlinkage long sys_sysinfo(struct sysinfo __user *info) 1398 + int do_sysinfo(struct sysinfo *info) 1399 1399 { 1400 - struct sysinfo val; 1401 1400 unsigned long mem_total, sav_total; 1402 1401 unsigned int mem_unit, bitcount; 1403 1402 unsigned long seq; 1404 1403 1405 - memset((char *)&val, 0, sizeof(struct sysinfo)); 1404 + memset(info, 0, sizeof(struct sysinfo)); 1406 1405 1407 1406 do { 1408 1407 struct timespec tp; ··· 1421 1422 tp.tv_nsec = tp.tv_nsec - NSEC_PER_SEC; 1422 1423 tp.tv_sec++; 1423 1424 } 1424 - val.uptime = tp.tv_sec + (tp.tv_nsec ? 1 : 0); 1425 + info->uptime = tp.tv_sec + (tp.tv_nsec ? 1 : 0); 1425 1426 1426 - val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT); 1427 - val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT); 1428 - val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT); 1427 + info->loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT); 1428 + info->loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT); 1429 + info->loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT); 1429 1430 1430 - val.procs = nr_threads; 1431 + info->procs = nr_threads; 1431 1432 } while (read_seqretry(&xtime_lock, seq)); 1432 1433 1433 - si_meminfo(&val); 1434 - si_swapinfo(&val); 1434 + si_meminfo(info); 1435 + si_swapinfo(info); 1435 1436 1436 1437 /* 1437 1438 * If the sum of all the available memory (i.e. ram + swap) ··· 1442 1443 * -Erik Andersen <andersee@debian.org> 1443 1444 */ 1444 1445 1445 - mem_total = val.totalram + val.totalswap; 1446 - if (mem_total < val.totalram || mem_total < val.totalswap) 1446 + mem_total = info->totalram + info->totalswap; 1447 + if (mem_total < info->totalram || mem_total < info->totalswap) 1447 1448 goto out; 1448 1449 bitcount = 0; 1449 - mem_unit = val.mem_unit; 1450 + mem_unit = info->mem_unit; 1450 1451 while (mem_unit > 1) { 1451 1452 bitcount++; 1452 1453 mem_unit >>= 1; ··· 1458 1459 1459 1460 /* 1460 1461 * If mem_total did not overflow, multiply all memory values by 1461 - * val.mem_unit and set it to 1. This leaves things compatible 1462 + * info->mem_unit and set it to 1. This leaves things compatible 1462 1463 * with 2.2.x, and also retains compatibility with earlier 2.4.x 1463 1464 * kernels... 1464 1465 */ 1465 1466 1466 - val.mem_unit = 1; 1467 - val.totalram <<= bitcount; 1468 - val.freeram <<= bitcount; 1469 - val.sharedram <<= bitcount; 1470 - val.bufferram <<= bitcount; 1471 - val.totalswap <<= bitcount; 1472 - val.freeswap <<= bitcount; 1473 - val.totalhigh <<= bitcount; 1474 - val.freehigh <<= bitcount; 1467 + info->mem_unit = 1; 1468 + info->totalram <<= bitcount; 1469 + info->freeram <<= bitcount; 1470 + info->sharedram <<= bitcount; 1471 + info->bufferram <<= bitcount; 1472 + info->totalswap <<= bitcount; 1473 + info->freeswap <<= bitcount; 1474 + info->totalhigh <<= bitcount; 1475 + info->freehigh <<= bitcount; 1475 1476 1476 - out: 1477 + out: 1478 + return 0; 1479 + } 1480 + 1481 + asmlinkage long sys_sysinfo(struct sysinfo __user *info) 1482 + { 1483 + struct sysinfo val; 1484 + 1485 + do_sysinfo(&val); 1486 + 1477 1487 if (copy_to_user(info, &val, sizeof(struct sysinfo))) 1478 1488 return -EFAULT; 1479 1489