commit b553458289d3ba0983b1bba51f07c588100ad8e6
parent 79c3f601382979ac79163a0b0c78a7b12be32f7f
Author: erai <erai@omiltem.net>
Date: Tue, 4 Jun 2024 23:26:56 -0400
signal handlers
Diffstat:
M | as.c | | | 5 | +++++ |
M | cc1.c | | | 6 | ++++++ |
M | sshd.c | | | 78 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ |
M | syscall.c | | | 34 | ++++++++++++++++++++++++++++++++-- |
4 files changed, 109 insertions(+), 14 deletions(-)
diff --git a/as.c b/as.c
@@ -307,6 +307,11 @@ fixup_label(c: *assembler, l: *label) {
}
}
+emit_restorer(c: *assembler) {
+ as_modri(c, OP_MOVI, R_RAX, 15);
+ as_op(c, OP_SYSCALL);
+}
+
emit_ptr(c: *assembler, l: *label) {
reserve(c, 16);
as_modrm(c, OP_LEA, R_RAX, R_RIP, 0, 0, 128);
diff --git a/cc1.c b/cc1.c
@@ -1613,6 +1613,12 @@ main(argc: int, argv: **byte, envp: **byte) {
emit_ret(c.as);
}
+ d = find(c, "_restorer", 0:*byte, 1);
+ if (d.func_defined && !d.func_label.fixed) {
+ fixup_label(c.as, d.func_label);
+ emit_restorer(c.as);
+ }
+
d = find(c, "_include", 0:*byte, 1);
if (d.func_defined && !d.func_label.fixed) {
fixup_label(c.as, d.func_label);
diff --git a/sshd.c b/sshd.c
@@ -1,27 +1,33 @@
read_line(fd: int, buf: *byte, max: int): int {
var len: int;
- var c: int;
+ var ret: int;
+ var c: byte;
len = 0;
loop {
if len == max {
return 0;
}
- c = fdgetc(fd);
- if c == '\n' {
- buf[len] = 0:byte;
- return len;
+ ret = read(fd, &c, 1);
+
+ if ret == -EINTR {
+ continue;
}
- if c == -1 {
+ if ret == 0 {
return 0;
}
- if c == '\r' {
+ if c == '\n':byte {
+ buf[len] = 0:byte;
+ return len;
+ }
+
+ if c == '\r':byte {
continue;
}
- buf[len] = c:byte;
+ buf[len] = c;
len = len + 1;
}
}
@@ -34,6 +40,9 @@ writeall(fd: int, buf: *byte, n: int): int {
}
ret = write(fd, buf, n);
+ if ret == -EINTR {
+ continue;
+ }
if ret < 0 {
return ret;
}
@@ -51,6 +60,10 @@ read_fill(fd: int, buf: *byte, n: int): int {
}
ret = read(fd, buf, n);
+ if ret == -EINTR {
+ continue;
+ }
+
if ret <= 0 {
return -1;
}
@@ -1265,7 +1278,7 @@ doauth(ctx: *sshd_ctx) {
// <- SSH_MSG_USERAUTH_REQUEST
read_frame(ctx);
decode_userauth_request(&cua, ctx);
- if !ssh_streq(&cua.service, "ssh-connection") || !ssh_streq(&cua.user, "erai") {
+ if !ssh_streq(&cua.service, "ssh-connection") || !ssh_streq(&cua.user, ctx.username) {
die("bad auth");
}
@@ -1312,7 +1325,7 @@ doauth(ctx: *sshd_ctx) {
encode_str(&s, ctx);
b = SSH_MSG_USERAUTH_REQUEST;
encode_u8(&b, ctx);
- set_str(&s, "erai");
+ set_str(&s, ctx.username);
encode_str(&s, ctx);
set_str(&s, "ssh-connection");
encode_str(&s, ctx);
@@ -1520,6 +1533,20 @@ dorequest(ctx: *sshd_ctx) {
}
}
+struct pfd4 {
+ p0: int;
+ p1: int;
+ p2: int;
+ p3: int;
+}
+
+reset_pfd(pfd: *int, ctx: *sshd_ctx) {
+ pfd[0] = ctx.fd | (POLLIN << 32);
+ pfd[1] = ctx.child_stdin | (POLLOUT << 32);
+ pfd[2] = ctx.child_stdout | (POLLIN << 32);
+ pfd[3] = ctx.child_stderr | (POLLIN << 32);
+}
+
client_loop(ctx: *sshd_ctx) {
var tag: int;
@@ -1575,6 +1602,7 @@ struct sshd_ctx {
userpub: _ed25519_pub;
hostkey: *byte;
hostkeylen: int;
+ username: *byte;
userkey: *byte;
userkeylen: int;
buf: *byte;
@@ -1625,6 +1653,25 @@ format_key(d: **byte, dlen: *int, k: *byte, ctx: *sshd_ctx) {
clear_frame(ctx);
}
+dosigchld() {
+ loop {
+ if wait(-1, 0:*int, WNOHANG) < 0 {
+ break;
+ }
+ }
+}
+
+_restorer();
+
+signal(sig: int, handler: func()) {
+ var act: sigaction;
+ act.handler = (&dosigchld):int;
+ act.flags = 1 << 26;
+ act.restorer = _restorer:int;
+ act.mask = 0;
+ sigaction(sig, &act, 0:*sigaction);
+}
+
main(argc: int, argv: **byte, envp: **byte) {
var fd: int;
var cfd: int;
@@ -1634,6 +1681,8 @@ main(argc: int, argv: **byte, envp: **byte) {
var a: alloc;
setup_alloc(&a);
+ signal(SIGCHLD, dosigchld);
+
bzero((&ctx):*byte, sizeof(ctx));
if unhex((&ctx.userpub):*byte, "5afb3032d86d60d700e1782bfe8083ff95504cecbda531bef5ba8cdd20f34c82") != 32 {
@@ -1649,6 +1698,7 @@ main(argc: int, argv: **byte, envp: **byte) {
ctx.ckex = alloc(ctx.a, 4096);
ctx.sver = "SSH-2.0-omiltem";
+ ctx.username = "erai";
format_key(&ctx.hostkey, &ctx.hostkeylen, (&ctx.pub):*byte, &ctx);
format_key(&ctx.userkey, &ctx.userkeylen, (&ctx.userpub):*byte, &ctx);
@@ -1657,7 +1707,7 @@ main(argc: int, argv: **byte, envp: **byte) {
die("failed to open socket");
}
- port = 2020;
+ port = 2222;
sa.fpa = AF_INET | ((port & 0xff) << 24) | (((port >> 8) & 0xff) << 16);
sa.pad = 0;
if bind(fd, (&sa):*byte, sizeof(sa)) != 0 {
@@ -1670,10 +1720,14 @@ main(argc: int, argv: **byte, envp: **byte) {
loop {
ctx.fd = accept(fd, 0:*byte, 0:*int);
- if ctx.fd < 0 {
+ if ctx.fd == -EINTR {
continue;
}
+ if ctx.fd < 0 {
+ exit(1);
+ }
+
if fork() == 0 {
close(fd);
cmain(&ctx);
diff --git a/syscall.c b/syscall.c
@@ -7,11 +7,23 @@ enum {
O_CREAT = 64,
O_DIRECTORY = 0x1000,
+ EINTR = 4,
+
AF_INET = 2,
SOCK_STREAM = 1,
POLLIN = 1,
POLLOUT = 4,
+
+ WNOHANG = 1,
+
+ SIG_DFL = 0,
+ SIG_IGN = 1,
+
+ SIGINT = 2,
+ SIGALRM = 14,
+ SIGCHLD = 17,
+ SIGWINCH = 28,
}
_start(argc: int, argv: **byte, envp: **byte) {
@@ -39,7 +51,7 @@ fstat(fd: int, buf: *byte): int {
return syscall(5, fd, buf:int, 0, 0, 0, 0);
}
-poll(pfd: *byte, nfd: int, timeout: int): int {
+poll(pfd: *int, nfd: int, timeout: int): int {
return syscall(7, pfd:int, nfd, timeout, 0, 0, 0);
}
@@ -47,6 +59,17 @@ mmap(addr: int, len: int, prot: int, flags: int, fd: int, off: int): int {
return syscall(9, addr, len, prot, flags, fd, off);
}
+struct sigaction {
+ handler: int;
+ flags: int;
+ restorer: int;
+ mask: int;
+}
+
+sigaction(sig: int, act: *sigaction, oact: *sigaction): int {
+ return syscall(13, sig, act:int, oact:int, 8, 0, 0);
+}
+
pipe(rfd: *int, wfd: *int): int {
var buf: int;
var ret: int;
@@ -91,7 +114,14 @@ exit(n: int) {
}
wait(pid: int, status: *int, flags: int): int {
- return syscall(61, pid, status:int, flags, 0, 0, 0);
+ var s: int;
+ var ret: int;
+ s = 0;
+ ret = syscall(61, pid, s:int, flags, 0, 0, 0);
+ if status {
+ *status = s & (-1 >> 32);
+ }
+ return ret;
}
rename(oldname: *byte, newname: *byte): int {