On 10/20, Tycho Andersen wrote: > > +long seccomp_get_filter(struct task_struct *task, unsigned long filter_off, > + void __user *data) > +{ > + struct seccomp_filter *filter; > + struct sock_fprog_kern *fprog; > + long ret; > + unsigned long count = 0; > + > + if (!capable(CAP_SYS_ADMIN) || > + current->seccomp.mode != SECCOMP_MODE_DISABLED) { > + return -EACCES; > + } > + > + spin_lock_irq(&task->sighand->siglock); > + if (task->seccomp.mode != SECCOMP_MODE_FILTER) { > + ret = -EINVAL; > + goto out_task; > + } > + > + filter = task->seccomp.filter; > + while (filter) { > + filter = filter->prev; > + count++; > + } > + > + if (filter_off >= count) { > + ret = -ENOENT; > + goto out_task; > + } > + count -= filter_off; > + > + filter = task->seccomp.filter; > + while (filter && count > 1) { > + filter = filter->prev; > + count--; > + } > + > + if (WARN_ON(count != 1)) { > + /* The filter tree shouldn't shrink while we're using it. */ > + ret = -ENOENT; > + goto out_task; > + } > + > + fprog = filter->prog->orig_prog; > + if (!fprog) { > + /* This must be a new non-cBPF filter, since we save every > + * every cBPF filter's orig_prog above when > + * CONFIG_CHECKPOINT_RESTORE is enabled. > + */ > + ret = -EMEDIUMTYPE; > + goto out_task; > + } > + > + ret = fprog->len; > + if (!data) > + goto out_task; > + > + if (copy_to_user(data, fprog->filter, bpf_classic_proglen(fprog))) { > + ret = -EFAULT; > + goto out_task; > + }
Oh wait, I didn't notice this when I looked at v7. No, you can't do copy_to_user() from atomic context. You need to pin this filter, drop the lock/irq, then copy_to_user(). Oleg. -- To unsubscribe from this list: send the line "unsubscribe linux-api" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html