From: Arnd Bergmann <arnd@arndb.de>
To: Kyle McMartin <kyle@parisc-linux.org>
Cc: akpm@osdl.org, linux-arch@vger.kernel.org,
parisc-linux@lists.parisc-linux.org
Subject: Re: [PATCH] Generic compat_sys_sysinfo
Date: Sat, 25 Nov 2006 14:28:27 +0100 [thread overview]
Message-ID: <200611251428.28018.arnd@arndb.de> (raw)
In-Reply-To: <20061125014313.GD11643@athena.road.mcmartin.ca>
On Saturday 25 November 2006 02:43, Kyle McMartin wrote:
> +asmlinkage long
> +compat_sys_sysinfo(struct compat_sysinfo __user *info)
> +{
> + struct sysinfo s;
> + int ret;
> + mm_segment_t old_fs = get_fs ();
> + int bitcount = 0;
> +
> + set_fs (KERNEL_DS);
> + ret = sys_sysinfo((struct sysinfo __user *)&s);
> + set_fs (old_fs);
Maybe we should avoid the ugly get_fs/set_fs hack at the same time
and do it more like the (untested) code below. I also noticed that
all implementations of compat_sys_sysinfo do not set the reserved
fields to zero in user space, so maybe it should also be converted
to use copy_to_user().
Arnd <><
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 24b6111..634959a 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -322,6 +322,9 @@ static inline int __attribute__ ((format
(void)__tmp; \
})
+struct sysinfo;
+extern void do_sysinfo(struct sysinfo *);
+
#endif /* __KERNEL__ */
#define SI_LOAD_SHIFT 16
diff --git a/kernel/compat.c b/kernel/compat.c
index 6952dd0..cd6e0ee 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -1016,3 +1016,66 @@ asmlinkage long compat_sys_migrate_pages
return sys_migrate_pages(pid, nr_bits + 1, old, new);
}
#endif
+
+struct compat_sysinfo {
+ s32 uptime;
+ u32 loads[3];
+ u32 totalram;
+ u32 freeram;
+ u32 sharedram;
+ u32 bufferram;
+ u32 totalswap;
+ u32 freeswap;
+ u16 procs;
+ u16 pad;
+ u32 totalhigh;
+ u32 freehigh;
+ u32 mem_unit;
+ char _f[20 - 2 * sizeof(u32) - sizeof(int)];
+};
+
+asmlinkage long compat_sys_sysinfo(struct compat_sysinfo __user *info)
+{
+ struct sysinfo s;
+ int bitcount = 0;
+
+ do_sysinfo(&s);
+
+ /*
+ * Check to see if any memory value is too large for 32-bit and
+ * scale down if needed.
+ */
+ if ((s.totalram >> 32) || (s.totalswap >> 32)) {
+ while (s.mem_unit < PAGE_SIZE) {
+ s.mem_unit <<= 1;
+ bitcount++;
+ }
+ s.totalram >>= bitcount;
+ s.freeram >>= bitcount;
+ s.sharedram >>= bitcount;
+ s.bufferram >>= bitcount;
+ s.totalswap >>= bitcount;
+ s.freeswap >>= bitcount;
+ s.totalhigh >>= bitcount;
+ s.freehigh >>= bitcount;
+ }
+
+ if (!access_ok(VERIFY_WRITE, info, sizeof(struct compat_sysinfo))
+ || __put_user(s.uptime, &info->uptime)
+ || __put_user(s.loads[0], &info->loads[0])
+ || __put_user(s.loads[1], &info->loads[1])
+ || __put_user(s.loads[2], &info->loads[2])
+ || __put_user(s.totalram, &info->totalram)
+ || __put_user(s.freeram, &info->freeram)
+ || __put_user(s.sharedram, &info->sharedram)
+ || __put_user(s.bufferram, &info->bufferram)
+ || __put_user(s.totalswap, &info->totalswap)
+ || __put_user(s.freeswap, &info->freeswap)
+ || __put_user(s.procs, &info->procs)
+ || __put_user(s.totalhigh, &info->totalhigh)
+ || __put_user(s.freehigh, &info->freehigh)
+ || __put_user(s.mem_unit, &info->mem_unit))
+ return -EFAULT;
+
+ return 0;
+}
diff --git a/kernel/timer.c b/kernel/timer.c
index c1c7fbc..878568b 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1251,17 +1251,16 @@ asmlinkage long sys_gettid(void)
}
/**
- * sys_sysinfo - fill in sysinfo struct
+ * do_sysinfo - fill in sysinfo struct
* @info: pointer to buffer to fill
- */
-asmlinkage long sys_sysinfo(struct sysinfo __user *info)
+ */
+void do_sysinfo(struct sysinfo *val)
{
- struct sysinfo val;
unsigned long mem_total, sav_total;
unsigned int mem_unit, bitcount;
unsigned long seq;
- memset((char *)&val, 0, sizeof(struct sysinfo));
+ memset(val, 0, sizeof(struct sysinfo));
do {
struct timespec tp;
@@ -1281,17 +1280,17 @@ asmlinkage long sys_sysinfo(struct sysin
tp.tv_nsec = tp.tv_nsec - NSEC_PER_SEC;
tp.tv_sec++;
}
- val.uptime = tp.tv_sec + (tp.tv_nsec ? 1 : 0);
+ val->uptime = tp.tv_sec + (tp.tv_nsec ? 1 : 0);
- val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
- val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
- val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
+ val->loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
+ val->loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
+ val->loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
- val.procs = nr_threads;
+ val->procs = nr_threads;
} while (read_seqretry(&xtime_lock, seq));
- si_meminfo(&val);
- si_swapinfo(&val);
+ si_meminfo(val);
+ si_swapinfo(val);
/*
* If the sum of all the available memory (i.e. ram + swap)
@@ -1302,41 +1301,46 @@ asmlinkage long sys_sysinfo(struct sysin
* -Erik Andersen <andersee@debian.org>
*/
- mem_total = val.totalram + val.totalswap;
- if (mem_total < val.totalram || mem_total < val.totalswap)
- goto out;
+ mem_total = val->totalram + val->totalswap;
+ if (mem_total < val->totalram || mem_total < val->totalswap)
+ return;
bitcount = 0;
- mem_unit = val.mem_unit;
+ mem_unit = val->mem_unit;
while (mem_unit > 1) {
bitcount++;
mem_unit >>= 1;
sav_total = mem_total;
mem_total <<= 1;
if (mem_total < sav_total)
- goto out;
+ return;
}
/*
* If mem_total did not overflow, multiply all memory values by
- * val.mem_unit and set it to 1. This leaves things compatible
+ * val->mem_unit and set it to 1. This leaves things compatible
* with 2.2.x, and also retains compatibility with earlier 2.4.x
* kernels...
*/
- val.mem_unit = 1;
- val.totalram <<= bitcount;
- val.freeram <<= bitcount;
- val.sharedram <<= bitcount;
- val.bufferram <<= bitcount;
- val.totalswap <<= bitcount;
- val.freeswap <<= bitcount;
- val.totalhigh <<= bitcount;
- val.freehigh <<= bitcount;
+ val->mem_unit = 1;
+ val->totalram <<= bitcount;
+ val->freeram <<= bitcount;
+ val->sharedram <<= bitcount;
+ val->bufferram <<= bitcount;
+ val->totalswap <<= bitcount;
+ val->freeswap <<= bitcount;
+ val->totalhigh <<= bitcount;
+ val->freehigh <<= bitcount;
+}
+
+asmlinkage long sys_sysinfo(struct sysinfo __user *info)
+{
+ struct sysinfo val;
+
+ do_sysinfo(&val);
- out:
if (copy_to_user(info, &val, sizeof(struct sysinfo)))
return -EFAULT;
-
return 0;
}
prev parent reply other threads:[~2006-11-25 13:28 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-11-25 1:43 [PATCH] Generic compat_sys_sysinfo Kyle McMartin
2006-11-25 1:43 ` [parisc-linux] " Kyle McMartin
2006-11-25 4:00 ` Matthew Wilcox
2006-11-25 4:00 ` [parisc-linux] " Matthew Wilcox
2006-11-25 4:02 ` David Miller
2006-11-25 13:28 ` Arnd Bergmann [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200611251428.28018.arnd@arndb.de \
--to=arnd@arndb.de \
--cc=akpm@osdl.org \
--cc=kyle@parisc-linux.org \
--cc=linux-arch@vger.kernel.org \
--cc=parisc-linux@lists.parisc-linux.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.