harden ipc and frontend recovery

This commit is contained in:
2026-08-11 19:34:47 +09:00
parent 4bfb659b6d
commit 9dc116a035
14 changed files with 495 additions and 245 deletions

View File

@@ -2,8 +2,8 @@ CFLAGS = -Wall -O2 -I.. `pkg-config --cflags gtk+-3.0`
LDFLAGS = `pkg-config --libs gtk+-3.0`
DSTDIR ?= $(shell find /usr/lib* -type d -path "*/gtk-3.0/*/immodules" 2>/dev/null | head -1)
im-strans.so: main.c
$(CC) -shared -fPIC $(CFLAGS) -o $@ $< $(LDFLAGS)
im-strans.so: main.c ../ipc.c ../ipc.h
$(CC) -shared -fPIC $(CFLAGS) -o $@ main.c ../ipc.c $(LDFLAGS)
docker: main.c Dockerfile
docker build -t strans-gtk .

View File

@@ -12,7 +12,7 @@ struct Im
{
GtkIMContext parent;
int fd;
char pre[256];
char pre[Ipcfieldmax+1];
int prelen;
};
@@ -36,52 +36,61 @@ srvconnect(Im *im)
return;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path, sizeof(addr.sun_path), "/tmp/strans.%d", getuid());
snprintf(addr.sun_path, sizeof(addr.sun_path), IPCPATH, getuid());
if(connect(im->fd, (struct sockaddr*)&addr, sizeof(addr)) < 0){
close(im->fd);
im->fd = -1;
}
}
static void
srvclose(Im *im)
{
int was;
if(im->fd >= 0)
close(im->fd);
im->fd = -1;
was = im->prelen;
im->pre[0] = '\0';
im->prelen = 0;
if(was > 0){
g_signal_emit_by_name(im, "preedit-changed");
g_signal_emit_by_name(im, "preedit-end");
}
}
static int
readresp(Im *im, char *buf, int bufsz)
{
unsigned char hdr[2], pl;
int n, was;
Ipcresp resp;
int was;
if(read(im->fd, hdr, 2) != 2)
return -1;
n = hdr[1];
buf[0] = '\0';
if(n > 0 && n < bufsz){
if(read(im->fd, buf, n) != n)
return -1;
buf[n] = '\0';
}
if(read(im->fd, &pl, 1) != 1)
return -1;
if(pl >= sizeof(im->pre))
return -1;
was = im->prelen;
if(pl > 0 && read(im->fd, im->pre, pl) != pl)
if(ipcreadresp(im->fd, 1, buf, bufsz, im->pre,
sizeof(im->pre), &resp) < 0)
return -1;
im->pre[pl] = '\0';
im->prelen = pl;
if(was == 0 && pl > 0)
im->prelen = resp.npreedit;
if(was == 0 && im->prelen > 0)
g_signal_emit_by_name(im, "preedit-start");
if(was != 0 || pl != 0)
if(was != 0 || im->prelen != 0)
g_signal_emit_by_name(im, "preedit-changed");
if(was > 0 && pl == 0)
if(was > 0 && im->prelen == 0)
g_signal_emit_by_name(im, "preedit-end");
return hdr[0];
return resp.eaten;
}
static uint32_t
kget(uint32_t gdk)
{
if(gdk >= 0xff00)
uint32_t u;
u = gdk_keyval_to_unicode(gdk);
if((gdk & 0xff000000) == 0x01000000 && u != 0)
return u;
if(gdk >= 0xff00 && gdk <= 0xffff)
return Kspec + (gdk - 0xff00);
return gdk_keyval_to_unicode(gdk);
return u;
}
static uint32_t
@@ -104,17 +113,17 @@ mget(uint32_t state)
static void
sendreset(Im *im)
{
unsigned char buf[4];
char resp[64];
unsigned char buf[Ipcreqsz];
char resp[Ipcfieldmax+1];
if(im->fd < 0)
if(im->fd < 0){
srvclose(im);
return;
buf[0] = 1;
buf[1] = 0;
buf[2] = Kesc & 0xff;
buf[3] = Kesc >> 8;
if(send(im->fd, buf, 4, MSG_NOSIGNAL) == 4)
readresp(im, resp, sizeof(resp));
}
ipcpackreq(buf, 1, 0, Kesc);
if(ipcsend(im->fd, buf, sizeof buf) < 0 ||
readresp(im, resp, sizeof(resp)) < 0)
srvclose(im);
}
static gboolean
@@ -137,8 +146,8 @@ static gboolean
kpress(GtkIMContext *ctx, GdkEventKey *ev)
{
Im *im;
unsigned char buf[4];
char resp[64];
unsigned char buf[Ipcreqsz];
char resp[Ipcfieldmax+1];
uint32_t key, mod;
int r;
GtkInputPurpose purpose;
@@ -154,21 +163,18 @@ kpress(GtkIMContext *ctx, GdkEventKey *ev)
if(purpose == GTK_INPUT_PURPOSE_PASSWORD || purpose == GTK_INPUT_PURPOSE_PIN)
return plaincommit(ctx, key, mod);
srvconnect(im);
if(im->fd < 0)
if(im->fd < 0){
srvclose(im);
return plaincommit(ctx, key, mod);
buf[0] = 1;
buf[1] = mod;
buf[2] = key & 0xff;
buf[3] = key >> 8;
if(send(im->fd, buf, 4, MSG_NOSIGNAL) != 4){
close(im->fd);
im->fd = -1;
}
ipcpackreq(buf, 1, mod, key);
if(ipcsend(im->fd, buf, sizeof buf) < 0){
srvclose(im);
return plaincommit(ctx, key, mod);
}
r = readresp(im, resp, sizeof(resp));
if(r < 0){
close(im->fd);
im->fd = -1;
srvclose(im);
return plaincommit(ctx, key, mod);
}
if(resp[0] != '\0')
@@ -228,6 +234,8 @@ static void
init(Im *im)
{
im->fd = -1;
im->pre[0] = '\0';
im->prelen = 0;
}
static void