Commit d4d23add3abcd18d8021b99f230df608ccb2f007
Committed by
Linus Torvalds
1 parent
72fd4a35a8
Exists in
master
and in
4 other branches
[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>
Showing 18 changed files with 112 additions and 453 deletions Side-by-side Diff
- arch/ia64/ia32/ia32_entry.S
- arch/ia64/ia32/sys_ia32.c
- arch/mips/kernel/linux32.c
- arch/mips/kernel/scall64-n32.S
- arch/mips/kernel/scall64-o32.S
- arch/parisc/kernel/sys_parisc32.c
- arch/parisc/kernel/syscall_table.S
- arch/powerpc/kernel/sys_ppc32.c
- arch/s390/kernel/compat_linux.c
- arch/s390/kernel/compat_wrapper.S
- arch/s390/kernel/syscalls.S
- arch/sparc64/kernel/sys_sparc32.c
- arch/sparc64/kernel/systbls.S
- arch/x86_64/ia32/ia32entry.S
- arch/x86_64/ia32/sys_ia32.c
- include/linux/kernel.h
- kernel/compat.c
- kernel/timer.c
arch/ia64/ia32/ia32_entry.S
arch/ia64/ia32/sys_ia32.c
... | ... | @@ -2209,74 +2209,6 @@ |
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 | { |
arch/mips/kernel/linux32.c
... | ... | @@ -193,50 +193,6 @@ |
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 |
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/parisc/kernel/sys_parisc32.c
... | ... | @@ -579,70 +579,6 @@ |
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 | */ |
arch/parisc/kernel/syscall_table.S
arch/powerpc/kernel/sys_ppc32.c
... | ... | @@ -198,73 +198,6 @@ |
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 |
arch/s390/kernel/compat_linux.c
... | ... | @@ -398,51 +398,6 @@ |
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 | { |
arch/s390/kernel/compat_wrapper.S
... | ... | @@ -517,10 +517,10 @@ |
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: |
arch/s390/kernel/syscalls.S
... | ... | @@ -124,7 +124,7 @@ |
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) |
arch/sparc64/kernel/sys_sparc32.c
... | ... | @@ -459,70 +459,6 @@ |
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; |
arch/sparc64/kernel/systbls.S
... | ... | @@ -61,7 +61,7 @@ |
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 |
arch/x86_64/ia32/ia32entry.S
arch/x86_64/ia32/sys_ia32.c
... | ... | @@ -523,72 +523,6 @@ |
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 | { |
include/linux/kernel.h
kernel/compat.c
... | ... | @@ -1016,4 +1016,69 @@ |
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 | +} |
kernel/timer.c
... | ... | @@ -1392,17 +1392,16 @@ |
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; |
1409 | 1408 | |
1410 | 1409 | |
1411 | 1410 | |
... | ... | @@ -1422,17 +1421,17 @@ |
1422 | 1421 | tp.tv_nsec = tp.tv_nsec - NSEC_PER_SEC; |
1423 | 1422 | tp.tv_sec++; |
1424 | 1423 | } |
1425 | - val.uptime = tp.tv_sec + (tp.tv_nsec ? 1 : 0); | |
1424 | + info->uptime = tp.tv_sec + (tp.tv_nsec ? 1 : 0); | |
1426 | 1425 | |
1427 | - val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT); | |
1428 | - val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT); | |
1429 | - val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT); | |
1426 | + info->loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT); | |
1427 | + info->loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT); | |
1428 | + info->loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT); | |
1430 | 1429 | |
1431 | - val.procs = nr_threads; | |
1430 | + info->procs = nr_threads; | |
1432 | 1431 | } while (read_seqretry(&xtime_lock, seq)); |
1433 | 1432 | |
1434 | - si_meminfo(&val); | |
1435 | - si_swapinfo(&val); | |
1433 | + si_meminfo(info); | |
1434 | + si_swapinfo(info); | |
1436 | 1435 | |
1437 | 1436 | /* |
1438 | 1437 | * If the sum of all the available memory (i.e. ram + swap) |
1439 | 1438 | |
... | ... | @@ -1443,11 +1442,11 @@ |
1443 | 1442 | * -Erik Andersen <andersee@debian.org> |
1444 | 1443 | */ |
1445 | 1444 | |
1446 | - mem_total = val.totalram + val.totalswap; | |
1447 | - if (mem_total < val.totalram || mem_total < val.totalswap) | |
1445 | + mem_total = info->totalram + info->totalswap; | |
1446 | + if (mem_total < info->totalram || mem_total < info->totalswap) | |
1448 | 1447 | goto out; |
1449 | 1448 | bitcount = 0; |
1450 | - mem_unit = val.mem_unit; | |
1449 | + mem_unit = info->mem_unit; | |
1451 | 1450 | while (mem_unit > 1) { |
1452 | 1451 | bitcount++; |
1453 | 1452 | mem_unit >>= 1; |
1454 | 1453 | |
1455 | 1454 | |
... | ... | @@ -1459,22 +1458,31 @@ |
1459 | 1458 | |
1460 | 1459 | /* |
1461 | 1460 | * If mem_total did not overflow, multiply all memory values by |
1462 | - * val.mem_unit and set it to 1. This leaves things compatible | |
1461 | + * info->mem_unit and set it to 1. This leaves things compatible | |
1463 | 1462 | * with 2.2.x, and also retains compatibility with earlier 2.4.x |
1464 | 1463 | * kernels... |
1465 | 1464 | */ |
1466 | 1465 | |
1467 | - val.mem_unit = 1; | |
1468 | - val.totalram <<= bitcount; | |
1469 | - val.freeram <<= bitcount; | |
1470 | - val.sharedram <<= bitcount; | |
1471 | - val.bufferram <<= bitcount; | |
1472 | - val.totalswap <<= bitcount; | |
1473 | - val.freeswap <<= bitcount; | |
1474 | - val.totalhigh <<= bitcount; | |
1475 | - val.freehigh <<= bitcount; | |
1466 | + info->mem_unit = 1; | |
1467 | + info->totalram <<= bitcount; | |
1468 | + info->freeram <<= bitcount; | |
1469 | + info->sharedram <<= bitcount; | |
1470 | + info->bufferram <<= bitcount; | |
1471 | + info->totalswap <<= bitcount; | |
1472 | + info->freeswap <<= bitcount; | |
1473 | + info->totalhigh <<= bitcount; | |
1474 | + info->freehigh <<= bitcount; | |
1476 | 1475 | |
1477 | - out: | |
1476 | +out: | |
1477 | + return 0; | |
1478 | +} | |
1479 | + | |
1480 | +asmlinkage long sys_sysinfo(struct sysinfo __user *info) | |
1481 | +{ | |
1482 | + struct sysinfo val; | |
1483 | + | |
1484 | + do_sysinfo(&val); | |
1485 | + | |
1478 | 1486 | if (copy_to_user(info, &val, sizeof(struct sysinfo))) |
1479 | 1487 | return -EFAULT; |
1480 | 1488 |