Skip to content

Commit bf0da1c

Browse files
committed
kernel, ksud: implement clone_type sepolicy support
- Add clone_type/copy_perm parsing and kernel-side sepolicy patch support. - Clone attributes, roles, constraints, avtab rules, permissive state and filename transitions for the new type. - Keep clone_type failures from publishing partial policy updates and align live policy duplication with runtime buffer growth needs.
1 parent fda952b commit bf0da1c

5 files changed

Lines changed: 488 additions & 21 deletions

File tree

kernel/selinux/rules.c

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,8 @@ static int sepol_expected_argc(u32 cmd)
255255
return 4;
256256
case KSU_SEPOLICY_CMD_GENFSCON:
257257
return 3;
258+
case KSU_SEPOLICY_CMD_CLONE_TYPE:
259+
return 2;
258260
default:
259261
return -EINVAL;
260262
}
@@ -423,6 +425,20 @@ static int apply_one_sepolicy_cmd(struct policydb *db, const struct sepol_data *
423425
}
424426
return 0;
425427

428+
case KSU_SEPOLICY_CMD_CLONE_TYPE:
429+
ret = sepol_require_not_all(args[0], "src");
430+
if (ret < 0)
431+
return ret;
432+
ret = sepol_require_not_all(args[1], "dst");
433+
if (ret < 0)
434+
return ret;
435+
436+
if (!ksu_clone_type(db, args[0], args[1])) {
437+
pr_err("sepol: clone_type failed.\n");
438+
return -EINVAL;
439+
}
440+
return 0;
441+
426442
default:
427443
pr_err("sepol: unknown cmd: %d\n", header->cmd);
428444
return -EINVAL;
@@ -432,6 +448,7 @@ static int apply_one_sepolicy_cmd(struct policydb *db, const struct sepol_data *
432448
int handle_sepolicy(void __user *user_data, u64 data_len)
433449
{
434450
struct selinux_policy *pol, *old_pol;
451+
struct selinux_policy *locked_old_pol;
435452
struct policydb *db;
436453
struct sepol_batch_cursor cursor;
437454
u8 *payload;
@@ -462,14 +479,16 @@ int handle_sepolicy(void __user *user_data, u64 data_len)
462479
}
463480

464481
mutex_lock(&selinux_state.policy_mutex);
465-
466-
old_pol = selinux_state.policy;
467-
pol = ksu_dup_sepolicy(rcu_dereference_protected(old_pol, lockdep_is_held(&selinux_state.policy_mutex)));
482+
locked_old_pol = rcu_dereference_protected(selinux_state.policy, lockdep_is_held(&selinux_state.policy_mutex));
483+
pol = ksu_dup_sepolicy(locked_old_pol);
468484
if (IS_ERR(pol)) {
485+
mutex_unlock(&selinux_state.policy_mutex);
469486
ret = PTR_ERR(pol);
470487
pr_err("ksu_dup_sepolicy err: %d\n", ret);
471-
goto out_unlock;
488+
goto out_free;
472489
}
490+
mutex_unlock(&selinux_state.policy_mutex);
491+
pr_info("sepol: duplicated policy ready, payload_len=%llu\n", data_len);
473492
db = &pol->policydb;
474493

475494
cursor.cur = payload;
@@ -505,24 +524,40 @@ int handle_sepolicy(void __user *user_data, u64 data_len)
505524
}
506525
}
507526

527+
pr_info("sepol: begin cmd #%u cmd=%u subcmd=%u\n", cmd_index, header.cmd, header.subcmd);
508528
ret = apply_one_sepolicy_cmd(db, &header, args);
509529
if (ret < 0) {
510530
pr_err("sepol: cmd #%u failed, cmd=%u subcmd=%u.\n", cmd_index, header.cmd, header.subcmd);
531+
if (header.cmd == KSU_SEPOLICY_CMD_CLONE_TYPE)
532+
goto out_drop_new_policy;
511533
} else {
512534
success_cmd_count++;
535+
pr_info("sepol: end cmd #%u cmd=%u subcmd=%u\n", cmd_index, header.cmd, header.subcmd);
513536
}
514537
cmd_index++;
515538
}
516539

540+
mutex_lock(&selinux_state.policy_mutex);
541+
old_pol = rcu_dereference_protected(selinux_state.policy, lockdep_is_held(&selinux_state.policy_mutex));
542+
if (old_pol != locked_old_pol) {
543+
ret = -EAGAIN;
544+
pr_err("sepol: policy changed during offline patch, retry required.\n");
545+
goto out_drop_new_policy_locked;
546+
}
547+
517548
rcu_assign_pointer(selinux_state.policy, pol);
549+
pr_info("sepol: publishing new policy\n");
518550
synchronize_rcu();
519551
ksu_destroy_sepolicy(old_pol);
520552

521553
reset_avc_cache();
554+
pr_info("sepol: policy publish complete, success_cmd_count=%d\n", success_cmd_count);
522555
ret = success_cmd_count;
523556
goto out_unlock;
524557

525558
out_drop_new_policy:
559+
mutex_lock(&selinux_state.policy_mutex);
560+
out_drop_new_policy_locked:
526561
ksu_destroy_sepolicy(pol);
527562
out_unlock:
528563
mutex_unlock(&selinux_state.policy_mutex);

0 commit comments

Comments
 (0)