aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHidehiko Abe <hidehiko@google.com>2018-05-09 08:15:58 -0700
committerandroid-build-merger <android-build-merger@google.com>2018-05-09 08:15:58 -0700
commite9bbd4152dc1e8b43ddaeedf219a778d4f4354ec (patch)
tree77a026569353649679276371ec1b112084e011c5
parent4c64a6a0262b74704a8a3bff3868b41801e9f3b0 (diff)
parentf240b14514c6b5d4493ce608741ff83fcbc38ce4 (diff)
downloadsquashfs-tools-e9bbd4152dc1e8b43ddaeedf219a778d4f4354ec.tar.gz
Cherry-pick UID/GID mapping support.
am: f240b14514 Change-Id: Ib1795ddb96a8f623c03d6f2bcb62e2a049e9ab10
-rw-r--r--squashfs-tools/mksquashfs.c152
-rw-r--r--squashfs-tools/mksquashfs.h4
-rw-r--r--squashfs-tools/read_fs.c8
3 files changed, 152 insertions, 12 deletions
diff --git a/squashfs-tools/mksquashfs.c b/squashfs-tools/mksquashfs.c
index 5ac11ad..6fe9555 100644
--- a/squashfs-tools/mksquashfs.c
+++ b/squashfs-tools/mksquashfs.c
@@ -274,6 +274,18 @@ char *destination_file = NULL;
char *recovery_file = NULL;
int recover = TRUE;
+/* uid/gid mapping tables */
+#define UGID_ENTRIES 340
+
+struct ugid_map_entry {
+ unsigned int child_id;
+ unsigned int parent_id;
+ unsigned int length;
+};
+struct ugid_map_entry uid_mapping[UGID_ENTRIES], gid_mapping[UGID_ENTRIES];
+unsigned int uid_map_count = 0, gid_map_count = 0;
+
+
struct id *id_hash_table[ID_ENTRIES];
struct id *id_table[SQUASHFS_IDS], *sid_table[SQUASHFS_IDS];
unsigned int uid_count = 0, guid_count = 0;
@@ -739,9 +751,33 @@ struct id *create_id(unsigned int id)
}
-unsigned int get_uid(unsigned int uid)
+int resolve_child_ugid(unsigned int *ugid,
+ const struct ugid_map_entry *ugid_mapping,
+ unsigned int ugid_map_count)
+{
+ unsigned int i;
+
+ for (i = 0; i < ugid_map_count; i++) {
+ if (ugid_mapping[i].parent_id <= *ugid &&
+ *ugid <
+ ugid_mapping[i].parent_id + ugid_mapping[i].length) {
+ *ugid = ugid_mapping[i].child_id + *ugid -
+ ugid_mapping[i].parent_id;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+unsigned int get_uid(unsigned int uid, int resolve)
{
- struct id *entry = get_id(uid);
+ struct id *entry;
+
+ if (resolve && !resolve_child_ugid(&uid, uid_mapping, uid_map_count))
+ BAD_ERROR("uid not found in mapping: %d\n", uid);
+ entry = get_id(uid);
if(entry == NULL) {
if(id_count == SQUASHFS_IDS)
@@ -758,9 +794,13 @@ unsigned int get_uid(unsigned int uid)
}
-unsigned int get_guid(unsigned int guid)
+unsigned int get_guid(unsigned int guid, int resolve)
{
- struct id *entry = get_id(guid);
+ struct id *entry;
+
+ if (resolve && !resolve_child_ugid(&guid, gid_mapping, gid_map_count))
+ BAD_ERROR("gid not found in mapping: %d\n", guid);
+ entry = get_id(guid);
if(entry == NULL) {
if(id_count == SQUASHFS_IDS)
@@ -972,10 +1012,10 @@ int create_inode(squashfs_inode *i_no, struct dir_info *dir_info,
base->mode = SQUASHFS_MODE(buf->st_mode);
base->uid = get_uid((unsigned int) global_uid == -1 ?
- buf->st_uid : global_uid);
+ buf->st_uid : global_uid, 1);
base->inode_type = type;
base->guid = get_guid((unsigned int) global_gid == -1 ?
- buf->st_gid : global_gid);
+ buf->st_gid : global_gid, 1);
base->mtime = buf->st_mtime;
base->inode_number = get_inode_no(dir_ent->inode);
@@ -5300,6 +5340,63 @@ int parse_num(char *arg, int *res)
}
+int parse_ugid_map(char *map_str,
+ struct ugid_map_entry ugid_mapping[UGID_ENTRIES],
+ unsigned int *ugid_map_count)
+{
+ char *line_state, *token_state;
+ char *line, *line_str, *token, *token_str;
+ long long numbers[3];
+ int i;
+
+ for (*ugid_map_count = 0, line_str = map_str;;
+ ++*ugid_map_count, line_str = NULL) {
+ line = strtok_r(line_str, "\n", &line_state);
+ if (line == NULL)
+ break;
+ ERROR("line: %s\n", line);
+ if (*ugid_map_count >= UGID_ENTRIES) {
+ ERROR("Too many entries for u/gid mapping\n");
+ return -1;
+ }
+
+ for (i = 0, token_str = line; i < 3; i++, token_str = NULL) {
+ token = strtok_r(token_str, " ", &token_state);
+ ERROR("token: %d, %s\n", i, token);
+ if (token == NULL ||
+ !parse_numberll(token, &numbers[i], 0) ||
+ numbers[i] < 0 || numbers[i] > ULONG_MAX) {
+ ERROR("Malformed u/gid mapping line1\n");
+ return -1;
+ }
+ }
+
+ if (numbers[0] + numbers[2] > ULONG_MAX) {
+ ERROR("u/gid mapping overflow\n");
+ return -1;
+ }
+
+ if (numbers[1] + numbers[2] > ULONG_MAX) {
+ ERROR("u/gid mapping overflow\n");
+ return -1;
+ }
+
+ if (strtok_r(NULL, " ", &token_state) != NULL) {
+ ERROR("Malformed u/gid mapping line2\n");
+ return -1;
+ }
+
+ ugid_mapping[*ugid_map_count].child_id =
+ (unsigned int)numbers[0];
+ ugid_mapping[*ugid_map_count].parent_id =
+ (unsigned int)numbers[1];
+ ugid_mapping[*ugid_map_count].length = (unsigned int)numbers[2];
+ }
+
+ return 0;
+}
+
+
int get_physical_memory()
{
int phys_mem;
@@ -5989,6 +6086,30 @@ print_compressor_options:
exit(1);
}
root_name = argv[i];
+ } else if (strcmp(argv[i], "-uid-map") == 0) {
+ if (++i == argc) {
+ ERROR("%s: -uid-map: missing mapping\n",
+ argv[0]);
+ exit(1);
+ }
+ if (parse_ugid_map(argv[i], uid_mapping,
+ &uid_map_count) != 0) {
+ ERROR("%s: -uid-map: invalid mapping\n",
+ argv[0]);
+ exit(1);
+ }
+ } else if (strcmp(argv[i], "-gid-map") == 0) {
+ if (++i == argc) {
+ ERROR("%s: -gid-map: missing mapping\n",
+ argv[0]);
+ exit(1);
+ }
+ if (parse_ugid_map(argv[i], gid_mapping,
+ &gid_map_count) != 0) {
+ ERROR("%s: -gid-map: invalid mapping\n",
+ argv[0]);
+ exit(1);
+ }
} else if(strcmp(argv[i], "-version") == 0) {
VERSION();
} else {
@@ -6077,6 +6198,12 @@ printOptions:
"dirs/files\n");
ERROR("-regex\t\t\tAllow POSIX regular expressions to "
"be used in exclude\n\t\t\tdirs/files\n");
+ ERROR("-uid-map <mapping>\tUser ID mapping.\n");
+ ERROR("\t\t\tFollows the format described in "
+ "user_namespaces(7).\n");
+ ERROR("-gid-map <mapping>\tGroup ID mapping.\n");
+ ERROR("\t\t\tFollows the format described in "
+ "user_namespaces(7).\n");
ERROR("\nFilesystem append options:\n");
ERROR("-noappend\t\tdo not append to existing "
"filesystem\n");
@@ -6129,6 +6256,19 @@ printOptions:
}
}
+ if (!uid_map_count) {
+ uid_mapping[0].child_id = 0;
+ uid_mapping[0].parent_id = 0;
+ uid_mapping[0].length = 4294967295u;
+ uid_map_count = 1;
+ }
+ if (!gid_map_count) {
+ gid_mapping[0].child_id = 0;
+ gid_mapping[0].parent_id = 0;
+ gid_mapping[0].length = 4294967295u;
+ gid_map_count = 1;
+ }
+
/* ANDROID CHANGES START*/
#ifdef ANDROID
if (fs_config_file) {
diff --git a/squashfs-tools/mksquashfs.h b/squashfs-tools/mksquashfs.h
index bfbf0bf..d5cc205 100644
--- a/squashfs-tools/mksquashfs.h
+++ b/squashfs-tools/mksquashfs.h
@@ -158,8 +158,8 @@ extern int read_fs_bytes(int, long long, int, void *);
extern void add_file(long long, long long, long long, unsigned int *, int,
unsigned int, int, int);
extern struct id *create_id(unsigned int);
-extern unsigned int get_uid(unsigned int);
-extern unsigned int get_guid(unsigned int);
+extern unsigned int get_uid(unsigned int, int);
+extern unsigned int get_guid(unsigned int, int);
extern int read_bytes(int, void *, int);
extern unsigned short get_checksum_mem(char *, int);
#endif
diff --git a/squashfs-tools/read_fs.c b/squashfs-tools/read_fs.c
index ca84460..3ea9262 100644
--- a/squashfs-tools/read_fs.c
+++ b/squashfs-tools/read_fs.c
@@ -214,8 +214,8 @@ int scan_inode_table(int fd, long long start, long long end,
/* bad type, corrupted filesystem */
goto corrupted;
- get_uid(id_table[dir_inode->base.uid]);
- get_guid(id_table[dir_inode->base.guid]);
+ get_uid(id_table[dir_inode->base.uid], 0);
+ get_guid(id_table[dir_inode->base.guid], 0);
/* allocate fragment to file mapping table */
file_mapping = calloc(sBlk->fragments, sizeof(struct append_file *));
@@ -234,8 +234,8 @@ int scan_inode_table(int fd, long long start, long long end,
(unsigned int) (cur_ptr - *inode_table),
base.inode_type);
- get_uid(id_table[base.uid]);
- get_guid(id_table[base.guid]);
+ get_uid(id_table[base.uid], 0);
+ get_guid(id_table[base.guid], 0);
switch(base.inode_type) {
case SQUASHFS_FILE_TYPE: {