Commit 81d2e766 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] /proc/ppc64 and /proc/iSeries fixes from Linas Vepstas

From: Anton Blanchard <anton@samba.org>

Linas Vepstas has audited the ppc64 proc code and found a number of issues.
parent 1a6100ca
......@@ -220,19 +220,25 @@ int proc_mf_dump_side
int proc_mf_change_side(struct file *file, const char *buffer, unsigned long count, void *data)
{
char stkbuf[10];
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if ((*buffer != 'A') &&
(*buffer != 'B') &&
(*buffer != 'C') &&
(*buffer != 'D'))
if (count > 9) count = 9;
if (copy_from_user (stkbuf, buffer, count)) {
return -EFAULT;
}
stkbuf[count] = 0;
if ((*stkbuf != 'A') &&
(*stkbuf != 'B') &&
(*stkbuf != 'C') &&
(*stkbuf != 'D'))
{
printk(KERN_ERR "mf_proc.c: proc_mf_change_side: invalid side\n");
return -EINVAL;
}
mf_setSide(*buffer);
mf_setSide(*stkbuf);
return count;
}
......@@ -256,6 +262,7 @@ int proc_mf_dump_src
int proc_mf_change_src(struct file *file, const char *buffer, unsigned long count, void *data)
{
char stkbuf[10];
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
......@@ -265,11 +272,16 @@ int proc_mf_change_src(struct file *file, const char *buffer, unsigned long coun
return -EINVAL;
}
if ((count == 1) && ((*buffer) == '\0'))
if (count > 9) count = 9;
if (copy_from_user (stkbuf, buffer, count)) {
return -EFAULT;
}
if ((count == 1) && ((*stkbuf) == '\0'))
{
mf_clearSrc();
} else {
mf_displaySrc(*(u32 *)buffer);
mf_displaySrc(*(u32 *)stkbuf);
}
return count;
......
......@@ -127,7 +127,7 @@ void proc_ppc64_init(void)
ent->nlink = 1;
ent->data = (void *)proc_ppc64_pmc_cpu_root[i];
ent->read_proc = (void *)proc_ppc64_pmc_stab_read;
ent->write_proc = (void *)proc_ppc64_pmc_stab_read;
ent->write_proc = NULL;
}
ent = create_proc_entry("htab", S_IRUGO | S_IWUSR,
......@@ -136,7 +136,7 @@ void proc_ppc64_init(void)
ent->nlink = 1;
ent->data = (void *)proc_ppc64_pmc_cpu_root[i];
ent->read_proc = (void *)proc_ppc64_pmc_htab_read;
ent->write_proc = (void *)proc_ppc64_pmc_htab_read;
ent->write_proc = NULL;
}
}
......@@ -146,7 +146,7 @@ void proc_ppc64_init(void)
ent->nlink = 1;
ent->data = (void *)proc_ppc64_pmc_system_root;
ent->read_proc = (void *)proc_ppc64_pmc_stab_read;
ent->write_proc = (void *)proc_ppc64_pmc_stab_read;
ent->write_proc = NULL;
}
ent = create_proc_entry("htab", S_IRUGO | S_IWUSR,
......@@ -155,7 +155,7 @@ void proc_ppc64_init(void)
ent->nlink = 1;
ent->data = (void *)proc_ppc64_pmc_system_root;
ent->read_proc = (void *)proc_ppc64_pmc_htab_read;
ent->write_proc = (void *)proc_ppc64_pmc_htab_read;
ent->write_proc = NULL;
}
/* Create directories for the hardware counters. */
......@@ -168,7 +168,7 @@ void proc_ppc64_init(void)
ent->nlink = 1;
ent->data = (void *)proc_ppc64_pmc_cpu_root[i];
ent->read_proc = (void *)proc_ppc64_pmc_hw_read;
ent->write_proc = (void *)proc_ppc64_pmc_hw_read;
ent->write_proc = NULL;
}
}
......@@ -178,7 +178,7 @@ void proc_ppc64_init(void)
ent->nlink = 1;
ent->data = (void *)proc_ppc64_pmc_system_root;
ent->read_proc = (void *)proc_ppc64_pmc_hw_read;
ent->write_proc = (void *)proc_ppc64_pmc_hw_read;
ent->write_proc = NULL;
}
}
......@@ -676,15 +676,22 @@ static inline void proc_pmc_tlb(void)
int proc_pmc_set_control( struct file *file, const char *buffer, unsigned long count, void *data )
{
if ( ! strncmp( buffer, "stop", 4 ) )
char stkbuf[10];
if (count > 9) count = 9;
if (copy_from_user (stkbuf, buffer, count)) {
return -EFAULT;
}
stkbuf[count] = 0;
if ( ! strncmp( stkbuf, "stop", 4 ) )
proc_pmc_stop();
else if ( ! strncmp( buffer, "start", 5 ) )
else if ( ! strncmp( stkbuf, "start", 5 ) )
proc_pmc_start();
else if ( ! strncmp( buffer, "reset", 5 ) )
else if ( ! strncmp( stkbuf, "reset", 5 ) )
proc_pmc_reset();
else if ( ! strncmp( buffer, "cpi", 3 ) )
else if ( ! strncmp( stkbuf, "cpi", 3 ) )
proc_pmc_cpi();
else if ( ! strncmp( buffer, "tlb", 3 ) )
else if ( ! strncmp( stkbuf, "tlb", 3 ) )
proc_pmc_tlb();
/* IMPLEMENT ME */
......
......@@ -241,12 +241,18 @@ void proc_rtas_init(void)
static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf,
size_t count, loff_t *ppos)
{
char stkbuf[40]; /* its small, its on stack */
struct rtc_time tm;
unsigned long nowtime;
char *dest;
int error;
nowtime = simple_strtoul(buf, &dest, 10);
if (39 < count) count = 39;
if (copy_from_user (stkbuf, buf, count)) {
return -EFAULT;
}
stkbuf[count] = 0;
nowtime = simple_strtoul(stkbuf, &dest, 10);
if (*dest != '\0' && *dest != '\n') {
printk("ppc_rtas_poweron_write: Invalid time\n");
return count;
......@@ -267,18 +273,23 @@ static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf,
static ssize_t ppc_rtas_poweron_read(struct file * file, char * buf,
size_t count, loff_t *ppos)
{
char stkbuf[40]; /* its small, its on stack */
int n;
if (power_on_time == 0)
n = sprintf(buf, "Power on time not set\n");
n = snprintf(stkbuf, 40, "Power on time not set\n");
else
n = sprintf(buf, "%lu\n", power_on_time);
n = snprintf(stkbuf, 40, "%lu\n", power_on_time);
if (*ppos >= strlen(buf))
int sn = strlen (stkbuf) +1;
if (*ppos >= sn)
return 0;
if (n > strlen(buf) - *ppos)
n = strlen(buf) - *ppos;
if (n > sn - *ppos)
n = sn - *ppos;
if (n > count)
n = count;
if (copy_to_user (buf, stkbuf + (*ppos), n)) {
return -EFAULT;
}
*ppos += n;
return n;
}
......@@ -291,11 +302,16 @@ static ssize_t ppc_rtas_progress_write(struct file * file, const char * buf,
{
unsigned long hex;
strcpy(progress_led, buf); /* save the string */
if (count >= MAX_LINELENGTH) count = MAX_LINELENGTH -1;
if (copy_from_user (progress_led, buf, count)) { /* save the string */
return -EFAULT;
}
progress_led[count] = 0;
/* Lets see if the user passed hexdigits */
hex = simple_strtoul(buf, NULL, 10);
ppc_md.progress ((char *)buf, hex);
hex = simple_strtoul(progress_led, NULL, 10);
ppc_md.progress ((char *)progress_led, hex);
return count;
/* clear the line */ /* ppc_md.progress(" ", 0xffff);*/
......@@ -305,14 +321,30 @@ static ssize_t ppc_rtas_progress_read(struct file * file, char * buf,
size_t count, loff_t *ppos)
{
int n = 0;
if (progress_led != NULL)
n = sprintf (buf, "%s\n", progress_led);
if (*ppos >= strlen(buf))
if (progress_led == NULL) return 0;
char * tmpbuf = kmalloc (MAX_LINELENGTH, GFP_KERNEL);
if (!tmpbuf) {
printk(KERN_ERR "error: kmalloc failed\n");
return -ENOMEM;
}
n = sprintf (tmpbuf, "%s\n", progress_led);
int sn = strlen (tmpbuf) +1;
if (*ppos >= sn) {
kfree (tmpbuf);
return 0;
if (n > strlen(buf) - *ppos)
n = strlen(buf) - *ppos;
}
if (n > sn - *ppos)
n = sn - *ppos;
if (n > count)
n = count;
if (copy_to_user (buf, tmpbuf + (*ppos), n)) {
kfree (tmpbuf);
return -EFAULT;
}
kfree (tmpbuf);
*ppos += n;
return n;
}
......@@ -323,12 +355,18 @@ static ssize_t ppc_rtas_progress_read(struct file * file, char * buf,
static ssize_t ppc_rtas_clock_write(struct file * file, const char * buf,
size_t count, loff_t *ppos)
{
char stkbuf[40]; /* its small, its on stack */
struct rtc_time tm;
unsigned long nowtime;
char *dest;
int error;
nowtime = simple_strtoul(buf, &dest, 10);
if (39 < count) count = 39;
if (copy_from_user (stkbuf, buf, count)) {
return -EFAULT;
}
stkbuf[count] = 0;
nowtime = simple_strtoul(stkbuf, &dest, 10);
if (*dest != '\0' && *dest != '\n') {
printk("ppc_rtas_clock_write: Invalid time\n");
return count;
......@@ -356,21 +394,27 @@ static ssize_t ppc_rtas_clock_read(struct file * file, char * buf,
year = ret[0]; mon = ret[1]; day = ret[2];
hour = ret[3]; min = ret[4]; sec = ret[5];
char stkbuf[40]; /* its small, its on stack */
if (error != 0){
printk(KERN_WARNING "error: reading the clock returned: %s\n",
ppc_rtas_process_error(error));
n = sprintf (buf, "0");
n = snprintf (stkbuf, 40, "0");
} else {
n = sprintf (buf, "%lu\n", mktime(year, mon, day, hour, min, sec));
n = snprintf (stkbuf, 40, "%lu\n", mktime(year, mon, day, hour, min, sec));
}
kfree(ret);
if (*ppos >= strlen(buf))
int sn = strlen (stkbuf) +1;
if (*ppos >= sn)
return 0;
if (n > strlen(buf) - *ppos)
n = strlen(buf) - *ppos;
if (n > sn - *ppos)
n = sn - *ppos;
if (n > count)
n = count;
if (copy_to_user (buf, stkbuf + (*ppos), n)) {
return -EFAULT;
}
*ppos += n;
return n;
}
......@@ -764,7 +808,7 @@ int get_location_code(struct individual_sensor s, char * buffer)
n += check_location_string(ret, buffer + n);
n += sprintf ( buffer+n, " ");
/* see how many characters we have printed */
sprintf ( t, "%s ", ret);
snprintf ( t, 50, "%s ", ret);
pos += strlen(t);
if (pos >= llen) pos=0;
......@@ -777,10 +821,17 @@ int get_location_code(struct individual_sensor s, char * buffer)
static ssize_t ppc_rtas_tone_freq_write(struct file * file, const char * buf,
size_t count, loff_t *ppos)
{
char stkbuf[40]; /* its small, its on stack */
unsigned long freq;
char *dest;
int error;
freq = simple_strtoul(buf, &dest, 10);
if (39 < count) count = 39;
if (copy_from_user (stkbuf, buf, count)) {
return -EFAULT;
}
stkbuf[count] = 0;
freq = simple_strtoul(stkbuf, &dest, 10);
if (*dest != '\0' && *dest != '\n') {
printk("ppc_rtas_tone_freq_write: Invalid tone freqency\n");
return count;
......@@ -799,14 +850,19 @@ static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf,
size_t count, loff_t *ppos)
{
int n;
n = sprintf(buf, "%lu\n", rtas_tone_frequency);
char stkbuf[40]; /* its small, its on stack */
n = snprintf(stkbuf, 40, "%lu\n", rtas_tone_frequency);
if (*ppos >= strlen(buf))
int sn = strlen (stkbuf) +1;
if (*ppos >= sn)
return 0;
if (n > strlen(buf) - *ppos)
n = strlen(buf) - *ppos;
if (n > sn - *ppos)
n = sn - *ppos;
if (n > count)
n = count;
if (copy_to_user (buf, stkbuf + (*ppos), n)) {
return -EFAULT;
}
*ppos += n;
return n;
}
......@@ -816,10 +872,17 @@ static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf,
static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf,
size_t count, loff_t *ppos)
{
char stkbuf[40]; /* its small, its on stack */
unsigned long volume;
char *dest;
int error;
volume = simple_strtoul(buf, &dest, 10);
if (39 < count) count = 39;
if (copy_from_user (stkbuf, buf, count)) {
return -EFAULT;
}
stkbuf[count] = 0;
volume = simple_strtoul(stkbuf, &dest, 10);
if (*dest != '\0' && *dest != '\n') {
printk("ppc_rtas_tone_volume_write: Invalid tone volume\n");
return count;
......@@ -840,14 +903,19 @@ static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf,
size_t count, loff_t *ppos)
{
int n;
n = sprintf(buf, "%lu\n", rtas_tone_volume);
char stkbuf[40]; /* its small, its on stack */
n = snprintf(stkbuf, 40, "%lu\n", rtas_tone_volume);
if (*ppos >= strlen(buf))
int sn = strlen (stkbuf) +1;
if (*ppos >= sn)
return 0;
if (n > strlen(buf) - *ppos)
n = strlen(buf) - *ppos;
if (n > sn - *ppos)
n = sn - *ppos;
if (n > count)
n = count;
if (copy_to_user (buf, stkbuf + (*ppos), n)) {
return -EFAULT;
}
*ppos += n;
return n;
}
......@@ -135,17 +135,24 @@ static ssize_t scanlog_read(struct file *file, char *buf,
static ssize_t scanlog_write(struct file * file, const char * buf,
size_t count, loff_t *ppos)
{
char stkbuf[20];
unsigned long status;
if (count > 19) count = 19;
if (copy_from_user (stkbuf, buf, count)) {
return -EFAULT;
}
stkbuf[count] = 0;
if (buf) {
if (strncmp(buf, "reset", 5) == 0) {
if (strncmp(stkbuf, "reset", 5) == 0) {
DEBUG("reset scanlog\n");
status = rtas_call(ibm_scan_log_dump, 2, 1, NULL, NULL, 0);
DEBUG("rtas returns %ld\n", status);
} else if (strncmp(buf, "debugon", 7) == 0) {
} else if (strncmp(stkbuf, "debugon", 7) == 0) {
printk(KERN_ERR "scanlog: debug on\n");
scanlog_debug = 1;
} else if (strncmp(buf, "debugoff", 8) == 0) {
} else if (strncmp(stkbuf, "debugoff", 8) == 0) {
printk(KERN_ERR "scanlog: debug off\n");
scanlog_debug = 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment