mirror of
https://github.com/jamesstringer90/appsandbox.git
synced 2026-10-19 01:31:28 -05:00
Fix Ubuntu Firefox permissions and APT sources
This commit is contained in:
1 parent
6d2e10fd0b
commit
16f8a72cc0
5 files changed
+212
-2
No files matched your search
@@ -30,7 +30,7 @@
|
||||
#define EXT4_FIRST_INO 11u /* s_first_ino: first non-reserved */
|
||||
|
||||
/* Feature flags - kept very small. */
|
||||
#define EXT4_FEATURE_COMPAT 0
|
||||
#define EXT4_FEATURE_COMPAT 0x08u
|
||||
#define EXT4_FEATURE_INCOMPAT (0x02u | 0x40u) /* FILETYPE | EXTENTS */
|
||||
#define EXT4_FEATURE_RO_COMPAT (0x01u | 0x02u | 0x08u | 0x20u | 0x40u)
|
||||
/* SPARSE_SUPER | LARGE_FILE | HUGE_FILE
|
||||
@@ -224,6 +224,15 @@ typedef struct {
|
||||
} ext4_inode_t;
|
||||
/* sizeof = 0xa0 = 160. Inode-size 256 leaves 96 trailing bytes (xattrs). */
|
||||
|
||||
typedef struct {
|
||||
uint8_t e_name_len;
|
||||
uint8_t e_name_index;
|
||||
uint16_t e_value_offs;
|
||||
uint32_t e_value_inum;
|
||||
uint32_t e_value_size;
|
||||
uint32_t e_hash;
|
||||
} ext4_xattr_entry_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t eh_magic;
|
||||
uint16_t eh_entries;
|
||||
@@ -291,6 +300,8 @@ typedef struct {
|
||||
/* For dirs only - serialized entry blob (filled at close). */
|
||||
uint8_t *dir_blob;
|
||||
uint32_t dir_blob_len;
|
||||
void *capability;
|
||||
uint32_t capability_size;
|
||||
} inode_rec_t;
|
||||
|
||||
struct ext4_writer {
|
||||
@@ -1022,6 +1033,29 @@ int ext4_writer_add_file(ext4_writer_t *w, const char *path,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ext4_writer_set_capability(ext4_writer_t *w, const char *path,
|
||||
const void *data, size_t size)
|
||||
{
|
||||
if (!data || (size != 12 && size != 20 && size != 24)) return -1;
|
||||
dir_node_t *parent;
|
||||
char leaf[256];
|
||||
if (split_path(w, path, &parent, leaf, sizeof(leaf)) != 0) return -1;
|
||||
for (dir_entry_rec_t *e = parent->entries; e; e = e->next) {
|
||||
if (strcmp(e->name, leaf) != 0) continue;
|
||||
if (e->file_type != EXT4_FT_REG_FILE) return -1;
|
||||
inode_rec_t *r = w->inodes[e->inode];
|
||||
void *copy = malloc(size);
|
||||
if (!copy) return -1;
|
||||
memcpy(copy, data, size);
|
||||
free(r->capability);
|
||||
r->capability = copy;
|
||||
r->capability_size = (uint32_t)size;
|
||||
r->body.i_extra_isize = (uint16_t)(sizeof(ext4_inode_t) - 128);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ext4_writer_add_symlink(ext4_writer_t *w, const char *path,
|
||||
const char *target, size_t target_len,
|
||||
uint32_t uid, uint32_t gid, uint32_t mtime)
|
||||
@@ -1232,6 +1266,22 @@ static int write_all_inodes(ext4_writer_t *w)
|
||||
memcpy(tbl + idx * INODE_SIZE,
|
||||
&w->inodes[inode_num]->body,
|
||||
sizeof(ext4_inode_t));
|
||||
inode_rec_t *r = w->inodes[inode_num];
|
||||
if (r->capability_size) {
|
||||
uint8_t *inode = tbl + idx * INODE_SIZE;
|
||||
uint32_t magic = 0xEA020000u;
|
||||
memcpy(inode + sizeof(ext4_inode_t), &magic, sizeof(magic));
|
||||
ext4_xattr_entry_t *entry = (ext4_xattr_entry_t *)(
|
||||
inode + sizeof(ext4_inode_t) + sizeof(magic));
|
||||
entry->e_name_len = 10;
|
||||
entry->e_name_index = 6;
|
||||
entry->e_value_offs = (uint16_t)(INODE_SIZE - r->capability_size -
|
||||
sizeof(ext4_inode_t) - sizeof(magic));
|
||||
entry->e_value_size = r->capability_size;
|
||||
memcpy(entry + 1, "capability", entry->e_name_len);
|
||||
memcpy(inode + INODE_SIZE - r->capability_size,
|
||||
r->capability, r->capability_size);
|
||||
}
|
||||
any = 1;
|
||||
}
|
||||
if (!any) continue;
|
||||
@@ -1474,6 +1524,7 @@ int ext4_writer_close(ext4_writer_t *w)
|
||||
for (uint32_t i = 1; i <= w->total_inodes; i++) {
|
||||
if (w->inodes[i]) {
|
||||
free(w->inodes[i]->dir_blob);
|
||||
free(w->inodes[i]->capability);
|
||||
free(w->inodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Feature subset (deliberately small):
|
||||
* INCOMPAT : FILETYPE | EXTENTS
|
||||
* RO_COMPAT : SPARSE_SUPER | LARGE_FILE | HUGE_FILE | DIR_NLINK | EXTRA_ISIZE
|
||||
* No journal, no metadata_csum, no xattrs, no flex_bg, no 64bit, no HTREE.
|
||||
*
|
||||
* Layout:
|
||||
* block_size = 4096
|
||||
@@ -47,6 +46,8 @@ int ext4_writer_add_dir(ext4_writer_t *w, const char *path,
|
||||
int ext4_writer_add_file(ext4_writer_t *w, const char *path,
|
||||
uint16_t perms, uint32_t uid, uint32_t gid,
|
||||
uint32_t mtime, const void *data, uint64_t size);
|
||||
int ext4_writer_set_capability(ext4_writer_t *w, const char *path,
|
||||
const void *data, size_t size);
|
||||
int ext4_writer_add_symlink(ext4_writer_t *w, const char *path,
|
||||
const char *target, size_t target_len,
|
||||
uint32_t uid, uint32_t gid, uint32_t mtime);
|
||||
|
||||
@@ -453,6 +453,143 @@ int sqfs_read_metadata_block(sqfs_ctx_t *ctx, uint64_t *off,
|
||||
return -1;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint64_t next_block;
|
||||
uint64_t end;
|
||||
size_t pos;
|
||||
size_t len;
|
||||
uint8_t data[SQFS_METADATA_SIZE];
|
||||
} sqfs_xattr_cursor_t;
|
||||
|
||||
static int xattr_next_block(sqfs_ctx_t *ctx, sqfs_xattr_cursor_t *c)
|
||||
{
|
||||
uint16_t hdr;
|
||||
if (c->next_block >= c->end || c->end - c->next_block < 2 ||
|
||||
sqfs_read_raw(ctx, c->next_block, &hdr, sizeof(hdr)) != 0 ||
|
||||
(hdr & 0x7fff) > c->end - c->next_block - 2)
|
||||
return -1;
|
||||
if (sqfs_read_metadata_block(ctx, &c->next_block, c->data, &c->len) != 0 ||
|
||||
c->len == 0 || (c->next_block != c->end && c->len != SQFS_METADATA_SIZE))
|
||||
return -1;
|
||||
c->pos = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xattr_cursor_start(sqfs_ctx_t *ctx, sqfs_xattr_cursor_t *c,
|
||||
uint64_t start, uint64_t end, size_t offset)
|
||||
{
|
||||
if (end > ctx->sb.bytes_used || start >= end || offset >= SQFS_METADATA_SIZE)
|
||||
return -1;
|
||||
c->next_block = start;
|
||||
c->end = end;
|
||||
if (xattr_next_block(ctx, c) != 0 || offset >= c->len) return -1;
|
||||
c->pos = offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xattr_read(sqfs_ctx_t *ctx, sqfs_xattr_cursor_t *c,
|
||||
void *out, size_t size)
|
||||
{
|
||||
uint8_t *p = (uint8_t *)out;
|
||||
while (size) {
|
||||
if (c->pos == c->len && xattr_next_block(ctx, c) != 0) return -1;
|
||||
size_t n = c->len - c->pos;
|
||||
if (n > size) n = size;
|
||||
if (p) { memcpy(p, c->data + c->pos, n); p += n; }
|
||||
c->pos += n;
|
||||
size -= n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sqfs_read_capability(sqfs_ctx_t *ctx, const sqfs_entry_t *entry,
|
||||
void **out_data, size_t *out_size)
|
||||
{
|
||||
*out_data = NULL;
|
||||
*out_size = 0;
|
||||
if (entry->type != SQFS_EREG_TYPE || entry->_xattr_idx == UINT32_MAX)
|
||||
return 0;
|
||||
|
||||
struct {
|
||||
uint64_t start;
|
||||
uint32_t count;
|
||||
uint32_t unused;
|
||||
} table;
|
||||
struct {
|
||||
uint64_t ref;
|
||||
uint32_t count;
|
||||
uint32_t size;
|
||||
} id;
|
||||
uint64_t table_off = ctx->sb.xattr_id_table_start;
|
||||
if (table_off > ctx->sb.bytes_used ||
|
||||
sizeof(table) > ctx->sb.bytes_used - table_off ||
|
||||
sqfs_read_raw(ctx, table_off, &table, sizeof(table)) != 0 ||
|
||||
entry->_xattr_idx >= table.count)
|
||||
return -1;
|
||||
|
||||
uint64_t index_bytes = (((uint64_t)table.count * sizeof(id) +
|
||||
SQFS_METADATA_SIZE - 1) / SQFS_METADATA_SIZE) * 8;
|
||||
table_off += sizeof(table);
|
||||
if (index_bytes != ctx->sb.bytes_used - table_off) return -1;
|
||||
uint64_t xattr_end, id_block;
|
||||
uint64_t id_offset = (uint64_t)entry->_xattr_idx * sizeof(id);
|
||||
if (sqfs_read_raw(ctx, table_off, &xattr_end, sizeof(xattr_end)) != 0 ||
|
||||
sqfs_read_raw(ctx, table_off + (id_offset / SQFS_METADATA_SIZE) * 8,
|
||||
&id_block, sizeof(id_block)) != 0 ||
|
||||
table.start < sizeof(sqfs_superblock_t) || table.start >= xattr_end ||
|
||||
xattr_end > id_block || id_block >= ctx->sb.xattr_id_table_start)
|
||||
return -1;
|
||||
|
||||
sqfs_xattr_cursor_t c;
|
||||
if (xattr_cursor_start(ctx, &c, id_block, ctx->sb.xattr_id_table_start,
|
||||
(size_t)(id_offset % SQFS_METADATA_SIZE)) != 0 ||
|
||||
xattr_read(ctx, &c, &id, sizeof(id)) != 0 ||
|
||||
id.count == 0 ||
|
||||
(id.ref >> 16) >= xattr_end - table.start ||
|
||||
xattr_cursor_start(ctx, &c, table.start + (id.ref >> 16), xattr_end,
|
||||
(size_t)(id.ref & 0xffff)) != 0)
|
||||
return -1;
|
||||
|
||||
for (uint32_t i = 0; i < id.count; i++) {
|
||||
uint16_t attr[2];
|
||||
char name[sizeof("capability") - 1];
|
||||
uint32_t value_size;
|
||||
if (xattr_read(ctx, &c, attr, sizeof(attr)) != 0 ||
|
||||
attr[1] == 0 || (attr[0] & ~0x1ffu) != 0)
|
||||
return -1;
|
||||
int match = (attr[0] & 0xff) == 2 && attr[1] == sizeof(name);
|
||||
if (xattr_read(ctx, &c, match ? name : NULL, attr[1]) != 0 ||
|
||||
xattr_read(ctx, &c, &value_size, sizeof(value_size)) != 0 ||
|
||||
((attr[0] & 0x100) && value_size != sizeof(uint64_t)))
|
||||
return -1;
|
||||
if (!match || memcmp(name, "capability", sizeof(name)) != 0) {
|
||||
if (xattr_read(ctx, &c, NULL, value_size) != 0) return -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (attr[0] & 0x100) {
|
||||
uint64_t ref;
|
||||
if (xattr_read(ctx, &c, &ref, sizeof(ref)) != 0 ||
|
||||
(ref >> 16) >= xattr_end - table.start ||
|
||||
xattr_cursor_start(ctx, &c, table.start + (ref >> 16), xattr_end,
|
||||
(size_t)(ref & 0xffff)) != 0 ||
|
||||
xattr_read(ctx, &c, &value_size, sizeof(value_size)) != 0)
|
||||
return -1;
|
||||
}
|
||||
if (value_size != 12 && value_size != 20 && value_size != 24) return -1;
|
||||
void *value = malloc(value_size);
|
||||
if (!value) return -1;
|
||||
if (xattr_read(ctx, &c, value, value_size) != 0) {
|
||||
free(value);
|
||||
return -1;
|
||||
}
|
||||
*out_data = value;
|
||||
*out_size = value_size;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---- Inode + directory parsing ----
|
||||
*
|
||||
* All structs are stored little-endian. We use memcpy into local typed
|
||||
@@ -688,6 +825,7 @@ static int walk_inode(walk_state_t *w, uint64_t inode_ref)
|
||||
e.gid = id_lookup(ctx, hdr.gid_idx);
|
||||
e.mtime = hdr.mtime;
|
||||
e._file_inode_off = (size_t)(p - ctx->inode_stream.buf);
|
||||
e._xattr_idx = UINT32_MAX;
|
||||
|
||||
switch (hdr.type) {
|
||||
case SQFS_DIR_TYPE: {
|
||||
@@ -730,6 +868,7 @@ static int walk_inode(walk_state_t *w, uint64_t inode_ref)
|
||||
sqfs_ext_file_t f;
|
||||
memcpy(&f, body, sizeof(f));
|
||||
e.size = f.file_size;
|
||||
e._xattr_idx = f.xattr_idx;
|
||||
if (w->cb_rc == 0) w->cb_rc = w->cb(&e, w->user);
|
||||
w->n_files++;
|
||||
return w->cb_rc;
|
||||
|
||||
@@ -118,6 +118,7 @@ typedef struct {
|
||||
/* For regular files, set by the walker, used by the callback to fetch
|
||||
* the bytes (deferred so the callback can stream / skip as needed). */
|
||||
uint64_t _file_inode_off; /* internal: offset of file's inode in table */
|
||||
uint32_t _xattr_idx;
|
||||
} sqfs_entry_t;
|
||||
|
||||
/* Callback signature. Return 0 to continue, non-zero to abort traversal. */
|
||||
@@ -135,4 +136,7 @@ int sqfs_walk(sqfs_ctx_t *ctx, sqfs_walk_cb_t cb, void *user);
|
||||
int sqfs_read_file(sqfs_ctx_t *ctx, const sqfs_entry_t *entry,
|
||||
void **out_data, size_t *out_size);
|
||||
|
||||
int sqfs_read_capability(sqfs_ctx_t *ctx, const sqfs_entry_t *entry,
|
||||
void **out_data, size_t *out_size);
|
||||
|
||||
#endif
|
||||
@@ -544,6 +544,8 @@ typedef struct slot {
|
||||
uint32_t uid, gid, mtime, rdev;
|
||||
uint64_t size;
|
||||
void *data;
|
||||
void *capability;
|
||||
size_t capability_size;
|
||||
char *symlink_target;
|
||||
uint32_t symlink_target_size;
|
||||
uint64_t mem_bytes;
|
||||
@@ -707,6 +709,14 @@ static DWORD WINAPI decompress_worker(LPVOID arg)
|
||||
}
|
||||
s->size = sz;
|
||||
s->mem_bytes += sz;
|
||||
if (sqfs_read_capability(p->sq, &e, &s->capability, &s->capability_size) != 0) {
|
||||
log_err(L"sqfs_read_capability failed");
|
||||
free(s->data); free(s->path); free(s);
|
||||
InterlockedIncrement((volatile LONG *)&p->n_errors);
|
||||
free(w);
|
||||
continue;
|
||||
}
|
||||
s->mem_bytes += s->capability_size;
|
||||
pipeline_push(p, s);
|
||||
free(w);
|
||||
}
|
||||
@@ -783,6 +793,9 @@ static DWORD WINAPI consumer_thread(LPVOID arg)
|
||||
case SQFS_REG_TYPE: case SQFS_EREG_TYPE:
|
||||
rc = ext4_writer_add_file(p->ew, s->path, s->mode, s->uid, s->gid, s->mtime,
|
||||
s->data, s->size);
|
||||
if (rc == 0 && s->capability_size)
|
||||
rc = ext4_writer_set_capability(p->ew, s->path,
|
||||
s->capability, s->capability_size);
|
||||
if (rc == 0) { p->n_files++; p->bytes_total += s->size; }
|
||||
/* Mirror unicode.pf2 into /boot/grub/fonts/ (loadfont's default
|
||||
* search path). */
|
||||
@@ -832,6 +845,7 @@ static DWORD WINAPI consumer_thread(LPVOID arg)
|
||||
|
||||
free(s->path);
|
||||
free(s->data);
|
||||
free(s->capability);
|
||||
free(s->symlink_target);
|
||||
free(s);
|
||||
}
|
||||
@@ -1281,6 +1295,7 @@ static void plant_firstboot_service(ext4_writer_t *ew)
|
||||
"# in one shot — saves repeated apt overhead and avoids the\n"
|
||||
"# install-build-deps-after-trying-to-build ordering bug.\n"
|
||||
"echo \"==== STEP 7.4: apt sources + install all build tools ====\"\n"
|
||||
"rm -f /etc/apt/sources.list.d/cdrom.sources\n"
|
||||
"APT_SOURCES_DIR=/etc/apt/appsandbox-sources.list.d\n"
|
||||
"install -d \"$APT_SOURCES_DIR\"\n"
|
||||
"if [ -d /opt/appsandbox/local-apt/dists ]; then\n"
|
||||
|
||||
Reference in new issue
Block a user