Commit d4d23add3abcd18d8021b99f230df608ccb2f007

Authored by Kyle McMartin
Committed by Linus Torvalds
1 parent 72fd4a35a8

[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
... ... @@ -326,7 +326,7 @@
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
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
... ... @@ -217,7 +217,7 @@
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 */
arch/mips/kernel/scall64-o32.S
... ... @@ -321,7 +321,7 @@
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
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
... ... @@ -197,7 +197,7 @@
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)
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
... ... @@ -515,7 +515,7 @@
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
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
... ... @@ -313,6 +313,9 @@
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
... ... @@ -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 +}
... ... @@ -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