Skip to content

Commit dc1ebd1

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 dc1ebd1

5 files changed

Lines changed: 475 additions & 29 deletions

File tree

kernel/selinux/rules.c

Lines changed: 35 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,15 @@ 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);
473491
db = &pol->policydb;
474492

475493
cursor.cur = payload;
@@ -508,21 +526,34 @@ int handle_sepolicy(void __user *user_data, u64 data_len)
508526
ret = apply_one_sepolicy_cmd(db, &header, args);
509527
if (ret < 0) {
510528
pr_err("sepol: cmd #%u failed, cmd=%u subcmd=%u.\n", cmd_index, header.cmd, header.subcmd);
529+
if (header.cmd == KSU_SEPOLICY_CMD_CLONE_TYPE)
530+
goto out_drop_new_policy;
511531
} else {
512532
success_cmd_count++;
513533
}
514534
cmd_index++;
515535
}
516536

537+
mutex_lock(&selinux_state.policy_mutex);
538+
old_pol = rcu_dereference_protected(selinux_state.policy, lockdep_is_held(&selinux_state.policy_mutex));
539+
if (old_pol != locked_old_pol) {
540+
ret = -EAGAIN;
541+
pr_err("sepol: policy changed during offline patch, retry required.\n");
542+
goto out_drop_new_policy_locked;
543+
}
544+
517545
rcu_assign_pointer(selinux_state.policy, pol);
518546
synchronize_rcu();
519547
ksu_destroy_sepolicy(old_pol);
520548

521549
reset_avc_cache();
550+
pr_info("sepol: policy publish complete, success_cmd_count=%d\n", success_cmd_count);
522551
ret = success_cmd_count;
523552
goto out_unlock;
524553

525554
out_drop_new_policy:
555+
mutex_lock(&selinux_state.policy_mutex);
556+
out_drop_new_policy_locked:
526557
ksu_destroy_sepolicy(pol);
527558
out_unlock:
528559
mutex_unlock(&selinux_state.policy_mutex);

0 commit comments

Comments
 (0)