[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:
parent
89559a6119
commit
d06a8fb130
153
fs/9p/conv.c
153
fs/9p/conv.c
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue