mirror of
https://github.com/linux-msm/cdba.git
synced 2026-10-06 21:32:09 -07:00
cdba-server: Provide QDL access control list
The newly introduced support for QDL-based remote flashing of devices is powerful, but provides an easy way to alter shared boards in unwanted ways. Introduce an optional "qdl_access" entry to the device configuration, which allows to specify a list of entries each one defining a set of users and their accepted flash targets. A special target "all" can be used to give e.g. administrators unrestricted access to the flash. Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
This commit is contained in:
1 parent
4be6c26fbe
commit
48efa3096e
7 files changed
+189
No files matched your search
@@ -81,6 +81,33 @@ devices:
|
||||
fastboot_set_active: true
|
||||
fastboot_key_timeout: 2
|
||||
|
||||
- board: qdlboard
|
||||
users:
|
||||
- username
|
||||
console: /dev/ttyUSB1
|
||||
fastboot: abcdef04
|
||||
qdl_programmer: /path/to/prog_firehose_ddr.elf
|
||||
qdl_access:
|
||||
- user: username
|
||||
targets:
|
||||
- boot_a
|
||||
- boot_b
|
||||
- 0/efiesp
|
||||
- 0/123456
|
||||
- user: admin
|
||||
targets:
|
||||
- all
|
||||
|
||||
QDL access targets use QDL's target syntax: <partition-name>, <lun>,
|
||||
<lun>/<partition-name>, or <lun>/<start-sector>. The CDBA server checks the
|
||||
requested target string against the configured access list before invoking QDL,
|
||||
but does not resolve the target to a physical partition itself. For a bare
|
||||
<partition-name>, QDL searches across all LUNs and flashes the first matching
|
||||
partition. If multiple LUNs might contain the same partition name, or if the ACL
|
||||
must identify an exact location, use the explicit <lun>/<partition-name> or
|
||||
<lun>/<start-sector> form instead. The special target "all" allows any QDL
|
||||
target.
|
||||
|
||||
- board: testboard
|
||||
console: /dev/serial/by-id/usb-1234-if00-port0
|
||||
name: GPIO controller board
|
||||
|
||||
@@ -148,8 +148,24 @@ static void msg_edl_flash(const void *data, size_t len)
|
||||
{
|
||||
const char *target = data;
|
||||
|
||||
if (!selected_device || !current_edl_file)
|
||||
return;
|
||||
|
||||
if (!len || target[len - 1]) {
|
||||
fprintf(stderr, "invalid EDL flash target\n");
|
||||
watch_quit();
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "edl flash into '%s'\n", target);
|
||||
|
||||
if (!device_qdl_access_allowed(selected_device, username, target)) {
|
||||
fprintf(stderr, "user '%s' is not allowed to flash EDL target '%s' on %s\n",
|
||||
username, target, selected_device->board);
|
||||
watch_quit();
|
||||
return;
|
||||
}
|
||||
|
||||
current_edl_file->target = strdup(target);
|
||||
current_edl_file = NULL;
|
||||
}
|
||||
|
||||
@@ -11,3 +11,11 @@ devices:
|
||||
qdl_programmer: /path/to/prog_firehose_ddr.elf
|
||||
qdl_serial: 1234567890ABCDEF
|
||||
qdl_storage: ufs
|
||||
qdl_access:
|
||||
- user: alice
|
||||
targets:
|
||||
- all
|
||||
- user: bob
|
||||
targets:
|
||||
- userdata
|
||||
- 0/123456
|
||||
@@ -410,6 +410,33 @@ void device_info(const char *username, const void *data, size_t dlen)
|
||||
cdba_send_buf(MSG_BOARD_INFO, len, description);
|
||||
}
|
||||
|
||||
bool device_qdl_access_allowed(struct device *device,
|
||||
const char *username,
|
||||
const char *target)
|
||||
{
|
||||
struct device_qdl_user *user;
|
||||
struct device_qdl_target *qdl_target;
|
||||
|
||||
if (!device->qdl_access)
|
||||
return true;
|
||||
|
||||
if (!username || !target)
|
||||
return false;
|
||||
|
||||
list_for_each_entry(user, device->qdl_access, node) {
|
||||
if (strcmp(user->username, username))
|
||||
continue;
|
||||
|
||||
list_for_each_entry(qdl_target, &user->targets, node) {
|
||||
if (!strcmp(qdl_target->target, "all") ||
|
||||
!strcmp(qdl_target->target, target))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void device_close(struct device *dev)
|
||||
{
|
||||
if (!dev->usb_always_on)
|
||||
|
||||
@@ -67,6 +67,7 @@ struct device {
|
||||
char *qdl_programmer;
|
||||
char *qdl_serial;
|
||||
char *qdl_storage;
|
||||
struct list_head *qdl_access;
|
||||
|
||||
char *status_cmd;
|
||||
|
||||
@@ -79,6 +80,19 @@ struct device_user {
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
struct device_qdl_target {
|
||||
const char *target;
|
||||
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
struct device_qdl_user {
|
||||
const char *username;
|
||||
struct list_head targets;
|
||||
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
void device_add(struct device *device);
|
||||
|
||||
struct device *device_open(const char *board,
|
||||
@@ -104,6 +118,9 @@ void device_list_devices(const char *username);
|
||||
void device_info(const char *username, const void *data, size_t dlen);
|
||||
void device_fastboot_continue(struct device *device);
|
||||
bool device_is_running(struct device *device);
|
||||
bool device_qdl_access_allowed(struct device *device,
|
||||
const char *username,
|
||||
const char *target);
|
||||
|
||||
extern const struct control_ops alpaca_ops;
|
||||
extern const struct control_ops cdb_assist_ops;
|
||||
|
||||
@@ -128,6 +128,70 @@ static void parse_users(struct device_parser *dp, struct device *dev)
|
||||
device_parser_expect(dp, YAML_SEQUENCE_END_EVENT, NULL, 0);
|
||||
}
|
||||
|
||||
static void parse_qdl_targets(struct device_parser *dp, struct list_head *targets)
|
||||
{
|
||||
char value[TOKEN_LENGTH];
|
||||
|
||||
if (device_parser_accept(dp, YAML_SCALAR_EVENT, value, 0))
|
||||
return;
|
||||
|
||||
device_parser_expect(dp, YAML_SEQUENCE_START_EVENT, NULL, 0);
|
||||
|
||||
while (device_parser_accept(dp, YAML_SCALAR_EVENT, value, TOKEN_LENGTH)) {
|
||||
struct device_qdl_target *target = calloc(1, sizeof(*target));
|
||||
|
||||
target->target = strdup(value);
|
||||
list_append(targets, &target->node);
|
||||
}
|
||||
|
||||
device_parser_expect(dp, YAML_SEQUENCE_END_EVENT, NULL, 0);
|
||||
}
|
||||
|
||||
static void parse_qdl_access(struct device_parser *dp, struct device *dev)
|
||||
{
|
||||
char key[TOKEN_LENGTH];
|
||||
|
||||
dev->qdl_access = calloc(1, sizeof(*dev->qdl_access));
|
||||
list_init(dev->qdl_access);
|
||||
|
||||
if (device_parser_accept(dp, YAML_SCALAR_EVENT, key, 0))
|
||||
return;
|
||||
|
||||
device_parser_expect(dp, YAML_SEQUENCE_START_EVENT, NULL, 0);
|
||||
|
||||
while (device_parser_accept(dp, YAML_MAPPING_START_EVENT, NULL, 0)) {
|
||||
struct device_qdl_user *user = calloc(1, sizeof(*user));
|
||||
bool have_username = false;
|
||||
bool have_targets = false;
|
||||
|
||||
list_init(&user->targets);
|
||||
|
||||
while (device_parser_accept(dp, YAML_SCALAR_EVENT, key, TOKEN_LENGTH)) {
|
||||
if (!strcmp(key, "user")) {
|
||||
device_parser_expect(dp, YAML_SCALAR_EVENT, key, TOKEN_LENGTH);
|
||||
user->username = strdup(key);
|
||||
have_username = true;
|
||||
} else if (!strcmp(key, "targets")) {
|
||||
parse_qdl_targets(dp, &user->targets);
|
||||
have_targets = true;
|
||||
} else {
|
||||
fprintf(stderr, "device parser: unknown qdl_access key \"%s\"\n", key);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!have_username || !have_targets || list_empty(&user->targets)) {
|
||||
fprintf(stderr, "device parser: incomplete qdl_access entry\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
list_append(dev->qdl_access, &user->node);
|
||||
device_parser_expect(dp, YAML_MAPPING_END_EVENT, NULL, 0);
|
||||
}
|
||||
|
||||
device_parser_expect(dp, YAML_SEQUENCE_END_EVENT, NULL, 0);
|
||||
}
|
||||
|
||||
static void parse_board(struct device_parser *dp)
|
||||
{
|
||||
struct device *dev;
|
||||
@@ -142,6 +206,11 @@ static void parse_board(struct device_parser *dp)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(key, "qdl_access")) {
|
||||
parse_qdl_access(dp, dev);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(key, "local_gpio")) {
|
||||
dev->control_options = local_gpio_ops.parse_options(dp);
|
||||
if (dev->control_options)
|
||||
|
||||
+25
@@ -94,6 +94,31 @@ properties:
|
||||
description: storage type to pass to QDL when flashing
|
||||
type: string
|
||||
|
||||
qdl_access:
|
||||
description: >
|
||||
User access allowance for QDL flash targets. Targets use QDL syntax:
|
||||
<partition-name>, <lun>, <lun>/<partition-name>, or
|
||||
<lun>/<start-sector>. Bare partition names are resolved by QDL
|
||||
across all LUNs; use "all" to allow any target.
|
||||
type: array
|
||||
uniqueItems: true
|
||||
minItems: 1
|
||||
items:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
user:
|
||||
type: string
|
||||
targets:
|
||||
type: array
|
||||
uniqueItems: true
|
||||
minItems: 1
|
||||
items:
|
||||
type: string
|
||||
required:
|
||||
- user
|
||||
- targets
|
||||
|
||||
qcomlt_debug_board:
|
||||
description: Qlt Debug Board control tty device path
|
||||
$ref: "#/$defs/device_path"
|
||||
|
||||
Reference in new issue
Block a user