aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorWilly Tarreau <w@1wt.eu>2016-01-18 16:36:09 +0100
committerSimon Shields <keepcalm444@gmail.com>2016-05-03 22:55:13 +1000
commitaf47328e8d37683c911edf5703cdc45d8047490e (patch)
tree63a501a76679b28e0e3abbffea9925ef46078539 /include
parent046fdefc1dfbbc9f34b569ae77b3258c4eb588a5 (diff)
downloadkernel_samsung_smdk4412-af47328e8d37683c911edf5703cdc45d8047490e.tar.gz
kernel_samsung_smdk4412-af47328e8d37683c911edf5703cdc45d8047490e.tar.bz2
kernel_samsung_smdk4412-af47328e8d37683c911edf5703cdc45d8047490e.zip
pipe: limit the per-user amount of pages allocated in pipes
On no-so-small systems, it is possible for a single process to cause an OOM condition by filling large pipes with data that are never read. A typical process filling 4000 pipes with 1 MB of data will use 4 GB of memory. On small systems it may be tricky to set the pipe max size to prevent this from happening. This patch makes it possible to enforce a per-user soft limit above which new pipes will be limited to a single page, effectively limiting them to 4 kB each, as well as a hard limit above which no new pipes may be created for this user. This has the effect of protecting the system against memory abuse without hurting other users, and still allowing pipes to work correctly though with less data at once. The limit are controlled by two new sysctls : pipe-user-pages-soft, and pipe-user-pages-hard. Both may be disabled by setting them to zero. The default soft limit allows the default number of FDs per process (1024) to create pipes of the default size (64kB), thus reaching a limit of 64MB before starting to create only smaller pipes. With 256 processes limited to 1024 FDs each, this results in 1024*64kB + (256*1024 - 1024) * 4kB = 1084 MB of memory allocated for a user. The hard limit is disabled by default to avoid breaking existing applications that make intensive use of pipes (eg: for splicing). Reported-by: socketpair@gmail.com Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Mitigates: CVE-2013-4312 (Linux 2.0+) Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Willy Tarreau <w@1wt.eu> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Conflicts: Documentation/sysctl/fs.txt fs/pipe.c include/linux/sched.h Change-Id: Ic7c678af18129943e16715fdaa64a97a7f0854be
Diffstat (limited to 'include')
-rw-r--r--include/linux/pipe_fs_i.h4
-rw-r--r--include/linux/sched.h1
2 files changed, 5 insertions, 0 deletions
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 0072a5366e9..1aefc3f0359 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -43,6 +43,7 @@ struct pipe_buffer {
* @fasync_writers: writer side fasync
* @inode: inode this pipe is attached to
* @bufs: the circular array of pipe buffers
+ * @user: the user who created this pipe
**/
struct pipe_inode_info {
wait_queue_head_t wait;
@@ -57,6 +58,7 @@ struct pipe_inode_info {
struct fasync_struct *fasync_writers;
struct inode *inode;
struct pipe_buffer *bufs;
+ struct user_struct *user;
};
/*
@@ -142,6 +144,8 @@ void pipe_unlock(struct pipe_inode_info *);
void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *);
extern unsigned int pipe_max_size, pipe_min_size;
+extern unsigned long pipe_user_pages_hard;
+extern unsigned long pipe_user_pages_soft;
int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 8ff666cf782..ad2f17f36ab 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -705,6 +705,7 @@ struct user_struct {
unsigned long mq_bytes; /* How many bytes can be allocated to mqueue? */
#endif
unsigned long locked_shm; /* How many pages of mlocked shm ? */
+ atomic_long_t pipe_bufs; /* how many pages are allocated in pipe buffers */
#ifdef CONFIG_KEYS
struct key *uid_keyring; /* UID specific keyring */