Merge tag 'urbit-v1.12'

urbit-v1.12

Arvo 417K
Vere 1.12

This is a hotfix release, fixing another memory corruption vulnerability
introduced in v1.10 and improving snapshot durability.

Release Notes

- restores the guard page (preventing road stack overflow) after |meld
- improves snapshot error handling and messaging
- fixes an overflow bug affecting jammed scry output (-X)

Contributions:

Joe Bryan (16):
      u3: protect guard page in u3e_yolo()
      vere: bumps version
      u3: assert guard page invariants when saving snapshot
      u3: initialize guard page in u3m_boot_lite()
      vere: bumps version
      nix: update linux-aarch64 overlay to exclude macos m1
      u3: handle partial reads in snapshot system
      u3: handle partial writes in snapshot system
      u3: print mprotect errors in snapshot system
      u3: print error msg if system page size is incompatible
      u3: detect snapshots from a larger loom, print and exit
      u3: normalize home-road stack after snapshot restoration
      u3: handle and print lseek errors in snapshot system
      u3: print errors while deleting snapshot patch
      vere: bumps version
      vere: bumps version

Liam Fitzgerald (1):
      pier: fix jamming archive
This commit is contained in:
Joe Bryan 2022-11-15 14:43:12 -05:00
commit 12196d1113
5 changed files with 161 additions and 37 deletions

View File

