Merge branch 'for-4.11-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
Pull cgroup fixes from Tejun Heo: "This contains fixes for two long standing subtle bugs: - kthread_bind() on a new kthread binds it to specific CPUs and prevents userland from messing with the affinity or cgroup membership. Unfortunately, for cgroup membership, there's a window between kthread creation and kthread_bind*() invocation where the kthread can be moved into a non-root cgroup by userland. Depending on what controllers are in effect, this can assign the kthread unexpected attributes. For example, in the reported case, workqueue workers ended up in a non-root cpuset cgroups and had their CPU affinities overridden. This broke workqueue invariants and led to workqueue stalls. Fixed by closing the window between kthread creation and kthread_bind() as suggested by Oleg. - There was a bug in cgroup mount path which could allow two competing mount attempts to attach the same cgroup_root to two different superblocks. This was caused by mishandling return value from kernfs_pin_sb(). Fixed" * 'for-4.11-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: cgroup: avoid attaching a cgroup root to two different superblocks cgroup, kthread: close race window where new kthreads can be migrated to non-root cgroups
This commit is contained in:
@@ -1146,7 +1146,7 @@ struct dentry *cgroup1_mount(struct file_system_type *fs_type, int flags,
|
||||
* path is super cold. Let's just sleep a bit and retry.
|
||||
*/
|
||||
pinned_sb = kernfs_pin_sb(root->kf_root, NULL);
|
||||
if (IS_ERR(pinned_sb) ||
|
||||
if (IS_ERR_OR_NULL(pinned_sb) ||
|
||||
!percpu_ref_tryget_live(&root->cgrp.self.refcnt)) {
|
||||
mutex_unlock(&cgroup_mutex);
|
||||
if (!IS_ERR_OR_NULL(pinned_sb))
|
||||
|
@@ -2425,11 +2425,12 @@ ssize_t __cgroup_procs_write(struct kernfs_open_file *of, char *buf,
|
||||
tsk = tsk->group_leader;
|
||||
|
||||
/*
|
||||
* Workqueue threads may acquire PF_NO_SETAFFINITY and become
|
||||
* trapped in a cpuset, or RT worker may be born in a cgroup
|
||||
* with no rt_runtime allocated. Just say no.
|
||||
* kthreads may acquire PF_NO_SETAFFINITY during initialization.
|
||||
* If userland migrates such a kthread to a non-root cgroup, it can
|
||||
* become trapped in a cpuset, or RT kthread may be born in a
|
||||
* cgroup with no rt_runtime allocated. Just say no.
|
||||
*/
|
||||
if (tsk == kthreadd_task || (tsk->flags & PF_NO_SETAFFINITY)) {
|
||||
if (tsk->no_cgroup_migration || (tsk->flags & PF_NO_SETAFFINITY)) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock_rcu;
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/cgroup.h>
|
||||
#include <trace/events/sched.h>
|
||||
|
||||
static DEFINE_SPINLOCK(kthread_create_lock);
|
||||
@@ -225,6 +226,7 @@ static int kthread(void *_create)
|
||||
|
||||
ret = -EINTR;
|
||||
if (!test_bit(KTHREAD_SHOULD_STOP, &self->flags)) {
|
||||
cgroup_kthread_ready();
|
||||
__kthread_parkme(self);
|
||||
ret = threadfn(data);
|
||||
}
|
||||
@@ -538,6 +540,7 @@ int kthreadd(void *unused)
|
||||
set_mems_allowed(node_states[N_MEMORY]);
|
||||
|
||||
current->flags |= PF_NOFREEZE;
|
||||
cgroup_init_kthreadd();
|
||||
|
||||
for (;;) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
Reference in New Issue
Block a user