Skip to content

Commit 48efa30

Browse files
committed
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>
1 parent 4be6c26 commit 48efa30

7 files changed

Lines changed: 189 additions & 0 deletions

File tree

README

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,33 @@ devices:
8181
fastboot_set_active: true
8282
fastboot_key_timeout: 2
8383

84+
- board: qdlboard
85+
users:
86+
- username
87+
console: /dev/ttyUSB1
88+
fastboot: abcdef04
89+
qdl_programmer: /path/to/prog_firehose_ddr.elf
90+
qdl_access:
91+
- user: username
92+
targets:
93+
- boot_a
94+
- boot_b
95+
- 0/efiesp
96+
- 0/123456
97+
- user: admin
98+
targets:
99+
- all
100+
101+
QDL access targets use QDL's target syntax: <partition-name>, <lun>,
102+
<lun>/<partition-name>, or <lun>/<start-sector>. The CDBA server checks the
103+
requested target string against the configured access list before invoking QDL,
104+
but does not resolve the target to a physical partition itself. For a bare
105+
<partition-name>, QDL searches across all LUNs and flashes the first matching
106+
partition. If multiple LUNs might contain the same partition name, or if the ACL
107+
must identify an exact location, use the explicit <lun>/<partition-name> or
108+
<lun>/<start-sector> form instead. The special target "all" allows any QDL
109+
target.
110+
84111
- board: testboard
85112
console: /dev/serial/by-id/usb-1234-if00-port0
86113
name: GPIO controller board

cdba-server.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,24 @@ static void msg_edl_flash(const void *data, size_t len)
148148
{
149149
const char *target = data;
150150

151+
if (!selected_device || !current_edl_file)
152+
return;
153+
154+
if (!len || target[len - 1]) {
155+
fprintf(stderr, "invalid EDL flash target\n");
156+
watch_quit();
157+
return;
158+
}
159+
151160
fprintf(stderr, "edl flash into '%s'\n", target);
152161

162+
if (!device_qdl_access_allowed(selected_device, username, target)) {
163+
fprintf(stderr, "user '%s' is not allowed to flash EDL target '%s' on %s\n",
164+
username, target, selected_device->board);
165+
watch_quit();
166+
return;
167+
}
168+
153169
current_edl_file->target = strdup(target);
154170
current_edl_file = NULL;
155171
}

config-samples/sample13.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,11 @@ devices:
1111
qdl_programmer: /path/to/prog_firehose_ddr.elf
1212
qdl_serial: 1234567890ABCDEF
1313
qdl_storage: ufs
14+
qdl_access:
15+
- user: alice
16+
targets:
17+
- all
18+
- user: bob
19+
targets:
20+
- userdata
21+
- 0/123456

device.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,33 @@ void device_info(const char *username, const void *data, size_t dlen)
410410
cdba_send_buf(MSG_BOARD_INFO, len, description);
411411
}
412412

