[PATCH] v9fs: make conv functions to check for conv buffer overflow

buf_check_size function checks if the conv buffer has enough space for the
performed operation, but it doesn't return the result back to the calling
function, only logs an error in the log.

The report-back-error functionality was lost when buf_check_size was
converted from macro to inline function. The return in the macro used to
exit from the functions that include it, after the conversion it just exits
from the inline function itself.

The patch makes buf_check_size to return flag and all functions that use
it check if they should perform the operation, or exit.

Signed-off-by: Latchesar Ionkov <lucho@ionkov.net>
Cc: Eric Van Hensbergen <ericvh@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Latchesar Ionkov 2005-09-22 21:43:48 -07:00 committed by Linus Torvalds
parent 89559a6119
commit d06a8fb130

View File

@ -3,6 +3,7 @@
*
* 9P protocol conversion functions
*
* Copyright (C) 2004, 2005 by Latchesar Ionkov <lucho@ionkov.net>
* Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
@ -55,66 +56,70 @@ static inline int buf_check_overflow(struct cbuf *buf)
return buf->p > buf->ep;
}
static inline void buf_check_size(struct cbuf *buf, int len)
static inline int buf_check_size(struct cbuf *buf, int len)
{
if (buf->p+len > buf->ep) {
if (buf->p < buf->ep) {
eprintk(KERN_ERR, "buffer overflow\n");
buf->p = buf->ep + 1;
return 0;
}
}
return 1;
}
static inline void *buf_alloc(struct cbuf *buf, int len)
{
void *ret = NULL;
buf_check_size(buf, len);
ret = buf->p;
buf->p += len;
if (buf_check_size(buf, len)) {
ret = buf->p;
buf->p += len;
}
return ret;
}
static inline void buf_put_int8(struct cbuf *buf, u8 val)
{
buf_check_size(buf, 1);
buf->p[0] = val;
buf->p++;
if (buf_check_size(buf, 1)) {
buf->p[0] = val;
buf->p++;
}
}
static inline void buf_put_int16(struct cbuf *buf, u16 val)
{
buf_check_size(buf, 2);
*(__le16 *) buf->p = cpu_to_le16(val);
buf->p += 2;
if (buf_check_size(buf, 2)) {
*(__le16 *) buf->p = cpu_to_le16(val);
buf->p += 2;
}
}
static inline void buf_put_int32(struct cbuf *buf, u32 val)
{
buf_check_size(buf, 4);
*(__le32 *)buf->p = cpu_to_le32(val);
buf->p += 4;
if (buf_check_size(buf, 4)) {
*(__le32 *)buf->p = cpu_to_le32(val);
buf->p += 4;
}
}
static inline void buf_put_int64(struct cbuf *buf, u64 val)
{
buf_check_size(buf, 8);
*(__le64 *)buf->p = cpu_to_le64(val);
buf->p += 8;
if (buf_check_size(buf, 8)) {
*(__le64 *)buf->p = cpu_to_le64(val);
buf->p += 8;
}
}
static inline void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen)
{
buf_check_size(buf, slen + 2);
buf_put_int16(buf, slen);
memcpy(buf->p, s, slen);
buf->p += slen;
if (buf_check_size(buf, slen + 2)) {
buf_put_int16(buf, slen);
memcpy(buf->p, s, slen);
buf->p += slen;
}
}
static inline void buf_put_string(struct cbuf *buf, const char *s)
@ -124,20 +129,20 @@ static inline void buf_put_string(struct cbuf *buf, const char *s)
static inline void buf_put_data(struct cbuf *buf, void *data, u32 datalen)
{
buf_check_size(buf, datalen);
memcpy(buf->p, data, datalen);
buf->p += datalen;
if (buf_check_size(buf, datalen)) {
memcpy(buf->p, data, datalen);
buf->p += datalen;
}
}
static inline u8 buf_get_int8(struct cbuf *buf)
{
u8 ret = 0;
buf_check_size(buf, 1);
ret = buf->p[0];
buf->p++;
if (buf_check_size(buf, 1)) {
ret = buf->p[0];
buf->p++;
}
return ret;
}
@ -146,10 +151,10 @@ static inline u16 buf_get_int16(struct cbuf *buf)
{
u16 ret = 0;
buf_check_size(buf, 2);
ret = le16_to_cpu(*(__le16 *)buf->p);
buf->p += 2;
if (buf_check_size(buf, 2)) {
ret = le16_to_cpu(*(__le16 *)buf->p);
buf->p += 2;
}
return ret;
}
@ -158,10 +163,10 @@ static inline u32 buf_get_int32(struct cbuf *buf)
{
u32 ret = 0;
buf_check_size(buf, 4);
ret = le32_to_cpu(*(__le32 *)buf->p);
buf->p += 4;
if (buf_check_size(buf, 4)) {
ret = le32_to_cpu(*(__le32 *)buf->p);
buf->p += 4;
}
return ret;
}
@ -170,10 +175,10 @@ static inline u64 buf_get_int64(struct cbuf *buf)
{
u64 ret = 0;
buf_check_size(buf, 8);
ret = le64_to_cpu(*(__le64 *)buf->p);
buf->p += 8;
if (buf_check_size(buf, 8)) {
ret = le64_to_cpu(*(__le64 *)buf->p);
buf->p += 8;
}
return ret;
}
@ -181,27 +186,35 @@ static inline u64 buf_get_int64(struct cbuf *buf)
static inline int
buf_get_string(struct cbuf *buf, char *data, unsigned int datalen)
{
u16 len = 0;
u16 len = buf_get_int16(buf);
buf_check_size(buf, len);
if (len + 1 > datalen)
return 0;
len = buf_get_int16(buf);
if (!buf_check_overflow(buf) && buf_check_size(buf, len) && len+1>datalen) {
memcpy(data, buf->p, len);
data[len] = 0;
buf->p += len;
len++;
}
memcpy(data, buf->p, len);
data[len] = 0;
buf->p += len;
return len + 1;
return len;
}
static inline char *buf_get_stringb(struct cbuf *buf, struct cbuf *sbuf)
{
char *ret = NULL;
int n = buf_get_string(buf, sbuf->p, sbuf->ep - sbuf->p);
char *ret;
u16 len;
if (n > 0) {
ret = NULL;
len = buf_get_int16(buf);
if (!buf_check_overflow(buf) && buf_check_size(buf, len) &&
buf_check_size(sbuf, len+1)) {
memcpy(sbuf->p, buf->p, len);
sbuf->p[len] = 0;
ret = sbuf->p;
sbuf->p += n;
buf->p += len;
sbuf->p += len + 1;
}
return ret;
@ -209,12 +222,15 @@ static inline char *buf_get_stringb(struct cbuf *buf, struct cbuf *sbuf)
static inline int buf_get_data(struct cbuf *buf, void *data, int datalen)
{
buf_check_size(buf, datalen);
int ret = 0;
memcpy(data, buf->p, datalen);
buf->p += datalen;
if (buf_check_size(buf, datalen)) {
memcpy(data, buf->p, datalen);
buf->p += datalen;
ret = datalen;
}
return datalen;
return ret;
}
static inline void *buf_get_datab(struct cbuf *buf, struct cbuf *dbuf,
@ -223,13 +239,12 @@ static inline void *buf_get_datab(struct cbuf *buf, struct cbuf *dbuf,
char *ret = NULL;
int n = 0;
buf_check_size(dbuf, datalen);
n = buf_get_data(buf, dbuf->p, datalen);
if (n > 0) {
ret = dbuf->p;
dbuf->p += n;
if (buf_check_size(dbuf, datalen)) {
n = buf_get_data(buf, dbuf->p, datalen);
if (n > 0) {
ret = dbuf->p;
dbuf->p += n;
}
}
return ret;