Fix issues in new nmrp code

This commit is contained in:
Joseph C. Lehner 2017-02-21 17:55:39 +01:00
parent 63dec92a57
commit 44782bee4c
2 changed files with 26 additions and 33 deletions

View file

@ -26,6 +26,7 @@ dofuzz: fuzz
echo core | sudo tee /proc/sys/kernel/core_pattern echo core | sudo tee /proc/sys/kernel/core_pattern
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
afl-fuzz -i fuzzin -o fuzzout -- ./fuzz afl-fuzz -i fuzzin -o fuzzout -- ./fuzz
echo powersave | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
clean: clean:
rm -f $(nmrpflash_OBJ) nmrpflash rm -f $(nmrpflash_OBJ) nmrpflash

58
nmrp.c
View file

@ -148,6 +148,7 @@ static void *msg_opt(struct nmrp_msg *msg, uint16_t type, uint16_t* len)
return opt->val; return opt->val;
} }
opt = (struct nmrp_opt*)(((char *)opt) + olen);
rem -= olen; rem -= olen;
} while (rem); } while (rem);
@ -214,13 +215,7 @@ static void msg_mkadvertise(struct nmrp_msg *msg, const char *magic)
static void msg_mkconfack(struct nmrp_msg *msg, uint32_t ipaddr, uint32_t ipmask, uint16_t region) static void msg_mkconfack(struct nmrp_msg *msg, uint32_t ipaddr, uint32_t ipmask, uint16_t region)
{ {
char *p; char *p;
struct { uint32_t ip[2] = { ipaddr, ipmask };
uint32_t addr;
uint32_t mask;
} PACKED ip = {
.addr = ipaddr,
.mask = ipmask
};
msg_init(msg, NMRP_C_CONF_ACK); msg_init(msg, NMRP_C_CONF_ACK);
p = msg_mkopt(msg, msg->opts, NMRP_O_DEV_IP, &ip, 8); p = msg_mkopt(msg, msg->opts, NMRP_O_DEV_IP, &ip, 8);
@ -261,7 +256,7 @@ static int pkt_send(struct ethsock *sock, struct nmrp_pkt *pkt)
static int pkt_recv(struct ethsock *sock, struct nmrp_pkt *pkt) static int pkt_recv(struct ethsock *sock, struct nmrp_pkt *pkt)
{ {
ssize_t bytes, len; ssize_t bytes, mlen;
memset(pkt, 0, sizeof(*pkt)); memset(pkt, 0, sizeof(*pkt));
bytes = ethsock_recv(sock, pkt, sizeof(*pkt)); bytes = ethsock_recv(sock, pkt, sizeof(*pkt));
@ -269,20 +264,19 @@ static int pkt_recv(struct ethsock *sock, struct nmrp_pkt *pkt)
return 1; return 1;
} else if (!bytes) { } else if (!bytes) {
return 2; return 2;
} else if (bytes < NMRP_MIN_PKT_LEN) {
fprintf(stderr, "Short packet (%d bytes)\n", (int)bytes);
return 1;
} }
len = ntohs(pkt->msg.len) + sizeof(pkt->eh); mlen = ntohs(pkt->msg.len);
if (bytes < len) { if (bytes < (mlen + sizeof(pkt->eh))
fprintf(stderr, "Short packet (expected %d, got %d).\n", || bytes < NMRP_MIN_PKT_LEN
(int)len, (int)bytes); || mlen < NMRP_HDR_LEN) {
fprintf(stderr, "Short packet (%d raw, %d message)\n",
(int)bytes, (int)mlen);
return 1; return 1;
} else if (bytes > sizeof(pkt->msg) + sizeof(pkt->eh)) { } else if (mlen > sizeof(pkt->msg)) {
fprintf(stderr, "Packet size exceeds maximum (got %d).\n", printf("Truncating %d byte message.\n", (int)mlen);
(int)bytes); pkt->msg.len = htons(sizeof(pkt->msg));
} }
return 0; return 0;
@ -366,10 +360,8 @@ int nmrp_do(struct nmrpd_args *args)
struct ethsock_arp_undo *arp_undo = NULL; struct ethsock_arp_undo *arp_undo = NULL;
uint32_t intf_addr; uint32_t intf_addr;
void (*sigh_orig)(int); void (*sigh_orig)(int);
struct { struct in_addr ipaddr;
struct in_addr addr; struct in_addr ipmask;
struct in_addr mask;
} PACKED ipconf;
if (args->op != NMRP_UPLOAD_FW) { if (args->op != NMRP_UPLOAD_FW) {
fprintf(stderr, "Operation not implemented.\n"); fprintf(stderr, "Operation not implemented.\n");
@ -381,9 +373,9 @@ int nmrp_do(struct nmrpd_args *args)
return 1; return 1;
} }
ipconf.mask.s_addr = inet_addr(args->ipmask); ipmask.s_addr = inet_addr(args->ipmask);
if (ipconf.mask.s_addr == INADDR_NONE if (ipmask.s_addr == INADDR_NONE
|| netmask(bitcount(ipconf.mask.s_addr)) != ipconf.mask.s_addr) { || netmask(bitcount(ipmask.s_addr)) != ipmask.s_addr) {
fprintf(stderr, "Invalid subnet mask '%s'.\n", args->ipmask); fprintf(stderr, "Invalid subnet mask '%s'.\n", args->ipmask);
return 1; return 1;
} }
@ -404,7 +396,7 @@ int nmrp_do(struct nmrpd_args *args)
autoip = false; autoip = false;
} }
if ((ipconf.addr.s_addr = inet_addr(args->ipaddr)) == INADDR_NONE) { if ((ipaddr.s_addr = inet_addr(args->ipaddr)) == INADDR_NONE) {
fprintf(stderr, "Invalid IP address '%s'.\n", args->ipaddr); fprintf(stderr, "Invalid IP address '%s'.\n", args->ipaddr);
return 1; return 1;
} }
@ -447,7 +439,7 @@ int nmrp_do(struct nmrpd_args *args)
sigh_orig = signal(SIGINT, sigh); sigh_orig = signal(SIGINT, sigh);
if (!autoip) { if (!autoip) {
status = is_valid_ip(sock, &ipconf.addr, &ipconf.mask); status = is_valid_ip(sock, &ipaddr, &ipmask);
if (status <= 0) { if (status <= 0) {
if (!status) { if (!status) {
fprintf(stderr, "Address %s/%s cannot be used on interface %s.\n", fprintf(stderr, "Address %s/%s cannot be used on interface %s.\n",
@ -460,7 +452,7 @@ int nmrp_do(struct nmrpd_args *args)
printf("Adding %s to interface %s.\n", args->ipaddr_intf, args->intf); printf("Adding %s to interface %s.\n", args->ipaddr_intf, args->intf);
} }
if (ethsock_ip_add(sock, intf_addr, ipconf.mask.s_addr, &ip_undo) != 0) { if (ethsock_ip_add(sock, intf_addr, ipmask.s_addr, &ip_undo) != 0) {
goto out; goto out;
} }
} }
@ -532,7 +524,7 @@ int nmrp_do(struct nmrpd_args *args)
status = 1; status = 1;
goto out; goto out;
case NMRP_C_CONF_REQ: case NMRP_C_CONF_REQ:
msg_mkconfack(&tx.msg, ipconf.addr.s_addr, ipconf.mask.s_addr, region); msg_mkconfack(&tx.msg, ipaddr.s_addr, ipmask.s_addr, region);
expect = NMRP_C_TFTP_UL_REQ; expect = NMRP_C_TFTP_UL_REQ;
printf("Received configuration request from %s.\n", printf("Received configuration request from %s.\n",
@ -543,7 +535,7 @@ int nmrp_do(struct nmrpd_args *args)
printf("Sending configuration: %s, netmask %s.\n", printf("Sending configuration: %s, netmask %s.\n",
args->ipaddr, args->ipmask); args->ipaddr, args->ipmask);
if (ethsock_arp_add(sock, rx.eh.ether_shost, ipconf.addr.s_addr, &arp_undo) != 0) { if (ethsock_arp_add(sock, rx.eh.ether_shost, ipaddr.s_addr, &arp_undo) != 0) {
goto out; goto out;
} }
@ -580,17 +572,17 @@ int nmrp_do(struct nmrpd_args *args)
if (args->tftpcmd) { if (args->tftpcmd) {
printf("Executing '%s' ... \n", args->tftpcmd); printf("Executing '%s' ... \n", args->tftpcmd);
setenv("IP", inet_ntoa(ipconf.addr), 1); setenv("IP", inet_ntoa(ipaddr), 1);
setenv("PORT", lltostr(args->port, 10), 1); setenv("PORT", lltostr(args->port, 10), 1);
setenv("MAC", mac_to_str(rx.eh.ether_shost), 1); setenv("MAC", mac_to_str(rx.eh.ether_shost), 1);
setenv("NETMASK", inet_ntoa(ipconf.mask), 1); setenv("NETMASK", inet_ntoa(ipmask), 1);
//setenv("FILENAME", args->file_remote ? args->file_remote : "", 1); //setenv("FILENAME", args->file_remote ? args->file_remote : "", 1);
status = system(args->tftpcmd); status = system(args->tftpcmd);
} }
if (!status && args->file_local) { if (!status && args->file_local) {
if (!autoip) { if (!autoip) {
status = is_valid_ip(sock, &ipconf.addr, &ipconf.mask); status = is_valid_ip(sock, &ipaddr, &ipmask);
if (status < 0) { if (status < 0) {
goto out; goto out;
} else if (!status) { } else if (!status) {