* Note: due to races, there is not a single serializable order * between parallel calls to the sysctl. */
| 329 | * between parallel calls to the sysctl. |
| 330 | */ |
| 331 | static int |
| 332 | sysctl_rules(SYSCTL_HANDLER_ARGS) |
| 333 | { |
| 334 | char *string, *copy_string, *new_string; |
| 335 | struct rulehead head, save_head; |
| 336 | int error; |
| 337 | |
| 338 | new_string = NULL; |
| 339 | if (req->newptr != NULL) { |
| 340 | new_string = malloc(MAC_RULE_STRING_LEN, M_PORTACL, |
| 341 | M_WAITOK | M_ZERO); |
| 342 | mtx_lock(&rule_mtx); |
| 343 | strcpy(new_string, rule_string); |
| 344 | mtx_unlock(&rule_mtx); |
| 345 | string = new_string; |
| 346 | } else |
| 347 | string = rule_string; |
| 348 | |
| 349 | error = sysctl_handle_string(oidp, string, MAC_RULE_STRING_LEN, req); |
| 350 | if (error) |
| 351 | goto out; |
| 352 | |
| 353 | if (req->newptr != NULL) { |
| 354 | copy_string = strdup(string, M_PORTACL); |
| 355 | TAILQ_INIT(&head); |
| 356 | error = parse_rules(copy_string, &head); |
| 357 | free(copy_string, M_PORTACL); |
| 358 | if (error) |
| 359 | goto out; |
| 360 | |
| 361 | TAILQ_INIT(&save_head); |
| 362 | mtx_lock(&rule_mtx); |
| 363 | TAILQ_CONCAT(&save_head, &rule_head, r_entries); |
| 364 | TAILQ_CONCAT(&rule_head, &head, r_entries); |
| 365 | strcpy(rule_string, string); |
| 366 | mtx_unlock(&rule_mtx); |
| 367 | toast_rules(&save_head); |
| 368 | } |
| 369 | out: |
| 370 | if (new_string != NULL) |
| 371 | free(new_string, M_PORTACL); |
| 372 | return (error); |
| 373 | } |
| 374 | |
| 375 | SYSCTL_PROC(_security_mac_portacl, OID_AUTO, rules, |
| 376 | CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, |
nothing calls this directly
no test coverage detected