Merge branch 'work.sysctl' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull in Christoph Hellwig's series that changes the sysctl's ->proc_handler methods to take kernel pointers instead. It gets rid of the set_fs address space overrides used by BPF. As per discussion, pull in the feature branch into bpf-next as it relates to BPF sysctl progs. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Link: https://lore.kernel.org/bpf/20200427071508.GV23230@ZenIV.linux.org.uk/T/
This commit is contained in:
@@ -1122,16 +1122,13 @@ const struct bpf_verifier_ops cg_dev_verifier_ops = {
|
||||
* @head: sysctl table header
|
||||
* @table: sysctl table
|
||||
* @write: sysctl is being read (= 0) or written (= 1)
|
||||
* @buf: pointer to buffer passed by user space
|
||||
* @buf: pointer to buffer (in and out)
|
||||
* @pcount: value-result argument: value is size of buffer pointed to by @buf,
|
||||
* result is size of @new_buf if program set new value, initial value
|
||||
* otherwise
|
||||
* @ppos: value-result argument: value is position at which read from or write
|
||||
* to sysctl is happening, result is new position if program overrode it,
|
||||
* initial value otherwise
|
||||
* @new_buf: pointer to pointer to new buffer that will be allocated if program
|
||||
* overrides new value provided by user space on sysctl write
|
||||
* NOTE: it's caller responsibility to free *new_buf if it was set
|
||||
* @type: type of program to be executed
|
||||
*
|
||||
* Program is run when sysctl is being accessed, either read or written, and
|
||||
@@ -1142,8 +1139,7 @@ const struct bpf_verifier_ops cg_dev_verifier_ops = {
|
||||
*/
|
||||
int __cgroup_bpf_run_filter_sysctl(struct ctl_table_header *head,
|
||||
struct ctl_table *table, int write,
|
||||
void __user *buf, size_t *pcount,
|
||||
loff_t *ppos, void **new_buf,
|
||||
void **buf, size_t *pcount, loff_t *ppos,
|
||||
enum bpf_attach_type type)
|
||||
{
|
||||
struct bpf_sysctl_kern ctx = {
|
||||
@@ -1158,36 +1154,28 @@ int __cgroup_bpf_run_filter_sysctl(struct ctl_table_header *head,
|
||||
.new_updated = 0,
|
||||
};
|
||||
struct cgroup *cgrp;
|
||||
loff_t pos = 0;
|
||||
int ret;
|
||||
|
||||
ctx.cur_val = kmalloc_track_caller(ctx.cur_len, GFP_KERNEL);
|
||||
if (ctx.cur_val) {
|
||||
mm_segment_t old_fs;
|
||||
loff_t pos = 0;
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
if (table->proc_handler(table, 0, (void __user *)ctx.cur_val,
|
||||
&ctx.cur_len, &pos)) {
|
||||
/* Let BPF program decide how to proceed. */
|
||||
ctx.cur_len = 0;
|
||||
}
|
||||
set_fs(old_fs);
|
||||
} else {
|
||||
if (!ctx.cur_val ||
|
||||
table->proc_handler(table, 0, ctx.cur_val, &ctx.cur_len, &pos)) {
|
||||
/* Let BPF program decide how to proceed. */
|
||||
ctx.cur_len = 0;
|
||||
}
|
||||
|
||||
if (write && buf && *pcount) {
|
||||
if (write && *buf && *pcount) {
|
||||
/* BPF program should be able to override new value with a
|
||||
* buffer bigger than provided by user.
|
||||
*/
|
||||
ctx.new_val = kmalloc_track_caller(PAGE_SIZE, GFP_KERNEL);
|
||||
ctx.new_len = min_t(size_t, PAGE_SIZE, *pcount);
|
||||
if (!ctx.new_val ||
|
||||
copy_from_user(ctx.new_val, buf, ctx.new_len))
|
||||
if (ctx.new_val) {
|
||||
memcpy(ctx.new_val, *buf, ctx.new_len);
|
||||
} else {
|
||||
/* Let BPF program decide how to proceed. */
|
||||
ctx.new_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
@@ -1198,7 +1186,8 @@ int __cgroup_bpf_run_filter_sysctl(struct ctl_table_header *head,
|
||||
kfree(ctx.cur_val);
|
||||
|
||||
if (ret == 1 && ctx.new_updated) {
|
||||
*new_buf = ctx.new_val;
|
||||
kfree(*buf);
|
||||
*buf = ctx.new_val;
|
||||
*pcount = ctx.new_len;
|
||||
} else {
|
||||
kfree(ctx.new_val);
|
||||
|
Reference in New Issue
Block a user