mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 17:30:02 +00:00
![Glauber Costa](/assets/img/avatar_default.png)
Because those architectures will draw their stacks directly from the page allocator, rather than the slab cache, we can directly pass __GFP_KMEMCG flag, and issue the corresponding free_pages. This code path is taken when the architecture doesn't define CONFIG_ARCH_THREAD_INFO_ALLOCATOR (only ia64 seems to), and has THREAD_SIZE >= PAGE_SIZE. Luckily, most - if not all - of the remaining architectures fall in this category. This will guarantee that every stack page is accounted to the memcg the process currently lives on, and will have the allocations to fail if they go over limit. For the time being, I am defining a new variant of THREADINFO_GFP, not to mess with the other path. Once the slab is also tracked by memcg, we can get rid of that flag. Tested to successfully protect against :(){ :|:& };: Signed-off-by: Glauber Costa <glommer@parallels.com> Acked-by: Frederic Weisbecker <fweisbec@redhat.com> Acked-by: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Reviewed-by: Michal Hocko <mhocko@suse.cz> Cc: Christoph Lameter <cl@linux.com> Cc: David Rientjes <rientjes@google.com> Cc: Greg Thelen <gthelen@google.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: JoonSoo Kim <js1304@gmail.com> Cc: Mel Gorman <mel@csn.ul.ie> Cc: Pekka Enberg <penberg@cs.helsinki.fi> Cc: Rik van Riel <riel@redhat.com> Cc: Suleiman Souhlal <suleiman@google.com> Cc: Tejun Heo <tj@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
153 lines
4.1 KiB
C
153 lines
4.1 KiB
C
/* thread_info.h: common low-level thread information accessors
|
|
*
|
|
* Copyright (C) 2002 David Howells (dhowells@redhat.com)
|
|
* - Incorporating suggestions made by Linus Torvalds
|
|
*/
|
|
|
|
#ifndef _LINUX_THREAD_INFO_H
|
|
#define _LINUX_THREAD_INFO_H
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/bug.h>
|
|
|
|
struct timespec;
|
|
struct compat_timespec;
|
|
|
|
/*
|
|
* System call restart block.
|
|
*/
|
|
struct restart_block {
|
|
long (*fn)(struct restart_block *);
|
|
union {
|
|
/* For futex_wait and futex_wait_requeue_pi */
|
|
struct {
|
|
u32 __user *uaddr;
|
|
u32 val;
|
|
u32 flags;
|
|
u32 bitset;
|
|
u64 time;
|
|
u32 __user *uaddr2;
|
|
} futex;
|
|
/* For nanosleep */
|
|
struct {
|
|
clockid_t clockid;
|
|
struct timespec __user *rmtp;
|
|
#ifdef CONFIG_COMPAT
|
|
struct compat_timespec __user *compat_rmtp;
|
|
#endif
|
|
u64 expires;
|
|
} nanosleep;
|
|
/* For poll */
|
|
struct {
|
|
struct pollfd __user *ufds;
|
|
int nfds;
|
|
int has_timeout;
|
|
unsigned long tv_sec;
|
|
unsigned long tv_nsec;
|
|
} poll;
|
|
};
|
|
};
|
|
|
|
extern long do_no_restart_syscall(struct restart_block *parm);
|
|
|
|
#include <linux/bitops.h>
|
|
#include <asm/thread_info.h>
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
#ifdef CONFIG_DEBUG_STACK_USAGE
|
|
# define THREADINFO_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO)
|
|
#else
|
|
# define THREADINFO_GFP (GFP_KERNEL | __GFP_NOTRACK)
|
|
#endif
|
|
|
|
#define THREADINFO_GFP_ACCOUNTED (THREADINFO_GFP | __GFP_KMEMCG)
|
|
|
|
/*
|
|
* flag set/clear/test wrappers
|
|
* - pass TIF_xxxx constants to these functions
|
|
*/
|
|
|
|
static inline void set_ti_thread_flag(struct thread_info *ti, int flag)
|
|
{
|
|
set_bit(flag, (unsigned long *)&ti->flags);
|
|
}
|
|
|
|
static inline void clear_ti_thread_flag(struct thread_info *ti, int flag)
|
|
{
|
|
clear_bit(flag, (unsigned long *)&ti->flags);
|
|
}
|
|
|
|
static inline int test_and_set_ti_thread_flag(struct thread_info *ti, int flag)
|
|
{
|
|
return test_and_set_bit(flag, (unsigned long *)&ti->flags);
|
|
}
|
|
|
|
static inline int test_and_clear_ti_thread_flag(struct thread_info *ti, int flag)
|
|
{
|
|
return test_and_clear_bit(flag, (unsigned long *)&ti->flags);
|
|
}
|
|
|
|
static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
|
|
{
|
|
return test_bit(flag, (unsigned long *)&ti->flags);
|
|
}
|
|
|
|
#define set_thread_flag(flag) \
|
|
set_ti_thread_flag(current_thread_info(), flag)
|
|
#define clear_thread_flag(flag) \
|
|
clear_ti_thread_flag(current_thread_info(), flag)
|
|
#define test_and_set_thread_flag(flag) \
|
|
test_and_set_ti_thread_flag(current_thread_info(), flag)
|
|
#define test_and_clear_thread_flag(flag) \
|
|
test_and_clear_ti_thread_flag(current_thread_info(), flag)
|
|
#define test_thread_flag(flag) \
|
|
test_ti_thread_flag(current_thread_info(), flag)
|
|
|
|
#define set_need_resched() set_thread_flag(TIF_NEED_RESCHED)
|
|
#define clear_need_resched() clear_thread_flag(TIF_NEED_RESCHED)
|
|
|
|
#if defined TIF_RESTORE_SIGMASK && !defined HAVE_SET_RESTORE_SIGMASK
|
|
/*
|
|
* An arch can define its own version of set_restore_sigmask() to get the
|
|
* job done however works, with or without TIF_RESTORE_SIGMASK.
|
|
*/
|
|
#define HAVE_SET_RESTORE_SIGMASK 1
|
|
|
|
/**
|
|
* set_restore_sigmask() - make sure saved_sigmask processing gets done
|
|
*
|
|
* This sets TIF_RESTORE_SIGMASK and ensures that the arch signal code
|
|
* will run before returning to user mode, to process the flag. For
|
|
* all callers, TIF_SIGPENDING is already set or it's no harm to set
|
|
* it. TIF_RESTORE_SIGMASK need not be in the set of bits that the
|
|
* arch code will notice on return to user mode, in case those bits
|
|
* are scarce. We set TIF_SIGPENDING here to ensure that the arch
|
|
* signal code always gets run when TIF_RESTORE_SIGMASK is set.
|
|
*/
|
|
static inline void set_restore_sigmask(void)
|
|
{
|
|
set_thread_flag(TIF_RESTORE_SIGMASK);
|
|
WARN_ON(!test_thread_flag(TIF_SIGPENDING));
|
|
}
|
|
static inline void clear_restore_sigmask(void)
|
|
{
|
|
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
|
}
|
|
static inline bool test_restore_sigmask(void)
|
|
{
|
|
return test_thread_flag(TIF_RESTORE_SIGMASK);
|
|
}
|
|
static inline bool test_and_clear_restore_sigmask(void)
|
|
{
|
|
return test_and_clear_thread_flag(TIF_RESTORE_SIGMASK);
|
|
}
|
|
#endif /* TIF_RESTORE_SIGMASK && !HAVE_SET_RESTORE_SIGMASK */
|
|
|
|
#ifndef HAVE_SET_RESTORE_SIGMASK
|
|
#error "no set_restore_sigmask() provided and default one won't work"
|
|
#endif
|
|
|
|
#endif /* __KERNEL__ */
|
|
|
|
#endif /* _LINUX_THREAD_INFO_H */
|