Commit 5e12f283 authored by David S. Miller's avatar David S. Miller

[OpenPROM]: Fix signedness/user-access checking bugs in openprom char driver and openpromfs.

parent 10715329
...@@ -68,7 +68,7 @@ static int options_node = 0; ...@@ -68,7 +68,7 @@ static int options_node = 0;
*/ */
static int copyin(struct openpromio *info, struct openpromio **opp_p) static int copyin(struct openpromio *info, struct openpromio **opp_p)
{ {
int bufsize; unsigned int bufsize;
if (!info || !opp_p) if (!info || !opp_p)
return -EFAULT; return -EFAULT;
......
...@@ -77,7 +77,8 @@ static ssize_t nodenum_read(struct file *file, char *buf, ...@@ -77,7 +77,8 @@ static ssize_t nodenum_read(struct file *file, char *buf,
return 0; return 0;
if (count > 9 - file->f_pos) if (count > 9 - file->f_pos)
count = 9 - file->f_pos; count = 9 - file->f_pos;
copy_to_user(buf, buffer + file->f_pos, count); if (copy_to_user(buf, buffer + file->f_pos, count))
return -EFAULT;
file->f_pos += count; file->f_pos += count;
return count; return count;
} }
...@@ -184,7 +185,8 @@ static ssize_t property_read(struct file *filp, char *buf, ...@@ -184,7 +185,8 @@ static ssize_t property_read(struct file *filp, char *buf,
if (count > i - k) count = i - k; if (count > i - k) count = i - k;
if (op->flag & OPP_STRING) { if (op->flag & OPP_STRING) {
if (!k) { if (!k) {
__put_user('\'', buf); if (put_user('\'', buf))
return -EFAULT;
k++; k++;
count--; count--;
} }
...@@ -195,17 +197,21 @@ static ssize_t property_read(struct file *filp, char *buf, ...@@ -195,17 +197,21 @@ static ssize_t property_read(struct file *filp, char *buf,
j = count; j = count;
if (j >= 0) { if (j >= 0) {
copy_to_user(buf + k - filp->f_pos, if (copy_to_user(buf + k - filp->f_pos,
op->value + k - 1, j); op->value + k - 1, j))
return -EFAULT;
count -= j; count -= j;
k += j; k += j;
} }
if (count) if (count) {
__put_user('\'', &buf [k++ - filp->f_pos]); if (put_user('\'', &buf [k++ - filp->f_pos]))
if (count > 1) return -EFAULT;
__put_user('\n', &buf [k++ - filp->f_pos]); }
if (count > 1) {
if (put_user('\n', &buf [k++ - filp->f_pos]))
return -EFAULT;
}
} else if (op->flag & OPP_STRINGLIST) { } else if (op->flag & OPP_STRINGLIST) {
char *tmp; char *tmp;
...@@ -225,7 +231,8 @@ static ssize_t property_read(struct file *filp, char *buf, ...@@ -225,7 +231,8 @@ static ssize_t property_read(struct file *filp, char *buf,
} }
strcpy(s, "'\n"); strcpy(s, "'\n");
copy_to_user(buf, tmp + k, count); if (copy_to_user(buf, tmp + k, count))
return -EFAULT;
kfree(tmp); kfree(tmp);
k += count; k += count;
...@@ -243,27 +250,34 @@ static ssize_t property_read(struct file *filp, char *buf, ...@@ -243,27 +250,34 @@ static ssize_t property_read(struct file *filp, char *buf,
if (first == last) { if (first == last) {
sprintf (buffer, "%08x.", *first); sprintf (buffer, "%08x.", *first);
copy_to_user (buf, buffer + first_off, last_cnt - first_off); if (copy_to_user(buf, buffer + first_off,
last_cnt - first_off))
return -EFAULT;
buf += last_cnt - first_off; buf += last_cnt - first_off;
} else { } else {
for (q = first; q <= last; q++) { for (q = first; q <= last; q++) {
sprintf (buffer, "%08x.", *q); sprintf (buffer, "%08x.", *q);
if (q == first) { if (q == first) {
copy_to_user (buf, buffer + first_off, if (copy_to_user(buf, buffer + first_off,
9 - first_off); 9 - first_off))
return -EFAULT;
buf += 9 - first_off; buf += 9 - first_off;
} else if (q == last) { } else if (q == last) {
copy_to_user (buf, buffer, last_cnt); if (copy_to_user(buf, buffer, last_cnt))
return -EFAULT;
buf += last_cnt; buf += last_cnt;
} else { } else {
copy_to_user (buf, buffer, 9); if (copy_to_user(buf, buffer, 9))
return -EFAULT;
buf += 9; buf += 9;
} }
} }
} }
if (last == (u32 *)(op->value + op->len - 4) && last_cnt == 9) if (last == (u32 *)(op->value + op->len - 4) && last_cnt == 9) {
__put_user('\n', (buf - 1)); if (put_user('\n', (buf - 1)))
return -EFAULT;
}
k += count; k += count;
...@@ -272,24 +286,29 @@ static ssize_t property_read(struct file *filp, char *buf, ...@@ -272,24 +286,29 @@ static ssize_t property_read(struct file *filp, char *buf,
if ((k < i - 1) && (k & 1)) { if ((k < i - 1) && (k & 1)) {
sprintf (buffer, "%02x", *(op->value + (k >> 1))); sprintf (buffer, "%02x", *(op->value + (k >> 1)));
__put_user(buffer[1], &buf[k++ - filp->f_pos]); if (put_user(buffer[1], &buf[k++ - filp->f_pos]))
return -EFAULT;
count--; count--;
} }
for (; (count > 1) && (k < i - 1); k += 2) { for (; (count > 1) && (k < i - 1); k += 2) {
sprintf (buffer, "%02x", *(op->value + (k >> 1))); sprintf (buffer, "%02x", *(op->value + (k >> 1)));
copy_to_user (buf + k - filp->f_pos, buffer, 2); if (copy_to_user(buf + k - filp->f_pos, buffer, 2))
return -EFAULT;
count -= 2; count -= 2;
} }
if (count && (k < i - 1)) { if (count && (k < i - 1)) {
sprintf (buffer, "%02x", *(op->value + (k >> 1))); sprintf (buffer, "%02x", *(op->value + (k >> 1)));
__put_user(buffer[0], &buf[k++ - filp->f_pos]); if (put_user(buffer[0], &buf[k++ - filp->f_pos]))
return -EFAULT;
count--; count--;
} }
if (count) if (count) {
__put_user('\n', &buf [k++ - filp->f_pos]); if (put_user('\n', &buf [k++ - filp->f_pos]))
return -EFAULT;
}
} }
count = k - filp->f_pos; count = k - filp->f_pos;
filp->f_pos = k; filp->f_pos = k;
...@@ -326,7 +345,8 @@ static ssize_t property_write(struct file *filp, const char *buf, ...@@ -326,7 +345,8 @@ static ssize_t property_write(struct file *filp, const char *buf,
if (j == 9) j = 0; if (j == 9) j = 0;
if (!j) { if (!j) {
char ctmp; char ctmp;
__get_user(ctmp, &buf[i]); if (get_user(ctmp, &buf[i]))
return -EFAULT;
if (ctmp != '.') { if (ctmp != '.') {
if (ctmp != '\n') { if (ctmp != '\n') {
if (op->flag & OPP_BINARY) if (op->flag & OPP_BINARY)
...@@ -341,7 +361,8 @@ static ssize_t property_write(struct file *filp, const char *buf, ...@@ -341,7 +361,8 @@ static ssize_t property_write(struct file *filp, const char *buf,
} }
} else { } else {
char ctmp; char ctmp;
__get_user(ctmp, &buf[i]); if (get_user(ctmp, &buf[i]))
return -EFAULT;
if (ctmp < '0' || if (ctmp < '0' ||
(ctmp > '9' && ctmp < 'A') || (ctmp > '9' && ctmp < 'A') ||
(ctmp > 'F' && ctmp < 'a') || (ctmp > 'F' && ctmp < 'a') ||
...@@ -379,8 +400,10 @@ static ssize_t property_write(struct file *filp, const char *buf, ...@@ -379,8 +400,10 @@ static ssize_t property_write(struct file *filp, const char *buf,
last_cnt = (k + count) % 9; last_cnt = (k + count) % 9;
if (first + 1 == last) { if (first + 1 == last) {
memset (tmp, '0', 8); memset (tmp, '0', 8);
copy_from_user (tmp + first_off, buf, if (copy_from_user(tmp + first_off, buf,
(count + first_off > 8) ? 8 - first_off : count); (count + first_off > 8) ?
8 - first_off : count))
return -EFAULT;
mask = 0xffffffff; mask = 0xffffffff;
mask2 = 0xffffffff; mask2 = 0xffffffff;
for (j = 0; j < first_off; j++) for (j = 0; j < first_off; j++)
...@@ -399,8 +422,10 @@ static ssize_t property_write(struct file *filp, const char *buf, ...@@ -399,8 +422,10 @@ static ssize_t property_write(struct file *filp, const char *buf,
if (q == first) { if (q == first) {
if (first_off < 8) { if (first_off < 8) {
memset (tmp, '0', 8); memset (tmp, '0', 8);
copy_from_user (tmp + first_off, buf, if (copy_from_user(tmp + first_off,
8 - first_off); buf,
8 - first_off))
return -EFAULT;
mask = 0xffffffff; mask = 0xffffffff;
for (j = 0; j < first_off; j++) for (j = 0; j < first_off; j++)
mask >>= 1; mask >>= 1;
...@@ -411,7 +436,8 @@ static ssize_t property_write(struct file *filp, const char *buf, ...@@ -411,7 +436,8 @@ static ssize_t property_write(struct file *filp, const char *buf,
} else if ((q == last - 1) && last_cnt } else if ((q == last - 1) && last_cnt
&& (last_cnt < 8)) { && (last_cnt < 8)) {
memset (tmp, '0', 8); memset (tmp, '0', 8);
copy_from_user (tmp, buf, last_cnt); if (copy_from_user(tmp, buf, last_cnt))
return -EFAULT;
mask = 0xffffffff; mask = 0xffffffff;
for (j = 0; j < 8 - last_cnt; j++) for (j = 0; j < 8 - last_cnt; j++)
mask <<= 1; mask <<= 1;
...@@ -421,7 +447,8 @@ static ssize_t property_write(struct file *filp, const char *buf, ...@@ -421,7 +447,8 @@ static ssize_t property_write(struct file *filp, const char *buf,
} else { } else {
char tchars[17]; /* XXX yuck... */ char tchars[17]; /* XXX yuck... */
copy_from_user(tchars, buf, 16); if (copy_from_user(tchars, buf, 16))
return -EFAULT;
*q = simple_strtoul (tchars, 0, 16); *q = simple_strtoul (tchars, 0, 16);
buf += 9; buf += 9;
} }
...@@ -444,7 +471,8 @@ static ssize_t property_write(struct file *filp, const char *buf, ...@@ -444,7 +471,8 @@ static ssize_t property_write(struct file *filp, const char *buf,
*/ */
if (k > 0) if (k > 0)
return -EINVAL; return -EINVAL;
__get_user(ctmp, buf); if (get_user(ctmp, buf))
return -EFAULT;
if (ctmp == '\'') { if (ctmp == '\'') {
op->flag |= OPP_QUOTED; op->flag |= OPP_QUOTED;
buf++; buf++;
...@@ -476,7 +504,8 @@ static ssize_t property_write(struct file *filp, const char *buf, ...@@ -476,7 +504,8 @@ static ssize_t property_write(struct file *filp, const char *buf,
kfree (b); kfree (b);
} }
p = op->value + filp->f_pos - ((op->flag & OPP_QUOTED) ? 1 : 0); p = op->value + filp->f_pos - ((op->flag & OPP_QUOTED) ? 1 : 0);
copy_from_user (p, buf, count); if (copy_from_user(p, buf, count))
return -EFAULT;
op->flag |= OPP_DIRTY; op->flag |= OPP_DIRTY;
for (i = 0; i < count; i++, p++) for (i = 0; i < count; i++, p++)
if (*p == '\n') { if (*p == '\n') {
......
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