@ -3,8 +3,9 @@ final: prev:
let let
isAarch64 = prev.stdenv.hostPlatform.isAarch64; isAarch64 = prev.stdenv.hostPlatform.isAarch64;
isDarwin = prev.stdenv.isDarwin;
in prev.lib.optionalAttrs isAarch64 { in prev.lib.optionalAttrs (isAarch64 && !isDarwin) {
libsigsegv = prev.libsigsegv.overrideAttrs (attrs: { libsigsegv = prev.libsigsegv.overrideAttrs (attrs: {
preConfigure = (prev.preConfigure or "") + '' preConfigure = (prev.preConfigure or "") + ''
sed -i 's/^CFG_FAULT=$/CFG_FAULT=fault-linux-arm.h/' configure sed -i 's/^CFG_FAULT=$/CFG_FAULT=fault-linux-arm.h/' configure

View File

@ -226,8 +226,9 @@ _ce_center_guard_page(void)
if ( -1 == mprotect(u3a_into(gar_pag_p), pag_siz_i, PROT_NONE) ) { if ( -1 == mprotect(u3a_into(gar_pag_p), pag_siz_i, PROT_NONE) ) {
fprintf(stderr, fprintf(stderr,
"loom: failed to protect the guard page " "loom: failed to protect the guard page "
"(base address %p)\r\n", "(base address %p): %s\r\n",
u3a_into(gar_pag_p)); u3a_into(gar_pag_p),
strerror(errno));
goto fail; goto fail;
} }
@ -353,10 +354,17 @@ _ce_image_open(u3e_image* img_u)
static void static void
_ce_patch_write_control(u3_ce_patch* pat_u) _ce_patch_write_control(u3_ce_patch* pat_u)
{ {
c3_w len_w = sizeof(u3e_control) + ssize_t ret_i;
(pat_u->con_u->pgs_w * sizeof(u3e_line)); c3_w len_w = sizeof(u3e_control) +
(pat_u->con_u->pgs_w * sizeof(u3e_line));
if ( len_w != write(pat_u->ctl_i, pat_u->con_u, len_w) ) { if ( len_w != (ret_i = write(pat_u->ctl_i, pat_u->con_u, len_w)) ) {
if ( 0 < ret_i ) {
fprintf(stderr, "loom: patch ctl partial write: %zu\r\n", (size_t)ret_i);
}
else {
fprintf(stderr, "loom: patch ctl write: %s\r\n", strerror(errno));
}
c3_assert(0); c3_assert(0);
} }
} }
@ -424,11 +432,17 @@ _ce_patch_delete(void)
{ {
c3_c ful_c[8193]; c3_c ful_c[8193];
snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c); snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c);
c3_unlink(ful_c); if ( unlink(ful_c) ) {
fprintf(stderr, "loom: failed to delete control.bin: %s\r\n",
strerror(errno));
}
snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c); snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c);
c3_unlink(ful_c); if ( unlink(ful_c) ) {
fprintf(stderr, "loom: failed to remove memory.bin: %s\r\n",
strerror(errno));
}
} }
/* _ce_patch_verify(): check patch data mug. /* _ce_patch_verify(): check patch data mug.
@ -436,7 +450,8 @@ _ce_patch_delete(void)
static c3_o static c3_o
_ce_patch_verify(u3_ce_patch* pat_u) _ce_patch_verify(u3_ce_patch* pat_u)
{ {
c3_w i_w; ssize_t ret_i;
c3_w i_w;
if ( u3e_version != pat_u->con_u->ver_y ) { if ( u3e_version != pat_u->con_u->ver_y ) {
fprintf(stderr, "loom: patch version mismatch: have %u, need %u\r\n", fprintf(stderr, "loom: patch version mismatch: have %u, need %u\r\n",
@ -454,8 +469,13 @@ _ce_patch_verify(u3_ce_patch* pat_u)
fprintf(stderr, "loom: patch seek: %s\r\n", strerror(errno)); fprintf(stderr, "loom: patch seek: %s\r\n", strerror(errno));
return c3n; return c3n;
} }
if ( -1 == read(pat_u->mem_i, mem_w, pag_siz_i) ) { if ( pag_siz_i != (ret_i = read(pat_u->mem_i, mem_w, pag_siz_i)) ) {
fprintf(stderr, "loom: patch read: %s\r\n", strerror(errno)); if ( 0 < ret_i ) {
fprintf(stderr, "loom: patch partial read: %zu\r\n", (size_t)ret_i);
}
else {
fprintf(stderr, "loom: patch read fail: %s\r\n", strerror(errno));
}
return c3n; return c3n;
} }
{ {
@ -542,8 +562,23 @@ _ce_patch_write_page(u3_ce_patch* pat_u,
c3_w pgc_w, c3_w pgc_w,
c3_w* mem_w) c3_w* mem_w)
{ {
c3_assert(-1 != lseek(pat_u->mem_i, pgc_w * pag_siz_i, SEEK_SET)); ssize_t ret_i;
c3_assert(pag_siz_i == write(pat_u->mem_i, mem_w, pag_siz_i));
if ( -1 == lseek(pat_u->mem_i, pgc_w * pag_siz_i, SEEK_SET) ) {
fprintf(stderr, "loom: patch page seek: %s\r\n", strerror(errno));
c3_assert(0);
}
if ( pag_siz_i != (ret_i = write(pat_u->mem_i, mem_w, pag_siz_i)) ) {
if ( 0 < ret_i ) {
fprintf(stderr, "loom: patch page partial write: %zu\r\n",
(size_t)ret_i);
}
else {
fprintf(stderr, "loom: patch page write: %s\r\n", strerror(errno));
}
c3_assert(0);
}
} }
/* _ce_patch_count_page(): count a page, producing new counter. /* _ce_patch_count_page(): count a page, producing new counter.
@ -586,6 +621,7 @@ _ce_patch_save_page(u3_ce_patch* pat_u,
pag_siz_i, pag_siz_i,
PROT_READ) ) PROT_READ) )
{ {
fprintf(stderr, "loom: patch mprotect: %s\r\n", strerror(errno));
c3_assert(0); c3_assert(0);
} }
@ -613,6 +649,9 @@ _ce_patch_compose(void)
nor_w = (nwr_w + (pag_wiz_i - 1)) >> u3a_page; nor_w = (nwr_w + (pag_wiz_i - 1)) >> u3a_page;
sou_w = (swu_w + (pag_wiz_i - 1)) >> u3a_page; sou_w = (swu_w + (pag_wiz_i - 1)) >> u3a_page;
c3_assert( ((gar_pag_p >> u3a_page) >= nor_w)
&& ((gar_pag_p >> u3a_page) <= (u3a_pages - (sou_w + 1))) );
} }
#ifdef U3_SNAPSHOT_VALIDATION #ifdef U3_SNAPSHOT_VALIDATION
@ -714,7 +753,8 @@ _ce_image_resize(u3e_image* img_u, c3_w pgs_w)
static void static void
_ce_patch_apply(u3_ce_patch* pat_u) _ce_patch_apply(u3_ce_patch* pat_u)
{ {
c3_w i_w; ssize_t ret_i;
c3_w i_w;
// resize images // resize images
// //
@ -748,8 +788,14 @@ _ce_patch_apply(u3_ce_patch* pat_u)
off_w = (u3a_pages - (pag_w + 1)); off_w = (u3a_pages - (pag_w + 1));
} }
if ( -1 == read(pat_u->mem_i, mem_w, pag_siz_i) ) { if ( pag_siz_i != (ret_i = read(pat_u->mem_i, mem_w, pag_siz_i)) ) {
fprintf(stderr, "loom: patch apply read: %s\r\n", strerror(errno)); if ( 0 < ret_i ) {
fprintf(stderr, "loom: patch apply partial read: %zu\r\n",
(size_t)ret_i);
}
else {
fprintf(stderr, "loom: patch apply read: %s\r\n", strerror(errno));
}
c3_assert(0); c3_assert(0);
} }
else { else {
@ -757,8 +803,14 @@ _ce_patch_apply(u3_ce_patch* pat_u)
fprintf(stderr, "loom: patch apply seek: %s\r\n", strerror(errno)); fprintf(stderr, "loom: patch apply seek: %s\r\n", strerror(errno));
c3_assert(0); c3_assert(0);
} }
if ( -1 == write(fid_i, mem_w, pag_siz_i) ) { if ( pag_siz_i != (ret_i = write(fid_i, mem_w, pag_siz_i)) ) {
fprintf(stderr, "loom: patch apply write: %s\r\n", strerror(errno)); if ( 0 < ret_i ) {
fprintf(stderr, "loom: patch apply partial write: %zu\r\n",
(size_t)ret_i);
}
else {
fprintf(stderr, "loom: patch apply write: %s\r\n", strerror(errno));
}
c3_assert(0); c3_assert(0);
} }
} }
@ -779,13 +831,24 @@ _ce_image_blit(u3e_image* img_u,
return; return;
} }
c3_w i_w; ssize_t ret_i;
c3_w siz_w = pag_siz_i; c3_w i_w;
c3_w siz_w = pag_siz_i;
if ( -1 == lseek(img_u->fid_i, 0, SEEK_SET) ) {
fprintf(stderr, "loom: image blit seek 0: %s\r\n", strerror(errno));
c3_assert(0);
}
lseek(img_u->fid_i, 0, SEEK_SET);
for ( i_w = 0; i_w < img_u->pgs_w; i_w++ ) { for ( i_w = 0; i_w < img_u->pgs_w; i_w++ ) {
if ( -1 == read(img_u->fid_i, ptr_w, siz_w) ) { if ( siz_w != (ret_i = read(img_u->fid_i, ptr_w, siz_w)) ) {
fprintf(stderr, "loom: image blit read: %s\r\n", strerror(errno)); if ( 0 < ret_i ) {
fprintf(stderr, "loom: image blit partial read: %zu\r\n",
(size_t)ret_i);
}
else {
fprintf(stderr, "loom: image blit read: %s\r\n", strerror(errno));
}
c3_assert(0); c3_assert(0);
} }
@ -811,15 +874,25 @@ _ce_image_fine(u3e_image* img_u,
c3_w* ptr_w, c3_w* ptr_w,
c3_ws stp_ws) c3_ws stp_ws)
{ {
c3_w i_w; ssize_t ret_i;
c3_w buf_w[pag_wiz_i]; c3_w i_w;
c3_w buf_w[pag_wiz_i];
if ( -1 == lseek(img_u->fid_i, 0, SEEK_SET) ) {
fprintf(stderr, "loom: image fine seek 0: %s\r\n", strerror(errno));
c3_assert(0);
}
lseek(img_u->fid_i, 0, SEEK_SET);
for ( i_w=0; i_w < img_u->pgs_w; i_w++ ) { for ( i_w=0; i_w < img_u->pgs_w; i_w++ ) {
c3_w mem_w, fil_w; c3_w mem_w, fil_w;
if ( -1 == read(img_u->fid_i, buf_w, pag_siz_i) ) { if ( pag_siz_i != (ret_i = read(img_u->fid_i, buf_w, pag_siz_i)) ) {
fprintf(stderr, "loom: image fine read: %s\r\n", strerror(errno)); if ( 0 < ret_i ) {
fprintf(stderr, "loom: image fine partial read: %zu\r\n", (size_t)ret_i);
}
else {
fprintf(stderr, "loom: image fine read: %s\r\n", strerror(errno));
}
c3_assert(0); c3_assert(0);
} }
mem_w = u3r_mug_words(ptr_w, pag_wiz_i); mem_w = u3r_mug_words(ptr_w, pag_wiz_i);
@ -845,7 +918,8 @@ _ce_image_fine(u3e_image* img_u,
static c3_o static c3_o
_ce_image_copy(u3e_image* fom_u, u3e_image* tou_u) _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u)
{ {
c3_w i_w; ssize_t ret_i;
c3_w i_w;
// resize images // resize images
// //
@ -866,8 +940,14 @@ _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u)
c3_w mem_w[pag_wiz_i]; c3_w mem_w[pag_wiz_i];
c3_w off_w = i_w; c3_w off_w = i_w;
if ( -1 == read(fom_u->fid_i, mem_w, pag_siz_i) ) { if ( pag_siz_i != (ret_i = read(fom_u->fid_i, mem_w, pag_siz_i)) ) {
fprintf(stderr, "loom: image copy read: %s\r\n", strerror(errno)); if ( 0 < ret_i ) {
fprintf(stderr, "loom: image copy partial read: %zu\r\n",
(size_t)ret_i);
}
else {
fprintf(stderr, "loom: image copy read: %s\r\n", strerror(errno));
}
return c3n; return c3n;
} }
else { else {
@ -875,8 +955,14 @@ _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u)
fprintf(stderr, "loom: image copy seek: %s\r\n", strerror(errno)); fprintf(stderr, "loom: image copy seek: %s\r\n", strerror(errno));
return c3n; return c3n;
} }
if ( -1 == write(tou_u->fid_i, mem_w, pag_siz_i) ) { if ( pag_siz_i != (ret_i = write(tou_u->fid_i, mem_w, pag_siz_i)) ) {
fprintf(stderr, "loom: image copy write: %s\r\n", strerror(errno)); if ( 0 < ret_i ) {
fprintf(stderr, "loom: image copy partial write: %zu\r\n",
(size_t)ret_i);
}
else {
fprintf(stderr, "loom: image copy write: %s\r\n", strerror(errno));
}
return c3n; return c3n;
} }
} }
@ -1006,7 +1092,15 @@ u3e_live(c3_o nuu_o, c3_c* dir_c)
{ {
// require that our page size is a multiple of the system page size. // require that our page size is a multiple of the system page size.
// //
c3_assert(0 == (1 << (2 + u3a_page)) % sysconf(_SC_PAGESIZE)); {
size_t sys_i = sysconf(_SC_PAGESIZE);
if ( pag_siz_i % sys_i ) {
fprintf(stderr, "loom: incompatible system page size (%zuKB)\r\n",
sys_i >> 10);
exit(1);
}
}
u3P.dir_c = dir_c; u3P.dir_c = dir_c;
u3P.nor_u.nam_c = "north"; u3P.nor_u.nam_c = "north";
@ -1041,6 +1135,13 @@ u3e_live(c3_o nuu_o, c3_c* dir_c)
_ce_patch_delete(); _ce_patch_delete();
} }
// detect snapshots from a larger loom
//
if ( (u3P.nor_u.pgs_w + u3P.sou_u.pgs_w + 1) >= u3a_pages ) {
fprintf(stderr, "boot: snapshot too big for loom\r\n");
exit(1);
}
// mark all pages dirty (pages in the snapshot will be marked clean) // mark all pages dirty (pages in the snapshot will be marked clean)
// //
u3e_foul(); u3e_foul();
@ -1083,9 +1184,18 @@ u3e_yolo(void)
// NB: u3e_save() will reinstate protection flags // NB: u3e_save() will reinstate protection flags
// //
if ( 0 != mprotect((void *)u3_Loom, u3a_bytes, (PROT_READ | PROT_WRITE)) ) { if ( 0 != mprotect((void *)u3_Loom, u3a_bytes, (PROT_READ | PROT_WRITE)) ) {
// XX confirm recoverable errors
//
fprintf(stderr, "loom: yolo: %s\r\n", strerror(errno));
return c3n; return c3n;
} }
if ( 0 != mprotect(u3a_into(gar_pag_p), pag_siz_i, PROT_NONE) ) {
fprintf(stderr, "loom: failed to protect guard page: %s\r\n",
strerror(errno));
c3_assert(0);
}
return c3y; return c3y;
} }

View File

@ -590,6 +590,11 @@ _find_home(void)
u3H = (void *)((mem_w + len_w) - siz_w); u3H = (void *)((mem_w + len_w) - siz_w);
u3R = &u3H->rod_u; u3R = &u3H->rod_u;
// this looks risky, but there are no legitimate scenarios
// where it's wrong
//
u3R->cap_p = u3R->mat_p = u3a_words - c3_wiseof(*u3H);
} }
/* u3m_pave(): instantiate or activate image. /* u3m_pave(): instantiate or activate image.
@ -1858,6 +1863,10 @@ u3m_boot_lite(void)
*/ */
u3m_pave(c3y); u3m_pave(c3y);
/* Place the guard page.
*/
u3e_init();
/* Initialize the jet system. /* Initialize the jet system.
*/ */
u3j_boot(c3y); u3j_boot(c3y);

View File

@ -492,8 +492,12 @@ _pier_on_scry_done(void* ptr_v, u3_noun nun)
{ {
u3_atom puf = u3i_string(u3_Host.ops_u.puf_c); u3_atom puf = u3i_string(u3_Host.ops_u.puf_c);
if ( c3y == u3r_sing(c3__jam, puf) ) { if ( c3y == u3r_sing(c3__jam, puf) ) {
out = u3qe_jam(res); c3_d len_d;
c3_y* byt_y;
u3s_jam_xeno(res, &len_d, &byt_y);
out = u3i_bytes(len_d, byt_y);
ext_c = "jam"; ext_c = "jam";
free(byt_y);
} }
else if ( c3y == u3a_is_atom(res) ) { else if ( c3y == u3a_is_atom(res) ) {
out = u3dc("scot", u3k(puf), u3k(res)); out = u3dc("scot", u3k(puf), u3k(res));

View File

@ -1 +1 @@
1.11 1.12