From: Mikael Pettersson Part 3/3 of perfctr control API changes: - Changed sys_vperfctr_control() to handle variable-sized cpu_control data. Moved cpu_control field to end of struct vperfctr_control, added size parameter to sys_vperfctr_control(), and changed do_vperfctr_control() to only copy as many bytes as user-space indicates. Together with the array-of-struct layout for per-counter control fields, this: * maintains API compatibility even if future processors add more counters, and * allows for reduced argument copying when user-space only uses a small subset of the available counters. - Bump version. Signed-off-by: Mikael Pettersson Signed-off-by: Andrew Morton --- 25-akpm/drivers/perfctr/version.h | 2 +- 25-akpm/drivers/perfctr/virtual.c | 15 +++++++++++---- 25-akpm/include/linux/perfctr.h | 7 ++++--- 3 files changed, 16 insertions(+), 8 deletions(-) diff -puN drivers/perfctr/version.h~perfctr-virtual-update drivers/perfctr/version.h --- 25/drivers/perfctr/version.h~perfctr-virtual-update 2004-11-28 00:54:09.043505472 -0800 +++ 25-akpm/drivers/perfctr/version.h 2004-11-28 00:54:09.051504256 -0800 @@ -1 +1 @@ -#define VERSION "2.7.6" +#define VERSION "2.7.8" diff -puN drivers/perfctr/virtual.c~perfctr-virtual-update drivers/perfctr/virtual.c --- 25/drivers/perfctr/virtual.c~perfctr-virtual-update 2004-11-28 00:54:09.045505168 -0800 +++ 25-akpm/drivers/perfctr/virtual.c 2004-11-28 00:54:09.053503952 -0800 @@ -1,4 +1,4 @@ -/* $Id: virtual.c,v 1.107 2004/10/23 23:28:45 mikpe Exp $ +/* $Id: virtual.c,v 1.110 2004/11/24 00:38:30 mikpe Exp $ * Virtual per-process performance counters. * * Copyright (C) 1999-2004 Mikael Pettersson @@ -541,6 +541,7 @@ void __vperfctr_set_cpus_allowed(struct static int do_vperfctr_control(struct vperfctr *perfctr, const struct vperfctr_control __user *argp, + unsigned int argbytes, struct task_struct *tsk) { struct vperfctr_control *control; @@ -561,9 +562,14 @@ static int do_vperfctr_control(struct vp if (!control) return -ENOMEM; + err = -EINVAL; + if (argbytes > sizeof *control) + goto out_kfree; err = -EFAULT; - if (copy_from_user(control, argp, sizeof *control)) + if (copy_from_user(control, argp, argbytes)) goto out_kfree; + if (argbytes < sizeof *control) + memset((char*)control + argbytes, 0, sizeof *control - argbytes); if (control->cpu_control.nractrs || control->cpu_control.nrictrs) { cpumask_t old_mask, new_mask; @@ -1046,7 +1052,8 @@ static void vperfctr_put_tsk(struct task } asmlinkage long sys_vperfctr_control(int fd, - const struct vperfctr_control __user *control) + const struct vperfctr_control __user *argp, + unsigned int argbytes) { struct vperfctr *perfctr; struct task_struct *tsk; @@ -1060,7 +1067,7 @@ asmlinkage long sys_vperfctr_control(int ret = PTR_ERR(tsk); goto out; } - ret = do_vperfctr_control(perfctr, control, tsk); + ret = do_vperfctr_control(perfctr, argp, argbytes, tsk); vperfctr_put_tsk(tsk); out: put_vperfctr(perfctr); diff -puN include/linux/perfctr.h~perfctr-virtual-update include/linux/perfctr.h --- 25/include/linux/perfctr.h~perfctr-virtual-update 2004-11-28 00:54:09.046505016 -0800 +++ 25-akpm/include/linux/perfctr.h 2004-11-28 00:54:09.053503952 -0800 @@ -1,4 +1,4 @@ -/* $Id: perfctr.h,v 1.83 2004/07/17 00:37:52 mikpe Exp $ +/* $Id: perfctr.h,v 1.85 2004/11/24 00:38:21 mikpe Exp $ * Performance-Monitoring Counters driver * * Copyright (C) 1999-2004 Mikael Pettersson @@ -46,12 +46,12 @@ struct vperfctr_state { /* virtual perfctr control object */ struct vperfctr_control { int si_signo; - struct perfctr_cpu_control cpu_control; unsigned int preserve; unsigned int _reserved1; unsigned int _reserved2; unsigned int _reserved3; unsigned int _reserved4; + struct perfctr_cpu_control cpu_control; }; /* commands for sys_vperfctr_read() */ @@ -76,7 +76,8 @@ asmlinkage long sys_perfctr_info(struct struct perfctr_cpu_mask __user*); asmlinkage long sys_vperfctr_open(int tid, int creat); asmlinkage long sys_vperfctr_control(int fd, - const struct vperfctr_control __user*); + const struct vperfctr_control __user *argp, + unsigned int argbytes); asmlinkage long sys_vperfctr_unlink(int fd); asmlinkage long sys_vperfctr_iresume(int fd); asmlinkage long sys_vperfctr_read(int fd, unsigned int cmd, void __user *argp, unsigned int argbytes); _