[Devel] [PATCH rh7] oom: fix NULL ptr deref on oom if memory cgroup is disabled

Konstantin Khorenko khorenko at virtuozzo.com
Fri Apr 29 09:25:50 PDT 2016


Going to send it to mainstream?

--
Best regards,

Konstantin Khorenko,
Virtuozzo Linux Kernel Team

On 04/27/2016 04:09 PM, Vladimir Davydov wrote:
> mem_cgroup_iter and try_get_mem_cgroup_from_mm return NULL in this case,
> handle this properly.
>
> https://jira.sw.ru/browse/PSBM-43328
>
> Signed-off-by: Vladimir Davydov <vdavydov at virtuozzo.com>
> ---
>   include/linux/memcontrol.h |  5 +++--
>   mm/memcontrol.c            |  4 +++-
>   mm/oom_kill.c              | 20 +++++++++++---------
>   3 files changed, 17 insertions(+), 12 deletions(-)
>
> diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
> index d90f6c77dc69..743fb0b6f621 100644
> --- a/include/linux/memcontrol.h
> +++ b/include/linux/memcontrol.h
> @@ -31,6 +31,8 @@ struct mm_struct;
>   struct kmem_cache;
>   struct oom_context;
>
> +extern struct oom_context global_oom_ctx;
> +
>   /* Stats that can be updated by kernel. */
>   enum mem_cgroup_page_stat_item {
>   	MEMCG_NR_FILE_MAPPED, /* # of pages charged as file rss */
> @@ -392,8 +394,7 @@ mem_cgroup_update_lru_size(struct lruvec *lruvec, enum lru_list lru,
>   static inline struct oom_context *
>   mem_cgroup_oom_context(struct mem_cgroup *memcg)
>   {
> -	extern struct oom_context oom_ctx;
> -	return &oom_ctx;
> +	return &global_oom_ctx;
>   }
>
>   static inline unsigned long mem_cgroup_overdraft(struct mem_cgroup *memcg)
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 61c395b7c4ed..fa66d1128cfb 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -1699,6 +1699,8 @@ void mem_cgroup_note_oom_kill(struct mem_cgroup *root_memcg,
>
>   struct oom_context *mem_cgroup_oom_context(struct mem_cgroup *memcg)
>   {
> +	if (mem_cgroup_disabled())
> +		return &global_oom_ctx;
>   	if (!memcg)
>   		memcg = root_mem_cgroup;
>   	return &memcg->oom_ctx;
> @@ -1708,7 +1710,7 @@ unsigned long mem_cgroup_overdraft(struct mem_cgroup *memcg)
>   {
>   	unsigned long long guarantee, usage;
>
> -	if (mem_cgroup_is_root(memcg))
> +	if (mem_cgroup_disabled() || mem_cgroup_is_root(memcg))
>   		return 0;
>
>   	guarantee = ACCESS_ONCE(memcg->oom_guarantee);
> diff --git a/mm/oom_kill.c b/mm/oom_kill.c
> index 2402fcceda6e..7a328e8c3204 100644
> --- a/mm/oom_kill.c
> +++ b/mm/oom_kill.c
> @@ -51,12 +51,10 @@ static DEFINE_SPINLOCK(oom_context_lock);
>   #define OOM_BASE_RAGE	-10
>   #define OOM_MAX_RAGE	20
>
> -#ifndef CONFIG_MEMCG
> -struct oom_context oom_ctx = {
> +struct oom_context global_oom_ctx = {
>   	.rage		= OOM_BASE_RAGE,
> -	.waitq		= __WAIT_QUEUE_HEAD_INITIALIZER(oom_ctx.waitq),
> +	.waitq		= __WAIT_QUEUE_HEAD_INITIALIZER(global_oom_ctx.waitq),
>   };
> -#endif
>
>   void init_oom_context(struct oom_context *ctx)
>   {
> @@ -187,7 +185,8 @@ static unsigned long mm_overdraft(struct mm_struct *mm)
>   	memcg = try_get_mem_cgroup_from_mm(mm);
>   	ctx = mem_cgroup_oom_context(memcg);
>   	overdraft = ctx->overdraft;
> -	mem_cgroup_put(memcg);
> +	if (memcg)
> +		mem_cgroup_put(memcg);
>
>   	return overdraft;
>   }
> @@ -497,7 +496,8 @@ void mark_oom_victim(struct task_struct *tsk)
>   		ctx->marked = true;
>   	}
>   	spin_unlock(&oom_context_lock);
> -	mem_cgroup_put(memcg);
> +	if (memcg)
> +		mem_cgroup_put(memcg);
>   }
>
>   /**
> @@ -608,7 +608,7 @@ bool oom_trylock(struct mem_cgroup *memcg)
>   		 * information will be used in oom_badness.
>   		 */
>   		ctx->overdraft = mem_cgroup_overdraft(iter);
> -		parent = parent_mem_cgroup(iter);
> +		parent = iter ? parent_mem_cgroup(iter) : NULL;
>   		if (parent && iter != memcg)
>   			ctx->overdraft = max(ctx->overdraft,
>   				mem_cgroup_oom_context(parent)->overdraft);
> @@ -645,7 +645,8 @@ void oom_unlock(struct mem_cgroup *memcg)
>   			 * on it for the victim to exit below.
>   			 */
>   			victim_memcg = iter;
> -			mem_cgroup_get(iter);
> +			if (iter)
> +				mem_cgroup_get(iter);
>
>   			mem_cgroup_iter_break(memcg, iter);
>   			break;
> @@ -695,7 +696,8 @@ void oom_unlock(struct mem_cgroup *memcg)
>   	 */
>   	ctx = mem_cgroup_oom_context(victim_memcg);
>   	__wait_oom_context(ctx);
> -	mem_cgroup_put(victim_memcg);
> +	if (victim_memcg)
> +		mem_cgroup_put(victim_memcg);
>   }
>
>   /*
>


More information about the Devel mailing list