mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-29 16:12:10 +00:00
MINOR: tools: provide a may_access() function and make dump_hex() use it
It's a bit too easy to crash by accident when using dump_hex() on any area. Let's have a function to check if the memory may safely be read first. This one abuses the stat() syscall checking if it returns EFAULT or not, in which case it means we're not allowed to read from there. In other situations it may return other codes or even a success if the area pointed to by the file exists. It's important not to abuse it though and as such it's tested only once per output line.
This commit is contained in:
parent
6bdf3e9b11
commit
3710105945
@ -1423,7 +1423,8 @@ int dump_text(struct buffer *out, const char *buf, int bsize);
|
||||
int dump_binary(struct buffer *out, const char *buf, int bsize);
|
||||
int dump_text_line(struct buffer *out, const char *buf, int bsize, int len,
|
||||
int *line, int ptr);
|
||||
void dump_hex(struct buffer *out, const char *pfx, const void *buf, int len);
|
||||
void dump_hex(struct buffer *out, const char *pfx, const void *buf, int len, int unsafe);
|
||||
int may_access(const void *ptr);
|
||||
|
||||
/* same as realloc() except that ptr is also freed upon failure */
|
||||
static inline void *my_realloc2(void *ptr, size_t size)
|
||||
|
@ -325,7 +325,7 @@ static int debug_parse_cli_hex(char **args, char *payload, struct appctx *appctx
|
||||
len = ((start + 128) & -16) - start;
|
||||
|
||||
chunk_reset(&trash);
|
||||
dump_hex(&trash, " ", (const void *)start, len);
|
||||
dump_hex(&trash, " ", (const void *)start, len, 1);
|
||||
trash.area[trash.data] = 0;
|
||||
appctx->ctx.cli.severity = LOG_INFO;
|
||||
appctx->ctx.cli.msg = trash.area;
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
@ -4009,6 +4011,26 @@ fail_wl:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* indicates if a memory location may safely be read or not. The trick consists
|
||||
* in performing a harmless syscall using this location as an input and letting
|
||||
* the operating system report whether it's OK or not. For this we have the
|
||||
* stat() syscall, which will return EFAULT when the memory location supposed
|
||||
* to contain the file name is not readable. If it is readable it will then
|
||||
* either return 0 if the area contains an existing file name, or -1 with
|
||||
* another code. This must not be abused, and some audit systems might detect
|
||||
* this as abnormal activity. It's used only for unsafe dumps.
|
||||
*/
|
||||
int may_access(const void *ptr)
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
if (stat(ptr, &buf) == 0)
|
||||
return 1;
|
||||
if (errno == EFAULT)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* print a string of text buffer to <out>. The format is :
|
||||
* Non-printable chars \t, \n, \r and \e are * encoded in C format.
|
||||
* Other non-printable chars are encoded "\xHH". Space, '\', and '=' are also escaped.
|
||||
@ -4081,9 +4103,10 @@ int dump_binary(struct buffer *out, const char *buf, int bsize)
|
||||
* The output will not wrap pas the buffer's end so it is more optimal if the
|
||||
* caller makes sure the buffer is aligned first. A trailing zero will always
|
||||
* be appended (and not counted) if there is room for it. The caller must make
|
||||
* sure that the area is dumpable first.
|
||||
* sure that the area is dumpable first. If <unsafe> is non-null, the memory
|
||||
* locations are checked first for being readable.
|
||||
*/
|
||||
void dump_hex(struct buffer *out, const char *pfx, const void *buf, int len)
|
||||
void dump_hex(struct buffer *out, const char *pfx, const void *buf, int len, int unsafe)
|
||||
{
|
||||
const unsigned char *d = buf;
|
||||
int i, j, start;
|
||||
@ -4094,25 +4117,32 @@ void dump_hex(struct buffer *out, const char *pfx, const void *buf, int len)
|
||||
for (i = 0; i < start + len; i += 16) {
|
||||
chunk_appendf(out, (sizeof(void *) == 4) ? "%s%8p: " : "%s%16p: ", pfx, d + i);
|
||||
|
||||
// 0: unchecked, 1: checked safe, 2: danger
|
||||
unsafe = !!unsafe;
|
||||
if (unsafe && !may_access(d + i))
|
||||
unsafe = 2;
|
||||
|
||||
for (j = 0; j < 16; j++) {
|
||||
if ((i + j >= start) && (i + j < start + len))
|
||||
chunk_appendf(out, "%02x ", d[i + j]);
|
||||
else
|
||||
if ((i + j < start) || (i + j >= start + len))
|
||||
chunk_strcat(out, "'' ");
|
||||
else if (unsafe > 1)
|
||||
chunk_strcat(out, "** ");
|
||||
else
|
||||
chunk_appendf(out, "%02x ", d[i + j]);
|
||||
|
||||
if (j == 7)
|
||||
chunk_strcat(out, "- ");
|
||||
}
|
||||
chunk_strcat(out, " ");
|
||||
for (j = 0; j < 16; j++) {
|
||||
if ((i + j >= start) && (i + j < start + len)) {
|
||||
if (isprint(d[i + j]))
|
||||
chunk_appendf(out, "%c", d[i + j]);
|
||||
else
|
||||
chunk_strcat(out, ".");
|
||||
}
|
||||
else
|
||||
if ((i + j < start) || (i + j >= start + len))
|
||||
chunk_strcat(out, "'");
|
||||
else if (unsafe > 1)
|
||||
chunk_strcat(out, "*");
|
||||
else if (isprint(d[i + j]))
|
||||
chunk_appendf(out, "%c", d[i + j]);
|
||||
else
|
||||
chunk_strcat(out, ".");
|
||||
}
|
||||
chunk_strcat(out, "\n");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user