413+
bool device_qdl_access_allowed(struct device *device,
414+
const char *username,
415+
const char *target)
416+
{
417+
struct device_qdl_user *user;
418+
struct device_qdl_target *qdl_target;
419+
420+
if (!device->qdl_access)
421+
return true;
422+
423+
if (!username || !target)
424+
return false;
425+
426+
list_for_each_entry(user, device->qdl_access, node) {
427+
if (strcmp(user->username, username))
428+
continue;
429+
430+
list_for_each_entry(qdl_target, &user->targets, node) {
431+
if (!strcmp(qdl_target->target, "all") ||
432+
!strcmp(qdl_target->target, target))
433+
return true;
434+
}
435+
}
436+
437+
return false;
438+
}
439+
413440
void device_close(struct device *dev)
414441
{
415442
if (!dev->usb_always_on)

device.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ struct device {
6767
char *qdl_programmer;
6868
char *qdl_serial;
6969
char *qdl_storage;
70+
struct list_head *qdl_access;
7071

7172
char *status_cmd;
7273

@@ -79,6 +80,19 @@ struct device_user {
7980
struct list_head node;
8081
};
8182

83+
struct device_qdl_target {
84+
const char *target;
85+
86+
struct list_head node;
87+
};
88+
89+
struct device_qdl_user {
90+
const char *username;
91+
struct list_head targets;
92+
93+
struct list_head node;
94+
};
95+
8296
void device_add(struct device *device);
8397

8498
struct device *device_open(const char *board,
@@ -104,6 +118,9 @@ void device_list_devices(const char *username);
104118
void device_info(const char *username, const void *data, size_t dlen);
105119
void device_fastboot_continue(struct device *device);
106120
bool device_is_running(struct device *device);
121+
bool device_qdl_access_allowed(struct device *device,
122+
const char *username,
123+
const char *target);
107124

108125
extern const struct control_ops alpaca_ops;
109126
extern const struct control_ops cdb_assist_ops;

device_parser.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,70 @@ static void parse_users(struct device_parser *dp, struct device *dev)
128128
device_parser_expect(dp, YAML_SEQUENCE_END_EVENT, NULL, 0);
129129
}
130130

131+
static void parse_qdl_targets(struct device_parser *dp, struct list_head *targets)
132+
{
133+
char value[TOKEN_LENGTH];
134+
135+
if (device_parser_accept(dp, YAML_SCALAR_EVENT, value, 0))
136+
return;
137+
138+
device_parser_expect(dp, YAML_SEQUENCE_START_EVENT, NULL, 0);
139+
140+
while (device_parser_accept(dp, YAML_SCALAR_EVENT, value, TOKEN_LENGTH)) {
141+
struct device_qdl_target *target = calloc(1, sizeof(*target));
142+
143+
target->target = strdup(value);
144+
list_append(targets, &target->node);
145+
}
146+
147+
device_parser_expect(dp, YAML_SEQUENCE_END_EVENT, NULL, 0);
148+
}
149+
150+
static void parse_qdl_access(struct device_parser *dp, struct device *dev)
151+
{
152+
char key[TOKEN_LENGTH];
153+
154+
dev->qdl_access = calloc(1, sizeof(*dev->qdl_access));
155+
list_init(dev->qdl_access);
156+
157+
if (device_parser_accept(dp, YAML_SCALAR_EVENT, key, 0))
158+
return;
159+
160+
device_parser_expect(dp, YAML_SEQUENCE_START_EVENT, NULL, 0);
161+
162+
while (device_parser_accept(dp, YAML_MAPPING_START_EVENT, NULL, 0)) {
163+
struct device_qdl_user *user = calloc(1, sizeof(*user));
164+
bool have_username = false;
165+
bool have_targets = false;
166+
167+
list_init(&user->targets);
168+
169+
while (device_parser_accept(dp, YAML_SCALAR_EVENT, key, TOKEN_LENGTH)) {
170+
if (!strcmp(key, "user")) {
171+
device_parser_expect(dp, YAML_SCALAR_EVENT, key, TOKEN_LENGTH);
172+
user->username = strdup(key);
173+
have_username = true;
174+
} else if (!strcmp(key, "targets")) {
175+
parse_qdl_targets(dp, &user->targets);
176+
have_targets = true;
177+
} else {
178+
fprintf(stderr, "device parser: unknown qdl_access key \"%s\"\n", key);
179+
exit(1);
180+
}
181+
}
182+
183+
if (!have_username || !have_targets || list_empty(&user->targets)) {
184+
fprintf(stderr, "device parser: incomplete qdl_access entry\n");
185+
exit(1);
186+
}
187+
188+
list_append(dev->qdl_access, &user->node);
189+
device_parser_expect(dp, YAML_MAPPING_END_EVENT, NULL, 0);
190+
}
191+
192+
device_parser_expect(dp, YAML_SEQUENCE_END_EVENT, NULL, 0);
193+
}
194+
131195
static void parse_board(struct device_parser *dp)
132196
{
133197
struct device *dev;
@@ -142,6 +206,11 @@ static void parse_board(struct device_parser *dp)
142206
continue;
143207
}
144208

209+
if (!strcmp(key, "qdl_access")) {
210+
parse_qdl_access(dp, dev);
211+
continue;
212+
}
213+
145214
if (!strcmp(key, "local_gpio")) {
146215
dev->control_options = local_gpio_ops.parse_options(dp);
147216
if (dev->control_options)

schema.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,31 @@ properties:
9494
description: storage type to pass to QDL when flashing
9595
type: string
9696

97+
qdl_access:
98+
description: >
99+
User access allowance for QDL flash targets. Targets use QDL syntax:
100+
<partition-name>, <lun>, <lun>/<partition-name>, or
101+
<lun>/<start-sector>. Bare partition names are resolved by QDL
102+
across all LUNs; use "all" to allow any target.
103+
type: array
104+
uniqueItems: true
105+
minItems: 1
106+
items:
107+
type: object
108+
additionalProperties: false
109+
properties:
110+
user:
111+
type: string
112+
targets:
113+
type: array
114+
uniqueItems: true
115+
minItems: 1
116+
items:
117+
type: string
118+
required:
119+
- user
120+
- targets
121+
97122
qcomlt_debug_board:
98123
description: Qlt Debug Board control tty device path
99124
$ref: "#/$defs/device_path"

0 commit comments

Comments
 (0)