Commit a2564d06 authored by Joel Granados's avatar Joel Granados
Browse files

loadpin: Implement custom proc_handler for enforce



Add a new static variable (loadpin_root_writable) to keep the
write-ability state of enforce. Remove set_sysctl and const qualify
loadpin_sysctl_table (moves into .rodata) as there is no longer need to
change the value of extra1. The new proc_handler_loadpin returns -EINVAL
when loadpin_root_writable is false and the kernel var (enforce) is
being written. The old way of modifying the write-ability of enforce
stays in loadpin_check and is still set by calling sb_is_writable.

Signed-off-by: default avatarJoel Granados <joel.granados@kernel.org>
parent b22d81fb
Loading
Loading
Loading
Loading
+16 −21
Original line number Diff line number Diff line
@@ -52,32 +52,29 @@ static DEFINE_SPINLOCK(pinned_root_spinlock);
static bool deny_reading_verity_digests;
#endif

// initialized to false
static bool loadpin_root_writable;
#ifdef CONFIG_SYSCTL
static struct ctl_table loadpin_sysctl_table[] = {

static int proc_handler_loadpin(const struct ctl_table *table, int dir,
				void *buffer, size_t *lenp, loff_t *ppos)
{
	if (!loadpin_root_writable && SYSCTL_USER_TO_KERN(dir))
		return -EINVAL;
	return proc_dointvec_minmax(table, dir, buffer, lenp, ppos);
}

static const struct ctl_table loadpin_sysctl_table[] = {
	{
		.procname       = "enforce",
		.data           = &enforce,
		.maxlen         = sizeof(int),
		.mode           = 0644,
		.proc_handler   = proc_dointvec_minmax,
		.extra1         = SYSCTL_ONE,
		.proc_handler   = proc_handler_loadpin,
		.extra1         = SYSCTL_ZERO,
		.extra2         = SYSCTL_ONE,
	},
};

static void set_sysctl(bool is_writable)
{
	/*
	 * If load pinning is not enforced via a read-only block
	 * device, allow sysctl to change modes for testing.
	 */
	if (is_writable)
		loadpin_sysctl_table[0].extra1 = SYSCTL_ZERO;
	else
		loadpin_sysctl_table[0].extra1 = SYSCTL_ONE;
}
#else
static inline void set_sysctl(bool is_writable) { }
#endif

static void report_writable(struct super_block *mnt_sb, bool writable)
@@ -131,7 +128,6 @@ static int loadpin_check(struct file *file, enum kernel_read_file_id id)
	struct super_block *load_root;
	const char *origin = kernel_read_file_id_str(id);
	bool first_root_pin = false;
	bool load_root_writable;

	/* If the file id is excluded, ignore the pinning. */
	if ((unsigned int)id < ARRAY_SIZE(ignore_read_file_id) &&
@@ -152,7 +148,6 @@ static int loadpin_check(struct file *file, enum kernel_read_file_id id)
	}

	load_root = file->f_path.mnt->mnt_sb;
	load_root_writable = sb_is_writable(load_root);

	/* First loaded module/firmware defines the root for all others. */
	spin_lock(&pinned_root_spinlock);
@@ -168,8 +163,8 @@ static int loadpin_check(struct file *file, enum kernel_read_file_id id)
	spin_unlock(&pinned_root_spinlock);

	if (first_root_pin) {
		report_writable(pinned_root, load_root_writable);
		set_sysctl(load_root_writable);
		loadpin_root_writable = sb_is_writable(pinned_root);
		report_writable(pinned_root, loadpin_root_writable);
		report_load(origin, file, "pinned");
	}