Skip to content

Commit c995838

Browse files
committed
Make improvements
- Clean up sigaction() code - Add a port scanner example - Introduce a ParseCidr() API - Clean up our futex abstraction code - Fix a harmless integer overflow in ParseIp() - Use kernel semaphores on NetBSD to make threads much faster
1 parent 539bddc commit c995838

File tree

107 files changed

+1085
-492
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

107 files changed

+1085
-492
lines changed

examples/portscan.c

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#if 0
2+
/*─────────────────────────────────────────────────────────────────╗
3+
│ To the extent possible under law, Justine Tunney has waived │
4+
│ all copyright and related or neighboring rights to this file, │
5+
│ as it is written in the following disclaimers: │
6+
│ • http://unlicense.org/ │
7+
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
8+
╚─────────────────────────────────────────────────────────────────*/
9+
#endif
10+
#include "libc/assert.h"
11+
#include "libc/calls/calls.h"
12+
#include "libc/calls/struct/timeval.h"
13+
#include "libc/errno.h"
14+
#include "libc/fmt/conv.h"
15+
#include "libc/fmt/fmt.h"
16+
#include "libc/mem/alloca.h"
17+
#include "libc/runtime/runtime.h"
18+
#include "libc/sock/sock.h"
19+
#include "libc/sock/struct/sockaddr.h"
20+
#include "libc/stdio/stdio.h"
21+
#include "libc/str/str.h"
22+
#include "libc/sysv/consts/af.h"
23+
#include "libc/sysv/consts/ipproto.h"
24+
#include "libc/sysv/consts/so.h"
25+
#include "libc/sysv/consts/sock.h"
26+
#include "libc/sysv/consts/sol.h"
27+
#include "net/http/ip.h"
28+
29+
/**
30+
* @fileoverview fast local network port scanner, e.g.
31+
*
32+
* make -j8 o//examples/portscan.com
33+
* o//examples/portscan.com 10.10.10.0/24 22
34+
*/
35+
36+
const char *FormatIp(char buf[16], uint32_t ip) {
37+
snprintf(buf, 16, "%hhu.%hhu.%hhu.%hhu", ip >> 24, ip >> 16, ip >> 8, ip);
38+
return buf;
39+
}
40+
41+
#define FormatIp(x) FormatIp(alloca(16), x)
42+
43+
int main(int argc, char *argv[]) {
44+
int port;
45+
struct Cidr in;
46+
uint32_t netmask;
47+
const char *status;
48+
struct timeval timeout;
49+
uint32_t network_address;
50+
uint32_t last_host_address;
51+
uint32_t first_host_address;
52+
53+
if (argc != 3) {
54+
PrintUsage:
55+
fprintf(stderr,
56+
"usage: %s IP/CIDR PORT\n"
57+
"example: %s 192.168.0.0/24 22\n",
58+
argv[0], argv[0]);
59+
return 1;
60+
}
61+
62+
in = ParseCidr(argv[1], -1);
63+
if (in.addr == -1) {
64+
fprintf(stderr, "error: bad ip/cidr\n");
65+
goto PrintUsage;
66+
}
67+
68+
port = atoi(argv[2]);
69+
if (!(1 <= port && port <= 65535)) {
70+
fprintf(stderr, "error: bad port\n");
71+
goto PrintUsage;
72+
}
73+
74+
if (in.cidr > 30) {
75+
fprintf(stderr, "error: maximum supported cidr is 30\n");
76+
goto PrintUsage;
77+
}
78+
79+
if (in.cidr < 22) {
80+
fprintf(stderr, "error: minimum cidr support right now is 22\n");
81+
goto PrintUsage;
82+
}
83+
84+
netmask = -1u << (32 - in.cidr);
85+
network_address = in.addr & netmask;
86+
first_host_address = network_address + 1;
87+
last_host_address = (network_address | ~netmask) - 1;
88+
89+
assert(last_host_address > first_host_address);
90+
assert(last_host_address - first_host_address < 1024);
91+
92+
fprintf(stderr, "scanning %s through %s\n", FormatIp(first_host_address),
93+
FormatIp(last_host_address));
94+
95+
timeout = timeval_frommillis(100);
96+
for (int64_t ip = first_host_address; ip <= last_host_address; ++ip) {
97+
if (!fork()) {
98+
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
99+
setsockopt(3, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
100+
setsockopt(3, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
101+
if (!connect(3,
102+
(struct sockaddr *)&(struct sockaddr_in){
103+
.sin_family = AF_INET,
104+
.sin_addr.s_addr = htonl(ip),
105+
.sin_port = htons(port),
106+
},
107+
sizeof(struct sockaddr_in))) {
108+
status = "open";
109+
} else if (errno == ECONNREFUSED) {
110+
status = "closed";
111+
} else if (errno != EINPROGRESS) {
112+
status = _strerrno(errno);
113+
} else {
114+
status = 0;
115+
}
116+
if (status) {
117+
printf("%-15s %s\n", FormatIp(ip), status);
118+
}
119+
_Exit(0);
120+
}
121+
}
122+
for (;;) {
123+
if (wait(0) == -1 && errno == ECHILD) {
124+
break;
125+
}
126+
}
127+
}

libc/calls/calls.mk

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,10 @@ o/$(MODE)/libc/calls/timespec_tomicros.o \
184184
o/$(MODE)/libc/calls/timespec_totimeval.o \
185185
o/$(MODE)/libc/calls/timespec_fromnanos.o \
186186
o/$(MODE)/libc/calls/timespec_frommillis.o \
187-
o/$(MODE)/libc/calls/timespec_frommicros.o: private \
187+
o/$(MODE)/libc/calls/timespec_frommicros.o \
188+
o/$(MODE)/libc/calls/timeval_tomillis.o \
189+
o/$(MODE)/libc/calls/timeval_frommillis.o \
190+
o/$(MODE)/libc/calls/timeval_frommicros.o: private \
188191
OVERRIDE_CFLAGS += \
189192
-O2
190193

libc/calls/sigaction.c

Lines changed: 101 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,6 @@
2222
#include "libc/calls/internal.h"
2323
#include "libc/calls/sig.internal.h"
2424
#include "libc/calls/state.internal.h"
25-
#include "libc/calls/struct/sigaction-freebsd.internal.h"
26-
#include "libc/calls/struct/sigaction-linux.internal.h"
27-
#include "libc/calls/struct/sigaction-netbsd.h"
28-
#include "libc/calls/struct/sigaction-openbsd.internal.h"
29-
#include "libc/calls/struct/sigaction-xnu.internal.h"
3025
#include "libc/calls/struct/sigaction.h"
3126
#include "libc/calls/struct/sigaction.internal.h"
3227
#include "libc/calls/struct/siginfo.internal.h"
@@ -46,6 +41,7 @@
4641
#include "libc/mem/mem.h"
4742
#include "libc/runtime/runtime.h"
4843
#include "libc/str/str.h"
44+
#include "libc/sysv/consts/limits.h"
4945
#include "libc/sysv/consts/sa.h"
5046
#include "libc/sysv/consts/sig.h"
5147
#include "libc/sysv/errfuns.h"
@@ -58,110 +54,111 @@ STATIC_YOINK("strsignal"); // for kprintf()
5854

5955
#define SA_RESTORER 0x04000000
6056

61-
#ifndef SWITCHEROO
62-
#define SWITCHEROO(S1, S2, A, B, C, D) \
63-
do { \
64-
autotype((S2).A) a = (typeof((S2).A))(S1).A; \
65-
autotype((S2).B) b = (typeof((S2).B))(S1).B; \
66-
autotype((S2).C) c = (typeof((S2).C))(S1).C; \
67-
typeof((S2).D) d; \
68-
bzero(&d, sizeof(d)); \
69-
memcpy(&d, &((S1).D), MIN(sizeof(d), sizeof((S1).D))); \
70-
(S2).A = a; \
71-
(S2).B = b; \
72-
(S2).C = c; \
73-
bzero(&((S2).D), sizeof((S2).D)); \
74-
memcpy(&((S2).D), &d, MIN(sizeof(d), sizeof((S2).D))); \
75-
} while (0);
76-
#endif
77-
78-
union metasigaction {
79-
struct sigaction cosmo;
80-
struct sigaction_linux linux;
81-
struct sigaction_freebsd freebsd;
82-
struct sigaction_openbsd openbsd;
83-
struct sigaction_netbsd netbsd;
84-
struct sigaction_xnu_in xnu_in;
85-
struct sigaction_xnu_out xnu_out;
86-
};
87-
88-
void __sigenter_xnu(int, struct siginfo *, void *) hidden;
89-
void __sigenter_linux(int, struct siginfo *, void *) hidden;
90-
void __sigenter_netbsd(int, struct siginfo *, void *) hidden;
91-
void __sigenter_freebsd(int, struct siginfo *, void *) hidden;
92-
void __sigenter_openbsd(int, struct siginfo *, void *) hidden;
93-
9457
static void sigaction_cosmo2native(union metasigaction *sa) {
58+
void *handler;
59+
uint64_t flags;
60+
void *restorer;
61+
uint32_t mask[4];
9562
if (!sa) return;
96-
switch (__hostos) {
97-
case _HOSTLINUX:
98-
SWITCHEROO(sa->cosmo, sa->linux, sa_handler, sa_flags, sa_restorer,
99-
sa_mask);
100-
break;
101-
case _HOSTXNU:
102-
SWITCHEROO(sa->cosmo, sa->xnu_in, sa_handler, sa_flags, sa_restorer,
103-
sa_mask);
104-
break;
105-
case _HOSTFREEBSD:
106-
SWITCHEROO(sa->cosmo, sa->freebsd, sa_handler, sa_flags, sa_flags,
107-
sa_mask);
108-
break;
109-
case _HOSTOPENBSD:
110-
SWITCHEROO(sa->cosmo, sa->openbsd, sa_handler, sa_flags, sa_flags,
111-
sa_mask);
112-
break;
113-
case _HOSTNETBSD:
114-
SWITCHEROO(sa->cosmo, sa->netbsd, sa_handler, sa_flags, sa_flags,
115-
sa_mask);
116-
break;
117-
default:
118-
break;
63+
flags = sa->cosmo.sa_flags;
64+
handler = sa->cosmo.sa_handler;
65+
restorer = sa->cosmo.sa_restorer;
66+
mask[0] = sa->cosmo.sa_mask.__bits[0];
67+
mask[1] = sa->cosmo.sa_mask.__bits[0] >> 32;
68+
mask[2] = sa->cosmo.sa_mask.__bits[1];
69+
mask[3] = sa->cosmo.sa_mask.__bits[1] >> 32;
70+
if (IsLinux()) {
71+
sa->linux.sa_flags = flags;
72+
sa->linux.sa_handler = handler;
73+
sa->linux.sa_restorer = restorer;
74+
sa->linux.sa_mask[0] = mask[0];
75+
sa->linux.sa_mask[1] = mask[1];
76+
} else if (IsXnu()) {
77+
sa->xnu_in.sa_flags = flags;
78+
sa->xnu_in.sa_handler = handler;
79+
sa->xnu_in.sa_restorer = restorer;
80+
sa->xnu_in.sa_mask[0] = mask[0];
81+
} else if (IsFreebsd()) {
82+
sa->freebsd.sa_flags = flags;
83+
sa->freebsd.sa_handler = handler;
84+
sa->freebsd.sa_mask[0] = mask[0];
85+
sa->freebsd.sa_mask[1] = mask[1];
86+
sa->freebsd.sa_mask[2] = mask[2];
87+
sa->freebsd.sa_mask[3] = mask[3];
88+
} else if (IsOpenbsd()) {
89+
sa->openbsd.sa_flags = flags;
90+
sa->openbsd.sa_handler = handler;
91+
sa->openbsd.sa_mask[0] = mask[0];
92+
} else if (IsNetbsd()) {
93+
sa->netbsd.sa_flags = flags;
94+
sa->netbsd.sa_handler = handler;
95+
sa->netbsd.sa_mask[0] = mask[0];
96+
sa->netbsd.sa_mask[1] = mask[1];
97+
sa->netbsd.sa_mask[2] = mask[2];
98+
sa->netbsd.sa_mask[3] = mask[3];
11999
}
120100
}
121101

122102
static void sigaction_native2cosmo(union metasigaction *sa) {
103+
void *handler;
104+
uint64_t flags;
105+
void *restorer = 0;
106+
uint32_t mask[4] = {0};
123107
if (!sa) return;
124-
switch (__hostos) {
125-
case _HOSTLINUX:
126-
SWITCHEROO(sa->linux, sa->cosmo, sa_handler, sa_flags, sa_restorer,
127-
sa_mask);
128-
break;
129-
case _HOSTXNU:
130-
SWITCHEROO(sa->xnu_out, sa->cosmo, sa_handler, sa_flags, sa_flags,
131-
sa_mask);
132-
break;
133-
case _HOSTFREEBSD:
134-
SWITCHEROO(sa->freebsd, sa->cosmo, sa_handler, sa_flags, sa_flags,
135-
sa_mask);
136-
break;
137-
case _HOSTOPENBSD:
138-
SWITCHEROO(sa->openbsd, sa->cosmo, sa_handler, sa_flags, sa_flags,
139-
sa_mask);
140-
break;
141-
case _HOSTNETBSD:
142-
SWITCHEROO(sa->netbsd, sa->cosmo, sa_handler, sa_flags, sa_flags,
143-
sa_mask);
144-
break;
145-
default:
146-
break;
108+
if (IsLinux()) {
109+
flags = sa->linux.sa_flags;
110+
handler = sa->linux.sa_handler;
111+
restorer = sa->linux.sa_restorer;
112+
mask[0] = sa->linux.sa_mask[0];
113+
mask[1] = sa->linux.sa_mask[1];
114+
} else if (IsXnu()) {
115+
flags = sa->xnu_out.sa_flags;
116+
handler = sa->xnu_out.sa_handler;
117+
mask[0] = sa->xnu_out.sa_mask[0];
118+
} else if (IsFreebsd()) {
119+
flags = sa->freebsd.sa_flags;
120+
handler = sa->freebsd.sa_handler;
121+
mask[0] = sa->freebsd.sa_mask[0];
122+
mask[1] = sa->freebsd.sa_mask[1];
123+
mask[2] = sa->freebsd.sa_mask[2];
124+
mask[3] = sa->freebsd.sa_mask[3];
125+
} else if (IsOpenbsd()) {
126+
flags = sa->openbsd.sa_flags;
127+
handler = sa->openbsd.sa_handler;
128+
mask[0] = sa->openbsd.sa_mask[0];
129+
} else if (IsNetbsd()) {
130+
flags = sa->netbsd.sa_flags;
131+
handler = sa->netbsd.sa_handler;
132+
mask[0] = sa->netbsd.sa_mask[0];
133+
mask[1] = sa->netbsd.sa_mask[1];
134+
mask[2] = sa->netbsd.sa_mask[2];
135+
mask[3] = sa->netbsd.sa_mask[3];
136+
} else {
137+
return;
147138
}
139+
sa->cosmo.sa_flags = flags;
140+
sa->cosmo.sa_handler = handler;
141+
sa->cosmo.sa_restorer = restorer;
142+
sa->cosmo.sa_mask.__bits[0] = mask[0] | (uint64_t)mask[1] << 32;
143+
sa->cosmo.sa_mask.__bits[1] = mask[2] | (uint64_t)mask[3] << 32;
148144
}
149145

150146
static int __sigaction(int sig, const struct sigaction *act,
151147
struct sigaction *oldact) {
152-
_Static_assert((sizeof(struct sigaction) > sizeof(struct sigaction_linux) &&
153-
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_in) &&
154-
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_out) &&
155-
sizeof(struct sigaction) > sizeof(struct sigaction_freebsd) &&
156-
sizeof(struct sigaction) > sizeof(struct sigaction_openbsd) &&
157-
sizeof(struct sigaction) > sizeof(struct sigaction_netbsd)),
158-
"sigaction cosmo abi needs tuning");
148+
_Static_assert(
149+
(sizeof(struct sigaction) >= sizeof(struct sigaction_linux) &&
150+
sizeof(struct sigaction) >= sizeof(struct sigaction_xnu_in) &&
151+
sizeof(struct sigaction) >= sizeof(struct sigaction_xnu_out) &&
152+
sizeof(struct sigaction) >= sizeof(struct sigaction_freebsd) &&
153+
sizeof(struct sigaction) >= sizeof(struct sigaction_openbsd) &&
154+
sizeof(struct sigaction) >= sizeof(struct sigaction_netbsd)),
155+
"sigaction cosmo abi needs tuning");
159156
int64_t arg4, arg5;
160157
int rc, rva, oldrva;
161158
sigaction_f sigenter;
162159
struct sigaction *ap, copy;
163160
if (IsMetal()) return enosys(); /* TODO: Signals on Metal */
164-
if (!(0 < sig && sig < NSIG)) return einval();
161+
if (!(1 <= sig && sig <= _NSIG)) return einval();
165162
if (sig == SIGKILL || sig == SIGSTOP) return einval();
166163
if (IsAsan() && ((act && !__asan_is_valid(act, sizeof(*act))) ||
167164
(oldact && !__asan_is_valid(oldact, sizeof(*oldact))))) {
@@ -184,18 +181,23 @@ static int __sigaction(int sig, const struct sigaction *act,
184181
if (act) {
185182
memcpy(&copy, act, sizeof(copy));
186183
ap = &copy;
187-
if (IsXnu()) {
184+
185+
if (IsLinux()) {
186+
if (!(ap->sa_flags & SA_RESTORER)) {
187+
ap->sa_flags |= SA_RESTORER;
188+
ap->sa_restorer = &__restore_rt;
189+
}
190+
if (IsWsl1()) {
191+
sigenter = __sigenter_wsl;
192+
} else {
193+
sigenter = ap->sa_sigaction;
194+
}
195+
} else if (IsXnu()) {
188196
ap->sa_restorer = (void *)&__sigenter_xnu;
189197
sigenter = __sigenter_xnu;
190198
// mitigate Rosetta signal handling strangeness
191199
// https://github.com/jart/cosmopolitan/issues/455
192200
ap->sa_flags |= SA_SIGINFO;
193-
} else if (IsLinux()) {
194-
if (!(ap->sa_flags & SA_RESTORER)) {
195-
ap->sa_flags |= SA_RESTORER;
196-
ap->sa_restorer = &__restore_rt;
197-
}
198-
sigenter = __sigenter_linux;
199201
} else if (IsNetbsd()) {
200202
sigenter = __sigenter_netbsd;
201203
} else if (IsFreebsd()) {

0 commit comments

Comments
 (0)